Audacity 3.2.0
UIHandle.h
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5UIHandle.h
6
7Paul Licameli
8
9**********************************************************************/
10
11#ifndef __AUDACITY_UI_HANDLE__
12#define __AUDACITY_UI_HANDLE__
13
14#include <utility>
15#include <memory>
16#include <typeinfo>
17#include "TrackPanelDrawable.h" // to inherit
18
19class wxDC;
20class wxRect;
21class wxRegion;
22class wxWindow;
23
24class AudacityProject;
25class Channel;
26struct HitTestPreview;
27class Track;
28class TrackPanelCell;
31
33// A TrackPanelCell reports a handle object of some subclass, in response to a
34// hit test at a mouse position; then this handle processes certain events,
35// and maintains necessary state through click-drag-release event sequences.
36class AUDACITY_DLL_API UIHandle /* not final */ : public TrackPanelDrawable
37{
38public:
39 // See RefreshCode.h for bit flags:
40 using Result = unsigned;
41
42 // Future: may generalize away from current Track class
44
45 virtual ~UIHandle() = 0;
46
47 // Before clicking, the handle is notified that it has been "hit"
48 // This might put the handle into its first rotated state
49 // (or last, if forward is false) or mark itself as needing a highlight.
50 // Default does nothing.
51 virtual void Enter(bool forward, AudacityProject *pProject);
52
53 // Tell whether the handle has more than one TAB key rotation state.
54 // Default is always false.
55 virtual bool HasRotation() const;
56
57 // If not previously in the last rotation state (or first if !forward),
58 // change rotation state and return true; else return false
59 // Default does nothing and returns false
60 virtual bool Rotate(bool forward);
61
62 // Tell whether the handle has its own escape action. In case it is already
63 // clicked, it will not cancel on Escape key if true.
64 // Default is always false.
65 virtual bool HasEscape(AudacityProject *pProject) const;
66
67 // The handle may change state and mark itself for highlight change.
68 // Default does nothing and returns false
69 virtual bool Escape(AudacityProject *pProject);
70
72
74 virtual bool HandlesRightClick();
75
76 // Assume hit test (implemented in other classes) was positive.
77 // May return Cancelled, overriding the hit test decision and stopping drag.
78 // Otherwise the framework will later call Release or Cancel after
79 // some number of Drag calls.
80 virtual Result Click
81 (const TrackPanelMouseEvent &event, AudacityProject *pProject) = 0;
82
83 // Assume previously Clicked and not yet Released or Cancelled.
84 // pCell may be other than for Click; may be NULL, and rect empty.
85 // Return value may include the Cancelled return flag,
86 // in which case the handle will not be invoked again.
87 virtual Result Drag
88 (const TrackPanelMouseEvent &event, AudacityProject *pProject) = 0;
89
90 // Can be called when the handle has been hit but not yet clicked,
91 // or called after Drag().
92 // Specifies cursor and status bar message.
94 (const TrackPanelMouseState &state, AudacityProject *pProject) = 0;
95
96 // Assume previously Clicked and not yet Released or Cancelled.
97 // event.pCell may be other than for Click; may be NULL, and rect empty.
98 // Can use pParent as parent to pop up a context menu,
99 // connecting and disconnecting event handlers for the menu items.
100 // Cancelled in return flags has no effect.
102 (const TrackPanelMouseEvent &event, AudacityProject *pProject,
103 wxWindow *pParent) = 0;
104
105 // Assume previously Clicked and not yet Released or Cancelled.
106 // Cancelled in return flags has no effect.
107 virtual Result Cancel(AudacityProject *pProject) = 0;
108
109 // Whether to force Release (not Cancel!) of the drag when a
110 // keystroke command is about to be dispatched. Default is always false.
111 // When default is false, any remembered pointers to tracks should be
112 // weak_ptrs.
113 virtual bool StopsOnKeystroke();
114
115 // Notification after a command is dispatched; generally, it will need to
116 // be overridden only in case StopsOnKeystroke() returns false. Default
117 // does nothing.
118 // PRL: all former uses of this are now accomplished with weak_ptr instead
119 // to avoid dangling pointers to tracks. But maybe there will be a future
120 // use?
121 virtual void OnProjectChange(AudacityProject *pProject);
122
124 virtual std::shared_ptr<const Track> FindTrack() const = 0;
125
128 virtual bool IsDragging() const;
129
130public:
131 Result GetChangeHighlight() const { return mChangeHighlight; }
132 void SetChangeHighlight(Result val) { mChangeHighlight = val; }
133
134 // If AssignUIHandlePtr is used, then this function is also called before any
135 // overwrite.
136 // Make overloads of this for other subclasses, to cause refresh
137 // of the cell during mouse motion within it.
139 (const UIHandle &/*oldState*/, const UIHandle &/*newState*/)
140 {
141 return 0;
142 }
143
145 static std::shared_ptr<const Track>
146 TrackFromChannel(const std::shared_ptr<const Channel> &pChannel);
147
148protected:
149 // Derived classes can set this nonzero in a constructor, which is enough
150 // to cause repaint of the cell whenever the pointer hits the target,
151 // or leaves it without clicking, or releases or escapes from a drag.
152 Result mChangeHighlight { 0 };
153
154};
155
156using UIHandlePtr = std::shared_ptr<UIHandle>;
157
158// A frequent convenience for defining a hit test.
159// Construct a NEW handle as if hit the first time; then either keep it, or
160// use it to overwrite the state of a previously constructed handle that has not
161// yet been released.
162template<typename Subclass>
163std::shared_ptr<Subclass> AssignUIHandlePtr
164( std::weak_ptr<Subclass> &holder, const std::shared_ptr<Subclass> &pNew )
165{
166 // Either assign to a null weak_ptr, or else rewrite what the weak_ptr
167 // points at. Thus a handle already pointed at changes its state but not its
168 // identity. This may matter for the framework that holds the strong
169 // pointers.
170 auto ptr = holder.lock();
171 if (!ptr) {
172 holder = pNew;
173 return pNew;
174 }
175 else {
176 //type slicing check
177 wxASSERT(typeid(*ptr) == typeid(*pNew));
178
179 auto code = Subclass::NeedChangeHighlight( *ptr, *pNew );
180 *ptr = std::move(*pNew);
181 ptr->SetChangeHighlight( code );
182 return ptr;
183 }
184}
185
186#endif
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:164
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
Drawing interface common to cells, groups of cells, and temporary handles in CellularPanel.
Short-lived drawing and event-handling object associated with a TrackPanelCell.
Definition: UIHandle.h:37
virtual Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject)=0
virtual Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent)=0
unsigned Result
Definition: UIHandle.h:40
void SetChangeHighlight(Result val)
Definition: UIHandle.h:132
Result GetChangeHighlight() const
Definition: UIHandle.h:131
virtual std::shared_ptr< const Track > FindTrack() const =0
static UIHandle::Result NeedChangeHighlight(const UIHandle &, const UIHandle &)
Definition: UIHandle.h:139
virtual HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject)=0
virtual Result Cancel(AudacityProject *pProject)=0
virtual Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject)=0