/*******************************************************************************
 * Copyright (c) 2000, 2005 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
 *     Michael Williamson (eclipse-bugs@magnaworks.com) - patch (see Bugzilla #92545) 
 *******************************************************************************/
package org.eclipse.ui.forms.widgets;

import java.io.File;

import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.forms.*;
import org.eclipse.ui.internal.forms.widgets.FormUtil;

/**
 * The toolkit is responsible for creating SWT controls adapted to work in
 * Eclipse forms. In addition to changing their presentation properties (fonts,
 * colors etc.), various listeners are attached to make them behave correctly in
 * the form context.
 * <p>
 * In addition to being the control factory, the toolkit is also responsible for
 * painting flat borders for select controls, managing hyperlink groups and
 * control colors.
 * <p>
 * The toolkit creates some of the most common controls used to populate Eclipse
 * forms. Controls that must be created using their constructors,
 * <code>adapt()</code> method is available to change its properties in the
 * same way as with the supported toolkit controls.
 * <p>
 * Typically, one toolkit object is created per workbench part (for example, an
 * editor or a form wizard). The toolkit is disposed when the part is disposed.
 * To conserve resources, it is possible to create one color object for the
 * entire plug-in and share it between several toolkits. The plug-in is
 * responsible for disposing the colors (disposing the toolkit that uses shared
 * color object will not dispose the colors).
 * <p>
 * FormToolkit is normally instantiated, but can also be subclassed if some of
 * the methods needs to be modified. In those cases, <code>super</code> must
 * be called to preserve normal behaviour.
 * 
 * @since 3.0
 */
public class FormToolkit {
	public static final String KEY_DRAW_BORDER = "FormWidgetFactory.drawBorder"; //$NON-NLS-1$

	public static final String TREE_BORDER = "treeBorder"; //$NON-NLS-1$

	public static final String TEXT_BORDER = "textBorder"; //$NON-NLS-1$

	private int borderStyle = SWT.NULL;

	private FormColors colors;

	private int orientation = Window.getDefaultOrientation();

	// private KeyListener deleteListener;
	private BorderPainter borderPainter;

	private BoldFontHolder boldFontHolder;

	private HyperlinkGroup hyperlinkGroup;

	/* default */
	VisibilityHandler visibilityHandler;

	/* default */
	KeyboardHandler keyboardHandler;

