Fix crash when trying to seek to keyframes via the video slider with no keyframes loaded, and use wxAutoBufferedPaintDC rather than manual double-buffering

Originally committed to SVN as r6432.
This commit is contained in:
Thomas Goyne 2012-02-02 19:18:21 +00:00
parent b8a7c6cb1e
commit 6717334c12
2 changed files with 19 additions and 43 deletions

View file

@ -37,6 +37,7 @@
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
#include <wx/dcbuffer.h>
#include <wx/settings.h> #include <wx/settings.h>
#endif #endif
@ -56,6 +57,8 @@ VideoSlider::VideoSlider (wxWindow* parent, agi::Context *c)
{ {
SetClientSize(20,25); SetClientSize(20,25);
SetMinSize(wxSize(20, 25)); SetMinSize(wxSize(20, 25));
SetBackgroundStyle(wxBG_STYLE_PAINT);
slots.push_back(OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL)); slots.push_back(OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL));
slots.push_back(c->videoController->AddSeekListener(&VideoSlider::SetValue, this)); slots.push_back(c->videoController->AddSeekListener(&VideoSlider::SetValue, this));
slots.push_back(c->videoController->AddVideoOpenListener(&VideoSlider::VideoOpened, this)); slots.push_back(c->videoController->AddVideoOpenListener(&VideoSlider::VideoOpened, this));
@ -86,9 +89,7 @@ void VideoSlider::KeyframesChanged(std::vector<int> const& newKeyframes) {
} }
int VideoSlider::GetValueAtX(int x) { int VideoSlider::GetValueAtX(int x) {
int w,h; int w = GetClientSize().GetWidth();
GetClientSize(&w,&h);
// Special case // Special case
if (w <= 10) return 0; if (w <= 10) return 0;
@ -98,8 +99,7 @@ int VideoSlider::GetValueAtX(int x) {
int VideoSlider::GetXAtValue(int value) { int VideoSlider::GetXAtValue(int value) {
if (max <= 0) return 0; if (max <= 0) return 0;
int w,h; int w = GetClientSize().GetWidth();
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;
} }
@ -109,23 +109,24 @@ BEGIN_EVENT_TABLE(VideoSlider, wxWindow)
EVT_PAINT(VideoSlider::OnPaint) EVT_PAINT(VideoSlider::OnPaint)
EVT_SET_FOCUS(VideoSlider::OnFocus) EVT_SET_FOCUS(VideoSlider::OnFocus)
EVT_KILL_FOCUS(VideoSlider::OnFocus) EVT_KILL_FOCUS(VideoSlider::OnFocus)
EVT_ERASE_BACKGROUND(VideoSlider::OnEraseBackground)
END_EVENT_TABLE() END_EVENT_TABLE()
void VideoSlider::OnMouse(wxMouseEvent &event) { void VideoSlider::OnMouse(wxMouseEvent &event) {
bool had_focus = HasFocus();
if (event.ButtonDown())
SetFocus();
if (event.LeftIsDown()) { if (event.LeftIsDown()) {
int x = event.GetX(); int x = event.GetX();
// If the slider didn't already have focus, don't seek if the user // 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 // clicked very close to the current location as they were probably
// just trying to focus the slider // just trying to focus the slider
if (wxWindow::FindFocus() != this && abs(x - GetXAtValue(val)) < 4) { if (!had_focus && abs(x - GetXAtValue(val)) < 4)
SetFocus();
return; return;
}
// Shift click to snap to keyframe // Shift click to snap to keyframe
if (event.ShiftDown()) { if (event.ShiftDown() && keyframes.size()) {
int clickedFrame = GetValueAtX(x); int clickedFrame = GetValueAtX(x);
std::vector<int>::const_iterator pos = lower_bound(keyframes.begin(), keyframes.end(), clickedFrame); std::vector<int>::const_iterator pos = lower_bound(keyframes.begin(), keyframes.end(), clickedFrame);
if (pos == keyframes.end()) if (pos == keyframes.end())
@ -136,7 +137,6 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
if (*pos == val) return; if (*pos == val) return;
SetValue(*pos); SetValue(*pos);
} }
// Normal click // Normal click
else { else {
int go = GetValueAtX(x); int go = GetValueAtX(x);
@ -145,10 +145,7 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
} }
c->videoController->JumpToFrame(val); c->videoController->JumpToFrame(val);
SetFocus();
} }
else if (event.ButtonDown())
SetFocus();
} }
void VideoSlider::OnKeyDown(wxKeyEvent &event) { void VideoSlider::OnKeyDown(wxKeyEvent &event) {
@ -165,18 +162,9 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) {
} }
void VideoSlider::OnPaint(wxPaintEvent &) { void VideoSlider::OnPaint(wxPaintEvent &) {
wxPaintDC dc(this); wxAutoBufferedPaintDC dc(this);
DrawImage(dc);
}
void VideoSlider::DrawImage(wxDC &destdc) {
int w,h; int w,h;
GetClientSize(&w,&h); GetClientSize(&w, &h);
// Back buffer
wxMemoryDC dc;
wxBitmap bmp(w,h);
dc.SelectObject(bmp);
// Colors // Colors
wxColour shad = wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW); wxColour shad = wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW);
@ -193,8 +181,7 @@ void VideoSlider::DrawImage(wxDC &destdc) {
dc.DrawRectangle(0,0,w,h); dc.DrawRectangle(0,0,w,h);
// Selection border // Selection border
bool selected = wxWindow::FindFocus() == this; if (HasFocus()) {
if (selected) {
dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.SetPen(wxPen(shad,1,wxDOT)); dc.SetPen(wxPen(shad,1,wxDOT));
dc.DrawRectangle(0,0,w,h); dc.DrawRectangle(0,0,w,h);
@ -253,12 +240,8 @@ void VideoSlider::DrawImage(wxDC &destdc) {
// Draw selection // Draw selection
dc.SetPen(*wxTRANSPARENT_PEN); dc.SetPen(*wxTRANSPARENT_PEN);
if (selected) dc.SetBrush(wxBrush(sel)); dc.SetBrush(HasFocus() ? wxBrush(sel) : wxBrush(notSel));
else dc.SetBrush(wxBrush(notSel));
dc.DrawRectangle(curX-3,y2+1,7,4); dc.DrawRectangle(curX-3,y2+1,7,4);
// Draw final
destdc.Blit(0,0,w,h,&dc,0,0);
} }
void VideoSlider::OnFocus(wxFocusEvent &) { void VideoSlider::OnFocus(wxFocusEvent &) {

View file

@ -45,15 +45,11 @@
namespace agi { struct Context; } namespace agi { struct Context; }
class VideoContext; class VideoContext;
class SubtitlesGrid;
/// DOCME
/// @class VideoSlider /// @class VideoSlider
/// @brief DOCME /// @brief Slider for displaying and adjusting the video position
///
/// DOCME
class VideoSlider: public wxWindow { class VideoSlider: public wxWindow {
agi::Context *c; agi::Context *c; ///< Associated project context
std::vector<int> keyframes; ///< Currently loaded keyframes std::vector<int> keyframes; ///< Currently loaded keyframes
std::vector<agi::signal::Connection> slots; std::vector<agi::signal::Connection> slots;
@ -64,8 +60,6 @@ class VideoSlider: public wxWindow {
int GetValueAtX(int x); int GetValueAtX(int x);
/// Get the x-coordinate for a frame number /// Get the x-coordinate for a frame number
int GetXAtValue(int value); int GetXAtValue(int value);
/// Render the slider
void DrawImage(wxDC &dc);
/// Set the position of the slider /// Set the position of the slider
void SetValue(int value); void SetValue(int value);
@ -76,9 +70,8 @@ class VideoSlider: public wxWindow {
void OnMouse(wxMouseEvent &event); void OnMouse(wxMouseEvent &event);
void OnKeyDown(wxKeyEvent &event); void OnKeyDown(wxKeyEvent &event);
void OnPaint(wxPaintEvent &event); void OnPaint(wxPaintEvent &);
void OnFocus(wxFocusEvent &event); void OnFocus(wxFocusEvent &);
void OnEraseBackground(wxEraseEvent &) {}
public: public:
VideoSlider(wxWindow* parent, agi::Context *c); VideoSlider(wxWindow* parent, agi::Context *c);