git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31234 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1145 lines
28 KiB
C++
1145 lines
28 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: toolwnd.cpp
|
|
// Purpose: wxToolWindow implementation.
|
|
// Author: Aleksandras Gluchovas
|
|
// Modified by:
|
|
// Created: 06/09/98
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) Aleksandras Gluchovas
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "toolwnd.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/fl/toolwnd.h"
|
|
|
|
#define _IMG_A 0xAA // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
|
|
#define _IMG_B 0x00 // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
|
|
#define _IMG_C 0x55 // Note: modified from _C to _IMG_C, for consistency reasons.
|
|
#define _IMG_D 0x00 // Note: modified from _D to _IMG_D, for consistency reasons.
|
|
|
|
// FOR NOW:: static
|
|
|
|
static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D,
|
|
_IMG_A,_IMG_B,_IMG_C,_IMG_D,
|
|
_IMG_A,_IMG_B,_IMG_C,_IMG_D,
|
|
_IMG_A,_IMG_B,_IMG_C,_IMG_D
|
|
};
|
|
|
|
/***** Implementation for class wxToolWindow *****/
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS( wxToolWindow, wxFrame)
|
|
|
|
BEGIN_EVENT_TABLE( wxToolWindow, wxFrame )
|
|
|
|
EVT_PAINT ( wxToolWindow::OnPaint )
|
|
EVT_MOTION ( wxToolWindow::OnMotion )
|
|
EVT_LEFT_DOWN( wxToolWindow::OnLeftDown )
|
|
EVT_LEFT_UP ( wxToolWindow::OnLeftUp )
|
|
EVT_SIZE ( wxToolWindow::OnSize )
|
|
|
|
|
|
EVT_ERASE_BACKGROUND( wxToolWindow::OnEraseBackground )
|
|
|
|
END_EVENT_TABLE()
|
|
|
|
enum INTERNAL_HIT_CODES
|
|
{
|
|
HITS_WND_NOTHING,
|
|
HITS_WND_CLIENT,
|
|
HITS_WND_TITLE,
|
|
|
|
HITS_WND_LEFT_EDGE,
|
|
HITS_WND_RIGHT_EDGE,
|
|
HITS_WND_TOP_EDGE,
|
|
HITS_WND_BOTTOM_EDGE,
|
|
|
|
HITS_WND_TOP_LEFT_CORNER,
|
|
HITS_WND_BOTTOM_RIGHT_CORNER,
|
|
HITS_WND_TOP_RIGHT_CORNER,
|
|
HITS_WND_BOTTOM_LEFT_CORNER
|
|
};
|
|
|
|
wxToolWindow::wxToolWindow()
|
|
|
|
: mpClientWnd ( NULL ),
|
|
|
|
#ifndef __WXMSW__
|
|
mTitleFont( 8, wxSWISS, wxNORMAL, wxNORMAL ),
|
|
#else
|
|
// just to simulate MS-Dev style
|
|
mTitleFont( 8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("MS Sans Serif") ),
|
|
#endif
|
|
|
|
mTitleHeight ( 16 ),
|
|
mClntHorizGap ( 2 ),
|
|
mClntVertGap ( 2 ),
|
|
mWndVertGap ( 4 ),
|
|
mWndHorizGap ( 4 ),
|
|
|
|
mButtonGap ( 2 ),
|
|
mInTitleMargin( 4 ),
|
|
mHintBorder ( 4 ),
|
|
|
|
mResizeStarted( false ),
|
|
mRealTimeUpdatesOn( true ),
|
|
|
|
mMTolerance ( 5 ), // mouse-resizing tollerance
|
|
|
|
mCursorType( HITS_WND_NOTHING ),
|
|
mMouseCaptured( false ),
|
|
|
|
mpScrDc( NULL )
|
|
|
|
{
|
|
}
|
|
|
|
wxToolWindow::~wxToolWindow()
|
|
{
|
|
if ( mpScrDc ) delete mpScrDc;
|
|
|
|
for( size_t i = 0; i != mButtons.Count(); ++i )
|
|
delete mButtons[i];
|
|
}
|
|
|
|
void wxToolWindow::LayoutMiniButtons()
|
|
{
|
|
int w,h;
|
|
|
|
GetSize( &w, &h );
|
|
|
|
int x = w - mWndHorizGap - mInTitleMargin - BTN_BOX_WIDTH;
|
|
int y = mWndVertGap + 2;
|
|
|
|
for( size_t i = 0; i != mButtons.Count(); ++i )
|
|
{
|
|
mButtons[i]->SetPos( wxPoint( x,y ) );
|
|
x-= BTN_BOX_WIDTH + mButtonGap;
|
|
}
|
|
}
|
|
|
|
void wxToolWindow::SetClient( wxWindow* pWnd )
|
|
{
|
|
mpClientWnd = pWnd;
|
|
}
|
|
|
|
wxWindow* wxToolWindow::GetClient()
|
|
{
|
|
return mpClientWnd;
|
|
}
|
|
|
|
void wxToolWindow::SetTitleFont( wxFont& font )
|
|
{
|
|
mTitleFont = font;
|
|
}
|
|
|
|
void wxToolWindow::AddMiniButton( cbMiniButton* pBtn )
|
|
{
|
|
pBtn->mpWnd = this;
|
|
|
|
mButtons.Add( pBtn );
|
|
|
|
// not necesserely now..
|
|
//LayoutMiniButtons();
|
|
}
|
|
|
|
void wxToolWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
|
|
{
|
|
wxPaintDC pdc( this );
|
|
wxWindowDC dc( this );
|
|
|
|
int w,h;
|
|
GetSize( &w, &h );
|
|
|
|
wxBrush backGround( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE), wxSOLID );
|
|
//dc.SetBrush( *wxLIGHT_GREY_BRUSH );
|
|
dc.SetBrush( backGround );
|
|
dc.SetPen( *wxTRANSPARENT_PEN );
|
|
|
|
int y = mWndVertGap + mTitleHeight + mClntVertGap;
|
|
|
|
dc.DrawRectangle( 0,0, w, y ); // Top grey part.
|
|
dc.DrawRectangle( 0,y-1, mWndHorizGap + mClntHorizGap, h - y ); // Left grey part.
|
|
dc.DrawRectangle( w - ( mWndHorizGap + mClntHorizGap ), y-1,
|
|
mWndHorizGap + mClntHorizGap, h - y ); // Right grey part.
|
|
dc.DrawRectangle( 0, h - mWndVertGap - mClntVertGap, w, mWndVertGap + mClntVertGap ); // Bottom grey part.
|
|
|
|
// draw shades
|
|
dc.SetPen( *wxLIGHT_GREY_PEN );
|
|
|
|
dc.DrawLine( 0,0, w, 0 );
|
|
dc.DrawLine( 0,0, 0, h );
|
|
|
|
dc.SetPen( *wxWHITE_PEN );
|
|
|
|
dc.DrawLine( 1,1, w, 1 );
|
|
dc.DrawLine( 1,2, 1, h );
|
|
|
|
dc.SetPen( *wxGREY_PEN );
|
|
|
|
dc.DrawLine( w - 2, 1, w - 2, h - 1 );
|
|
dc.DrawLine( 1, h - 2, w - 2, h - 2 );
|
|
|
|
dc.SetPen( *wxBLACK_PEN );
|
|
|
|
dc.DrawLine( 0, h - 1, w, h - 1 );
|
|
dc.DrawLine( w-1, 0, w-1, h );
|
|
|
|
// fill inner area
|
|
|
|
dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( wxColour( 0,0,128 ), wxSOLID ) );
|
|
|
|
dc.DrawRectangle( mWndHorizGap, mWndVertGap, w - mWndHorizGap*2, mTitleHeight );
|
|
|
|
dc.SetFont( mTitleFont );
|
|
|
|
for( size_t i = 0; i != mButtons.Count(); ++i )
|
|
mButtons[i]->Draw( dc );
|
|
|
|
int x1 = mWndHorizGap + mClntHorizGap;
|
|
int x2 = mButtons[ mButtons.GetCount() - 1 ]->mPos.x - mClntHorizGap*2;
|
|
|
|
dc.SetClippingRegion( x1, mWndVertGap + mClntVertGap, x2 - x1, mTitleHeight );
|
|
|
|
dc.SetTextForeground( *wxWHITE );
|
|
dc.SetBackgroundMode( wxTRANSPARENT );
|
|
dc.DrawText( GetTitle(), mWndHorizGap + 2, mWndVertGap + 1 );
|
|
}
|
|
|
|
void wxToolWindow::GetScrWindowRect( wxRect& r )
|
|
{
|
|
int x,y;
|
|
GetPosition(&x,&y);
|
|
int w,h;
|
|
GetSize( &w, &h );
|
|
|
|
r.x = x; r.y = y;
|
|
r.width = w; r.height = h;
|
|
}
|
|
|
|
void wxToolWindow::GetScrMousePos( wxMouseEvent& event, wxPoint& pos )
|
|
{
|
|
int x = event.m_x, y = event.m_y;
|
|
|
|
ClientToScreen( &x, &y );
|
|
|
|
pos.x = x; pos.y = y;
|
|
}
|
|
|
|
int wxToolWindow::HitTestWindow( wxMouseEvent& event )
|
|
{
|
|
wxPoint pos;
|
|
wxRect r;
|
|
|
|
GetScrMousePos( event, pos );
|
|
GetScrWindowRect( r );
|
|
|
|
int k = mMTolerance;
|
|
|
|
if ( !( pos.x >= r.x && pos.y >= r.y &&
|
|
pos.x < r.x + r.width &&
|
|
pos.y < r.y + r.height )
|
|
)
|
|
return HITS_WND_NOTHING;
|
|
|
|
if ( pos.y <= r.y + k )
|
|
{
|
|
if ( pos.x < r.x + k*2 )
|
|
return HITS_WND_TOP_LEFT_CORNER;
|
|
else
|
|
{
|
|
if ( pos.x >= r.x + r.width - k*2 )
|
|
return HITS_WND_TOP_RIGHT_CORNER;
|
|
else
|
|
return HITS_WND_TOP_EDGE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pos.y >= r.y + r.height - k )
|
|
{
|
|
if ( pos.x < r.x + k*2 )
|
|
return HITS_WND_BOTTOM_LEFT_CORNER;
|
|
else
|
|
{
|
|
if ( pos.x > r.x + r.width - k*2 )
|
|
return HITS_WND_BOTTOM_RIGHT_CORNER;
|
|
else
|
|
return HITS_WND_BOTTOM_EDGE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pos.x <= r.x + k )
|
|
return HITS_WND_LEFT_EDGE;
|
|
else
|
|
{
|
|
if ( pos.x >= r.x + r.width - k )
|
|
return HITS_WND_RIGHT_EDGE;
|
|
else
|
|
{
|
|
if ( pos.y <= r.y + mWndVertGap + mTitleHeight + mClntVertGap )
|
|
return HITS_WND_TITLE;
|
|
else
|
|
return HITS_WND_CLIENT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void wxToolWindow::DrawHintRect( const wxRect& r )
|
|
{
|
|
// BUG BUG BUG (wx):: somehow stippled brush works only
|
|
// when the bitmap created on stack, not
|
|
// as a member of the class
|
|
|
|
int prevLF = mpScrDc->GetLogicalFunction();
|
|
|
|
mpScrDc->SetLogicalFunction( wxXOR );
|
|
|
|
wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
|
|
|
|
wxBrush checkerBrush( checker );
|
|
|
|
mpScrDc->SetPen( *wxTRANSPARENT_PEN );
|
|
mpScrDc->SetBrush( checkerBrush );
|
|
|
|
int half = mHintBorder / 2;
|
|
|
|
mpScrDc->DrawRectangle( r.x - half, r.y - half,
|
|
r.width + 2*half, mHintBorder );
|
|
|
|
mpScrDc->DrawRectangle( r.x - half, r.y + r.height - half,
|
|
r.width + 2*half, mHintBorder );
|
|
|
|
mpScrDc->DrawRectangle( r.x - half, r.y + half - 1,
|
|
mHintBorder, r.height - 2*half + 2);
|
|
|
|
mpScrDc->DrawRectangle( r.x + r.width - half,
|
|
r.y + half - 1,
|
|
mHintBorder, r.height - 2*half + 2);
|
|
|
|
mpScrDc->SetBrush( wxNullBrush );
|
|
|
|
mpScrDc->SetLogicalFunction( prevLF );
|
|
}
|
|
|
|
void wxToolWindow::SetHintCursor( int type )
|
|
{
|
|
if ( mResizeStarted )
|
|
return;
|
|
|
|
if ( type == HITS_WND_NOTHING || type == HITS_WND_CLIENT )
|
|
{
|
|
// the cursor is out of window - reset to arrow
|
|
|
|
if ( mMouseCaptured )
|
|
{
|
|
ReleaseMouse();
|
|
mMouseCaptured = false;
|
|
}
|
|
|
|
SetCursor( wxCURSOR_ARROW );
|
|
|
|
mCursorType = type;
|
|
|
|
return;
|
|
}
|
|
|
|
// did the cursor actually changed?
|
|
|
|
if ( type != mCursorType )
|
|
{
|
|
mCursorType = type;
|
|
|
|
switch ( type )
|
|
{
|
|
case HITS_WND_LEFT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break;
|
|
case HITS_WND_RIGHT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break;
|
|
case HITS_WND_TOP_EDGE : SetCursor( wxCURSOR_SIZENS ); break;
|
|
case HITS_WND_BOTTOM_EDGE : SetCursor( wxCURSOR_SIZENS ); break;
|
|
|
|
case HITS_WND_TOP_LEFT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break;
|
|
case HITS_WND_BOTTOM_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break;
|
|
case HITS_WND_TOP_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break;
|
|
case HITS_WND_BOTTOM_LEFT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break;
|
|
|
|
case HITS_WND_TITLE : SetCursor( wxCURSOR_ARROW ); break;
|
|
case HITS_WND_CLIENT : SetCursor( wxCURSOR_ARROW ); break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
if (mMouseCaptured)
|
|
{
|
|
mMouseCaptured = false;
|
|
ReleaseMouse();
|
|
}
|
|
}
|
|
|
|
if ( !mMouseCaptured )
|
|
{
|
|
mMouseCaptured = true;
|
|
CaptureMouse();
|
|
}
|
|
}
|
|
|
|
#define FL_INFINITY 32768
|
|
|
|
static inline void clip_to( int& value, long from, long till )
|
|
{
|
|
if ( value < from )
|
|
value = from;
|
|
|
|
if ( value > till )
|
|
value = till;
|
|
}
|
|
|
|
void wxToolWindow::AdjustRectPos( const wxRect& original, const wxSize& newDim, wxRect& newRect )
|
|
{
|
|
if ( mCursorType == HITS_WND_TOP_EDGE ||
|
|
mCursorType == HITS_WND_TOP_LEFT_CORNER )
|
|
{
|
|
newRect.x = original.x + original.width - newDim.x;
|
|
newRect.y = original.y + original.height - newDim.y;
|
|
}
|
|
else
|
|
if ( mCursorType == HITS_WND_LEFT_EDGE ||
|
|
mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
|
|
{
|
|
newRect.x = original.x + original.width - newDim.x;
|
|
newRect.y = original.y;
|
|
}
|
|
else
|
|
if ( mCursorType == HITS_WND_RIGHT_EDGE ||
|
|
mCursorType == HITS_WND_TOP_RIGHT_CORNER )
|
|
{
|
|
newRect.x = original.x;
|
|
newRect.y = original.y + original.height - newDim.y;
|
|
}
|
|
else
|
|
if ( mCursorType == HITS_WND_BOTTOM_EDGE ||
|
|
mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
|
|
{
|
|
newRect.x = original.x;
|
|
newRect.y = original.y;
|
|
}
|
|
|
|
newRect.width = newDim.x;
|
|
newRect.height = newDim.y;
|
|
}
|
|
|
|
void wxToolWindow::CalcResizedRect( wxRect& rect, wxPoint& delta, const wxSize& minDim )
|
|
{
|
|
// Microsoft's rect-coordinates are best suited
|
|
// for the case of corner-clipping
|
|
|
|
int left = mInitialRect.x;
|
|
int top = mInitialRect.y;
|
|
int right = mInitialRect.x + mInitialRect.width;
|
|
int bottom = mInitialRect.y + mInitialRect.height;
|
|
|
|
// constraint delta edge is dragged
|
|
|
|
switch ( mCursorType )
|
|
{
|
|
case HITS_WND_LEFT_EDGE : delta.y = 0; break;
|
|
case HITS_WND_RIGHT_EDGE : delta.y = 0; break;
|
|
case HITS_WND_TOP_EDGE : delta.x = 0; break;
|
|
case HITS_WND_BOTTOM_EDGE : delta.x = 0; break;
|
|
default: break;
|
|
}
|
|
|
|
if ( mCursorType == HITS_WND_TOP_EDGE ||
|
|
mCursorType == HITS_WND_TOP_LEFT_CORNER )
|
|
{
|
|
left += delta.x;
|
|
top += delta.y;
|
|
|
|
clip_to( left, -FL_INFINITY, mInitialRect.x + mInitialRect.width - minDim.x );
|
|
clip_to( top, -FL_INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
|
|
}
|
|
else
|
|
if ( mCursorType == HITS_WND_LEFT_EDGE ||
|
|
mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
|
|
{
|
|
left += delta.x;
|
|
bottom += delta.y;
|
|
|
|
clip_to( left, -FL_INFINITY, mInitialRect.x + mInitialRect.width - minDim.x );
|
|
clip_to( bottom, mInitialRect.y + minDim.y, FL_INFINITY );
|
|
}
|
|
else
|
|
if ( mCursorType == HITS_WND_RIGHT_EDGE ||
|
|
mCursorType == HITS_WND_TOP_RIGHT_CORNER )
|
|
{
|
|
right += delta.x;
|
|
top += delta.y;
|
|
|
|
clip_to( right, mInitialRect.x + minDim.x, FL_INFINITY );
|
|
clip_to( top, -FL_INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
|
|
}
|
|
else
|
|
if ( mCursorType == HITS_WND_BOTTOM_EDGE ||
|
|
mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
|
|
{
|
|
right += delta.x;
|
|
bottom += delta.y;
|
|
|
|
clip_to( right, mInitialRect.x + minDim.x, FL_INFINITY );
|
|
clip_to( bottom, mInitialRect.y + minDim.y, FL_INFINITY );
|
|
}
|
|
else
|
|
{
|
|
wxFAIL_MSG( _T("what did the cursor hit?") );
|
|
}
|
|
|
|
rect.x = left;
|
|
rect.y = top;
|
|
rect.width = right - left;
|
|
rect.height = bottom - top;
|
|
}
|
|
|
|
wxSize wxToolWindow::GetMinimalWndDim()
|
|
{
|
|
return wxSize( (mWndHorizGap + mClntHorizGap)*2 + BTN_BOX_WIDTH*4,
|
|
(mWndVertGap + mClntVertGap )*2 + mTitleHeight );
|
|
}
|
|
|
|
void wxToolWindow::OnMotion( wxMouseEvent& event )
|
|
{
|
|
if ( !mResizeStarted )
|
|
{
|
|
for( size_t i = 0; i != mButtons.Count(); ++i )
|
|
mButtons[i]->OnMotion( wxPoint( event.m_x, event.m_y ) );
|
|
|
|
SetHintCursor( HitTestWindow( event ) );
|
|
return;
|
|
}
|
|
|
|
wxPoint pos;
|
|
GetScrMousePos( event, pos );
|
|
|
|
if ( mCursorType == HITS_WND_TITLE )
|
|
{
|
|
int w,h;
|
|
GetSize( &w, &h );
|
|
|
|
SetSize( mInitialRect.x + pos.x - mDragOrigin.x,
|
|
mInitialRect.y + pos.y - mDragOrigin.y,
|
|
w,h, 0 );
|
|
}
|
|
|
|
else
|
|
{
|
|
wxPoint delta( pos.x - mDragOrigin.x, pos.y - mDragOrigin.y );
|
|
|
|
wxRect newRect;
|
|
|
|
wxSize minDim = GetMinimalWndDim();
|
|
|
|
CalcResizedRect( newRect, delta, minDim );
|
|
|
|
wxSize borderDim( ( mWndHorizGap + mClntHorizGap )*2,
|
|
( mWndVertGap + mClntVertGap )*2 + mTitleHeight );
|
|
|
|
wxSize preferred = GetPreferredSize( wxSize( newRect.width - borderDim.x,
|
|
newRect.height - borderDim.y ) );
|
|
|
|
preferred.x += borderDim.x;
|
|
preferred.y += borderDim.y;
|
|
|
|
//CalcResizedRect( newRect, delta, preferred );
|
|
|
|
wxRect finalRect = newRect;
|
|
|
|
AdjustRectPos( newRect, preferred, finalRect );
|
|
|
|
if ( mRealTimeUpdatesOn )
|
|
{
|
|
SetSize( finalRect.x, finalRect.y,
|
|
finalRect.width, finalRect.height, 0 );
|
|
}
|
|
else
|
|
{
|
|
DrawHintRect( mPrevHintRect );
|
|
DrawHintRect( finalRect );
|
|
|
|
::wxLogTrace(wxT("wxToolWindow"),wxT("%d,%d / %d,%d\n"), finalRect.x, finalRect.y, finalRect.width, finalRect.height);
|
|
}
|
|
|
|
mPrevHintRect = finalRect;
|
|
}
|
|
}
|
|
|
|
void wxToolWindow::OnLeftDown( wxMouseEvent& event )
|
|
{
|
|
int result = HitTestWindow( event );
|
|
|
|
for( size_t i = 0; i != mButtons.Count(); ++i )
|
|
{
|
|
mButtons[i]->OnLeftDown( wxPoint( event.m_x, event.m_y ) );
|
|
|
|
if ( mButtons[i]->IsPressed() )
|
|
return; // button hitted,
|
|
}
|
|
|
|
if ( result >= HITS_WND_LEFT_EDGE || result == HITS_WND_TITLE )
|
|
{
|
|
GetScrMousePos( event, mDragOrigin );
|
|
|
|
/*
|
|
if ( mMouseCaptured `)
|
|
{
|
|
ReleaseMouse();
|
|
mMouseCaptured = false;
|
|
}*/
|
|
|
|
if ( result == HITS_WND_TITLE &&
|
|
HandleTitleClick( event ) )
|
|
return;
|
|
|
|
mResizeStarted = true;
|
|
|
|
int x,y;
|
|
GetPosition( &x, &y );
|
|
|
|
mInitialRect.x = x;
|
|
mInitialRect.y = y;
|
|
|
|
GetSize( &x, &y );
|
|
mInitialRect.width = x;
|
|
mInitialRect.height = y;
|
|
|
|
mPrevHintRect = mInitialRect;
|
|
|
|
if ( mCursorType != HITS_WND_TITLE && !mRealTimeUpdatesOn )
|
|
{
|
|
mpScrDc = new wxScreenDC();
|
|
|
|
wxScreenDC::StartDrawingOnTop( (wxRect*)NULL );
|
|
|
|
DrawHintRect( mInitialRect );
|
|
}
|
|
}
|
|
}
|
|
|
|
void wxToolWindow::OnLeftUp( wxMouseEvent& event )
|
|
{
|
|
for( size_t i = 0; i != mButtons.Count(); ++i )
|
|
{
|
|
mButtons[i]->OnLeftUp( wxPoint( event.m_x, event.m_y ) );
|
|
|
|
if ( mButtons[i]->WasClicked() )
|
|
{
|
|
OnMiniButtonClicked( i ); // notify derived classes
|
|
mButtons[i]->Reset();
|
|
}
|
|
}
|
|
|
|
if ( mResizeStarted )
|
|
{
|
|
mResizeStarted = false;
|
|
|
|
if ( mCursorType != HITS_WND_TITLE )
|
|
{
|
|
if ( !mRealTimeUpdatesOn )
|
|
{
|
|
DrawHintRect( mPrevHintRect );
|
|
|
|
wxScreenDC::EndDrawingOnTop();
|
|
|
|
delete mpScrDc;
|
|
|
|
mpScrDc = NULL;
|
|
|
|
SetSize( mPrevHintRect.x, mPrevHintRect.y,
|
|
mPrevHintRect.width, mPrevHintRect.height, 0 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void wxToolWindow::OnSize( wxSizeEvent& WXUNUSED(event) )
|
|
{
|
|
if ( mpClientWnd )
|
|
{
|
|
int w,h;
|
|
GetSize( &w, &h );
|
|
|
|
int x = mWndHorizGap + mClntHorizGap;
|
|
int y = mWndVertGap + mTitleHeight + mClntVertGap;
|
|
|
|
mpClientWnd->SetSize( x-1, y-1,
|
|
w - 2*(mWndHorizGap + mClntHorizGap),
|
|
h - y - mClntVertGap - mWndVertGap,
|
|
0
|
|
);
|
|
}
|
|
|
|
LayoutMiniButtons();
|
|
}
|
|
|
|
wxSize wxToolWindow::GetPreferredSize( const wxSize& given )
|
|
{
|
|
return given;
|
|
}
|
|
|
|
void wxToolWindow::OnEraseBackground( wxEraseEvent& WXUNUSED(event) )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
/***** Implementation for class cbMiniButton *****/
|
|
|
|
cbMiniButton::cbMiniButton()
|
|
|
|
: mVisible( true ),
|
|
mEnabled( true ),
|
|
|
|
mpLayout( NULL ),
|
|
mpPane ( NULL ),
|
|
mpPlugin( NULL ),
|
|
mpWnd ( NULL ),
|
|
|
|
mWasClicked( false ),
|
|
mDragStarted( false ),
|
|
mPressed( false )
|
|
{}
|
|
|
|
void cbMiniButton::SetPos( const wxPoint& pos )
|
|
{
|
|
mPos = pos;
|
|
}
|
|
|
|
bool cbMiniButton::HitTest( const wxPoint& pos )
|
|
{
|
|
if ( !mVisible ) return false;
|
|
|
|
return ( pos.x >= mPos.x && pos.y >= mPos.y &&
|
|
pos.x < mPos.x + BTN_BOX_WIDTH &&
|
|
pos.y < mPos.y + BTN_BOX_HEIGHT );
|
|
}
|
|
|
|
void cbMiniButton::OnLeftDown( const wxPoint& pos )
|
|
{
|
|
if ( !mVisible || mDragStarted ) return;
|
|
|
|
if ( HitTest( pos ) && mEnabled )
|
|
{
|
|
if ( mpPlugin )
|
|
{
|
|
mpLayout->CaptureEventsForPane( mpPane );
|
|
mpLayout->CaptureEventsForPlugin( mpPlugin );
|
|
}
|
|
else
|
|
mpWnd->CaptureMouse();
|
|
|
|
mDragStarted = true;
|
|
mPressed = true;
|
|
mWasClicked = false;
|
|
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void cbMiniButton::OnLeftUp( const wxPoint& WXUNUSED(pos) )
|
|
{
|
|
if ( !mVisible || !mDragStarted ) return;
|
|
|
|
if ( mpPlugin )
|
|
{
|
|
mpLayout->ReleaseEventsFromPane( mpPane );
|
|
mpLayout->ReleaseEventsFromPlugin( mpPlugin );
|
|
}
|
|
else
|
|
mpWnd->ReleaseMouse();
|
|
|
|
mWasClicked = mPressed;
|
|
mDragStarted = false;
|
|
|
|
mPressed = false;
|
|
Refresh();
|
|
}
|
|
|
|
void cbMiniButton::OnMotion( const wxPoint& pos )
|
|
{
|
|
if ( !mVisible ) return;
|
|
|
|
if ( mDragStarted )
|
|
{
|
|
mPressed = HitTest( pos );
|
|
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void cbMiniButton::Refresh()
|
|
{
|
|
if ( mpLayout )
|
|
{
|
|
wxClientDC dc( &mpLayout->GetParentFrame() );
|
|
|
|
Draw( dc );
|
|
}
|
|
else
|
|
{
|
|
wxWindowDC dc( mpWnd );
|
|
|
|
Draw( dc );
|
|
}
|
|
}
|
|
|
|
void cbMiniButton::Draw( wxDC& dc )
|
|
{
|
|
if ( !mVisible ) return;
|
|
|
|
dc.SetPen( *wxTRANSPARENT_PEN );
|
|
|
|
dc.SetBrush( *wxLIGHT_GREY_BRUSH );
|
|
|
|
dc.DrawRectangle( mPos.x + 1, mPos.y + 1, BTN_BOX_WIDTH - 2, BTN_BOX_HEIGHT - 2 );
|
|
|
|
// "hard-code" metafile
|
|
|
|
if ( !mPressed )
|
|
dc.SetPen( *wxWHITE_PEN );
|
|
else
|
|
dc.SetPen( *wxBLACK_PEN );
|
|
|
|
dc.DrawLine( mPos.x, mPos.y, mPos.x + BTN_BOX_WIDTH, mPos.y );
|
|
dc.DrawLine( mPos.x, mPos.y, mPos.x, mPos.y + BTN_BOX_HEIGHT );
|
|
|
|
dc.SetPen( *wxGREY_PEN );
|
|
|
|
if ( !mPressed )
|
|
{
|
|
dc.DrawLine( mPos.x + 1, mPos.y + BTN_BOX_HEIGHT - 2,
|
|
mPos.x + BTN_BOX_WIDTH - 1, mPos.y + BTN_BOX_HEIGHT - 2 );
|
|
|
|
dc.DrawLine( mPos.x + BTN_BOX_WIDTH - 2, mPos.y + 1,
|
|
mPos.x + BTN_BOX_WIDTH - 2, mPos.y + BTN_BOX_HEIGHT - 1 );
|
|
}
|
|
else
|
|
{
|
|
dc.DrawLine( mPos.x + 1, mPos.y + 1,
|
|
mPos.x + BTN_BOX_WIDTH - 2, mPos.y + 1 );
|
|
|
|
dc.DrawLine( mPos.x + 1, mPos.y + 1,
|
|
mPos.x + 1, mPos.y + BTN_BOX_HEIGHT - 2 );
|
|
}
|
|
|
|
if ( !mPressed )
|
|
dc.SetPen( *wxBLACK_PEN );
|
|
else
|
|
dc.SetPen( *wxWHITE_PEN );
|
|
|
|
dc.DrawLine( mPos.x, mPos.y + BTN_BOX_HEIGHT - 1,
|
|
mPos.x + BTN_BOX_WIDTH, mPos.y + BTN_BOX_HEIGHT - 1 );
|
|
|
|
dc.DrawLine( mPos.x + BTN_BOX_WIDTH - 1, mPos.y ,
|
|
mPos.x + BTN_BOX_WIDTH - 1, mPos.y + BTN_BOX_HEIGHT );
|
|
}
|
|
|
|
bool cbMiniButton::WasClicked()
|
|
{
|
|
return mWasClicked;
|
|
}
|
|
|
|
void cbMiniButton::Reset()
|
|
{
|
|
mWasClicked = false;
|
|
}
|
|
|
|
/***** Implementation fro class cbCloseBox *****/
|
|
|
|
void cbCloseBox::Draw( wxDC& dc )
|
|
{
|
|
#if defined(__WXGTK__) || defined(__WXX11__)
|
|
|
|
cbMiniButton::Draw( dc );
|
|
|
|
wxPen pen( wxColour( 64,64,64 ) ,1, wxSOLID );
|
|
|
|
dc.SetPen( pen );
|
|
|
|
int width = BTN_BOX_WIDTH - 7;
|
|
|
|
int xOfs = (mPressed) ? 4 : 3;
|
|
int yOfs = (mPressed) ? 4 : 3;
|
|
|
|
int one = 1;
|
|
for( int i = 0; i != BTN_X_WIEGHT; ++i )
|
|
{
|
|
dc.DrawLine( mPos.x + xOfs + i - one,
|
|
mPos.y + yOfs - one,
|
|
mPos.x + xOfs + i + width,
|
|
mPos.y + yOfs + width + one);
|
|
|
|
dc.DrawLine( mPos.x + xOfs + i + width ,
|
|
mPos.y + yOfs - one - one,
|
|
mPos.x + xOfs + i - one,
|
|
mPos.y + yOfs + width );
|
|
}
|
|
|
|
#else
|
|
|
|
cbMiniButton::Draw( dc );
|
|
|
|
dc.SetPen( *wxBLACK_PEN );
|
|
|
|
int width = BTN_BOX_WIDTH - 7;
|
|
|
|
int xOfs = (mPressed) ? 4 : 3;
|
|
int yOfs = (mPressed) ? 4 : 3;
|
|
|
|
for( int i = 0; i != BTN_X_WIEGHT; ++i )
|
|
{
|
|
dc.DrawLine( mPos.x + xOfs + i,
|
|
mPos.y + yOfs,
|
|
mPos.x + xOfs + i + width,
|
|
mPos.y + yOfs + width );
|
|
|
|
dc.DrawLine( mPos.x + xOfs + i + width - 1,
|
|
mPos.y + yOfs,
|
|
mPos.x + xOfs + i - 1,
|
|
mPos.y + yOfs + width );
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/***** Implementation fro class cbCollapseBox *****/
|
|
|
|
inline static void my_swap( int& a, int& b )
|
|
{
|
|
long tmp = a;
|
|
a = b;
|
|
b = tmp;
|
|
}
|
|
|
|
void cbCollapseBox::Draw( wxDC& dc )
|
|
{
|
|
cbMiniButton::Draw( dc );
|
|
|
|
dc.SetPen( *wxTRANSPARENT_PEN );
|
|
|
|
wxPoint arr[3];
|
|
|
|
int yOfs = (mPressed) ? 3 : 2;
|
|
int xOfs = (mPressed) ? 5 : 4;
|
|
int width = BTN_BOX_WIDTH - 8;
|
|
|
|
// rotating/shifting triangle inside collapse box
|
|
|
|
arr[0].x = xOfs;
|
|
arr[0].y = yOfs-1;
|
|
arr[2].x = xOfs;
|
|
arr[2].y = BTN_BOX_HEIGHT - yOfs - 1;
|
|
arr[1].x = xOfs + width;
|
|
arr[1].y = (arr[2].y + arr[0].y)/2;
|
|
|
|
if ( !mIsAtLeft )
|
|
{
|
|
arr[0].x = BTN_BOX_WIDTH - arr[0].x;
|
|
arr[1].x = BTN_BOX_WIDTH - arr[1].x;
|
|
arr[2].x = BTN_BOX_WIDTH - arr[2].x;
|
|
}
|
|
|
|
if ( !mpPane->IsHorizontal() )
|
|
{
|
|
my_swap( arr[0].y, arr[0].x );
|
|
my_swap( arr[1].y, arr[1].x );
|
|
my_swap( arr[2].y, arr[2].x );
|
|
|
|
arr[0].x += 1;
|
|
arr[1].x += 1;
|
|
arr[2].x += 1;
|
|
|
|
//arr[1].y -= 1;
|
|
}
|
|
|
|
arr[0].x += mPos.x;
|
|
arr[0].y += mPos.y;
|
|
arr[1].x += mPos.x;
|
|
arr[1].y += mPos.y;
|
|
arr[2].x += mPos.x;
|
|
arr[2].y += mPos.y;
|
|
|
|
if ( !mEnabled ) dc.SetBrush( *wxGREY_BRUSH );
|
|
else dc.SetBrush( *wxBLACK_BRUSH );
|
|
|
|
dc.DrawPolygon( 3, arr );
|
|
dc.SetBrush( wxNullBrush );
|
|
}
|
|
|
|
/***** Implementation for class cbDockBoxBox *****/
|
|
|
|
void cbDockBox::Draw( wxDC& dc )
|
|
{
|
|
cbMiniButton::Draw( dc );
|
|
|
|
int width = BTN_BOX_WIDTH - 7;
|
|
|
|
int xOfs = (mPressed) ? 4 : 3;
|
|
int yOfs = (mPressed) ? 4 : 3;
|
|
|
|
dc.SetPen( *wxBLACK_PEN );
|
|
dc.SetBrush( *wxBLACK_BRUSH );
|
|
|
|
dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width, width );
|
|
|
|
xOfs += 1;
|
|
yOfs += 1;
|
|
|
|
dc.SetBrush( *wxWHITE_BRUSH );
|
|
|
|
dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width-2, width-2 );
|
|
}
|
|
|
|
/***** Implementation for class wxToolWindow *****/
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS( cbFloatedBarWindow, wxToolWindow )
|
|
|
|
BEGIN_EVENT_TABLE( cbFloatedBarWindow, wxToolWindow )
|
|
|
|
EVT_LEFT_DCLICK( cbFloatedBarWindow::OnDblClick )
|
|
|
|
END_EVENT_TABLE()
|
|
|
|
cbFloatedBarWindow::cbFloatedBarWindow()
|
|
|
|
: mpBar( NULL )
|
|
{
|
|
AddMiniButton( new cbCloseBox() );
|
|
AddMiniButton( new cbDockBox() );
|
|
}
|
|
|
|
void cbFloatedBarWindow::SetBar( cbBarInfo* pBar )
|
|
{
|
|
mpBar = pBar;
|
|
}
|
|
|
|
cbBarInfo* cbFloatedBarWindow::GetBar()
|
|
{
|
|
return mpBar;
|
|
}
|
|
|
|
void cbFloatedBarWindow::SetLayout( wxFrameLayout* pLayout )
|
|
{
|
|
mpLayout = pLayout;
|
|
}
|
|
|
|
void cbFloatedBarWindow::PositionFloatedWnd( int scrX, int scrY,
|
|
int width, int height )
|
|
{
|
|
wxSize minDim = GetMinimalWndDim();
|
|
|
|
SetSize( scrX - mWndHorizGap - mClntHorizGap,
|
|
scrY - mClntVertGap - mTitleHeight - mWndVertGap,
|
|
width + minDim.x, height + minDim.y, 0 );
|
|
}
|
|
|
|
wxSize cbFloatedBarWindow::GetPreferredSize( const wxSize& given )
|
|
{
|
|
if ( mpBar->mDimInfo.GetDimHandler() )
|
|
{
|
|
cbBarDimHandlerBase* pHandler = mpBar->mDimInfo.GetDimHandler();
|
|
|
|
wxSize prefDim;
|
|
|
|
// int vtad = *((int*)pHandler);
|
|
|
|
pHandler->OnResizeBar( mpBar, given, prefDim );
|
|
|
|
return prefDim;
|
|
}
|
|
else
|
|
{
|
|
if ( mpBar->IsFixed() )
|
|
return mpBar->mDimInfo.mSizes[ wxCBAR_FLOATING ];
|
|
else
|
|
return given; // not-fixed bars are resized exactly the way user wants
|
|
}
|
|
}
|
|
|
|
void cbFloatedBarWindow::OnMiniButtonClicked( int btnIdx )
|
|
{
|
|
// #1 - close mini-button
|
|
// #0 - dock mini-button
|
|
|
|
if ( btnIdx == 0 )
|
|
{
|
|
mpBar->mAlignment = -1; // sepcial "marking" for hidden bars out of floated state
|
|
mpLayout->SetBarState( mpBar, wxCBAR_HIDDEN, true );
|
|
}
|
|
else
|
|
mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, true );
|
|
}
|
|
|
|
bool cbFloatedBarWindow::HandleTitleClick( wxMouseEvent& event )
|
|
{
|
|
ReleaseMouse();
|
|
mMouseCaptured = false;
|
|
|
|
wxPoint scrPos;
|
|
GetScrMousePos( event, scrPos );
|
|
|
|
int msX = scrPos.x,
|
|
msY = scrPos.y;
|
|
|
|
mpLayout->GetParentFrame().ScreenToClient( &msX, &msY );
|
|
|
|
int x,y;
|
|
GetPosition(&x,&y);
|
|
int w,h;
|
|
GetSize( &w, &h );
|
|
|
|
wxSize minDim = GetMinimalWndDim();
|
|
|
|
w -= minDim.x;
|
|
h -= minDim.y;
|
|
|
|
x += mWndHorizGap + mClntHorizGap;
|
|
y += mWndVertGap + mTitleHeight + mClntVertGap;
|
|
|
|
mpLayout->GetParentFrame().ScreenToClient( &x, &y );
|
|
|
|
wxRect& bounds = mpBar->mDimInfo.mBounds[ wxCBAR_FLOATING ];
|
|
|
|
bounds.x = x;
|
|
bounds.y = y;
|
|
bounds.width = w;
|
|
bounds.height = h;
|
|
|
|
cbStartBarDraggingEvent dragEvt( mpBar, wxPoint(msX,msY),
|
|
mpLayout->GetPanesArray()[FL_ALIGN_TOP] );
|
|
|
|
mpLayout->FirePluginEvent( dragEvt );
|
|
|
|
return true;
|
|
}
|
|
|
|
void cbFloatedBarWindow::OnDblClick( wxMouseEvent& WXUNUSED(event) )
|
|
{
|
|
mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, true );
|
|
|
|
//wxMessageBox("toolWnd - dblClick!");
|
|
}
|
|
|