Modify the TimingController interface to support dragging more than one marker at once. Updates #20.

Originally committed to SVN as r6460.
This commit is contained in:
Thomas Goyne 2012-02-10 00:04:13 +00:00
parent 51a3831794
commit 32c8cc0974
4 changed files with 48 additions and 42 deletions

View file

@ -464,7 +464,7 @@ public:
class AudioMarkerInteractionObject : public AudioDisplayInteractionObject {
// Object-pair being interacted with
AudioMarker *marker;
std::vector<AudioMarker*> 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<AudioMarker*> 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<AudioMarker*> 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

View file

@ -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<AudioMarker*> 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<AudioMarker*> 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<AudioMarker*> const& marker, int new_position, int snap_range) = 0;
/// @brief Destructor
virtual ~AudioTimingController() { }

View file

@ -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<AudioMarker*> OnLeftClick(int ms, bool ctrl_down, int sensitivity, int snap_range);
std::vector<AudioMarker*> OnRightClick(int ms, bool, int sensitivity, int snap_range);
void OnMarkerDrag(std::vector<AudioMarker*> 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<AudioMarker*> 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<AudioMarker*>(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<AudioMarker*>(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<AudioMarker*>(1, right);
}
AudioMarker * AudioTimingControllerDialogue::OnRightClick(int ms, int sensitivity, int snap_range)
std::vector<AudioMarker*> AudioTimingControllerDialogue::OnRightClick(int ms, bool, int sensitivity, int snap_range)
{
AudioMarkerDialogueTiming *right = GetRightMarker();
SetMarker(right, SnapPosition(ms, snap_range));
return right;
return std::vector<AudioMarker*>(1, right);
}
void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int new_position, int snap_range)
void AudioTimingControllerDialogue::OnMarkerDrag(std::vector<AudioMarker*> 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<AudioMarkerDialogueTiming*>(marker), SnapPosition(new_position, snap_range));

View file

@ -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<AudioMarker*> OnLeftClick(int ms, bool, int sensitivity, int);
std::vector<AudioMarker*> OnRightClick(int, bool, int, int) { return std::vector<AudioMarker*>(); }
void OnMarkerDrag(std::vector<AudioMarker*> 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<AudioMarker*> 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<AudioMarker*>(1, &markers[syl]);
if (syl > 0 && range.contains(markers[syl - 1]))
return &markers[syl - 1];
return std::vector<AudioMarker*>(1, &markers[syl - 1]);
cur_syl = syl;
AnnounceUpdatedPrimaryRange();
AnnounceUpdatedStyleRanges();
return 0;
return std::vector<AudioMarker*>();
}
void AudioTimingControllerKaraoke::OnMarkerDrag(AudioMarker *m, int new_position, int) {
KaraokeMarker *marker = static_cast<KaraokeMarker*>(m);
void AudioTimingControllerKaraoke::OnMarkerDrag(std::vector<AudioMarker*> const& m, int new_position, int) {
assert(m.size() == 1);
KaraokeMarker *marker = static_cast<KaraokeMarker*>(m[0]);
// No rearranging of syllables allowed
new_position = mid(
marker == &markers.front() ? start_marker.GetPosition() : (marker - 1)->GetPosition(),