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�B 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�B 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 259 if (child instanceof TabPane) { 260 add((TabPane) child); 261 return; 262 } 263 264 if (child instanceof TabLink) { 265 add((TabLink) child); 266 return; 267 } 268 269 if (child instanceof DropdownTab) { 270 add((DropdownTab) child); 271 return; 272 } 273 274 if (GWT.isProdMode()) { 275 throw new IllegalArgumentException( 276 "TabPanel can add only TabPane or TabLink or Tab or DorpdownTab. you added " 277 + child); 278 } 279 } 280 281 private void add(DropdownTab dropdownTab) { 282 283 tabs.add(dropdownTab); 284 285 List<Tab> tabList = dropdownTab.getTabList(); 286 for (Tab tab : tabList) { 287 tabLinkList.add(tab.asTabLink()); 288 TabPane tabPane = tab.getTabPane(); 289 tabContent.add(tabPane); 290 } 291 } 292 293 private void add(TabPane child) { 294 295 if (child.isCreateTabLink()) { 296 TabLink tabLink = new TabLink(child); 297 tabs.add(tabLink); 298 tabLinkList.add(tabLink); 299 } 300 tabContent.add(child); 301 } 302 303 private void add(final TabLink child) { 304 305 if (child.isCreateTabPane() && child.getTabPane() == null) { 306 TabPane pane = new TabPane(child.getText()); 307 child.setTablePane(pane); 308 tabContent.add(pane); 309 } else if (child.getTabPane() != null) { 310 tabContent.add(child.getTabPane()); 311 } 312 tabs.add(child); 313 tabLinkList.add(child); 314 } 315 316 @Override 317 public void clear() { 318 tabContent.clear(); 319 tabs.clear(); 320 tabLinkList.clear(); 321 } 322 323 /** 324 * Remove tab or tabpane. 325 * <p> 326 * If Tablink has TabPane,romve TabPane with TabLink. </pre> {@inheritDoc} 327 */ 328 @Override 329 public boolean remove(int index) { 330 Widget widget = tabs.getWidget(index); 331 332 if (widget instanceof TabLink) { 333 TabLink link = (TabLink) widget; 334 if (link.getTabPane() != null) { 335 link.getTabPane().removeFromParent(); 336 } 337 tabLinkList.remove(link); 338 return tabs.remove(index); 339 } else if (widget instanceof DropdownTab) { 340 341 DropdownTab dropdownTab = (DropdownTab) widget; 342 343 List<Tab> tabList = dropdownTab.getTabList(); 344 345 for (Tab tab : tabList) { 346 tabLinkList.remove(tab.asTabLink()); 347 if (tab.getTabPane() != null) { 348 tab.getTabPane().removeFromParent(); 349 } 350 } 351 return tabs.remove(dropdownTab); 352 } else if (widget instanceof TabPane) { 353 354 return tabContent.remove(widget); 355 } 356 357 return super.remove(widget); 358 } 359 360 /** 361 * remove TabLink or TabPane. 362 * <p> 363 * </p> 364 * {@inheritDoc} 365 */ 366 @Override 367 public boolean remove(Widget w) { 368 369 if (w instanceof TabLink) { 370 TabLink link = (TabLink) w; 371 tabLinkList.remove(link); 372 if (link.getTabPane() != null) { 373 link.getTabPane().removeFromParent(); 374 } 375 return tabs.remove(w); 376 } else if (w instanceof DropdownTab) { 377 DropdownTab dropdownTab = (DropdownTab) w; 378 379 List<Tab> tabList = dropdownTab.getTabList(); 380 381 for (Tab tab : tabList) { 382 383 tabLinkList.remove(tab.asTabLink()); 384 if (tab.getTabPane() != null) { 385 tab.getTabPane().removeFromParent(); 386 } 387 } 388 389 return tabs.remove(dropdownTab); 390 391 } else if (w instanceof TabPane) { 392 return tabContent.remove(w); 393 } 394 395 return super.remove(w); 396 } 397 398 /** 399 * {@inheritDoc} 400 */ 401 @Override 402 public boolean remove(IsWidget child) { 403 404 if (child instanceof Tab) { 405 Tab tab = (Tab) child; 406 407 TabLink link = tab.asTabLink(); 408 409 if (link.getTabPane() != null) { 410 link.getTabPane().removeFromParent(); 411 } 412 tabLinkList.remove(link); 413 return tabs.remove(link); 414 } else if (child instanceof DropdownTab) { 415 DropdownTab tab = (DropdownTab) child; 416 417 List<Tab> tabList = tab.getTabList(); 418 419 for (Tab tab2 : tabList) { 420 tabLinkList.remove(tab2.asTabLink()); 421 if (tab2.getTabPane() != null) { 422 tabContent.remove(tab2.getTabPane()); 423 } 424 } 425 return super.remove(child); 426 } 427 428 return super.remove(child); 429 } 430 431 /** 432 * Activate tab by index. 433 * @param index tab index. 434 */ 435 public void selectTab(int index) { 436 tabLinkList.get(index).show(); 437 } 438 439 /** 440 * Get Current selected tab index. 441 * <p> 442 * if not found, return <code>-1.</code> 443 * </p> 444 * 445 * @return tab index. 446 */ 447 public int getSelectedTab() { 448 449 for (int i = 0; i < tabLinkList.size(); i++) { 450 if (tabLinkList.get(i).isActive()) { 451 return i; 452 } 453 } 454 return -1; 455 } 456 457 private void setHandlerFunctions(final TabLink e) { 458 if (isOrWasAttached()) { 459 setHandlerFunctions(e.getAnchor().getElement()); 460 return; 461 } 462 463 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 464 465 @Override 466 public void execute() { 467 setHandlerFunctions(e.getAnchor().getElement()); 468 } 469 }); 470 471 } 472 473 protected void onShow(Event e, Element target, Element relatedTarget) { 474 ShowEvent event = new ShowEvent(e); 475 event.setTarget(findTabLink(target)); 476 event.setRelatedTarget(findTabLink(relatedTarget)); 477 fireEvent(event); 478 } 479 480 protected void onShown(Event e, Element target, Element relatedTarget) { 481 ShownEvent event = new ShownEvent(e); 482 event.setTarget(findTabLink(target)); 483 event.setRelatedTarget(findTabLink(relatedTarget)); 484 fireEvent(event); 485 } 486 487 public HandlerRegistration addShowHandler(ShowEvent.Handler handler) { 488 return addHandler(handler, ShowEvent.TYPE); 489 } 490 491 public HandlerRegistration addShownHandler(ShownEvent.Handler handler) { 492 return addHandler(handler, ShownEvent.TYPE); 493 } 494 495 private TabLink findTabLink(Element e) { 496 for (TabLink tabLink : tabLinkList) 497 if (tabLink.getAnchor().getElement().equals(e)) 498 return tabLink; 499 500 return null; 501 } 502 503 //@formatter:off 504 private native void setHandlerFunctions(Element e) /*-{ 505 var that = this; 506 var $this = $wnd.jQuery(e); 507 508 $this.off('show'); 509 $this.off('shown'); 510 511 $this.on('show', function(e) { 512 [email protected]::onShow(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/dom/client/Element;Lcom/google/gwt/dom/client/Element;)(e, e.target, e.relatedTarget); 513 }); 514 $this.on('shown', function(e) { 515 [email protected]::onShown(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/dom/client/Element;Lcom/google/gwt/dom/client/Element;)(e, e.target, e.relatedTarget); 516 }); 517 }-*/; 518 //@formatter:on 519 520}