new ArdourButton class, to start to provide more control over how our buttons work...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 26 Oct 2011 21:01:14 +0000 (21:01 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 26 Oct 2011 21:01:14 +0000 (21:01 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@10311 d708f5d6-7413-0410-9779-e7cbd77b26cf

25 files changed:
gtk2_ardour/ardour3_styles.rc.in
gtk2_ardour/ardour3_ui_dark.rc.in
gtk2_ardour/ardour3_ui_default.conf
gtk2_ardour/ardour3_ui_light.rc.in
gtk2_ardour/ardour3_widget_list.rc
gtk2_ardour/ardour_button.cc [new file with mode: 0644]
gtk2_ardour/ardour_button.h [new file with mode: 0644]
gtk2_ardour/ardour_ui_dependents.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/cairo_widget.cc
gtk2_ardour/cairo_widget.h
gtk2_ardour/canvas_vars.h
gtk2_ardour/led.cc
gtk2_ardour/led.h
gtk2_ardour/mixer_strip.cc
gtk2_ardour/mixer_strip.h
gtk2_ardour/processor_box.cc
gtk2_ardour/processor_box.h
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
gtk2_ardour/theme_manager.cc
gtk2_ardour/ui_config.cc
gtk2_ardour/ui_config.h
gtk2_ardour/wscript

index 634768e6f6a1a0781bbab42aa6df6525bf9d8c78..3b3ff039bf29c3cc073fbb32304464e97ffb1727 100644 (file)
@@ -148,52 +148,16 @@ style "mixer_track_rec_enable_button_active" = "track_rec_enable_button_active"
        ythickness = 0
 }
 
-style "monitor_input_button" = "small_button"
+style "monitor" = "small_button"
 {
-        fg[NORMAL] = darker(@@COLPREFIX@_fg)
-        fg[PRELIGHT] = darker(@@COLPREFIX@_fg)
-        bg[NORMAL] = mix(0.1,@@COLPREFIX@_monitor,darker(@@COLPREFIX@_bg))
-        bg[PRELIGHT] = mix(0.1,@@COLPREFIX@_somewhat_bright_indicator,darker(@@COLPREFIX@_bg))
 }
 
-style "monitor_input_button_active" = "small_button"
+style "solo_isolate" = "very_small_text"
 {
-       fg[NORMAL] = @@COLPREFIX@_fg
-       fg[PRELIGHT] = @@COLPREFIX@_fg
-       bg[NORMAL] = mix (0.8, @@COLPREFIX@_monitor, darker (@@COLPREFIX@_bg))
-       bg[PRELIGHT] = mix (0.8, @@COLPREFIX@_monitor, darker (@@COLPREFIX@_bg))
 }
 
-style "monitor_input_button_alternate" = "small_button"
+style "solo_safe" = "very_small_text"
 {
-       fg[NORMAL] = @@COLPREFIX@_fg
-       fg[PRELIGHT] = @@COLPREFIX@_fg
-        bg[NORMAL] = mix(0.5,@@COLPREFIX@_monitor,darker(@@COLPREFIX@_bg))
-        bg[PRELIGHT] = mix(0.5,@@COLPREFIX@_monitor,darker(@@COLPREFIX@_bg))
-}
-
-style "monitor_disk_button" = "small_button"
-{
-        fg[NORMAL] = darker(@@COLPREFIX@_fg)
-        fg[PRELIGHT] = darker(@@COLPREFIX@_fg)
-        bg[NORMAL] = mix(0.1,@@COLPREFIX@_monitor,darker(@@COLPREFIX@_bg))
-        bg[PRELIGHT] = mix(0.1,@@COLPREFIX@_monitor,darker(@@COLPREFIX@_bg))
-}
-
-style "monitor_disk_button_active" = "small_button"
-{
-       fg[NORMAL] = @@COLPREFIX@_fg
-       fg[PRELIGHT] = @@COLPREFIX@_fg
-       bg[NORMAL] = @@COLPREFIX@_monitor
-       bg[PRELIGHT] = @@COLPREFIX@_monitor
-}
-
-style "monitor_disk_button_alternate" = "small_button"
-{
-       fg[NORMAL] = @@COLPREFIX@_fg
-       fg[PRELIGHT] = @@COLPREFIX@_fg
-        bg[NORMAL] = mix(0.5,@@COLPREFIX@_monitor,darker(@@COLPREFIX@_bg))
-        bg[PRELIGHT] = mix(0.5,@@COLPREFIX@_monitor,darker(@@COLPREFIX@_bg))
 }
 
 style "solo_button" = "small_button"
@@ -203,18 +167,6 @@ style "solo_button" = "small_button"
   fg[ACTIVE] = @@COLPREFIX@_darkest
 }
 
-style "solo_isolate_led"
-{
-  fg[NORMAL] = mix(0.2,@@COLPREFIX@_isolate, @@COLPREFIX@_darkest)
-  fg[ACTIVE] = @@COLPREFIX@_isolate
-}
-
-style "solo_safe_led"
-{
-  fg[NORMAL] = mix(0.2,@@COLPREFIX@_isolate, @@COLPREFIX@_darkest)
-  fg[ACTIVE] = @@COLPREFIX@_isolate
-}
-
 style "solo_button_alternate" = "small_button"
 {
         #
@@ -263,6 +215,10 @@ style "solo_button_active" = "small_button"
        fg[PRELIGHT] = @@COLPREFIX@_darkest
 }
 
+style "processor" = "small_text"
+{
+}
+
 style "mixer_invert_button" = "small_button"
 {
        bg[ACTIVE] = @@COLPREFIX@_not_so_bright_indicator
@@ -294,42 +250,6 @@ style "mixer_solo_button_active" = "solo_button_active"
        ythickness = 0
 }
 
-style "mixer_monitor_input" = "monitor_input_button"
-{
-       xthickness = 0
-       ythickness = 0
-}
-
-style "mixer_monitor_input_active" = "monitor_input_button_active"
-{
-       xthickness = 0
-       ythickness = 0
-}
-
-style "mixer_monitor_input_alternate" = "monitor_input_button_alternate"
-{
-       xthickness = 0
-       ythickness = 0
-}
-
-style "mixer_monitor_disk" = "monitor_disk_button"
-{
-       xthickness = 0
-       ythickness = 0
-}
-
-style "mixer_monitor_disk_active" = "monitor_disk_button_active"
-{
-       xthickness = 0
-       ythickness = 0
-}
-
-style "mixer_monitor_disk_alternate" = "monitor_disk_button_alternate"
-{
-       xthickness = 0
-       ythickness = 0
-}
-
 style "monitor_opt_button" = "small_button"
 {
         bg[NORMAL] = mix(0.1,@@COLPREFIX@_not_so_bright_indicator,@@COLPREFIX@_bg)
@@ -985,14 +905,6 @@ style "processor_list" = "very_small_text"
        bg[NORMAL] = @@COLPREFIX@_darkest
         bg[ACTIVE] = shade (1.8, @@COLPREFIX@_fg_selected)
         fg[ACTIVE] = @@COLPREFIX@_darkest
-       GtkCheckButton::indicator-size = 10
-       GtkCheckButton::indicator-spacing = 0
-}
-
-# Colour of a processor frame when it is selected
-style "processor_frame_selected"
-{
-       bg[NORMAL] = @@COLPREFIX@_fg_selected
 }
 
 # Colour of a processor frame when it is a send whose level is being controller by the fader
@@ -1001,42 +913,6 @@ style "processor_frame_active_send"
        bg[NORMAL] = @@COLPREFIX@_send_fg
 }
 
-# Fader processor's background
-style "processor_fader"
-{
-       bg[NORMAL] = @@COLPREFIX@_processor_fader_bg
-}
-
-# Fader processor's frame
-style "processor_fader_frame" 
-{
-bg[NORMAL] = @@COLPREFIX@_processor_fader_frame
-}
-
-# Pre-fader processor's background
-style "processor_prefader"
-{
-       bg[NORMAL] = @@COLPREFIX@_processor_prefader
-}
-
-# Pre-fader processor's frame
-style "processor_prefader_frame"
-{
-       bg[NORMAL] = @@COLPREFIX@_processor_prefader_frame
-}
-
-# Post-fader processor's background
-style "processor_postfader"
-{
-       bg[NORMAL] = @@COLPREFIX@_processor_postfader
-}
-
-# Post-fader processor's frame
-style "processor_postfader_frame"
-{
-       bg[NORMAL] = @@COLPREFIX@_processor_postfader_frame
-}
-
 # MixerPanZone:
 #
 # the NORMAL fg color is used for the pan puck
index 05865b11d5556bc07df59633b7a8a33d10754bcb..2ad1d7c5d4ede49ef278d2ecf39895906ce8720e 100644 (file)
@@ -27,6 +27,7 @@
 #@color solo #A8F730
 #@color midi_channel_selector #A8F730
 #@color isolate #B9ECF2
+#@color solo_lock #3593DA
 #@color mute #FFFA87
 #@color mono #DEC
 #@color monitor #FFAB34
@@ -41,7 +42,7 @@
 #@color send_bg #C4C4B8
 
 #@color processor_frame_selected #E2CC33
