Audacity 3.2.0
LabelTextHandle.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5LabelTextHandle.cpp
6
7Paul Licameli split from TrackPanel.cpp
8
9**********************************************************************/
10
11
12#include "LabelTextHandle.h"
13
14#include "LabelTrackView.h"
15
16#include "../../../HitTestResult.h"
17#include "../../../LabelTrack.h"
18#include "ProjectAudioIO.h"
19#include "ProjectHistory.h"
20#include "../../../RefreshCode.h"
21#include "SelectionState.h"
22#include "../../../TrackPanelMouseEvent.h"
23#include "ViewInfo.h"
24#include "../../../../images/Cursors.h"
25
26#include <wx/clipbrd.h>
27
29( const std::shared_ptr<LabelTrack> &pLT, int labelNum )
30 : mpLT{ pLT }
31 , mLabelNum{ labelNum }
32{
33}
34
36{
37#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
39#endif
40}
41
43{
44 static auto ibeamCursor =
45 ::MakeCursor(wxCURSOR_IBEAM, IBeamCursorXpm, 17, 16);
46 return {
47 XO("Click to edit label text"),
48 ibeamCursor.get()
49 };
50}
51
53(std::weak_ptr<LabelTextHandle> &holder,
54 const wxMouseState &state, const std::shared_ptr<LabelTrack> &pLT)
55{
56 // If Control is down, let the select handle be hit instead
57 int labelNum;
58 if (!state.ControlDown() &&
59 (labelNum =
60 LabelTrackView::OverATextBox(*pLT, state.m_x, state.m_y) ) >= 0) {
61 auto result = std::make_shared<LabelTextHandle>( pLT, labelNum );
62 result = AssignUIHandlePtr(holder, result);
63 return result;
64 }
65
66 return {};
67}
68
70{
71}
72
73std::shared_ptr<const Track> LabelTextHandle::FindTrack() const
74{
75 return mpLT.lock();
76}
77
79{
80 auto pTrack = mpLT.lock();
81 if (!pTrack)
82 return;
83
84 auto &view = LabelTrackView::Get( *pTrack );
85 if (evt.ButtonDown())
86 {
87 const auto selIndex = LabelTrackView::OverATextBox( *pTrack, evt.m_x, evt.m_y );
88 if ( selIndex != -1 ) {
89 if (evt.LeftDown()) {
90 mRightDragging = false;
91 // Find the NEW drag end
92 auto position = view.FindCursorPosition(selIndex, evt.m_x );
93
94 // Anchor shift-drag at the farther end of the previous highlight
95 // that is farther from the click, on Mac, for consistency with
96 // its text editors, but on the others, re-use the previous
97 // anchor.
98 auto initial = view.GetInitialCursorPosition();
99 if (evt.ShiftDown()) {
100#ifdef __WXMAC__
101 // Set the drag anchor at the end of the previous selection
102 // that is farther from the NEW drag end
103 const auto current = view.GetCurrentCursorPosition();
104 if ( abs( position - current ) > abs( position - initial ) )
105 initial = current;
106#else
107 // initial position remains as before
108#endif
109 }
110 else
111 initial = position;
112
113 view.SetTextSelection(selIndex, initial, position );
114 }
115 else
116 {
117 if (!view.IsTextSelected(project))
118 {
119 auto position = view.FindCursorPosition(selIndex, evt.m_x);
120 view.SetTextSelection(selIndex, position, position);
121 }
122 // Actually this might be right or middle down
123 mRightDragging = true;
124 }
125 // Middle click on GTK: paste from primary selection
126#if defined(__WXGTK__) && (HAVE_GTK)
127 if (evt.MiddleDown()) {
128 // Check for a click outside of the selected label's text box; in this
129 // case PasteSelectedText() will start a NEW label at the click
130 // location
131 if (!LabelTrackView::OverTextBox(&labelStruct, evt.m_x, evt.m_y))
132 view.ResetTextSelection();
133 double t = zoomInfo.PositionToTime(evt.m_x, r.x);
134 newSel = SelectedRegion(t, t);
135 }
136#endif
137 }
138#if defined(__WXGTK__) && (HAVE_GTK)
139 if (evt.MiddleDown()) {
140 // Paste text, making a NEW label if none is selected.
141 wxTheClipboard->UsePrimarySelection(true);
142 view.PasteSelectedText(project, newSel.t0(), newSel.t1());
143 wxTheClipboard->UsePrimarySelection(false);
144 }
145#endif
146 }
147}
148
150{
151 return true;
152}
153
155(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
156{
157 auto pLT = mpLT.lock();
158 if (!pLT)
160
161 auto result = LabelDefaultClickHandle::Click( evt, pProject );
162
163 const wxMouseEvent &event = evt.event;
164 auto &viewInfo = ViewInfo::Get( *pProject );
165
166 HandleTextClick(*pProject, event);
167
168 return result | RefreshCode::RefreshCell;
169}
170
172 AudacityProject &project, const wxMouseEvent & evt)
173{
174 auto pTrack = mpLT.lock();
175 if (!pTrack)
176 return;
177 auto &view = LabelTrackView::Get( *pTrack );
178
179 if(evt.LeftUp())
180 {
181#if 0
182 // AWD: Due to wxWidgets bug #7491 (fix not ported to 2.8 branch) we
183 // should never write the primary selection. We can enable this block
184 // when we move to the 3.0 branch (or if a fixed 2.8 version is released
185 // and we can do a runtime version check)
186#if defined (__WXGTK__) && defined (HAVE_GTK)
187 // On GTK, if we just dragged out a text selection, set the primary
188 // selection
189 if (mInitialCursorPos != mCurrentCursorPos) {
190 wxTheClipboard->UsePrimarySelection(true);
191 CopySelectedText();
192 wxTheClipboard->UsePrimarySelection(false);
193 }
194#endif
195#endif
196
197 return;
198 }
199
200 if(evt.Dragging())
201 {
202 auto index = view.GetTextEditIndex(project);
203 if (!mRightDragging && index != -1)
204 // Update drag end
205 view.SetCurrentCursorPosition(view.FindCursorPosition(index, evt.m_x ));
206 return;
207 }
208
209 if (evt.RightUp())
210 {
211 auto index = view.GetTextEditIndex(project);
212 if(index != -1 &&
213 LabelTrackView::OverTextBox(pTrack->GetLabel(index), evt.m_x, evt.m_y))
214 {
215 // popup menu for editing
216 // TODO: handle context menus via CellularPanel?
217 view.ShowContextMenu( project );
218 }
219 }
220
221 return;
222}
223
225(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
226{
227 auto &project = *pProject;
228 using namespace RefreshCode;
229 auto result = LabelDefaultClickHandle::Drag( evt, pProject );
230
231 const wxMouseEvent &event = evt.event;
232 auto pLT = TrackList::Get( *pProject ).Lock(mpLT);
233 if(pLT)
235
236 // locate the initial mouse position
237 if (event.LeftIsDown()) {
238 if (mLabelTrackStartXPos == -1) {
239 mLabelTrackStartXPos = event.m_x;
240 mLabelTrackStartYPos = event.m_y;
241
242 auto pView = pLT ? &LabelTrackView::Get( *pLT ) : nullptr;
243 if (pLT && (pView->GetTextEditIndex( project ) != -1) &&
245 pLT->GetLabel(pView->GetTextEditIndex( project )),
249 }
250 // if initial mouse position in the text box
251 // then only drag text
252 if (mLabelTrackStartYPos == -1)
253 result |= RefreshCell;
254 }
255
256 return result;
257}
258
261{
262 return HitPreview();
263}
264
266(const TrackPanelMouseEvent &evt, AudacityProject *pProject,
267 wxWindow *pParent)
268{
269 auto result = LabelDefaultClickHandle::Release( evt, pProject, pParent );
270
271 // Only selected a part of a text string and changed track selectedness.
272 // No undoable effects.
273
274 const wxMouseEvent &event = evt.event;
275 auto pLT = TrackList::Get( *pProject ).Lock(mpLT);
276 if (pLT)
277 HandleTextDragRelease( *pProject, event );
278
279 // handle mouse left button up
280 if (event.LeftUp())
282
283 return result | RefreshCode::RefreshNone;
284}
285
287{
288 auto result = LabelDefaultClickHandle::Cancel( pProject );
289 return result | RefreshCode::RefreshAll;
290}
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
XO("Cut/Copy/Paste")
const auto project
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:189
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
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Result Cancel(AudacityProject *pProject) override
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Result Cancel(AudacityProject *pProject) override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
void HandleTextDragRelease(AudacityProject &project, const wxMouseEvent &evt)
virtual ~LabelTextHandle()
static UIHandlePtr HitTest(std::weak_ptr< LabelTextHandle > &holder, const wxMouseState &state, const std::shared_ptr< LabelTrack > &pLT)
void HandleTextClick(AudacityProject &project, const wxMouseEvent &evt)
bool mRightDragging
flag to tell if it's a valid dragging
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
void Enter(bool forward, AudacityProject *) override
LabelTextHandle(const std::shared_ptr< LabelTrack > &pLT, int labelNum)
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
static HitTestPreview HitPreview()
std::shared_ptr< const Track > FindTrack() const override
std::weak_ptr< LabelTrack > mpLT
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
static LabelTrackView & Get(LabelTrack &)
static bool OverTextBox(const LabelStruct *pLabel, int x, int y)
static int OverATextBox(const LabelTrack &track, int xx, int yy)
Defines a selected portion of a project.
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1079
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
Result mChangeHighlight
Definition: UIHandle.h:152
unsigned Result
Definition: UIHandle.h:40
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16