Logo Search packages:      
Sourcecode: wxwindows2.4 version File versions

toolwnd.cpp

/////////////////////////////////////////////////////////////////////////////
// Name:        toolwnd.cpp
// Purpose:     wxToolWindow implementation.
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     06/09/98
// RCS-ID:      $Id: toolwnd.cpp,v 1.9.2.2 2005/06/20 17:34:36 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/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& event )
{
    wxPaintDC pdc( this );
      wxWindowDC dc( this );

      int w,h;
      GetSize( &w, &h );

    wxBrush backGround( wxSystemSettings::GetSystemColour(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;
      }

      if ( !mMouseCaptured )
      {
            mMouseCaptured = TRUE;
            CaptureMouse();
      }

      // 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; 
            }
      }
}

#define 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, -INFINITY, mInitialRect.x + mInitialRect.width  - minDim.x  );
            clip_to( top,  -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,    -INFINITY, mInitialRect.x + mInitialRect.width  - minDim.x  );
            clip_to( bottom,  mInitialRect.y + minDim.y, 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, INFINITY );
            clip_to( top,   -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,  INFINITY );
            clip_to( bottom, mInitialRect.y + minDim.y, 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("%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& 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& 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& 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& event )
{
      mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, TRUE );

      //wxMessageBox("toolWnd - dblClick!");
}


Generated by  Doxygen 1.6.0   Back to index