Audacity  3.0.3
NoteTrackControls.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 NoteTrackControls.cpp
6 
7 Paul Licameli split from TrackPanel.cpp
8 
9 **********************************************************************/
10 
11 
12 #ifdef USE_MIDI
13 #include "NoteTrackControls.h"
14 
15 #include "NoteTrackButtonHandle.h"
16 
17 #include "../../ui/PlayableTrackButtonHandles.h"
18 #include "NoteTrackSliderHandles.h"
19 
20 #include "../../../../HitTestResult.h"
21 #include "../../../../TrackArtist.h"
22 #include "../../../../TrackPanel.h"
23 #include "../../../../TrackPanelMouseEvent.h"
24 #include "../../../../NoteTrack.h"
25 #include "../../../../widgets/PopupMenuTable.h"
26 #include "Project.h"
27 #include "../../../../ProjectHistory.h"
28 #include "../../../../ProjectWindows.h"
29 #include "../../../../RefreshCode.h"
30 #include "../../../../prefs/ThemePrefs.h"
31 
32 #include <mutex>
33 #include <wx/app.h>
34 #include <wx/frame.h>
35 
38 {
39 }
40 
41 std::vector<UIHandlePtr> NoteTrackControls::HitTest
42 (const TrackPanelMouseState & st,
43  const AudacityProject *pProject)
44 {
45  // Hits are mutually exclusive, results single
46  std::vector<UIHandlePtr> results;
47  const wxMouseState &state = st.state;
48  const wxRect &rect = st.rect;
49  if (state.ButtonIsDown(wxMOUSE_BTN_ANY)) {
50  auto track = std::static_pointer_cast<NoteTrack>(FindTrack());
51  auto result = [&]{
52  UIHandlePtr result;
53  if (NULL != (result = MuteButtonHandle::HitTest(
54  mMuteHandle, state, rect, pProject, track)))
55  return result;
56 
57  if (NULL != (result = SoloButtonHandle::HitTest(
58  mSoloHandle, state, rect, pProject, track)))
59  return result;
60 #ifdef EXPERIMENTAL_MIDI_OUT
61  if (NULL != (result = VelocitySliderHandle::HitTest(
62  mVelocityHandle, state, rect, track)))
63  return result;
64  if (NULL != (result = NoteTrackButtonHandle::HitTest(
65  mClickHandle, state, rect, track)))
66  return result;
67 #endif
68  return result;
69  }();
70  if (result) {
71  results.push_back(result);
72  return results;
73  }
74  }
75 
76  return NoteTrackControlsBase::HitTest(st, pProject);
77 }
78 
80 {
82  : PopupMenuTable{ "NoteTrack" }
83  {}
85 
86 public:
87  static NoteTrackMenuTable &Instance();
88 
89 private:
90  void InitUserData(void *pUserData) override
91  {
92  mpData = static_cast<NoteTrackControlsBase::InitMenuData*>(pUserData);
93  }
94 
96 
97  void OnChangeOctave(wxCommandEvent &);
98 };
99 
101 {
102  static NoteTrackMenuTable instance;
103  return instance;
104 }
105 
106 enum {
107  OnUpOctaveID = 30000,
109 };
110 
112 void NoteTrackMenuTable::OnChangeOctave(wxCommandEvent &event)
113 {
114  NoteTrack *const pTrack = static_cast<NoteTrack*>(mpData->pTrack);
115 
116  wxASSERT(event.GetId() == OnUpOctaveID
117  || event.GetId() == OnDownOctaveID);
118 
119  const bool bDown = (OnDownOctaveID == event.GetId());
120  pTrack->ShiftNoteRange((bDown) ? -12 : 12);
121 
122  AudacityProject *const project = &mpData->project;
123  ProjectHistory::Get( *project )
124  .ModifyState(false);
126 }
127 
129  BeginSection( "Basic" );
130  AppendItem( "Up", OnUpOctaveID, XXO("Up &Octave"), POPUP_MENU_FN( OnChangeOctave ) );
131  AppendItem( "Down", OnDownOctaveID, XXO("Down Octa&ve"), POPUP_MENU_FN( OnChangeOctave ) );
134 
136 {
137 #if defined(USE_MIDI)
139 #else
140  return NULL;
141 #endif
142 }
143 
144 // drawing related
145 #include "../../../../widgets/ASlider.h"
146 #include "../../../../TrackInfo.h"
147 #include "../../../../TrackPanelDrawingContext.h"
148 #include "ViewInfo.h"
149 
151 
152 #ifdef USE_MIDI
153 enum : int {
154  // PRL: was it correct to include the margin?
157 };
158 #endif
159 
160 #include "NoteTrackButtonHandle.h"
161 #include "NoteTrackSliderHandles.h"
162 
163 namespace {
164 void GetMidiControlsHorizontalBounds( const wxRect &rect, wxRect &dest )
165 {
166  dest.x = rect.x + 1; // To center slightly
167  // PRL: TODO: kMidiCellWidth is defined in terms of the other constant
168  // kTrackInfoWidth but I am trying to avoid use of that constant.
169  // Can cell width be computed from dest.width instead?
170  dest.width = kMidiCellWidth * 4;
171 }
172 
174 ( LWSlider *(*Selector)
175  (const wxRect &sliderRect, const NoteTrack *t, bool captured, wxWindow*),
176  wxDC *dc, const wxRect &rect, const Track *pTrack,
177  wxWindow *pParent,
178  bool captured, bool highlight )
179 {
180  wxRect sliderRect = rect;
181  TrackInfo::GetSliderHorizontalBounds( rect.GetTopLeft(), sliderRect );
182  auto nt = static_cast<const NoteTrack*>( pTrack );
183  Selector( sliderRect, nt, captured, pParent )->OnPaint(*dc, highlight);
184 }
185 
186 #ifdef EXPERIMENTAL_MIDI_OUT
187 void VelocitySliderDrawFunction
188 ( TrackPanelDrawingContext &context,
189  const wxRect &rect, const Track *pTrack )
190 {
191  auto dc = &context.dc;
192  auto target = dynamic_cast<VelocitySliderHandle*>( context.target.get() );
193  bool hit = target && target->GetTrack().get() == pTrack;
194  bool captured = hit && target->IsClicked();
195 
196  const auto artist = TrackArtist::Get( context );
197  auto pParent = FindProjectFrame( artist->parent->GetProject() );
198 
200  &NoteTrackControls::VelocitySlider, dc, rect, pTrack,
201  pParent, captured, hit);
202 }
203 #endif
204 
206 ( TrackPanelDrawingContext &context,
207  const wxRect &rect, const Track *pTrack )
208 {
209  auto target = dynamic_cast<NoteTrackButtonHandle*>( context.target.get() );
210  bool hit = target && target->GetTrack().get() == pTrack;
211  auto channel = hit ? target->GetChannel() : -1;
212  auto &dc = context.dc;
213  wxRect midiRect = rect;
214  GetMidiControlsHorizontalBounds(rect, midiRect);
216  ( static_cast<const NoteTrack *>(pTrack), dc, midiRect, channel );
217 }
218 }
219 
220 static const struct NoteTrackTCPLines
222  (TCPLines&)*this =
224  insert( end(), {
227 #ifdef EXPERIMENTAL_MIDI_OUT
229  VelocitySliderDrawFunction },
230 #endif
231  } );
233 
234 void NoteTrackControls::GetVelocityRect(const wxPoint &topleft, wxRect & dest)
235 {
236  TrackInfo::GetSliderHorizontalBounds( topleft, dest );
238  dest.y = topleft.y + results.first;
239  dest.height = results.second;
240 }
241 
242 void NoteTrackControls::GetMidiControlsRect(const wxRect & rect, wxRect & dest)
243 {
244  GetMidiControlsHorizontalBounds( rect, dest );
245  auto results = TrackInfo::CalcItemY(
247  dest.y = rect.y + results.first;
248  dest.height = results.second;
249 }
250 
252 {
254 }
255 
257 {
258  return noteTrackTCPLines;
259 };
260 
261 namespace {
262 
263 #ifdef EXPERIMENTAL_MIDI_OUT
264  std::unique_ptr<LWSlider>
265  gVelocityCaptured
266  , gVelocity
267  ;
268 #endif
269 
270 }
271 
272 #ifdef EXPERIMENTAL_MIDI_OUT
274 (const wxRect &sliderRect, const NoteTrack *t, bool captured, wxWindow *pParent)
275 {
276  static std::once_flag flag;
277  std::call_once( flag, [] {
278  wxCommandEvent dummy;
279  ReCreateVelocitySlider( dummy );
280  wxTheApp->Bind(EVT_THEME_CHANGE, ReCreateVelocitySlider);
281  } );
282 
283  wxPoint pos = sliderRect.GetPosition();
284  float velocity = t ? t->GetVelocity() : 0.0;
285 
286  gVelocity->Move(pos);
287  gVelocity->Set(velocity);
288  gVelocityCaptured->Move(pos);
289  gVelocityCaptured->Set(velocity);
290 
291  auto slider = (captured ? gVelocityCaptured : gVelocity).get();
292  slider->SetParent( pParent );
293  return slider;
294 }
295 #endif
296 
298 {
299  evt.Skip();
300 #ifdef EXPERIMENTAL_MIDI_OUT
301  wxPoint point{ 0, 0 };
302  wxRect sliderRect;
303  GetVelocityRect(point, sliderRect);
304 
305  /* i18n-hint: Title of the Velocity slider, used to adjust the volume of note tracks */
306  gVelocity = std::make_unique<LWSlider>(nullptr, XO("Velocity"),
307  wxPoint(sliderRect.x, sliderRect.y),
308  wxSize(sliderRect.width, sliderRect.height),
309  VEL_SLIDER);
310  gVelocity->SetDefaultValue(0.0);
311  gVelocityCaptured = std::make_unique<LWSlider>(nullptr, XO("Velocity"),
312  wxPoint(sliderRect.x, sliderRect.y),
313  wxSize(sliderRect.width, sliderRect.height),
314  VEL_SLIDER);
315  gVelocityCaptured->SetDefaultValue(0.0);
316 #endif
317 }
318 
321  return [](NoteTrack &track) {
322  return std::make_shared<NoteTrackControls>( track.SharedPointer() );
323  };
324 }
325 
326 #include "../../../ui/TrackView.h"
327 
330  return [](NoteTrack &) {
332  };
333 }
334 
335 #endif
kMidiCellHeight
@ kMidiCellHeight
Definition: NoteTrackControls.cpp:156
ProjectHistory::ModifyState
void ModifyState(bool bWantsAutoSave)
Definition: ProjectHistory.cpp:124
TrackInfo::TCPLine::kItemMidiControlsRect
@ kItemMidiControlsRect
Definition: TrackInfo.h:46
NoteTrackControls::mSoloHandle
std::weak_ptr< SoloButtonHandle > mSoloHandle
Definition: NoteTrackControls.h:40
MuteButtonHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< MuteButtonHandle > &holder, const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject, const std::shared_ptr< Track > &pTrack)
Definition: PlayableTrackButtonHandles.cpp:59
NoteTrackControls::VelocitySlider
static LWSlider * VelocitySlider(const wxRect &sliderRect, const NoteTrack *t, bool captured, wxWindow *pParent)
kTrackInfoSliderHeight
@ kTrackInfoSliderHeight
Definition: ViewInfo.h:109
anonymous_namespace{NoteTrackControls.cpp}::MidiControlsDrawFunction
void MidiControlsDrawFunction(TrackPanelDrawingContext &context, const wxRect &rect, const Track *pTrack)
Definition: NoteTrackControls.cpp:206
TCPLines
TrackInfo::TCPLines TCPLines
Definition: TrackInfo.cpp:101
RefreshCode::RefreshAll
@ RefreshAll
Definition: RefreshCode.h:26
flag
static std::once_flag flag
Definition: WaveformView.cpp:1119
NoteTrack::ShiftNoteRange
void ShiftNoteRange(int offset)
Shifts all notes vertically by the given pitch.
Definition: NoteTrack.cpp:1017
NoteTrackControls::~NoteTrackControls
~NoteTrackControls()
Definition: NoteTrackControls.cpp:37
Project.h
PopupMenuTable
Definition: PopupMenuTable.h:115
CommonTrackControls::StaticTCPLines
static const TCPLines & StaticTCPLines()
Definition: TrackInfo.cpp:122
NoteTrackTCPLines::NoteTrackTCPLines
NoteTrackTCPLines()
Definition: NoteTrackControls.cpp:221
NoteTrack::DrawLabelControls
static void DrawLabelControls(const NoteTrack *pTrack, wxDC &dc, const wxRect &rect, int highlightedChannel=-1)
Definition: NoteTrack.cpp:262
CommonTrackPanelCell::FindTrack
std::shared_ptr< Track > FindTrack()
Definition: CommonTrackPanelCell.h:46
TrackPanelDrawingContext
Definition: TrackPanelDrawingContext.h:22
NoteTrackControls::mMuteHandle
std::weak_ptr< MuteButtonHandle > mMuteHandle
Definition: NoteTrackControls.h:39
NoteTrackTCPLines
Definition: NoteTrackControls.cpp:221
NoteTrackMenuTable
Definition: NoteTrackControls.cpp:80
VEL_SLIDER
#define VEL_SLIDER
Definition: ASlider.h:37
NoteTrackMenuTable::InitUserData
void InitUserData(void *pUserData) override
Called before the menu items are appended.
Definition: NoteTrackControls.cpp:90
TrackInfo::CalcItemY
AUDACITY_DLL_API std::pair< int, int > CalcItemY(const TCPLines &lines, unsigned iItem)
Definition: TrackInfo.cpp:145
XO
#define XO(s)
Definition: Internat.h:31
kTrackInfoBtnSize
@ kTrackInfoBtnSize
Definition: ViewInfo.h:108
TrackPanelDrawingContext::dc
wxDC & dc
Definition: TrackPanelDrawingContext.h:23
CommonTrackControls::InitMenuData::result
unsigned result
Definition: CommonTrackControls.h:39
TrackInfo::TCPLine::kItemVelocity
@ kItemVelocity
Definition: TrackInfo.h:45
NoteTrackControls::ReCreateVelocitySlider
static void ReCreateVelocitySlider(wxEvent &)
Definition: NoteTrackControls.cpp:297
AppendItem
AppendItem("Up", OnUpOctaveID, XXO("Up &Octave"), POPUP_MENU_FN(OnChangeOctave))
TrackPanelMouseState::rect
const wxRect & rect
Definition: TrackPanelMouseEvent.h:39
NoteTrackButtonHandle::GetTrack
std::shared_ptr< NoteTrack > GetTrack() const
Definition: NoteTrackButtonHandle.h:41
OnUpOctaveID
@ OnUpOctaveID
Definition: NoteTrackControls.cpp:107
CommonTrackControls::InitMenuData::project
AudacityProject & project
Definition: CommonTrackControls.h:36
BeginSection
BeginSection("Basic")
NoteTrackMenuTable::Instance
static NoteTrackMenuTable & Instance()
Definition: NoteTrackControls.cpp:100
TrackArtist::Get
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:79
XXO
#define XXO(s)
Definition: Internat.h:44
LWSlider
Lightweight version of ASlider. In other words it does not have a window permanently associated with ...
Definition: ASlider.h:62
CommonTrackControls::HitTest
virtual std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *) override=0
Definition: CommonTrackControls.cpp:36
NoteTrackControls::mVelocityHandle
std::weak_ptr< VelocitySliderHandle > mVelocityHandle
Definition: NoteTrackControls.h:42
UIHandlePtr
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
CommonTrackControls::InitMenuData
Definition: CommonTrackControls.h:34
ViewInfo.h
POPUP_MENU_FN
#define POPUP_MENU_FN(memFn)
Definition: PopupMenuTable.h:324
kMidiCellWidth
@ kMidiCellWidth
Definition: NoteTrackControls.cpp:155
EndSection
EndSection()
kTrackInfoSliderExtra
@ kTrackInfoSliderExtra
Definition: ViewInfo.h:112
NoteTrackMenuTable::mpData
NoteTrackControlsBase::InitMenuData * mpData
Definition: NoteTrackControls.cpp:95
BEGIN_POPUP_MENU
#define BEGIN_POPUP_MENU(HandlerClass)
Definition: PopupMenuTable.h:316
NoteTrackMenuTable::OnChangeOctave
void OnChangeOctave(wxCommandEvent &)
Scrolls the note track up or down by an octave.
Definition: NoteTrackControls.cpp:112
anonymous_namespace{NoteTrackControls.cpp}::SliderDrawFunction
void SliderDrawFunction(LWSlider *(*Selector)(const wxRect &sliderRect, const NoteTrack *t, bool captured, wxWindow *), wxDC *dc, const wxRect &rect, const Track *pTrack, wxWindow *pParent, bool captured, bool highlight)
Definition: NoteTrackControls.cpp:174
NoteTrackSliderHandles.h
SoloButtonHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< SoloButtonHandle > &holder, const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject, const std::shared_ptr< Track > &pTrack)
Definition: PlayableTrackButtonHandles.cpp:115
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:239
TrackInfo::DefaultTrackHeight
AUDACITY_DLL_API unsigned DefaultTrackHeight(const TCPLines &topLines)
Definition: TrackInfo.cpp:565
NoteTrackControls::HitTest
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
Definition: NoteTrackControls.cpp:42
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:92
TrackInfo::TCPLine
Definition: TrackInfo.h:36
Track::GetChannel
virtual ChannelType GetChannel() const
Definition: Track.h:441
TrackPanelMouseState
Definition: TrackPanelMouseEvent.h:28
TrackPanelDrawingContext::target
UIHandlePtr target
Definition: TrackPanelDrawingContext.h:24
noteTrackTCPLines
NoteTrackTCPLines noteTrackTCPLines
AttachedVirtualFunction::Override
For defining overrides of the method.
Definition: AttachedVirtualFunction.h:184
TrackInfo::GetSliderHorizontalBounds
AUDACITY_DLL_API void GetSliderHorizontalBounds(const wxPoint &topleft, wxRect &dest)
Definition: TrackInfo.cpp:487
FindProjectFrame
wxFrame * FindProjectFrame(AudacityProject *project)
Get a pointer to the window associated with a project, or null if the given pointer is null,...
Definition: ProjectWindows.cpp:88
NoteTrackMenuTable::NoteTrackMenuTable
NoteTrackMenuTable()
Definition: NoteTrackControls.cpp:81
NoteTrackButtonHandle.h
NoteTrackControls::mClickHandle
std::weak_ptr< NoteTrackButtonHandle > mClickHandle
Definition: NoteTrackControls.h:41
TCPLine
TrackInfo::TCPLine TCPLine
Definition: NoteTrackControls.cpp:150
NoteTrackControls::GetMidiControlsRect
static void GetMidiControlsRect(const wxRect &rect, wxRect &dest)
Definition: NoteTrackControls.cpp:242
NoteTrackControls::GetVelocityRect
static void GetVelocityRect(const wxPoint &topleft, wxRect &dest)
Definition: NoteTrackControls.cpp:234
CommonTrackControls::InitMenuData::pTrack
Track * pTrack
Definition: CommonTrackControls.h:37
NoteTrackControls::DefaultNoteTrackHeight
static unsigned DefaultNoteTrackHeight()
Definition: NoteTrackControls.cpp:251
kTrackInfoWidth
@ kTrackInfoWidth
Definition: ZoomInfo.h:36
NoteTrackButtonHandle
Definition: NoteTrackButtonHandle.h:22
NoteTrackButtonHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< NoteTrackButtonHandle > &holder, const wxMouseState &state, const wxRect &rect, const std::shared_ptr< NoteTrack > &pTrack)
Definition: NoteTrackButtonHandle.cpp:52
OnDownOctaveID
@ OnDownOctaveID
Definition: NoteTrackControls.cpp:108
NoteTrackControls.h
NoteTrackControls
Definition: NoteTrackControls.h:35
anonymous_namespace{NoteTrackControls.cpp}::GetMidiControlsHorizontalBounds
void GetMidiControlsHorizontalBounds(const wxRect &rect, wxRect &dest)
Definition: NoteTrackControls.cpp:164
TrackPanelMouseState::state
wxMouseState & state
Definition: TrackPanelMouseEvent.h:38
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
NoteTrack
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:67
DEFINE_ATTACHED_VIRTUAL_OVERRIDE
DEFINE_ATTACHED_VIRTUAL_OVERRIDE(DoGetNoteTrackControls)
Definition: NoteTrackControls.cpp:320
kLeftMargin
@ kLeftMargin
Definition: ZoomInfo.h:33
END_POPUP_MENU
#define END_POPUP_MENU()
Definition: PopupMenuTable.h:331
NoteTrackMenuTable::DECLARE_POPUP_MENU
DECLARE_POPUP_MENU(NoteTrackMenuTable)
NoteTrackControls::GetTCPLines
const TCPLines & GetTCPLines() const override
Definition: NoteTrackControls.cpp:256