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

📄 dockpanel.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        wxDockPanel.cpp
// Purpose:     wxDockPanel implementation.
// Author:      Mark McCormack
// Modified by:
// Created:     23/02/04
// RCS-ID:
// Copyright:
// Licence:     wxWindows license
/////////////////////////////////////////////////////////////////////////////

#include <wx/intl.h>
#include <wx/dockpanel.h>
#include <wx/dockhost.h>
#include <wx/dockwindow.h>
#include <wx/toolbutton.h>
#include <wx/gdi.h>
#include <wx/pane.h>
#include <wx/gripper.h>

#include <wx/sizer.h>
#include <wx/gdicmn.h>
#include <wx/settings.h>

// ----------------------------------------------------------------------------
// wxDockPanel constants & wx-macros
// ----------------------------------------------------------------------------

IMPLEMENT_DYNAMIC_CLASS( wxDockPanel, wxPanel )

BEGIN_EVENT_TABLE( wxDockPanel, wxPanel )
    EVT_SIZE( wxDockPanel::OnSize )
    EVT_BUTTON( 0, wxDockPanel::OnPaneClose )
    EVT_PANE_CLOSED( wxDockPanel::OnPaneClose )
    EVT_GRIP_DBLCLICK( wxDockPanel::OnGripDblClick )
    EVT_GRIP_LEFTDOWN( wxDockPanel::OnGripLeftDown )
    EVT_GRIP_LEFTUP( wxDockPanel::OnGripLeftUp )
#ifdef __WXGTK__
	EVT_LEFT_UP( wxDockPanel::OnLeftUp )
	EVT_MOTION( wxDockPanel::OnMouseMove )
#endif
END_EVENT_TABLE()

const unsigned int gripperSize = 14;
const unsigned int closeSize = 13;
const unsigned int closeBorder = 1;

// ----------------------------------------------------------------------------
// wxDockPanel implementation
// ----------------------------------------------------------------------------

void wxDockPanel::Init() {
    docked_ = false;
    mouseCaptured_ = false;
    pDockWindow_ = NULL;
    pDockHost_ = NULL;
    pClient_ = NULL;
    pStockClient_ = NULL;
    pPane_ = NULL;
    pClientSizer_ = NULL;
    pGripWindow_ = NULL;
    pCloseButton_ = NULL;
    area_ = 0;
    lockAreaValue_ = false;
    flags_ = 0x0000;
}

bool wxDockPanel::Create( wxWindow *parent, wxWindowID id, const wxString& name, unsigned int flags ) {
    wxASSERT(parent);
    // create ourselves
    bool r =  wxPanel::Create( parent, id, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxFULL_REPAINT_ON_RESIZE | wxCLIP_CHILDREN, name );
    flags_ = flags;

    // create default client area
    pClient_ = new wxPanel( this, 0, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN );
    pStockClient_ = pClient_;

    // create grip window
    pGripWindow_ = new wxGripWindow( this, GetOrientation(), wxGdi::wxGRIP_STYLE_HEADER );
    pGripWindow_->SetLabel( parent->GetTitle() );

    // create close window
    pCloseButton_ = new wxToolButton( this, 0 );
    pCloseButton_->SetDrawMargin( 1 );
    pCloseButton_->SetToolTip( _("Close") );

    return r;
}

void wxDockPanel::SetDockWindow( wxDockWindowBase * pOwner ) {
    pDockWindow_ = pOwner;

    // assign the cursor for hover over the gripper
    pGripWindow_->SetCursor( g_gdi.GetMoveCursor() );
}

wxDockWindowBase * wxDockPanel::GetDockWindow() {
    return pDockWindow_;
}

void wxDockPanel::SetDockedHost( wxDockHost * pDockHost ) {
    if( !pDockHost && pDockHost_ ) {
        // call update on host before clear
        pDockHost_->UpdateSize();
    }
    pDockHost_ = pDockHost;

    // internal update
    docked_ = pDockHost ? true : false;

    if( pDockHost ) {
        // call update on new host
        pDockHost->UpdateSize();
    }

    childUpdate();
}

wxDockHost * wxDockPanel::GetDockedHost() {
    return pDockHost_;
}

void wxDockPanel::OnSize( wxSizeEvent& WXUNUSED(event) ) {
    UpdateSize();
}

void wxDockPanel::OnPaneClose( wxCommandEvent& WXUNUSED(event) ) {
    wxASSERT(pDockWindow_);
    pDockWindow_->Remove();
}

