00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
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
00070 bool r = wxPanel::Create( parent, id, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxFULL_REPAINT_ON_RESIZE | wxCLIP_CHILDREN, name );
00071 flags_ = flags;
00072
00073
00074 pClient_ = new wxPanel( this, 0, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN );
00075 pStockClient_ = pClient_;
00076
00077
00078 pGripWindow_ = new wxGripWindow( this, GetOrientation(), wxGdi::wxGRIP_STYLE_HEADER );
00079 pGripWindow_->SetLabel( parent->GetTitle() );
00080
00081
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
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
00103 pDockHost_->UpdateSize();
00104 }
00105 pDockHost_ = pDockHost;
00106
00107
00108 docked_ = pDockHost ? true : false;
00109
00110 if( pDockHost ) {
00111
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
00131 wxLayoutManager * pLayoutManager = pDockWindow_->GetLayoutManager();
00132 wxASSERT(pLayoutManager);
00133 pLayoutManager->UpdateAllHosts( false );
00134 }
00135
00136 void wxDockPanel::OnGripDblClick( wxMouseEvent& WXUNUSED(event) ) {
00137
00138 wxDockWindow * pDockWindow = static_cast<wxDockWindow *>(GetDockWindow());
00139 wxASSERT(pDockWindow);
00140 wxLayoutManager * pLayoutManager = pDockWindow->GetLayoutManager();
00141 wxASSERT(pLayoutManager);
00142
00143
00144 pLayoutManager->UndockWindow( GetDockWindow() );
00145 }
00146
00147 void wxDockPanel::OnGripLeftDown( wxMouseEvent& event ) {
00148 wxDockWindow * pDockWindow = static_cast<wxDockWindow *>(GetDockWindow());
00149 wxASSERT(pDockWindow);
00150
00151
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
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
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
00205 #if __WXGTK__
00206 if( docked_ && (pPane_ || flags_ & wxDPC_NO_CONTROLS) ) {
00207
00208 #else
00209 if( !docked_ || pPane_ || (flags_ & wxDPC_NO_CONTROLS) ) {
00210 #endif
00211
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
00222 orientation = wxVERTICAL;
00223 }
00224 #endif
00225
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
00247 return;
00248 }
00249
00250
00251 if( pClient_ ) {
00252 pClient_->Hide();
00253 }
00254
00255
00256 if( !pClient ) {
00257
00258 wxASSERT(pStockClient_);
00259 pClient_ = pStockClient_;
00260 }
00261 else {
00262 wxPaneBase * pPotentialPane = (wxPane *)wxDynamicCast( pClient, wxPaneBase );
00263 if( autoPane && !pPotentialPane ) {
00264
00265
00266 wxPane * pAutoPane = new wxPane( this, -1, pDockWindow_->GetTitle() );
00267 pClient->Reparent( pAutoPane );
00268 pAutoPane->SetClient( pClient );
00269 pClient_ = pAutoPane;
00270 }
00271 else {
00272
00273 pClient->Reparent( this );
00274 pClient_ = pClient;
00275 }
00276 }
00277 wxASSERT(pClient_);
00278 pClient_->Show();
00279
00280
00281 pPane_ = (wxPane *)wxDynamicCast( pClient_, wxPaneBase );
00282 if( pPane_ ) {
00283
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;
00300
00301
00302 pClientSizer_ = new wxBoxSizer( wxHORIZONTAL );
00303 pClient_->SetSizer( pClientSizer_ );
00304 pClient_->SetAutoLayout( true );
00305
00306
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
00321 if( pDockHost_ ) {
00322 return pDockHost_->GetOrientation();
00323 }
00324
00325
00326 return wxHORIZONTAL;
00327 }
00328
00329 wxRect wxDockPanel::GetScreenArea() {
00330
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
00341 return screenRect;
00342 }
00343
00344 if( GetOrientation() == wxHORIZONTAL ) {
00345
00346 screenRect.width /= 2;
00347 if( hi.placement == wxHIP_BACK ) {
00348 screenRect.x += screenRect.width;
00349 }
00350 }
00351 else {
00352
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
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
00398 if( pPane_ ) {
00399 pPane_->ShowHeader( docked_ ? true : false );
00400 pPane_->SetOrientation( GetOrientation() == wxVERTICAL ? wxHORIZONTAL : wxVERTICAL );
00401 }
00402 }