org.l2x6.eircc.ui.misc.IrcImages.java Source code

Java tutorial

Introduction

Here is the source code for org.l2x6.eircc.ui.misc.IrcImages.java

Source

/*
 * Copyright (c) 2014 Peter Palaga.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.l2x6.eircc.ui.misc;

import java.awt.Dimension;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.gmf.runtime.draw2d.ui.render.RenderInfo;
import org.eclipse.gmf.runtime.draw2d.ui.render.RenderedImage;
import org.eclipse.gmf.runtime.draw2d.ui.render.factory.RenderedImageFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.viewers.DecorationOverlayIcon;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.RGB;
import org.l2x6.eircc.core.model.AbstractIrcChannel;
import org.l2x6.eircc.core.model.IrcAccount;
import org.l2x6.eircc.core.model.IrcAccountsStatistics;
import org.l2x6.eircc.core.model.IrcBase;
import org.l2x6.eircc.core.model.IrcChannelUser;
import org.l2x6.eircc.core.model.IrcLog;
import org.l2x6.eircc.core.model.IrcMessage;
import org.l2x6.eircc.core.model.IrcModel;
import org.l2x6.eircc.core.model.IrcObject;
import org.l2x6.eircc.core.model.IrcUser;
import org.l2x6.eircc.core.model.PlainIrcChannel;
import org.l2x6.eircc.ui.prefs.IrcPreferences;

/**
 * @author <a href="mailto:ppalaga@redhat.com">Peter Palaga</a>
 */
public class IrcImages {
    private static class GmfRenderInfo implements RenderInfo {
        private final ImageSize size;

        /**
         * @param size
         */
        public GmfRenderInfo(ImageSize size) {
            super();
            this.size = size;
        }

        @Override
        public RGB getBackgroundColor() {
            return null;
        }

        @Override
        public RGB getForegroundColor() {
            return null;
        }

        @Override
        public int getHeight() {
            return size.getHeight();
        }

        @Override
        public int getWidth() {
            return size.getWidth();
        }

        @Override
        public void setValues(int width, int height, boolean maintainAspectRatio, boolean antialias, RGB background,
                RGB foreground) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean shouldAntiAlias() {
            return true;
        }

        @Override
        public boolean shouldMaintainAspectRatio() {
            return false;
        }
    }

    public class ImageImageDescriptor extends ImageDescriptor {
        private Image fImage;

        /**
         * Constructor for ImagImageDescriptor.
         */
        public ImageImageDescriptor(Image image) {
            super();
            fImage = image;
        }

        /*
         * (non-Javadoc)
         *
         * @see Object#equals(Object)
         */
        @Override
        public boolean equals(Object obj) {
            return (obj != null) && getClass().equals(obj.getClass())
                    && fImage.equals(((ImageImageDescriptor) obj).fImage);
        }

        /*
         * (non-Javadoc)
         *
         * @see ImageDescriptor#getImageData()
         */
        @Override
        public ImageData getImageData() {
            return fImage.getImageData();
        }

        /*
         * (non-Javadoc)
         *
         * @see Object#hashCode()
         */
        @Override
        public int hashCode() {
            return fImage.hashCode();
        }
    }

