Optional tabs down the LHS of the editor window to indicate edit group membership.
authorCarl Hetherington <carl@carlh.net>
Sat, 20 Jun 2009 13:41:55 +0000 (13:41 +0000)
committerCarl Hetherington <carl@carlh.net>
Sat, 20 Jun 2009 13:41:55 +0000 (13:41 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@5220 d708f5d6-7413-0410-9779-e7cbd77b26cf

18 files changed:
gtk2_ardour/ardour.menus.in
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.cc
gtk2_ardour/editor_edit_groups.cc
gtk2_ardour/editor_route_list.cc
gtk2_ardour/editor_summary.cc
gtk2_ardour/editor_summary.h
gtk2_ardour/port_matrix_column_labels.cc
gtk2_ardour/port_matrix_component.cc
gtk2_ardour/port_matrix_component.h
gtk2_ardour/port_matrix_row_labels.cc
gtk2_ardour/utils.cc
gtk2_ardour/utils.h
gtk2_ardour/wscript
libs/ardour/ardour/session.h
libs/ardour/ardour/session_configuration_vars.h
libs/ardour/session.cc

index e965f0dee63b0560b38cf9ec446e9ba741b97429..b8d34b276ad72489e3054d9b4edcbf7a7bb7da0e 100644 (file)
                <menuitem action='ToggleMeasureVisibility'/>
                <menuitem action='ToggleWaveformsWhileRecording'/>
                <menuitem action='ToggleSummary'/>
+               <menuitem action='ToggleEditGroupTabs'/>
         </menu>
         <menu name='JACK' action='JACK'>
                <menuitem action='JACKDisconnect'/>
index 7f2d502d9509b0a6492652b356e4f6871bff6433..613c91f2b81e86cf345d4786354a013a18a5db15 100644 (file)
@@ -95,6 +95,7 @@
 #include "bundle_manager.h"
 #include "global_port_matrix.h"
 #include "editor_drag.h"
+#include "editor_group_tabs.h"
 
 #include "i18n.h"
 
@@ -452,7 +453,12 @@ Editor::Editor ()
        vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling), true);
        track_canvas->signal_map_event().connect (mem_fun (*this, &Editor::track_canvas_map_handler));
 
-       controls_layout.add (edit_controls_vbox);
+       HBox* h = manage (new HBox);
+       _group_tabs = new EditorGroupTabs (this);
+       h->pack_start (*_group_tabs, PACK_SHRINK);
+       h->pack_start (edit_controls_vbox);
+       controls_layout.add (*h);
+       
        controls_layout.set_name ("EditControlsBase");
        controls_layout.add_events (Gdk::SCROLL_MASK);
        controls_layout.signal_scroll_event().connect (mem_fun(*this, &Editor::control_layout_scroll), false);
@@ -974,6 +980,8 @@ Editor::show_window ()
                /* re-hide summary widget if necessary */
                parameter_changed ("show-summary");
 
+               parameter_changed ("show-edit-group-tabs");
+
                /* now reset all audio_time_axis heights, because widgets might need
                   to be re-hidden
                */
@@ -1428,6 +1436,7 @@ Editor::connect_to_session (Session *t)
        session->register_with_memento_command_factory(_id, this);
 
        _summary->set_session (session);
+       _group_tabs->set_session (session);
        
        start_updating ();
 }
index 81f8eab5aa2c368902e93b2b2a04ef46050507a1..66b65e7470eb2698c53c2994198cdce965568774 100644 (file)
@@ -114,6 +114,7 @@ class TimeAxisView;
 class TimeFXDialog;
 class TimeSelection;
 class TrackSelection;
+class EditorGroupTabs;
 
 /* <CMT Additions> */
 class ImageFrameView;
@@ -344,6 +345,7 @@ class Editor : public PublicEditor
        void toggle_zero_line_visibility ();
        void toggle_waveforms_while_recording ();
        void set_summary ();
