use button joiner for smart mode; polish up the visuals on the joiner a bit

git-svn-id: svn://localhost/ardour2/branches/3.0@11439 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2012-02-03 18:31:10 +00:00
parent ac268b1224
commit c21c9e6662
6 changed files with 131 additions and 53 deletions

View File

@ -4,6 +4,7 @@
#include <gtkmm/toggleaction.h>
#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/rgb_macros.h"
#include "ardour_ui.h"
#include "button_joiner.h"
@ -13,6 +14,8 @@ using namespace Gtk;
ButtonJoiner::ButtonJoiner (Gtk::Widget& l, Gtk::Widget& r)
: left (l)
, right (r)
, active_fill_pattern (0)
, inactive_fill_pattern (0)
{
packer.set_homogeneous (true);
packer.pack_start (l);
@ -21,34 +24,65 @@ ButtonJoiner::ButtonJoiner (Gtk::Widget& l, Gtk::Widget& r)
align.add (packer);
align.set (0.5, 1.0);
align.set_padding (7, 0, 5, 5);
align.set_padding (9, 0, 9, 9);
align.show ();
add (align);
add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|
Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
/* child cairo widgets need the color of the inner edge as their
* "background"
*/
Gdk::Color col;
col.set_rgb_p (0.172, 0.192, 0.364);
provide_background_for_cairo_widget (*this, col);
}
ButtonJoiner::~ButtonJoiner ()
{
if (active_fill_pattern) {
cairo_pattern_destroy (active_fill_pattern);
cairo_pattern_destroy (inactive_fill_pattern);
}
}
void
ButtonJoiner::render (cairo_t* cr)
{
double h = get_height();
double r, g, b;
if (_active_state == Gtkmm2ext::ActiveState (0)) {
r = 0.0;
g = 0.0;
b = 0.0;
cairo_set_source (cr, inactive_fill_pattern);
} else {
r = 0.16;
g = 0.58;
b = 0.757;
cairo_set_source (cr, active_fill_pattern);
}
Gtkmm2ext::rounded_top_rectangle (cr, 0, 0, get_width(), h, 9);
cairo_set_source_rgb (cr, r, g, b);
cairo_fill (cr);
/* outer rect */
Gtkmm2ext::rounded_top_rectangle (cr, 0, 0, get_width(), h, 12);
cairo_fill_preserve (cr);
/* outer edge */
cairo_set_line_width (cr, 1);
cairo_set_source_rgb (cr, 0.172, 0.192, 0.364);
cairo_stroke (cr);
/* inner "edge" */
Gtkmm2ext::rounded_top_rectangle (cr, 8, 8, get_width() - 16, h - 8, 9);
cairo_stroke (cr);
}
void
ButtonJoiner::on_size_allocate (Allocation& alloc)
{
CairoWidget::on_size_allocate (alloc);
set_colors ();
}
bool
@ -143,20 +177,32 @@ ButtonJoiner::set_active_state (Gtkmm2ext::ActiveState s)
void
ButtonJoiner::set_colors ()
{
double r, g, b;
uint32_t start_color;
uint32_t end_color;
uint32_t r, g, b, a;
if (_active_state == Gtkmm2ext::ActiveState (0)) {
r = 0.0;
g = 0.0;
b = 0.0;
} else {
r = 0.16;
g = 0.58;
b = 0.757;
if (active_fill_pattern) {
cairo_pattern_destroy (active_fill_pattern);
cairo_pattern_destroy (inactive_fill_pattern);
}
Gdk::Color col;
col.set_rgb_p (r, g, b);
provide_background_for_cairo_widget (*this, col);
active_fill_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
inactive_fill_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
start_color = ARDOUR_UI::config()->color_by_name ("transport button: fill start");
end_color = ARDOUR_UI::config()->color_by_name ("transport button: fill end");
UINT_TO_RGBA (start_color, &r, &g, &b, &a);
cairo_pattern_add_color_stop_rgba (inactive_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 (inactive_fill_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0);
start_color = ARDOUR_UI::config()->color_by_name ("transport button: fill start active");
end_color = ARDOUR_UI::config()->color_by_name ("transport button: fill end active");
UINT_TO_RGBA (start_color, &r, &g, &b, &a);
cairo_pattern_add_color_stop_rgba (active_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 (active_fill_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0);
queue_draw ();
}

View File

@ -11,6 +11,8 @@
class ButtonJoiner : public CairoWidget, public Gtkmm2ext::Activatable {
public:
ButtonJoiner (Gtk::Widget&, Gtk::Widget&);
~ButtonJoiner ();
void set_related_action (Glib::RefPtr<Gtk::Action>);
void set_active_state (Gtkmm2ext::ActiveState);
@ -18,6 +20,7 @@ class ButtonJoiner : public CairoWidget, public Gtkmm2ext::Activatable {
void render (cairo_t*);
bool on_button_release_event (GdkEventButton*);
void on_size_request (Gtk::Requisition*);
void on_size_allocate (Gtk::Allocation&);
void action_sensitivity_changed ();
void action_visibility_changed ();
@ -30,6 +33,9 @@ class ButtonJoiner : public CairoWidget, public Gtkmm2ext::Activatable {
Gtk::HBox packer;
Gtk::Alignment align;
cairo_pattern_t* active_fill_pattern;
cairo_pattern_t* inactive_fill_pattern;
void set_colors ();
};

View File

@ -2445,7 +2445,7 @@ Editor::get_state ()
node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
node->add_property ("mouse-mode", enum2str(mouse_mode));
node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
node->add_property ("join-object-range", join_object_range_button.get_active () ? "yes" : "no");
node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
if (act) {
@ -2766,29 +2766,54 @@ Editor::setup_toolbar ()
mode_box->set_border_width (2);
mode_box->set_spacing(4);
/* table containing mode buttons */
HBox* mouse_mode_box = manage (new HBox);
HBox* mouse_mode_hbox1 = manage (new HBox);
HBox* mouse_mode_hbox2 = manage (new HBox);
VBox* mouse_mode_vbox1 = manage (new VBox);
VBox* mouse_mode_vbox2 = manage (new VBox);
Alignment* mouse_mode_align1 = manage (new Alignment);
Alignment* mouse_mode_align2 = manage (new Alignment);
HBox* mouse_mode_button_box = manage (new HBox ());
mouse_mode_button_box->set_spacing (2);
Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
mouse_mode_size_group->add_widget (mouse_move_button);
mouse_mode_size_group->add_widget (mouse_select_button);
mouse_mode_size_group->add_widget (mouse_zoom_button);
mouse_mode_size_group->add_widget (mouse_gain_button);
mouse_mode_size_group->add_widget (mouse_timefx_button);
mouse_mode_size_group->add_widget (mouse_audition_button);
mouse_mode_size_group->add_widget (mouse_draw_button);
mouse_mode_size_group->add_widget (internal_edit_button);
if (Profile->get_sae()) {
mouse_mode_button_box->pack_start (mouse_move_button);
} else {
mouse_mode_button_box->pack_start (mouse_move_button);
mouse_mode_button_box->pack_start (join_object_range_button);
mouse_mode_button_box->pack_start (mouse_select_button);
}
/* make them just a bit bigger */
mouse_move_button.set_size_request (-1, 25);
mouse_mode_button_box->pack_start (mouse_zoom_button);
smart_mode_joiner = manage (new ButtonJoiner (mouse_move_button, mouse_select_button));
smart_mode_joiner->set_related_action (smart_mode_action);
if (!Profile->get_sae()) {
mouse_mode_button_box->pack_start (mouse_gain_button);
}
mouse_move_button.set_rounded_corner_mask (0x1); // upper left only
mouse_select_button.set_rounded_corner_mask (0x2); // upper right only
mouse_mode_button_box->pack_start (mouse_timefx_button);
mouse_mode_button_box->pack_start (mouse_audition_button);
mouse_mode_button_box->pack_start (mouse_draw_button);
mouse_mode_button_box->pack_start (internal_edit_button);
mouse_mode_hbox2->set_spacing (2);
mouse_mode_box->set_spacing (2);
mouse_mode_hbox1->pack_start (*smart_mode_joiner, false, false);
mouse_mode_hbox2->pack_start (mouse_zoom_button, false, false);
mouse_mode_hbox2->pack_start (mouse_gain_button, false, false);
mouse_mode_hbox2->pack_start (mouse_timefx_button, false, false);
mouse_mode_hbox2->pack_start (mouse_audition_button, false, false);
mouse_mode_hbox2->pack_start (mouse_draw_button, false, false);
mouse_mode_hbox2->pack_start (internal_edit_button, false, false);
mouse_mode_vbox1->pack_start (*mouse_mode_hbox1, false, false);
mouse_mode_vbox2->pack_start (*mouse_mode_hbox2, false, false);
mouse_mode_align1->add (*mouse_mode_vbox1);
mouse_mode_align1->set (0.5, 1.0, 0.0, 0.0);
mouse_mode_align2->add (*mouse_mode_vbox2);
mouse_mode_align2->set (0.5, 1.0, 0.0, 0.0);
mouse_mode_box->pack_start (*mouse_mode_align1, false, false);
mouse_mode_box->pack_start (*mouse_mode_align2, false, false);
edit_mode_strings.push_back (edit_mode_to_string (Slide));
if (!Profile->get_sae()) {
@ -2801,7 +2826,7 @@ Editor::setup_toolbar ()
edit_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_mode_selection_done));
mode_box->pack_start (edit_mode_selector, false, false);
mode_box->pack_start (*mouse_mode_button_box, false, false);
mode_box->pack_start (*mouse_mode_box, false, false);
_mouse_mode_tearoff = manage (new TearOff (*mode_box));
_mouse_mode_tearoff->set_name ("MouseModeBase");
@ -2976,7 +3001,7 @@ Editor::setup_tooltips ()
ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
ARDOUR_UI::instance()->set_tip (join_object_range_button, _("Select/Move Objects or Ranges"));
ARDOUR_UI::instance()->set_tip (smart_mode_joiner, _("Smart Mode (Select/Move Objects + Ranges)"));
ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Edit Region Contents (e.g. notes)"));
ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Forwards"));

View File

@ -104,6 +104,7 @@ class AutomationLine;
class AutomationSelection;
class AutomationTimeAxisView;
class BundleManager;
class ButtonJoiner;
class ControlPoint;
class CrossfadeView;
class DragManager;
@ -1554,7 +1555,9 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
ArdourButton mouse_zoom_button;
ArdourButton mouse_timefx_button;
ArdourButton mouse_audition_button;
ArdourButton join_object_range_button;
ButtonJoiner* smart_mode_joiner;
Glib::RefPtr<Gtk::ToggleAction> smart_mode_action;
void mouse_mode_toggled (Editing::MouseMode m);
void mouse_mode_object_range_toggled () {}

View File

@ -421,9 +421,7 @@ Editor::register_actions ()
mouse_draw_button.set_name ("mouse mode button");
act = ActionManager::register_toggle_action (mouse_mode_actions, "set-mouse-mode-object-range", _("Link Object / Range Tools"), sigc::mem_fun (*this, &Editor::mouse_mode_object_range_toggled));
join_object_range_button.set_related_action (act);
join_object_range_button.set_image (::get_icon ("tool_object_range"));
join_object_range_button.set_name ("mouse mode button");
smart_mode_action = Glib::RefPtr<ToggleAction>::cast_static (act);
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-gain", _("Gain Tool"), sigc::bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
mouse_gain_button.set_related_action (act);

View File

@ -307,7 +307,7 @@ Editor::set_canvas_cursor ()
}
/* up-down cursor as a cue that automation can be dragged up and down when in join object/range mode */
if (join_object_range_button.get_active()) {
if (smart_mode_action->get_active()) {
double x, y;
get_pointer_position (x, y);
ArdourCanvas::Item* i = track_canvas->get_item_at (x, y);
@ -807,7 +807,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
if (tvp.first) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
if (join_object_range_button.get_active() && atv) {
if (smart_mode_action->get_active() && atv) {
/* smart "join" mode: drag automation */
_drags->set (new AutomationRangeDrag (this, atv->base_item(), selection->time), event, _cursors->up_down);
} else {
@ -1010,7 +1010,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case SelectionItem:
{
if (join_object_range_button.get_active()) {
if (smart_mode_action->get_active()) {
/* we're in "smart" joined mode, and we've clicked on a Selection */
double const y = event->button.y + vertical_adjustment.get_value() - canvas_timebars_vsize;
pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
@ -1923,7 +1923,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
}
break;
case SelectionItem:
if (join_object_range_button.get_active()) {
if (smart_mode_action->get_active()) {
set_canvas_cursor ();
}
break;
@ -2735,7 +2735,7 @@ Editor::update_join_object_range_location (double /*x*/, double y)
that we're over requires searching the playlist.
*/
if (join_object_range_button.get_active() == false || (mouse_mode != MouseRange && mouse_mode != MouseObject)) {
if (!smart_mode_action->get_active() || (mouse_mode != MouseRange && mouse_mode != MouseObject)) {
_join_object_range_state = JOIN_OBJECT_RANGE_NONE;
return;
}