Audacity  3.0.3
NoteTrackVRulerControls.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 NoteTrackVRulerControls.cpp
6 
7 Paul Licameli split from TrackPanel.cpp
8 
9 **********************************************************************/
10 
11 
12 
13 #ifdef USE_MIDI
15 
16 #include "NoteTrackVZoomHandle.h"
17 
18 #include "../../../../HitTestResult.h"
19 #include "../../../../NoteTrack.h"
20 #include "../../../../ProjectHistory.h"
21 #include "../../../../RefreshCode.h"
22 #include "../../../../TrackArtist.h"
23 #include "../../../../TrackPanelMouseEvent.h"
24 
25 #include "AColor.h"
26 #include "../../../../TrackPanelDrawingContext.h"
27 #include "../../../../widgets/Ruler.h"
28 
29 #include <wx/dc.h>
30 
33 {
34 }
35 
36 std::vector<UIHandlePtr> NoteTrackVRulerControls::HitTest
37 (const TrackPanelMouseState &st,
38  const AudacityProject *pProject)
39 {
40  std::vector<UIHandlePtr> results;
41  UIHandlePtr result;
42 
43  if ( st.state.GetX() <= st.rect.GetRight() - kGuard ) {
44  auto track = std::static_pointer_cast<NoteTrack>(FindTrack());
46  mVZoomHandle, st.state, track, st.rect);
47  if (result)
48  results.push_back(result);
49  }
50 
51  auto more = TrackVRulerControls::HitTest(st, pProject);
52  std::copy(more.begin(), more.end(), std::back_inserter(results));
53 
54  return results;
55 }
56 
58 (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
59 {
60  using namespace RefreshCode;
61  const wxMouseEvent &event = evt.event;
62 
63  if (!(event.ShiftDown() || event.CmdDown()))
64  return RefreshNone;
65 
66  // Always stop propagation even if the ruler didn't change. The ruler
67  // is a narrow enough target.
68  evt.event.Skip(false);
69 
70  const auto pTrack = FindTrack();
71  if (!pTrack)
72  return RefreshNone;
73 
74  auto steps = evt.steps;
75  const auto nt = static_cast<NoteTrack*>(pTrack.get());
76 
77  if (event.CmdDown() && !event.ShiftDown()) {
78  if (steps > 0)
79  nt->ZoomIn(evt.rect, evt.event.m_y);
80  else
81  nt->ZoomOut(evt.rect, evt.event.m_y);
82  } else if (!event.CmdDown() && event.ShiftDown()) {
83  // Scroll some fixed number of notes, independent of zoom level or track height:
84  static const int movement = 6; // 6 semitones is half an octave
85  nt->ShiftNoteRange((int) (steps * movement));
86  } else {
87  return RefreshNone;
88  }
89 
90  ProjectHistory::Get( *pProject ).ModifyState(false);
91 
92  return RefreshCell | UpdateVRuler;
93 }
94 
96  TrackPanelDrawingContext &context,
97  const wxRect &rect_, unsigned iPass )
98 {
99  TrackVRulerControls::Draw( context, rect_, iPass );
100 
101  // Draw on a later pass like other vertical rulers,
102  // although the bevel is done a little differently
103 
104  if ( iPass == TrackArtist::PassControls ) {
105  // The note track draws a vertical keyboard to label pitches
106  auto track = std::static_pointer_cast<NoteTrack>( FindTrack() );
107  if ( !track )
108  return;
109 
110  auto rect = rect_;
111  --rect.width;
112  --rect.height;
113 
114  bool highlight = false;
115 #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
116  highlight = rect.Contains(context.lastState.GetPosition());
117 #endif
118 
119  const auto artist = TrackArtist::Get( context );
120  UpdateRuler(rect);
121 
122  auto dc = &context.dc;
123 
124  dc->SetPen(highlight ? AColor::uglyPen : *wxTRANSPARENT_PEN);
125  dc->SetBrush(*wxWHITE_BRUSH);
126  wxRect bev = rect;
127  bev.x++;
128  bev.width--;
129  dc->DrawRectangle(bev);
130 
131  rect.y += 1;
132  rect.height -= 1;
133 
134  NoteTrackDisplayData data{ track.get(), rect };
135 
136  wxPen hilitePen;
137  hilitePen.SetColour(120, 120, 120);
138  wxBrush blackKeyBrush;
139  blackKeyBrush.SetColour(70, 70, 70);
140 
141  dc->SetBrush(blackKeyBrush);
142 
143  int fontSize = 10;
144 #ifdef __WXMSW__
145  fontSize = 8;
146 #endif
147 
148  wxFont labelFont(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
149  dc->SetFont(labelFont);
150 
151  int octave = 0;
152  int obottom = data.GetOctaveBottom(octave);
153  int marg = data.GetNoteMargin();
154 
155  while (obottom >= rect.y) {
156  dc->SetPen(*wxBLACK_PEN);
157  for (int white = 0; white < 7; white++) {
158  int pos = data.GetWhitePos(white);
159  if (obottom - pos > rect.y + marg + 1 &&
160  // don't draw too close to margin line -- it's annoying
161  obottom - pos < rect.y + rect.height - marg - 3)
162  AColor::Line(*dc, rect.x, obottom - pos,
163  rect.x + rect.width, obottom - pos);
164  }
165  wxRect br = rect;
166  br.height = data.GetPitchHeight(1);
167  br.x++;
168  br.width = 17;
169  for (int black = 0; black < 5; black++) {
170  br.y = obottom - data.GetBlackPos(black);
171  if (br.y > rect.y + marg - 2 && br.y + br.height < rect.y + rect.height - marg) {
172  dc->SetPen(hilitePen);
173  dc->DrawRectangle(br);
174  dc->SetPen(*wxBLACK_PEN);
175  AColor::Line(*dc,
176  br.x + 1, br.y + br.height - 1,
177  br.x + br.width - 1, br.y + br.height - 1);
178  AColor::Line(*dc,
179  br.x + br.width - 1, br.y + 1,
180  br.x + br.width - 1, br.y + br.height - 1);
181  }
182  }
183 
184  if (octave >= 1 && octave <= 10) {
185  wxString s;
186  // ISO standard: A440 is in the 4th octave, denoted
187  // A4 <- the "4" should be a subscript.
188  s.Printf(wxT("C%d"), octave - 1);
189  wxCoord width, height;
190  dc->GetTextExtent(s, &width, &height);
191  if (obottom - height + 4 > rect.y &&
192  obottom + 4 < rect.y + rect.height) {
193  dc->SetTextForeground(wxColour(60, 60, 255));
194  dc->DrawText(s, rect.x + rect.width - width,
195  obottom - height + 2);
196  }
197  }
198  obottom = data.GetOctaveBottom(++octave);
199  }
200  // draw lines delineating the out-of-bounds margins
201  dc->SetPen(*wxBLACK_PEN);
202  // you would think the -1 offset here should be -2 to match the
203  // adjustment to rect.y (see above), but -1 produces correct output
204  AColor::Line(*dc, rect.x, rect.y + marg - 1, rect.x + rect.width, rect.y + marg - 1);
205  // since the margin gives us the bottom of the line,
206  // the extra -1 gets us to the top
207  AColor::Line(*dc, rect.x, rect.y + rect.height - marg - 1,
208  rect.x + rect.width, rect.y + rect.height - marg - 1);
209 
210  }
211 }
212 
213 
214 void NoteTrackVRulerControls::UpdateRuler( const wxRect &rect )
215 {
216  // The note track isn't drawing a ruler at all!
217  // But it needs to!
218 
219  const auto nt = std::static_pointer_cast< NoteTrack >( FindTrack() );
220  if (!nt)
221  return;
222 
223  static Ruler ruler;
224  const auto vruler = &ruler;
225 
226  vruler->SetBounds(rect.x, rect.y, rect.x + 1, rect.y + rect.height-1);
227  vruler->SetOrientation(wxVERTICAL);
228 
229  vruler->GetMaxSize( &nt->vrulerSize.x, &nt->vrulerSize.y );
230 }
231 #endif
ProjectHistory::ModifyState
void ModifyState(bool bWantsAutoSave)
Definition: ProjectHistory.cpp:124
NoteTrackVZoomHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< NoteTrackVZoomHandle > &holder, const wxMouseState &state, const std::shared_ptr< NoteTrack > &pTrack, const wxRect &rect)
Definition: NoteTrackVZoomHandle.cpp:91
NoteTrackVRulerControls::HandleWheelRotation
unsigned HandleWheelRotation(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: NoteTrackVRulerControls.cpp:58
TrackPanelMouseEvent::rect
const wxRect & rect
Definition: TrackPanelMouseEvent.h:59
RefreshCode::RefreshNone
@ RefreshNone
Definition: RefreshCode.h:21
CommonTrackPanelCell::FindTrack
std::shared_ptr< Track > FindTrack()
Definition: CommonTrackPanelCell.h:46
TrackPanelDrawingContext
Definition: TrackPanelDrawingContext.h:22
AColor::Line
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:109
NoteTrackVRulerControls::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: NoteTrackVRulerControls.cpp:95
NoteTrackVRulerControls::mVZoomHandle
std::weak_ptr< NoteTrackVZoomHandle > mVZoomHandle
Definition: NoteTrackVRulerControls.h:46
TrackPanelDrawingContext::dc
wxDC & dc
Definition: TrackPanelDrawingContext.h:23
NoteTrackVRulerControls::HitTest
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
Definition: NoteTrackVRulerControls.cpp:37
anonymous_namespace{TimeTrackVRulerControls.cpp}::ruler
Ruler & ruler()
Definition: TimeTrackVRulerControls.cpp:34
TrackPanelMouseState::rect
const wxRect & rect
Definition: TrackPanelMouseEvent.h:39
NoteTrackVRulerControls.h
TrackArtist::Get
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:79
NoteTrackDisplayData
Data used to display a note track.
Definition: NoteTrack.h:231
NoteTrackVRulerControls::UpdateRuler
void UpdateRuler(const wxRect &rect) override
Definition: NoteTrackVRulerControls.cpp:214
Ruler
Used to display a Ruler.
Definition: Ruler.h:26
TrackPanelDrawingContext::lastState
wxMouseState lastState
Definition: TrackPanelDrawingContext.h:25
NoteTrackVZoomHandle.h
UIHandlePtr
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
TrackArtist::PassControls
@ PassControls
Definition: TrackArtist.h:84
RefreshCode::UpdateVRuler
@ UpdateVRuler
Definition: RefreshCode.h:30
AColor::uglyPen
static wxPen uglyPen
Definition: AColor.h:130
RefreshCode::RefreshCell
@ RefreshCell
Definition: RefreshCode.h:24
kGuard
const int kGuard
Definition: TrackVRulerControls.h:20
TrackVRulerControls::HitTest
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
Definition: TrackVRulerControls.cpp:55
NoteTrackVRulerControls::~NoteTrackVRulerControls
~NoteTrackVRulerControls()
Definition: NoteTrackVRulerControls.cpp:32
TrackVRulerControls::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: TrackVRulerControls.cpp:97
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
TrackPanelMouseEvent
Definition: TrackPanelMouseEvent.h:46
NoteTrack::ZoomIn
void ZoomIn(const wxRect &rect, int y)
Zooms in a constant factor (subject to zoom limits)
Definition: NoteTrack.h:140
Ruler::SetBounds
void SetBounds(int left, int top, int right, int bottom)
Definition: Ruler.cpp:332
TrackPanelMouseState
Definition: TrackPanelMouseEvent.h:28
RefreshCode
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
AColor.h
TrackPanelMouseEvent::event
wxMouseEvent & event
Definition: TrackPanelMouseEvent.h:58
TrackPanelMouseState::state
wxMouseState & state
Definition: TrackPanelMouseEvent.h:38
TrackPanelMouseEvent::steps
double steps
Definition: TrackPanelMouseEvent.h:62
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