Preferences/Config changes for image-surface settings
[ardour.git] / gtk2_ardour / time_axis_view.cc
index 5bd26b193a987f56dfad6281dd636e8d6b91537b..6ae0c3c5b8a5020f1f69e8a3d4e612f4fe85a494 100644 (file)
@@ -1,21 +1,28 @@
 /*
-    Copyright (C) 2000 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.
-
-*/
+ * Copyright (C) 2005-2007 Doug McLain <doug@nostar.net>
+ * Copyright (C) 2005-2008 Nick Mainsbridge <mainsbridge@gmail.com>
+ * Copyright (C) 2005-2019 Paul Davis <paul@linuxaudiosystems.com>
+ * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
+ * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
+ * Copyright (C) 2006-2016 Tim Mayberry <mojofunk@gmail.com>
+ * Copyright (C) 2008-2012 Carl Hetherington <carl@carlh.net>
+ * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
+ * Copyright (C) 2014-2015 Ben Loftis <ben@harrisonconsoles.com>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
 
 #include <cstdlib>
 #include <cmath>
 #include <string>
 #include <list>
 
+#include <boost/smart_ptr/scoped_ptr.hpp>
+
+#include <gtkmm/separator.h>
 
 #include "pbd/error.h"
 #include "pbd/convert.h"
 #include "pbd/stacktrace.h"
 #include "pbd/unwind.h"
 
-#include <gtkmm2ext/doi.h>
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/selector.h>
+#include "ardour/profile.h"
+
+#include "gtkmm2ext/colors.h"
+#include "gtkmm2ext/doi.h"
+#include "gtkmm2ext/utils.h"
 
 #include "canvas/canvas.h"
 #include "canvas/rectangle.h"
 #include "canvas/debug.h"
 #include "canvas/utils.h"
-#include "canvas/colors.h"
 
-#include "ardour/profile.h"
+#include "widgets/tooltips.h"
 
 #include "ardour_dialog.h"
+#include "audio_time_axis.h"
 #include "floating_text_entry.h"
 #include "gui_thread.h"
 #include "public_editor.h"
@@ -55,7 +67,6 @@
 #include "streamview.h"
 #include "editor_drag.h"
 #include "editor.h"
-#include "tooltips.h"
 #include "ui_config.h"
 
 #include "pbd/i18n.h"
@@ -64,10 +75,10 @@ using namespace std;
 using namespace Gtk;
 using namespace Gdk;
 using namespace ARDOUR;
-using namespace ARDOUR_UI_UTILS;
 using namespace PBD;
 using namespace Editing;
 using namespace ArdourCanvas;
+using namespace ArdourWidgets;
 using Gtkmm2ext::Keyboard;
 
 #define TOP_LEVEL_WIDGET controls_ebox
@@ -128,7 +139,7 @@ TimeAxisView::TimeAxisView (ARDOUR::Session* sess, PublicEditor& ed, TimeAxisVie
        _canvas_separator = new ArdourCanvas::Line(_canvas_display);
        CANVAS_DEBUG_NAME (_canvas_separator, "separator for TAV");
        _canvas_separator->set (ArdourCanvas::Duple(0.0, 0.0), ArdourCanvas::Duple(ArdourCanvas::COORD_MAX, 0.0));
-       _canvas_separator->set_outline_color(ArdourCanvas::rgba_to_color (0, 0, 0, 1.0));
+       _canvas_separator->set_outline_color(Gtkmm2ext::rgba_to_color (0, 0, 0, 1.0));
        _canvas_separator->set_outline_width(1.0);
        _canvas_separator->hide();
 
@@ -148,10 +159,9 @@ TimeAxisView::TimeAxisView (ARDOUR::Session* sess, PublicEditor& ed, TimeAxisVie
        set_tooltip (name_label, _("Track/Bus name (double click to edit)"));
 
        {
-               std::auto_ptr<Gtk::Entry> an_entry (new Gtkmm2ext::FocusEntry);
+               boost::scoped_ptr<Gtk::Entry> an_entry (new FocusEntry);
                an_entry->set_name (X_("TrackNameEditor"));
-               Gtk::Requisition req;
-               an_entry->size_request (req);
+               Gtk::Requisition req = an_entry->size_request ();
 
                name_label.set_size_request (-1, req.height);
                name_label.set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
@@ -219,12 +229,11 @@ TimeAxisView::TimeAxisView (ARDOUR::Session* sess, PublicEditor& ed, TimeAxisVie
        top_hbox.pack_start (scroomer_placeholder, false, false); // OR pack_end to move after meters ?
 
        UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &TimeAxisView::color_handler));
+       UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &TimeAxisView::parameter_changed));
 }
 
 TimeAxisView::~TimeAxisView()
 {
-       CatchDeletion (this);
-
        in_destructor = true;
 
        for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
@@ -578,7 +587,9 @@ TimeAxisView::set_height (uint32_t h, TrackHeightMode m)
        uint32_t lanes = 0;
        if (m == TotalHeight) {
                for (Children::iterator i = children.begin(); i != children.end(); ++i) {
-                       if ( !(*i)->hidden()) ++lanes;
+                       if (!(*i)->hidden()) {
+                               ++lanes;
+                       }
                }
        }
        h /= (lanes + 1);
@@ -618,7 +629,7 @@ TimeAxisView::begin_name_edit ()
        }
 
        Gtk::Window* toplevel = (Gtk::Window*) control_parent->get_toplevel();
