📄 wxsdragwindow.cpp
字号:
#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 + -