+       void set_edit_group_tabs ();
        void toggle_measure_visibility ();
        void toggle_logo_visibility ();
 
@@ -2239,6 +2241,8 @@ public:
        void update_canvas_now ();
        void streamview_height_changed ();
 
+       EditorGroupTabs* _group_tabs;
+
        friend class Drag;
        friend class RegionDrag;
        friend class RegionMoveDrag;
@@ -2264,6 +2268,7 @@ public:
        friend class RegionInsertDrag;
 
        friend class EditorSummary;
+       friend class EditorGroupTabs;
 };
 
 #endif /* __ardour_editor_h__ */
index f3a3fac2e3b161fe48eb53f6fd58df000a0f3243..99e241862be794f7a55095ef6d3d033436f38754 100644 (file)
@@ -29,6 +29,7 @@
 #include "utils.h"
 #include "i18n.h"
 #include "audio_time_axis.h"
+#include "editor_group_tabs.h"
 
 using namespace Gtk;
 using namespace Glib;
@@ -808,6 +809,8 @@ Editor::register_actions ()
        ActionManager::register_toggle_action (editor_actions, X_("ToggleWaveformsWhileRecording"), _("Show Waveforms While Recording"), mem_fun (*this, &Editor::toggle_waveforms_while_recording));
 
        ActionManager::register_toggle_action (editor_actions, X_("ToggleSummary"), _("Show Summary"), mem_fun (*this, &Editor::set_summary));
+
+       ActionManager::register_toggle_action (editor_actions, X_("ToggleEditGroupTabs"), _("Show Edit Group Tabs"), mem_fun (*this, &Editor::set_edit_group_tabs));
        
        ActionManager::register_toggle_action (editor_actions, X_("ToggleMeasureVisibility"), _("Show Measures"), mem_fun (*this, &Editor::toggle_measure_visibility));
        
@@ -895,6 +898,16 @@ Editor::set_summary ()
        }
 }
 
+void
+Editor::set_edit_group_tabs ()
+{
+       Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleEditGroupTabs"));
+       if (act) {
+               Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
+               session->config.set_show_edit_group_tabs (tact->get_active ());
+       }
+}
+
 void
 Editor::toggle_measure_visibility ()
 {
@@ -1289,6 +1302,22 @@ Editor::parameter_changed (std::string p)
                                tact->set_active (s);
                        }
                }
+       } else if (p == "show-edit-group-tabs") {
+
+               bool const s = session->config.get_show_edit_group_tabs ();
+               if (s) {
+                       _group_tabs->show ();
+               } else {
+                       _group_tabs->hide ();
+               }
+
+               Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleEditGroupTabs"));
+               if (act) {
+                       Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
+                       if (tact->get_active () != s) {
+                               tact->set_active (s);
+                       }
+               }
        }
 }
 
index a0e7372ded3b91d889490b93bd9f19e2bf0e3bf9..9dbdbfad38b9d2653d75730fbaaa4359ef908d94 100644 (file)
@@ -30,6 +30,7 @@
 #include "time_axis_view.h"
 #include "prompter.h"
 #include "gui_thread.h"
+#include "editor_group_tabs.h"
 
 #include "ardour/route.h"
 
@@ -248,6 +249,8 @@ Editor::add_edit_group (RouteGroup* group)
        }
 
        in_edit_group_row_change = false;
+
+       _group_tabs->set_dirty ();
 }
 
 void
@@ -288,6 +291,8 @@ Editor::group_flags_changed (void* src, RouteGroup* group)
        }
 
        in_edit_group_row_change = false;
+
+       _group_tabs->set_dirty ();
 }
 
 void
index 56cc3f5cf1d7d9da6c7bffdb79b477c58b2d4e56..1cce9fb517445fc86b917dca9d56c989db80c84e 100644 (file)
@@ -33,6 +33,7 @@
 #include "gui_thread.h"
 #include "actions.h"
 #include "utils.h"
+#include "editor_group_tabs.h"
 
 #include "pbd/unknown_type.h"
 
@@ -424,6 +425,7 @@ Editor::sync_track_view_list_and_route_list ()
        }
 
        _summary->set_dirty ();
+       _group_tabs->set_dirty ();
 
        return false; // do not call again (until needed)
 }
index a56a97e0dd5cdeaa34495c4c83ecbd8876247e47..b7ae937a405725d16e502c58ca26d0b1b8b990b7 100644 (file)
@@ -37,10 +37,6 @@ using namespace ARDOUR;
 EditorSummary::EditorSummary (Editor* e)
        : _editor (e),
          _session (0),
-         _pixmap (0),
-         _regions_dirty (true),
-         _width (512),
-         _height (32),
          _x_scale (1),
          _y_scale (1),
          _last_playhead (-1),
@@ -70,47 +66,13 @@ EditorSummary::set_session (Session* s)
        set_dirty ();
 }
 
-/** Destroy */
-EditorSummary::~EditorSummary ()
-{
-       if (_pixmap) {
-               gdk_pixmap_unref (_pixmap);
-       }
-}
-
 /** Handle an expose event.
  *  @param event Event from GTK.
  */
 bool
 EditorSummary::on_expose_event (GdkEventExpose* event)
 {
-       /* Render the regions pixmap */
-       
-       Gdk::Rectangle const exposure (
-               event->area.x, event->area.y, event->area.width, event->area.height
-               );
-
-       Gdk::Rectangle r = exposure;
-       Gdk::Rectangle content (0, 0, _width, _height);
-       bool intersects;
-       r.intersect (content, intersects);
-       
-       if (intersects) {
-
-               GdkPixmap* p = get_pixmap (get_window()->gobj ());
-
-               gdk_draw_drawable (
-                       get_window()->gobj(),
-                       get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(),
-                       p,
-                       r.get_x(),
-                       r.get_y(),
-                       r.get_x(),
-                       r.get_y(),
-                       r.get_width(),
-                       r.get_height()
-                       );
-       }
+       CairoWidget::on_expose_event (event);
 
        cairo_t* cr = gdk_cairo_create (get_window()->gobj());
 
@@ -148,29 +110,6 @@ EditorSummary::on_expose_event (GdkEventExpose* event)
        return true;
 }
 
-/** @param drawable GDK drawable.
- *  @return pixmap for the regions.
- */
-GdkPixmap *
-EditorSummary::get_pixmap (GdkDrawable* drawable)
-{
-       if (_regions_dirty) {
-
-               if (_pixmap) {
-                       gdk_pixmap_unref (_pixmap);
-               }
-               _pixmap = gdk_pixmap_new (drawable, _width, _height, -1);
-
-               cairo_t* cr = gdk_cairo_create (_pixmap);
-               render (cr);
-               cairo_destroy (cr);
-
-               _regions_dirty = false;
-       }
-
-       return _pixmap;
-}
-
 /** Render the required regions to a cairo context.
  *  @param cr Context.
  */
@@ -206,6 +145,7 @@ EditorSummary::render (cairo_t* cr)
 
        if (max_height * _y_scale > tallest_region_pixels) {
                _y_scale = static_cast<double> (tallest_region_pixels) / max_height;
+
        }
 
        /* render regions */
@@ -247,16 +187,6 @@ EditorSummary::render_region (RegionView* r, cairo_t* cr, nframes_t start, doubl
        cairo_stroke (cr);
 }
 
-/** Set the summary so that the whole thing will be re-rendered next time it is required */
-void
-EditorSummary::set_dirty ()
-{
-       ENSURE_GUI_THREAD (mem_fun (*this, &EditorSummary::set_dirty));
-
-       _regions_dirty = true;
-       queue_draw ();
-}
-
 /** Set the summary so that just the overlays (viewbox, playhead etc.) will be re-rendered */
 void
 EditorSummary::set_overlays_dirty ()