-#@color processor_fader_bg #666666
+#@color processor_fader #666666
 #@color processor_fader_frame #7F7F7F
 #@color processor_prefader #4D0000
 #@color processor_prefader_frame #7F0000
index 196bb89710955bdc2f86d3d4c561904c685c08a2..770b9156fa4d01c1f78f36c57e2a286739fbf466 100644 (file)
     <Option name="waveform fill" value="3d4753dc"/>
     <Option name="zero line" value="b5b5b525"/>
     <Option name="zoom rect" value="c6d1b26d"/>
+    <Option name="processor prefader border start" value="630a0aff"/>
+    <Option name="processor prefader border end" value="630a0aff"/>
+    <Option name="processor prefader border start selected" value="edc400ff"/>
+    <Option name="processor prefader border end selected" value="ffd300ff"/>
+    <Option name="processor prefader fill start" value="873c3cff"/>
+    <Option name="processor prefader fill end" value="542525ff"/>
+    <Option name="processor prefader fill start active" value="873c3cff"/>
+    <Option name="processor prefader fill end active" value="542525ff"/>
+    <Option name="processor prefader fill start mid" value="873c3cff"/>
+    <Option name="processor prefader fill end mid" value="542525ff"/>
+    <Option name="processor prefader led" value="26550eff"/>
+    <Option name="processor prefader led active" value="78cb4eff"/>
+    <Option name="processor prefader led mid" value="26550eff"/>
+    <Option name="processor prefader text" value="aaaaa3ff"/>
+    <Option name="processor prefader text active" value="eeeeecff"/>
+    <Option name="processor prefader text mid" value="aaaaa3ff"/>
+    <Option name="processor fader border start" value="7cb5d9ff"/>
+    <Option name="processor fader border end" value="6493b0ff"/>
+    <Option name="processor fader border start selected" value="cdfaf8ff"/>
+    <Option name="processor fader border end selected" value="c0ebe9ff"/>
+    <Option name="processor fader fill start" value="5d90b0ff"/>
+    <Option name="processor fader fill end" value="154c6eff"/>
+    <Option name="processor fader fill start active" value="5d90b0ff"/>
+    <Option name="processor fader fill end active" value="154d6fff"/>
+    <Option name="processor fader fill start mid" value="5d90b0ff"/>
+    <Option name="processor fader fill end mid" value="154d6fff"/>
+    <Option name="processor fader led" value="26550eff"/>
+    <Option name="processor fader led active" value="78cb4eff"/>
+    <Option name="processor fader led mid" value="26550eff"/>
+    <Option name="processor fader text" value="aaaaa3ff"/>
+    <Option name="processor fader text active" value="eeeeecff"/>
+    <Option name="processor fader text mid" value="aaaaa3ff"/>
+    <Option name="processor postfader border start" value="1d631dff"/>
+    <Option name="processor postfader border end" value="1d631dff"/>
+    <Option name="processor postfader border start selected" value="46f046ff"/>
+    <Option name="processor postfader border end selected" value="46f046ff"/>
+    <Option name="processor postfader fill start" value="415947ff"/>
+    <Option name="processor postfader fill end" value="405945ff"/>
+    <Option name="processor postfader fill start active" value="415947ff"/>
+    <Option name="processor postfader fill end active" value="405945ff"/>
+    <Option name="processor postfader fill start mid" value="415947ff"/>
+    <Option name="processor postfader fill end mid" value="405945ff"/>
+    <Option name="processor postfader led" value="26550eff"/>
+    <Option name="processor postfader led active" value="78cb4eff"/>
+    <Option name="processor postfader led mid" value="26550eff"/>
+    <Option name="processor postfader text" value="aaaaa3ff"/>
+    <Option name="processor postfader text active" value="eeeeecff"/>
+    <Option name="processor postfader text mid" value="aaaaa3ff"/>
+    <Option name="monitor border start" value="9a908eff"/>
+    <Option name="monitor border end" value="675c5bff"/>
+    <Option name="monitor border start selected" value="46f046ff"/>
+    <Option name="monitor border end selected" value="46f046ff"/>
+    <Option name="monitor fill start" value="5d5856ff"/>
+    <Option name="monitor fill end" value="564d48ff"/>
+    <Option name="monitor fill start active" value="d3704fff"/>
+    <Option name="monitor fill end active" value="c58c41ff"/>
+    <Option name="monitor fill start mid" value="b25e42ff"/>
+    <Option name="monitor fill end mid" value="665646ff"/>
+    <Option name="monitor led" value="26550eff"/>
+    <Option name="monitor led active" value="78cb4eff"/>
+    <Option name="monitor led mid" value="26550eff"/>
+    <Option name="monitor text" value="aaaaa3ff"/>
+    <Option name="monitor text active" value="5d5a5bff"/>
+    <Option name="monitor text mid" value="aaaaa3ff"/>
+    <Option name="solo isolate border start" value="bbeff5ff"/>
+    <Option name="solo isolate border end" value="0041ddff"/>
+    <Option name="solo isolate border start selected" value="46f046ff"/>
+    <Option name="solo isolate border end selected" value="46f046ff"/>
+    <Option name="solo isolate fill start" value="475c5eff"/>
+    <Option name="solo isolate fill end" value="3e4f51ff"/>
+    <Option name="solo isolate fill start active" value="637f82ff"/>
+    <Option name="solo isolate fill end active" value="5b7577ff"/>
+    <Option name="solo isolate fill start mid" value="51686bff"/>
+    <Option name="solo isolate fill end mid" value="475c5eff"/>
+    <Option name="solo isolate led" value="3e4f51ff"/>
+    <Option name="solo isolate led active" value="9ff837ff"/>
+    <Option name="solo isolate led mid" value="6daa25ff"/>
+    <Option name="solo isolate text" value="e3e3d9ff"/>
+    <Option name="solo isolate text active" value="e3e3d9ff"/>
+    <Option name="solo isolate text mid" value="e3e3d9ff"/>
+    <Option name="solo safe border start" value="94e833ff"/>
+    <Option name="solo safe border end" value="54841cff"/>
+    <Option name="solo safe border start selected" value="3ca5f5ff"/>
+    <Option name="solo safe border end selected" value="2a75adff"/>
+    <Option name="solo safe fill start" value="536b6dff"/>
+    <Option name="solo safe fill end" value="3c5e13ff"/>
+    <Option name="solo safe fill start active" value="619921ff"/>
+    <Option name="solo safe fill end active" value="55841dff"/>
+    <Option name="solo safe fill start mid" value="5b7577ff"/>
+    <Option name="solo safe fill end mid" value="506568ff"/>
+    <Option name="solo safe led" value="477018ff"/>
+    <Option name="solo safe led active" value="9ff837ff"/>
+    <Option name="solo safe led mid" value="6daa25ff"/>
+    <Option name="solo safe text" value="e2e2d8ff"/>
+    <Option name="solo safe text active" value="e3e3d9ff"/>
+    <Option name="solo safe text mid" value="e3e3d9ff"/>
   </Canvas>
 </Ardour>
index 20d16ef2f2e749c277f1bf2292519b9d6d384a18..b4501e89de23783bd5786f6575d96c6316551c5c 100644 (file)
@@ -27,6 +27,7 @@
 #@color solo #A8F730
 #@color midi_channel_selector #A8F730
 #@color isolate #B9ECF2
+#@color solo_lock #3593DA
 #@color mute #FFFA87
 #@color mono #DEC
 #@color monitor #7596DE
index 9f0a3c03938ad9aa7574fc1263788ddff2824578..8daf1c2ceec3b4edefcd1aac1bc9caf6cc9a9efa 100644 (file)
@@ -78,15 +78,7 @@ widget "*MixerSoloButton" style:highest "mixer_solo_button"
 widget "*MixerSoloButton-alternate" style:highest "mixer_solo_button_alternate"
 widget "*MixerSoloButton-alternate2" style:highest "mixer_solo_button_alternate2"
 widget "*MixerSoloButton-active" style:highest "mixer_solo_button_active"
-
-widget "*MixerMonitorInputButton" style:highest "mixer_monitor_input"
-widget "*MixerMonitorInputButton-active" style:highest "mixer_monitor_input_active"
-widget "*MixerMonitorInputButton-alternate" style:highest "mixer_monitor_input_alternate"
-
-widget "*MixerMonitorDiskButton" style:highest "mixer_monitor_disk"
-widget "*MixerMonitorDiskButton-active" style:highest "mixer_monitor_disk_active"
-widget "*MixerMonitorDiskButton-alternate" style:highest "mixer_monitor_disk_alternate"
-
+widget "*monitor" style:highest "monitor"
 widget "*TrackLoopButton*" style:highest "track_loop_button"
 widget "*PanAutomationLineSelector*" style:highest "multiline_combo"
 widget "*EditorTimeButton*" style:highest "time_button"
@@ -386,19 +378,10 @@ widget "*RegionListWholeFile" style:highest "treeview_parent_node"
 widget "*EditorHScrollbar" style:highest "editor_hscrollbar"
 widget "*MidiListView*" style:highest "treeview_display"
 widget "*ProcessorList*" style:highest "processor_list"
