1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Implements a simple layout algorithm, plus
4 // wxSashLayoutWindow which is an example of a window with
5 // layout-awareness (via event handlers). This is suited to
6 // IDE-style window layout.
7 // Author: Julian Smart
11 // Copyright: (c) Julian Smart
12 // Licence: wxWindows licence
13 /////////////////////////////////////////////////////////////////////////////
16 #pragma implementation "laywin.h"
19 // For compilers that support precompilation, includes "wx/wx.h".
20 #include "wx/wxprec.h"
31 #include "wx/laywin.h"
33 IMPLEMENT_DYNAMIC_CLASS(wxQueryLayoutInfoEvent
, wxEvent
)
34 IMPLEMENT_DYNAMIC_CLASS(wxCalculateLayoutEvent
, wxEvent
)
36 IMPLEMENT_CLASS(wxSashLayoutWindow
, wxSashWindow
)
38 BEGIN_EVENT_TABLE(wxSashLayoutWindow
, wxSashWindow
)
39 EVT_CALCULATE_LAYOUT(wxSashLayoutWindow::OnCalculateLayout
)
40 EVT_QUERY_LAYOUT_INFO(wxSashLayoutWindow::OnQueryLayoutInfo
)
43 wxSashLayoutWindow::wxSashLayoutWindow(wxWindow
*parent
, wxWindowID id
, const wxPoint
& pos
,
44 const wxSize
& size
, long style
, const wxString
& name
):
45 wxSashWindow(parent
, id
, pos
, size
, style
, name
)
47 m_orientation
= wxLAYOUT_HORIZONTAL
;
48 m_alignment
= wxLAYOUT_TOP
;
51 // These are the functions that wxWin will call to ascertain the window
53 void wxSashLayoutWindow::OnQueryLayoutInfo(wxQueryLayoutInfoEvent
& event
)
55 // int flags = event.GetFlags();
56 int requestedLength
= event
.GetRequestedLength();
58 // This code won't be in the final thing, it's just so we don't have to give it
59 // real windows: mock up some dimensions.
61 event
.SetOrientation(m_orientation
);
62 event
.SetAlignment(m_alignment
);
64 if (m_orientation
== wxLAYOUT_HORIZONTAL
)
65 event
.SetSize(wxSize(requestedLength
, m_defaultSize
.y
));
67 event
.SetSize(wxSize(m_defaultSize
.x
, requestedLength
));
70 // Called by parent to allow window to take a bit out of the
71 // client rectangle, and size itself if not in wxLAYOUT_QUERY mode.
72 // Will eventually be an event.
74 void wxSashLayoutWindow::OnCalculateLayout(wxCalculateLayoutEvent
& event
)
76 wxRect
clientSize(event
.GetRect());
78 int flags
= event
.GetFlags();
83 // Let's assume that all windows stretch the full extent of the window in
84 // the direction of that window orientation. This will work for non-docking toolbars,
85 // and the status bar. Note that the windows have to have been created in a certain
86 // order to work, else you might get a left-aligned window going to the bottom
87 // of the window, and the status bar appearing to the right of it. The
88 // status bar would have to be created after or before the toolbar(s).
93 int length
= (GetOrientation() == wxLAYOUT_HORIZONTAL
) ? clientSize
.width
: clientSize
.height
;
94 wxLayoutOrientation orient
= GetOrientation();
96 // We assume that a window that says it's horizontal, wants to be stretched in that
97 // direction. Is this distinction too fine? Do we assume that any horizontal
98 // window needs to be stretched in that direction? Possibly.
99 int whichDimension
= (GetOrientation() == wxLAYOUT_HORIZONTAL
) ? wxLAYOUT_LENGTH_X
: wxLAYOUT_LENGTH_Y
;
101 wxQueryLayoutInfoEvent
infoEvent(GetId());
102 infoEvent
.SetEventObject(this);
103 infoEvent
.SetRequestedLength(length
);
104 infoEvent
.SetFlags(orient
| whichDimension
);
106 if (!GetEventHandler()->ProcessEvent(infoEvent
))
109 wxSize sz
= infoEvent
.GetSize();
111 if (sz
.x
== 0 && sz
.y
== 0) // Assume it's invisible
114 // Now we know the size it wants to be. We wish to decide where to place it, i.e.
116 switch (GetAlignment())
120 thisRect
.x
= clientSize
.x
; thisRect
.y
= clientSize
.y
;
121 thisRect
.width
= sz
.x
; thisRect
.height
= sz
.y
;
122 clientSize
.y
+= thisRect
.height
;
123 clientSize
.height
-= thisRect
.height
;
128 thisRect
.x
= clientSize
.x
; thisRect
.y
= clientSize
.y
;
129 thisRect
.width
= sz
.x
; thisRect
.height
= sz
.y
;
130 clientSize
.x
+= thisRect
.width
;
131 clientSize
.width
-= thisRect
.width
;
136 thisRect
.x
= clientSize
.x
+ (clientSize
.width
- sz
.x
); thisRect
.y
= clientSize
.y
;
137 thisRect
.width
= sz
.x
; thisRect
.height
= sz
.y
;
138 clientSize
.width
-= thisRect
.width
;
141 case wxLAYOUT_BOTTOM
:
143 thisRect
.x
= clientSize
.x
; thisRect
.y
= clientSize
.y
+ (clientSize
.height
- sz
.y
);
144 thisRect
.width
= sz
.x
; thisRect
.height
= sz
.y
;
145 clientSize
.height
-= thisRect
.height
;
155 if ((flags
& wxLAYOUT_QUERY
) == 0)
157 // If not in query mode, resize the window.
158 // TODO: add wxRect& form to wxWindow::SetSize
159 SetSize(thisRect
.x
, thisRect
.y
, thisRect
.width
, thisRect
.height
);
162 event
.SetRect(clientSize
);
169 // Lays out windows for an MDI frame. The MDI client area gets what's left
171 bool wxLayoutAlgorithm::LayoutMDIFrame(wxMDIParentFrame
* frame
)
174 frame
->GetClientSize(& cw
, & ch
);
176 wxRect
rect(0, 0, cw
, ch
);
178 wxCalculateLayoutEvent event
;
181 wxNode
* node
= frame
->GetChildren()->First();
184 wxWindow
* win
= (wxWindow
*) node
->Data();
186 event
.SetId(win
->GetId());
187 event
.SetEventObject(win
);
188 event
.SetFlags(0); // ??
190 win
->GetEventHandler()->ProcessEvent(event
);
195 wxWindow
* clientWindow
= frame
->GetClientWindow();
197 rect
= event
.GetRect();
199 clientWindow
->SetSize(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
204 // Layout algorithm for normal frame. mainWindow gets what's left over.
205 bool wxLayoutAlgorithm::LayoutFrame(wxFrame
* frame
, wxWindow
* mainWindow
)
208 frame
->GetClientSize(& cw
, & ch
);
210 wxRect
rect(0, 0, cw
, ch
);
212 wxCalculateLayoutEvent event
;
215 wxNode
* node
= frame
->GetChildren()->First();
218 wxWindow
* win
= (wxWindow
*) node
->Data();
220 event
.SetId(win
->GetId());
221 event
.SetEventObject(win
);
222 event
.SetFlags(0); // ??
224 win
->GetEventHandler()->ProcessEvent(event
);
229 rect
= event
.GetRect();
231 mainWindow
->SetSize(rect
.x
, rect
.y
, rect
.width
, rect
.height
);