001 package org.gwtbootstrap3.client.ui;
002
003 /*
004 * #%L
005 * GwtBootstrap3
006 * %%
007 * Copyright (C) 2013 GwtBootstrap3
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 * http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023 import java.util.List;
024
025 import org.gwtbootstrap3.client.ui.base.ComplexWidget;
026 import org.gwtbootstrap3.client.ui.base.HasDataParent;
027 import org.gwtbootstrap3.client.ui.base.HasDataTarget;
028 import org.gwtbootstrap3.client.ui.base.HasDataToggle;
029 import org.gwtbootstrap3.client.ui.base.HasHref;
030 import org.gwtbootstrap3.client.ui.base.HasIcon;
031 import org.gwtbootstrap3.client.ui.base.HasIconPosition;
032 import org.gwtbootstrap3.client.ui.base.HasPull;
033 import org.gwtbootstrap3.client.ui.base.HasTarget;
034 import org.gwtbootstrap3.client.ui.base.HasTargetHistoryToken;
035 import org.gwtbootstrap3.client.ui.base.mixin.AttributeMixin;
036 import org.gwtbootstrap3.client.ui.base.mixin.DataParentMixin;
037 import org.gwtbootstrap3.client.ui.base.mixin.DataTargetMixin;
038 import org.gwtbootstrap3.client.ui.base.mixin.DataToggleMixin;
039 import org.gwtbootstrap3.client.ui.base.mixin.EnabledMixin;
040 import org.gwtbootstrap3.client.ui.base.mixin.FocusableMixin;
041 import org.gwtbootstrap3.client.ui.base.mixin.IconTextMixin;
042 import org.gwtbootstrap3.client.ui.base.mixin.PullMixin;
043 import org.gwtbootstrap3.client.ui.constants.Attributes;
044 import org.gwtbootstrap3.client.ui.constants.IconFlip;
045 import org.gwtbootstrap3.client.ui.constants.IconPosition;
046 import org.gwtbootstrap3.client.ui.constants.IconRotate;
047 import org.gwtbootstrap3.client.ui.constants.IconSize;
048 import org.gwtbootstrap3.client.ui.constants.IconType;
049 import org.gwtbootstrap3.client.ui.constants.Pull;
050 import org.gwtbootstrap3.client.ui.constants.Styles;
051 import org.gwtbootstrap3.client.ui.constants.Toggle;
052
053 import com.google.gwt.dom.client.AnchorElement;
054 import com.google.gwt.dom.client.Document;
055 import com.google.gwt.event.dom.client.ClickEvent;
056 import com.google.gwt.event.dom.client.ClickHandler;
057 import com.google.gwt.event.dom.client.DoubleClickEvent;
058 import com.google.gwt.event.dom.client.DoubleClickHandler;
059 import com.google.gwt.event.dom.client.HasClickHandlers;
060 import com.google.gwt.event.dom.client.HasDoubleClickHandlers;
061 import com.google.gwt.event.shared.HandlerRegistration;
062 import com.google.gwt.user.client.DOM;
063 import com.google.gwt.user.client.Event;
064 import com.google.gwt.user.client.History;
065 import com.google.gwt.user.client.ui.Focusable;
066 import com.google.gwt.user.client.ui.HasEnabled;
067 import com.google.gwt.user.client.ui.HasHTML;
068 import com.google.gwt.user.client.ui.Widget;
069
070 /**
071 * Anchor {@code <a>} element with text and optional icon.
072 *
073 * @author Sven Jacobs
074 * @author Joshua Godi
075 * @author Grant Slender
076 */
077 public class Anchor extends ComplexWidget implements HasEnabled, HasClickHandlers, HasDoubleClickHandlers, HasHref, HasDataToggle, HasDataParent,
078 HasTargetHistoryToken, HasHTML, HasIcon, HasIconPosition, Focusable, HasDataTarget, HasTarget, HasPull {
079
080 private final PullMixin<Anchor> pullMixin = new PullMixin<Anchor>(this);
081 private final DataToggleMixin<Anchor> toggleMixin = new DataToggleMixin<Anchor>(this);
082 private final DataParentMixin<Anchor> parentMixin = new DataParentMixin<Anchor>(this);
083 private final IconTextMixin<Anchor> iconTextMixin = new IconTextMixin<Anchor>(this);
084 private final DataTargetMixin<Anchor> targetMixin = new DataTargetMixin<Anchor>(this);
085 private final AttributeMixin<Anchor> attributeMixin = new AttributeMixin<Anchor>(this);
086 private final FocusableMixin<Anchor> focusableMixin = new FocusableMixin<Anchor>(this);
087 private final EnabledMixin<Anchor> enabledMixin = new EnabledMixin<Anchor>(this);
088 private String targetHistoryToken;
089
090 /**
091 * Creates an anchor widget with the desired HREF
092 *
093 * @param href href for the anchor
094 */
095 public Anchor(final String href) {
096 setElement(Document.get().createAnchorElement());
097 setHref(href);
098 iconTextMixin.addTextWidgetToParent();
099 }
100
101 /**
102 * Creates an achor widget with the desired HREF and text
103 *
104 * @param text text for the anchor
105 * @param href href for the anchor
106 */
107 public Anchor(final String text, final String href) {
108 this(href);
109 setText(text);
110 }
111
112 /**
113 * Creates a default anchor with a default href
114 */
115 public Anchor() {
116 this(EMPTY_HREF);
117 }
118
119 /**
120 * {@inheritDoc}
121 */
122 @Override
123 public HandlerRegistration addClickHandler(final ClickHandler handler) {
124 return addDomHandler(handler, ClickEvent.getType());
125 }
126
127 /**
128 * {@inheritDoc}
129 */
130 @Override
131 public HandlerRegistration addDoubleClickHandler(final DoubleClickHandler handler) {
132 return addDomHandler(handler, DoubleClickEvent.getType());
133 }
134
135 /**
136 * {@inheritDoc}
137 */
138 @Override
139 public void setText(final String text) {
140 iconTextMixin.setText(text);
141 }
142
143 /**
144 * {@inheritDoc}
145 */
146 @Override
147 public String getText() {
148 return iconTextMixin.getText();
149 }
150
151 /**
152 * {@inheritDoc}
153 */
154 @Override
155 public void setIcon(final IconType iconType) {
156 iconTextMixin.setIcon(iconType);
157 }
158
159 /**
160 * {@inheritDoc}
161 */
162 @Override
163 public IconType getIcon() {
164 return iconTextMixin.getIcon();
165 }
166
167 /**
168 * {@inheritDoc}
169 */
170 @Override
171 public void setIconPosition(final IconPosition iconPosition) {
172 iconTextMixin.setIconPosition(iconPosition);
173 }
174
175 /**
176 * {@inheritDoc}
177 */
178 @Override
179 public IconPosition getIconPosition() {
180 return iconTextMixin.getIconPosition();
181 }
182
183 /**
184 * {@inheritDoc}
185 */
186 @Override
187 public void setIconSize(final IconSize iconSize) {
188 iconTextMixin.setIconSize(iconSize);
189 }
190
191 /**
192 * {@inheritDoc}
193 */
194 @Override
195 public IconSize getIconSize() {
196 return iconTextMixin.getIconSize();
197 }
198
199 /**
200 * {@inheritDoc}
201 */
202 @Override
203 public void setIconFlip(final IconFlip iconFlip) {
204 iconTextMixin.setIconFlip(iconFlip);
205 }
206
207 /**
208 * {@inheritDoc}
209 */
210 @Override
211 public IconFlip getIconFlip() {
212 return iconTextMixin.getIconFlip();
213 }
214
215 /**
216 * {@inheritDoc}
217 */
218 @Override
219 public void setIconRotate(final IconRotate iconRotate) {
220 iconTextMixin.setIconRotate(iconRotate);
221 }
222
223 /**
224 * {@inheritDoc}
225 */
226 @Override
227 public IconRotate getIconRotate() {
228 return iconTextMixin.getIconRotate();
229 }
230
231 /**
232 * {@inheritDoc}
233 */
234 @Override
235 public void setIconBordered(final boolean iconBordered) {
236 iconTextMixin.setIconBordered(iconBordered);
237 }
238
239 /**
240 * {@inheritDoc}
241 */
242 @Override
243 public boolean isIconBordered() {
244 return iconTextMixin.isIconBordered();
245 }
246
247 /**
248 * {@inheritDoc}
249 */
250 @Override
251 public void setIconMuted(final boolean iconMuted) {
252 iconTextMixin.setIconMuted(iconMuted);
253 }
254
255 /**
256 * {@inheritDoc}
257 */
258 @Override
259 public boolean isIconMuted() {
260 return iconTextMixin.isIconMuted();
261 }
262
263 /**
264 * {@inheritDoc}
265 */
266 @Override
267 public void setIconLight(final boolean iconLight) {
268 iconTextMixin.setIconLight(iconLight);
269 }
270
271 /**
272 * {@inheritDoc}
273 */
274 @Override
275 public boolean isIconLight() {
276 return iconTextMixin.isIconLight();
277 }
278
279 /**
280 * {@inheritDoc}
281 */
282 @Override
283 public void setIconSpin(final boolean iconSpin) {
284 iconTextMixin.setIconSpin(iconSpin);
285 }
286
287 /**
288 * {@inheritDoc}
289 */
290 @Override
291 public boolean isIconSpin() {
292 return iconTextMixin.isIconSpin();
293 }
294
295 /**
296 * {@inheritDoc}
297 */
298 @Override
299 public void setIconFixedWidth(final boolean iconFixedWidth) {
300 iconTextMixin.setIconFixedWidth(iconFixedWidth);
301 }
302
303 /**
304 * {@inheritDoc}
305 */
306 @Override
307 public boolean isIconFixedWidth() {
308 return iconTextMixin.isIconFixedWidth();
309 }
310
311 /**
312 * {@inheritDoc}
313 */
314 @Override
315 public void setHref(final String href) {
316 AnchorElement.as(getElement()).setHref(href);
317 }
318
319 /**
320 * {@inheritDoc}
321 */
322 @Override
323 public String getHref() {
324 return AnchorElement.as(getElement()).getHref();
325 }
326
327 /**
328 * {@inheritDoc}
329 */
330 @Override
331 public void setTargetHistoryToken(final String targetHistoryToken) {
332 this.targetHistoryToken = targetHistoryToken;
333 final String hash = History.encodeHistoryToken(targetHistoryToken);
334 setHref("#" + hash);
335 }
336
337 /**
338 * {@inheritDoc}
339 */
340 @Override
341 public String getTargetHistoryToken() {
342 return targetHistoryToken;
343 }
344
345 /**
346 * {@inheritDoc}
347 */
348 @Override
349 public void setDataParent(final String dataParent) {
350 parentMixin.setDataParent(dataParent);
351 }
352
353 /**
354 * {@inheritDoc}
355 */
356 @Override
357 public String getDataParent() {
358 return parentMixin.getDataParent();
359 }
360
361 /**
362 * {@inheritDoc}
363 */
364 @Override
365 public void setDataToggle(final Toggle toggle) {
366 toggleMixin.setDataToggle(toggle);
367 }
368
369 /**
370 * {@inheritDoc}
371 */
372 @Override
373 public Toggle getDataToggle() {
374 return toggleMixin.getDataToggle();
375 }
376
377 /**
378 * {@inheritDoc}
379 */
380 @Override
381 public int getTabIndex() {
382 return focusableMixin.getTabIndex();
383 }
384
385 /**
386 * {@inheritDoc}
387 */
388 @Override
389 public void setTabIndex(final int index) {
390 focusableMixin.setTabIndex(index);
391 }
392
393 /**
394 * {@inheritDoc}
395 */
396 @Override
397 public void setAccessKey(final char key) {
398 focusableMixin.setAccessKey(key);
399 }
400
401 /**
402 * {@inheritDoc}
403 */
404 @Override
405 public void setFocus(final boolean focused) {
406 focusableMixin.setFocus(focused);
407 }
408
409 /**
410 * {@inheritDoc}
411 */
412 @Override
413 public String getHTML() {
414 return getElement().getInnerHTML();
415 }
416
417 /**
418 * {@inheritDoc}
419 */
420 @Override
421 public void setHTML(final String html) {
422 getElement().setInnerHTML(html);
423 }
424
425 @Override
426 public void setDataTargetWidgets(final List<Widget> widgets) {
427 targetMixin.setDataTargetWidgets(widgets);
428 }
429
430 @Override
431 public void setDataTargetWidget(final Widget widget) {
432 targetMixin.setDataTargetWidget(widget);
433 }
434
435 /**
436 * {@inheritDoc}
437 */
438 @Override
439 public void setDataTarget(final String dataTarget) {
440 targetMixin.setDataTarget(dataTarget);
441 }
442
443 /**
444 * {@inheritDoc}
445 */
446 @Override
447 public String getDataTarget() {
448 return targetMixin.getDataTarget();
449 }
450
451 /**
452 * {@inheritDoc}
453 */
454 @Override
455 public void setTarget(final String target) {
456 attributeMixin.setAttribute(Attributes.TARGET, target);
457 }
458
459 /**
460 * {@inheritDoc}
461 */
462 @Override
463 public String getTarget() {
464 return attributeMixin.getAttribute(Attributes.TARGET);
465 }
466
467 /**
468 * {@inheritDoc}
469 */
470 @Override
471 public void setPull(final Pull pull) {
472 pullMixin.setPull(pull);
473 }
474
475 /**
476 * {@inheritDoc}
477 */
478 @Override
479 public Pull getPull() {
480 return pullMixin.getPull();
481 }
482
483 /**
484 * {@inheritDoc}
485 */
486 @Override
487 public boolean isEnabled() {
488 return enabledMixin.isEnabled();
489 }
490
491 /**
492 * {@inheritDoc}
493 */
494 @Override
495 public void setEnabled(final boolean enabled) {
496 enabledMixin.setEnabled(enabled);
497 }
498
499 /**
500 * {@inheritDoc}
501 */
502 @Override
503 protected void onAttach() {
504 super.onAttach();
505
506 // Adding styles to the heading depending on the parent
507 if (getParent() != null) {
508 if (getParent() instanceof Alert) {
509 addStyleName(Styles.ALERT_LINK);
510 }
511 }
512 }
513
514 /**
515 * We override this because the <a></a> tag doesn't support the disabled property. So on clicks and focus, if disabled then ignore
516 *
517 * @param event dom event
518 */
519 @Override
520 public void onBrowserEvent(final Event event) {
521 switch (DOM.eventGetType(event)) {
522 case Event.ONDBLCLICK:
523 case Event.ONFOCUS:
524 case Event.ONCLICK:
525 if (!isEnabled()) {
526 return;
527 }
528 break;
529 }
530 super.onBrowserEvent(event);
531 }
532 }