-widget "*ProcessorFrameSelected" style:highest "processor_frame_selected"
-widget "*ProcessorFrameActiveSend" style:highest "processor_frame_active_send"
-widget "*ProcessorFaderFrame" style:highest "processor_fader_frame"
-widget "*ProcessorPreFader" style:highest "processor_prefader"
-widget "*ProcessorPreFaderFrame" style:highest "processor_prefader_frame"
-widget "*ProcessorFader" style:highest "processor_fader"
-widget "*ProcessorPostFader" style:highest "processor_postfader"
-widget "*ProcessorPostFaderFrame" style:highest "processor_postfader_frame"
 widget "*PortMatrixLabel*" style:highest "small_text"
 widget "*MidiTracerTextView" style:highest "midi_tracer_textview"
-widget "*SoloIsolatedLED" style:highest "solo_isolate_led"
-widget "*SoloSafeLED" style:highest "solo_safe_led"
-widget "*SoloLEDLabel" style:highest "very_small_text"
+widget "*solo isolate" style:highest "solo_isolate"
+widget "*solo safe" style:highest "solo_safe"
 widget "*ContrastingPopup" style:highest "contrasting_popup"
 widget "*ContrastingPopup*" style:highest "contrasting_popup"
 widget "*MidiChannelSelectorButton" style:highest "midi_channel_selector_button"
@@ -414,3 +397,7 @@ widget "*InsertTimeClock" style:highest "default_clock_display"
 widget "*EditorRouteGroupsAllGroupButton" style:highest "default_toggle_button"
 widget "*MidiSoundNotesButton" style:highest "default_toggle_button"
 widget "*MeasureLatencyButton" style:highest "default_toggle_button"
