1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.vaadin.gwt.client.tabsheet.widget;
35
36 import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.ActiveTabChangedEvent;
37 import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.ShowAllTabsEvent;
38 import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.ShowAllTabsHandler;
39 import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.TabCloseEvent;
40 import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.TabCloseEventHandler;
41 import info.magnolia.ui.vaadin.gwt.client.tabsheet.tab.widget.MagnoliaTabLabel;
42 import info.magnolia.ui.vaadin.gwt.client.tabsheet.tab.widget.MagnoliaTabWidget;
43 import info.magnolia.ui.vaadin.gwt.client.tabsheet.util.CollectionUtil;
44
45 import java.util.Collections;
46 import java.util.HashMap;
47 import java.util.Iterator;
48 import java.util.LinkedList;
49 import java.util.List;
50 import java.util.Map;
51
52 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
53 import com.google.gwt.dom.client.NativeEvent;
54 import com.google.gwt.event.dom.client.ClickEvent;
55 import com.google.gwt.event.dom.client.ClickHandler;
56 import com.google.gwt.user.client.DOM;
57 import com.google.gwt.user.client.Element;
58 import com.google.gwt.user.client.ui.ComplexPanel;
59 import com.google.gwt.user.client.ui.DialogBox;
60 import com.google.gwt.user.client.ui.MenuBar;
61 import com.google.gwt.user.client.ui.MenuItem;
62 import com.google.gwt.user.client.ui.SimplePanel;
63 import com.google.gwt.user.client.ui.Widget;
64 import com.google.web.bindery.event.shared.EventBus;
65 import com.vaadin.client.ui.VButton;
66
67
68
69
70
71
72 @Deprecated
73 public class TabBarWidget extends ComplexPanel {
74
75 private static final String SINGLE_TAB_CLASS_NAME = "single-tab";
76
77 private final List<MagnoliaTabLabel> tabLabels = new LinkedList<>();
78
79 private final Element tabContainer = DOM.createElement("ul");
80
81 private final EventBus eventBus;
82
83 private VShellShowAllTabLabel showAllTab;
84
85 private final HiddenTabsPopup hiddenTabsPopup;
86
87 private MagnoliaTabLabel activeTab;
88
89 public TabBarWidget(EventBus eventBus) {
90 this.eventBus = eventBus;
91 setElement(tabContainer);
92 setStyleName("nav");
93 addStyleDependentName("tabs");
94
95 hiddenTabsPopup = new HiddenTabsPopup(eventBus);
96 add(hiddenTabsPopup, tabContainer);
97 bindHandlers();
98 }
99
100 public void reArrangeTabVisibility() {
101 if (tabLabels.isEmpty()) {
102 return;
103 }
104
105 if (activeTab == null) {
106 activeTab = tabLabels.get(0);
107 }
108
109
110 hiddenTabsPopup.setVisible(true);
111 int toggleWidth = hiddenTabsPopup.getOffsetWidth();
112 int availableWidth = tabContainer.getOffsetWidth();
113
114
115 activeTab.setVisible(true);
116 availableWidth -= activeTab.getOffsetWidth();
117
118
119 if (showAllTab != null) {
120 availableWidth -= showAllTab.getOffsetWidth();
121 }
122
123
124 Map<MagnoliaTabLabel, Integer> tabWidths = new HashMap<>();
125 for (MagnoliaTabLabel tab : tabLabels) {
126 if (tab == activeTab) {
127 continue;
128 }
129 tab.setVisible(true);
130 tabWidths.put(tab, tab.getOffsetWidth());
131 }
132
133
134 Iterator<MagnoliaTabLabel> it = tabLabels.iterator();
135 boolean outOfSpace = false;
136 while (it.hasNext()) {
137 MagnoliaTabLabel tab = it.next();
138
139 if (tab == activeTab) {
140 continue;
141 }
142 if (!outOfSpace) {
143 int width = tabWidths.get(tab);
144 int maxWidth = Collections.max(tabWidths.values());
145
146 if ((!it.hasNext() && availableWidth >= width)
147
148
149 || (maxWidth + toggleWidth <= availableWidth)) {
150 tabWidths.remove(tab);
151 availableWidth -= width;
152 continue;
153 } else {
154 outOfSpace = true;
155 }
156 }
157
158 tab.setVisible(false);
159 }
160
161
162 hiddenTabsPopup.hide();
163 hiddenTabsPopup.menubar.clearItems();
164 it = tabLabels.iterator();
165 while (it.hasNext()) {
166 MagnoliaTabLabel tab = it.next();
167 if (!tab.isVisible()) {
168 hiddenTabsPopup.addTabLabel(tab);
169 }
170 }
171 hiddenTabsPopup.showControlIfNeeded();
172 }
173
174 private void bindHandlers() {
175 eventBus.addHandler(ActiveTabChangedEvent.TYPE, new ActiveTabChangedEvent.Handler() {
176 @Override
177 public void onActiveTabChanged(final ActiveTabChangedEvent event) {
178 if (event.getTab() == null) return;
179 final MagnoliaTabWidget tab = event.getTab();
180 final MagnoliaTabLabel label = tab.getLabel();
181 if (label != null) {
182 for (final MagnoliaTabLabel tabLabel : tabLabels) {
183 tabLabel.removeStyleName("active");
184 }
185 label.addStyleName("active");
186 showAll(false);
187 activeTab = label;
188 hiddenTabsPopup.menuWrapper.hide();
189 if (!label.isVisible()) {
190 reArrangeTabVisibility();
191 }
192 }
193 }
194 });
195
196 eventBus.addHandler(TabCloseEvent.TYPE, new TabCloseEventHandler() {
197 @Override
198 public void onTabClosed(TabCloseEvent event) {
199 final MagnoliaTabLabel tabLabel = event.getTab().getLabel();
200 boolean wasActive = tabLabel.getStyleName().contains("active");
201 if (wasActive) {
202 final MagnoliaTabLabel nextLabel = getNextLabel(tabLabel);
203 if (nextLabel != null) {
204 nextLabel.addStyleName("active");
205 activeTab = nextLabel;
206 }
207 }
208 tabLabels.remove(tabLabel);
209 remove(tabLabel);
210 updateSingleTabStyle();
211 reArrangeTabVisibility();
212 }
213 });
214
215 eventBus.addHandler(ShowAllTabsEvent.TYPE, new ShowAllTabsHandler() {
216
217 @Override
218 public void onShowAllTabs(ShowAllTabsEvent event) {
219 for (final MagnoliaTabLabel tabLabel : tabLabels) {
220 tabLabel.removeStyleName("active");
221 }
222 showAll(true);
223 }
224 });
225 }
226
227 protected MagnoliaTabLabelnt/tabsheet/tab/widget/MagnoliaTabLabel.html#MagnoliaTabLabel">MagnoliaTabLabel getNextLabel(final MagnoliaTabLabel label) {
228 return CollectionUtil.getNext(tabLabels, label);
229 }
230
231 public void addTabLabel(MagnoliaTabLabel label) {
232 label.setEventBus(eventBus);
233 if (!tabLabels.contains(label)) {
234 tabLabels.add(label);
235
236 insert(label, tabContainer, tabLabels.size() - 1, true);
237 updateSingleTabStyle();
238 }
239 }
240
241 public void updateSingleTabStyle() {
242 if (tabLabels.size() <= 1) {
243 tabContainer.addClassName(SINGLE_TAB_CLASS_NAME);
244 } else {
245 tabContainer.removeClassName(SINGLE_TAB_CLASS_NAME);
246 }
247 }
248
249 public void addShowAllTab(boolean showAll, String label) {
250 if (showAll && showAllTab == null) {
251 showAllTab = new VShellShowAllTabLabel(label);
252 add(showAllTab, getElement());
253 } else if (!showAll && showAllTab != null) {
254 remove(showAllTab);
255 showAllTab = null;
256 }
257 reArrangeTabVisibility();
258 }
259
260 private class VShellShowAllTabLabel extends SimplePanel {
261
262 private final VButton textWrapper = new VButton();
263
264 public VShellShowAllTabLabel(String label) {
265 super(DOM.createElement("li"));
266 addStyleName("show-all");
267 textWrapper.getElement().setInnerHTML(label);
268 textWrapper.getElement().setClassName("tab-title");
269 this.add(textWrapper);
270 }
271
272 @Override
273 protected void onLoad() {
274 super.onLoad();
275 bindHandlers();
276 }
277
278 private void bindHandlers() {
279 addDomHandler(new ClickHandler() {
280 @Override
281 public void onClick(ClickEvent event) {
282 onClickGeneric(event.getNativeEvent());
283 }
284 }, ClickEvent.getType());
285
286 textWrapper.addClickHandler(new ClickHandler() {
287 @Override
288 public void onClick(ClickEvent event) {
289 textWrapper.setFocus(false);
290 onClickGeneric(event.getNativeEvent());
291 }
292 });
293 }
294
295 private void onClickGeneric(NativeEvent nativeEvent) {
296 eventBus.fireEvent(new ShowAllTabsEvent());
297 nativeEvent.stopPropagation();
298 }
299
300 }
301
302
303
304
305 static class HiddenTabsPopup extends Widget {
306
307 private final DialogBox menuWrapper = new DialogBox(true);
308 private final HiddenTabsMenuBar menubar = new HiddenTabsMenuBar();
309 private final EventBus eventBus;
310
311 public HiddenTabsPopup(EventBus eventBus) {
312 this.eventBus = eventBus;
313
314 setElement(DOM.createElement("li"));
315 addStyleName("icon-arrow2_e");
316 addStyleName("hidden-tabs-popup-button");
317 menuWrapper.add(menubar);
318 menuWrapper.setStyleName("context-menu-wrapper");
319
320
321 setVisible(false);
322 }
323
324 @Override
325 protected void onLoad() {
326 super.onLoad();
327 bindHandlers();
328 }
329
330 public void addTabLabel(final MagnoliaTabLabel label) {
331 final MenuItem item = menubar.addItem(label.getCaption(), new ScheduledCommand() {
332 @Override
333 public void execute() {
334 menuWrapper.hide();
335 eventBus.fireEvent(new ActiveTabChangedEvent(label.getTab()));
336 }
337 });
338 item.addStyleName("menu-item");
339 }
340
341 private void bindHandlers() {
342 addDomHandler(new ClickHandler() {
343 @Override
344 public void onClick(ClickEvent event) {
345 event.preventDefault();
346 event.stopPropagation();
347 menuWrapper.setPopupPosition(getAbsoluteLeft() + getOffsetWidth(), getAbsoluteTop());
348 menuWrapper.show();
349 }
350
351 }, ClickEvent.getType());
352 }
353
354 public void hide() {
355 menuWrapper.hide();
356 setVisible(false);
357 }
358
359 public void showControlIfNeeded() {
360 setVisible(!menubar.isEmpty());
361 }
362
363 private class HiddenTabsMenuBar extends MenuBar {
364
365 public HiddenTabsMenuBar() {
366 super(true);
367 setStyleName("context-menu");
368 addStyleName("hidden-tabs-menu");
369 }
370
371 public boolean isEmpty() {
372 return super.getItems().isEmpty();
373 }
374 }
375 }
376
377 public void showAll(boolean showAll) {
378 if (showAllTab != null) {
379 if (showAll) {
380 showAllTab.addStyleName("active");
381 } else {
382 if (showAllTab.getStyleName().contains("active")) {
383 showAllTab.removeStyleName("active");
384 }
385 }
386 }
387 }
388
389 }