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
) 
  37 IMPLEMENT_CLASS(wxSashLayoutWindow
, wxSashWindow
) 
  39 BEGIN_EVENT_TABLE(wxSashLayoutWindow
, wxSashWindow
) 
  40     EVT_CALCULATE_LAYOUT(wxSashLayoutWindow::OnCalculateLayout
) 
  41     EVT_QUERY_LAYOUT_INFO(wxSashLayoutWindow::OnQueryLayoutInfo
) 
  44 bool wxSashLayoutWindow::Create(wxWindow 
*parent
, wxWindowID id
, const wxPoint
& pos
, 
  45         const wxSize
& size
, long style
, const wxString
& name
) 
  47     return wxSashWindow::Create(parent
, id
, pos
, size
, style
, name
); 
  50 void wxSashLayoutWindow::Init() 
  52     m_orientation 
= wxLAYOUT_HORIZONTAL
; 
  53     m_alignment 
= wxLAYOUT_TOP
; 
  56 // This is the function that wxLayoutAlgorithm calls to ascertain the window 
  58 void wxSashLayoutWindow::OnQueryLayoutInfo(wxQueryLayoutInfoEvent
& event
) 
  60   //    int flags = event.GetFlags(); 
  61     int requestedLength 
= event
.GetRequestedLength(); 
  63     event
.SetOrientation(m_orientation
); 
  64     event
.SetAlignment(m_alignment
); 
  66     if (m_orientation 
== wxLAYOUT_HORIZONTAL
) 
  67         event
.SetSize(wxSize(requestedLength
, m_defaultSize
.y
)); 
  69         event
.SetSize(wxSize(m_defaultSize
.x
, requestedLength
)); 
  72 // Called by parent to allow window to take a bit out of the 
  73 // client rectangle, and size itself if not in wxLAYOUT_QUERY mode. 
  75 void wxSashLayoutWindow::OnCalculateLayout(wxCalculateLayoutEvent
& event
) 
  77     wxRect 
clientSize(event
.GetRect()); 
  79     int flags 
= event
.GetFlags(); 
  84     // Let's assume that all windows stretch the full extent of the window in 
  85     // the direction of that window orientation. This will work for non-docking toolbars, 
  86     // and the status bar. Note that the windows have to have been created in a certain 
  87     // order to work, else you might get a left-aligned window going to the bottom 
  88     // of the window, and the status bar appearing to the right of it. The 
  89     // status bar would have to be created after or before the toolbar(s). 
  94     int length 
= (GetOrientation() == wxLAYOUT_HORIZONTAL
) ? clientSize
.width 
: clientSize
.height
; 
  95     wxLayoutOrientation orient 
= GetOrientation(); 
  97     // We assume that a window that says it's horizontal, wants to be stretched in that 
  98     // direction. Is this distinction too fine? Do we assume that any horizontal 
  99     // window needs to be stretched in that direction? Possibly. 
 100     int whichDimension 
= (GetOrientation() == wxLAYOUT_HORIZONTAL
) ? wxLAYOUT_LENGTH_X 
: wxLAYOUT_LENGTH_Y
; 
 102     wxQueryLayoutInfoEvent 
infoEvent(GetId()); 
 103     infoEvent
.SetEventObject(this); 
 104     infoEvent
.SetRequestedLength(length
); 
 105     infoEvent
.SetFlags(orient 
| whichDimension
); 
 107     if (!GetEventHandler()->ProcessEvent(infoEvent
)) 
 110     wxSize sz 
= infoEvent
.GetSize(); 
 112     if (sz
.x 
== 0 && sz
.y 
== 0) // Assume it's invisible 
 115     // Now we know the size it wants to be. We wish to decide where to place it, i.e. 
 117     switch (GetAlignment()) 
 121             thisRect
.x 
= clientSize
.x
; thisRect
.y 
= clientSize
.y
; 
 122             thisRect
.width 
= sz
.x
; thisRect
.height 
= sz
.y
; 
 123             clientSize
.y 
+= thisRect
.height
; 
 124             clientSize
.height 
-= thisRect
.height
; 
 129             thisRect
.x 
= clientSize
.x
; thisRect
.y 
= clientSize
.y
; 
 130             thisRect
.width 
= sz
.x
; thisRect
.height 
= sz
.y
; 
 131             clientSize
.x 
+= thisRect
.width
; 
 132             clientSize
.width 
-= thisRect
.width
; 
 137             thisRect
.x 
= clientSize
.x 
+ (clientSize
.width 
- sz
.x
); thisRect
.y 
= clientSize
.y
; 
 138             thisRect
.width 
= sz
.x
; thisRect
.height 
= sz
.y
; 
 139             clientSize
.width 
-= thisRect
.width
; 
 142         case wxLAYOUT_BOTTOM
