Audacity  3.0.3
ToolDock.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  ToolDock.cpp
6 
7  Dominic Mazzoni
8  Shane T. Mueller
9  Leland Lucius
10 
11 *******************************************************************//*******************************************************************//**********************************************************************/
23 
24 
25 #include "ToolDock.h"
26 
27 #include <wx/tokenzr.h>
28 
29 // For compilers that support precompilation, includes "wx/wx.h".
30 #include <wx/wxprec.h>
31 
32 #ifndef WX_PRECOMP
33 #include <wx/dcclient.h>
34 #include <wx/defs.h>
35 #include <wx/event.h>
36 #include <wx/gdicmn.h>
37 #include <wx/intl.h>
38 #include <wx/panel.h>
39 #include <wx/settings.h>
40 #include <wx/window.h>
41 #endif /* */
42 
43 #include <algorithm>
44 
45 #include "AColor.h"
46 #include "AllThemeResources.h"
47 #include "ImageManipulation.h"
48 #include "Prefs.h"
49 #include "../widgets/Grabber.h"
50 
53 
55  -> Iterator
56 {
57  auto This = const_cast<ToolBarConfiguration*>(this);
58  return std::find_if(This->begin(), This->end(),
59  [=](const Place &place){
60  return place.pTree->pBar == bar;
61  });
62 }
63 
65  -> std::pair<Forest*, Forest::iterator>
66 {
67  auto findTree = [=](Forest &forest){
68  return std::find_if(forest.begin(), forest.end(),
69  [=](const Tree &tree){ return tree.pBar == bar; });
70  };
71 
72  auto iter1 = findTree(mForest);
73  if (iter1 != mForest.end())
74  return { &mForest, iter1 };
75 
76  Forest::iterator result;
77  auto iter = std::find_if(begin(), end(),
78  [&](const Place &place){
79  auto &children = place.pTree->children;
80  return (result = findTree(children)) != children.end();
81  }
82  );
83  if (iter != end())
84  return { &iter->pTree->children, result };
85 
86  return { nullptr, Forest::iterator{} };
87 }
88 
89 auto ToolBarConfiguration::Find(const ToolBar *bar) const -> Position
90 {
91  auto iter = FindPlace(bar);
92  if (iter == end())
93  return UnspecifiedPosition;
94  else
95  return iter->position;
96 }
97 
99 {
100  if (position == UnspecifiedPosition) {
101  // Add at the "end" of the layout
102  // bottommost and rightmost
103  Forest *pForest = &mForest;
104  while (!pForest->empty())
105  pForest = &pForest->back().children;
106  pForest->push_back( Tree {} );
107  pForest->back().pBar = bar;
108  }
109  else {
110  // Insert at what depth?
111  auto pForest = &mForest;
112  if (position.rightOf) {
113  const auto parent = FindPlace(position.rightOf);
114  if (parent != end())
115  // Insert among children of some node
116  pForest = &parent->pTree->children;
117  }
118  else {
119  // Insert a new root in the top forest
120  }
121 
122  // Insert at what breadth?
123  const auto begin = pForest->begin();
124  auto iter = begin;
125  const auto end = pForest->end();
126  bool adopt = false;
127 
128  if (position.below) {
129  iter = std::find_if(begin, end,
130  [=](const Tree &tree){ return tree.pBar == position.below; }
131  );
132  if (iter != end) {
133  ++iter;
134  if (iter != end)
135  adopt = true;
136  }
137  else
138  // Not found, default to topmost
139  iter = begin;
140  }
141  else
142  // No previous sibling specified, so insert as first
143  adopt = (iter != end);
144 
145  // Insert as a leaf, or as an internal node?
146  if (adopt && position.adopt) {
147  // Existing children of parent become grandchildren
148 
149  // Make NEW node
150  Tree tree;
151  tree.pBar = bar;
152 
153  // Do adoption
154  const auto barHeight = bar->GetSize().GetY() + toolbarGap;
155  auto totalHeight = 0;
156  while (iter != pForest->end() &&
157  barHeight >=
158  (totalHeight += (iter->pBar->GetSize().GetY() + toolbarGap))) {
159  tree.children.push_back(Tree{});
160  auto &child = tree.children.back();
161  child.pBar = iter->pBar;
162  child.children.swap(iter->children);
163  iter = pForest->erase(iter);
164  }
165 
166  // Put the node in the tree
167  iter = pForest->insert(iter, Tree{});
168  (*iter).swap(tree);
169  }
170  else
171  // Insert as a leaf
172  pForest->insert(iter, Tree {})->pBar = bar;
173  }
174 }
175 
177  (ToolBar *bar, const std::vector<int> &path)
178 {
179  auto pForest = &mForest;
180  Tree *pTree {};
181 
182  // Guarantee the existence of nodes
183  for (auto ii : path) {
184  Forest::size_type uu = std::max(0, ii);
185  // This may make more than one default-constructed tree, which we
186  // will fill in with some other call to InsertAtPath, or else cleanup
187  // with RemoveNulls
188  pForest->resize(std::max(uu + 1, pForest->size()));
189  pTree = &(*pForest)[uu];
190  pForest = &pTree->children;
191  }
192 
193  if (pTree)
194  pTree->pBar = bar;
195 }
196 
197 void ToolBarConfiguration::Remove(Forest &forest, Forest::iterator iter)
198 {
199  // Reparent all of the children of the deleted node
200  Tree tree;
201  tree.swap(*iter);
202  iter = forest.erase(iter);
203  auto &children = tree.children;
204  auto cIter = children.rbegin(), cEnd = children.rend();
205  while (cIter != cEnd) {
206  iter = forest.insert(iter, Tree{});
207  (*iter).swap(*cIter);
208  ++cIter;
209  }
210 }
211 
213 {
214  auto results = FindPeers(bar);
215  auto pForest = results.first;
216  if (pForest) {
217  // Reparent all of the children of the deleted node
218  auto iter = results.second;
219  wxASSERT(iter->pBar == bar);
220  Remove(*pForest, iter);
221  }
222 }
223 
225 {
226  // Do not assume the bar is absent, though in practice that is always so
227  if (!Contains(bar))
228  Insert(bar);
229 }
230 
232 {
233  // Future: might hide a bar without eliminating it from the configuration
234  Remove(bar);
235 }
236 
238 {
239  auto iter = FindPlace(bar);
240  auto endit = end();
241  if (iter == endit)
242  // not present
243  return true;
244  if (++iter == endit)
245  // Last of all
246  return true;
247  if (bar->GetRect().y != iter->pTree->pBar->GetRect().y)
248  // Next step in preorder traversal is not rightward to a child drawn at
249  // the same height
250  return true;
251  return false;
252 }
253 
255  (ToolBarConfiguration *pConfiguration,
256  Legacy *pLegacy,
257  ToolBar *bar, bool &visible, bool defaultVisible)
258 {
259  bool result = true;
260 
261  // Future: might remember visibility in the configuration, not forgetting
262  // positions of hidden bars.
263  gPrefs->Read( wxT("Show"), &visible, defaultVisible);
264 
265  if (pConfiguration && visible) {
266  int ord;
267  gPrefs->Read( wxT("Order"), &ord, -1 );
268  // Index was written 1-based
269  --ord;
270  if (ord >= ToolBarCount)
271  result = false;
272  else if (ord >= 0)
273  {
274  // Legacy preferences
275  while (pLegacy->bars.size() <= size_t(ord))
276  pLegacy->bars.push_back(nullptr);
277  pLegacy->bars[ord] = bar;
278  }
279  else {
280  wxString strPath;
281  gPrefs->Read( wxT("Path"), &strPath );
282  if (!strPath.empty()) {
283  wxStringTokenizer toker { strPath, wxT(",") };
284  std::vector<int> path;
285  while(toker.HasMoreTokens()) {
286  auto token = toker.GetNextToken();
287  auto ii = wxAtoi(token);
288  path.push_back(ii);
289  }
290  pConfiguration->InsertAtPath(bar, path);
291  }
292  }
293  }
294 
295  return result;
296 }
297 
299 {
300  for (size_t ii = 0; ii < forest.size(); ++ii) {
301  if(forest[ii].pBar == nullptr)
302  Remove(forest, forest.begin() + ii--);
303  }
304 
305  // Now do the same recursively
306  for (auto &tree : forest)
307  RemoveNulls(tree.children);
308 }
309 
311 {
312  // Be sure no nodes contain NULL,
313  // against the case of obsolete preferences, perhaps
315 
316  // Interpret what was saved in old .cfg files under "order"
317  // which specified toolbar configuration simply as a sequence, not a tree
318  ToolBar *prev {};
319  for (auto pBar : legacy.bars) {
320  if (!pBar)
321  continue;
322 
323  Position position{ prev };
324  Insert(pBar, position);
325 
326  prev = pBar;
327  }
328 }
329 
331  (const ToolBarConfiguration *pConfiguration, const ToolBar *bar)
332 {
333  // Assume a path has been set in gPrefs suitable for bar
334  if (pConfiguration) {
335  // Write comma-separated list of numbers specifying position in the tree
336  wxString strPath;
337  const auto cIter = pConfiguration->FindPlace(bar);
338  const auto path = cIter.GetPath();
339  if (!path.empty()) {
340  auto iter = path.begin(), end = path.end();
341  strPath += wxString::Format(wxT("%d"), *iter++);
342  while (iter != end)
343  strPath += wxString::Format(wxT(",%d"), *iter++);
344  }
345  gPrefs->Write(wxT("Path"), strPath);
346 
347  // Remove any legacy configuration info.
348  // Note: this causes Audacity 2.1.2 and earlier to create toolbars
349  // always in default position when reading a .cfg saved by Audacity
350  // 2.1.3 or later
351  gPrefs->DeleteEntry(wxT("Order"));
352  }
353  gPrefs->Write( wxT("Show"), bar->IsVisible() );
354 }
355 
357 
361 
362 //
363 // Custom event
364 //
365 //DEFINE_EVENT_TYPE( EVT_TOOLBAR_FLOAT );
366 
367 BEGIN_EVENT_TABLE( ToolDock, wxPanelWrapper )
368  EVT_GRABBER( wxID_ANY, ToolDock::OnGrabber )
369  EVT_ERASE_BACKGROUND( ToolDock::OnErase )
370  EVT_PAINT( ToolDock::OnPaint )
371  EVT_SIZE( ToolDock::OnSize )
372  EVT_MOUSE_EVENTS( ToolDock::OnMouseEvents )
374 
375 //
376 // Constructor
377 //
378 ToolDock::ToolDock( wxEvtHandler *manager, wxWindow *parent, int dockid ):
379  wxPanelWrapper( parent, dockid, wxDefaultPosition, parent->GetSize() )
380 {
381  SetLabel( XO( "ToolDock" ) );
382  SetName( XO( "ToolDock" ) );
383 
384  // Init
385  mManager = manager;
386  memset(mBars, 0, sizeof(mBars)); // otherwise uninitialized
387  SetBackgroundColour(theTheme.Colour( clrMedium ));
388  SetLayoutDirection(wxLayout_LeftToRight);
389  // Use for testing gaps
390  // SetOwnBackgroundColour( wxColour( 255, 0, 0 ) );
391 }
392 
393 //
394 // Destructor
395 //
397 {
398 }
399 
400 //
401 // Remove the toolbar from our control
402 //
404 {
405  if( mConfiguration.Contains( bar ) )
406  {
407  mConfiguration.Remove( bar );
408  }
409  mBars[ bar->GetId() ] = nullptr;
410 }
411 
412 //
413 // Handle ToolDock events
414 //
415 void ToolDock::Dock( ToolBar *bar, bool deflate, ToolBarConfiguration::Position position )
416 {
417 #ifndef __WXMAC__
418  // Apply the deflate fix only on Mac, else you introduce the opposite bug on others
419  deflate = false;
420 #endif
421 
422  // Adopt the toolbar into our family
423  bar->Reparent( this );
424  mBars[ bar->GetId() ] = bar;
425 
426  // Reset size
427  bar->SetSize(
428  // Undo the expansion that was applied when un-docking
429  bar->GetSize().x - (deflate ? 2 * ToolBarFloatMargin : 0),
430  // Don't need to adjust y the same way.
431  bar->GetDockedSize().y
432  );
433 
434  // Park the NEW bar in the correct berth
435  if (!mConfiguration.Contains(bar) && bar->IsVisible())
436  mConfiguration.Insert( bar, position );
437 
438  // Inform toolbar of change
439  bar->SetDocked( this, false );
440 }
441 
442 // Initial docking of bars
444 {
445  // Add all ordered toolbars
446  for(const auto &place : GetConfiguration()) {
447  auto bar = place.pTree->pBar;
448  this->Dock(bar, false);
449  // Show it -- hidden bars are not (yet) ever saved as part of a
450  // configuration
451  Expose( bar->GetId(), true );
452  }
453  Updated();
454 }
455 
456 // A policy object for the skeleton routine below
458 {
459 public:
460  virtual void ModifySize
461  (ToolBar *,
462  const wxRect &,
465  wxSize &)
466  {
467  }
468 
469  virtual void Visit
470  (ToolBar *ct, wxPoint point) = 0;
471 
472  virtual bool ShouldVisitSpaces() = 0;
473 
474  virtual void FinalRect
475  (const wxRect &, ToolBarConfiguration::Position)
476  {
477  }
478 };
479 
480 // Skeleton routine common to insertion of a toolbar, and figuring out
481 // width-constrained layout of toolbars
483  ToolBarConfiguration *pWrappedConfiguration)
484 {
485  if (pWrappedConfiguration)
486  pWrappedConfiguration->Clear();
487 
488  // Get size of our parent since we haven't been sized yet
489  int width, height;
490  GetParent()->GetClientSize( &width, &height );
491  width -= toolbarGap;
492  height -= toolbarGap;
493 
494  // Rectangle of space to allocate
495  wxRect main{ toolbarGap, toolbarGap,
496  // Allow limited width, but arbitrary height, for the root rectangle
497  width, std::numeric_limits<int>::max() };
498 
499  // For recording the nested subdivisions of the rectangle
500  struct Item {
501  int myBarID { NoBarID };
502  int parentBarID { NoBarID };
503  ToolBar *lastSib {};
504  ToolBar *lastWrappedChild {};
505  wxRect rect;
506  } layout[ ToolBarCount ];
507 
508  ToolBar *lastRoot {};
509  ToolBar *lastWrappedRoot {};
510 
511  // Process all docked and visible toolbars
512  for ( const auto &place : this->GetConfiguration() )
513  {
514  // Cache toolbar pointer
515  const auto ct = place.pTree->pBar;
516 
517  // set up the chain of ancestors.
518  const auto parent = place.position.rightOf;
519  const auto type = ct->GetType();
520  auto &newItem = layout[ type ];
521  newItem.parentBarID = parent ? parent->GetType() : NoBarID;
522  // Mark the slots that really were visited, for final pass through
523  // the spaces.
524  newItem.myBarID = type;
525 
526  const auto parentItem = parent ? &layout[ parent->GetType() ] : nullptr;
527  ToolBar *prevSib;
528  if (!parent) {
529  prevSib = lastRoot;
530  lastRoot = ct;
531  }
532  else {
533  auto &sib = parentItem->lastSib;
534  prevSib = sib;
535  sib = ct;
536  }
537  auto prevPosition = ToolBarConfiguration::Position{ parent, prevSib };
538 
539  // Determine the size of the toolbar to fit, with advice from
540  // the visitor object
541  wxSize sz = ct->GetSize();
542  {
543  wxRect temp;
544  temp.SetPosition(ct->GetParent()->ClientToScreen(ct->GetPosition()));
545  temp.SetSize(sz);
546  visitor.ModifySize(ct, temp, prevPosition, place.position, sz);
547  }
548 
549  // Inflate the size to leave margins
550  int tw = sz.GetWidth() + toolbarGap;
551  int th = sz.GetHeight() + toolbarGap;
552 
553  // Choose the rectangle to subdivide
554  // Find a box that we fit in by going up the tree as needed --
555  // thus when parent space is exhausted, fall back on ancestors --
556  // so if the tree has too much depth for the width of the
557  // window, the toolbars may "wrap."
558  // Can always fall back to the main rectangle even if the bar is too
559  // wide.
560  auto pItem = parentItem;
561  auto pRect = pItem ? &pItem->rect : &main;
562  while (pRect != &main)
563  {
564  // Get out if it will fit
565  bool bTooWide = tw > pRect->GetWidth();
566  // We'd like to be able to add a tall toolbar in at the start of a row,
567  // even if there isn't enough height for it.
568  // If so, we'd have to at least change how we calculate 'bTooHigh'.
569  bool bTooHigh = th > pRect->GetHeight();
570  //bTooHigh &= stack[stkcnt].GetWidth() < (width - toolbarGap);
571  //bTooHigh = false;
572 
573  if (!bTooWide && !bTooHigh)
574  break;
575 
576  if (pItem->parentBarID == NoBarID) {
577  pItem = nullptr;
578  pRect = &main;
579  }
580  else {
581  pItem = &layout[ pItem->parentBarID ];
582  pRect = &pItem->rect;
583  }
584  }
585 
586  // Record where the toolbar wrapped
587  ToolBar *& sib = pItem ? pItem->lastWrappedChild : lastWrappedRoot;
588  ToolBarConfiguration::Position newPosition {
589  pItem ? this->mBars[ pItem->myBarID ] : nullptr,
590  sib
591  };
592  sib = ct;
593  if (pWrappedConfiguration)
594  pWrappedConfiguration->Insert(ct, newPosition);
595 
596  // Place the toolbar at the upper left part of the rectangle.
597  const auto cpos = pRect->GetPosition();
598  visitor.Visit(ct, cpos);
599 
600  // Allocate an upper portion of the rectangle to this bar.
601  pRect->y += th;
602  pRect->height -= th;
603 
604  // A right portion of that upper portion remains available for
605  // descendant bars and is remembered in the layout array.
606  int x = cpos.x + tw;
607  newItem.rect = wxRect{ x, cpos.y, width - x, th };
608  }
609 
610  if (visitor.ShouldVisitSpaces()) {
611  // Visit the fringe where NEW leaves of the tree could go
612 
613  // Find the items with leftover spaces
614  const auto end = std::remove_if(layout, layout + ToolBarCount,
615  [](const Item &item){
616  return item.myBarID == NoBarID || item.rect.IsEmpty();
617  }
618  );
619  // Sort top to bottom for definiteness, though perhaps not really needed
620  std::sort(layout, end,
621  [](const Item &lhs, const Item &rhs){
622  return lhs.rect.y < rhs.rect.y;
623  }
624  );
625  for (auto iter = layout; iter != end; ++iter) {
626  const auto &item = *iter;
627  const auto &rect = item.rect;
628 
629  auto globalRect = rect;
630  globalRect.SetPosition( this->ClientToScreen(rect.GetPosition()) );
631 
632  // Let the visitor determine size
633  wxSize sz {};
635  position { this->mBars[ item.myBarID ], item.lastWrappedChild },
636  prevPosition {};
637  visitor.ModifySize(nullptr, globalRect, prevPosition, position, sz);
638  int tw = sz.GetWidth() + toolbarGap;
639  int th = sz.GetHeight() + toolbarGap;
640 
641  // Test fit
642  bool bTooWide = tw > rect.GetWidth();
643  bool bTooHigh = th > rect.GetHeight();
644  if (!bTooWide && !bTooHigh) {
645  // Call visitor again to confirm the placement
646  const auto cpos = rect.GetPosition();
647  visitor.Visit(nullptr, cpos);
648  }
649  }
650  }
651 
652  // Report the final bounding box of all the bars, and a position where
653  // you can insert a NEW bar at bottom left.
654  ToolBarConfiguration::Position finalPosition { nullptr, lastRoot };
655  visitor.FinalRect(
656  wxRect { toolbarGap, toolbarGap, main.width, main.y }, finalPosition
657  );
658 }
659 
660 //
661 // Layout the toolbars
662 //
664 {
665  struct SizeSetter final : public LayoutVisitor
666  {
667  SizeSetter (ToolDock *d) : dock{ d } {}
668 
669  void Visit
670  (ToolBar *bar, wxPoint point)
671  override
672  {
673  // Place the toolbar
674  if(bar)
675  bar->SetPosition( point );
676  }
677 
678  bool ShouldVisitSpaces() override
679  {
680  return false;
681  }
682 
683  virtual void FinalRect
684  (const wxRect &rect, ToolBarConfiguration::Position)
685  override
686  {
687  // Set the final size of the dock window
688  dock->SetMinSize( rect.GetSize() );
689  }
690 
691  ToolDock *dock;
692  } sizeSetter {
693  this
694  };
695  VisitLayout(sizeSetter, &mWrappedConfiguration);
696 
697  // Set tab order and layout internal controls.
698  {
699  ToolBar *lt{};
700  for ( const auto &place : GetConfiguration() ) {
701  auto ct = place.pTree->pBar;
702  if( lt ){
703  ct->MoveAfterInTabOrder( lt );
704  }
705  lt = ct;
706  // Bug 1371.
707  // After a dock size change, the toolbars may need relaying inside.
708  lt->Layout();
709  }
710  }
711 
712  // Clean things up
713  Refresh( false );
714 }
715 
716 // Determine the position where a NEW bar would be placed
717 //
718 // 'rect' will be the rectangle for the dock marker (black triangle)
720  ToolDock::PositionBar( ToolBar *t, const wxPoint & pos, wxRect & rect )
721 {
722  // Set width and size, but we must still find x and y.
723  rect = t->GetRect();
724 
725  using Position = ToolBarConfiguration::Position;
726  Position result { ToolBarConfiguration::UnspecifiedPosition };
727  struct Inserter : public LayoutVisitor
728  {
729  struct Stop {};
730 
731  Inserter(Position &p, wxRect &r, const wxPoint &pt, ToolBar *t)
732  : result(p), rect(r), point(pt), tb(t)
733  {}
734 
735  void ModifySize
736  (ToolBar *ct,
737  const wxRect &rectIn,
738  ToolBarConfiguration::Position prevPosition,
740  wxSize &sz)
741  override
742  {
743  // Maybe insert the NEW bar if it hasn't already been done
744  // and is in the right place.
745 
746  // Does the location fall within this bar?
747  if (rectIn.Contains(point))
748  {
749  sz = tb->GetDockedSize();
750  // Choose a position always, if there is a bar to displace.
751  // Else, only if the fit is possible.
752  if (ct || (sz.x <= rectIn.width && sz.y <= rectIn.height)) {
753  // May choose current or previous.
754  if (ct &&
755  (sz.y < rectIn.height ||
756  point.y < (rectIn.GetTop() + rectIn.GetBottom()) / 2))
757  // "Wedge" the bar into a crack alone, not adopting others,
758  // if either a short bar displaces a tall one, or else
759  // the displacing bar is at least at tall, but the pointer is
760  // in the upper half of the box.
761  usedPrev = true, result = prevPosition, result.adopt = false;
762  else
763  result = position;
764  }
765  // Now wait until the other callback below to discover x and y
766  }
767  }
768 
769  void Visit
770  (ToolBar *, wxPoint pointIn)
771  override
772  {
774  // If we've placed it, we're done.
775  rect.x = pointIn.x;
776  rect.y = pointIn.y;
777  if (usedPrev)
778  rect.y -= tb->GetDockedSize().GetHeight() / 2;
779 
780  throw Stop {};
781  }
782  }
783 
784  bool ShouldVisitSpaces() override
785  {
786  return true;
787  }
788 
789  void FinalRect
790  (const wxRect &finalRect, ToolBarConfiguration::Position finalPosition)
791  override
792  {
794  // Default of all other placements.
795  result = finalPosition;
796  wxPoint point1 { finalRect.GetLeft(), finalRect.GetBottom() };
797  rect.SetPosition(point1);
798  }
799  }
800 
801 
802  Position &result;
803  wxRect &rect;
804  const wxPoint point;
805  ToolBar *const tb;
806  bool usedPrev { false };
807  } inserter {
808  result, rect, pos, t
809  };
810 
811  try { this->VisitLayout(inserter); } catch (const Inserter::Stop&) {}
812 
813  // rect is decided
814  return result;
815 }
816 
818 {
819  backup.Clear();
820  backup.Swap(mConfiguration);
822 }
823 
825 {
828  mConfiguration.Swap(backup);
829 }
830 
831 //
832 // Set the visible/hidden state of a toolbar
833 //
834 void ToolDock::Expose( int type, bool show )
835 {
836  ToolBar *t = mBars[ type ];
837 
838  // Maintain the docked array
839  const auto shown = mConfiguration.Shows( t );
840  if( show && !shown )
841  mConfiguration.Show( t );
842  else if( !show && shown )
843  mConfiguration.Hide( t );
844 
845  // Make it (dis)appear
846  t->Expose( show );
847 }
848 
849 //
850 // Queues an EVT_TOOLBAR_UPDATED command event to notify any
851 // interested parties of an updated toolbar or dock layout
852 //
854 {
855  // Queue an update event
856  wxCommandEvent e( EVT_TOOLBAR_UPDATED, GetId() );
857  GetParent()->GetEventHandler()->AddPendingEvent( e );
858 }
859 
860 //
861 // Handle grabber clicking
862 //
864 {
865  // auto pos = event.GetPosition();
866  if (!event.IsEscaping()) {
867  // Pass it on to the manager since it isn't in the handling hierarchy
868  mManager->ProcessEvent( event );
869  }
870 }
871 
872 //
873 // Handle sizing
874 //
875 void ToolDock::OnSize( wxSizeEvent & WXUNUSED(event) )
876 {
877 // event.Skip();
878 }
879 
880 //
881 // Prevent flicker
882 //
883 void ToolDock::OnErase( wxEraseEvent & WXUNUSED(event) )
884 {
885  // Ignore it to prevent flashing
886 }
887 
888 //
889 // Repaint toolbar gap lines
890 //
891 void ToolDock::OnPaint( wxPaintEvent & WXUNUSED(event) )
892 {
893  // Don't use a wxBufferedPaintDC() here. It produces a bogus
894  // background on Windows and GTK.
895  wxPaintDC dc( this );
896 
897  // Start with a clean background
898  //
899  // Under GTK, we don't set the toolbar background to the background
900  // colour in the system theme. Instead we use our own colour.
901 
902  dc.SetBackground( wxBrush( theTheme.Colour( clrMedium )));
903  dc.Clear();
904 
905  // Set the gap color
906  AColor::Dark( &dc, false );
907 
908  // Draw the initial horizontal and vertical gaps
909  wxSize sz = GetClientSize();
910 
911  AColor::Line(dc, 0, 0, sz.GetWidth(), 0 );
912  AColor::Line(dc, 0, 0, 0, sz.GetHeight() );
913 
914  // Draw the gap between each bar
915  for (const auto &place : GetConfiguration())
916  {
917  auto toolbar = place.pTree->pBar;
918  if (!toolbar)
919  continue;
920 
921  wxRect r = toolbar->GetRect();
922 
923  // Draw a horizontal line under the bar extending to the right edge of
924  // the dock
925  AColor::Line( dc,
926  r.GetLeft(),
927  r.GetBottom() + 1,
928  sz.GetWidth(),
929  r.GetBottom() + 1 );
930 
931  // For all bars but the last...
932  // ...and for bars that aren't the last in a row, draw a
933  // vertical gap line
934  if (!mConfiguration.IsRightmost(toolbar)) {
935  AColor::Line(dc,
936  r.GetRight() + 1,
937  r.GetTop(),
938  r.GetRight() + 1,
939  r.GetBottom() + 1 );
940  }
941  }
942 }
943 
944 void ToolDock::OnMouseEvents(wxMouseEvent &event)
945 {
946  // Do this hack so scrubber can detect mouse drags anywhere
947  event.ResumePropagation(wxEVENT_PROPAGATE_MAX);
948  event.Skip();
949 }
toolbarGap
#define toolbarGap
Definition: ToolBar.h:64
ToolDock::RestoreConfiguration
void RestoreConfiguration(ToolBarConfiguration &backup)
Definition: ToolDock.cpp:824
ToolBarConfiguration
Definition: ToolDock.h:50
ToolBarConfiguration::Place
Definition: ToolDock.h:108
ToolDock
A dynamic panel where a ToolBar can be docked.
Definition: ToolDock.h:290
ToolDock::OnMouseEvents
void OnMouseEvents(wxMouseEvent &event)
Definition: ToolDock.cpp:944
ToolBarCount
@ ToolBarCount
Definition: ToolBar.h:87
ToolBarConfiguration::Position::rightOf
ToolBar * rightOf
Definition: ToolDock.h:71
ToolBarConfiguration::Position
Definition: ToolDock.h:70
ToolDock::LayoutVisitor::ShouldVisitSpaces
virtual bool ShouldVisitSpaces()=0
ToolDock::LayoutVisitor
Definition: ToolDock.cpp:458
ToolBarConfiguration::Place::pTree
Tree * pTree
Definition: ToolDock.h:109
ToolDock::mBars
ToolBar * mBars[ToolBarCount]
Definition: ToolDock.h:343
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
AllThemeResources.h
ToolBarConfiguration::Shows
bool Shows(const ToolBar *bar) const
Definition: ToolDock.h:246
wxPanelWrapper
Definition: wxPanelWrapper.h:41
ToolDock::mWrappedConfiguration
ToolBarConfiguration mWrappedConfiguration
Definition: ToolDock.h:341
ToolBarConfiguration::RemoveNulls
void RemoveNulls(Forest &forest)
Definition: ToolDock.cpp:298
ToolDock::Undock
void Undock(ToolBar *bar)
Definition: ToolDock.cpp:403
ToolBarConfiguration::Tree::children
Forest children
Definition: ToolDock.h:274
ToolBarConfiguration::Contains
bool Contains(const ToolBar *bar) const
Definition: ToolDock.h:233
AColor::Line
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:109
ToolBarConfiguration::mForest
Forest mForest
Definition: ToolDock.h:286
ToolDock::Updated
void Updated()
Definition: ToolDock.cpp:853
ToolDock::GetConfiguration
ToolBarConfiguration & GetConfiguration()
Definition: ToolDock.h:309
FileConfig::DeleteEntry
virtual bool DeleteEntry(const wxString &key, bool bDeleteGroupIfEmpty=true) wxOVERRIDE
Definition: FileConfig.cpp:209
XO
#define XO(s)
Definition: Internat.h:31
ToolDock::LayoutToolBars
void LayoutToolBars()
Definition: ToolDock.cpp:663
IMPLEMENT_CLASS
IMPLEMENT_CLASS(ToolDock, wxPanelWrapper)
ToolBarConfiguration::Legacy::bars
std::vector< ToolBar * > bars
Definition: ToolDock.h:254
ToolBarConfiguration::begin
Iterator begin()
Definition: ToolDock.h:228
ToolDock::Expose
void Expose(int type, bool show)
Definition: ToolDock.cpp:834
ToolBarConfiguration::Forest
std::vector< Tree > Forest
Definition: ToolDock.h:52
ToolBarConfiguration::IsRightmost
bool IsRightmost(const ToolBar *bar) const
Definition: ToolDock.cpp:237
ToolDock.h
ToolDock::VisitLayout
void VisitLayout(LayoutVisitor &visitor, ToolBarConfiguration *pWrappedConfiguration=nullptr)
Definition: ToolDock.cpp:482
ToolDock::LayoutVisitor::FinalRect
virtual void FinalRect(const wxRect &, ToolBarConfiguration::Position)
Definition: ToolDock.cpp:475
GrabberEvent::IsEscaping
bool IsEscaping() const
Definition: Grabber.h:74
ToolBarConfiguration::Clear
void Clear()
Definition: ToolDock.h:61
ToolDock::OnSize
void OnSize(wxSizeEvent &event)
Definition: ToolDock.cpp:875
ToolBarConfiguration::Position::adopt
bool adopt
Definition: ToolDock.h:73
ToolBarConfiguration::UnspecifiedPosition
static const Position UnspecifiedPosition
Definition: ToolDock.h:105
ToolBarConfiguration::Read
static bool Read(ToolBarConfiguration *pConfiguration, Legacy *pLegacy, ToolBar *bar, bool &visible, bool defaultVisible)
Definition: ToolDock.cpp:255
ToolBar::GetType
int GetType()
Definition: ToolBar.cpp:390
ToolDock::PositionBar
ToolBarConfiguration::Position PositionBar(ToolBar *t, const wxPoint &pos, wxRect &rect)
Definition: ToolDock.cpp:720
ToolDock::~ToolDock
~ToolDock()
Definition: ToolDock.cpp:396
GrabberEvent
Grabber Class.
Definition: Grabber.h:48
ToolBarConfiguration::Tree
Definition: ToolDock.h:272
ToolBarFloatMargin
@ ToolBarFloatMargin
Definition: ToolBar.h:91
ToolBarConfiguration::Position::below
ToolBar * below
Definition: ToolDock.h:72
ToolDock::LayoutVisitor::Visit
virtual void Visit(ToolBar *ct, wxPoint point)=0
ToolDock::OnPaint
void OnPaint(wxPaintEvent &event)
Definition: ToolDock.cpp:891
EVT_GRABBER
#define EVT_GRABBER(id, fn)
Definition: Grabber.h:93
ToolBarConfiguration::Iterator
Definition: ToolDock.h:117
theTheme
THEME_API Theme theTheme
Definition: Theme.cpp:79
ToolDock::OnErase
void OnErase(wxEraseEvent &event)
Definition: ToolDock.cpp:883
ToolBar::GetDockedSize
virtual wxSize GetDockedSize()
Definition: ToolBar.h:145
ToolDock::LoadConfig
void LoadConfig()
Definition: ToolDock.cpp:443
Registry::Visit
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItem *pRegistry)
Definition: Registry.cpp:713
AColor::Dark
static void Dark(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:351
ToolBar::Expose
virtual bool Expose(bool show=true)
Definition: ToolBar.cpp:444
ToolBarConfiguration::Insert
void Insert(ToolBar *bar, Position position=UnspecifiedPosition)
Definition: ToolDock.cpp:98
ToolBarConfiguration::Hide
void Hide(ToolBar *bar)
Definition: ToolDock.cpp:231
ToolBarConfiguration::Write
static void Write(const ToolBarConfiguration *pConfiguration, const ToolBar *bar)
Definition: ToolDock.cpp:331
ToolDock::OnGrabber
void OnGrabber(GrabberEvent &event)
Definition: ToolDock.cpp:863
ToolBarConfiguration::PostRead
void PostRead(Legacy &legacy)
Definition: ToolDock.cpp:310
ToolBar
Works with ToolManager and ToolDock to provide a dockable window in which buttons can be placed.
Definition: ToolBar.h:98
ToolDock::WrapConfiguration
void WrapConfiguration(ToolBarConfiguration &backup)
Definition: ToolDock.cpp:817
ThemeBase::Colour
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1189
ToolDock::mManager
wxEvtHandler * mManager
Definition: ToolDock.h:335
ToolBarConfiguration::Legacy
Definition: ToolDock.h:253
Prefs.h
ToolBarConfiguration::end
Iterator end() const
Definition: ToolDock.h:229
ToolBarConfiguration::Find
Position Find(const ToolBar *bar) const
Definition: ToolDock.cpp:89
ToolBar::SetDocked
virtual void SetDocked(ToolDock *dock, bool pushed)
Definition: ToolBar.cpp:638
ToolBarConfiguration::Iterator::GetPath
std::vector< int > GetPath() const
Definition: ToolDock.h:168
ToolDock::mConfiguration
ToolBarConfiguration mConfiguration
Definition: ToolDock.h:338
ToolBarConfiguration::FindPeers
std::pair< Forest *, Forest::iterator > FindPeers(const ToolBar *bar)
Definition: ToolDock.cpp:64
AColor.h
ToolBar::IsVisible
bool IsVisible() const
Definition: ToolBar.cpp:431
END_EVENT_TABLE
END_EVENT_TABLE()
ToolDock::LayoutVisitor::ModifySize
virtual void ModifySize(ToolBar *, const wxRect &, ToolBarConfiguration::Position, ToolBarConfiguration::Position, wxSize &)
Definition: ToolDock.cpp:461
ImageManipulation.h
ToolDock::Dock
void Dock(ToolBar *bar, bool deflate, ToolBarConfiguration::Position ndx=ToolBarConfiguration::UnspecifiedPosition)
Definition: ToolDock.cpp:415
ToolBarConfiguration::Tree::swap
void swap(Tree &that)
Definition: ToolDock.h:276
NoBarID
@ NoBarID
Definition: ToolBar.h:71
ToolBarConfiguration::Swap
void Swap(ToolBarConfiguration &that)
Definition: ToolDock.h:56
ToolBarConfiguration::Show
void Show(ToolBar *bar)
Definition: ToolDock.cpp:224
ToolBarConfiguration::Remove
void Remove(const ToolBar *bar)
Definition: ToolDock.cpp:212
ToolBarConfiguration::InsertAtPath
void InsertAtPath(ToolBar *bar, const std::vector< int > &path)
Definition: ToolDock.cpp:177
ToolBarConfiguration::Tree::pBar
ToolBar * pBar
Definition: ToolDock.h:273
ToolBarConfiguration::FindPlace
Iterator FindPlace(const ToolBar *bar) const
Definition: ToolDock.cpp:54