📄 dockhost.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: wxDockHost.cpp
// Purpose: wxDockHost implementation.
// Author: Mark McCormack
// Modified by:
// Created: 23/02/04
// RCS-ID:
// Copyright:
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#include <wx/dockhost.h>
#include <wx/dockwindow.h>
#include <wx/dockpanel.h>
#include <wx/gdi.h>
#include <wx/exsplitter.h>
#include <wx/list.h>
#include <wx/listimpl.cpp>
// ----------------------------------------------------------------------------
// wxDockHost constants & wx-macros
// ----------------------------------------------------------------------------
IMPLEMENT_CLASS( wxDockHost, wxPanel )
BEGIN_EVENT_TABLE( wxDockHost, wxPanel )
EVT_SIZE( wxDockHost::OnSize )
EVT_SPLITTER_MOVED( wxDockHost::OnSplitterMoved )
EVT_CALCULATE_LAYOUT( wxDockHost::OnCalculateLayout )
END_EVENT_TABLE()
WX_DEFINE_LIST( DockWindowList );
WX_DEFINE_LIST( SplitterList );
// ----------------------------------------------------------------------------
// wxDockHost implementation
// ----------------------------------------------------------------------------
wxDockHost::~wxDockHost() {
delete pSizingSplitter_;
}
void wxDockHost::Init() {
dir_ = wxALL;
areaSize_ = INITIAL_HOST_SIZE;
panelArea_ = 0;
lockPanelValue_ = false;
internalSizeEvent_ = false;
pLayoutManager_ = NULL;
pos_.x = 0;
pos_.y = 0;
size_.x = 0;
size_.y = 0;
numPanels_ = 0;
numSplitters_ = 0;
splitterFlags_ = 0x0000;
pSizingSplitter_ = NULL;
splitters_.Clear();
dockWindows_.Clear();
}
bool wxDockHost::Create( wxWindow *parent, wxWindowID id, wxDirection dir, const wxString& name ) {
wxASSERT(parent);
dir_ = dir;
bool r = wxPanel::Create( parent, id, pos_, size_, wxTAB_TRAVERSAL | wxCLIP_CHILDREN, name );
return r;
}
void wxDockHost::SetLayoutManager( wxLayoutManager * pLayoutManager ) {
pLayoutManager_ = pLayoutManager;
// create sizer splitter
wxWindow * win1 = (dir_ == wxLEFT || dir_ == wxTOP) ? this : NULL;
wxWindow * win2 = (dir_ == wxRIGHT || dir_ == wxBOTTOM) ? this : NULL;
wxOrientation orientation = (GetOrientation() == wxHORIZONTAL) ? wxVERTICAL : wxHORIZONTAL;
pSizingSplitter_ = new wxExSplitter( this, orientation, win1, win2, 0x0000 );
SettingsChanged();
}
wxLayoutManager * wxDockHost::GetLayoutManager() {
return pLayoutManager_;
}
void wxDockHost::SetAreaSize( int size ) {
areaSize_ = size;
}
int wxDockHost::GetAreaSize() {
return areaSize_;
}
DockWindowList & wxDockHost::GetDockWindowList() {
DockWindowList dockWindows;
wxWindowList & children = GetChildren();
dockWindows_.Clear();
for( int c=0; c<(int)children.GetCount(); c++ ) {
// get child
wxWindowListNode * pChildNode = children.Item( c );
wxASSERT(pChildNode);
wxWindow * pChild = pChildNode->GetData();
wxASSERT(pChild);
// is it a panel?
wxDockPanel * pPanel = wxDynamicCast( pChild, wxDockPanel );
if( pPanel ) {
// add the panel's window
dockWindows_.Append( pPanel->GetDockWindow() );
}
}
return dockWindows_;
}
void wxDockHost::OnSize( wxSizeEvent &event ) {
if( !pLayoutManager_ ) {
// we have not beem given an owner yet, ignore event
return;
}
wxSize newSize = event.GetSize();
if( !IsEmpty() ) {
// if host is being used then update the host's area value
if( GetOrientation() == wxHORIZONTAL ) {
areaSize_ = newSize.GetHeight();
}
else {
areaSize_ = newSize.GetWidth();
}
if( !internalSizeEvent_ ) {
pLayoutManager_->UpdateAllHosts( true, this );
}
}
UpdateSize( true );
}
void wxDockHost::OnSplitterMoved( wxCommandEvent &event ) {
if( event.GetEventObject() != pSizingSplitter_ ) {
// recalc on panel splitter movement
RecalcPanelAreas();
}
}
void wxDockHost::UpdateSize( bool useProportions ) {
// calculate where we should be
/*
wxRect hp = CalcHostPlacement();
if( pLayoutManager_ ) {
// ask the manager for trim with other hosts
hp = pLayoutManager_->TrimDockArea( this, hp );
}
SetSize( hp );
*/
calcPanelPlacement( useProportions );
}
void wxDockHost::DockPanel( wxDockPanel * pDockPanel, HostInfo &hi ) {
if( hi.pPanel == pDockPanel ) {
// we don't need to do anything
return;
}
// make the panel a child of this host
pDockPanel->Reparent( this );
wxWindowList & children = GetChildren();
// if a target panel was specified, move child in relation to where we want it in the children list
if( hi.pPanel ) {
int insertIndex = children.IndexOf( hi.pPanel );
if( insertIndex == wxNOT_FOUND ) {
// panel no longer exists in this host
hi.pPanel = NULL;
}
}
// delete original node
wxWindowListNode * pNode = children.Find( pDockPanel );
children.DeleteNode( pNode );
int insertIndex = children.IndexOf( hi.pPanel );
if( insertIndex != wxNOT_FOUND ) {
// inserting panel is found, to the front or back?
if( hi.placement == HIP_BACK ) {
insertIndex++;
}
children.Insert( insertIndex, pDockPanel );
}
else {
// panel does not exist, insert at the back
int count = getAssetCount();
if( count > 0 ) {
wxWindowListNode * pChildNode = children.Item( count-1 );
wxASSERT(pChildNode);
hi.pPanel = wxDynamicCast( pChildNode->GetData(), wxDockPanel );
hi.placement = HIP_BACK;
}
children.Append( pDockPanel );
}
RecalcPanelAreas();
if( hi.pPanel ) {
// split area with target dock panel
int newArea = (hi.pPanel->GetArea() - SPLITTER_SIZE) / 2;
hi.pPanel->SetArea( newArea );
pDockPanel->SetArea( newArea );
}
else {
// dock panel has all the available area
pDockPanel->SetArea( panelArea_ );
}
pDockPanel->SetDockedHost( this );
}
void wxDockHost::UndockPanel( wxDockPanel * pDockPanel ) {
// see if we have any information about how we docked
wxWindowList & children = GetChildren();
// find node
wxWindowListNode * pNode = children.Find( pDockPanel );
assert(pNode);
wxDockPanel * pGivePanel = NULL;
// distribute free area
if( getAssetCount() > 1 ) {
int lastIndex = children.GetCount()-1;
wxWindowListNode * pLastNode = children.Item( lastIndex );
wxASSERT(pLastNode);
if( pNode == pLastNode ) {
// node is the last node, give to prev
do {
pNode = children.Item( --lastIndex );
pGivePanel = wxDynamicCast( pNode->GetData(), wxDockPanel );
} while( !pGivePanel );
}
else {
// give to next
int currentIndex = children.IndexOf( pDockPanel );
do {
pNode = children.Item( ++currentIndex );
pGivePanel = wxDynamicCast( pNode->GetData(), wxDockPanel );
} while( !pGivePanel );
}
}
// give the area back
if( pGivePanel ) {
int newArea = pDockPanel->GetArea() + pGivePanel->GetArea() + SPLITTER_SIZE;
pGivePanel->SetArea( newArea );
}
// remove the panel from this host
wxDockWindowBase * pDockWindow = pDockPanel->GetDockWindow();
pDockPanel->Reparent( pDockWindow );
pDockPanel->SetDockedHost( NULL );
}
wxRect wxDockHost::GetScreenArea() {
// return the screen area for this host
wxRect hp = CalcHostPlacement( true );
if( pLayoutManager_ ) {
hp = pLayoutManager_->TrimDockArea( this, hp );
}
return pLayoutManager_->RectToScreen( hp );
}
wxRect wxDockHost::GetScreenArea( HostInfo &hi ) {
// return the screen area for the info
if( !hi.pPanel ) {
return GetScreenArea();
}
else {
return hi.pPanel->GetScreenArea( hi );
}
}
wxRect wxDockHost::GetClientArea() {
// return the client area for this host
return CalcHostPlacement();
}
wxOrientation wxDockHost::GetOrientation() {
switch( dir_ ) {
case wxLEFT:
case wxRIGHT:
return wxVERTICAL;
break;
case wxTOP:
case wxBOTTOM:
return wxHORIZONTAL;
break;
case wxALL:
wxASSERT_MSG( false, _T("wxALL is not valid") );
break;
}
// failed
return wxHORIZONTAL;
}
wxDirection wxDockHost::GetDirection() {
return dir_;
}
wxRect wxDockHost::CalcHostPlacement( bool hitTest ) {
int area = areaSize_;
if( IsEmpty() ) {
// host is empty
if( !hitTest ) {
// no testing - therefore, no size
area = 0;
}
}
// lets work out where we would like to go
wxRect pcr = pLayoutManager_->GetDockArea();
switch( dir_ ) {
case wxLEFT:
pos_.x = pcr.x;
pos_.y = pcr.y;
size_.x = area;
size_.y = pcr.height;
break;
case wxTOP:
pos_.x = pcr.x;
pos_.y = pcr.y;
size_.x = pcr.width;
size_.y = area;
break;
case wxBOTTOM:
pos_.x = pcr.x;
pos_.y = pcr.GetBottom() - area;
size_.x = pcr.width;
size_.y = area;
break;
case wxRIGHT:
pos_.x = pcr.GetRight() - area;
pos_.y = pcr.y;
size_.x = area;
size_.y = pcr.height;
break;
case wxALL:
// n/a
break;
}
wxRect t( pos_, size_ );
return t;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -