1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  CellularPanel.h
6 
7  Paul Licameli
8 
9  **********************************************************************/
10 
11 #ifndef __AUDACITY_CELLULAR_PANEL__
12 #define __AUDACITY_CELLULAR_PANEL__
13 
14 #include "widgets/OverlayPanel.h" // to inherit
15 
16 class ViewInfo;
17 class AudacityProject;
18 
19 class TrackPanelCell;
20 struct TrackPanelDrawingContext;
21 class TrackPanelGroup;
22 class TrackPanelNode;
23 struct TrackPanelMouseEvent;
24 struct TrackPanelMouseState;
25 class TranslatableString;
26 
27 class UIHandle;
28 using UIHandlePtr = std::shared_ptr<UIHandle>;
29 
30 // This class manages a panel divided into a number of sub-rectangles called
31 // cells, that each implement hit tests returning click-drag-release handler
32 // objects, and other services.
33 // It has no dependency on the Track class.
34 class AUDACITY_DLL_API CellularPanel : public OverlayPanel {
35 public:
36    CellularPanel(wxWindow * parent, wxWindowID id,
37                  const wxPoint & pos,
38                  const wxSize & size,
39                  ViewInfo *viewInfo,
40                  // default as for wxPanel:
41                  long style = wxTAB_TRAVERSAL | wxNO_BORDER);
42    ~CellularPanel() override;
43 
44    // Overridables:
45 
46    virtual AudacityProject *GetProject() const = 0;
47 
48    // Get the root object defining a recursive subdivision of the panel's
49    // area into cells
50    virtual std::shared_ptr<TrackPanelNode> Root() = 0;
51 
52    virtual TrackPanelCell *GetFocusedCell() = 0;
53    virtual void SetFocusedCell() = 0;
54 
55    virtual void ProcessUIHandleResult
56    (TrackPanelCell *pClickedCell, TrackPanelCell *pLatestCell,
57     unsigned refreshResult) = 0;
58 
59    virtual void UpdateStatusMessage( const TranslatableString & )  = 0;
60 
61 public:
62    // Structure and functions for generalized visitation of the subdivision
63    struct Visitor {
64       virtual ~Visitor();
65       virtual void VisitCell( const wxRect &rect, TrackPanelCell &cell );
66       virtual void BeginGroup( const wxRect &rect, TrackPanelGroup &group );
67       virtual void EndGroup( const wxRect &rect, TrackPanelGroup &group );
68    };
69 
70    // Most general visit
71    void Visit( Visitor &visitor );
72 
73    // Easier visit when you care only about cells
74    using SimpleCellVisitor =
75       std::function< void( const wxRect &rect, TrackPanelCell &cell ) >;
76    void VisitCells( const SimpleCellVisitor &visitor );
77 
78    // Easier visits when you want to visit each node once only
79    using SimpleNodeVisitor =
80       std::function< void( const wxRect &rect, TrackPanelNode &node ) >;
81    void VisitPreorder( const SimpleNodeVisitor &visitor );
82    void VisitPostorder( const SimpleNodeVisitor &visitor );
83 
84    // Find cell by coordinate
85    struct FoundCell {
86       std::shared_ptr< TrackPanelCell > pCell;
87       wxRect rect;
88    };
89 
90    FoundCell FindCell(int mouseX, int mouseY);
91 
92    // Search the tree of subdivisions of the panel area for the given cell.
93    // If more than one sub-area is associated with the same cell object, it
94    // is not specified which rectangle is returned.
95    wxRect FindRect(const TrackPanelCell &cell);
96 
97    // Search the tree of subdivisions of the panel area for a node (group or
98    // cell) satisfying the predicate. If more than one sub-area is associated
99    // with some node satisfying the predicate, it is not specified which
100    // rectangle is returned.
101    wxRect FindRect(const std::function< bool( TrackPanelNode& ) > &pred);
102 
103    UIHandlePtr Target();
104 
105    std::shared_ptr<TrackPanelCell> LastCell() const;
106 
107    bool IsMouseCaptured();
108 
109    wxCoord MostRecentXCoord() const;
110 
111    void HandleCursorForPresentMouseState(bool doHit = true);
112 
113    // Visit the Draw functions of all cells that intersect the panel area,
114    // and of handles associated with such cells,
115    // and of all groups of cells,
116    // repeatedly with a pass count from 0 to nPasses - 1
117    void Draw( TrackPanelDrawingContext &context, unsigned nPasses );
118 
119 protected:
120    bool HasEscape();
121    bool CancelDragging( bool escaping );
122    void DoContextMenu( TrackPanelCell *pCell = nullptr );
123    void ClearTargets();
124 
125 private:
126    void Visit(
127       const wxRect &rect, const std::shared_ptr<TrackPanelNode> &node,
128       Visitor &visitor );
129 
130    bool HasRotation();
131    bool ChangeTarget(bool forward, bool cycle);
132 
133    void OnMouseEvent(wxMouseEvent & event);
134    void OnCaptureLost(wxMouseCaptureLostEvent & event);
135    void OnCaptureKey(wxCommandEvent & event);
136    void OnKeyDown(wxKeyEvent & event);
137    void OnChar(wxKeyEvent & event);
138    void OnKeyUp(wxKeyEvent & event);
139 
140    void OnSetFocus(wxFocusEvent & event);
141    void OnKillFocus(wxFocusEvent & event);
142    void DoKillFocus();
143 
144    void OnContextMenu(wxContextMenuEvent & event);
145 
146    void HandleInterruptedDrag();
147    void Uncapture( bool escaping, wxMouseState *pState = nullptr );
148    bool HandleEscapeKey(bool down);
149    void UpdateMouseState(const wxMouseState &state);
150    void HandleModifierKey();
151 
152    void HandleClick( const TrackPanelMouseEvent &tpmEvent );
153    void HandleWheelRotation( TrackPanelMouseEvent &tpmEvent );
154 
155    void HandleMotion( wxMouseState &state, bool doHit = true );
156    void HandleMotion
157    ( const TrackPanelMouseState &tpmState, bool doHit = true );
158    void Leave();
159 
160 
161 protected:
162    ViewInfo *mViewInfo;
163 
164    // To do: make a drawing method and make this private
165    wxMouseState mLastMouseState;
166 
167 private:
168    struct State;
169    std::unique_ptr<State> mState;
170 
171    struct Filter;
172 
173    DECLARE_EVENT_TABLE()
174 };
175 
176 #endif
177