void wxDockPanel::OnGripDblClick( wxMouseEvent& WXUNUSED(event) ) {
    // in gripper area
    wxDockWindow * pDockWindow = static_cast<wxDockWindow *>(GetDockWindow());
    wxASSERT(pDockWindow);
    wxLayoutManager * pLayoutManager = pDockWindow->GetLayoutManager();
    wxASSERT(pLayoutManager);

    // undock the panel back onto the owner window
    pLayoutManager->UndockWindow( GetDockWindow() );
}

void wxDockPanel::OnGripLeftDown( wxMouseEvent& event ) {
    wxDockWindow * pDockWindow = static_cast<wxDockWindow *>(GetDockWindow());
    wxASSERT(pDockWindow);

    // start dragging when docked
    wxPoint curPoint( event.GetPosition() );
    curPoint = ClientToScreen( curPoint );
#ifdef __WXGTK__
	if( docked_ ) {
	    pDockWindow->StartDragging( curPoint.x, curPoint.y, false );
		CaptureMouse();
	}
	else
#endif
    pDockWindow->StartDragging( curPoint.x, curPoint.y );
}

void wxDockPanel::OnGripLeftUp( wxMouseEvent& WXUNUSED(event) ) {
    wxDockWindowBase * pDockWindow = GetDockWindow();
    wxASSERT(pDockWindow);

#ifdef __WXGTK__
	if( docked_ ) {
		ReleaseMouse();
		pDockWindow->StopDragging( false );
	}
	else
#endif
    pDockWindow->StopDragging();
}

#ifdef __WXGTK__
void wxDockPanel::OnMouseMove( wxMouseEvent& event ) {
	// forward mouse move messages to owner
	ClientToScreen( &event.m_x, &event.m_y );
	pDockWindow_->ScreenToClient( &event.m_x, &event.m_y );
	pDockWindow_->OnMouseMove( event );
}

void wxDockPanel::OnLeftUp( wxMouseEvent& event ) {
	// stopping any dragging
	pDockWindow_->StopDragging();
}
#endif

