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.base; 017 018import com.github.gwtbootstrap.client.ui.NavLink; 019import com.github.gwtbootstrap.client.ui.constants.Alignment; 020import com.github.gwtbootstrap.client.ui.constants.Constants; 021import com.google.gwt.core.client.GWT; 022import com.google.gwt.dom.client.Document; 023import com.google.gwt.dom.client.Element; 024import com.google.gwt.event.dom.client.*; 025import com.google.gwt.event.shared.HandlerRegistration; 026import com.google.gwt.uibinder.client.UiChild; 027import com.google.gwt.user.client.ui.HasText; 028import com.google.gwt.user.client.ui.HasWidgets; 029import com.google.gwt.user.client.ui.Widget; 030 031//@formatter:off 032 033/** 034 * Base class for dropdown widgets. 035 * 036 * @author Carlos A Becker 037 * @author Dominik Mayer 038 * 039 * @since 2.0.4.0 040 */ 041//@formatter:on 042public abstract class DropdownBase extends ComplexWidget implements HasChangeHandlers, HasClickHandlers, HasWidgets, HasText, HasIcon { 043 044 private UnorderedList menu = new UnorderedList(); 045 046 protected IconAnchor trigger; 047 048 private NavLink link; 049 050 private NavLinkClickHandler handler = new NavLinkClickHandler(); 051 052 private boolean dropup; 053 054 /** 055 * Creates a new widget of the given type. 056 * 057 * @param type the HTML tag to be used for the widget 058 */ 059 public DropdownBase(String type) { 060 super(type); 061 createAndAddTrigger(); 062 menu.setStyleName("dropdown-menu"); 063 super.add(menu); 064 } 065 066 private void createAndAddTrigger() { 067 trigger = createTrigger(); 068 // Prevents exception when the impl class does not have a trigger. 069 if (trigger != null) { 070 trigger.addStyleName("dropdown-toggle"); 071 trigger.getElement().setAttribute(Constants.DATA_TOGGLE, "dropdown"); 072 super.add(trigger); 073 } 074 } 075 076 /** 077 * Sets the text of the dropdown trigger. 078 * 079 * @param text 080 */ 081 public void setText(String text) { 082 trigger.setText(text); 083 } 084 085 /** 086 * @return the text of the dropdown trigger. 087 */ 088 public String getText() { 089 return trigger.getText(); 090 } 091 092 /** 093 * Get trigger wiget 094 * 095 * @return trigger wiget 096 */ 097 public IconAnchor getTriggerWidget() { 098 return trigger; 099 } 100 101 102 /** 103 * Get menu unordered list widget 104 * 105 * @return menu 106 */ 107 public UnorderedList getMenuWiget() { 108 return menu; 109 } 110 111 /** 112 * Implement this method to create the trigger appropriate for your widget. 113 * It has to be an {@link IconAnchor} or a subtype. 114 * 115 * @return the created trigger 116 */ 117 protected abstract IconAnchor createTrigger(); 118 119 /** 120 * Set dropup style. 121 * 122 * @param dropup true:Set Dropup false:Un-set Dropup 123 */ 124 public void setDropup(boolean dropup) { 125 126 this.dropup = dropup; 127 128 if (dropup) 129 addStyleName(Constants.DROPUP); 130 else 131 removeStyleName(Constants.DROPUP); 132 } 133 134 /** 135 * Is widget dropup? 136 * 137 * @return true:Dropup false:Dropdown 138 */ 139 public boolean isDropup() { 140 return this.dropup; 141 } 142 143 /** 144 * {@inheritDoc} 145 */ 146 @Override 147 protected void onLoad() { 148 super.onLoad(); 149 if (trigger != null) { 150 configure(trigger.getElement()); 151 } 152 } 153 154 /** 155 * Adds a widget to the dropdown menu. 156 * 157 * @param widget the widget that will be added to the menu 158 * @see #addWidget(Widget) 159 */ 160 @Override 161 public void add(Widget widget) { 162 menu.add(widget); 163 if (widget instanceof NavLink) { 164 ((NavLink) widget).addClickHandler(handler); 165 } 166 } 167 168 @Override 169 public HandlerRegistration addChangeHandler(ChangeHandler handler) { 170 return addDomHandler(handler, ChangeEvent.getType()); 171 } 172 173 /** 174 * Adds a widget to the the dropdown widget, <b>not</b> to the dropdown 175 * menu. 176 * <p/> 177 * <p/> 178 * Use {@link #add(Widget)} if you want to add a widget to the dropdown 179 * menu. 180 * 181 * @param widget the widget to be added. 182 */ 183 protected void addWidget(Widget widget) { 184 super.add(widget); 185 } 186 187 private native void configure(Element e) /*-{ 188 $wnd.jQuery(e).dropdown(); 189 }-*/; 190 191 /** 192 * Pull the dropdown menu to right 193 * 194 * @param rightDropdown <code>true</code> pull to right, otherwise to left. Default is 195 * <code>false</code> 196 */ 197 public void setRightDropdown(boolean rightDropdown) { 198 menu.setStyleName(Alignment.RIGHT.get(), rightDropdown); 199 } 200 201 private class NavLinkClickHandler implements ClickHandler { 202 203 @Override 204 public void onClick(ClickEvent event) { 205 try { 206 IconAnchor iconAnchor = (IconAnchor) event.getSource(); 207 link = (NavLink) iconAnchor.getParent(); 208 } catch (Exception e) { 209 GWT.log(e.getMessage(), e); 210 } 211 DomEvent.fireNativeEvent(Document.get().createChangeEvent(), DropdownBase.this); 212 } 213 214 } 215 216 /** 217 * Method to get the {@link NavLink} that has been clicked most recently. 218 * 219 * @return Last clicked NavLink or <code>null</code> if none have been 220 * clicked. 221 */ 222 public NavLink getLastSelectedNavLink() { 223 return link; 224 } 225 226 @Override 227 public void clear() { 228 menu.clear(); 229 } 230 231 @Override 232 public HandlerRegistration addClickHandler(ClickHandler handler) { 233 return trigger.addClickHandler(handler); 234 } 235 236 /** 237 * Add widget to trigger anchodr 238 * 239 * @param w added widget 240 */ 241 @UiChild(tagname = "customTrigger", limit = 1) 242 public void addCustomTrigger(Widget w) { 243 trigger.insert(w, 0); 244 } 245 246}