/*******************************************************************************
 * Copyright (c) 2000, 2007 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.forms;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;

/**
 * Manages colors that will be applied to forms and form widgets. The colors are
 * chosen to make the widgets look correct in the editor area. If a different
 * set of colors is needed, subclass this class and override 'initialize' and/or
 * 'initializeColors'.
 * 
 * @since 3.0
 */
public class FormColors {
	/**
	 * Key for the form title foreground color.
	 * 
	 * @deprecated use <code>IFormColors.TITLE</code>.
	 */
	public static final String TITLE = IFormColors.TITLE;

	/**
	 * Key for the tree/table border color.
	 * 
	 * @deprecated use <code>IFormColors.BORDER</code>
	 */
	public static final String BORDER = IFormColors.BORDER;

	/**
	 * Key for the section separator color.
	 * 
	 * @deprecated use <code>IFormColors.SEPARATOR</code>.
	 */
	public static final String SEPARATOR = IFormColors.SEPARATOR;

	/**
	 * Key for the section title bar background.
	 * 
	 * @deprecated use <code>IFormColors.TB_BG
	 */
	public static final String TB_BG = IFormColors.TB_BG;

	/**
	 * Key for the section title bar foreground.
	 * 
	 * @deprecated use <code>IFormColors.TB_FG</code>
	 */
	public static final String TB_FG = IFormColors.TB_FG;

	/**
	 * Key for the section title bar gradient.
	 * 
	 * @deprecated use <code>IFormColors.TB_GBG</code>
	 */
	public static final String TB_GBG = IFormColors.TB_GBG;

	/**
	 * Key for the section title bar border.
	 * 
	 * @deprecated use <code>IFormColors.TB_BORDER</code>.
	 */
	public static final String TB_BORDER = IFormColors.TB_BORDER;

	/**
	 * Key for the section toggle color. Since 3.1, this color is used for all
	 * section styles.
	 * 
	 * @deprecated use <code>IFormColors.TB_TOGGLE</code>.
	 */
	public static final String TB_TOGGLE = IFormColors.TB_TOGGLE;

	/**
	 * Key for the section toggle hover color.
	 * 
	 * @since 3.1
	 * @deprecated use <code>IFormColors.TB_TOGGLE_HOVER</code>.
	 */
	public static final String TB_TOGGLE_HOVER = IFormColors.TB_TOGGLE_HOVER;

	protected Map colorRegistry = new HashMap(10);

	protected Color background;

	protected Color foreground;

	private boolean shared;

	protected Display display;

	protected Color border;

	/**
	 * Creates form colors using the provided display.
	 * 
	 * @param display
	 *            the display to use
	 */
	public FormColors(Display display) {
		this.display = display;
		initialize();
	}

	/**
	 * Returns the display used to create colors.
	 * 
	 * @return the display
	 */
	public Display getDisplay() {
		return display;
	}

	/**
	 * Initializes the colors. Subclasses can override this method to change the
	 * way colors are created. Alternatively, only the color table can be
	 * modified by overriding <code>initializeColorTable()</code>.
	 * 
	 * @see #initializeColorTable
	 */
	protected void initialize() {
		background = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
		foreground = display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
		initializeColorTable();
		updateBorderColor();
	}

