1765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye/*******************************************************************************
2765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Copyright (c) 2011 Google, Inc.
3765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * All rights reserved. This program and the accompanying materials
4765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * are made available under the terms of the Eclipse Public License v1.0
5765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * which accompanies this distribution, and is available at
6765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * http://www.eclipse.org/legal/epl-v10.html
7765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye *
8765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Contributors:
9765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye *    Google, Inc. - initial API and implementation
10765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye *******************************************************************************/
11765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyepackage org.eclipse.wb.core.controls;
12765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
13765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.SWT;
14765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.events.FocusAdapter;
15765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.events.FocusEvent;
16765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.events.KeyAdapter;
17765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.events.KeyEvent;
18765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.events.SelectionAdapter;
19765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.events.SelectionEvent;
20765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.graphics.Color;
21765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.graphics.Point;
22765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.graphics.Rectangle;
23765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Button;
24765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Composite;
25765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Display;
26765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Event;
27765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Layout;
28765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Spinner;
29765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Text;
30765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
31765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.text.DecimalFormat;
32765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.text.MessageFormat;
33765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.text.ParseException;
34765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
35765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye/**
36765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Custom implementation of {@link Spinner}.
37765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye *
38765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @author scheglov_ke
39765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @coverage core.control
40765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */
41765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyepublic class CSpinner extends Composite {
42765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final Color COLOR_VALID = Display.getCurrent().getSystemColor(
43765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      SWT.COLOR_LIST_BACKGROUND);
44765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final Color COLOR_INVALID = new Color(null, 255, 230, 230);
45765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private int m_minimum = 0;
46765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private int m_maximum = 100;
47765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private int m_increment = 1;
48765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private int m_value = 0;
49765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private int m_multiplier = 1;
50765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private String m_formatPattern = "0";
51765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private DecimalFormat m_format = new DecimalFormat(m_formatPattern);
52765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
53765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
54765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // GUI fields
55765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
56765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
57765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private final Button m_button;
58765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private final Text m_text;
59765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private final Spinner m_spinner;
60765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private Composite win32Hack;
61765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
62765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
63765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
64765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Constructor
65765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
66765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
67765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public CSpinner(Composite parent, int style) {
68765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    super(parent, style);
69765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_button = new Button(this, SWT.ARROW | SWT.DOWN);
70765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    {
71765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int textStyle = SWT.SINGLE | SWT.RIGHT;
72765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (IS_OS_MAC_OSX_COCOA) {
73765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        textStyle |= SWT.BORDER;
74765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
75765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text = new Text(this, textStyle);
76765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text.setText("" + m_value);
77765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text.addKeyListener(new KeyAdapter() {
78765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        @Override
79765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        public void keyPressed(KeyEvent e) {
80765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          if (e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.ARROW_DOWN) {
81765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            e.doit = false;
82765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            updateValue(e.keyCode);
83765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          }
84765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        }
85765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
86765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        @Override
87765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        public void keyReleased(KeyEvent e) {
88765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          try {
89765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            m_value = (int) (m_format.parse(m_text.getText()).doubleValue() * m_multiplier);
90765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            if (m_value < m_minimum || m_value > m_maximum) {
91765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye              m_text.setBackground(COLOR_INVALID);
92765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye              setState(MessageFormat.format(
93765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye                  Messages.CSpinner_outOfRange,
94765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye                  m_value,
95765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye                  m_minimum,
96765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye                  m_maximum));
97765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye              notifySelectionListeners(false);
98765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            } else {
99765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye              setState(null);
100765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye              notifySelectionListeners(true);
101765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            }
102765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          } catch (ParseException ex) {
103765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            setState(MessageFormat.format(
104765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye                Messages.CSpinner_canNotParse,
105765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye                m_text.getText(),
106765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye                m_formatPattern));
107765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            notifySelectionListeners(false);
108765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          }
109765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        }
110765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      });
111765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
112765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    if (!IS_OS_MAC_OSX) {
113765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      win32Hack = new Composite(this, SWT.NONE);
114765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      win32Hack.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
115765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      win32Hack.moveAbove(null);
116765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      win32Hack.moveBelow(m_text);
117765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
118765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    {
119765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner = new Spinner(this, SWT.VERTICAL);
120765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setMinimum(0);
121765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setMaximum(50);
122765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setIncrement(1);
123765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setPageIncrement(1);
124765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setSelection(25);
125765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.addFocusListener(new FocusAdapter() {
126765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        @Override
127765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        public void focusGained(FocusEvent e) {
128765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          setFocus();
129765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        }
130765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      });
131765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.addSelectionListener(new SelectionAdapter() {
132765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        @Override
133765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        public void widgetSelected(SelectionEvent e) {
134765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          m_text.forceFocus();
135765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          if (m_spinner.getSelection() > 25) {
136765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            updateValue(SWT.ARROW_UP);
137765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          } else {
138765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            updateValue(SWT.ARROW_DOWN);
139765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          }
140765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          m_spinner.setSelection(25);
141765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        }
142765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      });
143765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
144765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (IS_OS_WINDOWS_XP || IS_OS_WINDOWS_2003) {
145765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        setLayout(new WindowsXpLayout());
146765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      } else if (IS_OS_WINDOWS_VISTA || IS_OS_WINDOWS_7) {
147765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        setLayout(new WindowsVistaLayout());
148765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      } else if (IS_OS_LINUX) {
149765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        setLayout(new LinuxLayout());
150765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      } else if (IS_OS_MAC_OSX) {
151765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        if (IS_OS_MAC_OSX_COCOA) {
152765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          setLayout(new MacCocoaLayout());
153765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        } else {
154765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          setLayout(new MacLayout());
155765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        }
156765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      } else {
157765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        setLayout(new WindowsXpLayout());
158765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
159765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
160765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
161765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
162765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
163765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
164765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Access
165765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
166765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
167765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  @Override
168765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public void setEnabled(boolean enabled) {
169765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    super.setEnabled(enabled);
170765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_text.setEnabled(enabled);
171765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_spinner.setEnabled(enabled);
172765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
173765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
174765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
175765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Sets the number of decimal places used by the receiver.
176765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * <p>
177765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * See {@link Spinner#setDigits(int)}.
178765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
179765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public void setDigits(int digits) {
180765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_formatPattern = "0.";
181765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_multiplier = 1;
182765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    for (int i = 0; i < digits; i++) {
183765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_formatPattern += "0";
184765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_multiplier *= 10;
185765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
186765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_format = new DecimalFormat(m_formatPattern);
187765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    updateText();
188765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
189765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
190765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
191765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Sets minimum and maximum using single invocation.
192765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
193765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public void setRange(int minimum, int maximum) {
194765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    setMinimum(minimum);
195765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    setMaximum(maximum);
196765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
197765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
198765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
199765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * @return the minimum value that the receiver will allow.
200765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
201765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public int getMinimum() {
202765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    return m_minimum;
203765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
204765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
205765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
206765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Sets the minimum value that the receiver will allow.
207765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
208765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public void setMinimum(int minimum) {
209765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_minimum = minimum;
210765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    setSelection(Math.max(m_value, m_minimum));
211765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
212765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
213765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
214765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Sets the maximum value that the receiver will allow.
215765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
216765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public void setMaximum(int maximum) {
217765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_maximum = maximum;
218765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    setSelection(Math.min(m_value, m_maximum));
219765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
220765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
221765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
222765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Sets the amount that the receiver's value will be modified by when the up/down arrows are
223765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * pressed to the argument, which must be at least one.
224765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
225765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public void setIncrement(int increment) {
226765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_increment = increment;
227765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
228765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
229765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
230765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Sets the <em>value</em>, which is the receiver's position, to the argument. If the argument is
231765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * not within the range specified by minimum and maximum, it will be adjusted to fall within this
232765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * range.
233765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
234765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public void setSelection(int newValue) {
235765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    newValue = Math.min(Math.max(m_minimum, newValue), m_maximum);
236765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    if (newValue != m_value) {
237765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_value = newValue;
238765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      updateText();
239765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // set valid state
240765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      setState(null);
241765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
242765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
243765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
244765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private void updateText() {
245765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    String text = m_format.format((double) m_value / m_multiplier);
246765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_text.setText(text);
247765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_text.selectAll();
248765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
249765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
250765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
251765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * @return the <em>selection</em>, which is the receiver's position.
252765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
253765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public int getSelection() {
254765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    return m_value;
255765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
256765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
257765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
258765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
259765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Update
260765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
261765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
262765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
263765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Updates {@link #m_value} into given direction.
264765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
265765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private void updateValue(int direction) {
266765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    // prepare new value
267765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    int newValue;
268765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    {
269765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      newValue = m_value;
270765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (direction == SWT.ARROW_UP) {
271765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        newValue += m_increment;
272765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
273765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (direction == SWT.ARROW_DOWN) {
274765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        newValue -= m_increment;
275765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
276765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
277765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    // update value
278765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    setSelection(newValue);
279765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    notifySelectionListeners(true);
280765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
281765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
282765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
283765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Sets the valid/invalid state.
284765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   *
285765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * @param message
286765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   *          the message to show, or <code>null</code> if valid.
287765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
288765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private void setState(String message) {
289765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_text.setToolTipText(message);
290765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    if (message == null) {
291765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text.setBackground(COLOR_VALID);
292765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    } else {
293765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text.setBackground(COLOR_INVALID);
294765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
295765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
296765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
297765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
298765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Notifies {@link SWT#Selection} listeners with value and state.
299765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
300765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private void notifySelectionListeners(boolean valid) {
301765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    Event event = new Event();
302765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    event.detail = m_value;
303765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    event.doit = valid;
304765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    notifyListeners(SWT.Selection, event);
305765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
306765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
307765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
308765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
309765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Windows XP
310765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
311765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
312765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
313765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Implementation of {@link Layout} for Windows XP.
314765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
315765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private class WindowsXpLayout extends Layout {
316765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
317765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
318765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point size = m_text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
319765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      size.x += m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT).x - m_spinner.getClientArea().width;
320765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // add Text widget margin
321765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      size.y += 2;
322765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // apply hints
323765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (wHint != SWT.DEFAULT) {
324765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        size.x = Math.min(size.x, wHint);
325765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
326765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (hHint != SWT.DEFAULT) {
327765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        size.y = Math.min(size.y, hHint);
328765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
329765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // OK, final size
330765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      return size;
331765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
332765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
333765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
334765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected void layout(Composite composite, boolean flushCache) {
335765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Rectangle cRect = composite.getClientArea();
336765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (cRect.isEmpty()) {
337765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        return;
338765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
339765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare size of Text
340765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point tSize = m_text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
341765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare size of Spinner
342765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point sSize;
343765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize = m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
344765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize.y = Math.min(sSize.y, Math.min(tSize.y, cRect.height));
345765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize.x = Math.min(sSize.x, cRect.width);
346765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare width of arrows part of Spinner
347765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int arrowWidth = m_button.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
348765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // set bounds for Spinner and Text
349765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setBounds(
350765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          cRect.x + cRect.width - sSize.x + 1,
351765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          cRect.y - 1,
352765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          sSize.x,
353765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          cRect.height + 2);
354765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text.setBounds(cRect.x, cRect.y + 1, cRect.width - arrowWidth, tSize.y);
355765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      win32Hack.setBounds(cRect.x, cRect.y, cRect.width - arrowWidth, sSize.y);
356765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
357765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
358765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
359765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
360765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Windows Vista
361765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
362765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
363765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
364765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Implementation of {@link Layout} for Windows Vista.
365765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
366765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private class WindowsVistaLayout extends Layout {
367765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
368765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
369765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point size = m_text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
370765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      size.x += m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT).x - m_spinner.getClientArea().width;
371765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // add Text widget margin
372765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      size.y += 3;
373765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // apply hints
374765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (wHint != SWT.DEFAULT) {
375765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        size.x = Math.min(size.x, wHint);
376765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
377765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (hHint != SWT.DEFAULT) {
378765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        size.y = Math.min(size.y, hHint);
379765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
380765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // OK, final size
381765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      return size;
382765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
383765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
384765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
385765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected void layout(Composite composite, boolean flushCache) {
386765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Rectangle cRect = composite.getClientArea();
387765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (cRect.isEmpty()) {
388765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        return;
389765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
390765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare size of Text
391765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point tSize = m_text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
392765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare size of Spinner
393765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point sSize;
394765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize = m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
395765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize.y = Math.min(sSize.y, Math.min(tSize.y, cRect.height));
396765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize.x = Math.min(sSize.x, cRect.width);
397765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare width of arrows part of Spinner
398765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int arrowWidth = m_button.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
399765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // set bounds for Spinner and Text
400765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setBounds(
401765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          cRect.x + cRect.width - sSize.x + 1,
402765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          cRect.y - 1,
403765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          sSize.x,
404765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          cRect.height + 2);
405765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text.setBounds(cRect.x, cRect.y + 1, cRect.width - arrowWidth, tSize.y);
406765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      win32Hack.setBounds(cRect.x, cRect.y, cRect.width - arrowWidth, sSize.y);
407765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
408765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
409765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
410765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
411765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Linux
412765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
413765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
414765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
415765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Implementation of {@link Layout} for Linux.
416765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
417765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private class LinuxLayout extends Layout {
418765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
419765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
420765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point size = m_text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
421765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      size.x += m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT).x - m_spinner.getClientArea().width;
422765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // apply hints
423765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (wHint != SWT.DEFAULT) {
424765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        size.x = Math.min(size.x, wHint);
425765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
426765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (hHint != SWT.DEFAULT) {
427765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        size.y = Math.min(size.y, hHint);
428765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
429765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // OK, final size
430765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      return size;
431765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
432765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
433765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
434765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected void layout(Composite composite, boolean flushCache) {
435765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Rectangle cRect = composite.getClientArea();
436765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (cRect.isEmpty()) {
437765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        return;
438765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
439765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare size of Text
440765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point tSize = m_text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
441765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare size of Spinner
442765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point sSize;
443765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize = m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
444765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize.y = Math.min(sSize.y, Math.min(tSize.y, cRect.height));
445765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize.x = Math.min(sSize.x, cRect.width);
446765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare width of arrows part of Spinner
447765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int arrowWidth;
448765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      {
449765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        m_spinner.setSize(sSize);
450765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        arrowWidth = sSize.x - m_spinner.getClientArea().width;
451765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
452765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // set bounds for Spinner and Text
453765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setBounds(cRect.x + cRect.width - sSize.x, cRect.y - 2, sSize.x, cRect.height + 4);
454765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text.setBounds(cRect.x, cRect.y, cRect.width - arrowWidth, tSize.y);
455765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
456765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
457765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
458765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
459765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // MacOSX
460765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
461765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
462765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
463765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Implementation of {@link Layout} for MacOSX.
464765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
465765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private class MacLayout extends Layout {
466765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
467765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
468765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point size = m_text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
469765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      size.x += m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT).x - m_spinner.getClientArea().width;
470765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // add Text widget margin
471765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      size.y += 4;
472765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // apply hints
473765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (wHint != SWT.DEFAULT) {
474765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        size.x = Math.min(size.x, wHint);
475765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
476765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (hHint != SWT.DEFAULT) {
477765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        size.y = Math.min(size.y, hHint);
478765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
479765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // OK, final size
480765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      return size;
481765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
482765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
483765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
484765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected void layout(Composite composite, boolean flushCache) {
485765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Rectangle cRect = composite.getClientArea();
486765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (cRect.isEmpty()) {
487765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        return;
488765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
489765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare size of Text
490765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point tSize = m_text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
491765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      tSize.y += 4;
492765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare size of Spinner
493765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point sSize;
494765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize = m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
495765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize.y = Math.min(sSize.y, Math.min(tSize.y, cRect.height));
496765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      sSize.x = Math.min(sSize.x, cRect.width);
497765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare width of arrows part of Spinner
498765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int arrowWidth = m_button.computeSize(-1, -1).x;
499765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // set bounds for Spinner and Text
500765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setBounds(cRect.x + cRect.width - sSize.x, cRect.y, sSize.x, cRect.height);
501765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text.setBounds(cRect.x, cRect.y + 2, cRect.width - arrowWidth - 2, tSize.y);
502765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
503765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
504765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
505765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Implementation of {@link Layout} for MacOSX Cocoa.
506765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
507765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private class MacCocoaLayout extends Layout {
508765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
509765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
510765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point textSize = m_text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
511765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point spinnerSize = m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT);
512765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int arrowWidth = m_button.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
513765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int width = textSize.x + arrowWidth;
514765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int height = Math.max(spinnerSize.y, textSize.y);
515765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // apply hints
516765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (wHint != SWT.DEFAULT) {
517765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        width = Math.min(width, wHint);
518765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
519765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (hHint != SWT.DEFAULT) {
520765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        height = Math.min(height, hHint);
521765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
522765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      return new Point(width, height);
523765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
524765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
525765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    @Override
526765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    protected void layout(Composite composite, boolean flushCache) {
527765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Rectangle clientArea = composite.getClientArea();
528765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (clientArea.isEmpty()) {
529765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        return;
530765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
531765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare size of Spinner
532765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point spinnerSize = m_spinner.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
533765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare width of arrows part of Spinner
534765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int arrowWidth = m_button.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
535765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_spinner.setBounds(clientArea.x + clientArea.width - arrowWidth - 1, clientArea.y
536765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          + clientArea.height
537765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          - spinnerSize.y, arrowWidth + 2, spinnerSize.y);
538765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_text.setBounds(
539765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          clientArea.x + 2,
540765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          clientArea.y + 2,
541765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          clientArea.width - arrowWidth - 5,
542765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          clientArea.y + clientArea.height - 4);
543765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
544765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
545765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
546765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
547765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
548765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // System utils
549765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
550765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
551765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final String OS_NAME = System.getProperty("os.name");
552765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final String OS_VERSION = System.getProperty("os.version");
553765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final String WS_TYPE = SWT.getPlatform();
554765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final boolean IS_OS_MAC_OSX = isOS("Mac OS X");
555765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final boolean IS_OS_MAC_OSX_COCOA = IS_OS_MAC_OSX && "cocoa".equals(WS_TYPE);
556765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final boolean IS_OS_LINUX = isOS("Linux") || isOS("LINUX");
557765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final boolean IS_OS_WINDOWS_XP = isWindowsVersion("5.1");
558765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final boolean IS_OS_WINDOWS_2003 = isWindowsVersion("5.2");
559765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final boolean IS_OS_WINDOWS_VISTA = isWindowsVersion("6.0");
560765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static final boolean IS_OS_WINDOWS_7 = isWindowsVersion("6.1");
561765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
562765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static boolean isOS(String osName) {
563765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    return OS_NAME != null && OS_NAME.startsWith(osName);
564765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
565765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
566765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private static boolean isWindowsVersion(String windowsVersion) {
567765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    return isOS("Windows") && OS_VERSION != null && OS_VERSION.startsWith(windowsVersion);
568765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
569765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye}
570