📄 dockhost.cpp
字号:
}
bool wxDockHost::IsEmpty() {
return getAssetCount() == 0;
}
bool wxDockHost::TestForPanel( int sx, int sy, HostInfo &hi ) {
if( IsEmpty() ) {
// host is empty
wxRect hRect = GetScreenArea();
if( hRect.Inside( sx, sy ) ) {
hi = this;
return true;
}
}
wxWindowList & children = GetChildren();
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 ) {
wxRect localRect = pPanel->GetRect();
wxRect screenRect = RectToScreen( localRect );
if( screenRect.Inside( sx, sy ) ) {
// hit-test success on panel
hi = this;
hi.pPanel = pPanel;
hi.placement = pPanel->TestForPlacement( sx, sy );
return true;
}
}
}
return false;
}
wxRect wxDockHost::RectToScreen( wxRect &rect ) {
// convert an child rect to screen rect
wxRect tRect( rect );
wxPoint pos = ClientToScreen( tRect.GetPosition() );
tRect.SetPosition( pos );
return tRect;
}
void wxDockHost::RecalcPanelAreas() {
// get the client window
wxRect cr = GetClientRect();
// set the avaialble panel area
int hostArea = GetOrientation() == wxHORIZONTAL ? cr.width : cr.height;
int splittersArea = (numSplitters_ * SPLITTER_SIZE);
if( !lockPanelValue_ ) {
panelArea_ = (hostArea - splittersArea);
}
wxWindowList & children = GetChildren();
int childCount = children.GetCount();
for( int c=0; c<childCount; c++ ) {
// get child
wxWindowListNode * pChildNode = children.Item( c );
wxASSERT(pChildNode);
wxWindow * pChild = pChildNode->GetData();
wxASSERT(pChild);
// what is it?
wxDockPanel * pPanel = wxDynamicCast( pChild, wxDockPanel );
if( pPanel ) {
// set the taken panel area
int size = (GetOrientation() == wxHORIZONTAL) ? pPanel->GetRect().width : pPanel->GetRect().height;
pPanel->SetArea( size );
}
}
}
void wxDockHost::OnCalculateLayout( wxCalculateLayoutEvent &event ) {
// check for a 'query only' event
bool queryMode = false;
if( (event.GetFlags() & wxLAYOUT_QUERY) != 0 ) {
queryMode = true;
}
wxRect areaRect = event.GetRect();
// if we are the first host then save the area as the 'docking area'
if( pLayoutManager_->IsPrimaryDockHost( this ) ) {
pLayoutManager_->SetDockArea( areaRect );
}
if( IsEmpty() ) {
// we have no effect when we are empty
SetSize( 0,0,0,0 );
return;
}
internalSizeEvent_ = true;
// chew off a bit of area for ourselves from the layout area
switch( GetDirection() ) {
case wxLEFT:
if( !queryMode ) SetSize( areaRect.GetX(), areaRect.GetY(), areaSize_, areaRect.GetHeight() );
areaRect.SetX( areaRect.GetX() + areaSize_ );
areaRect.SetWidth( areaRect.GetWidth() - areaSize_ );
break;
case wxTOP:
if( !queryMode ) SetSize( areaRect.GetX(), areaRect.GetY(), areaRect.GetWidth(), areaSize_ );
areaRect.SetY( areaRect.GetY() + areaSize_ );
areaRect.SetHeight( areaRect.GetHeight() - areaSize_ );
break;
case wxBOTTOM:
if( !queryMode ) SetSize( areaRect.GetX(), areaRect.GetY() + (areaRect.GetHeight() - areaSize_), areaRect.GetWidth(), areaSize_ );
areaRect.SetHeight( areaRect.GetHeight() - areaSize_ );
break;
case wxRIGHT:
if( !queryMode ) SetSize( areaRect.GetX() + (areaRect.GetWidth() - areaSize_), areaRect.GetY(), areaSize_, areaRect.GetHeight() );
areaRect.SetWidth( areaRect.GetWidth() - areaSize_ );
break;
break;
case wxALL:
// n/a
break;
}
event.SetRect( areaRect );
internalSizeEvent_ = false;
}
void wxDockHost::SettingsChanged() {
unsigned int dwFlags = pLayoutManager_->GetFlags();
bool liveUpdate = (dwFlags & wxDWF_LIVE_UPDATE) == wxDWF_LIVE_UPDATE;
bool splitterBorders = (dwFlags & wxDWF_SPLITTER_BORDERS) == wxDWF_SPLITTER_BORDERS;
unsigned int flags = liveUpdate ? wxESF_LIVE_UPDATE : 0;
flags |= splitterBorders ? wxESF_DRAW_GRIPPER : 0;
// inform our splitters
for( unsigned int i=0; i<splitters_.GetCount(); ++i ) {
wxExSplitter * pSplitter = splitters_[i];
pSplitter->SetFlags( flags );
}
pSizingSplitter_->SetFlags( flags );
splitterFlags_ = flags;
}
void wxDockHost::calcPanelPlacement( bool useProportions ) {
updateSplitters();
wxWindowList & children = GetChildren();
int childCount = children.GetCount();
if( IsEmpty() ) {
return;
}
// get the client window
wxRect cr = GetClientRect();
int areaRemaining = GetOrientation() == wxHORIZONTAL ? cr.width : cr.height;
int splittersArea = (numSplitters_ * SPLITTER_SIZE);
int panelArea = (areaRemaining - splittersArea);
int panelAllowance = panelArea;
int areaPos = 0;
int panelCount = 0;
for( int c=0; c<childCount; c++ ) {
// get child
wxWindowListNode * pChildNode = children.Item( c );
wxASSERT(pChildNode);
wxWindow * pChild = pChildNode->GetData();
wxASSERT(pChild);
if( pChild == pSizingSplitter_ ) {
// ignore host's own size splitter
continue;
}
// what is it?
wxDockPanel * pPanel = wxDynamicCast( pChild, wxDockPanel );
int childChunk = 0;
if( !pPanel ) {
// is a splitter
childChunk = SPLITTER_SIZE;
}
else {
panelCount++;
// give the panel it's required proportion of the available size
if( panelCount < numPanels_ ) {
if( useProportions ) {
// use proportions
float proportion = (float)pPanel->GetArea() / panelArea_;
childChunk = (int)((float)proportion * panelArea);
}
else {
// use absolutes
childChunk = pPanel->GetArea();
}
panelAllowance -= childChunk;
}
else {
// last chunk gets whatever is left over
childChunk = panelAllowance;
panelAllowance = 0;
}
}
// adjust size
if( GetOrientation() == wxHORIZONTAL ) {
int top = (dir_ == wxTOP) ? 0 : SPLITTER_SIZE;
int height = cr.height - SPLITTER_SIZE;
pChild->SetSize( areaPos, top, childChunk, height );
}
else {
int left = (dir_ == wxLEFT) ? 0 : SPLITTER_SIZE;
int width = cr.width - SPLITTER_SIZE;
pChild->SetSize( left, areaPos, width, childChunk );
}
areaPos += childChunk + 1; // XXX: not sure if we should have to do this extra increment?
}
assert(pSizingSplitter_);
// adjust size splitter
if( GetOrientation() == wxHORIZONTAL ) {
int areaHeight = cr.height - SPLITTER_SIZE;
int splitterTop = (dir_ == wxTOP) ? areaHeight : 0;
pSizingSplitter_->SetSize( 0, splitterTop, cr.width, SPLITTER_SIZE );
}
else {
int areaWidth = cr.width - SPLITTER_SIZE;
int splitterLeft = (dir_ == wxLEFT) ? areaWidth : 0;
pSizingSplitter_->SetSize( splitterLeft, 0, SPLITTER_SIZE, cr.height );
}
if( lockPanelValue_ ) {
// recalc on load
RecalcPanelAreas();
}
}
int wxDockHost::getAssetCount() {
wxWindowList & children = GetChildren();
int childCount = children.GetCount();
// removes 1 for the host's own splitter
return childCount-1;
}
void wxDockHost::updateSplitters() {
// adds/removes splitters dynamically as required
wxWindowList & children = GetChildren();
int childCount = children.GetCount();
eChildType lastChildType = CT_NONE;
wxWindow * pLastChild = NULL;
numPanels_ = 0;
numSplitters_ = 0;
wxWindowList newChildList;
SplitterList toDeleteSplitters;
splitters_.Clear();
int c;
for( c=0; c<childCount; c++ ) {
// get child
wxWindowListNode * pChildNode = children.Item( c );
wxASSERT(pChildNode);
wxWindow * pChild = pChildNode->GetData();
wxASSERT(pChild);
if( pChild == pSizingSplitter_ ) {
newChildList.Append( pSizingSplitter_ );
// ignore host's own size splitter
continue;
}
// what is it?
wxDockPanel * pPanel = wxDynamicCast( pChild, wxDockPanel );
if( pPanel ) {
if( lastChildType == CT_PANEL ) {
// we need to add a splitter
wxASSERT(pLastChild);
wxExSplitter * pSplitter = new wxExSplitter( this, GetOrientation(), pLastChild, pPanel, splitterFlags_ );
newChildList.Append( pSplitter );
numSplitters_++;
splitters_.Append( pSplitter );
}
// add original panel
newChildList.Append( pPanel );
numPanels_++;
// save lasts
lastChildType = CT_PANEL;
pLastChild = (wxWindow *)pPanel;
}
else {
if( lastChildType == CT_SPLITTER || c == 1 || c == (childCount-1) ) {
// we need to remove a splitter
wxExSplitter * pPanelSplitter = wxDynamicCast( pChildNode->GetData(), wxExSplitter );
toDeleteSplitters.Append( pPanelSplitter );
}
else {
// add original splitter
pLastChild = wxDynamicCast( pChildNode->GetData(), wxExSplitter );
newChildList.Append( pLastChild );
numSplitters_++;
splitters_.Append( (wxExSplitter *)pLastChild );
}
// save lasts
lastChildType = CT_SPLITTER;
}
}
// delete unrequired splitters
for ( SplitterList::Node *node = toDeleteSplitters.GetFirst(); node; node = node->GetNext() ) {
delete node->GetData();
}
// update window list
children = newChildList;
// make sure splitters are connected to the correct panels
int newChildCount = children.GetCount();
for( c=0; c<newChildCount; c++ ) {
// get child
wxWindowListNode * pChildNode = children.Item( c );
wxASSERT(pChildNode);
wxExSplitter * pPanelSplitter = wxDynamicCast( pChildNode->GetData(), wxExSplitter );
if( pPanelSplitter == pSizingSplitter_ ) {
// ignore host's own size splitter
continue;
}
if( pPanelSplitter ) {
// get panels to either side of the splitter
wxASSERT(c>1);
wxASSERT(c<(newChildCount-1));
wxDockPanel * pFrontPanel = wxDynamicCast( children.Item( c-1 )->GetData(), wxDockPanel );
wxASSERT(pFrontPanel);
wxDockPanel * pBackPanel = wxDynamicCast( children.Item( c+1 )->GetData(), wxDockPanel );
wxASSERT(pBackPanel);
pPanelSplitter->SetWindows( pFrontPanel, pBackPanel );
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -