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

📄 wxsdragwindow.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "wxsheaders.h"
#include "wxsdragwindow.h"

#include <wx/dcclient.h>
#include <wx/dcbuffer.h>
#include <configmanager.h>

#include "widget.h"
#include "wxsevent.h"
#include "wxsmith.h"
#include "resources/wxswindowres.h"

wxsDragWindow::wxsDragWindow(wxWindow* Cover,wxsWidget* Wdg,const wxSize& Size):
    wxControl(Cover,-1,wxDefaultPosition,Size,wxNO_BORDER|wxSTAY_ON_TOP),
    RootWidget(Wdg), CurDragPoint(NULL), CurDragWidget(NULL), RefreshTimer(this,1),
    BackFetchTimer(this,2), Background(NULL), BackFetchMode(true), PaintAfterFetch(false),
    BlockTimerRefresh(false), BlockWidgetSelect(false),
    DragParent(NULL), DragParentBitmap(NULL),
    DragTarget(NULL), DragTargetBitmap(NULL)
{
	RefreshTimer.Start(50);
	Background = new wxBitmap(GetSize().GetWidth(),GetSize().GetHeight());
}

wxsDragWindow::~wxsDragWindow()
{
	ClearDragPoints();
	delete Background;
	if ( DragTargetBitmap ) delete DragTargetBitmap;
	if ( DragParentBitmap ) delete DragParentBitmap;
}

void wxsDragWindow::OnPaint(wxPaintEvent& event)
{
    wxWindow* Wnd = this;
    wxPaintDC DC(Wnd);
	if ( !BackFetchMode || PaintAfterFetch )
	{
        AddGraphics(DC);
        PaintAfterFetch = false;
        BlockTimerRefresh = false;
	}
	else
	{
	    BlockTimerRefresh = true;
	    // When in background fetch mode, this widget is hidden in order
	    // to fetch background image
	    Hide();
	    FetchArea.Union(GetUpdateRegion());
		BackFetchTimer.Start(wxsDWFetchDelay,true);
	}
}

void wxsDragWindow::TimerRefresh(wxTimerEvent& event)
{
    if ( BlockTimerRefresh ) return;
    wxClientDC DC(this);
	AddGraphics(DC);
}

void wxsDragWindow::OnEraseBack(wxEraseEvent& event)
{
    if ( !BackFetchMode || PaintAfterFetch )
    {
        wxDC& DC = *event.GetDC();
        DC.DrawBitmap(*Background,0,0,false);
    }
}

void wxsDragWindow::OnMouse(wxMouseEvent& event)
{
    DragPointData* NewDragPoint = NULL;
    wxsWidget* NewDragWidget = NULL;
    int MouseX = event.GetX();
    int MouseY = event.GetY();
    wxsWidget* UnderCursor = FindWidgetAtPos(MouseX,MouseY,RootWidget);

    // If we're out of window
    if ( !UnderCursor )
    {
        UnderCursor = RootWidget;
        // Small trick - changing to probably best container
        while ( UnderCursor->GetChildCount()==1 &&
                UnderCursor->GetChild(0)->IsContainer() )
        {
            UnderCursor = UnderCursor->GetChild(0);
        }
    }

    // Posting this event to previews
    ForwardMouseEventToPreview(event,UnderCursor);

    // Disabling background fetch mode when dragging
    BackFetchMode = !event.Dragging();

    BlockTimerRefresh = event.Dragging();

    // Searching for items covered by mouse
    NewDragPoint = FindCoveredPoint(MouseX,MouseY);
    if ( !NewDragPoint ) NewDragPoint = FindCoveredEdge(MouseX,MouseY);
    if ( !NewDragPoint ) NewDragWidget = UnderCursor;

    // Updating drag assist
    UpdateAssist(event.Dragging(),UnderCursor);

	// Processing events
         if ( event.LeftUp()   ) DragFinish(UnderCursor);
    else if ( event.Dragging() ) DragProcess(MouseX,MouseY,UnderCursor);
    else if ( event.LeftDown() ) DragInit(NewDragPoint,NewDragWidget,event.ControlDown(),MouseX,MouseY);

    // Changing cursor
    UpdateCursor(event.Dragging(),NewDragPoint,NewDragWidget);
}

