org.eclipse.mylyn.commons.workbench.GradientDrawer.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.commons.workbench.GradientDrawer.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2010 Tasktop Technologies and others.
 * 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
 *
 * Contributors:
 *     Tasktop Technologies - initial API and implementation
 *     Frank Becker - improvements
 *******************************************************************************/

package org.eclipse.mylyn.commons.workbench;

import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.mylyn.commons.ui.compatibility.CommonThemes;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.themes.IThemeManager;

/**
 * @author Mik Kersten
 * @author Frank Becker
 * @since 3.7
 */
public abstract class GradientDrawer {

    private final Listener CATEGORY_GRADIENT_DRAWER = new Listener() {
        public void handleEvent(Event event) {
            if (shouldApplyGradient(event)) {
                Scrollable scrollable = (Scrollable) event.widget;
                GC gc = event.gc;

                Rectangle area = scrollable.getClientArea();
                Rectangle rect = event.getBounds();

                /* Paint the selection beyond the end of last column */
                expandRegion(event, scrollable, gc, area);

                /* Draw Gradient Rectangle */
                Color oldForeground = gc.getForeground();
                Color oldBackground = gc.getBackground();

                gc.setForeground(categoryGradientEnd);
                gc.drawLine(0, rect.y, area.width, rect.y);

                gc.setForeground(categoryGradientStart);
                gc.setBackground(categoryGradientEnd);

                // gc.setForeground(categoryGradientStart);
                // gc.setBackground(categoryGradientEnd);
                // gc.setForeground(new Clr(Display.getCurrent(), 255, 0, 0));

                gc.fillGradientRectangle(0, rect.y + 1, area.width, rect.height, true);

                /* Bottom Line */
                // gc.setForeground();
                gc.setForeground(categoryGradientEnd);
                gc.drawLine(0, rect.y + rect.height - 1, area.width, rect.y + rect.height - 1);

                gc.setForeground(oldForeground);
                gc.setBackground(oldBackground);
                /* Mark as Background being handled */
                event.detail &= ~SWT.BACKGROUND;
            }
        }

        private void expandRegion(Event event, Scrollable scrollable, GC gc, Rectangle area) {
            int columnCount;
            if (scrollable instanceof Table) {
                columnCount = ((Table) scrollable).getColumnCount();
            } else {
                columnCount = ((Tree) scrollable).getColumnCount();
            }

            if (event.index == columnCount - 1 || columnCount == 0) {
                int width = area.x + area.width - event.x;
                if (width > 0) {
                    Region region = new Region();
                    gc.getClipping(region);
                    region.add(event.x, event.y, width, event.height);
                    gc.setClipping(region);
                    region.dispose();
                }
            }
        }
    };

    protected abstract boolean shouldApplyGradient(Event event);

