From f098e2fac8e90e8961769d7e72585ba2795f6ef5 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 15 Jul 2011 04:05:22 +0000 Subject: [PATCH] Add an optional Validate method to commands Originally committed to SVN as r5459. --- aegisub/src/base_grid.cpp | 22 ++------ aegisub/src/base_grid.h | 2 +- aegisub/src/command/app.cpp | 12 ++++ aegisub/src/command/audio.cpp | 50 +++++++++++++---- aegisub/src/command/command.h | 11 ++++ aegisub/src/command/edit.cpp | 64 ++++++++++++++++++--- aegisub/src/command/grid.cpp | 14 ++++- aegisub/src/command/keyframe.cpp | 8 +++ aegisub/src/command/subtitle.cpp | 28 ++++++++-- aegisub/src/command/time.cpp | 41 +++++++++++--- aegisub/src/command/timecode.cpp | 8 +++ aegisub/src/command/video.cpp | 95 +++++++++++++++----------------- aegisub/src/frame_main.cpp | 38 ------------- aegisub/src/subs_grid.cpp | 3 +- 14 files changed, 252 insertions(+), 144 deletions(-) diff --git a/aegisub/src/base_grid.cpp b/aegisub/src/base_grid.cpp index d2278de66..ac91b1fb7 100644 --- a/aegisub/src/base_grid.cpp +++ b/aegisub/src/base_grid.cpp @@ -461,28 +461,14 @@ int BaseGrid::GetLastSelRow() const { /// @brief Gets all selected rows -/// @param[out] cont Is the selection contiguous, i.e. free from holes /// @return Array with indices of selected lines /// -wxArrayInt BaseGrid::GetSelection(bool *cont) const { - int last = -1; - bool continuous = true; - - std::set sel_row_indices; - +wxArrayInt BaseGrid::GetSelection() const { + wxArrayInt res(selection.size()); for (Selection::const_iterator it = selection.begin(); it != selection.end(); ++it) { - sel_row_indices.insert(GetDialogueIndex(*it)); + res.push_back(GetDialogueIndex(*it)); } - - // Iterating the int set yields a sorted list - wxArrayInt res; - for (std::set::iterator it = sel_row_indices.begin(); it != sel_row_indices.end(); ++it) { - res.Add(*it); - if (last != -1 && *it != last+1) continuous = false; - last = *it; - } - - if (cont) *cont = continuous; + std::sort(res.begin(), res.end()); return res; } diff --git a/aegisub/src/base_grid.h b/aegisub/src/base_grid.h index 1e97779d4..ccb645a3c 100644 --- a/aegisub/src/base_grid.h +++ b/aegisub/src/base_grid.h @@ -158,7 +158,7 @@ public: int GetFirstSelRow() const; int GetLastSelRow() const; void SelectVisible(); - wxArrayInt GetSelection(bool *continuous=NULL) const; + wxArrayInt GetSelection() const; void ClearMaps(); /// @brief Update the row <-> AssDialogue mappings diff --git a/aegisub/src/command/app.cpp b/aegisub/src/command/app.cpp index 52a2dbb46..1b9f443ed 100644 --- a/aegisub/src/command/app.cpp +++ b/aegisub/src/command/app.cpp @@ -85,6 +85,10 @@ struct app_display_audio_subs : public Command { void operator()(agi::Context *c) { wxGetApp().frame->SetDisplayMode(0,1); } + + bool Validate(const agi::Context *c) { + return c->audioController->IsAudioOpen(); + } }; @@ -98,6 +102,10 @@ struct app_display_full : public Command { void operator()(agi::Context *c) { wxGetApp().frame->SetDisplayMode(1,1); } + + bool Validate(const agi::Context *c) { + return c->audioController->IsAudioOpen() && c->videoController->IsLoaded() && !c->detachedVideo; + } }; @@ -124,6 +132,10 @@ struct app_display_video_subs : public Command { void operator()(agi::Context *c) { wxGetApp().frame->SetDisplayMode(1,0); } + + bool Validate(const agi::Context *c) { + return c->videoController->IsLoaded() && !c->detachedVideo; + } }; diff --git a/aegisub/src/command/audio.cpp b/aegisub/src/command/audio.cpp index 675ac7511..2d595adf5 100644 --- a/aegisub/src/command/audio.cpp +++ b/aegisub/src/command/audio.cpp @@ -49,18 +49,25 @@ #include "../audio_timing.h" #include "../compat.h" #include "../include/aegisub/context.h" -#include "../selection_controller.h" #include "../main.h" - -typedef SelectionController::Selection Selection; +#include "../selection_controller.h" +#include "../video_context.h" namespace { + typedef SelectionController::Selection Selection; using cmd::Command; + + struct validate_audio_open : public Command { + bool Validate(const agi::Context *c) { + return c->audioController->IsAudioOpen(); + } + }; + /// @defgroup cmd-audio Audio commands. /// @{ /// Closes the currently open audio file. -struct audio_close : public Command { +struct audio_close : public validate_audio_open { CMD_NAME("audio/close") STR_MENU("&Close Audio") STR_DISP("Close Audio") @@ -126,6 +133,10 @@ struct audio_open_video : public Command { STR_DISP("Open Audio from Video") STR_HELP("Opens the audio from the current video file.") + bool Validate(const agi::Context *c) { + return c->videoController->IsLoaded(); + } + void operator()(agi::Context *c) { c->audioController->OpenAudio(_T("audio-video:cache")); } @@ -176,11 +187,12 @@ struct audio_save_clip : public Command { }; /// Play the current audio selection -struct audio_play_selection : public Command { +struct audio_play_selection : public validate_audio_open { CMD_NAME("audio/play/selection") STR_MENU("Play audio selection") STR_DISP("Play audio selection") STR_HELP("Play selection") + void operator()(agi::Context *c) { c->audioController->PlayPrimaryRange(); } @@ -192,17 +204,23 @@ struct audio_stop : public Command { STR_MENU("Stop playing") STR_DISP("Stop playing") STR_HELP("Stop") + + bool Validate(const agi::Context *c) { + return c->audioController->IsPlaying(); + } + void operator()(agi::Context *c) { c->audioController->Stop(); } }; /// Play 500 ms before the selected audio range -struct audio_play_before : public Command { +struct audio_play_before : public validate_audio_open { CMD_NAME("audio/play/selection/before") STR_MENU("Play 500 ms before selection") STR_DISP("Play 500 ms before selection") STR_HELP("Play 500 ms before selection") + void operator()(agi::Context *c) { SampleRange times(c->audioController->GetPrimaryPlaybackRange()); c->audioController->PlayRange(SampleRange( @@ -212,11 +230,12 @@ struct audio_play_before : public Command { }; /// Play 500 ms after the selected audio range -struct audio_play_after : public Command { +struct audio_play_after : public validate_audio_open { CMD_NAME("audio/play/selection/after") STR_MENU("Play 500 ms after selection") STR_DISP("Play 500 ms after selection") STR_HELP("Play 500 ms after selection") + void operator()(agi::Context *c) { SampleRange times(c->audioController->GetPrimaryPlaybackRange()); c->audioController->PlayRange(SampleRange( @@ -226,11 +245,12 @@ struct audio_play_after : public Command { }; /// Play from the beginning of the audio range to the end of the file -struct audio_play_end : public Command { +struct audio_play_end : public validate_audio_open { CMD_NAME("audio/play/selection/end") STR_MENU("Play last 500 ms of selection") STR_DISP("Play last 500 ms of selection") STR_HELP("Play last 500 ms of selection") + void operator()(agi::Context *c) { SampleRange times(c->audioController->GetPrimaryPlaybackRange()); c->audioController->PlayRange(SampleRange( @@ -242,11 +262,12 @@ struct audio_play_end : public Command { }; /// Play the first 500 ms of the audio range -struct audio_play_begin : public Command { +struct audio_play_begin : public validate_audio_open { CMD_NAME("audio/play/selection/begin") STR_MENU("Play first 500 ms of selection") STR_DISP("Play first 500 ms of selection") STR_HELP("Play first 500 ms of selection") + void operator()(agi::Context *c) { SampleRange times(c->audioController->GetPrimaryPlaybackRange()); c->audioController->PlayRange(SampleRange( @@ -258,11 +279,12 @@ struct audio_play_begin : public Command { }; /// Play the last 500 ms of the audio range -struct audio_play_to_end : public Command { +struct audio_play_to_end : public validate_audio_open { CMD_NAME("audio/play/to_end") STR_MENU("Play from selection start to end of file") STR_DISP("Play from selection start to end of file") STR_HELP("Play from selection start to end of file") + void operator()(agi::Context *c) { c->audioController->PlayToEnd(c->audioController->GetPrimaryPlaybackRange().begin()); } @@ -275,6 +297,7 @@ struct audio_commit : public Command { STR_MENU("Commit") STR_DISP("Commit") STR_HELP("Commit") + void operator()(agi::Context *c) { c->audioController->GetTimingController()->Commit(); } @@ -286,6 +309,7 @@ struct audio_go_to : public Command { STR_MENU("Go to selection") STR_DISP("Go to selection") STR_HELP("Go to selection") + void operator()(agi::Context *c) { //if (c->audioController->GetTimingController()) //audioDisplay->ScrollSampleRangeInView(c->audioController->GetTimingController()->GetIdealVisibleSampleRange()); @@ -302,6 +326,7 @@ struct audio_autoscroll : public Command { STR_MENU("Auto scrolls audio display to selected line") STR_DISP("Auto scrolls audio display to selected line") STR_HELP("Auto scrolls audio display to selected line") + void operator()(agi::Context *c) { toggle("Audio/Auto/Scroll"); } @@ -313,6 +338,7 @@ struct audio_autocommit : public Command { STR_MENU("Automatically commit all changes") STR_DISP("Automatically commit all changes") STR_HELP("Automatically commit all changes") + void operator()(agi::Context *c) { toggle("Audio/Auto/Commit"); } @@ -324,6 +350,7 @@ struct audio_autonext : public Command { STR_MENU("Auto goes to next line on commit") STR_DISP("Auto goes to next line on commit") STR_HELP("Auto goes to next line on commit") + void operator()(agi::Context *c) { toggle("Audio/Next Line on Commit"); } @@ -335,6 +362,7 @@ struct audio_vertical_link : public Command { STR_MENU("Link vertical zoom and volume sliders") STR_DISP("Link vertical zoom and volume sliders") STR_HELP("Link vertical zoom and volume sliders") + void operator()(agi::Context *c) { toggle("Audio/Link"); } @@ -353,8 +381,10 @@ namespace cmd { reg(new audio_commit); reg(new audio_go_to); reg(new audio_open); +#if _DEBUG reg(new audio_open_blank); reg(new audio_open_noise); +#endif reg(new audio_open_video); reg(new audio_play_after); reg(new audio_play_before); diff --git a/aegisub/src/command/command.h b/aegisub/src/command/command.h index 5cfdd8da2..e82adb5da 100644 --- a/aegisub/src/command/command.h +++ b/aegisub/src/command/command.h @@ -66,6 +66,17 @@ namespace cmd { /// Command function virtual void operator()(agi::Context *c)=0; + /// Check whether or not it makes sense to call this command at this time + /// @param c Project context + /// + /// This function should be very fast, as it is called whenever a menu + /// containing this command is opened and is called periodically for + /// any commands used in a toolbar + /// + /// Note that it is still legal to call commands when this returns + /// false. In this situation, commands should do nothing. + virtual bool Validate(const agi::Context *c) { return true; } + /// Destructor virtual ~Command() { }; }; diff --git a/aegisub/src/command/edit.cpp b/aegisub/src/command/edit.cpp index bc668e699..13b28f098 100644 --- a/aegisub/src/command/edit.cpp +++ b/aegisub/src/command/edit.cpp @@ -58,8 +58,20 @@ namespace { /// @defgroup cmd-edit Editing commands. /// @{ +struct validate_sel_nonempty : public Command { + bool Validate(const agi::Context *c) { + return c->selectionController->GetSelectedSet().size() > 0; + } +}; + +struct validate_sel_multiple : public Command { + bool Validate(const agi::Context *c) { + return c->selectionController->GetSelectedSet().size() > 1; + } +}; + /// Copy subtitles. -struct edit_line_copy : public Command { +struct edit_line_copy : public validate_sel_nonempty { CMD_NAME("edit/line/copy") STR_MENU("Copy Lines") STR_DISP("Copy Lines") @@ -76,7 +88,7 @@ struct edit_line_copy : public Command { /// Cut subtitles. -struct edit_line_cut: public Command { +struct edit_line_cut: public validate_sel_nonempty { CMD_NAME("edit/line/cut") STR_MENU("Cut Lines") STR_DISP("Cut Lines") @@ -93,7 +105,7 @@ struct edit_line_cut: public Command { /// Delete currently selected lines. -struct edit_line_delete : public Command { +struct edit_line_delete : public validate_sel_nonempty { CMD_NAME("edit/line/delete") STR_MENU("Delete Lines") STR_DISP("Delete Lines") @@ -106,7 +118,7 @@ struct edit_line_delete : public Command { /// Duplicate the selected lines. -struct edit_line_duplicate : public Command { +struct edit_line_duplicate : public validate_sel_nonempty { CMD_NAME("edit/line/duplicate") STR_MENU("&Duplicate Lines") STR_DISP("Duplicate Lines") @@ -126,6 +138,10 @@ struct edit_line_duplicate_shift : public Command { STR_DISP("Duplicate and Shift by 1 Frame") STR_HELP("Duplicate lines and shift by one frame.") + bool Validate(const agi::Context *c) { + return !c->selectionController->GetSelectedSet().empty() && c->videoController->IsLoaded(); + } + void operator()(agi::Context *c) { wxArrayInt sels = c->subsGrid->GetSelection(); c->subsGrid->DuplicateLines(sels.front(), sels.back(), true); @@ -174,7 +190,7 @@ static void combine_concat(AssDialogue *first, AssDialogue *second) { static void combine_drop(AssDialogue *, AssDialogue *) { } /// Joins selected lines in a single one, as karaoke. -struct edit_line_join_as_karaoke : public Command { +struct edit_line_join_as_karaoke : public validate_sel_multiple { CMD_NAME("edit/line/join/as_karaoke") STR_MENU("As &Karaoke") STR_DISP("As Karaoke") @@ -187,7 +203,7 @@ struct edit_line_join_as_karaoke : public Command { /// Joins selected lines in a single one, concatenating text together. -struct edit_line_join_concatenate : public Command { +struct edit_line_join_concatenate : public validate_sel_multiple { CMD_NAME("edit/line/join/concatenate") STR_MENU("&Concatenate") STR_DISP("Concatenate") @@ -200,7 +216,7 @@ struct edit_line_join_concatenate : public Command { /// Joins selected lines in a single one, keeping text of first and discarding remaining. -struct edit_line_join_keep_first : public Command { +struct edit_line_join_keep_first : public validate_sel_multiple { CMD_NAME("edit/line/join/keep_first") STR_MENU("Keep &First") STR_DISP("Keep First") @@ -219,6 +235,15 @@ struct edit_line_paste : public Command { STR_DISP("Paste Lines") STR_HELP("Paste subtitles.") + bool Validate(const agi::Context *c) { + if (wxTheClipboard->Open()) { + bool can_paste = wxTheClipboard->IsSupported(wxDF_TEXT); + wxTheClipboard->Close(); + return can_paste; + } + return false; + } + void operator()(agi::Context *c) { if (c->parent->FindFocus() == c->editBox->TextEdit) { c->editBox->TextEdit->Paste(); @@ -236,6 +261,15 @@ struct edit_line_paste_over : public Command { STR_DISP("Paste Lines Over") STR_HELP("Paste subtitles over others.") + bool Validate(const agi::Context *c) { + if (wxTheClipboard->Open()) { + bool can_paste = wxTheClipboard->IsSupported(wxDF_TEXT); + wxTheClipboard->Close(); + return can_paste && c->selectionController->GetSelectedSet().size(); + } + return false; + } + void operator()(agi::Context *c) { c->subsGrid->PasteLines(c->subsGrid->GetFirstSelRow(),true); } @@ -243,7 +277,7 @@ struct edit_line_paste_over : public Command { /// Recombine subtitles when they have been split and merged. -struct edit_line_recombine : public Command { +struct edit_line_recombine : public validate_sel_multiple { CMD_NAME("edit/line/recombine") STR_MENU("Recombine Lines") STR_DISP("Recombine Lines") @@ -256,7 +290,7 @@ struct edit_line_recombine : public Command { /// Uses karaoke timing to split line into multiple smaller lines. -struct edit_line_split_by_karaoke : public Command { +struct edit_line_split_by_karaoke : public validate_sel_nonempty { CMD_NAME("edit/line/split/by_karaoke") STR_MENU("Split Lines (by karaoke)") STR_DISP("Split Lines (by karaoke)") @@ -284,6 +318,10 @@ struct edit_line_swap : public Command { STR_DISP("Swap Lines") STR_HELP("Swaps the two selected lines.") + bool Validate(const agi::Context *c) { + return c->selectionController->GetSelectedSet().size() == 2; + } + void operator()(agi::Context *c) { SelectionController::Selection sel = c->selectionController->GetSelectedSet(); if (sel.size() == 2) { @@ -305,6 +343,10 @@ struct edit_redo : public Command { STR_DISP("Redo") STR_HELP("Redoes last action.") + bool Validate(const agi::Context *c) { + return !c->ass->IsRedoStackEmpty(); + } + void operator()(agi::Context *c) { c->videoController->Stop(); c->ass->Redo(); @@ -333,6 +375,10 @@ struct edit_undo : public Command { STR_DISP("Undo") STR_HELP("Undoes last action.") + bool Validate(const agi::Context *c) { + return !c->ass->IsUndoStackEmpty(); + } + void operator()(agi::Context *c) { c->videoController->Stop(); c->ass->Undo(); diff --git a/aegisub/src/command/grid.cpp b/aegisub/src/command/grid.cpp index b12c2d63a..32c01ff88 100644 --- a/aegisub/src/command/grid.cpp +++ b/aegisub/src/command/grid.cpp @@ -167,12 +167,16 @@ struct grid_swap_up : public Command { STR_DISP("Move line up") STR_HELP("Move the selected line up one row") + bool Validate(agi::Context *c) { + return c->selectionController->GetActiveLine() != 0; + } + void operator()(agi::Context *c) { if (AssDialogue *line = c->selectionController->GetActiveLine()) { if (move_one(c->ass->Line.rbegin(), c->ass->Line.rend(), line)) - /// todo Maybe add COMMIT_ORDER, as the grid is the only thing - /// that needs to care about this - /// Probably not worth it + /// @todo Maybe add COMMIT_ORDER, as the grid is the only thing + /// that needs to care about this + /// Probably not worth it c->ass->Commit(_("swap lines"), AssFile::COMMIT_FULL); } } @@ -185,6 +189,10 @@ struct grid_swap_down : public Command { STR_DISP("Move line down") STR_HELP("Move the selected line down one row") + bool Validate(agi::Context *c) { + return c->selectionController->GetActiveLine() != 0; + } + void operator()(agi::Context *c) { if (AssDialogue *line = c->selectionController->GetActiveLine()) { if (move_one(c->ass->Line.begin(), c->ass->Line.end(), line)) diff --git a/aegisub/src/command/keyframe.cpp b/aegisub/src/command/keyframe.cpp index af1455168..041faebbd 100644 --- a/aegisub/src/command/keyframe.cpp +++ b/aegisub/src/command/keyframe.cpp @@ -62,6 +62,10 @@ struct keyframe_close : public Command { STR_DISP("Close Keyframes") STR_HELP("Closes the currently open keyframes list.") + bool Validate(const agi::Context *c) { + return c->videoController->OverKeyFramesLoaded(); + } + void operator()(agi::Context *c) { c->videoController->CloseKeyframes(); } @@ -99,6 +103,10 @@ struct keyframe_save : public Command { STR_DISP("Save Keyframes") STR_HELP("Saves the current keyframe list.") + bool Validate(const agi::Context *c) { + return c->videoController->KeyFramesLoaded(); + } + void operator()(agi::Context *c) { wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString()); wxString filename = wxFileSelector(_T("Select the Keyframes file to open"),path,_T(""),_T("*.key.txt"),_T("Text files (*.txt)|*.txt"),wxFD_OVERWRITE_PROMPT | wxFD_SAVE); diff --git a/aegisub/src/command/subtitle.cpp b/aegisub/src/command/subtitle.cpp index 10f0cd421..30df21e91 100644 --- a/aegisub/src/command/subtitle.cpp +++ b/aegisub/src/command/subtitle.cpp @@ -67,6 +67,18 @@ namespace { /// @defgroup cmd-subtitle Subtitle commands. /// @{ +struct validate_nonempty_selection : public Command { + bool Validate(const agi::Context *c) { + return !c->selectionController->GetSelectedSet().empty(); + } +}; + +struct validate_nonempty_selection_video_loaded : public Command { + bool Validate(const agi::Context *c) { + return c->videoController->IsLoaded() && !c->selectionController->GetSelectedSet().empty(); + } +}; + /// Open the attachment list. struct subtitle_attachment : public Command { CMD_NAME("subtitle/attachment") @@ -127,7 +139,7 @@ static void insert_subtitle_at_video(agi::Context *c, bool after) { } /// Inserts a line after current. -struct subtitle_insert_after : public Command { +struct subtitle_insert_after : public validate_nonempty_selection { CMD_NAME("subtitle/insert/after") STR_MENU("&After Current") STR_DISP("After Current") @@ -161,7 +173,7 @@ struct subtitle_insert_after : public Command { }; /// Inserts a line after current, starting at video time. -struct subtitle_insert_after_videotime : public Command { +struct subtitle_insert_after_videotime : public validate_nonempty_selection_video_loaded { CMD_NAME("subtitle/insert/after/videotime") STR_MENU("After Current, at Video Time") STR_DISP("After Current, at Video Time") @@ -174,7 +186,7 @@ struct subtitle_insert_after_videotime : public Command { /// Inserts a line before current. -struct subtitle_insert_before : public Command { +struct subtitle_insert_before : public validate_nonempty_selection { CMD_NAME("subtitle/insert/before") STR_MENU("&Before Current") STR_DISP("Before Current") @@ -211,7 +223,7 @@ struct subtitle_insert_before : public Command { /// Inserts a line before current, starting at video time. -struct subtitle_insert_before_videotime : public Command { +struct subtitle_insert_before_videotime : public validate_nonempty_selection_video_loaded { CMD_NAME("subtitle/insert/before/videotime") STR_MENU("Before Current, at Video Time") STR_DISP("Before Current, at Video Time") @@ -286,6 +298,10 @@ struct subtitle_open_video : public Command { void operator()(agi::Context *c) { wxGetApp().frame->LoadSubtitles(c->videoController->videoName, "binary"); } + + bool Validate(const agi::Context *c) { + return c->videoController->IsLoaded() && c->videoController->HasSubtitles(); + } }; @@ -377,6 +393,10 @@ struct subtitle_select_visible : public Command { c->videoController->Stop(); c->subsGrid->SelectVisible(); } + + bool Validate(agi::Context *c) { + return c->videoController->IsLoaded(); + } }; diff --git a/aegisub/src/command/time.cpp b/aegisub/src/command/time.cpp index 9b5f4a19d..d6b61ba07 100644 --- a/aegisub/src/command/time.cpp +++ b/aegisub/src/command/time.cpp @@ -57,11 +57,38 @@ namespace { using cmd::Command; + + struct validate_video_loaded : public Command { + bool Validate(const agi::Context *c) { + return c->videoController->IsLoaded(); + } + }; + + struct validate_adjoinable : public Command { + bool Validate(const agi::Context *c) { + SelectionController::Selection sel = c->selectionController->GetSelectedSet(); + if (sel.size() < 2) return false; + + bool found = false; + for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it) { + AssDialogue *diag = dynamic_cast(*it); + if (!diag) continue; + if (sel.count(diag)) { + found = true; + } + else if (found) { + return false; + } + } + return true; + } + }; + /// @defgroup cmd-time Time manipulation commands. /// @{ /// Changes times of subs so end times begin on next's start time. -struct time_continuous_end : public Command { +struct time_continuous_end : public validate_adjoinable { CMD_NAME("time/continuous/end") STR_MENU("Change &End") STR_DISP("Change End") @@ -75,7 +102,7 @@ struct time_continuous_end : public Command { /// Changes times of subs so start times begin on previous's end time. -struct time_continuous_start : public Command { +struct time_continuous_start : public validate_adjoinable { CMD_NAME("time/continuous/start") STR_MENU("Change &Start") STR_DISP("Change Start") @@ -90,7 +117,7 @@ struct time_continuous_start : public Command { /// Shift selection so first selected line starts at current frame. -struct time_frame_current : public Command { +struct time_frame_current : public validate_video_loaded { CMD_NAME("time/frame/current") STR_MENU("Shift to Current Frame") STR_DISP("Shift to Current Frame") @@ -139,7 +166,7 @@ struct time_shift : public Command { /// Set end of selected subtitles to current video frame. -struct time_snap_end_video : public Command { +struct time_snap_end_video : public validate_video_loaded { CMD_NAME("time/snap/end_video") STR_MENU("Snap End to Video") STR_DISP("Snap End to Video") @@ -152,7 +179,7 @@ struct time_snap_end_video : public Command { /// Shift selected subtitles so first selected starts at this frame. -struct time_snap_frame : public Command { +struct time_snap_frame : public validate_video_loaded { CMD_NAME("time/snap/frame") STR_MENU("Shift Subtitles to Frame") STR_DISP("Shift Subtitles to Frame") @@ -181,7 +208,7 @@ struct time_snap_frame : public Command { /// Set start and end of subtitles to the keyframes around current video frame. -struct time_snap_scene : public Command { +struct time_snap_scene : public validate_video_loaded { CMD_NAME("time/snap/scene") STR_MENU("Snap to Scene") STR_DISP("Snap to Scene") @@ -262,7 +289,7 @@ struct time_add_lead_out : public Command { /// Set start of selected subtitles to current video frame. -struct time_snap_start_video : public Command { +struct time_snap_start_video : public validate_video_loaded { CMD_NAME("time/snap/start_video") STR_MENU("Snap Start to Video") STR_DISP("Snap Start to Video") diff --git a/aegisub/src/command/timecode.cpp b/aegisub/src/command/timecode.cpp index f8b4e00f3..f0f1dd375 100644 --- a/aegisub/src/command/timecode.cpp +++ b/aegisub/src/command/timecode.cpp @@ -62,6 +62,10 @@ struct timecode_close : public Command { STR_DISP("Close Timecodes File") STR_HELP("Closes the currently open timecodes file.") + bool Validate(const agi::Context *c) { + return c->videoController->OverTimecodesLoaded(); + } + void operator()(agi::Context *c) { c->videoController->CloseTimecodes(); } @@ -94,6 +98,10 @@ struct timecode_save : public Command { STR_DISP("Save Timecodes File") STR_HELP("Saves a VFR timecodes v2 file.") + bool Validate(const agi::Context *c) { + return c->videoController->TimecodesLoaded(); + } + void operator()(agi::Context *c) { wxString path = lagi_wxString(OPT_GET("Path/Last/Timecodes")->GetString()); wxString str = wxString(_("All Supported Types")) + _T("(*.txt)|*.txt|") + _("All Files") + _T(" (*.*)|*.*"); diff --git a/aegisub/src/command/video.cpp b/aegisub/src/command/video.cpp index 5d4f0b4e9..6f7b69b6a 100644 --- a/aegisub/src/command/video.cpp +++ b/aegisub/src/command/video.cpp @@ -63,24 +63,34 @@ namespace { /// @defgroup cmd-video Video commands. /// @{ +struct validator_video_loaded : public Command { + bool Validate(const agi::Context *c) { + return c->videoController->IsLoaded(); + } +}; + +struct validator_video_attached : public Command { + bool Validate(const agi::Context *c) { + return c->videoController->IsLoaded() && !c->detachedVideo; + } +}; /// Forces video to 2.35 aspect ratio. -struct video_aspect_cinematic : public Command { +struct video_aspect_cinematic : public validator_video_attached { CMD_NAME("video/aspect/cinematic") STR_MENU("&Cinematic (2.35)") STR_DISP("Cinematic (235)") STR_HELP("Forces video to 2.35 aspect ratio.") void operator()(agi::Context *c) { - c->videoController->Stop(); - c->videoController->SetAspectRatio(3); - wxGetApp().frame->SetDisplayMode(1,-1); + c->videoController->Stop(); + c->videoController->SetAspectRatio(3); + wxGetApp().frame->SetDisplayMode(1,-1); } }; - /// Forces video to a custom aspect ratio. -struct video_aspect_custom : public Command { +struct video_aspect_custom : public validator_video_attached { CMD_NAME("video/aspect/custom") STR_MENU("Custom..") STR_DISP("Custom") @@ -134,10 +144,8 @@ struct video_aspect_custom : public Command { } }; - - /// Leave video on original aspect ratio. -struct video_aspect_default : public Command { +struct video_aspect_default : public validator_video_attached { CMD_NAME("video/aspect/default") STR_MENU("&Default") STR_DISP("Default") @@ -150,10 +158,8 @@ struct video_aspect_default : public Command { } }; - - /// Forces video to 4:3 aspect ratio. -struct video_aspect_full : public Command { +struct video_aspect_full : public validator_video_attached { CMD_NAME("video/aspect/full") STR_MENU("&Fullscreen (4:3)") STR_DISP("Fullscreen (4:3)") @@ -166,9 +172,8 @@ struct video_aspect_full : public Command { } }; - /// Forces video to 16:9 aspect ratio. -struct video_aspect_wide : public Command { +struct video_aspect_wide : public validator_video_attached { CMD_NAME("video/aspect/wide") STR_MENU("&Widescreen (16:9)") STR_DISP("Widescreen (16:9)") @@ -181,9 +186,8 @@ struct video_aspect_wide : public Command { } }; - /// Closes the currently open video file. -struct video_close : public Command { +struct video_close : public validator_video_loaded { CMD_NAME("video/close") STR_MENU("&Close Video") STR_DISP("Close Video") @@ -194,10 +198,8 @@ struct video_close : public Command { } }; - - /// Detach video, displaying it in a separate Window. -struct video_detach : public Command { +struct video_detach : public validator_video_loaded { CMD_NAME("video/detach") STR_MENU("Detach Video") STR_DISP("Detach Video") @@ -208,9 +210,8 @@ struct video_detach : public Command { } }; - /// Shows video details. -struct video_details : public Command { +struct video_details : public validator_video_loaded { CMD_NAME("video/details") STR_MENU("Show Video Details..") STR_DISP("Show Video Details") @@ -222,9 +223,8 @@ struct video_details : public Command { } }; - /// -struct video_focus_seek : public Command { +struct video_focus_seek : public validator_video_loaded { CMD_NAME("video/focus_seek") STR_MENU("XXX: no idea") STR_DISP("XXX: no idea") @@ -242,9 +242,8 @@ struct video_focus_seek : public Command { } }; - /// Seek to the next frame. -struct video_frame_next : public Command { +struct video_frame_next : public validator_video_loaded { CMD_NAME("video/frame/next") STR_MENU("Next Frame") STR_DISP("Next Frame") @@ -256,7 +255,7 @@ struct video_frame_next : public Command { }; /// Seek to the next subtitle boundary. -struct video_frame_next_boundary : public Command { +struct video_frame_next_boundary : public validator_video_loaded { CMD_NAME("video/frame/next/boundary") STR_MENU("Next Boundary") STR_DISP("Next Boundary") @@ -286,7 +285,7 @@ struct video_frame_next_boundary : public Command { }; /// Seek to the next keyframe. -struct video_frame_next_keyframe : public Command { +struct video_frame_next_keyframe : public validator_video_loaded { CMD_NAME("video/frame/next/keyframe") STR_MENU("Next Keyframe") STR_DISP("Next Keyframe") @@ -302,7 +301,7 @@ struct video_frame_next_keyframe : public Command { }; /// Fast jump forward -struct video_frame_next_large : public Command { +struct video_frame_next_large : public validator_video_loaded { CMD_NAME("video/frame/next/large") STR_MENU("Fast jump forward") STR_DISP("Fast jump forward") @@ -316,7 +315,7 @@ struct video_frame_next_large : public Command { }; /// Seek to the previous frame. -struct video_frame_prev : public Command { +struct video_frame_prev : public validator_video_loaded { CMD_NAME("video/frame/prev") STR_MENU("Previous Frame") STR_DISP("Previous Frame") @@ -328,7 +327,7 @@ struct video_frame_prev : public Command { }; /// Seek to the previous subtitle boundary. -struct video_frame_prev_boundary : public Command { +struct video_frame_prev_boundary : public validator_video_loaded { CMD_NAME("video/frame/prev/boundary") STR_MENU("Previous Boundary") STR_DISP("Previous Boundary") @@ -358,7 +357,7 @@ struct video_frame_prev_boundary : public Command { }; /// Seek to the previous keyframe. -struct video_frame_prev_keyframe : public Command { +struct video_frame_prev_keyframe : public validator_video_loaded { CMD_NAME("video/frame/prev/keyframe") STR_MENU("Previous Keyframe") STR_DISP("Previous Keyframe") @@ -377,7 +376,7 @@ struct video_frame_prev_keyframe : public Command { }; /// Fast jump backwards -struct video_frame_prev_large : public Command { +struct video_frame_prev_large : public validator_video_loaded { CMD_NAME("video/frame/prev/large") STR_MENU("Fast jump backwards") STR_DISP("Fast jump backwards") @@ -391,7 +390,7 @@ struct video_frame_prev_large : public Command { }; /// Jump to frame or time. -struct video_jump : public Command { +struct video_jump : public validator_video_loaded { CMD_NAME("video/jump") STR_MENU("&Jump to..") STR_DISP("Jump to") @@ -406,9 +405,8 @@ struct video_jump : public Command { } }; - /// Jumps the video to the end frame of current subtitle. -struct video_jump_end : public Command { +struct video_jump_end : public validator_video_loaded { CMD_NAME("video/jump/end") STR_MENU("Jump Video to End") STR_DISP("Jump Video to End") @@ -419,9 +417,8 @@ struct video_jump_end : public Command { } }; - /// Jumps the video to the start frame of current subtitle. -struct video_jump_start : public Command { +struct video_jump_start : public validator_video_loaded { CMD_NAME("video/jump/start") STR_MENU("Jump Video to Start") STR_DISP("Jump Video to Start") @@ -432,7 +429,6 @@ struct video_jump_start : public Command { } }; - /// Opens a video file. struct video_open : public Command { CMD_NAME("video/open") @@ -452,7 +448,6 @@ struct video_open : public Command { } }; - /// Opens a video clip with solid colour. struct video_open_dummy : public Command { CMD_NAME("video/open/dummy") @@ -481,7 +476,7 @@ struct video_opt_autoscroll : public Command { }; /// Play video. -struct video_play : public Command { +struct video_play : public validator_video_loaded { CMD_NAME("video/play") STR_MENU("Play") STR_DISP("Play") @@ -493,7 +488,7 @@ struct video_play : public Command { }; /// Play video for the active line. -struct video_play_line : public Command { +struct video_play_line : public validator_video_loaded { CMD_NAME("video/play/line") STR_MENU("Play line") STR_DISP("Play line") @@ -505,7 +500,7 @@ struct video_play_line : public Command { }; /// Show a mask over the video. -struct video_show_overscan : public Command { +struct video_show_overscan : public validator_video_loaded { CMD_NAME("video/show_overscan") STR_MENU("Show Overscan Mask") STR_DISP("Show Overscan Mask") @@ -517,9 +512,8 @@ struct video_show_overscan : public Command { } }; - /// Set zoom to 100%. -class video_zoom_100: public Command { +class video_zoom_100: public validator_video_attached { public: CMD_NAME("video/zoom/100") STR_MENU("&100%") @@ -533,7 +527,7 @@ public: }; /// Stop video playback -class video_stop: public Command { +class video_stop: public validator_video_loaded { public: CMD_NAME("video/stop") STR_MENU("Stop video") @@ -546,7 +540,7 @@ public: }; /// Set zoom to 200%. -class video_zoom_200: public Command { +class video_zoom_200: public validator_video_attached { public: CMD_NAME("video/zoom/200") STR_MENU("&200%") @@ -559,9 +553,8 @@ public: } }; - /// Set zoom to 50%. -class video_zoom_50: public Command { +class video_zoom_50: public validator_video_attached { public: CMD_NAME("video/zoom/50") STR_MENU("&50%") @@ -574,9 +567,8 @@ public: } }; - /// Zoom video in. -struct video_zoom_in : public Command { +struct video_zoom_in : public validator_video_attached { CMD_NAME("video/zoom/in") STR_MENU("Zoom In") STR_DISP("Zoom In") @@ -587,9 +579,8 @@ struct video_zoom_in : public Command { } }; - /// Zoom video out. -struct video_zoom_out : public Command { +struct video_zoom_out : public validator_video_attached { CMD_NAME("video/zoom/out") STR_MENU("Zoom Out") STR_DISP("Zoom Out") diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp index 4ae3f817d..d1bafc9d9 100644 --- a/aegisub/src/frame_main.cpp +++ b/aegisub/src/frame_main.cpp @@ -764,15 +764,6 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) { // View menu else if (curMenu == menu::menu->GetMenu("main/view")) { - // Flags - bool aud = context->audioController->IsAudioOpen(); - bool vid = context->videoController->IsLoaded() && !context->detachedVideo; - - // Set states - MenuBar->Enable(cmd::id("app/display/audio_subs"),aud); - MenuBar->Enable(cmd::id("app/display/video_subs"),vid); - MenuBar->Enable(cmd::id("app/display/full"),aud && vid); - // Select option if (!showVideo && !showAudio) MenuBar->Check(cmd::id("app/display/subs"),true); else if (showVideo && !showAudio) MenuBar->Check(cmd::id("app/display/video_subs"),true); @@ -783,37 +774,14 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) { if (sub_grid == 1) MenuBar->Check(cmd::id("grid/tags/show"), true); if (sub_grid == 2) MenuBar->Check(cmd::id("grid/tags/simplify"), true); if (sub_grid == 3) MenuBar->Check(cmd::id("grid/tags/hide"), true); - - } - // Video menu else if (curMenu == menu::menu->GetMenu("main/video")) { - bool state = context->videoController->IsLoaded(); - bool attached = state && !context->detachedVideo; - // Set states - MenuBar->Enable(cmd::id("video/jump"),state); - MenuBar->Enable(cmd::id("video/jump/start"),state); - MenuBar->Enable(cmd::id("video/jump/end"),state); - MenuBar->Enable(cmd::id("main/video/set zoom"), attached); - MenuBar->Enable(cmd::id("video/zoom/50"),attached); - MenuBar->Enable(cmd::id("video/zoom/100"),attached); - MenuBar->Enable(cmd::id("video/zoom/200"),attached); - MenuBar->Enable(cmd::id("video/close"),state); - MenuBar->Enable(cmd::id("main/video/override ar"),attached); - MenuBar->Enable(cmd::id("video/aspect/default"),attached); - MenuBar->Enable(cmd::id("video/aspect/full"),attached); - MenuBar->Enable(cmd::id("video/aspect/wide"),attached); - MenuBar->Enable(cmd::id("video/aspect/cinematic"),attached); - MenuBar->Enable(cmd::id("video/aspect/custom"),attached); - MenuBar->Enable(cmd::id("video/detach"),state); MenuBar->Enable(cmd::id("timecode/save"),context->videoController->TimecodesLoaded()); MenuBar->Enable(cmd::id("timecode/close"),context->videoController->OverTimecodesLoaded()); MenuBar->Enable(cmd::id("keyframe/close"),context->videoController->OverKeyFramesLoaded()); MenuBar->Enable(cmd::id("keyframe/save"),context->videoController->KeyFramesLoaded()); - MenuBar->Enable(cmd::id("video/details"),state); - MenuBar->Enable(cmd::id("video/show_overscan"),state); // Set AR radio int arType = context->videoController->GetAspectRatioType(); @@ -861,13 +829,7 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) { // Entries state = count > 0; - MenuBar->Enable(cmd::id("subtitle/insert/before"),state); - MenuBar->Enable(cmd::id("subtitle/insert/after"),state); - MenuBar->Enable(cmd::id("edit/line/split/by_karaoke"),state); - MenuBar->Enable(cmd::id("edit/line/delete"),state); state2 = count > 0 && context->videoController->IsLoaded(); - MenuBar->Enable(cmd::id("subtitle/insert/before/videotime"),state2); - MenuBar->Enable(cmd::id("subtitle/insert/after/videotime"),state2); MenuBar->Enable(cmd::id("main/subtitle/insert lines"),state); state = count > 0 && continuous; MenuBar->Enable(cmd::id("edit/line/duplicate"),state); diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index f039b1876..9f3e536f0 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -188,11 +188,10 @@ void SubtitlesGrid::OnPopupMenu(bool alternate) { // Duplicate selection append_command(menu, "edit/line/duplicate", state); append_command(menu, "edit/line/duplicate/shift", state); - append_command(menu, "edit/line/join/as_karaoke", state); // Swaps selection state = (sels == 2); - //append_command(menu, "MENU_SWAP", state); + append_command(menu, "edit/line/swap", state); // Join selection state = (sels >= 2 && continuous);