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