new_snap: Snapped Cursor ( squashed commit )
authorBen Loftis <ben@harrisonconsoles.com>
Fri, 9 Feb 2018 14:21:45 +0000 (08:21 -0600)
committerBen Loftis <ben@harrisonconsoles.com>
Fri, 9 Feb 2018 14:21:45 +0000 (08:21 -0600)
Snapped Cursor is a line that follows the edit point, and indicates where the operation will occur.
This replaces and extends the line that appears with the Cut tool.
New associated preferences:  snap_threshold and show_snap_cursor.

14 files changed:
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_canvas.cc
gtk2_ardour/editor_drag.cc
gtk2_ardour/editor_drag.h
gtk2_ardour/editor_mouse.cc
gtk2_ardour/luainstance.cc
gtk2_ardour/marker.cc
gtk2_ardour/midi_region_view.cc
gtk2_ardour/mini_timeline.cc
gtk2_ardour/mini_timeline.h
gtk2_ardour/public_editor.h
gtk2_ardour/rc_option_editor.cc
gtk2_ardour/ui_config_vars.h

index b827ac0eb1fee6a799a16e73e6a91b6fe042a11f..9ce693184a966782ba1bf43824806ef6ce551dd8 100644 (file)
@@ -335,6 +335,7 @@ Editor::Editor ()
        , cd_mark_label (_("CD Markers"))
        , videotl_label (_("Video Timeline"))
        , videotl_group (0)
+       , snapped_cursor (0)
        , playhead_cursor (0)
        , edit_packer (4, 4, true)
        , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
@@ -367,7 +368,6 @@ Editor::Editor ()
        , pending_keyboard_selection_start (0)
        , _snap_type (SnapToBeat)
        , _snap_mode (SnapOff)
-       , snap_threshold (5.0)
        , ignore_gui_changes (false)
        , _drags (new DragManager (this))
        , lock_dialog (0)
@@ -1406,8 +1406,13 @@ Editor::set_session (Session *t)
        _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
        _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
 
+       playhead_cursor->track_canvas_item().reparent ((ArdourCanvas::Item*) get_cursor_scroll_group());
        playhead_cursor->show ();
 
+       snapped_cursor->track_canvas_item().reparent ((ArdourCanvas::Item*) get_cursor_scroll_group());
+       snapped_cursor->set_color (UIConfiguration::instance().color ("edit point"));
+       snapped_cursor->show ();
+
        boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
        Config->map_parameters (pc);
        _session->config.map_parameters (pc);
@@ -2287,6 +2292,7 @@ Editor::set_edit_point_preference (EditPoint ep, bool force)
 
        switch (_edit_point) {
        case EditAtPlayhead:
+//ToDo:  hide or show mouse_cursor
                action = "edit-at-playhead";
                break;
        case EditAtSelectedMarker:
@@ -2637,6 +2643,15 @@ Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
        return std::make_pair ( (TimeAxisView *) 0, 0);
 }
 
+void
+Editor::set_snapped_cursor_position (samplepos_t pos)
+{
+       if ( _edit_point == EditAtMouse ) {
+               snapped_cursor->set_position(pos);
+       }
+}
+
+
 /** Snap a position to the grid, if appropriate, taking into account current
  *  grid settings and also the state of any snap modifier keys that may be pressed.
  *  @param start Position to snap.
@@ -2756,6 +2771,8 @@ Editor::snap_to_internal (MusicSample& start, RoundMode direction, bool for_mark
        samplepos_t before;
        samplepos_t after;
 
+       int snap_threshold_s = pixel_to_sample(UIConfiguration::instance().get_snap_threshold());
+
        switch (_snap_type) {
        case SnapToTimecodeFrame:
        case SnapToTimecodeSeconds:
@@ -2942,12 +2959,12 @@ Editor::snap_to_internal (MusicSample& start, RoundMode direction, bool for_mark
                }
 
                if (presnap > start.sample) {
-                       if (presnap > (start.sample + pixel_to_sample(snap_threshold))) {
+                       if (presnap > (start.sample + snap_threshold_s)) {
                                start.set (presnap, 0);
                        }
 
                } else if (presnap < start.sample) {
-                       if (presnap < (start.sample - pixel_to_sample(snap_threshold))) {
+                       if (presnap < (start.sample - snap_threshold_s)) {
                                start.set (presnap, 0);
                        }
                }
@@ -5797,27 +5814,6 @@ Editor::super_rapid_screen_update ()
                current_mixer_strip->fast_update ();
        }
 
-       /* PLAYHEAD AND VIEWPORT */
-
-       /* There are a few reasons why we might not update the playhead / viewport stuff:
-        *
-        * 1.  we don't update things when there's a pending locate request, otherwise
-        *     when the editor requests a locate there is a chance that this method
-        *     will move the playhead before the locate request is processed, causing
-        *     a visual glitch.
-        * 2.  if we're not rolling, there's nothing to do here (locates are handled elsewhere).
-        * 3.  if we're still at the same sample that we were last time, there's nothing to do.
-        */
-       if (_pending_locate_request || !_session->transport_rolling ()) {
-               _last_update_time = 0;
-               return;
-       }
-
-       if (_dragging_playhead) {
-               _last_update_time = 0;
-               return;
-       }
-
        bool latent_locate = false;
        samplepos_t sample = _session->audible_sample (&latent_locate);
        const int64_t now = g_get_monotonic_time ();