    private final IPropertyChangeListener THEME_CHANGE_LISTENER = new IPropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent event) {
            if (event.getProperty().equals(IThemeManager.CHANGE_CURRENT_THEME)
                    || event.getProperty().equals(CommonThemes.COLOR_SCHEDULED_PAST)
                    || event.getProperty().equals(CommonThemes.COLOR_COMPLETED_TODAY)
                    || event.getProperty().equals(CommonThemes.COLOR_COMPLETED)
                    || event.getProperty().equals(CommonThemes.COLOR_OVERDUE)
                    || event.getProperty().equals(CommonThemes.COLOR_SCHEDULED_TODAY)
                    || event.getProperty().equals(CommonThemes.COLOR_SCHEDULED_PAST)
                    || event.getProperty().equals(CommonThemes.COLOR_SCHEDULED_TODAY)
                    || event.getProperty().equals(CommonThemes.COLOR_SCHEDULED_THIS_WEEK)
                    || event.getProperty().equals(CommonThemes.COLOR_TASK_ACTIVE)
                    || CommonThemes.isCommonTheme(event.getProperty())) {
                configureGradientColors();
            }
        }
    };

    private boolean gradientListenerAdded = false;

    private final IThemeManager themeManager;

    private Color categoryGradientStart;

    private Color categoryGradientEnd;

    private final TreeViewer treeViewer;

    public GradientDrawer(IThemeManager theThemeManager, TreeViewer treeViewer) {
        this.themeManager = theThemeManager;
        this.treeViewer = treeViewer;
        treeViewer.getControl().addDisposeListener(new DisposeListener() {

            public void widgetDisposed(DisposeEvent e) {
                if (themeManager != null) {
                    themeManager.removePropertyChangeListener(THEME_CHANGE_LISTENER);
                }
            }
        });
        configureGradientColors();
        themeManager.addPropertyChangeListener(THEME_CHANGE_LISTENER);
    }

    private void configureGradientColors() {
        categoryGradientStart = themeManager.getCurrentTheme().getColorRegistry()
                .get(CommonThemes.COLOR_CATEGORY_GRADIENT_START);
        categoryGradientEnd = themeManager.getCurrentTheme().getColorRegistry()
                .get(CommonThemes.COLOR_CATEGORY_GRADIENT_END);

        boolean customized = true;
        if (categoryGradientStart != null && categoryGradientStart.getRed() == 240
                && categoryGradientStart.getGreen() == 240 && categoryGradientStart.getBlue() == 240
                && categoryGradientEnd != null && categoryGradientEnd.getRed() == 220
                && categoryGradientEnd.getGreen() == 220 && categoryGradientEnd.getBlue() == 220) {
            customized = false;
        }

        if (gradientListenerAdded == false && categoryGradientStart != null
                && !categoryGradientStart.equals(categoryGradientEnd)) {
            getViewer().getTree().addListener(SWT.EraseItem, CATEGORY_GRADIENT_DRAWER);
            gradientListenerAdded = true;
            if (!customized) {
                // Set parent-based colors
                Color parentBackground = getViewer().getTree().getParent().getBackground();
                double GRADIENT_TOP;// = 1.05;// 1.02;
                double GRADIENT_BOTTOM;// = .995;// 1.035;

                // Constants to darken or lighten the default gradients
                if ("Windows 7".equals(System.getProperty("os.name"))) { //$NON-NLS-1$//$NON-NLS-2$
                    GRADIENT_TOP = 1.05;
                    GRADIENT_BOTTOM = 1.09;
                } else {
                    GRADIENT_TOP = 1.05;
                    GRADIENT_BOTTOM = .995;
                }

                int red = Math.max(0, Math.min(255, (int) (parentBackground.getRed() * GRADIENT_TOP)));
                int green = Math.max(0, Math.min(255, (int) (parentBackground.getGreen() * GRADIENT_TOP)));
                int blue = Math.max(0, Math.min(255, (int) (parentBackground.getBlue() * GRADIENT_TOP)));

                try {
                    categoryGradientStart = new Color(Display.getDefault(), red, green, blue);
                } catch (Exception e) {
                    categoryGradientStart = getViewer().getTree().getParent().getBackground();
                    //               StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not set color: " + red //$NON-NLS-1$
                    //                     + ", " + green + ", " + blue, e)); //$NON-NLS-1$ //$NON-NLS-2$
                }
                red = Math.min(255, Math.max(0, (int) (parentBackground.getRed() / GRADIENT_BOTTOM)));
                green = Math.min(255, Math.max(0, (int) (parentBackground.getGreen() / GRADIENT_BOTTOM)));
                blue = Math.min(255, Math.max(0, (int) (parentBackground.getBlue() / GRADIENT_BOTTOM)));

                try {
                    categoryGradientEnd = new Color(Display.getDefault(), red, green, blue);
                } catch (Exception e) {
                    categoryGradientStart = getViewer().getTree().getParent().getBackground();
                    //               StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not set color: " + red //$NON-NLS-1$
                    //                     + ", " + green + ", " + blue, e)); //$NON-NLS-1$ //$NON-NLS-2$
                }
            }
        } else if (categoryGradientStart != null && categoryGradientStart.equals(categoryGradientEnd)) {
            getViewer().getTree().removeListener(SWT.EraseItem, CATEGORY_GRADIENT_DRAWER);
            gradientListenerAdded = false;
        }
    }

    public TreeViewer getViewer() {
        return treeViewer;
    }

}