Mostly rewrite the VideoDisplay sizing logic
Fixes layout errors after maximizing when the window previously wasn't big enough to fit the video and an infinite loop caused by wxGTK not updating the window size immediately. Makes it so that the bottom video toolbar is not pushed offscreen by high video zoom. This is not always desirable, but should be an improvement in most cases. Closes #1409. Originally committed to SVN as r6926.
This commit is contained in:
parent
a7b254e95f
commit
f90d7a56fa
3 changed files with 73 additions and 112 deletions
|
@ -124,30 +124,22 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, agi::Context *context)
|
|||
toolbarSizer->Add(visualSubToolBar, wxSizerFlags());
|
||||
|
||||
// Top sizer
|
||||
// Detached and attached video needs different flags, see bugs #742 and #853
|
||||
int highSizerFlags = isDetached ? wxEXPAND : 0;
|
||||
wxSizer *topTopSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
|
||||
topTopSizer->Add(toolbarSizer,0,wxEXPAND,0);
|
||||
topTopSizer->Add(videoDisplay,1,highSizerFlags,0);
|
||||
topSizer->Add(topTopSizer,1,wxEXPAND,0);
|
||||
topSizer->Add(new wxStaticLine(this),0,wxEXPAND,0);
|
||||
wxSizer *topSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
topSizer->Add(toolbarSizer, 0, wxEXPAND);
|
||||
topSizer->Add(videoDisplay, isDetached, isDetached ? wxEXPAND : 0);
|
||||
|
||||
// Sizers
|
||||
wxSizer *videoSliderSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
videoSliderSizer->Add(videoSlider,1,wxEXPAND|wxLEFT,0);
|
||||
videoBottomSizer->Add(VideoPosition,1,wxLEFT|wxALIGN_CENTER,5);
|
||||
videoBottomSizer->Add(VideoSubsPos,1,wxALIGN_CENTER,0);
|
||||
videoBottomSizer->Add(zoomBox, 0, wxALIGN_CENTER, 5);
|
||||
videoSliderSizer->Add(videoSlider, wxSizerFlags(1).Expand());
|
||||
videoBottomSizer->Add(VideoPosition, wxSizerFlags(1).Center().Border(wxLEFT));
|
||||
videoBottomSizer->Add(VideoSubsPos, wxSizerFlags(1).Center());
|
||||
videoBottomSizer->Add(zoomBox, wxSizerFlags(0).Center());
|
||||
|
||||
// If we're detached we do want to fill out as much space we can.
|
||||
// But if we're in the main window, the subs grid needs space more than us.
|
||||
wxSizer *VideoSizer = new wxBoxSizer(wxVERTICAL);
|
||||
VideoSizer->Add(topSizer,isDetached?1:0,wxEXPAND,0);
|
||||
VideoSizer->Add(topSizer, 1, wxEXPAND, 0);
|
||||
VideoSizer->Add(new wxStaticLine(this), 0, wxEXPAND, 0);
|
||||
VideoSizer->Add(videoSliderSizer,0,wxEXPAND,0);
|
||||
VideoSizer->Add(videoBottomSizer,0,wxEXPAND,0);
|
||||
if (!isDetached)
|
||||
VideoSizer->AddStretchSpacer(1);
|
||||
SetSizer(VideoSizer);
|
||||
|
||||
UpdateTimeBoxes();
|
||||
|
|
|
@ -94,11 +94,9 @@ VideoDisplay::VideoDisplay(
|
|||
wxComboBox *zoomBox,
|
||||
wxWindow* parent,
|
||||
agi::Context *c)
|
||||
: wxGLCanvas (parent, -1, attribList, wxDefaultPosition, wxDefaultSize, 0, wxPanelNameStr)
|
||||
: wxGLCanvas(parent, -1, attribList)
|
||||
, autohideTools(OPT_GET("Tool/Visual/Autohide"))
|
||||
, con(c)
|
||||
, w(8)
|
||||
, h(8)
|
||||
, viewport_left(0)
|
||||
, viewport_width(0)
|
||||
, viewport_bottom(0)
|
||||
|
@ -114,8 +112,8 @@ VideoDisplay::VideoDisplay(
|
|||
zoomBox->Bind(wxEVT_COMMAND_TEXT_ENTER, &VideoDisplay::SetZoomFromBoxText, this);
|
||||
|
||||
con->videoController->Bind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
|
||||
slots.push_back(con->videoController->AddVideoOpenListener(&VideoDisplay::UpdateSize, this, false));
|
||||
slots.push_back(con->videoController->AddARChangeListener(&VideoDisplay::UpdateSize, this, true));
|
||||
slots.push_back(con->videoController->AddVideoOpenListener(&VideoDisplay::UpdateSize, this));
|
||||
slots.push_back(con->videoController->AddARChangeListener(&VideoDisplay::UpdateSize, this));
|
||||
|
||||
Bind(wxEVT_PAINT, std::tr1::bind(&VideoDisplay::Render, this));
|
||||
Bind(wxEVT_SIZE, &VideoDisplay::OnSizeEvent, this);
|
||||
|
@ -133,7 +131,6 @@ VideoDisplay::VideoDisplay(
|
|||
|
||||
c->videoDisplay = this;
|
||||
|
||||
UpdateSize();
|
||||
if (con->videoController->IsLoaded())
|
||||
con->videoController->JumpToFrame(con->videoController->GetFrameN());
|
||||
}
|
||||
|
@ -195,14 +192,14 @@ void VideoDisplay::Render() try {
|
|||
return;
|
||||
|
||||
if (!viewport_height || !viewport_width)
|
||||
UpdateSize();
|
||||
PositionVideo();
|
||||
|
||||
videoOut->Render(viewport_left, viewport_bottom, viewport_width, viewport_height);
|
||||
E(glViewport(0, std::min(viewport_bottom, 0), w, h));
|
||||
E(glViewport(0, std::min(viewport_bottom, 0), videoSize.GetWidth(), videoSize.GetHeight()));
|
||||
|
||||
E(glMatrixMode(GL_PROJECTION));
|
||||
E(glLoadIdentity());
|
||||
E(glOrtho(0.0f, w, h, 0.0f, -1000.0f, 1000.0f));
|
||||
E(glOrtho(0.0f, videoSize.GetWidth(), videoSize.GetHeight(), 0.0f, -1000.0f, 1000.0f));
|
||||
|
||||
if (OPT_GET("Video/Overscan Mask")->GetBool()) {
|
||||
double ar = con->videoController->GetAspectRatioValue();
|
||||
|
@ -271,106 +268,81 @@ void VideoDisplay::DrawOverscanMask(float horizontal_percent, float vertical_per
|
|||
gl.DrawMultiPolygon(points, vstart, vcount, Vector2D(viewport_left, viewport_top), Vector2D(viewport_width, viewport_height), true);
|
||||
}
|
||||
|
||||
void VideoDisplay::UpdateSize(bool force) {
|
||||
void VideoDisplay::PositionVideo() {
|
||||
if (!con->videoController->IsLoaded() || !IsShownOnScreen()) return;
|
||||
|
||||
int vidW = con->videoController->GetWidth();
|
||||
int vidH = con->videoController->GetHeight();
|
||||
viewport_left = 0;
|
||||
viewport_bottom = GetClientSize().GetHeight() - videoSize.GetHeight();
|
||||
viewport_top = 0;
|
||||
viewport_width = videoSize.GetWidth();
|
||||
viewport_height = videoSize.GetHeight();
|
||||
|
||||
int arType = con->videoController->GetAspectRatioType();
|
||||
double arValue = con->videoController->GetAspectRatioValue();
|
||||
if (freeSize) {
|
||||
int vidW = con->videoController->GetWidth();
|
||||
int vidH = con->videoController->GetHeight();
|
||||
|
||||
if (freeSize && !force) {
|
||||
GetClientSize(&w,&h);
|
||||
viewport_left = 0;
|
||||
viewport_bottom = 0;
|
||||
viewport_top = 0;
|
||||
viewport_width = w;
|
||||
viewport_height = h;
|
||||
|
||||
// Set aspect ratio
|
||||
double displayAr = double(w) / h;
|
||||
double videoAr = arType == 0 ? double(vidW)/vidH : arValue;
|
||||
int arType = con->videoController->GetAspectRatioType();
|
||||
double displayAr = double(viewport_width) / viewport_height;
|
||||
double videoAr = arType == 0 ? double(vidW) / vidH : con->videoController->GetAspectRatioValue();
|
||||
|
||||
// Window is wider than video, blackbox left/right
|
||||
if (displayAr - videoAr > 0.01f) {
|
||||
int delta = w - videoAr * h;
|
||||
int delta = viewport_width - videoAr * viewport_height;
|
||||
viewport_left = delta / 2;
|
||||
viewport_width = w - delta;
|
||||
viewport_width -= delta;
|
||||
}
|
||||
|
||||
// Video is wider than window, blackbox top/bottom
|
||||
else if (videoAr - displayAr > 0.01f) {
|
||||
int delta = h - w / videoAr;
|
||||
int delta = viewport_height - viewport_width / videoAr;
|
||||
viewport_top = viewport_bottom = delta / 2;
|
||||
viewport_height = h - delta;
|
||||
}
|
||||
|
||||
zoomValue = double(h) / vidH;
|
||||
zoomBox->ChangeValue(wxString::Format("%g%%", zoomValue * 100.));
|
||||
}
|
||||
else {
|
||||
wxEventBlocker blocker(this);
|
||||
h = vidH * zoomValue;
|
||||
w = arType == 0 ? vidW * zoomValue : vidH * zoomValue * arValue;
|
||||
|
||||
wxWindow *top = GetParent();
|
||||
while (!top->IsTopLevel()) top = top->GetParent();
|
||||
|
||||
int cw, ch;
|
||||
if (freeSize) {
|
||||
cw = w;
|
||||
ch = h;
|
||||
}
|
||||
else {
|
||||
// Cap the canvas size to the window size
|
||||
int maxH, maxW;
|
||||
top->GetClientSize(&maxW, &maxH);
|
||||
cw = std::min(w, maxW);
|
||||
ch = std::min(h, maxH);
|
||||
}
|
||||
|
||||
viewport_left = 0;
|
||||
viewport_bottom = ch - h;
|
||||
viewport_top = 0;
|
||||
viewport_width = w;
|
||||
viewport_height = h;
|
||||
|
||||
wxSize size(cw, ch);
|
||||
if (size != GetClientSize()) {
|
||||
if (freeSize) {
|
||||
top->SetSize(top->GetSize() + size - GetClientSize());
|
||||
SetClientSize(size);
|
||||
}
|
||||
else {
|
||||
SetMinClientSize(size);
|
||||
SetMaxClientSize(size);
|
||||
|
||||
GetGrandParent()->Layout();
|
||||
|
||||
// The sizer makes us use the full width, which at very low zoom
|
||||
// levels results in stretched video, so after using the sizer to
|
||||
// update the parent window sizes, reset our size to the correct
|
||||
// value
|
||||
SetSize(cw, ch);
|
||||
}
|
||||
viewport_height -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
if (tool)
|
||||
tool->SetDisplayArea(viewport_left, viewport_top, viewport_width, viewport_height);
|
||||
|
||||
Refresh(false);
|
||||
Render();
|
||||
}
|
||||
|
||||
void VideoDisplay::UpdateSize() {
|
||||
if (!con->videoController->IsLoaded() || !IsShownOnScreen()) return;
|
||||
|
||||
videoSize.Set(con->videoController->GetWidth(), con->videoController->GetHeight());
|
||||
videoSize *= zoomValue;
|
||||
if (con->videoController->GetAspectRatioType() != 0)
|
||||
videoSize.SetWidth(videoSize.GetHeight() * con->videoController->GetAspectRatioValue());
|
||||
|
||||
wxEventBlocker blocker(this);
|
||||
if (freeSize) {
|
||||
wxWindow *top = GetParent();
|
||||
while (!top->IsTopLevel()) top = top->GetParent();
|
||||
top->SetSize(top->GetSize() + videoSize - GetClientSize());
|
||||
SetClientSize(videoSize);
|
||||
}
|
||||
else {
|
||||
SetMinClientSize(videoSize);
|
||||
SetMaxClientSize(videoSize);
|
||||
|
||||
GetGrandParent()->Layout();
|
||||
}
|
||||
|
||||
PositionVideo();
|
||||
}
|
||||
|
||||
void VideoDisplay::OnSizeEvent(wxSizeEvent &event) {
|
||||
UpdateSize();
|
||||
event.Skip();
|
||||
if (freeSize) {
|
||||
videoSize = GetClientSize();
|
||||
PositionVideo();
|
||||
zoomValue = double(viewport_height) / con->videoController->GetHeight();
|
||||
zoomBox->ChangeValue(wxString::Format("%g%%", zoomValue * 100.));
|
||||
}
|
||||
else {
|
||||
PositionVideo();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoDisplay::OnMouseEvent(wxMouseEvent& event) {
|
||||
assert(w > 0);
|
||||
|
||||
if (event.ButtonDown())
|
||||
SetFocus();
|
||||
|
||||
|
@ -407,14 +379,14 @@ void VideoDisplay::SetZoom(double value) {
|
|||
zoomValue = std::max(value, .125);
|
||||
zoomBox->SetSelection(value / .125 - 1);
|
||||
zoomBox->ChangeValue(wxString::Format("%g%%", zoomValue * 100.));
|
||||
UpdateSize(true);
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VideoDisplay::SetZoomFromBox(wxCommandEvent &) {
|
||||
int sel = zoomBox->GetSelection();
|
||||
if (sel != wxNOT_FOUND) {
|
||||
zoomValue = (sel + 1) * .125;
|
||||
UpdateSize(true);
|
||||
UpdateSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,10 +407,8 @@ void VideoDisplay::SetTool(VisualToolBase *new_tool) {
|
|||
|
||||
tool.reset(new_tool);
|
||||
tool->SetToolbar(toolBar);
|
||||
tool->SetDisplayArea(viewport_left, viewport_top, viewport_width, viewport_height);
|
||||
|
||||
// Update size as the new typesetting tool may have changed the subtoolbar size
|
||||
GetGrandParent()->Layout();
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
|
|
|
@ -77,10 +77,9 @@ class VideoDisplay : public wxGLCanvas {
|
|||
/// The frame number currently being displayed
|
||||
int currentFrame;
|
||||
|
||||
/// The width of the canvas in screen pixels
|
||||
int w;
|
||||
/// The height of the canvas in screen pixels
|
||||
int h;
|
||||
/// The size of the video in screen at the current zoom level, which may not
|
||||
/// be the same as the actual client size of the display
|
||||
wxSize videoSize;
|
||||
|
||||
Vector2D mouse_pos;
|
||||
|
||||
|
@ -128,8 +127,8 @@ class VideoDisplay : public wxGLCanvas {
|
|||
bool InitContext();
|
||||
|
||||
/// @brief Set the size of the display based on the current zoom and video resolution
|
||||
/// @param force Force the size to be set based on zoom even in detached mode
|
||||
void UpdateSize(bool force = false);
|
||||
void UpdateSize();
|
||||
void PositionVideo();
|
||||
/// Set the zoom level to that indicated by the dropdown
|
||||
void SetZoomFromBox(wxCommandEvent&);
|
||||
/// Set the zoom level to that indicated by the text
|
||||
|
|
Loading…
Reference in a new issue