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.jquerywrapper.JQueryCallback;
37 import info.magnolia.ui.vaadin.gwt.client.jquerywrapper.JQueryWrapper;
38 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.viewport.animation.FadeAnimation;
39 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.viewport.animation.JQueryAnimation;
40 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.viewport.widget.AppPreloader;
41 import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.ActiveTabChangedEvent;
42 import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.TabSetChangedEvent;
43 import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.TabSetChangedEvent.Handler;
44 import info.magnolia.ui.vaadin.gwt.client.tabsheet.tab.widget.MagnoliaTabWidget;
45 import info.magnolia.ui.vaadin.gwt.client.tabsheet.util.CollectionUtil;
46
47 import java.util.Iterator;
48 import java.util.LinkedList;
49 import java.util.List;
50
51 import com.google.gwt.core.client.Scheduler;
52 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
53 import com.google.gwt.dom.client.Style;
54 import com.google.gwt.dom.client.Style.Display;
55 import com.google.gwt.dom.client.Style.Position;
56 import com.google.gwt.dom.client.Style.Unit;
57 import com.google.gwt.event.shared.HandlerRegistration;
58 import com.google.gwt.user.client.DOM;
59 import com.google.gwt.user.client.Element;
60 import com.google.gwt.user.client.Timer;
61 import com.google.gwt.user.client.ui.FlowPanel;
62 import com.google.gwt.user.client.ui.ScrollPanel;
63 import com.google.gwt.user.client.ui.Widget;
64 import com.google.web.bindery.event.shared.EventBus;
65
66
67
68
69
70
71
72 public class MagnoliaTabSheetViewImpl extends FlowPanel implements MagnoliaTabSheetView {
73
74 private static final String CLASSNAME_CONTENT_SHOW_ALL = "show-all";
75
76 private final List<MagnoliaTabWidget> tabs = new LinkedList<MagnoliaTabWidget>();
77
78 private final ScrollPanel scroller = new ScrollPanel();
79
80 private final FlowPanel tabPanel = new FlowPanel();
81
82 private final TabBarWidget tabBar;
83
84 private MagnoliaTabWidget activeTab = null;
85
86 private boolean showingAllTabs;
87
88 private AppPreloader preloader = new AppPreloader();
89
90 private FadeAnimation preloaderFadeOut = new FadeAnimation(0d, true);
91
92 private Element logo;
93
94 private ScheduledCommand removePreloaderCommand;
95
96 private EventBus eventBus;
97
98 public MagnoliaTabSheetViewImpl(EventBus eventBus) {
99 super();
100 this.eventBus = eventBus;
101 this.tabBar = new TabBarWidget(eventBus);
102 this.logo = DOM.createDiv();
103 addStyleName("v-shell-tabsheet");
104 scroller.addStyleName("v-shell-tabsheet-scroller");
105 tabPanel.addStyleName("v-shell-tabsheet-tab-wrapper");
106 getElement().appendChild(logo);
107 add(tabBar);
108 add(scroller);
109 scroller.setWidget(tabPanel);
110 scroller.getElement().getStyle().setPosition(Position.ABSOLUTE);
111 this.preloaderFadeOut.addCallback(new JQueryCallback() {
112 @Override
113 public void execute(JQueryWrapper query) {
114 doRemovePreloader();
115 }
116 });
117
118 eventBus.addHandler(ActiveTabChangedEvent.TYPE, new ActiveTabChangedEvent.Handler() {
119 @Override
120 public void onActiveTabChanged(ActiveTabChangedEvent event) {
121 fireEvent(event);
122 }
123 });
124
125 }
126
127 @Override
128 public TabBarWidget getTabContainer() {
129 return tabBar;
130 }
131
132
133 @Override
134 public void removeTab(MagnoliaTabWidget tabToOrphan) {
135 if (activeTab == tabToOrphan) {
136 final MagnoliaTabWidget nextTab = CollectionUtil.getNext(getTabs(), tabToOrphan);
137 if (nextTab != null) {
138 setActiveTab(nextTab);
139 }
140 }
141 getTabs().remove(tabToOrphan);
142 tabPanel.remove(tabToOrphan);
143 }
144
145 @Override
146 public void setActiveTab(final MagnoliaTabWidget tab) {
147 this.activeTab = tab;
148
149 showAllTabContents(false);
150 tab.getElement().getStyle().clearDisplay();
151 animateHeightChange(tab);
152 }
153
154 private static final int HEIGHT_CHANGE_ANIMATION_DURATION = 200;
155
156 private void animateHeightChange(MagnoliaTabWidget newActiveTab) {
157 final Style tabPanelStyle = tabPanel.getElement().getStyle();
158 int offsetTabHeight = tabPanel.getOffsetHeight();
159 tabPanelStyle.clearHeight();
160 int newHeight = newActiveTab.getOffsetHeight();
161 final String heightPropertyCC = offsetTabHeight < newHeight ? "maxHeight" : "minHeight";
162 final String heightProperty = offsetTabHeight < newHeight ? "max-height" : "min-height";
163
164 final JQueryAnimation animation = new JQueryAnimation();
165 tabPanelStyle.setProperty(heightPropertyCC, offsetTabHeight + "px");
166 animation.setProperty(heightProperty, newHeight);
167 tabPanelStyle.setOverflow(Style.Overflow.HIDDEN);
168 animation.addCallback(new JQueryCallback() {
169 @Override
170 public void execute(JQueryWrapper query) {
171 tabPanelStyle.clearOverflow();
172 tabPanelStyle.clearProperty(heightPropertyCC);
173 }
174 });
175 animation.run(HEIGHT_CHANGE_ANIMATION_DURATION, tabPanel.getElement());
176 }
177
178 @Override
179 public MagnoliaTabWidget getActiveTab() {
180 return activeTab;
181 }
182
183
184 @Override
185 public List<MagnoliaTabWidget> getTabs() {
186 return tabs;
187 }
188
189 @Override
190 public void showAllTabContents(boolean visible) {
191 for (MagnoliaTabWidget tab : getTabs()) {
192
193 if (visible) {
194 tab.getElement().getStyle().clearDisplay();
195 tab.getElement().getStyle().clearHeight();
196 } else {
197 tab.getElement().getStyle().setDisplay(Display.NONE);
198 tab.getElement().getStyle().setHeight(100, Unit.PCT);
199 }
200 }
201 if (visible) {
202 addStyleName(CLASSNAME_CONTENT_SHOW_ALL);
203 } else {
204 removeStyleName(CLASSNAME_CONTENT_SHOW_ALL);
205 }
206 showingAllTabs = visible;
207 }
208
209 @Override
210 public boolean isShowingAllTabs() {
211 return showingAllTabs;
212 }
213
214 @Override
215 public void updateTab(MagnoliaTabWidget tab) {
216 if (!tabs.contains(tab)) {
217 showPreloader();
218 getTabs().add(tab);
219 tabPanel.add(tab);
220 tabBar.addTabLabel(tab.getLabel());
221 fireEvent(new TabSetChangedEvent(this));
222 }
223 }
224
225 @Override
226 protected void onLoad() {
227 super.onLoad();
228 fireEvent(new TabSetChangedEvent(this));
229 }
230
231 @Override
232 public HandlerRegistration addTabSetChangedHandler(Handler handler) {
233 return addHandler(handler, TabSetChangedEvent.TYPE);
234 }
235
236 @Override
237 public HandlerRegistration addActiveTabChangedHandler(ActiveTabChangedEvent.Handler handler) {
238 return addHandler(handler, ActiveTabChangedEvent.TYPE);
239 }
240
241 @Override
242 public void setLogo(String logo, String logoBgColor) {
243 this.logo.addClassName("v-shell-tabsheet-logo");
244 this.logo.addClassName(logo);
245 this.logo.getStyle().setBackgroundColor(logoBgColor);
246 }
247
248 @Override
249 public void setMaxHeight(int height) {
250 int tabBarHeight = getOffsetHeight() - scroller.getOffsetHeight();
251 height -= tabBarHeight;
252 final Style scrollerStyle = scroller.getElement().getStyle();;
253 scrollerStyle.setPosition(Position.ABSOLUTE);
254 scrollerStyle.setOverflow(Style.Overflow.AUTO);
255 scrollerStyle.setProperty("zoom", "1");
256 scrollerStyle.setProperty("maxHeight", height + "px");
257 }
258
259 Timer preloaderRemoverTimer = new Timer() {
260 @Override
261 public void run() {
262 doRemovePreloader();
263 }
264 };
265
266 @Override
267 public void showPreloader() {
268 preloaderFadeOut.cancel();
269 preloaderRemoverTimer.cancel();
270 if (tabPanel != preloader.getParent()) {
271 preloader.getElement().getStyle().setTop(0, Unit.PX);
272 preloader.getElement().getStyle().setZIndex(10000);
273 tabPanel.add(preloader);
274 }
275 }
276
277 @Override
278 public void removePreloader() {
279 if (removePreloaderCommand == null) {
280 removePreloaderCommand = new ScheduledCommand() {
281 @Override
282 public void execute() {
283 if (tabPanel == preloader.getParent()) {
284 preloaderFadeOut.run(500, preloader.getElement());
285 }
286 removePreloaderCommand = null;
287 }
288 };
289 Scheduler.get().scheduleDeferred(removePreloaderCommand);
290 preloaderRemoverTimer.schedule(1000);
291 }
292 }
293
294 @Override
295 public void clearTabs() {
296 final Iterator<Widget> it = tabPanel.iterator();
297 while (it.hasNext()) {
298 final Widget w = it.next();
299 if (w == getActiveTab()) {
300 tabPanel.setHeight(w.getOffsetHeight() + "px");
301 }
302 if (w != preloader) {
303 w.getElement().getStyle().setDisplay(Display.NONE);
304 }
305 }
306 }
307
308 private void doRemovePreloader() {
309 tabPanel.remove(preloader);
310 }
311 }