diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2016-06-07 14:38:57 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2016-06-07 14:52:24 -0400 |
commit | 06c9101f910dc76158f275da3df7e3387f06fe1f (patch) | |
tree | 4c10183e0512848305d264b0bfbb9164a0444e75 | |
parent | ee40e8d026dd0e19d1ad513590aadaa9f630b4c0 (diff) |
first pass at moving color theme management into its own preferences tab
-rw-r--r-- | gtk2_ardour/color_theme_manager.cc | 553 | ||||
-rw-r--r-- | gtk2_ardour/color_theme_manager.h | 152 | ||||
-rw-r--r-- | gtk2_ardour/rc_option_editor.cc | 3 | ||||
-rw-r--r-- | gtk2_ardour/theme_manager.cc | 475 | ||||
-rw-r--r-- | gtk2_ardour/theme_manager.h | 90 | ||||
-rw-r--r-- | gtk2_ardour/wscript | 1 |
6 files changed, 713 insertions, 561 deletions
diff --git a/gtk2_ardour/color_theme_manager.cc b/gtk2_ardour/color_theme_manager.cc new file mode 100644 index 0000000000..c3d0765726 --- /dev/null +++ b/gtk2_ardour/color_theme_manager.cc @@ -0,0 +1,553 @@ +/* + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <cmath> +#include <errno.h> + +#include "fix_carbon.h" + +#include "pbd/gstdio_compat.h" + +#include <gtkmm/stock.h> +#include <gtkmm/settings.h> + +#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/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 "color_theme_manager.h" +#include "rgb_macros.h" +#include "ui_config.h" +#include "utils.h" + +#include "i18n.h" + +using namespace std; +using namespace Gtk; +using namespace PBD; +using namespace ARDOUR; +using namespace ARDOUR_UI_UTILS; + +ColorThemeManager::ColorThemeManager () + : reset_button (_("Restore Defaults")) + , palette_viewport (*palette_scroller.get_hadjustment(), *palette_scroller.get_vadjustment()) + , palette_group (0) + , palette_window (0) +{ + reset_button.signal_clicked().connect (sigc::mem_fun (*this, &ColorThemeManager::reset_canvas_colors)); + + /* Now the alias list */ + + 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.set_headers_visible (true); + + alias_display.signal_button_press_event().connect (sigc::mem_fun (*this, &ColorThemeManager::alias_button_press_event), false); + + alias_scroller.add (alias_display); + + palette_group = initialize_palette_canvas (*palette_viewport.canvas()); + palette_viewport.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &ColorThemeManager::palette_canvas_allocated), palette_group, palette_viewport.canvas(), + sigc::mem_fun (*this, &ColorThemeManager::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")); + + notebook.set_size_request (400, 400); + + set_spacing (12); + pack_start (reset_button, false, false); + pack_start (notebook, true, true); + + /* no need to call setup_palette() here, it will be done when its size is allocated */ + setup_aliases (); + setup_modifiers (); + + UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ColorThemeManager::colors_changed)); + + show_all (); +} + +void +ColorThemeManager::setup_modifiers () +{ + UIConfiguration* uic (&UIConfiguration::instance()); + 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, &ColorThemeManager::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 +ColorThemeManager::modifier_edited (Gtk::Range* range, string name) +{ + using namespace ArdourCanvas; + + double alpha = range->get_value(); + SVAModifier svam (SVAModifier::Assign, -1.0, -1.0, alpha); + UIConfiguration::instance().set_modifier (name, svam); +} + +void +ColorThemeManager::colors_changed () +{ + setup_palette (); + setup_aliases (); + setup_modifiers (); +} + +void +ColorThemeManager::reset_canvas_colors() +{ + string cfile; + string basename; + + basename = UIConfiguration::instance().color_file_name (true, true, true); + + if (find_file (ardour_config_search_path(), basename, cfile)) { + string backup = cfile + string (X_(".old")); + g_rename (cfile.c_str(), backup.c_str()); + /* don't really care if it fails */ + } + + UIConfiguration::instance().load_defaults(); + UIConfiguration::instance().save_state (); +} + +ArdourCanvas::Container* +ColorThemeManager::initialize_palette_canvas (ArdourCanvas::Canvas& canvas) +{ + using namespace ArdourCanvas; + + /* 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); + + /* new container to hold everything */ + + return new ArdourCanvas::Container (scroll_group); +} + +void +ColorThemeManager::palette_canvas_allocated (Gtk::Allocation& alloc, ArdourCanvas::Container* group, ArdourCanvas::Canvas* canvas, sigc::slot<bool,GdkEvent*,std::string> event_handler) +{ + build_palette_canvas (*canvas, *group, event_handler); +} + +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 +ColorThemeManager::build_palette_canvas (ArdourCanvas::Canvas& canvas, ArdourCanvas::Container& group, sigc::slot<bool,GdkEvent*,std::string> event_handler) +{ + using namespace ArdourCanvas; + + /* we want the colors sorted by hue, with their name */ + + UIConfiguration::Colors& colors (UIConfiguration::instance().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 +ColorThemeManager::palette_size_request (Gtk::Requisition* req) +{ + uint32_t ncolors = UIConfiguration::instance().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 +ColorThemeManager::setup_palette () +{ + build_palette_canvas (*palette_viewport.canvas(), *palette_group, sigc::mem_fun (*this, &ColorThemeManager::palette_event)); +} + +bool +ColorThemeManager::palette_event (GdkEvent* ev, string name) +{ + switch (ev->type) { + case GDK_BUTTON_RELEASE: + edit_palette_color (name); + return true; + default: + break; + } + return true; +} + +void +ColorThemeManager::edit_palette_color (std::string name) +{ + using namespace ArdourCanvas; + double r,g, b, a; + UIConfiguration* uic (&UIConfiguration::instance()); + 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, &ColorThemeManager::palette_color_response), name)); + color_dialog.present(); +} + +void +ColorThemeManager::palette_color_response (int result, std::string name) +{ + using namespace ArdourCanvas; + + color_dialog_connection.disconnect (); + + UIConfiguration* uic (&UIConfiguration::instance()); + 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 +ColorThemeManager::alias_palette_event (GdkEvent* ev, string new_alias, string target_name) +{ + switch (ev->type) { + case GDK_BUTTON_RELEASE: + UIConfiguration::instance().set_alias (target_name, new_alias); + return true; + break; + default: + break; + } + return false; +} + +void +ColorThemeManager::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 */ + UIConfiguration::instance().set_alias (target_name, old_alias); + break; + + default: + /* do nothing */ + break; + } + + palette_window->hide (); +} + +void +ColorThemeManager::choose_color_from_palette (string const & name) +{ + UIConfiguration* uic (&UIConfiguration::instance()); + 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, &ColorThemeManager::palette_size_request)); + canvas->signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &ColorThemeManager::palette_canvas_allocated), group, canvas, + sigc::bind (sigc::mem_fun (*this, &ColorThemeManager::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, &ColorThemeManager::alias_palette_response), name, i->second)); + + palette_window->set_position (WIN_POS_MOUSE); + palette_window->present (); +} + +void +ColorThemeManager::setup_aliases () +{ + using namespace ArdourCanvas; + + UIConfiguration* uic (&UIConfiguration::instance()); + 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 +ColorThemeManager::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; +} + +void +ColorThemeManager::parameter_changed (string const&) +{ +} + +void +ColorThemeManager::set_state_from_config () +{ + +} + +void +ColorThemeManager::add_to_page (OptionEditorPage* page) +{ + add_widget_to_page (page, this); +} + +Gtk::Widget& +ColorThemeManager::tip_widget() +{ + return reset_button; /* XXX need a better widget for this purpose */ +} diff --git a/gtk2_ardour/color_theme_manager.h b/gtk2_ardour/color_theme_manager.h new file mode 100644 index 0000000000..b83b5ae523 --- /dev/null +++ b/gtk2_ardour/color_theme_manager.h @@ -0,0 +1,152 @@ +/* + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_gtk_color_manager_h__ +#define __ardour_gtk_color_manager_h__ + +#include <gtkmm/treeview.h> +#include <gtkmm/treestore.h> +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/colorselection.h> +#include <gtkmm/radiobutton.h> +#include <gtkmm/button.h> +#include <gtkmm/scale.h> +#include <gtkmm/rc.h> + +#include "canvas/types.h" +#include "canvas/canvas.h" + +#include "option_editor.h" +#include "ui_config.h" + +namespace ArdourCanvas { + class Container; + class ScrollGroup; +} + +class ArdourDialog; + +class ColorThemeManager : public Gtk::VBox, public OptionEditorComponent +{ + public: + ColorThemeManager(); + + void reset_canvas_colors(); + void on_color_theme_changed (); + + /** Called when a configuration parameter's value has changed. + * @param p parameter name + */ + void parameter_changed (std::string const & p); + + /** Called to instruct the object to set its UI state from the configuration */ + void set_state_from_config (); + + /** Called to instruct the object to add itself to an OptionEditorPage */ + void add_to_page (OptionEditorPage *); + + void set_note (std::string const &); + + Gtk::Widget& tip_widget(); + + private: + Gtk::Button reset_button; + Gtk::Notebook notebook; + + /* handls response from color dialog when it is used to + edit a derived color. + */ + void palette_color_response (int, std::string); + + Gtk::ScrolledWindow palette_scroller; + ArdourCanvas::GtkCanvasViewport palette_viewport; + ArdourCanvas::Container* palette_group; + + /* these methods create and manage a canvas for use in either the + palette tab or in a separate dialog. Different behaviour is + accomplished by changing the event handler passed into the + allocation handler. We do it there because we have to rebuild + the canvas on allocation events, and during the rebuild, connect + each rectangle to the event handler. + + the alternative is one event handler for the canvas and a map + of where each color rectangle is. nothing wrong with this + but the per-rect event setup is simpler and avoids building + and looking up the map information. + */ + ArdourCanvas::Container* initialize_palette_canvas (ArdourCanvas::Canvas& canvas); + void build_palette_canvas (ArdourCanvas::Canvas&, ArdourCanvas::Container&, sigc::slot<bool,GdkEvent*,std::string> event_handler); + void palette_canvas_allocated (Gtk::Allocation& alloc, ArdourCanvas::Container* group, ArdourCanvas::Canvas* canvas, sigc::slot<bool,GdkEvent*,std::string> event_handler); + void palette_size_request (Gtk::Requisition*); + + /* handles events from a palette canvas inside the palette (derived + colors) tab + */ + bool palette_event (GdkEvent*, std::string name); + /* allows user to edit a named color (e.g. "color 3") after clicking + on it inside the palette tab. + */ + void edit_palette_color (std::string); + + struct ColorAliasModelColumns : public Gtk::TreeModel::ColumnRecord { + ColorAliasModelColumns() { + add (name); + add (alias); + add (color); + add (key); + } + + Gtk::TreeModelColumn<std::string> name; + Gtk::TreeModelColumn<std::string> alias; + Gtk::TreeModelColumn<Gdk::Color> color; + Gtk::TreeModelColumn<std::string> key; + }; + + ColorAliasModelColumns alias_columns; + Gtk::TreeView alias_display; + Glib::RefPtr<Gtk::TreeStore> alias_list; + Gtk::ScrolledWindow alias_scroller; + + bool alias_button_press_event (GdkEventButton*); + + ArdourDialog* palette_window; + sigc::connection palette_response_connection; + + void choose_color_from_palette (std::string const &target_name); + + bool alias_palette_event (GdkEvent*, std::string, std::string); + void alias_palette_response (int, std::string, std::string); + + void setup_aliases (); + void setup_palette (); + + Gtk::ScrolledWindow modifier_scroller; + Gtk::VBox modifier_vbox; + + void setup_modifiers (); + void modifier_edited (Gtk::Range*, std::string); + + Gtk::ColorSelectionDialog color_dialog; + sigc::connection color_dialog_connection; + + void colors_changed (); + void set_ui_to_state (); +}; + +#endif /* __ardour_gtk_color_manager_h__ */ diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index e039164e8e..6e94744041 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -55,6 +55,7 @@ #include "ardour_window.h" #include "ardour_dialog.h" #include "ardour_ui.h" +#include "color_theme_manager.h" #include "gui_thread.h" #include "meter_patterns.h" #include "midi_tracer.h" @@ -3332,6 +3333,8 @@ if (!ARDOUR::Profile->get_mixbus()) { ThemeManager* tm = manage (new ThemeManager); add_page (_("Theme"), *tm); + add_option (_("Theme/Colors"), new ColorThemeManager); + //trigger some parameter-changed messages which affect widget-visibility or -sensitivity parameter_changed ("send-ltc"); parameter_changed ("sync-source"); diff --git a/gtk2_ardour/theme_manager.cc b/gtk2_ardour/theme_manager.cc index 83085236c9..084bc368ca 100644 --- a/gtk2_ardour/theme_manager.cc +++ b/gtk2_ardour/theme_manager.cc @@ -58,8 +58,7 @@ using namespace ARDOUR; using namespace ARDOUR_UI_UTILS; ThemeManager::ThemeManager() - : reset_button (_("Restore Defaults")) - , flat_buttons (_("Draw \"flat\" buttons")) + : 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")) @@ -72,34 +71,9 @@ ThemeManager::ThemeManager() , floating_monitor_section (_("Float detached monitor-section window")) , icon_set_label (_("Icon Set")) , color_theme_label (_("Color Theme")) - , palette_viewport (*palette_scroller.get_hadjustment(), *palette_scroller.get_vadjustment()) - , palette_group (0) - , palette_window (0) { Gtk::HBox* hbox; - /* Now the alias list */ - - 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.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 */ set_homogeneous (false); @@ -147,7 +121,6 @@ ThemeManager::ThemeManager() hbox->show_all (); } - pack_start (reset_button, PACK_SHRINK); #ifndef __APPLE__ pack_start (all_dialogs, PACK_SHRINK); pack_start (transients_follow_front, PACK_SHRINK); @@ -188,19 +161,6 @@ ThemeManager::ThemeManager() 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); - show_all (); waveform_gradient_depth.set_update_policy (Gtk::UPDATE_DELAYED); @@ -213,7 +173,6 @@ ThemeManager::ThemeManager() 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)); - 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)); @@ -237,74 +196,6 @@ ThemeManager::ThemeManager() string_compose (_("When detaching the monitoring section, mark it as \"Utility\" window to stay in front.\n" "This requires a restart of %1 to take effect"), PROGRAM_NAME)); - set_size_request (-1, 400); - /* no need to call setup_palette() here, it will be done when its size is allocated */ - setup_aliases (); - setup_modifiers (); - - UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ThemeManager::colors_changed)); -} - -ThemeManager::~ThemeManager() -{ -} - -void -ThemeManager::setup_modifiers () -{ - UIConfiguration* uic (&UIConfiguration::instance()); - 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); - UIConfiguration::instance().set_modifier (name, svam); -} - -void -ThemeManager::colors_changed () -{ - setup_palette (); - setup_aliases (); - setup_modifiers (); -} - -int -ThemeManager::save (string /*path*/) -{ - return 0; } void @@ -411,367 +302,3 @@ ThemeManager::set_ui_to_state() timeline_item_gradient_depth.set_value(UIConfiguration::instance().get_timeline_item_gradient_depth()); } -void -ThemeManager::reset_canvas_colors() -{ - string cfile; - string basename; - - basename = UIConfiguration::instance().color_file_name (true, true, true); - - if (find_file (ardour_config_search_path(), basename, cfile)) { - string backup = cfile + string (X_(".old")); - g_rename (cfile.c_str(), backup.c_str()); - /* don't really care if it fails */ - } - - UIConfiguration::instance().load_defaults(); - UIConfiguration::instance().save_state (); - set_ui_to_state(); -} - -ArdourCanvas::Container* -ThemeManager::initialize_palette_canvas (ArdourCanvas::Canvas& canvas) -{ - using namespace ArdourCanvas; - - /* 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); - - /* new container to hold everything */ - - return new ArdourCanvas::Container (scroll_group); -} - -void -ThemeManager::palette_canvas_allocated (Gtk::Allocation& alloc, ArdourCanvas::Container* group, ArdourCanvas::Canvas* canvas, sigc::slot<bool,GdkEvent*,std::string> event_handler) -{ - build_palette_canvas (*canvas, *group, event_handler); -} - -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<bool,GdkEvent*,std::string> event_handler) -{ - using namespace ArdourCanvas; - - /* we want the colors sorted by hue, with their name */ - - UIConfiguration::Colors& colors (UIConfiguration::instance().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 = UIConfiguration::instance().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 (&UIConfiguration::instance()); - 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 (&UIConfiguration::instance()); - 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: - UIConfiguration::instance().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 */ - UIConfiguration::instance().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 (&UIConfiguration::instance()); - 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 (&UIConfiguration::instance()); - 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; -} diff --git a/gtk2_ardour/theme_manager.h b/gtk2_ardour/theme_manager.h index 467db41d78..93d558810c 100644 --- a/gtk2_ardour/theme_manager.h +++ b/gtk2_ardour/theme_manager.h @@ -17,38 +17,27 @@ */ -#ifndef __ardour_gtk_color_manager_h__ -#define __ardour_gtk_color_manager_h__ +#ifndef __ardour_gtk_theme_manager_h__ +#define __ardour_gtk_theme_manager_h__ #include <gtkmm/treeview.h> #include <gtkmm/treestore.h> #include <gtkmm/scrolledwindow.h> -#include <gtkmm/colorselection.h> #include <gtkmm/radiobutton.h> #include <gtkmm/button.h> #include <gtkmm/scale.h> #include <gtkmm/rc.h> -#include "canvas/types.h" -#include "canvas/canvas.h" - #include "ui_config.h" -namespace ArdourCanvas { - class Container; - class ScrollGroup; -} - class ArdourDialog; class ThemeManager : public Gtk::VBox { public: ThemeManager(); - ~ThemeManager(); int save (std::string path); - void reset_canvas_colors(); void on_flat_buttons_toggled (); void on_blink_rec_arm_toggled (); @@ -81,7 +70,6 @@ class ThemeManager : public Gtk::VBox Gtk::ColorSelectionDialog color_dialog; sigc::connection color_dialog_connection; - Gtk::Button reset_button; Gtk::CheckButton flat_buttons; Gtk::CheckButton blink_rec_button; Gtk::CheckButton region_color_button; @@ -99,81 +87,9 @@ class ThemeManager : public Gtk::VBox Gtk::Label color_theme_label; Gtk::ComboBox color_theme_dropdown; - /* handls response from color dialog when it is used to - edit a derived color. - */ - void palette_color_response (int, std::string); - - Gtk::ScrolledWindow palette_scroller; - ArdourCanvas::GtkCanvasViewport palette_viewport; - ArdourCanvas::Container* palette_group; - - /* these methods create and manage a canvas for use in either the - palette tab or in a separate dialog. Different behaviour is - accomplished by changing the event handler passed into the - allocation handler. We do it there because we have to rebuild - the canvas on allocation events, and during the rebuild, connect - each rectangle to the event handler. - - the alternative is one event handler for the canvas and a map - of where each color rectangle is. nothing wrong with this - but the per-rect event setup is simpler and avoids building - and looking up the map information. - */ - ArdourCanvas::Container* initialize_palette_canvas (ArdourCanvas::Canvas& canvas); - void build_palette_canvas (ArdourCanvas::Canvas&, ArdourCanvas::Container&, sigc::slot<bool,GdkEvent*,std::string> event_handler); - void palette_canvas_allocated (Gtk::Allocation& alloc, ArdourCanvas::Container* group, ArdourCanvas::Canvas* canvas, sigc::slot<bool,GdkEvent*,std::string> event_handler); - void palette_size_request (Gtk::Requisition*); - - /* handles events from a palette canvas inside the palette (derived - colors) tab - */ - bool palette_event (GdkEvent*, std::string name); - /* allows user to edit a named color (e.g. "color 3") after clicking - on it inside the palette tab. - */ - void edit_palette_color (std::string); - - struct ColorAliasModelColumns : public Gtk::TreeModel::ColumnRecord { - ColorAliasModelColumns() { - add (name); - add (alias); - add (color); - add (key); - } - - Gtk::TreeModelColumn<std::string> name; - Gtk::TreeModelColumn<std::string> alias; - Gtk::TreeModelColumn<Gdk::Color> color; - Gtk::TreeModelColumn<std::string> key; - }; - - ColorAliasModelColumns alias_columns; - Gtk::TreeView alias_display; - Glib::RefPtr<Gtk::TreeStore> alias_list; - Gtk::ScrolledWindow alias_scroller; - - bool alias_button_press_event (GdkEventButton*); - - ArdourDialog* palette_window; - sigc::connection palette_response_connection; - - void choose_color_from_palette (std::string const &target_name); - - bool alias_palette_event (GdkEvent*, std::string, std::string); - void alias_palette_response (int, std::string, std::string); - - void setup_aliases (); - void setup_palette (); - - Gtk::ScrolledWindow modifier_scroller; - Gtk::VBox modifier_vbox; - - void setup_modifiers (); - void modifier_edited (Gtk::Range*, std::string); void colors_changed (); void set_ui_to_state (); }; -#endif /* __ardour_gtk_color_manager_h__ */ +#endif /* __ardour_gtk_theme_manager_h__ */ diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index bbdd1dbf4b..32e1c87d63 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -59,6 +59,7 @@ gtk2_ardour_sources = [ 'bundle_manager.cc', 'button_joiner.cc', 'clock_group.cc', + 'color_theme_manager.cc', 'configinfo.cc', 'control_point.cc', 'control_point_dialog.cc', |