change the way the audio clock cursor is drawn (somewhat of an experiment but it...
[ardour.git] / gtk2_ardour / audio_clock.cc
index 7d6dd3cfcde6b7a655d7aca916c2e7a4261ea623..8de39d58f1d5100ffe4c52ebd21c25e6a51f1470 100644 (file)
 #include "gtkmm2ext/rgb_macros.h"
 
 #include "ardour/profile.h"
+#include "ardour/lmath.h"
 #include "ardour/session.h"
 #include "ardour/slave.h"
 #include "ardour/tempo.h"
 #include "ardour/types.h"
 
-#include "ardour_ui.h"
 #include "audio_clock.h"
-#include "global_signals.h"
 #include "utils.h"
 #include "keyboard.h"
 #include "gui_thread.h"
+#include "ui_config.h"
 #include "i18n.h"
 
 using namespace ARDOUR;
@@ -54,7 +54,7 @@ using Gtkmm2ext::Keyboard;
 
 sigc::signal<void> AudioClock::ModeChanged;
 vector<AudioClock*> AudioClock::clocks;
-const double AudioClock::info_font_scale_factor = 0.50;
+const double AudioClock::info_font_scale_factor = 0.68;
 const double AudioClock::separator_height = 0.0;
 const double AudioClock::x_leading_padding = 6.0;
 
@@ -64,13 +64,15 @@ const double AudioClock::x_leading_padding = 6.0;
 #define TXTSPAN "<span font-family=\"Sans\" foreground=\"white\">"
 
 AudioClock::AudioClock (const string& clock_name, bool transient, const string& widget_name,
-                       bool allow_edit, bool follows_playhead, bool duration, bool with_info)
+                       bool allow_edit, bool follows_playhead, bool duration, bool with_info,
+                       bool accept_on_focus_out)
        : ops_menu (0)
        , _name (clock_name)
        , is_transient (transient)
        , is_duration (duration)
        , editable (allow_edit)
        , _follows_playhead (follows_playhead)
+       , _accept_on_focus_out (accept_on_focus_out)
        , _off (false)
        , em_width (0)
        , _edit_by_click_field (false)
@@ -95,6 +97,8 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string&
        , last_sdelta (0)
        , dragging (false)
        , drag_field (Field (0))
+       , xscale (1.0)
+       , yscale (1.0)
 {
        set_flags (CAN_FOCUS);
 
@@ -116,8 +120,8 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string&
                clocks.push_back (this);
        }
 
-       ColorsChanged.connect (sigc::mem_fun (*this, &AudioClock::set_colors));
-       DPIReset.connect (sigc::mem_fun (*this, &AudioClock::dpi_reset));
+       UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &AudioClock::set_colors));
+       UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &AudioClock::dpi_reset));
 }
 
 AudioClock::~AudioClock ()
@@ -193,6 +197,7 @@ AudioClock::set_font (Pango::FontDescription font)
 
        tmp->set_text ("8");
        tmp->get_pixel_size (em_width, ignore_height);
+       
 
        /* force redraw of markup with new font-size */
        set (last_when, true);