    public enum ImageKey {
        ACCOUNT("account.gif", IrcAccount.class), //
        ACCOUNT_NEW("account-new.png"), //
        ADMIN_OVERLAY("admin-overlay.png", null, SWT.NONE, "admin-overlay.svg", ImageSize._7x8), //
        BLUE_BALL_OVERLAY("blue-ball-overlay.png", null, SWT.NONE, "blue-ball-overlay.svg", ImageSize._7x7), //
        CHANNEL("channel.png", AbstractIrcChannel.class, SWT.NONE, "channel.svg", ImageSize._16x16), //
        CHANNEL_HISTORY("channel-history.png", AbstractIrcChannel.class, SWT.NONE, "channel-history.svg",
                ImageSize._16x16), //
        CONNECT("connect.gif"), //
        DISCONNECT("disconnect.gif"), //
        ORANGE_BALL_OVERLAY("orange-ball-overlay.png", null, SWT.NONE, "orange-ball-overlay.svg", ImageSize._7x7), //
        GREEN_BALL_OVERLAY("green-ball-overlay.png", null, SWT.NONE, "green-ball-overlay.svg", ImageSize._7x7), //
        IRC_CLIENT("eircc.png", IrcModel.class, SWT.NONE, "eircc.svg", ImageSize._16x16), //
        IRC_CLIENT_DISABLED(IRC_CLIENT, SWT.IMAGE_GRAY), //
        JOIN_CHANNEL("join-channel.gif"), //
        LEAVE_CHANNEL("leave-channel.gif"), //
        MESSAGE("message.png", IrcMessage.class, SWT.NONE, "message.svg", ImageSize._16x16), //
        NEW_OVERLAY("new-overlay.png"), //
        REFRESH("refresh.gif"), //
        SEARCH("irc-search.png", null, SWT.NONE, "irc-search.svg", ImageSize._16x16), //
        SMILEY_OVERLAY("smiley-overlay.png", null, SWT.NONE, "smiley-overlay.svg", ImageSize._7x7), //
        USER("user.gif", IrcUser.class), //
        WARNING_OVERLAY("warning-overlay.gif", null, SWT.NONE, "warning-overlay.svg", ImageSize._7x8);

        private static final Map<Class<?>, ImageKey> CLASS_LOOKUP;

        static {
            ImageKey[] imageKeys = ImageKey.values();
            Map<Class<?>, ImageKey> m = new HashMap<Class<?>, IrcImages.ImageKey>(
                    imageKeys.length + imageKeys.length / 2 + 1);
            for (ImageKey imageKey : imageKeys) {
                if (imageKey.modelClass != null) {
                    m.put(imageKey.modelClass, imageKey);
                }
            }
            /* Assing images to some extra classes */
            m.put(IrcChannelUser.class, USER);
            m.put(PlainIrcChannel.class, CHANNEL);
            CLASS_LOOKUP = Collections.unmodifiableMap(m);
        }

        private static StringBuilder appendKey(StringBuilder sb, String name, int flags, ImageSize size) {
            return sb.append("f").append(flags).append("-").append(name).append("-").append(size.getWidth())
                    .append("x").append(size.getHeight());
        }

        public static ImageKey fromModelClass(Class<?> cl) {
            return CLASS_LOOKUP.get(cl);
        }

        private final int flags;

        private final String key16x16;
        private final Class<?> modelClass;
        private final String path16x16;
        private final String pathSvg;

        /**
         * As stupid as the name of this field may sound... this is a width and
         * height of the image in pixels. 16x16 is only the form factor, whereas
         * the image may be an overlay for this form factor that in reality has
         * 7x7 pixels.
         */
        private final ImageSize size16x16;

        private ImageKey(ImageKey imageKey, int flags) {
            this(imageKey.path16x16, imageKey.modelClass, flags, imageKey.pathSvg, imageKey.size16x16);
        }

        /**
         * @param path
         */
        private ImageKey(String path16x16) {
            this(path16x16, null, SWT.NONE, null, ImageSize._16x16);
        }

        /**
         * @param path
         * @param modelClass
         */
        private ImageKey(String path16x16, Class<?> modelClass) {
            this(path16x16, modelClass, SWT.NONE, null, ImageSize._16x16);
        }

        private ImageKey(String path16x16, Class<?> modelClass, int flags, String pathSvg, ImageSize size16x16) {
            this.path16x16 = path16x16;
            this.modelClass = modelClass;
            this.flags = flags;
            this.pathSvg = pathSvg;
            this.size16x16 = size16x16;
            this.key16x16 = appendKey(new StringBuilder(), name(), flags, ImageSize._16x16).toString();
        }

        public void appendKey(StringBuilder sb, ImageSize size) {
            if (size == ImageSize._16x16) {
                sb.append(key16x16);
            } else {
                appendKey(sb, name(), flags, size);
            }
        }

        public String getAbsolutePath() {
            return "/icons/" + path16x16;
        }

        public String getAbsolutePathSvg() {
            return "/icons-src/" + pathSvg;
        }

        public int getFlags() {
            return flags;
        }

        /**
         * @param size
         * @return
         */
        public String getKey(ImageSize size) {
            return appendKey(new StringBuilder(), name(), flags, size).toString();
        }

        public String getKey16x16() {
            return key16x16;
        }

