1 /**
2 * File name: preset_browser_view.h
3 * Project: Geonkick (A percussion synthesizer)
4 *
5 * Copyright (C) 2020 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 "preset_browser_view.h"
25 #include "preset_browser_model.h"
26
27 #include <RkPainter.h>
28 #include <RkImage.h>
29 #include <RkEvent.h>
30 #include <RkButton.h>
31 #include <RkContainer.h>
32
33 RK_DECLARE_IMAGE_RC(next_page);
34 RK_DECLARE_IMAGE_RC(next_page_hover);
35 RK_DECLARE_IMAGE_RC(next_page_on);
36 RK_DECLARE_IMAGE_RC(prev_page);
37 RK_DECLARE_IMAGE_RC(prev_page_hover);
38 RK_DECLARE_IMAGE_RC(prev_page_on);
39
PresetBrowserView(GeonkickWidget * parent,PresetBrowserModel * model)40 PresetBrowserView::PresetBrowserView(GeonkickWidget *parent,
41 PresetBrowserModel* model)
42 : GeonkickWidget(parent)
43 , browserModel{model}
44 , topPadding{15}
45 , leftPadding{5}
46 , columnWidth{150}
47 , rowHeight{20}
48 , overRow{-1}
49 , overColumn{-1}
50 , nextPresetPageButton{nullptr}
51 , prevPresetPageButton{nullptr}
52 , nextFolderPageButton{nullptr}
53 , prevFolderPageButton{nullptr}
54 , bottomContainer{nullptr}
55 {
56 setSize(620, 290);
57 RK_ACT_BIND(browserModel, folderSelected, RK_ACT_ARGS(PresetFolder*), this, update());
58 RK_ACT_BIND(browserModel, presetSelected, RK_ACT_ARGS(Preset*), this, update());
59 RK_ACT_BIND(browserModel, presetPageChanged, RK_ACT_ARGS(), this, updatePageButtons());
60 RK_ACT_BIND(browserModel, folderPageChanged, RK_ACT_ARGS(), this, updatePageButtons());
61 RK_ACT_BIND(browserModel, folderSelected, RK_ACT_ARGS(PresetFolder*), this, updatePageButtons());
62 RK_ACT_BIND(browserModel, presetSelected, RK_ACT_ARGS(Preset*), this, updatePageButtons());
63
64 bottomContainer = new RkContainer(this);
65 bottomContainer->setSize({width(), 24});
66 bottomContainer->setPosition({0, height() - 24 - 5});
67 bottomContainer->setHiddenTakesPlace();
68
69 bottomContainer->addSpace((leftPadding + columnWidth) - 2 * 24 - 10);
70 nextFolderPageButton = new RkButton(this);
71 nextFolderPageButton->setType(RkButton::ButtonType::ButtonPush);
72 nextFolderPageButton->setSize(24, 24);
73 nextFolderPageButton->setImage(RkImage(nextFolderPageButton->size(), RK_IMAGE_RC(next_page)),
74 RkButton::State::Unpressed);
75 nextFolderPageButton->setImage(RkImage(nextFolderPageButton->size(), RK_IMAGE_RC(next_page_hover)),
76 RkButton::State::UnpressedHover);
77 nextFolderPageButton->setImage(RkImage(nextFolderPageButton->size(), RK_IMAGE_RC(next_page_on)),
78 RkButton::State::Pressed);
79 RK_ACT_BIND(nextFolderPageButton, pressed, RK_ACT_ARGS(), browserModel, folderNextPage());
80
81 prevFolderPageButton = new RkButton(this);
82 prevFolderPageButton->setType(RkButton::ButtonType::ButtonPush);
83 prevFolderPageButton->setSize(24, 24);
84 prevFolderPageButton->setImage(RkImage(prevFolderPageButton->size(), RK_IMAGE_RC(prev_page)),
85 RkButton::State::Unpressed);
86 prevFolderPageButton->setImage(RkImage(prevFolderPageButton->size(), RK_IMAGE_RC(prev_page_hover)),
87 RkButton::State::UnpressedHover);
88 prevFolderPageButton->setImage(RkImage(prevFolderPageButton->size(), RK_IMAGE_RC(prev_page_on)),
89 RkButton::State::Pressed);
90 RK_ACT_BIND(prevFolderPageButton, pressed, RK_ACT_ARGS(), browserModel, folderPreviousPage());
91 bottomContainer->addWidget(prevFolderPageButton);
92 bottomContainer->addSpace(5);
93 bottomContainer->addWidget(nextFolderPageButton);
94
95 bottomContainer->addSpace(10, Rk::Alignment::AlignRight);
96 nextPresetPageButton = new RkButton(this);
97 nextPresetPageButton->setType(RkButton::ButtonType::ButtonPush);
98 nextPresetPageButton->setSize(24, 24);
99 nextPresetPageButton->setImage(RkImage(nextPresetPageButton->size(), RK_IMAGE_RC(next_page)),
100 RkButton::State::Unpressed);
101 nextPresetPageButton->setImage(RkImage(nextPresetPageButton->size(), RK_IMAGE_RC(next_page_hover)),
102 RkButton::State::UnpressedHover);
103 nextPresetPageButton->setImage(RkImage(nextPresetPageButton->size(), RK_IMAGE_RC(next_page_on)),
104 RkButton::State::Pressed);
105 RK_ACT_BIND(nextPresetPageButton, pressed, RK_ACT_ARGS(), browserModel, nextPresetPage());
106 bottomContainer->addWidget(nextPresetPageButton, Rk::Alignment::AlignRight);
107 bottomContainer->addSpace(5, Rk::Alignment::AlignRight);
108
109 prevPresetPageButton = new RkButton(this);
110 prevPresetPageButton->setType(RkButton::ButtonType::ButtonPush);
111 prevPresetPageButton->setSize(24, 24);
112 prevPresetPageButton->setImage(RkImage(prevPresetPageButton->size(), RK_IMAGE_RC(prev_page)),
113 RkButton::State::Unpressed);
114 prevPresetPageButton->setImage(RkImage(prevPresetPageButton->size(), RK_IMAGE_RC(prev_page_hover)),
115 RkButton::State::UnpressedHover);
116 prevPresetPageButton->setImage(RkImage(prevPresetPageButton->size(), RK_IMAGE_RC(prev_page_on)),
117 RkButton::State::Pressed);
118 RK_ACT_BIND(prevPresetPageButton, pressed, RK_ACT_ARGS(), browserModel, previousPresetPage());
119 bottomContainer->addWidget(prevPresetPageButton, Rk::Alignment::AlignRight);
120 updatePageButtons();
121 setBackgroundColor({60, 60, 60});
122 }
123
paintWidget(RkPaintEvent * event)124 void PresetBrowserView::paintWidget(RkPaintEvent *event)
125 {
126 RkImage img(size());
127 RkPainter painter(&img);
128 painter.fillRect(rect(), background());
129 painter.fillRect({0, 0, leftPadding + columnWidth, height()}, {40, 40, 40, 70});
130 painter.setPen(RkColor(50, 50, 50));
131 painter.drawLine({leftPadding + columnWidth, 0}, {leftPadding + columnWidth, height()});
132 auto font = painter.font();
133 font.setSize(12);
134 painter.setFont(font);
135 if (browserModel->columns()) {
136 int xColumn = leftPadding;
137 int yRow = topPadding;
138 for (size_t col = 0; col < browserModel->columns(); col++) {
139 for (size_t row = 0; row < browserModel->rows(); row++) {
140 auto presetName = browserModel->presetName(row, col);
141 if (browserModel->isKit(row, col))
142 presetName = "KIT: " + presetName;
143 auto font = painter.font();
144 RkRect textRect(xColumn + 15, yRow, columnWidth, rowHeight);
145 painter.setPen(RkColor(60, 60, 60));
146 if (browserModel->isSelected(row, col)) {
147 font.setWeight(RkFont::Weight::Bold);
148 painter.setFont(font);
149 painter.setPen(RkColor(230, 230, 230));
150 } else {
151 font.setWeight(RkFont::Weight::Normal);
152 painter.setFont(font);
153 painter.setPen(RkColor(180, 180, 180));
154 }
155
156 if (static_cast<decltype(row)>(overRow) == row
157 && static_cast<decltype(col)>(overColumn) == col) {
158 painter.setPen(RkColor(255, 255, 255));
159 }
160 painter.drawText(textRect, presetName, Rk::Alignment::AlignLeft);
161 yRow += rowHeight;
162 }
163 xColumn += columnWidth;
164 yRow = topPadding;
165 }
166 }
167 RkPainter paint(this);
168 paint.drawImage(img, 0, 0);
169 }
170
mouseButtonPressEvent(RkMouseEvent * event)171 void PresetBrowserView::mouseButtonPressEvent(RkMouseEvent *event)
172 {
173 browserModel->select((event->y() - topPadding) / rowHeight,
174 (event->x() - leftPadding) / columnWidth);
175 }
176
mouseMoveEvent(RkMouseEvent * event)177 void PresetBrowserView::mouseMoveEvent(RkMouseEvent *event)
178 {
179 auto overColumnTmp = (event->x() - leftPadding) / columnWidth;
180 bool toUpdate = false;
181 if (overColumnTmp != overColumn) {
182 overColumn = overColumnTmp;
183 toUpdate = true;
184 }
185
186 auto overRowTmp = (event->y() - topPadding) / rowHeight;
187 if (overRowTmp != overRow) {
188 overRow = overRowTmp;
189 toUpdate = true;
190 }
191
192 if (toUpdate)
193 update();
194 }
195
updatePageButtons()196 void PresetBrowserView::updatePageButtons()
197 {
198 prevFolderPageButton->show(browserModel->folderPages() > 1);
199 nextFolderPageButton->show(browserModel->folderPages() > 1);
200 prevPresetPageButton->show(browserModel->presetPages() > 1);
201 nextPresetPageButton->show(browserModel->presetPages() > 1);
202 bottomContainer->update();
203 update();
204 }
205
206