mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-10 23:46:20 +01:00
push2: menu presentation now working
This commit is contained in:
parent
0610e1dc8d
commit
9cc40aafa0
2 changed files with 243 additions and 153 deletions
|
|
@ -39,184 +39,169 @@ 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));
|
||||
|
||||
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));
|
||||
|
||||
columns[n].lines = t;
|
||||
columns[n].active_bg = r;
|
||||
columns[n].top = -1;
|
||||
columns[n].active = -1;
|
||||
t->set_font_description (fd);
|
||||
t->set (*si);
|
||||
displays.push_back (t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Push2Menu::fill_column (int col, vector<string> v)
|
||||
Push2Menu::set_layout (int c, int r)
|
||||
{
|
||||
if (col < 0 || col > 7) {
|
||||
return;
|
||||
}
|
||||
ncols = c;
|
||||
nrows = r;
|
||||
|
||||
columns[col].text = v;
|
||||
|
||||
if (v.empty()) {
|
||||
columns[col].active = -1;
|
||||
} else {
|
||||
columns[col].active = 0;
|
||||
}
|
||||
|
||||
set_text (col, 0);
|
||||
set_active (_active);
|
||||
rearrange (_active);
|
||||
}
|
||||
|
||||
void
|
||||
Push2Menu::set_text (int col, int top_row)
|
||||
Push2Menu::rearrange (uint32_t initial_display)
|
||||
{
|
||||
if (top_row > (int) columns[col].text.size() - nrows || top_row < 0) {
|
||||
if (initial_display >= displays.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (top_row == columns[col].top) {
|
||||
return;
|
||||
vector<Text*>::iterator i = displays.begin();
|
||||
|
||||
/* move to first */
|
||||
|
||||
for (uint32_t n = 0; n < initial_display; ++n) {
|
||||
(*i)->hide ();
|
||||
++i;
|
||||
}
|
||||
|
||||
uint32_t index = initial_display;
|
||||
uint32_t col = 0;
|
||||
uint32_t row = 0;
|
||||
bool active_shown = false;
|
||||
|
||||
vector<string>::iterator s = columns[col].text.begin();
|
||||
s += top_row;
|
||||
while (i != displays.end()) {
|
||||
|
||||
string rows;
|
||||
Coord x = col * Push2Canvas::inter_button_spacing();
|
||||
Coord y = 2 + (row * baseline);
|
||||
|
||||
while (true) {
|
||||
rows += *s;
|
||||
++s;
|
||||
if (s != columns[col].text.end()) {
|
||||
rows += '\n';
|
||||
} else {
|
||||
break;
|
||||
(*i)->set_position (Duple (x, y));
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
columns[col].lines->set (rows);
|
||||
columns[col].top = top_row;
|
||||
(*i)->show ();
|
||||
last = index;
|
||||
++i;
|
||||
++index;
|
||||
|
||||
redraw ();
|
||||
}
|
||||
|
||||
void
|
||||
Push2Menu::scroll (int col, int dir)
|
||||
{
|
||||
if (dir > 0) {
|
||||
set_text (col, columns[col].top + 1);
|
||||
} else {
|
||||
set_text (col, columns[col].top - 1);
|
||||
}
|
||||
|
||||
redraw ();
|
||||
}
|
||||
|
||||
void
|
||||
Push2Menu::set_active (int col, int index)
|
||||
{
|
||||
if (col < 0 || col > 7) {
|
||||
columns[col].active_bg->hide ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 0 || index > (int) columns[col].text.size()) {
|
||||
columns[col].active_bg->hide ();
|
||||
return;
|
||||
}
|
||||
|
||||
columns[col].active = index;
|
||||
int effective_row = columns[col].active - columns[col].top;
|
||||
|
||||
/* Move active bg */
|
||||
|
||||
Duple p (columns[col].active_bg->position());
|
||||
|
||||
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 ();
|
||||
|
||||
if (columns[col].active < nrows/2) {
|
||||
set_text (col, 0);
|
||||
} else {
|
||||
set_text (col, columns[col].active - (nrows/2) + 1);
|
||||
}
|
||||
|
||||
ActiveChanged (); /* emit signal */
|
||||
|
||||
redraw ();
|
||||
}
|
||||
|
||||
void
|
||||
Push2Menu::step_active (int col, int dir)
|
||||
{
|
||||
if (col < 0 || col > 7) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (columns[col].text.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
if (++row >= nrows) {
|
||||
row = 0;
|
||||
if (++col >= ncols) {
|
||||
/* no more to display */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
redraw ();
|
||||
while (i != displays.end()) {
|
||||
(*i)->hide ();
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!active_shown) {
|
||||
active_bg->hide ();
|
||||
}
|
||||
|
||||
first = initial_display;
|
||||
|
||||
Rearranged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
int
|
||||
Push2Menu::get_active (int col)
|
||||
void
|
||||
Push2Menu::scroll (Direction dir, bool page)
|
||||
{
|
||||
if (col < 0 || col > 7) {
|
||||
return -1;
|
||||
}
|
||||
switch (dir) {
|
||||
case DirectionUp:
|
||||
if (_active == 0) {
|
||||
if (wrap) {
|
||||
set_active (displays.size() - 1);
|
||||
}
|
||||
} else {
|
||||
set_active (_active - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
return columns[col].active;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -224,3 +209,83 @@ Push2Menu::render (Rect const& area, Cairo::RefPtr<Cairo::Context> context) cons
|
|||
{
|
||||
render_children (area, context);
|
||||
}
|
||||
|
||||
void
|
||||
Push2Menu::set_active (uint32_t index)
|
||||
{
|
||||
if (index == _active) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index >= displays.size()) {
|
||||
active_bg->hide ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* set text color for old active item, and the new one */
|
||||
|
||||
if (_active <= displays.size()) {
|
||||
displays[_active]->set_color (text_color);
|
||||
}
|
||||
|
||||
displays[index]->set_color (contrast_color);
|
||||
|
||||
Duple p = displays[index]->position ();
|
||||
|
||||
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;
|
||||
|
||||
if (_active < first) {
|
||||
|
||||
/* we jumped before current visible range : try to put its column first
|
||||
*/
|
||||
|
||||
rearrange (active_top());
|
||||
|
||||
} else if (_active > last) {
|
||||
|
||||
/* we jumped after current visible range : try putting its
|
||||
* column last
|
||||
*/
|
||||
|
||||
rearrange (active_top() - ((ncols - 1) * nrows));
|
||||
}
|
||||
|
||||
ActiveChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Push2Menu::set_active_color (Color c)
|
||||
{
|
||||
active_color = c;
|
||||
contrast_color = contrasting_text_color (active_color);
|
||||
if (active_bg) {
|
||||
active_bg->set_fill_color (c);
|
||||
}
|
||||
|
||||
if (_active < displays.size()) {
|
||||
displays[_active]->set_color (contrast_color);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Push2Menu::set_font_description (Pango::FontDescription fd)
|
||||
{
|
||||
font_description = fd;
|
||||
|
||||
for (vector<Text*>::iterator t = displays.begin(); t != displays.end(); ++t) {
|
||||
(*t)->set_font_description (fd);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,14 @@
|
|||
#ifndef __ardour_push2_menu_h__
|
||||
#define __ardour_push2_menu_h__
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Cairo {
|
||||
class Context;
|
||||
class Region;
|
||||
}
|
||||
|
||||
#include <pangomm/layout.h>
|
||||
#include <pangomm/fontdescription.h>
|
||||
|
||||
#include "pbd/signals.h"
|
||||
|
||||
|
|
@ -40,34 +42,57 @@ namespace ArdourSurface {
|
|||
class Push2Menu : public ArdourCanvas::Container
|
||||
{
|
||||
public:
|
||||
Push2Menu (ArdourCanvas::Item* parent);
|
||||
Push2Menu (ArdourCanvas::Item* parent, std::vector<std::string>);
|
||||
|
||||
void render (ArdourCanvas::Rect const& area, Cairo::RefPtr<Cairo::Context> context) const;
|
||||
|
||||
void fill_column (int col, std::vector<std::string>);
|
||||
void set_active (int col, int index);
|
||||
void step_active (int col, int dir);
|
||||
int get_active (int col);
|
||||
void set_wrap (bool);
|
||||
void set_active (uint32_t index);
|
||||
|
||||
uint32_t active () const { return _active; }
|
||||
uint32_t items() const { return displays.size(); }
|
||||
|
||||
uint32_t rows() const { return nrows; }
|
||||
uint32_t cols() const { return ncols; }
|
||||
|
||||
void set_layout (int cols, int rows);
|
||||
void set_font_description (Pango::FontDescription);
|
||||
void set_text_color (ArdourCanvas::Color);
|
||||
void set_active_color (ArdourCanvas::Color);
|
||||
|
||||
bool can_scroll_left() const { return first >= nrows; }
|
||||
bool can_scroll_right() const { return last < displays.size() - 1; }
|
||||
|
||||
enum Direction { DirectionUp, DirectionDown, DirectionLeft, DirectionRight };
|
||||
void scroll (Direction, bool page = false);
|
||||
|
||||
PBD::Signal0<void> ActiveChanged;
|
||||
PBD::Signal0<void> Selected;
|
||||
PBD::Signal0<void> Rearranged;
|
||||
|
||||
private:
|
||||
struct Column {
|
||||
std::vector<std::string> text;
|
||||
ArdourCanvas::Rectangle* active_bg;
|
||||
ArdourCanvas::Text* lines;
|
||||
int top;
|
||||
int active;
|
||||
};
|
||||
std::vector<ArdourCanvas::Text*> displays;
|
||||
ArdourCanvas::Rectangle* active_bg;
|
||||
|
||||
Column columns[8];
|
||||
void rearrange (uint32_t initial_display);
|
||||
|
||||
void scroll (int col, int dir);
|
||||
void set_text (int col, int top);
|
||||
double baseline;
|
||||
int row_start;
|
||||
int col_start;
|
||||
uint32_t ncols;
|
||||
uint32_t nrows;
|
||||
bool wrap;
|
||||
uint32_t first;
|
||||
uint32_t last;
|
||||
uint32_t _active;
|
||||
|
||||
int nrows;
|
||||
mutable double baseline;
|
||||
ArdourCanvas::Color text_color;
|
||||
ArdourCanvas::Color active_color;
|
||||
ArdourCanvas::Color contrast_color;
|
||||
Pango::FontDescription font_description;
|
||||
|
||||
inline int active_row () const { return _active % nrows; }
|
||||
inline int active_col () const { return (_active / nrows); }
|
||||
inline int active_top () const { return active_col() * nrows; }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue