Android release v6.7_preview1
[xcsoar.git] / src / Widget / TwoWidgets.cpp
blob82188ac3be1ecd2946bf3280b691a68edaa335c1
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "TwoWidgets.hpp"
26 #include <algorithm>
28 TwoWidgets::~TwoWidgets()
30 delete second;
31 delete first;
34 void
35 TwoWidgets::UpdateLayout()
37 const auto layout = CalculateLayout(rc);
38 first->Move(layout.first);
39 second->Move(layout.second);
42 gcc_const
43 static int
44 CalculateSplit(int top, int bottom, unsigned min_a,
45 unsigned min_b, unsigned max_b)
47 assert(bottom >= top);
48 assert(min_b <= max_b);
50 const unsigned height = bottom - top;
52 if (min_a <= 0 || min_b <= 0)
53 /* at least one Widet doesn't know its minimums size; there may be
54 better solutions for this, but this workaround is good enough
55 for fixing the assertion failure in DevicesConfigPanel */
56 return (top + bottom) / 2;
57 else if (height >= min_a + max_b)
58 /* more than enough space: align the second Widget at the bottom
59 and give the rest to the first Widget */
60 return bottom - max_b;
61 else if (height >= min_a + min_b)
62 /* still somewhat enough space */
63 return bottom - min_b;
64 else {
65 /* give the best for the rest */
66 const PixelScalar first_height =
67 std::min(min_a, height / 2);
68 return top + first_height;
72 PixelScalar
73 TwoWidgets::CalculateSplit(const PixelRect &rc) const
75 const PixelSize min_a = first->GetMinimumSize();
76 const PixelSize min_b = second->GetMinimumSize();
77 const PixelSize max_b = second->GetMaximumSize();
79 return vertical
80 ? ::CalculateSplit(rc.top, rc.bottom, min_a.cy,
81 min_b.cy, max_b.cy)
82 : ::CalculateSplit(rc.left, rc.right, min_a.cx,
83 min_b.cx, max_b.cx);
86 std::pair<PixelRect,PixelRect>
87 TwoWidgets::CalculateLayout(const PixelRect &rc) const
89 PixelRect a = rc, b = rc;
90 if (vertical)
91 a.bottom = b.top = CalculateSplit(rc);
92 else
93 a.right = b.left = CalculateSplit(rc);
94 return std::make_pair(a, b);
97 PixelSize
98 TwoWidgets::GetMinimumSize() const
100 const PixelSize a = first->GetMinimumSize();
101 const PixelSize b = second->GetMinimumSize();
103 return vertical
104 ? PixelSize{ std::max(a.cx, b.cx), a.cy + b.cy }
105 : PixelSize{ a.cx + b.cx, std::max(a.cy, b.cy) };
108 PixelSize
109 TwoWidgets::GetMaximumSize() const
111 const PixelSize a = first->GetMaximumSize();
112 const PixelSize b = second->GetMaximumSize();
114 return vertical
115 ? PixelSize{ std::max(a.cx, b.cx), a.cy + b.cy }
116 : PixelSize{ a.cx + b.cx, std::max(a.cy, b.cy) };
120 * Calculates a "dummy" layout that is splitted in the middle. In
121 * TwoWidgets::Initialise() and TwoWidgets::Prepare(), we are not
122 * allowed to call Widget::GetMinimumSize() yet.
124 gcc_const
125 static std::pair<PixelRect,PixelRect>
126 DummyLayout(const PixelRect rc, bool vertical)
128 PixelRect a = rc, b = rc;
129 if (vertical)
130 a.bottom = b.top = (rc.top + rc.bottom) / 2;
131 else
132 a.right = b.left = (rc.left + rc.right) / 2;
133 return std::make_pair(a, b);
136 void
137 TwoWidgets::Initialise(ContainerWindow &parent, const PixelRect &rc)
139 this->rc = rc;
140 const auto layout = DummyLayout(rc, vertical);
141 first->Initialise(parent, layout.first);
142 second->Initialise(parent, layout.second);
145 void
146 TwoWidgets::Prepare(ContainerWindow &parent, const PixelRect &rc)
148 this->rc = rc;
149 const auto layout = DummyLayout(rc, vertical);
150 first->Prepare(parent, layout.first);
151 second->Prepare(parent, layout.second);
154 void
155 TwoWidgets::Unprepare()
157 first->Unprepare();
158 second->Unprepare();
161 bool
162 TwoWidgets::Save(bool &changed)
164 return first->Save(changed) && second->Save(changed);
167 bool
168 TwoWidgets::Click()
170 return first->Click() || second->Click();
173 void
174 TwoWidgets::ReClick()
176 first->ReClick();
177 second->ReClick();
180 void
181 TwoWidgets::Show(const PixelRect &rc)
183 this->rc = rc;
184 const auto layout = CalculateLayout(rc);
185 first->Show(layout.first);
186 second->Show(layout.second);
189 bool
190 TwoWidgets::Leave()
192 return first->Leave() && second->Leave();
195 void
196 TwoWidgets::Hide()
198 first->Hide();
199 second->Hide();
202 void
203 TwoWidgets::Move(const PixelRect &rc)
205 this->rc = rc;
206 const auto layout = CalculateLayout(rc);
207 first->Move(layout.first);
208 second->Move(layout.second);
211 bool
212 TwoWidgets::SetFocus()
214 return first->SetFocus() || second->SetFocus();