@@ -5857,6 +5853,47 @@ Editor::super_rapid_screen_update ()
        } else {
                _last_update_time = now;
        }
+       
+       //snapped cursor stuff ( the snapped_cursor shows where an operation is going to occur )
+       bool ignored;
+       MusicSample where (sample, 0);
+       if ( !UIConfiguration::instance().get_show_snapped_cursor() ) {
+               snapped_cursor->hide ();
+       } else if ( _edit_point == EditAtPlayhead && !_dragging_playhead) {
+               snap_to (where);  // can't use snap_to_with_modifier?
+               snapped_cursor->set_position (where.sample);
+               snapped_cursor->show ();
+       } else if ( _edit_point == EditAtSelectedMarker ) {
+               //NOTE:  I don't think EditAtSelectedMarker should snap.  they are what they are.
+               //however, the current editing code -does- snap so I'll draw it that way for now.
+               MusicSample ms (selection->markers.front()->position(), 0);
+               snap_to (ms);  // should use snap_to_with_modifier?
+               snapped_cursor->set_position ( ms.sample );
+               snapped_cursor->show ();
+       } else if (mouse_sample (where.sample, ignored)) {   //cursor is in the editing canvas. show it.
+               snapped_cursor->show ();
+       } else { //mouse is out of the editing canvas.  hide the snapped_cursor
+               snapped_cursor->hide ();
+       }
+       
+       /* There are a few reasons why we might not update the playhead / viewport stuff:
+        *
+        * 1.  we don't update things when there's a pending locate request, otherwise
+        *     when the editor requests a locate there is a chance that this method
+        *     will move the playhead before the locate request is processed, causing
+        *     a visual glitch.
+        * 2.  if we're not rolling, there's nothing to do here (locates are handled elsewhere).
+        * 3.  if we're still at the same frame that we were last time, there's nothing to do.
+        */
+       if (_pending_locate_request) {
+               _last_update_time = 0;
+               return;
+       }
+
+       if (_dragging_playhead) {
+               _last_update_time = 0;
+               return;
+       }
 
        if (playhead_cursor->current_sample () == sample) {
                return;
index 498a4e0fe024f4b7eb858ef7980b89d469374e8e..5829927d1a0a00c3209ea842804f2ef88cd2a349 100644 (file)
@@ -169,7 +169,6 @@ public:
        void prev_snap_choice_music_and_time ();
        void set_snap_to (Editing::SnapType);
        void set_snap_mode (Editing::SnapMode);
-       void set_snap_threshold (double pixel_distance) {snap_threshold = pixel_distance;}
 
        Editing::SnapMode  snap_mode () const;
        Editing::SnapType  snap_type () const;
@@ -472,6 +471,8 @@ public:
                      ARDOUR::RoundMode   direction = ARDOUR::RoundNearest,
                      bool                for_mark  = false);
 
+       void set_snapped_cursor_position (samplepos_t pos);
+
        void begin_selection_op_history ();
        void begin_reversible_selection_op (std::string cmd_name);
        void commit_reversible_selection_op ();
@@ -533,6 +534,7 @@ public:
        ArdourCanvas::ScrollGroup* get_hscroll_group () const { return h_scroll_group; }
        ArdourCanvas::ScrollGroup* get_hvscroll_group () const { return hv_scroll_group; }
        ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const { return cursor_scroll_group; }
+       ArdourCanvas::Container* get_drag_motion_group () const { return _drag_motion_group; }
 
        ArdourCanvas::GtkCanvasViewport* get_track_canvas () const;
 
@@ -1032,6 +1034,8 @@ private:
 
        friend class EditorCursor;
 
