1 #include "filezilla.h"
2 #include "splitter.h"
3 
BEGIN_EVENT_TABLE(CSplitterWindowEx,wxSplitterWindow)4 BEGIN_EVENT_TABLE(CSplitterWindowEx, wxSplitterWindow)
5 EVT_SIZE(CSplitterWindowEx::OnSize)
6 END_EVENT_TABLE()
7 
8 CSplitterWindowEx::CSplitterWindowEx()
9 {
10 }
11 
CSplitterWindowEx(wxWindow * parent,wxWindowID id,wxPoint const & point,wxSize const & size,long style,wxString const & name)12 CSplitterWindowEx::CSplitterWindowEx(wxWindow* parent, wxWindowID id, wxPoint const& point, wxSize const& size, long style, wxString const& name)
13 	: wxSplitterWindow(parent, id, point, size, style, name)
14 {
15 }
16 
Create(wxWindow * parent,wxWindowID id,wxPoint const & point,wxSize const & size,long style,wxString const & name)17 bool CSplitterWindowEx::Create(wxWindow* parent, wxWindowID id, wxPoint const& point, wxSize const& size, long style, wxString const& name)
18 {
19 	return wxSplitterWindow::Create(parent, id, point, size, style, name);
20 }
21 
SetSashGravity(double gravity)22 void CSplitterWindowEx::SetSashGravity(double gravity)
23 {
24 	// Only support these three for now
25 	wxASSERT(gravity == 0.0 || gravity == 0.5 || gravity == 1.0);
26 
27 	wxSplitterWindow::SetSashGravity(gravity);
28 }
29 
OnSize(wxSizeEvent & event)30 void CSplitterWindowEx::OnSize(wxSizeEvent& event)
31 {
32 	// Code copied from wxWidgets and adjusted for better gravity handling
33 
34 	// only process this message if we're not iconized - otherwise iconizing
35 	// and restoring a window containing the splitter has a funny side effect
36 	// of changing the splitter position!
37 	wxWindow *parent = wxGetTopLevelParent(this);
38 	bool iconized;
39 
40 	auto winTop = dynamic_cast<wxTopLevelWindow*>(parent);
41 	if (winTop) {
42 		iconized = winTop->IsIconized();
43 	}
44 	else {
45 		wxFAIL_MSG(wxT("should have a top level parent!"));
46 
47 		iconized = false;
48 	}
49 
50 	if (iconized) {
51 		m_lastSize = wxSize(0, 0);
52 
53 		event.Skip();
54 
55 		return;
56 	}
57 
58 	if (m_windowTwo) {
59 		int w, h;
60 		GetClientSize(&w, &h);
61 
62 		int size = (m_splitMode == wxSPLIT_VERTICAL) ? w : h;
63 
64 		int newPosition = m_sashPosition;
65 
66 		int const old_size = (m_splitMode == wxSPLIT_VERTICAL) ? m_lastSize.x : m_lastSize.y;
67 		if (old_size != 0 ) {
68 			if (m_sashGravity == 0.5) {
69 				newPosition = static_cast<int>(size * m_relative_sash_position);
70 			}
71 			else if (m_sashGravity == 1.0) {
72 				int delta = size - old_size;
73 				if (delta != 0) {
74 					newPosition = m_sashPosition + delta;
75 					if (newPosition < m_minimumPaneSize) {
76 						newPosition = m_minimumPaneSize;
77 					}
78 				}
79 			}
80 			else {
81 				if (newPosition > size - m_minimumPaneSize - GetSashSize()) {
82 					newPosition = size - m_minimumPaneSize - GetSashSize();
83 				}
84 			}
85 		}
86 
87 		if (newPosition >= size - 5) {
88 			newPosition = wxMax(10, size - 40);
89 		}
90 
91 		newPosition = CalcSoftLimit(newPosition);
92 
93 		if (newPosition != m_sashPosition) {
94 			SetSashPositionAndNotify(newPosition);
95 		}
96 
97 		m_lastSize = wxSize(w,h);
98 	}
99 
100 	SizeWindows();
101 }
102 
SetMinimumPaneSize(int paneSize,int paneSize_soft)103 void CSplitterWindowEx::SetMinimumPaneSize(int paneSize, int paneSize_soft)
104 {
105 	wxASSERT(paneSize_soft >= paneSize || paneSize_soft == -1);
106 
107 	wxSplitterWindow::SetMinimumPaneSize(paneSize);
108 
109 	m_soft_min_pane_size = paneSize_soft;
110 }
111 
OnSashPositionChanging(int newSashPosition)112 int CSplitterWindowEx::OnSashPositionChanging(int newSashPosition)
113 {
114 	newSashPosition = AdjustSashPosition(newSashPosition);
115 	newSashPosition = CalcSoftLimit(newSashPosition);
116 
117 	newSashPosition = wxSplitterWindow::OnSashPositionChanging(newSashPosition);
118 
119 	if (newSashPosition != -1) {
120 		int w, h;
121 		GetClientSize(&w, &h);
122 
123 		int size = m_splitMode == wxSPLIT_VERTICAL ? w : h;
124 
125 		m_relative_sash_position = static_cast<double>(newSashPosition) / size;
126 	}
127 
128 	return newSashPosition;
129 }
130 
CalcSoftLimit(int newSashPosition)131 int CSplitterWindowEx::CalcSoftLimit(int newSashPosition)
132 {
133 	if (m_soft_min_pane_size != -1) {
134 		int w, h;
135 		GetClientSize(&w, &h);
136 
137 		int size = m_splitMode == wxSPLIT_VERTICAL ? w : h;
138 
139 		int limit = size / 2;
140 		if (limit > m_soft_min_pane_size) {
141 			limit = m_soft_min_pane_size;
142 		}
143 		if (newSashPosition < limit) {
144 			newSashPosition = limit;
145 		}
146 		else if (newSashPosition > size - limit - GetSashSize()) {
147 			newSashPosition = wxMax(limit, size - limit - GetSashSize());
148 		}
149 	}
150 
151 	return newSashPosition;
152 }
153 
SetRelativeSashPosition(double relative_sash_position)154 void CSplitterWindowEx::SetRelativeSashPosition(double relative_sash_position)
155 {
156 	wxASSERT(relative_sash_position >= 0 && relative_sash_position <= 1);
157 
158 	int w, h;
159 	GetClientSize(&w, &h);
160 
161 	int size = m_splitMode == wxSPLIT_VERTICAL ? w : h;
162 
163 	wxSplitterWindow::SetSashPosition((int)(size * relative_sash_position));
164 
165 	m_relative_sash_position = relative_sash_position;
166 }
167 
SetSashPosition(int sash_position)168 void CSplitterWindowEx::SetSashPosition(int sash_position)
169 {
170 	if (!m_windowTwo) {
171 		m_lastSashPosition = sash_position;
172 		return;
173 	}
174 
175 	int w, h;
176 	GetClientSize(&w, &h);
177 
178 	int size = (m_splitMode == wxSPLIT_VERTICAL) ? w : h;
179 
180 	if (!sash_position) {
181 		sash_position = size / 2;
182 	}
183 	if (sash_position < 0 && m_sashGravity == 1.0) {
184 		sash_position = size + sash_position - GetSashSize();
185 	}
186 
187 	wxSplitterWindow::SetSashPosition(sash_position);
188 
189 	m_relative_sash_position = static_cast<double>(sash_position) / size;
190 }
191 
Unsplit(wxWindow * toRemove)192 bool CSplitterWindowEx::Unsplit(wxWindow* toRemove)
193 {
194 	if (m_sashGravity == 1) {
195 		int w, h;
196 		GetClientSize(&w, &h);
197 
198 		int size = m_splitMode == wxSPLIT_VERTICAL ? w : h;
199 
200 		m_lastSashPosition = m_sashPosition + GetSashSize() - size;
201 	}
202 	else {
203 		m_lastSashPosition = m_sashPosition;
204 	}
205 
206 	return wxSplitterWindow::Unsplit(toRemove);
207 }
208 
PrepareSplit(wxWindow * window1,wxWindow * window2,int & sashPosition,bool horizontal)209 void CSplitterWindowEx::PrepareSplit(wxWindow* window1, wxWindow* window2, int & sashPosition, bool horizontal)
210 {
211 	int w, h;
212 	GetClientSize(&w, &h);
213 
214 	int size = horizontal ? h : w;
215 
216 	if (sashPosition == 0) {
217 		if (m_sashGravity == 0.5) {
218 			sashPosition = (int)(size * m_relative_sash_position);
219 		}
220 		else if (m_lastSashPosition != -1) {
221 			if (m_lastSashPosition < 0) {
222 				sashPosition = size + m_lastSashPosition - GetSashSize();
223 			}
224 			else {
225 				sashPosition = m_lastSashPosition;
226 			}
227 		}
228 	}
229 
230 	// Needs to be set to avoid resizing oddity:
231 	// Maximize window -> Unsplit -> Restore -> Split -> Resize window
232 	m_lastSize = wxSize(w, h);
233 
234 	if (window1 && window2) {
235 		window1->MoveBeforeInTabOrder(window2);
236 	}
237 }
238 
SplitHorizontally(wxWindow * window1,wxWindow * window2,int sashPosition)239 bool CSplitterWindowEx::SplitHorizontally(wxWindow* window1, wxWindow* window2, int sashPosition /*=0*/)
240 {
241 	PrepareSplit(window1, window2, sashPosition, true);
242 	return wxSplitterWindow::SplitHorizontally(window1, window2, sashPosition);
243 }
244 
SplitVertically(wxWindow * window1,wxWindow * window2,int sashPosition)245 bool CSplitterWindowEx::SplitVertically(wxWindow* window1, wxWindow* window2, int sashPosition /*=0*/)
246 {
247 	PrepareSplit(window1, window2, sashPosition, false);
248 	return wxSplitterWindow::SplitVertically(window1, window2, sashPosition);
249 }
250 
GetSashPosition() const251 int CSplitterWindowEx::GetSashPosition() const
252 {
253 	if (m_windowTwo || m_lastSashPosition == -1) {
254 		int sashPosition = wxSplitterWindow::GetSashPosition();
255 
256 		if (m_sashGravity == 1.0) {
257 			int w, h;
258 			GetClientSize(&w, &h);
259 
260 			int size = m_splitMode == wxSPLIT_VERTICAL ? w : h;
261 
262 			sashPosition = sashPosition + GetSashSize() - size;
263 		}
264 
265 		return sashPosition;
266 	}
267 
268 	return m_lastSashPosition;
269 }
270 
Initialize(wxWindow * window)271 void CSplitterWindowEx::Initialize(wxWindow *window)
272 {
273 	wxSplitterWindow::Initialize(window);
274 
275 	SizeWindows();
276 }
277