Mana
Loading...
Searching...
No Matches
tabbedarea.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2008-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
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.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
23
24#include "graphics.h"
25
26#include "gui/widgets/tab.h"
27
28#include <guichan/widgets/container.hpp>
29
31{
32 mWidgetContainer->setOpaque(false);
33 addWidgetListener(this);
34
35 mArrowButton[0] = std::make_unique<Button>(std::string(), "shift_left", this);
36 mArrowButton[1] = std::make_unique<Button>(std::string(), "shift_right", this);
37 mArrowButton[0]->setButtonIcon("tab_arrows_left.png");
38 mArrowButton[1]->setButtonIcon("tab_arrows_right.png");
39
40 add(mArrowButton[0].get());
41 add(mArrowButton[1].get());
42
43 widgetResized(nullptr);
44}
45
47{
48 return mTabs.size();
49}
50
51Tab *TabbedArea::getTab(const std::string &name) const
52{
53 for (const auto &[tab, _] : mTabs)
54 {
55 if (tab->getCaption() == name)
56 return static_cast<Tab*>(tab);
57 }
58 return nullptr;
59}
60
61void TabbedArea::draw(gcn::Graphics *graphics)
62{
63 if (mTabs.empty())
64 return;
65
66 auto g = static_cast<Graphics*>(graphics);
67 g->pushClipRect(getChildrenArea());
68
69 drawChildren(graphics);
70
71 g->popClipRect();
72}
73
74gcn::Widget *TabbedArea::getWidget(const std::string &name) const
75{
76 for (const auto &[tab, widget] : mTabs)
77 {
78 if (tab->getCaption() == name)
79 return widget;
80 }
81
82 return nullptr;
83}
84
86{
87 if (gcn::Tab *tab = getSelectedTab())
88 return getWidget(tab->getCaption());
89
90 return nullptr;
91}
92
93void TabbedArea::addTab(gcn::Tab* tab, gcn::Widget* widget)
94{
95 gcn::TabbedArea::addTab(tab, widget);
96
97 int frameSize = widget->getFrameSize();
98 widget->setPosition(frameSize, frameSize);
99 widget->setSize(mWidgetContainer->getWidth() - frameSize * 2,
100 mWidgetContainer->getHeight() - frameSize * 2);
101
104}
105
106void TabbedArea::addTab(const std::string &caption, gcn::Widget *widget)
107{
108 Tab *tab = new Tab;
109 tab->setCaption(caption);
110 mTabsToDelete.push_back(tab);
111
112 addTab(tab, widget);
113}
114
115void TabbedArea::removeTab(gcn::Tab *tab)
116{
117 if (tab == mSelectedTab)
118 {
119 if (getNumberOfTabs() > 1)
120 setSelectedTab(std::max(0, getSelectedTabIndex() - 1));
121 else
122 mSelectedTab = nullptr;
123 }
124
125 for (auto iter = mTabs.begin(); iter != mTabs.end(); iter++)
126 {
127 if (iter->first == tab)
128 {
129 mTabContainer->remove(tab);
130 mTabs.erase(iter);
131 break;
132 }
133 }
134
135 for (auto iter = mTabsToDelete.begin(); iter != mTabsToDelete.end(); iter++)
136 {
137 if (*iter == tab)
138 {
139 mTabsToDelete.erase(iter);
140 delete tab;
141 break;
142 }
143 }
144
145 adjustSize();
148}
149
151{
152 logicChildren();
153}
154
155void TabbedArea::mousePressed(gcn::MouseEvent &mouseEvent)
156{
157 if (mouseEvent.isConsumed())
158 return;
159
160 if (mouseEvent.getButton() == gcn::MouseEvent::LEFT)
161 {
162 gcn::Widget *widget = mTabContainer->getWidgetAt(mouseEvent.getX(),
163 mouseEvent.getY());
164
165 if (auto *tab = dynamic_cast<gcn::Tab*>(widget))
166 {
167 setSelectedTab(tab);
168 requestFocus();
169 }
170 }
171}
172
173void TabbedArea::setSelectedTab(gcn::Tab *tab)
174{
175 gcn::TabbedArea::setSelectedTab(tab);
176
177 if (Tab *newTab = dynamic_cast<Tab*>(tab))
178 newTab->setCurrent();
179
180 widgetResized(nullptr);
181}
182
183void TabbedArea::widgetResized(const gcn::Event &event)
184{
185 adjustSize();
186
187 if (gcn::Widget *w = getCurrentWidget())
188 {
189 int frameSize = w->getFrameSize();
190 w->setSize(mWidgetContainer->getWidth() - frameSize * 2,
191 mWidgetContainer->getHeight() - frameSize * 2);
192 }
193
194 // Check whether there is room to show more tabs now.
195 int innerWidth = getWidth() - 4 - mArrowButton[0]->getWidth()
196 - mArrowButton[1]->getWidth();
197 int newWidth = mVisibleTabsWidth;
198 while (mTabScrollIndex && newWidth < innerWidth)
199 {
200 newWidth += mTabs[mTabScrollIndex - 1].first->getWidth();
201 if (newWidth < innerWidth)
203 }
204
205 // Move the right arrow to fit the windows content.
206 mArrowButton[1]->setPosition(getWidth() - mArrowButton[1]->getWidth(), 0);
207
210}
211
213{
214 mTabsWidth = 0;
215 for (const auto &[tab, _] : mTabs)
216 mTabsWidth += tab->getWidth();
217
219}
220
222{
224 for (unsigned int i = mTabScrollIndex; i < mTabs.size(); ++i)
225 mVisibleTabsWidth += mTabs[i].first->getWidth();
226}
227
229{
230 int maxTabHeight = 0;
231 for (auto &tab : mTabs)
232 {
233 if (tab.first->getHeight() > maxTabHeight)
234 {
235 maxTabHeight = tab.first->getHeight();
236 }
237 }
238
239 int x = mArrowButton[0]->isVisible() ? mArrowButton[0]->getWidth() : 0;
240 for (unsigned i = mTabScrollIndex; i < mTabs.size(); ++i)
241 {
242 gcn::Tab* tab = mTabs[i].first;
243 tab->setPosition(x, maxTabHeight - tab->getHeight());
244 x += tab->getWidth();
245 }
246
247 // If the tabs are scrolled, we hide them away.
248 if (mTabScrollIndex > 0)
249 {
250 x = 0;
251 for (unsigned i = 0; i < mTabScrollIndex; ++i)
252 {
253 gcn::Tab* tab = mTabs[i].first;
254 x -= tab->getWidth();
255 tab->setPosition(x, maxTabHeight - tab->getHeight());
256 }
257 }
258}
259
260void TabbedArea::action(const gcn::ActionEvent& actionEvent)
261{
262 Widget *source = actionEvent.getSource();
263
264 if (Tab *tab = dynamic_cast<Tab*>(source))
265 {
266 setSelectedTab(tab);
267 }
268 else
269 {
270 if (actionEvent.getId() == "shift_left")
271 {
272 if (mTabScrollIndex > 0)
274 }
275 else if (actionEvent.getId() == "shift_right")
276 {
277 if (mTabScrollIndex < mTabs.size() - 1)
279 }
281
283 }
284}
285
287{
289
290 const bool arrowButtonsVisible = mTabsWidth > getWidth() - 2;
291 mArrowButton[0]->setVisible(arrowButtonsVisible);
292 mArrowButton[1]->setVisible(arrowButtonsVisible);
293
294 if (!arrowButtonsVisible)
295 mTabScrollIndex = 0;
296
297 mArrowButton[0]->setEnabled(mTabScrollIndex > 0);
298
299 // Right arrow consistency check
300 const int availableWidth = getWidth() - 2 - mArrowButton[0]->getWidth()
301 - mArrowButton[1]->getWidth();
302 mArrowButton[1]->setEnabled(mVisibleTabsWidth >= availableWidth);
303}
A central point of control for graphics.
Definition graphics.h:78
void pushClipRect(const gcn::Rectangle &rect)
Definition graphics.cpp:252
A tab, the same as the Guichan tab in 0.8, but extended to allow transparency.
Definition tab.h:33
void setCaption(const std::string &caption)
Sets the caption of the tab.
Definition tab.cpp:49
void draw(gcn::Graphics *graphics) override
Draw the tabbed area.
void updateVisibleTabsWidth()
Update the overall width of visible tab.
int mVisibleTabsWidth
The overall width of visible tab.
Definition tabbedarea.h:143
void action(const gcn::ActionEvent &actionEvent) override
void logic() override
Override the logic function since it's broken in guichan 0.8.
void widgetResized(const gcn::Event &event) override
void addTab(gcn::Tab *tab, gcn::Widget *widget) override
Add a tab.
int mTabsWidth
The overall width of all tab.
Definition tabbedarea.h:132
void mousePressed(gcn::MouseEvent &mouseEvent) override
gcn::Widget * getCurrentWidget()
Returns the widget for the current tab.
void removeTab(gcn::Tab *tab) override
Override the remove tab function as it's broken in guichan 0.8.
void updateTabsWidth()
Update the overall width of all tab.
void setSelectedTab(unsigned int index) override
Definition tabbedarea.h:101
Tab * getTab(const std::string &name) const
Return tab with specified name as caption.
void adjustTabPositions()
int getNumberOfTabs() const
Return how many tabs have been created.
gcn::Widget * getWidget(const std::string &name) const
Returns the widget with the tab that has specified caption.
void updateArrowEnableState()
Check whether the arrow should be clickable.
std::unique_ptr< Button > mArrowButton[2]
The tab arrows.
Definition tabbedarea.h:118
unsigned mTabScrollIndex
The tab scroll index.
Definition tabbedarea.h:152
Graphics * graphics
Definition client.cpp:104
#define _(s)
Definition gettext.h:38