+       EditorCursor* snapped_cursor;
+
        EditorCursor* playhead_cursor;
        samplepos_t playhead_cursor_sample () const;
 
@@ -1529,9 +1533,6 @@ private:
        Editing::SnapType _snap_type;
        Editing::SnapMode _snap_mode;
 
-       /// Snap threshold in pixels
-       double snap_threshold;
-
        bool ignore_gui_changes;
 
        DragManager* _drags;
index 5aeed49f43454a6ebe10689e49baf2bdd4511e0f..a60d3eab9ced61220b320ea8b5b0981b6b841491 100644 (file)
@@ -217,6 +217,8 @@ Editor::initialize_canvas ()
 
        playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event);
 
+       snapped_cursor = new EditorCursor (*this);
+
        _canvas_drop_zone = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, 0.0));
        /* this thing is transparent */
        _canvas_drop_zone->set_fill (false);
index 9d36b28e1b468f4863ca9148fe24a9edaaa74509..0dab9d8d0faecfc23e2906ed9adc63d95f08847d 100644 (file)
@@ -719,6 +719,8 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, MusicSample* pending_
                }
        }
 
+       _editor->set_snapped_cursor_position(pending_region_position->sample);
+
        return dx;
 }
 
@@ -3320,6 +3322,7 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
        _marker->set_position (adjusted_current_sample (event, false));
 
        show_verbose_cursor_time (_real_section->sample());
+       _editor->set_snapped_cursor_position(_real_section->sample());
 }
 
 void
@@ -3485,6 +3488,7 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
                map.gui_set_tempo_position (_real_section, pf, sub_num);
 
                show_verbose_cursor_time (_real_section->sample());
+               _editor->set_snapped_cursor_position(_real_section->sample());
        }
        _marker->set_position (adjusted_current_sample (event, false));
 }
@@ -4609,6 +4613,7 @@ MarkerDrag::motion (GdkEvent* event, bool)
        assert (!_copied_locations.empty());
 
        show_verbose_cursor_time (newframe);
+       _editor->set_snapped_cursor_position(newframe);
 }
 
 void
@@ -6144,6 +6149,8 @@ NoteDrag::motion (GdkEvent * event, bool first_move)
                        uint8_t new_note = min (max (_primary->note()->note() + note_delta, 0), 127);
 
                        _region->show_verbose_cursor_for_new_note_value (_primary->note(), new_note);
+
+                       _editor->set_snapped_cursor_position( _region->source_beats_to_absolute_samples(_primary->note()->time()) );
                }
        }
 }
@@ -6956,16 +6963,11 @@ CrossfadeEdgeDrag::aborted (bool)
 
 RegionCutDrag::RegionCutDrag (Editor* e, ArdourCanvas::Item* item, samplepos_t pos)
        : Drag (e, item, true)
-       , line (new EditorCursor (*e))
 {
-       line->set_position (pos);
-       line->show ();
-       line->track_canvas_item().reparent (_editor->_drag_motion_group);
 }
 
 RegionCutDrag::~RegionCutDrag ()
 {
-       delete line;
 }
 
 void
@@ -6978,10 +6980,6 @@ RegionCutDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
 void
 RegionCutDrag::motion (GdkEvent* event, bool)
 {
-       MusicSample pos (_drags->current_pointer_sample(), 0);
-       _editor->snap_to_with_modifier (pos, event);
-
-       line->set_position (pos.sample);
 }
 
 void
@@ -6992,7 +6990,6 @@ RegionCutDrag::finished (GdkEvent* event, bool)
 
        MusicSample pos (_drags->current_pointer_sample(), 0);
        _editor->snap_to_with_modifier (pos, event);
-       line->hide ();
 
        RegionSelection rs = _editor->get_regions_from_selection_and_mouse (pos.sample);
 
index 53006676be767c6a133370a5b09ba8204184898d..3dde8d80ad9eb57741565449f35c024ab537e61f 100644 (file)
@@ -511,7 +511,6 @@ public:
        void aborted (bool);
 
 private:
-       EditorCursor* line;
 };
 
 /** Drags to create regions */
index 250988985373de114b4a0ea73e00a438caca96f1..bb8b2accaee9a21975b634f43b904a2bdbeb5970 100644 (file)
@@ -2078,6 +2078,15 @@ Editor::motion_handler (ArdourCanvas::Item* /*item*/, GdkEvent* event, bool from
 
        update_join_object_range_location (event->motion.y);
 
+       //snapped_cursor stuff ( the snapped_cursor shows where an operation is going to occur )
+       bool ignored;
+       MusicSample where (0, 0);
+       if (mouse_sample (where.sample, ignored)) {
+               snap_to_with_modifier (where, event);
+               set_snapped_cursor_position (where.sample);
+       }
+               
+       //drags might also change the snapped_cursor location, because we are snapping the thing being dragged, not the actual mouse cursor
        if (_drags->active ()) {
                return _drags->motion_handler (event, from_autoscroll);
        }
index 361b1e238c437fd966c590907103c42ecfc79c4f..9fe03ea077938f9049e5953b0153648825dacd91 100644 (file)
@@ -837,7 +837,6 @@ LuaInstance::register_classes (lua_State* L)
                .addFunction ("snap_type", &PublicEditor::snap_type)
                .addFunction ("snap_mode", &PublicEditor::snap_mode)
                .addFunction ("set_snap_mode", &PublicEditor::set_snap_mode)
-               .addFunction ("set_snap_threshold", &PublicEditor::set_snap_threshold)
 
                .addFunction ("undo", &PublicEditor::undo)
                .addFunction ("redo", &PublicEditor::redo)
index 29acc70e5d6a215b2c851e29c5bdafb67ba36dfc..a5084bf2c9c048c26cb89f82a8747ff4ec132269 100644 (file)
@@ -348,7 +348,6 @@ ArdourMarker::setup_line ()
                if (_track_canvas_line == 0) {
 
                        _track_canvas_line = new ArdourCanvas::Line (editor.get_hscroll_group());
-                       _track_canvas_line->set_outline_color (UIConfiguration::instance().color ("edit point"));
                        _track_canvas_line->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_marker_event), group, this));
                }
 
@@ -359,7 +358,7 @@ ArdourMarker::setup_line ()
                _track_canvas_line->set_x1 (d.x);
                _track_canvas_line->set_y0 (d.y);
                _track_canvas_line->set_y1 (ArdourCanvas::COORD_MAX);
-               _track_canvas_line->set_outline_color (_selected ? UIConfiguration::instance().color ("edit point") : _color);
+               _track_canvas_line->set_outline_color ( _selected ? UIConfiguration::instance().color ("entered marker") : _color );
                _track_canvas_line->raise_to_top ();
                _track_canvas_line->show ();
 
index 4a19a6697ac18189f5b1ad1a1d502173511efc6b..53b42b27f2dbc641eb001d01044cce2a095e483d 100644 (file)
@@ -347,6 +347,9 @@ MidiRegionView::canvas_group_event(GdkEvent* ev)
                return RegionView::canvas_group_event (ev);
        }
 
+       //For now, move the snapped cursor aside so it doesn't bother you during internal editing
+       //trackview.editor().set_snapped_cursor_position(_region->position());
+
        bool r;
 
        switch (ev->type) {
@@ -3035,6 +3038,7 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
                        } else {
                                snapped_x = trackview.editor ().pixel_to_sample (current_x);
                        }
+
                        const Temporal::Beats beats = Temporal::Beats (tmap.exact_beat_at_sample (snapped_x + midi_region()->position(), divisions)
                                                                     - midi_region()->beat()) + midi_region()->start_beats();
 
@@ -3058,6 +3062,8 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
                        show_verbose_cursor (buf, 0, 0);
 
                        cursor_set = true;
+
+                       trackview.editor().set_snapped_cursor_position ( snapped_x + midi_region()->position() );
                }
 
        }
index 9d7dc61d73709534ca925125b91ca940af8f8926..b4652583ca3e34300e03d18354613bb99b1eb453 100644 (file)
@@ -151,6 +151,7 @@ void
 MiniTimeline::set_colors ()
 {
        // TODO  UIConfiguration::instance().color & font
+       _phead_color = UIConfiguration::instance().color ("play head");
 }
 
 void
