home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / contrib / src / fl / toolwnd.cpp < prev    next >
C/C++ Source or Header  |  2002-07-21  |  26KB  |  1,147 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        toolwnd.cpp
  3. // Purpose:     wxToolWindow implementation.
  4. // Author:      Aleksandras Gluchovas
  5. // Modified by:
  6. // Created:     06/09/98
  7. // RCS-ID:      $Id: toolwnd.cpp,v 1.9 2002/07/21 10:17:02 GD Exp $
  8. // Copyright:   (c) Aleksandras Gluchovas
  9. // Licence:       wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13.     #pragma implementation "toolwnd.h"
  14. #endif
  15.  
  16. // For compilers that support precompilation, includes "wx.h".
  17. #include "wx/wxprec.h"
  18.  
  19. #ifdef __BORLANDC__
  20. #pragma hdrstop
  21. #endif
  22.  
  23. #ifndef WX_PRECOMP
  24. #include "wx/wx.h"
  25. #endif
  26.  
  27. #include "wx/fl/toolwnd.h"
  28.  
  29. #define _IMG_A  0xAA    // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
  30. #define _IMG_B  0x00    // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
  31. #define _IMG_C  0x55    // Note: modified from _C to _IMG_C, for consistency reasons.
  32. #define _IMG_D  0x00    // Note: modified from _D to _IMG_D, for consistency reasons.
  33.  
  34. // FOR NOW:: static
  35.  
  36. static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D,
  37.                                                 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
  38.                                                 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
  39.                                                 _IMG_A,_IMG_B,_IMG_C,_IMG_D
  40.                                               };
  41.  
  42. /***** Implementation for class wxToolWindow *****/
  43.  
  44. IMPLEMENT_DYNAMIC_CLASS( wxToolWindow, wxFrame)
  45.  
  46. BEGIN_EVENT_TABLE( wxToolWindow, wxFrame )
  47.  
  48.     EVT_PAINT    ( wxToolWindow::OnPaint )
  49.     EVT_MOTION   ( wxToolWindow::OnMotion )
  50.     EVT_LEFT_DOWN( wxToolWindow::OnLeftDown )
  51.     EVT_LEFT_UP  ( wxToolWindow::OnLeftUp )
  52.     EVT_SIZE     ( wxToolWindow::OnSize )
  53.  
  54.  
  55.     EVT_ERASE_BACKGROUND( wxToolWindow::OnEraseBackground )
  56.  
  57. END_EVENT_TABLE()
  58.  
  59. enum INTERNAL_HIT_CODES
  60. {
  61.     HITS_WND_NOTHING,
  62.     HITS_WND_CLIENT,
  63.     HITS_WND_TITLE,
  64.  
  65.     HITS_WND_LEFT_EDGE,
  66.     HITS_WND_RIGHT_EDGE,
  67.     HITS_WND_TOP_EDGE,
  68.     HITS_WND_BOTTOM_EDGE,
  69.  
  70.     HITS_WND_TOP_LEFT_CORNER,
  71.     HITS_WND_BOTTOM_RIGHT_CORNER,
  72.     HITS_WND_TOP_RIGHT_CORNER,
  73.     HITS_WND_BOTTOM_LEFT_CORNER
  74. };
  75.  
  76. wxToolWindow::wxToolWindow()
  77.  
  78.     : mpClientWnd   ( NULL ),
  79.       
  80. #ifndef __WXMSW__
  81.       mTitleFont( 8, wxSWISS,  wxNORMAL, wxNORMAL ),
  82. #else
  83.       // just to simulate MS-Dev style
  84.       mTitleFont( 8, wxSWISS,  wxNORMAL, wxNORMAL, FALSE, "MS Sans Serif" ),
  85. #endif
  86.  
  87.       mTitleHeight  ( 16 ),
  88.       mClntHorizGap ( 2 ),
  89.       mClntVertGap  ( 2 ),
  90.       mWndVertGap   ( 4 ),
  91.       mWndHorizGap  ( 4 ),
  92.  
  93.       mButtonGap    ( 2 ),
  94.       mInTitleMargin( 4 ),
  95.       mHintBorder   ( 4 ),
  96.  
  97.       mResizeStarted( FALSE ),
  98.       mRealTimeUpdatesOn( TRUE ),
  99.    
  100.       mMTolerance   ( 5 ), // mouse-resizing tollerance
  101.  
  102.       mCursorType( HITS_WND_NOTHING ),
  103.       mMouseCaptured( FALSE ),
  104.       
  105.       mpScrDc( NULL )
  106.  
  107. {
  108. }
  109.  
  110. wxToolWindow::~wxToolWindow()
  111. {
  112.     if ( mpScrDc ) delete mpScrDc; 
  113.  
  114.     for( size_t i = 0; i != mButtons.Count(); ++i )
  115.         
  116.         delete mButtons[i];
  117. }
  118.  
  119. void wxToolWindow::LayoutMiniButtons()
  120. {                      
  121.     int w,h;
  122.  
  123.     GetSize( &w, &h );
  124.  
  125.     int x = w - mWndHorizGap - mInTitleMargin - BTN_BOX_WIDTH; 
  126.     int y = mWndVertGap + 2;
  127.  
  128.     for( size_t i = 0; i != mButtons.Count(); ++i )
  129.     {
  130.         mButtons[i]->SetPos( wxPoint( x,y ) );
  131.         x-= BTN_BOX_WIDTH + mButtonGap;
  132.     }
  133. }
  134.  
  135. void wxToolWindow::SetClient( wxWindow* pWnd )
  136. {
  137.     mpClientWnd = pWnd;
  138. }
  139.  
  140. wxWindow* wxToolWindow::GetClient()
  141. {
  142.     return mpClientWnd;
  143. }
  144.  
  145. void wxToolWindow::SetTitleFont( wxFont& font )
  146. {
  147.     mTitleFont = font;
  148. }
  149.  
  150. void wxToolWindow::AddMiniButton( cbMiniButton* pBtn )
  151. {
  152.     pBtn->mpWnd = this;
  153.  
  154.     mButtons.Add( pBtn );
  155.  
  156.     // not necesserely now..
  157.     //LayoutMiniButtons();
  158. }
  159.  
  160. void wxToolWindow::OnPaint( wxPaintEvent& event )
  161. {
  162.     wxPaintDC pdc( this );
  163.     wxWindowDC dc( this );
  164.  
  165.     int w,h;
  166.     GetSize( &w, &h );
  167.  
  168.     wxBrush backGround( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE), wxSOLID );
  169.     //dc.SetBrush( *wxLIGHT_GREY_BRUSH );
  170.     dc.SetBrush( backGround ); 
  171.     dc.SetPen( *wxTRANSPARENT_PEN );
  172.  
  173.     int y = mWndVertGap + mTitleHeight + mClntVertGap;
  174.     dc.DrawRectangle( 0,0, w, y );                                      // Top grey part.
  175.     dc.DrawRectangle( 0,y-1, mWndHorizGap + mClntHorizGap, h - y );     // Left grey part.
  176.     dc.DrawRectangle( w - ( mWndHorizGap + mClntHorizGap ), y-1,
  177.                       mWndHorizGap + mClntHorizGap, h - y );            // Right grey part.
  178.     dc.DrawRectangle( 0, h - mWndVertGap - mClntVertGap, w, mWndVertGap + mClntVertGap ); // Bottom grey part.
  179.  
  180.     // draw shades
  181.     dc.SetPen( *wxLIGHT_GREY_PEN );
  182.  
  183.     dc.DrawLine( 0,0, w, 0 );
  184.     dc.DrawLine( 0,0, 0, h );
  185.  
  186.     dc.SetPen( *wxWHITE_PEN );
  187.  
  188.     dc.DrawLine( 1,1, w, 1 );
  189.     dc.DrawLine( 1,2, 1, h );
  190.  
  191.     dc.SetPen( *wxGREY_PEN );
  192.  
  193.     dc.DrawLine( w - 2, 1, w - 2, h - 1 );
  194.     dc.DrawLine( 1, h - 2, w - 2, h - 2 );
  195.  
  196.     dc.SetPen( *wxBLACK_PEN );
  197.  
  198.     dc.DrawLine( 0, h - 1, w, h - 1 );
  199.     dc.DrawLine( w-1, 0, w-1, h );
  200.  
  201.     // fill inner area
  202.  
  203.     dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( wxColour( 0,0,128 ), wxSOLID ) );
  204.  
  205.     dc.DrawRectangle( mWndHorizGap, mWndVertGap, w - mWndHorizGap*2, mTitleHeight );
  206.  
  207.     dc.SetFont( mTitleFont );
  208.  
  209.     for( size_t i = 0; i != mButtons.Count(); ++i )
  210.  
  211.         mButtons[i]->Draw( dc );
  212.  
  213.     int x1 = mWndHorizGap + mClntHorizGap;
  214.     int x2 = mButtons[ mButtons.GetCount() - 1 ]->mPos.x - mClntHorizGap*2;
  215.  
  216.     dc.SetClippingRegion( x1, mWndVertGap + mClntVertGap, x2 - x1, mTitleHeight );
  217.  
  218.     dc.SetTextForeground( *wxWHITE );
  219.     dc.SetBackgroundMode(  wxTRANSPARENT );
  220.     dc.DrawText( GetTitle(), mWndHorizGap + 2, mWndVertGap + 1 );
  221. }
  222.  
  223. void wxToolWindow::GetScrWindowRect( wxRect& r )
  224. {
  225.     int x,y;
  226.     GetPosition(&x,&y);
  227.     int w,h;
  228.     GetSize( &w, &h );
  229.  
  230.     r.x = x; r.y = y;
  231.     r.width = w; r.height = h;
  232. }
  233.  
  234. void wxToolWindow::GetScrMousePos( wxMouseEvent& event, wxPoint& pos )
  235. {
  236.     int x = event.m_x, y = event.m_y;
  237.  
  238.     ClientToScreen( &x, &y );
  239.  
  240.     pos.x = x; pos.y = y;
  241. }
  242.  
  243. int wxToolWindow::HitTestWindow( wxMouseEvent& event )
  244. {
  245.     wxPoint pos;
  246.     wxRect r;
  247.  
  248.     GetScrMousePos( event, pos );
  249.     GetScrWindowRect( r );
  250.  
  251.     int k = mMTolerance;
  252.  
  253.     if ( !( pos.x >= r.x && pos.y >= r.y &&
  254.             pos.x < r.x + r.width &&
  255.             pos.y < r.y + r.height ) 
  256.        )
  257.        return HITS_WND_NOTHING; 
  258.  
  259.     if ( pos.y <= r.y + k )
  260.     {
  261.         if ( pos.x < r.x + k*2 )
  262.  
  263.             return HITS_WND_TOP_LEFT_CORNER;
  264.         else
  265.         if ( pos.x >= r.x + r.width - k*2 )
  266.  
  267.             return HITS_WND_TOP_RIGHT_CORNER;
  268.         else
  269.             return HITS_WND_TOP_EDGE;
  270.     }
  271.     else
  272.     if ( pos.y >= r.y + r.height - k )
  273.     {
  274.         if ( pos.x < r.x + k*2 )
  275.  
  276.             return HITS_WND_BOTTOM_LEFT_CORNER;
  277.         else
  278.         if ( pos.x > r.x + r.width - k*2 )
  279.  
  280.             return HITS_WND_BOTTOM_RIGHT_CORNER;
  281.         else
  282.             return HITS_WND_BOTTOM_EDGE;
  283.     }
  284.     else
  285.     if ( pos.x <= r.x + k )
  286.     
  287.         return HITS_WND_LEFT_EDGE;
  288.     else
  289.     if ( pos.x >= r.x + r.width - k )
  290.  
  291.         return HITS_WND_RIGHT_EDGE;
  292.     else
  293.     {
  294.         if ( pos.y <= r.y + mWndVertGap + mTitleHeight + mClntVertGap )
  295.  
  296.             return HITS_WND_TITLE;
  297.         else
  298.             return HITS_WND_CLIENT;
  299.     }
  300. }
  301.  
  302. void wxToolWindow::DrawHintRect( const wxRect& r )
  303. {
  304.     // BUG BUG BUG (wx):: somehow stippled brush works only  
  305.     //                      when the bitmap created on stack, not
  306.     //                      as a member of the class
  307.  
  308.     int prevLF = mpScrDc->GetLogicalFunction();
  309.  
  310.     mpScrDc->SetLogicalFunction( wxXOR );
  311.  
  312.     wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
  313.  
  314.     wxBrush checkerBrush( checker );
  315.  
  316.     mpScrDc->SetPen( *wxTRANSPARENT_PEN );
  317.     mpScrDc->SetBrush( checkerBrush );
  318.  
  319.     int half = mHintBorder / 2;
  320.  
  321.     mpScrDc->DrawRectangle( r.x - half, r.y - half,
  322.                             r.width + 2*half, mHintBorder );
  323.  
  324.     mpScrDc->DrawRectangle( r.x - half, r.y + r.height - half,
  325.                             r.width + 2*half, mHintBorder );
  326.  
  327.     mpScrDc->DrawRectangle( r.x - half, r.y + half - 1,
  328.                             mHintBorder, r.height - 2*half + 2);
  329.  
  330.     mpScrDc->DrawRectangle( r.x + r.width - half,
  331.                             r.y + half - 1,
  332.                             mHintBorder, r.height - 2*half + 2);
  333.  
  334.     mpScrDc->SetBrush( wxNullBrush );
  335.  
  336.     mpScrDc->SetLogicalFunction( prevLF );
  337. }
  338.  
  339. void wxToolWindow::SetHintCursor( int type )
  340. {
  341.     if ( mResizeStarted )
  342.         return;
  343.  
  344.     if ( type == HITS_WND_NOTHING || type == HITS_WND_CLIENT )
  345.     {
  346.         // the cursor is out of window - reset to arrow
  347.  
  348.         if ( mMouseCaptured )
  349.         {
  350.             ReleaseMouse();
  351.             mMouseCaptured = FALSE;
  352.         }
  353.  
  354.         SetCursor( wxCURSOR_ARROW );
  355.  
  356.         mCursorType = type;
  357.  
  358.         return;
  359.     }
  360.  
  361.     if ( !mMouseCaptured )
  362.     {
  363.         mMouseCaptured = TRUE;
  364.         CaptureMouse();
  365.     }
  366.  
  367.     // did the cursor actually changed?
  368.     
  369.     if ( type != mCursorType )
  370.     {
  371.         mCursorType = type;
  372.  
  373.         switch ( type )
  374.         {
  375.             case HITS_WND_LEFT_EDGE   : SetCursor( wxCURSOR_SIZEWE ); break;
  376.             case HITS_WND_RIGHT_EDGE  : SetCursor( wxCURSOR_SIZEWE ); break;
  377.             case HITS_WND_TOP_EDGE    : SetCursor( wxCURSOR_SIZENS ); break;
  378.             case HITS_WND_BOTTOM_EDGE : SetCursor( wxCURSOR_SIZENS ); break;
  379.  
  380.             case HITS_WND_TOP_LEFT_CORNER     : SetCursor( wxCURSOR_SIZENWSE ); break;
  381.             case HITS_WND_BOTTOM_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break;
  382.             case HITS_WND_TOP_RIGHT_CORNER    : SetCursor( wxCURSOR_SIZENESW ); break;
  383.             case HITS_WND_BOTTOM_LEFT_CORNER  : SetCursor( wxCURSOR_SIZENESW ); break;
  384.  
  385.             case HITS_WND_TITLE  : SetCursor( wxCURSOR_ARROW ); break;
  386.             case HITS_WND_CLIENT : SetCursor( wxCURSOR_ARROW ); break;
  387.  
  388.             default: break; 
  389.         }
  390.     }
  391. }
  392.  
  393. #define INFINITY 32768
  394.  
  395. static inline void clip_to( int& value, long from, long till )
  396. {
  397.     if ( value < from ) 
  398.         value = from;
  399.  
  400.     if ( value > till ) 
  401.         value = till;
  402. }
  403.  
  404. void wxToolWindow::AdjustRectPos( const wxRect& original, const wxSize& newDim, wxRect& newRect )
  405. {
  406.     if ( mCursorType == HITS_WND_TOP_EDGE || 
  407.          mCursorType == HITS_WND_TOP_LEFT_CORNER )
  408.     {
  409.         newRect.x = original.x + original.width  - newDim.x;
  410.         newRect.y = original.y + original.height - newDim.y;
  411.     }
  412.     else
  413.     if ( mCursorType == HITS_WND_LEFT_EDGE || 
  414.          mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
  415.     {
  416.         newRect.x = original.x + original.width  - newDim.x;
  417.         newRect.y = original.y;
  418.     }
  419.     else
  420.     if ( mCursorType == HITS_WND_RIGHT_EDGE || 
  421.          mCursorType == HITS_WND_TOP_RIGHT_CORNER )
  422.     {
  423.         newRect.x = original.x;
  424.         newRect.y = original.y + original.height - newDim.y;
  425.     }
  426.     else
  427.     if ( mCursorType == HITS_WND_BOTTOM_EDGE || 
  428.          mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
  429.     {
  430.         newRect.x = original.x;
  431.         newRect.y = original.y;
  432.     }
  433.  
  434.     newRect.width  = newDim.x;
  435.     newRect.height = newDim.y;
  436. }
  437.  
  438. void wxToolWindow::CalcResizedRect( wxRect& rect, wxPoint& delta, const wxSize& minDim )
  439. {
  440.     // Microsoft's rect-coordinates are best suited
  441.     // for the case of corner-clipping
  442.     
  443.     int left   = mInitialRect.x;
  444.     int top    = mInitialRect.y;
  445.     int right  = mInitialRect.x + mInitialRect.width;
  446.     int bottom = mInitialRect.y + mInitialRect.height;
  447.  
  448.     // constraint delta edge is dragged
  449.  
  450.     switch ( mCursorType )
  451.     {
  452.         case HITS_WND_LEFT_EDGE   : delta.y = 0; break;
  453.         case HITS_WND_RIGHT_EDGE  : delta.y = 0; break;
  454.         case HITS_WND_TOP_EDGE    : delta.x = 0; break;
  455.         case HITS_WND_BOTTOM_EDGE : delta.x = 0; break;
  456.         default: break;
  457.     }
  458.  
  459.     if ( mCursorType == HITS_WND_TOP_EDGE || 
  460.          mCursorType == HITS_WND_TOP_LEFT_CORNER )
  461.     {
  462.         left += delta.x;
  463.         top  += delta.y;
  464.  
  465.         clip_to( left, -INFINITY, mInitialRect.x + mInitialRect.width  - minDim.x  );
  466.         clip_to( top,  -INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
  467.     }
  468.     else
  469.     if ( mCursorType == HITS_WND_LEFT_EDGE || 
  470.          mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
  471.     {
  472.         left   += delta.x;
  473.         bottom += delta.y;
  474.  
  475.         clip_to( left,    -INFINITY, mInitialRect.x + mInitialRect.width  - minDim.x  );
  476.         clip_to( bottom,  mInitialRect.y + minDim.y, INFINITY );
  477.     }
  478.     else
  479.     if ( mCursorType == HITS_WND_RIGHT_EDGE || 
  480.          mCursorType == HITS_WND_TOP_RIGHT_CORNER )
  481.     {
  482.         right += delta.x;
  483.         top   += delta.y;
  484.  
  485.         clip_to( right, mInitialRect.x + minDim.x, INFINITY );
  486.         clip_to( top,   -INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
  487.     }
  488.     else
  489.     if ( mCursorType == HITS_WND_BOTTOM_EDGE || 
  490.          mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
  491.     {
  492.         right  += delta.x;
  493.         bottom += delta.y;
  494.  
  495.         clip_to( right,  mInitialRect.x + minDim.x,  INFINITY );
  496.         clip_to( bottom, mInitialRect.y + minDim.y, INFINITY );
  497.     }
  498.     else
  499.     {
  500.         wxFAIL_MSG( _T("what did the cursor hit?") );
  501.     }
  502.  
  503.     rect.x = left;
  504.     rect.y = top;
  505.     rect.width  = right - left;
  506.     rect.height = bottom - top;
  507. }
  508.  
  509. wxSize wxToolWindow::GetMinimalWndDim()
  510. {
  511.     return wxSize( (mWndHorizGap + mClntHorizGap)*2 + BTN_BOX_WIDTH*4,
  512.                    (mWndVertGap  + mClntVertGap )*2 + mTitleHeight );
  513. }
  514.  
  515. void wxToolWindow::OnMotion( wxMouseEvent& event )
  516. {
  517.     if ( !mResizeStarted )
  518.     {
  519.         for( size_t i = 0; i != mButtons.Count(); ++i )
  520.         
  521.             mButtons[i]->OnMotion( wxPoint( event.m_x, event.m_y ) );
  522.  
  523.         SetHintCursor( HitTestWindow( event ) );
  524.         return;
  525.     }
  526.  
  527.     wxPoint pos;
  528.     GetScrMousePos( event, pos );
  529.  
  530.     if ( mCursorType == HITS_WND_TITLE )
  531.     {
  532.         int w,h;
  533.         GetSize( &w, &h );
  534.  
  535.         SetSize( mInitialRect.x + pos.x - mDragOrigin.x,
  536.                  mInitialRect.y + pos.y - mDragOrigin.y,
  537.                  w,h, 0 );
  538.     }
  539.  
  540.     else
  541.     {
  542.         wxPoint delta( pos.x - mDragOrigin.x, pos.y - mDragOrigin.y );
  543.  
  544.         wxRect newRect;
  545.  
  546.         wxSize minDim = GetMinimalWndDim();
  547.  
  548.         CalcResizedRect( newRect, delta, minDim );
  549.  
  550.         wxSize borderDim( ( mWndHorizGap + mClntHorizGap )*2,
  551.                           ( mWndVertGap  + mClntVertGap  )*2 + mTitleHeight );
  552.  
  553.         wxSize preferred = GetPreferredSize( wxSize( newRect.width  - borderDim.x, 
  554.                                                      newRect.height - borderDim.y ) );
  555.  
  556.         preferred.x += borderDim.x;
  557.         preferred.y += borderDim.y;
  558.  
  559.         //CalcResizedRect( newRect, delta, preferred );
  560.  
  561.         wxRect finalRect = newRect;
  562.  
  563.         AdjustRectPos( newRect, preferred, finalRect );
  564.  
  565.         if ( mRealTimeUpdatesOn )
  566.         {
  567.                 SetSize( finalRect.x, finalRect.y,
  568.                          finalRect.width, finalRect.height, 0 );
  569.         }
  570.         else
  571.         {
  572.             DrawHintRect( mPrevHintRect );
  573.             DrawHintRect( finalRect );
  574.  
  575.             ::wxLogTrace("%d,%d / %d,%d\n", finalRect.x, finalRect.y, finalRect.width, finalRect.height);
  576.         }
  577.  
  578.         mPrevHintRect = finalRect;
  579.     }
  580. }
  581.  
  582. void wxToolWindow::OnLeftDown( wxMouseEvent& event )
  583. {
  584.     int result = HitTestWindow( event );
  585.  
  586.     for( size_t i = 0; i != mButtons.Count(); ++i )
  587.     {
  588.         mButtons[i]->OnLeftDown( wxPoint( event.m_x, event.m_y ) );
  589.  
  590.         if ( mButtons[i]->IsPressed() ) 
  591.  
  592.             return; // button hitted, 
  593.     }
  594.  
  595.     if ( result >= HITS_WND_LEFT_EDGE || result == HITS_WND_TITLE )
  596.     {
  597.         GetScrMousePos( event, mDragOrigin );
  598.  
  599.         /*
  600.         if ( mMouseCaptured `)
  601.         {
  602.             ReleaseMouse();
  603.             mMouseCaptured = FALSE;
  604.         }*/
  605.  
  606.         if ( result == HITS_WND_TITLE && 
  607.              HandleTitleClick( event )
  608.            )
  609.         {
  610.  
  611.            return;
  612.         }
  613.  
  614.         mResizeStarted = TRUE;
  615.  
  616.         int x,y;
  617.         GetPosition( &x, &y );
  618.  
  619.         mInitialRect.x = x;
  620.         mInitialRect.y = y;
  621.  
  622.         GetSize( &x, &y );
  623.         mInitialRect.width  = x;
  624.         mInitialRect.height = y;
  625.  
  626.         mPrevHintRect = mInitialRect;
  627.  
  628.         if ( mCursorType != HITS_WND_TITLE && !mRealTimeUpdatesOn )
  629.         {
  630.             mpScrDc = new wxScreenDC();
  631.  
  632.             wxScreenDC::StartDrawingOnTop( (wxRect*)NULL );
  633.  
  634.             DrawHintRect( mInitialRect );
  635.         }
  636.     }
  637. }
  638.  
  639. void wxToolWindow::OnLeftUp( wxMouseEvent& event )
  640. {
  641.     for( size_t i = 0; i != mButtons.Count(); ++i )
  642.     {
  643.         mButtons[i]->OnLeftUp( wxPoint( event.m_x, event.m_y ) );
  644.  
  645.         if ( mButtons[i]->WasClicked() )
  646.         {
  647.             OnMiniButtonClicked( i ); // notify derived classes
  648.             mButtons[i]->Reset();
  649.         }
  650.     }
  651.  
  652.     if ( mResizeStarted ) 
  653.     {
  654.         mResizeStarted = FALSE;
  655.  
  656.         if ( mCursorType != HITS_WND_TITLE )
  657.         {
  658.             if ( !mRealTimeUpdatesOn )
  659.             {
  660.                 DrawHintRect( mPrevHintRect );
  661.  
  662.                 wxScreenDC::EndDrawingOnTop();
  663.  
  664.                 delete mpScrDc;
  665.  
  666.                 mpScrDc = NULL;
  667.  
  668.                 SetSize( mPrevHintRect.x, mPrevHintRect.y,
  669.                          mPrevHintRect.width, mPrevHintRect.height, 0 );
  670.             }
  671.         }
  672.     }
  673. }
  674.  
  675. void wxToolWindow::OnSize( wxSizeEvent& event )
  676. {
  677.     if ( mpClientWnd )
  678.     {
  679.         int w,h;
  680.         GetSize( &w, &h );
  681.  
  682.         int x = mWndHorizGap + mClntHorizGap;
  683.         int y = mWndVertGap  + mTitleHeight + mClntVertGap;
  684.  
  685.         mpClientWnd->SetSize( x-1, y-1, 
  686.                               w - 2*(mWndHorizGap + mClntHorizGap),
  687.                               h - y - mClntVertGap - mWndVertGap, 
  688.                               0  
  689.                             );
  690.     }
  691.  
  692.     LayoutMiniButtons();
  693. }
  694.  
  695. wxSize wxToolWindow::GetPreferredSize( const wxSize& given )
  696. {
  697.     return given;
  698. }
  699.  
  700. void wxToolWindow::OnEraseBackground( wxEraseEvent& event )
  701. {
  702.     // nothing
  703. }
  704.  
  705. /***** Implementation for class cbMiniButton *****/
  706.  
  707. cbMiniButton::cbMiniButton()
  708.  
  709.     : mVisible( TRUE ),
  710.       mEnabled( TRUE ),
  711.  
  712.       mpLayout( NULL ),
  713.       mpPane  ( NULL ),
  714.       mpPlugin( NULL ),
  715.       mpWnd   ( NULL ),
  716.  
  717.       mWasClicked( FALSE ),
  718.       mDragStarted( FALSE ),
  719.       mPressed( FALSE )
  720. {}
  721.  
  722. void cbMiniButton::SetPos( const wxPoint& pos )
  723. {
  724.     mPos = pos;
  725. }
  726.  
  727. bool cbMiniButton::HitTest( const wxPoint& pos )
  728. {
  729.     if ( !mVisible ) return FALSE;
  730.  
  731.     return ( pos.x >= mPos.x && pos.y >= mPos.y &&
  732.              pos.x < mPos.x + BTN_BOX_WIDTH     &&
  733.              pos.y < mPos.y + BTN_BOX_HEIGHT );
  734. }
  735.  
  736. void cbMiniButton::OnLeftDown( const wxPoint& pos )
  737. {
  738.     if ( !mVisible || mDragStarted ) return;
  739.  
  740.     if ( HitTest( pos ) && mEnabled )
  741.     {
  742.         if ( mpPlugin )
  743.         {
  744.             mpLayout->CaptureEventsForPane( mpPane );
  745.             mpLayout->CaptureEventsForPlugin( mpPlugin );
  746.         }
  747.         else
  748.             mpWnd->CaptureMouse();
  749.  
  750.         mDragStarted = TRUE;
  751.         mPressed     = TRUE;
  752.         mWasClicked  = FALSE;
  753.  
  754.         Refresh();
  755.     }
  756. }
  757.  
  758. void cbMiniButton::OnLeftUp( const wxPoint& pos )
  759. {
  760.     if ( !mVisible || !mDragStarted ) return;
  761.  
  762.     if ( mpPlugin )
  763.     {
  764.         mpLayout->ReleaseEventsFromPane( mpPane );
  765.         mpLayout->ReleaseEventsFromPlugin( mpPlugin );
  766.     }
  767.     else
  768.         mpWnd->ReleaseMouse();
  769.  
  770.     mWasClicked  = mPressed;
  771.     mDragStarted = FALSE;
  772.  
  773.     mPressed = FALSE;
  774.     Refresh();
  775. }
  776.  
  777. void cbMiniButton::OnMotion( const wxPoint& pos )
  778. {
  779.     if ( !mVisible ) return;
  780.  
  781.     if ( mDragStarted )
  782.     {
  783.         mPressed = HitTest( pos );
  784.  
  785.         Refresh();
  786.     }
  787. }
  788.  
  789. void cbMiniButton::Refresh()
  790. {
  791.     if ( mpLayout )
  792.     {
  793.         wxClientDC dc( &mpLayout->GetParentFrame() );
  794.  
  795.         Draw( dc );
  796.     }
  797.     else
  798.     {
  799.         wxWindowDC dc( mpWnd );
  800.  
  801.         Draw( dc );
  802.     }
  803. }
  804.  
  805. void cbMiniButton::Draw( wxDC& dc )
  806. {
  807.     if ( !mVisible ) return;
  808.  
  809.     dc.SetPen( *wxTRANSPARENT_PEN );
  810.  
  811.     dc.SetBrush( *wxLIGHT_GREY_BRUSH );
  812.  
  813.     dc.DrawRectangle( mPos.x + 1, mPos.y + 1, BTN_BOX_WIDTH - 2, BTN_BOX_HEIGHT - 2 );
  814.  
  815.     // "hard-code" metafile
  816.  
  817.     if ( !mPressed )
  818.  
  819.         dc.SetPen( *wxWHITE_PEN );
  820.     else
  821.         dc.SetPen( *wxBLACK_PEN );
  822.  
  823.     dc.DrawLine( mPos.x, mPos.y, mPos.x + BTN_BOX_WIDTH, mPos.y );
  824.     dc.DrawLine( mPos.x, mPos.y, mPos.x, mPos.y + BTN_BOX_HEIGHT );
  825.  
  826.     dc.SetPen( *wxGREY_PEN );
  827.  
  828.     if ( !mPressed )
  829.     {
  830.         dc.DrawLine( mPos.x + 1, mPos.y + BTN_BOX_HEIGHT - 2, 
  831.                      mPos.x + BTN_BOX_WIDTH - 1, mPos.y + BTN_BOX_HEIGHT - 2 );
  832.         
  833.         dc.DrawLine( mPos.x + BTN_BOX_WIDTH - 2, mPos.y + 1, 
  834.                      mPos.x + BTN_BOX_WIDTH - 2, mPos.y + BTN_BOX_HEIGHT - 1 );
  835.     }
  836.     else
  837.     {
  838.         dc.DrawLine( mPos.x + 1, mPos.y + 1, 
  839.                      mPos.x + BTN_BOX_WIDTH - 2, mPos.y + 1 );
  840.                      
  841.         dc.DrawLine( mPos.x + 1, mPos.y + 1,
  842.                      mPos.x + 1, mPos.y + BTN_BOX_HEIGHT - 2 );
  843.     }
  844.  
  845.     if ( !mPressed )
  846.  
  847.         dc.SetPen( *wxBLACK_PEN );
  848.     else
  849.         dc.SetPen( *wxWHITE_PEN );
  850.  
  851.     dc.DrawLine( mPos.x, mPos.y + BTN_BOX_HEIGHT - 1,  
  852.                  mPos.x + BTN_BOX_WIDTH, mPos.y + BTN_BOX_HEIGHT - 1 );
  853.  
  854.     dc.DrawLine( mPos.x + BTN_BOX_WIDTH - 1, mPos.y ,
  855.                  mPos.x + BTN_BOX_WIDTH - 1, mPos.y + BTN_BOX_HEIGHT );
  856. }
  857.  
  858. bool cbMiniButton::WasClicked() 
  859.     return mWasClicked; 
  860. }
  861.  
  862. void cbMiniButton::Reset() 
  863.     mWasClicked = FALSE; 
  864. }
  865.  
  866. /***** Implementation fro class cbCloseBox *****/
  867.  
  868. void cbCloseBox::Draw( wxDC& dc )
  869. {
  870. #if defined(__WXGTK__) || defined(__WXX11__)
  871.  
  872.     cbMiniButton::Draw( dc );
  873.     
  874.     wxPen pen( wxColour( 64,64,64 ) ,1, wxSOLID );
  875.     
  876.     dc.SetPen( pen );
  877.     
  878.     int width = BTN_BOX_WIDTH - 7;
  879.     
  880.     int xOfs = (mPressed) ? 4 : 3;
  881.     int yOfs = (mPressed) ? 4 : 3;    
  882.  
  883.     int one = 1;
  884.     for( int i = 0; i != BTN_X_WIEGHT; ++i )
  885.     {
  886.         dc.DrawLine( mPos.x + xOfs + i - one,
  887.                      mPos.y + yOfs - one,
  888.                      mPos.x + xOfs + i + width,
  889.                      mPos.y + yOfs + width  + one);
  890.     
  891.         dc.DrawLine( mPos.x + xOfs + i + width ,
  892.                      mPos.y + yOfs - one - one,
  893.                      mPos.x + xOfs + i - one,
  894.                      mPos.y + yOfs + width );
  895.     }
  896.     
  897. #else
  898.  
  899.     cbMiniButton::Draw( dc );
  900.  
  901.     dc.SetPen( *wxBLACK_PEN );
  902.  
  903.     int width = BTN_BOX_WIDTH - 7;
  904.  
  905.     int xOfs = (mPressed) ? 4 : 3;
  906.     int yOfs = (mPressed) ? 4 : 3;
  907.  
  908.     for( int i = 0; i != BTN_X_WIEGHT; ++i )
  909.     {
  910.         dc.DrawLine( mPos.x + xOfs + i,
  911.                      mPos.y + yOfs,
  912.                      mPos.x + xOfs + i + width,
  913.                      mPos.y + yOfs + width );
  914.  
  915.         dc.DrawLine( mPos.x + xOfs + i + width - 1,
  916.                      mPos.y + yOfs,
  917.                      mPos.x + xOfs + i - 1,
  918.                      mPos.y + yOfs + width );
  919.     }
  920.  
  921. #endif
  922.  
  923. }
  924.  
  925. /***** Implementation fro class cbCollapseBox *****/
  926.  
  927. inline static void my_swap( int& a, int& b )
  928. {
  929.     long tmp = a;
  930.     a = b;
  931.     b = tmp;
  932. }
  933.  
  934. void cbCollapseBox::Draw( wxDC& dc )
  935. {
  936.     cbMiniButton::Draw( dc );
  937.  
  938.     dc.SetPen( *wxTRANSPARENT_PEN );
  939.  
  940.     wxPoint arr[3];
  941.  
  942.     int yOfs  = (mPressed) ? 3 : 2;
  943.     int xOfs  = (mPressed) ? 5 : 4;
  944.     int width = BTN_BOX_WIDTH - 8;
  945.  
  946.     // rotating/shifting triangle inside collapse box
  947.  
  948.     arr[0].x = xOfs;
  949.     arr[0].y = yOfs-1;
  950.     arr[2].x = xOfs;
  951.     arr[2].y = BTN_BOX_HEIGHT - yOfs - 1;
  952.     arr[1].x = xOfs + width;
  953.     arr[1].y = (arr[2].y + arr[0].y)/2;
  954.  
  955.     if ( !mIsAtLeft )
  956.     {
  957.         arr[0].x = BTN_BOX_WIDTH - arr[0].x;
  958.         arr[1].x = BTN_BOX_WIDTH - arr[1].x;
  959.         arr[2].x = BTN_BOX_WIDTH - arr[2].x;
  960.     }
  961.  
  962.     if ( !mpPane->IsHorizontal() )
  963.     {
  964.         my_swap( arr[0].y, arr[0].x );
  965.         my_swap( arr[1].y, arr[1].x );
  966.         my_swap( arr[2].y, arr[2].x );
  967.  
  968.         arr[0].x += 1;
  969.         arr[1].x += 1;
  970.         arr[2].x += 1;
  971.  
  972.         //arr[1].y -= 1;
  973.     }
  974.  
  975.     arr[0].x += mPos.x;
  976.     arr[0].y += mPos.y;
  977.     arr[1].x += mPos.x;
  978.     arr[1].y += mPos.y;
  979.     arr[2].x += mPos.x;
  980.     arr[2].y += mPos.y;
  981.  
  982.     if ( !mEnabled ) dc.SetBrush( *wxGREY_BRUSH );
  983.                 else dc.SetBrush( *wxBLACK_BRUSH );
  984.  
  985.     dc.DrawPolygon( 3, arr );
  986.     dc.SetBrush( wxNullBrush );
  987. }
  988.  
  989. /***** Implementation for class cbDockBoxBox *****/
  990.  
  991. void cbDockBox::Draw( wxDC& dc )
  992. {
  993.     cbMiniButton::Draw( dc );
  994.  
  995.     int width = BTN_BOX_WIDTH - 7;
  996.  
  997.     int xOfs = (mPressed) ? 4 : 3;
  998.     int yOfs = (mPressed) ? 4 : 3;
  999.  
  1000.     dc.SetPen( *wxBLACK_PEN );
  1001.     dc.SetBrush( *wxBLACK_BRUSH );
  1002.  
  1003.     dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width, width );
  1004.  
  1005.     xOfs += 1;
  1006.     yOfs += 1;
  1007.  
  1008.     dc.SetBrush( *wxWHITE_BRUSH );
  1009.  
  1010.     dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width-2, width-2 );
  1011. }
  1012.  
  1013. /***** Implementation for class wxToolWindow *****/
  1014.  
  1015. IMPLEMENT_DYNAMIC_CLASS( cbFloatedBarWindow, wxToolWindow )
  1016.  
  1017. BEGIN_EVENT_TABLE( cbFloatedBarWindow, wxToolWindow )
  1018.  
  1019.     EVT_LEFT_DCLICK( cbFloatedBarWindow::OnDblClick )
  1020.  
  1021. END_EVENT_TABLE()
  1022.  
  1023. cbFloatedBarWindow::cbFloatedBarWindow()
  1024.  
  1025.     : mpBar( NULL )
  1026. {
  1027.     AddMiniButton( new cbCloseBox() );
  1028.     AddMiniButton( new cbDockBox()  );
  1029. }
  1030.  
  1031. void cbFloatedBarWindow::SetBar( cbBarInfo* pBar )
  1032. {
  1033.     mpBar = pBar;
  1034. }
  1035.  
  1036. cbBarInfo* cbFloatedBarWindow::GetBar()
  1037. {
  1038.     return mpBar;
  1039. }
  1040.  
  1041. void cbFloatedBarWindow::SetLayout( wxFrameLayout* pLayout )
  1042. {
  1043.     mpLayout = pLayout;
  1044. }
  1045.  
  1046. void cbFloatedBarWindow::PositionFloatedWnd( int scrX,  int scrY,
  1047.                                              int width, int height )
  1048. {
  1049.     wxSize minDim = GetMinimalWndDim();
  1050.  
  1051.     SetSize( scrX - mWndHorizGap - mClntHorizGap, 
  1052.              scrY - mClntVertGap - mTitleHeight - mWndVertGap, 
  1053.              width + minDim.x, height + minDim.y, 0 );
  1054. }
  1055.  
  1056. wxSize cbFloatedBarWindow::GetPreferredSize( const wxSize& given )
  1057. {
  1058.     if ( mpBar->mDimInfo.GetDimHandler() )
  1059.     {
  1060.  
  1061.         cbBarDimHandlerBase* pHandler = mpBar->mDimInfo.GetDimHandler();
  1062.  
  1063.         wxSize prefDim;
  1064.  
  1065.         // int vtad = *((int*)pHandler);
  1066.  
  1067.         pHandler->OnResizeBar( mpBar, given, prefDim );
  1068.  
  1069.         return prefDim;
  1070.     }
  1071.     else
  1072.     {
  1073.         if ( mpBar->IsFixed() ) 
  1074.  
  1075.             return mpBar->mDimInfo.mSizes[ wxCBAR_FLOATING ];
  1076.         else
  1077.             return given; // not-fixed bars are resized exactly the way user wants
  1078.     }
  1079. }
  1080.  
  1081. void cbFloatedBarWindow::OnMiniButtonClicked( int btnIdx )
  1082. {
  1083.     // #1 - close mini-button
  1084.     // #0 - dock mini-button
  1085.  
  1086.     if ( btnIdx == 0 )
  1087.     {
  1088.         mpBar->mAlignment = -1; // sepcial "marking" for hidden bars out of floated state
  1089.         mpLayout->SetBarState( mpBar, wxCBAR_HIDDEN, TRUE );
  1090.     }
  1091.     else
  1092.         mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, TRUE );
  1093. }
  1094.  
  1095. bool cbFloatedBarWindow::HandleTitleClick( wxMouseEvent& event )
  1096. {
  1097.     ReleaseMouse();
  1098.     mMouseCaptured = FALSE;
  1099.  
  1100.     wxPoint scrPos;
  1101.     GetScrMousePos( event, scrPos );
  1102.  
  1103.     int msX = scrPos.x,
  1104.         msY = scrPos.y;
  1105.  
  1106.     mpLayout->GetParentFrame().ScreenToClient( &msX, &msY );
  1107.  
  1108.      int x,y;
  1109.     GetPosition(&x,&y);
  1110.     int w,h;
  1111.     GetSize( &w, &h );
  1112.  
  1113.     wxSize minDim = GetMinimalWndDim();
  1114.  
  1115.     w -= minDim.x;
  1116.     h -= minDim.y;
  1117.  
  1118.     x += mWndHorizGap + mClntHorizGap;
  1119.     y += mWndVertGap  + mTitleHeight + mClntVertGap;
  1120.  
  1121.     mpLayout->GetParentFrame().ScreenToClient( &x, &y );
  1122.  
  1123.     wxRect& bounds = mpBar->mDimInfo.mBounds[ wxCBAR_FLOATING ];
  1124.  
  1125.     bounds.x = x;
  1126.     bounds.y = y;
  1127.     bounds.width  = w;
  1128.     bounds.height = h;
  1129.  
  1130.     cbStartBarDraggingEvent dragEvt( mpBar, wxPoint(msX,msY), 
  1131.                                      mpLayout->GetPanesArray()[FL_ALIGN_TOP] );
  1132.             
  1133.     mpLayout->FirePluginEvent( dragEvt );
  1134.  
  1135.     return TRUE;
  1136. }
  1137.  
  1138. void cbFloatedBarWindow::OnDblClick( wxMouseEvent& event )
  1139. {
  1140.     mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, TRUE );
  1141.  
  1142.     //wxMessageBox("toolWnd - dblClick!");
  1143. }
  1144.  
  1145.