new ArdourButton class, to start to provide more control over how our buttons work and appear; use ArdourButtons for monitor, solo isolate and solo safe buttons, and in the processor box; don't save UI config file (canvas colors) to the user's home dir unless one or more parameters were modified by the user

git-svn-id: svn://localhost/ardour2/branches/3.0@10311 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2011-10-26 21:01:14 +00:00
parent ae3eb6e3f4
commit 51ab5ccabf
25 changed files with 885 additions and 355 deletions

View 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

View 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

View File

@ -142,5 +142,101 @@
<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>

View 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

View 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"

View File

@ -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 ();
}

View File

@ -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__ */

View 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

View 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());

View File

@ -21,10 +21,12 @@
#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 ();
}
}
}

View 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

View 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")

View 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)
{

View 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);

View 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 {

View 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;

View 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
@ -153,13 +135,6 @@ ProcessorEntry::drag_text () const
return name ();
}
void
ProcessorEntry::set_visual_state (Gtk::StateType t)
{
_visual_state = t;
setup_visuals ();
}
void
ProcessorEntry::set_position (Position p)
{
@ -167,47 +142,42 @@ ProcessorEntry::set_position (Position p)
setup_visuals ();
}
void
ProcessorEntry::set_visual_state (Gtk::StateType t)
{
/* 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
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 ());
}
}

View 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;

View 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:

View 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;
}

View 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;

View 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;

View 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;
}

View 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__ */

View 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',