@@ -648,7 +649,8 @@ MiniTimeline::render (Cairo::RefPtr<Cairo::Context> const& ctx, cairo_rectangle_
        /* playhead on top */
        int xc = width * 0.5f;
        cairo_set_line_width (cr, 1.0);
-       cairo_set_source_rgb (cr, 1, 0, 0); // playhead color
+       double r,g,b,a;  Gtkmm2ext::color_to_rgba(_phead_color, r,g,b,a);
+       cairo_set_source_rgb (cr, r,g,b); // playhead color
        cairo_move_to (cr, xc - .5, 0);
        cairo_rel_line_to (cr, 0, height);
        cairo_stroke (cr);
index 21b316df396ff8b53bd26b2e4095d905f531e0dc..b0cb5ee8cda4d9a4bf1e99611e7c33bd5a218b6f 100644 (file)
@@ -101,6 +101,8 @@ private:
 
        Gtk::Menu* _minitl_context_menu;
 
+       uint32_t _phead_color;
+
        struct JumpRange {
                JumpRange (int l, int r, samplepos_t t, bool p = false)
                        : left (l), right (r), to (t), prelight (p) {}
index 9fbdb106bc4410b67b86e6756765fd3f03ac9858..6df7777818fd2e69c7980e508fd7b8f27098a610 100644 (file)
@@ -143,11 +143,6 @@ public:
         */
        virtual void set_snap_mode (Editing::SnapMode m) = 0;
 
-       /** Set the snap threshold.
-        * @param t Snap threshold in `units'.
-        */
-       virtual void set_snap_threshold (double t) = 0;
-
        /**
         * Snap a value according to the current snap setting.
         * ensure_snap overrides SnapOff and magnetic snap
@@ -426,6 +421,7 @@ public:
        virtual ArdourCanvas::ScrollGroup* get_hscroll_group () const = 0;
        virtual ArdourCanvas::ScrollGroup* get_hvscroll_group () const = 0;
        virtual ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const = 0;
+       virtual ArdourCanvas::Container* get_drag_motion_group () const = 0;
 
        virtual ArdourCanvas::GtkCanvasViewport* get_track_canvas() const = 0;
 
@@ -467,6 +463,8 @@ public:
                                            ARDOUR::RoundMode   direction = ARDOUR::RoundNearest,
                                            bool                for_mark  = false) = 0;
 
+       virtual void set_snapped_cursor_position (samplepos_t pos) = 0;
+
        virtual void get_regions_at (RegionSelection &, samplepos_t where, TrackViewList const &) const = 0;
        virtual void get_regions_after (RegionSelection&, samplepos_t where, const TrackViewList& ts) const = 0;
        virtual RegionSelection get_regions_from_selection_and_mouse (samplepos_t) = 0;
index bef5780fadca36a404f2adbe26f6c58f0c30b8f6..ce099883fe02bf32e0ec312d926135f7d02edc4b 100644 (file)
@@ -2490,6 +2490,26 @@ RCOptionEditor::RCOptionEditor ()
 
        add_option (_("Editor"), rsas);
 
+       add_option (_("Editor/Snap"), new OptionEditorHeading (_("General Snap options:")));
+       
+       add_option (_("Editor/Snap"),
+                   new SpinOption<uint32_t> (
+                           "snap-threshold",
+                           _("Snap Threshold (pixels)"),
+                           sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_threshold),
+                           sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_threshold),
+                           10, 200,
+                           1, 10
+                           ));
+
+       add_option (_("Editor/Snap"),
+            new BoolOption (
+                    "show-snapped-cursor",
+                    _("Show Snapped Cursor"),
+                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_snapped_cursor),
+                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_snapped_cursor)
+                    ));
+
        add_option (_("Editor/Modifiers"), new OptionEditorHeading (_("Keyboard Modifiers")));
        add_option (_("Editor/Modifiers"), new KeyboardOptions);
        add_option (_("Editor/Modifiers"), new OptionEditorBlank ());
index 50960d70bfe808cafb95a8d0e961c9c65b810554..f4b516495ca28905dd00ff02943e311b80d2b52e 100644 (file)
@@ -100,3 +100,6 @@ UI_CONFIG_VARIABLE (bool, prefer_inline_over_gui, "prefer-inline-over-gui", true
 UI_CONFIG_VARIABLE (uint32_t, action_table_columns, "action-table-columns", 0)
 UI_CONFIG_VARIABLE (bool, use_wm_visibility, "use-wm-visibility", true)
 UI_CONFIG_VARIABLE (std::string, stripable_color_palette, "stripable-color-palette", "#AA3939:#FFAAAA:#D46A6A:#801515:#550000:#AA8E39:#FFEAAA:#D4BA6A:#806515:#554000:#343477:#8080B3:#565695:#1A1A59:#09093B:#2D882D:#88CC88:#55AA55:#116611:#004400")  /* Gtk::ColorSelection::palette_to_string */
+
+UI_CONFIG_VARIABLE (bool, show_snapped_cursor, "show-snapped-cursor", true)
+UI_CONFIG_VARIABLE (uint32_t, snap_threshold, "snap-threshold", 25)