void wxsDragWindow::ForwardMouseEventToPreview(wxMouseEvent& event,wxsWidget* Widget)
{
    if ( Widget )
    {
    	int WidgetRelativeX = event.GetX();
    	int WidgetRelativeY = event.GetY();
    	ClientToScreen(&WidgetRelativeX,&WidgetRelativeY);
    	Widget->GetPreview()->ScreenToClient(&WidgetRelativeX,&WidgetRelativeY);
    	event.m_x = WidgetRelativeX;
    	event.m_y = WidgetRelativeY;
    	Widget->PreviewMouseEvent(event);
    }
}

wxsDragWindow::DragPointData* wxsDragWindow::FindCoveredPoint(int MouseX,int MouseY)
{
    DragPointData* Found = NULL;
    for ( DragPointsI i = DragPoints.begin(); i!=DragPoints.end(); ++i )
    {
    	if ( !IsVisible((*i)->Widget) ) continue;
        int PosX = (*i)->PosX - DragBoxSize/2;
        int PosY = (*i)->PosY - DragBoxSize/2;

        if ( MouseX >= PosX &&
             MouseY >= PosY &&
             MouseX <= PosX + DragBoxSize &&
             MouseY <= PosY + DragBoxSize )
        {
            Found = *i;
            if ( !Found->NoAction ) break;
        }
    }
    return Found;
}

wxsDragWindow::DragPointData* wxsDragWindow::FindCoveredEdge(int MouseX,int MouseY)
{
    DragPointData* Found = NULL;

    for ( DragPointsI i = DragPoints.begin(); i!=DragPoints.end(); ++i )
    {
        DragPointData* DPD = *i;

        if ( !IsVisible(DPD->Widget) ) continue;

        switch ( DPD->Type )
        {
            case Top:
            case Btm:
                {
                    int PosX1, PosX2;
                    int SizeW, SizeH;
                    DPD->Widget->GetPreview()->GetSize(&SizeW,&SizeH);
                    if ( SizeH < DragBoxSize ) break; // There must be place to drag this widget
                    FindAbsolutePosition(DPD->Widget,&PosX1,&PosX2);
                    ScreenToClient(&PosX1,&PosX2);
                    PosX2 = PosX1 + SizeW;
                    int PosY = DPD->PosY - DragBoxSize / 2;

                    if ( MouseX >= PosX1 &&
                         MouseX <= PosX2 &&
                         MouseY >= PosY &&
                         MouseY <= PosY + DragBoxSize )
                    {
                        Found = DPD;
                    }
                }
                break;

            case Left:
            case Right:
                {
                    int PosY1, PosY2;
                    int SizeW, SizeH;
                    DPD->Widget->GetPreview()->GetSize(&SizeW,&SizeH);
                    if ( SizeW < DragBoxSize ) break; // There must be place to drag this widget
                    FindAbsolutePosition(DPD->Widget,&PosY1,&PosY2);
                    ScreenToClient(&PosY1,&PosY2);

                    PosY1 = PosY2;
                    PosY2 = PosY1 + SizeH;
                    int PosX = DPD->PosX - DragBoxSize / 2;

                    if ( MouseY >= PosY1 &&
                         MouseY <= PosY2 &&
                         MouseX >= PosX &&
                         MouseX <= PosX + DragBoxSize )
                    {
                        Found = DPD;
                    }
                }
                break;

            default:
                break;
        }

        if ( Found && !Found->NoAction ) break;
    }

    return Found;
}

wxsDragWindow::DragPointData* wxsDragWindow::FindLeftTop(wxsWidget* Widget)
{
    for ( DragPointsI i = DragPoints.begin(); i!=DragPoints.end(); ++i )
    {
        if ( (*i)->Widget == Widget )
        {
            return (*i)->WidgetPoints[LeftTop];
        }
    }
    return NULL;
}

void wxsDragWindow::DragInit(wxsDragWindow::DragPointData* NewDragPoint,wxsWidget* NewDragWidget,bool MultipleSel,int MouseX,int MouseY)
{
    if ( NewDragPoint || NewDragWidget )
    {
        DragMouseBegX = MouseX;
        DragMouseBegY = MouseY;
        DragDistanceSmall = true;
        //CaptureMouse();

        if ( NewDragWidget )
        {
            if ( MultipleSel ) { GrayDragPoints (); }
            else               { ClearDragPoints(); }

            CurDragWidget = NewDragWidget;
            CurDragPoint = FindLeftTop(CurDragWidget);

            if ( !CurDragPoint )
            {
                // Haven't found drag point for this widget - new points will be added
                CurDragPoint = BuildDragPoints(CurDragWidget);
                BlackDragPoints(CurDragWidget);
            }
            else
            {
                // This widget is already selected - only main selected widget will be changed
                GrayDragPoints();
                BlackDragPoints(CurDragWidget);
            }
            SelectWidget(CurDragWidget);
            UpdateGraphics();
        }
        else
        {
            // CurDragWidget == NULL means we're moving drag point only, not whole widget
            CurDragWidget = NULL;
            CurDragPoint = NewDragPoint;
        }

        for ( DragPointsI i = DragPoints.begin(); i!=DragPoints.end(); ++i )
        {
            // Copying initial position data
            DragPointData* DPD = *i;
            DPD->DragInitPosX = DPD->PosX;
            DPD->DragInitPosY = DPD->PosY;
        }

    }
    else
    {
        // Nothing selected
        CurDragPoint = NULL;
        CurDragWidget = NULL;
    }
}

