From 32c8cc09744470c46de8a82968630944d7f85fb5 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 10 Feb 2012 00:04:13 +0000 Subject: [PATCH] Modify the TimingController interface to support dragging more than one marker at once. Updates #20. Originally committed to SVN as r6460. --- aegisub/src/audio_display.cpp | 20 +++++++++--------- aegisub/src/audio_timing.h | 29 ++++++++++++++------------- aegisub/src/audio_timing_dialogue.cpp | 22 +++++++++++--------- aegisub/src/audio_timing_karaoke.cpp | 19 +++++++++--------- 4 files changed, 48 insertions(+), 42 deletions(-) diff --git a/aegisub/src/audio_display.cpp b/aegisub/src/audio_display.cpp index 190fc55f6..a0f685463 100644 --- a/aegisub/src/audio_display.cpp +++ b/aegisub/src/audio_display.cpp @@ -464,7 +464,7 @@ public: class AudioMarkerInteractionObject : public AudioDisplayInteractionObject { // Object-pair being interacted with - AudioMarker *marker; + std::vector markers; AudioTimingController *timing_controller; // Audio display drag is happening on AudioDisplay *display; @@ -478,8 +478,8 @@ class AudioMarkerInteractionObject : public AudioDisplayInteractionObject { int snap_range; public: - AudioMarkerInteractionObject(AudioMarker *marker, AudioTimingController *timing_controller, AudioDisplay *display, AudioController *controller, wxMouseButton button_used) - : marker(marker) + AudioMarkerInteractionObject(std::vector markers, AudioTimingController *timing_controller, AudioDisplay *display, AudioController *controller, wxMouseButton button_used) + : markers(markers) , timing_controller(timing_controller) , display(display) , controller(controller) @@ -494,7 +494,7 @@ public: if (event.Dragging()) { timing_controller->OnMarkerDrag( - marker, + markers, display->TimeFromRelativeX(event.GetPosition().x), default_snap != event.ShiftDown() ? display->TimeFromAbsoluteX(snap_range) : 0); } @@ -1093,14 +1093,14 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event) if (event.LeftDown() || event.RightDown()) { int timepos = TimeFromRelativeX(mousepos.x); - AudioMarker *marker = event.LeftDown() ? - timing->OnLeftClick(timepos, drag_sensitivity, snap_sensitivity) : - timing->OnRightClick(timepos, drag_sensitivity, snap_sensitivity); + std::vector markers = event.LeftDown() ? + timing->OnLeftClick(timepos, event.CmdDown(), drag_sensitivity, snap_sensitivity) : + timing->OnRightClick(timepos, event.CmdDown(), drag_sensitivity, snap_sensitivity); - if (marker) + if (markers.size()) { RemoveTrackCursor(); - audio_marker.reset(new AudioMarkerInteractionObject(marker, timing, this, controller, (wxMouseButton)event.GetButton())); + audio_marker.reset(new AudioMarkerInteractionObject(markers, timing, this, controller, (wxMouseButton)event.GetButton())); SetDraggedObject(audio_marker.get()); return; } @@ -1173,6 +1173,8 @@ void AudioDisplay::OnAudioOpen(AudioProvider *provider) connections.push_back(OPT_SUB("Colour/Audio Display/Spectrum", &AudioDisplay::ReloadRenderingSettings, this)); connections.push_back(OPT_SUB("Colour/Audio Display/Waveform", &AudioDisplay::ReloadRenderingSettings, this)); connections.push_back(OPT_SUB("Audio/Renderer/Spectrum/Quality", &AudioDisplay::ReloadRenderingSettings, this)); + + OnTimingController(); } } else diff --git a/aegisub/src/audio_timing.h b/aegisub/src/audio_timing.h index 730300f40..13964784b 100644 --- a/aegisub/src/audio_timing.h +++ b/aegisub/src/audio_timing.h @@ -112,29 +112,30 @@ public: /// controlling the mouse cursor. virtual bool IsNearbyMarker(int ms, int sensitivity) const = 0; - /// @brief The user pressed the left button down at an empty place in the audio + /// @brief The user pressed the left mouse button on the audio /// @param ms The time in milliseconds the user clicked + /// @param ctrl_down Is the user currently holding the ctrl key down? /// @param sensitivity Distance in milliseconds to consider existing markers /// @param snap_range Maximum snapping range in milliseconds - /// @return An audio marker or 0. If a marker is returned and the user - /// starts dragging the mouse after pressing down the button, the returned - /// marker is being dragged. - virtual AudioMarker * OnLeftClick(int ms, int sensitivity, int snap_range) = 0; + /// @return All audio markers at the clicked position which are eligible + /// to be dragged, if any. + virtual std::vector OnLeftClick(int ms, bool ctrl_down, int sensitivity, int snap_range) = 0; - /// @brief The user pressed the right button down at an empty place in the audio + /// @brief The user pressed the right mouse button on the audio /// @param ms The time in milliseconds the user clicked + /// @param ctrl_down Is the user currently holding the ctrl key down? /// @param sensitivity Distance in milliseconds to consider existing markers /// @param snap_range Maximum snapping range in milliseconds - /// @return An audio marker or 0. If a marker is returned and the user - /// starts dragging the mouse after pressing down the button, the returned - /// marker is being dragged. - virtual AudioMarker * OnRightClick(int ms, int sensitivity, int snap_range) = 0; + /// @return All audio markers at the clicked position which are eligible + /// to be dragged, if any. + virtual std::vector OnRightClick(int ms, bool ctrl_down, int sensitivity, int snap_range) = 0; - /// @brief The user dragged a timing marker - /// @param marker The marker being dragged + /// @brief The user dragged one or more timing markers + /// @param marker The markers being dragged. This is guaranteed to be + /// a vector returned from OnLeftClick or OnRightClick. /// @param new_position Time position the marker was dragged to - /// @param snap_range Maximum snapping range in milliseconds - virtual void OnMarkerDrag(AudioMarker *marker, int new_position, int snap_range) = 0; + /// @param snap_range Maximum snapping range in milliseconds + virtual void OnMarkerDrag(std::vector const& marker, int new_position, int snap_range) = 0; /// @brief Destructor virtual ~AudioTimingController() { } diff --git a/aegisub/src/audio_timing_dialogue.cpp b/aegisub/src/audio_timing_dialogue.cpp index 2019cb8ff..ad760124f 100644 --- a/aegisub/src/audio_timing_dialogue.cpp +++ b/aegisub/src/audio_timing_dialogue.cpp @@ -231,9 +231,9 @@ public: void Commit(); void Revert(); bool IsNearbyMarker(int ms, int sensitivity) const; - AudioMarker * OnLeftClick(int ms, int sensitivity, int snap_range); - AudioMarker * OnRightClick(int ms, int sensitivity, int snap_range); - void OnMarkerDrag(AudioMarker *marker, int new_position, int snap_range); + std::vector OnLeftClick(int ms, bool ctrl_down, int sensitivity, int snap_range); + std::vector OnRightClick(int ms, bool, int sensitivity, int snap_range); + void OnMarkerDrag(std::vector const& markers, int new_position, int snap_range); public: // Specific interface @@ -494,7 +494,7 @@ bool AudioTimingControllerDialogue::IsNearbyMarker(int ms, int sensitivity) cons return range.contains(active_markers[0]) || range.contains(active_markers[1]); } -AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int ms, int sensitivity, int snap_range) +std::vector AudioTimingControllerDialogue::OnLeftClick(int ms, bool ctrl_down, int sensitivity, int snap_range) { assert(sensitivity >= 0); @@ -511,32 +511,34 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int ms, int sensitivity // Clicked near the left marker: // Insta-move it and start dragging it SetMarker(left, SnapPosition(ms, snap_range)); - return left; + return std::vector(1, left); } if (dist_r < dist_l && dist_r <= sensitivity) { // Clicked near the right marker: // Only drag it. For insta-move, the user must right-click. - return right; + return std::vector(1, right); } // Clicked far from either marker: // Insta-set the left marker to the clicked position and return the right as the dragged one, // such that if the user does start dragging, he will create a new selection from scratch SetMarker(left, SnapPosition(ms, snap_range)); - return right; + return std::vector(1, right); } -AudioMarker * AudioTimingControllerDialogue::OnRightClick(int ms, int sensitivity, int snap_range) +std::vector AudioTimingControllerDialogue::OnRightClick(int ms, bool, int sensitivity, int snap_range) { AudioMarkerDialogueTiming *right = GetRightMarker(); SetMarker(right, SnapPosition(ms, snap_range)); - return right; + return std::vector(1, right); } -void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int new_position, int snap_range) +void AudioTimingControllerDialogue::OnMarkerDrag(std::vector const& markers, int new_position, int snap_range) { + assert(markers.size() == 1); + AudioMarker *marker = markers[0]; assert(marker == &active_markers[0] || marker == &active_markers[1]); SetMarker(static_cast(marker), SnapPosition(new_position, snap_range)); diff --git a/aegisub/src/audio_timing_karaoke.cpp b/aegisub/src/audio_timing_karaoke.cpp index 9d46245da..e73cb9f24 100644 --- a/aegisub/src/audio_timing_karaoke.cpp +++ b/aegisub/src/audio_timing_karaoke.cpp @@ -129,9 +129,9 @@ public: void Commit(); void Revert(); bool IsNearbyMarker(int ms, int sensitivity) const; - AudioMarker * OnLeftClick(int ms, int sensitivity, int); - AudioMarker * OnRightClick(int, int, int) { return 0; } - void OnMarkerDrag(AudioMarker *marker, int new_position, int); + std::vector OnLeftClick(int ms, bool, int sensitivity, int); + std::vector OnRightClick(int, bool, int, int) { return std::vector(); } + void OnMarkerDrag(std::vector const& marker, int new_position, int); AudioTimingControllerKaraoke(agi::Context *c, AssKaraoke *kara, agi::signal::Connection& file_changed); }; @@ -289,25 +289,26 @@ bool AudioTimingControllerKaraoke::IsNearbyMarker(int ms, int sensitivity) const return false; } -AudioMarker *AudioTimingControllerKaraoke::OnLeftClick(int ms, int sensitivity, int) { +std::vector AudioTimingControllerKaraoke::OnLeftClick(int ms, bool, int sensitivity, int) { TimeRange range(ms - sensitivity, ms + sensitivity); size_t syl = distance(markers.begin(), lower_bound(markers.begin(), markers.end(), ms)); if (syl < markers.size() && range.contains(markers[syl])) - return &markers[syl]; + return std::vector(1, &markers[syl]); if (syl > 0 && range.contains(markers[syl - 1])) - return &markers[syl - 1]; + return std::vector(1, &markers[syl - 1]); cur_syl = syl; AnnounceUpdatedPrimaryRange(); AnnounceUpdatedStyleRanges(); - return 0; + return std::vector(); } -void AudioTimingControllerKaraoke::OnMarkerDrag(AudioMarker *m, int new_position, int) { - KaraokeMarker *marker = static_cast(m); +void AudioTimingControllerKaraoke::OnMarkerDrag(std::vector const& m, int new_position, int) { + assert(m.size() == 1); + KaraokeMarker *marker = static_cast(m[0]); // No rearranging of syllables allowed new_position = mid( marker == &markers.front() ? start_marker.GetPosition() : (marker - 1)->GetPosition(),