1) There is a problem in that floating frames are not currently supported with !mRealTimeUpdates. We wrote a patch to correct this problem. You will find it attached to this posting. Here is a description of what was changed and why. In cbBarDragPlugin::ShowHint(), SetBarState is called every time mpCurPane changes. This is correct. However, this also happens every time, even if mRealTimeUpdates is false. The state should not be changed during the drag operation if mRealTimeUpdates is off. This is corrected in this patch. Code was also added in cbBarDragPlugin::OnLButtonUp() to actually do the state changing, only if mRealTimeUpdates is off. Normally, this is performed in ShowHint if mRealTimeUpdates is on. I also took the liberty of changing the drag cursor back to an arrow. This is the way it is in MS Visual C++, and it looks way better. The MoveWindow cursor looks terrible, IMHO. When FL gets the embedded cursor code working, we can switch back to a hand or something else. 2) This time we have discovered a crash bug in FL. The steps to reproduce this bug are as follows: 1. Open up a pane, dock it. 2. Click the Expand button (arrow button) in the frame hints portion 3. Click it again to Collapse the pane. 4. Now click the close button of the pane. Crash. We investigated what was causing this problem, and it turns out that the button state never gets unset. Once a button is pressed, it is always pressed. Thus, when the expand/ collapse button is pressed, and then the close button is pressed, the pane will close, but then FL will also try to expand or collapse the pane as well, because it thinks that the expand/collapse button was set. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15802 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
569 lines
14 KiB
C++
569 lines
14 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: barhintspl.h
|
|
// Purpose: Implementation for cbBarHintsPlugin
|
|
// Author: Aleksandras Gluchovas
|
|
// Modified by:
|
|
// Created: 30/11/98 (my 22th birthday :-)
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) Aleksandras Gluchovas
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "barhintspl.h"
|
|
#endif
|
|
|
|
// 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/utils.h"
|
|
#include "wx/fl/barhintspl.h"
|
|
|
|
// fixed settings
|
|
|
|
#define GROOVE_WIDTH 3 // left shade + middle line + right shade
|
|
#define GROOVE_TO_GROOVE_GAP 1
|
|
#define BOX_T_BOX_GAP 2
|
|
#define BOX_TO_GROOVE_GAP 3
|
|
|
|
#define BOXES_IN_HINT 2
|
|
#define CLOSE_BOX_IDX 0
|
|
#define COLLAPSE_BOX_IDX 1
|
|
|
|
// used interally
|
|
|
|
#define CLOSE_BOX_HITTED 1
|
|
#define COLLAPSE_BOX_HITTED 2
|
|
|
|
/***** Implementation fro class cbBarHintsPlugin *****/
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS( cbBarHintsPlugin, cbPluginBase )
|
|
|
|
BEGIN_EVENT_TABLE( cbBarHintsPlugin, cbPluginBase )
|
|
|
|
EVT_PL_SIZE_BAR_WND ( cbBarHintsPlugin::OnSizeBarWindow )
|
|
EVT_PL_DRAW_BAR_DECOR( cbBarHintsPlugin::OnDrawBarDecorations )
|
|
|
|
EVT_PL_LEFT_DOWN( cbBarHintsPlugin::OnLeftDown )
|
|
EVT_PL_LEFT_UP ( cbBarHintsPlugin::OnLeftUp )
|
|
EVT_PL_MOTION ( cbBarHintsPlugin::OnMotion )
|
|
|
|
END_EVENT_TABLE()
|
|
|
|
cbBarHintsPlugin::cbBarHintsPlugin(void)
|
|
|
|
: mpPane( 0 ),
|
|
mBtnPressed ( FALSE ),
|
|
mCloseBoxOn ( TRUE ),
|
|
mCollapseBoxOn( TRUE ),
|
|
mGrooveCount ( 2 ),
|
|
mHintGap ( 4 ),
|
|
mXWeight ( 2 )
|
|
{
|
|
mBoxes[CLOSE_BOX_IDX] = NULL;
|
|
mBoxes[COLLAPSE_BOX_IDX] = NULL;
|
|
}
|
|
|
|
cbBarHintsPlugin::cbBarHintsPlugin( wxFrameLayout* pLayout, int paneMask )
|
|
|
|
: cbPluginBase( pLayout, paneMask ),
|
|
mpPane( 0 ),
|
|
mBtnPressed ( FALSE ),
|
|
mCloseBoxOn ( TRUE ),
|
|
mCollapseBoxOn( TRUE ),
|
|
mGrooveCount ( 2 ),
|
|
mHintGap ( 5 ),
|
|
mXWeight ( 2 )
|
|
{
|
|
mBoxes[CLOSE_BOX_IDX] = NULL;
|
|
mBoxes[COLLAPSE_BOX_IDX] = NULL;
|
|
}
|
|
|
|
|
|
cbBarHintsPlugin::~cbBarHintsPlugin()
|
|
{
|
|
if (mBoxes[CLOSE_BOX_IDX])
|
|
delete mBoxes[CLOSE_BOX_IDX];
|
|
|
|
if (mBoxes[COLLAPSE_BOX_IDX])
|
|
delete mBoxes[COLLAPSE_BOX_IDX];
|
|
} // cbBarHintsPlugin destructor
|
|
|
|
|
|
void cbBarHintsPlugin::SetGrooveCount( int nGrooves )
|
|
{
|
|
mGrooveCount = nGrooves;
|
|
}
|
|
|
|
void cbBarHintsPlugin::CreateBoxes()
|
|
{
|
|
cbCloseBox* box1 = new cbCloseBox();
|
|
cbCollapseBox* box2 = new cbCollapseBox();
|
|
|
|
mBoxes[CLOSE_BOX_IDX] = box1;
|
|
mBoxes[COLLAPSE_BOX_IDX] = box2;
|
|
|
|
int i;
|
|
for ( i = 0; i != BOXES_IN_HINT; ++i )
|
|
{
|
|
mBoxes[i]->mpLayout = mpLayout;
|
|
mBoxes[i]->mpPlugin = this;
|
|
mBoxes[i]->mpWnd = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void cbBarHintsPlugin::Draw3DBox( wxDC& dc, const wxPoint& pos, bool pressed )
|
|
{
|
|
}
|
|
|
|
void cbBarHintsPlugin::DrawCloseBox( wxDC& dc, const wxPoint& pos, bool pressed )
|
|
{
|
|
}
|
|
|
|
void cbBarHintsPlugin::DrawCollapseBox( wxDC& dc, const wxPoint& pos,
|
|
bool atLeft, bool disabled, bool pressed )
|
|
{
|
|
}
|
|
|
|
void cbBarHintsPlugin::DrawGrooves( wxDC& dc, const wxPoint& pos, int length )
|
|
{
|
|
int ofs = 0;
|
|
|
|
int i;
|
|
for ( i = 0; i != mGrooveCount; ++i, ofs += ( GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP ) )
|
|
{
|
|
if ( mpPane->IsHorizontal() )
|
|
{
|
|
dc.SetPen( mpLayout->mLightPen );
|
|
dc.DrawLine( pos.x + ofs, pos.y, pos.x + ofs, pos.y + length - 1 );
|
|
dc.DrawPoint( pos.x + ofs + 1, pos.y );
|
|
|
|
dc.SetPen( mpLayout->mDarkPen );
|
|
dc.DrawLine( pos.x + ofs + 2, pos.y, pos.x + ofs + 2, pos.y + length );
|
|
dc.DrawPoint( pos.x + ofs + 1, pos.y + length - 1 );
|
|
dc.DrawPoint( pos.x + ofs, pos.y + length - 1 );
|
|
}
|
|
else
|
|
{
|
|
dc.SetPen( mpLayout->mLightPen );
|
|
dc.DrawLine( pos.x, pos.y + ofs, pos.x + length - 1, pos.y + ofs );
|
|
dc.DrawPoint( pos.x, pos.y + ofs + 1 );
|
|
|
|
dc.SetPen( mpLayout->mDarkPen );
|
|
dc.DrawLine( pos.x, pos.y + ofs + 2, pos.x + length, pos.y + ofs + 2 );
|
|
dc.DrawPoint( pos.x + length - 1, pos.y + ofs + 1 );
|
|
dc.DrawPoint( pos.x + length - 1, pos.y + ofs );
|
|
}
|
|
}
|
|
}
|
|
|
|
void cbBarHintsPlugin::ExcludeHints( wxRect& rect, cbBarInfo& info )
|
|
{
|
|
int boxHeight = BTN_BOX_HEIGHT;
|
|
|
|
// collapse and close box are not placed on fixed bars
|
|
|
|
if ( info.IsFixed() || ( !mCloseBoxOn && !mCollapseBoxOn ) )
|
|
|
|
boxHeight = 0;
|
|
|
|
int height = wxMax( mGrooveCount*(GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP)
|
|
- GROOVE_TO_GROOVE_GAP,
|
|
boxHeight
|
|
);
|
|
|
|
if ( mpPane->IsHorizontal() )
|
|
{
|
|
rect.x += ( mHintGap*2 + height );
|
|
rect.width -= (height + 2*mHintGap);
|
|
|
|
rect.x -= info.mDimInfo.mHorizGap + 2;
|
|
rect.width += info.mDimInfo.mHorizGap + 2;
|
|
}
|
|
else
|
|
{
|
|
rect.y += (mHintGap*2 + height);
|
|
rect.height -= (height + 2*mHintGap);
|
|
|
|
rect.y -= info.mDimInfo.mVertGap + 2;
|
|
rect.height += info.mDimInfo.mVertGap + 2;
|
|
}
|
|
}
|
|
|
|
void cbBarHintsPlugin::DoDrawHint( wxDC& dc, wxRect& rect,
|
|
int pos, int boxOfs, int grooveOfs,
|
|
bool isFixed )
|
|
{
|
|
if ( !isFixed )
|
|
{
|
|
if ( mpPane->IsHorizontal() )
|
|
{
|
|
if ( mCloseBoxOn )
|
|
|
|
mBoxes[CLOSE_BOX_IDX]->Draw( dc );
|
|
|
|
if ( mCollapseBoxOn )
|
|
|
|
mBoxes[COLLAPSE_BOX_IDX]->Draw( dc );
|
|
}
|
|
else
|
|
{
|
|
if ( mCloseBoxOn )
|
|
|
|
mBoxes[CLOSE_BOX_IDX]->Draw( dc );
|
|
|
|
if ( mCollapseBoxOn )
|
|
|
|
mBoxes[COLLAPSE_BOX_IDX]->Draw( dc );
|
|
}
|
|
}
|
|
|
|
if ( mpPane->IsHorizontal() )
|
|
|
|
DrawGrooves( dc, wxPoint( rect.x + mHintGap + grooveOfs, pos ),
|
|
rect.height - (pos - rect.y) - mHintGap );
|
|
else
|
|
DrawGrooves( dc, wxPoint( rect.x + mHintGap, rect.y + mHintGap + grooveOfs ),
|
|
(pos - rect.x) - mHintGap );
|
|
}
|
|
|
|
void cbBarHintsPlugin::GetHintsLayout( wxRect& rect, cbBarInfo& info,
|
|
int& boxOfs, int& grooveOfs, int& pos )
|
|
{
|
|
int boxHeight = BTN_BOX_HEIGHT;
|
|
// int boxWidth = BTN_BOX_WIDTH + BOX_TO_GROOVE_GAP + BTN_BOX_WIDTH;
|
|
|
|
// collapse and close box are not placed on fixed bars
|
|
|
|
if ( info.IsFixed() || ( !mCloseBoxOn && !mCollapseBoxOn ) )
|
|
{
|
|
boxHeight = 0;
|
|
// boxWidth = 0;
|
|
}
|
|
/*
|
|
else
|
|
if ( !mCloseBoxOn || !mCollapseBoxOn )
|
|
|
|
boxWidth = BTN_BOX_WIDTH;
|
|
*/
|
|
int grooveHeight = mGrooveCount*(GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP)
|
|
- GROOVE_TO_GROOVE_GAP;
|
|
|
|
int height = wxMax( grooveHeight, boxHeight );
|
|
|
|
// center boxs and groves with respect to each other
|
|
|
|
boxOfs = ( height - boxHeight ) / 2;
|
|
grooveOfs = ( height - grooveHeight ) / 2;
|
|
|
|
pos = ( mpPane->IsHorizontal() ) ? rect.y + mHintGap
|
|
: rect.x + rect.width - mHintGap;
|
|
|
|
// setup positions for boxes
|
|
|
|
if ( !info.IsFixed() )
|
|
{
|
|
// what direction "collapse-triangle" should look at?
|
|
|
|
bool& isAtLeft = ((cbCollapseBox*)(mBoxes[COLLAPSE_BOX_IDX]))->mIsAtLeft;
|
|
|
|
isAtLeft= info.mBounds.x <= mpPane->mPaneWidth - ( info.mBounds.x + info.mBounds.width );
|
|
|
|
if ( info.IsExpanded() )
|
|
{
|
|
isAtLeft = FALSE;
|
|
|
|
cbBarInfo* pCur = info.mpPrev;
|
|
|
|
while( pCur )
|
|
{
|
|
if ( !pCur->IsFixed() )
|
|
{
|
|
isAtLeft = TRUE; break;
|
|
}
|
|
|
|
pCur = pCur->mpPrev;
|
|
}
|
|
}
|
|
|
|
// collapse/expand works only when more not-fixed bars are present in the same row
|
|
|
|
mBoxes[COLLAPSE_BOX_IDX]->Enable( info.mpRow->mNotFixedBarsCnt > 1 );
|
|
|
|
int i;
|
|
for ( i = 0; i != BOXES_IN_HINT; ++i )
|
|
{
|
|
mBoxes[i]->mpPane = mpPane;
|
|
}
|
|
|
|
if ( mpPane->IsHorizontal() )
|
|
{
|
|
if ( mCloseBoxOn )
|
|
{
|
|
mBoxes[CLOSE_BOX_IDX]->mPos = wxPoint( rect.x + mHintGap + boxOfs, pos );
|
|
|
|
pos += BTN_BOX_HEIGHT;
|
|
}
|
|
|
|
if ( mCollapseBoxOn )
|
|
{
|
|
if ( mCloseBoxOn ) pos += BOX_T_BOX_GAP;
|
|
|
|
mBoxes[COLLAPSE_BOX_IDX]->mPos = wxPoint( rect.x + mHintGap + boxOfs, pos );
|
|
|
|
pos += BTN_BOX_HEIGHT;
|
|
|
|
pos += BOX_TO_GROOVE_GAP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( mCloseBoxOn )
|
|
{
|
|
pos -= BTN_BOX_WIDTH;
|
|
|
|
mBoxes[CLOSE_BOX_IDX]->mPos = wxPoint( pos , rect.y + mHintGap + boxOfs );
|
|
}
|
|
|
|
if ( mCollapseBoxOn )
|
|
{
|
|
if ( mCloseBoxOn ) pos -= BOX_T_BOX_GAP;
|
|
|
|
pos -= BTN_BOX_WIDTH;
|
|
|
|
mBoxes[COLLAPSE_BOX_IDX]->mPos = wxPoint( pos, rect.y + mHintGap + boxOfs );
|
|
|
|
pos -= BOX_TO_GROOVE_GAP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline bool is_in_box( const wxPoint& rectPos, const wxPoint& mousePos )
|
|
{
|
|
return ( mousePos.x >= rectPos.x &&
|
|
mousePos.y >= rectPos.y &&
|
|
mousePos.x < rectPos.x + BTN_BOX_WIDTH &&
|
|
mousePos.y < rectPos.y + BTN_BOX_HEIGHT );
|
|
}
|
|
|
|
int cbBarHintsPlugin::HitTestHints( cbBarInfo& info, const wxPoint& pos )
|
|
{
|
|
wxPoint inPane = pos;
|
|
mpPane->PaneToFrame( &inPane.x, &inPane.y );
|
|
|
|
wxRect& rect = info.mBoundsInParent;
|
|
|
|
if ( info.IsFixed() ) return FALSE;
|
|
|
|
int boxOfs, grooveOfs, coord;
|
|
|
|
GetHintsLayout( rect, info, boxOfs, grooveOfs, coord );
|
|
|
|
if ( mpPane->IsHorizontal() )
|
|
{
|
|
if ( mCloseBoxOn )
|
|
{
|
|
if ( is_in_box( wxPoint( rect.x + mHintGap + boxOfs, coord ), inPane ) )
|
|
|
|
return CLOSE_BOX_HITTED;
|
|
|
|
coord += BTN_BOX_HEIGHT;
|
|
}
|
|
|
|
if ( mCollapseBoxOn )
|
|
{
|
|
if ( mCloseBoxOn ) coord += BOX_T_BOX_GAP;
|
|
|
|
if ( is_in_box( wxPoint( rect.x + mHintGap + boxOfs, coord ), inPane ) )
|
|
|
|
return COLLAPSE_BOX_HITTED;
|
|
|
|
coord += BTN_BOX_HEIGHT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( mCloseBoxOn )
|
|
{
|
|
coord -= BTN_BOX_WIDTH;
|
|
|
|
if ( is_in_box( wxPoint( coord , rect.y + mHintGap + boxOfs ), inPane ) )
|
|
|
|
return CLOSE_BOX_HITTED;
|
|
}
|
|
|
|
if ( mCollapseBoxOn )
|
|
{
|
|
if ( mCloseBoxOn ) coord -= BOX_T_BOX_GAP;
|
|
coord -= BTN_BOX_WIDTH;
|
|
|
|
if ( is_in_box( wxPoint( coord, rect.y + mHintGap + boxOfs ), inPane ) )
|
|
|
|
return COLLAPSE_BOX_HITTED;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// handlers for plugin-events
|
|
|
|
void cbBarHintsPlugin::OnSizeBarWindow( cbSizeBarWndEvent& event )
|
|
{
|
|
wxRect& rect = event.mBoundsInParent;
|
|
mpPane = event.mpPane;
|
|
|
|
ExcludeHints( rect, *event.mpBar );
|
|
|
|
event.Skip(); // pass event to the next plugin in the chain
|
|
}
|
|
|
|
void cbBarHintsPlugin::OnDrawBarDecorations( cbDrawBarDecorEvent& event )
|
|
{
|
|
wxRect& rect = event.mBoundsInParent;
|
|
mpPane = event.mpPane;
|
|
|
|
int boxOfs, grooveOfs, pos;
|
|
|
|
GetHintsLayout( rect, *event.mpBar, boxOfs, grooveOfs, pos );
|
|
|
|
DoDrawHint( *event.mpDc, rect, pos, boxOfs, grooveOfs, event.mpBar->IsFixed() );
|
|
|
|
// let other plugins add on their decorations
|
|
|
|
event.Skip();
|
|
}
|
|
|
|
void cbBarHintsPlugin::OnLeftDown( cbLeftDownEvent& event )
|
|
{
|
|
mpPane = event.mpPane;
|
|
wxPoint inFrame = event.mPos;
|
|
|
|
mpPane->PaneToFrame( &inFrame.x, &inFrame.y );
|
|
|
|
wxBarIterator iter( mpPane->GetRowList() );
|
|
|
|
mpClickedBar = NULL;
|
|
|
|
while ( iter.Next() )
|
|
{
|
|
cbBarInfo& bar = iter.BarInfo();
|
|
|
|
int boxOfs, grooveOfs, pos;
|
|
|
|
GetHintsLayout( bar.mBoundsInParent, bar, boxOfs, grooveOfs, pos );
|
|
|
|
if ( !bar.IsFixed() )
|
|
{
|
|
int i;
|
|
for ( i = 0; i != BOXES_IN_HINT; ++i )
|
|
{
|
|
mBoxes[i]->mPressed = FALSE;
|
|
mBoxes[i]->mWasClicked = FALSE;
|
|
}
|
|
for ( i = 0; i != BOXES_IN_HINT; ++i )
|
|
{
|
|
mBoxes[i]->OnLeftDown( inFrame );
|
|
|
|
if ( mBoxes[i]->mPressed )
|
|
{
|
|
mBtnPressed = TRUE;
|
|
mpClickedBar = &bar;
|
|
|
|
return; // event handled
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
event.Skip();
|
|
}
|
|
|
|
void cbBarHintsPlugin::OnLeftUp( cbLeftUpEvent& event )
|
|
{
|
|
if ( mBtnPressed )
|
|
{
|
|
wxPoint inFrame = event.mPos;
|
|
mpPane->PaneToFrame( &inFrame.x, &inFrame.y );
|
|
|
|
int boxOfs, grooveOfs, pos;
|
|
|
|
GetHintsLayout( mpClickedBar->mBoundsInParent, *mpClickedBar, boxOfs, grooveOfs, pos );
|
|
|
|
int result = HitTestHints( *mpClickedBar, event.mPos );
|
|
|
|
int i;
|
|
for ( i = 0; i != BOXES_IN_HINT; ++i )
|
|
{
|
|
mBoxes[i]->OnLeftUp( inFrame );
|
|
|
|
if ( mBoxes[i]->WasClicked() )
|
|
{
|
|
if ( i == 0 )
|
|
{
|
|
mpLayout->SetBarState( mpClickedBar, wxCBAR_HIDDEN, TRUE );
|
|
}
|
|
else
|
|
{
|
|
if ( mpClickedBar->IsExpanded() )
|
|
mpPane->ContractBar( mpClickedBar );
|
|
else
|
|
mpPane->ExpandBar( mpClickedBar );
|
|
}
|
|
}
|
|
}
|
|
|
|
mBtnPressed = FALSE;
|
|
return;
|
|
}
|
|
else
|
|
event.Skip();
|
|
}
|
|
|
|
void cbBarHintsPlugin::OnMotion( cbMotionEvent& event )
|
|
{
|
|
if ( mBtnPressed )
|
|
{
|
|
wxPoint inFrame = event.mPos;
|
|
mpPane->PaneToFrame( &inFrame.x, &inFrame.y );
|
|
|
|
mpPane = event.mpPane;
|
|
|
|
int i;
|
|
for ( i = 0; i != BOXES_IN_HINT; ++i )
|
|
{
|
|
mBoxes[i]->OnMotion( inFrame );
|
|
}
|
|
}
|
|
else
|
|
event.Skip();
|
|
}
|
|
|
|
void cbBarHintsPlugin::OnInitPlugin()
|
|
{
|
|
cbPluginBase::OnInitPlugin();
|
|
|
|
cbDockPane** panes = mpLayout->GetPanesArray();
|
|
|
|
int i;
|
|
for ( i = 0; i != MAX_PANES; ++i )
|
|
{
|
|
if ( panes[i]->MatchesMask( mPaneMask ) )
|
|
{
|
|
panes[i]->mProps.mMinCBarDim.x = 25;
|
|
panes[i]->mProps.mMinCBarDim.y = 16;
|
|
}
|
|
}
|
|
CreateBoxes();
|
|
}
|