        public String getPath16x16() {
            return path16x16;
        }

        public ImageSize getSize16x16() {
            return size16x16;
        }
    }

    public static class ImageSize {
        public static final ImageSize _16x16 = new ImageSize(16, 16);
        public static final ImageSize _7x7 = new ImageSize(7, 7);
        public static final ImageSize _7x8 = new ImageSize(7, 8);
        private final int height;
        private final int width;

        /**
         * @param trayIconSize
         */
        public ImageSize(Dimension dimension) {
            this.width = dimension.width;
            this.height = dimension.height;
        }

        /**
         * @param width
         * @param height
         */
        public ImageSize(int width, int height) {
            super();
            this.width = width;
            this.height = height;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            ImageSize other = (ImageSize) obj;
            if (height != other.height)
                return false;
            if (width != other.width)
                return false;
            return true;
        }

        public int getHeight() {
            return height;
        }

        public int getWidth() {
            return width;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + height;
            result = prime * result + width;
            return result;
        }

        public ImageSize scaleToSquare(int size) {
            return new ImageSize(width * size / ImageSize._16x16.getWidth(),
                    height * size / ImageSize._16x16.getHeight());
        }

        @Override
        public String toString() {
            return "" + width + "x" + height;
        }

    }

    private static final IrcImages INSTANCE = new IrcImages();

    public static Image fromSvg(URL url, ImageSize size) {
        RenderInfo ri = new GmfRenderInfo(size);
        RenderedImage renderedImage = RenderedImageFactory.getInstance(url, ri);
        return renderedImage.getSWTImage();
    }

    public static IrcImages getInstance() {
        return INSTANCE;
    }

    private static String getKey(ImageKey[] overlays, ImageSize size) {
        int i = 0;
        StringBuilder sb = new StringBuilder();
        overlays[i++].appendKey(sb, size);
        for (; i < overlays.length; i++) {
            ImageKey imageKey = overlays[i];
            if (imageKey != null) {
                sb.append("_q").append(i - 1).append('_').append(imageKey.getKey16x16());
            }
        }
        return sb.toString();
    }

    private final ImageRegistry imageRegistry = new ImageRegistry();

    /**
     *
     */
    public IrcImages() {

        for (ImageKey imageKey : ImageKey.values()) {
            ImageDescriptor imageDescriptor = ImageDescriptor.createFromFile(this.getClass(),
                    imageKey.getAbsolutePath());
            if (imageKey.getFlags() != SWT.NONE) {
                imageDescriptor = ImageDescriptor.createWithFlags(imageDescriptor, imageKey.getFlags());
            }
            imageRegistry.put(imageKey.getKey16x16(), imageDescriptor);
        }

    }

    public void dispose() {
        imageRegistry.dispose();
    }

    public Image[] getFlashingImage(IrcAccountsStatistics stats, ImageSize size) {
        IrcPreferences prefs = IrcPreferences.getInstance();
        if (stats.hasChannelsNamingMe() && prefs.shouldTrayFlashOnNamingMe()) {
            return new Image[] { getImage(getOverlays(stats, true), size),
                    getImage(getOverlays(stats, false), size) };
        } else {
            return new Image[] { getImage(getOverlays(stats, true), size) };
        }
    }

    public Image getImage(Class<?> cl) {
        return imageRegistry.get(ImageKey.fromModelClass(cl).getKey16x16());
    }

    public Image getImage(ImageKey imageKey) {
        return imageRegistry.get(imageKey.getKey16x16());
    }

    public Image getImage(ImageKey[] overlays) {
        return getImage(overlays, ImageSize._16x16);
    }

    public Image getImage(ImageKey[] overlays, ImageSize size) {
        String key = getKey(overlays, size);
        getImageDescriptor(key, overlays, size);
        return imageRegistry.get(key);
    }

    public Image getImage(IrcBase element) {
        if (element == null) {
            return null;
        }
        if (element instanceof IrcAccount) {
            return getImage(getOverlays((IrcAccount) element));
        } else if (element instanceof AbstractIrcChannel) {
            return getImage(getOverlays((AbstractIrcChannel) element));
        } else if (element instanceof IrcModel) {
            return getImage(getOverlays(((IrcModel) element).getAccountsStatistics(), true));
        } else if (element instanceof IrcChannelUser) {
            return getImage(getOverlays((IrcChannelUser) element));
        }
        return getImage(element.getClass());
    }

