Audacity  3.0.3
LabelTextHandle.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 LabelTextHandle.cpp
6 
7 Paul 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 
73 void LabelTextHandle::HandleTextClick(AudacityProject &project, const wxMouseEvent & evt)
74 {
75  auto pTrack = mpLT.lock();
76  if (!pTrack)
77  return;
78 
79  auto &view = LabelTrackView::Get( *pTrack );
80  if (evt.ButtonDown())
81  {
82  const auto selIndex = LabelTrackView::OverATextBox( *pTrack, evt.m_x, evt.m_y );
83  if ( selIndex != -1 ) {
84  if (evt.LeftDown()) {
85  mRightDragging = false;
86  // Find the NEW drag end
87  auto position = view.FindCursorPosition(selIndex, evt.m_x );
88 
89  // Anchor shift-drag at the farther end of the previous highlight
90  // that is farther from the click, on Mac, for consistency with
91  // its text editors, but on the others, re-use the previous
92  // anchor.
93  auto initial = view.GetInitialCursorPosition();
94  if (evt.ShiftDown()) {
95 #ifdef __WXMAC__
96  // Set the drag anchor at the end of the previous selection
97  // that is farther from the NEW drag end
98  const auto current = view.GetCurrentCursorPosition();
99  if ( abs( position - current ) > abs( position - initial ) )
100  initial = current;
101 #else
102  // initial position remains as before
103 #endif
104  }
105  else
106  initial = position;
107 
108  view.SetTextSelection(selIndex, initial, position );
109  }
110  else
111  {
112  if (!view.IsTextSelected(project))
113  {
114  auto position = view.FindCursorPosition(selIndex, evt.m_x);
115  view.SetTextSelection(selIndex, position, position);
116  }
117  // Actually this might be right or middle down
118  mRightDragging = true;
119  }
120  // Middle click on GTK: paste from primary selection
121 #if defined(__WXGTK__) && (HAVE_GTK)
122  if (evt.MiddleDown()) {
123  // Check for a click outside of the selected label's text box; in this
124  // case PasteSelectedText() will start a NEW label at the click
125  // location
126  if (!LabelTrackView::OverTextBox(&labelStruct, evt.m_x, evt.m_y))
127  view.ResetTextSelection();
128  double t = zoomInfo.PositionToTime(evt.m_x, r.x);
129  newSel = SelectedRegion(t, t);
130  }
131 #endif
132  }
133 #if defined(__WXGTK__) && (HAVE_GTK)
134  if (evt.MiddleDown()) {
135  // Paste text, making a NEW label if none is selected.
136  wxTheClipboard->UsePrimarySelection(true);
137  view.PasteSelectedText(project, newSel.t0(), newSel.t1());
138  wxTheClipboard->UsePrimarySelection(false);
139  }
140 #endif
141  }
142 }
143 
145 (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
146 {
147  auto pLT = mpLT.lock();
148  if (!pLT)
149  return RefreshCode::Cancelled;
150 
151  auto result = LabelDefaultClickHandle::Click( evt, pProject );
152 
153  const wxMouseEvent &event = evt.event;
154  auto &viewInfo = ViewInfo::Get( *pProject );
155 
156  HandleTextClick(*pProject, event);
157 
158  return result | RefreshCode::RefreshCell;
159 }
160 
162  AudacityProject &project, const wxMouseEvent & evt)
163 {
164  auto pTrack = mpLT.lock();
165  if (!pTrack)
166  return;
167  auto &view = LabelTrackView::Get( *pTrack );
168 
169  if(evt.LeftUp())
170  {
171 #if 0
172  // AWD: Due to wxWidgets bug #7491 (fix not ported to 2.8 branch) we
173  // should never write the primary selection. We can enable this block
174  // when we move to the 3.0 branch (or if a fixed 2.8 version is released
175  // and we can do a runtime version check)
176 #if defined (__WXGTK__) && defined (HAVE_GTK)
177  // On GTK, if we just dragged out a text selection, set the primary
178  // selection
179  if (mInitialCursorPos != mCurrentCursorPos) {
180  wxTheClipboard->UsePrimarySelection(true);
181  CopySelectedText();
182  wxTheClipboard->UsePrimarySelection(false);
183  }
184 #endif
185 #endif
186 
187  return;
188  }
189 
190  if(evt.Dragging())
191  {
192  auto index = view.GetTextEditIndex(project);
193  if (!mRightDragging && index != -1)
194  // Update drag end
195  view.SetCurrentCursorPosition(view.FindCursorPosition(index, evt.m_x ));
196  return;
197  }
198 
199  if (evt.RightUp())
200  {
201  auto index = view.GetTextEditIndex(project);
202  if(index != -1 &&
203  LabelTrackView::OverTextBox(pTrack->GetLabel(index), evt.m_x, evt.m_y))
204  {
205  // popup menu for editing
206  // TODO: handle context menus via CellularPanel?
207  view.ShowContextMenu( project );
208  }
209  }
210 
211  return;
212 }
213 
215 (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
216 {
217  auto &project = *pProject;
218  using namespace RefreshCode;
219  auto result = LabelDefaultClickHandle::Drag( evt, pProject );
220 
221  const wxMouseEvent &event = evt.event;
222  auto pLT = TrackList::Get( *pProject ).Lock(mpLT);
223  if(pLT)
224  HandleTextDragRelease( project, event );
225 
226  // locate the initial mouse position
227  if (event.LeftIsDown()) {
228  if (mLabelTrackStartXPos == -1) {
229  mLabelTrackStartXPos = event.m_x;
230  mLabelTrackStartYPos = event.m_y;
231 
232  auto pView = pLT ? &LabelTrackView::Get( *pLT ) : nullptr;
233  if (pLT && (pView->GetTextEditIndex( project ) != -1) &&
235  pLT->GetLabel(pView->GetTextEditIndex( project )),
239  }
240  // if initial mouse position in the text box
241  // then only drag text
242  if (mLabelTrackStartYPos == -1)
243  result |= RefreshCell;
244  }
245 
246  return result;
247 }
248 
251 {
252  return HitPreview();
253 }
254 
256 (const TrackPanelMouseEvent &evt, AudacityProject *pProject,
257  wxWindow *pParent)
258 {
259  auto result = LabelDefaultClickHandle::Release( evt, pProject, pParent );
260 
261  // Only selected a part of a text string and changed track selectedness.
262  // No undoable effects.
263 
264  const wxMouseEvent &event = evt.event;
265  auto pLT = TrackList::Get( *pProject ).Lock(mpLT);
266  if (pLT)
267  HandleTextDragRelease( *pProject, event );
268 
269  // handle mouse left button up
270  if (event.LeftUp())
272 
273  return result | RefreshCode::RefreshNone;
274 }
275 
277 {
278  auto result = LabelDefaultClickHandle::Cancel( pProject );
279  return result | RefreshCode::RefreshAll;
280 }
LabelTextHandle::HitPreview
static HitTestPreview HitPreview()
Definition: LabelTextHandle.cpp:42
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:156
LabelDefaultClickHandle::Drag
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: LabelDefaultClickHandle.cpp:83
LabelDefaultClickHandle::Click
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: LabelDefaultClickHandle.cpp:60
RefreshCode::RefreshAll
@ RefreshAll
Definition: RefreshCode.h:26
RefreshCode::RefreshNone
@ RefreshNone
Definition: RefreshCode.h:21
TrackList::Lock
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1524
MakeCursor
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:176
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
XO
#define XO(s)
Definition: Internat.h:31
LabelTextHandle.h
LabelTextHandle::LabelTextHandle
LabelTextHandle(const std::shared_ptr< LabelTrack > &pLT, int labelNum)
Definition: LabelTextHandle.cpp:29
LabelTextHandle::Cancel
Result Cancel(AudacityProject *pProject) override
Definition: LabelTextHandle.cpp:276
LabelTrackView::OverTextBox
static bool OverTextBox(const LabelStruct *pLabel, int x, int y)
Definition: LabelTrackView.cpp:1287
LabelTextHandle::HandleTextClick
void HandleTextClick(AudacityProject &project, const wxMouseEvent &evt)
Definition: LabelTextHandle.cpp:73
LabelTextHandle::mpLT
std::weak_ptr< LabelTrack > mpLT
Definition: LabelTextHandle.h:65
LabelTextHandle::mLabelTrackStartXPos
int mLabelTrackStartXPos
Definition: LabelTextHandle.h:67
LabelTextHandle::mLabelTrackStartYPos
int mLabelTrackStartYPos
Definition: LabelTextHandle.h:68
LabelTextHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< LabelTextHandle > &holder, const wxMouseState &state, const std::shared_ptr< LabelTrack > &pLT)
Definition: LabelTextHandle.cpp:53
LabelTrackView::OverATextBox
static int OverATextBox(const LabelTrack &track, int xx, int yy)
Definition: LabelTrackView.cpp:1273
UIHandle::mChangeHighlight
Result mChangeHighlight
Definition: UIHandle.h:133
LabelDefaultClickHandle::Cancel
Result Cancel(AudacityProject *pProject) override
Definition: LabelDefaultClickHandle.cpp:96
UIHandle::Result
unsigned Result
Definition: UIHandle.h:37
LabelTrackView.h
UIHandlePtr
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
HitTestPreview
Definition: HitTestResult.h:20
LabelTrackView::Get
static LabelTrackView & Get(LabelTrack &)
Definition: LabelTrackView.cpp:158
RefreshCode::RefreshCell
@ RefreshCell
Definition: RefreshCode.h:24
LabelTextHandle::Enter
void Enter(bool forward, AudacityProject *) override
Definition: LabelTextHandle.cpp:35
LabelDefaultClickHandle::Release
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: LabelDefaultClickHandle.cpp:89
LabelTextHandle::~LabelTextHandle
virtual ~LabelTextHandle()
Definition: LabelTextHandle.cpp:69
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:495
LabelTextHandle::Preview
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Definition: LabelTextHandle.cpp:250
LabelTextHandle::Release
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: LabelTextHandle.cpp:256
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:113
TrackPanelMouseEvent
Definition: TrackPanelMouseEvent.h:46
LabelTextHandle::HandleTextDragRelease
void HandleTextDragRelease(AudacityProject &project, const wxMouseEvent &evt)
Definition: LabelTextHandle.cpp:161
TrackPanelMouseState
Definition: TrackPanelMouseEvent.h:28
AssignUIHandlePtr
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:145
LabelTextHandle::mRightDragging
bool mRightDragging
flag to tell if it's a valid dragging
Definition: LabelTextHandle.h:71
RefreshCode
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
LabelTextHandle::Click
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: LabelTextHandle.cpp:145
LabelTextHandle::Drag
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: LabelTextHandle.cpp:215
TrackPanelMouseEvent::event
wxMouseEvent & event
Definition: TrackPanelMouseEvent.h:58
SelectedRegion
Defines a selected portion of a project.
Definition: SelectedRegion.h:38