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

📄 dockhost.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////
// 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 + -