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

📄 exsplitter.cpp

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

#include <wx/exsplitter.h>
#include <wx/gdi.h>
#include <wx/dockhost.h>

#include <wx/dcscreen.h>

// ----------------------------------------------------------------------------
// wxExSplitter implementation
// ----------------------------------------------------------------------------

IMPLEMENT_CLASS( wxExSplitter, wxWindow )
DEFINE_LOCAL_EVENT_TYPE( wxEVT_SPLITTER_MOVED )

BEGIN_EVENT_TABLE( wxExSplitter, wxWindow )
    EVT_LEFT_DOWN( wxExSplitter::OnLeftDown )
    EVT_MOTION( wxExSplitter::OnMouseMove )
    EVT_LEFT_UP( wxExSplitter::OnLeftUp )
    EVT_ERASE_BACKGROUND( wxExSplitter::OnErase )
    EVT_PAINT( wxExSplitter::OnPaint )
END_EVENT_TABLE()

void wxExSplitter::Init() {
    memset(&pWindow_, 0, sizeof(pWindow_));
    pOwner_ = NULL;
    bounded_ = false;
    dragging_ = false;
    minSize_ = MINIMUM_WINDOW_SIZE;
    flags_ = 0x0000;
    startPosition_.x = startPosition_.y = 0;
}

bool wxExSplitter::Create( wxWindow * parent, wxOrientation orientation, wxWindow * win1, wxWindow * win2, unsigned int flags ) {
    wxASSERT(parent);
    bool r = wxWindow::Create( parent, -1, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE );

    // assign
    pOwner_ = parent;
    pWindow_[0] = win1;
    pWindow_[1] = win2;
    orientation_ = orientation;
    flags_ = flags;

    // set the type of cursor we need
    if( orientation_ == wxHORIZONTAL ) {
        SetCursor( g_gdi.GetHSplitCursor() );
    }
    else {
        SetCursor( g_gdi.GetVSplitCursor() );
    }

    return r;
}

void wxExSplitter::SetWindows( wxWindow * pWin1, wxWindow * pWin2 ) {
    // set windows
    pWindow_[0] = pWin1;
    pWindow_[1] = pWin2;
}

void wxExSplitter::SetFlags( unsigned int flags ) {
    flags_ = flags;
}

void wxExSplitter::OnLeftDown( wxMouseEvent& event ) {
    // take origin
    startPosition_ = ClientToScreen( event.GetPosition() );
    dragging_ = true;
    
    // take snapshots
    startRect_[0] = pWindow_[0] ? pWindow_[0]->GetRect() : wxRect();
    startRect_[1] = pWindow_[1] ? pWindow_[1]->GetRect() : wxRect();
    startRectUs_ = GetRect();
    endRectUs_ = startRectUs_;
    
    // check boundaries
    SetBoundaries();

    // draw start position
	lastDrawnRect_ = wxRect();
#ifndef __WXGTK__
	// XXX: work-around for GTK, due to GTK repainting over our initial screen XOR rectangle, it is best for
	// now to not draw the initial XOR rectangle under this platform
    draw( startRectUs_ );
#endif	
    
    // we want all further mouse events
    CaptureMouse();
}

void wxExSplitter::OnMouseMove( wxMouseEvent& event ) {
    if( dragging_ ) {
        wxPoint pos = ClientToScreen( event.GetPosition() );

        if (bounded_) {
            // check for boundary crossing
            if ((pos.x < boundary[0].x) ||
                (pos.x > boundary[1].x) ||
                (pos.y < boundary[0].y) ||
                (pos.y > boundary[1].y)) {
                return;
            }
        }

        wxRect r0 = startRect_[0], r1 = startRect_[1], r = startRectUs_;
        if( orientation_ == wxHORIZONTAL ) {
            // resize in the horizontal
            int dx = pos.x - startPosition_.x;
            if( pWindow_[0] && (r0.width + dx) < minSize_ ) dx = minSize_ - r0.width;
            if( pWindow_[1] && (r1.width - dx) < minSize_ ) dx = r1.width - minSize_;

            r0.width += dx;
            r1.width -= dx;
            r1.x += dx;
            r.x += dx;
        }
        else {
            // resize in the vertical
            int dy = pos.y - startPosition_.y;
            if( pWindow_[0] && (r0.height + dy) < minSize_ ) dy = minSize_ - r0.height;
            if( pWindow_[1] && (r1.height - dy) < minSize_ ) dy = r1.height - minSize_;

            r0.height += dy;
            r1.height -= dy;
            r1.y += dy;
            r.y += dy;
        }
        
        // perform the actual re-sizes
        if( flags_ & wxESF_LIVE_UPDATE ) {
            // update now
            if( pWindow_[0] ) pWindow_[0]->SetSize( r0 );
            if( pWindow_[1] ) pWindow_[1]->SetSize( r1 );
            if( !pWindow_[0] ) {
                // don't alter x/y for right/bottom single edge cases
                r.x = startRectUs_.x;
                r.y = startRectUs_.y;
            }
            SetSize( r );

            // generate size change event
            wxCommandEvent e( wxEVT_SPLITTER_MOVED, GetId() );
            e.SetEventObject( this );
            GetEventHandler()->ProcessEvent( e );
        }
        else {
            // draw now...
			if( lastDrawnRect_.GetWidth() && lastDrawnRect_.GetHeight() ) {
            	draw( lastDrawnRect_ );
			}
            draw( r );
            
            // ...update later
            endRect_[0] = r0;
            endRect_[1] = r1;
            endRectUs_ = r;
            if( !pWindow_[0] ) {
                // don't alter x/y for right/bottom single edge cases
                endRectUs_.x = startRectUs_.x;
                endRectUs_.y = startRectUs_.y;
            }
        }
    }
}

