1 // Copyright (c) 2011, Thomas Goyne <plorkyeran@aegisub.org>
2 //
3 // Permission to use, copy, modify, and distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 //
15 // Aegisub Project http://www.aegisub.org/
16 
17 /// @file persist_location.cpp
18 /// @see persist_location.h
19 /// @ingroup utility
20 
21 #include "persist_location.h"
22 
23 #include "options.h"
24 
25 #include <wx/dialog.h>
26 #include <wx/display.h>
27 
PersistLocation(wxDialog * dialog,std::string options_prefix,bool size_too)28 PersistLocation::PersistLocation(wxDialog *dialog, std::string options_prefix, bool size_too)
29 : x_opt(OPT_SET(options_prefix + "/Last/X"))
30 , y_opt(OPT_SET(options_prefix + "/Last/Y"))
31 , w_opt(size_too ? OPT_SET(options_prefix + "/Last/Width") : nullptr)
32 , h_opt(size_too ? OPT_SET(options_prefix + "/Last/Height") : nullptr)
33 , maximize_opt(OPT_SET(options_prefix + "/Maximized"))
34 , dialog(dialog)
35 {
36 	int x = x_opt->GetInt();
37 	int y = y_opt->GetInt();
38 	if (x == -1 && y == -1)
39 		dialog->CenterOnParent();
40 	else {
41 		// First move to the saved place so that it ends up on the right monitor
42 		dialog->Move(x, y);
43 
44 		if (size_too && w_opt->GetInt() > 0 && h_opt->GetInt() > 0)
45 			dialog->SetSize(w_opt->GetInt(), h_opt->GetInt());
46 
47 		int display_index = wxDisplay::GetFromWindow(dialog);
48 
49 		// If it's moved offscreen center on the parent and try again
50 		if (display_index == wxNOT_FOUND) {
51 			dialog->CenterOnParent();
52 			display_index = wxDisplay::GetFromWindow(dialog);
53 		}
54 
55 		// If it's still offscreen just give up
56 		if (display_index == wxNOT_FOUND) return;
57 
58 		wxRect display_area = wxDisplay(display_index).GetClientArea();
59 		wxSize dialog_size = dialog->GetSize();
60 
61 		// Ensure that the top-left corner is onscreen
62 		if (x < display_area.x) x = display_area.x;
63 		if (y < display_area.y) y = display_area.y;
64 
65 		// Ensure that the bottom-right corner is onscreen as long as doing so
66 		// wouldn't force the top-left corner offscreen
67 		if (x + dialog_size.x > display_area.GetRight())
68 			x = std::max(display_area.x, display_area.GetRight() - dialog_size.x);
69 		if (y + dialog_size.y > display_area.GetBottom())
70 			y = std::max(display_area.y, display_area.GetBottom() - dialog_size.y);
71 
72 		dialog->Move(x, y);
73 	}
74 
75 	dialog->Bind(wxEVT_MOVE, &PersistLocation::OnMove, this);
76 
77 	dialog->Bind(wxEVT_SIZE, &PersistLocation::OnSize, this);
78 	if ((dialog->GetWindowStyle() & wxMAXIMIZE_BOX) && maximize_opt->GetBool())
79 		dialog->Maximize();
80 }
81 
OnMove(wxMoveEvent & e)82 void PersistLocation::OnMove(wxMoveEvent &e) {
83 	wxPoint pos = dialog->GetPosition();
84 	x_opt->SetInt(pos.x);
85 	y_opt->SetInt(pos.y);
86 	e.Skip();
87 }
88 
OnSize(wxSizeEvent & e)89 void PersistLocation::OnSize(wxSizeEvent &e) {
90 	maximize_opt->SetBool(dialog->IsMaximized());
91 	if (w_opt) {
92 		w_opt->SetInt(dialog->GetSize().GetWidth());
93 		h_opt->SetInt(dialog->GetSize().GetHeight());
94 	}
95 	e.Skip();
96 }
97