Vital
Loading...
Searching...
No Matches
transpose_quantize.cpp
Go to the documentation of this file.
1
3
5#include "skin.h"
6#include "fonts.h"
7#include "common.h"
9
10namespace {
16 void setKeyBounds(Rectangle<float>* bounds, float y, float width, float height) {
17 static constexpr int kWhiteKeys = 7;
18 static constexpr int kMissingBlackKey = 2;
19 static constexpr float kHeightDifferenceMult = 0.86602540378f;
20 static constexpr float kPaddingRatio = 0.03f;
21 static constexpr float kOuterPaddingRatio = 0.11f;
22
23 int inner_padding = width * kPaddingRatio;
24 int outer_padding = width * kOuterPaddingRatio;
25 float key_width = (width - (kWhiteKeys - 1) * inner_padding - 2 * outer_padding) * 1.0f / kWhiteKeys;
26 float y_mid = y + (height - key_width) / 2.0f;
27 float height_offset = kHeightDifferenceMult * (key_width + inner_padding);
28 float y_black = y_mid - height_offset / 2.0f;
29 float y_white = y_black + height_offset;
30
31 // White keys
32 for (int i = 0; i < kWhiteKeys; ++i) {
33 float x = outer_padding + (key_width + inner_padding) * i;
34 int index = 2 * i;
35 if (i > kMissingBlackKey)
36 index--;
37
38 bounds[index] = Rectangle<float>(x, y_white, key_width, key_width);
39 }
40
41 // Black keys
42 float black_offset = (key_width + inner_padding) / 2.0f;
43 for (int i = 0; i < kWhiteKeys - 1; ++i) {
44 if (i == kMissingBlackKey)
45 continue;
46
47 float x = outer_padding + black_offset + (key_width + inner_padding) * i;
48 int index = 2 * i;
49 if (i < kMissingBlackKey)
50 index++;
51 bounds[index] = Rectangle<float>(x, y_black, key_width, key_width);
52 }
53 }
54}
55
56TransposeQuantizeCallOut::TransposeQuantizeCallOut(bool* selected, bool* global_snap) :
57 SynthSection("Transpose Quantize Call Out"), selected_(selected), global_snap_(global_snap),
58 hover_index_(-1), enabling_(false), disabling_(false) {
59 global_snap_button_ = std::make_unique<ToggleButton>("Global Snap");
60 global_snap_button_->addListener(this);
61 addAndMakeVisible(global_snap_button_.get());
62 global_snap_button_->setLookAndFeel(TextLookAndFeel::instance());
63 global_snap_button_->setToggleState(*global_snap, dontSendNotification);
64
66}
67
69 int title_height = getHeight() * kTitleHeightRatio;
70 int text_height = title_height * kTitleTextRatio;
71
72 g.setColour(parent_->findColour(Skin::kBodyText, true));
73 g.setFont(Fonts::instance()->proportional_light().withPointHeight(text_height));
74 g.drawText("TRANSPOSE SNAP", 0, 0, getWidth(), title_height, Justification::centred);
75
76 g.setColour(parent_->findColour(Skin::kLabelBackground, true));
78 g.fillRoundedRectangle(global_snap_button_->getBounds().toFloat(), rounding);
79
80 for (int i = 0; i < vital::kNotesPerOctave; ++i) {
81 if (selected_[i]) {
82 if (*global_snap_)
83 g.setColour(parent_->findColour(Skin::kUiActionButton, true));
84 else
85 g.setColour(parent_->findColour(Skin::kWidgetPrimary1, true));
86 }
87 else
88 g.setColour(parent_->findColour(Skin::kLightenScreen, true));
89
90 g.fillEllipse(key_bounds_[i]);
91 }
92
93 if (hover_index_ >= 0) {
94 g.setColour(parent_->findColour(Skin::kLightenScreen, true));
95 g.fillEllipse(key_bounds_[hover_index_]);
96 }
97}
98
100 int title_height = getHeight() * kTitleHeightRatio;
101 int global_height = getHeight() * kGlobalHeightRatio;
102 setKeyBounds(key_bounds_, title_height, getWidth(), getHeight() - title_height - global_height);
103 global_snap_button_->setBounds(0, getHeight() - global_height, getWidth(), global_height);
104 repaint();
105}
106
107void TransposeQuantizeCallOut::mouseDown(const MouseEvent& e) {
108 int hover_index = getHoverIndex(e);
109 enabling_ = false;
110 disabling_ = false;
111 if (hover_index < 0)
112 return;
113
114 if (selected_[hover_index])
115 disabling_ = true;
116 else
117 enabling_ = true;
118
119 selected_[hover_index] = !selected_[hover_index];
120 notify();
121 repaint();
122}
123
124void TransposeQuantizeCallOut::mouseDrag(const MouseEvent& e) {
125 int index = getHoverIndex(e);
126
127 hover_index_ = index;
128 if (hover_index_ < 0)
129 return;
130
131 if (!disabling_ && !enabling_) {
132 if (selected_[hover_index_])
133 disabling_ = true;
134 else
135 enabling_ = true;
136 }
137
138 if (disabling_ && selected_[hover_index_]) {
139 selected_[hover_index_] = false;
140 notify();
141 repaint();
142 }
143 else if (enabling_ && !selected_[hover_index_]) {
144 selected_[hover_index_] = true;
145 notify();
146 repaint();
147 }
148}
149
150void TransposeQuantizeCallOut::mouseMove(const MouseEvent& e) {
151 int hover_index = getHoverIndex(e);
152 if (hover_index != hover_index_) {
153 hover_index_ = hover_index;
154 repaint();
155 }
156}
157
158void TransposeQuantizeCallOut::mouseExit(const MouseEvent& e) {
159 hover_index_ = -1;
160 repaint();
161}
162
163void TransposeQuantizeCallOut::buttonClicked(Button* clicked_button) {
164 *global_snap_ = global_snap_button_->getToggleState();
165 notify();
166 repaint();
167}
168
169int TransposeQuantizeCallOut::getHoverIndex(const MouseEvent& e) {
170 float key_radius = key_bounds_[0].getWidth() / 2.0f;
171 float key_radius2 = key_radius * key_radius;
172 Point<float> position = e.position;
173
174 for (int i = 0; i < vital::kNotesPerOctave; ++i) {
175 if (position.getDistanceSquaredFrom(key_bounds_[i].getCentre()) <= key_radius2)
176 return i;
177 }
178
179 return -1;
180}
181
183 global_snap_(false), hover_(false) {
184 for (int i = 0; i < vital::kNotesPerOctave; ++i)
185 selected_[i] = false;
186}
187
189 for (int i = 0; i < vital::kNotesPerOctave; ++i) {
190 if (selected_[i]) {
191 if (global_snap_)
192 g.setColour(findColour(Skin::kUiActionButton, true));
193 else
194 g.setColour(findColour(Skin::kWidgetPrimary1, true));
195 }
196 else
197 g.setColour(findColour(Skin::kLightenScreen, true));
198
199 g.fillEllipse(key_bounds_[i]);
200 }
201
202 if (hover_) {
203 g.setColour(findColour(Skin::kLightenScreen, true));
204 for (int i = 0; i < vital::kNotesPerOctave; ++i)
205 g.fillEllipse(key_bounds_[i]);
206 }
207}
208
210 setKeyBounds(key_bounds_, 0, getWidth(), getHeight());
212 redrawImage(false);
213}
214
215void TransposeQuantizeButton::mouseDown(const MouseEvent& e) {
216 static constexpr float kWidthMult = 4.0f;
217 static constexpr float kHeightRatio = 0.6f;
218
219 int width = getWidth() * kWidthMult;
220 int height = width * kHeightRatio;
221
222 TransposeQuantizeCallOut* quantize = new TransposeQuantizeCallOut(selected_, &global_snap_);
223 quantize->addQuantizeListener(this);
224 quantize->setSize(width, height);
225 quantize->setParent(findParentComponentOfClass<SynthSection>());
226 quantize->setLookAndFeel(DefaultLookAndFeel::instance());
227
228 CallOutBox& callout = CallOutBox::launchAsynchronously(std::unique_ptr<Component>(quantize), getScreenBounds(), nullptr);
229 callout.setLookAndFeel(DefaultLookAndFeel::instance());
230 callout.setColour(Skin::kBody, findColour(Skin::kBody, true));
231 callout.setColour(Skin::kPopupBorder, findColour(Skin::kPopupBorder, true));
232
233 hover_ = false;
234 redrawImage(true);
235}
236
237void TransposeQuantizeButton::mouseEnter(const MouseEvent& e) {
238 hover_ = true;
239 redrawImage(true);
240}
241
242void TransposeQuantizeButton::mouseExit(const MouseEvent& e) {
243 hover_ = false;
244 redrawImage(true);
245}
246
248 int value = 0;
249 if (global_snap_)
250 value = 1 << vital::kNotesPerOctave;
251
252 for (int i = 0; i < vital::kNotesPerOctave; ++i) {
253 if (selected_[i])
254 value += 1 << i;
255 }
256 return value;
257}
258
260 for (int i = 0; i < vital::kNotesPerOctave; ++i)
261 selected_[i] = (value >> i) & 1;
262
263 global_snap_ = value >> vital::kNotesPerOctave;
264 redrawImage(true);
265}
266
268 for (Listener* listener : listeners_)
269 listener->quantizeUpdated();
270
271 redrawImage(true);
272}
static DefaultLookAndFeel * instance()
Singleton instance accessor.
Definition default_look_and_feel.h:157
static Fonts * instance()
Gets the singleton instance of the Fonts class.
Definition fonts.h:52
virtual void resized() override
Called when the component is resized.
Definition open_gl_component.cpp:121
A component that uses OpenGL to render a cached image of a JUCE component or custom drawing.
Definition open_gl_image_component.h:18
virtual void redrawImage(bool force)
Redraws the image if necessary, creating or updating the internal Image.
Definition open_gl_image_component.cpp:16
@ kLabelBackgroundRounding
Definition skin.h:74
@ kUiActionButton
Definition skin.h:196
@ kPopupBorder
Definition skin.h:145
@ kWidgetPrimary1
Definition skin.h:165
@ kBodyText
Definition skin.h:133
@ kLightenScreen
Definition skin.h:141
@ kLabelBackground
Definition skin.h:135
@ kBody
Definition skin.h:129
@ kOscillator
Definition skin.h:35
Base class for all synthesizer sections, providing UI layout, painting, and interaction logic.
Definition synth_section.h:193
float findValue(Skin::ValueId value_id) const
Finds a value in the skin overrides or from the parent if not found locally.
Definition synth_section.cpp:18
const SynthSection * parent_
Definition synth_section.h:814
void setSkinOverride(Skin::SectionOverride skin_override)
Definition synth_section.h:303
void setParent(const SynthSection *parent)
Sets the parent SynthSection.
Definition synth_section.h:253
static TextLookAndFeel * instance()
Singleton instance access.
Definition text_look_and_feel.h:106
Interface for objects that want to be notified of quantization changes.
Definition transpose_quantize.h:97
int getValue()
Definition transpose_quantize.cpp:247
void mouseEnter(const MouseEvent &e) override
Definition transpose_quantize.cpp:237
TransposeQuantizeButton()
Constructor.
Definition transpose_quantize.cpp:182
void setValue(int value)
Definition transpose_quantize.cpp:259
void quantizeUpdated() override
Called when quantization updates occur in the callout.
Definition transpose_quantize.cpp:267
void mouseDown(const MouseEvent &e) override
Definition transpose_quantize.cpp:215
void mouseExit(const MouseEvent &e) override
Definition transpose_quantize.cpp:242
void resized() override
Handles resizing to compute note layout.
Definition transpose_quantize.cpp:209
void paint(Graphics &g) override
Definition transpose_quantize.cpp:188
A callout component that allows selecting which notes are quantized for transposition.
Definition transpose_quantize.h:17
void buttonClicked(Button *clicked_button) override
Definition transpose_quantize.cpp:163
void mouseMove(const MouseEvent &e) override
Definition transpose_quantize.cpp:150
static constexpr float kTitleHeightRatio
The ratio of the title height to the total height.
Definition transpose_quantize.h:20
void mouseDrag(const MouseEvent &e) override
Definition transpose_quantize.cpp:124
void mouseExit(const MouseEvent &e) override
Definition transpose_quantize.cpp:158
TransposeQuantizeCallOut(bool *selected, bool *global_snap)
Definition transpose_quantize.cpp:56
void resized() override
Resizes and lays out the components within the callout.
Definition transpose_quantize.cpp:99
void mouseDown(const MouseEvent &e) override
Handles mouse events to enable/disable notes.
Definition transpose_quantize.cpp:107
static constexpr float kGlobalHeightRatio
The ratio of the global section height to the total height.
Definition transpose_quantize.h:22
void addQuantizeListener(Listener *listener)
Definition transpose_quantize.h:61
static constexpr float kTitleTextRatio
The ratio of the title text size to the title height.
Definition transpose_quantize.h:24
void paint(Graphics &g) override
Definition transpose_quantize.cpp:68
constexpr int kNotesPerOctave
Number of semitones per octave.
Definition common.h:51
Declares classes for selecting and applying transpose quantization to notes.