@@ -216,15 +221,15 @@ AudioClock::set_colors ()
        uint32_t cursor_color;
 
        if (active_state()) {
-               bg_color = ARDOUR_UI::config()->color (string_compose ("%1 active: background", get_name()));
-               text_color = ARDOUR_UI::config()->color (string_compose ("%1 active: text", get_name()));
-               editing_color = ARDOUR_UI::config()->color (string_compose ("%1 active: edited text", get_name()));
-               cursor_color = ARDOUR_UI::config()->color (string_compose ("%1 active: cursor", get_name()));
+               bg_color = UIConfiguration::instance().color (string_compose ("%1 active: background", get_name()));
+               text_color = UIConfiguration::instance().color (string_compose ("%1 active: text", get_name()));
+               editing_color = UIConfiguration::instance().color (string_compose ("%1 active: edited text", get_name()));
+               cursor_color = UIConfiguration::instance().color (string_compose ("%1 active: cursor", get_name()));
        } else {
-               bg_color = ARDOUR_UI::config()->color (string_compose ("%1: background", get_name()));
-               text_color = ARDOUR_UI::config()->color (string_compose ("%1: text", get_name()));
-               editing_color = ARDOUR_UI::config()->color (string_compose ("%1: edited text", get_name()));
-               cursor_color = ARDOUR_UI::config()->color (string_compose ("%1: cursor", get_name()));
+               bg_color = UIConfiguration::instance().color (string_compose ("%1: background", get_name()));
+               text_color = UIConfiguration::instance().color (string_compose ("%1: text", get_name()));
+               editing_color = UIConfiguration::instance().color (string_compose ("%1: edited text", get_name()));
+               cursor_color = UIConfiguration::instance().color (string_compose ("%1: cursor", get_name()));
        }
 
        /* store for bg and cursor in render() */
@@ -277,6 +282,15 @@ AudioClock::set_colors ()
        queue_draw ();
 }
 
+void
+AudioClock::set_scale (double x, double y)
+{
+       xscale = x;
+       yscale = y;
+
+       queue_draw ();
+}
+
 void
 AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
 {
@@ -296,10 +310,26 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
                cairo_fill (cr);
        }
 
-       cairo_move_to (cr, (get_width() - layout_width) / 2.0, (upper_height - layout_height) / 2.0);
+       double lw = layout_width * xscale;
+       double lh = layout_height * yscale;
+
+       if (lw >= get_width()) {
+               cairo_move_to (cr, 0.0, (upper_height - lh) / 2.0);
+       } else {
+               cairo_move_to (cr, (get_width() - lw) / 2.0, (upper_height - lh) / 2.0);
+       }
+
+       if (xscale != 1.0 || yscale != 1.0) {
+               cairo_save (cr);
+               cairo_scale (cr, xscale, yscale);
+       }
 
        pango_cairo_show_layout (cr, _layout->gobj());
 