void wxsDragWindow::DragProcess(int MouseX,int MouseY,wxsWidget* UnderCursor)
{
    if ( !CurDragPoint || CurDragPoint->NoAction ) return;
    int ShiftX = MouseX - DragMouseBegX;
    int ShiftY = MouseY - DragMouseBegY;

    if ( abs(ShiftX) + abs(ShiftY) >= MinDragDistance ) DragDistanceSmall = false;
    if ( DragDistanceSmall ) return;

    // Creating local array of pointers to all drag points
    DragPointData* WidgetPoints[DragBoxTypeCnt];
    memcpy(WidgetPoints,CurDragPoint->WidgetPoints,sizeof(WidgetPoints));

    // Shifting corner points

    #define DoShiftX(Placement) WidgetPoints[Placement]->PosX = WidgetPoints[Placement]->DragInitPosX + ShiftX
    #define DoShiftY(Placement) WidgetPoints[Placement]->PosY = WidgetPoints[Placement]->DragInitPosY + ShiftY

    if ( CurDragWidget )
    {
        // Snapping to sizer area
        if ( UnderCursor && !UnderCursor->IsContainer() &&

             (wxsDWAssistType == wxsDTNone) )
        {
            wxsWidget* Parent = UnderCursor->GetParent();
            if ( Parent && Parent->GetInfo().Sizer )
            {
                // Changing parent to sizer - current dragged widget
                // will be placed in place of UnderCursor
                ShiftX = 0;
                ShiftY = 0;
                UnderCursor->GetPreview()->ClientToScreen(&ShiftX,&ShiftY);
                CurDragWidget->GetPreview()->ScreenToClient(&ShiftX,&ShiftY);
            }
        }

        // Standard proceedure - just shifting everything
        for ( DragPointsI i = DragPoints.begin(); i != DragPoints.end(); ++i )
        {
            (*i)->PosX = (*i)->DragInitPosX + ShiftX;
            (*i)->PosY = (*i)->DragInitPosY + ShiftY;
        }

        RebuildEdgePoints(WidgetPoints);
    }
    else
    {
        // Shifting corners
        switch ( CurDragPoint->Type )
        {
            case LeftTop:
                DoShiftX(LeftTop);
                DoShiftY(LeftTop);
                DoShiftY(RightTop);
                DoShiftX(LeftBtm);
                break;

            case Top:
                DoShiftY(LeftTop);
                DoShiftY(RightTop);
                break;

            case RightTop:
                DoShiftY(LeftTop);
                DoShiftX(RightTop);
                DoShiftY(RightTop);
                DoShiftX(RightBtm);
                break;

            case Left:
                DoShiftX(LeftTop);
                DoShiftX(LeftBtm);
                break;

            case Right:
                DoShiftX(RightTop);
                DoShiftX(RightBtm);
                break;

            case LeftBtm:
                DoShiftX(LeftTop);
                DoShiftX(LeftBtm);
                DoShiftY(LeftBtm);
                DoShiftY(RightBtm);
                break;

            case Btm:
                DoShiftY(LeftBtm);
                DoShiftY(RightBtm);
                break;

            case RightBtm:
                DoShiftX(RightTop);
                DoShiftY(LeftBtm);
                DoShiftX(RightBtm);
                DoShiftY(RightBtm);
                break;

            default:;
        }

        RebuildEdgePoints(WidgetPoints);
    }

    #undef DoShiftX
    #undef DoShiftY

    UpdateGraphics();
}

void wxsDragWindow::DragFinish(wxsWidget* UnderCursor)
{
    if ( HasCapture() ) ReleaseMouse();
    if ( !CurDragPoint || CurDragPoint->NoAction || DragDistanceSmall ) return;

⌨️ 快捷键说明

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