-       FloatingTextEntry* fte = new FloatingTextEntry (toplevel, name_label.get_text ());
+       FloatingTextEntry* fte = new FloatingTextEntry (toplevel, name ());
 
        fte->set_name ("TrackNameEditor");
        fte->use_text.connect (sigc::mem_fun (*this, &TimeAxisView::end_name_edit));
@@ -629,12 +640,12 @@ TimeAxisView::begin_name_edit ()
         */
 
        int x, y;
-        int wx, wy;
+       int wx, wy;
 
-        name_label.translate_coordinates (*toplevel, 0, 0, x, y);
-        toplevel->get_window()->get_origin (wx, wy);
+       name_label.translate_coordinates (*toplevel, 0, 0, x, y);
+       toplevel->get_window()->get_origin (wx, wy);
 
-        fte->move (wx + x, wy + y);
+       fte->move (wx + x, wy + y);
        fte->present ();
 }
 
@@ -659,7 +670,7 @@ TimeAxisView::end_name_edit (std::string str, int next_dir)
 
                                RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*>(*i);
 
-                               if (rtav && (!rtav->is_track() || rtav->track()->rec_enable_control()->get_value())) {
+                               if (rtav && rtav->is_track() && rtav->track()->rec_enable_control()->get_value()) {
                                        continue;
                                }
 
@@ -690,7 +701,7 @@ TimeAxisView::end_name_edit (std::string str, int next_dir)
 
                                RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*>(*i);
 
-                               if (rtav && (!rtav->is_track() || rtav->track()->rec_enable_control()->get_value())) {
+                               if (rtav && rtav->is_track() && rtav->track()->rec_enable_control()->get_value()) {
                                        continue;
                                }
 
@@ -796,7 +807,7 @@ TimeAxisView::set_samples_per_pixel (double fpp)
 }
 
 void
-TimeAxisView::show_timestretch (framepos_t start, framepos_t end, int layers, int layer)
+TimeAxisView::show_timestretch (samplepos_t start, samplepos_t end, int layers, int layer)
 {
        for (Children::iterator i = children.begin(); i != children.end(); ++i) {
                (*i)->show_timestretch (start, end, layers, layer);
@@ -817,10 +828,14 @@ TimeAxisView::show_selection (TimeSelection& ts)
        double x1;
        double x2;
        double y2;
-       SelectionRect *rect;    time_axis_frame.show();
+       SelectionRect *rect;
 
+       time_axis_frame.show();
 
        for (Children::iterator i = children.begin(); i != children.end(); ++i) {
+               if (!(*i)->selected () && !(*i)->propagate_time_selection ()) {
+                       continue;
+               }
                (*i)->show_selection (ts);
        }
 
@@ -838,9 +853,15 @@ TimeAxisView::show_selection (TimeSelection& ts)
        selection_group->show();
        selection_group->raise_to_top();
 
+       uint32_t gap = UIConfiguration::instance().get_vertical_region_gap ();
+       float ui_scale = UIConfiguration::instance().get_ui_scale ();
+       if (gap > 0 && ui_scale > 0) {
+               gap = ceil (gap * ui_scale);
+       }
+
        for (list<AudioRange>::iterator i = ts.begin(); i != ts.end(); ++i) {
-               framepos_t start, end;
-               framecnt_t cnt;
+               samplepos_t start, end;
+               samplecnt_t cnt;
 
                start = (*i).start;
                end = (*i).end;
@@ -852,6 +873,14 @@ TimeAxisView::show_selection (TimeSelection& ts)
                x2 = _editor.sample_to_pixel (start + cnt - 1);
                y2 = current_height() - 1;
 
+               if (dynamic_cast<AudioTimeAxisView*>(this)) {
+                       if (y2 > gap) {
+                               y2 -= gap;
+                       } else {
+                               y2 = 1;
+                       }
+               }
+
                rect->rect->set (ArdourCanvas::Rect (x1, 0, x2, y2));
 
                // trim boxes are at the top for selections
@@ -878,6 +907,9 @@ TimeAxisView::reshow_selection (TimeSelection& ts)
        show_selection (ts);
 
        for (Children::iterator i = children.begin(); i != children.end(); ++i) {
+               if (!(*i)->selected () && !(*i)->propagate_time_selection ()) {
+                       continue;
+               }
                (*i)->show_selection (ts);
        }
 }
@@ -959,7 +991,9 @@ TimeAxisView::get_selection_rect (uint32_t id)
 
                rect->rect = new ArdourCanvas::Rectangle (selection_group);
                CANVAS_DEBUG_NAME (rect->rect, "selection rect");
-               rect->rect->set_outline (false);
+               rect->rect->set_outline (true);
+               rect->rect->set_outline_width (1.0);
+               rect->rect->set_outline_color (UIConfiguration::instance().color ("selection"));
                rect->rect->set_fill_color (UIConfiguration::instance().color_mod ("selection rect", "selection rect"));
 
                rect->start_trim = new ArdourCanvas::Rectangle (selection_group);
@@ -1010,22 +1044,38 @@ TimeAxisView::remove_child (boost::shared_ptr<TimeAxisView> child)
 }
 
 /** Get selectable things within a given range.
- *  @param start Start time in session frames.
- *  @param end End time in session frames.
+ *  @param start Start time in session samples.
+ *  @param end End time in session samples.
  *  @param top Top y range, in trackview coordinates (ie 0 is the top of the track view)
  *  @param bot Bottom y range, in trackview coordinates (ie 0 is the top of the track view)
  *  @param result Filled in with selectable things.
  */
 void
-TimeAxisView::get_selectables (framepos_t /*start*/, framepos_t /*end*/, double /*top*/, double /*bot*/, list<Selectable*>& /*result*/, bool /*within*/)
+TimeAxisView::get_selectables (samplepos_t start, samplepos_t end, double top, double bot, list<Selectable*>& results, bool within)
 {
-       return;
+       for (Children::iterator i = children.begin(); i != children.end(); ++i) {
+               if (!(*i)->hidden()) {
+                       (*i)->get_selectables (start, end, top, bot, results, within);
+               }
+       }
+}
+
+void
+TimeAxisView::set_selected_points (PointSelection& points)
+{
+       for (Children::iterator i = children.begin(); i != children.end(); ++i) {
+               (*i)->set_selected_points (points);
+       }
 }
 
 void
-TimeAxisView::get_inverted_selectables (Selection& /*sel*/, list<Selectable*>& /*result*/)
+TimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
 {
-       return;
+       for (Children::iterator i = children.begin(); i != children.end(); ++i) {
+               if (!(*i)->hidden()) {
+                       (*i)->get_inverted_selectables (sel, results);
+               }
+       }
 }
 
 void
@@ -1148,6 +1198,20 @@ TimeAxisView::color_handler ()
        }
 }
 
+void
+TimeAxisView::parameter_changed (string const & what_changed)
+{
+       if (what_changed == "vertical-region-gap") {
+               if (selected ()) {
+                       show_selection (_editor.get_selection().time);
+               }
+       }
+
+       if (view()) {
+               view()->parameter_changed (what_changed);
+       }
+}
+
 /** @return Pair: TimeAxisView, layer index.
  * TimeAxisView is non-0 if this object covers @param y, or one of its children
  * does. @param y is an offset from the top of the trackview area.
@@ -1255,11 +1319,11 @@ TimeAxisView::preset_height (Height h)
 
 /** @return Child time axis views that are not hidden */
 TimeAxisView::Children
-TimeAxisView::get_child_list ()
+TimeAxisView::get_child_list () const
 {
        Children c;
 
-       for (Children::iterator i = children.begin(); i != children.end(); ++i) {
+       for (Children::const_iterator i = children.begin(); i != children.end(); ++i) {
                if (!(*i)->hidden()) {
                        c.push_back(*i);
                }