1 // Copyright (c) 2007, Rodrigo Braz Monteiro
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of the Aegisub Group nor the names of its contributors
13 //     may be used to endorse or promote products derived from this software
14 //     without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE.
27 //
28 // Aegisub Project http://www.aegisub.org/
29 
30 /// @file dialog_detached_video.cpp
31 /// @brief Detached video window
32 /// @ingroup main_ui
33 ///
34 
35 #include "dialog_detached_video.h"
36 
37 #include "format.h"
38 #include "include/aegisub/context.h"
39 #include "include/aegisub/hotkey.h"
40 #include "options.h"
41 #include "persist_location.h"
42 #include "project.h"
43 #include "utils.h"
44 #include "video_box.h"
45 #include "video_controller.h"
46 #include "video_display.h"
47 
48 #include <libaegisub/format_path.h>
49 #include <libaegisub/make_unique.h>
50 
51 #include <boost/filesystem/path.hpp>
52 
53 #include <wx/sizer.h>
54 #include <wx/display.h> /// Must be included last.
55 
DialogDetachedVideo(agi::Context * context)56 DialogDetachedVideo::DialogDetachedVideo(agi::Context *context)
57 : wxDialog(context->parent, -1, "Detached Video", wxDefaultPosition, wxSize(400,300), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxWANTS_CHARS)
58 , context(context)
59 , old_display(context->videoDisplay)
60 , old_slider(context->videoSlider)
61 , video_open(context->project->AddVideoProviderListener(&DialogDetachedVideo::OnVideoOpen, this))
62 {
63 	// Set obscure stuff
64 	SetExtraStyle((GetExtraStyle() & ~wxWS_EX_BLOCK_EVENTS) | wxWS_EX_PROCESS_UI_UPDATES);
65 
66 	SetTitle(fmt_tl("Video: %s", context->project->VideoName().filename()));
67 
68 	old_display->Unload();
69 
70 	// Video area;
71 	auto videoBox = new VideoBox(this, true, context);
72 	context->videoDisplay->SetMinClientSize(old_display->GetClientSize());
73 	videoBox->Layout();
74 
75 	// Set sizer
76 	wxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
77 	mainSizer->Add(videoBox,1,wxEXPAND);
78 	SetSizerAndFit(mainSizer);
79 
80 	// Ensure we can grow smaller, without these the window is locked to at least the initial size
81 	context->videoDisplay->SetMinSize(wxSize(1,1));
82 	videoBox->SetMinSize(wxSize(1,1));
83 	SetMinSize(wxSize(1,1));
84 
85 	persist = agi::make_unique<PersistLocation>(this, "Video/Detached");
86 
87 	int display_index = wxDisplay::GetFromWindow(this);
88 	// Ensure that the dialog is no larger than the screen
89 	if (display_index != wxNOT_FOUND) {
90 		wxRect bounds_rect = GetRect();
91 		wxRect disp_rect = wxDisplay(display_index).GetClientArea();
92 		SetSize(std::min(bounds_rect.width, disp_rect.width), std::min(bounds_rect.height, disp_rect.height));
93 	}
94 
95 	OPT_SET("Video/Detached/Enabled")->SetBool(true);
96 
97 	Bind(wxEVT_CLOSE_WINDOW, &DialogDetachedVideo::OnClose, this);
98 	Bind(wxEVT_ICONIZE, &DialogDetachedVideo::OnMinimize, this);
99 	Bind(wxEVT_CHAR_HOOK, &DialogDetachedVideo::OnKeyDown, this);
100 
101 	AddFullScreenButton(this);
102 }
103 
~DialogDetachedVideo()104 DialogDetachedVideo::~DialogDetachedVideo() { }
105 
OnClose(wxCloseEvent & evt)106 void DialogDetachedVideo::OnClose(wxCloseEvent &evt) {
107 	context->videoDisplay->Destroy();
108 
109 	context->videoDisplay = old_display;
110 	context->videoSlider = old_slider;
111 
112 	OPT_SET("Video/Detached/Enabled")->SetBool(false);
113 
114 	context->videoController->JumpToFrame(context->videoController->GetFrameN());
115 
116 	evt.Skip();
117 }
118 
OnMinimize(wxIconizeEvent & event)119 void DialogDetachedVideo::OnMinimize(wxIconizeEvent &event) {
120 	if (event.IsIconized()) {
121 		// Force the video display to repaint as otherwise the last displayed
122 		// frame stays visible even though the dialog is minimized
123 		Hide();
124 		Show();
125 	}
126 }
127 
OnKeyDown(wxKeyEvent & evt)128 void DialogDetachedVideo::OnKeyDown(wxKeyEvent &evt) {
129 	hotkey::check("Video Display", context, evt);
130 }
131 
OnVideoOpen(AsyncVideoProvider * new_provider)132 void DialogDetachedVideo::OnVideoOpen(AsyncVideoProvider *new_provider) {
133 	if (new_provider)
134 		SetTitle(fmt_tl("Video: %s", context->project->VideoName().filename()));
135 	else {
136 		Close();
137 		OPT_SET("Video/Detached/Enabled")->SetBool(true);
138 	}
139 }
140