neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
tab_page_container.ipp
Go to the documentation of this file.
1// tab_page_container.ipp
2/*
3neogfx C++ App/Game Engine
4Copyright (c) 2021 Leigh Johnston. All Rights Reserved.
5
6This program is free software: you can redistribute it and / or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
25
26namespace neogfx
27{
28 template <typename Base>
30 base_type{}, iContainerLayout{ *this }, iTabBar{ iContainerLayout.top(), *this, aClosableTabs, aStyle }
31 {
32 init();
33 }
34
35 template <typename Base>
37 base_type{ aParent }, iContainerLayout{ *this }, iTabBar{ iContainerLayout.top(), *this, aClosableTabs, aStyle }
38 {
39 init();
40 }
41
42 template <typename Base>
43 inline tab_page_container<Base>::tab_page_container(i_widget& aParent, i_layout& aTabBarLayout, bool aClosableTabs, neogfx::tab_container_style aStyle) :
44 base_type{ aParent }, iContainerLayout{ *this }, iTabBar{ aTabBarLayout, *this, aClosableTabs, aStyle }
45 {
46 init();
47 }
49 template <typename Base>
51 base_type{ aLayout }, iContainerLayout{ *this }, iTabBar{ iContainerLayout.top(), *this, aClosableTabs, aStyle }
52 {
53 init();
54 }
56 template <typename Base>
57 inline tab_page_container<Base>::tab_page_container(i_layout& aLayout, i_layout& aTabBarLayout, bool aClosableTabs, neogfx::tab_container_style aStyle) :
58 base_type{ aLayout }, iContainerLayout{ *this }, iTabBar{ aTabBarLayout, *this, aClosableTabs, aStyle }
59 {
60 init();
61 }
62
63 template <typename Base>
65 {
66 base_type::set_destroying();
67 while (tab_count() > 0)
68 remove_tab(tab_count() - 1);
69 }
71 template <typename Base>
73 {
74 return iTabBar;
75 }
77 template <typename Base>
79 {
80 return iContainerLayout.center();
81 }
83 template <typename Base>
85 {
86 return iTabBar.closable_tabs();
87 }
89 template <typename Base>
91 {
92 iTabBar.set_closable_tabs(aClosableTabs);
93 }
95 template <typename Base>
97 {
98 return iTabBar.tab_container_style();
99 }
101 template <typename Base>
104 if (tab_container_style() != aStyle)
105 {
106 iTabBar.set_tab_container_style(aStyle);
107 update_tab_bar_placement();
108 StyleChanged.trigger();
109 }
110 }
111
112 template <typename Base>
114 {
115 iTabBar.set_tab_icon_size(aIconSize);
116 }
117
118 template <typename Base>
119 inline bool tab_page_container<Base>::has_tabs() const noexcept
120 {
121 return !iTabs.empty();
122 }
123
124 template <typename Base>
125 inline uint32_t tab_page_container<Base>::tab_count() const noexcept
126 {
127 return static_cast<uint32_t>(iTabs.size());
128 }
129
130 template <typename Base>
132 {
133 return iTabBar.index_of(aTab);
134 }
135
136 template <typename Base>
137 inline const i_tab& tab_page_container<Base>::tab(tab_index aTabIndex) const
138 {
139 if (aTabIndex >= iTabs.size())
140 throw tab_not_found();
141 return iTabBar.tab(aTabIndex);
142 }
143
144 template <typename Base>
145 inline i_tab& tab_page_container<Base>::tab(tab_index aTabIndex)
146 {
147 return const_cast<i_tab&>(to_const(*this).tab(aTabIndex));
148 }
149
150 template <typename Base>
151 inline bool tab_page_container<Base>::has_tab_page(tab_index aTabIndex) const
152 {
153 if (aTabIndex >= iTabs.size())
154 throw tab_not_found();
155 auto existing = iTabs.find(&tab(aTabIndex));
156 if (existing == iTabs.end())
157 throw tab_not_found();
158 return existing->second != nullptr;
159 }
160
161 template <typename Base>
162 inline const i_tab_page& tab_page_container<Base>::tab_page(tab_index aTabIndex) const
163 {
164 if (aTabIndex >= iTabs.size())
165 throw tab_not_found();
166 auto existing = iTabs.find(&tab(aTabIndex));
167 if (existing == iTabs.end())
168 throw tab_not_found();
169 auto const& tabPagePtr = existing->second;
170 if (tabPagePtr == nullptr)
171 throw tab_page_not_found();
172 return *tabPagePtr;
173 }
174
175 template <typename Base>
177 {
178 return const_cast<i_tab_page&>(to_const(*this).tab_page(aTabIndex));
179 }
180
181 template <typename Base>
182 inline bool tab_page_container<Base>::is_tab_selected() const noexcept
183 {
184 for (auto& tab : iTabs)
185 if (tab.first->is_selected())
186 return true;
187 return false;
188 }
189
190 template <typename Base>
192 {
193 for (auto& tab : iTabs)
194 if (tab.first->is_selected())
195 return *tab.first;
196 throw tab_not_found();
197 }
198
199 template <typename Base>
201 {
202 return const_cast<i_tab&>(to_const(*this).selected_tab());
203 }
204
205 template <typename Base>
207 {
208 for (auto& tab : iTabs)
209 if (tab.first->is_selected())
210 {
211 if (tab.second == nullptr)
212 throw tab_page_not_found();
213 return *tab.second;
214 }
215 throw tab_not_found();
216 }
217
218 template <typename Base>
220 {
221 return const_cast<i_tab_page&>(to_const(*this).selected_tab_page());
222 }
223
224 template <typename Base>
226 {
227 auto& newTab = iTabBar.add_tab(aTabText);
228 iTabs.emplace(&newTab, tab_page_pointer{});
229 return newTab;
230 }
231
232 template <typename Base>
233 inline i_tab& tab_page_container<Base>::insert_tab(tab_index aTabIndex, i_string const& aTabText)
234 {
235 auto& newTab = iTabBar.insert_tab(aTabIndex, aTabText);
236 iTabs.emplace(&newTab, tab_page_pointer{});
237 return newTab;
238 }
239
240 template <typename Base>
241 inline void tab_page_container<Base>::remove_tab(tab_index aTabIndex)
242 {
243 iTabBar.remove_tab(aTabIndex);
244 }
245
246 template <typename Base>
247 inline void tab_page_container<Base>::show_tab(tab_index aTabIndex)
248 {
249 tab(aTabIndex).as_widget().show();
250 if (has_tab_page(aTabIndex))
251 tab_page(aTabIndex).as_widget().show();
252 }
253
254 template <typename Base>
255 inline void tab_page_container<Base>::hide_tab(tab_index aTabIndex)
256 {
257 tab(aTabIndex).as_widget().hide();
258 if (has_tab_page(aTabIndex))
259 tab_page(aTabIndex).as_widget().hide();
260 }
261
262 template <typename Base>
264 {
265 return iTabBar.next_visible_tab(aStartFrom);
266 }
267
268 template <typename Base>
270 {
271 return iTabBar.previous_visible_tab(aStartFrom);
272 }
273
274 template <typename Base>
276 {
277 iTabBar.select_next_tab();
278 }
279
280 template <typename Base>
282 {
283 iTabBar.select_previous_tab();
284 }
285
286 template <typename Base>
288 {
289 return add_tab_page(add_tab(aTabText));
290 }
291
292 template <typename Base>
293 inline i_tab_page& tab_page_container<Base>::insert_tab_page(tab_index aTabIndex, i_string const& aTabText)
294 {
295 return add_tab_page(insert_tab(aTabIndex, aTabText));
296 }
297
298 template <typename Base>
300 {
301 return add_tab_page(aTab, tab_page_pointer{ new neogfx::tab_page{ page_layout(), aTab } });
302 }
303
304 template <typename Base>
306 {
307 return add_tab_page(aTab, tab_page_pointer{ tab_page_pointer{}, &aWidget });
308 }
309
310 template <typename Base>
312 {
313 auto existingTab = iTabs.find(&aTab);
314 if (existingTab == iTabs.end())
315 throw tab_not_found();
316 existingTab->second = aWidget;
317 if (aTab.is_selected())
318 {
319 existingTab->second->as_widget().show();
321 existingTab->second->as_widget().set_focus();
322 iContainerLayout.update_layout();
323 }
324 else
325 existingTab->second->as_widget().hide();
326 TabPageAdded.trigger(*aWidget);
327 return *existingTab->second;
328 }
329
330 template <typename Base>
332 {
333 auto existingTab = iTabs.find(&aPage.tab());
334 if (existingTab != iTabs.end())
335 remove_tab(index_of(aPage.tab()));
336 }
337
338 template <typename Base>
340 {
341 iTabs.emplace(&aTab, tab_page_pointer{});
342 if (iTabs.size() == 1)
343 aTab.select();
344 }
345
346 template <typename Base>
348 {
349 for (auto& tab : iTabs)
350 if (tab.second != nullptr)
351 {
352 if (tab.first == &aTab)
353 {
354 tab.second->as_widget().show();
356 tab.second->as_widget().set_focus();
357 }
358 else
359 tab.second->as_widget().hide();
360 }
361 iContainerLayout.update_layout();
362 }
363
364 template <typename Base>
366 {
367 auto existingTab = iTabs.find(&aTab);
368 if (existingTab == iTabs.end())
369 throw tab_not_found();
370 auto temp = existingTab->second;
371 iTabs.erase(existingTab);
372 TabPageRemoved.trigger(*temp);
373 }
374
375 template <typename Base>
377 {
378 return false;
379 }
380
381 template <typename Base>
386
387 template <typename Base>
392
393 template <typename Base>
395 {
396 return *this;
397 }
398
399 template <typename Base>
401 {
402 return *this;
403 }
404
405 template <typename Base>
407 {
408 return true;
409 }
410
411 template <typename Base>
413 {
414 base_type::set_padding(neogfx::padding{});
415 iContainerLayout.set_padding(neogfx::padding{});
417 page_layout().parent_layout().set_minimum_size({});
418 update_tab_bar_placement();
419
421 }
422
423 template <typename Base>
424 inline void tab_page_container<Base>::update_tab_bar_placement()
425 {
427 {
429 iTabBar.parent_layout().set_size_policy({});
430 iTabBar.parent_layout().remove(iTabBar);
431 iContainerLayout.top().add(iTabBar);
432 iTabBar.parent_layout().set_size_policy(size_constraint::MinimumExpanding, size_constraint::Minimum);
433 break;
435 iTabBar.parent_layout().set_size_policy({});
436 iTabBar.parent_layout().remove(iTabBar);
437 iContainerLayout.bottom().add(iTabBar);
438 iTabBar.parent_layout().set_size_policy(size_constraint::MinimumExpanding, size_constraint::Minimum);
439 break;
441 iTabBar.parent_layout().set_size_policy({});
442 iTabBar.parent_layout().remove(iTabBar);
443 iContainerLayout.left().add(iTabBar);
444 iTabBar.parent_layout().set_size_policy(size_constraint::Minimum, size_constraint::MinimumExpanding);
445 break;
447 iTabBar.parent_layout().set_size_policy({});
448 iTabBar.parent_layout().remove(iTabBar);
449 iContainerLayout.right().add(iTabBar);
450 iTabBar.parent_layout().set_size_policy(size_constraint::Minimum, size_constraint::MinimumExpanding);
451 break;
452 }
453 }
454}
virtual const i_tab & tab() const =0
virtual void select()=0
virtual const i_widget & as_widget() const =0
virtual bool is_selected() const =0
virtual bool show(bool aVisible)=0
void set_padding(optional_padding const &aPadding, bool aUpdateLayout=true) override
const i_widget & as_widget() const override
void adding_tab(i_tab &aTab) override
const i_tab_page & tab_page(tab_index aTabIndex) const override
void selecting_tab(i_tab &aTab) override
bool closable_tabs() const noexcept override
void set_tab_icon_size(const size &aIconSize) override
i_tab_container & tab_bar() override
tab_page_container(bool aClosableTabs=false, neogfx::tab_container_style aStyle=neogfx::tab_container_style::TabAlignmentTop)
const i_tab_page & selected_tab_page() const override
i_tab & insert_tab(tab_index aTabIndex, i_string const &aTabText) override
i_tab_page & insert_tab_page(tab_index aTabIndex, i_string const &aTabText) override
const i_tab & tab(tab_index aTabIndex) const override
void hide_tab(tab_index aTabIndex) override
bool is_managing_layout() const override
void show_tab(tab_index aTabIndex) override
i_tab & add_tab(i_string const &aTabText) override
void removing_tab(i_tab &aTab) override
void remove_tab_page(i_tab_page &aPage) override
optional_tab_index previous_visible_tab(tab_index aStartFrom) const override
optional_tab_index next_visible_tab(tab_index aStartFrom) const override
bool has_tab_page(tab_index aTabIndex) const override
bool is_tab_selected() const noexcept override
uint32_t tab_count() const noexcept override
void remove_tab(tab_index aTabIndex) override
tab_index index_of(const i_tab &aTab) const override
void set_tab_container_style(neogfx::tab_container_style aStyle) override
bool has_parent_container() const override
bool has_tabs() const noexcept override
void set_closable_tabs(bool aClosableTabs) override
const i_tab_container & parent_container() const override
neogfx::tab_container_style tab_container_style() const noexcept override
const i_tab & selected_tab() const override
i_layout & page_layout() override
i_tab_page & add_tab_page(i_string const &aTabText) override
const widget & as_widget() const override
bool show(bool aVisible) override
Definition widget.ipp:1618