]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/fl/controlbar.cpp
Fixed/simplified Makefile
[wxWidgets.git] / contrib / src / fl / controlbar.cpp
CommitLineData
8e08b761
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: No names yet.
3// Purpose: Contrib. demo
4// Author: Aleksandras Gluchovas
5// Modified by:
6// Created: 06/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Aleksandras Gluchovas
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13 #pragma implementation "controlbar.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 <math.h>
28#include <stdlib.h>
29
30#include "wx/string.h"
31#include "wx/utils.h" // import wxMin,wxMax macros
32#include "wx/minifram.h"
33
34#include "wx/fl/controlbar.h"
35
36// import classes of default plugins
37
38#include "wx/fl/panedrawpl.h"
39#include "wx/fl/rowlayoutpl.h"
40#include "wx/fl/antiflickpl.h"
41#include "wx/fl/bardragpl.h"
42#include "wx/fl/cbcustom.h"
43
44#include "wx/fl/gcupdatesmgr.h" // import default updates manager class ("garbage-collecting" one)
45#include "wx/fl/updatesmgr.h"
46
47#include "wx/fl/toolwnd.h"
48
49// These are the event IDs being initialized to a value to
50// meet the new event paradigm as of wx2.3.0. Probably we
51// should find a way to make these be non-global, but this
52// works for right now.
53#if wxCHECK_VERSION(2,3,0)
54 wxEventType cbEVT_PL_LEFT_DOWN = wxNewEventType();
55 wxEventType cbEVT_PL_LEFT_UP = wxNewEventType();
56 wxEventType cbEVT_PL_RIGHT_DOWN = wxNewEventType();
57 wxEventType cbEVT_PL_RIGHT_UP = wxNewEventType();
58 wxEventType cbEVT_PL_MOTION = wxNewEventType();
59
60 wxEventType cbEVT_PL_LEFT_DCLICK = wxNewEventType();
61
62 wxEventType cbEVT_PL_LAYOUT_ROW = wxNewEventType();
63 wxEventType cbEVT_PL_RESIZE_ROW = wxNewEventType();
64 wxEventType cbEVT_PL_LAYOUT_ROWS = wxNewEventType();
65 wxEventType cbEVT_PL_INSERT_BAR = wxNewEventType();
66 wxEventType cbEVT_PL_RESIZE_BAR = wxNewEventType();
67 wxEventType cbEVT_PL_REMOVE_BAR = wxNewEventType();
68 wxEventType cbEVT_PL_SIZE_BAR_WND = wxNewEventType();
69
70 wxEventType cbEVT_PL_DRAW_BAR_DECOR = wxNewEventType();
71 wxEventType cbEVT_PL_DRAW_ROW_DECOR = wxNewEventType();
72 wxEventType cbEVT_PL_DRAW_PANE_DECOR = wxNewEventType();
73 wxEventType cbEVT_PL_DRAW_BAR_HANDLES = wxNewEventType();
74 wxEventType cbEVT_PL_DRAW_ROW_HANDLES = wxNewEventType();
75 wxEventType cbEVT_PL_DRAW_ROW_BKGROUND = wxNewEventType();
76 wxEventType cbEVT_PL_DRAW_PANE_BKGROUND = wxNewEventType();
77
78 wxEventType cbEVT_PL_START_BAR_DRAGGING = wxNewEventType();
79 wxEventType cbEVT_PL_DRAW_HINT_RECT = wxNewEventType();
80
81 wxEventType cbEVT_PL_START_DRAW_IN_AREA = wxNewEventType();
82 wxEventType cbEVT_PL_FINISH_DRAW_IN_AREA = wxNewEventType();
83
84 wxEventType cbEVT_PL_CUSTOMIZE_BAR = wxNewEventType();
85 wxEventType cbEVT_PL_CUSTOMIZE_LAYOUT = wxNewEventType();
86
87 wxEventType wxCUSTOM_CB_PLUGIN_EVENTS_START_AT = wxNewEventType();
88#endif // #if wxCHECK_VERSION(2,3,0)
89
90// some ascii-art, still can't get these *nice* cursors working on wx... :-(
91
92static const char* _gHorizCursorImg[] =
93{
94 "............XX....XX............",
95 "............XX....XX............",
96 "............XX....XX............",
97 "............XX....XX............",
98 "............XX....XX............",
99 "...X........XX....XX........X...",
100 "..XX........XX....XX........XX..",
101 ".XXX........XX....XX........XXX.",
102 "XXXXXXXXXXXXXX....XXXXXXXXXXXXXX",
103 ".XXX........XX....XX........XXX.",
104 "..XX........XX....XX........XX..",
105 "...X........XX....XX........X...",
106 "............XX....XX............",
107 "............XX....XX............",
108 "............XX....XX............",
109 "............XX....XX............"
110};
111
112static const char* _gVertCursorImg[] =
113{
114 "................X...............",
115 "...............XXX..............",
116 "..............XXXXX.............",
117 ".............XXXXXXX............",
118 "................X...............",
119 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
120 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
121 "................................",
122 "................................",
123 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
124 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
125 "................X...............",
126 ".............XXXXXXX............",
127 "..............XXXXX.............",
128 "...............XXX..............",
129 "................X..............."
130};
131
132// helper inline functions
133
134static inline bool rect_contains_point( const wxRect& rect, int x, int y )
135{
136 return ( x >= rect.x &&
137 y >= rect.y &&
138 x < rect.x + rect.width &&
139 y < rect.y + rect.height );
140}
141
142static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
143{
144 if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
145 ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
146
147 if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
148 ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
149
150 return 1;
151
152 return 0;
153}
154
155static inline void hide_rect( wxRect& r )
156{
157 r.x = 32768;
158 r.y = 32768;
159 r.width = 1;
160 r.height = 1;
161}
162
163static inline void clip_rect_against_rect( wxRect& r1, const wxRect& r2 )
164{
165 if ( r1.x < r2.x ||
166 r1.y < r2.y ||
167 r1.x >= r2.x + r2.width ||
168 r1.y >= r2.y + r2.height
169 )
170 {
171 hide_rect( r1 );
172 return;
173 }
174 else
175 {
176 if ( r1.x + r1.width > r2.x + r2.width )
177
178 r1.width = r2.x + r2.width - r1.x;
179
180 if ( r1.y + r1.height > r2.y + r2.height )
181
182 r1.height = r2.y + r2.height - r1.y;
183 }
184}
185
186/***** Implementation for class cbBarSpy *****/
187
188IMPLEMENT_DYNAMIC_CLASS( cbBarSpy, wxEvtHandler )
189
190cbBarSpy::cbBarSpy(void)
191 : mpLayout(0),
192 mpBarWnd(0)
193{}
194
195cbBarSpy::cbBarSpy( wxFrameLayout* pPanel )
196
197 : mpLayout(pPanel),
198 mpBarWnd(0)
199{}
200
201void cbBarSpy::SetBarWindow( wxWindow* pWnd )
202{
203 mpBarWnd = pWnd;
204}
205
206bool cbBarSpy::ProcessEvent(wxEvent& event)
207{
208 bool handled = wxEvtHandler::ProcessEvent( event );
209
210 int type = event.GetEventType();
211
212 if ( !handled && ( type == wxEVT_LEFT_DOWN ||
213 type == wxEVT_LEFT_DCLICK ) )
214 {
215 wxMouseEvent& mevent = *((wxMouseEvent*)&event);
216
217 int x = mevent.m_x;
218 int y = mevent.m_y;
219
220 mpBarWnd->ClientToScreen( &x, &y );
221 mpLayout->GetParentFrame().ScreenToClient( &x, &y );
222
223 mevent.m_x = x;
224 mevent.m_y = y;
225
226 // forwared not-handled event to frame-layout
227
228 if ( type == wxEVT_LEFT_DOWN )
229 {
230 //mpLayout->OnLButtonDown( mevent );
231 event.Skip();
232 }
233 else
234 mpLayout->OnLDblClick( mevent );
235
236 //event.Skip(FALSE);
237 }
238
239 return handled;
240}
241
242/***** Implementation for class wxFrameLayout *****/
243
244IMPLEMENT_DYNAMIC_CLASS( wxFrameLayout, wxEvtHandler )
245
246BEGIN_EVENT_TABLE( wxFrameLayout, wxEvtHandler )
247
248 EVT_PAINT ( wxFrameLayout::OnPaint )
249 EVT_SIZE ( wxFrameLayout::OnSize )
250 EVT_LEFT_DOWN ( wxFrameLayout::OnLButtonDown )
251 EVT_LEFT_UP ( wxFrameLayout::OnLButtonUp )
252 EVT_RIGHT_DOWN ( wxFrameLayout::OnRButtonDown )
253 EVT_RIGHT_UP ( wxFrameLayout::OnRButtonUp )
254 EVT_MOTION ( wxFrameLayout::OnMouseMove )
255
256 EVT_LEFT_DCLICK( wxFrameLayout::OnLDblClick )
257
258 EVT_IDLE ( wxFrameLayout::OnIdle )
259 EVT_SET_FOCUS ( wxFrameLayout::OnSetFocus )
260 EVT_KILL_FOCUS ( wxFrameLayout::OnKillFocus )
261
262 EVT_ACTIVATE ( wxFrameLayout::OnActivate )
263
264 EVT_ERASE_BACKGROUND( wxFrameLayout::OnEraseBackground )
265
266END_EVENT_TABLE()
267
268// FIXME:: how to eliminate these cut&pasted constructors?
269
270wxFrameLayout::wxFrameLayout(void)
271
272 : mpFrame ( NULL ),
273 mpFrameClient( NULL ),
274
275 mDarkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID ),
276 mLightPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT), 1, wxSOLID ),
277 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
278 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID ),
279 mBorderPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
280
281 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT ),
282
283 mpPaneInFocus( NULL ),
284 mpLRUPane ( NULL ),
285
286
287 mpTopPlugin ( NULL ),
288 mpCaputesInput( NULL ),
289
290 mClientWndRefreshPending( FALSE ),
291 mRecalcPending( TRUE ),
292 mCheckFocusWhenIdle( FALSE )
293{
294 CreateCursors();
295
296 for( int i = 0; i != MAX_PANES; ++i )
297
298 mPanes[i] = NULL;
299
300 mFloatingOn = CanReparent();
301}
302
303wxFrameLayout::wxFrameLayout( wxWindow* pParentFrame, wxWindow* pFrameClient, bool activateNow )
304
305 : mpFrame( pParentFrame ),
306 mpFrameClient(pFrameClient),
307
308 mDarkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID ),
309 mLightPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT), 1, wxSOLID ),
310 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
311 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID ),
312 mBorderPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
313
314 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT ),
315
316 mpPaneInFocus( NULL ),
317 mpLRUPane ( NULL ),
318
319 mFloatingOn ( TRUE ),
320
321 mpTopPlugin ( NULL ),
322 mpCaputesInput( NULL ),
323
324 mClientWndRefreshPending( FALSE ),
325 mRecalcPending( TRUE ),
326 mCheckFocusWhenIdle( FALSE ),
327
328 mpUpdatesMgr( NULL )
329{
330 CreateCursors();
331
332 for( int i = 0; i != MAX_PANES; ++i )
333
334 mPanes[i] = new cbDockPane( i, this );
335
336 if ( activateNow )
337 {
338 HookUpToFrame();
339
340 // FOR NOW::
341 // DBG:: set RED color of frame's background for the
342 // prurpose of tracking engine bugs "visually"
343
344 GetParentFrame().SetBackgroundColour( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) );
345 }
346
347 mFloatingOn = CanReparent();
348}
349
350// NOTE:: below are the only plaftorm-check "ifdef"s in the docking system!
351
352bool wxFrameLayout::CanReparent()
353{
354#ifdef __WXMSW__
355 return TRUE;
356#elif defined (__WXGTK__)
357 //return TRUE;
358 return FALSE;
359#else
360
361 return FALSE; // reparenting is not yet supported by Motif and others
362#endif
363}
364
365/*
366#ifdef __WXMSW__
367 #inlcude "windows.h"
368#endif
369*/
370
371void wxFrameLayout::ReparentWindow( wxWindow* pChild, wxWindow* pNewParent )
372{
373#ifdef __WXMSW__
374#if 0
375
376 if ( pChild->GetParent() )
377 {
378 bool success = pChild->GetParent()->GetChildren().DeleteObject( pChild );
379
380 wxASSERT( success ); // DBG::
381 }
382
383 ::SetParent( (HWND)pChild->m_hWnd, (HWND)pNewParent->m_hWnd );
384
385 pNewParent->GetChildren().Append( pChild );
386
387 pChild->SetParent( pNewParent );
388#endif
389 pChild->Reparent(pNewParent);
390
391 return;
392#elif defined(__WXGTK__)
393 // FOR NOW:: floating with wxGtk still very buggy
394
395 return;
396
397 //pChild->ReParent( pNewParent );
398
399 //return;
400#else
401 wxMessageBox( "Sorry, docking is not supported for ports other than MSW and wxGTK" );
402#endif
403}
404
405void wxFrameLayout::DestroyBarWindows()
406{
407 wxNode* pSpy = mBarSpyList.First();
408
409 while( pSpy )
410 {
411 cbBarSpy& spy = *((cbBarSpy*)pSpy->Data());
412
413 if ( spy.mpBarWnd->GetEventHandler() == &spy )
414
415 spy.mpBarWnd->PopEventHandler();
416
417 delete &spy;
418
419 pSpy = pSpy->Next();
420 }
421
422 mBarSpyList.Clear();
423
424 for( size_t i = 0; i != mAllBars.Count(); ++i )
425 {
426 if ( mAllBars[i]->mpBarWnd )
427 {
428 mAllBars[i]->mpBarWnd->Destroy();
429 mAllBars[i]->mpBarWnd = NULL;
430 }
431 }
432}
433
434void wxFrameLayout::ShowFloatedWindows( bool show )
435{
436 wxNode* pNode = mFloatedFrames.First();
437
438 while( pNode )
439 {
440 cbFloatedBarWindow* pFFrm = ((cbFloatedBarWindow*)pNode->Data());
441
442 pFFrm->Show( show );
443
444 pNode = pNode->Next();
445 }
446}
447
448wxFrameLayout::~wxFrameLayout()
449{
450 UnhookFromFrame();
451
452 if ( mpUpdatesMgr )
453 delete mpUpdatesMgr;
454
455 PopAllPlugins();
456
457 // destoy the chain of plugins from left to right
458
459 wxEvtHandler* pCur = mpTopPlugin;
460
461 if ( pCur )
462
463 while ( pCur->GetPreviousHandler() )
464
465 pCur = pCur->GetPreviousHandler();
466
467 while ( pCur )
468 {
469 wxEvtHandler* pNext = pCur->GetNextHandler();
470
471 delete pCur;
472
473 pCur = pNext;
474 }
475
476 // destroy contents of arrays and lists
477
478 size_t i = 0;
479
480 for( i = 0; i != MAX_PANES; ++i )
481 {
482 if ( mPanes[i] )
483 delete mPanes[i];
484 }
485 if ( mpHorizCursor )
486 delete mpHorizCursor;
487 if ( mpVertCursor )
488 delete mpVertCursor;
489 if ( mpNormalCursor )
490 delete mpNormalCursor;
491 if ( mpDragCursor )
492 delete mpDragCursor;
493 if ( mpNECursor )
494 delete mpNECursor;
495
496 wxNode* pSpy = mBarSpyList.First();
497
498 while( pSpy )
499 {
500 cbBarSpy& spy = *((cbBarSpy*)pSpy->Data());
501
502 if ( spy.mpBarWnd->GetEventHandler() == &spy )
503
504 spy.mpBarWnd->PopEventHandler();
505
506 delete &spy;
507
508 pSpy = pSpy->Next();
509 }
510
511 for( i = 0; i != mAllBars.Count(); ++i )
512
513 delete mAllBars[i];
514}
515
516void wxFrameLayout::EnableFloating( bool enable )
517{
518 mFloatingOn = enable && CanReparent();
519}
520
521void wxFrameLayout::Activate()
522{
523 HookUpToFrame();
524
525 RefreshNow( TRUE );
526
527 ShowFloatedWindows( TRUE );
528}
529
530void wxFrameLayout::Deactivate()
531{
532 ShowFloatedWindows( FALSE );
533
534 UnhookFromFrame();
535
536 HideBarWindows();
537}
538
539void wxFrameLayout::SetFrameClient( wxWindow* pFrameClient )
540{
541 mpFrameClient = pFrameClient;
542}
543
544wxWindow* wxFrameLayout::GetFrameClient()
545{
546 return mpFrameClient;
547}
548
549cbUpdatesManagerBase& wxFrameLayout::GetUpdatesManager()
550{
551 if ( !mpUpdatesMgr )
552 mpUpdatesMgr = CreateUpdatesManager();
553
554 return *mpUpdatesMgr;
555}
556
557void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase* pUMgr )
558{
559 if ( mpUpdatesMgr )
560 delete mpUpdatesMgr;
561
562 mpUpdatesMgr = pUMgr;
563
564 mpUpdatesMgr->SetLayout( this );
565}
566
567cbUpdatesManagerBase* wxFrameLayout::CreateUpdatesManager()
568{
569 return new cbGCUpdatesMgr( this );
570 //return new cbSimpleUpdatesMgr( this );
571}
572
573void wxFrameLayout::AddBar( wxWindow* pBarWnd,
574 const cbDimInfo& dimInfo,
575 int alignment,
576 int rowNo,
577 int columnPos,
578 const wxString& name,
579 bool spyEvents,
580 int state
581 )
582{
583 if ( pBarWnd && spyEvents )
584 {
585 // hook up spy to bar window
586 cbBarSpy* pSpy = new cbBarSpy( this );
587
588 pSpy->SetBarWindow( pBarWnd );
589 pBarWnd->PushEventHandler( pSpy );
590
591 mBarSpyList.Append( pSpy );
592 }
593
594 cbBarInfo* pInfo = new cbBarInfo();
595
596 pInfo->mName = name;
597 pInfo->mpBarWnd = pBarWnd;
598 pInfo->mDimInfo = dimInfo;
599 pInfo->mState = state;
600 pInfo->mAlignment = alignment;
601 pInfo->mRowNo = rowNo;
602 pInfo->mBounds.x = columnPos;
603
604 mAllBars.Add( pInfo );
605
606 DoSetBarState( pInfo );
607}
608
609bool wxFrameLayout::RedockBar( cbBarInfo* pBar,
610 const wxRect& shapeInParent,
611 cbDockPane* pToPane,
612 bool updateNow )
613{
614 if ( !pToPane )
615
616 pToPane = HitTestPanes( shapeInParent, NULL );
617
618 if ( !pToPane )
619
620 return FALSE; // bar's shape does not hit any pane
621 // - redocking is NOT possible
622
623 cbDockPane* pBarPane = GetBarPane( pBar );
624
625 if ( updateNow )
626
627 GetUpdatesManager().OnStartChanges();
628
629 pBarPane->RemoveBar( pBar );
630
631 // FIXME FIXME:: the below recalc. may be a *huge* performance
632 // hit, it could be eliminated though...
633 // but first the "pane-postion-changed" problem
634 // have to be fixed
635
636 RecalcLayout( FALSE );
637
638 pToPane->InsertBar( pBar, shapeInParent );
639
640 RecalcLayout( FALSE );
641
642 // finish update "transaction"
643
644 if ( updateNow )
645 {
646 GetUpdatesManager().OnFinishChanges();
647 GetUpdatesManager().UpdateNow();
648 }
649
650 return TRUE;
651}
652
653cbBarInfo* wxFrameLayout::FindBarByName( const wxString& name )
654{
655 for( size_t i = 0; i != mAllBars.Count(); ++i )
656
657 if ( mAllBars[i]->mName == name )
658
659 return mAllBars[i];
660
661 return NULL;
662}
663
664cbBarInfo* wxFrameLayout::FindBarByWindow( const wxWindow* pWnd )
665{
666 for( size_t i = 0; i != mAllBars.Count(); ++i )
667
668 if ( mAllBars[i]->mpBarWnd == pWnd )
669
670 return mAllBars[i];
671
672 return NULL;
673}
674
675BarArrayT& wxFrameLayout::GetBars()
676{
677 return mAllBars;
678}
679
680void wxFrameLayout::SetBarState( cbBarInfo* pBar, int newState, bool updateNow )
681{
682 if ( newState == wxCBAR_FLOATING && !mFloatingOn )
683
684 return;
685
686 if ( updateNow )
687
688 GetUpdatesManager().OnStartChanges();
689
690 pBar->mUMgrData.SetDirty(TRUE);
691
692 // check bar's previous state
693
694 if ( pBar->mState != wxCBAR_HIDDEN && pBar->mState != wxCBAR_FLOATING )
695 {
696 cbDockPane* pPane;
697 cbRowInfo* pRow;
698
699 bool success = LocateBar( pBar, &pRow, &pPane );
700
701 wxASSERT( success ); // DBG::
702
703 // save LRU-dim info before removing bar
704
705 pBar->mDimInfo.mLRUPane = pPane->GetAlignment();
706 pBar->mDimInfo.mBounds[ pPane->GetAlignment() ] = pBar->mBounds;
707
708 // remove it from the pane it was docked on
709
710 pPane->RemoveBar( pBar );
711
712 }
713
714 if ( pBar->mState == wxCBAR_FLOATING && newState != wxCBAR_FLOATING )
715 {
716 // remove bar's window form the containing mini-frame
717 // and set it's parent to be layout's parent frame
718
719 if ( pBar->mpBarWnd )
720 {
721 pBar->mpBarWnd->Show(FALSE); // to avoid flicker upon reparenting
722
723 wxNode* pNode = mFloatedFrames.First();
724
725 while( pNode )
726 {
727 cbFloatedBarWindow* pFFrm = ((cbFloatedBarWindow*)pNode->Data());
728
729 if ( pFFrm->GetBar() == pBar )
730 {
731 pFFrm->Show( FALSE ); // reduces flicker sligthly
732
733 ReparentWindow( pBar->mpBarWnd, &GetParentFrame() );
734
735 pBar->mBounds = pBar->mDimInfo.mBounds[ pBar->mDimInfo.mLRUPane ];
736
737 if ( newState != wxCBAR_HIDDEN )
738
739 pBar->mAlignment = pBar->mDimInfo.mLRUPane;
740
741 mFloatedFrames.DeleteNode( pNode );
742
743 pFFrm->Show( FALSE );
744 pFFrm->Destroy(); break;
745 }
746
747 pNode = pNode->Next();
748 }
749
750 // FOR NOW:: excessive!
751 //if ( mpFrameClient ) mpFrameClient->Refresh();
752 if ( mpFrameClient )
753 mClientWndRefreshPending = TRUE;
754 }
755 }
756
757 pBar->mState = newState;
758
759 DoSetBarState( pBar );
760
761 if ( updateNow )
762 {
763 RecalcLayout(FALSE);
764
765 GetUpdatesManager().OnFinishChanges();
766 GetUpdatesManager().UpdateNow();
767 }
768}
769
770void wxFrameLayout::InverseVisibility( cbBarInfo* pBar )
771{
772 wxASSERT( pBar ); // DBG::
773
774 // "inverse" bar-visibility of the selected bar
775
776 int newState = 0;
777
778 if ( pBar->mState == wxCBAR_HIDDEN )
779 {
780 if ( pBar->mAlignment == -1 )
781 {
782 pBar->mAlignment = 0; // just remove "-1" marking
783 newState = wxCBAR_FLOATING;
784 }
785 else
786 if ( pBar->mAlignment == FL_ALIGN_TOP ||
787 pBar->mAlignment == FL_ALIGN_BOTTOM )
788
789 newState = wxCBAR_DOCKED_HORIZONTALLY;
790 else
791 newState = wxCBAR_DOCKED_VERTICALLY;
792 }
793 else
794 {
795 newState = wxCBAR_HIDDEN;
796
797 if ( pBar->mState == wxCBAR_FLOATING )
798
799 pBar->mAlignment = -1;
800 }
801
802 this->SetBarState( pBar, newState, TRUE );
803
804 if ( newState == wxCBAR_FLOATING )
805
806 this->RepositionFloatedBar( pBar );
807}
808
809void wxFrameLayout::ApplyBarProperties( cbBarInfo* pBar )
810{
811 if ( pBar->mState == wxCBAR_FLOATING )
812 {
813 RepositionFloatedBar( pBar );
814 }
815 else
816 if ( pBar->mState == wxCBAR_DOCKED_HORIZONTALLY ||
817 pBar->mState == wxCBAR_DOCKED_VERTICALLY
818 )
819 {
820 // FOR NOW:: nothing
821 }
822
823}
824
825void wxFrameLayout::RepositionFloatedBar( cbBarInfo* pBar )
826{
827 if ( !mFloatingOn ) return;
828
829 wxNode* pNode = mFloatedFrames.First();
830
831 while( pNode )
832 {
833 cbFloatedBarWindow* pFFrm = ((cbFloatedBarWindow*)pNode->Data());
834
835 if ( pFFrm->GetBar() == pBar )
836 {
837 wxRect& bounds = pBar->mDimInfo.mBounds[wxCBAR_FLOATING];
838
839 int x = bounds.x,
840 y = bounds.y;
841
842 GetParentFrame().ClientToScreen( &x, &y );
843
844 pFFrm->PositionFloatedWnd( x,y,
845 bounds.width,
846 bounds.height );
847
848 break;
849 }
850
851 pNode = pNode->Next();
852 }
853}
854
855void wxFrameLayout::DoSetBarState( cbBarInfo* pBar )
856{
857 if ( pBar->mState != wxCBAR_FLOATING &&
858 pBar->mState != wxCBAR_HIDDEN )
859
860 // dock it
861
862 mPanes[pBar->mAlignment]->InsertBar( pBar );
863 else
864 if ( pBar->mState == wxCBAR_HIDDEN )
865 {
866 // hide it
867
868 if ( pBar->mpBarWnd )
869
870 pBar->mpBarWnd->Show( FALSE );
871 }
872 else
873 {
874 if ( !mFloatingOn ) return;
875
876 // float it
877
878 if ( pBar->mpBarWnd == NULL || !CanReparent() )
879 {
880 // FOR NOW:: just hide it
881
882 if ( pBar->mpBarWnd )
883
884 pBar->mpBarWnd->Show( FALSE );
885
886 pBar->mState = wxCBAR_HIDDEN;
887
888 return;
889 }
890
891 cbFloatedBarWindow* pMiniFrm = new cbFloatedBarWindow();
892
893 pMiniFrm->SetBar( pBar );
894 pMiniFrm->SetLayout( this );
895
896 pMiniFrm->Create( &GetParentFrame(), -1, pBar->mName,
897 wxPoint( 50,50 ),
898 wxSize ( 0, 0 ),
899 wxFRAME_FLOAT_ON_PARENT | wxFRAME_TOOL_WINDOW
900 );
901
902 pMiniFrm->SetClient( pBar->mpBarWnd );
903
904 ReparentWindow( pBar->mpBarWnd, pMiniFrm );
905
906 mFloatedFrames.Append( pMiniFrm );
907
908 wxRect& bounds = pBar->mDimInfo.mBounds[wxCBAR_FLOATING];
909
910 // check if it wasn't floated anytime before
911
912 if ( bounds.width == -1 )
913 {
914 wxRect& clntRect = GetClientRect();
915
916 // adjust position into which the next floated bar will be placed
917
918 if ( mNextFloatedWndPos.x + bounds.width > clntRect.width )
919
920 mNextFloatedWndPos.x = mFloatingPosStep.x;
921
922 if ( mNextFloatedWndPos.y + bounds.height > clntRect.height )
923
924 mNextFloatedWndPos.y = mFloatingPosStep.y;
925
926 bounds.x = mNextFloatedWndPos.x + clntRect.x;
927 bounds.y = mNextFloatedWndPos.y + clntRect.y;
928
929 bounds.width = pBar->mDimInfo.mSizes[wxCBAR_FLOATING].x;
930 bounds.height = pBar->mDimInfo.mSizes[wxCBAR_FLOATING].y;
931
932 mNextFloatedWndPos.x += mFloatingPosStep.x;
933 mNextFloatedWndPos.y += mFloatingPosStep.y;
934 }
935
936 pMiniFrm->Show( TRUE );
937
938 // FIXME:: this is excessive
939 pBar->mpBarWnd->Show(TRUE);
940 }
941}
942
943void wxFrameLayout::RemoveBar( cbBarInfo* pBarInfo )
944{
945 // first, try to "guess" what was the perviouse state of the bar
946
947 cbDockPane* pPane;
948 cbRowInfo* pRow;
949
950 if ( LocateBar( pBarInfo, &pRow, &pPane ) )
951 {
952 // ...aha, bar was docked into one of the panes,
953 // remove it from there
954
955 pPane->RemoveBar( pBarInfo );
956 }
957
958 for( size_t i = 0; i != mAllBars.Count(); ++i )
959 {
960 if ( mAllBars[i] == pBarInfo )
961 {
962#if wxCHECK_VERSION(2,3,2)
963 mAllBars.RemoveAt(i);
964#else
965 mAllBars.Remove(i);
966#endif
967 if ( pBarInfo->mpBarWnd ) // hides it's window
968
969 pBarInfo->mpBarWnd->Show( FALSE );
970
971 delete pBarInfo;
972
973 return;
974 }
975 }
976 int avoidCompilerWarning = 0;
977 wxASSERT(avoidCompilerWarning); // DBG:: bar info should be present in the list of all bars of all panes
978
979}
980
981bool wxFrameLayout::LocateBar( cbBarInfo* pBarInfo,
982 cbRowInfo** ppRow,
983 cbDockPane** ppPane )
984{
985 (*ppRow) = NULL;
986 (*ppPane) = NULL;
987
988 for( int n = 0; n != MAX_PANES; ++n )
989 {
990 wxBarIterator i( mPanes[n]->GetRowList() );
991
992 while( i.Next() )
993
994 if ( &i.BarInfo() == pBarInfo )
995 {
996 (*ppPane) = mPanes[n];
997 (*ppRow ) = &i.RowInfo();
998
999 return TRUE;
1000 }
1001 }
1002
1003 return FALSE;
1004}
1005
1006void wxFrameLayout::RecalcLayout( bool repositionBarsNow )
1007{
1008 mRecalcPending = FALSE;
1009
1010 int frmWidth, frmHeight;
1011 mpFrame->GetClientSize( &frmWidth, &frmHeight );
1012 int paneHeight = 0;
1013
1014 int curY = 0;
1015 int curX = 0;
1016 wxRect rect;
1017
1018 // pane positioning priorities in decreasing order:
1019 // top, bottom, left, right
1020
1021 // setup TOP pane
1022
1023 cbDockPane* pPane = mPanes[ FL_ALIGN_TOP ];
1024
1025 pPane->SetPaneWidth( frmWidth );
1026 pPane->RecalcLayout();
1027
1028 paneHeight = pPane->GetPaneHeight();
1029
1030 rect.x = curX;
1031 rect.y = curY;
1032 rect.width = frmWidth;
1033 rect.height = wxMin( paneHeight, frmHeight - curY );
1034
1035 pPane->SetBoundsInParent( rect );
1036
1037 curY += paneHeight;
1038
1039 // setup BOTTOM pane
1040
1041 pPane = mPanes[ FL_ALIGN_BOTTOM ];
1042
1043 pPane->SetPaneWidth( frmWidth );
1044 pPane->RecalcLayout();
1045
1046 paneHeight = pPane->GetPaneHeight();
1047
1048 rect.x = curX;
1049 rect.y = wxMax( frmHeight - paneHeight, curY );
1050 rect.width = frmWidth;
1051 rect.height = frmHeight - rect.y;
1052
1053 pPane->SetBoundsInParent( rect );
1054
1055 // setup LEFT pane
1056
1057 pPane = mPanes[ FL_ALIGN_LEFT ];
1058
1059 // bottom pane's y
1060 pPane->SetPaneWidth( rect.y - curY );
1061
1062 pPane->RecalcLayout();
1063 paneHeight = pPane->GetPaneHeight();
1064
1065 // bottom rect's y
1066 rect.height = rect.y - curY;
1067 rect.x = curX;
1068 rect.y = curY;
1069 rect.width = wxMin( paneHeight, frmWidth );
1070
1071 pPane->SetBoundsInParent( rect );
1072
1073 curX += rect.width;
1074
1075 // setup RIGHT pane
1076
1077 pPane = mPanes[ FL_ALIGN_RIGHT ];
1078
1079 // left pane's height
1080 pPane->SetPaneWidth( rect.height );
1081
1082 pPane->RecalcLayout();
1083 paneHeight = pPane->GetPaneHeight();
1084
1085 // left pane's height
1086 rect.height = rect.height;
1087 rect.x = wxMax( frmWidth - paneHeight, curX );
1088 rect.y = curY;
1089 rect.width = frmWidth - rect.x;
1090
1091 pPane->SetBoundsInParent( rect );
1092
1093 // recalc bounds of the client-window
1094
1095 mClntWndBounds.x = mPanes[FL_ALIGN_LEFT]->mBoundsInParent.x +
1096 mPanes[FL_ALIGN_LEFT]->mBoundsInParent.width;
1097 mClntWndBounds.y = mPanes[FL_ALIGN_TOP ]->mBoundsInParent.y +
1098 mPanes[FL_ALIGN_TOP ]->mBoundsInParent.height;
1099
1100 mClntWndBounds.width = mPanes[FL_ALIGN_RIGHT]->mBoundsInParent.x -
1101 mClntWndBounds.x;
1102 mClntWndBounds.height = mPanes[FL_ALIGN_BOTTOM]->mBoundsInParent.y -
1103 mClntWndBounds.y;
1104
1105 if ( repositionBarsNow )
1106
1107 PositionPanes();
1108}
1109
1110int wxFrameLayout::GetClientHeight()
1111{
1112 // for better portablility wxWindow::GetSzie() is not used here
1113
1114 return mClntWndBounds.height;
1115}
1116
1117int wxFrameLayout::GetClientWidth()
1118{
1119 // for better portablility wxWindow::GetSzie() is not used here
1120
1121 return mClntWndBounds.width;
1122}
1123
1124void wxFrameLayout::PositionClientWindow()
1125{
1126 if ( mpFrameClient )
1127 {
1128 if ( mClntWndBounds.width >= 1 && mClntWndBounds.height >= 1 )
1129 {
1130 mpFrameClient->SetSize( mClntWndBounds.x, mClntWndBounds.y,
1131 mClntWndBounds.width, mClntWndBounds.height, 0 );
1132
1133 if ( !mpFrameClient->IsShown() )
1134
1135 mpFrameClient->Show( TRUE );
1136 }
1137 else
1138 mpFrameClient->Show( FALSE );
1139 }
1140}
1141
1142void wxFrameLayout::PositionPanes()
1143{
1144 PositionClientWindow();
1145
1146 // FOR NOW:: excessive updates!
1147 // reposition bars within all panes
1148
1149 for( int i = 0; i != MAX_PANES; ++i )
1150
1151 mPanes[i]->SizePaneObjects();
1152}
1153
1154void wxFrameLayout::OnSize( wxSizeEvent& event )
1155{
1156 if ( event.GetEventObject() == (wxObject*) mpFrame )
1157
1158 RecalcLayout(TRUE);
1159}
1160
1161/*** protected members ***/
1162
1163void wxFrameLayout::HideBarWindows()
1164{
1165 for( size_t i = 0; i != mAllBars.Count(); ++i )
1166
1167 if ( mAllBars[i]->mpBarWnd && mAllBars[i]->mState != wxCBAR_FLOATING )
1168
1169 mAllBars[i]->mpBarWnd->Show( FALSE );
1170
1171 // then floated frames
1172
1173 ShowFloatedWindows( FALSE );
1174
1175 if ( mpFrameClient )
1176
1177 mpFrameClient->Show( FALSE );
1178}
1179
1180void wxFrameLayout::UnhookFromFrame()
1181{
1182 // NOTE:: the SetEvtHandlerEnabled() method is not used
1183 // here, since it is assumed, that unhooking layout
1184 // from window may result destroying of the layout itself
1185 //
1186 // BUG BUG BUG (wx):: this would not be a problem if
1187 // wxEvtHandler's destructor would check if
1188 // this handler is currently the top-most
1189 // handler of some window, and additionally
1190 // to the reconnecting itself from the chain
1191 // it would also re-setup current event handler
1192 // of the window using wxWindow::SetEventHandler()
1193
1194 // FOR NOW::
1195
1196 if ( mpFrame->GetEventHandler() == this )
5921a14e 1197 {
8e08b761 1198 mpFrame->PopEventHandler();
5921a14e
GT
1199 return;
1200 }
8e08b761 1201
8e08b761
JS
1202 if ( mpFrame )
1203 {
1204 if ( this == mpFrame->GetEventHandler() )
5921a14e 1205 {
8e08b761 1206 mpFrame->SetEventHandler( this->GetNextHandler() );
5921a14e 1207 }
8e08b761 1208 else
5921a14e
GT
1209 {
1210 wxEvtHandler* pCur = mpFrame->GetEventHandler();
8e08b761 1211
5921a14e
GT
1212 while ( pCur )
1213 {
1214 if ( pCur == this )
1215 break;
8e08b761 1216
5921a14e 1217 pCur = pCur->GetNextHandler();
8e08b761
JS
1218 }
1219
5921a14e
GT
1220 // do not try to unhook ourselves if we're not hooked yet
1221 if ( !pCur )
1222 return;
1223 }
8e08b761 1224
5921a14e 1225 if ( GetPreviousHandler() )
8e08b761
JS
1226 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1227 else
1228 {
1229 mpFrame->PopEventHandler();
1230 return;
1231 }
1232
8e08b761 1233 if ( GetNextHandler() )
8e08b761
JS
1234 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1235
1236 SetNextHandler( NULL );
1237 SetPreviousHandler( NULL );
1238 }
1239}
1240
1241void wxFrameLayout::HookUpToFrame()
1242{
1243 // unhook us first, we're already hooked up
1244
1245 UnhookFromFrame();
1246
1247 // put ourselves on top
1248
1249 mpFrame->PushEventHandler( this );
1250}
1251
1252cbDockPane* wxFrameLayout::GetBarPane( cbBarInfo* pBar )
1253{
1254 for( int i = 0; i != MAX_PANES; ++i )
1255
1256 if ( mPanes[i]->BarPresent( pBar ) ) return mPanes[i];
1257
1258 return NULL;
1259}
1260
1261void wxFrameLayout::CreateCursors()
1262{
1263 /*
1264 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1265 char bits[64];
1266
1267 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1268
1269 mpHorizCursor = new wxCursor( bits, 32, 16 );
1270
1271 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1272
1273 mpVertCursor = new wxCursor( bits, 32, 16 );
1274 */
1275
1276 // FOR NOW:: use standard ones
1277
1278 mpHorizCursor = new wxCursor(wxCURSOR_SIZEWE);
1279 mpVertCursor = new wxCursor(wxCURSOR_SIZENS);
1280 mpNormalCursor = new wxCursor(wxCURSOR_ARROW );
1281 mpDragCursor = new wxCursor(wxCURSOR_CROSS );
1282 mpNECursor = new wxCursor(wxCURSOR_NO_ENTRY);
1283
1284 mFloatingPosStep.x = 25;
1285 mFloatingPosStep.y = 25;
1286
1287 mNextFloatedWndPos.x = mFloatingPosStep.x;
1288 mNextFloatedWndPos.y = mFloatingPosStep.y;
1289}
1290
1291bool wxFrameLayout::HitTestPane( cbDockPane* pPane, int x, int y )
1292{
1293 return rect_contains_point( pPane->GetRealRect(), x, y );
1294}
1295
1296cbDockPane* wxFrameLayout::HitTestPanes( const wxRect& rect,
1297 cbDockPane* pCurPane )
1298{
1299 // first, give the privilege to the current pane
1300
1301 if ( pCurPane && rect_hits_rect( pCurPane->GetRealRect(), rect ) )
1302
1303 return pCurPane;
1304
1305 for( int i = 0; i != MAX_PANES; ++i )
1306
1307 if ( pCurPane != mPanes[i] &&
1308 rect_hits_rect( mPanes[i]->GetRealRect(), rect ) )
1309
1310 return mPanes[i];
1311
1312 return 0;
1313}
1314
1315void wxFrameLayout::ForwardMouseEvent( wxMouseEvent& event,
1316 cbDockPane* pToPane,
1317 int eventType )
1318{
1319 wxPoint pos( event.m_x, event.m_y );
1320 pToPane->FrameToPane( &pos.x, &pos.y );
1321
1322#if wxCHECK_VERSION(2,3,0)
1323 if ( eventType == cbEVT_PL_LEFT_DOWN )
1324 {
1325 cbLeftDownEvent evt( pos, pToPane );
1326 FirePluginEvent( evt );
1327 }
1328 else if ( eventType == cbEVT_PL_LEFT_DCLICK )
1329 {
1330 cbLeftDClickEvent evt( pos, pToPane );
1331 FirePluginEvent( evt );
1332 }
1333 else if ( eventType == cbEVT_PL_LEFT_UP )
1334 {
1335 cbLeftUpEvent evt( pos, pToPane );
1336 FirePluginEvent( evt );
1337 }
1338 else if ( eventType == cbEVT_PL_RIGHT_DOWN )
1339 {
1340 cbRightDownEvent evt( pos, pToPane );
1341 FirePluginEvent( evt );
1342 }
1343 else if ( eventType == cbEVT_PL_RIGHT_UP )
1344 {
1345 cbRightUpEvent evt( pos, pToPane );
1346 FirePluginEvent( evt );
1347 }
1348 else if ( eventType == cbEVT_PL_MOTION )
1349 {
1350 cbMotionEvent evt( pos, pToPane );
1351 FirePluginEvent( evt );
1352 }
1353 else
1354 {
1355 int avoidCompilerWarning = 0;
1356 wxASSERT(avoidCompilerWarning); // DBG::
1357 }
1358#else
1359 switch ( eventType )
1360 {
1361 case cbEVT_PL_LEFT_DOWN : { cbLeftDownEvent evt( pos, pToPane );
1362 FirePluginEvent( evt ); break;
1363 }
1364
1365 case cbEVT_PL_LEFT_DCLICK:{ cbLeftDClickEvent evt( pos, pToPane );
1366 FirePluginEvent( evt ); break;
1367 }
1368
1369 case cbEVT_PL_LEFT_UP : { cbLeftUpEvent evt( pos, pToPane );
1370 FirePluginEvent( evt ); break;
1371 }
1372
1373 case cbEVT_PL_RIGHT_DOWN: { cbRightDownEvent evt( pos, pToPane );
1374 FirePluginEvent( evt ); break;
1375 }
1376
1377 case cbEVT_PL_RIGHT_UP : { cbRightUpEvent evt( pos, pToPane );
1378 FirePluginEvent( evt ); break;
1379 }
1380
1381 case cbEVT_PL_MOTION : { cbMotionEvent evt( pos, pToPane );
1382 FirePluginEvent( evt ); break;
1383 }
1384
1385 default : wxASSERT(0); // DBG::
1386 }
1387#endif // #if wxCHECK_VERSION(2,3,0)
1388} // wxFrameLayout::ForwardMouseEvent()
1389
1390
1391void wxFrameLayout::RouteMouseEvent( wxMouseEvent& event, int pluginEvtType )
1392{
1393 if ( mpPaneInFocus )
1394
1395 ForwardMouseEvent( event, mpPaneInFocus, pluginEvtType );
1396 else
1397 for( int i = 0; i != MAX_PANES; ++i )
1398
1399 if ( HitTestPane( mPanes[i], event.m_x, event.m_y ) )
1400 {
1401 ForwardMouseEvent( event, mPanes[i], pluginEvtType );
1402
1403 return;
1404 }
1405}
1406
1407/*** event handlers ***/
1408
1409void wxFrameLayout::OnRButtonDown( wxMouseEvent& event )
1410{
1411 RouteMouseEvent( event, cbEVT_PL_RIGHT_DOWN );
1412}
1413
1414void wxFrameLayout::OnRButtonUp( wxMouseEvent& event )
1415{
1416 RouteMouseEvent( event, cbEVT_PL_RIGHT_UP );
1417}
1418
1419void wxFrameLayout::OnLButtonDown( wxMouseEvent& event )
1420{
1421 RouteMouseEvent( event, cbEVT_PL_LEFT_DOWN );
1422}
1423
1424void wxFrameLayout::OnLDblClick( wxMouseEvent& event )
1425{
1426 RouteMouseEvent( event, cbEVT_PL_LEFT_DCLICK );
1427}
1428
1429void wxFrameLayout::OnLButtonUp( wxMouseEvent& event )
1430{
1431 RouteMouseEvent( event, cbEVT_PL_LEFT_UP );
1432}
1433
1434void wxFrameLayout::OnMouseMove( wxMouseEvent& event )
1435{
1436 if ( mpPaneInFocus )
1437
1438 ForwardMouseEvent( event, mpPaneInFocus, cbEVT_PL_MOTION );
1439 else
1440 for( int i = 0; i != MAX_PANES; ++i )
1441
1442 if ( HitTestPane( mPanes[i], event.m_x, event.m_y ) )
1443 {
1444 if ( mpLRUPane && mpLRUPane != mPanes[i] )
1445 {
1446 // simulate "mouse-leave" event
1447 ForwardMouseEvent( event, mpLRUPane, cbEVT_PL_MOTION );
1448 }
1449
1450 ForwardMouseEvent( event, mPanes[i], cbEVT_PL_MOTION );
1451
1452 mpLRUPane = mPanes[i];
1453
1454 return;
1455 }
1456
1457 if ( mpLRUPane )
1458 {
1459 // simulate "mouse-leave" event
1460 ForwardMouseEvent( event, mpLRUPane, cbEVT_PL_MOTION );
1461 mpLRUPane = 0;
1462 }
1463}
1464
1465void wxFrameLayout::OnPaint( wxPaintEvent& event )
1466{
1467 if ( mRecalcPending )
1468
1469 RecalcLayout( TRUE );
1470
1471 wxPaintDC dc(mpFrame);
1472
1473 for( int i = 0; i != MAX_PANES; ++i )
1474 {
1475 wxRect& rect = mPanes[i]->mBoundsInParent;
1476
1477 dc.SetClippingRegion( rect.x, rect.y, rect.width, rect.height );
1478
1479 mPanes[i]->PaintPane(dc);
1480
1481 dc.DestroyClippingRegion();
1482 }
1483
1484 event.Skip();
1485}
1486
1487void wxFrameLayout::OnEraseBackground( wxEraseEvent& event )
1488{
1489 // do nothing
1490}
1491
1492void wxFrameLayout::OnIdle( wxIdleEvent& event )
1493{
1494 wxWindow* focus = wxWindow::FindFocus();
1495
1496 if ( !focus && mCheckFocusWhenIdle )
1497 {
1498 wxMessageBox( "Hi, no more focus in this app!" );
1499
1500 mCheckFocusWhenIdle = FALSE;
1501 //ShowFloatedWindows( FALSE );
1502 }
1503
1504 mCheckFocusWhenIdle = FALSE;
1505
1506 event.Skip();
1507}
1508
1509
1510void wxFrameLayout::OnKillFocus( wxFocusEvent& event )
1511{
1512 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1513 //ShowFloatedWindows( FALSE );
1514}
1515
1516void wxFrameLayout::OnSetFocus( wxFocusEvent& event )
1517{
1518 //ShowFloatedWindows( TRUE );
1519}
1520
1521void wxFrameLayout::OnActivate( wxActivateEvent& event )
1522{
1523#if 0
1524 if ( event.GetActive() == FALSE )
1525 {
1526 wxWindow* focus = wxWindow::FindFocus();
1527
1528 if ( !focus || focus == &GetParentFrame() )
1529 {
1530 mCheckFocusWhenIdle = TRUE;
1531
1532 if ( !focus )
1533
1534 wxMessageBox("Deactivated!" );
1535
1536 }
1537 }
1538#endif
1539}
1540
1541void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties& props, int alignment )
1542{
1543 props = mPanes[alignment]->mProps;
1544}
1545
1546void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties& props, int paneMask )
1547{
1548 for( int i = 0; i != MAX_PANES; ++i )
1549
1550 if ( mPanes[i]->MatchesMask( paneMask ) )
1551
1552 mPanes[i]->mProps = props;
1553}
1554
1555void wxFrameLayout::SetMargins( int top, int bottom, int left, int right,
1556 int paneMask )
1557{
1558 for( int i = 0; i != MAX_PANES; ++i )
1559 {
1560 cbDockPane& pane = *mPanes[i];
1561
1562 if ( pane.MatchesMask( paneMask ) )
1563 {
1564 pane.mTopMargin = top;
1565 pane.mBottomMargin = bottom;
1566 pane.mLeftMargin = left;
1567 pane.mRightMargin = right;
1568 }
1569 }
1570}
1571
1572void wxFrameLayout::SetPaneBackground( const wxColour& colour )
1573{
1574 mBorderPen.SetColour( colour );
1575}
1576
1577void wxFrameLayout::RefreshNow( bool recalcLayout )
1578{
1579 if ( recalcLayout ) RecalcLayout( TRUE );
1580
1581 if ( mpFrame ) mpFrame->Refresh();
1582}
1583
1584/*** plugin-related methods ***/
1585
1586void wxFrameLayout::FirePluginEvent( cbPluginEvent& event )
1587{
1588 // check state of input capture, before processing the event
1589
1590 if ( mpCaputesInput )
1591 {
1592 bool isInputEvt = TRUE;
1593#if wxCHECK_VERSION(2,3,0)
1594 if ( event.m_eventType != cbEVT_PL_LEFT_DOWN &&
1595 event.m_eventType != cbEVT_PL_LEFT_UP &&
1596 event.m_eventType != cbEVT_PL_RIGHT_DOWN &&
1597 event.m_eventType != cbEVT_PL_RIGHT_UP &&
1598 event.m_eventType != cbEVT_PL_MOTION )
1599 isInputEvt = FALSE;
1600#else
1601 switch ( event.m_eventType )
1602 {
1603 case cbEVT_PL_LEFT_DOWN : break;
1604 case cbEVT_PL_LEFT_UP : break;
1605 case cbEVT_PL_RIGHT_DOWN : break;
1606 case cbEVT_PL_RIGHT_UP : break;
1607 case cbEVT_PL_MOTION : break;
1608
1609 default : isInputEvt = FALSE; break;
1610 }
1611#endif // #if wxCHECK_VERSION(2,3,0)
1612
1613 if ( isInputEvt )
1614 {
1615 mpCaputesInput->ProcessEvent( event );
1616 return;
1617 }
1618 }
1619
1620 GetTopPlugin().ProcessEvent( event );
1621}
1622
1623void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase* pPlugin )
1624{
1625 // cannot capture events for more than one plugin at a time
1626 wxASSERT( mpCaputesInput == NULL );
1627
1628 mpCaputesInput = pPlugin;
1629
1630}
1631
1632void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase* pPlugin )
1633{
1634 // events should be captured first
1635 wxASSERT( mpCaputesInput != NULL );
1636
1637 mpCaputesInput = NULL;
1638}
1639
1640void wxFrameLayout::CaptureEventsForPane( cbDockPane* toPane )
1641{
1642 // cannot capture events twice (without releasing)
1643 wxASSERT( mpPaneInFocus == NULL );
1644
1645 mpFrame->CaptureMouse();
1646
1647 mpPaneInFocus = toPane;
1648}
1649
1650void wxFrameLayout::ReleaseEventsFromPane( cbDockPane* fromPane )
1651{
1652 // cannot release events without capturing them
1653 wxASSERT( mpPaneInFocus != NULL );
1654
1655 mpFrame->ReleaseMouse();
1656
1657 mpPaneInFocus = NULL;
1658}
1659
1660cbPluginBase& wxFrameLayout::GetTopPlugin()
1661{
1662 if ( !mpTopPlugin )
1663
1664 PushDefaultPlugins(); // automatic configuration
1665
1666 return *mpTopPlugin;
1667}
1668
1669void wxFrameLayout::SetTopPlugin( cbPluginBase* pPlugin )
1670{
1671 mpTopPlugin = pPlugin;
1672}
1673
1674bool wxFrameLayout::HasTopPlugin()
1675{
1676 return ( mpTopPlugin != NULL );
1677}
1678
1679void wxFrameLayout::PushPlugin( cbPluginBase* pPlugin )
1680{
1681 if ( !mpTopPlugin )
1682
1683 mpTopPlugin = pPlugin;
1684 else
1685 {
1686 pPlugin->SetNextHandler( mpTopPlugin );
1687
1688 mpTopPlugin->SetPreviousHandler( pPlugin );
1689
1690 mpTopPlugin = pPlugin;
1691 }
1692
1693 mpTopPlugin->OnInitPlugin(); // notification
1694}
1695
1696void wxFrameLayout::PopPlugin()
1697{
1698 wxASSERT( mpTopPlugin ); // DBG:: at least one plugin should be present
1699
1700 cbPluginBase* pPopped = mpTopPlugin;
1701
1702 mpTopPlugin = (cbPluginBase*)mpTopPlugin->GetNextHandler();
1703
1704 delete pPopped;
1705}
1706
1707void wxFrameLayout::PopAllPlugins()
1708{
1709 while( mpTopPlugin ) PopPlugin();
1710}
1711
1712void wxFrameLayout::PushDefaultPlugins()
1713{
1714 // FIXME:: to much of the stuff for the default...
1715
1716 AddPlugin( CLASSINFO( cbRowLayoutPlugin ) );
1717 AddPlugin( CLASSINFO( cbBarDragPlugin ) );
1718 AddPlugin( CLASSINFO( cbPaneDrawPlugin ) );
1719}
1720
1721void wxFrameLayout::AddPlugin( wxClassInfo* pPlInfo, int paneMask )
1722{
1723 if ( FindPlugin ( pPlInfo ) ) return; // same type of plugin cannot be added twice
1724
1725 cbPluginBase* pObj = (cbPluginBase*)pPlInfo->CreateObject();
1726
1727 wxASSERT(pObj); // DBG:: plugin's class should be dynamic
1728
1729 pObj->mPaneMask = paneMask;
1730 pObj->mpLayout = this;
1731
1732 PushPlugin( pObj );
1733}
1734
1735void wxFrameLayout::AddPluginBefore( wxClassInfo* pNextPlInfo, wxClassInfo* pPlInfo,
1736 int paneMask )
1737{
1738 wxASSERT( pNextPlInfo != pPlInfo ); // DBG:: no sence
1739
1740 cbPluginBase* pNextPl = FindPlugin( pNextPlInfo );
1741
1742 if ( !pNextPl )
1743 {
1744 AddPlugin( pPlInfo, paneMask );
1745
1746 return;
1747 }
1748
1749 // remove existing one if present
1750
1751 cbPluginBase* pExistingPl = FindPlugin( pPlInfo );
1752
1753 if ( pExistingPl ) RemovePlugin( pPlInfo );
1754
1755 // create an instance
1756
1757 cbPluginBase* pNewPl = (cbPluginBase*)pPlInfo->CreateObject();
1758
1759 wxASSERT(pNewPl); // DBG:: plugin's class should be dynamic
1760
1761 // insert it to the chain
1762
1763 if ( pNextPl->GetPreviousHandler() )
1764
1765 pNextPl->GetPreviousHandler()->SetNextHandler( pNewPl );
1766 else
1767 mpTopPlugin = pNewPl;
1768
1769 pNewPl->SetNextHandler( pNextPl );
1770
1771 pNewPl->SetPreviousHandler( pNextPl->GetPreviousHandler() );
1772
1773 pNextPl->SetPreviousHandler( pNewPl );
1774
1775 // set it up
1776
1777 pNewPl->mPaneMask = paneMask;
1778 pNewPl->mpLayout = this;
1779
1780 pNewPl->OnInitPlugin();
1781}
1782
1783void wxFrameLayout::RemovePlugin( wxClassInfo* pPlInfo )
1784{
1785 cbPluginBase* pPlugin = FindPlugin( pPlInfo );
1786
1787 if ( !pPlugin ) return; // it's OK to remove not-existing plugin ;-)
1788
1789 if ( pPlugin->GetPreviousHandler() == NULL )
1790
1791 mpTopPlugin = (cbPluginBase*)pPlugin->GetNextHandler();
1792
1793 delete pPlugin;
1794}
1795
1796cbPluginBase* wxFrameLayout::FindPlugin( wxClassInfo* pPlInfo )
1797{
1798 cbPluginBase *pCur = mpTopPlugin;
1799
1800 while( pCur )
1801 {
1802 // NOTE:: it might appear useful matching plugin
1803 // classes "polymorphically":
1804
1805 if ( pCur->GetClassInfo()->IsKindOf( pPlInfo ) )
1806
1807 return pCur;
1808
1809 pCur = (cbPluginBase*)pCur->GetNextHandler();
1810 }
1811
1812 return NULL;
1813}
1814
1815/***** Implementation for class cbUpdateMgrData *****/
1816
1817IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData, wxObject )
1818
1819cbUpdateMgrData::cbUpdateMgrData()
1820
1821 : mPrevBounds( -1,-1,0,0 ),
1822 mIsDirty( TRUE ) // inidicate initial change
1823{}
1824
1825void cbUpdateMgrData::StoreItemState( const wxRect& boundsInParent )
1826{
1827 mPrevBounds = boundsInParent;
1828}
1829
1830void cbUpdateMgrData::SetDirty( bool isDirty )
1831{
1832 mIsDirty = isDirty;
1833}
1834
1835void cbUpdateMgrData::SetCustomData( wxObject* pCustomData )
1836{
1837 mpCustomData = pCustomData;
1838}
1839
1840/***** Implementation for class cbDockPane *****/
1841
1842void wxBarIterator::Reset()
1843{
1844 mpRow = ( mpRows->Count() ) ? (*mpRows)[0] : NULL;
1845 mpBar = NULL;
1846}
1847
1848wxBarIterator::wxBarIterator( RowArrayT& rows )
1849
1850 : mpRows( &rows ),
1851 mpRow ( NULL ),
1852 mpBar ( NULL )
1853{
1854 Reset();
1855}
1856
1857bool wxBarIterator::Next()
1858{
1859 if ( mpRow )
1860 {
1861 if ( mpBar )
1862 mpBar = mpBar->mpNext;
1863 else
1864 {
1865 if ( mpRow->mBars.GetCount() == 0 )
1866 {
1867 return FALSE;
1868 }
1869
1870 mpBar = mpRow->mBars[0];
1871 }
1872
1873 if ( !mpBar )
1874 {
1875 // skip to the next row
1876
1877 mpRow = mpRow->mpNext;
1878
1879 if ( mpRow )
1880
1881 mpBar = mpRow->mBars[0];
1882 else
1883 return FALSE;
1884 }
1885
1886 return TRUE;
1887 }
1888 else
1889 return FALSE;
1890}
1891
1892cbBarInfo& wxBarIterator::BarInfo()
1893{
1894 return *mpBar;
1895}
1896
1897cbRowInfo& wxBarIterator::RowInfo()
1898{
1899 return *mpRow;
1900}
1901
1902/***** Implementation for class cbBarDimHandlerBase *****/
1903
1904IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase, wxObject )
1905
1906cbBarDimHandlerBase::cbBarDimHandlerBase()
1907 : mRefCount(0)
1908{}
1909
1910void cbBarDimHandlerBase::AddRef()
1911{
1912 ++mRefCount;
1913}
1914
1915void cbBarDimHandlerBase::RemoveRef()
1916{
1917 if ( --mRefCount <= 0 ) delete this;
1918}
1919
1920/***** Implementation for class cbDimInfo *****/
1921
1922IMPLEMENT_DYNAMIC_CLASS( cbDimInfo, wxObject )
1923
1924cbDimInfo::cbDimInfo()
1925
1926 : mVertGap ( 0 ),
1927 mHorizGap( 0 ),
1928
1929 mIsFixed(TRUE),
1930 mpHandler( NULL )
1931{
1932 for( size_t i = 0; i != MAX_BAR_STATES; ++i )
1933 {
1934 mSizes[i].x = 20;
1935 mSizes[i].y = 20;
1936
1937 mBounds[i] = wxRect( -1,-1,-1,-1 );
1938 }
1939}
1940
1941cbDimInfo::cbDimInfo( cbBarDimHandlerBase* pDimHandler,
1942 bool isFixed )
1943
1944 : mVertGap ( 0 ),
1945 mHorizGap( 0 ),
1946 mIsFixed ( isFixed ),
1947
1948 mpHandler( pDimHandler )
1949{
1950 if ( mpHandler )
1951 {
1952 // int vtad = *((int*)mpHandler);
1953 mpHandler->AddRef();
1954 }
1955
1956 for( size_t i = 0; i != MAX_BAR_STATES; ++i )
1957 {
1958 mSizes[i].x = -1;
1959 mSizes[i].y = -1;
1960
1961 mBounds[i] = wxRect( -1,-1,-1,-1 );
1962 }
1963}
1964
1965cbDimInfo::cbDimInfo( int dh_x, int dh_y,
1966 int dv_x, int dv_y,
1967 int f_x, int f_y,
1968
1969 bool isFixed,
1970 int horizGap,
1971 int vertGap,
1972
1973 cbBarDimHandlerBase* pDimHandler
1974 )
1975 : mVertGap ( vertGap ),
1976 mHorizGap ( horizGap ),
1977 mIsFixed ( isFixed ),
1978 mpHandler( pDimHandler )
1979{
1980 if ( mpHandler )
1981 {
1982 // int vtad = *((int*)mpHandler);
1983 mpHandler->AddRef();
1984 }
1985
1986 mSizes[wxCBAR_DOCKED_HORIZONTALLY].x = dh_x;
1987 mSizes[wxCBAR_DOCKED_HORIZONTALLY].y = dh_y;
1988 mSizes[wxCBAR_DOCKED_VERTICALLY ].x = dv_x;
1989 mSizes[wxCBAR_DOCKED_VERTICALLY ].y = dv_y;
1990 mSizes[wxCBAR_FLOATING ].x = f_x;
1991 mSizes[wxCBAR_FLOATING ].y = f_y;
1992
1993 for( size_t i = 0; i != MAX_BAR_STATES; ++i )
1994 mBounds[i] = wxRect( -1,-1,-1,-1 );
1995}
1996
1997cbDimInfo::cbDimInfo( int x, int y,
1998 bool isFixed, int gap,
1999 cbBarDimHandlerBase* pDimHandler)
2000 : mVertGap ( gap ),
2001 mHorizGap ( gap ),
2002 mIsFixed ( isFixed ),
2003 mpHandler( pDimHandler )
2004{
2005 if ( mpHandler )
2006 {
2007 // int vtad = *((int*)mpHandler);
2008 mpHandler->AddRef();
2009 }
2010
2011 mSizes[wxCBAR_DOCKED_HORIZONTALLY].x = x;
2012 mSizes[wxCBAR_DOCKED_HORIZONTALLY].y = y;
2013 mSizes[wxCBAR_DOCKED_VERTICALLY ].x = x;
2014 mSizes[wxCBAR_DOCKED_VERTICALLY ].y = y;
2015 mSizes[wxCBAR_FLOATING ].x = x;
2016 mSizes[wxCBAR_FLOATING ].y = y;
2017
2018 for( size_t i = 0; i != MAX_BAR_STATES; ++i )
2019 mBounds[i] = wxRect( -1,-1,-1,-1 );
2020}
2021
2022cbDimInfo::~cbDimInfo()
2023{
2024 if ( mpHandler )
2025
2026 mpHandler->RemoveRef();
2027}
2028
2029const cbDimInfo& cbDimInfo::operator=( const cbDimInfo& other )
2030{
2031 if ( this == &other ) return *this;
2032
2033 for( int i = 0; i != MAX_BAR_STATES; ++i )
2034
2035 mSizes[i] = other.mSizes[i];
2036
2037 mIsFixed = other.mIsFixed;
2038 mpHandler = other.mpHandler;
2039
2040 mVertGap = other.mVertGap;
2041 mHorizGap = other.mHorizGap;
2042
2043 if ( mpHandler )
2044
2045 mpHandler->AddRef();
2046
2047 return *this;
2048}
2049
2050/***** Implementation for structure cbCommonPaneProperties *****/
2051
2052IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties, wxObject )
2053
2054cbCommonPaneProperties::cbCommonPaneProperties(void)
2055
2056 : mRealTimeUpdatesOn ( TRUE ),
2057 mOutOfPaneDragOn ( TRUE ),
2058 mExactDockPredictionOn( FALSE ),
2059 mNonDestructFirctionOn( FALSE ),
2060 mShow3DPaneBorderOn ( TRUE ),
2061 mBarFloatingOn ( FALSE ),
2062 mRowProportionsOn ( FALSE ),
2063 mColProportionsOn ( TRUE ),
2064 mBarCollapseIconsOn ( FALSE ),
2065 mBarDragHintsOn ( FALSE ),
2066
2067 mMinCBarDim( 16, 16 ),
2068 mResizeHandleSize( 4 )
2069{}
2070
2071/***** Implementation for class cbRowInfo *****/
2072
2073IMPLEMENT_DYNAMIC_CLASS( cbRowInfo, wxObject )
2074
2075cbRowInfo::cbRowInfo(void)
2076
2077 : mNotFixedBarsCnt( FALSE ),
2078 mpNext ( NULL ),
2079 mpPrev ( NULL ),
2080 mpExpandedBar ( NULL )
2081{}
2082
2083cbRowInfo::~cbRowInfo()
2084{
2085 // nothing! all bars are removed using global bar
2086 // list in wxFrameLayout class
2087}
2088
2089/***** Implementation for class cbBarInfo *****/
2090
2091IMPLEMENT_DYNAMIC_CLASS( cbBarInfo, wxObject )
2092
2093cbBarInfo::cbBarInfo(void)
2094
2095 : mpRow( NULL ),
2096
2097 mpNext( NULL ),
2098 mpPrev( NULL )
2099{}
2100
2101cbBarInfo::~cbBarInfo()
2102{
2103 // nothing
2104}
2105
2106/***** Implementation for class cbDockPane *****/
2107
2108IMPLEMENT_DYNAMIC_CLASS( cbDockPane, wxObject )
2109
2110// FIXME:: how to eliminate these cut&pasted constructors?
2111
2112cbDockPane::cbDockPane(void)
2113 : mLeftMargin ( 1 ),
2114 mRightMargin ( 1 ),
2115 mTopMargin ( 1 ),
2116 mBottomMargin( 1 ),
2117 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2118 // since the real dimensions of the pane may not
2119 // be known, while inserting bars initially
2120 mPaneHeight( 32768 ),
2121 mAlignment ( -1 ),
2122 mpLayout ( 0 ),
2123 mpStoredRow( NULL )
2124{}
2125
2126cbDockPane::cbDockPane( int alignment, wxFrameLayout* pPanel )
2127
2128 : mLeftMargin ( 1 ),
2129 mRightMargin ( 1 ),
2130 mTopMargin ( 1 ),
2131 mBottomMargin( 1 ),
2132 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2133 // since the real dimensions of the pane may not
2134 // be known, while inserting bars initially
2135 mPaneHeight( 32768 ),
2136 mAlignment ( alignment ),
2137 mpLayout ( pPanel ),
2138 mpStoredRow( NULL )
2139{}
2140
2141cbDockPane::~cbDockPane()
2142{
2143 for( size_t i = 0; i != mRows.Count(); ++i )
2144
2145 delete mRows[i];
2146
2147 mRowShapeData.DeleteContents( TRUE );
2148
2149 // NOTE:: control bar infromation structures are cleaned-up
2150 // in wxFrameLayout's destructor, using global control-bar list
2151}
2152
2153void cbDockPane::SetMargins( int top, int bottom, int left, int right )
2154{
2155 mTopMargin = top;
2156 mBottomMargin = bottom;
2157 mLeftMargin = left;
2158 mRightMargin = right;
2159}
2160
2161/*** helpers of cbDockPane ***/
2162
2163void cbDockPane::PaintBarDecorations( cbBarInfo* pBar, wxDC& dc )
2164{
2165 cbDrawBarDecorEvent evt( pBar, dc, this );
2166
2167 mpLayout->FirePluginEvent( evt );
2168}
2169
2170void cbDockPane::PaintBarHandles( cbBarInfo* pBar, wxDC& dc )
2171{
2172 cbDrawBarHandlesEvent evt( pBar, dc, this );
2173
2174 mpLayout->FirePluginEvent( evt );
2175}
2176
2177void cbDockPane::PaintBar( cbBarInfo* pBar, wxDC& dc )
2178{
2179 PaintBarDecorations( pBar, dc );
2180 PaintBarHandles( pBar, dc );
2181}
2182
2183void cbDockPane::PaintRowHandles( cbRowInfo* pRow, wxDC& dc )
2184{
2185 cbDrawRowHandlesEvent evt( pRow, dc, this );
2186
2187 mpLayout->FirePluginEvent( evt );
2188
2189 cbDrawRowDecorEvent evt1( pRow, dc, this );
2190
2191 mpLayout->FirePluginEvent( evt1 );
2192}
2193
2194void cbDockPane::PaintRowBackground ( cbRowInfo* pRow, wxDC& dc )
2195{
2196 cbDrawRowBkGroundEvent evt( pRow, dc, this );
2197
2198 mpLayout->FirePluginEvent( evt );
2199}
2200
2201void cbDockPane::PaintRowDecorations( cbRowInfo* pRow, wxDC& dc )
2202{
2203 size_t i = 0;
2204
2205 // decorations first
2206 for( i = 0; i != pRow->mBars.Count(); ++i )
2207
2208 PaintBarDecorations( pRow->mBars[i], dc );
2209
2210 // then handles if present
2211 for( i = 0; i != pRow->mBars.Count(); ++i )
2212
2213 PaintBarHandles( pRow->mBars[i], dc );
2214}
2215
2216void cbDockPane::PaintRow( cbRowInfo* pRow, wxDC& dc )
2217{
2218 PaintRowBackground ( pRow, dc );
2219 PaintRowDecorations( pRow, dc );
2220 PaintRowHandles ( pRow, dc );
2221}
2222
2223void cbDockPane::PaintPaneBackground( wxDC& dc )
2224{
2225 cbDrawPaneBkGroundEvent evt( dc, this );
2226
2227 mpLayout->FirePluginEvent( evt );
2228}
2229
2230void cbDockPane::PaintPaneDecorations( wxDC& dc )
2231{
2232 cbDrawPaneDecorEvent evt( dc, this );
2233
2234 mpLayout->FirePluginEvent( evt );
2235}
2236
2237void cbDockPane::PaintPane( wxDC& dc )
2238{
2239 PaintPaneBackground( dc );
2240
2241 size_t i = 0;
2242
2243 // first decorations
2244 for( i = 0; i != mRows.Count(); ++i )
2245 {
2246 PaintRowBackground( mRows[i], dc );
2247 PaintRowDecorations( mRows[i], dc );
2248 }
2249
2250 // than handles
2251 for( i = 0; i != mRows.Count(); ++i )
2252
2253 PaintRowHandles( mRows[i], dc );
2254
2255 // and finally
2256 PaintPaneDecorations( dc );
2257}
2258
2259void cbDockPane::SizeBar( cbBarInfo* pBar )
2260{
2261 cbSizeBarWndEvent evt( pBar, this );
2262
2263 mpLayout->FirePluginEvent( evt );
2264 return;
2265}
2266
2267void cbDockPane::SizeRowObjects( cbRowInfo* pRow )
2268{
2269 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2270
2271 SizeBar( pRow->mBars[i] );
2272}
2273
2274void cbDockPane::SizePaneObjects()
2275{
2276 for( size_t i = 0; i != mRows.Count(); ++i )
2277
2278 SizeRowObjects( mRows[i] );
2279}
2280
2281wxDC* cbDockPane::StartDrawInArea( const wxRect& area )
2282{
2283 wxDC* pDc = 0;
2284
2285 cbStartDrawInAreaEvent evt( area, &pDc, this );
2286
2287 mpLayout->FirePluginEvent( evt );
2288
2289 return pDc;
2290}
2291
2292void cbDockPane::FinishDrawInArea( const wxRect& area )
2293{
2294 cbFinishDrawInAreaEvent evt( area, this );
2295
2296 mpLayout->FirePluginEvent( evt );
2297}
2298
2299bool cbDockPane::IsFixedSize( cbBarInfo* pInfo )
2300{
2301 return ( pInfo->mDimInfo.mIsFixed );
2302}
2303
2304int cbDockPane::GetNotFixedBarsCount( cbRowInfo* pRow )
2305{
2306 int cnt = 0;
2307
2308 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2309
2310 if ( !pRow->mBars[i]->IsFixed() ) ++cnt;
2311
2312 return cnt;
2313}
2314
2315void cbDockPane::RemoveBar( cbBarInfo* pBar )
2316{
2317 bool needsRestoring = mProps.mNonDestructFirctionOn &&
2318 mpStoredRow == pBar->mpRow;
2319
2320 cbRemoveBarEvent evt( pBar, this );
2321
2322 mpLayout->FirePluginEvent( evt );
2323
2324 if ( needsRestoring )
2325 {
2326 SetRowShapeData( mpStoredRow, &mRowShapeData );
2327
2328 mpStoredRow = NULL;
2329 }
2330}
2331
2332void cbDockPane::SyncRowFlags( cbRowInfo* pRow )
2333{
2334 // setup mHasOnlyFixedBars flag for the row information
2335 pRow->mHasOnlyFixedBars = TRUE;
2336
2337 pRow->mNotFixedBarsCnt = 0;
2338
2339 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2340 {
2341 cbBarInfo& bar = *pRow->mBars[i];
2342
2343 bar.mpRow = pRow;
2344
2345 if ( !bar.IsFixed() )
2346 {
2347 pRow->mHasOnlyFixedBars = FALSE;
2348 ++pRow->mNotFixedBarsCnt;
2349 }
2350 }
2351}
2352
2353void cbDockPane::FrameToPane( int* x, int* y )
2354{
2355 *x -= mLeftMargin;
2356 *y -= mTopMargin;
2357
2358 if ( mAlignment == FL_ALIGN_TOP ||
2359 mAlignment == FL_ALIGN_BOTTOM
2360 )
2361 {
2362 *x -= mBoundsInParent.x;
2363 *y -= mBoundsInParent.y;
2364 }
2365 else
2366 {
2367 int rx = *x, ry = *y;
2368
2369 *x = ry - mBoundsInParent.y;
2370
2371 *y = rx - mBoundsInParent.x;
2372 }
2373}
2374
2375void cbDockPane::PaneToFrame( int* x, int* y )
2376{
2377 if ( mAlignment == FL_ALIGN_TOP ||
2378 mAlignment == FL_ALIGN_BOTTOM
2379 )
2380 {
2381 *x += mBoundsInParent.x;
2382 *y += mBoundsInParent.y;
2383 }
2384 else
2385 {
2386 int rx = *x, ry = *y;
2387
2388 *x = ry + mBoundsInParent.x;
2389
2390 *y = mBoundsInParent.y + rx;
2391 }
2392
2393 *x += mLeftMargin;
2394 *y += mTopMargin;
2395}
2396
2397void cbDockPane::FrameToPane( wxRect* pRect )
2398{
2399 wxPoint upperLeft ( pRect->x, pRect->y );
2400 wxPoint lowerRight( pRect->x + pRect->width,
2401 pRect->y + pRect->height );
2402
2403 FrameToPane( &upperLeft.x, &upperLeft.y );
2404 FrameToPane( &lowerRight.x, &lowerRight.y );
2405
2406 pRect->x = wxMin(upperLeft.x,lowerRight.x);
2407 pRect->y = wxMin(upperLeft.y,lowerRight.y);
2408
2409 pRect->width = abs( lowerRight.x - upperLeft.x );
2410 pRect->height = abs( lowerRight.y - upperLeft.y );
2411}
2412
2413void cbDockPane::PaneToFrame( wxRect* pRect )
2414{
2415 wxPoint upperLeft ( pRect->x, pRect->y );
2416 wxPoint lowerRight( pRect->x + pRect->width,
2417 pRect->y + pRect->height );
2418
2419 PaneToFrame( &upperLeft.x, &upperLeft.y );
2420 PaneToFrame( &lowerRight.x, &lowerRight.y );
2421
2422 //wxRect newRect = wxRect( upperLeft, lowerRight );
2423
2424 pRect->x = wxMin(upperLeft.x,lowerRight.x);
2425 pRect->y = wxMin(upperLeft.y,lowerRight.y);
2426
2427 pRect->width = abs( lowerRight.x - upperLeft.x );
2428 pRect->height = abs( lowerRight.y - upperLeft.y );
2429}
2430
2431int cbDockPane::GetRowAt( int paneY )
2432{
2433 if ( paneY < 0 ) return -1;
2434
2435 int curY = 0;
2436
2437 size_t i = 0;
2438
2439 for( ; i != mRows.Count(); ++i )
2440 {
2441 int rowHeight = mRows[i]->mRowHeight;
2442
2443 int third = rowHeight/3;
2444
2445 if ( paneY >= curY && paneY < curY + third )
2446 return i-1;
2447
2448 if ( paneY >= curY + third && paneY < curY + rowHeight - third )
2449 return i;
2450
2451 curY += rowHeight;
2452 }
2453
2454 return i;
2455}
2456
2457int cbDockPane::GetRowAt( int upperY, int lowerY )
2458{
2459 /*
2460 // OLD STUFF::
2461 int range = lowerY - upperY;
2462 int oneThird = range / 3;
2463
2464 wxNode* pRow = mRows.First();
2465 int row = 0;
2466 int curY = 0;
2467
2468 if ( lowerY <= 0 ) return -1;
2469
2470 while( pRow )
2471 {
2472 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2473
2474 if ( upperY >= curY &&
2475 lowerY < curY ) return row;
2476
2477 if ( upperY <= curY &&
2478 lowerY >= curY &&
2479 curY - upperY >= oneThird ) return row-1;
2480
2481 if ( ( upperY < curY + rowHeight &&
2482 lowerY >= curY + rowHeight &&
2483 curY + rowHeight - lowerY >= oneThird )
2484 )
2485 return row+1;
2486
2487 if ( lowerY <= curY + rowHeight ) return row;
2488
2489 ++row;
2490 curY += rowHeight;
2491 pRow = pRow->Next();
2492 }
2493 */
2494
2495 int mid = upperY + (lowerY - upperY)/2;
2496
2497 if ( mid < 0 ) return -1;
2498
2499 int curY = 0;
2500 size_t i = 0;
2501
2502 for( ; i != mRows.Count(); ++i )
2503 {
2504 int rowHeight = mRows[i]->mRowHeight;
2505
2506 if ( mid >= curY && mid < curY + rowHeight ) return i;
2507
2508 curY += rowHeight;
2509 }
2510
2511 return i;
2512}
2513
2514int cbDockPane::GetRowY( cbRowInfo* pRow )
2515{
2516 int curY = 0;
2517
2518 for( size_t i = 0; i != mRows.Count(); ++i )
2519 {
2520 if ( mRows[i] == pRow ) break;
2521
2522 curY += mRows[i]->mRowHeight;
2523 }
2524
2525 return curY;
2526}
2527
2528bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo* pRow )
2529{
2530 while ( pRow->mpPrev )
2531 {
2532 pRow = pRow->mpPrev;
2533
2534 if ( pRow->mHasOnlyFixedBars )
2535
2536 return TRUE;
2537 }
2538
2539 return FALSE;
2540}
2541
2542bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo* pRow )
2543{
2544 while( pRow->mpNext )
2545 {
2546 pRow = pRow->mpNext;
2547
2548 if ( pRow->mHasOnlyFixedBars )
2549
2550 return TRUE;
2551 }
2552
2553 return FALSE;
2554}
2555
2556bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo* pBar )
2557{
2558 while( pBar->mpPrev )
2559 {
2560 pBar = pBar->mpPrev;
2561
2562 if ( pBar->IsFixed() )
2563
2564 return TRUE;
2565 }
2566
2567 return FALSE;
2568}
2569
2570bool cbDockPane::HasNotFixedBarsRight( cbBarInfo* pBar )
2571{
2572 while( pBar->mpNext )
2573 {
2574 pBar = pBar->mpNext;
2575
2576 if ( pBar->IsFixed() )
2577
2578 return TRUE;
2579 }
2580
2581 return FALSE;
2582}
2583
2584void cbDockPane::CalcLengthRatios( cbRowInfo* pInRow )
2585{
2586 int totalWidth = 0;
2587
2588 size_t i = 0;
2589
2590 // clac current-maximal-total-length of all maximized bars
2591
2592 for( i = 0; i != pInRow->mBars.GetCount(); ++i )
2593 {
2594 cbBarInfo& bar = *pInRow->mBars[i];
2595
2596 if ( !bar.IsFixed() )
2597
2598 totalWidth += bar.mBounds.width;
2599 }
2600
2601 // set up persentages of occupied space for each maximized bar
2602
2603 for( i = 0; i != pInRow->mBars.Count(); ++i )
2604 {
2605 cbBarInfo& bar = *pInRow->mBars[i];
2606
2607 if ( !bar.IsFixed() )
2608
2609 bar.mLenRatio = double(bar.mBounds.width)/double(totalWidth);
2610 }
2611}
2612
2613void cbDockPane::RecalcRowLayout( cbRowInfo* pRow )
2614{
2615 cbLayoutRowEvent evt( pRow, this );
2616
2617 mpLayout->FirePluginEvent( evt );
2618}
2619
2620void cbDockPane::ExpandBar( cbBarInfo* pBar )
2621{
2622 mpLayout->GetUpdatesManager().OnStartChanges();
2623
2624 if ( !pBar->mpRow->mpExpandedBar )
2625 {
2626 // save ratios only when there arent any bars expanded yet
2627
2628 cbArrayFloat& ratios = pBar->mpRow->mSavedRatios;
2629
2630 ratios.Clear();
2631 ratios.Alloc( pBar->mpRow->mNotFixedBarsCnt );
2632
2633 cbBarInfo* pCur = pBar->mpRow->mBars[0];
2634
2635 while( pCur )
2636 {
2637 if ( !pCur->IsFixed() )
2638 {
2639 ratios.Add( 0.0 );
2640 ratios[ ratios.GetCount() - 1 ] = pCur->mLenRatio;
2641 }
2642
2643 pCur = pCur->mpNext;
2644 }
2645 }
2646
2647 cbBarInfo* pCur = pBar->mpRow->mBars[0];
2648
2649 while( pCur )
2650 {
2651 pCur->mLenRatio = 0.0; // minimize the rest
2652
2653 pCur = pCur->mpNext;
2654 }
2655
2656 pBar->mLenRatio = 1.0; // 100%
2657 pBar->mBounds.width = 0;
2658
2659 pBar->mpRow->mpExpandedBar = pBar;
2660
2661 mpLayout->RecalcLayout( FALSE );
2662
2663 mpLayout->GetUpdatesManager().OnFinishChanges();
2664 mpLayout->GetUpdatesManager().UpdateNow();
2665}
2666
2667void cbDockPane::ContractBar( cbBarInfo* pBar )
2668{
2669 mpLayout->GetUpdatesManager().OnStartChanges();
2670
2671 // FIXME: What's the purpose of this???
2672 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2673
2674 // restore ratios which were present before expansion
2675
2676 cbBarInfo* pCur = pBar->mpRow->mBars[0];
2677
2678 cbArrayFloat& ratios = pBar->mpRow->mSavedRatios;
2679
2680 size_t i = 0;
2681
2682 while( pCur )
2683 {
2684 if ( !pCur->IsFixed() )
2685 {
2686 pCur->mLenRatio = ratios[i];
2687 ++i;
2688 }
2689
2690 pCur = pCur->mpNext;
2691 }
2692
2693 ratios.Clear();
2694 ratios.Shrink();
2695
2696 pBar->mpRow->mpExpandedBar = NULL;
2697
2698 mpLayout->RecalcLayout( FALSE );
2699
2700 mpLayout->GetUpdatesManager().OnFinishChanges();
2701 mpLayout->GetUpdatesManager().UpdateNow();
2702}
2703
2704void cbDockPane::InitLinksForRow( cbRowInfo* pRow )
2705{
2706 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2707 {
2708 cbBarInfo& bar = *pRow->mBars[i];
2709
2710 if ( i == 0 )
2711
2712 bar.mpPrev = NULL;
2713 else
2714 bar.mpPrev = pRow->mBars[i-1];
2715
2716 if ( i == pRow->mBars.Count() - 1 )
2717
2718 bar.mpNext = NULL;
2719 else
2720 bar.mpNext = pRow->mBars[i+1];
2721 }
2722}
2723
2724void cbDockPane::InitLinksForRows()
2725{
2726 for( size_t i = 0; i != mRows.Count(); ++i )
2727 {
2728 cbRowInfo& row = *mRows[i];
2729
2730 if ( i == 0 )
2731
2732 row.mpPrev = NULL;
2733 else
2734 row.mpPrev = mRows[i-1];
2735
2736 if ( i == mRows.Count() - 1 )
2737
2738 row.mpNext = NULL;
2739 else
2740 row.mpNext = mRows[i+1];
2741 }
2742}
2743
2744void cbDockPane::DoInsertBar( cbBarInfo* pBar, int rowNo )
2745{
2746 cbRowInfo* pRow = NULL;
2747
2748 if ( rowNo == -1 || rowNo >= (int)mRows.Count() )
2749 {
2750 pRow = new cbRowInfo();
2751
2752 if ( rowNo == -1 && mRows.Count() )
2753
2754 mRows.Insert( pRow, 0 );
2755 else
2756 mRows.Add( pRow );
2757
2758 InitLinksForRows();
2759 }
2760 else
2761 {
2762 pRow = mRows[rowNo];
2763
2764 if ( mProps.mNonDestructFirctionOn == TRUE )
2765 {
2766 // store original shape of the row (before the bar is inserted)
2767
2768 mpStoredRow = pRow;
2769
2770 GetRowShapeData( mpStoredRow, &mRowShapeData );
2771 }
2772 }
2773
2774 if ( pRow->mBars.Count() )
2775
2776 pRow->mpExpandedBar = NULL;
2777
2778 cbInsertBarEvent insEvt( pBar, pRow, this );
2779
2780 mpLayout->FirePluginEvent( insEvt );
2781
2782 mpLayout->GetUpdatesManager().OnRowWillChange( pRow, this );
2783}
2784
2785void cbDockPane::InsertBar( cbBarInfo* pBarInfo, const wxRect& atRect )
2786{
2787 wxRect rect = atRect;
2788 FrameToPane( &rect );
2789
2790 pBarInfo->mBounds.x = rect.x;
2791 pBarInfo->mBounds.width = rect.width;
2792 pBarInfo->mBounds.height = rect.height;
2793
2794 int row = GetRowAt( rect.y, rect.y + rect.height );
2795
2796 DoInsertBar( pBarInfo, row );
2797}
2798
2799void cbDockPane::InsertBar( cbBarInfo* pBar, cbRowInfo* pIntoRow )
2800{
2801 cbInsertBarEvent insEvt( pBar, pIntoRow, this );
2802
2803 mpLayout->FirePluginEvent( insEvt );
2804
2805 mpLayout->GetUpdatesManager().OnRowWillChange( pIntoRow, this );
2806}
2807
2808void cbDockPane::InsertBar( cbBarInfo* pBarInfo )
2809{
2810 // set transient properties
2811
2812 pBarInfo->mpRow = NULL;
2813 pBarInfo->mHasLeftHandle = FALSE;
2814 pBarInfo->mHasRightHandle = FALSE;
2815 pBarInfo->mLenRatio = 0.0;
2816
2817 // set preferred bar dimensions, according to the state in which
2818 // the bar is being inserted
2819
2820 pBarInfo->mBounds.width = pBarInfo->mDimInfo.mSizes[ pBarInfo->mState ].x;
2821 pBarInfo->mBounds.height = pBarInfo->mDimInfo.mSizes[ pBarInfo->mState ].y;
2822
2823 DoInsertBar( pBarInfo, pBarInfo->mRowNo );
2824}
2825
2826void cbDockPane::RemoveRow( cbRowInfo* pRow )
2827{
2828 // first, hide all bar-windows in the removed row
2829 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2830
2831 if ( pRow->mBars[i]->mpBarWnd )
2832
2833 pRow->mBars[i]->mpBarWnd->Show( FALSE );
2834
2835 mRows.Remove( pRow );
2836
2837 pRow->mUMgrData.SetDirty(TRUE);
2838}
2839
2840void cbDockPane::InsertRow( cbRowInfo* pRow, cbRowInfo* pBeforeRow )
2841{
2842 if ( !pBeforeRow )
2843
2844 mRows.Add( pRow );
2845 else
2846 mRows.Insert( pRow, mRows.Index( pBeforeRow ) );
2847
2848 InitLinksForRows();
2849
2850 pRow->mUMgrData.SetDirty(TRUE);
2851
2852 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2853
2854 pRow->mBars[i]->mUMgrData.SetDirty( TRUE );
2855
2856 SyncRowFlags( pRow );
2857}
2858
2859void cbDockPane::SetPaneWidth(int width)
2860{
2861 if ( IsHorizontal() )
2862
2863 mPaneWidth = width - mLeftMargin - mRightMargin;
2864 else
2865 mPaneWidth = width - mTopMargin - mBottomMargin;
2866}
2867
2868
2869void cbDockPane::SetBoundsInParent( const wxRect& rect )
2870{
2871
2872 mBoundsInParent = rect;
2873
2874 // set pane dimensions in local coordinates
2875
2876 if ( IsHorizontal() )
2877 {
2878 mPaneWidth = mBoundsInParent.width - ( mRightMargin + mLeftMargin );
2879 mPaneHeight = mBoundsInParent.height - ( mTopMargin + mBottomMargin );
2880 }
2881 else
2882 {
2883 mPaneWidth = mBoundsInParent.height - ( mTopMargin + mBottomMargin );
2884 mPaneHeight = mBoundsInParent.width - ( mRightMargin + mLeftMargin );
2885 }
2886
2887 // convert bounding rectangles of all pane items into parent frame's coordinates
2888
2889 wxBarIterator i( mRows );
2890
2891 wxRect noMarginsRect = mBoundsInParent;
2892
2893 noMarginsRect.x += mLeftMargin;
2894 noMarginsRect.y += mTopMargin;
2895 noMarginsRect.width -= ( mLeftMargin + mRightMargin );
2896 noMarginsRect.height -= ( mTopMargin + mBottomMargin );
2897
2898 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2899
2900 if ( mBoundsInParent.width < 0 ||
2901 mBoundsInParent.height < 0 )
2902
2903 hide_rect( mBoundsInParent );
2904
2905 if ( noMarginsRect.width < 0 ||
2906 noMarginsRect.height < 0 )
2907
2908 hide_rect( noMarginsRect );
2909
2910 // calculate mBoundsInParent for each item in the pane
2911
2912 while( i.Next() )
2913 {
2914 cbBarInfo& bar = i.BarInfo();
2915
2916 cbRowInfo* pRowInfo = bar.mpRow;
2917
2918 // set up row info, if this is first bar in the row
2919
2920 if ( pRowInfo && bar.mpPrev == NULL )
2921 {
2922 pRowInfo->mBoundsInParent.y = pRowInfo->mRowY;
2923 pRowInfo->mBoundsInParent.x = 0;
2924 pRowInfo->mBoundsInParent.width = mPaneWidth;
2925 pRowInfo->mBoundsInParent.height = pRowInfo->mRowHeight;
2926
2927 PaneToFrame( &pRowInfo->mBoundsInParent );
2928
2929 clip_rect_against_rect( pRowInfo->mBoundsInParent, noMarginsRect );
2930 }
2931
2932 wxRect bounds = bar.mBounds;
2933
2934 // exclude dimensions of handles, when calculating
2935 // bar's bounds in parent (i.e. "visual bounds")
2936
2937 if ( bar.mHasLeftHandle )
2938 {
2939 bounds.x += mProps.mResizeHandleSize;
2940 bounds.width -= mProps.mResizeHandleSize;
2941 }
2942
2943 if ( bar.mHasRightHandle )
2944
2945 bounds.width -= mProps.mResizeHandleSize;
2946
2947 PaneToFrame( &bounds );
2948
2949 clip_rect_against_rect( bounds, noMarginsRect );
2950
2951 bar.mBoundsInParent = bounds;
2952 }
2953}
2954
2955bool cbDockPane::BarPresent( cbBarInfo* pBar )
2956{
2957 wxBarIterator iter( mRows );
2958
2959 while( iter.Next() )
2960
2961 if ( &iter.BarInfo() == pBar ) return TRUE;
2962
2963 return FALSE;
2964}
2965
2966cbRowInfo* cbDockPane::GetRow( int row )
2967{
2968 if ( row >= (int)mRows.Count() ) return NULL;
2969
2970 return mRows[ row ];
2971}
2972
2973int cbDockPane::GetRowIndex( cbRowInfo* pRow )
2974{
2975 for( size_t i = 0; i != mRows.Count(); ++i )
2976 {
2977 if ( mRows[i] == pRow )
2978 return i;
2979 }
2980
2981 int avoidCompilerWarning = 0;
2982 wxASSERT(avoidCompilerWarning); // DBG:: row should be present
2983
2984 return 0;
2985}
2986
2987int cbDockPane::GetPaneHeight()
2988{
2989 // first, recalculate row heights and the Y-positions
2990
2991 cbLayoutRowsEvent evt( this );
2992 mpLayout->FirePluginEvent( evt );
2993
2994 int height = 0;
2995
2996 if ( IsHorizontal() )
2997
2998 height += mTopMargin + mBottomMargin;
2999 else
3000 height += mLeftMargin + mRightMargin;
3001
3002 int count = mRows.Count();
3003
3004 if ( count )
3005
3006 height += mRows[count-1]->mRowY + mRows[count-1]->mRowHeight;
3007
3008 return height;
3009}
3010
3011int cbDockPane::GetAlignment()
3012{
3013 return mAlignment;
3014}
3015
3016bool cbDockPane::MatchesMask( int paneMask )
3017{
3018 int thisMask = 0;
3019
3020 // FIXME:: use array instead of switch()
3021
3022 switch (mAlignment)
3023 {
3024 case FL_ALIGN_TOP : thisMask = FL_ALIGN_TOP_PANE; break;
3025 case FL_ALIGN_BOTTOM : thisMask = FL_ALIGN_BOTTOM_PANE;break;
3026 case FL_ALIGN_LEFT : thisMask = FL_ALIGN_LEFT_PANE; break;
3027 case FL_ALIGN_RIGHT : thisMask = FL_ALIGN_RIGHT_PANE; break;
3028
3029 default:
3030 int avoidCompilerWarning = 0;
3031 wxASSERT(avoidCompilerWarning); // DBG:: bogus alignment type
3032 }
3033
3034 return ( thisMask & paneMask ) != 0;
3035}
3036
3037void cbDockPane::RecalcLayout()
3038{
3039 // first, reposition rows and items vertically
3040
3041 cbLayoutRowsEvent evt( this );
3042 mpLayout->FirePluginEvent( evt );
3043
3044 // then horizontally in each row
3045
3046 for( size_t i = 0; i != mRows.Count(); ++i )
3047
3048 RecalcRowLayout( mRows[i] );
3049}
3050
3051int cbDockPane::GetDockingState()
3052{
3053 if ( mAlignment == FL_ALIGN_TOP ||
3054 mAlignment == FL_ALIGN_BOTTOM )
3055 {
3056 return wxCBAR_DOCKED_HORIZONTALLY;
3057 }
3058 else
3059 return wxCBAR_DOCKED_VERTICALLY;
3060}
3061
3062inline bool cbDockPane::HasPoint( const wxPoint& pos, int x, int y,
3063 int width, int height )
3064{
3065 return ( pos.x >= x &&
3066 pos.y >= y &&
3067 pos.x < x + width &&
3068 pos.y < y + height );
3069}
3070
3071int cbDockPane::HitTestPaneItems( const wxPoint& pos,
3072 cbRowInfo** ppRow,
3073 cbBarInfo** ppBar
3074 )
3075{
3076 (*ppRow) = NULL;
3077 (*ppBar) = NULL;
3078
3079 for( size_t i = 0; i != mRows.Count(); ++i )
3080 {
3081 cbRowInfo& row = *mRows[i];
3082
3083 *ppRow = &row;
3084
3085 // hit-test handles of the row, if present
3086
3087 if ( row.mHasUpperHandle )
3088 {
3089 if ( HasPoint( pos, 0, row.mRowY,
3090 row.mRowWidth, mProps.mResizeHandleSize ) )
3091
3092 return CB_UPPER_ROW_HANDLE_HITTED;
3093 }
3094 else
3095 if ( row.mHasLowerHandle )
3096 {
3097 if ( HasPoint( pos, 0, row.mRowY + row.mRowHeight - mProps.mResizeHandleSize,
3098 row.mRowWidth, mProps.mResizeHandleSize ) )
3099
3100 return CB_LOWER_ROW_HANDLE_HITTED;
3101 }
3102
3103 // hit-test bar handles and bar content
3104
3105 for( size_t k = 0; k != row.mBars.Count(); ++k )
3106 {
3107 cbBarInfo& bar = *row.mBars[k];
3108 wxRect& bounds = bar.mBounds;
3109
3110 *ppBar = &bar;
3111
3112 if ( bar.mHasLeftHandle )
3113 {
3114 if ( HasPoint( pos, bounds.x, bounds.y,
3115 mProps.mResizeHandleSize, bounds.height ) )
3116
3117 return CB_LEFT_BAR_HANDLE_HITTED;
3118 }
3119 else
3120 if ( bar.mHasRightHandle )
3121 {
3122 if ( HasPoint( pos, bounds.x + bounds.width - mProps.mResizeHandleSize, bounds.y,
3123 mProps.mResizeHandleSize, bounds.height ) )
3124
3125 return CB_RIGHT_BAR_HANDLE_HITTED;
3126 }
3127
3128 if ( HasPoint( pos, bounds.x, bounds.y, bounds.width, bounds.height ) )
3129
3130 return CB_BAR_CONTENT_HITTED;
3131
3132 } // hit-test next bar
3133
3134 } // next row
3135
3136 return CB_NO_ITEMS_HITTED;
3137}
3138
3139void cbDockPane::GetBarResizeRange( cbBarInfo* pBar, int* from, int *till,
3140 bool forLeftHandle )
3141{
3142 cbBarInfo* pGivenBar = pBar;
3143
3144 int notFree = 0;
3145
3146 // calc unavailable space from the left
3147
3148 while( pBar->mpPrev )
3149 {
3150 pBar = pBar->mpPrev;
3151
3152 if ( !pBar->IsFixed() ) notFree += mProps.mMinCBarDim.x;
3153 else notFree += pBar->mBounds.width;
3154 }
3155
3156 *from = notFree;
3157
3158 pBar = pGivenBar;
3159
3160 notFree = 0;
3161
3162 // calc unavailable space from the right
3163
3164 while( pBar->mpNext )
3165 {
3166 pBar = pBar->mpNext;
3167
3168 if ( pBar->mBounds.x >= mPaneWidth ) break;
3169
3170 // treat not-fixed bars as minimized
3171
3172 if ( !pBar->IsFixed() )
3173
3174 notFree += mProps.mMinCBarDim.x;
3175 else
3176 {
3177 if ( pBar->mBounds.x + pBar->mBounds.width >= mPaneWidth )
3178 {
3179 notFree += mPaneWidth - pBar->mBounds.x;
3180 break;
3181 }
3182 else
3183 notFree += pBar->mBounds.width;
3184 }
3185
3186 }
3187
3188 *till = mPaneWidth - notFree;
3189
3190 // do not let resizing totally deform the bar itself
3191
3192 if ( forLeftHandle )
3193
3194 (*till) -= mProps.mMinCBarDim.x;
3195 else
3196
3197 (*from) += mProps.mMinCBarDim.x;
3198}
3199
3200int cbDockPane::GetMinimalRowHeight( cbRowInfo* pRow )
3201{
3202 int height = mProps.mMinCBarDim.y;
3203
3204 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
3205
3206 if ( pRow->mBars[i]->IsFixed() )
3207
3208 height = wxMax( height, pRow->mBars[i]->mBounds.height );
3209
3210 if ( pRow->mHasUpperHandle )
3211
3212 height += mProps.mResizeHandleSize;
3213
3214 if ( pRow->mHasLowerHandle )
3215
3216 height += mProps.mResizeHandleSize;
3217
3218 return height;
3219}
3220
3221void cbDockPane::SetRowHeight( cbRowInfo* pRow, int newHeight )
3222{
3223 if ( pRow->mHasUpperHandle )
3224
3225 newHeight -= mProps.mResizeHandleSize;
3226
3227 if ( pRow->mHasLowerHandle )
3228
3229 newHeight -= mProps.mResizeHandleSize;
3230
3231 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
3232
3233 if ( !pRow->mBars[i]->IsFixed() )
3234
3235 pRow->mBars[i]->mBounds.height = newHeight;
3236}
3237
3238void cbDockPane::GetRowResizeRange( cbRowInfo* pRow, int* from, int* till,
3239 bool forUpperHandle )
3240{
3241 cbRowInfo* pGivenRow = pRow;
3242
3243 // calc unavailable space from above
3244
3245 int notFree = 0;
3246
3247 while( pRow->mpPrev )
3248 {
3249 pRow = pRow->mpPrev;
3250
3251 notFree += GetMinimalRowHeight( pRow );
3252
3253 };
3254
3255 *from = notFree;
3256
3257 // allow accupy the client window space by resizing pane rows
3258 if ( mAlignment == FL_ALIGN_BOTTOM )
3259
3260 *from -= mpLayout->GetClientHeight();
3261 else
3262 if ( mAlignment == FL_ALIGN_RIGHT )
3263
3264 *from -= mpLayout->GetClientWidth();
3265
3266 // calc unavailable space from below
3267
3268 pRow = pGivenRow;
3269
3270 notFree = 0;
3271
3272 while( pRow->mpNext )
3273 {
3274 pRow = pRow->mpNext;
3275
3276 notFree += GetMinimalRowHeight( pRow );
3277
3278 }
3279
3280 *till = mPaneHeight - notFree;
3281
3282 // allow adjustinig pane space vs. client window space by resizing pane row heights
3283
3284 if ( mAlignment == FL_ALIGN_TOP )
3285
3286 *till += mpLayout->GetClientHeight();
3287 else
3288 if ( mAlignment == FL_ALIGN_LEFT )
3289
3290 *till += mpLayout->GetClientWidth();
3291
3292 // do not let the resizing of the row totally squeeze the row itself
3293
3294 cbRowInfo& row = *pGivenRow;
3295
3296 if ( forUpperHandle )
3297 {
3298 *till = row.mRowY + row.mRowHeight - GetMinimalRowHeight( pGivenRow );
3299
3300 if ( row.mHasUpperHandle )
3301
3302 *till -= mProps.mResizeHandleSize;
3303 }
3304 else
3305 {
3306 *from += GetMinimalRowHeight( pGivenRow );
3307
3308 if ( row.mHasLowerHandle )
3309
3310 *from -= mProps.mResizeHandleSize;
3311 }
3312}
3313
3314void cbDockPane::ResizeRow( cbRowInfo* pRow, int ofs,
3315 bool forUpperHandle )
3316{
3317 cbResizeRowEvent evt( pRow, ofs, forUpperHandle, this );
3318
3319 mpLayout->FirePluginEvent( evt );
3320}
3321
3322void cbDockPane::ResizeBar( cbBarInfo* pBar, int ofs,
3323 bool forLeftHandle )
3324{
3325 pBar->mpRow->mpExpandedBar = NULL;
3326
3327 mpLayout->GetUpdatesManager().OnStartChanges();
3328
3329 wxRect& bounds = pBar->mBounds;
3330
3331 if ( forLeftHandle )
3332 {
3333 // do not allow bar width become less then minimal
3334 if ( bounds.x + ofs > bounds.x + bounds.width - mProps.mMinCBarDim.x )
3335 {
3336 bounds.width = mProps.mMinCBarDim.x;
3337 bounds.x += ofs;
3338 }
3339 else
3340 {
3341 bounds.x += ofs;
3342 bounds.width -= ofs;
3343 }
3344 }
3345 else
3346 {
3347 // move bar left if necessary
3348 if ( bounds.width + ofs < mProps.mMinCBarDim.x )
3349 {
3350 bounds.x = bounds.x + bounds.width + ofs - mProps.mMinCBarDim.x;
3351 bounds.width = mProps.mMinCBarDim.x;
3352 }
3353 else
3354 // resize right border only
3355 bounds.width += ofs;
3356 }
3357
3358
3359 cbRowInfo* pToRow = pBar->mpRow;
3360
3361 this->RemoveBar( pBar );
3362
3363 InsertBar( pBar, pToRow );
3364
3365 mpLayout->RecalcLayout(FALSE);
3366
3367 mpLayout->GetUpdatesManager().OnFinishChanges();
3368 mpLayout->GetUpdatesManager().UpdateNow();
3369}
3370
3371
3372/*** row/bar resizing related methods ***/
3373
3374void cbDockPane::DrawVertHandle( wxDC& dc, int x, int y, int height )
3375{
3376 int lower = y + height;
3377
3378 dc.SetPen( mpLayout->mLightPen );
3379 dc.DrawLine( x,y, x, lower );
3380
3381 dc.SetPen( mpLayout->mGrayPen );
3382 for( int i = 0; i != mProps.mResizeHandleSize-1; ++i )
3383 {
3384 ++x;
3385 dc.DrawLine( x,y, x, lower );
3386 }
3387
3388 dc.SetPen( mpLayout->mDarkPen );
3389 ++x;
3390 dc.DrawLine( x,y, x, lower );
3391
3392 dc.SetPen( mpLayout->mBlackPen );
3393 ++x;
3394 dc.DrawLine( x,y, x, lower );
3395}
3396
3397void cbDockPane::DrawHorizHandle( wxDC& dc, int x, int y, int width )
3398{
3399 int right = x + width;
3400
3401 dc.SetPen( mpLayout->mLightPen );
3402 dc.DrawLine( x,y, right, y );
3403
3404 dc.SetPen( mpLayout->mGrayPen );
3405
3406 for( int i = 0; i != mProps.mResizeHandleSize-1; ++i )
3407 {
3408 ++y;
3409 dc.DrawLine( x,y, right, y );
3410 }
3411
3412 dc.SetPen( mpLayout->mDarkPen );
3413 dc.DrawLine( x,y, right, ++y );
3414
3415 dc.SetPen( mpLayout->mBlackPen );
3416 dc.DrawLine( x,y, right, ++y );
3417}
3418
3419cbBarInfo* cbDockPane::GetBarInfoByWindow( wxWindow* pBarWnd )
3420{
3421 wxBarIterator i( mRows );
3422
3423 while( i.Next() )
3424
3425 if ( i.BarInfo().mpBarWnd == pBarWnd )
3426
3427 return &i.BarInfo();
3428
3429 return NULL;
3430}
3431
3432void cbDockPane::GetRowShapeData( cbRowInfo* pRow, wxList* pLst )
3433{
3434 pLst->DeleteContents( TRUE );
3435 pLst->Clear();
3436
3437 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
3438 {
3439 cbBarInfo& bar = *pRow->mBars[i];
3440
3441 cbBarShapeData* pData = new cbBarShapeData();
3442
3443 pLst->Append( (wxObject*)pData );
3444
3445 pData->mBounds = bar.mBounds;
3446 pData->mLenRatio = bar.mLenRatio;
3447 }
3448}
3449
3450void cbDockPane::SetRowShapeData( cbRowInfo* pRow, wxList* pLst )
3451{
3452 if ( pLst->First() == NULL ) return;
3453
3454 wxNode* pData = pLst->First();
3455
3456 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
3457 {
3458 wxASSERT( pData ); // DBG::
3459
3460 cbBarInfo& bar = *pRow->mBars[i];;
3461
3462 cbBarShapeData& data = *((cbBarShapeData*)pData->Data());
3463
3464 bar.mBounds = data.mBounds;
3465 bar.mLenRatio = data.mLenRatio;
3466
3467 pData = pData->Next();
3468 }
3469}
3470
3471/***** Implementation for class cbUpdatesManagerBase *****/
3472
3473IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase, wxObject )
3474
3475/***** Implementation for class cbPluginBase *****/
3476
3477IMPLEMENT_ABSTRACT_CLASS( cbPluginBase, wxEvtHandler )
3478
3479cbPluginBase::~cbPluginBase()
3480{
3481 // nothing
3482}
3483
3484bool cbPluginBase::ProcessEvent(wxEvent& event)
3485{
3486 if ( mPaneMask == wxALL_PANES )
3487
3488 return wxEvtHandler::ProcessEvent( event );
3489
3490 // extract mask info. from received event
3491
3492 cbPluginEvent& evt = *( (cbPluginEvent*)&event );
3493
3494 if ( evt.mpPane == 0 &&
3495 mPaneMask == wxALL_PANES )
3496
3497 return wxEvtHandler::ProcessEvent( event );
3498
3499 int mask = 0;
3500
3501 switch ( evt.mpPane->mAlignment )
3502 {
3503 case FL_ALIGN_TOP : mask = FL_ALIGN_TOP_PANE; break;
3504 case FL_ALIGN_BOTTOM : mask = FL_ALIGN_BOTTOM_PANE;break;
3505 case FL_ALIGN_LEFT : mask = FL_ALIGN_LEFT_PANE; break;
3506 case FL_ALIGN_RIGHT : mask = FL_ALIGN_RIGHT_PANE; break;
3507 }
3508
3509 // if event's pane maks matches the plugin's mask
3510
3511 if ( mPaneMask & mask )
3512
3513 return wxEvtHandler::ProcessEvent( event );
3514
3515 // otherwise pass to the next handler if present
3516
3517 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event ) )
3518
3519 return TRUE;
3520 else
3521 return FALSE;
3522}
3523