@@ -273,22 +203,9 @@ EditorSummary::on_size_request (Gtk::Requisition *req)
 {
        /* Use a dummy, small width and the actual height that we want */
        req->width = 64;
-       req->height = _height;
+       req->height = 32;
 }
 
-/** Handle a size allocation.
- *  @param alloc GTK allocation.
- */
-void
-EditorSummary::on_size_allocate (Gtk::Allocation& alloc)
-{
-       Gtk::EventBox::on_size_allocate (alloc);
-
-       _width = alloc.get_width ();
-       _height = alloc.get_height ();
-
-       set_dirty ();
-}
 
 void
 EditorSummary::centre_on_click (GdkEventButton* ev)
index 1da6a3985fed96c13178a447059e71eccfc5a80b..1d68e3b7936e6d1d68f4a81df7e2aceb30d67ff0 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __gtk_ardour_editor_summary_h__
 #define __gtk_ardour_editor_summary_h__
 
-#include <gtkmm/eventbox.h>
+#include "cairo_widget.h"
 
 namespace ARDOUR {
        class Session;
@@ -31,28 +31,24 @@ class Editor;
 /** Class to provide a visual summary of the contents of an editor window; represents
  *  the whole session as a set of lines, one per region view.
  */
-class EditorSummary : public Gtk::EventBox
+class EditorSummary : public CairoWidget
 {
 public:
        EditorSummary (Editor *);
-       ~EditorSummary ();
 
        void set_session (ARDOUR::Session *);
-       void set_dirty ();
        void set_overlays_dirty ();
 
 private:
-       void centre_on_click (GdkEventButton *);
        bool on_expose_event (GdkEventExpose *);
        void on_size_request (Gtk::Requisition *);
-       void on_size_allocate (Gtk::Allocation &);
        bool on_button_press_event (GdkEventButton *);
        bool on_button_release_event (GdkEventButton *);
        bool on_motion_notify_event (GdkEventMotion *);
        bool on_scroll_event (GdkEventScroll *);
 
+       void centre_on_click (GdkEventButton *);
        void render (cairo_t *);
-       GdkPixmap* get_pixmap (GdkDrawable *);
        void render_region (RegionView*, cairo_t*, nframes_t, double) const;
        void get_editor (std::pair<double, double> *, std::pair<double, double> *) const;
        void set_editor (std::pair<double, double> const &, std::pair<double, double> const &);
@@ -60,10 +56,6 @@ private:
 
        Editor* _editor; ///< our editor
        ARDOUR::Session* _session; ///< our session
-       GdkPixmap* _pixmap; ///< pixmap containing a rendering of the region views, or 0
-       bool _regions_dirty; ///< true if _pixmap requires re-rendering, otherwise false
-       int _width; ///< pixmap width
-       int _height; ///< pixmap height
        double _x_scale; ///< pixels per frame for the x axis of the pixmap
        double _y_scale;
        double _last_playhead;
index 5c1749c4bca1e469d412c931a0f8648e97cde516..a1ec3920887bf35923eef7b01c7b5eaa8a766203 100644 (file)
@@ -23,6 +23,7 @@
 #include "port_matrix_column_labels.h"
 #include "port_matrix.h"
 #include "port_matrix_body.h"
+#include "utils.h"
 
 PortMatrixColumnLabels::PortMatrixColumnLabels (PortMatrix* m, PortMatrixBody* b)
        : PortMatrixLabels (m, b)
@@ -162,8 +163,9 @@ PortMatrixColumnLabels::render (cairo_t* cr)
                        cairo_rectangle (cr, x, _height - rh, w, rh);
                }
                cairo_fill (cr);
-               
-               std::pair<std::string, double> const display = display_port_name (cr, (*i)->name, w);
+
+               std::string const upper = Glib::ustring ((*i)->name).uppercase ();
+               std::pair<std::string, double> const display = fit_to_pixels (cr, upper, w);
 
                /* plot it */
                set_source_rgb (cr, text_colour());
index a68e21730df92fec43bdb3db39e304edf47727b7..3086e11e907031be9bc3b001c8e091b5788f8dc7 100644 (file)
@@ -110,34 +110,3 @@ PortMatrixComponent::dimensions ()
        return std::make_pair (_width, _height);
 }
 
