001/* 002 * Copyright 2012 GWT-Bootstrap 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.github.gwtbootstrap.client.ui; 017 018import java.util.ArrayList; 019import java.util.List; 020 021import com.github.gwtbootstrap.client.ui.base.DivWidget; 022import com.github.gwtbootstrap.client.ui.resources.Bootstrap; 023import com.google.gwt.core.client.GWT; 024import com.google.gwt.core.client.Scheduler; 025import com.google.gwt.core.client.Scheduler.ScheduledCommand; 026import com.google.gwt.dom.client.Element; 027import com.google.gwt.dom.client.NativeEvent; 028import com.google.gwt.event.dom.client.DomEvent; 029import com.google.gwt.event.shared.EventHandler; 030import com.google.gwt.event.shared.HandlerRegistration; 031import com.google.gwt.user.client.Event; 032import com.google.gwt.user.client.ui.IsWidget; 033import com.google.gwt.user.client.ui.Widget; 034 035//@formatter:off 036/** 037 * The container for a tabbable nav. 038 * 039 * @since 2.0.4.0 040 * @author Dominik Mayer 041 * @author ohashi keisuke 042 */ 043//@formatter:on 044public class TabPanel extends DivWidget { 045 046 public static class ShowEvent extends DomEvent<ShowEvent.Handler> { 047 private static final Type<ShowEvent.Handler> TYPE = new Type<ShowEvent.Handler>( 048 "show", new ShowEvent()); 049 050 private TabLink target; 051 private TabLink relatedTarget; 052 053 protected ShowEvent() { 054 } 055 056 public ShowEvent(NativeEvent event) { 057 setNativeEvent(event); 058 if(Element.is(event.getRelatedEventTarget())) { 059 setRelativeElement(Element.as(event.getRelatedEventTarget())); 060 } 061 } 062 063 public interface Handler extends EventHandler { 064 065 void onShow(ShowEvent showEvent); 066 } 067 068 @Override 069 protected void dispatch(Handler handler) { 070 handler.onShow(this); 071 } 072 073 @Override 074 public com.google.gwt.event.dom.client.DomEvent.Type<ShowEvent.Handler> getAssociatedType() { 075 return TYPE; 076 } 077 078 /** 079 * Get target 080 * 081 * @return target 082 */ 083 public TabLink getTarget() { 084 return target; 085 } 086 087 /** 088 * Set target 089 * 090 * @param target 091 * target 092 */ 093 public void setTarget(TabLink target) { 094 this.target = target; 095 } 096 097 /** 098 * Get relatedTarget。 099 * 100 * @return relatedTarget 101 */ 102 public TabLink getRelatedTarget() { 103 return relatedTarget; 104 } 105 106 /** 107 * Set relatedTarget 108 * 109 * @param relatedTarget 110 * relatedTarget 111 */ 112 public void setRelatedTarget(TabLink relatedTarget) { 113 this.relatedTarget = relatedTarget; 114 } 115 } 116 117 public static class ShownEvent extends DomEvent<ShownEvent.Handler> { 118 private static final Type<ShownEvent.Handler> TYPE = new Type<ShownEvent.Handler>( 119 "shown", new ShownEvent()); 120 121 private TabLink target; 122 private TabLink relatedTarget; 123 124 protected ShownEvent() { 125 } 126 127 public ShownEvent(NativeEvent event) { 128 setNativeEvent(event); 129 if(Element.is(event.getRelatedEventTarget())) { 130 setRelativeElement(Element.as(event.getRelatedEventTarget())); 131 } 132 } 133 134 public interface Handler extends EventHandler { 135 136 void onShow(ShownEvent shownEvent); 137 } 138 139 @Override 140 protected void dispatch(Handler handler) { 141 handler.onShow(this); 142 } 143 144 @Override 145 public com.google.gwt.event.dom.client.DomEvent.Type<ShownEvent.Handler> getAssociatedType() { 146 return TYPE; 147 } 148 149 /** 150 * Get target 151 * 152 * @return target 153 */ 154 public TabLink getTarget() { 155 return target; 156 } 157 158 /** 159 * Set target 160 * 161 * @param target 162 * target 163 */ 164 public void setTarget(TabLink target) { 165 this.target = target; 166 } 167 168 /** 169 * Get relatedTarget。 170 * 171 * @return relatedTarget 172 */ 173 public TabLink getRelatedTarget() { 174 return relatedTarget; 175 } 176 177 /** 178 * Set relatedTarget 179 * 180 * @param relatedTarget 181 * relatedTarget 182 */ 183 public void setRelatedTarget(TabLink relatedTarget) { 184 this.relatedTarget = relatedTarget; 185 } 186 } 187 188 private static class TabContent extends DivWidget { 189 190 public TabContent() { 191 setStyleName(Bootstrap.tab_content); 192 } 193 } 194 195 private NavTabs tabs = new NavTabs(); 196 197 private List<TabLink> tabLinkList = new ArrayList<TabLink>(); 198 199 private TabContent tabContent = new TabContent(); 200 201 /** 202 * Create an empty {@link Bootstrap.Tabs#ABOVE} style TabPanel. 203 */ 204 public TabPanel() { 205 this(Bootstrap.Tabs.ABOVE); 206 } 207 208 /** 209 * Create an empty TabPanel. 210 * @param position tab position. 211 */ 212 public TabPanel(Bootstrap.Tabs position) { 213 setStyle(position); 214 if(Bootstrap.Tabs.BELOW == position) { 215 //tabs should be added after content to display it below content in this case 216 super.add(tabContent); 217 super.add(tabs); 218 } else { 219 super.add(tabs); 220 super.add(tabContent); 221 } 222 223 setHandlerFunctions(getElement()); 224 } 225 226 /** 227 * Set tab position 228 * @param position tab position. 229 */ 230 public void setTabPosition(String position) { 231 if (tabs.getParent() != null) { 232 remove(tabs); 233 remove(tabContent); 234 } 235 236 if (position.equalsIgnoreCase("below")) { 237 //tabs should be added after content to display it below content in this case 238 setStyle(Bootstrap.Tabs.BELOW); 239 super.add(tabContent); 240 super.add(tabs); 241 } else if (position.equalsIgnoreCase("left")) { 242 setStyle(Bootstrap.Tabs.LEFT); 243 super.add(tabs); 244 super.add(tabContent); 245 } else if (position.equalsIgnoreCase("right")) { 246 setStyle(Bootstrap.Tabs.RIGHT); 247 super.add(tabs); 248 super.add(tabContent); 249 } else { 250 setStyle(Bootstrap.Tabs.ABOVE); 251 super.add(tabs); 252 super.add(tabContent); 253 } 254 } 255 256 @Override 257 public void add(Widget child) { 258 if (child instanceof TabPane) { 259 add((TabPane) child); 260 return; 261 } 262 263 if (child instanceof TabLink) { 264 add((TabLink) child); 265 return; 266 } 267 268 if (child instanceof DropdownTab) { 269 add((DropdownTab) child); 270 return; 271 } 272 273 if (GWT.isProdMode()) { 274 throw new IllegalArgumentException( 275 "TabPanel can add only TabPane or TabLink or Tab or DorpdownTab. you added " 276 + child); 277 } 278 } 279 280 private void add(DropdownTab dropdownTab) { 281 tabs.add(dropdownTab); 282 283 List<Tab> tabList = dropdownTab.getTabList(); 284 for (Tab tab : tabList) { 285 tabLinkList.add(tab.asTabLink()); 286 TabPane tabPane = tab.getTabPane(); 287 tabContent.add(tabPane); 288 } 289 } 290 291 private void add(TabPane child) { 292 if (child.isCreateTabLink()) { 293 TabLink tabLink = new TabLink(child); 294 tabs.add(tabLink); 295 tabLinkList.add(tabLink); 296 } 297 tabContent.add(child); 298 } 299 300 private void add(final TabLink child) { 301 if (child.isCreateTabPane() && child.getTabPane() == null) { 302 TabPane pane = new TabPane(child.getText()); 303 child.setTabPane(pane); 304 tabContent.add(pane); 305 } else if (child.getTabPane() != null) { 306 tabContent.add(child.getTabPane()); 307 } 308 tabs.add(child); 309 tabLinkList.add(child); 310 } 311 312 @Override 313 public void clear() { 314 tabContent.clear(); 315 tabs.clear(); 316 tabLinkList.clear(); 317 } 318 319 /** 320 * Remove tab or tabpane. 321 * <p> 322 * If Tablink has TabPane,romve TabPane with TabLink. </pre> {@inheritDoc} 323 */ 324 @Override 325 public boolean remove(int index) { 326 Widget widget = tabs.getWidget(index); 327 328 if (widget instanceof TabLink) { 329 TabLink link = (TabLink) widget; 330 if (link.getTabPane() != null) { 331 link.getTabPane().removeFromParent(); 332 } 333 tabLinkList.remove(link); 334 return tabs.remove(index); 335 } else if (widget instanceof DropdownTab) { 336 337 DropdownTab dropdownTab = (DropdownTab) widget; 338 339 List<Tab> tabList = dropdownTab.getTabList(); 340 341 for (Tab tab : tabList) { 342 tabLinkList.remove(tab.asTabLink()); 343 if (tab.getTabPane() != null) { 344 tab.getTabPane().removeFromParent(); 345 } 346 } 347 return tabs.remove(dropdownTab); 348 } else if (widget instanceof TabPane) { 349 350 return tabContent.remove(widget); 351 } 352 353 return super.remove(widget); 354 } 355 356 /** 357 * remove TabLink or TabPane. 358 * <p> 359 * </p> 360 * {@inheritDoc} 361 */ 362 @Override 363 public boolean remove(Widget w) { 364 365 if (w instanceof TabLink) { 366 TabLink link = (TabLink) w; 367 tabLinkList.remove(link); 368 if (link.getTabPane() != null) { 369 link.getTabPane().removeFromParent(); 370 } 371 return tabs.remove(w); 372 } else if (w instanceof DropdownTab) { 373 DropdownTab dropdownTab = (DropdownTab) w; 374 375 List<Tab> tabList = dropdownTab.getTabList(); 376 377 for (Tab tab : tabList) { 378 379 tabLinkList.remove(tab.asTabLink()); 380 if (tab.getTabPane() != null) { 381 tab.getTabPane().removeFromParent(); 382 } 383 } 384 385 return tabs.remove(dropdownTab); 386 387 } else if (w instanceof TabPane) { 388 return tabContent.remove(w); 389 } 390 391 return super.remove(w); 392 } 393 394 /** 395 * {@inheritDoc} 396 */ 397 @Override 398 public boolean remove(IsWidget child) { 399 400 if (child instanceof Tab) { 401 Tab tab = (Tab) child; 402 403 TabLink link = tab.asTabLink(); 404 405 if (link.getTabPane() != null) { 406 link.getTabPane().removeFromParent(); 407 } 408 tabLinkList.remove(link); 409 return tabs.remove(link); 410 } else if (child instanceof DropdownTab) { 411 DropdownTab tab = (DropdownTab) child; 412 413 List<Tab> tabList = tab.getTabList(); 414 415 for (Tab tab2 : tabList) { 416 tabLinkList.remove(tab2.asTabLink()); 417 if (tab2.getTabPane() != null) { 418 tabContent.remove(tab2.getTabPane()); 419 } 420 } 421 return super.remove(child); 422 } 423 424 return super.remove(child); 425 } 426 427 /** 428 * Activate tab by index. 429 * @param index tab index. 430 */ 431 public void selectTab(int index) { 432 tabLinkList.get(index).show(); 433 } 434 435 /** 436 * Get Current selected tab index. 437 * <p> 438 * if not found, return <code>-1.</code> 439 * </p> 440 * 441 * @return tab index. 442 */ 443 public int getSelectedTab() { 444 445 for (int i = 0; i < tabLinkList.size(); i++) { 446 if (tabLinkList.get(i).isActive()) { 447 return i; 448 } 449 } 450 return -1; 451 } 452 453 private void setHandlerFunctions(final TabLink e) { 454 if (isOrWasAttached()) { 455 setHandlerFunctions(e.getAnchor().getElement()); 456 return; 457 } 458 459 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 460 461 @Override 462 public void execute() { 463 setHandlerFunctions(e.getAnchor().getElement()); 464 } 465 }); 466 467 } 468 469 protected void onShow(Event e, Element target, Element relatedTarget) { 470 ShowEvent event = new ShowEvent(e); 471 event.setTarget(findTabLink(target)); 472 event.setRelatedTarget(findTabLink(relatedTarget)); 473 fireEvent(event); 474 } 475 476 protected void onShown(Event e, Element target, Element relatedTarget) { 477 ShownEvent event = new ShownEvent(e); 478 event.setTarget(findTabLink(target)); 479 event.setRelatedTarget(findTabLink(relatedTarget)); 480 fireEvent(event); 481 } 482 483 public HandlerRegistration addShowHandler(ShowEvent.Handler handler) { 484 return addHandler(handler, ShowEvent.TYPE); 485 } 486 487 public HandlerRegistration addShownHandler(ShownEvent.Handler handler) { 488 return addHandler(handler, ShownEvent.TYPE); 489 } 490 491 private TabLink findTabLink(Element e) { 492 for (TabLink tabLink : tabLinkList) 493 if (tabLink.getAnchor().getElement().equals(e)) 494 return tabLink; 495 496 return null; 497 } 498 499 //@formatter:off 500 private native void setHandlerFunctions(Element e) /*-{ 501 var that = this; 502 var $this = $wnd.jQuery(e); 503 504 $this.off('show'); 505 $this.off('shown'); 506 507 $this.on('show', function(e) { 508 that.@com.github.gwtbootstrap.client.ui.TabPanel::onShow(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/dom/client/Element;Lcom/google/gwt/dom/client/Element;)(e, e.target, e.relatedTarget); 509 }); 510 $this.on('shown', function(e) { 511 that.@com.github.gwtbootstrap.client.ui.TabPanel::onShown(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/dom/client/Element;Lcom/google/gwt/dom/client/Element;)(e, e.target, e.relatedTarget); 512 }); 513 }-*/; 514 //@formatter:on 515 516}