    public ImageDescriptor getImageDescriptor(ImageKey imageKey) {
        return getImageDescriptor(imageKey, ImageSize._16x16);
    }

    public ImageDescriptor getImageDescriptor(ImageKey imageKey, ImageKey overlayKey, ImageSize size,
            int quadrant) {
        ImageKey[] overlays = new ImageKey[6];
        overlays[0] = imageKey;
        overlays[quadrant + 1] = overlayKey;
        String key = getKey(overlays, size);
        return getImageDescriptor(key, overlays, size);
    }

    public ImageDescriptor getImageDescriptor(ImageKey imageKey, ImageSize size) {
        if (imageKey == null) {
            return null;
        }
        String key = imageKey.getKey(size);
        ImageDescriptor result = imageRegistry.getDescriptor(key);
        if (result == null) {
            /* this should happen for non-16x16 images only */
            String svgPath = imageKey.getAbsolutePathSvg();
            if (svgPath != null) {
                URL url = getClass().getClassLoader().getResource(imageKey.getAbsolutePathSvg());
                if (url == null) {
                    return null;
                }
                Image image = fromSvg(url, imageKey.getSize16x16().scaleToSquare(size.getWidth()));
                if (imageKey.getFlags() != SWT.NONE) {
                    result = ImageDescriptor.createWithFlags(new ImageImageDescriptor(image), imageKey.getFlags());
                } else {
                    result = new ImageImageDescriptor(image);
                }
                imageRegistry.put(key, result);
            }
        }
        return result;
    }

    public ImageDescriptor getImageDescriptor(IrcObject element) {
        return getImageDescriptor(element, ImageSize._16x16);
    }

    public ImageDescriptor getImageDescriptor(IrcObject element, ImageSize size) {
        if (element == null) {
            return null;
        }
        ImageKey[] overlays;
        if (element instanceof IrcAccount) {
            overlays = getOverlays((IrcAccount) element);
        } else if (element instanceof AbstractIrcChannel) {
            overlays = getOverlays((AbstractIrcChannel) element);
        } else {
            return getImageDescriptor(ImageKey.fromModelClass(element.getClass()), size);
        }
        String key = getKey(overlays, size);
        return getImageDescriptor(key, overlays, size);
    }

    public ImageDescriptor getImageDescriptor(String key, ImageKey[] overlays, ImageSize size) {
        ImageDescriptor result = imageRegistry.getDescriptor(key);
        if (result == null) {
            switch (overlays.length) {
            case 1:
                result = getImageDescriptor(overlays[0], size);
                break;
            case 6:
                result = new DecorationOverlayIcon(getImage(overlays[0]), toOverlayDescriptors(overlays, size));
                imageRegistry.put(key, result);
                break;
            default:
                throw new IllegalArgumentException("Unexpected overlays length.");
            }
        }
        return result;
    }

    private ImageKey[] getOverlays(AbstractIrcChannel channel) {
        boolean hasOverlays = false;
        ImageKey topLeftOverlay = null;
        ImageKey topRightOverlay = null;
        ImageKey bottomLeftOverlay = null;
        ImageKey bottomRightOverlay = null;
        ImageKey underlay = null;
        IrcLog log = channel.getLog();
        if (log != null) {
            switch (log.getNotificationLevel()) {
            case ME_NAMED:
                topRightOverlay = ImageKey.SMILEY_OVERLAY;
                hasOverlays = true;
                break;
            case UNREAD_MESSAGES:
                topRightOverlay = ImageKey.BLUE_BALL_OVERLAY;
                hasOverlays = true;
                break;
            case UNREAD_MESSAGES_FROM_A_TRACKED_USER:
                topRightOverlay = ImageKey.ORANGE_BALL_OVERLAY;
                hasOverlays = true;
                break;
            case NO_NOTIFICATION:
                if (channel.isJoined()) {
                    topRightOverlay = ImageKey.GREEN_BALL_OVERLAY;
                    hasOverlays = true;
                }
                break;
            }
        } else if (channel.isJoined()) {
            topRightOverlay = ImageKey.GREEN_BALL_OVERLAY;
            hasOverlays = true;
        }

        if (hasOverlays) {
            return new ImageKey[] { ImageKey.CHANNEL, topLeftOverlay, topRightOverlay, bottomLeftOverlay,
                    bottomRightOverlay, underlay };
        } else {
            return new ImageKey[] { ImageKey.CHANNEL };
        }
    }

