+ /* we want the colors sorted by hue, with their name */
+
+ UIConfiguration::Colors& colors (ARDOUR_UI::config()->colors);
+ vector<NamedColor> nc;
+ for (UIConfiguration::Colors::const_iterator x = colors.begin(); x != colors.end(); ++x) {
+ nc.push_back (NamedColor (x->first, HSV (x->second)));
+ }
+ SortByHue sorter;
+ sort (nc.begin(), nc.end(), sorter);
+
+ const uint32_t color_limit = nc.size();
+ const double box_size = 20.0;
+ const double width = canvas.width();
+ const double height = canvas.height();
+
+ uint32_t color_num = 0;
+
+ /* clear existing rects and delete them */
+
+ group.clear (true);
+
+ for (uint32_t y = 0; y < height - box_size && color_num < color_limit; y += box_size) {
+ for (uint32_t x = 0; x < width - box_size && color_num < color_limit; x += box_size) {
+ ArdourCanvas::Rectangle* r = new ArdourCanvas::Rectangle (&group, ArdourCanvas::Rect (x, y, x + box_size, y + box_size));
+
+ string name = nc[color_num++].name;
+
+ UIConfiguration::Colors::iterator c = colors.find (name);
+
+ if (c != colors.end()) {
+ Color color = c->second;
+ r->set_fill_color (color);
+ r->set_outline_color (rgba_to_color (0.0, 0.0, 0.0, 1.0));
+ r->set_tooltip (name);
+ r->Event.connect (sigc::bind (event_handler, name));
+ }
+ }
+ }
+}
+
+void
+ThemeManager::palette_size_request (Gtk::Requisition* req)
+{
+ uint32_t ncolors = ARDOUR_UI::config()->colors.size();
+ const int box_size = 20;
+
+ double c = sqrt ((double)ncolors);
+ req->width = (int) floor (c * box_size);
+ req->height = (int) floor (c * box_size);
+
+ /* add overflow row if necessary */
+
+ if (fmod (ncolors, c) != 0.0) {
+ req->height += box_size;
+ }
+}
+
+void
+ThemeManager::setup_palette ()
+{
+ build_palette_canvas (*palette_viewport.canvas(), *palette_group, sigc::mem_fun (*this, &ThemeManager::palette_event));
+}
+
+bool
+ThemeManager::palette_event (GdkEvent* ev, string name)
+{
+ switch (ev->type) {
+ case GDK_BUTTON_RELEASE:
+ edit_palette_color (name);
+ return true;
+ default:
+ break;
+ }
+ return true;
+}
+
+void
+ThemeManager::edit_palette_color (std::string name)
+{
+ using namespace ArdourCanvas;
+ double r,g, b, a;
+ UIConfiguration* uic (ARDOUR_UI::config());
+ ArdourCanvas::Color c = uic->color (name);
+ Gdk::Color gdkcolor;
+
+ color_to_rgba (c, r, g, b, a);
+
+ gdkcolor.set_rgb_p (r, g, b);
+ color_dialog.get_colorsel()->set_previous_color (gdkcolor);
+ color_dialog.get_colorsel()->set_current_color (gdkcolor);
+ color_dialog.get_colorsel()->set_previous_alpha ((guint16) (a * 65535));
+ color_dialog.get_colorsel()->set_current_alpha ((guint16) (a * 65535));
+
+ color_dialog_connection.disconnect ();
+ color_dialog_connection = color_dialog.signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ThemeManager::palette_color_response), name));
+ color_dialog.present();
+}
+
+void
+ThemeManager::palette_color_response (int result, std::string name)
+{
+ using namespace ArdourCanvas;
+
+ color_dialog_connection.disconnect ();
+
+ UIConfiguration* uic (ARDOUR_UI::config());
+ Gdk::Color gdkcolor;
+ double r,g, b, a;
+
+ switch (result) {
+ case RESPONSE_ACCEPT:
+ case RESPONSE_OK:
+ gdkcolor = color_dialog.get_colorsel()->get_current_color();
+ a = color_dialog.get_colorsel()->get_current_alpha() / 65535.0;
+ r = gdkcolor.get_red_p();
+ g = gdkcolor.get_green_p();
+ b = gdkcolor.get_blue_p();
+
+ uic->set_color (name, rgba_to_color (r, g, b, a));
+ break;
+
+ default:
+ break;
+ }
+
+ color_dialog.hide ();
+}
+
+bool
+ThemeManager::alias_palette_event (GdkEvent* ev, string new_alias, string target_name)
+{
+ switch (ev->type) {
+ case GDK_BUTTON_RELEASE:
+ ARDOUR_UI::config()->set_alias (target_name, new_alias);
+ return true;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+void
+ThemeManager::alias_palette_response (int response, std::string target_name, std::string old_alias)
+{
+ switch (response) {
+ case GTK_RESPONSE_OK:
+ case GTK_RESPONSE_ACCEPT:
+ /* rebuild alias list with new color: inefficient but simple */
+ setup_aliases ();
+ break;
+
+ case GTK_RESPONSE_REJECT:
+ /* revert choice */
+ ARDOUR_UI::config()->set_alias (target_name, old_alias);
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+
+ palette_window->hide ();
+}
+
+void
+ThemeManager::choose_color_from_palette (string const & name)
+{
+ UIConfiguration* uic (ARDOUR_UI::config());
+ UIConfiguration::ColorAliases::iterator i = uic->color_aliases.find (name);
+
+ if (i == uic->color_aliases.end()) {
+ return;
+ }
+
+ delete palette_window;
+
+ palette_window = new ArdourDialog (_("Color Palette"));
+ palette_window->add_button (Stock::CANCEL, RESPONSE_REJECT); /* using CANCEL causes confusion if dialog is closed via CloseAllDialogs */
+ palette_window->add_button (Stock::OK, RESPONSE_OK);
+
+ ArdourCanvas::GtkCanvas* canvas = new ArdourCanvas::GtkCanvas ();
+ ArdourCanvas::Container* group = initialize_palette_canvas (*canvas);
+
+ canvas->signal_size_request().connect (sigc::mem_fun (*this, &ThemeManager::palette_size_request));
+ canvas->signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &ThemeManager::palette_canvas_allocated), group, canvas,
+ sigc::bind (sigc::mem_fun (*this, &ThemeManager::alias_palette_event), name)));
+
+ palette_window->get_vbox()->pack_start (*canvas);
+ palette_window->show_all ();
+
+ palette_response_connection = palette_window->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ThemeManager::alias_palette_response), name, i->second));
+
+ palette_window->set_position (WIN_POS_MOUSE);
+ palette_window->present ();
+}
+
+void
+ThemeManager::setup_aliases ()
+{
+ using namespace ArdourCanvas;
+
+ UIConfiguration* uic (ARDOUR_UI::config());
+ UIConfiguration::ColorAliases& aliases (uic->color_aliases);
+
+ alias_list->clear ();
+
+ for (UIConfiguration::ColorAliases::iterator i = aliases.begin(); i != aliases.end(); ++i) {
+ TreeModel::Children rows = alias_list->children();