1 /**
2 * File name: top_bar.cpp
3 * Project: Geonkick (A kick synthesizer)
4 *
5 * Copyright (C) 2018 Iurie Nistor (http://iuriepage.wordpress.com)
6 *
7 * This file is part of Geonkick.
8 *
9 * GeonKick is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include <cmath> // for std::fabs() from redkite/RkTransition.h
25 #include "top_bar.h"
26 #include "geonkick_button.h"
27 #include "preset_browser_model.h"
28 #include "preset_browser_view.h"
29 #include "ViewState.h"
30 #include "kit_model.h"
31 #include "percussion_model.h"
32 #include "MidiKeyWidget.h"
33
34 #include <RkLabel.h>
35 #include <RkButton.h>
36 #include <RkTransition.h>
37 #include <RkContainer.h>
38
39 RK_DECLARE_IMAGE_RC(separator);
40 RK_DECLARE_IMAGE_RC(logo);
41 RK_DECLARE_IMAGE_RC(open);
42 RK_DECLARE_IMAGE_RC(open_hover);
43 RK_DECLARE_IMAGE_RC(save);
44 RK_DECLARE_IMAGE_RC(save_hover);
45 RK_DECLARE_IMAGE_RC(export);
46 RK_DECLARE_IMAGE_RC(export_hover);
47 RK_DECLARE_IMAGE_RC(reset);
48 RK_DECLARE_IMAGE_RC(reset_hover);
49 RK_DECLARE_IMAGE_RC(reset_active);
50 RK_DECLARE_IMAGE_RC(play);
51 RK_DECLARE_IMAGE_RC(play_pressed);
52 RK_DECLARE_IMAGE_RC(play_hover);
53 RK_DECLARE_IMAGE_RC(layer1);
54 RK_DECLARE_IMAGE_RC(layer2);
55 RK_DECLARE_IMAGE_RC(layer3);
56 RK_DECLARE_IMAGE_RC(layer1_disabled);
57 RK_DECLARE_IMAGE_RC(layer2_disabled);
58 RK_DECLARE_IMAGE_RC(layer3_disabled);
59 RK_DECLARE_IMAGE_RC(layer1_hover);
60 RK_DECLARE_IMAGE_RC(layer2_hover);
61 RK_DECLARE_IMAGE_RC(layer3_hover);
62 RK_DECLARE_IMAGE_RC(tune_checkbox_on);
63 RK_DECLARE_IMAGE_RC(tune_checkbox_off);
64 RK_DECLARE_IMAGE_RC(tune_checkbox_hover);
65 RK_DECLARE_IMAGE_RC(topmenu_controls_active);
66 RK_DECLARE_IMAGE_RC(topmenu_controls_hover);
67 RK_DECLARE_IMAGE_RC(topmenu_controls_off);
68 RK_DECLARE_IMAGE_RC(topmenu_midi_off);
69 RK_DECLARE_IMAGE_RC(topmenu_midi_active);
70 RK_DECLARE_IMAGE_RC(topmenu_midi_hover);
71 #ifndef GEONKICK_SINGLE
72 RK_DECLARE_IMAGE_RC(topmenu_kit_active);
73 RK_DECLARE_IMAGE_RC(topmenu_kit_hover);
74 RK_DECLARE_IMAGE_RC(topmenu_kit_off);
75 #endif // GEONKICK_SINGLE
76 RK_DECLARE_IMAGE_RC(topmenu_presets_active);
77 RK_DECLARE_IMAGE_RC(topmenu_presets_hover);
78 RK_DECLARE_IMAGE_RC(topmenu_presets_off);
79 RK_DECLARE_IMAGE_RC(topmenu_samples_active);
80 RK_DECLARE_IMAGE_RC(topmenu_samples_hover);
81 RK_DECLARE_IMAGE_RC(topmenu_samples_off);
82
TopBar(GeonkickWidget * parent,KitModel * model)83 TopBar::TopBar(GeonkickWidget *parent, KitModel *model)
84 : GeonkickWidget(parent)
85 , kitModel{model}
86 , openFileButton{nullptr}
87 , saveFileButton{nullptr}
88 , exportFileButton{nullptr}
89 , presetNameLabel{nullptr}
90 , layer1Button{nullptr}
91 , layer2Button{nullptr}
92 , layer3Button{nullptr}
93 , controlsButton{nullptr}
94 , midiKeyButton{nullptr}
95 #ifndef GEONKICK_SINGLE
96 , kitButton{nullptr}
97 #endif // GEONKICK_SINGLE
98 , presetsButton{nullptr}
99 , samplesButton{nullptr}
100 {
101 setFixedSize({parent->width(), 30});
102 auto mainLayout = new RkContainer(this);
103 mainLayout->setSize(size());
104
105 auto logo = new RkLabel(this);
106 RkImage image(62, 10, RK_IMAGE_RC(logo));
107 logo->setSize(image.width(), image.height());
108 logo->setBackgroundColor(68, 68, 70);
109 logo->setImage(image);
110 logo->show();
111 mainLayout->addWidget(logo);
112 addSeparator(mainLayout, 10);
113
114 openFileButton = new GeonkickButton(this);
115 openFileButton->show();
116 openFileButton->setSize(26, 10);
117 openFileButton->setType(RkButton::ButtonType::ButtonCheckable);
118 openFileButton->setImage(RkImage(openFileButton->size(), RK_IMAGE_RC(open)),
119 RkButton::State::Unpressed);
120 openFileButton->setImage(RkImage(openFileButton->size(), RK_IMAGE_RC(open_hover)),
121 RkButton::State::UnpressedHover);
122 openFileButton->setImage(RkImage(openFileButton->size(), RK_IMAGE_RC(open_hover)),
123 RkButton::State::Pressed);
__anon175a8eb20102()124 RK_ACT_BINDL(openFileButton, pressed, RK_ACT_ARGS(), [=](){openFileButton->setPressed(false);
125 action openFile();});
126 mainLayout->addWidget(openFileButton);
127 addSeparator(mainLayout, 10);
128
129 saveFileButton = new GeonkickButton(this);
130 saveFileButton->setSize(23, 10);
131 saveFileButton->setType(RkButton::ButtonType::ButtonCheckable);
132 saveFileButton->setImage(RkImage(saveFileButton->size(), RK_IMAGE_RC(save)),
133 RkButton::State::Unpressed);
134 saveFileButton->setImage(RkImage(saveFileButton->size(), RK_IMAGE_RC(save_hover)),
135 RkButton::State::UnpressedHover);
136 saveFileButton->setImage(RkImage(saveFileButton->size(), RK_IMAGE_RC(save_hover)),
137 RkButton::State::Pressed);
__anon175a8eb20202()138 RK_ACT_BINDL(saveFileButton, pressed, RK_ACT_ARGS(), [=](){saveFileButton->setPressed(false);
139 action saveFile();});
140 mainLayout->addWidget(saveFileButton);
141 addSeparator(mainLayout, 10);
142
143 exportFileButton = new GeonkickButton(this);
144 exportFileButton->setSize(29, 10);
145 saveFileButton->setType(RkButton::ButtonType::ButtonCheckable);
146 exportFileButton->setImage(RkImage(exportFileButton->size(), RK_IMAGE_RC(export)),
147 RkButton::State::Unpressed);
148 exportFileButton->setImage(RkImage(exportFileButton->size(), RK_IMAGE_RC(export_hover)),
149 RkButton::State::UnpressedHover);
150 exportFileButton->setImage(RkImage(exportFileButton->size(), RK_IMAGE_RC(export_hover)),
151 RkButton::State::Pressed);
__anon175a8eb20302()152 RK_ACT_BINDL(exportFileButton, pressed, RK_ACT_ARGS(), [=](){exportFileButton->setPressed(false);
153 action openExport();});
154 mainLayout->addWidget(exportFileButton);
155 addSeparator(mainLayout, 10);
156
157 auto playButton = new RkButton(this);
158 playButton->setType(RkButton::ButtonType::ButtonPush);
159 playButton->setSize(43, 18);
160 playButton->setImage(RkImage(playButton->size(), RK_IMAGE_RC(play)),
161 RkButton::State::Unpressed);
162 playButton->setImage(RkImage(playButton->size(), RK_IMAGE_RC(play_hover)),
163 RkButton::State::UnpressedHover);
164 playButton->setImage(RkImage(playButton->size(), RK_IMAGE_RC(play_pressed)),
165 RkButton::State::Pressed);
166 RK_ACT_BIND(playButton, pressed, RK_ACT_ARGS(), kitModel->api(), playKick());
167 playButton->show();
168 mainLayout->addWidget(playButton);
169 addSeparator(mainLayout, 10);
170
171 createLyersButtons(mainLayout);
172 addSeparator(mainLayout, 10);
173
174 auto resetButton = new RkButton(this);
175 resetButton->setSize(33, 18);
176 resetButton->setType(RkButton::ButtonType::ButtonPush);
177 resetButton->setImage(RkImage(resetButton->size(), RK_IMAGE_RC(reset)),
178 RkButton::State::Unpressed);
179 resetButton->setImage(RkImage(resetButton->size(), RK_IMAGE_RC(reset_hover)),
180 RkButton::State::UnpressedHover);
181 resetButton->setImage(RkImage(resetButton->size(), RK_IMAGE_RC(reset_active)),
182 RkButton::State::Pressed);
183 resetButton->show();
184 RK_ACT_BIND(resetButton, pressed, RK_ACT_ARGS(), this, resetToDefault());
185 mainLayout->addWidget(resetButton);
186
187 addSeparator(mainLayout, 10);
188
189 tuneCheckbox = new GeonkickButton(this);
190 tuneCheckbox->setCheckable(true);
191 tuneCheckbox->setFixedSize(33, 18);
192 tuneCheckbox->setImage(RkImage(tuneCheckbox->size(), RK_IMAGE_RC(tune_checkbox_off)),
193 RkButton::State::Unpressed);
194 tuneCheckbox->setImage(RkImage(tuneCheckbox->size(), RK_IMAGE_RC(tune_checkbox_on)),
195 RkButton::State::Pressed);
196 tuneCheckbox->setImage(RkImage(tuneCheckbox->size(), RK_IMAGE_RC(tune_checkbox_hover)),
197 RkButton::State::PressedHover);
198 tuneCheckbox->setImage(RkImage(tuneCheckbox->size(), RK_IMAGE_RC(tune_checkbox_hover)),
199 RkButton::State::UnpressedHover);
200 tuneCheckbox->show();
201 RK_ACT_BIND(tuneCheckbox, toggled, RK_ACT_ARGS(bool b), kitModel->api(),
202 tuneAudioOutput(kitModel->api()->currentPercussion(), b));
203 mainLayout->addWidget(tuneCheckbox);
204 addSeparator(mainLayout, 10);
205
206 presetNameLabel = new RkLabel(this);
207 presetNameLabel->setBackgroundColor(background());
208 presetNameLabel->setTextColor({210, 226, 226, 140});
209 auto font = presetNameLabel->font();
210 font.setSize(10);
211 presetNameLabel->setFont(font);
212 presetNameLabel->setSize(80, 30);
213 presetNameLabel->show();
214 mainLayout->addWidget(presetNameLabel);
215
216 addSeparator(mainLayout);
217 midiKeyButton = new GeonkickButton(this);
218 midiKeyButton->setTextColor({200, 200, 200});
219 midiKeyButton->setType(RkButton::ButtonType::ButtonUncheckable);
220 midiKeyButton->setSize(36, 20);
221 midiKeyButton->setImage(RkImage(midiKeyButton->size(), RK_IMAGE_RC(topmenu_midi_off)),
222 RkButton::State::Unpressed);
223 midiKeyButton->setImage(RkImage(midiKeyButton->size(), RK_IMAGE_RC(topmenu_midi_active)),
224 RkButton::State::Pressed);
225 midiKeyButton->setImage(RkImage(midiKeyButton->size(), RK_IMAGE_RC(topmenu_midi_hover)),
226 RkButton::State::UnpressedHover);
227 RK_ACT_BIND(midiKeyButton, toggled,
228 RK_ACT_ARGS(bool pressed),
229 this,
230 showMidiPopup());
231 mainLayout->addWidget(midiKeyButton);
232
233 // Controls button
234 addSeparator(mainLayout);
235 controlsButton = new GeonkickButton(this);
236 controlsButton->setPressed(viewState()->getMainView() == ViewState::View::Controls);
237 controlsButton->setFixedSize(54, 20);
238 controlsButton->setImage(RkImage(controlsButton->size(), RK_IMAGE_RC(topmenu_controls_off)),
239 RkButton::State::Unpressed);
240 controlsButton->setImage(RkImage(controlsButton->size(), RK_IMAGE_RC(topmenu_controls_active)),
241 RkButton::State::Pressed);
242 controlsButton->setImage(RkImage(controlsButton->size(), RK_IMAGE_RC(topmenu_controls_hover)),
243 RkButton::State::UnpressedHover);
244 controlsButton->show();
245 mainLayout->addWidget(controlsButton);
246 RK_ACT_BIND(controlsButton, pressed, RK_ACT_ARGS(),
247 viewState(), setMainView(ViewState::View::Controls));
248 RK_ACT_BIND(viewState(), mainViewChanged, RK_ACT_ARGS(ViewState::View view),
249 controlsButton, setPressed(view == ViewState::View::Controls));
250
251 #ifndef GEONKICK_SINGLE
252 // Kit button
253 addSeparator(mainLayout);
254 kitButton = new GeonkickButton(this);
255 kitButton->setPressed(viewState()->getMainView() == ViewState::View::Kit);
256 kitButton->setFixedSize(54, 20);
257 kitButton->setImage(RkImage(kitButton->size(), RK_IMAGE_RC(topmenu_kit_off)),
258 RkButton::State::Unpressed);
259 kitButton->setImage(RkImage(kitButton->size(), RK_IMAGE_RC(topmenu_kit_active)),
260 RkButton::State::Pressed);
261 kitButton->setImage(RkImage(kitButton->size(), RK_IMAGE_RC(topmenu_kit_hover)),
262 RkButton::State::UnpressedHover);
263 kitButton->show();
264 RK_ACT_BIND(kitButton, pressed, RK_ACT_ARGS(),
265 viewState(), setMainView(ViewState::View::Kit));
266 RK_ACT_BIND(viewState(), mainViewChanged, RK_ACT_ARGS(ViewState::View view),
267 kitButton, setPressed(view == ViewState::View::Kit));
268 mainLayout->addWidget(kitButton);
269 #endif // GEONKICK_SINGLE
270
271 // Presets button
272 addSeparator(mainLayout);
273 presetsButton = new GeonkickButton(this);
274 presetsButton->setPressed(viewState()->getMainView() == ViewState::View::Presets);
275 presetsButton->setFixedSize(54, 20);
276 presetsButton->setImage(RkImage(presetsButton->size(), RK_IMAGE_RC(topmenu_presets_off)),
277 RkButton::State::Unpressed);
278 presetsButton->setImage(RkImage(presetsButton->size(), RK_IMAGE_RC(topmenu_presets_active)),
279 RkButton::State::Pressed);
280 presetsButton->setImage(RkImage(presetsButton->size(), RK_IMAGE_RC(topmenu_presets_hover)),
281 RkButton::State::UnpressedHover);
282 presetsButton->show();
283 RK_ACT_BIND(presetsButton, pressed, RK_ACT_ARGS(),
284 viewState(), setMainView(ViewState::View::Presets));
285 RK_ACT_BIND(viewState(), mainViewChanged, RK_ACT_ARGS(ViewState::View view),
286 presetsButton, setPressed(view == ViewState::View::Presets));
287 mainLayout->addWidget(presetsButton);
288
289 // Samples button
290 addSeparator(mainLayout);
291 samplesButton = new GeonkickButton(this);
292 samplesButton->setPressed(viewState()->getMainView() == ViewState::View::Samples);
293 samplesButton->setFixedSize(54, 20);
294 samplesButton->setImage(RkImage(samplesButton->size(), RK_IMAGE_RC(topmenu_samples_off)),
295 RkButton::State::Unpressed);
296 samplesButton->setImage(RkImage(samplesButton->size(), RK_IMAGE_RC(topmenu_samples_active)),
297 RkButton::State::Pressed);
298 samplesButton->setImage(RkImage(samplesButton->size(), RK_IMAGE_RC(topmenu_samples_hover)),
299 RkButton::State::UnpressedHover);
300 samplesButton->show();
301 RK_ACT_BIND(samplesButton, pressed, RK_ACT_ARGS(),
302 viewState(), setMainView(ViewState::View::Samples));
303 RK_ACT_BIND(viewState(), mainViewChanged, RK_ACT_ARGS(ViewState::View view),
304 samplesButton, setPressed(view == ViewState::View::Samples));
305 mainLayout->addWidget(samplesButton);
306
307 RK_ACT_BIND(kitModel, modelUpdated, RK_ACT_ARGS(), this, updateGui());
308 RK_ACT_BINDL(kitModel, percussionUpdated, RK_ACT_ARGS(PercussionModel* model),
__anon175a8eb20402(PercussionModel* model) 309 [=](PercussionModel* model) {
310 if (model->isSelected())
311 updateGui();
312 } );
313 updateGui();
314 }
315
addSeparator(RkContainer * mainLayout,int width)316 void TopBar::addSeparator(RkContainer *mainLayout, int width)
317 {
318 mainLayout->addSpace(width);
319 auto separator = new RkLabel(this);
320 separator->setSize(2, 21);
321 separator->setBackgroundColor(68, 68, 70);
322 separator->setImage(RkImage(separator->size(), RK_IMAGE_RC(separator)));
323 separator->show();
324 mainLayout->addWidget(separator);
325 mainLayout->addSpace(width);
326 }
327
createLyersButtons(RkContainer * mainLayout)328 void TopBar::createLyersButtons(RkContainer *mainLayout)
329 {
330 layer1Button = new GeonkickButton(this);
331 layer1Button->setBackgroundColor(background());
332 layer1Button->setSize(24, 18);
333 layer1Button->setImage(RkImage(layer1Button->size(), RK_IMAGE_RC(layer1_disabled)),
334 RkButton::State::Unpressed);
335 layer1Button->setImage(RkImage(layer1Button->size(), RK_IMAGE_RC(layer1)),
336 RkButton::State::Pressed);
337 layer1Button->setImage(RkImage(layer1Button->size(), RK_IMAGE_RC(layer1_hover)),
338 RkButton::State::PressedHover);
339 layer1Button->setImage(RkImage(layer1Button->size(), RK_IMAGE_RC(layer1_hover)),
340 RkButton::State::UnpressedHover);
341
342 layer1Button->setCheckable(true);
343 mainLayout->addWidget(layer1Button);
344 mainLayout->addSpace(2);
345
346 layer2Button = new GeonkickButton(this);
347 layer2Button->setBackgroundColor(background());
348 layer2Button->setSize(24, 18);
349 layer2Button->setImage(RkImage(layer2Button->size(), RK_IMAGE_RC(layer2_disabled)),
350 RkButton::State::Unpressed);
351 layer2Button->setImage(RkImage(layer2Button->size(), RK_IMAGE_RC(layer2)),
352 RkButton::State::Pressed);
353 layer2Button->setImage(RkImage(layer2Button->size(), RK_IMAGE_RC(layer2_hover)),
354 RkButton::State::PressedHover);
355 layer2Button->setImage(RkImage(layer2Button->size(), RK_IMAGE_RC(layer2_hover)),
356 RkButton::State::UnpressedHover);
357
358 layer2Button->setCheckable(true);
359 mainLayout->addWidget(layer2Button);
360 mainLayout->addSpace(2);
361
362 layer3Button = new GeonkickButton(this);
363 layer3Button->setBackgroundColor(background());
364 layer3Button->setSize(24, 18);
365 layer3Button->setImage(RkImage(layer3Button->size(), RK_IMAGE_RC(layer3_disabled)),
366 RkButton::State::Unpressed);
367 layer3Button->setImage(RkImage(layer3Button->size(), RK_IMAGE_RC(layer3)),
368 RkButton::State::Pressed);
369 layer3Button->setImage(RkImage(layer3Button->size(), RK_IMAGE_RC(layer3_hover)),
370 RkButton::State::PressedHover);
371 layer3Button->setImage(RkImage(layer3Button->size(), RK_IMAGE_RC(layer3_hover)),
372 RkButton::State::UnpressedHover);
373
374 layer3Button->setCheckable(true);
375 mainLayout->addWidget(layer3Button);
376
377 RK_ACT_BIND(layer1Button, toggled, RK_ACT_ARGS(bool b),
378 kitModel->api(), enbaleLayer(GeonkickApi::Layer::Layer1, b));
379 RK_ACT_BIND(layer3Button, toggled, RK_ACT_ARGS(bool b),
380 kitModel->api(), enbaleLayer(GeonkickApi::Layer::Layer3, b));
381 RK_ACT_BIND(layer2Button, toggled, RK_ACT_ARGS(bool b),
382 kitModel->api(), enbaleLayer(GeonkickApi::Layer::Layer2, b));
383 }
384
setPresetName(const std::string & name)385 void TopBar::setPresetName(const std::string &name)
386 {
387 if (name.size() > 20) {
388 std::string preset = name;
389 preset.resize(15);
390 preset += "...";
391 presetNameLabel->setText(preset);
392 } else {
393 presetNameLabel->setText(name);
394 }
395 }
396
updateGui()397 void TopBar::updateGui()
398 {
399 auto api = kitModel->api();
400 layer1Button->setPressed(api->isLayerEnabled(GeonkickApi::Layer::Layer1));
401 layer2Button->setPressed(api->isLayerEnabled(GeonkickApi::Layer::Layer2));
402 layer3Button->setPressed(api->isLayerEnabled(GeonkickApi::Layer::Layer3));
403 tuneCheckbox->setPressed(api->isAudioOutputTuned(api->currentPercussion()));
404 setPresetName(kitModel->currentPercussion()->name());
405 midiKeyButton->setText(MidiKeyWidget::midiKeyToNote(kitModel->currentPercussion()->key()));
406 }
407
showMidiPopup()408 void TopBar::showMidiPopup()
409 {
410 auto midiPopup = new MidiKeyWidget(dynamic_cast<GeonkickWidget*>(getTopWidget()),
411 kitModel->currentPercussion());
412 midiPopup->setPosition(midiKeyButton->x() - 170, y() + 35);
413 RK_ACT_BIND(midiPopup,
414 isAboutToClose,
415 RK_ACT_ARGS(),
416 midiKeyButton,
417 setPressed(false));
418 midiPopup->show();
419 }
420