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.Icon;
019import com.github.gwtbootstrap.client.ui.constants.*;
020import com.google.gwt.dom.client.AnchorElement;
021import com.google.gwt.event.dom.client.ClickEvent;
022import com.google.gwt.event.dom.client.ClickHandler;
023import com.google.gwt.event.dom.client.HasClickHandlers;
024import com.google.gwt.event.dom.client.HasMouseDownHandlers;
025import com.google.gwt.event.dom.client.MouseDownEvent;
026import com.google.gwt.event.dom.client.MouseDownHandler;
027import com.google.gwt.event.shared.HandlerRegistration;
028import com.google.gwt.user.client.DOM;
029import com.google.gwt.user.client.Event;
030import com.google.gwt.user.client.ui.Focusable;
031import com.google.gwt.user.client.ui.HasEnabled;
032import com.google.gwt.user.client.ui.HasName;
033import com.google.gwt.user.client.ui.HasText;
034import com.google.gwt.user.client.ui.impl.FocusImpl;
035
036/**
037 * An Anchor with optional image and caret.
038 *
039 * <p>
040 * It uses a HTML {@code <a>} tag and can contain text and child widgets. But
041 * not both at the same time.
042 * </p>
043 *
044 * <p>
045 * <h3>UiBinder Usage:</h3>
046 * {@code <b:IconAnchor icon="plane" href="www.twitter.com">Some Text</b:IconAnchor>}
047 * </p>
048 *
049 * <p>
050 * Here we add a second Icon:
051 *
052 * <pre>
053 * {@code <b:IconAnchor icon="STAR" text="There is a widget so the text goes here">
054 *     <b:Icon type="STAR" />
055 * </b:IconAnchor>}
056 * </pre>
057 *
058 * All parameter are optional. All setters can be used as parameters.
059 * </p>
060 *
061 * @since 2.0.4.0
062 *
063 * @author Dominik Mayer
064 * @author ohashi keisuke
065 */
066public class IconAnchor extends ComplexWidget implements HasText, HasIcon, HasHref, HasClickHandlers, HasEnabled, Focusable, HasName, HasMouseDownHandlers {
067
068    private static final FocusImpl impl = FocusImpl.getFocusImplForWidget();
069
070        private Icon icon = new Icon();
071
072        private TextNode text = new TextNode("");
073
074        private Caret caret = new Caret();
075
076    private IconPosition iconPosition;
077
078        /**
079         * Creates the widget and sets the {@code href} property to
080         * {@code javascript:;} in order to avoid problems when clicking on it.
081         */
082        public IconAnchor() {
083                super("a");
084                setIconPosition(IconPosition.LEFT);
085                setEmptyHref();
086        }
087
088        /**
089         * {@inheritDoc}
090         */
091        @Override
092        public void setIconPosition(IconPosition position) {
093
094            this.iconPosition = position;
095        icon.removeFromParent();
096            text.removeFromParent();
097
098        if(IconPosition.RIGHT == position) {
099            this.insert(text , 0);
100            this.insert(icon , 1);
101            return;
102
103        } else if(IconPosition.LEFT == position){
104                this.insert(icon, 0);
105                this.insert(text, 1);
106                return;
107            }
108
109        }
110
111    /**
112     * {@inheritDoc}
113     */
114    @Override
115    public void setIcon(IconType type) {
116        setBaseIcon(type);
117    }
118
119    /**
120     * {@inheritDoc}
121     */
122    @Override
123    public void setBaseIcon(BaseIconType type) {
124        this.icon.setBaseType(type);
125    }
126
127        /**
128         * {@inheritDoc}
129         */
130        @Override
131        public void setIconSize(IconSize size) {
132                icon.setIconSize(size);
133        }
134
135        /**
136         * {@inheritDoc}
137         */
138        public void setText(String text) {
139            this.text.removeFromParent();
140            this.text = new TextNode(" " + text + " ");
141            setIconPosition(iconPosition);
142        }
143
144        /**
145         * {@inheritDoc}
146         */
147        public String getText() {
148                return text.getText();
149        }
150
151        /**
152         * {@inheritDoc}
153         */
154        public void setHref(String href) {
155                getElement().setAttribute("href", href);
156        }
157
158        /**
159         * {@inheritDoc}
160         */
161        public String getHref() {
162                return getElement().getAttribute("href");
163        }
164
165        /**
166         * Shows or hides the caret.
167         *
168         * @param visible
169         *            <code>true</code> if the caret should be shown.
170         */
171        public void setCaret(boolean visible) {
172                if (visible)
173                        super.add(caret);
174                else
175                        super.remove(caret);
176        }
177
178        /**
179         * {@inheritDoc}
180         */
181        public void setTargetHistoryToken(String targetHistoryToken) {
182                setHref("#" + targetHistoryToken);
183        }
184
185        /**
186         * {@inheritDoc}
187         */
188        public String getTargetHistoryToken() {
189                String[] hrefs = getHref().split("#");
190                return hrefs[1];
191        }
192
193        /**
194         * Sets the <code>href</code>property of this element to "javascript:;" in
195         * order to get another cursor (hand).
196         */
197        public void setEmptyHref() {
198                setHref(Constants.EMPTY_HREF);
199        }
200
201        /**
202         * {@inheritDoc}
203         */
204        @Override
205        public HandlerRegistration addClickHandler(ClickHandler handler) {
206                return addDomHandler(handler, ClickEvent.getType());
207        }
208
209    /**
210     * {@inheritDoc}
211     */
212    @Override
213    public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
214        return addDomHandler(handler, MouseDownEvent.getType());
215    }
216
217    /**
218         * {@inheritDoc}
219         */
220        @Override
221        public boolean isEnabled() {
222                return !DOM.getElementPropertyBoolean(getElement(), "disabled");
223        }
224
225        /**
226         * {@inheritDoc}
227         */
228        @Override
229        public void setEnabled(boolean enabled) {
230                DOM.setElementPropertyBoolean(getElement(), "disabled", !enabled);
231        }
232
233        /**
234         * {@inheritDoc}
235         */
236        @Override
237        public void onBrowserEvent(Event event) {
238                switch (DOM.eventGetType(event)) {
239                case Event.ONCLICK:
240                        if (isEnabled()) {
241                                super.onBrowserEvent(event);
242                        }
243                        break;
244                default:
245                        super.onBrowserEvent(event);
246                        break;
247                }
248
249        }
250
251    @Override
252    public int getTabIndex() {
253        return impl.getTabIndex(getElement());
254    }
255
256    @Override
257    public void setAccessKey(char key) {
258        DOM.setElementProperty(getElement(), "accessKey", "" + key);
259    }
260
261    @Override
262    public void setFocus(boolean focused) {
263        if (focused) {
264            impl.focus(getElement());
265        } else {
266            impl.blur(getElement());
267        }
268    }
269
270    @Override
271    public void setTabIndex(int index) {
272        impl.setTabIndex(getElement(), index);
273    }
274
275    @Override
276    protected void onAttach() {
277        super.onAttach();
278
279        // Accessibility: setting tab index to be 0 by default, ensuring element
280        // appears in tab sequence. We must ensure that the element doesn't already
281        // have a tabIndex set. This is not a problem for normal widgets, but when
282        // a widget is used to wrap an existing static element, it can already have
283        // a tabIndex.
284        int tabIndex = getTabIndex();
285        if (-1 == tabIndex) {
286            setTabIndex(0);
287        }
288    }
289
290    /**
291     * Set active style name.
292     * @param active <code>true</code> : set active <code>false</code> : unset active
293     */
294    public void setActive(boolean active) {
295        setStyleName(Constants.ACTIVE, active);
296    }
297
298    /**
299     * Has the active css style name?
300     * @return <code>true</code>: has <code>false</code> : none.
301     */
302    public boolean isActive() {
303        return getStyleName().contains(Constants.ACTIVE);
304    }
305
306    /**
307     * {@inheritDoc}
308     */
309    @Override
310    public void setName(String name) {
311        getAnchorElement().setName(name);
312    }
313
314    /**
315     * {@inheritDoc}
316     */
317    @Override
318    public String getName() {
319        return getAnchorElement().getName();
320    }
321
322    /**
323     * Set target attribute
324     * @param target target name
325     */
326    public void setTarget(String target) {
327        getAnchorElement().setTarget(target);
328    }
329
330    /**
331     * Get target attribute value
332     * @return target attribute value
333     */
334    public String getTarget() {
335        return getAnchorElement().getTarget();
336    }
337
338    protected AnchorElement getAnchorElement() {
339        return AnchorElement.as(getElement());
340    }
341
342    /**
343     * {@inheritDoc}
344     */
345    @Override
346    public void setCustomIconStyle(String customIconStyle) {
347        icon.addStyleName(customIconStyle);
348    }
349
350}