	/**
	 * Allocates colors for the following keys: BORDER, SEPARATOR and
	 * TITLE. Subclasses can override to allocate these colors differently.
	 */
	protected void initializeColorTable() {
		createTitleColor();
		createColor(IFormColors.SEPARATOR, getColor(IFormColors.TITLE).getRGB());
		RGB black = getSystemColor(SWT.COLOR_BLACK);
		RGB borderRGB = getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT);
		createColor(IFormColors.BORDER, blend(borderRGB, black, 80));
	}

	/**
	 * Allocates colors for the section tool bar (all the keys that start with
	 * TB). Since these colors are only needed when TITLE_BAR style is used with
	 * the Section widget, they are not needed all the time and are allocated on
	 * demand. Consequently, this method will do nothing if the colors have been
	 * already initialized. Call this method prior to using colors with the TB
	 * keys to ensure they are available.
	 */
	public void initializeSectionToolBarColors() {
		if (colorRegistry.containsKey(IFormColors.TB_BG))
			return;
		createTitleBarGradientColors();
		createTitleBarOutlineColors();
		createTwistieColors();
	}

	/**
	 * Allocates additional colors for the form header, namely background
	 * gradients, bottom separator keylines and DND highlights. Since these
	 * colors are only needed for clients that want to use these particular
	 * style of header rendering, they are not needed all the time and are
	 * allocated on demand. Consequently, this method will do nothing if the
	 * colors have been already initialized. Call this method prior to using
	 * color keys with the H_ prefix to ensure they are available.
	 * 
	 * @since 3.3
	 */
	protected void initializeFormHeaderColors() {
		if (colorRegistry.containsKey(IFormColors.H_BOTTOM_KEYLINE2))
			return;
		createFormHeaderColors();
	}

	/**
	 * Returns the RGB value of the system color represented by the code
	 * argument, as defined in <code>SWT</code> class.
	 * 
	 * @param code
	 *            the system color constant as defined in <code>SWT</code>
	 *            class.
	 * @return the RGB value of the system color
	 */
	public RGB getSystemColor(int code) {
		return getDisplay().getSystemColor(code).getRGB();
	}

	/**
	 * Creates the color for the specified key using the provided RGB object.
	 * The color object will be returned and also put into the registry. When
	 * the class is disposed, the color will be disposed with it.
	 * 
	 * @param key
	 *            the unique color key
	 * @param rgb
	 *            the RGB object
	 * @return the allocated color object
	 */
	public Color createColor(String key, RGB rgb) {
		return createColor(key, rgb.red, rgb.green, rgb.blue);
	}

	/**
	 * Creates a color that can be used for areas of the form that is inactive.
	 * These areas can contain images, links, controls and other content but are
	 * considered auxilliary to the main content area.
	 * 
	 * <p>
	 * The color should not be disposed because it is managed by this class.
	 * 
	 * @return the inactive form color
	 * @since 3.1
	 */
	public Color getInactiveBackground() {
		String key = "__ncbg__"; //$NON-NLS-1$
		Color color = getColor(key);
		if (color == null) {
			RGB sel = getSystemColor(SWT.COLOR_LIST_SELECTION);
			// a blend of 95% white and 5% list selection system color
			RGB ncbg = blend(sel, getSystemColor(SWT.COLOR_WHITE), 5);
			color = createColor(key, ncbg);
		}
		return color;
	}

	/**
	 * Creates the color for the specified key using the provided RGB values.
	 * The color object will be returned and also put into the registry. If
	 * there is already another color object under the same key in the registry,
	 * the existing object will be disposed. When the class is disposed, the
	 * color will be disposed with it.
	 * 
	 * @param key
	 *            the unique color key
	 * @param r
	 *            red value
	 * @param g
	 *            green value
	 * @param b
	 *            blue value
	 * @return the allocated color object
	 */
	public Color createColor(String key, int r, int g, int b) {
		Color c = new Color(display, r, g, b);
		Color prevC = (Color) colorRegistry.get(key);
		if (prevC != null)
			prevC.dispose();
		colorRegistry.put(key, c);
		return c;
	}

	/**
	 * Computes the border color relative to the background. Allocated border
	 * color is designed to work well with white. Otherwise, stanard widget
	 * background color will be used.
	 */
	protected void updateBorderColor() {
		if (isWhiteBackground())
			border = getColor(IFormColors.BORDER);
		else {
			border = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
			Color bg = getImpliedBackground();
			if (border.getRed() == bg.getRed()
					&& border.getGreen() == bg.getGreen()
					&& border.getBlue() == bg.getBlue())
				border = display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW);
		}
	}

	/**
	 * Sets the background color. All the toolkits that use this class will
	 * share the same background.
	 * 
	 * @param bg
	 *            background color
	 */
	public void setBackground(Color bg) {
		this.background = bg;
		updateBorderColor();
		updateFormHeaderColors();
	}

	/**
	 * Sets the foreground color. All the toolkits that use this class will
	 * share the same foreground.
	 * 
	 * @param fg
	 *            foreground color
	 */
	public void setForeground(Color fg) {
		this.foreground = fg;
	}

	/**
	 * Returns the current background color.
	 * 
	 * @return the background color
	 */
	public Color getBackground() {
		return background;
	}

	/**
	 * Returns the current foreground color.
	 * 
	 * @return the foreground color
	 */
	public Color getForeground() {
		return foreground;
	}

	/**
	 * Returns the computed border color. Border color depends on the background
	 * and is recomputed whenever the background changes.
	 * 
	 * @return the current border color
	 */
	public Color getBorderColor() {
		return border;
	}

	/**
	 * Tests if the background is white. White background has RGB value
	 * 255,255,255.
	 * 
	 * @return <samp>true</samp> if background is white, <samp>false</samp>
	 *         otherwise.
	 */
	public boolean isWhiteBackground() {
		Color bg = getImpliedBackground();
		return bg.getRed() == 255 && bg.getGreen() == 255
				&& bg.getBlue() == 255;
	}

	/**
	 * Returns the color object for the provided key or <samp>null </samp> if
	 * not in the registry.
	 * 
	 * @param key
	 *            the color key
	 * @return color object if found, or <samp>null </samp> if not.
	 */
	public Color getColor(String key) {
		if (key.startsWith(IFormColors.TB_PREFIX))
			initializeSectionToolBarColors();
		else if (key.startsWith(IFormColors.H_PREFIX))
			initializeFormHeaderColors();
		return (Color) colorRegistry.get(key);
	}

	/**
	 * Disposes all the colors in the registry.
	 */
	public void dispose() {
		Iterator e = colorRegistry.values().iterator();
		while (e.hasNext())
			((Color) e.next()).dispose();
		colorRegistry = null;
	}

	/**
	 * Marks the colors shared. This prevents toolkits that share this object
	 * from disposing it.
	 */
	public void markShared() {
		this.shared = true;
	}

	/**
	 * Tests if the colors are shared.
	 * 
	 * @return <code>true</code> if shared, <code>false</code> otherwise.
	 */
	public boolean isShared() {
		return shared;
	}

	/**
	 * Blends c1 and c2 based in the provided ratio.
	 * 
	 * @param c1
	 *            first color
	 * @param c2
	 *            second color
	 * @param ratio
	 *            percentage of the first color in the blend (0-100)
	 * @return the RGB value of the blended color
	 * @since 3.1
	 */
	public static RGB blend(RGB c1, RGB c2, int ratio) {
		int r = blend(c1.red, c2.red, ratio);
		int g = blend(c1.green, c2.green, ratio);
		int b = blend(c1.blue, c2.blue, ratio);
		return new RGB(r, g, b);
	}

	/**
	 * Tests the source RGB for range.
	 * 
	 * @param rgb
	 *            the tested RGB
	 * @param from
	 *            range start (excluding the value itself)
	 * @param to
	 *            range end (excluding the value itself)
	 * @return <code>true</code> if at least one of the primary colors in the
	 *         source RGB are within the provided range, <code>false</code>
	 *         otherwise.
	 * @since 3.1
	 */
	public static boolean testAnyPrimaryColor(RGB rgb, int from, int to) {
		if (testPrimaryColor(rgb.red, from, to))
			return true;
		if (testPrimaryColor(rgb.green, from, to))
			return true;
		if (testPrimaryColor(rgb.blue, from, to))
			return true;
		return false;
	}

	/**
	 * Tests the source RGB for range.
	 * 
	 * @param rgb
	 *            the tested RGB
	 * @param from
	 *            range start (excluding the value itself)
	 * @param to
	 *            tange end (excluding the value itself)
	 * @return <code>true</code> if at least two of the primary colors in the
	 *         source RGB are within the provided range, <code>false</code>
	 *         otherwise.
	 * @since 3.1
	 */
	public static boolean testTwoPrimaryColors(RGB rgb, int from, int to) {
		int total = 0;
		if (testPrimaryColor(rgb.red, from, to))
			total++;
		if (testPrimaryColor(rgb.green, from, to))
			total++;
		if (testPrimaryColor(rgb.blue, from, to))
			total++;
		return total >= 2;
	}

	/**
	 * Blends two primary color components based on the provided ratio.
	 * 
	 * @param v1
	 *            first component
	 * @param v2
	 *            second component
	 * @param ratio
	 *            percentage of the first component in the blend
	 * @return
	 */
	private static int blend(int v1, int v2, int ratio) {
		int b = (ratio * v1 + (100 - ratio) * v2) / 100;
		return Math.min(255, b);
	}

	private Color getImpliedBackground() {
		if (getBackground() != null)
			return getBackground();
		return getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
	}

	private static boolean testPrimaryColor(int value, int from, int to) {
		return value > from && value < to;
	}

	private void createTitleColor() {
		/*
		 * RGB rgb = getSystemColor(SWT.COLOR_LIST_SELECTION); // test too light
		 * if (testTwoPrimaryColors(rgb, 120, 151)) rgb = blend(rgb, BLACK, 80);
		 * else if (testTwoPrimaryColors(rgb, 150, 256)) rgb = blend(rgb, BLACK,
		 * 50); createColor(TITLE, rgb);
		 */
		RGB bg = getImpliedBackground().getRGB();
		RGB listSelection = getSystemColor(SWT.COLOR_LIST_SELECTION);
		RGB listForeground = getSystemColor(SWT.COLOR_LIST_FOREGROUND);
		RGB rgb = listSelection;

		// Group 1
		// Rule: If at least 2 of the LIST_SELECTION RGB values are equal to or
		// between 0 and 120, then use 100% LIST_SELECTION as it is (no
		// additions)
		// Examples: XP Default, Win Classic Standard, Win High Con White, Win
		// Classic Marine
		if (testTwoPrimaryColors(listSelection, -1, 121))
			rgb = listSelection;
		// Group 2
		// When LIST_BACKGROUND = white (255, 255, 255) or not black, text
		// colour = LIST_SELECTION @ 100% Opacity + 50% LIST_FOREGROUND over
		// LIST_BACKGROUND
		// Rule: If at least 2 of the LIST_SELECTION RGB values are equal to or
		// between 121 and 255, then add 50% LIST_FOREGROUND to LIST_SELECTION
		// foreground colour
		// Examples: Win Vista, XP Silver, XP Olive , Win Classic Plum, OSX
		// Aqua, OSX Graphite, Linux GTK
		else if (testTwoPrimaryColors(listSelection, 120, 256)
				|| (bg.red == 0 && bg.green == 0 && bg.blue == 0))
			rgb = blend(listSelection, listForeground, 50);
		// Group 3
		// When LIST_BACKGROUND = black (0, 0, 0), text colour = LIST_SELECTION
		// @ 100% Opacity + 50% LIST_FOREGROUND over LIST_BACKGROUND
		// Rule: If LIST_BACKGROUND = 0, 0, 0, then add 50% LIST_FOREGROUND to
		// LIST_SELECTION foreground colour
		// Examples: Win High Con Black, Win High Con #1, Win High Con #2
		// (covered in the second part of the OR clause above)
		createColor(IFormColors.TITLE, rgb);
	}

	private void createTwistieColors() {
		RGB rgb = getColor(IFormColors.TITLE).getRGB();
		RGB white = getSystemColor(SWT.COLOR_WHITE);
		createColor(TB_TOGGLE, rgb);
		rgb = blend(rgb, white, 60);
		createColor(TB_TOGGLE_HOVER, rgb);
	}

	private void createTitleBarGradientColors() {
		RGB tbBg = getSystemColor(SWT.COLOR_TITLE_BACKGROUND);
		RGB bg = getImpliedBackground().getRGB();

		// Group 1
		// Rule: If at least 2 of the RGB values are equal to or between 180 and
		// 255, then apply specified opacity for Group 1
		// Examples: Vista, XP Silver, Wn High Con #2
		// Gradient Bottom = TITLE_BACKGROUND @ 30% Opacity over LIST_BACKGROUND
		// Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND
		if (testTwoPrimaryColors(tbBg, 179, 256))
			tbBg = blend(tbBg, bg, 30);

		// Group 2
		// Rule: If at least 2 of the RGB values are equal to or between 121 and
		// 179, then apply specified opacity for Group 2
		// Examples: XP Olive, OSX Graphite, Linux GTK, Wn High Con Black
		// Gradient Bottom = TITLE_BACKGROUND @ 20% Opacity over LIST_BACKGROUND
		// Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND
		else if (testTwoPrimaryColors(tbBg, 120, 180))
			tbBg = blend(tbBg, bg, 20);

		// Group 3
		// Rule: Everything else
		// Examples: XP Default, Wn Classic Standard, Wn Marine, Wn Plum, OSX
		// Aqua, Wn High Con White, Wn High Con #1
		// Gradient Bottom = TITLE_BACKGROUND @ 10% Opacity over LIST_BACKGROUND
		// Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND
		else {
			tbBg = blend(tbBg, bg, 10);
		}

		createColor(IFormColors.TB_BG, tbBg);
		
		// for backward compatibility
		createColor(TB_GBG, tbBg);
	}

	private void createTitleBarOutlineColors() {
		// title bar outline - border color
		RGB tbBorder = getSystemColor(SWT.COLOR_TITLE_BACKGROUND);
		RGB bg = getImpliedBackground().getRGB();
		// Group 1
		// Rule: If at least 2 of the RGB values are equal to or between 180 and
		// 255, then apply specified opacity for Group 1
		// Examples: Vista, XP Silver, Wn High Con #2
		// Keyline = TITLE_BACKGROUND @ 70% Opacity over LIST_BACKGROUND
		if (testTwoPrimaryColors(tbBorder, 179, 256))
			tbBorder = blend(tbBorder, bg, 70);

		// Group 2
		// Rule: If at least 2 of the RGB values are equal to or between 121 and
		// 179, then apply specified opacity for Group 2
		// Examples: XP Olive, OSX Graphite, Linux GTK, Wn High Con Black

		// Keyline = TITLE_BACKGROUND @ 50% Opacity over LIST_BACKGROUND
		else if (testTwoPrimaryColors(tbBorder, 120, 180))
			tbBorder = blend(tbBorder, bg, 50);

		// Group 3
		// Rule: Everything else
		// Examples: XP Default, Wn Classic Standard, Wn Marine, Wn Plum, OSX
		// Aqua, Wn High Con White, Wn High Con #1

		// Keyline = TITLE_BACKGROUND @ 30% Opacity over LIST_BACKGROUND
		else {
			tbBorder = blend(tbBorder, bg, 30);
		}
		createColor(FormColors.TB_BORDER, tbBorder);
	}

	private void updateFormHeaderColors() {
		if (colorRegistry.containsKey(IFormColors.H_GRADIENT_END)) {
			disposeIfFound(IFormColors.H_GRADIENT_END);
			disposeIfFound(IFormColors.H_GRADIENT_START);
			disposeIfFound(IFormColors.H_BOTTOM_KEYLINE1);
			disposeIfFound(IFormColors.H_BOTTOM_KEYLINE2);
			disposeIfFound(IFormColors.H_HOVER_LIGHT);
			disposeIfFound(IFormColors.H_HOVER_FULL);
			initializeFormHeaderColors();
		}
	}

	private void disposeIfFound(String key) {
		Color color = getColor(key);
		if (color != null) {
			colorRegistry.remove(key);
			color.dispose();
		}
	}

	private void createFormHeaderColors() {
		createFormHeaderGradientColors();
		createFormHeaderKeylineColors();
		createFormHeaderDNDColors();
	}

	private void createFormHeaderGradientColors() {
		RGB titleBg = getSystemColor(SWT.COLOR_TITLE_BACKGROUND);
		Color bgColor = getImpliedBackground();
		RGB bg = bgColor.getRGB();
		RGB bottom, top;
		// Group 1
		// Rule: If at least 2 of the RGB values are equal to or between 180 and
		// 255, then apply specified opacity for Group 1
		// Examples: Vista, XP Silver, Wn High Con #2
		// Gradient Bottom = TITLE_BACKGROUND @ 30% Opacity over LIST_BACKGROUND
		// Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND
		if (testTwoPrimaryColors(titleBg, 179, 256)) {
			bottom = blend(titleBg, bg, 30);
			top = bg;
		}

		// Group 2
		// Rule: If at least 2 of the RGB values are equal to or between 121 and
		// 179, then apply specified opacity for Group 2
		// Examples: XP Olive, OSX Graphite, Linux GTK, Wn High Con Black
		// Gradient Bottom = TITLE_BACKGROUND @ 20% Opacity over LIST_BACKGROUND
		// Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND
		else if (testTwoPrimaryColors(titleBg, 120, 180)) {
			bottom = blend(titleBg, bg, 20);
			top = bg;
		}

		// Group 3
		// Rule: If at least 2 of the RGB values are equal to or between 0 and
		// 120, then apply specified opacity for Group 3
		// Examples: XP Default, Wn Classic Standard, Wn Marine, Wn Plum, OSX
		// Aqua, Wn High Con White, Wn High Con #1
		// Gradient Bottom = TITLE_BACKGROUND @ 10% Opacity over LIST_BACKGROUND
		// Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND
		else {
			bottom = blend(titleBg, bg, 10);
			top = bg;
		}
		createColor(IFormColors.H_GRADIENT_END, top);
		createColor(IFormColors.H_GRADIENT_START, bottom);
	}

	private void createFormHeaderKeylineColors() {
		RGB titleBg = getSystemColor(SWT.COLOR_TITLE_BACKGROUND);
		Color bgColor = getImpliedBackground();
		RGB bg = bgColor.getRGB();
		RGB keyline2;
		// H_BOTTOM_KEYLINE1
		createColor(IFormColors.H_BOTTOM_KEYLINE1, new RGB(255, 255, 255));

		// H_BOTTOM_KEYLINE2
		// Group 1
		// Rule: If at least 2 of the RGB values are equal to or between 180 and
		// 255, then apply specified opacity for Group 1
		// Examples: Vista, XP Silver, Wn High Con #2
		// Keyline = TITLE_BACKGROUND @ 70% Opacity over LIST_BACKGROUND
		if (testTwoPrimaryColors(titleBg, 179, 256))
			keyline2 = blend(titleBg, bg, 70);

		// Group 2
		// Rule: If at least 2 of the RGB values are equal to or between 121 and
		// 179, then apply specified opacity for Group 2
		// Examples: XP Olive, OSX Graphite, Linux GTK, Wn High Con Black
		// Keyline = TITLE_BACKGROUND @ 50% Opacity over LIST_BACKGROUND
		else if (testTwoPrimaryColors(titleBg, 120, 180))
			keyline2 = blend(titleBg, bg, 50);

		// Group 3
		// Rule: If at least 2 of the RGB values are equal to or between 0 and
		// 120, then apply specified opacity for Group 3
		// Examples: XP Default, Wn Classic Standard, Wn Marine, Wn Plum, OSX
		// Aqua, Wn High Con White, Wn High Con #1

		// Keyline = TITLE_BACKGROUND @ 30% Opacity over LIST_BACKGROUND
		else
			keyline2 = blend(titleBg, bg, 30);
		// H_BOTTOM_KEYLINE2
		createColor(IFormColors.H_BOTTOM_KEYLINE2, keyline2);
	}

	private void createFormHeaderDNDColors() {
		RGB titleBg = getSystemColor(SWT.COLOR_TITLE_BACKGROUND_GRADIENT);
		Color bgColor = getImpliedBackground();
		RGB bg = bgColor.getRGB();
		RGB light, full;
		// ALL Themes
		//
		// Light Highlight
		// When *near* the 'hot' area
		// Rule: If near the title in the 'hot' area, show background highlight
		// TITLE_BACKGROUND_GRADIENT @ 40%
		light = blend(titleBg, bg, 40);
		// Full Highlight
		// When *on* the title area (regions 1 and 2)
		// Rule: If near the title in the 'hot' area, show background highlight
		// TITLE_BACKGROUND_GRADIENT @ 60%
		full = blend(titleBg, bg, 60);
		// H_DND_LIGHT
		// H_DND_FULL
		createColor(IFormColors.H_HOVER_LIGHT, light);
		createColor(IFormColors.H_HOVER_FULL, full);
	}
}
