com.lambourg.webgallery.client.widgets.TitleBarIcon.java Source code

Java tutorial

Introduction

Here is the source code for com.lambourg.webgallery.client.widgets.TitleBarIcon.java

Source

/* Copyright Jerome Lambourg, 2014 
 * Licensed under GPL v3
 */
package com.lambourg.webgallery.client.widgets;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.Context2d.Composite;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.lambourg.webgallery.client.events.ToggledEvent;
import com.lambourg.webgallery.client.events.ToggledEventHandler;
import com.lambourg.webgallery.client.folderview.Style;

public class TitleBarIcon extends LayoutPanel implements HasHandlers {
    private Canvas canvas;
    private Image imgNormal;
    private Image imgActive;
    private boolean active;
    private boolean over;

    public TitleBarIcon(ImageResource normal) {
        this(normal, null);
    }

    public TitleBarIcon(ImageResource normal, ImageResource active) {
        super();
        this.setStyleName("wg-titlebar-icon");

        this.setWidth(Style.titleIconSize + "px");
        this.setHeight(Style.titleIconSize + "px");

        this.imgNormal = new Image(normal.getSafeUri());
        if (active != null) {
            this.imgActive = new Image(active.getSafeUri());
        } else {
            this.imgActive = null;
        }

        this.canvas = Canvas.createIfSupported();
        this.add(this.canvas);
        this.canvas.setWidth(Style.titleIconSize + "px");
        this.canvas.setHeight(Style.titleIconSize + "px");

        this.active = false;
        this.over = false;

        this.setWidgetLeftRight(this.canvas, 0, Unit.PX, 0, Unit.PX);
        this.setWidgetTopBottom(this.canvas, 0, Unit.PX, 0, Unit.PX);

        this.canvas.addMouseOverHandler(new MouseOverHandler() {
            @Override
            public void onMouseOver(MouseOverEvent event) {
                TitleBarIcon.this.over = true;
                TitleBarIcon.this.draw();
            }
        });
        this.canvas.addMouseOutHandler(new MouseOutHandler() {
            @Override
            public void onMouseOut(MouseOutEvent event) {
                TitleBarIcon.this.over = false;
                TitleBarIcon.this.draw();
            }
        });
        this.canvas.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                TitleBarIcon.this.clicked(event);
            }
        });
        this.addAttachHandler(new AttachEvent.Handler() {
            @Override
            public void onAttachOrDetach(AttachEvent event) {
                if (!event.isAttached()) {
                    return;
                }
                Scheduler.get().scheduleDeferred(new ScheduledCommand() {
                    @Override
                    public void execute() {
                        TitleBarIcon.this.draw();
                    }
                });
            }
        });
    }

    public void setActive(boolean active) {
        if (this.imgActive != null) {
            this.active = active;
            this.draw();
        }
    }

    public boolean getActive() {
        return this.active;
    }

    private void clicked(ClickEvent event) {
        if (this.imgActive != null) {
            this.active = !this.active;
            this.draw();
            this.fireEvent(new ToggledEvent(this, this.active));
        } else {
            this.fireEvent(event);
        }

    }

    /* Draws the icon using only its shape, and replacing the color by the
     * appropriate foreground color regarding the icon state
     */
    private void draw() {
        Context2d ctx;
        Canvas buffer = Canvas.createIfSupported();
        Image img;
        int size = Style.toPixelRatio(Style.titleIconSize);

        this.canvas.setCoordinateSpaceWidth(size);
        this.canvas.setCoordinateSpaceHeight(size + Style.toPixelRatio(1));
        buffer.setCoordinateSpaceWidth(size);
        buffer.setCoordinateSpaceHeight(size);

        if (this.active) {
            img = this.imgActive;
        } else {
            img = this.imgNormal;
        }

        //  We need to draw the icon itself in a separate buffer, and only
        //  after apply the shadow.
        //  The reason is that in order to draw the icon using the color we
        //  want, we need to use composite operations, and this is not
        //  compatible with the shadow effect we want.
        ctx = buffer.getContext2d();
        if (this.over) {
            ctx.setFillStyle("#fff");
        } else {
            ctx.setFillStyle("#ddd");
        }
        ctx.fillRect(0, 0, size, size);
        ctx.setGlobalCompositeOperation(Composite.DESTINATION_ATOP);
        ctx.drawImage(ImageElement.as(img.getElement()), 0, 0, size, size);
        ctx.restore();

        ctx = this.canvas.getContext2d();
        ctx.setShadowBlur(0.0);
        ctx.setShadowColor("#333");
        ctx.setShadowOffsetY(Style.toPixelRatio(1));

        ctx.drawImage(buffer.getCanvasElement(), 0, 0, size, size);
    }

    public int getWidth() {
        return Style.titleIconSize;
    }

    public int getHeight() {
        return Style.titleIconSize;
    }

    public HandlerRegistration addToggledHandler(ToggledEventHandler handler) {
        return this.addHandler(handler, ToggledEvent.TYPE);
    }

    public HandlerRegistration addClickHandler(ClickHandler handler) {
        return this.addHandler(handler, ClickEvent.getType());
    }
}