    private ImageKey[] getOverlays(IrcAccount account) {
        boolean hasOverlays = false;
        ImageKey topLeftOverlay = null;
        ImageKey topRightOverlay = null;
        ImageKey bottomLeftOverlay = null;
        ImageKey bottomRightOverlay = null;
        ImageKey underlay = null;
        switch (account.getState()) {
        case ONLINE:
            topRightOverlay = ImageKey.GREEN_BALL_OVERLAY;
            hasOverlays = true;
            break;
        case OFFLINE:
            break;
        case OFFLINE_AFTER_ERROR:
            topLeftOverlay = ImageKey.WARNING_OVERLAY;
            hasOverlays = true;
            break;
        }
        if (hasOverlays) {
            return new ImageKey[] { ImageKey.ACCOUNT, topLeftOverlay, topRightOverlay, bottomLeftOverlay,
                    bottomRightOverlay, underlay };
        } else {
            return new ImageKey[] { ImageKey.ACCOUNT };
        }

    }

    /**
     * @param element
     * @return
     */
    private ImageKey[] getOverlays(IrcAccountsStatistics stats, boolean withUnseenBall) {

        /*
         * colored or desaturated base image depending on whether there are
         * channels online
         */
        ImageKey base = stats.getChannelsOnline() > 0 ? ImageKey.IRC_CLIENT : ImageKey.IRC_CLIENT_DISABLED;
        ImageKey topLeftOverlay = stats.hasChannelsOfflineAfterError() ? ImageKey.WARNING_OVERLAY : null;
        ImageKey topRightOverlay = null;
        ImageKey bottomLeftOverlay = null;
        ImageKey bottomRightOverlay = null;
        ImageKey underlay = null;

        if (stats.hasChannelsNamingMe()) {
            topRightOverlay = withUnseenBall ? ImageKey.SMILEY_OVERLAY : null;
        } else if (stats.hasChannelsWithUnreadMessagesFromTrackedUsers()) {
            topRightOverlay = ImageKey.ORANGE_BALL_OVERLAY;
        } else if (stats.hasChannelsWithUnreadMessages()) {
            topRightOverlay = ImageKey.BLUE_BALL_OVERLAY;
        }

        boolean hasOverlays = topLeftOverlay != null || topRightOverlay != null || bottomLeftOverlay != null
                || bottomRightOverlay != null || underlay != null;

        if (hasOverlays) {
            return new ImageKey[] { base, topLeftOverlay, topRightOverlay, bottomLeftOverlay, bottomRightOverlay,
                    underlay };
        } else {
            return new ImageKey[] { base };
        }
    }

    /**
     * @param element
     * @return
     */
    private ImageKey[] getOverlays(IrcChannelUser user) {
        boolean hasOverlays = false;
        ImageKey topLeftOverlay = null;
        ImageKey topRightOverlay = null;
        ImageKey bottomLeftOverlay = null;
        ImageKey bottomRightOverlay = null;
        ImageKey underlay = null;
        if (user != null && user.getFlags().isOp()) {
            bottomRightOverlay = ImageKey.ADMIN_OVERLAY;
            hasOverlays = true;
        }
        if (hasOverlays) {
            return new ImageKey[] { ImageKey.USER, topLeftOverlay, topRightOverlay, bottomLeftOverlay,
                    bottomRightOverlay, underlay };
        } else {
            return new ImageKey[] { ImageKey.USER };
        }

    }

    private ImageDescriptor[] toOverlayDescriptors(ImageKey[] overlays, ImageSize size) {
        int i = 1;
        return new ImageDescriptor[] { getImageDescriptor(overlays[i++], size),
                getImageDescriptor(overlays[i++], size), getImageDescriptor(overlays[i++], size),
                getImageDescriptor(overlays[i++], size), getImageDescriptor(overlays[i++], size) };
    }

}