void wxExSplitter::OnErase( wxEraseEvent& WXUNUSED(event) ) {
    // skip erase
}

void wxExSplitter::OnPaint( wxPaintEvent& WXUNUSED(event) ) {
    wxPaintDC dc(this);
 
    wxRect cr = GetClientRect();
	
    // draw physical splitter image
	if( flags_ & wxESF_DRAW_GRIPPER ) {
		g_gdi.DrawSplitter( dc, cr, orientation_ );
	}
    else {
		g_gdi.DrawBackground( dc, cr );
    }
}

void wxExSplitter::OnLeftUp( wxMouseEvent& WXUNUSED(event) ) {
    if( !dragging_ ) return;

    // release mouse
    ReleaseMouse();
    dragging_ = false;

    // need to update here?
    if( !(flags_ & wxESF_LIVE_UPDATE) ) {
        // erase end position
        draw( lastDrawnRect_ );

        if( endRectUs_.GetWidth() || endRectUs_.GetHeight() ) {
            // update associated windows
            for( int i=0; i<SPLITTER_WINDOWS; i++ ) {
                // make sure window pointer valid
                if( pWindow_[i] ) {
                    // make sure new size rectangle valid
                    if( endRect_[i].GetWidth() || endRect_[i].GetHeight() ) {
                        pWindow_[i]->SetSize( endRect_[i] );
                    }
                }
            }
            SetSize( endRectUs_ );        
        }
    }

    // generate size change event
    wxCommandEvent e(wxEVT_SPLITTER_MOVED, GetId());
    e.SetEventObject(this);
    GetEventHandler()->ProcessEvent(e);
}

void wxExSplitter::draw( wxRect r ) {
    if( flags_ & wxESF_LIVE_UPDATE ) return;
    
    // draw our position onto the screen [XOR]
    wxScreenDC dc;

    wxRect screenRect = r;
    screenRect.SetPosition( pOwner_->ClientToScreen( screenRect.GetPosition() ) );
    g_gdi.DrawPattern( dc, screenRect );
    lastDrawnRect_ = r;
}

void wxExSplitter::SetBoundaries() {
    bounded_ = false;

    if ((pWindow_[0] && pWindow_[1]) || (!pWindow_[0] && !pWindow_[1])) {
        return;
    }

    wxDockHost* dh = wxDynamicCast(pOwner_, wxDockHost);

    if (!dh || (dh -> GetSizingSplitter() != this)) {
        return;
    }

    bounded_ = true;

    wxWindow* parent = dh -> GetParent();
    wxLayoutManager* pLayoutManager = dh -> GetLayoutManager();
    wxSize clientSize = parent -> GetClientSize();

    if (pLayoutManager) {
        wxRect dockArea = pLayoutManager->GetDockArea();
        boundary[0] = dockArea.GetPosition();
        clientSize = dockArea.GetSize();
    }
    else {
        boundary[0] = wxPoint(0, 0);
        clientSize = parent->GetClientSize();
    }
    boundary[0] = parent->ClientToScreen(boundary[0]);

    boundary[0].x += SPLITTER_SIZE;
    boundary[0].y += SPLITTER_SIZE;

    boundary[1] = boundary[0];

    boundary[1].x += (clientSize.GetWidth() - (SPLITTER_SIZE * 2));
    boundary[1].y += (clientSize.GetHeight() - (SPLITTER_SIZE * 2));

    if (!pLayoutManager) {
        return;
    }

    // search other dockhosts with this orientation
    wxDirection ldir = wxALL;

    switch (dh -> GetDirection()) {
    case wxLEFT   :
        ldir = wxRIGHT;  break;
    case wxRIGHT  :
        ldir = wxLEFT;   break;
    case wxTOP    :
        ldir = wxBOTTOM; break;
    case wxBOTTOM :
        ldir = wxTOP;    break;
    default       :
        ldir = wxALL;    break;
    }

    if (ldir == wxALL) {
        return;
    }

    wxDockHost* dockhost = pLayoutManager -> GetDockHost(ldir);
    if (dockhost && !dockhost -> IsEmpty()) {
        wxRect hr = dockhost -> GetScreenArea();

        switch (ldir) {
        case wxLEFT   :
            boundary[0].x = hr.GetRight() + SPLITTER_SIZE; break;
        case wxRIGHT  :
            boundary[1].x = hr.GetLeft() - SPLITTER_SIZE; break;
        case wxTOP    :
            boundary[0].y = hr.GetBottom() + SPLITTER_SIZE; break;
        case wxBOTTOM :
            boundary[1].y = hr.GetTop() - SPLITTER_SIZE; break;
        case wxALL    :
            wxASSERT(false); break;
        }
    }
}

⌨️ 快捷键说明

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