-std::pair<std::string, double>
-PortMatrixComponent::display_port_name (cairo_t* cr, std::string const &n, double avail) const
-{
-       /* XXX hopefully there exists a more efficient way of doing this */
-       
-       Glib::ustring name = Glib::ustring (n).uppercase ();
-       bool abbreviated = false;
-       uint32_t width = 0;
-               
-       while (1) {
-               if (name.length() <= 2) {
-                       break;
-               }
-                       
-               cairo_text_extents_t ext;
-               cairo_text_extents (cr, name.c_str(), &ext);
-               if (ext.width < avail) {
-                       width = ext.width;
-                       break;
-               }
-                       
-               if (abbreviated) {
-                       name = name.substr (0, name.length() - 2) + ".";
-               } else {
-                       name = name.substr (0, name.length() - 1) + ".";
-                       abbreviated = true;
-               }
-       }
-
-       return std::make_pair (name, width);
-}
index 3980731e553d579a5270b8f60d7335bab9370c84..fcb3c8da8eabaf3ee53dd0a284d489f062f319e9 100644 (file)
@@ -168,7 +168,6 @@ protected:
        
        void set_source_rgb (cairo_t *, Gdk::Color const &);
        void set_source_rgba (cairo_t *, Gdk::Color const &, double);
-       std::pair<std::string, double> display_port_name (cairo_t*, std::string const &, double) const;
 
        /** Render the complete component to a cairo context. */
        virtual void render (cairo_t *) = 0;
index 8334b7b44f965a7eddb9250a43adbb1ade3a4de7..799fb8c14f05ba5ffdce5a103328b9b898960cfe 100644 (file)
@@ -25,6 +25,7 @@
 #include "port_matrix.h"
 #include "port_matrix_body.h"
 #include "i18n.h"
+#include "utils.h"
 
 PortMatrixRowLabels::PortMatrixRowLabels (PortMatrix* m, PortMatrixBody* b)
        : PortMatrixLabels (m, b)
@@ -131,7 +132,8 @@ PortMatrixRowLabels::render (cairo_t* cr)
                cairo_fill (cr);
                    
                /* hence what abbreviation (or not) we need for the group name */
-               std::pair<std::string, double> display = display_port_name (cr, (*i)->name, h);
+               std::string const upper = Glib::ustring ((*i)->name).uppercase ();
+               std::pair<std::string, double> display = fit_to_pixels (cr, upper, h);
 
                /* plot it */
                set_source_rgb (cr, text_colour());
index f5490c025a47ee7d48169a50ca8aba8467d6618f..dc410136d7f2d78a67d5f9cf35f3aa46e1ffe69d 100644 (file)
@@ -113,11 +113,43 @@ fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font
        return txt;
 }
 