void wxDockPanel::UpdateSize() {
    wxWindowList & children = GetChildren();
    if( children.GetCount() == 0 ) {
        return;
    }

    int tGripperSize = gripperSize;
    int tCloseSize = closeSize;

    wxOrientation orientation = GetOrientation();

    // layout
#if __WXGTK__
    if( docked_ && (pPane_ || flags_ & wxDPC_NO_CONTROLS) ) {
        // docked and pane/no controls required
#else
    if( !docked_ || pPane_ || (flags_ & wxDPC_NO_CONTROLS) ) {
#endif
        // undocked/with pane control/no controls required
        wxRect cr = GetClientRect();
        pClient_->SetSize( 0, 0, cr.width, cr.height );
		pClient_->Layout();
        pGripWindow_->SetSize( wxSize( 0,0 ) );
        pCloseButton_->SetSize( wxSize( 0,0 ) );
        }
    else {
#if __WXGTK__
        if( !docked_ ) {
            // undocked - show header
            orientation = wxVERTICAL;
        }
#endif
        // docked/or with internal controls
        wxRect cr = GetClientRect();
        if( orientation == wxHORIZONTAL ) {
            pClient_->SetSize( tGripperSize, 0, cr.width-tGripperSize, cr.height );
			pClient_->Layout();
            pGripWindow_->SetSize( 0, tCloseSize + closeBorder, tGripperSize, cr.height - tCloseSize - closeBorder );
            pGripWindow_->SetOrientation( wxHORIZONTAL );
            pCloseButton_->SetSize( 0, closeBorder, tGripperSize, tCloseSize );
        }
        else {
            pClient_->SetSize( 0, tGripperSize, cr.width, cr.height-tGripperSize );
			pClient_->Layout();
			pGripWindow_->SetSize( 0, 0, cr.width - tCloseSize - closeBorder, tGripperSize );
            pGripWindow_->SetOrientation( wxVERTICAL );
            pCloseButton_->SetSize( cr.width - tCloseSize - closeBorder, 0, tCloseSize, tGripperSize );
        }
    }
}

void wxDockPanel::SetClient( wxWindow * pClient, bool autoPane ) {
    if (pClient == pClient_) {
        // ignore if we already have the given client as our client
        return;
    }

    // if we do nothing else with it, at least hide the old client
    if( pClient_ ) {
        pClient_->Hide();
    }

    // replace current client
    if( !pClient ) {
        // remove user client
        wxASSERT(pStockClient_);
        pClient_ = pStockClient_;
    }
    else {
        wxPaneBase * pPotentialPane = (wxPane *)wxDynamicCast( pClient, wxPaneBase );
        if( autoPane && !pPotentialPane ) {
            // automatically add a pane client and then add the actual client to it (of course don't want to 'AutoPane'
            // actual pane controls)
            wxPane * pAutoPane = new wxPane( this, -1, pDockWindow_->GetTitle() );
            pClient->Reparent( pAutoPane );
            pAutoPane->SetClient( pClient );
            pClient_ = pAutoPane;
        }
        else {
		    // just add the client normally
            pClient->Reparent( this );
            pClient_ = pClient;
        }
    }
    wxASSERT(pClient_);
    pClient_->Show();

    // we know about wxPane clients
    pPane_ = (wxPane *)wxDynamicCast( pClient_, wxPaneBase );
    if( pPane_ ) {
        // size the pane to our client area
        wxSize size = GetClientSize();
        pPane_->SetSize( size );
    }

    childUpdate();

    UpdateSize();
}

wxWindow * wxDockPanel::GetClient() {
    wxASSERT(pClient_);
    return pClient_;
}

void wxDockPanel::AutoFitSingleChild() {
    if( pClientSizer_ ) return;    // already done

    // create simple 'expand all' sizer
    pClientSizer_ = new wxBoxSizer( wxHORIZONTAL );
    pClient_->SetSizer( pClientSizer_ );
    pClient_->SetAutoLayout( true );

    // apply to client child
    wxWindowList & children = pClient_->GetChildren();
    if( children.GetCount() != 1 ) {
        wxASSERT_MSG( false, _T("AutoFitSingleChild() only works when there is a single child!") );
    }
    wxWindowListNode * pChildNode = children.GetFirst();
    wxASSERT(pChildNode);
    wxWindow * pChild = pChildNode->GetData();
    wxASSERT(pChild);
    pClientSizer_->Add( pChild, 1, wxGROW|wxALL, 0 );
    pClient_->Layout();
}

wxOrientation wxDockPanel::GetOrientation() {
    // get from host
    if( pDockHost_ ) {
        return pDockHost_->GetOrientation();
    }

    // getOrientation() makes no sense when panel is not docked!
    return wxHORIZONTAL;
}

wxRect wxDockPanel::GetScreenArea() {
    // get the screen area for this panel
    wxASSERT(pDockHost_);
    wxRect r = GetRect();

    return pDockHost_->RectToScreen( r );
}

wxRect wxDockPanel::GetScreenArea( HostInfo &hi ) {
    wxRect screenRect = GetScreenArea();
    if( hi.placement == HIP_NONE ) {
        // return all panel area
        return screenRect;
    }

    if( GetOrientation() == wxHORIZONTAL ) {
        // return a horizontal area
        screenRect.width /= 2;
        if( hi.placement == HIP_BACK ) {
            screenRect.x += screenRect.width;
        }
    }
    else {
        // return a vertical area
        screenRect.height /= 2;
        if( hi.placement == HIP_BACK ) {
            screenRect.y += screenRect.height;
        }
    }
    return screenRect;
}

ePlacement wxDockPanel::TestForPlacement( int sx, int sy ) {
    ePlacement placement = HIP_NONE;
    wxRect screenRect = GetScreenArea();

    // work out which half of the panel a screen point is in
    if( GetOrientation() == wxHORIZONTAL ) {
        screenRect.width /= 2;
        placement = screenRect.Inside( sx, sy ) ? HIP_FRONT : HIP_BACK;
    }
    else {
        screenRect.height /= 2;
        placement = screenRect.Inside( sx, sy ) ? HIP_FRONT : HIP_BACK;
    }
    return placement;
}

int wxDockPanel::GetArea() {
    return area_;
}

void wxDockPanel::SetArea( int area ) {
    if( lockAreaValue_ ) {
        return;
    }
    area_ = area;
}

void wxDockPanel::LockAreaValue( bool state ) {
    lockAreaValue_ = state;
}

bool wxDockPanel::IsDocked() {
    return docked_;
}

void wxDockPanel::childUpdate() {
    // we know about wxPane clients
    if( pPane_ ) {
        pPane_->ShowHeader( docked_ ? true : false );
        pPane_->SetOrientation( GetOrientation() == wxVERTICAL ? wxHORIZONTAL : wxVERTICAL );
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -