summaryrefslogtreecommitdiff
path: root/libs/surfaces/push2/menu.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2016-09-21 15:25:01 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2016-09-27 14:59:31 -0500
commit9cc40aafa0dd06f1449c81fcbccd4a5eb971115d (patch)
tree8ecc30156d63ff12289383f9f951879fde167870 /libs/surfaces/push2/menu.cc
parent0610e1dc8d5fd2a8edb912df2ef82c3f64083fb3 (diff)
push2: menu presentation now working
Diffstat (limited to 'libs/surfaces/push2/menu.cc')
-rw-r--r--libs/surfaces/push2/menu.cc281
1 files changed, 173 insertions, 108 deletions
diff --git a/libs/surfaces/push2/menu.cc b/libs/surfaces/push2/menu.cc
index da1c98ac04..a31e485e18 100644
--- a/libs/surfaces/push2/menu.cc
+++ b/libs/surfaces/push2/menu.cc
@@ -39,188 +39,253 @@ using namespace ArdourCanvas;
#include "pbd/i18n.h"
#include "menu.h"
-Push2Menu::Push2Menu (Item* parent)
+Push2Menu::Push2Menu (Item* parent, vector<string> s)
: Container (parent)
, baseline (-1)
+ , ncols (0)
+ , nrows (0)
+ , wrap (true)
+ , first (0)
+ , last (0)
+ , _active (UINT32_MAX)
{
- Pango::FontDescription fd2 ("Sans 10");
+ Pango::FontDescription fd ("Sans 10");
if (baseline < 0) {
Push2Canvas* p2c = dynamic_cast<Push2Canvas*> (canvas());
Glib::RefPtr<Pango::Layout> throwaway = Pango::Layout::create (p2c->image_context());
- throwaway->set_font_description (fd2);
+ throwaway->set_font_description (fd);
throwaway->set_text (X_("Hg")); /* ascender + descender) */
int h, w;
throwaway->get_pixel_size (w, h);
baseline = h;
- // nrows = Push2::rows / baseline;
}
+ active_bg = new Rectangle (this);
- for (int n = 0; n < 8; ++n) {
+ for (vector<string>::iterator si = s.begin(); si != s.end(); ++si) {
Text* t = new Text (this);
- t->set_font_description (fd2);
- t->set_color (rgba_to_color (0.23, 0.0, 0.349, 1.0));
+ t->set_font_description (fd);
+ t->set (*si);
+ displays.push_back (t);
+ }
- const double x = 10.0 + (n * Push2Canvas::inter_button_spacing());
- const double y = 2.0;
- t->set_position (Duple (x, y));
+}
- Rectangle* r = new Rectangle (this);
- r->set (Rect (x, y, x + Push2Canvas::inter_button_spacing(), y + baseline));
+void
+Push2Menu::set_layout (int c, int r)
+{
+ ncols = c;
+ nrows = r;
- columns[n].lines = t;
- columns[n].active_bg = r;
- columns[n].top = -1;
- columns[n].active = -1;
- }
+ set_active (_active);
+ rearrange (_active);
}
void
-Push2Menu::fill_column (int col, vector<string> v)
+Push2Menu::rearrange (uint32_t initial_display)
{
- if (col < 0 || col > 7) {
+ if (initial_display >= displays.size()) {
return;
}
- columns[col].text = v;
+ vector<Text*>::iterator i = displays.begin();
- if (v.empty()) {
- columns[col].active = -1;
- } else {
- columns[col].active = 0;
+ /* move to first */
+
+ for (uint32_t n = 0; n < initial_display; ++n) {
+ (*i)->hide ();
+ ++i;
}
- set_text (col, 0);
-}
+ uint32_t index = initial_display;
+ uint32_t col = 0;
+ uint32_t row = 0;
+ bool active_shown = false;
-void
-Push2Menu::set_text (int col, int top_row)
-{
- if (top_row > (int) columns[col].text.size() - nrows || top_row < 0) {
- return;
- }
+ while (i != displays.end()) {
- if (top_row == columns[col].top) {
- return;
- }
+ Coord x = col * Push2Canvas::inter_button_spacing();
+ Coord y = 2 + (row * baseline);
+ (*i)->set_position (Duple (x, y));
- vector<string>::iterator s = columns[col].text.begin();
- s += top_row;
+ if (index == _active) {
+ active_bg->set (Rect (x - 1, y - 1,
+ x - 1 + Push2Canvas::inter_button_spacing(), y - 1 + baseline));
+ active_bg->show ();
+ active_shown = true;
+ }
- string rows;
+ (*i)->show ();
+ last = index;
+ ++i;
+ ++index;
- while (true) {
- rows += *s;
- ++s;
- if (s != columns[col].text.end()) {
- rows += '\n';
- } else {
- break;
+ if (++row >= nrows) {
+ row = 0;
+ if (++col >= ncols) {
+ /* no more to display */
+ break;
+ }
}
+
}
- columns[col].lines->set (rows);
- columns[col].top = top_row;
+ while (i != displays.end()) {
+ (*i)->hide ();
+ ++i;
+ }
+
+ if (!active_shown) {
+ active_bg->hide ();
+ }
- redraw ();
+ first = initial_display;
+
+ Rearranged (); /* EMIT SIGNAL */
}
void
-Push2Menu::scroll (int col, int dir)
+Push2Menu::scroll (Direction dir, bool page)
{
- if (dir > 0) {
- set_text (col, columns[col].top + 1);
- } else {
- set_text (col, columns[col].top - 1);
+ switch (dir) {
+ case DirectionUp:
+ if (_active == 0) {
+ if (wrap) {
+ set_active (displays.size() - 1);
+ }
+ } else {
+ set_active (_active - 1);
+ }
+ break;
+
+ case DirectionDown:
+ if (_active == displays.size() - 1) {
+ if (wrap) {
+ set_active (0);
+ }
+ } else {
+ set_active (_active + 1);
+ }
+ break;
+
+ case DirectionLeft:
+ if (page) {
+ set_active (max (0, (int) (first - (nrows * ncols))));
+ } else {
+ if (_active / nrows == 0) {
+ /* in the first column, go to last column, same row */
+ if (wrap) {
+ set_active (displays.size() - 1 - active_row ());
+ }
+ } else {
+ /* move to same row, previous column */
+ set_active (_active - nrows);
+ }
+ }
+ break;
+
+ case DirectionRight:
+ if (page) {
+ set_active (min ((uint32_t) displays.size(), first + (nrows * ncols)));
+ } else {
+ if (_active / nrows == ncols) {
+ /* in the last column, go to same row in first column */
+ if (wrap) {
+ set_active (active_row());
+ }
+ } else {
+ /* move to same row, next column */
+ set_active (_active + nrows);
+ }
+ }
+ break;
}
+}
- redraw ();
+void
+Push2Menu::render (Rect const& area, Cairo::RefPtr<Cairo::Context> context) const
+{
+ render_children (area, context);
}
void
-Push2Menu::set_active (int col, int index)
+Push2Menu::set_active (uint32_t index)
{
- if (col < 0 || col > 7) {
- columns[col].active_bg->hide ();
+ if (index == _active) {
return;
}
- if (index < 0 || index > (int) columns[col].text.size()) {
- columns[col].active_bg->hide ();
+ if (index >= displays.size()) {
+ active_bg->hide ();
return;
}
- columns[col].active = index;
- int effective_row = columns[col].active - columns[col].top;
+ /* set text color for old active item, and the new one */
- /* Move active bg */
+ if (_active <= displays.size()) {
+ displays[_active]->set_color (text_color);
+ }
- Duple p (columns[col].active_bg->position());
+ displays[index]->set_color (contrast_color);
- columns[col].active_bg->set (Rect (p.x, p.y + (effective_row * baseline),
- p.x + Push2Canvas::inter_button_spacing(), p.y + baseline));
- columns[col].active_bg->show ();
+ Duple p = displays[index]->position ();
- if (columns[col].active < nrows/2) {
- set_text (col, 0);
- } else {
- set_text (col, columns[col].active - (nrows/2) + 1);
- }
+ active_bg->set (Rect (p.x - 1, p.y - 1, p.x - 1 + Push2Canvas::inter_button_spacing(), p.y - 1 + baseline ));
+ active_bg->show ();
+ _active = index;
- ActiveChanged (); /* emit signal */
+ if (_active < first) {
- redraw ();
-}
+ /* we jumped before current visible range : try to put its column first
+ */
-void
-Push2Menu::step_active (int col, int dir)
-{
- if (col < 0 || col > 7) {
- return;
- }
+ rearrange (active_top());
- if (columns[col].text.empty()) {
- return;
+ } else if (_active > last) {
+
+ /* we jumped after current visible range : try putting its
+ * column last
+ */
+
+ rearrange (active_top() - ((ncols - 1) * nrows));
}
+ ActiveChanged (); /* EMIT SIGNAL */
+}
- if (dir < 0) {
- if (columns[col].active == -1) {
- set_active (col, -1);
- } else {
- columns[col].active = columns[col].active - 1;
- if (columns[col].active < 0) {
- set_active (col, columns[col].text.size() - 1);
- }
- }
- } else {
- if (columns[col].active == -1) {
- set_active (col, 0);
- } else {
- columns[col].active = columns[col].active + 1;
- if (columns[col].active >= (int) columns[col].text.size()) {
- set_active (col, 0);
- }
- }
+void
+Push2Menu::set_text_color (Color c)
+{
+ text_color = c;
+
+ for (vector<Text*>::iterator t = displays.begin(); t != displays.end(); ++t) {
+ (*t)->set_color (c);
}
- redraw ();
}
-int
-Push2Menu::get_active (int col)
+void
+Push2Menu::set_active_color (Color c)
{
- if (col < 0 || col > 7) {
- return -1;
+ active_color = c;
+ contrast_color = contrasting_text_color (active_color);
+ if (active_bg) {
+ active_bg->set_fill_color (c);
}
- return columns[col].active;
+ if (_active < displays.size()) {
+ displays[_active]->set_color (contrast_color);
+ }
}
void
-Push2Menu::render (Rect const& area, Cairo::RefPtr<Cairo::Context> context) const
+Push2Menu::set_font_description (Pango::FontDescription fd)
{
- render_children (area, context);
+ font_description = fd;
+
+ for (vector<Text*>::iterator t = displays.begin(); t != displays.end(); ++t) {
+ (*t)->set_font_description (fd);
+ }
}