home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / contrib / src / fl / bardragpl.cpp < prev    next >
C/C++ Source or Header  |  2002-06-12  |  24KB  |  965 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        bardragpl.cpp
  3. // Purpose:     cbBarDragPlugin implementation
  4. // Author:      Aleksandras Gluchovas
  5. // Modified by:
  6. // Created:     23/09/98
  7. // RCS-ID:      $Id: bardragpl.cpp,v 1.5 2002/06/12 08:29:12 JS Exp $
  8. // Copyright:   (c) Aleksandras Gluchovas
  9. // Licence:       wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13.     #pragma implementation "bardragpl.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/bardragpl.h"
  28.  
  29. #define POS_UNDEFINED -32768
  30.  
  31. // helpers, FOR NOW:: static
  32.  
  33. static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
  34. {
  35.     if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
  36.          ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
  37.  
  38.         if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
  39.              ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
  40.              
  41.             return TRUE;
  42.  
  43.     return FALSE;
  44. }
  45.  
  46. static inline bool rect_contains_point( const wxRect& rect, int x, int y )
  47. {
  48.     return ( x >= rect.x &&
  49.              y >= rect.y &&
  50.              x <  rect.x + rect.width  &&
  51.              y <  rect.y + rect.height );
  52. }
  53.  
  54. /***** Implementation for class cbBarDragPlugin *****/
  55.  
  56. IMPLEMENT_DYNAMIC_CLASS( cbBarDragPlugin, cbPluginBase )
  57.  
  58. BEGIN_EVENT_TABLE( cbBarDragPlugin, cbPluginBase )
  59.  
  60.     //EVT_PL_LEFT_DOWN          ( cbBarDragPlugin::OnLButtonDown      )
  61.     EVT_PL_LEFT_UP              ( cbBarDragPlugin::OnLButtonUp        )
  62.     EVT_PL_MOTION              ( cbBarDragPlugin::OnMouseMove        )
  63.     EVT_PL_DRAW_HINT_RECT     ( cbBarDragPlugin::OnDrawHintRect     )
  64.     EVT_PL_START_BAR_DRAGGING ( cbBarDragPlugin::OnStartBarDragging )
  65.     EVT_PL_LEFT_DCLICK          ( cbBarDragPlugin::OnLDblClick        )
  66.  
  67. END_EVENT_TABLE()
  68.  
  69. cbBarDragPlugin::cbBarDragPlugin(void)
  70.  
  71.     : mBarDragStarted    ( FALSE ),
  72.       mCanStick          ( TRUE ),
  73.       mpScrDc            ( NULL ),
  74.       mpCurCursor        ( NULL ),
  75.       mpDraggedBar       ( NULL ),
  76.       mInClientHintBorder( 4 )
  77. {}
  78.  
  79. cbBarDragPlugin::cbBarDragPlugin( wxFrameLayout* pPanel, int paneMask )
  80.  
  81.     : cbPluginBase( pPanel, paneMask ),
  82.         
  83.       mBarDragStarted    ( FALSE ),
  84.       mCanStick          ( TRUE ),
  85.       mpScrDc            ( NULL ),
  86.       mpCurCursor        ( NULL ),
  87.       mpDraggedBar       ( NULL ),
  88.       mInClientHintBorder( 4 )
  89. {}
  90.  
  91. cbBarDragPlugin::~cbBarDragPlugin()
  92. {
  93.     // nothing
  94. }
  95.  
  96. // helper methods (protected)
  97.  
  98. // clips (top/bottom) or (right/left) edges against the frame's bounding rect.
  99.  
  100. void do_clip_edges( int len, int& rectPos, int& rectLen )
  101. {
  102.     if ( rectPos < 0 )
  103.     {
  104.         rectLen += rectPos;
  105.         rectPos = 0;
  106.         if ( rectLen < 0 )
  107.             rectLen = 1;
  108.     }
  109.     else
  110.     if ( rectPos > len-1 )
  111.     {
  112.         rectPos = len-1;
  113.         rectLen = 1;
  114.     }
  115.     else
  116.     if ( rectPos + rectLen - 1 > len )
  117.     
  118.         rectLen -= (rectPos + rectLen) - len + 1;
  119. }
  120.  
  121. void cbBarDragPlugin::ClipRectInFrame( wxRect& rect )
  122. {
  123.     int w, h;
  124.     mpLayout->GetParentFrame().GetClientSize( &w, &h );
  125.  
  126.     do_clip_edges( w, rect.x, rect.width  );
  127.     do_clip_edges( h, rect.y, rect.height );
  128. }
  129.  
  130. void cbBarDragPlugin::ClipPosInFrame( wxPoint& pos )
  131. {
  132.     int w, h;
  133.     mpLayout->GetParentFrame().GetClientSize( &w, &h );
  134.  
  135.     if ( pos.x < 0 )
  136.         pos.x = 0;
  137.     if ( pos.y < 0 )
  138.         pos.y = 0;
  139.     if ( pos.x > w )
  140.         pos.x = w-1;
  141.     if ( pos.y > h )
  142.         pos.y = h-1;
  143. }
  144.  
  145. void cbBarDragPlugin::AdjustHintRect( wxPoint& mousePos )
  146. {
  147.     mHintRect.x = mousePos.x - mMouseInRectX;
  148.     mHintRect.y = mousePos.y - mMouseInRectY;
  149. }
  150.  
  151. cbDockPane* cbBarDragPlugin::HitTestPanes( wxRect& rect )
  152. {
  153.     //wxRect clipped = rect;
  154.  
  155.     //ClipRectInFrame( clipped );
  156.  
  157.     cbDockPane** pPanes = mpLayout->GetPanesArray();
  158.  
  159.     for( int i = 0; i != MAX_PANES; ++i )
  160.     
  161.         if ( rect_hits_rect( pPanes[i]->mBoundsInParent, rect ) )
  162.  
  163.             return pPanes[i];
  164.  
  165.     return NULL;
  166. }
  167.  
  168. cbDockPane* cbBarDragPlugin::HitTestPanes( wxPoint& pos )
  169. {
  170.     wxPoint clipped = pos;
  171.  
  172.     //ClipPosInFrame( pos );
  173.  
  174.     cbDockPane** pPanes = mpLayout->GetPanesArray();
  175.  
  176.     for( int i = 0; i != MAX_PANES; ++i )
  177.     
  178.         if ( rect_contains_point( pPanes[i]->mBoundsInParent, clipped.x, clipped.y ) )
  179.  
  180.             return pPanes[i];
  181.  
  182.     return NULL;
  183. }
  184.  
  185. bool cbBarDragPlugin::HitsPane( cbDockPane* pPane, wxRect& rect )
  186. {
  187.     return rect_hits_rect( pPane->mBoundsInParent, rect );
  188. }
  189.  
  190. int cbBarDragPlugin::GetDistanceToPane( cbDockPane* pPane, wxPoint& mousePos )
  191. {
  192.     wxRect& bounds = pPane->mBoundsInParent;
  193.  
  194.     switch( pPane->mAlignment )
  195.     {
  196.         case FL_ALIGN_TOP    : return mousePos.y - ( bounds.y + bounds.height );
  197.  
  198.         case FL_ALIGN_BOTTOM : return bounds.y - mousePos.y;
  199.  
  200.         case FL_ALIGN_LEFT   : return mousePos.x - ( bounds.x + bounds.width  );
  201.  
  202.         case FL_ALIGN_RIGHT  : return bounds.x - mousePos.x;
  203.  
  204.         default : return 0; // never reached
  205.     }
  206.  
  207. //    return 0;
  208. }
  209.  
  210. bool cbBarDragPlugin::IsInOtherPane( wxPoint& mousePos )
  211. {
  212.     cbDockPane* pPane = HitTestPanes( mousePos );
  213.  
  214.     if ( pPane && pPane != mpCurPane ) return TRUE;
  215.                                   else return FALSE;
  216. }
  217.  
  218. bool cbBarDragPlugin::IsInClientArea( wxPoint& mousePos )
  219. {
  220.     return  ( HitTestPanes( mousePos ) == NULL );
  221. }
  222.  
  223. bool cbBarDragPlugin::IsInClientArea( wxRect& rect )
  224. {
  225.     return ( HitTestPanes( rect ) == NULL );
  226. }
  227.  
  228. void cbBarDragPlugin::CalcOnScreenDims( wxRect& rect )
  229. {
  230.     if ( !mpCurPane || mpDraggedBar->IsFixed() ) return;
  231.  
  232.     wxRect inPane = rect;
  233.  
  234.     mpCurPane->FrameToPane( &inPane );
  235.  
  236.     int rowNo = mpCurPane->GetRowAt( inPane.y, inPane.y + inPane.height );
  237.  
  238.     bool isMaximized = ( rowNo >= (int)mpCurPane->GetRowList().Count() || rowNo < 0 );
  239.  
  240.     if ( isMaximized )
  241.     {
  242.         inPane.x = 0;
  243.         inPane.width = mpCurPane->mPaneWidth;
  244.  
  245.         mpCurPane->PaneToFrame( &inPane );
  246.  
  247.         rect = inPane;
  248.     }
  249. }
  250.  
  251. // helpers 
  252.  
  253. static inline void check_upper_overrun( int& pos, int width, int mousePos )
  254. {
  255.     if ( mousePos >= pos + width )
  256.  
  257.         pos = mousePos - width/2;
  258. }
  259.  
  260. static inline void check_lower_overrun( int& pos, int width, int mousePos )
  261. {
  262.     if ( mousePos <= pos )
  263.  
  264.         pos = mousePos - width/2;
  265. }
  266.  
  267. void cbBarDragPlugin::StickToPane( cbDockPane* pPane, wxPoint& mousePos )
  268. {
  269.     int wInPane = GetBarWidthInPane ( pPane );
  270.     int hInPane = GetBarHeightInPane( pPane );
  271.  
  272.     // adjsut hint-rect horizontally (in pane's orientation)
  273.     
  274.     if ( pPane->IsHorizontal() )
  275.     {
  276.         mHintRect.width  = wInPane;
  277.         mHintRect.height = hInPane;
  278.     }
  279.     else
  280.     {
  281.         mHintRect.height = wInPane;
  282.         mHintRect.width  = hInPane;
  283.     }
  284.  
  285.     // adjsut hint-rect vertically (in pane's orientation)
  286.  
  287.     wxRect& bounds = pPane->mBoundsInParent;
  288.  
  289.     // TRUE, if hint enters the pane through it's lower edge
  290.  
  291.     bool fromLowerEdge = ( pPane->IsHorizontal() ) 
  292.                          ? mousePos.y > bounds.y
  293.                          : mousePos.x > bounds.x;
  294.  
  295.     // NOTE:: about all the below min/max things: they are meant to ensure
  296.     //        that the mouse pointer doesn't overrun (leave) the hint-rectangle
  297.     //        when its dimensions are recalculated upon sticking it to the pane
  298.  
  299.     if ( pPane->IsHorizontal() && fromLowerEdge )
  300.     {
  301.         int paneBottomEdgeY = bounds.y + bounds.height;
  302.  
  303.         mHintRect.y = wxMin( paneBottomEdgeY, mousePos.y );
  304.  
  305.         check_lower_overrun( mHintRect.y, hInPane, mousePos.y );
  306.  
  307.     }
  308.     else
  309.     if ( pPane->IsHorizontal() && !fromLowerEdge )
  310.     {
  311.         int paneTopEdgeY = bounds.y;
  312.  
  313.         mHintRect.y = wxMax( paneTopEdgeY - hInPane, mousePos.y - hInPane );
  314.  
  315.         check_upper_overrun( mHintRect.y, hInPane, mousePos.y );
  316.     }
  317.     else
  318.     if ( !pPane->IsHorizontal() && fromLowerEdge )
  319.     {
  320.         int paneRightEdgeX = bounds.x + bounds.width;
  321.  
  322.         mHintRect.x = wxMin( paneRightEdgeX, mousePos.x );
  323.  
  324.         check_lower_overrun( mHintRect.x, hInPane, mousePos.x );
  325.     }
  326.     else
  327.     if ( !pPane->IsHorizontal() && !fromLowerEdge )
  328.     {
  329.         int paneLeftEdgeX = bounds.x;
  330.  
  331.         mHintRect.x = wxMax( paneLeftEdgeX - hInPane, mousePos.x - hInPane );
  332.  
  333.         check_upper_overrun( mHintRect.x, hInPane, mousePos.x );
  334.     }
  335.  
  336.     mMouseInRectX = mousePos.x - mHintRect.x;
  337.     mMouseInRectY = mousePos.y - mHintRect.y;
  338.  
  339.     mpCurPane = pPane; // memorize pane to which the hint is currently sticked
  340. }
  341.  
  342. void cbBarDragPlugin::UnstickFromPane( cbDockPane* pPane, wxPoint& mousePos )
  343. {
  344.     // unsticking causes rectangle to get the shape in which
  345.     // dragged control-bar would be when floated
  346.  
  347.     int newWidth  = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].x;
  348.     int newHeight = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].y;
  349.  
  350.     wxRect& flBounds = mpDraggedBar->mDimInfo.mBounds[wxCBAR_FLOATING];
  351.  
  352.     if ( flBounds.width != -1 )
  353.     {
  354.         newWidth  = flBounds.width;
  355.         newHeight = flBounds.height;
  356.     }
  357.  
  358.     mHintRect.width  = newWidth;
  359.     mHintRect.height = newHeight;
  360.  
  361.     wxRect& bounds = pPane->mBoundsInParent;
  362.  
  363.     // TRUE, if hint leaves the pane through it's lower edge
  364.  
  365.     bool fromLowerEdge = ( pPane->IsHorizontal() ) 
  366.                          ? mousePos.y > bounds.y
  367.                          : mousePos.x > bounds.x;
  368.  
  369.     // NOTE:: ...all the below min/max things - see comments about it in StickToPane(..)
  370.  
  371.     if ( pPane->IsHorizontal() && fromLowerEdge )
  372.     {    
  373. //        bool fromLowerEdge = mousePos.y > bounds.y;
  374.  
  375.         mHintRect.y = wxMax( bounds.y + bounds.height + 1, mousePos.y - newHeight );
  376.  
  377.         check_upper_overrun( mHintRect.y, newHeight, mousePos.y );
  378.  
  379.         // this is how MFC's hint behaves:
  380.  
  381.         if ( mMouseInRectX > newWidth )
  382.         
  383.             mHintRect.x = mousePos.x - ( newWidth / 2 );
  384.     }
  385.     else
  386.     if ( pPane->IsHorizontal() && !fromLowerEdge )
  387.     {
  388.         mHintRect.y = wxMin( bounds.y - newHeight - 1, mousePos.y );
  389.  
  390.         // -/-
  391.  
  392.         if ( mMouseInRectX > newWidth )
  393.         
  394.             mHintRect.x = mousePos.x - ( newWidth / 2 );
  395.  
  396.         check_lower_overrun( mHintRect.y, newHeight, mousePos.y );
  397.     }
  398.     else
  399.     if ( !pPane->IsHorizontal() && fromLowerEdge )
  400.     {
  401.         mHintRect.x = wxMax( bounds.x + bounds.width, mousePos.x - newWidth );
  402.  
  403.         // -/-
  404.         
  405.         if ( mMouseInRectY > newHeight )
  406.  
  407.             mHintRect.y = mousePos.y - ( newHeight / 2 );
  408.  
  409.         check_upper_overrun( mHintRect.x, newWidth, mousePos.x );
  410.     }
  411.     else
  412.     if ( !pPane->IsHorizontal() && !fromLowerEdge )
  413.     {
  414.         mHintRect.x = wxMin( bounds.x - newWidth - 1, mousePos.x );
  415.  
  416.         // -/-
  417.         
  418.         if ( mMouseInRectY > newHeight )
  419.  
  420.             mHintRect.y = mousePos.y - ( newHeight / 2 );
  421.  
  422.         check_lower_overrun( mHintRect.x, newWidth, mousePos.x );
  423.     }
  424.  
  425.     mMouseInRectX = mousePos.x - mHintRect.x;
  426.     mMouseInRectY = mousePos.y - mHintRect.y;
  427.  
  428.     mpCurPane = NULL;
  429. }                
  430.  
  431. int cbBarDragPlugin::GetBarWidthInPane( cbDockPane* pPane )
  432. {
  433.     if ( pPane == mpSrcPane )
  434.  
  435.         return mBarWidthInSrcPane;
  436.  
  437.     // this is how MFC's bars behave:
  438.  
  439.     if ( pPane->IsHorizontal() )
  440.     
  441.         return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].x;
  442.     else
  443.         return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY  ].x;
  444. }
  445.  
  446. int cbBarDragPlugin::GetBarHeightInPane( cbDockPane* pPane )
  447. {
  448.     if ( pPane->IsHorizontal() )
  449.     
  450.         return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].y;
  451.     else
  452.         return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY  ].y;
  453. }
  454.  
  455. void cbBarDragPlugin::ShowHint( bool prevWasInClient )
  456. {
  457.     bool wasDocked = FALSE;
  458.  
  459.  
  460.     if ( mpSrcPane->mProps.mRealTimeUpdatesOn == FALSE )
  461.     {
  462.         // do heavy calculations first
  463.  
  464.         wxRect actualRect = mHintRect; // will be adjusted depending on drag-settings
  465.  
  466.         if ( mpSrcPane->mProps.mExactDockPredictionOn && mpCurPane )
  467.         {
  468.             bool success = mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, FALSE );
  469.  
  470.             wxASSERT( success ); // DBG::
  471.  
  472.             actualRect = mpDraggedBar->mBounds;
  473.  
  474.             mpCurPane->PaneToFrame( &actualRect );
  475.         }
  476.         else
  477.             CalcOnScreenDims( actualRect );
  478.  
  479.         // release previous hint
  480.  
  481.         if ( mPrevHintRect.x != POS_UNDEFINED )
  482.         {
  483.             // erase previous rectangle
  484.  
  485.             cbDrawHintRectEvent evt( mPrevHintRect, prevWasInClient, TRUE, FALSE );
  486.  
  487.             mpLayout->FirePluginEvent( evt );
  488.         }
  489.  
  490.         // draw new hint
  491.  
  492.         cbDrawHintRectEvent evt( actualRect, mpCurPane == NULL, FALSE, FALSE );
  493.  
  494.         mpLayout->FirePluginEvent( evt );
  495.  
  496.         mPrevHintRect = actualRect;
  497.     }
  498.     else 
  499.     {
  500.         // otherwise, if real-time updates option is ON
  501.  
  502.         if ( mpDraggedBar->mState != wxCBAR_FLOATING && !mpCurPane )
  503.         {
  504.             mpLayout->SetBarState( mpDraggedBar, wxCBAR_FLOATING, TRUE );
  505.         }
  506.          else
  507.         if ( mpDraggedBar->mState == wxCBAR_FLOATING && mpCurPane )
  508.         {
  509.             mpLayout->SetBarState( mpDraggedBar, wxCBAR_DOCKED_HORIZONTALLY, FALSE );
  510.  
  511.             wasDocked = TRUE;
  512.         }
  513.  
  514.         if ( mpCurPane )
  515.         {
  516.             mpLayout->GetUpdatesManager().OnStartChanges();
  517.  
  518.             if ( wasDocked )
  519.  
  520.                 mpDraggedBar->mUMgrData.SetDirty( TRUE );
  521.  
  522.             bool success = mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, FALSE );
  523.  
  524.             wxASSERT( success ); // DBG ::
  525.  
  526.             mpLayout->GetUpdatesManager().OnFinishChanges();
  527.             mpLayout->GetUpdatesManager().UpdateNow();
  528.         }
  529.         else
  530.         {
  531.             if ( mpLayout->mFloatingOn )
  532.             {
  533.                 // move the top-most floated bar around as user drags the hint
  534.  
  535.                 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect;
  536.  
  537.                 mpLayout->ApplyBarProperties( mpDraggedBar );
  538.             }
  539.         }
  540.     }
  541. }
  542.  
  543. /*** event handlers ***/
  544.  
  545. void cbBarDragPlugin::OnMouseMove( cbMotionEvent& event )
  546. {
  547.     // calculate postion in frame's coordiantes
  548.  
  549.     if ( !mBarDragStarted )
  550.     {
  551.         event.Skip(); // pass event to the next plugin
  552.         return;
  553.     }
  554.  
  555.     wxPoint mousePos = event.mPos;
  556.  
  557.     event.mpPane->PaneToFrame( &mousePos.x, &mousePos.y );
  558.  
  559.     bool   prevIsInClient = ( mpCurPane == 0 );
  560.  
  561.     AdjustHintRect( mousePos );
  562.  
  563.     // if the hint-rect is not "tempted" to any pane yet
  564.  
  565.     if ( mpCurPane == NULL )
  566.     {
  567.         cbDockPane* pPane = HitTestPanes( mHintRect );
  568.  
  569.         if ( !pPane ) 
  570.             
  571.             // enable sticking again, if we've left the pane completely
  572.             mCanStick = TRUE;
  573.  
  574.         if ( mCanStick && pPane && 
  575.              GetDistanceToPane( pPane, mousePos ) < GetBarHeightInPane( pPane ) )
  576.         
  577.             StickToPane( pPane, mousePos );
  578.         else
  579.             if ( pPane && HitTestPanes( mousePos ) == pPane && 0 ) // FOR NOW:: disabled
  580.  
  581.                 StickToPane( pPane, mousePos );
  582.     }
  583.     else
  584.     {
  585.         // otherwise, when rect is now sticked to some of the panes
  586.         // check if it should still remain in this pane
  587.  
  588.         mCanStick = TRUE;
  589.  
  590.         bool mouseInOther = IsInOtherPane( mousePos );
  591.  
  592.         if ( mouseInOther )
  593.         {
  594.                 cbDockPane* pPane = HitTestPanes( mousePos );
  595.  
  596.                 StickToPane( pPane, mousePos );
  597.         }
  598.         else
  599.         {
  600.             if ( IsInClientArea( mousePos ) )
  601.             {
  602.                 cbDockPane* pPane = HitTestPanes( mHintRect );
  603.  
  604.                 if ( pPane && 
  605.                      pPane != mpCurPane &&
  606.                      GetDistanceToPane( pPane, mousePos ) < GetBarHeightInPane( pPane ) )
  607.  
  608.                         StickToPane( pPane, mousePos );
  609.                 else
  610.                 if ( !pPane )
  611.                 {
  612.                     UnstickFromPane( mpCurPane, mousePos );
  613.  
  614.                     // FOR NOW:: disabled, would cause some mess
  615.                     //mCanStick = FALSE; // prevents from sticking to this
  616.                                          // pane again, flag is reset when hint-rect
  617.                                          // leaves the pane completely
  618.                 }
  619.                 else
  620.                 if ( GetDistanceToPane( pPane, mousePos ) > GetBarHeightInPane( pPane ) )
  621.                 {
  622.                     if ( !HitsPane( mpCurPane, mHintRect ) )
  623.                     {
  624.                         UnstickFromPane( mpCurPane, mousePos );
  625.  
  626.                         // FOR NOW:: disabled, would cause some mess
  627.                         //mCanStick = FALSE; // prevents from sticking to this
  628.                                              // pane again, flag is reset when hint-rect
  629.                                              // leaves the pane completely
  630.                     }
  631.                 }
  632.  
  633.             }
  634.             else
  635.             {
  636.             }
  637.         }
  638.     }
  639.  
  640.     ShowHint( prevIsInClient );
  641.  
  642.     wxCursor* pPrevCurs = mpCurCursor;
  643.  
  644.     if ( mpCurPane )
  645.     {
  646.         mpCurCursor = mpLayout->mpNormalCursor;
  647.     }
  648.     else
  649.     {
  650.         // if floating is off, and we are in the client
  651.         // area, the cursor will be invalid, otherwise
  652.         // it will be the normal cursor
  653.         
  654.         if (mpLayout->mFloatingOn)
  655.         {
  656.             mpCurCursor = mpLayout->mpNormalCursor;
  657.         }
  658.         else
  659.         {
  660.             mpCurCursor = mpLayout->mpNECursor;
  661.     }
  662.  
  663.     }
  664.     if ( pPrevCurs != mpCurCursor )
  665.         mpLayout->GetParentFrame().SetCursor( *mpCurCursor );
  666. }
  667.  
  668. void cbBarDragPlugin::OnLButtonDown( cbLeftDownEvent& event )
  669. {
  670.     if ( mBarDragStarted  )
  671.     {
  672.         wxMessageBox("DblClick!");
  673.     }
  674.  
  675.     event.Skip();
  676. }
  677.  
  678. void cbBarDragPlugin::OnLButtonUp( cbLeftUpEvent& event )
  679. {
  680.     if ( mBarDragStarted  )
  681.     {
  682.         if ( mpSrcPane->mProps.mRealTimeUpdatesOn == FALSE )
  683.         {
  684.             // erase current rectangle, and finsih on-screen drawing session
  685.  
  686.             cbDrawHintRectEvent evt( mPrevHintRect, mpCurPane == NULL, TRUE, TRUE );
  687.  
  688.             mpLayout->FirePluginEvent( evt );
  689.  
  690.             if ( mpCurPane != NULL )
  691.             {
  692.                 if ( mpSrcPane->mProps.mExactDockPredictionOn )
  693.                 {
  694.                     mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, FALSE );
  695.  
  696.                     mpLayout->GetUpdatesManager().OnFinishChanges();
  697.                     mpLayout->GetUpdatesManager().UpdateNow();
  698.                 }
  699.                 else
  700.                 {
  701.                     if (mpDraggedBar->mState == wxCBAR_FLOATING)
  702.                     {
  703.                         mpLayout->SetBarState( mpDraggedBar, wxCBAR_DOCKED_HORIZONTALLY, TRUE);
  704.                     }
  705.  
  706.                     mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane );
  707.             }
  708.         }
  709.              else
  710.             {
  711.                 if (mpDraggedBar->mState != wxCBAR_FLOATING)
  712.                 {
  713.                     mpLayout->SetBarState(mpDraggedBar, wxCBAR_FLOATING, true);
  714.                 }
  715.  
  716.                 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect;
  717.                 mpLayout->ApplyBarProperties( mpDraggedBar );
  718.             }
  719.         }
  720.     
  721.         mHintRect.width = -1;
  722.  
  723.         // In Windows, at least, the frame needs to have a null cursor
  724.         // else child windows (such as text windows) inherit the cursor
  725. #if 1
  726.         mpLayout->GetParentFrame().SetCursor( wxNullCursor );
  727. #else
  728.         mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
  729. #endif
  730.  
  731.         mpLayout->ReleaseEventsFromPane( event.mpPane );
  732.         mpLayout->ReleaseEventsFromPlugin( this );
  733.  
  734.         mBarDragStarted = FALSE;
  735.  
  736.         if ( mBarWasFloating && mpDraggedBar->mState != wxCBAR_FLOATING )
  737.         {
  738.             // save bar's floating position before it was docked 
  739.  
  740.             mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mFloatedBarBounds;
  741.         }
  742.     }
  743.     else
  744.         event.Skip(); // pass event to the next plugin
  745. }
  746.  
  747. void cbBarDragPlugin::OnLDblClick( cbLeftDClickEvent& event )
  748. {
  749.     int avoidCompilerWarning = 1;
  750.     if ( avoidCompilerWarning )
  751.     {
  752.         cbBarInfo* pHittedBar;
  753.         cbRowInfo* pRow;
  754.  
  755.         if ( event.mpPane->HitTestPaneItems( event.mPos,       // in pane's coordiantes
  756.                                              &pRow,
  757.                                              &pHittedBar ) == CB_BAR_CONTENT_HITTED
  758.            )
  759.             {
  760.                 mpLayout->SetBarState( pHittedBar, wxCBAR_FLOATING, TRUE );
  761.  
  762.                 mpLayout->RepositionFloatedBar( pHittedBar );
  763.  
  764.                 return; // event is "eaten" by this plugin
  765.             }
  766.  
  767.         mBarDragStarted = FALSE;
  768.  
  769.         event.Skip();
  770.     }
  771.  
  772.     //wxMessageBox("Hi, dblclick arrived!");
  773. }
  774.  
  775. void cbBarDragPlugin::OnStartBarDragging( cbStartBarDraggingEvent& event )
  776. {
  777.     mpDraggedBar = event.mpBar;
  778.     mpSrcPane    = event.mpPane; 
  779.  
  780.     mpLayout->CaptureEventsForPane( event.mpPane );
  781.     mpLayout->CaptureEventsForPlugin( this );
  782.  
  783.     mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
  784.  
  785.     mBarDragStarted = TRUE;
  786.  
  787.     wxRect inParent = mpDraggedBar->mBounds;
  788.  
  789.     mBarWasFloating = mpDraggedBar->mState == wxCBAR_FLOATING;
  790.         
  791.     if ( mBarWasFloating )
  792.     {    
  793.         inParent = mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ];
  794.         mFloatedBarBounds = inParent;
  795.     }
  796.     else
  797.         event.mpPane->PaneToFrame( &inParent );
  798.  
  799.     mHintRect.x = POS_UNDEFINED;
  800.  
  801.     mHintRect.width  = inParent.width;
  802.     mHintRect.height = inParent.height;
  803.  
  804.     mMouseInRectX = event.mPos.x - inParent.x;
  805.     mMouseInRectY = event.mPos.y - inParent.y;
  806.  
  807.     mpSrcPane = event.mpPane;
  808.  
  809.     if ( mpDraggedBar->mState == wxCBAR_FLOATING )
  810.  
  811.         mpCurPane = NULL;
  812.     else
  813.         mpCurPane = event.mpPane;
  814.  
  815.     mPrevHintRect.x = POS_UNDEFINED;
  816.  
  817.     mCanStick = FALSE; // we're not stuck into any pane now - 
  818.                        // there's nowhere to "stick-twice"
  819.  
  820.     mBarWidthInSrcPane = mpDraggedBar->mDimInfo.mSizes[ mpDraggedBar->mState ].x;
  821.  
  822.     if ( mpSrcPane->mProps.mRealTimeUpdatesOn == FALSE && 
  823.          mpSrcPane->mProps.mExactDockPredictionOn  )
  824.     
  825.         mpLayout->GetUpdatesManager().OnStartChanges(); // capture initial state of layout
  826.     
  827.     // simulate the first mouse movement
  828.  
  829.     int x = event.mPos.x, y = event.mPos.y;
  830.  
  831.     mpSrcPane->FrameToPane( &x, &y );
  832.  
  833.     cbMotionEvent motionEvt( wxPoint(x,y), event.mpPane );
  834.  
  835.  
  836.     this->OnMouseMove( motionEvt );
  837.  
  838.     return; // event is "eaten" by this plugin
  839. }
  840.  
  841. /*** on-screen hint-tracking related methods ***/
  842.  
  843. void cbBarDragPlugin::OnDrawHintRect( cbDrawHintRectEvent& event )
  844. {
  845.     if ( !mpScrDc ) StartTracking();
  846.  
  847.     DoDrawHintRect( event.mRect, event.mIsInClient );
  848.  
  849.     if ( event.mLastTime )
  850.  
  851.         FinishTracking();
  852. }
  853.  
  854. #define _IMG_A  0xAA    // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
  855. #define _IMG_B  0x00    // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
  856. #define _IMG_C  0x55    // Note: modified from _C to _IMG_C, for consistency reasons.
  857. #define _IMG_D  0x00    // Note: modified from _D to _IMG_D, for consistency reasons.
  858.  
  859. // FOR NOW:: static
  860.  
  861. static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D,
  862.                                                 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
  863.                                                 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
  864.                                                 _IMG_A,_IMG_B,_IMG_C,_IMG_D
  865.                                               };
  866.  
  867. void cbBarDragPlugin::StartTracking()
  868. {
  869.     mpScrDc = new wxScreenDC;
  870.  
  871.     wxScreenDC::StartDrawingOnTop(&mpLayout->GetParentFrame());
  872. }
  873.  
  874. void cbBarDragPlugin::DoDrawHintRect( wxRect& rect, bool isInClientRect)
  875. {
  876.     wxRect scrRect;
  877.  
  878.     RectToScr( rect, scrRect );
  879.  
  880.     int prevLF = mpScrDc->GetLogicalFunction();
  881.  
  882.     mpScrDc->SetLogicalFunction( wxINVERT );
  883.  
  884.     if ( isInClientRect )
  885.     {
  886.         // BUG BUG BUG (wx):: somehow stippled brush works only  
  887.         //                      when the bitmap created on stack, not
  888.         //                      as a member of the class
  889.  
  890.         wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
  891.  
  892.         wxBrush checkerBrush( checker );
  893.  
  894.         mpScrDc->SetPen( mpLayout->mNullPen );
  895.         mpScrDc->SetBrush( checkerBrush );
  896.  
  897.         int half = mInClientHintBorder / 2;
  898.  
  899.         mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y - half,
  900.                                 scrRect.width + 2*half, mInClientHintBorder );
  901.  
  902.         mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + scrRect.height - half,
  903.                                 scrRect.width + 2*half, mInClientHintBorder );
  904.  
  905.         mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + half - 1,
  906.                                 mInClientHintBorder, scrRect.height - 2*half + 2);
  907.  
  908.         mpScrDc->DrawRectangle( scrRect.x + scrRect.width - half,
  909.                                 scrRect.y + half - 1,
  910.                                 mInClientHintBorder, scrRect.height - 2*half + 2);
  911.  
  912.         mpScrDc->SetBrush( wxNullBrush );
  913.     }
  914.     else
  915.     {
  916.         mpScrDc->SetPen( mpLayout->mBlackPen );
  917.  
  918.         mpScrDc->DrawLine( scrRect.x, scrRect.y, 
  919.                            scrRect.x + scrRect.width, scrRect.y );
  920.  
  921.         mpScrDc->DrawLine( scrRect.x, scrRect.y + 1, 
  922.                            scrRect.x, scrRect.y + scrRect.height );
  923.  
  924.         mpScrDc->DrawLine( scrRect.x+1, scrRect.y + scrRect.height, 
  925.                            scrRect.x + scrRect.width, scrRect.y + scrRect.height );
  926.  
  927.         mpScrDc->DrawLine( scrRect.x + scrRect.width , scrRect.y, 
  928.                            scrRect.x + scrRect.width, scrRect.y + scrRect.height + 1);
  929.     }
  930.  
  931.     mpScrDc->SetLogicalFunction( prevLF );
  932. }
  933.  
  934. void cbBarDragPlugin::DrawHintRect ( wxRect& rect, bool isInClientRect)
  935. {
  936.     DoDrawHintRect( rect, isInClientRect );    
  937. }
  938.  
  939. void cbBarDragPlugin::EraseHintRect( wxRect& rect, bool isInClientRect)
  940. {
  941.     DoDrawHintRect( rect, isInClientRect );    
  942. }
  943.  
  944. void cbBarDragPlugin::FinishTracking()
  945. {
  946.     wxScreenDC::EndDrawingOnTop();
  947.  
  948.     delete mpScrDc;
  949.  
  950.     mpScrDc = NULL;
  951. }
  952.  
  953. void cbBarDragPlugin::RectToScr( wxRect& frameRect, wxRect& scrRect )
  954. {
  955.     scrRect = frameRect;
  956.  
  957.     int x = frameRect.x, y = frameRect.y;
  958.  
  959.     mpLayout->GetParentFrame().ClientToScreen( &x, &y );
  960.  
  961.     scrRect.x = x;
  962.     scrRect.y = y;
  963. }
  964.  
  965.