+std::pair<std::string, double>
+fit_to_pixels (cairo_t* cr, std::string name, double avail)
+{
+       /* XXX hopefully there exists a more efficient way of doing this */
+
+       bool abbreviated = false;
+       uint32_t width = 0;
+               
+       while (1) {
+               if (name.length() <= 4) {
+                       break;
+               }
+                       
+               cairo_text_extents_t ext;
+               cairo_text_extents (cr, name.c_str(), &ext);
+               if (ext.width < avail) {
+                       width = ext.width;
+                       break;
+               }
+                       
+               if (abbreviated) {
+                       name = name.substr (0, name.length() - 4) + "...";
+               } else {
+                       name = name.substr (0, name.length() - 3) + "...";
+                       abbreviated = true;
+               }
+       }
+
+       return std::make_pair (name, width);
+}
+
+
 gint
 just_hide_it (GdkEventAny *ev, Gtk::Window *win)
 {
        win->hide ();
-       return TRUE;
+       return 0;
 }
 
 /* xpm2rgb copied from nixieclock, which bore the legend:
index eb74864a78ec3e7964f4db0d95386e6b1f1751ea..cf563560a4c146241b81daaf9ae054cbde79dd9c 100644 (file)
@@ -53,6 +53,9 @@ slider_position_to_gain (double pos)
 }
 
 Glib::ustring fit_to_pixels (const Glib::ustring&, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses = false);
+
+std::pair<std::string, double> fit_to_pixels (cairo_t *, std::string, double);
+
 int pixel_width (const Glib::ustring& str, Pango::FontDescription& font);
 
 gint   just_hide_it (GdkEventAny*, Gtk::Window*);
index a61b3733d29422669a2a9dba17e3c3bf24c7e76a..da2f2edadd60da3f2406e40e6b3af8bd944ac48a 100644 (file)
@@ -81,6 +81,7 @@ def build(bld):
                automation_time_axis.cc
                axis_view.cc
                bundle_manager.cc
+               cairo_widget.cc
                canvas-flag.cc
                canvas-note-event.cc
                canvas-note.cc
@@ -106,6 +107,7 @@ def build(bld):
                editor_drag.cc
                editor_edit_groups.cc
                editor_export_audio.cc
+               editor_group_tabs.cc
                editor_hscroller.cc
                editor_keyboard.cc
                editor_keys.cc
index b2486982420684db803914d60a0f910d7e16e313..5b6b55b01c0056cac14666dbed5adcafdb92c928 100644 (file)
@@ -377,6 +377,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
        sigc::signal<void> Located;
 
        sigc::signal<void,RouteList&> RouteAdded;
+       sigc::signal<void> RouteEditGroupChanged;
 
        void request_roll_at_and_return (nframes_t start, nframes_t return_to);
        void request_bounded_roll (nframes_t start, nframes_t end);
@@ -1485,6 +1486,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
 
        int load_regions (const XMLNode& node);
 
+       void route_edit_group_changed ();
+
        /* SOURCES */
 
        mutable Glib::Mutex source_lock;
index e3bb7283cbc35941f035c7aebeba3984a8fe1a0a..b7bdcf6aa77f26aeac419d0adb099aefe181060e 100644 (file)
@@ -46,3 +46,4 @@ CONFIG_VARIABLE (bool, jack_time_master, "jack-time-master", true)
 CONFIG_VARIABLE (bool, use_video_sync, "use-video-sync", false)
 CONFIG_VARIABLE (float, video_pullup, "video-pullup", 0.0f)
 CONFIG_VARIABLE (bool, show_summary, "show-summary", true)
+CONFIG_VARIABLE (bool, show_edit_group_tabs, "show-edit-group-tabs", true)
index 23c6ce89c1c577cd7f3344af366ef36dd0e7a3f0..a4cee0abea8becfb2edad142d84f406f68632bc1 100644 (file)
@@ -2078,6 +2078,7 @@ Session::add_routes (RouteList& new_routes, bool save)
                (*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
                (*x)->output()->changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
                (*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false));
+               (*x)->edit_group_changed.connect (hide (mem_fun (*this, &Session::route_edit_group_changed)));
 
                if ((*x)->is_master()) {
                        _master_out = (*x);
@@ -4243,3 +4244,9 @@ Session::solo_model_changed ()
                (*i)->put_control_outs_at (p);
        }
 }
+
+void
+Session::route_edit_group_changed ()
+{
+       RouteEditGroupChanged (); /* EMIT SIGNAL */
+}