00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012 #include <wx/slidebar.h>
00013 #include <wx/barholder.h>
00014 #include <wx/util.h>
00015
00016 #include <wx/menu.h>
00017 #include <wx/list.h>
00018 #include <wx/listimpl.cpp>
00019 #include <wx/dynarray.h>
00020 #include <wx/arrimpl.cpp>
00021
00022 using namespace wxUtil;
00023
00024 enum eContextMenu {
00025 IDM_LOCK_BARS = 200,
00026 IDM_ITEMS,
00027 };
00028
00029 #define MINIMUM_HEIGHT 4 // if we are empty, this is our minimum presence
00030
00031 #define STREAM_VERSION wxT("wxSlideBar-Stream-v1.0")
00032
00033
00034
00035
00036
00037 BEGIN_EVENT_TABLE( wxSlideBar, wxWindow )
00038
00039 EVT_CALCULATE_LAYOUT( wxSlideBar::OnCalculateLayout )
00040 EVT_QUERY_LAYOUT_INFO( wxSlideBar::OnQueryLayoutInfo )
00041 EVT_CONTEXT_MENU( wxSlideBar::OnContextMenu )
00042 EVT_MENU( IDM_LOCK_BARS, wxSlideBar::OnLockBars )
00043 EVT_SIZE( wxSlideBar::OnSize )
00044 END_EVENT_TABLE()
00045
00046 DEFINE_EVENT_TYPE( wxEVT_SLIDEBAR_SIZE_CHANGED )
00047 DEFINE_EVENT_TYPE( wxEVT_SLIDEBAR_UPDATE_LAYOUT )
00048
00049 IMPLEMENT_DYNAMIC_CLASS( wxSlideBar, wxWindow )
00050
00051 WX_DEFINE_LIST( BarHolderList );
00052 WX_DEFINE_OBJARRAY( BarPlacementArray );
00053
00054
00055
00056
00057
00058 void wxSlideBar::Init() {
00059 areaHeight_ = 0;
00060 areaWidth_ = 0;
00061 mode_ = wxSLIDE_MODE_SIMPLE;
00062 barList_.Clear();
00063 barLock_ = false;
00064 pContextMenu_ = NULL;
00065 }
00066
00067 bool wxSlideBar::Create( wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) {
00068 wxASSERT(parent);
00069
00070 if( !wxWindow::Create( parent, id, pos, size, style | wxCLIP_CHILDREN, name ) ) {
00071 return FALSE;
00072 }
00073 SetBackgroundColour(GetBackgroundColour());
00074
00075 return TRUE;
00076 }
00077
00078 wxSlideBar::~wxSlideBar() {
00079
00080 if( pContextMenu_ ) {
00081 delete pContextMenu_;
00082 pContextMenu_ = NULL;
00083 }
00084 }
00085
00086 void wxSlideBar::OnQueryLayoutInfo( wxQueryLayoutInfoEvent& WXUNUSED(event) ) {
00087
00088 }
00089
00090 void wxSlideBar::OnCalculateLayout( wxCalculateLayoutEvent& event ) {
00091
00092 bool queryMode = false;
00093 if( (event.GetFlags() & wxLAYOUT_QUERY) != 0 ) {
00094 queryMode = true;
00095 }
00096
00097 wxRect areaRect = event.GetRect();
00098
00099
00100 int width = areaRect.GetWidth();
00101 int height = 0;
00102 BarPlacementArray & bpl = CalcBarPlacement( width, &height );
00103 if( !queryMode ) {
00104 applyBarPlacement( bpl );
00105 SetSize( areaRect.GetX(), areaRect.GetY(), areaRect.GetWidth(), height );
00106 }
00107
00108
00109 areaRect.SetY( areaRect.GetY() + height );
00110 areaRect.SetHeight( areaRect.GetHeight() - height );
00111 event.SetRect( areaRect );
00112 }
00113
00114 void wxSlideBar::SetMode( wxSlideBarMode mode ) {
00115
00116 mode_ = mode;
00117 UpdateLayout();
00118 }
00119
00120 wxSlideBarMode wxSlideBar::GetMode() {
00121 return mode_;
00122 }
00123
00124 void wxSlideBar::SetBarLock( bool enable ) {
00125
00126 barLock_ = enable;
00127
00128
00129 for( BarHolderList::Node *node = barList_.GetFirst(); node; node = node->GetNext() ) {
00130
00131 wxBarHolder * pBarHolder = node->GetData();
00132 wxASSERT(pBarHolder);
00133 pBarHolder->ShowGripper( !enable );
00134 }
00135
00136 UpdateLayout();
00137 }
00138
00139 bool wxSlideBar::GetBarLock() {
00140 return barLock_;
00141 }
00142
00143 wxBarHolder * wxSlideBar::AddWindow( wxWindow * pWindow, const wxString & label, unsigned int flags ) {
00144
00145 wxASSERT(pWindow);
00146
00147
00148 wxBarHolder * pBarHolder = new wxBarHolder( this, 0 );
00149 pBarHolder->AddWindow( pWindow, label, flags );
00150 pBarHolder->SetSlideBar( this );
00151 wxString key = pBarHolder->GetLabel();
00152 barList_.Append( key, pBarHolder );
00153 UpdateLayout();
00154
00155 return pBarHolder;
00156 }
00157
00158 void wxSlideBar::UpdateLayout() {
00159
00160 wxCommandEvent e( wxEVT_SLIDEBAR_UPDATE_LAYOUT );
00161 e.SetEventObject( this );
00162 GetEventHandler()->AddPendingEvent( e );
00163
00164
00165
00166
00167
00168
00169
00170 }
00171
00172 void wxSlideBar::DoGetSize( int * x, int * y ) const {
00173 if( x ) *x = areaWidth_;
00174 if( y ) *y = areaHeight_;
00175 }
00176
00177 wxSize wxSlideBar::DoGetBestSize() const {
00178 return GetSize();
00179 }
00180
00181 void wxSlideBar::OnSize( wxSizeEvent &event ) {
00182 int oldHeight = areaHeight_;
00183
00184
00185 wxSize size = event.GetSize();
00186 areaWidth_ = size.GetWidth();
00187 areaHeight_ = size.GetHeight();
00188
00189
00190 if( oldHeight != areaHeight_ ) {
00191
00192 wxCommandEvent e( wxEVT_SLIDEBAR_SIZE_CHANGED );
00193 e.SetEventObject( this );
00194 GetEventHandler()->AddPendingEvent( e );
00195 }
00196 }
00197
00198 void wxSlideBar::OnContextMenu( wxContextMenuEvent &event ) {
00199
00200 createContextMenu();
00201 wxPoint mp = event.GetPosition();
00202 mp = ScreenToClient( mp );
00203 PopupMenu( pContextMenu_, mp );
00204 deleteContextMenu();
00205 }
00206
00207 void wxSlideBar::OnLockBars( wxCommandEvent & WXUNUSED(event) ) {
00208
00209 SetBarLock( GetBarLock() ^ true );
00210 }
00211
00212 void wxSlideBar::OnContextItem( wxCommandEvent &event ) {
00213 int id = event.GetId();
00214
00215
00216 BarHolderList::Node * node = barList_.Item( id - IDM_ITEMS );
00217 wxASSERT(node);
00218 wxBarHolder * pBarHolder = node->GetData();
00219 wxASSERT(pBarHolder);
00220
00221 bool visible = pBarHolder->IsShown();
00222 pBarHolder->Show( visible ^ true );
00223
00224 UpdateLayout();
00225 }
00226
00227 wxBarHolder * wxSlideBar::GetBarHolderAt( BarPlacementArray &barPlacementArray, wxPoint pt ) {
00228
00229 for( unsigned int i=0; i<barPlacementArray.GetCount(); i++ ) {
00230
00231 wxBarPlacement &pl = barPlacementArray.Item( i );
00232 wxBarHolder * pBarHolder = pl.pBarHolder;
00233 wxASSERT(pBarHolder);
00234 wxRect r = pl.placement;
00235 if( r.Inside( pt ) ) {
00236 return pBarHolder;
00237 }
00238 }
00239
00240 return NULL;
00241 }
00242
00243 wxBarHolder * wxSlideBar::GetBarHolderAt( wxPoint pt ) {
00244
00245 for( BarHolderList::Node *node = barList_.GetFirst(); node; node = node->GetNext() ) {
00246
00247 wxBarHolder * pBarHolder = node->GetData();
00248 wxASSERT(pBarHolder);
00249 if( !pBarHolder->IsShown() ) {
00250
00251 continue;
00252 }
00253
00254 wxRect r = pBarHolder->GetRect();
00255 if( r.Inside( pt ) ) {
00256 return pBarHolder;
00257 }
00258 }
00259
00260 return NULL;
00261 }
00262
00263 void wxSlideBar::SwapBarHolders( wxBarHolder * p1, wxBarHolder * p2 ) {
00264
00265 wxASSERT(p1 && p2);
00266 BarHolderList::Node *p1Node = barList_.Find( p1 );
00267 BarHolderList::Node *p2Node = barList_.Find( p2 );
00268 wxASSERT(p1Node && p1Node);
00269 p1Node->SetData( p2 );
00270 p2Node->SetData( p1 );
00271 }
00272
00273 BarPlacementArray & wxSlideBar::CalcBarPlacement( int width, int * pAreaHeight ) {
00274 barPlacementArray_.Clear();
00275 if( width == -1 ) {
00276 width = GetClientSize().x;
00277 }
00278 if( width == 0 ) {
00279 return barPlacementArray_;
00280 }
00281
00282
00283 bool finished = false;
00284 int x = 0, y = 0, rowHeight = 0, rowWidth = width;
00285 BarPlacementArray rowHolders;
00286 for( BarHolderList::Node *node = barList_.GetFirst(); node; ) {
00287
00288 wxBarHolder * pBarHolder = node->GetData();
00289 wxASSERT(pBarHolder);
00290
00291
00292 if( !pBarHolder->IsShown() ) {
00293
00294 node = node->GetNext();
00295 if( !node ) {
00296 finished = true;
00297 }
00298 else
00299 continue;
00300 }
00301
00302
00303 wxSize barSize = pBarHolder->GetBestSize();
00304
00305 wxBarPlacement barPlacement;
00306 barPlacement.pBarHolder = pBarHolder;
00307 wxRect & r = barPlacement.placement;
00308
00309
00310 bool noFit = false;
00311 if( !finished && (x + barSize.GetWidth() <= width || x == 0) ) {
00312
00313 r.SetPosition( wxPoint( x, y ) );
00314 r.SetSize( barSize );
00315 rowHolders.Add( barPlacement );
00316 x += barSize.GetWidth();
00317 node = node->GetNext();
00318 if( !node ) {
00319 finished = true;
00320 }
00321 if( rowHeight < barSize.GetHeight() ) {
00322
00323 rowHeight = barSize.GetHeight();
00324 }
00325 }
00326 else {
00327
00328 noFit = true;
00329 }
00330
00331
00332 if( finished || noFit || (mode_ == wxSLIDE_MODE_SIMPLE) ) {
00333 for( unsigned int c = 0; c<rowHolders.GetCount(); c++ ) {
00334
00335 wxBarPlacement &bp = rowHolders[c];
00336 wxRect & r = bp.placement;
00337 int width = (c == (rowHolders.GetCount()-1) ? (rowWidth - r.GetX()) : r.GetWidth() );
00338 int height = rowHeight;
00339 r.SetSize( wxSize( width, height ) );
00340
00341
00342 barPlacementArray_.Add( bp );
00343 }
00344
00345
00346 y += rowHeight;
00347 x = 0;
00348 rowHeight = 0;
00349 rowWidth = width;
00350 rowHolders.Clear();
00351 }
00352 }
00353
00354
00355 if( y == 0 ) y = MINIMUM_HEIGHT;
00356
00357
00358 if( pAreaHeight ) *pAreaHeight = y;
00359
00360 return barPlacementArray_;
00361 }
00362
00363 bool wxSlideBar::SaveToStream( wxOutputStream &stream ) {
00364
00365
00366 WriteString( stream, STREAM_VERSION );
00367
00368
00369 stream.Write( &mode_, sizeof( mode_ ) );
00370 stream.Write( &barLock_, sizeof( barLock_ ) );
00371
00372
00373 WriteString( stream, wxT("<layout>") );
00374
00375 int barCount = barList_.GetCount();
00376 stream.Write( &barCount, sizeof( barCount ) );
00377 for( BarHolderList::Node *node = barList_.GetFirst(); node; node = node->GetNext() ) {
00378 wxBarHolder * pBarHolder = node->GetData();
00379
00380
00381 WriteString( stream, pBarHolder->GetLabel() );
00382
00383
00384 bool visible = pBarHolder->IsShown();
00385 stream.Write( &visible, sizeof( visible ) );
00386 }
00387
00388 return true;
00389 }
00390
00391 bool wxSlideBar::LoadFromStream( wxInputStream &stream ) {
00392
00393
00394 wxString version = ReadString( stream );
00395 if( version != STREAM_VERSION ) {
00396 return false;
00397 }
00398
00399
00400 stream.Read( &mode_, sizeof( mode_ ) );
00401 bool barLock = false;
00402 stream.Read( &barLock, sizeof( barLock ) );
00403 SetBarLock( barLock );
00404
00405 wxString layoutTag = ReadString( stream );
00406 if( layoutTag == wxT("<layout>") ) {
00407
00408 BarHolderList tmpBarList( wxKEY_STRING );
00409 for( BarHolderList::Node *node = barList_.GetFirst(); node; node = node->GetNext() ) {
00410 wxBarHolder * pBarHolder = node->GetData();
00411 tmpBarList.Append( pBarHolder->GetLabel(), pBarHolder );
00412 }
00413 barList_.Clear();
00414
00415
00416 int barCount = 0;
00417 stream.Read( &barCount, sizeof( barCount ) );
00418 for( int i=0; i<barCount; i++ ) {
00419
00420 wxString name = ReadString( stream );
00421
00422
00423 BarHolderList::Node * node = tmpBarList.Find( name );
00424 if( !node ) {
00425
00426 continue;
00427 }
00428 wxBarHolder * pBarHolder = node->GetData();
00429
00430
00431 bool visible = false;
00432 stream.Read( &visible, sizeof( visible ) );
00433 pBarHolder->Show( visible );
00434
00435
00436 barList_.Append( name, pBarHolder );
00437 }
00438
00439 }
00440
00441 UpdateLayout();
00442
00443 return true;
00444 }
00445
00446 bool wxSlideBar::SaveToXML( const wxString& filename ) {
00447 return true;
00448 }
00449
00450 bool wxSlideBar::LoadFromXML( const wxString& filename ) {
00451 return true;
00452 }
00453
00454
00455
00456 void wxSlideBar::applyBarPlacement( BarPlacementArray & bpl ) {
00457
00458 for( unsigned int i=0; i<bpl.GetCount(); i++ ) {
00459
00460 wxBarPlacement &pl = bpl.Item( i );
00461 wxBarHolder * pBarHolder = pl.pBarHolder;
00462 wxASSERT(pBarHolder);
00463 pBarHolder->Move( pl.placement.GetPosition() );
00464 pBarHolder->SetHeightOverride( pl.placement.GetHeight() );
00465 pBarHolder->SetWidthOverride( pl.placement.GetWidth() );
00466 pBarHolder->UpdateSize();
00467 }
00468 }
00469
00470 void wxSlideBar::createContextMenu() {
00471 wxASSERT(!pContextMenu_);
00472
00473
00474 pContextMenu_ = new wxMenu;
00475
00476
00477 int c = 0;
00478 for( BarHolderList::Node *node = barList_.GetFirst(); node; node = node->GetNext() ) {
00479
00480 wxBarHolder * pBarHolder = node->GetData();
00481 wxASSERT(pBarHolder);
00482 wxString label = pBarHolder->GetLabel();
00483
00484
00485 if( label.Length() > 0 ) {
00486
00487 int itemId = IDM_ITEMS + c;
00488 pContextMenu_->AppendCheckItem( itemId, label );
00489
00490
00491 bool check = pBarHolder->IsShown();
00492 pContextMenu_->Check( itemId, check );
00493 c++;
00494
00495
00496 GetEventHandler()->Connect( itemId, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &wxSlideBar::OnContextItem );
00497 contextIdEnd_ = itemId;
00498 }
00499 }
00500 contextIdStart_ = IDM_ITEMS;
00501
00502
00503 if( c ) {
00504 pContextMenu_->AppendSeparator();
00505 }
00506 pContextMenu_->AppendCheckItem( IDM_LOCK_BARS, wxT("&Lock the bars") );
00507 pContextMenu_->Check( IDM_LOCK_BARS, barLock_ );
00508 }
00509
00510 void wxSlideBar::deleteContextMenu() {
00511 wxASSERT(pContextMenu_);
00512
00513 for( int i=contextIdStart_; i<=contextIdEnd_; i++ ) {
00514 GetEventHandler()->Disconnect( i );
00515 }
00516 delete pContextMenu_;
00517 pContextMenu_ = NULL;
00518 }
00519
00520 void wxSlideBar::refreshBars() {
00521 for( BarHolderList::Node *node = barList_.GetFirst(); node; node = node->GetNext() ) {
00522 wxBarHolder * pBarHolder = node->GetData();
00523 pBarHolder->Refresh();
00524 }
00525 }