⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dockhost.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}

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 + -