📄 bardragpl.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: bardragpl.cpp
// Purpose: cbBarDragPlugin implementation
// Author: Aleksandras Gluchovas
// Modified by:
// Created: 23/09/98
// RCS-ID: $Id: bardragpl.cpp,v 1.10 2005/09/23 12:47:41 MR Exp $
// Copyright: (c) Aleksandras Gluchovas
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/fl/bardragpl.h"
#define POS_UNDEFINED -32768
// helpers, FOR NOW:: static
static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
{
if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
return true;
return false;
}
static inline bool rect_contains_point( const wxRect& rect, int x, int y )
{
return ( x >= rect.x &&
y >= rect.y &&
x < rect.x + rect.width &&
y < rect.y + rect.height );
}
/***** Implementation for class cbBarDragPlugin *****/
IMPLEMENT_DYNAMIC_CLASS( cbBarDragPlugin, cbPluginBase )
BEGIN_EVENT_TABLE( cbBarDragPlugin, cbPluginBase )
//EVT_PL_LEFT_DOWN ( cbBarDragPlugin::OnLButtonDown )
EVT_PL_LEFT_UP ( cbBarDragPlugin::OnLButtonUp )
EVT_PL_MOTION ( cbBarDragPlugin::OnMouseMove )
EVT_PL_DRAW_HINT_RECT ( cbBarDragPlugin::OnDrawHintRect )
EVT_PL_START_BAR_DRAGGING ( cbBarDragPlugin::OnStartBarDragging )
EVT_PL_LEFT_DCLICK ( cbBarDragPlugin::OnLDblClick )
END_EVENT_TABLE()
cbBarDragPlugin::cbBarDragPlugin(void)
: mBarDragStarted ( false ),
mCanStick ( true ),
mpScrDc ( NULL ),
mpCurCursor ( NULL ),
mpDraggedBar ( NULL ),
mInClientHintBorder( 4 )
{}
cbBarDragPlugin::cbBarDragPlugin( wxFrameLayout* pPanel, int paneMask )
: cbPluginBase( pPanel, paneMask ),
mBarDragStarted ( false ),
mCanStick ( true ),
mpScrDc ( NULL ),
mpCurCursor ( NULL ),
mpDraggedBar ( NULL ),
mInClientHintBorder( 4 )
{}
cbBarDragPlugin::~cbBarDragPlugin()
{
// nothing
}
// helper methods (protected)
// clips (top/bottom) or (right/left) edges against the frame's bounding rect.
void do_clip_edges( int len, int& rectPos, int& rectLen )
{
if ( rectPos < 0 )
{
rectLen += rectPos;
rectPos = 0;
if ( rectLen < 0 )
rectLen = 1;
}
else
if ( rectPos > len-1 )
{
rectPos = len-1;
rectLen = 1;
}
else
if ( rectPos + rectLen - 1 > len )
rectLen -= (rectPos + rectLen) - len + 1;
}
void cbBarDragPlugin::ClipRectInFrame( wxRect& rect )
{
int w, h;
mpLayout->GetParentFrame().GetClientSize( &w, &h );
do_clip_edges( w, rect.x, rect.width );
do_clip_edges( h, rect.y, rect.height );
}
void cbBarDragPlugin::ClipPosInFrame( wxPoint& pos )
{
int w, h;
mpLayout->GetParentFrame().GetClientSize( &w, &h );
if ( pos.x < 0 )
pos.x = 0;
if ( pos.y < 0 )
pos.y = 0;
if ( pos.x > w )
pos.x = w-1;
if ( pos.y > h )
pos.y = h-1;
}
void cbBarDragPlugin::AdjustHintRect( wxPoint& mousePos )
{
mHintRect.x = mousePos.x - mMouseInRectX;
mHintRect.y = mousePos.y - mMouseInRectY;
}
cbDockPane* cbBarDragPlugin::HitTestPanes( wxRect& rect )
{
//wxRect clipped = rect;
//ClipRectInFrame( clipped );
cbDockPane** pPanes = mpLayout->GetPanesArray();
for( int i = 0; i != MAX_PANES; ++i )
if ( rect_hits_rect( pPanes[i]->mBoundsInParent, rect ) )
return pPanes[i];
return NULL;
}
cbDockPane* cbBarDragPlugin::HitTestPanes( wxPoint& pos )
{
wxPoint clipped = pos;
//ClipPosInFrame( pos );
cbDockPane** pPanes = mpLayout->GetPanesArray();
for( int i = 0; i != MAX_PANES; ++i )
if ( rect_contains_point( pPanes[i]->mBoundsInParent, clipped.x, clipped.y ) )
return pPanes[i];
return NULL;
}
bool cbBarDragPlugin::HitsPane( cbDockPane* pPane, wxRect& rect )
{
return rect_hits_rect( pPane->mBoundsInParent, rect );
}
int cbBarDragPlugin::GetDistanceToPane( cbDockPane* pPane, wxPoint& mousePos )
{
wxRect& bounds = pPane->mBoundsInParent;
switch( pPane->mAlignment )
{
case FL_ALIGN_TOP : return mousePos.y - ( bounds.y + bounds.height );
case FL_ALIGN_BOTTOM : return bounds.y - mousePos.y;
case FL_ALIGN_LEFT : return mousePos.x - ( bounds.x + bounds.width );
case FL_ALIGN_RIGHT : return bounds.x - mousePos.x;
default : return 0; // never reached
}
// return 0;
}
bool cbBarDragPlugin::IsInOtherPane( wxPoint& mousePos )
{
cbDockPane* pPane = HitTestPanes( mousePos );
if ( pPane && pPane != mpCurPane ) return true;
else return false;
}
bool cbBarDragPlugin::IsInClientArea( wxPoint& mousePos )
{
return ( HitTestPanes( mousePos ) == NULL );
}
bool cbBarDragPlugin::IsInClientArea( wxRect& rect )
{
return ( HitTestPanes( rect ) == NULL );
}
void cbBarDragPlugin::CalcOnScreenDims( wxRect& rect )
{
if ( !mpCurPane || mpDraggedBar->IsFixed() ) return;
wxRect inPane = rect;
mpCurPane->FrameToPane( &inPane );
int rowNo = mpCurPane->GetRowAt( inPane.y, inPane.y + inPane.height );
bool isMaximized = ( rowNo >= (int)mpCurPane->GetRowList().Count() || rowNo < 0 );
if ( isMaximized )
{
inPane.x = 0;
inPane.width = mpCurPane->mPaneWidth;
mpCurPane->PaneToFrame( &inPane );
rect = inPane;
}
}
// helpers
static inline void check_upper_overrun( int& pos, int width, int mousePos )
{
if ( mousePos >= pos + width )
pos = mousePos - width/2;
}
static inline void check_lower_overrun( int& pos, int width, int mousePos )
{
if ( mousePos <= pos )
pos = mousePos - width/2;
}
void cbBarDragPlugin::StickToPane( cbDockPane* pPane, wxPoint& mousePos )
{
int wInPane = GetBarWidthInPane ( pPane );
int hInPane = GetBarHeightInPane( pPane );
// adjsut hint-rect horizontally (in pane's orientation)
if ( pPane->IsHorizontal() )
{
mHintRect.width = wInPane;
mHintRect.height = hInPane;
}
else
{
mHintRect.height = wInPane;
mHintRect.width = hInPane;
}
// adjsut hint-rect vertically (in pane's orientation)
wxRect& bounds = pPane->mBoundsInParent;
// true, if hint enters the pane through it's lower edge
bool fromLowerEdge = ( pPane->IsHorizontal() )
? mousePos.y > bounds.y
: mousePos.x > bounds.x;
// NOTE:: about all the below min/max things: they are meant to ensure
// that the mouse pointer doesn't overrun (leave) the hint-rectangle
// when its dimensions are recalculated upon sticking it to the pane
if ( pPane->IsHorizontal() && fromLowerEdge )
{
int paneBottomEdgeY = bounds.y + bounds.height;
mHintRect.y = wxMin( paneBottomEdgeY, mousePos.y );
check_lower_overrun( mHintRect.y, hInPane, mousePos.y );
}
else
if ( pPane->IsHorizontal() && !fromLowerEdge )
{
int paneTopEdgeY = bounds.y;
mHintRect.y = wxMax( paneTopEdgeY - hInPane, mousePos.y - hInPane );
check_upper_overrun( mHintRect.y, hInPane, mousePos.y );
}
else
if ( !pPane->IsHorizontal() && fromLowerEdge )
{
int paneRightEdgeX = bounds.x + bounds.width;
mHintRect.x = wxMin( paneRightEdgeX, mousePos.x );
check_lower_overrun( mHintRect.x, hInPane, mousePos.x );
}
else
if ( !pPane->IsHorizontal() && !fromLowerEdge )
{
int paneLeftEdgeX = bounds.x;
mHintRect.x = wxMax( paneLeftEdgeX - hInPane, mousePos.x - hInPane );
check_upper_overrun( mHintRect.x, hInPane, mousePos.x );
}
mMouseInRectX = mousePos.x - mHintRect.x;
mMouseInRectY = mousePos.y - mHintRect.y;
mpCurPane = pPane; // memorize pane to which the hint is currently sticked
}
void cbBarDragPlugin::UnstickFromPane( cbDockPane* pPane, wxPoint& mousePos )
{
// unsticking causes rectangle to get the shape in which
// dragged control-bar would be when floated
int newWidth = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].x;
int newHeight = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].y;
wxRect& flBounds = mpDraggedBar->mDimInfo.mBounds[wxCBAR_FLOATING];
if ( flBounds.width != -1 )
{
newWidth = flBounds.width;
newHeight = flBounds.height;
}
mHintRect.width = newWidth;
mHintRect.height = newHeight;
wxRect& bounds = pPane->mBoundsInParent;
// true, if hint leaves the pane through it's lower edge
bool fromLowerEdge = ( pPane->IsHorizontal() )
? mousePos.y > bounds.y
: mousePos.x > bounds.x;
// NOTE:: ...all the below min/max things - see comments about it in StickToPane(..)
if ( pPane->IsHorizontal() && fromLowerEdge )
{
// bool fromLowerEdge = mousePos.y > bounds.y;
mHintRect.y = wxMax( bounds.y + bounds.height + 1, mousePos.y - newHeight );
check_upper_overrun( mHintRect.y, newHeight, mousePos.y );
// this is how MFC's hint behaves:
if ( mMouseInRectX > newWidth )
mHintRect.x = mousePos.x - ( newWidth / 2 );
}
else
if ( pPane->IsHorizontal() && !fromLowerEdge )
{
mHintRect.y = wxMin( bounds.y - newHeight - 1, mousePos.y );
// -/-
if ( mMouseInRectX > newWidth )
mHintRect.x = mousePos.x - ( newWidth / 2 );
check_lower_overrun( mHintRect.y, newHeight, mousePos.y );
}
else
if ( !pPane->IsHorizontal() && fromLowerEdge )
{
mHintRect.x = wxMax( bounds.x + bounds.width, mousePos.x - newWidth );
// -/-
if ( mMouseInRectY > newHeight )
mHintRect.y = mousePos.y - ( newHeight / 2 );
check_upper_overrun( mHintRect.x, newWidth, mousePos.x );
}
else
if ( !pPane->IsHorizontal() && !fromLowerEdge )
{
mHintRect.x = wxMin( bounds.x - newWidth - 1, mousePos.x );
// -/-
if ( mMouseInRectY > newHeight )
mHintRect.y = mousePos.y - ( newHeight / 2 );
check_lower_overrun( mHintRect.x, newWidth, mousePos.x );
}
mMouseInRectX = mousePos.x - mHintRect.x;
mMouseInRectY = mousePos.y - mHintRect.y;
mpCurPane = NULL;
}
int cbBarDragPlugin::GetBarWidthInPane( cbDockPane* pPane )
{
if ( pPane == mpSrcPane )
return mBarWidthInSrcPane;
// this is how MFC's bars behave:
if ( pPane->IsHorizontal() )
return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].x;
else
return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY ].x;
}
int cbBarDragPlugin::GetBarHeightInPane( cbDockPane* pPane )
{
if ( pPane->IsHorizontal() )
return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].y;
else
return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY ].y;
}
void cbBarDragPlugin::ShowHint( bool prevWasInClient )
{
bool wasDocked = false;
if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false )
{
// do heavy calculations first
wxRect actualRect = mHintRect; // will be adjusted depending on drag-settings
if ( mpSrcPane->mProps.mExactDockPredictionOn && mpCurPane )
{
#ifdef __WXDEBUG__
bool success =
#endif
mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false );
wxASSERT( success ); // DBG::
actualRect = mpDraggedBar->mBounds;
mpCurPane->PaneToFrame( &actualRect );
}
else
CalcOnScreenDims( actualRect );
// release previous hint
if ( mPrevHintRect.x != POS_UNDEFINED )
{
// erase previous rectangle
cbDrawHintRectEvent evt( mPrevHintRect, prevWasInClient, true, false );
mpLayout->FirePluginEvent( evt );
}
// draw new hint
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -