Main Page | Namespace List | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

dockpanel.cpp

Go to the documentation of this file.
00001 
00002 // Name:        wxDockPanel.cpp
00003 // Purpose:     wxDockPanel implementation.
00004 // Author:      Mark McCormack
00005 // Modified by:
00006 // Created:     23/02/04
00007 // RCS-ID:      $Id: dockpanel.cpp,v 1.8 2005/05/12 14:04:47 frm Exp $
00008 // Copyright:   (c) 2004 Mark McCormack
00009 // Licence:     wxWindows license
00011 
00012 #include <wx/dockpanel.h>
00013 #include <wx/dockhost.h>
00014 #include <wx/dockwindow.h>
00015 #include <wx/toolbutton.h>
00016 #include <wx/gdi.h>
00017 #include <wx/pane.h>
00018 #include <wx/gripper.h>
00019 
00020 #include <wx/sizer.h>
00021 #include <wx/gdicmn.h>
00022 #include <wx/settings.h>
00023 
00024 // ----------------------------------------------------------------------------
00025 // wxDockPanel constants & wx-macros
00026 // ----------------------------------------------------------------------------
00027 
00028 IMPLEMENT_DYNAMIC_CLASS( wxDockPanel, wxPanel )
00029 
00030 BEGIN_EVENT_TABLE( wxDockPanel, wxPanel )
00031     EVT_SIZE( wxDockPanel::OnSize )
00032     EVT_BUTTON( 0, wxDockPanel::OnPaneClose )
00033     EVT_PANE_CLOSED( wxDockPanel::OnPaneClose )
00034     EVT_GRIP_DBLCLICK( wxDockPanel::OnGripDblClick )
00035     EVT_GRIP_LEFTDOWN( wxDockPanel::OnGripLeftDown )
00036     EVT_GRIP_LEFTUP( wxDockPanel::OnGripLeftUp )
00037 #ifdef __WXGTK__
00038     EVT_LEFT_UP( wxDockPanel::OnLeftUp )  
00039     EVT_MOTION( wxDockPanel::OnMouseMove )
00040 #endif    
00041 END_EVENT_TABLE()
00042 
00043 const unsigned int gripperSize = 14;
00044 const unsigned int closeSize = 13;
00045 const unsigned int closeBorder = 1;
00046 
00047 // ----------------------------------------------------------------------------
00048 // wxDockPanel implementation
00049 // ----------------------------------------------------------------------------
00050 
00051 void wxDockPanel::Init() {
00052     docked_ = false;
00053     mouseCaptured_ = false;
00054     pDockWindow_ = NULL;
00055     pDockHost_ = NULL;
00056     pClient_ = NULL;
00057     pStockClient_ = NULL;
00058     pPane_ = NULL;
00059     pClientSizer_ = NULL;
00060     pGripWindow_ = NULL;
00061     pCloseButton_ = NULL;
00062     area_ = 0;
00063     lockAreaValue_ = false;
00064     flags_ = 0x0000;
00065 }
00066 
00067 bool wxDockPanel::Create( wxWindow *parent, wxWindowID id, const wxString& name, unsigned int flags ) {
00068     wxASSERT(parent);
00069     // create ourselves
00070     bool r =  wxPanel::Create( parent, id, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxFULL_REPAINT_ON_RESIZE | wxCLIP_CHILDREN, name );
00071     flags_ = flags;
00072     
00073     // create default client area
00074     pClient_ = new wxPanel( this, 0, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN );
00075     pStockClient_ = pClient_;
00076     
00077     // create grip window
00078     pGripWindow_ = new wxGripWindow( this, GetOrientation(), wxGdi::wxGRIP_STYLE_HEADER );
00079     pGripWindow_->SetLabel( parent->GetTitle() );
00080     
00081     // create close window
00082     pCloseButton_ = new wxToolButton( this, 0 );
00083     pCloseButton_->SetDrawMargin( 1 );
00084     pCloseButton_->SetToolTip( wxT("Close") );
00085 
00086     return r;
00087 }
00088 
00089 void wxDockPanel::SetDockWindow( wxDockWindowBase * pOwner ) {
00090     pDockWindow_ = pOwner;
00091     
00092     // assign the cursor for hover over the gripper
00093     pGripWindow_->SetCursor( g_gdi.GetMoveCursor() );
00094 }
00095 
00096 wxDockWindowBase * wxDockPanel::GetDockWindow() {
00097     return pDockWindow_;
00098 }
00099 
00100 void wxDockPanel::SetDockedHost( wxDockHost * pDockHost ) {
00101     if( !pDockHost && pDockHost_ ) {
00102         // call update on host before clear
00103         pDockHost_->UpdateSize();
00104     }
00105     pDockHost_ = pDockHost;
00106     
00107     // internal update
00108     docked_ = pDockHost ? true : false;
00109 
00110     if( pDockHost ) {
00111         // call update on new host
00112         pDockHost->UpdateSize();
00113     }
00114 
00115     childUpdate();
00116 }
00117 
00118 wxDockHost * wxDockPanel::GetDockedHost() {
00119     return pDockHost_;
00120 }
00121 
00122 void wxDockPanel::OnSize( wxSizeEvent& WXUNUSED(event) ) {
00123     UpdateSize();
00124 }
00125 
00126 void wxDockPanel::OnPaneClose( wxCommandEvent& WXUNUSED(event) ) {
00127     wxASSERT(pDockWindow_);
00128     pDockWindow_->Remove();
00129 
00130     // Run the update to fix the menu
00131     wxLayoutManager * pLayoutManager = pDockWindow_->GetLayoutManager();
00132     wxASSERT(pLayoutManager);
00133     pLayoutManager->UpdateAllHosts( false );
00134 }
00135 
00136 void wxDockPanel::OnGripDblClick( wxMouseEvent& WXUNUSED(event) ) { 
00137     // in gripper area
00138     wxDockWindow * pDockWindow = static_cast<wxDockWindow *>(GetDockWindow());
00139     wxASSERT(pDockWindow);
00140     wxLayoutManager * pLayoutManager = pDockWindow->GetLayoutManager();
00141     wxASSERT(pLayoutManager);
00142     
00143     // undock the panel back onto the owner window
00144     pLayoutManager->UndockWindow( GetDockWindow() );
00145 }
00146 
00147 void wxDockPanel::OnGripLeftDown( wxMouseEvent& event ) { 
00148     wxDockWindow * pDockWindow = static_cast<wxDockWindow *>(GetDockWindow());
00149     wxASSERT(pDockWindow);
00150 
00151     // start dragging when docked
00152     wxPoint curPoint( event.GetPosition() );
00153     curPoint = ClientToScreen( curPoint );
00154 #ifdef __WXGTK__
00155     if( docked_ ) {
00156         pDockWindow->StartDragging( curPoint.x, curPoint.y, false );
00157         CaptureMouse();
00158     }
00159     else
00160 #endif    
00161     pDockWindow->StartDragging( curPoint.x, curPoint.y );
00162 }
00163 
00164 void wxDockPanel::OnGripLeftUp( wxMouseEvent& WXUNUSED(event) ) { 
00165     wxDockWindowBase * pDockWindow = GetDockWindow();
00166     wxASSERT(pDockWindow);
00167 
00168 #ifdef __WXGTK__
00169     if( docked_ ) {
00170         ReleaseMouse();
00171         pDockWindow->StopDragging( false );
00172     }
00173     else
00174 #endif    
00175     pDockWindow->StopDragging();
00176 }
00177 
00178 #ifdef __WXGTK__
00179 void wxDockPanel::OnMouseMove( wxMouseEvent& event ) {
00180     // forward mouse move messages to owner
00181     ClientToScreen( &event.m_x, &event.m_y );
00182     pDockWindow_->ScreenToClient( &event.m_x, &event.m_y );
00183     pDockWindow_->OnMouseMove( event );
00184 }
00185 
00186 void wxDockPanel::OnLeftUp( wxMouseEvent& event ) {
00187     // stopping any dragging
00188     bool needrelease = wxWindow::GetCapture() == pDockWindow_;
00189     pDockWindow_->StopDragging(needrelease);
00190 }
00191 #endif    
00192 
00193 void wxDockPanel::UpdateSize() {
00194     wxWindowList & children = GetChildren();
00195     if( children.GetCount() == 0 ) {
00196         return;
00197     }
00198    
00199     int tGripperSize = gripperSize;
00200     int tCloseSize = closeSize;
00201 
00202     wxOrientation orientation = GetOrientation();
00203 
00204     // layout
00205 #if __WXGTK__
00206     if( docked_ && (pPane_ || flags_ & wxDPC_NO_CONTROLS) ) {
00207         // docked and pane/no controls required
00208 #else
00209     if( !docked_ || pPane_ || (flags_ & wxDPC_NO_CONTROLS) ) {
00210 #endif
00211         // undocked/with pane control/no controls required
00212         wxRect cr = GetClientRect();
00213         pClient_->SetSize( 0, 0, cr.width, cr.height );
00214         pClient_->Layout();
00215         pGripWindow_->SetSize( wxSize( 0,0 ) );
00216         pCloseButton_->SetSize( wxSize( 0,0 ) );
00217         }
00218     else {
00219 #if __WXGTK__
00220         if( !docked_ ) {
00221             // undocked - show header
00222             orientation = wxVERTICAL;
00223         }
00224 #endif
00225         // docked/or with internal controls
00226         wxRect cr = GetClientRect();
00227         if( orientation == wxHORIZONTAL ) {
00228             pClient_->SetSize( tGripperSize, 0, cr.width-tGripperSize, cr.height );
00229             pClient_->Layout();
00230             pGripWindow_->SetSize( 0, tCloseSize + closeBorder, tGripperSize, cr.height - tCloseSize - closeBorder );
00231             pGripWindow_->SetOrientation( wxHORIZONTAL );
00232             pCloseButton_->SetSize( 0, closeBorder, tGripperSize, tCloseSize );
00233         }
00234         else {
00235             pClient_->SetSize( 0, tGripperSize, cr.width, cr.height-tGripperSize );
00236             pClient_->Layout();
00237             pGripWindow_->SetSize( 0, 0, cr.width - tCloseSize - closeBorder, tGripperSize );
00238             pGripWindow_->SetOrientation( wxVERTICAL );
00239             pCloseButton_->SetSize( cr.width - tCloseSize - closeBorder, 0, tCloseSize, tGripperSize );
00240         }
00241     }
00242 }
00243 
00244 void wxDockPanel::SetClient( wxWindow * pClient, bool autoPane ) {
00245     if (pClient == pClient_) {
00246         // ignore if we already have the given client as our client
00247         return;
00248     }
00249 
00250     // if we do nothing else with it, at least hide the old client
00251     if( pClient_ ) {
00252         pClient_->Hide();
00253     }
00254 
00255     // replace current client
00256     if( !pClient ) {
00257         // remove user client
00258         wxASSERT(pStockClient_);
00259         pClient_ = pStockClient_;
00260     }
00261     else {
00262         wxPaneBase * pPotentialPane = (wxPane *)wxDynamicCast( pClient, wxPaneBase );
00263         if( autoPane && !pPotentialPane ) {
00264             // automatically add a pane client and then add the actual client to it (of course don't want to 'AutoPane'
00265             // actual pane controls)
00266             wxPane * pAutoPane = new wxPane( this, -1, pDockWindow_->GetTitle() );
00267             pClient->Reparent( pAutoPane );
00268             pAutoPane->SetClient( pClient );
00269             pClient_ = pAutoPane;
00270         }
00271         else {
00272             // just add the client normally
00273             pClient->Reparent( this );
00274             pClient_ = pClient;
00275         }
00276     }
00277     wxASSERT(pClient_);
00278     pClient_->Show();
00279 
00280     // we know about wxPane clients
00281     pPane_ = (wxPane *)wxDynamicCast( pClient_, wxPaneBase );
00282     if( pPane_ ) {
00283         // size the pane to our client area
00284         wxSize size = GetClientSize();
00285         pPane_->SetSize( size );
00286     }
00287 
00288     childUpdate();
00289 
00290     UpdateSize();
00291 }
00292 
00293 wxWindow * wxDockPanel::GetClient() {
00294     wxASSERT(pClient_);
00295     return pClient_;
00296 }
00297 
00298 void wxDockPanel::AutoFitSingleChild() {
00299     if( pClientSizer_ ) return;    // already done
00300     
00301     // create simple 'expand all' sizer
00302     pClientSizer_ = new wxBoxSizer( wxHORIZONTAL );
00303     pClient_->SetSizer( pClientSizer_ );
00304     pClient_->SetAutoLayout( true );
00305     
00306     // apply to client child
00307     wxWindowList & children = pClient_->GetChildren();
00308     if( children.GetCount() != 1 ) {
00309         wxASSERT_MSG( false, wxT("AutoFitSingleChild() only works when there is a single child!") );
00310     }
00311     wxWindowListNode * pChildNode = children.GetFirst();
00312     wxASSERT(pChildNode);
00313     wxWindow * pChild = pChildNode->GetData();
00314     wxASSERT(pChild);
00315     pClientSizer_->Add( pChild, 1, wxGROW|wxALL, 0 );
00316     pClient_->Layout();
00317 }
00318 
00319 wxOrientation wxDockPanel::GetOrientation() {
00320     // get from host
00321     if( pDockHost_ ) {
00322         return pDockHost_->GetOrientation();
00323     }
00324     
00325     // getOrientation() makes no sense when panel is not docked!
00326     return wxHORIZONTAL;
00327 }
00328 
00329 wxRect wxDockPanel::GetScreenArea() {
00330     // get the screen area for this panel
00331     wxASSERT(pDockHost_);
00332     wxRect r = GetRect();
00333     
00334     return pDockHost_->RectToScreen( r );
00335 }
00336 
00337 wxRect wxDockPanel::GetScreenArea( wxHostInfo &hi ) {
00338     wxRect screenRect = GetScreenArea();
00339     if( hi.placement == wxHIP_NONE ) {
00340         // return all panel area
00341         return screenRect;
00342     }
00343     
00344     if( GetOrientation() == wxHORIZONTAL ) {
00345         // return a horizontal area
00346         screenRect.width /= 2;
00347         if( hi.placement == wxHIP_BACK ) {
00348             screenRect.x += screenRect.width;
00349         }
00350     }
00351     else {
00352         // return a vertical area
00353         screenRect.height /= 2;
00354         if( hi.placement == wxHIP_BACK ) {
00355             screenRect.y += screenRect.height;
00356         }
00357     }
00358     return screenRect;
00359 }
00360 
00361 wxPlacement wxDockPanel::TestForPlacement( int sx, int sy ) {
00362     wxPlacement placement = wxHIP_NONE;
00363     wxRect screenRect = GetScreenArea();
00364     
00365     // work out which half of the panel a screen point is in
00366     if( GetOrientation() == wxHORIZONTAL ) {
00367         screenRect.width /= 2;
00368         placement = screenRect.Inside( sx, sy ) ? wxHIP_FRONT : wxHIP_BACK;
00369     }
00370     else {
00371         screenRect.height /= 2;
00372         placement = screenRect.Inside( sx, sy ) ? wxHIP_FRONT : wxHIP_BACK;
00373     }
00374     return placement;
00375 }
00376 
00377 int wxDockPanel::GetArea() {
00378     return area_;
00379 }
00380 
00381 void wxDockPanel::SetArea( int area ) {
00382     if( lockAreaValue_ ) {
00383         return;
00384     }
00385     area_ = area;
00386 }
00387 
00388 void wxDockPanel::LockAreaValue( bool state ) {
00389     lockAreaValue_ = state;
00390 }
00391 
00392 bool wxDockPanel::IsDocked() {
00393     return docked_;
00394 }
00395 
00396 void wxDockPanel::childUpdate() {
00397     // we know about wxPane clients
00398     if( pPane_ ) {
00399         pPane_->ShowHeader( docked_ ? true : false );
00400         pPane_->SetOrientation( GetOrientation() == wxVERTICAL ? wxHORIZONTAL : wxVERTICAL );
00401     }
00402 }

Generated on Sat May 14 14:54:39 2005 for wxDockIt by  doxygen 1.4.2