diff --git a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj
index 4eeb99e36..936106f3c 100644
--- a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj
+++ b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj
@@ -893,6 +893,14 @@
RelativePath="..\..\src\mythes.hxx"
>
+
+
+
+
diff --git a/aegisub/src/Makefile b/aegisub/src/Makefile
index 86b055700..07e3f635a 100644
--- a/aegisub/src/Makefile
+++ b/aegisub/src/Makefile
@@ -198,6 +198,7 @@ SRC += \
md5.c \
mkv_wrap.cpp \
mythes.cxx \
+ persist_location.cpp \
plugin_manager.cpp \
preferences.cpp \
preferences_base.cpp \
diff --git a/aegisub/src/dialog_detached_video.cpp b/aegisub/src/dialog_detached_video.cpp
index 7dc94aa3c..0d65af090 100644
--- a/aegisub/src/dialog_detached_video.cpp
+++ b/aegisub/src/dialog_detached_video.cpp
@@ -46,6 +46,7 @@
#include "dialog_detached_video.h"
#include "frame_main.h"
#include "main.h"
+#include "persist_location.h"
#include "video_box.h"
#include "video_context.h"
#include "video_display.h"
@@ -58,12 +59,6 @@ DialogDetachedVideo::DialogDetachedVideo(FrameMain *parent, agi::Context *contex
: wxDialog(parent,-1,_T("Detached Video"),wxDefaultPosition,wxSize(400,300),wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxWANTS_CHARS)
, parent(parent)
{
- // Set up window
- int x = OPT_GET("Video/Detached/Last/X")->GetInt();
- int y = OPT_GET("Video/Detached/Last/Y")->GetInt();
- if (x != -1 && y != -1) SetPosition(wxPoint(x,y));
- if (OPT_GET("Video/Detached/Maximized")->GetBool()) Maximize();
-
// Set obscure stuff
SetExtraStyle((GetExtraStyle() & ~wxWS_EX_BLOCK_EVENTS) | wxWS_EX_PROCESS_UI_UPDATES);
@@ -89,40 +84,18 @@ DialogDetachedVideo::DialogDetachedVideo(FrameMain *parent, agi::Context *contex
videoBox->SetMinSize(wxSize(1,1));
SetMinSize(wxSize(1,1));
+ persist.reset(new PersistLocation(this, "Video/Detached"));
+
int display_index = wxDisplay::GetFromWindow(this);
- if (display_index == wxNOT_FOUND)
- {
- int caption_size = wxSystemSettings::GetMetric(wxSYS_CAPTION_Y, this);
- Move(parent->GetPosition() + wxPoint(caption_size, caption_size));
- }
- else
- {
+ // Ensure that the dialog is no larger than the screen
+ if (display_index != wxNOT_FOUND) {
wxRect bounds_rect = GetRect();
wxRect disp_rect = wxDisplay(display_index).GetClientArea();
-
- // Ensure our x/y position is past the top left of the display
- int new_x = std::max(bounds_rect.x, disp_rect.x);
- int new_y = std::max(bounds_rect.y, disp_rect.y);
- // Pick the smallest size of display and window.
- // By doing this, we're guaranteed to get a width/height that fits on the display
- // and won't have to adjust width/height any further.
- int new_w = std::min(bounds_rect.width, disp_rect.width);
- int new_h = std::min(bounds_rect.height, disp_rect.height);
-
- // Check if bottom right corner is outside display and move inside then
- if (new_x + new_w > disp_rect.x + disp_rect.width)
- new_x = disp_rect.x + disp_rect.width - new_w;
- if (new_y + new_h > disp_rect.y + disp_rect.height)
- new_y = disp_rect.y + disp_rect.height - new_h;
-
- SetSize(new_x, new_y, new_w, new_h, wxSIZE_ALLOW_MINUS_ONE);
+ SetSize(std::min(bounds_rect.width, disp_rect.width), std::min(bounds_rect.height, disp_rect.height));
}
// Update
parent->SetDisplayMode(0, -1);
- GetPosition(&x, &y);
- OPT_SET("Video/Detached/Last/X")->SetInt(x);
- OPT_SET("Video/Detached/Last/Y")->SetInt(y);
OPT_SET("Video/Detached/Enabled")->SetBool(true);
// Copy the main accelerator table to this dialog
@@ -132,13 +105,11 @@ DialogDetachedVideo::DialogDetachedVideo(FrameMain *parent, agi::Context *contex
/// @brief Destructor
DialogDetachedVideo::~DialogDetachedVideo() {
- OPT_SET("Video/Detached/Maximized")->SetBool(IsMaximized());
}
// Event table
BEGIN_EVENT_TABLE(DialogDetachedVideo,wxDialog)
EVT_CLOSE(DialogDetachedVideo::OnClose)
- EVT_MOVE(DialogDetachedVideo::OnMove)
EVT_ICONIZE(DialogDetachedVideo::OnMinimize)
END_EVENT_TABLE()
@@ -151,14 +122,6 @@ void DialogDetachedVideo::OnClose(wxCloseEvent &WXUNUSED(event)) {
parent->SetDisplayMode(1,-1);
}
-/// @brief Move window
-/// @param event
-void DialogDetachedVideo::OnMove(wxMoveEvent &event) {
- wxPoint pos = event.GetPosition();
- OPT_SET("Video/Detached/Last/X")->SetInt(pos.x);
- OPT_SET("Video/Detached/Last/Y")->SetInt(pos.y);
-}
-
/// @brief Minimize event handler
/// @param event
void DialogDetachedVideo::OnMinimize(wxIconizeEvent &event) {
diff --git a/aegisub/src/dialog_detached_video.h b/aegisub/src/dialog_detached_video.h
index 75657b724..c64748742 100644
--- a/aegisub/src/dialog_detached_video.h
+++ b/aegisub/src/dialog_detached_video.h
@@ -40,8 +40,11 @@
#include
#endif
+#include
+
namespace agi { struct Context; }
class FrameMain;
+class PersistLocation;
class VideoBox;
/// DOCME
@@ -50,7 +53,7 @@ class VideoBox;
///
/// DOCME
class DialogDetachedVideo : public wxDialog {
-private:
+ agi::scoped_ptr persist;
/// DOCME
VideoBox *videoBox;
@@ -59,7 +62,6 @@ private:
FrameMain *parent;
void OnClose(wxCloseEvent &event);
- void OnMove(wxMoveEvent &event);
void OnMinimize(wxIconizeEvent &event);
public:
diff --git a/aegisub/src/persist_location.cpp b/aegisub/src/persist_location.cpp
new file mode 100644
index 000000000..2e5bb50bb
--- /dev/null
+++ b/aegisub/src/persist_location.cpp
@@ -0,0 +1,88 @@
+// Copyright (c) 2011, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+//
+// $Id$
+
+/// @file persist_location.cpp
+/// @see persist_location.h
+/// @ingroup utility
+
+#include "config.h"
+
+#include "persist_location.h"
+
+#include "main.h"
+
+#ifndef AGI_PRE
+#include
+#endif
+
+PersistLocation::PersistLocation(wxDialog *dialog, std::string options_prefix)
+: x_opt(OPT_SET(options_prefix + "/Last/X"))
+, y_opt(OPT_SET(options_prefix + "/Last/Y"))
+, maximize_opt(OPT_SET(options_prefix + "/Maximized"))
+{
+ dialog->Bind(wxEVT_MOVE, &PersistLocation::OnMove, this);
+ dialog->Bind(wxEVT_ICONIZE, &PersistLocation::OnMinimize, this);
+
+ if (maximize_opt->GetBool()) dialog->Maximize();
+
+ int x = x_opt->GetInt();
+ int y = y_opt->GetInt();
+ if (x == -1 && y == -1)
+ dialog->CenterOnParent();
+ else {
+ // First move to the saved place so that it ends up on the right monitor
+ dialog->Move(x, y);
+
+ int display_index = wxDisplay::GetFromWindow(dialog);
+
+ // If it's moved offscreen center on the parent and try again
+ if (display_index == wxNOT_FOUND) {
+ dialog->CenterOnParent();
+ display_index = wxDisplay::GetFromWindow(dialog);
+ }
+
+ // If it's still offscreen just give up
+ if (display_index == wxNOT_FOUND) return;
+
+ wxRect display_area = wxDisplay(display_index).GetClientArea();
+ wxSize dialog_size = dialog->GetSize();
+
+ // Ensure that the top-left corner is onscreen
+ if (x < display_area.x) x = display_area.x;
+ if (y < display_area.y) y = display_area.y;
+
+ // Ensure that the bottom-right corner is onscreen as long as doing so
+ // wouldn't force the top-left corner offscreen
+ if (x + dialog_size.x > display_area.GetRight())
+ x = std::max(display_area.x, display_area.GetRight() - dialog_size.x);
+ if (y + dialog_size.y > display_area.GetBottom())
+ y = std::max(display_area.y, display_area.GetBottom() - dialog_size.y);
+
+ dialog->Move(x, y);
+ }
+}
+
+void PersistLocation::OnMove(wxMoveEvent &evt) {
+ wxPoint pos = evt.GetPosition();
+ x_opt->SetInt(pos.x);
+ y_opt->SetInt(pos.y);
+}
+
+void PersistLocation::OnMinimize(wxIconizeEvent &evt) {
+ maximize_opt->SetBool(!evt.IsIconized());
+}
diff --git a/aegisub/src/persist_location.h b/aegisub/src/persist_location.h
new file mode 100644
index 000000000..3ebc87c69
--- /dev/null
+++ b/aegisub/src/persist_location.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+//
+// $Id$
+
+/// @file persist_location.h
+/// @see persist_location.cpp
+/// @ingroup utility
+
+namespace agi { class OptionValue; }
+class wxDialog;
+
+/// @class PersistLocation
+/// @brief Automatically save and restore the location of a dialog
+///
+/// This class saves the location of the supplied dialog to the preferences
+/// file with the given prefix, then restores the saved position when it is
+/// recreated in the future. This class should always have lifetime equal to
+/// the associated dialog, as it does not unbind its events.
+class PersistLocation {
+ agi::OptionValue *x_opt;
+ agi::OptionValue *y_opt;
+ agi::OptionValue *maximize_opt;
+
+ void OnMove(wxMoveEvent &evt);
+ void OnMinimize(wxIconizeEvent &evt);
+
+public:
+ /// Persist the location of a dialog
+ /// @param dialog The dialog to save and restore the position of
+ /// @param options_prefix Prefix for the options names to store the location
+ PersistLocation(wxDialog *dialog, std::string options_prefix);
+};