2 Copyright (C) 2016 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <cairomm/context.h>
20 #include <cairomm/surface.h>
21 #include <cairomm/region.h>
22 #include <pangomm/layout.h>
26 #include "canvas/text.h"
27 #include "canvas/types.h"
28 #include "canvas/rectangle.h"
29 #include "canvas/colors.h"
38 #define Rect ArdourCanvas::Rect
41 using namespace ARDOUR;
45 using namespace ArdourSurface;
46 using namespace ArdourCanvas;
48 Push2Menu::Push2Menu (Item* parent, vector<string> s)
58 Pango::FontDescription fd ("Sans 10");
61 Push2Canvas* p2c = dynamic_cast<Push2Canvas*> (canvas());
62 Glib::RefPtr<Pango::Layout> throwaway = Pango::Layout::create (p2c->image_context());
63 throwaway->set_font_description (fd);
64 throwaway->set_text (X_("Hg")); /* ascender + descender) */
66 throwaway->get_pixel_size (w, h);
70 active_bg = new Rectangle (this);
72 for (vector<string>::iterator si = s.begin(); si != s.end(); ++si) {
73 Text* t = new Text (this);
74 t->set_font_description (fd);
76 displays.push_back (t);
82 Push2Menu::set_layout (int c, int r)
92 Push2Menu::rearrange (uint32_t initial_display)
94 if (initial_display >= displays.size()) {
98 vector<Text*>::iterator i = displays.begin();
102 for (uint32_t n = 0; n < initial_display; ++n) {
107 uint32_t index = initial_display;
110 bool active_shown = false;
112 while (i != displays.end()) {
114 Coord x = col * Push2Canvas::inter_button_spacing();
115 Coord y = 2 + (row * baseline);
117 (*i)->set_position (Duple (x, y));
119 if (index == _active) {
120 active_bg->set (Rect (x - 1, y - 1,
121 x - 1 + Push2Canvas::inter_button_spacing(), y - 1 + baseline));
131 if (++row >= nrows) {
133 if (++col >= ncols) {
134 /* no more to display */
141 while (i != displays.end()) {
150 first = initial_display;
152 Rearranged (); /* EMIT SIGNAL */
156 Push2Menu::scroll (Direction dir, bool page)
162 set_active (displays.size() - 1);
165 set_active (_active - 1);
170 if (_active == displays.size() - 1) {
175 set_active (_active + 1);
181 set_active (max (0, (int) (first - (nrows * ncols))));
183 if (_active / nrows == 0) {
184 /* in the first column, go to last column, same row */
186 set_active (displays.size() - 1 - active_row ());
189 /* move to same row, previous column */
190 set_active (_active - nrows);
197 set_active (min ((uint32_t) displays.size(), first + (nrows * ncols)));
199 if (_active / nrows == ncols) {
200 /* in the last column, go to same row in first column */
202 set_active (active_row());
205 /* move to same row, next column */
206 set_active (_active + nrows);
214 Push2Menu::render (Rect const& area, Cairo::RefPtr<Cairo::Context> context) const
216 render_children (area, context);
220 Push2Menu::set_active (uint32_t index)
222 if (!parent() || (index == _active)) {
226 if (index >= displays.size()) {
231 /* set text color for old active item, and the new one */
233 if (_active <= displays.size()) {
234 displays[_active]->set_color (text_color);
237 displays[index]->set_color (contrast_color);
239 Duple p = displays[index]->position ();
241 active_bg->set (Rect (p.x - 1, p.y - 1, p.x - 1 + Push2Canvas::inter_button_spacing(), p.y - 1 + baseline ));
245 if (_active < first) {
247 /* we jumped before current visible range : try to put its column first
250 rearrange (active_top());
252 } else if (_active > last) {
254 /* we jumped after current visible range : try putting its
258 rearrange (active_top() - ((ncols - 1) * nrows));
261 ActiveChanged (); /* EMIT SIGNAL */
265 Push2Menu::set_text_color (Color c)
269 for (vector<Text*>::iterator t = displays.begin(); t != displays.end(); ++t) {
276 Push2Menu::set_active_color (Color c)
279 contrast_color = contrasting_text_color (active_color);
281 active_bg->set_fill_color (c);
284 if (_active < displays.size()) {
285 displays[_active]->set_color (contrast_color);
290 Push2Menu::set_font_description (Pango::FontDescription fd)
292 font_description = fd;
294 for (vector<Text*>::iterator t = displays.begin(); t != displays.end(); ++t) {
295 (*t)->set_font_description (fd);