X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Ftheme_manager.cc;h=1af708e524380a9f28c078e9af15dfb6b808c1d7;hb=1dfee4813923f36401af771ee8731ec1ba3f20af;hp=70f249c1c6cf8e456e5e8d6e2d2b88b9fb62e5f5;hpb=903c0863d9c7490c86cbcb652bd362a266a6d468;p=ardour.git diff --git a/gtk2_ardour/theme_manager.cc b/gtk2_ardour/theme_manager.cc index 70f249c1c6..1af708e524 100644 --- a/gtk2_ardour/theme_manager.cc +++ b/gtk2_ardour/theme_manager.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2007 Paul Davis + Copyright (C) 2000-2007 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,20 +22,32 @@ #include #include +#include "fix_carbon.h" + #include -#include -#include #include +#include "gtkmm2ext/gtk_ui.h" +#include "gtkmm2ext/cell_renderer_color_selector.h" +#include "gtkmm2ext/utils.h" + #include "pbd/file_utils.h" +#include "pbd/compose.h" -#include "ardour/configuration.h" #include "ardour/filesystem_paths.h" -#include "ardour/profile.h" +#include "canvas/container.h" +#include "canvas/rectangle.h" +#include "canvas/scroll_group.h" +#include "canvas/wave_view.h" + +#include "ardour_button.h" +#include "ardour_dialog.h" #include "theme_manager.h" #include "rgb_macros.h" #include "ardour_ui.h" +#include "global_signals.h" +#include "utils.h" #include "i18n.h" @@ -43,37 +55,55 @@ using namespace std; using namespace Gtk; using namespace PBD; using namespace ARDOUR; +using namespace ARDOUR_UI_UTILS; - -sigc::signal ColorsChanged; -sigc::signal ColorChanged; +namespace ARDOUR_UI_UTILS { + sigc::signal ColorsChanged; +} ThemeManager::ThemeManager() - : ArdourDialog ("ThemeManager"), - dark_button ("Dark theme"), - light_button ("Light theme"), - reset_button ("Restore Defaults") -{ - Gtkmm2ext::WindowTitle title (Glib::get_application_name ()); - title += _("Theme Manager"); - set_title (title.get_string ()); - - color_list = ListStore::create (columns); - color_display.set_model (color_list); - color_display.append_column (_("Object"), columns.name); - color_display.append_column (_("Color"), columns.color); - color_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0)); - color_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1)); - color_display.set_reorderable (false); - color_display.get_selection()->set_mode (SELECTION_NONE); - color_display.set_headers_visible (true); - - CellRenderer* color_cell = color_display.get_column_cell_renderer (1); - TreeViewColumn* color_column = color_display.get_column (1); - color_column->add_attribute (color_cell->property_cell_background_gdk(), columns.gdkcolor); + : dark_button (_("Dark Theme")) + , light_button (_("Light Theme")) + , reset_button (_("Restore Defaults")) + , flat_buttons (_("Draw \"flat\" buttons")) + , blink_rec_button (_("Blink Rec-Arm buttons")) + , region_color_button (_("Color regions using their track's color")) + , show_clipping_button (_("Show waveform clipping")) + , waveform_gradient_depth (0, 1.0, 0.05) + , waveform_gradient_depth_label (_("Waveforms color gradient depth")) + , timeline_item_gradient_depth (0, 1.0, 0.05) + , timeline_item_gradient_depth_label (_("Timeline item gradient depth")) + , all_dialogs (_("All floating windows are dialogs")) + , transients_follow_front (_("Transient windows follow front window.")) + , icon_set_label (_("Icon Set")) + , palette_viewport (*palette_scroller.get_hadjustment(), *palette_scroller.get_vadjustment()) + , palette_group (0) + , palette_window (0) +{ + /* Now the alias list */ - scroller.add (color_display); - scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC); + alias_list = TreeStore::create (alias_columns); + alias_display.set_model (alias_list); + alias_display.append_column (_("Object"), alias_columns.name); + + Gtkmm2ext::CellRendererColorSelector* color_renderer = manage (new Gtkmm2ext::CellRendererColorSelector); + TreeViewColumn* color_column = manage (new TreeViewColumn (_("Color"), *color_renderer)); + color_column->add_attribute (color_renderer->property_color(), alias_columns.color); + alias_display.append_column (*color_column); + + alias_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0)); + alias_display.get_column (0)->set_expand (true); + alias_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1)); + alias_display.get_column (1)->set_expand (false); + alias_display.set_reorderable (false); + alias_display.get_selection()->set_mode (SELECTION_NONE); + alias_display.set_headers_visible (true); + + alias_display.signal_button_press_event().connect (sigc::mem_fun (*this, &ThemeManager::alias_button_press_event), false); + + alias_scroller.add (alias_display); + + /* various buttons */ RadioButton::Group group = dark_button.get_group(); light_button.set_group(group); @@ -81,219 +111,627 @@ ThemeManager::ThemeManager() theme_selection_hbox.pack_start (dark_button); theme_selection_hbox.pack_start (light_button); - get_vbox()->set_homogeneous(false); - get_vbox()->pack_start (theme_selection_hbox, PACK_SHRINK); - get_vbox()->pack_start (reset_button, PACK_SHRINK); - get_vbox()->pack_start (scroller); + set_homogeneous (false); +#if 0 // disable light/dark theme choice. until the 'light theme gets some attention. + pack_start (theme_selection_hbox, PACK_SHRINK); +#endif + pack_start (reset_button, PACK_SHRINK); +#ifndef __APPLE__ + pack_start (all_dialogs, PACK_SHRINK); + pack_start (transients_follow_front, PACK_SHRINK); +#endif + pack_start (flat_buttons, PACK_SHRINK); + pack_start (blink_rec_button, PACK_SHRINK); + pack_start (region_color_button, PACK_SHRINK); + pack_start (show_clipping_button, PACK_SHRINK); + + Gtk::HBox* hbox; + + vector icon_sets = ::get_icon_sets (); + + if (icon_sets.size() > 1) { + Gtkmm2ext::set_popdown_strings (icon_set_dropdown, icon_sets); + icon_set_dropdown.set_active_text (ARDOUR_UI::config()->get_icon_set()); + + hbox = Gtk::manage (new Gtk::HBox()); + hbox->set_spacing (6); + hbox->pack_start (icon_set_label, false, false); + hbox->pack_start (icon_set_dropdown, true, true); + pack_start (*hbox, PACK_SHRINK); + } + + + hbox = Gtk::manage (new Gtk::HBox()); + hbox->set_spacing (6); + hbox->pack_start (waveform_gradient_depth, true, true); + hbox->pack_start (waveform_gradient_depth_label, false, false); + pack_start (*hbox, PACK_SHRINK); + + hbox = Gtk::manage (new Gtk::HBox()); + hbox->set_spacing (6); + hbox->pack_start (timeline_item_gradient_depth, true, true); + hbox->pack_start (timeline_item_gradient_depth_label, false, false); + pack_start (*hbox, PACK_SHRINK); + + palette_group = initialize_palette_canvas (*palette_viewport.canvas()); + palette_viewport.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &ThemeManager::palette_canvas_allocated), palette_group, palette_viewport.canvas(), + sigc::mem_fun (*this, &ThemeManager::palette_event))); + palette_scroller.add (palette_viewport); + + modifier_scroller.add (modifier_vbox); + + notebook.append_page (alias_scroller, _("Items")); + notebook.append_page (palette_scroller, _("Palette")); + notebook.append_page (modifier_scroller, _("Transparency")); + + pack_start (notebook); - color_display.signal_button_press_event().connect (mem_fun (*this, &ThemeManager::button_press_event), false); + show_all (); + waveform_gradient_depth.set_update_policy (Gtk::UPDATE_DELAYED); + timeline_item_gradient_depth.set_update_policy (Gtk::UPDATE_DELAYED); + color_dialog.get_colorsel()->set_has_opacity_control (true); color_dialog.get_colorsel()->set_has_palette (true); - - color_dialog.get_ok_button()->signal_clicked().connect (bind (mem_fun (color_dialog, &Gtk::Dialog::response), RESPONSE_ACCEPT)); - color_dialog.get_cancel_button()->signal_clicked().connect (bind (mem_fun (color_dialog, &Gtk::Dialog::response), RESPONSE_CANCEL)); - dark_button.signal_toggled().connect (mem_fun (*this, &ThemeManager::on_dark_theme_button_toggled)); - light_button.signal_toggled().connect (mem_fun (*this, &ThemeManager::on_light_theme_button_toggled)); - reset_button.signal_clicked().connect (mem_fun (*this, &ThemeManager::reset_canvas_colors)); + + set_ui_to_state(); + + color_dialog.get_ok_button()->signal_clicked().connect (sigc::bind (sigc::mem_fun (color_dialog, &Gtk::Dialog::response), RESPONSE_ACCEPT)); + color_dialog.get_cancel_button()->signal_clicked().connect (sigc::bind (sigc::mem_fun (color_dialog, &Gtk::Dialog::response), RESPONSE_CANCEL)); + dark_button.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_dark_theme_button_toggled)); + light_button.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_light_theme_button_toggled)); + reset_button.signal_clicked().connect (sigc::mem_fun (*this, &ThemeManager::reset_canvas_colors)); + flat_buttons.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_flat_buttons_toggled)); + blink_rec_button.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_blink_rec_arm_toggled)); + region_color_button.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_region_color_toggled)); + show_clipping_button.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_show_clip_toggled)); + waveform_gradient_depth.signal_value_changed().connect (sigc::mem_fun (*this, &ThemeManager::on_waveform_gradient_depth_change)); + timeline_item_gradient_depth.signal_value_changed().connect (sigc::mem_fun (*this, &ThemeManager::on_timeline_item_gradient_depth_change)); + all_dialogs.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_all_dialogs_toggled)); + transients_follow_front.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_transients_follow_front_toggled)); + icon_set_dropdown.signal_changed().connect (sigc::mem_fun (*this, &ThemeManager::on_icon_set_changed)); + + Gtkmm2ext::UI::instance()->set_tip (all_dialogs, + string_compose (_("Mark all floating windows to be type \"Dialog\" rather than using \"Utility\" for some.\n" + "This may help with some window managers. This requires a restart of %1 to take effect"), + PROGRAM_NAME)); + Gtkmm2ext::UI::instance()->set_tip (transients_follow_front, + string_compose (_("Make transient windows follow the front window when toggling between the editor and mixer.\n" + "This requires a restart of %1 to take effect"), PROGRAM_NAME)); set_size_request (-1, 400); - setup_theme (); + /* no need to call setup_palette() here, it will be done when its size is allocated */ + setup_aliases (); + setup_modifiers (); + + ARDOUR_UI_UTILS::ColorsChanged.connect (sigc::mem_fun (*this, &ThemeManager::colors_changed)); } ThemeManager::~ThemeManager() { } +void +ThemeManager::setup_modifiers () +{ + UIConfiguration* uic (ARDOUR_UI::config()); + UIConfiguration::Modifiers& modifiers (uic->modifiers); + Gtk::HBox* mod_hbox; + Gtk::Label* mod_label; + Gtk::HScale* mod_scale; + + Gtkmm2ext::container_clear (modifier_vbox); + + for (UIConfiguration::Modifiers::const_iterator m = modifiers.begin(); m != modifiers.end(); ++m) { + mod_hbox = manage (new HBox); + + mod_scale = manage (new HScale (0.0, 1.0, 0.01)); + mod_scale->set_draw_value (false); + mod_scale->set_value (m->second.a()); + mod_scale->set_update_policy (Gtk::UPDATE_DISCONTINUOUS); + mod_scale->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &ThemeManager::modifier_edited), mod_scale, m->first)); + + mod_label = manage (new Label (m->first)); + mod_label->set_alignment (1.0, 0.5); + mod_label->set_size_request (150, -1); /* 150 pixels should be enough for anyone */ + + mod_hbox->pack_start (*mod_label, false, true, 12); + mod_hbox->pack_start (*mod_scale, true, true); + + modifier_vbox.pack_start (*mod_hbox, false, false); + } + + modifier_vbox.show_all (); + +} + +void +ThemeManager::modifier_edited (Gtk::Range* range, string name) +{ + using namespace ArdourCanvas; + + double alpha = range->get_value(); + SVAModifier svam (SVAModifier::Assign, -1.0, -1.0, alpha); + ARDOUR_UI::config()->set_modifier (name, svam); +} + +void +ThemeManager::colors_changed () +{ + setup_palette (); + setup_aliases (); + setup_modifiers (); +} + int -ThemeManager::save (string path) +ThemeManager::save (string /*path*/) { return 0; } -bool -ThemeManager::button_press_event (GdkEventButton* ev) +void +ThemeManager::on_flat_buttons_toggled () { - TreeIter iter; - TreeModel::Path path; - TreeViewColumn* column; - int cellx; - int celly; + ARDOUR_UI::config()->set_flat_buttons (flat_buttons.get_active()); + ArdourButton::set_flat_buttons (flat_buttons.get_active()); + /* force a redraw */ + gtk_rc_reset_styles (gtk_settings_get_default()); +} - UIConfigVariable *ccvar; - - if (!color_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) { - return false; - } +void +ThemeManager::on_blink_rec_arm_toggled () +{ + ARDOUR_UI::config()->set_blink_rec_arm (blink_rec_button.get_active()); + ARDOUR::Config->ParameterChanged("blink-rec-arm"); +} - switch (GPOINTER_TO_UINT (column->get_data (X_("colnum")))) { - case 0: - /* allow normal processing to occur */ - return false; +void +ThemeManager::on_region_color_toggled () +{ + ARDOUR_UI::config()->set_color_regions_using_track_color (region_color_button.get_active()); +} - case 1: /* color */ - if ((iter = color_list->get_iter (path))) { - - int r,g, b, a; - uint32_t rgba = (*iter)[columns.rgba]; - Gdk::Color color; - - UINT_TO_RGBA (rgba, &r, &g, &b, &a); - color.set_rgb_p (r / 255.0, g / 255.0, b / 255.0); - color_dialog.get_colorsel()->set_previous_color (color); - color_dialog.get_colorsel()->set_current_color (color); - color_dialog.get_colorsel()->set_previous_alpha (a * 256); - color_dialog.get_colorsel()->set_current_alpha (a * 256); - - ResponseType result = (ResponseType) color_dialog.run(); - - switch (result) { - case RESPONSE_CANCEL: - break; - case RESPONSE_ACCEPT: - color = color_dialog.get_colorsel()->get_current_color(); - a = color_dialog.get_colorsel()->get_current_alpha(); - r = (int) floor (color.get_red_p() * 255.0); - g = (int) floor (color.get_green_p() * 255.0); - b = (int) floor (color.get_blue_p() * 255.0); - - rgba = RGBA_TO_UINT(r,g,b,a>>8); - //cerr << (*iter)[columns.name] << " == " << hex << rgba << endl; - //cerr << "a = " << a << endl; - (*iter)[columns.rgba] = rgba; - (*iter)[columns.gdkcolor] = color; - - ccvar = (*iter)[columns.pVar]; - ccvar->set(rgba); - - //ColorChanged (rgba); - ColorsChanged();//EMIT SIGNAL - break; - - default: - break; +void +ThemeManager::on_show_clip_toggled () +{ + ARDOUR_UI::config()->set_show_waveform_clipping (show_clipping_button.get_active()); + // "show-waveform-clipping" was a session config key + ArdourCanvas::WaveView::set_global_show_waveform_clipping (ARDOUR_UI::config()->get_show_waveform_clipping()); +} - } +void +ThemeManager::on_all_dialogs_toggled () +{ + ARDOUR_UI::config()->set_all_floating_windows_are_dialogs (all_dialogs.get_active()); +} - color_dialog.hide (); - } - return true; +void +ThemeManager::on_transients_follow_front_toggled () +{ + ARDOUR_UI::config()->set_transients_follow_front (transients_follow_front.get_active()); +} - default: - break; - } +void +ThemeManager::on_waveform_gradient_depth_change () +{ + double v = waveform_gradient_depth.get_value(); - return false; + ARDOUR_UI::config()->set_waveform_gradient_depth (v); + ArdourCanvas::WaveView::set_global_gradient_depth (v); } void -load_rc_file (const string& filename, bool themechange) +ThemeManager::on_timeline_item_gradient_depth_change () { - sys::path rc_file_path; + double v = timeline_item_gradient_depth.get_value(); - SearchPath spath (ardour_search_path()); - spath += user_config_directory(); - spath += system_config_search_path(); + ARDOUR_UI::config()->set_timeline_item_gradient_depth (v); +} - if (!find_file_in_search_path (spath, filename, rc_file_path)) { - warning << string_compose( - _("Unable to find UI style file %1 in search path %2. Ardour will look strange"), - filename, spath.to_string()) - << endmsg; - return; +void +ThemeManager::on_icon_set_changed () +{ + string new_set = icon_set_dropdown.get_active_text(); + ARDOUR_UI::config()->set_icon_set (new_set); +} + +void +ThemeManager::on_dark_theme_button_toggled() +{ + if (!dark_button.get_active()) return; + + UIConfiguration* uic (ARDOUR_UI::config()); + + uic->set_color_file("dark"); +} + +void +ThemeManager::on_light_theme_button_toggled() +{ + if (!light_button.get_active()) return; + + UIConfiguration* uic (ARDOUR_UI::config()); + + uic->set_color_file("light"); +} + +void +ThemeManager::set_ui_to_state() +{ + /* there is no way these values can change individually + * by themselves (w/o user-interaction) + * hence a common combined update function suffices + */ + + if (ARDOUR_UI::config()->get_color_file() == "light") { + light_button.set_active(true); + } else { + dark_button.set_active(true); } - cerr << "Loading ui configuration file " << rc_file_path.to_string() << endmsg; + /* there is no need to block signal handlers, here, + * all elements check if the value has changed and ignore NOOPs + */ + all_dialogs.set_active (ARDOUR_UI::config()->get_all_floating_windows_are_dialogs()); + transients_follow_front.set_active (ARDOUR_UI::config()->get_transients_follow_front()); + flat_buttons.set_active (ARDOUR_UI::config()->get_flat_buttons()); + blink_rec_button.set_active (ARDOUR_UI::config()->get_blink_rec_arm()); + region_color_button.set_active (ARDOUR_UI::config()->get_color_regions_using_track_color()); + show_clipping_button.set_active (ARDOUR_UI::config()->get_show_waveform_clipping()); + waveform_gradient_depth.set_value(ARDOUR_UI::config()->get_waveform_gradient_depth()); + timeline_item_gradient_depth.set_value(ARDOUR_UI::config()->get_timeline_item_gradient_depth()); +} - Gtkmm2ext::UI::instance()->load_rcfile (rc_file_path.to_string(), themechange); +void +ThemeManager::reset_canvas_colors() +{ + ARDOUR_UI::config()->load_defaults(); + ARDOUR_UI::config()->save_state (); + set_ui_to_state(); } -/* hmm, this is a problem. the profile doesn't - exist when the theme manager is constructed - and toggles buttons during "normal" GTK setup. - - a better solution will be to make all Profile - methods static or something. +ArdourCanvas::Container* +ThemeManager::initialize_palette_canvas (ArdourCanvas::Canvas& canvas) +{ + using namespace ArdourCanvas; - XXX FIX ME -*/ + /* hide background */ + canvas.set_background_color (rgba_to_color (0.0, 0.0, 1.0, 0.0)); + + /* bi-directional scroll group */ + + ScrollGroup* scroll_group = new ScrollGroup (canvas.root(), ScrollGroup::ScrollSensitivity (ScrollGroup::ScrollsVertically|ScrollGroup::ScrollsHorizontally)); + canvas.add_scroller (*scroll_group); -#define HACK_PROFILE_IS_SAE() (getenv("ARDOUR_SAE")!=0) + /* new container to hold everything */ + + return new ArdourCanvas::Container (scroll_group); +} void -ThemeManager::on_dark_theme_button_toggled() +ThemeManager::palette_canvas_allocated (Gtk::Allocation& alloc, ArdourCanvas::Container* group, ArdourCanvas::Canvas* canvas, sigc::slot event_handler) { - if (!dark_button.get_active()) return; + build_palette_canvas (*canvas, *group, event_handler); +} - if (HACK_PROFILE_IS_SAE()){ - ARDOUR_UI::config()->ui_rc_file.set("ardour3_ui_dark_sae.rc"); - } else { - ARDOUR_UI::config()->ui_rc_file.set("ardour3_ui_dark.rc"); +struct NamedColor { + string name; + ArdourCanvas::HSV color; + NamedColor (string s, ArdourCanvas::HSV c) : name (s), color (c) {} +}; + +struct SortByHue { + bool operator() (NamedColor const & a, NamedColor const & b) { + using namespace ArdourCanvas; + const HSV black (0, 0, 0); + if (a.color.is_gray() || b.color.is_gray()) { + return black.distance (a.color) < black.distance (b.color); + } else { + return a.color.h < b.color.h; + // const HSV red (rgba_to_color (1.0, 0.0, 0.0, 1.0)); + // return red.distance (a.color) < red.distance (b.color); + } } +}; + + +void +ThemeManager::build_palette_canvas (ArdourCanvas::Canvas& canvas, ArdourCanvas::Container& group, sigc::slot event_handler) +{ + using namespace ArdourCanvas; + + /* we want the colors sorted by hue, with their name */ + + UIConfiguration::Colors& colors (ARDOUR_UI::config()->colors); + vector 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; - load_rc_file (ARDOUR_UI::config()->ui_rc_file.get(), true); + 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::on_light_theme_button_toggled() +ThemeManager::palette_size_request (Gtk::Requisition* req) { - if (!light_button.get_active()) return; + uint32_t ncolors = ARDOUR_UI::config()->colors.size(); + const int box_size = 20; - if (HACK_PROFILE_IS_SAE()){ - ARDOUR_UI::config()->ui_rc_file.set("ardour3_ui_light_sae.rc"); - } else { - ARDOUR_UI::config()->ui_rc_file.set("ardour3_ui_light.rc"); + 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; } +} - load_rc_file (ARDOUR_UI::config()->ui_rc_file.get(), true); +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::setup_theme () +ThemeManager::edit_palette_color (std::string name) { - int r, g, b, a; - color_list->clear(); + 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(); +} - for (std::vector *>::iterator i = ARDOUR_UI::config()->canvas_colors.begin(); i != ARDOUR_UI::config()->canvas_colors.end(); i++) { - - TreeModel::Row row = *(color_list->append()); +void +ThemeManager::palette_color_response (int result, std::string name) +{ + using namespace ArdourCanvas; - Gdk::Color col; - uint32_t rgba = (*i)->get(); - UINT_TO_RGBA (rgba, &r, &g, &b, &a); - //cerr << (*i)->name() << " == " << hex << rgba << ": " << hex << r << " " << hex << g << " " << hex << b << endl; - col.set_rgb_p (r / 255.0, g / 255.0, b / 255.0); + 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; + } - row[columns.name] = (*i)->name(); - row[columns.color] = ""; - row[columns.pVar] = *i; - row[columns.rgba] = rgba; - row[columns.gdkcolor] = col; + 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; +} - ColorsChanged.emit(); +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; - bool env_defined = false; - string rcfile = Glib::getenv("ARDOUR3_UI_RC", env_defined); + case GTK_RESPONSE_REJECT: + /* revert choice */ + ARDOUR_UI::config()->set_alias (target_name, old_alias); + break; - if(!env_defined) { - rcfile = ARDOUR_UI::config()->ui_rc_file.get(); + default: + /* do nothing */ + break; } - if (rcfile == "ardour3_ui_dark.rc" || rcfile == "ardour3_ui_dark_sae.rc") { - dark_button.set_active(); - } else if (rcfile == "ardour3_ui_light.rc" || "ardour3_ui_light_sae.rc") { - light_button.set_active(); + 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; } - load_rc_file(rcfile, false); + 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::reset_canvas_colors() +ThemeManager::setup_aliases () { - ARDOUR_UI::config()->load_defaults(); - setup_theme (); + 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(); + TreeModel::Row row; + string::size_type colon; + + if ((colon = i->first.find (':')) != string::npos) { + + /* this is supposed to be a child node, so find the + * parent + */ + + string parent = i->first.substr (0, colon); + TreeModel::iterator ri; + + for (ri = rows.begin(); ri != rows.end(); ++ri) { + string s = (*ri)[alias_columns.name]; + if (s == parent) { + break; + } + } + + if (ri == rows.end()) { + /* not found, add the parent as new top level row */ + row = *(alias_list->append()); + row[alias_columns.name] = parent; + row[alias_columns.alias] = ""; + + /* now add the child as a child of this one */ + + row = *(alias_list->insert (row->children().end())); + row[alias_columns.name] = i->first.substr (colon+1); + } else { + row = *(alias_list->insert ((*ri)->children().end())); + row[alias_columns.name] = i->first.substr (colon+1); + } + + } else { + /* add as a child */ + row = *(alias_list->append()); + row[alias_columns.name] = i->first; + row[alias_columns.key] = i->first; + } + + row[alias_columns.key] = i->first; + row[alias_columns.alias] = i->second; + + Gdk::Color col; + double r, g, b, a; + Color c (uic->color (i->second)); + color_to_rgba (c, r, g, b, a); + col.set_rgb_p (r, g, b); + + row[alias_columns.color] = col; + } } +bool +ThemeManager::alias_button_press_event (GdkEventButton* ev) +{ + TreeIter iter; + TreeModel::Path path; + TreeViewColumn* column; + int cellx; + int celly; + + if (!alias_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) { + return false; + } + + guint32 colnum = GPOINTER_TO_UINT (column->get_data (X_("colnum"))); + + switch (colnum) { + case 0: + /* allow normal processing to occur */ + return false; + + case 1: /* color */ + if ((iter = alias_list->get_iter (path))) { + string target_color_alias = (*iter)[alias_columns.key]; + if (!target_color_alias.empty()) { + choose_color_from_palette (target_color_alias); + } + } + break; + } + + return true; +}