+       if (xscale != 1.0 || yscale != 1.0) {
+               cairo_restore (cr);
+       }
+
        if (_left_layout) {
 
                double h = get_height() - upper_height - separator_height;
@@ -310,7 +340,7 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
 
                if (mode_based_info_ratio != 1.0) {
 
-                       double left_rect_width = round (((get_width() - separator_height) * mode_based_info_ratio) + 0.5);
+                       double left_rect_width = get_left_rect_width();
 
                        if (_need_bg) {
                                if (corner_radius) {
@@ -376,42 +406,44 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
        }
 
        if (editing) {
-               if (!insert_map.empty()) {
+               Pango::Rectangle cursor;
 
-                       int xcenter = (get_width() - layout_width) /2;
+               if (!insert_map.empty()) {
 
                        if (input_string.length() < insert_map.size()) {
-                               Pango::Rectangle cursor;
 
-                               if (input_string.empty()) {
-                                       /* nothing entered yet, put cursor at the end
-                                          of string
-                                       */
-                                       cursor = _layout->get_cursor_strong_pos (edit_string.length() - 1);
-                               } else {
-                                       cursor = _layout->get_cursor_strong_pos (insert_map[input_string.length()]);
-                               }
+                               cursor = _layout->get_cursor_strong_pos (edit_string.length() - 1);
 
                                cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
+
                                cairo_rectangle (cr,
-                                                min (get_width() - 2.0,
-                                                     (double) xcenter + cursor.get_x()/PANGO_SCALE + em_width),
-                                                (upper_height - layout_height)/2.0,
-                                                2.0, cursor.get_height()/PANGO_SCALE);
-                               cairo_fill (cr);
+                                                cursor.get_x()/PANGO_SCALE,
+                                                (upper_height - layout_height)/2.0,
+                                                em_width,
+                                                cursor.get_height()/PANGO_SCALE);
+                               cairo_stroke (cr);
+
                        } else {
                                /* we've entered all possible digits, no cursor */
                        }
 
                } else {
-                       if (input_string.empty()) {
-                               cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
+                       cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
+
+                       if (edit_string.empty()) {
                                cairo_rectangle (cr,
-                                                (get_width()/2.0),
-                                                (upper_height - layout_height)/2.0,
-                                                2.0, upper_height);
-                               cairo_fill (cr);
+                                                get_width() - em_width,
+                                                (upper_height - layout_height)/2.0,
+                                                em_width, upper_height);
+                       } else {
+                               cursor = _layout->get_cursor_strong_pos (edit_string.length() - 1);
+                               cairo_rectangle (cr,
+                                                cursor.get_x()/PANGO_SCALE,
+                                                (upper_height - layout_height)/2.0,
+                                                em_width, upper_height);
                        }
+                               
+                       cairo_stroke (cr);
                }
        }
 }
@@ -446,11 +478,25 @@ AudioClock::set_clock_dimensions (Gtk::Requisition& req)
        tmp->set_font_description (font);
 
        /* this string is the longest thing we will ever display */
-       tmp->set_text (" 88:88:88,888");
+       if (_mode == MinSec)
+               tmp->set_text (" 88:88:88,888 ");
+       else
+               tmp->set_text (" 88:88:88,88 ");
        tmp->get_pixel_size (req.width, req.height);
 
+
        layout_height = req.height;
        layout_width = req.width;
+
+       /* get the figure width for the font. This doesn't have to super
+        * accurate since we only use it to measure the (roughly 1 character)
+        * offset from the position Pango tells us for the "cursor"
+        */
+
+       int ignore_height;
+
+       tmp->set_text ("8");
+       tmp->get_pixel_size (em_width, ignore_height);
 }
 
 void
@@ -1391,7 +1437,10 @@ AudioClock::on_key_press_event (GdkEventKey* ev)
                goto use_input_string;
 
        default:
-               return false;
+               /* do not allow other keys to passthru to the rest of the GUI
+                  when editing.
+               */
+               return true;
        }
 
        if (!insert_map.empty() && (input_string.length() >= insert_map.size())) {
@@ -1661,7 +1710,7 @@ AudioClock::on_focus_out_event (GdkEventFocus* ev)
        bool ret = CairoWidget::on_focus_out_event (ev);
 
        if (editing) {
-               end_edit (false);
+               end_edit (_accept_on_focus_out);
        }
 
        return ret;
@@ -2055,6 +2104,24 @@ AudioClock::frames_from_audioframes_string (const string& str) const
        return f;
 }
 
+void
+AudioClock::copy_text_to_clipboard () const
+{
+       string val;
+       if (editing) {
+               val = pre_edit_string;
+       } else {
+               val = _layout->get_text ();
+       }
+       const size_t trim = val.find_first_not_of(" ");
+       if (trim == string::npos) {
+               assert(0); // empty clock, can't be right.
+               return;
+       }
+       Glib::RefPtr<Clipboard> cl = Gtk::Clipboard::get();
+       cl->set_text (val.substr(trim));
+}
+
 void
 AudioClock::build_ops_menu ()
 {
@@ -2075,6 +2142,8 @@ AudioClock::build_ops_menu ()
                ops_items.push_back (MenuElem (_("Set From Playhead"), sigc::mem_fun(*this, &AudioClock::set_from_playhead)));
                ops_items.push_back (MenuElem (_("Locate to This Time"), sigc::mem_fun(*this, &AudioClock::locate)));
        }
+       ops_items.push_back (SeparatorElem());
+       ops_items.push_back (MenuElem (_("Copy to clipboard"), sigc::mem_fun(*this, &AudioClock::copy_text_to_clipboard)));
 }
 
 void
@@ -2111,6 +2180,9 @@ AudioClock::set_mode (Mode m)
 
        _layout->set_text ("");
 
+       Gtk::Requisition req;
+       set_clock_dimensions (req);
+
        if (_left_layout) {
 
                _left_layout->set_attributes (info_attributes);