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