// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.collide.client.ui.button; import com.google.collide.client.common.BaseResources; import com.google.collide.client.util.CssUtils; import com.google.collide.client.util.Elements; import com.google.collide.client.util.ImageResourceUtils; import com.google.collide.mvp.CompositeView; import com.google.collide.mvp.UiComponent; import com.google.gwt.resources.client.ImageResource; import elemental.events.Event; import elemental.events.EventListener; import elemental.html.AnchorElement; import elemental.html.DivElement; import elemental.html.Element; /** * A button containing and image and text. */ public class ImageButton extends UiComponent<ImageButton.View> { /** * Creates an {@link ImageButton}. */ public static class Builder { private final BaseResources.Resources res; private ImageResource image; private String text; private AnchorElement element; public Builder(BaseResources.Resources res) { this.res = res; } public Builder setImage(ImageResource image) { this.image = image; return this; } public Builder setText(String text) { this.text = text; return this; } public Builder setElement(AnchorElement element) { this.element = element; return this; } public ImageButton build() { // Create an element if one is not specified. AnchorElement anchor = element; if (anchor == null) { anchor = Elements.createAnchorElement(res.baseCss().button()); anchor.setHref("javascript:;"); } View view = new View(res, anchor); ImageButton button = new ImageButton(view); button.setImageAndText(image, text); return button; } } /** * Called when the button is clicked. */ public interface Listener { void onClick(); } /** * The View for the Header. */ public static class View extends CompositeView<ViewEvents> { /** * The spacing between the image and the text. */ private static final int ICON_SPACING = 8; private final BaseResources.Css baseCss; private final DivElement imageElem; private final DivElement imagePositioner; private final DivElement textElem; public View(BaseResources.Resources res, AnchorElement button) { baseCss = res.baseCss(); // Create an outer element. setElement(button); button.getStyle().setPosition("relative"); // Create a centered element to position the image. imagePositioner = Elements.createDivElement(); button.appendChild(imagePositioner); imagePositioner.getStyle().setPosition("absolute"); imagePositioner.getStyle().setTop("50%"); // Add the image. imageElem = Elements.createDivElement(); imagePositioner.appendChild(imageElem); imageElem.addClassName(baseCss.buttonImage()); imageElem.getStyle().setPosition("absolute"); // Override the margins set in base.css. Those margins are a hack. imageElem.getStyle().setMargin("0"); // Add the text. textElem = Elements.createDivElement(); textElem.getStyle().setHeight("100%"); button.appendChild(textElem); attachEventListeners(); } @Override public AnchorElement getElement() { return (AnchorElement) super.getElement(); } public Element getImageElement() { return imageElem; } @SuppressWarnings("null") private void setImageAndText(ImageResource image, String text) { // Update the image. boolean hasImage = (image != null); CssUtils.setDisplayVisibility2(imageElem, hasImage); if (hasImage) { ImageResourceUtils.applyImageResource(imageElem, image); } // Update the text. boolean hasText = (text != null && text.length() > 0); textElem.setTextContent(hasText ? text : ""); // Position the image. if (hasImage) { imageElem.getStyle().setTop(image.getHeight() / -2, "px"); if (hasText) { // Left align the image if we have text. imagePositioner.getStyle().setLeft(baseCss.buttonHorizontalPadding(), "px"); imageElem.getStyle().setLeft(0, "px"); } else { // Horizontally center the image if we do not have text. imagePositioner.getStyle().setLeft("50%"); imageElem.getStyle().setLeft(image.getWidth() / -2, "px"); } } /* * Position the text. Even if there is no text, we use the text element to * force the button element to be wide enough to contain the image. */ int left = 0; if (hasImage) { left += image.getWidth(); } if (hasText) { left += ICON_SPACING; } textElem.getStyle().setPaddingLeft(left, "px"); } private void attachEventListeners() { getElement().addEventListener(Event.CLICK, new EventListener() { @Override public void handleEvent(Event evt) { if (getDelegate() != null) { getDelegate().onButtonClicked(); } } }, false); } } /** * Events reported by the View. */ private interface ViewEvents { void onButtonClicked(); } private Listener listener; private ImageResource image; private boolean isImageHidden; private String text; private ImageButton(View view) { super(view); handleEvents(); } public void setListener(Listener listener) { this.listener = listener; } public void setImage(ImageResource image) { setImageAndText(image, this.text); } public void clearImage() { setImageAndText(null, this.text); } public void setText(String text) { setImageAndText(this.image, text); } public void clearText() { setImageAndText(this.image, null); } public void setImageAndText(ImageResource image, String text) { this.image = image; this.text = text; updateView(); } /** * Shows or hides the image. */ public void setImageHidden(boolean isHidden) { this.isImageHidden = isHidden; updateView(); } private void updateView() { getView().setImageAndText(isImageHidden ? null : image, text); } private void handleEvents() { getView().setDelegate(new ViewEvents() { @Override public void onButtonClicked() { if (listener != null) { listener.onClick(); } } }); } }