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