: 
 144             thisRect
.x 
= clientSize
.x
; thisRect
.y 
= clientSize
.y 
+ (clientSize
.height 
- sz
.y
); 
 145             thisRect
.width 
= sz
.x
; thisRect
.height 
= sz
.y
; 
 146             clientSize
.height 
-= thisRect
.height
; 
 156     if ((flags 
& wxLAYOUT_QUERY
) == 0) 
 158         // If not in query mode, resize the window. 
 159         // TODO: add wxRect& form to wxWindow::SetSize 
 160         wxSize sz 
= GetSize(); 
 161         wxPoint pos 
= GetPosition(); 
 162         SetSize(thisRect
.x
, thisRect
.y
, thisRect
.width
, thisRect
.height
); 
 164         // Make sure the sash is erased when the window is resized 
 165         if ((pos
.x 
!= thisRect
.x 
|| pos
.y 
!= thisRect
.y 
|| sz
.x 
!= thisRect
.width 
|| sz
.y 
!= thisRect
.height
) && 
 166             (GetSashVisible(wxSASH_TOP
) || GetSashVisible(wxSASH_RIGHT
) || GetSashVisible(wxSASH_BOTTOM
) || GetSashVisible(wxSASH_LEFT
))) 
 171     event
.SetRect(clientSize
); 
 179 // Lays out windows for an MDI frame. The MDI client area gets what's left 
 181 bool wxLayoutAlgorithm::LayoutMDIFrame(wxMDIParentFrame
* frame
, wxRect
* r
) 
 184     frame
->GetClientSize(& cw
, & ch
); 
 186     wxRect 
rect(0, 0, cw
, ch
); 
 190     wxCalculateLayoutEvent event
; 
 193     wxNode
* node 
= frame
->GetChildren().First(); 
 196         wxWindow
* win 
= (wxWindow
*) node
->Data(); 
 198         event
.SetId(win
->GetId()); 
 199         event
.SetEventObject(win
); 
 200         event
.SetFlags(0); // ?? 
 202         win
->GetEventHandler()->ProcessEvent(event
); 
 207     wxWindow
* clientWindow 
= frame
->GetClientWindow(); 
 209     rect 
= event
.GetRect(); 
 211     clientWindow
->SetSize(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 216 // Layout algorithm for any window. mainWindow gets what's left over. 
 217 bool wxLayoutAlgorithm::LayoutWindow(wxWindow
* parent
, wxWindow
* mainWindow
) 
 219     // Test if the parent is a sash window, and if so, 
 220     // reduce the available space to allow space for any active edges. 
 222     int leftMargin 
= 0, rightMargin 
= 0, topMargin 
= 0, bottomMargin 
= 0; 
 224     if (parent
->IsKindOf(CLASSINFO(wxSashWindow
))) 
 226         wxSashWindow
* sashWindow 
= (wxSashWindow
*) parent
; 
 228         leftMargin 
= sashWindow
->GetExtraBorderSize(); 
 229         rightMargin 
= sashWindow
->GetExtraBorderSize(); 
 230         topMargin 
= sashWindow
->GetExtraBorderSize(); 
 231         bottomMargin 
= sashWindow
->GetExtraBorderSize(); 
 233         if (sashWindow
->GetSashVisible(wxSASH_LEFT
)) 
 234             leftMargin 
+= sashWindow
->GetDefaultBorderSize(); 
 235         if (sashWindow
->GetSashVisible(wxSASH_RIGHT
)) 
 236             rightMargin 
+= sashWindow
->GetDefaultBorderSize(); 
 237         if (sashWindow
->GetSashVisible(wxSASH_TOP
)) 
 238             topMargin 
+= sashWindow
->GetDefaultBorderSize(); 
 239         if (sashWindow
->GetSashVisible(wxSASH_BOTTOM
)) 
 240             bottomMargin 
+= sashWindow
->GetDefaultBorderSize(); 
 245     parent
->GetClientSize(& cw
, & ch
); 
 247     wxRect 
rect(leftMargin
, topMargin
, cw 
- leftMargin 
- rightMargin
, ch 
- topMargin 
- bottomMargin
); 
 249     wxCalculateLayoutEvent event
; 
 252     wxNode
* node 
= parent
->GetChildren().First(); 
 255         wxWindow
* win 
= (wxWindow
*) node
->Data(); 
 257         if (win 
!= mainWindow
) 
 259             event
.SetId(win
->GetId()); 
 260             event
.SetEventObject(win
); 
 261             event
.SetFlags(0); // ?? 
 263             win
->GetEventHandler()->ProcessEvent(event
); 
 269     rect 
= event
.GetRect(); 
 272         mainWindow
->SetSize(rect
.x
, rect
.y
, rect
.width
, rect
.height
);