	private class BorderPainter implements PaintListener {
		public void paintControl(PaintEvent event) {
			Composite composite = (Composite) event.widget;
			Control[] children = composite.getChildren();
			for (int i = 0; i < children.length; i++) {
				Control c = children[i];
				boolean inactiveBorder = false;
				boolean textBorder = false;
				if (!c.isVisible())
					continue;
				if (c.getEnabled() == false && !(c instanceof CCombo))
					continue;
				if (c instanceof Hyperlink)
					continue;
				Object flag = c.getData(KEY_DRAW_BORDER);
				if (flag != null) {
					if (flag.equals(Boolean.FALSE))
						continue;
					if (flag.equals(TREE_BORDER))
						inactiveBorder = true;
					else if (flag.equals(TEXT_BORDER))
						textBorder = true;
				}
				if (getBorderStyle() == SWT.BORDER) {
					if (!inactiveBorder && !textBorder) {
						continue;
					}
					if (c instanceof Text || c instanceof Table
							|| c instanceof Tree || c instanceof TableTree)
						continue;
				}
				if (!inactiveBorder
						&& (c instanceof Text || c instanceof CCombo || textBorder)) {
					Rectangle b = c.getBounds();
					GC gc = event.gc;
					gc.setForeground(c.getBackground());
					gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1,
							b.height + 1);
					// gc.setForeground(getBorderStyle() == SWT.BORDER ? colors
					// .getBorderColor() : colors.getForeground());
					gc.setForeground(colors.getBorderColor());
					if (c instanceof CCombo)
						gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1,
								b.height + 1);
					else
						gc.drawRectangle(b.x - 1, b.y - 2, b.width + 1,
								b.height + 3);
				} else if (inactiveBorder || c instanceof Table
						|| c instanceof Tree || c instanceof TableTree) {
					Rectangle b = c.getBounds();
					GC gc = event.gc;
					gc.setForeground(colors.getBorderColor());
					gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1,
							b.height + 1);
				}
			}
		}
	}

	private static class VisibilityHandler extends FocusAdapter {
		public void focusGained(FocusEvent e) {
			Widget w = e.widget;
			if (w instanceof Control) {
				FormUtil.ensureVisible((Control) w);
			}
		}
	}

	private static class KeyboardHandler extends KeyAdapter {
		public void keyPressed(KeyEvent e) {
			Widget w = e.widget;
			if (w instanceof Control) {
				if (e.doit)
					FormUtil.processKey(e.keyCode, (Control) w);
			}
		}
	}

	private class BoldFontHolder {
		private Font normalFont;

		private Font boldFont;

		public BoldFontHolder() {
		}

		public Font getBoldFont(Font font) {
			createBoldFont(font);
			return boldFont;
		}

		private void createBoldFont(Font font) {
			if (normalFont == null || !normalFont.equals(font)) {
				normalFont = font;
				dispose();
			}
			if (boldFont == null) {
				boldFont = FormUtil.createBoldFont(colors.getDisplay(),
						normalFont);
			}
		}

		public void dispose() {
			if (boldFont != null) {
				boldFont.dispose();
				boldFont = null;
			}
		}
	}

	/**
	 * Creates a toolkit that is self-sufficient (will manage its own colors).
	 * 
	 */
	public FormToolkit(Display display) {
		this(new FormColors(display));
	}

	/**
	 * Creates a toolkit that will use the provided (shared) colors. The toolkit
	 * will <b>not </b> dispose the provided colors.
	 * 
	 * @param colors
	 *            the shared colors
	 */
	public FormToolkit(FormColors colors) {
		this.colors = colors;
		initialize();
	}

	/**
	 * Creates a button as a part of the form.
	 * 
	 * @param parent
	 *            the button parent
	 * @param text
	 *            an optional text for the button (can be <code>null</code>)
	 * @param style
	 *            the button style (for example, <code>SWT.PUSH</code>)
	 * @return the button widget
	 */
	public Button createButton(Composite parent, String text, int style) {
		Button button = new Button(parent, style | SWT.FLAT | orientation);
		if (text != null)
			button.setText(text);
		adapt(button, true, true);
		return button;
	}

	/**
	 * Creates the composite as a part of the form.
	 * 
	 * @param parent
	 *            the composite parent
	 * @return the composite widget
	 */
	public Composite createComposite(Composite parent) {
		return createComposite(parent, SWT.NULL);
	}

	/**
	 * Creates the composite as part of the form using the provided style.
	 * 
	 * @param parent
	 *            the composite parent
	 * @param style
	 *            the composite style
	 * @return the composite widget
	 */
	public Composite createComposite(Composite parent, int style) {
		Composite composite = new LayoutComposite(parent, style | orientation);
		adapt(composite);
		return composite;
	}

	/**
	 * Creats the composite that can server as a separator between various parts
	 * of a form. Separator height should be controlled by setting the height
	 * hint on the layout data for the composite.
	 * 
	 * @param parent
	 *            the separator parent
	 * @return the separator widget
	 */
	public Composite createCompositeSeparator(Composite parent) {
		final Composite composite = new Composite(parent, orientation);
		composite.addListener(SWT.Paint, new Listener() {
			public void handleEvent(Event e) {
				if (composite.isDisposed())
					return;
				Rectangle bounds = composite.getBounds();
				GC gc = e.gc;
				gc.setForeground(colors.getColor(FormColors.SEPARATOR));
				if (colors.getBackground() != null)
					gc.setBackground(colors.getBackground());
				gc.fillGradientRectangle(0, 0, bounds.width, bounds.height,
						false);
			}
		});
		if (parent instanceof Section)
			((Section) parent).setSeparatorControl(composite);
		return composite;
	}

	/**
	 * Creates a label as a part of the form.
	 * 
	 * @param parent
	 *            the label parent
	 * @param text
	 *            the label text
	 * @return the label widget
	 */
	public Label createLabel(Composite parent, String text) {
		return createLabel(parent, text, SWT.NONE);
	}

	/**
	 * Creates a label as a part of the form.
	 * 
	 * @param parent
	 *            the label parent
	 * @param text
	 *            the label text
	 * @param style
	 *            the label style
	 * @return the label widget
	 */
	public Label createLabel(Composite parent, String text, int style) {
		Label label = new Label(parent, style | orientation);
		if (text != null)
			label.setText(text);
		adapt(label, false, false);
		return label;
	}

	/**
	 * Creates a hyperlink as a part of the form. The hyperlink will be added to
	 * the hyperlink group that belongs to this toolkit.
	 * 
	 * @param parent
	 *            the hyperlink parent
	 * @param text
	 *            the text of the hyperlink
	 * @param style
	 *            the hyperlink style
	 * @return the hyperlink widget
	 */
	public Hyperlink createHyperlink(Composite parent, String text, int style) {
		Hyperlink hyperlink = new Hyperlink(parent, style | orientation);
		if (text != null)
			hyperlink.setText(text);
		hyperlink.addFocusListener(visibilityHandler);
		hyperlink.addKeyListener(keyboardHandler);
		hyperlinkGroup.add(hyperlink);
		return hyperlink;
	}

	/**
	 * Creates an image hyperlink as a part of the form. The hyperlink will be
	 * added to the hyperlink group that belongs to this toolkit.
	 * 
	 * @param parent
	 *            the hyperlink parent
	 * @param style
	 *            the hyperlink style
	 * @return the image hyperlink widget
	 */
	public ImageHyperlink createImageHyperlink(Composite parent, int style) {
		ImageHyperlink hyperlink = new ImageHyperlink(parent, style
				| orientation);
		hyperlink.addFocusListener(visibilityHandler);
		hyperlink.addKeyListener(keyboardHandler);
		hyperlinkGroup.add(hyperlink);
		return hyperlink;
	}

	/**
	 * Creates a rich text as a part of the form.
	 * 
	 * @param parent
	 *            the rich text parent
	 * @param trackFocus
	 *            if <code>true</code>, the toolkit will monitor focus
	 *            transfers to ensure that the hyperlink in focus is visible in
	 *            the form.
	 * @return the rich text widget
	 */
	public FormText createFormText(Composite parent, boolean trackFocus) {
		FormText engine = new FormText(parent, SWT.WRAP | orientation);
		engine.marginWidth = 1;
		engine.marginHeight = 0;
		engine.setHyperlinkSettings(getHyperlinkGroup());
		adapt(engine, trackFocus, true);
		engine.setMenu(parent.getMenu());
		return engine;
	}

	/**
	 * Adapts a control to be used in a form that is associated with this
	 * toolkit. This involves adjusting colors and optionally adding handlers to
	 * ensure focus tracking and keyboard management.
	 * 
	 * @param control
	 *            a control to adapt
	 * @param trackFocus
	 *            if <code>true</code>, form will be scrolled horizontally
	 *            and/or vertically if needed to ensure that the control is
	 *            visible when it gains focus. Set it to <code>false</code> if
	 *            the control is not capable of gaining focus.
	 * @param trackKeyboard
	 *            if <code>true</code>, the control that is capable of
	 *            gaining focus will be tracked for certain keys that are
	 *            important to the underlying form (for example, PageUp,
	 *            PageDown, ScrollUp, ScrollDown etc.). Set it to
	 *            <code>false</code> if the control is not capable of gaining
	 *            focus or these particular key event are already used by the
	 *            control.
	 */
	public void adapt(Control control, boolean trackFocus, boolean trackKeyboard) {
		control.setBackground(colors.getBackground());
		control.setForeground(colors.getForeground());
		if (control instanceof ExpandableComposite) {
			ExpandableComposite ec = (ExpandableComposite)control;
			if (ec.toggle != null) {
				if (trackFocus)
					ec.toggle.addFocusListener(visibilityHandler);
				if (trackKeyboard)
					ec.toggle.addKeyListener(keyboardHandler);
			}
			if (ec.textLabel != null) {
				if (trackFocus)
					ec.textLabel.addFocusListener(visibilityHandler);
				if (trackKeyboard)
					ec.textLabel.addKeyListener(keyboardHandler);
			}
			return;
		}
		if (trackFocus)
			control.addFocusListener(visibilityHandler);
		if (trackKeyboard)
			control.addKeyListener(keyboardHandler);
	}
	
	/**
	 * Adapts a composite to be used in a form associated with this toolkit.
	 * 
	 * @param composite
	 *            the composite to adapt
	 */
	public void adapt(Composite composite) {
		composite.setBackground(colors.getBackground());
		composite.addMouseListener(new MouseAdapter() {
			public void mouseDown(MouseEvent e) {
				((Control) e.widget).setFocus();
			}
		});
		composite.setMenu(composite.getParent().getMenu());
	}

	/**
	 * A helper method that ensures the provided control is visible when
	 * ScrolledComposite is somewhere in the parent chain. If scroll bars are
	 * visible and the control is clipped, the client of the scrolled composite
	 * will be scrolled to reveal the control.
	 * 
	 * @param c
	 *            the control to reveal
	 */
	public static void ensureVisible(Control c) {
		FormUtil.ensureVisible(c);
	}

	/**
	 * Creates a section as a part of the form.
	 * 
	 * @param parent
	 *            the section parent
	 * @param sectionStyle
	 *            the section style
	 * @return the section widget
	 */
	public Section createSection(Composite parent, int sectionStyle) {
		Section section = new Section(parent, orientation, sectionStyle);
		section.setMenu(parent.getMenu());
		adapt(section, true, true);
		if (section.toggle != null) {
			section.toggle.setHoverDecorationColor(colors
					.getColor(FormColors.TB_TOGGLE_HOVER));
			section.toggle.setDecorationColor(colors
					.getColor(FormColors.TB_TOGGLE));
		}
		section.setFont(boldFontHolder.getBoldFont(parent.getFont()));
		if ((sectionStyle & Section.TITLE_BAR) != 0
				|| (sectionStyle & Section.SHORT_TITLE_BAR) != 0) {
			colors.initializeSectionToolBarColors();
			section.setTitleBarBackground(colors.getColor(FormColors.TB_GBG));
			section.setTitleBarBorderColor(colors
					.getColor(FormColors.TB_BORDER));
			section.setTitleBarGradientBackground(colors
					.getColor(FormColors.TB_GBG));
			section.setTitleBarForeground(colors.getColor(FormColors.TB_FG));
		}
		return section;
	}

	/**
	 * Creates an expandable composite as a part of the form.
	 * 
	 * @param parent
	 *            the expandable composite parent
	 * @param expansionStyle
	 *            the expandable composite style
	 * @return the expandable composite widget
	 */
	public ExpandableComposite createExpandableComposite(Composite parent,
			int expansionStyle) {
		ExpandableComposite ec = new ExpandableComposite(parent, orientation,
				expansionStyle);
		ec.setMenu(parent.getMenu());
		adapt(ec, true, true);
		ec.setFont(boldFontHolder.getBoldFont(ec.getFont()));
		return ec;
	}

	/**
	 * Creates a separator label as a part of the form.
	 * 
	 * @param parent
	 *            the separator parent
	 * @param style
	 *            the separator style
	 * @return the separator label
	 */
	public Label createSeparator(Composite parent, int style) {
		Label label = new Label(parent, SWT.SEPARATOR | style | orientation);
		label.setBackground(colors.getBackground());
		label.setForeground(colors.getBorderColor());
		return label;
	}

	/**
	 * Creates a table as a part of the form.
	 * 
	 * @param parent
	 *            the table parent
	 * @param style
	 *            the table style
	 * @return the table widget
	 */
	public Table createTable(Composite parent, int style) {
		Table table = new Table(parent, style | borderStyle | orientation);
		adapt(table, false, false);
		// hookDeleteListener(table);
		return table;
	}

	/**
	 * Creates a text as a part of the form.
	 * 
	 * @param parent
	 *            the text parent
	 * @param value
	 *            the text initial value
	 * @return the text widget
	 */
	public Text createText(Composite parent, String value) {
		return createText(parent, value, SWT.SINGLE);
	}

	/**
	 * Creates a text as a part of the form.
	 * 
	 * @param parent
	 *            the text parent
	 * @param value
	 *            the text initial value
	 * @param style
	 *            the text style
	 * @return the text widget
	 */
	public Text createText(Composite parent, String value, int style) {
		Text text = new Text(parent, borderStyle | style | orientation);
		if (value != null)
			text.setText(value);
		text.setForeground(colors.getForeground());
		text.addFocusListener(visibilityHandler);
		return text;
	}

	/**
	 * Creates a tree widget as a part of the form.
	 * 
	 * @param parent
	 *            the tree parent
	 * @param style
	 *            the tree style
	 * @return the tree widget
	 */
	public Tree createTree(Composite parent, int style) {
		Tree tree = new Tree(parent, borderStyle | style | orientation);
		adapt(tree, false, false);
		// hookDeleteListener(tree);
		return tree;
	}

	/**
	 * Creates a scrolled form widget in the provided parent. If you do not
	 * require scrolling because there is already a scrolled composite up the
	 * parent chain, use 'createForm' instead.
	 * 
	 * @param parent
	 *            the scrolled form parent
	 * @return the form that can scroll itself
	 * @see #createForm
	 */
	public ScrolledForm createScrolledForm(Composite parent) {
		ScrolledForm form = new ScrolledForm(parent, SWT.V_SCROLL
				| SWT.H_SCROLL | orientation);
		form.setExpandHorizontal(true);
		form.setExpandVertical(true);
		form.setBackground(colors.getBackground());
		form.setForeground(colors.getColor(FormColors.TITLE));
		colors.initializeSectionToolBarColors();
		form.getForm().setSeparatorColor(colors.getColor(FormColors.TB_BORDER));
		form.setFont(JFaceResources.getHeaderFont());
		return form;
	}

	/**
	 * Creates a form widget in the provided parent. Note that this widget does
	 * not scroll its content, so make sure there is a scrolled composite up the
	 * parent chain. If you require scrolling, use 'createScrolledForm' instead.
	 * 
	 * @param parent
	 *            the form parent
	 * @return the form that does not scroll
	 * @see #createScrolledForm
	 */
	public Form createForm(Composite parent) {
		Form formContent = new Form(parent, orientation);
		formContent.setBackground(colors.getBackground());
		formContent.setForeground(colors.getColor(FormColors.TITLE));
		colors.initializeSectionToolBarColors();
		formContent.setSeparatorColor(colors.getColor(FormColors.TB_BORDER));
		formContent.setFont(JFaceResources.getHeaderFont());
		return formContent;
	}

	/**
	 * Creates a scrolled page book widget as a part of the form.
	 * 
	 * @param parent
	 *            the page book parent
	 * @param style
	 *            the text style
	 * @return the scrolled page book widget
	 */
	public ScrolledPageBook createPageBook(Composite parent, int style) {
		ScrolledPageBook book = new ScrolledPageBook(parent, style
				| orientation);
		adapt(book, true, true);
		book.setMenu(parent.getMenu());
		return book;
	}

	/**
	 * Disposes the toolkit.
	 */
	public void dispose() {
		if (colors.isShared() == false) {
			colors.dispose();
			colors = null;
		}
		boldFontHolder.dispose();
	}

	/**
	 * Returns the hyperlink group that manages hyperlinks for this toolkit.
	 * 
	 * @return the hyperlink group
	 */
	public HyperlinkGroup getHyperlinkGroup() {
		return hyperlinkGroup;
	}

	/**
	 * Sets the background color for the entire toolkit. The method delegates
	 * the call to the FormColors object and also updates the hyperlink group so
	 * that hyperlinks and other objects are in sync.
	 * 
	 * @param bg
	 *            the new background color
	 */
	public void setBackground(Color bg) {
		hyperlinkGroup.setBackground(bg);
		colors.setBackground(bg);
	}

	/**
	 * Refreshes the hyperlink colors by loading from JFace settings.
	 */
	public void refreshHyperlinkColors() {
		hyperlinkGroup.initializeDefaultForegrounds(colors.getDisplay());
	}

	/**
	 * Paints flat borders for widgets created by this toolkit within the
	 * provided parent. Borders will not be painted if the global border style
	 * is SWT.BORDER (i.e. if native borders are used). Call this method during
	 * creation of a form composite to get the borders of its children painted.
	 * Care should be taken when selection layout margins. At least one pixel
	 * pargin width and height must be chosen to allow the toolkit to paint the
	 * border on the parent around the widgets.
	 * <p>
	 * Borders are painted for some controls that are selected by the toolkit by
	 * default. If a control needs a border but is not on its list, it is
	 * possible to force border in the following way:
	 * 
	 * <pre>
	 * 
	 *  
	 *   
	 *           widget.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TREE_BORDER);
	 *           
	 *           or
	 *           
	 *           widget.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
	 *          
	 *   
	 *  
	 * </pre>
	 * 
	 * @param parent
	 *            the parent that owns the children for which the border needs
	 *            to be painted.
	 */
	public void paintBordersFor(Composite parent) {
		// if (borderStyle == SWT.BORDER)
		// return;
		if (borderPainter == null)
			borderPainter = new BorderPainter();
		parent.addPaintListener(borderPainter);
	}

	/**
	 * Returns the colors used by this toolkit.
	 * 
	 * @return the color object
	 */
	public FormColors getColors() {
		return colors;
	}

	/**
	 * Returns the border style used for various widgets created by this
	 * toolkit. The intent of the toolkit is to create controls with styles that
	 * yield a 'flat' appearance. On systems where the native borders are
	 * already flat, we set the style to SWT.BORDER and don't paint the borders
	 * ourselves. Otherwise, the style is set to SWT.NULL, and borders are
	 * painted by the toolkit.
	 * 
	 * @return the global border style
	 */
	public int getBorderStyle() {
		return borderStyle;
	}

	/**
	 * Sets the border style to be used when creating widgets. The toolkit
	 * chooses the correct style based on the platform but this value can be
	 * changed using this method.
	 * 
	 * @param style
	 *            <code>SWT.BORDER</code> or <code>SWT.NULL</code>
	 * @see #getBorderStyle
	 */
	public void setBorderStyle(int style) {
		this.borderStyle = style;
	}

	/**
	 * A utility method that ensures that the control is visible in the scrolled
	 * composite. The prerequisite for this method is that the control has a
	 * class that extends ScrolledComposite somewhere in the parent chain. If
	 * the control is partially or fully clipped, the composite is scrolled to
	 * set by setting the origin to the control origin.
	 * 
	 * @param c
	 *            the control to make visible
	 * @param verticalOnly
	 *            if <code>true</code>, the scrolled composite will be
	 *            scrolled only vertically if needed. Otherwise, the scrolled
	 *            composite origin will be set to the control origin.
	 * @since 3.1
	 */
	public static void setControlVisible(Control c, boolean verticalOnly) {
		ScrolledComposite scomp = FormUtil.getScrolledComposite(c);
		if (scomp == null)
			return;
		Point location = FormUtil.getControlLocation(scomp, c);
		scomp.setOrigin(location);
	}

	private void initialize() {
		initializeBorderStyle();
		hyperlinkGroup = new HyperlinkGroup(colors.getDisplay());
		hyperlinkGroup.setBackground(colors.getBackground());
		visibilityHandler = new VisibilityHandler();
		keyboardHandler = new KeyboardHandler();
		boldFontHolder = new BoldFontHolder();
	}

	private void initializeBorderStyle() {
		String osname = System.getProperty("os.name"); //$NON-NLS-1$
		if (osname.equals("Windows XP")) { //$NON-NLS-1$
			String javaHome = System.getProperty("java.home"); //$NON-NLS-1$
			File homeDir = new File(javaHome);
			File binDir = new File(homeDir, "bin"); //$NON-NLS-1$
			File manifest = new File(binDir, "javaw.exe.manifest"); //$NON-NLS-1$
			if (manifest.exists()) {
				// Skinned widgets used - check for Windows Classic
				// If not used, set the style to BORDER
				RGB rgb = colors.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
				if (rgb.red != 212 && rgb.green != 208 && rgb.blue != 200)
					borderStyle = SWT.BORDER;
			}
		} else if (osname.startsWith("Mac")) //$NON-NLS-1$
			borderStyle = SWT.BORDER;
	}

	/**
	 * Returns the orientation that all the widgets created by this toolkit will
	 * inherit, if set. Can be <code>SWT.NULL</code>,
	 * <code>SWT.LEFT_TO_RIGHT</code> and <code>SWT.RIGHT_TO_LEFT</code>.
	 * 
	 * @return orientation style for this toolkit, or <code>SWT.NULL</code> if
	 *         not set. The default orientation is inherited from the Window
	 *         default orientation.
	 * @see org.eclipse.jface.window.Window#getDefaultOrientation()
	 * @since 3.1
	 */

	public int getOrientation() {
		return orientation;
	}

	/**
	 * Sets the orientation that all the widgets created by this toolkit will
	 * inherit. Can be <code>SWT.NULL</code>, <code>SWT.LEFT_TO_RIGHT</code>
	 * and <code>SWT.RIGHT_TO_LEFT</code>.
	 * 
	 * @param orientation
	 *            style for this toolkit.
	 * @since 3.1
	 */

	public void setOrientation(int orientation) {
		this.orientation = orientation;
	}
}
