Make VideoSlider use commands for its key events

Originally committed to SVN as r5256.
This commit is contained in:
Thomas Goyne 2011-01-21 04:57:36 +00:00
parent 1f79d89e5b
commit 6ad2098749
8 changed files with 244 additions and 274 deletions

View File

@ -43,6 +43,8 @@
#include "command.h" #include "command.h"
#include "../ass_dialogue.h"
#include "../ass_time.h"
#include "../compat.h" #include "../compat.h"
#include "../frame_main.h" #include "../frame_main.h"
#include "../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. /// Seek to the previous frame.
struct video_frame_prev : public Command { struct video_frame_prev : public Command {
CMD_NAME("video/frame/prev") 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. /// Jump to frame or time.
struct video_jump : public Command { struct video_jump : public Command {
@ -493,7 +617,13 @@ void init_video(CommandManager *cm) {
cm->reg(new video_details); cm->reg(new video_details);
cm->reg(new video_focus_seek); cm->reg(new video_focus_seek);
cm->reg(new video_frame_next); 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);
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);
cm->reg(new video_jump_end); cm->reg(new video_jump_end);
cm->reg(new video_jump_start); cm->reg(new video_jump_start);

View File

@ -79,7 +79,6 @@ DialogDetachedVideo::DialogDetachedVideo(FrameMain *parent, agi::Context *contex
videoBox = new VideoBox(panel, true, NULL, context); videoBox = new VideoBox(panel, true, NULL, context);
videoBox->videoDisplay->freeSize = true; videoBox->videoDisplay->freeSize = true;
videoBox->videoDisplay->SetClientSize(initialDisplaySize); videoBox->videoDisplay->SetClientSize(initialDisplaySize);
videoBox->videoSlider->grid = context->subsGrid;
// Set sizer // Set sizer
wxSizer *mainSizer = new wxBoxSizer(wxVERTICAL); wxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);

View File

@ -298,7 +298,6 @@ void FrameMain::InitContents() {
StartupLog("Create subtitles grid"); StartupLog("Create subtitles grid");
context->subsGrid = SubsGrid = new SubtitlesGrid(Panel,context.get(),wxSize(600,100),wxWANTS_CHARS | wxSUNKEN_BORDER,"Subs grid"); context->subsGrid = SubsGrid = new SubtitlesGrid(Panel,context.get(),wxSize(600,100),wxWANTS_CHARS | wxSUNKEN_BORDER,"Subs grid");
context->selectionController = context->subsGrid; context->selectionController = context->subsGrid;
context->videoBox->videoSlider->grid = SubsGrid;
Search.context = context.get(); Search.context = context.get();
StartupLog("Create tool area splitter window"); StartupLog("Create tool area splitter window");

View File

@ -504,6 +504,27 @@
"enable" : true "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" : [ "video/frame/prev" : [
{ {
"modifiers" : [], "modifiers" : [],
@ -511,6 +532,27 @@
"enable" : true "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" : [ "visual typesetting set tool crosshair" : [
{ {
"modifiers" : [], "modifiers" : [],

View File

@ -90,7 +90,7 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, wxComboBox *zoomBox, agi::
add_option(this, videoBottomSizer, "video/opt/autoscroll", "Video/Subtitle Sync"); add_option(this, videoBottomSizer, "video/opt/autoscroll", "Video/Subtitle Sync");
// Seek // Seek
videoSlider = new VideoSlider(this,-1); videoSlider = new VideoSlider(this, context);
videoSlider->SetToolTip(_("Seek video.")); videoSlider->SetToolTip(_("Seek video."));
// Position // Position
@ -120,9 +120,6 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, wxComboBox *zoomBox, agi::
// Display // Display
videoDisplay = new VideoDisplay(this,VideoPosition,VideoSubsPos,zoomBox,this,context); videoDisplay = new VideoDisplay(this,VideoPosition,VideoSubsPos,zoomBox,this,context);
// Set display
videoSlider->Display = videoDisplay;
// Top sizer // Top sizer
// Detached and attached video needs different flags, see bugs #742 and #853 // Detached and attached video needs different flags, see bugs #742 and #853
int highSizerFlags = isDetached ? wxEXPAND : 0; int highSizerFlags = isDetached ? wxEXPAND : 0;

View File

@ -266,7 +266,7 @@ void VideoContext::JumpToFrame(int n) {
// Prevent intervention during playback // Prevent intervention during playback
if (isPlaying && n != playNextFrame) return; if (isPlaying && n != playNextFrame) return;
frame_n = n; frame_n = mid(0, n, GetLength() - 1);
Seek(n); Seek(n);
} }

View File

@ -40,52 +40,30 @@
#include <wx/settings.h> #include <wx/settings.h>
#endif #endif
#include "ass_dialogue.h" #include "include/aegisub/context.h"
#include "include/aegisub/hotkey.h"
#include "main.h" #include "main.h"
#include "subs_edit_box.h"
#include "selection_controller.h" #include "selection_controller.h"
#include "subs_grid.h" #include "subs_grid.h"
#include "utils.h" #include "utils.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.h"
#include "video_slider.h" #include "video_slider.h"
/// IDs VideoSlider::VideoSlider (wxWindow* parent, agi::Context *c)
enum { : wxWindow(parent, -1, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE)
NextFrame = 1300, , vc(c->videoController)
PrevFrame , grid(c->subsGrid)
}; , val(0)
, max(1)
/// @brief Constructor
/// @param parent
/// @param id
///
VideoSlider::VideoSlider (wxWindow* parent, wxWindowID id)
: wxWindow (parent,id,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE)
{ {
val = 0;
max = 1;
Display = NULL;
SetClientSize(20,25); SetClientSize(20,25);
SetMinSize(wxSize(20, 25)); SetMinSize(wxSize(20, 25));
locked = false; slots.push_back(OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL));
OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL); slots.push_back(vc->AddSeekListener(&VideoSlider::SetValue, this));
VideoContext *vc = VideoContext::Get(); slots.push_back(vc->AddVideoOpenListener(&VideoSlider::VideoOpened, this));
assert(vc); slots.push_back(vc->AddKeyframesListener(&VideoSlider::KeyframesChanged, this));
vc->AddSeekListener(&VideoSlider::SetValue, this);
vc->AddVideoOpenListener(&VideoSlider::VideoOpened, this);
vc->AddKeyframesListener(&VideoSlider::KeyframesChanged, this);
} }
VideoSlider::~VideoSlider() {
VideoContext *vc = VideoContext::Get();
assert(vc);
}
/// @brief Set value
/// @param value
/// @return
///
void VideoSlider::SetValue(int value) { void VideoSlider::SetValue(int value) {
if (val == value) return; if (val == value) return;
val = mid(0, value, max); val = mid(0, value, max);
@ -93,7 +71,6 @@ void VideoSlider::SetValue(int value) {
} }
void VideoSlider::VideoOpened() { void VideoSlider::VideoOpened() {
VideoContext *vc = VideoContext::Get();
max = vc->GetLength() - 1; max = vc->GetLength() - 1;
keyframes = vc->GetKeyFrames(); keyframes = vc->GetKeyFrames();
Refresh(false); Refresh(false);
@ -104,37 +81,21 @@ void VideoSlider::KeyframesChanged(std::vector<int> const& newKeyframes) {
Refresh(false); Refresh(false);
} }
/// @brief Get value at X
/// @param x
/// @return
///
int VideoSlider::GetValueAtX(int x) { int VideoSlider::GetValueAtX(int x) {
// Get dimensions
int w,h; int w,h;
GetClientSize(&w,&h); GetClientSize(&w,&h);
// Special case // Special case
if (w <= 10) return 0; if (w <= 10) return 0;
// Calculate
return (int64_t)(x-5)*(int64_t)max/(int64_t)(w-10); 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) { int VideoSlider::GetXAtValue(int value) {
// Get dimensions
int w,h;
GetClientSize(&w,&h);
// Special case
if (max <= 0) return 0; if (max <= 0) return 0;
// Calculate int w,h;
GetClientSize(&w,&h);
return (int64_t)value*(int64_t)(w-10)/(int64_t)max+5; 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) EVT_ERASE_BACKGROUND(VideoSlider::OnEraseBackground)
END_EVENT_TABLE() END_EVENT_TABLE()
/// @brief Mouse events
/// @param event
/// @return
///
void VideoSlider::OnMouse(wxMouseEvent &event) { void VideoSlider::OnMouse(wxMouseEvent &event) {
// Coordinates
int x = event.GetX(); int x = event.GetX();
//int y = event.GetY();
bool shift = event.m_shiftDown;
// Left click
if (event.ButtonIsDown(wxMOUSE_BTN_LEFT)) { if (event.ButtonIsDown(wxMOUSE_BTN_LEFT)) {
// Check if it's OK to drag // If the slider didn't already have focus, don't seek if the user
bool canDrag = wxWindow::FindFocus() == this; // clicked very close to the current location as they were probably
if (!canDrag) { // just trying to focus the slider
int tolerance = 4; if (wxWindow::FindFocus() != this && abs(x - GetXAtValue(val)) < 4) {
int curX = GetXAtValue(val); SetFocus();
if (x-curX < -tolerance || x-curX > tolerance) canDrag = true; return;
} }
// Drag
if (canDrag) {
// Shift click to snap to keyframe // Shift click to snap to keyframe
if (shift && Display) { if (event.m_shiftDown) {
std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
int keys = KeyFrames.size();
int clickedFrame = GetValueAtX(x); int clickedFrame = GetValueAtX(x);
int closest = 0; std::vector<int>::const_iterator pos = lower_bound(keyframes.begin(), keyframes.end(), clickedFrame);
int cur; if (pos == keyframes.end())
--pos;
else if (pos + 1 != keyframes.end() && clickedFrame - *pos > (*pos + 1) - clickedFrame)
++pos;
// Find closest if (*pos == val) return;
for (int i=0;i<keys;i++) { SetValue(*pos);
cur = KeyFrames[i];
if (abs(cur-clickedFrame) < abs(closest-clickedFrame)) {
closest = cur;
}
}
// Jump to frame
if (closest == val) return;
SetValue(closest);
} }
// Normal click // Normal click
@ -196,174 +139,48 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
if (go == val) return; if (go == val) return;
SetValue(go); SetValue(go);
} }
Refresh(false);
// Playing? if (vc->IsPlaying()) {
if (VideoContext::Get()->IsPlaying()) { vc->Stop();
VideoContext::Get()->Stop(); vc->JumpToFrame(val);
VideoContext::Get()->JumpToFrame(val); vc->Play();
VideoContext::Get()->Play();
} }
else VideoContext::Get()->JumpToFrame(val); else
} vc->JumpToFrame(val);
// Get focus
SetFocus(); SetFocus();
return;
} }
// Right/middle click
if (event.ButtonDown(wxMOUSE_BTN_RIGHT) || event.ButtonDown(wxMOUSE_BTN_MIDDLE)) { if (event.ButtonDown(wxMOUSE_BTN_RIGHT) || event.ButtonDown(wxMOUSE_BTN_MIDDLE)) {
SetFocus(); SetFocus();
} }
// Something else else if (!vc->IsPlaying())
else if (!VideoContext::Get()->IsPlaying()) event.Skip(); event.Skip();
} }
/// @brief Key down event
/// @param event
/// @return
///
void VideoSlider::OnKeyDown(wxKeyEvent &event) { void VideoSlider::OnKeyDown(wxKeyEvent &event) {
if (VideoContext::Get()->IsPlaying()) return; if (vc->IsPlaying()) return;
// Get flags if (hotkey::check("Video", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()))
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();
return; 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 // 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->GetEventHandler()->ProcessEvent(event);
grid->SetFocus(); grid->SetFocus();
return; return;
} }
// Forward other keys to video display
if (Display) {
Display->GetEventHandler()->ProcessEvent(event);
return;
}
event.Skip(); event.Skip();
} }
/// @brief Paint event
/// @param event
///
void VideoSlider::OnPaint(wxPaintEvent &event) { void VideoSlider::OnPaint(wxPaintEvent &event) {
wxPaintDC dc(this); wxPaintDC dc(this);
DrawImage(dc); DrawImage(dc);
} }
/// @brief Draw image
/// @param destdc
///
void VideoSlider::DrawImage(wxDC &destdc) { void VideoSlider::DrawImage(wxDC &destdc) {
// Get dimensions
int w,h; int w,h;
GetClientSize(&w,&h); GetClientSize(&w,&h);
@ -408,7 +225,7 @@ void VideoSlider::DrawImage(wxDC &destdc) {
// Draw keyframes // Draw keyframes
int curX; int curX;
if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) { if (OPT_GET("Video/Slider/Show Keyframes")->GetBool()) {
dc.SetPen(wxPen(shad)); dc.SetPen(wxPen(shad));
for (size_t i=0;i<keyframes.size();i++) { for (size_t i=0;i<keyframes.size();i++) {
curX = GetXAtValue(keyframes[i]); curX = GetXAtValue(keyframes[i]);
@ -455,19 +272,6 @@ void VideoSlider::DrawImage(wxDC &destdc) {
destdc.Blit(0,0,w,h,&dc,0,0); 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) { void VideoSlider::OnFocus(wxFocusEvent &event) {
Refresh(false); Refresh(false);
} }

View File

@ -35,10 +35,14 @@
/// ///
#ifndef AGI_PRE #ifndef AGI_PRE
#include <vector>
#include <wx/window.h> #include <wx/window.h>
#endif #endif
class VideoDisplay; #include <libaegisub/signal.h>
class VideoContext;
class SubtitlesGrid; class SubtitlesGrid;
/// DOCME /// DOCME
@ -47,24 +51,26 @@ class SubtitlesGrid;
/// ///
/// DOCME /// DOCME
class VideoSlider: public wxWindow { 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; ///< Current frame number
int val; int max; ///< Last frame number
/// DOCME
int max;
/// DOCME
bool locked;
/// Get the frame number for the given x coordinate
int GetValueAtX(int x); int GetValueAtX(int x);
/// Get the x-coordinate for a frame number
int GetXAtValue(int value); int GetXAtValue(int value);
/// Render the slider
void DrawImage(wxDC &dc); void DrawImage(wxDC &dc);
void UpdateImage(); /// Set the position of the slider
void SetValue(int value); void SetValue(int value);
/// Video open event handler
void VideoOpened(); void VideoOpened();
/// Keyframe open even handler
void KeyframesChanged(std::vector<int> const& newKeyframes); void KeyframesChanged(std::vector<int> const& newKeyframes);
void OnMouse(wxMouseEvent &event); void OnMouse(wxMouseEvent &event);
@ -74,14 +80,7 @@ class VideoSlider: public wxWindow {
void OnEraseBackground(wxEraseEvent &event) {} void OnEraseBackground(wxEraseEvent &event) {}
public: public:
/// DOCME VideoSlider(wxWindow* parent, agi::Context *c);
VideoDisplay *Display;
/// DOCME
SubtitlesGrid *grid;
VideoSlider(wxWindow* parent, wxWindowID id);
~VideoSlider();
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };