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