+widget "*processor prefader" style:highest "processor_prefader"
+widget "*processor fader" style:highest "processor_fader"
+widget "*processor postfader" style:highest "processor_postfader"
+widget "*ProcessorFrameActiveSend" style:highest "processor_frame_active_send"
diff --git a/gtk2_ardour/ardour_button.cc b/gtk2_ardour/ardour_button.cc
new file mode 100644 (file)
index 0000000..042e5fa
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+    Copyright (C) 2010 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 <iostream>
+#include <cmath>
+#include <algorithm>
+
+#include <pangomm/layout.h>
+
+#include "pbd/compose.h"
+
+#include "gtkmm2ext/utils.h"
+#include "gtkmm2ext/rgb_macros.h"
+
+#include "ardour_button.h"
+#include "ardour_ui.h"
+#include "global_signals.h"
+
+using namespace Gdk;
+using namespace Gtk;
+using namespace Glib;
+using std::max;
+using std::min;
+using std::cerr;
+using std::endl;
+
+ArdourButton::ArdourButton()
+        : _text_width (0)
+       , _text_height (0)
+       , _led_left (false)
+        , _diameter (0.0)
+        , _fixed_diameter (false)
+       , _distinct_led_click (true)
+       , edge_pattern (0)
+       , fill_pattern (0)
+       , led_inset_pattern (0)
+       , reflection_pattern (0)
+         
+{
+       ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler));
+}
+
+ArdourButton::~ArdourButton()
+{
+}
+
+void
+ArdourButton::set_text (const std::string& str)
+{
+       _text = str;
+
+       if (!_layout && !_text.empty()) {
+               _layout = Pango::Layout::create (get_pango_context());
+       } 
+       
+       _layout->set_text (str);
+
+       queue_resize ();
+}
+
+void
+ArdourButton::set_markup (const std::string& str)
+{
+       _text = str;
+
+       if (!_layout) {
+               _layout = Pango::Layout::create (get_pango_context());
+       } 
+
+       _layout->set_text (str);
+       queue_resize ();
+}
+
+void
+ArdourButton::render (cairo_t* cr)
+{
+        if (!_fixed_diameter) {
+                _diameter = std::min (_width, _height);
+        }
+
+       /* background fill. use parent window style, so that we fit in nicely.
+        */
+       
+       Color c = get_parent_bg ();
+       
+        cairo_rectangle (cr, 0, 0, _width, _height);
+        cairo_stroke_preserve (cr);
+        cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p());
+        cairo_fill (cr);
+
+       /* edge */
+
+       Gtkmm2ext::rounded_rectangle (cr, 0, 0, _width, _height, 9);
+       cairo_set_source (cr, edge_pattern);
+       cairo_fill (cr);
+
+       /*  button itself: leaves 1 pixel border of the edge visible all around. */
+
+       Gtkmm2ext::rounded_rectangle (cr, 1, 1, _width-2, _height-2, 9);
+       cairo_set_source (cr, fill_pattern);
+       cairo_fill (cr);
+
+       /* text, if any */
+
+       if (!_text.empty()) {
+               cairo_set_source_rgba (cr, text_r, text_g, text_b, text_a);
+               if (_led_left) {
+                       cairo_move_to (cr, _diameter + 3 + 4, _height/2.0 - _text_height/2.0);
+               } else {
+                       cairo_move_to (cr, 3, _height/2.0 - _text_height/2.0);
+               }
+               pango_cairo_show_layout (cr, _layout->gobj());
+       }
+
+       /* move to the center of the ArdourButton itself */
+
+       if (_led_left) {
+               cairo_translate (cr, 3 + (_diameter/2.0), _height/2.0);
+       } else {
+               cairo_translate (cr, _width - ((_diameter/2.0) + 4.0), _height/2.0);
+       }
+
+       //inset
+       cairo_arc (cr, 0, 0, _diameter/2, 0, 2 * M_PI);
+       cairo_set_source (cr, led_inset_pattern);
+       cairo_fill (cr);
+
+       //black ring
+       cairo_set_source_rgb (cr, 0, 0, 0);
+       cairo_arc (cr, 0, 0, _diameter/2-2, 0, 2 * M_PI);
+       cairo_fill(cr);
+
+       //led color
+       cairo_set_source_rgba (cr, led_r, led_g, led_b, led_a);
+       cairo_arc (cr, 0, 0, _diameter/2-3, 0, 2 * M_PI);
+       cairo_fill(cr);
+
+       //reflection
+       cairo_scale(cr, 0.7, 0.7);
+       cairo_arc (cr, 0, 0, _diameter/2-3, 0, 2 * M_PI);
+       cairo_set_source (cr, reflection_pattern);
+       cairo_fill (cr);
+       cairo_stroke (cr); // ??
+}
+
+void
+ArdourButton::set_state (CairoWidget::State s, bool yn)
+{
+       CairoWidget::set_state (s, yn);
+       set_colors ();
+}
+
+void
+ArdourButton::set_diameter (float d)
+{
+        _diameter = (d*2) + 5.0;
+
+        if (_diameter != 0.0) {
+                _fixed_diameter = true;
+        }
+
+        set_dirty ();
+}
+
+void
+ArdourButton::on_realize ()
+{
+        set_colors ();
+        CairoWidget::on_realize ();
+}
+
+void
+ArdourButton::on_size_request (Gtk::Requisition* req)
+{
+       int xpad = 0;
+       int ypad = 6;
+
+       if (!_text.empty()) {
+               _layout->get_pixel_size (_text_width, _text_height);
+               xpad += 6;
+       }
+               
+        if (_fixed_diameter) {
+                req->width = _text_width + (int) _diameter + xpad;
+                req->height = max (_text_height, (int) _diameter) + ypad;
+        } else {
+                CairoWidget::on_size_request (req);
+        }
+}
+
+void
+ArdourButton::set_colors ()
+{
+       uint32_t start_color;
+       uint32_t end_color;
+       uint32_t r, g, b, a;
+       uint32_t text_color;
+       uint32_t led_color;
+
+       /* we use the edge of the button to show Selected state, so the
+        * color/pattern used there will vary depending on that
+        */
+       
+       if (edge_pattern) {
+               cairo_pattern_destroy (edge_pattern);
+       }
+
+       edge_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, _height);
+       if (_state & CairoWidget::Selected) {
+               start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 border start selected", get_name()));
+               end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 border end selected", get_name()));
+       } else {
+               start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 border start", get_name()));
+               end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 border end", get_name()));
+       }
+       UINT_TO_RGBA (start_color, &r, &g, &b, &a);
+       cairo_pattern_add_color_stop_rgba (edge_pattern, 0, r/255.0,g/255.0,b/255.0, 0.7);
+       UINT_TO_RGBA (end_color, &r, &g, &b, &a);
+       cairo_pattern_add_color_stop_rgba (edge_pattern, 1, r/255.0,g/255.0,b/255.0, 0.7);
+
+       /* the fill pattern is used to indicate Normal/Active/Mid state
+        */
+
+       if (fill_pattern) {
+               cairo_pattern_destroy (fill_pattern);
+       }
+
+       fill_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, _height);
+       if (_state & Mid) {
+               start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 fill start mid", get_name()));
+               end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 fill end mid", get_name()));
+       } else if (_state & Active) {
+               start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 fill start active", get_name()));
+               end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 fill end active", get_name()));
+       } else {
+               start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 fill start", get_name()));
+               end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 fill end", get_name()));
+       }
+       UINT_TO_RGBA (start_color, &r, &g, &b, &a);
+       cairo_pattern_add_color_stop_rgba (fill_pattern, 0, r/255.0,g/255.0,b/255.0, a/255.0);
+       UINT_TO_RGBA (end_color, &r, &g, &b, &a);
+       cairo_pattern_add_color_stop_rgba (fill_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0);
+
+       if (led_inset_pattern) {
+               cairo_pattern_destroy (led_inset_pattern);
+       }
+
+       led_inset_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, _diameter);
+       cairo_pattern_add_color_stop_rgba (led_inset_pattern, 0, 0,0,0, 0.4);
+       cairo_pattern_add_color_stop_rgba (led_inset_pattern, 1, 1,1,1, 0.7);
+       
+       if (reflection_pattern) {
+               cairo_pattern_destroy (reflection_pattern);
+       }
+
+       reflection_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, _diameter/2-3);
+       cairo_pattern_add_color_stop_rgba (reflection_pattern, 0, 1,1,1, (_state & Active) ? 0.4 : 0.2);
+       cairo_pattern_add_color_stop_rgba (reflection_pattern, 1, 1,1,1, 0.0);
+
+       /* text and LED colors depend on Active/Normal/Mid */
+       if (_state & Active) {
+               text_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 text active", get_name()));
+               led_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 led active", get_name()));
+       } else if (_state & Mid) {
+               text_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 text mid", get_name()));
+               led_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 led active", get_name()));
+       } else {
+               text_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 text", get_name()));
+               led_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 led", get_name()));
+       }
+
+       UINT_TO_RGBA (text_color, &r, &g, &b, &a);
+       text_r = r/255.0;
+       text_g = g/255.0;
+       text_b = b/255.0;
+       text_a = a/255.0;
+       UINT_TO_RGBA (led_color, &r, &g, &b, &a);
+       led_r = r/255.0;
+       led_g = g/255.0;
+       led_b = b/255.0;
+       led_a = a/255.0;
+
+        set_dirty ();
+}
+
+void
+ArdourButton::set_led_left (bool yn)
+{
+       _led_left = yn;
+}
+
+bool
+ArdourButton::on_button_press_event (GdkEventButton *ev)
+{
+       if (_distinct_led_click) {
+               /* if within LED, swallow event */
+               
+               int top = lrint (_height/2.0 - _diameter/2.0);
+               int bottom = lrint (_height/2.0 + _diameter/2.0);
+               int left;
+               int right;
+               
+               if (_led_left) {
+                       left = 4;
+                       right = left + _diameter;
+               } else {
+                       left = lrint (_width - 4 - _diameter/2.0);
+                       right = left + _diameter;
+               }
+
+               if (ev->x >= left && ev->x <= right && ev->y <= bottom && ev->y >= top) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+bool
+ArdourButton::on_button_release_event (GdkEventButton *ev)
+{
+
+       if (_distinct_led_click) {
+
+               /* if within LED, emit signal */
+
+               int top = lrint (_height/2.0 - _diameter/2.0);
+               int bottom = lrint (_height/2.0 + _diameter/2.0);
+               int left;
+               int right;
+               if (_led_left) {
+                       left = 4;
+                       right = left + _diameter;
+               } else {
+                       left = lrint (_width - 4 - _diameter/2.0);
+                       right = left + _diameter;
+               }
+               
+               if (ev->x >= left && ev->x <= right && ev->y <= bottom && ev->y >= top) {
+                       signal_clicked(); /* EMIT SIGNAL */
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+void
+ArdourButton::set_distinct_led_click (bool yn)
+{
+       _distinct_led_click = yn;
+}
+
+void
+ArdourButton::color_handler ()
+{
+       set_colors ();
+       set_dirty ();
+}
diff --git a/gtk2_ardour/ardour_button.h b/gtk2_ardour/ardour_button.h
new file mode 100644 (file)
index 0000000..a499f60
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+    Copyright (C) 2010 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 __gtk2_ardour_ardour_button_h__
+#define __gtk2_ardour_ardour_button_h__
+
+#include <stdint.h>
+
+#include <gtkmm/activatable.h>
+
+#include "cairo_widget.h"
+
+class ArdourButton : public CairoWidget, Gtk::Activatable
+{
+  public:
+       ArdourButton ();
+       virtual ~ArdourButton ();
+
+        void set_diameter (float);
+
+       void set_text (const std::string&);
+       void set_markup (const std::string&);
+
+       void set_led_left (bool yn);
+       void set_distinct_led_click (bool yn);
+
+       sigc::signal<void> signal_clicked;
+
+       void set_state (State s, bool);
+
+  protected:
+       void render (cairo_t *);
+        void on_size_request (Gtk::Requisition* req);
+        void on_realize ();
+       bool on_button_press_event (GdkEventButton*);
+       bool on_button_release_event (GdkEventButton*);
+
+  private:
+       Glib::RefPtr<Pango::Layout> _layout;
+       std::string _text;
+       int     _text_width;
+       int     _text_height;
+       bool    _led_left;
+        float   _diameter;
+        bool    _fixed_diameter;
+       bool    _distinct_led_click;
+
+       cairo_pattern_t* edge_pattern;
+       cairo_pattern_t* fill_pattern;
+       cairo_pattern_t* led_inset_pattern;
+       cairo_pattern_t* reflection_pattern;
+
+       double text_r;
+       double text_g;
+       double text_b;
+       double text_a;
+
+       double led_r;
+       double led_g;
+       double led_b;
+       double led_a;
+
+        void set_colors ();
+       void color_handler ();
+};
+
+#endif /* __gtk2_ardour_ardour_button_h__ */
index 3f819829b90fac55d0e350739a845a8503138a02..937ba5ab819ae7743f01315c9bc8f3a5ca3a3a5d 100644 (file)
@@ -53,7 +53,9 @@ using namespace ARDOUR;
 void
 ARDOUR_UI::shutdown ()
 {
-       ui_config->save_state();
+       if (ui_config->dirty()) {
+               ui_config->save_state();
+       }
 }
 
 void
index bb627fc011baf760f07db026a135faa045044b64..c9381b7a6469474d520b58e51cc9e4d36d14b7b9 100644 (file)
@@ -867,7 +867,9 @@ ARDOUR_UI::save_ardour_state ()
                Config->add_extra_xml (_startup->engine_control()->get_state());
        }
        Config->save_state();
-       ui_config->save_state ();
+       if (ui_config->dirty()) {
+               ui_config->save_state ();
+       }
 
        XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
        XMLNode& mnode (mixer->get_state());
index 209770ab03c8c9287cbd8fa3c94425a2820cc055..11fcfdffd6997ce9e5bdecee06ac4d76e20d40fd 100644 (file)
 #include "gui_thread.h"
 
 CairoWidget::CairoWidget ()
-       : _width (1),
-         _height (1),
-         _dirty (true),
-         _pixmap (0)
+       : _width (1)
+       , _height (1)
+       , _state (CairoWidget::State (0))
+       , _dirty (true)
+       , _pixmap (0)
+         
 {
 
 }
@@ -109,3 +111,37 @@ CairoWidget::on_size_allocate (Gtk::Allocation& alloc)
 
        set_dirty ();
 }
+
+Gdk::Color
+CairoWidget::get_parent_bg ()
+{
+        Widget* parent;
+
+       parent = get_parent ();
+
+        while (parent && !parent->get_has_window()) {
+                parent = parent->get_parent();
+        }
+
+        if (parent && parent->get_has_window()) {
+               return parent->get_style ()->get_bg (parent->get_state());
+        } 
+
+       return get_style ()->get_bg (get_state());
+}
+
+void
+CairoWidget::set_state (CairoWidget::State s, bool yn)
+{
+       if (yn) {
+               if (!(_state & s)) {
+                       _state = CairoWidget::State (_state|s);
+                       StateChanged ();
+               }
+       } else {
+               if (_state & s) {
+                       _state = CairoWidget::State (_state & ~s);
+                       StateChanged ();
+               }
+       }
+}
index 8665f66198981e03ed39a2fd932ede6025979beb..e368a21a03454bd6d23bae5c2eca538a2ebac40f 100644 (file)
@@ -35,14 +35,33 @@ public:
 
        void set_dirty ();
 
+       /* widget states: unlike GTK, these OR-together so that
+          a widget can be both Active *and* Selected, rather than
+          each one being orthogonal.
+       */
+
+       enum State {
+               Active = 0x1,
+               Mid = 0x2,
+               Selected = 0x4,
+               Prelight = 0x8,
+               Insensitive = 0x10,
+       };
+
+       State state() const { return _state; }
+       virtual void set_state (State, bool);
+       sigc::signal<void> StateChanged;
+
 protected:
        /** Render the widget to the given Cairo context */
        virtual void render (cairo_t *) = 0;
        virtual bool on_expose_event (GdkEventExpose *);
        void on_size_allocate (Gtk::Allocation &);
+       Gdk::Color get_parent_bg ();
 
        int _width; ///< pixmap width
        int _height; ///< pixmap height
+       State _state;
 
 private:
        bool _dirty; ///< true if the pixmap requires re-rendering
index b8bb1f86081c0fca2bafcc2cfe9aa8659ba7b6b9..445b76ee1c8fb132770f73e448f80f74aed4a657 100644 (file)
@@ -136,3 +136,28 @@ CANVAS_VARIABLE(canvasvar_WaveFormClip, "clipped waveform")
 CANVAS_VARIABLE(canvasvar_WaveFormFill, "waveform fill")
 CANVAS_VARIABLE(canvasvar_ZeroLine, "zero line")
 CANVAS_VARIABLE(canvasvar_ZoomRect, "zoom rect")
+
+#define BUTTON_VARS(root,name) \
+CANVAS_VARIABLE(canvasvar_ ## root ## BorderStart, name " border start") \
+CANVAS_VARIABLE(canvasvar_ ## root ## BorderEnd, name " border end") \
+CANVAS_VARIABLE(canvasvar_ ## root ## BorderStartSelected, name " border start selected") \
+CANVAS_VARIABLE(canvasvar_ ## root ## BorderEndSelected, name " border end selected") \
+CANVAS_VARIABLE(canvasvar_ ## root ## FillStart, name " fill start") \
+CANVAS_VARIABLE(canvasvar_ ## root ## FillEnd, name " fill end") \
+CANVAS_VARIABLE(canvasvar_ ## root ## FillStartActive, name " fill start active") \
+CANVAS_VARIABLE(canvasvar_ ## root ## FillEndActive, name " fill end active") \
+CANVAS_VARIABLE(canvasvar_ ## root ## FillStartMid, name " fill start mid") \
+CANVAS_VARIABLE(canvasvar_ ## root ## FillEndMid, name " fill end mid") \
+CANVAS_VARIABLE(canvasvar_ ## root ## LED, name " led") \
+CANVAS_VARIABLE(canvasvar_ ## root ## LEDActive, name " led active") \
+CANVAS_VARIABLE(canvasvar_ ## root ## LEDMid, name " led mid") \
+CANVAS_VARIABLE(canvasvar_ ## root ## Text, name " text") \
+CANVAS_VARIABLE(canvasvar_ ## root ## TextActive, name " text active") \
+CANVAS_VARIABLE(canvasvar_ ## root ## TextMid, name " text mid") 
+
+BUTTON_VARS(ProcessorPreFader, "processor prefader")
+BUTTON_VARS(ProcessorFader, "processor fader")
+BUTTON_VARS(ProcessorPostFader, "processor postfader")
+BUTTON_VARS(MonitorButton, "monitor")
+BUTTON_VARS(SoloIsolateButton, "solo isolate")
+BUTTON_VARS(SoloSafeButton, "solo safe")
index 9a93e048d1d495247344f1115246137ded9d547d..259ebccd2d3137f58fa6669f2212fc3d9163639c 100644 (file)
@@ -70,15 +70,15 @@ LED::render (cairo_t* cr)
                 c = style->get_bg (get_state());
         }
 
-
+#if 0
         cairo_rectangle(cr, 0, 0, _width, _height);
         cairo_stroke_preserve(cr);
         cairo_set_source_rgb(cr, c.get_red_p(), c.get_green_p(), c.get_blue_p());
         cairo_fill(cr);
+#endif
 
        cairo_translate(cr, _width/2, _height/2);
 
-#if 0
        //inset
        cairo_pattern_t *pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, _diameter);
        cairo_pattern_add_color_stop_rgba (pat, 0, 0,0,0, 0.4);
@@ -107,15 +107,18 @@ LED::render (cairo_t* cr)
        cairo_set_source (cr, pat2);
        cairo_fill (cr);
        cairo_pattern_destroy (pat2);
-#endif
-
-       cairo_set_source_rgba (cr, _red, _green, _blue,  1.0);
-       cairo_arc (cr, 0, 0, _diameter/2-5, 0, 2 * M_PI);
-       cairo_fill(cr);
 
        cairo_stroke (cr);
 }
 
+void
+LED::set_active (bool yn) 
+{
+       _active = yn;
+       _visual_state = (yn ? 1 : 0);
+       set_colors_from_style ();
+}
+
 void
 LED::set_visual_state (int32_t s)
 {
index e2009ce1925ebf58967ef343161f11ab1023bb3f..e8514d60c053017e2121bb7664204ebe338dcb41 100644 (file)
@@ -30,6 +30,8 @@ class LED : public CairoWidget
        LED ();
        virtual ~LED ();
 
+       void set_active (bool yn);
+       bool active () const { return _active; }
         void set_visual_state (int32_t s);
         int32_t visual_state() const { return _visual_state; }
         void set_diameter (float);
index 5ce4caa3af1b74866a95e2073aa5fab38ccc17e8..7866cef0d8d9595d8d940fed7a7215f03c56a2e0 100644 (file)
@@ -56,7 +56,7 @@
 #include "mixer_strip.h"
 #include "mixer_ui.h"
 #include "keyboard.h"
-#include "led.h"
+#include "ardour_button.h"
 #include "public_editor.h"
 #include "send_ui.h"
 #include "io_selector.h"
@@ -86,7 +86,7 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session* sess, bool in_mixer)
        , gpm (sess, 250)
        , panners (sess)
        , button_table (3, 1)
-       , solo_led_table (2, 2)
+       , rec_solo_table (2, 2)
        , top_button_table (1, 2)
        , middle_button_table (1, 2)
        , bottom_button_table (1, 2)
@@ -185,54 +185,42 @@ MixerStrip::init ()
        mute_button->set_name ("MixerMuteButton");
        solo_button->set_name ("MixerSoloButton");
 
-       monitor_input_button->set_name ("MixerMonitorInputButton");
-       monitor_disk_button->set_name ("MixerMonitorInputButton");
+       monitor_input_button->set_diameter (3);
+       monitor_disk_button->set_diameter (3);
 
-        solo_isolated_led = manage (new LED);
+        solo_isolated_led = manage (new ArdourButton);
         solo_isolated_led->show ();
-        solo_isolated_led->set_diameter (6);
+        solo_isolated_led->set_diameter (3);
         solo_isolated_led->set_no_show_all (true);
-        solo_isolated_led->set_name (X_("SoloIsolatedLED"));
+        solo_isolated_led->set_name (X_("solo isolate"));
         solo_isolated_led->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
         solo_isolated_led->signal_button_release_event().connect (sigc::mem_fun (*this, &RouteUI::solo_isolate_button_release));
        UI::instance()->set_tip (solo_isolated_led, _("Isolate Solo"), "");
 
-        solo_safe_led = manage (new LED);
+        solo_safe_led = manage (new ArdourButton);
         solo_safe_led->show ();
-        solo_safe_led->set_diameter (6);
+        solo_safe_led->set_diameter (3);
         solo_safe_led->set_no_show_all (true);
-        solo_safe_led->set_name (X_("SoloSafeLED"));
+        solo_safe_led->set_name (X_("solo safe"));
         solo_safe_led->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
         solo_safe_led->signal_button_release_event().connect (sigc::mem_fun (*this, &RouteUI::solo_safe_button_release));
        UI::instance()->set_tip (solo_safe_led, _("Lock Solo Status"), "");
 
-       _iso_label = manage (new Label (_("iso")));
-       _safe_label = manage (new Label (_("lock")));
-
-       _iso_label->set_name (X_("SoloLEDLabel"));
-       _safe_label->set_name (X_("SoloLEDLabel"));
-
-       _iso_label->show ();
-       _safe_label->show ();
-
-        solo_led_table.set_spacings (0);
-        solo_led_table.set_border_width (1);
-       solo_led_table.attach (*_iso_label, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
-        solo_led_table.attach (*solo_isolated_led, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL);
-       solo_led_table.attach (*_safe_label, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
-        solo_led_table.attach (*solo_safe_led, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL);
-        solo_led_table.show ();
+       solo_safe_led->set_text (_("lock"));
+       solo_isolated_led->set_text (_("iso"));
 
        top_button_table.set_homogeneous (true);
-       top_button_table.set_spacings (0);
+       top_button_table.set_spacings (2);
        top_button_table.attach (*monitor_input_button, 0, 1, 0, 1);
         top_button_table.attach (*monitor_disk_button, 1, 2, 0, 1);
        top_button_table.show ();
 
-       below_panner_box.set_border_width (2);
-       below_panner_box.set_spacing (2);
-        below_panner_box.pack_end (solo_led_table, false, false);
-        below_panner_box.show ();
+       rec_solo_table.set_homogeneous (true);
+       rec_solo_table.set_row_spacings (2);
+       rec_solo_table.set_col_spacings (2);
+        rec_solo_table.attach (*solo_isolated_led, 1, 2, 0, 1);
+        rec_solo_table.attach (*solo_safe_led, 1, 2, 1, 2);
+        rec_solo_table.show ();
 
        button_table.set_homogeneous (true);
        button_table.set_spacings (0);
@@ -281,9 +269,9 @@ MixerStrip::init ()
        global_vpacker.pack_start (button_table, Gtk::PACK_SHRINK);
        global_vpacker.pack_start (processor_box, true, true);
        global_vpacker.pack_start (panners, Gtk::PACK_SHRINK);
-       global_vpacker.pack_start (top_button_table, Gtk::PACK_SHRINK);
-       global_vpacker.pack_start (below_panner_box, Gtk::PACK_SHRINK);
-       global_vpacker.pack_start (middle_button_table, Gtk::PACK_SHRINK);
+       global_vpacker.pack_start (top_button_table, Gtk::PACK_SHRINK, 2);
+       global_vpacker.pack_start (rec_solo_table, Gtk::PACK_SHRINK, 2);
+       global_vpacker.pack_start (middle_button_table, Gtk::PACK_SHRINK, 2);
        global_vpacker.pack_start (gpm, Gtk::PACK_SHRINK);
        global_vpacker.pack_start (bottom_button_table, Gtk::PACK_SHRINK);
        global_vpacker.pack_start (output_button, Gtk::PACK_SHRINK);
@@ -362,11 +350,11 @@ void
 MixerStrip::set_route (boost::shared_ptr<Route> rt)
 {
        if (rec_enable_button->get_parent()) {
-               below_panner_box.remove (*rec_enable_button);
+               rec_solo_table.remove (*rec_enable_button);
        }
 
        if (show_sends_button->get_parent()) {
-               below_panner_box.remove (*show_sends_button);
+               rec_solo_table.remove (*show_sends_button);
        }
 
        processor_box.set_route (rt);
@@ -388,10 +376,10 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
 
        if (route()->is_master()) {
                solo_button->hide ();
-               below_panner_box.hide ();
+               rec_solo_table.hide ();
        } else {
                solo_button->show ();
-               below_panner_box.show ();
+               rec_solo_table.show ();
        }
 
        if (_mixer_owned && (route()->is_master() || route()->is_monitor())) {
@@ -453,7 +441,7 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
 
        if (is_track ()) {
 
-               below_panner_box.pack_start (*rec_enable_button);
+               rec_solo_table.attach (*rec_enable_button, 0, 1, 0, 2);
                rec_enable_button->set_sensitive (_session->writable());
                rec_enable_button->show();
 
@@ -462,7 +450,7 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
                /* non-master bus */
 
                if (!_route->is_master()) {
-                       below_panner_box.pack_start (*show_sends_button);
+                       rec_solo_table.attach (*show_sends_button, 0, 1, 0, 2);
                        show_sends_button->show();
                }
        }
@@ -586,8 +574,8 @@ MixerStrip::set_width_enum (Width w, void* owner)
                                        panners.astate_string(_route->panner()->automation_state()));
                }
 
-               _iso_label->show ();
-               _safe_label->show ();
+               solo_isolated_led->set_text (_("iso"));
+               solo_safe_led->set_text (_("lock"));
 
                Gtkmm2ext::set_size_request_to_display_given_text (name_button, "long", 2, 2);
                set_size_request (-1, -1);
@@ -609,9 +597,9 @@ MixerStrip::set_width_enum (Width w, void* owner)
                        ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (
                        panners.short_astate_string(_route->panner()->automation_state()));
                }
-
-               _iso_label->hide ();
-               _safe_label->hide ();
+               
+               solo_isolated_led->set_text ("");
+               solo_safe_led->set_text ("");
 
                Gtkmm2ext::set_size_request_to_display_given_text (name_button, longest_label.c_str(), 2, 2);
                set_size_request (max (50, gpm.get_gm_width()), -1);
@@ -1737,11 +1725,20 @@ MixerStrip::set_button_names ()
        case Wide:
                rec_enable_button_label.set_text (_("Rec"));
                mute_button_label.set_text (_("Mute"));
-               monitor_input_button_label.set_text (_("In"));
-               monitor_disk_button_label.set_text (_("Disk"));
+               monitor_input_button->set_text (_("In"));
+               monitor_disk_button->set_text (_("Disk"));
+
                if (_route && _route->solo_safe()) {
-                       solo_button_label.set_text (X_("!"));
+                       solo_button->remove ();
+                       if (solo_safe_image == 0) {
+                               solo_safe_image = new Gtk::Image (::get_icon("solo-safe-enabled"));
+                               solo_safe_image->show ();
+                       }
+                       solo_button->add (*solo_safe_image);
                } else {
+                       solo_button->remove ();
+                       solo_button->add (solo_button_label);
+                       solo_button_label.show ();
                        if (!Config->get_solo_control_is_listen_control()) {
                                solo_button_label.set_text (_("Solo"));
                        } else {
@@ -1760,10 +1757,19 @@ MixerStrip::set_button_names ()
        default:
                rec_enable_button_label.set_text (_("R"));
                mute_button_label.set_text (_("M"));
-               monitor_input_button_label.set_text (_("I"));
-               monitor_disk_button_label.set_text (_("D"));
+               monitor_input_button->set_text (_("I"));
+               monitor_disk_button->set_text (_("D"));
                if (_route && _route->solo_safe()) {
-                       solo_button_label.set_text (X_("!"));
+                       solo_button->remove ();
+                       if (solo_safe_image == 0) {
+                               solo_safe_image = new Gtk::Image (::get_icon("solo-safe-enabled"));
+                               solo_safe_image->show ();
+                       }
+                       solo_button->add (*solo_safe_image);
+               } else {
+                       solo_button->remove ();
+                       solo_button->add (solo_button_label);
+                       solo_button_label.show ();
                        if (!Config->get_solo_control_is_listen_control()) {
                                solo_button_label.set_text (_("S"));
                        } else {
index b08e1da29ccabfee330cd02205e52ca9dfd491f4..3c123792f97a52b361bc92b49a64acbd9f93151e 100644 (file)
@@ -162,15 +162,11 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
        PannerUI     panners;
 
        Gtk::Table button_table;
-       Gtk::Table solo_led_table;
-       Gtk::HBox  below_panner_box;
+       Gtk::Table rec_solo_table;
        Gtk::Table top_button_table;
        Gtk::Table middle_button_table;
        Gtk::Table bottom_button_table;
 
-       Gtk::Label* _iso_label;
-       Gtk::Label* _safe_label;
-
        Gtk::Button                  gain_unit_button;
        Gtk::Label                   gain_unit_label;
        Gtk::Button                  meter_point_button;
index 26ec5f6c24af5ae6ddbc458ff5efe5fedcb37f90..0632147bbad67cabaa51dee2226d3f4cdd8fb676 100644 (file)
@@ -101,50 +101,32 @@ ProcessorEntry::ProcessorEntry (boost::shared_ptr<Processor> p, Width w)
        , _width (w)
        , _visual_state (Gtk::STATE_NORMAL)
 {
-       _hbox.pack_start (_active, false, false);
-       _event_box.add (_name);
-       _hbox.pack_start (_event_box, true, true);
-       _vbox.pack_start (_hbox);
-       _frame.add (_vbox);
-
-       /* without this, the border is mis-drawn on some systems */
-       _vbox.set_border_width (1);
-
-       _name.set_alignment (0, 0.5);
-       _name.set_text (name ());
-       _name.set_padding (2, 2);
-
-       if (boost::dynamic_pointer_cast<Amp> (p)) {
-               /* Fader processor gets a special look */
-               _event_box.set_name ("ProcessorFader");
-               _frame.set_name ("ProcessorFaderFrame");
-               _name.set_padding (2, 4);
-       }
-
-       _active.set_active (_processor->active ());
-       _active.signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::active_toggled));
-
-       _frame.show ();
+       _vbox.pack_start (_button, true, true);
        _vbox.show ();
-       _hbox.show ();
-       _event_box.show ();
-       _name.show ();
-       _active.show ();
+       
+       _button.set_state (CairoWidget::Active, _processor->active());
+       _button.set_diameter (3);
+       _button.signal_clicked.connect (sigc::mem_fun (*this, &ProcessorEntry::led_clicked));
+       _button.set_text (name());
+       _button.set_led_left (true);
+       _button.show ();
 
        _processor->ActiveChanged.connect (active_connection, invalidator (*this), boost::bind (&ProcessorEntry::processor_active_changed, this), gui_context());
        _processor->PropertyChanged.connect (name_connection, invalidator (*this), ui_bind (&ProcessorEntry::processor_property_changed, this, _1), gui_context());
+
+       setup_visuals ();
 }
 
 EventBox&
 ProcessorEntry::action_widget ()
 {
-       return _event_box;
+       return _button;
 }
 
 Gtk::Widget&
 ProcessorEntry::widget ()
 {
-       return _frame;
+       return _vbox;
 }
 
 string
@@ -154,17 +136,32 @@ ProcessorEntry::drag_text () const
 }
 
 void
-ProcessorEntry::set_visual_state (Gtk::StateType t)
+ProcessorEntry::set_position (Position p)
 {
-       _visual_state = t;
+       _position = p;
        setup_visuals ();
 }
 
 void
-ProcessorEntry::set_position (Position p)
+ProcessorEntry::set_visual_state (Gtk::StateType t)
 {
-       _position = p;
-       setup_visuals ();
+       /* map from GTK state to CairoWidget */
+
+       switch (t) {
+       case Gtk::STATE_ACTIVE:
+               _button.set_state (CairoWidget::Active, true);
+               break;
+
+       case Gtk::STATE_SELECTED:
+               _button.set_state (CairoWidget::Selected, true);
+               break;
+
+       case Gtk::STATE_NORMAL:
+       default:
+               _button.set_state (CairoWidget::Selected, false);
+               _button.set_state (CairoWidget::Active, false);
+               break;
+       }
 }
 
 void
@@ -172,42 +169,15 @@ ProcessorEntry::setup_visuals ()
 {
        switch (_position) {
        case PreFader:
-               _event_box.set_name ("ProcessorPreFader");
-               if (_visual_state == Gtk::STATE_NORMAL) {
-                       _frame.set_name ("ProcessorPreFaderFrame");
-               }
+               _button.set_name ("processor prefader");
                break;
 
        case Fader:
-               _event_box.set_name ("ProcessorFader");
-               if (_visual_state == Gtk::STATE_NORMAL) {
-                       _frame.set_name ("ProcessorFaderFrame");
-               }
+               _button.set_name ("processor fader");
                break;
 
        case PostFader:
-               _event_box.set_name ("ProcessorPostFader");
-               if (_visual_state == Gtk::STATE_NORMAL) {
-                       _frame.set_name ("ProcessorPostFaderFrame");
-               }
-               break;
-       }
-
-       switch (_visual_state) {
-       case Gtk::STATE_NORMAL:
-               /* _frame has been set up above */
-               _event_box.set_state (Gtk::STATE_NORMAL);
-               break;
-       case Gtk::STATE_SELECTED:
-               _frame.set_name ("ProcessorFrameSelected");
-               /* don't change the background of the box when it is selected */
-               _event_box.set_state (Gtk::STATE_NORMAL);
-               break;
-       case Gtk::STATE_ACTIVE:
-               _frame.set_name ("ProcessorFrameActiveSend");
-               _event_box.set_state (Gtk::STATE_ACTIVE);
-               break;
-       default:
+               _button.set_name ("processor postfader");
                break;
        }
 }
@@ -226,32 +196,26 @@ ProcessorEntry::set_enum_width (Width w)
 }
 
 void
-ProcessorEntry::active_toggled ()
+ProcessorEntry::led_clicked()
 {
-       if (_active.get_active ()) {
-               if (!_processor->active ()) {
-                       _processor->activate ();
-               }
+       if (!_processor->active ()) {
+               _processor->activate ();
        } else {
-               if (_processor->active ()) {
-                       _processor->deactivate ();
-               }
+               _processor->deactivate ();
        }
 }
 
 void
 ProcessorEntry::processor_active_changed ()
 {
-       if (_active.get_active () != _processor->active ()) {
-               _active.set_active (_processor->active ());
-       }
+       _button.set_state (CairoWidget::Active, _processor->active());
 }
 
 void
 ProcessorEntry::processor_property_changed (const PropertyChange& what_changed)
 {
        if (what_changed.contains (ARDOUR::Properties::name)) {
-               _name.set_text (name ());
+               _button.set_text (name ());
        }
 }
 
index eabe32a631adb1c8376309d0bd722512eba9dc87..68ba7e9679e2f9a562f6009c657b2de218fa6548 100644 (file)
@@ -53,6 +53,7 @@
 #include "send_ui.h"
 #include "enums.h"
 #include "window_proxy.h"
+#include "ardour_button.h"
 
 class MotionController;
 class PluginSelector;
@@ -123,24 +124,18 @@ public:
        virtual void hide_things () {}
 
 protected:
-
-       virtual void setup_visuals ();
-
+       ArdourButton _button;
        Gtk::VBox _vbox;
        Position _position;
 
-private:
+       virtual void setup_visuals ();
 
-       void active_toggled ();
+private:
+       void led_clicked();
        void processor_active_changed ();
        void processor_property_changed (const PBD::PropertyChange&);
        std::string name () const;
 
-       Gtk::Frame _frame;
-       Gtk::EventBox _event_box;
-       Gtk::Label _name;
-       Gtk::HBox _hbox;
-       Gtk::CheckButton _active;
        boost::shared_ptr<ARDOUR::Processor> _processor;
        Width _width;
        Gtk::StateType _visual_state;
index 6e409c05c2d733a56c82622b5fb189a67ae25ac4..736476e49b1208288e73276e192907449c06a778 100644 (file)
@@ -2350,8 +2350,16 @@ RouteTimeAxisView::set_button_names ()
        rec_enable_button_label.set_text (_("r"));
 
         if (_route && _route->solo_safe()) {
-                solo_button_label.set_text (X_("!"));
+               solo_button->remove ();
+               if (solo_safe_image == 0) {
+                       solo_safe_image = new Gtk::Image (::get_icon("solo-safe-enabled"));
+                       solo_safe_image->show ();
+               }
+               solo_button->add (*solo_safe_image);
         } else {
+               solo_button->remove ();
+               solo_button->add (solo_button_label);
+               solo_button_label.show ();
                 if (Config->get_solo_control_is_listen_control()) {
                         switch (Config->get_listen_position()) {
                         case AfterFaderListen:
index 9cb4941566b2dcce40fdf82c35a65bdb4d76f9fe..c0dd43404e9c77a1c3ceb0911d474890d69c899d 100644 (file)
@@ -34,7 +34,7 @@
 #include "ardour_ui.h"
 #include "editor.h"
 #include "route_ui.h"
-#include "led.h"
+#include "ardour_button.h"
 #include "keyboard.h"
 #include "utils.h"
 #include "prompter.h"
@@ -81,6 +81,7 @@ RouteUI::~RouteUI()
        delete sends_menu;
         delete record_menu;
        delete _invert_menu;
+       delete solo_safe_image;
 }
 
 void
@@ -107,6 +108,7 @@ RouteUI::init ()
        multiple_mute_change = false;
        multiple_solo_change = false;
        _i_am_the_modifier = 0;
+       solo_safe_image = 0;
 
        setup_invert_buttons ();
 
@@ -137,19 +139,15 @@ RouteUI::init ()
        // show_sends_button->set_self_managed (true);
        UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
 
-       monitor_input_button = manage (new BindableToggleButton ());
-       // monitor_input_button->set_self_managed (true);
-       monitor_input_button->set_name ("MonitorInputButton");
-       monitor_input_button->add (monitor_input_button_label);
-       monitor_input_button_label.show ();
+       monitor_input_button = manage (new ArdourButton ());
+       monitor_input_button->set_name ("monitor");
+       monitor_input_button->set_text (_("In"));
        UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
        monitor_input_button->set_no_show_all (true);
 
-       monitor_disk_button = manage (new BindableToggleButton ());
-       // monitor_disk_button->set_self_managed (true);
-       monitor_disk_button->set_name ("MonitorDiskButton");
-       monitor_disk_button->add (monitor_disk_button_label);
-       monitor_disk_button_label.show ();
+       monitor_disk_button = manage (new ArdourButton ());
+       monitor_disk_button->set_name ("monitor");
+       monitor_disk_button->set_text (_("Disk"));
        UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
        monitor_disk_button->set_no_show_all (true);
 
@@ -170,12 +168,15 @@ RouteUI::init ()
        solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
        mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
        mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
+       
+       monitor_input_button->set_distinct_led_click (false);
+       monitor_disk_button->set_distinct_led_click (false);
 
-       monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press), false);
-       monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release), false);
+       monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
+       monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
 
-       monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press), false);
-       monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release), false);
+       monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
+       monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
 }
 
 void
@@ -607,22 +608,26 @@ RouteUI::update_monitoring_display ()
        MonitorState ms = t->monitoring_state();
 
        if (t->monitoring_choice() & MonitorInput) {
-               monitor_input_button->set_visual_state (1);
+               monitor_input_button->set_state (CairoWidget::Active, true);
+               monitor_input_button->set_state (CairoWidget::Mid, false);
        } else {
                if (ms & MonitoringInput) {
-                       monitor_input_button->set_visual_state (2);
+                       monitor_input_button->set_state (CairoWidget::Mid, true);
+                       monitor_input_button->set_state (CairoWidget::Active, false);
                } else {
-                       monitor_input_button->set_visual_state (0);
+                       monitor_input_button->set_state (CairoWidget::State (CairoWidget::Active|CairoWidget::Mid), false);
                }
        }
 
        if (t->monitoring_choice() & MonitorDisk) {
-               monitor_disk_button->set_visual_state (1);
+               monitor_disk_button->set_state (CairoWidget::Active, true);
+                       monitor_disk_button->set_state (CairoWidget::Mid, false);
        } else {
                if (ms & MonitoringDisk) {
-                       monitor_disk_button->set_visual_state (2);
+                       monitor_disk_button->set_state (CairoWidget::Mid, true);
+                       monitor_disk_button->set_state (CairoWidget::Active, false);
                } else {
-                       monitor_disk_button->set_visual_state (0);
+                       monitor_disk_button->set_state (CairoWidget::State (CairoWidget::Active|CairoWidget::Mid), false);
                }
        }
 }
@@ -1061,11 +1066,11 @@ RouteUI::update_solo_display ()
         set_button_names ();
 
         if (solo_isolated_led) {
-                solo_isolated_led->set_visual_state (_route->solo_isolated() ? 1 : 0);
+                solo_isolated_led->set_state (CairoWidget::Active, _route->solo_isolated());
         }
 
         if (solo_safe_led) {
-                solo_safe_led->set_visual_state (_route->solo_safe() ? 1 : 0);
+                solo_safe_led->set_state (CairoWidget::Active, _route->solo_safe());
         }
 
        solo_button->set_visual_state (solo_visual_state (_route));
@@ -1335,7 +1340,7 @@ RouteUI::solo_isolate_button_release (GdkEventButton* ev)
                 return true;
         }
 
-        bool view = (solo_isolated_led->visual_state() != 0);
+        bool view = (solo_isolated_led->state() & (CairoWidget::Active|CairoWidget::Mid));
         bool model = _route->solo_isolated();
 
         /* called BEFORE the view has changed */
@@ -1366,7 +1371,7 @@ RouteUI::solo_isolate_button_release (GdkEventButton* ev)
 bool
 RouteUI::solo_safe_button_release (GdkEventButton*)
 {
-        _route->set_solo_safe (!(solo_safe_led->visual_state() > 0), this);
+        _route->set_solo_safe (!(solo_safe_led->state() & (CairoWidget::Active|CairoWidget::Mid)), this);
         return true;
 }
 
index d6667a3eebf4799f3f56b4dc967077045340993d..e9d81451f6d7497ae544bfeb6d97ba62290d7b80 100644 (file)
@@ -47,7 +47,7 @@ namespace Gtk {
 }
 
 class BindableToggleButton;
-class LED;
+class ArdourButton;
 
 class RouteUI : public virtual AxisView
 {
@@ -94,11 +94,13 @@ class RouteUI : public virtual AxisView
        BindableToggleButton* solo_button;
        BindableToggleButton* rec_enable_button; /* audio tracks */
        BindableToggleButton* show_sends_button; /* busses */
-       BindableToggleButton* monitor_input_button;
-       BindableToggleButton* monitor_disk_button;
+       ArdourButton* monitor_input_button;
+       ArdourButton* monitor_disk_button;
 
-        LED* solo_safe_led;
-        LED* solo_isolated_led;
+       Gtk::Image* solo_safe_image;
+
+        ArdourButton* solo_safe_led;
+        ArdourButton* solo_isolated_led;
 
        Gtk::Label solo_button_label;
        Gtk::Label mute_button_label;
index 8c2f92768b9a4f5076f332d0628ea2de0e58bbc7..b800554fb9ad2a0d9ee02248b36d9e40ecb8a50b 100644 (file)
@@ -163,6 +163,7 @@ ThemeManager::button_press_event (GdkEventButton* ev)
 
                                ccvar = (*iter)[columns.pVar];
                                ccvar->set(rgba);
+                               ARDOUR_UI::config()->set_dirty ();
 
                                //ColorChanged (rgba);
                                ColorsChanged();//EMIT SIGNAL
@@ -227,6 +228,7 @@ ThemeManager::on_dark_theme_button_toggled()
        } else {
                ARDOUR_UI::config()->ui_rc_file.set("ardour3_ui_dark.rc");
        }
+       ARDOUR_UI::config()->set_dirty ();
 
        load_rc_file (ARDOUR_UI::config()->ui_rc_file.get(), true);
 }
@@ -251,19 +253,20 @@ ThemeManager::setup_theme ()
        int r, g, b, a;
        color_list->clear();
 
-       for (std::vector<UIConfigVariable<uint32_t> *>::iterator i = ARDOUR_UI::config()->canvas_colors.begin(); i != ARDOUR_UI::config()->canvas_colors.end(); i++) {
+       for (std::map<std::string,UIConfigVariable<uint32_t> *>::iterator i = ARDOUR_UI::config()->canvas_colors.begin(); i != ARDOUR_UI::config()->canvas_colors.end(); i++) {
 
                TreeModel::Row row = *(color_list->append());
 
                Gdk::Color col;
-               uint32_t rgba = (*i)->get();
+               UIConfigVariable<uint32_t>* var = i->second;
+               uint32_t rgba = var->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);
 
-               row[columns.name] = (*i)->name();
+               row[columns.name] = var->name();
                row[columns.color] = "";
-               row[columns.pVar] = *i;
+               row[columns.pVar] = var;
                row[columns.rgba] = rgba;
                row[columns.gdkcolor] = col;
 
index 10628334fdae605d9ba51e3852f80dfc970eb646..84975bdbf2559e9624f303e7a5bf30cb5ec59093 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include <unistd.h>
+#include <cstdlib>
 #include <cstdio> /* for snprintf, grrr */
 
 #include <glibmm/miscutils.h>
@@ -28,6 +29,8 @@
 #include "pbd/file_utils.h"
 #include "pbd/error.h"
 
+#include "gtkmm2ext/rgb_macros.h"
+
 #include "ardour/ardour.h"
 #include "ardour/filesystem_paths.h"
 
@@ -49,7 +52,7 @@ UIConfiguration::UIConfiguration ()
 #include "canvas_vars.h"
 #undef  UI_CONFIG_VARIABLE
 #undef  CANVAS_VARIABLE
-       hack(true)
+       _dirty (false)
 {
        load_state();
 }
@@ -73,8 +76,7 @@ UIConfiguration::load_defaults ()
        }
 
        if (find_file_in_search_path (ardour_search_path() + system_config_search_path(),
-                                     rcfile, default_ui_rc_file) )
-       {
+                                     rcfile, default_ui_rc_file) ) {
                XMLTree tree;
                found = 1;
 
@@ -91,6 +93,8 @@ UIConfiguration::load_defaults ()
                        error << string_compose(_("default ui configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
                        return -1;
                }
+
+               _dirty = false;
        }
 
        return found;
@@ -104,8 +108,7 @@ UIConfiguration::load_state ()
        sys::path default_ui_rc_file;
 
        if ( find_file_in_search_path (ardour_search_path() + system_config_search_path(),
-                       "ardour3_ui_default.conf", default_ui_rc_file) )
-       {
+                       "ardour3_ui_default.conf", default_ui_rc_file) ) {
                XMLTree tree;
                found = true;
 
@@ -127,8 +130,7 @@ UIConfiguration::load_state ()
        sys::path user_ui_rc_file;
 
        if (find_file_in_search_path (ardour_search_path() + user_config_directory(),
-                       "ardour3_ui.conf", user_ui_rc_file))
-       {
+                       "ardour3_ui.conf", user_ui_rc_file)) {
                XMLTree tree;
                found = true;
 
@@ -145,12 +147,15 @@ UIConfiguration::load_state ()
                        error << string_compose(_("user ui configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
                        return -1;
                }
+
+               _dirty = false;
        }
 
        if (!found)
                error << _("could not find any ui configuration file, canvas will look broken.") << endmsg;
 
        pack_canvasvars();
+
        return 0;
 }
 
@@ -181,6 +186,8 @@ UIConfiguration::save_state()
                }
        }
 
+       _dirty = false;
+
        return 0;
 }
 
@@ -244,6 +251,7 @@ UIConfiguration::set_state (const XMLNode& root, int /*version*/)
 
                }
        }
+
        return 0;
 }
 
@@ -270,9 +278,38 @@ void
 UIConfiguration::pack_canvasvars ()
 {
 #undef  CANVAS_VARIABLE
-#define CANVAS_VARIABLE(var,name) canvas_colors.push_back(&var);
+#define CANVAS_VARIABLE(var,name) canvas_colors.insert (std::pair<std::string,UIConfigVariable<uint32_t>* >(name,&var));
 #include "canvas_vars.h"
 #undef  CANVAS_VARIABLE
 }
 
+static bool can_abort = false;
+
+uint32_t
+UIConfiguration::color_by_name (const std::string& name)
+{
+       map<std::string,UIConfigVariable<uint32_t>* >::iterator i = canvas_colors.find (name);
+
+       if (name == "processor fader led") {
+               can_abort = true;
+       }
+
+       if (i != canvas_colors.end()) {
+               return i->second->get();
+       }
+
+       // cerr << string_compose (_("Color %1 not found"), name) << endl;
+       return RGBA_TO_UINT (random()%256,random()%256,random()%256,0xff);
+}
+
+void
+UIConfiguration::set_dirty ()
+{
+       _dirty = true;
+}
 
+bool
+UIConfiguration::dirty () const
+{
+       return _dirty;
+}
index 09e844883161653f5ecd7c942d86256b41a49e51..f96659de76a661a60a2e00744392f3c06fca9494 100644 (file)
@@ -74,7 +74,10 @@ class UIConfiguration : public PBD::Stateful
        UIConfiguration();
        ~UIConfiguration();
 
-       std::vector<UIConfigVariable<uint32_t> *> canvas_colors;
+       std::map<std::string,UIConfigVariable<uint32_t> *> canvas_colors;
+
+       bool dirty () const;
+       void set_dirty ();
 
        int load_state ();
        int save_state ();
@@ -86,6 +89,8 @@ class UIConfiguration : public PBD::Stateful
        void set_variables (const XMLNode&);
        void pack_canvasvars ();
 
+       uint32_t color_by_name (const std::string&);
+
        sigc::signal<void,const char*> ParameterChanged;
 
 #undef  UI_CONFIG_VARIABLE
@@ -99,7 +104,7 @@ class UIConfiguration : public PBD::Stateful
 
   private:
        XMLNode& state ();
-       bool hack;
+       bool _dirty;
 };
 
 #endif /* __ardour_ui_configuration_h__ */
index 60942f512a2c73968774c4f705932f200325ff82..fa53333060df291711a3f717207a756d551e6931 100644 (file)
@@ -29,6 +29,7 @@ gtk2_ardour_sources = [
         'add_route_dialog.cc',
         'ambiguous_file_dialog.cc',
         'analysis_window.cc',
+        'ardour_button.cc',
         'ardour_dialog.cc',
         'ardour_ui.cc',
         'ardour_ui2.cc',