forked from mia/Aegisub
Make VideoSlider use commands for its key events
Originally committed to SVN as r5256.
This commit is contained in:
parent
1f79d89e5b
commit
6ad2098749
8 changed files with 244 additions and 274 deletions
|
@ -43,6 +43,8 @@
|
|||
|
||||
#include "command.h"
|
||||
|
||||
#include "../ass_dialogue.h"
|
||||
#include "../ass_time.h"
|
||||
#include "../compat.h"
|
||||
#include "../frame_main.h"
|
||||
#include "../main.h"
|
||||
|
@ -254,6 +256,66 @@ struct video_frame_next : public Command {
|
|||
}
|
||||
};
|
||||
|
||||
/// Seek to the next subtitle boundary.
|
||||
struct video_frame_next_boundary : public Command {
|
||||
CMD_NAME("video/frame/next/boundary")
|
||||
STR_MENU("Next Boundary")
|
||||
STR_DISP("Next Boundary")
|
||||
STR_HELP("Seek to the next subtitle boundary.")
|
||||
|
||||
void operator()(agi::Context *c) {
|
||||
AssDialogue *active_line = c->selectionController->GetActiveLine();
|
||||
if (!active_line) return;
|
||||
|
||||
int target = c->videoController->FrameAtTime(active_line->Start.GetMS(), agi::vfr::START);
|
||||
if (target > c->videoController->GetFrameN()) {
|
||||
c->videoController->JumpToFrame(target);
|
||||
return;
|
||||
}
|
||||
|
||||
target = c->videoController->FrameAtTime(active_line->End.GetMS(), agi::vfr::END);
|
||||
if (target > c->videoController->GetFrameN()) {
|
||||
c->videoController->JumpToFrame(target);
|
||||
return;
|
||||
}
|
||||
|
||||
c->selectionController->NextLine();
|
||||
AssDialogue *new_line = c->selectionController->GetActiveLine();
|
||||
if (new_line != active_line)
|
||||
c->videoController->JumpToTime(new_line->Start.GetMS());
|
||||
}
|
||||
};
|
||||
|
||||
/// Seek to the next keyframe.
|
||||
struct video_frame_next_keyframe : public Command {
|
||||
CMD_NAME("video/frame/next/keyframe")
|
||||
STR_MENU("Next Keyframe")
|
||||
STR_DISP("Next Keyframe")
|
||||
STR_HELP("Seek to the next keyframe.")
|
||||
|
||||
void operator()(agi::Context *c) {
|
||||
std::vector<int> const& kf = c->videoController->GetKeyFrames();
|
||||
std::vector<int>::const_iterator pos = lower_bound(kf.begin(), kf.end(), c->videoController->GetFrameN());
|
||||
if (pos != kf.end()) ++pos;
|
||||
|
||||
c->videoController->JumpToFrame(pos == kf.end() ? c->videoController->GetFrameN() - 1 : *pos);
|
||||
}
|
||||
};
|
||||
|
||||
/// Fast jump forward
|
||||
struct video_frame_next_large : public Command {
|
||||
CMD_NAME("video/frame/next/large")
|
||||
STR_MENU("Fast jump forward")
|
||||
STR_DISP("Fast jump forward")
|
||||
STR_HELP("Fast jump forward.")
|
||||
|
||||
void operator()(agi::Context *c) {
|
||||
c->videoController->JumpToFrame(
|
||||
c->videoController->GetFrameN() +
|
||||
OPT_GET("Video/Slider/Fast Jump Step")->GetInt());
|
||||
}
|
||||
};
|
||||
|
||||
/// Seek to the previous frame.
|
||||
struct video_frame_prev : public Command {
|
||||
CMD_NAME("video/frame/prev")
|
||||
|
@ -266,6 +328,68 @@ struct video_frame_prev : public Command {
|
|||
}
|
||||
};
|
||||
|
||||
/// Seek to the previous subtitle boundary.
|
||||
struct video_frame_prev_boundary : public Command {
|
||||
CMD_NAME("video/frame/prev/boundary")
|
||||
STR_MENU("Previous Boundary")
|
||||
STR_DISP("Previous Boundary")
|
||||
STR_HELP("Seek to the previous subtitle boundary.")
|
||||
|
||||
void operator()(agi::Context *c) {
|
||||
AssDialogue *active_line = c->selectionController->GetActiveLine();
|
||||
if (!active_line) return;
|
||||
|
||||
int target = c->videoController->FrameAtTime(active_line->End.GetMS(), agi::vfr::END);
|
||||
if (target < c->videoController->GetFrameN()) {
|
||||
c->videoController->JumpToFrame(target);
|
||||
return;
|
||||
}
|
||||
|
||||
target = c->videoController->FrameAtTime(active_line->Start.GetMS(), agi::vfr::START);
|
||||
if (target < c->videoController->GetFrameN()) {
|
||||
c->videoController->JumpToFrame(target);
|
||||
return;
|
||||
}
|
||||
|
||||
c->selectionController->PrevLine();
|
||||
AssDialogue *new_line = c->selectionController->GetActiveLine();
|
||||
if (new_line != active_line)
|
||||
c->videoController->JumpToTime(new_line->End.GetMS(), agi::vfr::END);
|
||||
}
|
||||
};
|
||||
|
||||
/// Seek to the previous keyframe.
|
||||
struct video_frame_prev_keyframe : public Command {
|
||||
CMD_NAME("video/frame/prev/keyframe")
|
||||
STR_MENU("Previous Keyframe")
|
||||
STR_DISP("Previous Keyframe")
|
||||
STR_HELP("Seek to the previous keyframe.")
|
||||
|
||||
void operator()(agi::Context *c) {
|
||||
int frame = c->videoController->GetFrameN();
|
||||
std::vector<int> const& kf = c->videoController->GetKeyFrames();
|
||||
std::vector<int>::const_iterator pos = lower_bound(kf.begin(), kf.end(), frame);
|
||||
|
||||
if (frame != 0 && (pos == kf.end() || *pos == frame))
|
||||
--pos;
|
||||
|
||||
c->videoController->JumpToFrame(*pos);
|
||||
}
|
||||
};
|
||||
|
||||
/// Fast jump backwards
|
||||
struct video_frame_prev_large : public Command {
|
||||
CMD_NAME("video/frame/prev/large")
|
||||
STR_MENU("Fast jump backwards")
|
||||
STR_DISP("Fast jump backwards")
|
||||
STR_HELP("Fast jump backwards")
|
||||
|
||||
void operator()(agi::Context *c) {
|
||||
c->videoController->JumpToFrame(
|
||||
c->videoController->GetFrameN() -
|
||||
OPT_GET("Video/Slider/Fast Jump Step")->GetInt());
|
||||
}
|
||||
};
|
||||
|
||||
/// Jump to frame or time.
|
||||
struct video_jump : public Command {
|
||||
|
@ -493,7 +617,13 @@ void init_video(CommandManager *cm) {
|
|||
cm->reg(new video_details);
|
||||
cm->reg(new video_focus_seek);
|
||||
cm->reg(new video_frame_next);
|
||||
cm->reg(new video_frame_next_boundary);
|
||||
cm->reg(new video_frame_next_keyframe);
|
||||
cm->reg(new video_frame_next_large);
|
||||
cm->reg(new video_frame_prev);
|
||||
cm->reg(new video_frame_prev_boundary);
|
||||
cm->reg(new video_frame_prev_keyframe);
|
||||
cm->reg(new video_frame_prev_large);
|
||||
cm->reg(new video_jump);
|
||||
cm->reg(new video_jump_end);
|
||||
cm->reg(new video_jump_start);
|
||||
|
|
|
@ -79,7 +79,6 @@ DialogDetachedVideo::DialogDetachedVideo(FrameMain *parent, agi::Context *contex
|
|||
videoBox = new VideoBox(panel, true, NULL, context);
|
||||
videoBox->videoDisplay->freeSize = true;
|
||||
videoBox->videoDisplay->SetClientSize(initialDisplaySize);
|
||||
videoBox->videoSlider->grid = context->subsGrid;
|
||||
|
||||
// Set sizer
|
||||
wxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
|
|
@ -298,7 +298,6 @@ void FrameMain::InitContents() {
|
|||
StartupLog("Create subtitles grid");
|
||||
context->subsGrid = SubsGrid = new SubtitlesGrid(Panel,context.get(),wxSize(600,100),wxWANTS_CHARS | wxSUNKEN_BORDER,"Subs grid");
|
||||
context->selectionController = context->subsGrid;
|
||||
context->videoBox->videoSlider->grid = SubsGrid;
|
||||
Search.context = context.get();
|
||||
|
||||
StartupLog("Create tool area splitter window");
|
||||
|
|
|
@ -504,6 +504,27 @@
|
|||
"enable" : true
|
||||
}
|
||||
],
|
||||
"video/frame/next/boundary" : [
|
||||
{
|
||||
"modifiers" : [ "Ctrl" ],
|
||||
"key" : "Right",
|
||||
"enable" : true
|
||||
}
|
||||
],
|
||||
"video/frame/next/keyframe" : [
|
||||
{
|
||||
"modifiers" : [ "Shift" ],
|
||||
"key" : "Right",
|
||||
"enable" : true
|
||||
}
|
||||
],
|
||||
"video/frame/next/large" : [
|
||||
{
|
||||
"modifiers" : [ "Alt" ],
|
||||
"key" : "Right",
|
||||
"enable" : true
|
||||
}
|
||||
],
|
||||
"video/frame/prev" : [
|
||||
{
|
||||
"modifiers" : [],
|
||||
|
@ -511,6 +532,27 @@
|
|||
"enable" : true
|
||||
}
|
||||
],
|
||||
"video/frame/prev/boundary" : [
|
||||
{
|
||||
"modifiers" : [ "Ctrl" ],
|
||||
"key" : "Left",
|
||||
"enable" : true
|
||||
}
|
||||
],
|
||||
"video/frame/prev/keyframe" : [
|
||||
{
|
||||
"modifiers" : [ "Shift" ],
|
||||
"key" : "Left",
|
||||
"enable" : true
|
||||
}
|
||||
],
|
||||
"video/frame/prev/large" : [
|
||||
{
|
||||
"modifiers" : [ "Alt" ],
|
||||
"key" : "Left",
|
||||
"enable" : true
|
||||
}
|
||||
],
|
||||
"visual typesetting set tool crosshair" : [
|
||||
{
|
||||
"modifiers" : [],
|
||||
|
|
|
@ -90,7 +90,7 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, wxComboBox *zoomBox, agi::
|
|||
add_option(this, videoBottomSizer, "video/opt/autoscroll", "Video/Subtitle Sync");
|
||||
|
||||
// Seek
|
||||
videoSlider = new VideoSlider(this,-1);
|
||||
videoSlider = new VideoSlider(this, context);
|
||||
videoSlider->SetToolTip(_("Seek video."));
|
||||
|
||||
// Position
|
||||
|
@ -120,9 +120,6 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, wxComboBox *zoomBox, agi::
|
|||
// Display
|
||||
videoDisplay = new VideoDisplay(this,VideoPosition,VideoSubsPos,zoomBox,this,context);
|
||||
|
||||
// Set display
|
||||
videoSlider->Display = videoDisplay;
|
||||
|
||||
// Top sizer
|
||||
// Detached and attached video needs different flags, see bugs #742 and #853
|
||||
int highSizerFlags = isDetached ? wxEXPAND : 0;
|
||||
|
|
|
@ -266,7 +266,7 @@ void VideoContext::JumpToFrame(int n) {
|
|||
// Prevent intervention during playback
|
||||
if (isPlaying && n != playNextFrame) return;
|
||||
|
||||
frame_n = n;
|
||||
frame_n = mid(0, n, GetLength() - 1);
|
||||
|
||||
Seek(n);
|
||||
}
|
||||
|
|
|
@ -40,52 +40,30 @@
|
|||
#include <wx/settings.h>
|
||||
#endif
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "include/aegisub/context.h"
|
||||
#include "include/aegisub/hotkey.h"
|
||||
#include "main.h"
|
||||
#include "subs_edit_box.h"
|
||||
#include "selection_controller.h"
|
||||
#include "subs_grid.h"
|
||||
#include "utils.h"
|
||||
#include "video_context.h"
|
||||
#include "video_display.h"
|
||||
#include "video_slider.h"
|
||||
|
||||
/// IDs
|
||||
enum {
|
||||
NextFrame = 1300,
|
||||
PrevFrame
|
||||
};
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param parent
|
||||
/// @param id
|
||||
///
|
||||
VideoSlider::VideoSlider (wxWindow* parent, wxWindowID id)
|
||||
: wxWindow (parent,id,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE)
|
||||
VideoSlider::VideoSlider (wxWindow* parent, agi::Context *c)
|
||||
: wxWindow(parent, -1, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE)
|
||||
, vc(c->videoController)
|
||||
, grid(c->subsGrid)
|
||||
, val(0)
|
||||
, max(1)
|
||||
{
|
||||
val = 0;
|
||||
max = 1;
|
||||
Display = NULL;
|
||||
SetClientSize(20,25);
|
||||
SetMinSize(wxSize(20, 25));
|
||||
locked = false;
|
||||
OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL);
|
||||
VideoContext *vc = VideoContext::Get();
|
||||
assert(vc);
|
||||
vc->AddSeekListener(&VideoSlider::SetValue, this);
|
||||
vc->AddVideoOpenListener(&VideoSlider::VideoOpened, this);
|
||||
vc->AddKeyframesListener(&VideoSlider::KeyframesChanged, this);
|
||||
slots.push_back(OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL));
|
||||
slots.push_back(vc->AddSeekListener(&VideoSlider::SetValue, this));
|
||||
slots.push_back(vc->AddVideoOpenListener(&VideoSlider::VideoOpened, this));
|
||||
slots.push_back(vc->AddKeyframesListener(&VideoSlider::KeyframesChanged, this));
|
||||
}
|
||||
|
||||
VideoSlider::~VideoSlider() {
|
||||
VideoContext *vc = VideoContext::Get();
|
||||
assert(vc);
|
||||
}
|
||||
|
||||
/// @brief Set value
|
||||
/// @param value
|
||||
/// @return
|
||||
///
|
||||
void VideoSlider::SetValue(int value) {
|
||||
if (val == value) return;
|
||||
val = mid(0, value, max);
|
||||
|
@ -93,7 +71,6 @@ void VideoSlider::SetValue(int value) {
|
|||
}
|
||||
|
||||
void VideoSlider::VideoOpened() {
|
||||
VideoContext *vc = VideoContext::Get();
|
||||
max = vc->GetLength() - 1;
|
||||
keyframes = vc->GetKeyFrames();
|
||||
Refresh(false);
|
||||
|
@ -104,37 +81,21 @@ void VideoSlider::KeyframesChanged(std::vector<int> const& newKeyframes) {
|
|||
Refresh(false);
|
||||
}
|
||||
|
||||
/// @brief Get value at X
|
||||
/// @param x
|
||||
/// @return
|
||||
///
|
||||
int VideoSlider::GetValueAtX(int x) {
|
||||
// Get dimensions
|
||||
int w,h;
|
||||
GetClientSize(&w,&h);
|
||||
|
||||
// Special case
|
||||
if (w <= 10) return 0;
|
||||
|
||||
// Calculate
|
||||
return (int64_t)(x-5)*(int64_t)max/(int64_t)(w-10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get X at value
|
||||
/// @param value
|
||||
/// @return
|
||||
///
|
||||
int VideoSlider::GetXAtValue(int value) {
|
||||
// Get dimensions
|
||||
int w,h;
|
||||
GetClientSize(&w,&h);
|
||||
|
||||
// Special case
|
||||
if (max <= 0) return 0;
|
||||
|
||||
// Calculate
|
||||
int w,h;
|
||||
GetClientSize(&w,&h);
|
||||
return (int64_t)value*(int64_t)(w-10)/(int64_t)max+5;
|
||||
}
|
||||
|
||||
|
@ -147,47 +108,29 @@ BEGIN_EVENT_TABLE(VideoSlider, wxWindow)
|
|||
EVT_ERASE_BACKGROUND(VideoSlider::OnEraseBackground)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
/// @brief Mouse events
|
||||
/// @param event
|
||||
/// @return
|
||||
///
|
||||
void VideoSlider::OnMouse(wxMouseEvent &event) {
|
||||
// Coordinates
|
||||
int x = event.GetX();
|
||||
//int y = event.GetY();
|
||||
bool shift = event.m_shiftDown;
|
||||
|
||||
// Left click
|
||||
if (event.ButtonIsDown(wxMOUSE_BTN_LEFT)) {
|
||||
// Check if it's OK to drag
|
||||
bool canDrag = wxWindow::FindFocus() == this;
|
||||
if (!canDrag) {
|
||||
int tolerance = 4;
|
||||
int curX = GetXAtValue(val);
|
||||
if (x-curX < -tolerance || x-curX > tolerance) canDrag = true;
|
||||
// If the slider didn't already have focus, don't seek if the user
|
||||
// clicked very close to the current location as they were probably
|
||||
// just trying to focus the slider
|
||||
if (wxWindow::FindFocus() != this && abs(x - GetXAtValue(val)) < 4) {
|
||||
SetFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Drag
|
||||
if (canDrag) {
|
||||
// Shift click to snap to keyframe
|
||||
if (shift && Display) {
|
||||
std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
|
||||
int keys = KeyFrames.size();
|
||||
if (event.m_shiftDown) {
|
||||
int clickedFrame = GetValueAtX(x);
|
||||
int closest = 0;
|
||||
int cur;
|
||||
std::vector<int>::const_iterator pos = lower_bound(keyframes.begin(), keyframes.end(), clickedFrame);
|
||||
if (pos == keyframes.end())
|
||||
--pos;
|
||||
else if (pos + 1 != keyframes.end() && clickedFrame - *pos > (*pos + 1) - clickedFrame)
|
||||
++pos;
|
||||
|
||||
// Find closest
|
||||
for (int i=0;i<keys;i++) {
|
||||
cur = KeyFrames[i];
|
||||
if (abs(cur-clickedFrame) < abs(closest-clickedFrame)) {
|
||||
closest = cur;
|
||||
}
|
||||
}
|
||||
|
||||
// Jump to frame
|
||||
if (closest == val) return;
|
||||
SetValue(closest);
|
||||
if (*pos == val) return;
|
||||
SetValue(*pos);
|
||||
}
|
||||
|
||||
// Normal click
|
||||
|
@ -196,174 +139,48 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
|
|||
if (go == val) return;
|
||||
SetValue(go);
|
||||
}
|
||||
Refresh(false);
|
||||
|
||||
// Playing?
|
||||
if (VideoContext::Get()->IsPlaying()) {
|
||||
VideoContext::Get()->Stop();
|
||||
VideoContext::Get()->JumpToFrame(val);
|
||||
VideoContext::Get()->Play();
|
||||
if (vc->IsPlaying()) {
|
||||
vc->Stop();
|
||||
vc->JumpToFrame(val);
|
||||
vc->Play();
|
||||
}
|
||||
else VideoContext::Get()->JumpToFrame(val);
|
||||
}
|
||||
|
||||
// Get focus
|
||||
else
|
||||
vc->JumpToFrame(val);
|
||||
SetFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Right/middle click
|
||||
if (event.ButtonDown(wxMOUSE_BTN_RIGHT) || event.ButtonDown(wxMOUSE_BTN_MIDDLE)) {
|
||||
SetFocus();
|
||||
}
|
||||
|
||||
// Something else
|
||||
else if (!VideoContext::Get()->IsPlaying()) event.Skip();
|
||||
else if (!vc->IsPlaying())
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Key down event
|
||||
/// @param event
|
||||
/// @return
|
||||
///
|
||||
void VideoSlider::OnKeyDown(wxKeyEvent &event) {
|
||||
if (VideoContext::Get()->IsPlaying()) return;
|
||||
if (vc->IsPlaying()) return;
|
||||
|
||||
// Get flags
|
||||
int key = event.GetKeyCode();
|
||||
#ifdef __APPLE__
|
||||
bool ctrl = event.m_metaDown;
|
||||
#else
|
||||
bool ctrl = event.m_controlDown;
|
||||
#endif
|
||||
bool alt = event.m_altDown;
|
||||
bool shift = event.m_shiftDown;
|
||||
int direction = 0;
|
||||
|
||||
// Pick direction
|
||||
if (key == WXK_LEFT) direction = -1;
|
||||
else if (key == WXK_RIGHT) direction = 1;
|
||||
|
||||
// If a direction was actually pressed
|
||||
if (direction) {
|
||||
// Standard move
|
||||
if (!ctrl && !shift && !alt) {
|
||||
if (direction == 1) VideoContext::Get()->NextFrame();
|
||||
else VideoContext::Get()->PrevFrame();
|
||||
if (hotkey::check("Video", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()))
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast move
|
||||
if (!ctrl && !shift && alt) {
|
||||
if (VideoContext::Get()->IsPlaying()) return;
|
||||
int target = mid<int>(0,val + direction * OPT_GET("Video/Slider/Fast Jump Step")->GetInt(),max);
|
||||
if (target != val) VideoContext::Get()->JumpToFrame(target);
|
||||
return;
|
||||
}
|
||||
|
||||
// Boundaries
|
||||
if (ctrl && !shift && !alt) {
|
||||
// Prepare
|
||||
wxArrayInt sel = grid->GetSelection();
|
||||
int cur;
|
||||
if (sel.Count() > 0) cur = sel[0];
|
||||
else {
|
||||
grid->SetActiveLine(grid->GetDialogue(0));
|
||||
grid->SelectRow(0);
|
||||
cur = 0;
|
||||
}
|
||||
AssDialogue *curDiag = grid->GetDialogue(cur);
|
||||
if (!curDiag) return;
|
||||
|
||||
// Jump to next sub boundary
|
||||
if (direction != 0) {
|
||||
int target1 = VideoContext::Get()->FrameAtTime(curDiag->Start.GetMS(),agi::vfr::START);
|
||||
int target2 = VideoContext::Get()->FrameAtTime(curDiag->End.GetMS(),agi::vfr::END);
|
||||
bool drawn = false;
|
||||
|
||||
// Forward
|
||||
if (direction == 1) {
|
||||
if (VideoContext::Get()->GetFrameN() < target1) VideoContext::Get()->JumpToFrame(target1);
|
||||
else if (VideoContext::Get()->GetFrameN() < target2) VideoContext::Get()->JumpToFrame(target2);
|
||||
else {
|
||||
if (cur+1 >= grid->GetRows()) return;
|
||||
grid->SetActiveLine(grid->GetDialogue(cur+1));
|
||||
grid->SelectRow(cur+1);
|
||||
grid->MakeCellVisible(cur+1,0);
|
||||
grid->SetVideoToSubs(true);
|
||||
grid->Refresh(false);
|
||||
drawn = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Backward
|
||||
else {
|
||||
if (VideoContext::Get()->GetFrameN() > target2) VideoContext::Get()->JumpToFrame(target2);
|
||||
else if (VideoContext::Get()->GetFrameN() > target1) VideoContext::Get()->JumpToFrame(target1);
|
||||
else {
|
||||
if (cur-1 < 0) return;
|
||||
grid->SetActiveLine(grid->GetDialogue(cur-1));
|
||||
grid->SelectRow(cur-1);
|
||||
grid->MakeCellVisible(cur-1,0);
|
||||
grid->SetVideoToSubs(false);
|
||||
grid->Refresh(false);
|
||||
drawn = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Snap to keyframe
|
||||
if (shift && !ctrl && !alt) {
|
||||
if (direction != 0) {
|
||||
std::vector<int>::iterator pos = std::lower_bound(keyframes.begin(), keyframes.end(), val);
|
||||
|
||||
if (direction < 0 && val != 0 && (pos == keyframes.end() || *pos == val))
|
||||
--pos;
|
||||
if (direction > 0 && pos != keyframes.end())
|
||||
++pos;
|
||||
|
||||
VideoContext::Get()->JumpToFrame(pos == keyframes.end() ? max : *pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Forward up/down to grid
|
||||
if (key == WXK_UP || key == WXK_DOWN) {
|
||||
if (event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_DOWN) {
|
||||
grid->GetEventHandler()->ProcessEvent(event);
|
||||
grid->SetFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Forward other keys to video display
|
||||
if (Display) {
|
||||
Display->GetEventHandler()->ProcessEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Paint event
|
||||
/// @param event
|
||||
///
|
||||
void VideoSlider::OnPaint(wxPaintEvent &event) {
|
||||
wxPaintDC dc(this);
|
||||
DrawImage(dc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Draw image
|
||||
/// @param destdc
|
||||
///
|
||||
void VideoSlider::DrawImage(wxDC &destdc) {
|
||||
// Get dimensions
|
||||
int w,h;
|
||||
GetClientSize(&w,&h);
|
||||
|
||||
|
@ -408,7 +225,7 @@ void VideoSlider::DrawImage(wxDC &destdc) {
|
|||
|
||||
// Draw keyframes
|
||||
int curX;
|
||||
if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) {
|
||||
if (OPT_GET("Video/Slider/Show Keyframes")->GetBool()) {
|
||||
dc.SetPen(wxPen(shad));
|
||||
for (size_t i=0;i<keyframes.size();i++) {
|
||||
curX = GetXAtValue(keyframes[i]);
|
||||
|
@ -455,19 +272,6 @@ void VideoSlider::DrawImage(wxDC &destdc) {
|
|||
destdc.Blit(0,0,w,h,&dc,0,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Update image
|
||||
///
|
||||
void VideoSlider::UpdateImage () {
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Focus change
|
||||
/// @param event
|
||||
///
|
||||
void VideoSlider::OnFocus(wxFocusEvent &event) {
|
||||
Refresh(false);
|
||||
}
|
||||
|
|
|
@ -35,10 +35,14 @@
|
|||
///
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <vector>
|
||||
|
||||
#include <wx/window.h>
|
||||
#endif
|
||||
|
||||
class VideoDisplay;
|
||||
#include <libaegisub/signal.h>
|
||||
|
||||
class VideoContext;
|
||||
class SubtitlesGrid;
|
||||
|
||||
/// DOCME
|
||||
|
@ -47,24 +51,26 @@ class SubtitlesGrid;
|
|||
///
|
||||
/// DOCME
|
||||
class VideoSlider: public wxWindow {
|
||||
std::vector<int> keyframes;
|
||||
VideoContext *vc; ///< Video controller
|
||||
SubtitlesGrid *grid; ///< temp hack; remove this once event forwarding is killed
|
||||
std::vector<int> keyframes; ///< Currently loaded keyframes
|
||||
std::vector<agi::signal::Connection> slots;
|
||||
|
||||
/// DOCME
|
||||
int val;
|
||||
|
||||
/// DOCME
|
||||
int max;
|
||||
|
||||
/// DOCME
|
||||
bool locked;
|
||||
int val; ///< Current frame number
|
||||
int max; ///< Last frame number
|
||||
|
||||
/// Get the frame number for the given x coordinate
|
||||
int GetValueAtX(int x);
|
||||
/// Get the x-coordinate for a frame number
|
||||
int GetXAtValue(int value);
|
||||
/// Render the slider
|
||||
void DrawImage(wxDC &dc);
|
||||
void UpdateImage();
|
||||
/// Set the position of the slider
|
||||
void SetValue(int value);
|
||||
|
||||
/// Video open event handler
|
||||
void VideoOpened();
|
||||
/// Keyframe open even handler
|
||||
void KeyframesChanged(std::vector<int> const& newKeyframes);
|
||||
|
||||
void OnMouse(wxMouseEvent &event);
|
||||
|
@ -74,14 +80,7 @@ class VideoSlider: public wxWindow {
|
|||
void OnEraseBackground(wxEraseEvent &event) {}
|
||||
|
||||
public:
|
||||
/// DOCME
|
||||
VideoDisplay *Display;
|
||||
|
||||
/// DOCME
|
||||
SubtitlesGrid *grid;
|
||||
|
||||
VideoSlider(wxWindow* parent, wxWindowID id);
|
||||
~VideoSlider();
|
||||
VideoSlider(wxWindow* parent, agi::Context *c);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue