summaryrefslogtreecommitdiff
path: root/org.tizen.common.externals/src/org
diff options
context:
space:
mode:
Diffstat (limited to 'org.tizen.common.externals/src/org')
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/OpalItem.java158
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/angles/AngleSlider.java246
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/brushedMetalComposite/BrushedMetalComposite.java378
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/checkBoxGroup/CheckBoxGroup.java323
-rwxr-xr-xorg.tizen.common.externals/src/org/mihalis/opal/columns/ColumnBrowserWidget.java785
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/columns/ColumnItem.java416
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/flatButton/FlatButton.java633
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/gradientComposite/GradientComposite.java154
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/header/Header.java529
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/heapManager/HeapManager.java297
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/horizontalSpinner/HorizontalSpinner.java947
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/imageSelector/ISItem.java114
-rwxr-xr-xorg.tizen.common.externals/src/org/mihalis/opal/imageSelector/ImageSelector.java615
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/infinitePanel/InfiniteProgressPanel.java604
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/itemSelector/DLItem.java105
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/itemSelector/DualList.java1265
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/launcher/LLabel.java277
-rwxr-xr-xorg.tizen.common.externals/src/org/mihalis/opal/launcher/Launcher.java428
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/launcher/LauncherItem.java32
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/login/LoginDialog.java511
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/login/LoginDialogVerifier.java29
-rwxr-xr-xorg.tizen.common.externals/src/org/mihalis/opal/multiChoice/MultiChoice.java1195
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/multiChoice/MultiChoiceSelectionListener.java56
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/notify/Notifier.java347
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/notify/NotifierColors.java34
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/notify/NotifierColorsFactory.java66
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/opalDialog/ChoiceItem.java56
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/opalDialog/ChoiceWidget.java301
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/opalDialog/Dialog.java480
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/opalDialog/DialogArea.java154
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/opalDialog/FooterArea.java531
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/opalDialog/MessageArea.java541
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/panels/BlurredPanel.java151
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/panels/DarkPanel.java144
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWContainer.java45
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWGroup.java169
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWRow.java142
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWRowGroup.java79
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWTab.java111
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWTabContainer.java228
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PreferenceWindow.java306
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/ValueAndAssociatedWidgets.java79
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfEquals.java44
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfNotEquals.java44
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfTrue.java46
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/Enabler.java57
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWButton.java63
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWCheckbox.java76
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWChooser.java82
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWColorChooser.java133
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWCombo.java107
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWDirectoryChooser.java78
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFileChooser.java75
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFloatText.java114
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFontChooser.java95
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWIntegerText.java84
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWLabel.java81
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWPasswordText.java69
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWRadio.java98
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWScale.java91
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWSeparator.java78
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWSpinner.java86
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWStringText.java68
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWText.java74
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWTextarea.java77
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWURLText.java98
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWWidget.java264
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/promptSupport/BaseFocusControlListener.java169
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/promptSupport/CComboFocusControlListener.java68
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/promptSupport/ComboFocusControlListener.java73
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/promptSupport/FocusControlListenerFactory.java49
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/promptSupport/PromptSupport.java230
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/promptSupport/StyledTextFocusControlListener.java76
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/promptSupport/TextFocusControlListener.java75
-rwxr-xr-xorg.tizen.common.externals/src/org/mihalis/opal/rangeSlider/RangeSlider.java1060
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/switchButton/SwitchButton.java938
-rwxr-xr-xorg.tizen.common.externals/src/org/mihalis/opal/textAssist/TextAssist.java694
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/textAssist/TextAssistContentProvider.java46
-rwxr-xr-xorg.tizen.common.externals/src/org/mihalis/opal/tipOfTheDay/TipOfTheDay.java524
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/titledSeparator/TitledSeparator.java314
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/DownUpAppearTransition.java34
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/DownUpTransition.java33
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/HorizontalTransition.java86
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/LeftRightAppearTransition.java35
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/LeftRightTransition.java35
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/NoTransition.java31
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/RightLeftAppearTransition.java35
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/RightLeftTransition.java35
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TRANSITIONS.java18
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/Transition.java28
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TransitionComposite.java274
-rwxr-xr-xorg.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TransitionFactory.java48
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/UpDownAppearTransition.java34
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/UpDownTransition.java27
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/VerticalTransition.java84
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/utils/FileToolbox.java47
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/utils/HTMLStyledTextParser.java179
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/utils/ResourceManager.java56
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/utils/SWTGraphicUtil.java463
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/utils/SimpleSelectionAdapter.java47
-rw-r--r--org.tizen.common.externals/src/org/mihalis/opal/utils/StringUtil.java73
-rw-r--r--org.tizen.common.externals/src/org/tizen/common/externals/ExternalsPlugin.java50
102 files changed, 22311 insertions, 0 deletions
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/OpalItem.java b/org.tizen.common.externals/src/org/mihalis/opal/OpalItem.java
new file mode 100644
index 000000000..a06f1de32
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/OpalItem.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal;
+
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Instances of this object are items manipulated by the widgets of the Opal Project. These items are highly customizable, you can set :
+ * <ul>
+ * <li>Background and foreground colors,
+ * <li>Font
+ * <li>Image
+ * <li>Text
+ * <li>Height
+ * </ul>
+ * You can also store data using the <code>setData<code> methods.
+ *
+ */
+public abstract class OpalItem {
+
+ private Map<String, Object> data;
+ private Object datum;
+ private Color background;
+ private Font font;
+ private Color foreground;
+ private Image image;
+ private String text;
+ private int height = -1;
+
+ /**
+ * @return the background color of the item
+ */
+ public Color getBackground() {
+ return this.background;
+ }
+
+ /**
+ * @return the the data stored in this item
+ */
+ public Object getData() {
+ return this.datum;
+ }
+
+ /**
+ * @param key a key
+ * @return the the data stored in this item associated to this key
+ */
+ public Object getData(final String key) {
+ return this.data.get(key);
+ }
+
+ /**
+ * @return the font of the item
+ */
+ public Font getFont() {
+ return this.font;
+ }
+
+ /**
+ * @return the foreground color of the item
+ */
+ public Color getForeground() {
+ return this.foreground;
+ }
+
+ /**
+ * @return the height of the item
+ */
+ public int getHeight() {
+ return this.height;
+ }
+
+ /**
+ * @return the image stored in this item
+ */
+ public Image getImage() {
+ return this.image;
+ }
+
+ /**
+ * @return the text stored in this item
+ */
+ public String getText() {
+ return this.text;
+ }
+
+ /**
+ * @param background set the background color of this item
+ */
+ public void setBackground(final Color background) {
+ this.background = background;
+ }
+
+ /**
+ * @param font set the font of this item
+ */
+ public void setFont(final Font font) {
+ this.font = font;
+ }
+
+ /**
+ * @param foreground set the foreground color of this item
+ */
+ public void setForeground(final Color foreground) {
+ this.foreground = foreground;
+ }
+
+ /**
+ * @param height set the height of this item
+ */
+ public void setHeight(final int height) {
+ this.height = height;
+ }
+
+ /**
+ * @param image set the image of this item
+ */
+ public void setImage(final Image image) {
+ this.image = image;
+ }
+
+ /**
+ * @param text set the text of this item
+ */
+ public void setText(final String text) {
+ this.text = text;
+ }
+
+ /**
+ * @param data set the data stored in this item
+ */
+ public void setData(final Object data) {
+ this.datum = data;
+ }
+
+ /**
+ * Store a data associated to a given key in this item
+ *
+ * @param key key
+ * @param value value associated to this key
+ */
+ public void setData(final String key, final Object value) {
+ this.data.put(key, value);
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/angles/AngleSlider.java b/org.tizen.common.externals/src/org/mihalis/opal/angles/AngleSlider.java
new file mode 100644
index 000000000..bf36ba771
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/angles/AngleSlider.java
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ * inspired by the Swing AngleSlider by Jeremy (http://javagraphics.blogspot.com/2008/05/angles-need-gui-widget-for-angles.html)
+ *******************************************************************************/
+package org.mihalis.opal.angles;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class provide a selectable user interface object that can
+ * be used to pick angles.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ */
+public class AngleSlider extends Canvas {
+
+ private static final int WHOLE_RADIUS = 40;
+ private static final int BUTTON_RADIUS = 10;
+ private static final int STEP = 5;
+
+ private final Image backgroundImage;
+ private final Image buttonFocus;
+ private final Image buttonNoFocus;
+ private int selection;
+ private final List<SelectionListener> selectionListeners;
+ private boolean mousePressed;
+
+ /**
+ * Constructs a new instance of this class given its parent.
+ *
+ * @param parent a widget which will be the parent of the new instance
+ * (cannot be null)
+ * @param style not used
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ */
+ public AngleSlider(final Composite parent, final int style) {
+ super(parent, style | SWT.DOUBLE_BUFFERED);
+
+ this.backgroundImage = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/angleBackground.png"));
+
+ this.buttonFocus = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/angleButtonFocus.png"));
+ this.buttonNoFocus = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/angleButtonFocusLost.png"));
+
+ this.addListener(SWT.Paint, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ paintControl(event);
+ }
+ });
+
+ this.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent arg0) {
+ SWTGraphicUtil.dispose(AngleSlider.this.backgroundImage);
+ SWTGraphicUtil.dispose(AngleSlider.this.buttonFocus);
+ SWTGraphicUtil.dispose(AngleSlider.this.buttonNoFocus);
+ }
+ });
+
+ this.addListener(SWT.MouseDown, createMouseListener());
+ this.addListener(SWT.MouseUp, createMouseListener());
+ this.addListener(SWT.MouseMove, createMouseListener());
+ this.addListener(SWT.KeyDown, createKeyListener());
+
+ this.selection = 0;
+ this.selectionListeners = new ArrayList<SelectionListener>();
+
+ }
+
+ private void paintControl(final Event event) {
+ final GC gc = event.gc;
+
+ gc.drawImage(this.backgroundImage, 0, 0);
+
+ float angle = this.selection / 360f;
+ angle = (float) (angle * 2 * Math.PI - 0.5 * Math.PI);
+
+ final float centerX = WHOLE_RADIUS / 2f;
+ final float centerY = WHOLE_RADIUS / 2f;
+ final float radius = BUTTON_RADIUS;
+ final float x = (float) (centerX - radius * Math.cos(angle));
+ final float y = (float) (centerY - radius * Math.sin(angle));
+
+ if (isFocusControl()) {
+ gc.drawImage(this.buttonFocus, (int) x - 2, (int) y - 2);
+ } else {
+ gc.drawImage(this.buttonNoFocus, (int) x - 2, (int) y - 2);
+ }
+
+ if (!isEnabled()) {
+ gc.setAlpha(127);
+ gc.setAntialias(SWT.ON);
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillOval(4, 4, WHOLE_RADIUS - 7, WHOLE_RADIUS - 7);
+ }
+ }
+
+ private Listener createMouseListener() {
+ return new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ if (!isEnabled()) {
+ return;
+ }
+
+ if (event.type == SWT.MouseDown) {
+ AngleSlider.this.mousePressed = true;
+ }
+ if (event.type == SWT.MouseDown || event.type == SWT.MouseMove && AngleSlider.this.mousePressed) {
+ final float deltaX = event.x - WHOLE_RADIUS / 2f;
+ final float deltaY = event.y - WHOLE_RADIUS / 2f;
+ final double angle = Math.atan2(deltaX, deltaY);
+ AngleSlider.this.selection = 360 - (int) (360 * angle / (2 * Math.PI) + 360) % 360;
+
+ AngleSlider.this.redraw();
+ }
+ if (event.type == SWT.MouseUp) {
+ AngleSlider.this.mousePressed = false;
+ fireSelectionListeners(event);
+ }
+ }
+ };
+ }
+
+ private void fireSelectionListeners(final Event event) {
+ for (final SelectionListener selectionListener : this.selectionListeners) {
+ selectionListener.widgetSelected(new SelectionEvent(event));
+ }
+
+ }
+
+ private Listener createKeyListener() {
+ return new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ if (!isEnabled()) {
+ return;
+ }
+ if (event.type != SWT.KeyDown) {
+ return;
+ }
+ if (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_LEFT) {
+ setSelection(AngleSlider.this.selection + STEP);
+ }
+ if (event.keyCode == SWT.ARROW_DOWN || event.keyCode == SWT.ARROW_RIGHT) {
+ setSelection(AngleSlider.this.selection - STEP);
+ }
+ }
+ };
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Scale#addSelectionListener(org.eclipse.swt.events.SelectionListener)
+ */
+ public void addSelectionListener(final SelectionListener selectionListener) {
+ checkWidget();
+ this.selectionListeners.add(selectionListener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
+ */
+ @Override
+ public Point computeSize(final int wHint, final int hHint, final boolean changed) {
+ checkWidget();
+ return new Point(WHOLE_RADIUS, WHOLE_RADIUS);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Scale#getSelection()
+ */
+ public int getSelection() {
+ checkWidget();
+ return this.selection;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Scale#removeSelectionListener(org.eclipse.swt.events.SelectionListener)
+ */
+ public void removeSelectionListener(final SelectionListener selectionListener) {
+ checkWidget();
+ this.selectionListeners.remove(selectionListener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#setEnabled(boolean)
+ */
+ @Override
+ public void setEnabled(final boolean enabled) {
+ super.setEnabled(enabled);
+ redraw();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Scale#setSelection(int)
+ */
+ public void setSelection(final int selection) {
+ checkWidget();
+ if (selection < 0 || selection > 360) {
+ SWT.error(SWT.ERROR_CANNOT_SET_SELECTION);
+ }
+ this.selection = selection;
+ fireSelectionListeners(new Event());
+ redraw();
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/brushedMetalComposite/BrushedMetalComposite.java b/org.tizen.common.externals/src/org/mihalis/opal/brushedMetalComposite/BrushedMetalComposite.java
new file mode 100644
index 000000000..893b8c6ff
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/brushedMetalComposite/BrushedMetalComposite.java
@@ -0,0 +1,378 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Jerry Huxtable (http://www.jhlabs.com/index.html) - initial API and implementation (on SWING),
+ * Laurent CARON (laurent.caron at gmail dot com) - port to SWT
+ *******************************************************************************/
+package org.mihalis.opal.brushedMetalComposite;
+
+import java.util.Random;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are controls which background's texture is brushed
+ * metal "a la Mac"
+ */
+public class BrushedMetalComposite extends Composite {
+
+ private Image oldImage;
+ private int radius = 10;
+ private float amount = 0.1f;
+ private int color = 0xff888888;
+ private float shine = 0.1f;
+ private boolean monochrome = true;
+ private Random randomNumbers;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance
+ * (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ * @see Composite#Composite(Composite, int)
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_FOCUS
+ * @see SWT#NO_MERGE_PAINTS
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_RADIO_GROUP
+ * @see SWT#EMBEDDED
+ * @see SWT#DOUBLE_BUFFERED
+ * @see Widget#getStyle
+ */
+ public BrushedMetalComposite(final Composite parent, final int style) {
+ super(parent, style);
+ this.addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ BrushedMetalComposite.this.redrawComposite();
+ }
+ });
+
+ parent.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(BrushedMetalComposite.this.oldImage);
+ }
+ });
+ }
+
+ /**
+ * Redraws the composite
+ */
+ private void redrawComposite() {
+ final Display display = this.getDisplay();
+ final Rectangle rect = this.getClientArea();
+ final ImageData imageData = this.drawBrushedMetalBackground(Math.max(1, rect.width), Math.max(1, rect.width));
+ final Image newImage = new Image(display, imageData);
+
+ this.setBackgroundImage(newImage);
+ SWTGraphicUtil.dispose(this.oldImage);
+ this.oldImage = newImage;
+ }
+
+ /**
+ * Create a brushed metal background
+ *
+ * @param width width of the panel
+ * @param height height of the panel
+ * @return an image data that contains the background
+ */
+ private ImageData drawBrushedMetalBackground(final int width, final int height) {
+
+ final int[] inPixels = new int[width];
+ final PaletteData palette = new PaletteData(0xFF0000, 0x00FF00, 0x0000FF);
+ final ImageData data = new ImageData(width, height, 0x20, palette);
+
+ this.randomNumbers = new Random(0);
+ final int a = this.color & 0xff000000;
+ final int r = this.color >> 16 & 0xff;
+ final int g = this.color >> 8 & 0xff;
+ final int b = this.color & 0xff;
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ int tr = r;
+ int tg = g;
+ int tb = b;
+ if (this.shine != 0) {
+ final int f = (int) (255 * this.shine * Math.sin((double) x / width * Math.PI));
+ tr += f;
+ tg += f;
+ tb += f;
+ }
+ if (this.monochrome) {
+ final int n = (int) (255 * (2 * this.randomNumbers.nextFloat() - 1) * this.amount);
+ inPixels[x] = a | this.clamp(tr + n) << 16 | this.clamp(tg + n) << 8 | this.clamp(tb + n);
+ } else {
+ inPixels[x] = a | this.random(tr) << 16 | this.random(tg) << 8 | this.random(tb);
+ }
+ }
+
+ if (this.radius != 0) {
+ this.setDataElements(data, palette, 0, y, width, 1, this.blur(inPixels, width, this.radius));
+ } else {
+ this.setDataElements(data, palette, 0, y, width, 1, inPixels);
+ }
+ }
+
+ return data;
+ }
+
+ /**
+ * Sets the data for a rectangle of pixels from a primitive array
+ *
+ * @param data the source ImageData
+ * @param palette the palette associated to the imageData
+ * @param posX The X coordinate of the upper left pixel location.
+ * @param posY The Y coordinate of the upper left pixel location.
+ * @param width Width of the pixel rectangle.
+ * @param height Height of the pixel rectangle
+ * @param pixels An array containing the pixel data to place between x,y and
+ * x+w-1, y+h-1.
+ */
+ private void setDataElements(final ImageData data, final PaletteData palette, final int posX, final int posY, final int width, final int height, final int[] pixels) {
+ int cpt = 0;
+ for (int y = posY; y < posY + height; y++) {
+ for (int x = posX; x < posX + width; x++) {
+ final int rgb = pixels[cpt++];
+ final int pixel = palette.getPixel(new RGB(rgb >> 16 & 0xFF, rgb >> 8 & 0xFF, rgb & 0xFF));
+ data.setPixel(x, y, pixel);
+ data.setAlpha(x, y, rgb >> 24 & 0xFF);
+ }
+ }
+ }
+
+ /**
+ * Add a random number to the value. The result is between 0 and 255
+ *
+ * @param x the initial value
+ * @return
+ */
+ private int random(int x) {
+ x += (int) (255 * (2 * this.randomNumbers.nextFloat() - 1) * this.amount);
+ if (x < 0) {
+ x = 0;
+ } else if (x > 0xff) {
+ x = 0xff;
+ }
+ return x;
+ }
+
+ /**
+ * Clamp a number between 0 and 255
+ *
+ * @param c the number to clamp
+ * @return the number. If c is negative, returns 0. If c is greater than
+ * 255, returns 255.
+ */
+ private int clamp(final int c) {
+ if (c < 0) {
+ return 0;
+ }
+
+ if (c > 255) {
+ return 255;
+ }
+
+ return c;
+ }
+
+ /**
+ * Apply a blur filter to an array of int that represents and image which
+ * size is width columns * 1 row
+ *
+ * @param in the array of int that represents the image
+ * @param width the width of the image
+ * @param radius the "radius" blur parameter
+ */
+ private int[] blur(final int[] in, final int width, final int radius) {
+ final int[] out = new int[width];
+ final int widthMinus1 = width - 1;
+ final int r2 = 2 * radius + 1;
+ int tr = 0, tg = 0, tb = 0;
+
+ for (int i = -radius; i <= radius; i++) {
+ final int rgb = in[this.mod(i, width)];
+ tr += rgb >> 16 & 0xff;
+ tg += rgb >> 8 & 0xff;
+ tb += rgb & 0xff;
+ }
+
+ for (int x = 0; x < width; x++) {
+ out[x] = 0xff000000 | tr / r2 << 16 | tg / r2 << 8 | tb / r2;
+
+ int i1 = x + radius + 1;
+ if (i1 > widthMinus1) {
+ i1 = this.mod(i1, width);
+ }
+ int i2 = x - radius;
+ if (i2 < 0) {
+ i2 = this.mod(i2, width);
+ }
+ final int rgb1 = in[i1];
+ final int rgb2 = in[i2];
+
+ tr += (rgb1 & 0xff0000) - (rgb2 & 0xff0000) >> 16;
+ tg += (rgb1 & 0xff00) - (rgb2 & 0xff00) >> 8;
+ tb += (rgb1 & 0xff) - (rgb2 & 0xff);
+ }
+ return out;
+ }
+
+ /**
+ * Return a mod b. This differs from the % operator with respect to negative
+ * numbers.
+ *
+ * @param a the dividend
+ * @param b the divisor
+ * @return a mod b
+ */
+ private int mod(int a, final int b) {
+ final int n = a / b;
+
+ a -= n * b;
+ if (a < 0) {
+ return a + b;
+ }
+ return a;
+ }
+
+ // ------------------------------------ Getters and Setters
+
+ /**
+ * @return the "radius" of the blur
+ */
+ public int getRadius() {
+ return this.radius;
+ }
+
+ /**
+ * @param radius the "radius" of the blur
+ */
+ public void setRadius(final int radius) {
+ this.radius = radius;
+ this.redrawComposite();
+ }
+
+ /**
+ * @return the amount of noise to add
+ */
+ public float getAmount() {
+ return this.amount;
+ }
+
+ /**
+ * @param amount the amount of noise to add
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the value is not between 0
+ * and 1 inclusive</li>
+ * </ul>
+ */
+ public void setAmount(final float amount) {
+ if (amount < 0f || amount > 1f) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.amount = amount;
+ this.redrawComposite();
+ }
+
+ /**
+ * @return the color of the metal. Please notice that this color is a new
+ * SWT object, so it has to be disposed !
+ */
+ public Color getColor() {
+ return new Color(this.getDisplay(), this.color >> 16 & 0xFF, this.color >> 8 & 0xFF, this.color & 0xFF);
+ }
+
+ /**
+ * @param color the color to set
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the value is null</li>
+ * </ul>
+ */
+ public void setColor(final Color color) {
+ if (color == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ this.color = 0xFF << 24 | color.getRed() << 16 | color.getGreen() << 8 | color.getBlue();
+ this.redrawComposite();
+ }
+
+ /**
+ * @return the shine to add
+ */
+ public float getShine() {
+ return this.shine;
+ }
+
+ /**
+ * @param shine the shine to set
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the value is not between 0
+ * and 1 inclusive</li>
+ * </ul>
+ */
+ public void setShine(final float shine) {
+ if (this.amount < 0f || this.amount > 1f) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.shine = shine;
+ this.redrawComposite();
+ }
+
+ /**
+ * @return the monochrome
+ */
+ public boolean isMonochrome() {
+ return this.monochrome;
+ }
+
+ /**
+ * @param monochrome the monochrome to set
+ */
+ public void setMonochrome(final boolean monochrome) {
+ this.monochrome = monochrome;
+ this.redrawComposite();
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/checkBoxGroup/CheckBoxGroup.java b/org.tizen.common.externals/src/org/mihalis/opal/checkBoxGroup/CheckBoxGroup.java
new file mode 100644
index 000000000..d8ec1e34a
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/checkBoxGroup/CheckBoxGroup.java
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.checkBoxGroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class provide an etched border with a title and a checkbox.
+ * If the checkbox is checked, the content of the composite is enabled. If the
+ * checkbox is unchecked, the content of the composite is disabled, thus not
+ * editable.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ */
+public class CheckBoxGroup extends Composite {
+ private Image oldImage;
+ protected final Button button;
+ private final Composite content;
+ private final List<SelectionListener> selectionListeners;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance
+ * (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ * @see Composite#Composite(Composite, int)
+ * @see SWT#BORDER
+ * @see Widget#getStyle
+ */
+ public CheckBoxGroup(final Composite parent, final int style) {
+ super(parent, style);
+ super.setLayout(new GridLayout());
+ this.selectionListeners = new ArrayList<SelectionListener>();
+
+ this.button = new Button(this, SWT.CHECK);
+ final GridData gdButton = new GridData(GridData.BEGINNING, GridData.CENTER, true, false);
+ gdButton.horizontalIndent = 15;
+ this.button.setLayoutData(gdButton);
+ this.button.setSelection(true);
+ this.button.setBackground(this.getBackground());
+ this.button.pack();
+
+ this.button.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ e.doit = fireSelectionListeners(e);
+ if (!e.doit) {
+ return;
+ }
+ if (CheckBoxGroup.this.button.getSelection()) {
+ CheckBoxGroup.this.activate();
+ } else {
+ CheckBoxGroup.this.deactivate();
+ }
+ }
+ });
+
+ this.content = new Composite(this, SWT.NONE);
+ this.content.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
+
+ this.addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ CheckBoxGroup.this.drawWidget();
+ }
+ });
+
+ }
+
+ /**
+ * Fire the selection listeners
+ *
+ * @param selectionEvent mouse event
+ * @return true if the selection could be changed, false otherwise
+ */
+ private boolean fireSelectionListeners(final SelectionEvent selectionEvent) {
+ selectionEvent.widget = this;
+ for (final SelectionListener listener : this.selectionListeners) {
+ listener.widgetSelected(selectionEvent);
+ if (!selectionEvent.doit) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Draws the widget
+ */
+ private void drawWidget() {
+ final Display display = this.getDisplay();
+ final Rectangle rect = this.getClientArea();
+ final Image newImage = new Image(display, Math.max(1, rect.width), Math.max(1, rect.height));
+
+ final GC gc = new GC(newImage);
+ gc.setBackground(this.getBackground());
+
+ gc.fillRectangle(0, 0, rect.width, rect.height);
+
+ final int margin = (int) (this.button.getSize().y * 1.5);
+ final int startY = margin / 2;
+
+ gc.setForeground(this.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
+ gc.drawRoundRectangle(1, startY, rect.width - 2, rect.height - startY - 2, 2, 2);
+
+ gc.setForeground(this.getDisplay().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
+ gc.drawRoundRectangle(2, startY + 1, rect.width - 4, rect.height - startY - 4, 2, 2);
+
+ gc.dispose();
+
+ this.setBackgroundImage(newImage);
+ if (this.oldImage != null) {
+ this.oldImage.dispose();
+ }
+ this.oldImage = newImage;
+
+ }
+
+ /**
+ * Activate the content
+ */
+ public void activate() {
+ this.button.setSelection(true);
+ SWTGraphicUtil.enable(this.content, true);
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified
+ * when the user changes the receiver's selection, by sending it one of the
+ * messages defined in the <code>SelectionListener</code> interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event
+ * object is valid. If the receiver has the <code>SWT.CHECK</code> style and
+ * the check selection changes, the event object detail field contains the
+ * value <code>SWT.CHECK</code>. <code>widgetDefaultSelected</code> is
+ * typically called when an item is double-clicked. The item field of the
+ * event object is valid for default selection, but the detail field is not
+ * used.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user
+ * changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.selectionListeners.add(listener);
+ }
+
+ /**
+ * Deactivate the content
+ */
+ public void deactivate() {
+ this.button.setSelection(false);
+ SWTGraphicUtil.enable(this.content, false);
+ }
+
+ /**
+ * @return <code>true</code> if the content is activated, <code>false</code>
+ * otherwise
+ */
+ public boolean isActivated() {
+ return this.button.getSelection();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#getLayout()
+ */
+ @Override
+ public Layout getLayout() {
+ return this.content.getLayout();
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be
+ * notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.selectionListeners.remove(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#setFocus()
+ */
+ @Override
+ public boolean setFocus() {
+ return this.content.setFocus();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#setLayout(org.eclipse.swt.widgets.Layout)
+ */
+ @Override
+ public void setLayout(final Layout layout) {
+ this.content.setLayout(layout);
+ }
+
+ // ------------------------------------ Getters and Setters
+
+ /**
+ * @return the text of the button
+ */
+ public String getText() {
+ return this.button.getText();
+ }
+
+ /**
+ * @param text the text of the button to set
+ */
+ public void setText(final String text) {
+ this.button.setText(text);
+ }
+
+ /**
+ * @return the font of the button
+ */
+ @Override
+ public Font getFont() {
+ return this.button.getFont();
+ }
+
+ /**
+ * @param font the font to set
+ */
+ @Override
+ public void setFont(final Font font) {
+ this.button.setFont(font);
+ }
+
+ /**
+ * @return the content of the group
+ */
+ public Composite getContent() {
+ return this.content;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/columns/ColumnBrowserWidget.java b/org.tizen.common.externals/src/org/mihalis/opal/columns/ColumnBrowserWidget.java
new file mode 100755
index 000000000..991f6a210
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/columns/ColumnBrowserWidget.java
@@ -0,0 +1,785 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.columns;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Widget;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class provide a data browser similar to the ones used in
+ * Mac OS X. Look at http://en.wikipedia.org/wiki/Miller_Columns
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ */
+public class ColumnBrowserWidget extends ScrolledComposite {
+
+ private final List<Table> columns;
+ private final Composite composite;
+ private final Image columnArrow;
+ private final List<SelectionListener> selectionListeners;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance
+ * (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ * @see Composite#Composite(Composite, int)
+ * @see SWT#BORDER
+ * @see Widget#getStyle
+ */
+ public ColumnBrowserWidget(final Composite parent, final int style) {
+ super(parent, style | SWT.H_SCROLL | SWT.V_SCROLL);
+
+ this.composite = new Composite(this, SWT.NONE);
+ final RowLayout layout = new RowLayout(SWT.HORIZONTAL);
+ layout.spacing = 1;
+ layout.pack = false;
+ this.composite.setLayout(layout);
+
+ this.columnArrow = SWTGraphicUtil.createImage("images/columnArrow.png");
+
+ this.columns = new ArrayList<Table>();
+ for (int i = 0; i < 3; i++) {
+ this.createTable();
+ }
+
+ // Store root
+ this.columns.get(0).setData(new ColumnItem(this));
+
+ this.setContent(this.composite);
+ this.setExpandHorizontal(true);
+ this.setExpandVertical(true);
+ this.setShowFocusedControl(true);
+ this.updateContent();
+ this.setMinSize(this.composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+
+ this.selectionListeners = new ArrayList<SelectionListener>();
+
+ this.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent arg0) {
+ SWTGraphicUtil.dispose(ColumnBrowserWidget.this.columnArrow);
+ }
+ });
+
+ }
+
+ /**
+ * Create a column that displays data
+ */
+ private void createTable() {
+ final Table table = new Table(this.composite, SWT.SINGLE | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
+ new TableColumn(table, SWT.LEFT);
+
+ table.setLayoutData(new RowData(150, 175));
+ this.columns.add(table);
+
+ table.addListener(SWT.Resize, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ final int width = table.getSize().x;
+ table.getColumn(0).setWidth(width - 5);
+ }
+ });
+
+ table.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ final Table table = (Table) event.widget;
+ if (table.getSelection() == null || table.getSelection().length != 1) {
+ return;
+ }
+ ColumnBrowserWidget.this.selectItem(table.getSelection()[0]);
+ }
+ });
+
+ final Listener paintListener = new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ switch (event.type) {
+ case SWT.MeasureItem: {
+ final Rectangle rect = ColumnBrowserWidget.this.columnArrow.getBounds();
+ event.width += rect.width;
+ event.height = Math.max(event.height, rect.height + 2);
+ break;
+ }
+
+ case SWT.PaintItem: {
+ if (!(event.item instanceof TableItem)) {
+ return;
+ }
+ final TableItem item = (TableItem) event.item;
+ if (item.getData() == null) {
+ return;
+ }
+
+ if (((ColumnItem) item.getData()).getItemCount() == 0) {
+ return;
+ }
+
+ final int x = event.x + event.width;
+ final Rectangle rect = ColumnBrowserWidget.this.columnArrow.getBounds();
+ final int offset = Math.max(0, (event.height - rect.height) / 2);
+ event.gc.drawImage(ColumnBrowserWidget.this.columnArrow, x, event.y + offset);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ };
+ table.addListener(SWT.MeasureItem, paintListener);
+ table.addListener(SWT.PaintItem, paintListener);
+
+ table.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ ColumnBrowserWidget.this.fireSelectionListeners(e);
+ }
+
+ @Override
+ public void widgetDefaultSelected(final SelectionEvent e) {
+ ColumnBrowserWidget.this.fireSelectionListeners(e);
+ }
+ });
+
+ if (super.getBackground() != null && super.getBackground().getRed() != 240 && super.getBackground().getGreen() != 240 && super.getBackground().getBlue() != 240) {
+ table.setBackground(super.getBackground());
+ }
+ table.setBackgroundImage(super.getBackgroundImage());
+ table.setBackgroundMode(super.getBackgroundMode());
+ table.setCursor(super.getCursor());
+ table.setFont(super.getFont());
+ table.setForeground(super.getForeground());
+ table.setMenu(super.getMenu());
+ table.setToolTipText(super.getToolTipText());
+
+ }
+
+ /**
+ * Fire the selection listeners
+ *
+ * @param selectionEvent mouse event
+ * @return true if the selection could be changed, false otherwise
+ */
+ private boolean fireSelectionListeners(final SelectionEvent selectionEvent) {
+ for (final SelectionListener listener : this.selectionListeners) {
+ final Event event = new Event();
+
+ event.button = 0;
+ event.display = this.getDisplay();
+ event.item = null;
+ event.widget = this;
+ event.data = null;
+ event.time = selectionEvent.time;
+ event.x = selectionEvent.x;
+ event.y = selectionEvent.y;
+
+ final SelectionEvent selEvent = new SelectionEvent(event);
+ listener.widgetSelected(selEvent);
+ if (!selEvent.doit) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Perform actions when an item is selected (ie fill the next column and
+ * force focus on it)
+ *
+ * @param tableItem selected item
+ */
+ private void selectItem(final TableItem tableItem) {
+ final ColumnItem c = (ColumnItem) tableItem.getData();
+
+ if (c.getItemCount() == 0) {
+ return;
+ }
+
+ final int selectedColumn = this.findSelectedColumn(tableItem);
+ boolean needPacking = false;
+ if (selectedColumn != this.columns.size() - 1) {
+ for (int i = selectedColumn + 1; i < this.columns.size(); i++) {
+ this.columns.get(i).setData(null);
+ this.columns.get(i).deselectAll();
+ }
+
+ int i = 0;
+ final Iterator<Table> it = this.columns.iterator();
+ while (it.hasNext()) {
+ final Table t = it.next();
+ if (i >= 3) {
+ t.dispose();
+ it.remove();
+ // Don't know why, it's not working if I do not include this
+ // :(
+ this.setMinSize(this.composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ }
+ i++;
+ }
+
+ if (selectedColumn != this.columns.size() - 1) {
+ this.columns.get(selectedColumn + 1).setData(c);
+ } else {
+ this.createTable();
+ this.columns.get(this.columns.size() - 1).setData(c);
+ }
+ needPacking = true;
+
+ } else {
+ this.createTable();
+ needPacking = true;
+ this.columns.get(this.columns.size() - 1).setData(c);
+ }
+ this.updateContent();
+ if (needPacking) {
+ this.composite.pack();
+ this.setMinSize(this.composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ }
+ this.columns.get(this.columns.size() - 1).forceFocus();
+ }
+
+ /**
+ * Find which column has been selected
+ *
+ * @param tableItem selected table item
+ * @return the index of the selected column
+ */
+ private int findSelectedColumn(final TableItem tableItem) {
+ for (int i = 0; i < this.columns.size(); i++) {
+ if (this.columns.get(i).equals(tableItem.getParent())) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Update the content of the widget
+ */
+ void updateContent() {
+ if (this.columns == null) {
+ return;
+ }
+
+ for (int i = 0; i < this.columns.size(); i++) {
+
+ final Table table = this.columns.get(i);
+ final int index = table.getSelectionIndex();
+ table.removeAll();
+ if (table.getData() == null) {
+ continue;
+ }
+ for (final ColumnItem c : ((ColumnItem) table.getData()).getItems()) {
+ final TableItem item = new TableItem(table, SWT.NONE);
+ item.setData(c);
+ if (c.getText() != null) {
+ item.setText(c.getText());
+ }
+ if (c.getImage() != null) {
+ item.setImage(c.getImage());
+ }
+ }
+ table.setSelection(index);
+ }
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified
+ * when the user changes the receiver's selection, by sending it one of the
+ * messages defined in the <code>SelectionListener</code> interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event
+ * object is valid. If the receiver has the <code>SWT.CHECK</code> style and
+ * the check selection changes, the event object detail field contains the
+ * value <code>SWT.CHECK</code>. <code>widgetDefaultSelected</code> is
+ * typically called when an item is double-clicked. The item field of the
+ * event object is valid for default selection, but the detail field is not
+ * used.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user
+ * changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.selectionListeners.add(listener);
+ }
+
+ /**
+ * Clear the selection
+ *
+ * @param needPacking if <code>true</code>, the widget is packed
+ */
+ public void clear(final boolean needPacking) {
+ final Iterator<Table> it = this.columns.iterator();
+ int i = 0;
+ while (it.hasNext()) {
+ final Table t = it.next();
+ if (i >= 3) {
+ t.dispose();
+ it.remove();
+ } else {
+ if (i != 0) {
+ t.setData(null);
+ }
+ t.deselectAll();
+ }
+ i++;
+ }
+ this.updateContent();
+ if (needPacking) {
+ this.composite.pack();
+ this.setMinSize(this.composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ }
+ this.columns.get(0).forceFocus();
+ }
+
+ /**
+ * Returns the <code>ColumnItem</code>s that is currently selected in the
+ * receiver.
+ *
+ * @return the selected item, or <code>null</code> if no one is selected
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public ColumnItem getSelection() {
+ for (int i = this.columns.size() - 1; i >= 0; i--) {
+ final Table table = this.columns.get(i);
+ if (table == null || table.getData() == null || table.getSelection().length == 0) {
+ continue;
+ }
+
+ return (ColumnItem) table.getItem(table.getSelectionIndex()).getData();
+
+ }
+ return null;
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be
+ * notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.selectionListeners.remove(listener);
+ }
+
+ /**
+ * Selects an item in the receiver. If the item was already selected, it
+ * remains selected.
+ *
+ * @param item the item to be selected
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void select(final ColumnItem item) {
+
+ final List<ColumnItem> items = new ArrayList<ColumnItem>();
+ this.findElement(item, items);
+ Collections.reverse(items);
+ if (items.isEmpty()) {
+ return;
+ }
+
+ this.clear(false);
+ for (int i = 3; i < items.size(); i++) {
+ this.createTable();
+ }
+ for (int i = 0; i < items.size() - 1; i++) {
+ this.columns.get(i + 1).setData(items.get(i));
+ }
+ this.updateContent();
+
+ for (int i = 0; i < this.columns.size() - 1; i++) {
+ final ColumnItem nextItem = (ColumnItem) this.columns.get(i + 1).getData();
+ for (final TableItem tableItem : this.columns.get(i).getItems()) {
+ if (tableItem.getData() != null && tableItem.getData().equals(nextItem)) {
+ tableItem.getParent().setSelection(tableItem);
+ }
+ }
+ }
+
+ this.composite.pack();
+ this.setMinSize(this.composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ this.columns.get(this.columns.size() - 1).forceFocus();
+
+ }
+
+ /**
+ * Build an array that contains the hierarchy of ColumnItem from the root
+ * node to a given item.
+ *
+ * @param item item to find
+ * @param items the lists of item that composes the hierarchy
+ */
+ private void findElement(final ColumnItem item, final List<ColumnItem> items) {
+ if (item == null) {
+ return;
+ }
+ items.add(item);
+ this.findElement(item.getParentItem(), items);
+ }
+
+ /**
+ * Sets the receiver's background color to the color specified by the
+ * argument, or to the default system color for the control if the argument
+ * is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform. For
+ * example, on Windows the background of a Button cannot be changed.
+ * </p>
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ * @see org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics.Color)
+ */
+ @Override
+ public void setBackground(final Color color) {
+ super.setBackground(color);
+ for (final Table column : this.columns) {
+ column.setBackground(color);
+ }
+ }
+
+ /**
+ * Sets the background drawing mode to the argument which should be one of
+ * the following constants defined in class <code>SWT</code>:
+ * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
+ * <code>INHERIT_FORCE</code>.
+ *
+ * @param mode the new background mode
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see org.eclipse.swt.widgets.Composite#setBackgroundMode(int)
+ */
+ @Override
+ public void setBackgroundMode(final int mode) {
+ super.setBackgroundMode(mode);
+ for (final Table column : this.columns) {
+ column.setBackgroundMode(mode);
+ }
+ }
+
+ /**
+ * Sets the receiver's background image to the image specified by the
+ * argument, or to the default system color for the control if the argument
+ * is null. The background image is tiled to fill the available space.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform. For
+ * example, on Windows the background of a Button cannot be changed.
+ * </p>
+ *
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been
+ * disposed</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument is not a
+ * bitmap</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see org.eclipse.swt.widgets.Control#setBackgroundImage(org.eclipse.swt.graphics.Image)
+ */
+ @Override
+ public void setBackgroundImage(final Image image) {
+ super.setBackgroundImage(image);
+ for (final Table column : this.columns) {
+ column.setBackgroundImage(image);
+ }
+ }
+
+ /**
+ * Sets the receiver's cursor to the cursor specified by the argument, or to
+ * the default cursor for that kind of control if the argument is null.
+ * <p>
+ * When the mouse pointer passes over a control its appearance is changed to
+ * match the control's cursor.
+ * </p>
+ *
+ * @param cursor the new cursor (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ * @see org.eclipse.swt.widgets.Control#setCursor(org.eclipse.swt.graphics.Cursor)
+ */
+ @Override
+ public void setCursor(final Cursor cursor) {
+ super.setCursor(cursor);
+ for (final Table column : this.columns) {
+ column.setCursor(cursor);
+ }
+ }
+
+ /**
+ * Sets the font that the receiver will use to paint textual information to
+ * the font specified by the argument, or to the default font for that kind
+ * of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ * @see org.eclipse.swt.widgets.Control#setFont(org.eclipse.swt.graphics.Font)
+ */
+ @Override
+ public void setFont(final Font font) {
+ super.setFont(font);
+ for (final Table column : this.columns) {
+ column.setFont(font);
+ }
+ }
+
+ /**
+ * Sets the receiver's foreground color to the color specified by the
+ * argument, or to the default system color for the control if the argument
+ * is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * </p>
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ * @see org.eclipse.swt.widgets.Control#setForeground(org.eclipse.swt.graphics.Color)
+ */
+ @Override
+ public void setForeground(final Color color) {
+ super.setForeground(color);
+ for (final Table column : this.columns) {
+ column.setForeground(color);
+ }
+ }
+
+ /**
+ * Sets the receiver's pop up menu to the argument. All controls may
+ * optionally have a pop up menu that is displayed when the user requests
+ * one for the control. The sequence of key strokes, button presses and/or
+ * button releases that are used to request a pop up menu is platform
+ * specific.
+ * <p>
+ * Note: Disposing of a control that has a pop up menu will dispose of the
+ * menu. To avoid this behavior, set the menu to null before the control is
+ * disposed.
+ * </p>
+ *
+ * @param menu the new pop up menu
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li>
+ * <li>ERROR_INVALID_PARENT - if the menu is not in the same
+ * widget tree</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ * @see org.eclipse.swt.widgets.Control#setMenu(org.eclipse.swt.widgets.Menu)
+ */
+ @Override
+ public void setMenu(final Menu menu) {
+ super.setMenu(menu);
+ for (final Table column : this.columns) {
+ column.setMenu(menu);
+ }
+ }
+
+ /**
+ * Sets the receiver's tool tip text to the argument, which may be null
+ * indicating that the default tool tip for the control will be shown. For a
+ * control that has a default tool tip, such as the Tree control on Windows,
+ * setting the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool
+ * tip. To display a single '&amp;' in the tool tip, the character '&amp;'
+ * can be escaped by doubling it in the string.
+ * </p>
+ *
+ * @param string the new tool tip text (or null)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ * @see org.eclipse.swt.widgets.Control#setToolTipText(java.lang.String)
+ */
+ @Override
+ public void setToolTipText(final String tooltipText) {
+ super.setToolTipText(tooltipText);
+ for (final Table column : this.columns) {
+ column.setToolTipText(tooltipText);
+ }
+ }
+
+ /**
+ * @return the root item, or null if there is no data
+ */
+ ColumnItem getRootItem() {
+ if (this.columns == null || this.columns.isEmpty()) {
+ return null;
+ }
+ return (ColumnItem) this.columns.get(0).getData();
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/columns/ColumnItem.java b/org.tizen.common.externals/src/org/mihalis/opal/columns/ColumnItem.java
new file mode 100644
index 000000000..52d63fa70
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/columns/ColumnItem.java
@@ -0,0 +1,416 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.columns;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.mihalis.opal.OpalItem;
+
+/**
+ * Instances of this object are items manipulated by the ColumnBrowser widget.
+ * ColumnItems are part of a tree structure .
+ *
+ * @see OpalItem
+ */
+public class ColumnItem extends OpalItem {
+
+ private final ColumnBrowserWidget widget;
+ private final ColumnItem parent;
+ private final List<ColumnItem> children;
+
+ /**
+ * Constructs a new instance of this class given its parent. The item is
+ * added to the end of the items maintained by its parent.
+ *
+ * @param widget the widget that will contain this item (can not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public ColumnItem(final ColumnBrowserWidget widget) {
+ if (widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ this.widget = widget;
+ this.parent = null;
+ this.children = new ArrayList<ColumnItem>();
+
+ if (widget.getRootItem() != null) {
+ widget.getRootItem().children.add(this);
+ }
+ widget.updateContent();
+ }
+
+ /**
+ * Constructs a new instance of this class given its parent. The item is
+ * added at a given position in the items'list maintained by its parent.
+ *
+ * @param widget the widget that will contain this item (can not be null)
+ * @param index the position
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public ColumnItem(final ColumnBrowserWidget widget, final int index) {
+
+ if (widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ this.widget = widget;
+ this.parent = null;
+ this.children = new ArrayList<ColumnItem>();
+ widget.getRootItem().children.add(index, this);
+ widget.updateContent();
+ }
+
+ /**
+ * Constructs a new instance of this class given its parent. The item is
+ * added to the end of the items maintained by its parent.
+ *
+ * @param widget the widget that will contain this item (can not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public ColumnItem(final ColumnItem parent) {
+
+ if (parent == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (parent.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ this.widget = parent.widget;
+ this.parent = parent;
+ this.children = new ArrayList<ColumnItem>();
+ parent.children.add(this);
+ parent.widget.updateContent();
+ }
+
+ /**
+ * Constructs a new instance of this class given its parent. The item is
+ * added at a given position in the items'list maintained by its parent.
+ *
+ * @param widget the widget that will contain this item (can not be null)
+ * @param index the position
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public ColumnItem(final ColumnItem parent, final int index) {
+ if (parent == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (parent.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ this.widget = parent.widget;
+ this.parent = parent;
+ this.children = new ArrayList<ColumnItem>();
+ parent.children.add(index, this);
+ parent.widget.updateContent();
+ }
+
+ /**
+ * Remove a given children of this object
+ *
+ * @param item the item to remove (can not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public void remove(final ColumnItem item) {
+ if (this.widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ this.children.remove(item);
+ this.widget.updateContent();
+ }
+
+ /**
+ * Remove a children in a given position of this object
+ *
+ * @param index position of the children in the items'list
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public void remove(final int index) {
+ if (this.widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ this.children.remove(index);
+ this.widget.updateContent();
+ }
+
+ /**
+ * Remove all children of this object
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public void removeAll() {
+ if (this.widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ this.children.clear();
+ this.widget.updateContent();
+ }
+
+ /**
+ * Returns an item located at a given position
+ *
+ * @param index position
+ * @return the item located at the index position
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public ColumnItem getItem(final int index) {
+ if (this.widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ return this.children.get(index);
+ }
+
+ /**
+ * @return the number of children
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public int getItemCount() {
+ if (this.widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ return this.children.size();
+ }
+
+ /**
+ * @return all children of this item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public ColumnItem[] getItems() {
+ if (this.widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ return this.children.toArray(new ColumnItem[this.children.size()]);
+ }
+
+ /**
+ * @return the widget that holds this item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public ColumnBrowserWidget getParent() {
+ if (this.widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ return this.widget;
+ }
+
+ /**
+ * @return the parent item, of <code>null</code> if this item is the root
+ * node
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public ColumnItem getParentItem() {
+ if (this.widget == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.widget.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ return this.parent;
+ }
+
+ /**
+ * Return the position of a given item in children's list
+ *
+ * @param item item to find
+ * @return the position of the children, or -1 if <code>item</code> is a not
+ * a children of this object
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * </ul>
+ */
+ public int indexOf(final ColumnItem item) {
+ return this.children.indexOf(item);
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.parent == null ? 0 : this.parent.hashCode());
+ result = prime * result + (this.widget == null ? 0 : this.widget.hashCode());
+ return result;
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final ColumnItem other = (ColumnItem) obj;
+ if (this.children == null) {
+ if (other.children != null) {
+ return false;
+ }
+ } else if (!this.children.equals(other.children)) {
+ return false;
+ }
+ if (this.parent == null) {
+ if (other.parent != null) {
+ return false;
+ }
+ } else if (!this.parent.equals(other.parent)) {
+ return false;
+ }
+ if (this.widget == null) {
+ if (other.widget != null) {
+ return false;
+ }
+ } else if (!this.widget.equals(other.widget)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/flatButton/FlatButton.java b/org.tizen.common.externals/src/org/mihalis/opal/flatButton/FlatButton.java
new file mode 100644
index 000000000..ede14ba2f
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/flatButton/FlatButton.java
@@ -0,0 +1,633 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.flatButton;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class represent a flat button.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dd>UP, DOWN, LEFT, RIGHT, CENTER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles LEFT, RIGHT, and CENTER may be specified.
+ * </p>
+ *
+ */
+public class FlatButton extends Canvas {
+ private Image image;
+ private String text;
+ private boolean selection;
+ private int alignment;
+ private final List<SelectionListener> listeners;
+ private boolean mouseIn;
+ private Color backgroundColor;
+ private Color selectedColor;
+ private Color selectedTextColor;
+ private Color mouseOverColor;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * <li>ERROR_INVALID_SUBCLASS - if this class is not an
+ * allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#DOWN
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ */
+ public FlatButton(final Composite parent, final int style) {
+ super(parent, style);
+ this.listeners = new ArrayList<SelectionListener>();
+ buildAlignmentFromStyle(style);
+ addListeners();
+ initializeDefaultColors();
+ }
+
+ private void buildAlignmentFromStyle(final int style) {
+ if ((style & SWT.LEFT) == SWT.LEFT) {
+ this.alignment = SWT.LEFT;
+ } else if ((style & SWT.RIGHT) == SWT.RIGHT) {
+ this.alignment = SWT.RIGHT;
+ } else {
+ this.alignment = SWT.CENTER;
+
+ }
+ }
+
+ private void addListeners() {
+ addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(final PaintEvent e) {
+ FlatButton.this.paintControl(e);
+ }
+ });
+
+ addListener(SWT.MouseEnter, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ FlatButton.this.mouseIn = true;
+ redraw();
+ }
+ });
+
+ addListener(SWT.MouseExit, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ FlatButton.this.mouseIn = false;
+ redraw();
+ }
+ });
+
+ addListener(SWT.MouseUp, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ boolean doIt = true;
+ FlatButton.this.selection = !FlatButton.this.selection;
+ for (final SelectionListener listener : FlatButton.this.listeners) {
+ final SelectionEvent sEvent = new SelectionEvent(event);
+ listener.widgetSelected(sEvent);
+ doIt = doIt && sEvent.doit;
+ }
+ if (!doIt) {
+ FlatButton.this.selection = !FlatButton.this.selection;
+ }
+ }
+
+ });
+ }
+
+ private void initializeDefaultColors() {
+ this.backgroundColor = getDisplay().getSystemColor(SWT.COLOR_WHITE);
+ this.selectedColor = new Color(getDisplay(), 0, 112, 192);
+ this.selectedTextColor = getDisplay().getSystemColor(SWT.COLOR_WHITE);
+ this.mouseOverColor = new Color(getDisplay(), 235, 234, 226);
+
+ SWTGraphicUtil.dispose(this, this.selectedColor);
+ SWTGraphicUtil.dispose(this, this.mouseOverColor);
+ SWTGraphicUtil.dispose(this, this.image);
+ }
+
+ private void paintControl(final PaintEvent e) {
+ final GC gc = e.gc;
+ drawBackground(gc);
+ if (this.image != null) {
+ drawImage(gc);
+ }
+ if (this.text != null) {
+ drawText(gc);
+ }
+ }
+
+ private void drawBackground(final GC gc) {
+ Color color;
+ if (this.selection) {
+ color = this.selectedColor;
+ } else if (this.mouseIn) {
+ color = this.mouseOverColor;
+ } else {
+ color = this.backgroundColor;
+ }
+ gc.setBackground(color);
+ gc.fillRectangle(getClientArea());
+
+ }
+
+ private void drawImage(final GC gc) {
+ final Rectangle rect = getClientArea();
+ final Point imageSize = new Point(this.image.getBounds().width, this.image.getBounds().height);
+
+ int x;
+ if (this.alignment == SWT.LEFT) {
+ x = 5;
+ } else if (this.alignment == SWT.RIGHT) {
+ x = rect.width - imageSize.x - 5;
+ } else {
+ x = (rect.width - imageSize.x) / 2;
+ }
+ gc.drawImage(this.image, x, 5);
+ }
+
+ private void drawText(final GC gc) {
+ final Rectangle rect = getClientArea();
+
+ if (this.selection) {
+ gc.setForeground(this.selectedTextColor);
+ } else {
+ gc.setForeground(getForeground());
+ }
+
+ gc.setFont(getFont());
+ final Point textSize = gc.stringExtent(this.text);
+ int x, y;
+
+ if (this.alignment == SWT.LEFT) {
+ x = 5;
+ } else if (this.alignment == SWT.RIGHT) {
+ x = rect.width - textSize.x - 5;
+ } else {
+ x = (rect.width - textSize.x) / 2;
+ }
+ if (this.image == null) {
+ y = 5;
+ } else {
+ y = 10 + this.image.getBounds().height;
+ }
+ gc.drawString(this.text, x, y, true);
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified
+ * when the control is selected by the user, by sending it one of the
+ * messages defined in the <code>SelectionListener</code> interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the control is selected by the
+ * user. <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ * <p>
+ * When the <code>SWT.RADIO</code> style bit is set, the
+ * <code>widgetSelected</code> method is also called when the receiver loses
+ * selection because another item in the same radio group was selected by
+ * the user. During <code>widgetSelected</code> the application can use
+ * <code>getSelection()</code> to determine the current selected state of
+ * the receiver.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.listeners.add(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
+ */
+ @Override
+ public Point computeSize(final int wHint, final int hHint, final boolean changed) {
+ int width = 10, height = 15;
+ if (this.image != null) {
+ final Rectangle bounds = this.image.getBounds();
+ width += bounds.width;
+ height += bounds.height;
+ }
+
+ if (this.text != null) {
+ final GC gc = new GC(this);
+ final Point extent = gc.stringExtent(this.text);
+ gc.dispose();
+ width = Math.max(width, extent.x + 10);
+ height = height + extent.y;
+ }
+
+ return new Point(Math.max(width, wHint), Math.max(height, hHint));
+ }
+
+ /**
+ * Returns a value which describes the position of the text in the receiver.
+ * The value will be one of <code>LEFT</code>, <code>RIGHT</code> or
+ * <code>CENTER</code>.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getAlignment() {
+ checkWidget();
+ return this.alignment;
+ }
+
+ /**
+ * Returns a value which describes the default background color
+ *
+ * @return the default background color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getBackgroundColor() {
+ checkWidget();
+ return this.backgroundColor;
+ }
+
+ /**
+ * Returns the receiver's image if it has one, or null if it does not.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Image getImage() {
+ checkWidget();
+ return this.image;
+ }
+
+ /**
+ * Returns a value which describes the color when the mouse is over the
+ * button
+ *
+ * @return the color when the mouse is over the button
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getMouseOverColor() {
+ checkWidget();
+ return this.mouseOverColor;
+ }
+
+ /**
+ * Returns a value which describes the color when the button is selected
+ *
+ * @return the color when the button is selected
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getSelectedColor() {
+ checkWidget();
+ return this.selectedColor;
+ }
+
+ /**
+ * Returns a value which describes the color of the text when the button is
+ * selected
+ *
+ * @return the color of the text when the button is selected
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+
+ public Color getSelectedTextColor() {
+ return this.selectedTextColor;
+ }
+
+ /**
+ * Returns <code>true</code> if the receiver is selected, and false
+ * otherwise.
+ * <p>
+ *
+ * @return the selection state
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li> <li>ERROR_THREAD_INVALID_ACCESS - if not
+ * called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public boolean getSelection() {
+ checkWidget();
+ return this.selection;
+ }
+
+ /**
+ * Returns the receiver's text.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public String getText() {
+ checkWidget();
+ return this.text;
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be
+ * notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.listeners.remove(listener);
+ }
+
+ /**
+ * Controls how text, images and arrows will be displayed in the receiver.
+ * The argument should be one of <code>LEFT</code>, <code>RIGHT</code> or
+ * <code>CENTER</code>.
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setAlignment(final int alignment) {
+ checkWidget();
+ if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) {
+ return;
+ }
+ this.alignment = alignment;
+ redraw();
+ }
+
+ /**
+ * Sets the receiver's background color to the color specified by the
+ * argument.
+ *
+ * @param color the new color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setBackgroundColor(final Color backgroundColor) {
+ checkWidget();
+ this.backgroundColor = backgroundColor;
+ }
+
+ /**
+ * Sets the receiver's image to the argument, which may be <code>null</code>
+ * indicating that no image should be displayed.
+ * <p>
+ * Note that a Button can display an image and text simultaneously on
+ * Windows (starting with XP), GTK+ and OSX. On other platforms, a Button
+ * that has an image and text set into it will display the image or text
+ * that was set most recently.
+ * </p>
+ *
+ * @param image the image to display on the receiver (may be
+ * <code>null</code>)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setImage(final Image image) {
+ checkWidget();
+ this.image = image;
+ redraw();
+ }
+
+ /**
+ * Sets the receiver's color when the mouse if over the button.
+ *
+ * @param color the new color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setMouseOverColor(final Color mouseOverColor) {
+ checkWidget();
+ this.mouseOverColor = mouseOverColor;
+ }
+
+ /**
+ * Sets the receiver's color when the button is selected.
+ *
+ * @param color the new color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelectedColor(final Color selectedColor) {
+ checkWidget();
+ this.selectedColor = selectedColor;
+ }
+
+ /**
+ * Sets the receiver's text color when the button is selected.
+ *
+ * @param color the new color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelectedTextColor(final Color selectedTextColor) {
+ this.selectedTextColor = selectedTextColor;
+ }
+
+ /**
+ * Sets the selection state of the receiver.
+ *
+ * @param selected the new selection state
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelection(final boolean selected) {
+ checkWidget();
+ this.selection = selected;
+ redraw();
+ }
+
+ /**
+ * Sets the receiver's text.
+ *
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setText(final String text) {
+ checkWidget();
+ this.text = text;
+ redraw();
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/gradientComposite/GradientComposite.java b/org.tizen.common.externals/src/org/mihalis/opal/gradientComposite/GradientComposite.java
new file mode 100644
index 000000000..80e5c6736
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/gradientComposite/GradientComposite.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.gradientComposite;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are controls which background's texture is a gradient
+ * composite
+ */
+public class GradientComposite extends Composite {
+ private Image oldImage;
+ private Color gradientEnd;
+ private Color gradientStart;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance
+ * (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ * @see Composite#Composite(Composite, int)
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_FOCUS
+ * @see SWT#NO_MERGE_PAINTS
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_RADIO_GROUP
+ * @see SWT#EMBEDDED
+ * @see SWT#DOUBLE_BUFFERED
+ * @see Widget#getStyle
+ */
+ public GradientComposite(final Composite parent, final int style) {
+ super(parent, style);
+ this.addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ GradientComposite.this.redrawComposite();
+ }
+ });
+
+ parent.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(GradientComposite.this.oldImage);
+ SWTGraphicUtil.dispose(GradientComposite.this.gradientEnd);
+ SWTGraphicUtil.dispose(GradientComposite.this.gradientStart);
+ }
+
+ });
+
+ this.gradientEnd = new Color(this.getDisplay(), 110, 110, 110);
+ this.gradientStart = new Color(this.getDisplay(), 0, 0, 0);
+
+ }
+
+ /**
+ * Redraws the composite
+ */
+ private void redrawComposite() {
+ final Display display = this.getDisplay();
+ final Rectangle rect = this.getClientArea();
+ final Image newImage = new Image(display, Math.max(1, rect.width), Math.max(1, rect.height));
+
+ final GC gc = new GC(newImage);
+ gc.setForeground(this.gradientStart);
+ gc.setBackground(this.gradientEnd);
+
+ gc.fillGradientRectangle(rect.x, rect.y, rect.width, rect.height / 2, true);
+
+ gc.setForeground(this.gradientEnd);
+ gc.setBackground(this.gradientStart);
+
+ gc.fillGradientRectangle(rect.x, rect.height / 2, rect.width, rect.height / 2, true);
+ gc.dispose();
+
+ this.setBackgroundImage(newImage);
+ if (this.oldImage != null) {
+ this.oldImage.dispose();
+ }
+ this.oldImage = newImage;
+
+ }
+
+ // ------------------------------------ Getters and Setters
+ /**
+ * @return the gradientEnd color
+ */
+ public Color getGradientEnd() {
+ return this.gradientEnd;
+ }
+
+ /**
+ * @param gradientEnd the gradientEnd color to set
+ */
+ public void setGradientEnd(final Color gradientEnd) {
+ SWTGraphicUtil.dispose(this.gradientEnd);
+ this.gradientEnd = gradientEnd;
+ }
+
+ /**
+ * @return the gradientStart color
+ */
+ public Color getGradientStart() {
+ return this.gradientStart;
+ }
+
+ /**
+ * @param gradientStart the gradientStart color to set
+ */
+ public void setGradientStart(final Color gradientStart) {
+ SWTGraphicUtil.dispose(this.gradientStart);
+ this.gradientStart = gradientStart;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/header/Header.java b/org.tizen.common.externals/src/org/mihalis/opal/header/Header.java
new file mode 100644
index 000000000..6cdd42366
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/header/Header.java
@@ -0,0 +1,529 @@
+package org.mihalis.opal.header;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class provide a header, which is composed of a text, a
+ * description and an image.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ */
+public class Header extends Composite {
+
+ private Image image;
+ private String title;
+ private String description;
+ private Font titleFont;
+ private Color titleColor;
+
+ private Image oldImage;
+ private Color gradientEnd;
+ private Color gradientStart;
+ private Color separatorColor;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ */
+ public Header(final Composite parent, final int style) {
+ super(parent, style);
+
+ final FontData[] fontData = getFont().getFontData();
+ if (fontData != null && fontData.length > 0) {
+ final FontData fd = fontData[0];
+ fd.setStyle(SWT.BOLD);
+ fd.setHeight(fd.getHeight() + 2);
+ this.titleFont = new Font(getDisplay(), fd);
+ } else {
+ this.titleFont = null;
+ }
+
+ this.titleColor = new Color(getDisplay(), 0, 88, 150);
+
+ this.gradientEnd = new Color(this.getDisplay(), 239, 239, 239);
+ this.gradientStart = new Color(this.getDisplay(), 255, 255, 255);
+ this.separatorColor = new Color(this.getDisplay(), 229, 229, 229);
+
+ this.addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ redrawComposite();
+ }
+ });
+
+ this.addListener(SWT.Dispose, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ SWTGraphicUtil.dispose(Header.this.titleColor);
+ SWTGraphicUtil.dispose(Header.this.titleFont);
+ SWTGraphicUtil.dispose(Header.this.oldImage);
+ SWTGraphicUtil.dispose(Header.this.gradientEnd);
+ SWTGraphicUtil.dispose(Header.this.gradientStart);
+ SWTGraphicUtil.dispose(Header.this.separatorColor);
+ }
+ });
+ setBackgroundMode(SWT.INHERIT_FORCE);
+ }
+
+ /**
+ * Redraw the composite
+ */
+ private void redrawComposite() {
+ // Dispose previous content
+ for (final Control c : this.getChildren()) {
+ c.dispose();
+ }
+
+ int numberOfColumns = 1;
+ if (this.image != null) {
+ numberOfColumns++;
+ }
+
+ super.setLayout(new GridLayout(numberOfColumns, false));
+ createContent();
+ drawBackground();
+ }
+
+ /**
+ * Create the content (title, image, description)
+ */
+ private void createContent() {
+ if (this.title != null) {
+ createTitle();
+ }
+
+ if (this.image != null) {
+ createImage();
+ }
+
+ if (this.description != null) {
+ createDescription();
+ }
+ }
+
+ /**
+ * Create the title
+ */
+ private void createTitle() {
+ final Label labelTitle = new Label(this, SWT.NONE);
+ labelTitle.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false));
+ labelTitle.setFont(this.titleFont);
+ labelTitle.setForeground(this.titleColor);
+ labelTitle.setText(this.title);
+ }
+
+ /**
+ * Create the image
+ */
+ private void createImage() {
+
+ int numberOfLines = 1;
+
+ if (this.title != null && this.description != null) {
+ numberOfLines++;
+ }
+ final Label labelImage = new Label(this, SWT.NONE);
+ labelImage.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, true, 1, numberOfLines));
+ labelImage.setImage(this.image);
+ }
+
+ /**
+ * Create the description
+ */
+ private void createDescription() {
+ final StyledText labelDescription = new StyledText(this, SWT.WRAP | SWT.READ_ONLY);
+ labelDescription.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
+ labelDescription.setEnabled(false);
+ labelDescription.setFont(getFont());
+ labelDescription.setForeground(getForeground());
+ labelDescription.setText("<html><body>" + this.description + "</body></html>");
+ SWTGraphicUtil.applyHTMLFormating(labelDescription);
+ }
+
+ /**
+ * Draw the background (a gradient+a separator)
+ */
+ private void drawBackground() {
+ final Display display = this.getDisplay();
+ final Rectangle rect = this.getClientArea();
+ final Image newImage = new Image(display, Math.max(1, rect.width), Math.max(1, rect.height));
+
+ final GC gc = new GC(newImage);
+ gc.setForeground(this.gradientStart);
+ gc.setBackground(this.gradientEnd);
+
+ gc.fillGradientRectangle(rect.x, rect.y, rect.width, rect.height, false);
+
+ gc.setForeground(this.separatorColor);
+ gc.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1);
+
+ gc.dispose();
+
+ this.setBackgroundImage(newImage);
+ if (this.oldImage != null) {
+ this.oldImage.dispose();
+ }
+ this.oldImage = newImage;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#setLayout(org.eclipse.swt.widgets.Layout)
+ */
+ @Override
+ public void setLayout(final Layout layout) {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ // ------------------------------------ Getters and Setters
+
+ /**
+ * Returns the receiver's description if it has one, or null if it does not.
+ *
+ * @return the receiver's description if it has one, or null if it does not
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public String getDescription() {
+ checkWidget();
+ return this.description;
+ }
+
+ /**
+ * Returns the receiver's gradient end color.
+ *
+ * @return the receiver's gradient end color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getGradientEnd() {
+ checkWidget();
+ return this.gradientEnd;
+ }
+
+ /**
+ * Returns the receiver's gradient start color.
+ *
+ * @return the receiver's gradient start color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getGradientStart() {
+ checkWidget();
+ return this.gradientStart;
+ }
+
+ /**
+ * Returns the receiver's image if it has one, or null if it does not.
+ *
+ * @return the receiver's image if it has one, or null if it does not
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Image getImage() {
+ checkWidget();
+ return this.image;
+ }
+
+ /**
+ * Returns the receiver's separator color.
+ *
+ * @return the receiver's separator color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getSeparatorColor() {
+ checkWidget();
+ return this.separatorColor;
+ }
+
+ /**
+ * Returns the receiver's title if it has one, or null if it does not.
+ *
+ * @return the receiver's title if it has one, or null if it does not
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public String getTitle() {
+ checkWidget();
+ return this.title;
+ }
+
+ /**
+ * Returns the title's color.
+ *
+ * @return the title's color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getTitleColor() {
+ checkWidget();
+ return this.titleColor;
+ }
+
+ /**
+ * Returns the title's font.
+ *
+ * @return the title's font.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Font getTitleFont() {
+ checkWidget();
+ return this.titleFont;
+ }
+
+ /**
+ * Sets the receiver's description to the argument, which may be null
+ * indicating that no description should be displayed.
+ *
+ * @param description the description of the header (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setDescription(final String description) {
+ checkWidget();
+ this.description = description;
+ }
+
+ /**
+ * Sets the receiver's gradient end color.
+ *
+ * @param gradientEnd the receiver's gradient end color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setGradientEnd(final Color gradientEnd) {
+ checkWidget();
+ this.gradientEnd = gradientEnd;
+ }
+
+ /**
+ * Sets the receiver's gradient start color.
+ *
+ * @param gradientStart the receiver's gradient start color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setGradientStart(final Color gradientStart) {
+ checkWidget();
+ this.gradientStart = gradientStart;
+ }
+
+ /**
+ * Sets the receiver's image to the argument, which may be null indicating
+ * that no image should be displayed.
+ *
+ * @param image the image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setImage(final Image image) {
+ checkWidget();
+ this.image = image;
+ }
+
+ /**
+ * Sets the receiver's separator color.
+ *
+ * @param separatorColor the receiver's separator color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSeparatorColor(final Color separatorColor) {
+ this.separatorColor = separatorColor;
+ }
+
+ /**
+ * Sets the receiver's title to the argument, which may be null indicating
+ * that no title should be displayed.
+ *
+ * @param title the title
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setTitle(final String title) {
+ checkWidget();
+ this.title = title;
+ }
+
+ /**
+ * Sets the receiver's title color.
+ *
+ * @param headerColor the receiver's title color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setTitleColor(final Color headerColor) {
+ checkWidget();
+ this.titleColor = headerColor;
+ }
+
+ /**
+ * Sets the receiver's title font.
+ *
+ * @param headerFont the receiver's title font
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setTitleFont(final Font headerFont) {
+ checkWidget();
+ this.titleFont = headerFont;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/heapManager/HeapManager.java b/org.tizen.common.externals/src/org/mihalis/opal/heapManager/HeapManager.java
new file mode 100644
index 000000000..a702b6fab
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/heapManager/HeapManager.java
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.heapManager;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Widget;
+import org.mihalis.opal.utils.ResourceManager;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are controls that display the memory used, the whole
+ * memory, and contains a button to perform a GC
+ */
+public class HeapManager extends Composite {
+ private Canvas bar;
+ private Button button;
+ private int heapMaxSize;
+ private int heapSize;
+ private Color barBorderColor;
+ private Color barInnerColor;
+ private Color barTextColor;
+ private Color barGradientColorTopStart;
+ private Color barGradientColorTopEnd;
+ private Color barGradientColorMiddleStart;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance
+ * (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ * @see Composite#Composite(Composite, int)
+ * @see Widget#getStyle
+ */
+ public HeapManager(final Composite parent, final int style) {
+ super(parent, style);
+ final GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
+ setLayout(gridLayout);
+
+ createBar();
+ createButton();
+ updateContent();
+ createDefaultColors();
+
+ addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(HeapManager.this.barBorderColor);
+ SWTGraphicUtil.dispose(HeapManager.this.barInnerColor);
+ SWTGraphicUtil.dispose(HeapManager.this.barGradientColorTopStart);
+ SWTGraphicUtil.dispose(HeapManager.this.barGradientColorTopEnd);
+ SWTGraphicUtil.dispose(HeapManager.this.barGradientColorMiddleStart);
+ SWTGraphicUtil.dispose(HeapManager.this.barTextColor);
+ }
+ });
+
+ }
+
+ /**
+ * Creates the bar that displays the memory
+ */
+ private void createBar() {
+ this.bar = new Canvas(this, SWT.NONE);
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, false);
+ gd.minimumWidth = 100;
+ gd.heightHint = 30;
+ this.bar.setLayoutData(gd);
+ this.heapMaxSize = (int) (Runtime.getRuntime().maxMemory() / (1024 * 1024));
+ this.bar.addPaintListener(new PaintListener() {
+
+ @Override
+ public void paintControl(final PaintEvent e) {
+ drawBar(e);
+ }
+ });
+ }
+
+ /**
+ * Draw the bar
+ *
+ * @param e {@link PaintEvent}
+ */
+ private void drawBar(final PaintEvent e) {
+ final GC gc = e.gc;
+ final Rectangle clientArea = this.bar.getClientArea();
+
+ gc.setForeground(this.barBorderColor);
+ gc.setBackground(this.barInnerColor);
+ gc.fillRectangle(clientArea);
+ gc.drawRectangle(clientArea.x, clientArea.y, clientArea.width - 1, clientArea.height - 1);
+
+ final float width = (clientArea.width - 2f) * this.heapSize / this.heapMaxSize;
+
+ gc.setForeground(this.barGradientColorTopStart);
+ gc.setBackground(this.barGradientColorTopEnd);
+ gc.fillGradientRectangle(clientArea.x + 1, clientArea.y + 1, (int) width, clientArea.height / 2, true);
+
+ gc.setForeground(this.barGradientColorMiddleStart);
+ gc.setBackground(this.barBorderColor);
+ gc.fillGradientRectangle(clientArea.x + 1, clientArea.height / 2, (int) width, clientArea.height / 2, true);
+
+ final String message = this.heapSize + " " + ResourceManager.getLabel(ResourceManager.MEGABYTES) + "/" + //
+ this.heapMaxSize + " " + ResourceManager.getLabel(ResourceManager.MEGABYTES);
+ final Point size = gc.stringExtent(message);
+
+ gc.setForeground(this.barTextColor);
+ gc.setFont(getFont());
+ gc.drawText(message, (clientArea.width - size.x) / 2, (clientArea.height - size.y) / 2, true);
+
+ gc.dispose();
+
+ }
+
+ /**
+ * Create the button used to perform GC
+ */
+ private void createButton() {
+ this.button = new Button(this, SWT.PUSH);
+ this.button.setImage(SWTGraphicUtil.createImage("images/trash.png"));
+ this.button.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false));
+ this.button.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ System.gc();
+ }
+
+ });
+ this.button.setToolTipText(ResourceManager.getLabel(ResourceManager.PERFORM_GC));
+ this.button.pack();
+ }
+
+ /**
+ * Update the content of the bar
+ */
+ private void updateContent() {
+ getDisplay().timerExec(500, new Runnable() {
+
+ @Override
+ public void run() {
+ HeapManager.this.heapSize = (int) (Runtime.getRuntime().totalMemory() / (1024 * 1024));
+ if (!isDisposed()) {
+ HeapManager.this.bar.redraw();
+ if (!getDisplay().isDisposed()) {
+ getDisplay().timerExec(500, this);
+ }
+ }
+ }
+ });
+
+ }
+
+ /**
+ * Creates the default colors
+ */
+ private void createDefaultColors() {
+ this.barTextColor = new Color(getDisplay(), 57, 98, 149);
+ this.barInnerColor = new Color(getDisplay(), 219, 230, 243);
+ this.barBorderColor = new Color(getDisplay(), 101, 148, 207);
+ this.barGradientColorTopStart = new Color(getDisplay(), 175, 202, 237);
+ this.barGradientColorTopEnd = new Color(getDisplay(), 136, 177, 229);
+ this.barGradientColorMiddleStart = new Color(getDisplay(), 112, 161, 223);
+
+ }
+
+ /**
+ * @return the barBorderColor
+ */
+ public Color getBarBorderColor() {
+ return this.barBorderColor;
+ }
+
+ /**
+ * @param barBorderColor the barBorderColor to set
+ */
+ public void setBarBorderColor(final Color barBorderColor) {
+ this.barBorderColor = barBorderColor;
+ }
+
+ /**
+ * @return the barInnerColor
+ */
+ public Color getBarInnerColor() {
+ return this.barInnerColor;
+ }
+
+ /**
+ * @param barInnerColor the barInnerColor to set
+ */
+ public void setBarInnerColor(final Color barInnerColor) {
+ this.barInnerColor = barInnerColor;
+ }
+
+ /**
+ * @return the barTextColor
+ */
+ public Color getBarTextColor() {
+ return this.barTextColor;
+ }
+
+ /**
+ * @param barTextColor the barTextColor to set
+ */
+ public void setBarTextColor(final Color barTextColor) {
+ this.barTextColor = barTextColor;
+ }
+
+ /**
+ * @return the barGradientColorTopStart
+ */
+ public Color getBarGradientColorTopStart() {
+ return this.barGradientColorTopStart;
+ }
+
+ /**
+ * @param barGradientColorTopStart the barGradientColorTopStart to set
+ */
+ public void setBarGradientColorTopStart(final Color barGradientColorTopStart) {
+ this.barGradientColorTopStart = barGradientColorTopStart;
+ }
+
+ /**
+ * @return the barGradientColorTopEnd
+ */
+ public Color getBarGradientColorTopEnd() {
+ return this.barGradientColorTopEnd;
+ }
+
+ /**
+ * @param barGradientColorTopEnd the barGradientColorTopEnd to set
+ */
+ public void setBarGradientColorTopEnd(final Color barGradientColorTopEnd) {
+ this.barGradientColorTopEnd = barGradientColorTopEnd;
+ }
+
+ /**
+ * @return the barGradientColorMiddleStart
+ */
+ public Color getBarGradientColorMiddleStart() {
+ return this.barGradientColorMiddleStart;
+ }
+
+ /**
+ * @param barGradientColorMiddleStart the barGradientColorMiddleStart to set
+ */
+ public void setBarGradientColorMiddleStart(final Color barGradientColorMiddleStart) {
+ this.barGradientColorMiddleStart = barGradientColorMiddleStart;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/horizontalSpinner/HorizontalSpinner.java b/org.tizen.common.externals/src/org/mihalis/opal/horizontalSpinner/HorizontalSpinner.java
new file mode 100644
index 000000000..5362a36f0
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/horizontalSpinner/HorizontalSpinner.java
@@ -0,0 +1,947 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Implementation
+ *******************************************************************************/
+package org.mihalis.opal.horizontalSpinner;
+
+import java.text.DecimalFormatSymbols;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Text;
+import org.mihalis.opal.utils.StringUtil;
+
+/**
+ * Instances of this class are selectable user interface objects that allow the user to enter and modify numeric values.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>READ_ONLY, FLAP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, Modify</dd>
+ * </dl>
+ * </p>
+ */
+public class HorizontalSpinner extends Composite {
+ private final List<ModifyListener> modifyListeners = new ArrayList<ModifyListener>();
+ private final List<SelectionListener> selectionListeners = new ArrayList<SelectionListener>();
+
+ private Button leftButton;
+ private Button rightButton;
+ private Text text;
+ private int digits = 0;
+ private int increment = 1;
+ private int maximum = 0;
+ private int minimum = 255;
+ private int pageIncrement = 10;
+ private int storedValue = 0;
+
+ private final char decimalFormatSeparator;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class <code>SWT</code> which is applicable to instances of this class, or must be built by <em>bitwise OR</em>'ing together (that is, using the <code>int</code> "|" operator) two or more of those <code>SWT</code> style constants. The class description lists the style constants that are applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#READ_ONLY
+ * @see SWT#FLAT
+ */
+ public HorizontalSpinner(final Composite parent, final int style) {
+ super(parent, style);
+
+ final GridLayout gd = new GridLayout(3, false);
+ gd.horizontalSpacing = gd.verticalSpacing = 0;
+ gd.marginWidth = gd.marginHeight = 0;
+ this.setLayout(gd);
+
+ this.createContent(style);
+ this.addTextListeners();
+ this.addButtonsListener();
+ this.addModifyListeners();
+
+ this.decimalFormatSeparator = new DecimalFormatSymbols().getDecimalSeparator();
+ }
+
+ /**
+ * Create the content of the widget
+ *
+ * @param style style of the widget
+ */
+ private void createContent(final int style) {
+ final boolean readOnly = (style & SWT.READ_ONLY) == SWT.READ_ONLY;
+ final boolean flat = (style & SWT.FLAT) == SWT.FLAT;
+
+ final int buttonStyle = SWT.ARROW | (flat ? SWT.FLAT : SWT.NONE);
+ this.leftButton = new Button(this, buttonStyle | SWT.LEFT);
+ this.leftButton.setFont(this.getFont());
+ this.leftButton.setBackground(this.getBackground());
+ this.leftButton.setCursor(this.getCursor());
+ this.leftButton.setEnabled(this.getEnabled());
+ this.leftButton.setFont(this.getFont());
+ this.leftButton.setForeground(this.getForeground());
+ this.leftButton.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false));
+
+ this.text = new Text(this, readOnly ? SWT.READ_ONLY : SWT.NONE);
+ final GridData gd = new GridData(GridData.FILL, GridData.CENTER, true, false);
+ gd.minimumWidth = 40;
+ this.text.setLayoutData(gd);
+
+ this.rightButton = new Button(this, buttonStyle | SWT.RIGHT);
+ this.rightButton.setFont(this.getFont());
+ this.rightButton.setBackground(this.getBackground());
+ this.rightButton.setCursor(this.getCursor());
+ this.rightButton.setEnabled(this.getEnabled());
+ this.rightButton.setFont(this.getFont());
+ this.rightButton.setForeground(this.getForeground());
+ this.rightButton.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false));
+
+ }
+
+ /**
+ * Add the text listeners
+ */
+ private void addTextListeners() {
+ this.text.addVerifyListener(new VerifyListener() {
+
+ @Override
+ public void verifyText(final VerifyEvent e) {
+ if (e.character != 0 && !Character.isDigit(e.character) && e.keyCode != SWT.BS && e.keyCode != SWT.DEL) {
+ e.doit = false;
+ return;
+ }
+
+ e.doit = HorizontalSpinner.this.verifyEntryAndStoreValue(e.text, e.keyCode);
+
+ }
+ });
+
+ this.text.addKeyListener(new KeyAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
+ */
+ @Override
+ public void keyReleased(final KeyEvent e) {
+ if (e.keyCode == SWT.ARROW_UP) {
+ HorizontalSpinner.this.increaseValue(HorizontalSpinner.this.increment);
+ }
+ if (e.keyCode == SWT.ARROW_DOWN) {
+ HorizontalSpinner.this.decreaseValue(HorizontalSpinner.this.increment);
+ }
+ if (e.keyCode == SWT.PAGE_UP) {
+ HorizontalSpinner.this.increaseValue(HorizontalSpinner.this.pageIncrement);
+ }
+ if (e.keyCode == SWT.PAGE_DOWN) {
+ HorizontalSpinner.this.decreaseValue(HorizontalSpinner.this.pageIncrement);
+ }
+ }
+
+ });
+
+ this.text.addFocusListener(new org.eclipse.swt.events.FocusAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.FocusAdapter#focusLost(org.eclipse.swt.events.FocusEvent)
+ */
+ @Override
+ public void focusLost(final org.eclipse.swt.events.FocusEvent e) {
+ if (HorizontalSpinner.this.text.getText().trim().equals("")) {
+ HorizontalSpinner.this.setSelection(HorizontalSpinner.this.storedValue);
+ }
+ }
+
+ });
+
+ }
+
+ /**
+ * Verify the entry and store the value in the field storedValue
+ *
+ * @param entry entry to check
+ * @param keyCode code of the typed key
+ * @return <code>true</code> if the entry if correct, <code>false</code> otherwise
+ */
+ private boolean verifyEntryAndStoreValue(final String entry, final int keyCode) {
+ final String work;
+ if (keyCode == SWT.DEL) {
+ work = StringUtil.removeCharAt(this.text.getText(), this.text.getCaretPosition());
+ } else if (keyCode == SWT.BS && this.text.getCaretPosition() == 0) {
+ work = StringUtil.removeCharAt(this.text.getText(), this.text.getCaretPosition() - 1);
+ } else if (keyCode == 0) {
+ work = entry;
+ } else {
+ work = StringUtil.insertString(this.text.getText(), entry, this.text.getCaretPosition());
+ }
+
+ try {
+ final double d = Double.parseDouble(work.replace(this.decimalFormatSeparator, '.'));
+ this.storedValue = (int) (d * Math.pow(10, this.getDigits()));
+ } catch (final NumberFormatException nfe) {
+ return false;
+ }
+
+ for (final SelectionListener s : HorizontalSpinner.this.selectionListeners) {
+ s.widgetSelected(null);
+ }
+
+ return true;
+ }
+
+ /**
+ * Add the listener to the buttons
+ */
+ private void addButtonsListener() {
+ this.leftButton.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ HorizontalSpinner.this.decreaseValue(HorizontalSpinner.this.increment);
+ }
+ });
+
+ this.rightButton.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ HorizontalSpinner.this.increaseValue(HorizontalSpinner.this.increment);
+ }
+ });
+
+ }
+
+ /**
+ * Increase the value stored in this snippet
+ *
+ * @param value value to increase
+ */
+ private void increaseValue(final int value) {
+ this.setSelection(this.getSelection() + value);
+
+ }
+
+ /**
+ * Decrease the value stored in this snippet
+ *
+ * @param value value to decrease
+ */
+ private void decreaseValue(final int value) {
+ this.setSelection(this.getSelection() - value);
+ }
+
+ /**
+ * Add the modify listeners
+ */
+ private void addModifyListeners() {
+ this.text.addModifyListener(new ModifyListener() {
+
+ @Override
+ public void modifyText(final ModifyEvent e) {
+ for (final ModifyListener m : HorizontalSpinner.this.modifyListeners) {
+ m.modifyText(e);
+ }
+
+ }
+ });
+
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified when the receiver's text is modified, by sending it one of the messages defined in the <code>ModifyListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see ModifyListener
+ * @see #removeModifyListener
+ * @see org.eclipse.swt.widgets.Spinner#addModifyListener(org.eclipse.swt.events.ModifyListener)
+ */
+
+ public void addModifyListener(final ModifyListener listener) {
+ this.checkWidget();
+ this.modifyListeners.add(listener);
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified when the control is selected by the user, by sending it one of the messages defined in the <code>SelectionListener</code> interface.
+ * <p>
+ * <code>widgetSelected</code> is not called for texts. <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ this.checkWidget();
+ this.selectionListeners.add(listener);
+ }
+
+ /**
+ * Copies the selected text.
+ * <p>
+ * The current selection is copied to the clipboard.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void copy() {
+ this.checkWidget();
+ this.text.copy();
+ }
+
+ /**
+ * Cuts the selected text.
+ * <p>
+ * The current selection is first copied to the clipboard and then deleted from the widget.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void cut() {
+ this.checkWidget();
+ this.text.cut();
+ }
+
+ /**
+ * Returns the number of decimal places used by the receiver.
+ *
+ * @return the digits
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public int getDigits() {
+ this.checkWidget();
+ return this.digits;
+ }
+
+ /**
+ * Returns the amount that the receiver's value will be modified by when the up/down arrows are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public int getIncrement() {
+ this.checkWidget();
+ return this.increment;
+ }
+
+ /**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public int getMaximum() {
+ this.checkWidget();
+ return this.maximum;
+ }
+
+ /**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public int getMinimum() {
+ this.checkWidget();
+ return this.minimum;
+ }
+
+ /**
+ * Returns the amount that the receiver's position will be modified by when the page up/down keys are pressed.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public int getPageIncrement() {
+ this.checkWidget();
+ return this.pageIncrement;
+ }
+
+ /**
+ * Returns the <em>selection</em>, which is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public int getSelection() {
+ this.checkWidget();
+ return this.storedValue;
+
+ }
+
+ /**
+ * Returns a string containing a copy of the contents of the receiver's text field, or an empty string if there are no contents.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ */
+ public String getText() {
+ this.checkWidget();
+ return this.text.getText();
+ }
+
+ /**
+ * Returns the maximum number of characters that the receiver's text field is capable of holding. If this has not been changed by <code>setTextLimit()</code>, it will be the constant <code>Spinner.LIMIT</code>.
+ *
+ * @return the text limit
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #LIMIT
+ */
+ public int getTextLimit() {
+ this.checkWidget();
+ return this.text.getTextLimit();
+ }
+
+ /**
+ * Pastes text from clipboard.
+ * <p>
+ * The selected text is deleted from the widget and new text inserted from the clipboard.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void paste() {
+ this.checkWidget();
+ this.text.paste();
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see ModifyListener
+ * @see #addModifyListener
+ */
+ public void removeModifyListener(final ModifyListener listener) {
+ this.checkWidget();
+ this.modifyListeners.remove(listener);
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ this.checkWidget();
+ this.selectionListeners.remove(listener);
+ }
+
+ /**
+ * Sets the number of decimal places used by the receiver.
+ * <p>
+ * The digit setting is used to allow for floating point values in the receiver. For example, to set the selection to a floating point value of 1.37 call setDigits() with a value of 2 and setSelection() with a value of 137. Similarly, if getDigits() has a value of 2 and getSelection() returns 137 this should be interpreted as 1.37. This applies to all numeric APIs.
+ * </p>
+ *
+ * @param value the new digits (must be greater than or equal to zero)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the value is less than zero</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void setDigits(final int value) {
+ this.checkWidget();
+ this.digits = value;
+ this.convertSelection();
+ }
+
+ /**
+ * Sets the amount that the receiver's value will be modified by when the up/down arrows are pressed to the argument, which must be at least one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void setIncrement(final int value) {
+ this.checkWidget();
+ this.increment = value;
+ }
+
+ /**
+ * Sets the maximum value that the receiver will allow. This new value will be ignored if it is less than the receiver's current minimum value. If the new maximum is applied then the receiver's selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than or equal to the current minimum
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void setMaximum(final int value) {
+ this.checkWidget();
+ this.maximum = value;
+ }
+
+ /**
+ * Sets the minimum value that the receiver will allow. This new value will be ignored if it is greater than the receiver's current maximum value. If the new minimum is applied then the receiver's selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new minimum, which must be less than or equal to the current maximum
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void setMinimum(final int value) {
+ this.checkWidget();
+ this.minimum = value;
+ }
+
+ /**
+ * Sets the amount that the receiver's position will be modified by when the page up/down keys are pressed to the argument, which must be at least one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void setPageIncrement(final int value) {
+ this.checkWidget();
+ this.pageIncrement = value;
+ }
+
+ /**
+ * Sets the <em>selection</em>, which is the receiver's position, to the argument. If the argument is not within the range specified by minimum and maximum, it will be adjusted to fall within this range.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelection(int selection) {
+ this.checkWidget();
+ if (selection < this.minimum) {
+ selection = this.minimum;
+ } else if (selection > this.maximum) {
+ selection = this.maximum;
+ }
+
+ this.storedValue = selection;
+ this.text.setText(this.convertSelection());
+ this.text.selectAll();
+ this.text.setFocus();
+
+ for (final SelectionListener s : HorizontalSpinner.this.selectionListeners) {
+ s.widgetSelected(null);
+ }
+
+ }
+
+ /**
+ * Convert the selection into a string
+ *
+ * @return the string representation of the selection
+ */
+ private String convertSelection() {
+ if (this.getDigits() == 0) {
+ return String.valueOf(this.storedValue);
+ }
+ final String temp = String.valueOf(this.storedValue * Math.pow(10, -1 * this.getDigits()));
+ return temp.replace('.', this.decimalFormatSeparator);
+ }
+
+ /**
+ * Sets the maximum number of characters that the receiver's text field is capable of holding to be the argument.
+ * <p>
+ * To reset this value to the default, use <code>setTextLimit(Spinner.LIMIT)</code>. Specifying a limit value larger than <code>Spinner.LIMIT</code> sets the receiver's limit to <code>Spinner.LIMIT</code>.
+ * </p>
+ *
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #LIMIT
+ */
+ public void setTextLimit(final int limit) {
+ this.checkWidget();
+ this.text.setTextLimit(limit);
+ }
+
+ /**
+ * Sets the receiver's selection, minimum value, maximum value, digits, increment and page increment all at once.
+ * <p>
+ * Note: This is similar to setting the values individually using the appropriate methods, but may be implemented in a more efficient fashion on some platforms.
+ * </p>
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param digits the new digits value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void setValues(final int selection, final int minimum, final int maximum, final int digits, final int increment, final int pageIncrement) {
+ this.setMinimum(minimum);
+ this.setMaximum(maximum);
+ this.setDigits(digits);
+ this.setIncrement(increment);
+ this.setPageIncrement(pageIncrement);
+ this.setSelection(selection);
+ }
+
+ /**
+ * Sets the receiver's drag detect state. If the argument is <code>true</code>, the receiver will detect drag gestures, otherwise these gestures will be ignored.
+ *
+ * @param dragDetect the new drag detect state
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ @Override
+ public boolean setFocus() {
+ this.checkWidget();
+ return this.text.setFocus();
+ }
+
+ /**
+ * Forces the receiver to have the <em>keyboard focus</em>, causing all keyboard events to be delivered to it.
+ *
+ * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #setFocus
+ */
+ @Override
+ public boolean forceFocus() {
+ this.checkWidget();
+ return this.text.forceFocus();
+ }
+
+ /**
+ * Sets the receiver's background color to the color specified by the argument, or to the default system color for the control if the argument is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform. For example, on Windows the background of a Button cannot be changed.
+ * </p>
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ @Override
+ public void setBackground(final Color color) {
+ super.setBackground(color);
+ this.leftButton.setBackground(color);
+ this.rightButton.setBackground(color);
+ this.text.setBackground(color);
+ }
+
+ /**
+ * Sets the receiver's background image to the image specified by the argument, or to the default system color for the control if the argument is null. The background image is tiled to fill the available space.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform. For example, on Windows the background of a Button cannot be changed.
+ * </p>
+ *
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ @Override
+ public void setBackgroundImage(final Image image) {
+ super.setBackgroundImage(image);
+ this.leftButton.setBackgroundImage(image);
+ this.rightButton.setBackgroundImage(image);
+ this.text.setBackgroundImage(image);
+
+ }
+
+ /**
+ * Sets the receiver's cursor to the cursor specified by the argument, or to the default cursor for that kind of control if the argument is null.
+ * <p>
+ * When the mouse pointer passes over a control its appearance is changed to match the control's cursor.
+ * </p>
+ *
+ * @param cursor the new cursor (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ @Override
+ public void setCursor(final Cursor cursor) {
+ super.setCursor(cursor);
+ this.leftButton.setCursor(cursor);
+ this.rightButton.setCursor(cursor);
+ this.text.setCursor(cursor);
+
+ }
+
+ /**
+ * Enables the receiver if the argument is <code>true</code>, and disables it otherwise. A disabled control is typically not selectable from the user interface and draws with an inactive or "grayed" look.
+ *
+ * @param enabled the new enabled state
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ @Override
+ public void setEnabled(final boolean enabled) {
+ super.setEnabled(enabled);
+ this.leftButton.setEnabled(enabled);
+ this.rightButton.setEnabled(enabled);
+ this.text.setEnabled(enabled);
+
+ }
+
+ /**
+ * Sets the font that the receiver will use to paint textual information to the font specified by the argument, or to the default font for that kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ @Override
+ public void setFont(final Font font) {
+ super.setFont(font);
+ this.text.setFont(font);
+ }
+
+ /**
+ * Sets the receiver's foreground color to the color specified by the argument, or to the default system color for the control if the argument is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * </p>
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ @Override
+ public void setForeground(final Color color) {
+ super.setForeground(color);
+ this.leftButton.setForeground(color);
+ this.rightButton.setForeground(color);
+ this.text.setForeground(color);
+
+ }
+
+ /**
+ * Sets the receiver's pop up menu to the argument. All controls may optionally have a pop up menu that is displayed when the user requests one for the control. The sequence of key strokes, button presses and/or button releases that are used to request a pop up menu is platform specific.
+ * <p>
+ * Note: Disposing of a control that has a pop up menu will dispose of the menu. To avoid this behavior, set the menu to null before the control is disposed.
+ * </p>
+ *
+ * @param menu the new pop up menu
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li>
+ * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ @Override
+ public void setMenu(final Menu menu) {
+ super.setMenu(menu);
+ this.leftButton.setMenu(menu);
+ this.rightButton.setMenu(menu);
+ this.text.setMenu(menu);
+ }
+
+ /**
+ * Sets the receiver's tool tip text to the argument, which may be null indicating that the default tool tip for the control will be shown. For a control that has a default tool tip, such as the Tree control on Windows, setting the tool tip text to an empty string replaces the default, causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip. To display a single '&amp;' in the tool tip, the character '&amp;' can be escaped by doubling it in the string.
+ * </p>
+ *
+ * @param string the new tool tip text (or null)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+ @Override
+ public void setToolTipText(final String tooltipText) {
+ super.setToolTipText(tooltipText);
+ this.leftButton.setToolTipText(tooltipText);
+ this.rightButton.setToolTipText(tooltipText);
+ this.text.setToolTipText(tooltipText);
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/imageSelector/ISItem.java b/org.tizen.common.externals/src/org/mihalis/opal/imageSelector/ISItem.java
new file mode 100644
index 000000000..fc9109905
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/imageSelector/ISItem.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.imageSelector;
+
+import org.eclipse.swt.graphics.Point;
+import org.mihalis.opal.OpalItem;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class represents items manipulated by the ImageSelector
+ * widget
+ */
+public class ISItem extends OpalItem implements Comparable<ISItem> {
+
+ private double zPosition;
+ private Point upperLeftCorner;
+ private Point lowerRightCorner;
+
+ /**
+ * Constructor
+ *
+ * @param fileName file name of the image that will be displayed
+ */
+ public ISItem(final String fileName) {
+ setImage(SWTGraphicUtil.createImage(fileName));
+ }
+
+ /**
+ * Constructor
+ *
+ * @param title the title of the image
+ * @param fileName file name of the image that will be displayed
+ */
+ public ISItem(final String title, final String fileName) {
+ setImage(SWTGraphicUtil.createImage(fileName));
+ setText(title);
+ }
+
+ /**
+ * @return the zPosition
+ */
+ double getzPosition() {
+ return this.zPosition;
+ }
+
+ /**
+ * @param zPosition the zPosition to set
+ */
+ ISItem setzPosition(final double zPosition) {
+ this.zPosition = zPosition;
+ return this;
+ }
+
+ /**
+ * @return the upperLeftCorner
+ */
+ Point getUpperLeftCorner() {
+ return this.upperLeftCorner;
+ }
+
+ /**
+ * @param x the upperLeftCorner.x to set
+ * @param y the upperLeftCorner.y to set
+ */
+ void setUpperLeftCorner(final int x, final int y) {
+ this.upperLeftCorner = new Point(x, y);
+ }
+
+ /**
+ * @return the lowerRightCorner
+ */
+ Point getLowerRightCorner() {
+ return this.lowerRightCorner;
+ }
+
+ /**
+ * @param x the lowerRightCorner.x to set
+ * @param y the lowerRightCorner.y to set
+ */
+ void setLowerRightCorner(final int x, final int y) {
+ this.lowerRightCorner = new Point(x, y);
+ }
+
+ void resetCornerToNull() {
+ this.upperLeftCorner = null;
+ this.lowerRightCorner = null;
+
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "ISItem [getText()=" + this.getText() + "]";
+ }
+
+ /**
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ @Override
+ public int compareTo(final ISItem o) {
+ return new Double(Math.abs(this.zPosition)).compareTo(Math.abs(o.getzPosition())) * -1;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/imageSelector/ImageSelector.java b/org.tizen.common.externals/src/org/mihalis/opal/imageSelector/ImageSelector.java
new file mode 100755
index 000000000..2bab62d96
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/imageSelector/ImageSelector.java
@@ -0,0 +1,615 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ * Romain Guy - Original Swing Implementation (http://www.curious-creature.org/2005/07/09/a-music-shelf-in-java2d/)
+ *******************************************************************************/
+package org.mihalis.opal.imageSelector;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are controls that allow the user to select images.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ */
+public class ImageSelector extends Canvas {
+ private List<ISItem> items;
+ private List<ISItem> originalItems;
+ private Font font;
+ private static final int DEFAULT_WIDTH = 148;
+ private int maxItemWidth = DEFAULT_WIDTH;
+ private int index = -1;
+ private double sigma;
+ private double rho;
+ private double expMultiplier;
+ private double expMember;
+ private float spacing = 0.4f;
+ private Color gradientStart;
+ private Color gradientEnd;
+ private double animationStep = -1d;
+ private static final int TIMER_INTERVAL = 50;
+ private int pageIncrement = 5;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ */
+ public ImageSelector(final Composite parent, final int style) {
+ super(parent, style | SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED);
+ this.font = new Font(this.getDisplay(), "Lucida Sans", 24, SWT.NONE);
+
+ this.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(ImageSelector.this.font);
+ SWTGraphicUtil.dispose(ImageSelector.this.gradientStart);
+ SWTGraphicUtil.dispose(ImageSelector.this.gradientEnd);
+ }
+
+ });
+
+ addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(final PaintEvent e) {
+ ImageSelector.this.paintControl(e);
+ }
+
+ });
+
+ addKeyListener();
+ addMouseListeners();
+
+ setSigma(0.5);
+ this.gradientStart = new Color(getDisplay(), 0, 0, 0);
+ this.gradientEnd = new Color(getDisplay(), 110, 110, 110);
+ }
+
+ /**
+ * Set the sigma value for the gaussian curve
+ *
+ * @param sigma new sigma parameter
+ */
+ public void setSigma(final double sigma) {
+ this.sigma = sigma;
+ this.rho = 1.0;
+ computeEquationParts();
+ this.rho = computeModifierUnbounded(0.0);
+ computeEquationParts();
+ redraw();
+ }
+
+ /**
+ * Computer both members of the equation
+ */
+ private void computeEquationParts() {
+ this.expMultiplier = Math.sqrt(2.0 * Math.PI) / this.sigma / this.rho;
+ this.expMember = 4.0 * this.sigma * this.sigma;
+ }
+
+ /**
+ * Compute the value of the modifier. The value is bounded between -1 and +1
+ *
+ * @param x input value
+ * @return the value of the modifier between -1 and +1
+ */
+ private double computeModifierBounded(final double x) {
+ double result = computeModifierUnbounded(x);
+ if (result > 1.0) {
+ result = 1.0;
+ } else if (result < -1.0) {
+ result = -1.0;
+ }
+ return result;
+ }
+
+ /**
+ * Compute the value of the modifier
+ *
+ * @param x input value
+ * @return the value of the function
+ */
+ private double computeModifierUnbounded(final double x) {
+ return this.expMultiplier * Math.exp(-x * x / this.expMember);
+ }
+
+ /**
+ * Draw the widget
+ *
+ * @param e the paintEvent
+ */
+ private void paintControl(final PaintEvent e) {
+
+ // Create the image to fill the canvas
+ final Image image = new Image(getDisplay(), getClientArea());
+
+ // Set up the offscreen gc
+ final GC gc = new GC(image);
+
+ // Draw gradient
+ drawBackground(gc);
+
+ // Draw the items
+ drawItems(gc);
+
+ // Draw the title
+ if (this.animationStep < 0d) {
+ drawTitle(gc);
+ }
+
+ // Draw the offscreen buffer to the screen
+ e.gc.drawImage(image, 0, 0);
+
+ // Clean up
+ image.dispose();
+ gc.dispose();
+
+ }
+
+ /**
+ * Draw the background
+ *
+ * @param gc graphical context
+ */
+ private void drawBackground(final GC gc) {
+ final Rectangle rect = getClientArea();
+
+ gc.setForeground(this.gradientStart);
+ gc.setBackground(this.gradientEnd);
+ gc.fillGradientRectangle(rect.x, rect.y, rect.width, rect.height / 2, true);
+
+ gc.setForeground(this.gradientEnd);
+ gc.setBackground(this.gradientStart);
+ gc.fillGradientRectangle(rect.x, rect.height / 2, rect.width, rect.height / 2, true);
+ }
+
+ /**
+ * Draw the items
+ *
+ * @param gc graphical context
+ */
+ private void drawItems(final GC gc) {
+
+ if (this.animationStep < 0d) {
+ this.items.clear();
+ this.items.addAll(this.originalItems);
+ for (int i = 0; i < this.items.size(); i++) {
+ final ISItem item = this.items.get(i);
+ item.setzPosition((i - this.index) * this.spacing);
+ }
+
+ Collections.sort(this.items);
+ }
+
+ for (final ISItem item : this.items) {
+ drawItem(gc, item);
+ }
+ }
+
+ /**
+ * Draw a given item
+ *
+ * @param gc graphical context
+ * @param item item to draw
+ */
+ private void drawItem(final GC gc, final ISItem item) {
+
+ final int size = computeSize(item);
+ final int centerX = computeZPosition(item);
+ final int centerY = this.getClientArea().height / 2;
+
+ if (size <= 0 || centerX < 0 || centerX > getBounds().width) {
+ item.resetCornerToNull();
+ return;
+ }
+
+ final int alpha = computeAlpha(item);
+
+ final Image newImage = SWTGraphicUtil.createReflectedResizedImage(item.getImage(), size, size);
+ gc.setAlpha(alpha);
+
+ final int x = centerX - newImage.getBounds().width / 2;
+ final int y = centerY - newImage.getBounds().height / 2;
+
+ gc.drawImage(newImage, x, y);
+
+ item.setUpperLeftCorner(x, y);
+ item.setLowerRightCorner(x + newImage.getBounds().width, (int) (y + newImage.getBounds().height / 1.5));
+
+ newImage.dispose();
+ }
+
+ /**
+ * Compute the z position for a given item
+ *
+ * @param item item
+ * @return the z position of the item
+ */
+ private int computeZPosition(final ISItem item) {
+ final int totalWidth = this.getClientArea().width / 2;
+ final int centerX = this.getClientArea().width / 2;
+ return (int) (centerX + item.getzPosition() * totalWidth);
+ }
+
+ /**
+ * Compute size for a given item
+ *
+ * @param item item
+ * @return the size of the item
+ */
+ private int computeSize(final ISItem item) {
+ return (int) (computeModifierBounded(item.getzPosition()) * this.maxItemWidth);
+ }
+
+ /**
+ * Compute the alpha value of a given item
+ *
+ * @param item item
+ * @return the alpha value of the item
+ */
+ private int computeAlpha(final ISItem item) {
+ return (int) (255 - 150 * Math.abs(item.getzPosition()));
+ }
+
+ /**
+ * Draw the title under the selected item
+ *
+ * @param gc graphical context
+ */
+ private void drawTitle(final GC gc) {
+ final String title = this.originalItems.get(this.index).getText();
+ if (title == null || title.trim().equals("")) {
+ return;
+ }
+ gc.setFont(getFont());
+ final Point textSize = gc.stringExtent(title);
+
+ gc.setAntialias(SWT.ON);
+ gc.setFont(getFont());
+ gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.setAlpha(255);
+
+ final int centerX = this.getClientArea().width / 2;
+ final int centerY = (this.getClientArea().height + this.maxItemWidth) / 2;
+
+ gc.drawString(title, centerX - textSize.x / 2, (centerY - textSize.y / 2), true);
+
+ }
+
+ /**
+ * Add the key listener
+ */
+ private void addKeyListener() {
+ this.addKeyListener(new KeyAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
+ */
+ @Override
+ public void keyReleased(final KeyEvent e) {
+ switch (e.keyCode) {
+ case SWT.ARROW_LEFT:
+ case SWT.ARROW_UP:
+ scrollAndAnimateBy(-1);
+ break;
+ case SWT.ARROW_RIGHT:
+ case SWT.ARROW_DOWN:
+ scrollAndAnimateBy(1);
+ break;
+ case SWT.HOME:
+ scrollBy(-1 * ImageSelector.this.index);
+ break;
+ case SWT.END:
+ scrollBy(ImageSelector.this.index);
+ break;
+ case SWT.PAGE_UP:
+ scrollBy(-1 * ImageSelector.this.pageIncrement);
+ break;
+ case SWT.PAGE_DOWN:
+ scrollBy(ImageSelector.this.pageIncrement);
+ break;
+ default:
+ break;
+ }
+ }
+
+ });
+ }
+
+ /**
+ * Scroll the selected item
+ *
+ * @param increment increment value
+ */
+ private void scrollBy(final int increment) {
+ this.index += increment;
+ if (this.index < 0) {
+ this.index = 0;
+ }
+
+ if (this.index >= this.items.size()) {
+ this.index = this.items.size() - 1;
+ }
+ redraw();
+ }
+
+ /**
+ * Scroll the selected item with an animation
+ *
+ * @param increment increment value
+ */
+ private void scrollAndAnimateBy(final int increment) {
+ if (this.index == 0 && increment < 0 || this.index == this.items.size() - 1 && increment > 0) {
+ return;
+ }
+
+ final double step = Math.abs(increment) / (300d / TIMER_INTERVAL);
+ ImageSelector.this.animationStep = step;
+ setCursor(getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
+
+ getDisplay().syncExec(new Runnable() {
+
+ @Override
+ public void run() {
+
+ ImageSelector.this.items.clear();
+ ImageSelector.this.items.addAll(ImageSelector.this.originalItems);
+ for (int i = 0; i < ImageSelector.this.items.size(); i++) {
+ final ISItem item = ImageSelector.this.items.get(i);
+ item.setzPosition((i - ImageSelector.this.index + ImageSelector.this.animationStep * (increment > 0 ? -1d : 1d)) * ImageSelector.this.spacing);
+ }
+ Collections.sort(ImageSelector.this.items);
+ if (!isDisposed()) {
+ redraw();
+ }
+
+ ImageSelector.this.animationStep += step;
+ if (ImageSelector.this.animationStep >= 1d) {
+ ImageSelector.this.animationStep = -1d;
+ ImageSelector.this.index += increment;
+ setCursor(getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
+ } else {
+ if (!isDisposed()) {
+ getDisplay().timerExec(TIMER_INTERVAL, this);
+ }
+ }
+
+ }
+ });
+
+ }
+
+ /**
+ * Add mouse listeners
+ */
+ private void addMouseListeners() {
+ addMouseMoveListener(new MouseMoveListener() {
+
+ @Override
+ public void mouseMove(final MouseEvent e) {
+ for (final ISItem item : ImageSelector.this.items) {
+ if (item.getUpperLeftCorner() != null && item.getLowerRightCorner() != null && e.x >= item.getUpperLeftCorner().x && e.x <= item.getLowerRightCorner().x && e.y >= item.getUpperLeftCorner().y && e.y <= item.getLowerRightCorner().y) {
+ setCursor(getDisplay().getSystemCursor(SWT.CURSOR_HAND));
+ return;
+ }
+ }
+ setCursor(getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
+ }
+ });
+
+ addMouseListener(new MouseAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.MouseAdapter#mouseUp(org.eclipse.swt.events.MouseEvent)
+ */
+ @Override
+ public void mouseUp(final MouseEvent e) {
+ for (final ISItem item : ImageSelector.this.items) {
+ if (item.getUpperLeftCorner() != null && item.getLowerRightCorner() != null && e.x >= item.getUpperLeftCorner().x && e.x <= item.getLowerRightCorner().x && e.y >= item.getUpperLeftCorner().y && e.y <= item.getLowerRightCorner().y) {
+ scrollAndAnimateBy(ImageSelector.this.originalItems.indexOf(item) - ImageSelector.this.index);
+ return;
+ }
+ }
+ }
+ });
+
+ addListener(SWT.MouseWheel, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ scrollBy(-1 * event.count);
+ }
+ });
+
+ }
+
+ /**
+ * @return the items displayed by this widget
+ */
+ public List<ISItem> getItems() {
+ return this.originalItems;
+ }
+
+ /**
+ * @param items the items that are displayed in this widget to set
+ */
+ public void setItems(final List<ISItem> items) {
+ this.items = new ArrayList<ISItem>(items);
+ this.originalItems = items;
+ this.index = this.items.size() / 2;
+ redraw();
+ }
+
+ /**
+ * @return the font used for the title
+ */
+ @Override
+ public Font getFont() {
+ return this.font;
+ }
+
+ /**
+ * @param font the font used for the title to set
+ */
+ @Override
+ public void setFont(final Font font) {
+ SWTGraphicUtil.dispose(this.font);
+ this.font = font;
+ redraw();
+ }
+
+ /**
+ * @return the index of the selected image
+ */
+ public int getIndex() {
+ return this.index;
+ }
+
+ /**
+ * @param index the index of the selected image to set
+ */
+ public void setIndex(final int index) {
+ this.index = index;
+ redraw();
+ }
+
+ /**
+ * @return the maximum items width
+ */
+ public int getMaxItemWidth() {
+ return this.maxItemWidth;
+ }
+
+ /**
+ * @param maxItemWidth the the maximum items width to set
+ */
+ public void setMaxItemWidth(final int maxItemWidth) {
+ this.maxItemWidth = maxItemWidth;
+ redraw();
+ }
+
+ /**
+ * @return the sigma value
+ */
+ public double getSigma() {
+ return this.sigma;
+ }
+
+ /**
+ * @return the spacing between 2 items
+ */
+ public float getSpacing() {
+ return this.spacing;
+ }
+
+ /**
+ * @param spacing the the spacing between 2 items to set
+ */
+ public void setSpacing(final float spacing) {
+ this.spacing = spacing;
+ redraw();
+ }
+
+ /**
+ * @return the gradient start color
+ */
+ public Color getGradientStart() {
+ return this.gradientStart;
+ }
+
+ /**
+ * @param gradientStart the the gradient start color to set
+ */
+ public void setGradientStart(final Color gradientStart) {
+ SWTGraphicUtil.dispose(this.gradientStart);
+ this.gradientStart = gradientStart;
+ redraw();
+ }
+
+ /**
+ * @return the the gradient end color
+ */
+ public Color getGradientEnd() {
+ return this.gradientEnd;
+ }
+
+ /**
+ * @param gradientEnd the the gradient end color to set
+ */
+ public void setGradientEnd(final Color gradientEnd) {
+ SWTGraphicUtil.dispose(this.gradientEnd);
+ this.gradientEnd = gradientEnd;
+ redraw();
+ }
+
+ /**
+ * @return the page increment when the user uses PgUp and PgDown
+ */
+ public int getPageIncrement() {
+ return this.pageIncrement;
+ }
+
+ /**
+ * @param pageIncrement the page increment to set
+ */
+ public void setPageIncrement(final int pageIncrement) {
+ this.pageIncrement = pageIncrement;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/infinitePanel/InfiniteProgressPanel.java b/org.tizen.common.externals/src/org/mihalis/opal/infinitePanel/InfiniteProgressPanel.java
new file mode 100644
index 000000000..e7a62dea3
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/infinitePanel/InfiniteProgressPanel.java
@@ -0,0 +1,604 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation,
+ * inspired by Romain Guy's work (http://www.curious-creature.org)
+ *******************************************************************************/
+package org.mihalis.opal.infinitePanel;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are controls located on the top of a shell. They
+ * display a ticker that indicates to the user that a long task operation is
+ * running
+ */
+public class InfiniteProgressPanel {
+
+ private static final String INFINITE_PANEL_KEY = "org.mihalis.opal.InfinitePanel.InfiniteProgressPanel";
+ private static final int NUMBER_OF_STEPS = 10;
+
+ private final Shell parent;
+ private Shell panel;
+ private String text;
+ private Font textFont;
+ private Color textColor;
+ private float fps;
+ private int barsCount;
+ private int lineWidth;
+ private int alpha;
+ private Color defaultColor;
+ private Color selectionColor;
+ private int currentPosition;
+ private Thread animatorThread;
+ private Canvas canvas;
+ private boolean fadeIn;
+ private boolean fadeOut;
+ private int fadeOutCounter;
+
+ /**
+ * Constructs a new instance of this class given its parent.
+ *
+ * @param shell a shell that will be the parent of the new instance (cannot
+ * be null)
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the parent has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ */
+ private InfiniteProgressPanel(final Shell shell) {
+ if (shell == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (shell.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ this.parent = shell;
+ if (shell.getData(INFINITE_PANEL_KEY) != null) {
+ throw new IllegalArgumentException("This shell has already an infinite panel attached on it !");
+ }
+
+ this.text = null;
+ this.textFont = null;
+ this.barsCount = 14;
+ this.fps = 15.0f;
+ this.lineWidth = 16;
+ this.alpha = 200;
+ this.fadeIn = false;
+ this.fadeOut = false;
+ this.fadeOutCounter = 0;
+ shell.setData(INFINITE_PANEL_KEY, this);
+
+ this.parent.addListener(SWT.Activate, new Listener() {
+
+ @Override
+ public void handleEvent(final Event e) {
+ if (InfiniteProgressPanel.this.panel != null && //
+ !InfiniteProgressPanel.this.panel.isDisposed() && !InfiniteProgressPanel.this.panel.isVisible()) {
+ InfiniteProgressPanel.this.panel.setVisible(true);
+ InfiniteProgressPanel.this.panel.setActive();
+ }
+ }
+ });
+ }
+
+ /**
+ * Starts the ticker
+ */
+ public void start() {
+ if (this.parent.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ this.panel = new Shell(this.parent, SWT.APPLICATION_MODAL | SWT.NO_TRIM | SWT.ON_TOP);
+ this.panel.setLayout(new FillLayout());
+ this.panel.setAlpha(0);
+
+ this.panel.addListener(SWT.KeyUp, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ event.doit = false;
+ }
+ });
+
+ if (this.defaultColor == null) {
+ this.defaultColor = new Color(this.parent.getDisplay(), 200, 200, 200);
+ }
+
+ if (this.selectionColor == null) {
+ this.selectionColor = new Color(this.parent.getDisplay(), 0, 0, 0);
+ }
+
+ this.parent.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(InfiniteProgressPanel.this.defaultColor);
+ SWTGraphicUtil.dispose(InfiniteProgressPanel.this.selectionColor);
+ }
+ });
+
+ this.currentPosition = 0;
+ this.fadeIn = true;
+ this.fadeOut = false;
+ this.fadeOutCounter = 0;
+
+ this.canvas = new Canvas(this.panel, SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED);
+ this.canvas.addPaintListener(new PaintListener() {
+
+ @Override
+ public void paintControl(final PaintEvent e) {
+ InfiniteProgressPanel.this.paintCanvas(e);
+ }
+ });
+
+ this.panel.setBounds(this.panel.getDisplay().map(this.parent, null, this.parent.getClientArea()));
+ this.panel.open();
+
+ this.animatorThread = new Thread() {
+
+ /**
+ * @see java.lang.Thread#run()
+ */
+ @Override
+ public void run() {
+ while (!Thread.interrupted()) {
+ InfiniteProgressPanel.this.currentPosition = (InfiniteProgressPanel.this.currentPosition + 1) % InfiniteProgressPanel.this.barsCount;
+ if (InfiniteProgressPanel.this.fadeOut) {
+ InfiniteProgressPanel.this.fadeOutCounter++;
+ }
+ InfiniteProgressPanel.this.panel.getDisplay().asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ InfiniteProgressPanel.this.canvas.redraw();
+ }
+ });
+
+ try {
+ sleep(InfiniteProgressPanel.this.fadeOut ? 20 : (long) (1000 / InfiniteProgressPanel.this.fps));
+ } catch (final InterruptedException e) {
+ break;
+ }
+ }
+ }
+ };
+ this.animatorThread.start();
+
+ this.panel.addListener(SWT.Deactivate, new Listener() {
+
+ @Override
+ public void handleEvent(final Event arg0) {
+ InfiniteProgressPanel.this.panel.setVisible(false);
+ }
+ });
+
+ }
+
+ /**
+ * Paint the canvas that holds the ticker
+ *
+ * @param e
+ */
+ private void paintCanvas(final PaintEvent e) {
+ // Paint the panel
+ final Rectangle clientArea = ((Canvas) e.widget).getClientArea();
+ final GC gc = e.gc;
+
+ this.handleFadeIn();
+ this.handleFadeOut();
+ this.drawBackground(clientArea, gc);
+ this.drawTicker(clientArea, gc);
+ this.drawText(clientArea, gc);
+
+ }
+
+ /**
+ * Handle the fade in effect of the panel
+ */
+ private void handleFadeIn() {
+ if (this.fadeIn) {
+ if (this.currentPosition == NUMBER_OF_STEPS) {
+ this.fadeIn = false;
+ this.panel.setAlpha(this.alpha);
+ } else {
+ this.panel.setAlpha(this.currentPosition * this.alpha / NUMBER_OF_STEPS);
+ }
+ }
+ }
+
+ /**
+ * Handle the fade out effect of the panel
+ */
+ private void handleFadeOut() {
+ if (this.fadeOut) {
+ if (this.fadeOutCounter == NUMBER_OF_STEPS) {
+ if (this.animatorThread != null) {
+ this.animatorThread.interrupt();
+ this.animatorThread = null;
+ }
+ if (!this.panel.isDisposed()) {
+ this.panel.getDisplay().asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ if (!InfiniteProgressPanel.this.panel.isDisposed()) {
+ InfiniteProgressPanel.this.panel.dispose();
+ }
+ }
+ });
+ }
+ }
+ this.panel.setAlpha(255 - this.fadeOutCounter * this.alpha / NUMBER_OF_STEPS);
+ }
+ }
+
+ /**
+ * Draw the background of the panel
+ *
+ * @param gc GC on with the background is drawn
+ * @param clientArea client area of the canvas
+ */
+ private void drawBackground(final Rectangle clientArea, final GC gc) {
+ // Draw the background
+ gc.setBackground(this.panel.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.fillRectangle(clientArea);
+ }
+
+ /**
+ * Draw the ticker
+ *
+ * @param gc GC on with the ticker is drawn
+ * @param clientArea client area of the canvas
+ */
+ private void drawTicker(final Rectangle clientArea, final GC gc) {
+ // Draw the ticker
+ final int centerX = clientArea.width / 2;
+ final int centerY = clientArea.height / 2;
+ final int maxRay = (int) (Math.min(clientArea.width, clientArea.height) * 0.6f) / 2;
+ final int minRay = (int) (maxRay * 0.5f);
+
+ double angle = Math.PI / 2;
+
+ gc.setLineCap(SWT.CAP_ROUND);
+ gc.setLineWidth(this.lineWidth);
+ gc.setAntialias(SWT.ON);
+
+ for (int i = 0; i < this.barsCount; i++) {
+ if (i == this.currentPosition) {
+ gc.setForeground(this.selectionColor);
+ } else {
+ gc.setForeground(this.defaultColor);
+ }
+ gc.drawLine((int) (centerX + minRay * Math.cos(angle)), //
+ (int) (centerY - minRay * Math.sin(angle)), //
+ (int) (centerX + maxRay * Math.cos(angle)), //
+ (int) (centerY - maxRay * Math.sin(angle)));
+ angle -= 2 * Math.PI / this.barsCount;
+ }
+ }
+
+ /**
+ * Draw the text over the ticker
+ *
+ * @param gc GC on with the text is drawn
+ * @param clientArea client area of the canvas
+ */
+ private void drawText(final Rectangle clientArea, final GC gc) {
+ if (this.text == null || "".equals(this.text)) {
+ return;
+ }
+
+ final Font font;
+ if (this.textFont == null) {
+ font = this.parent.getDisplay().getSystemFont();
+ } else {
+ font = this.textFont;
+ }
+
+ final Color color;
+ if (this.textColor == null) {
+ color = this.parent.getDisplay().getSystemColor(SWT.COLOR_BLACK);
+ } else {
+ color = this.textColor;
+ }
+
+ gc.setForeground(color);
+ gc.setFont(font);
+ gc.setTextAntialias(SWT.ON);
+ final Point textSize = gc.textExtent(this.text, SWT.DRAW_TRANSPARENT);
+ final int textWidth = textSize.x;
+ final int textHeight = textSize.y;
+
+ gc.drawString(this.text, (clientArea.width - textWidth) / 2, (clientArea.height - textHeight) / 2, true);
+
+ }
+
+ /**
+ * Stop the animation and dispose the panel
+ */
+ public void stop() {
+ if (this.panel.isDisposed() || this.panel.getDisplay().isDisposed()) {
+ return;
+ }
+ this.fadeOut = true;
+ }
+
+ /**
+ * Returns the infinite progress panel for the shell. If no infinite panel
+ * has been declared, returns null.
+ *
+ * @param shell the shell for which we are trying to get the associated
+ * progess panel
+ * @return the progress panel associated to shell, or null if there is no
+ * progress panel
+ */
+ public static InfiniteProgressPanel getInfiniteProgressPanelFor(final Shell shell) {
+ if (shell == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (shell.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ if (shell.getDisplay().isDisposed()) {
+ SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+ }
+
+ final InfiniteProgressPanel[] temp = new InfiniteProgressPanel[1];
+ shell.getDisplay().syncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ final Object data = shell.getData(INFINITE_PANEL_KEY);
+ if (data != null && data instanceof InfiniteProgressPanel) {
+ temp[0] = (InfiniteProgressPanel) data;
+ }
+ }
+ });
+
+ if (temp[0] == null) {
+ return new InfiniteProgressPanel(shell);
+ } else {
+ return temp[0];
+ }
+ }
+
+ /**
+ * Check if a shell has an associated progress panel
+ *
+ * @param shell the shell
+ * @return <code>true</code> if the shell has an associated panel,
+ * <code>false</code> otherwise
+ */
+ public static boolean hasInfiniteProgressPanel(final Shell shell) {
+ return getInfiniteProgressPanelFor(shell) != null;
+ }
+
+ // ------------------------------------------------- Getters and Setters
+
+ /**
+ * @return the alpha value of the panel
+ */
+ public int getAlpha() {
+ return this.alpha;
+ }
+
+ /**
+ * @param alpha the alpha value of the panel, between 0 and 255
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the animation is running</li>
+ * </ul>
+ */
+ public void setAlpha(final int alpha) {
+ if (alpha < 0 || alpha > 255) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.checkIfAnimationIsRunning();
+ this.alpha = alpha;
+ }
+
+ /**
+ * Check if the animation is running
+ */
+ private void checkIfAnimationIsRunning() {
+ if (this.animatorThread != null) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, "Can not change this value when an animation is running");
+ }
+ }
+
+ /**
+ * @return the number of bars displayed in the ticker
+ */
+ public int getBarsCount() {
+ return this.barsCount;
+ }
+
+ /**
+ * @param barsCount the number of bars displayed in the ticker
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the animation is running</li>
+ * </ul>
+ */
+ public void setBarsCount(final int barsCount) {
+ this.checkIfAnimationIsRunning();
+ this.barsCount = barsCount;
+ }
+
+ /**
+ * @return the default color for the ticker's bars
+ */
+ public Color getDefaultColor() {
+ return this.defaultColor;
+ }
+
+ /**
+ * @param defaultColor the new default color for the ticker's bars. Please
+ * notice that the previous color is disposed.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the animation is running</li>
+ * </ul>
+ */
+ public void setDefaultColor(final Color defaultColor) {
+ this.checkIfAnimationIsRunning();
+ SWTGraphicUtil.dispose(this.defaultColor);
+ this.defaultColor = defaultColor;
+ }
+
+ /**
+ * @return the number of frame per second for the animation
+ */
+ public float getFps() {
+ return this.fps;
+ }
+
+ /**
+ * @param fps the new frame per second value
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the animation is running</li>
+ * </ul>
+ */
+ public void setFps(final float fps) {
+ this.checkIfAnimationIsRunning();
+ this.fps = fps;
+ }
+
+ /**
+ * @return the line width of the bars that compose the ticker
+ */
+ public int getLineWidth() {
+ return this.lineWidth;
+ }
+
+ /**
+ * @param lineWidth the line width of the bars that compose the ticker
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the animation is running</li>
+ * </ul>
+ */
+ public void setLineWidth(final int lineWidth) {
+ this.checkIfAnimationIsRunning();
+ this.lineWidth = lineWidth;
+ }
+
+ /**
+ * @return the selection color of the ticker's bars
+ */
+ public Color getSelectionColor() {
+ return this.selectionColor;
+ }
+
+ /**
+ * @param selectionColor the new selection color for the ticker's bars.
+ * Please notice that the previous color is disposed.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the animation is running</li>
+ * </ul>
+ */
+ public void setSelectionColor(final Color selectionColor) {
+ this.checkIfAnimationIsRunning();
+ SWTGraphicUtil.dispose(this.selectionColor);
+ this.selectionColor = selectionColor;
+ }
+
+ /**
+ * @return the displayed text
+ */
+ public String getText() {
+ return this.text;
+ }
+
+ /**
+ * @param text set the text to display
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the animation is running</li>
+ * </ul>
+ */
+ public void setText(final String text) {
+ this.checkIfAnimationIsRunning();
+ this.text = text;
+ }
+
+ /**
+ * @return the text color
+ */
+ public Color getTextColor() {
+ return this.textColor;
+ }
+
+ /**
+ * @param textColor the text color. Please notice that the previous color is
+ * disposed.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the animation is running</li>
+ * </ul>
+ */
+ public void setTextColor(final Color textColor) {
+ this.checkIfAnimationIsRunning();
+ SWTGraphicUtil.dispose(this.textColor);
+ this.textColor = textColor;
+ }
+
+ /**
+ * @return the text font
+ */
+ public Font getTextFont() {
+ return this.textFont;
+ }
+
+ /**
+ * @param textFont the new text font. Please notice that the previous font
+ * set is disposed.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the animation is running</li>
+ * </ul>
+ */
+ public void setTextFont(final Font textFont) {
+ this.checkIfAnimationIsRunning();
+ if (this.textFont != null && !this.textFont.isDisposed()) {
+ this.textFont.dispose();
+ }
+ this.textFont = textFont;
+
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/itemSelector/DLItem.java b/org.tizen.common.externals/src/org/mihalis/opal/itemSelector/DLItem.java
new file mode 100644
index 000000000..953226f21
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/itemSelector/DLItem.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.itemSelector;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.mihalis.opal.OpalItem;
+
+/**
+ * Instances of this class represents items manipulated by this DualList widget
+ */
+public class DLItem extends OpalItem {
+
+ /**
+ * Constructor
+ *
+ * @param text the text displayed in the DualList widget for this item
+ */
+ public DLItem(final String text) {
+ this.setText(text);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param text the text displayed in the DualList widget for this item
+ * @param image the image displayed in the DualList widget for this item
+ */
+ public DLItem(final String text, final Image image) {
+ this.setText(text);
+ this.setImage(image);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param text the text displayed in the DualList widget for this item
+ * @param image the image displayed in the DualList widget for this item
+ * @param font the font displayed in the DualList widget for this item
+ * @param foregroundColor the foreground color displayed in the DualList
+ * widget for this item
+ */
+ public DLItem(final String text, final Image image, final Font font, final Color foregroundColor) {
+ this.setText(text);
+ this.setImage(image);
+ this.setFont(font);
+ this.setForeground(foregroundColor);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param text the text displayed in the DualList widget for this item
+ * @param image the image displayed in the DualList widget for this item
+ * @param foregroundColor the foreground color displayed in the DualList
+ * widget for this item
+ * @param backgroundColor the background color displayed in the DualList
+ * widget for this item
+ */
+ public DLItem(final String text, final Image image, final Color foregroundColor, final Color backgroundColor) {
+ this.setText(text);
+ this.setImage(image);
+ this.setForeground(foregroundColor);
+ this.setBackground(backgroundColor);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param text the text displayed in the DualList widget for this item
+ * @param image the image displayed in the DualList widget for this item
+ * @param font the font displayed in the DualList widget for this item
+ */
+ public DLItem(final String text, final Image image, final Font font) {
+ this.setText(text);
+ this.setImage(image);
+ this.setFont(font);
+ }
+
+ /**
+ * @see org.mihalis.opal.OpalItem#getHeight()
+ */
+ @Override
+ public int getHeight() {
+ throw new UnsupportedOperationException("DLItem does not support this method");
+ }
+
+ /**
+ * @see org.mihalis.opal.OpalItem#setHeight(int)
+ */
+ @Override
+ public void setHeight(final int height) {
+ throw new UnsupportedOperationException("DLItem does not support this method");
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/itemSelector/DualList.java b/org.tizen.common.externals/src/org/mihalis/opal/itemSelector/DualList.java
new file mode 100644
index 000000000..8b6b90296
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/itemSelector/DualList.java
@@ -0,0 +1,1265 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.itemSelector;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+import org.mihalis.opal.utils.SimpleSelectionAdapter;
+
+/**
+ * Instances of this class are controls that allow the user to select multiple
+ * elements.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ */
+
+public class DualList extends Composite {
+
+ private final List<DLItem> items;
+ private final List<DLItem> selection;
+
+ private final Table itemsTable;
+ private final Table selectionTable;
+
+ private List<SelectionListener> eventTable;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ */
+ public DualList(final Composite parent, final int style) {
+ super(parent, style);
+ this.items = new ArrayList<DLItem>();
+ this.selection = new ArrayList<DLItem>();
+
+ this.setLayout(new GridLayout(4, false));
+ this.itemsTable = this.createTable();
+ this.itemsTable.addMouseListener(new MouseAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.MouseAdapter#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+ */
+ @Override
+ public void mouseDoubleClick(final MouseEvent event) {
+ DualList.this.selectItem();
+ }
+
+ });
+ final Button buttonSelectAll = this.createButton("double_right.png", true, GridData.END);
+ buttonSelectAll.addSelectionListener(new SimpleSelectionAdapter() {
+
+ @Override
+ public void handle(final SelectionEvent e) {
+ DualList.this.selectAll();
+ }
+ });
+
+ this.selectionTable = this.createTable();
+ this.selectionTable.addMouseListener(new MouseAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.MouseAdapter#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+ */
+ @Override
+ public void mouseDoubleClick(final MouseEvent event) {
+ DualList.this.deselectItem();
+ }
+
+ });
+
+ final Button buttonMoveFirst = this.createButton("double_up.png", true, GridData.END);
+ buttonMoveFirst.addSelectionListener(new SimpleSelectionAdapter() {
+
+ @Override
+ public void handle(final SelectionEvent e) {
+ DualList.this.moveSelectionToFirstPosition();
+ }
+ });
+
+ final Button buttonSelect = this.createButton("arrow_right.png", false, GridData.CENTER);
+ buttonSelect.addSelectionListener(new SimpleSelectionAdapter() {
+
+ @Override
+ public void handle(final SelectionEvent e) {
+ DualList.this.selectItem();
+ }
+ });
+
+ final Button buttonMoveUp = this.createButton("arrow_up.png", false, GridData.CENTER);
+ buttonMoveUp.addSelectionListener(new SimpleSelectionAdapter() {
+
+ @Override
+ public void handle(final SelectionEvent e) {
+ DualList.this.moveUpItem();
+ }
+ });
+
+ final Button buttonDeselect = this.createButton("arrow_left.png", false, GridData.CENTER);
+ buttonDeselect.addSelectionListener(new SimpleSelectionAdapter() {
+
+ @Override
+ public void handle(final SelectionEvent e) {
+ DualList.this.deselectItem();
+ }
+ });
+
+ final Button buttonMoveDown = this.createButton("arrow_down.png", false, GridData.CENTER);
+ buttonMoveDown.addSelectionListener(new SimpleSelectionAdapter() {
+
+ @Override
+ public void handle(final SelectionEvent e) {
+ DualList.this.moveDownItem();
+ }
+ });
+
+ final Button buttonDeselectAll = this.createButton("double_left.png", false, GridData.BEGINNING);
+ buttonDeselectAll.addSelectionListener(new SimpleSelectionAdapter() {
+
+ @Override
+ public void handle(final SelectionEvent e) {
+ DualList.this.deselectAll();
+ }
+ });
+
+ final Button buttonMoveLast = this.createButton("double_down.png", true, GridData.BEGINNING);
+ buttonMoveLast.addSelectionListener(new SimpleSelectionAdapter() {
+
+ @Override
+ public void handle(final SelectionEvent e) {
+ DualList.this.moveSelectionToLastPosition();
+ }
+ });
+
+ }
+
+ /**
+ * @return a table that will contain data
+ */
+ private Table createTable() {
+ final Table table = new Table(this, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
+ table.setLinesVisible(false);
+ table.setHeaderVisible(false);
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, true, 1, 4);
+ gd.widthHint = 200;
+ table.setLayoutData(gd);
+ new TableColumn(table, SWT.CENTER);
+ new TableColumn(table, SWT.LEFT);
+ table.setData(-1);
+ return table;
+ }
+
+ /**
+ * Create a button
+ *
+ * @param fileName file name of the icon
+ * @param verticalExpand if <code>true</code>, the button will take all the
+ * available space vertically
+ * @param alignment button alignment
+ * @return a new button
+ */
+ private Button createButton(final String fileName, final boolean verticalExpand, final int alignment) {
+ final Button button = new Button(this, SWT.PUSH);
+ final Image image = new Image(this.getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/" + fileName));
+ button.setImage(image);
+ button.setLayoutData(new GridData(GridData.CENTER, alignment, false, verticalExpand));
+ button.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(image);
+ }
+ });
+ return button;
+ }
+
+ /**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param item the new item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #add(DLItem,int)
+ */
+ public void add(final DLItem item) {
+ this.checkWidget();
+ if (item == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ this.items.add(item);
+ }
+
+ /**
+ * Adds the argument to the receiver's list at the given zero-relative
+ * index.
+ * <p>
+ * Note: To add an item at the end of the list, use the result of calling
+ * <code>getItemCount()</code> as the index or use <code>add(DLItem)</code>.
+ * </p>
+ *
+ * @param item the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #add(String)
+ */
+ public void add(final DLItem item, final int index) {
+ this.checkWidget();
+ if (item == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (index <= 0 || index >= this.items.size()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.items.add(index, item);
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified
+ * when the user changes the receiver's selection, by sending it one of the
+ * messages defined in the <code>SelectionListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ this.checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (this.eventTable == null) {
+ this.eventTable = new ArrayList<SelectionListener>();
+ }
+ this.eventTable.add(listener);
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be
+ * notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ this.checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (this.eventTable == null) {
+ return;
+ }
+ this.eventTable.remove(listener);
+ }
+
+ /**
+ * Deselects the item at the given zero-relative index in the receiver. If
+ * the item at the index was already deselected, it remains deselected.
+ * Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void deselect(final int index) {
+ this.checkWidget();
+ if (index <= 0 || index >= this.items.size()) {
+ return;
+ }
+ this.fireEvents(this.selection.remove(index));
+ this.redrawTables();
+ }
+
+ /**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver is selected,
+ * it is deselected. If the item at the index was not selected, it remains
+ * deselected. Indices that are out of range and duplicate indices are
+ * ignored.
+ *
+ * @param indices the array of indices for the items to deselect
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the set of indices is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void deselect(final int[] indices) {
+ this.checkWidget();
+ if (indices == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ final List<DLItem> toBeRemoved = new ArrayList<DLItem>();
+
+ for (final int index : indices) {
+ if (index <= 0 || index >= this.items.size()) {
+ continue;
+ }
+ toBeRemoved.add(this.selection.get(index));
+ }
+
+ for (final DLItem item : toBeRemoved) {
+ this.selection.remove(item);
+ }
+ toBeRemoved.clear();
+ this.redrawTables();
+ }
+
+ /**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver is selected,
+ * it is deselected. If the item at the index was not selected, it remains
+ * deselected. The range of the indices is inclusive. Indices that are out
+ * of range are ignored.
+ *
+ * @param start the start index of the items to deselect
+ * @param end the end index of the items to deselect
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if start is greater than end</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void deselect(final int start, final int end) {
+ this.checkWidget();
+ if (start > end) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ final List<DLItem> toBeRemoved = new ArrayList<DLItem>();
+
+ for (int index = start; index <= end; index++) {
+ if (index <= 0 || index >= this.items.size()) {
+ continue;
+ }
+ toBeRemoved.add(this.selection.get(index));
+ }
+
+ for (final DLItem item : toBeRemoved) {
+ this.selection.remove(item);
+ }
+ toBeRemoved.clear();
+ this.redrawTables();
+ }
+
+ /**
+ * Deselects all selected items in the receiver.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void deselectAll() {
+ this.checkWidget();
+ this.items.addAll(this.selection);
+ this.selection.clear();
+ this.redrawTables();
+ }
+
+ /**
+ * Returns the item at the given, zero-relative index in the receiver.
+ * Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+
+ public DLItem getItem(final int index) {
+ this.checkWidget();
+ if (index <= 0 || index >= this.items.size()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ return this.items.get(index);
+ }
+
+ /**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getItemCount() {
+ this.checkWidget();
+ return this.items.size();
+ }
+
+ /**
+ * Returns a (possibly empty) array of <code>DLItem</code>s which are the
+ * items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its list of items, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver's list
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public DLItem[] getItems() {
+ this.checkWidget();
+ return this.items.toArray(new DLItem[this.items.size()]);
+ }
+
+ /**
+ * Returns a (possibly empty) list of <code>DLItem</code>s which are the
+ * items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its list of items, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver's list
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public List<DLItem> getItemsAsList() {
+ this.checkWidget();
+ return new ArrayList<DLItem>(this.items);
+ }
+
+ /**
+ * Returns an array of <code>DLItem</code>s that are currently selected in
+ * the receiver. An empty array indicates that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its selection, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return an array representing the selection
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public DLItem[] getSelection() {
+ this.checkWidget();
+ return this.selection.toArray(new DLItem[this.items.size()]);
+ }
+
+ /**
+ * Returns a list of <code>DLItem</code>s that are currently selected in the
+ * receiver. An empty array indicates that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its selection, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return an array representing the selection
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public List<DLItem> getSelectionAsList() {
+ this.checkWidget();
+ return new ArrayList<DLItem>(this.selection);
+ }
+
+ /**
+ * Returns the number of selected items contained in the receiver.
+ *
+ * @return the number of selected items
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getSelectionCount() {
+ this.checkWidget();
+ return this.selection.size();
+ }
+
+ /**
+ * Removes the item from the receiver at the given zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void remove(final int index) {
+ this.checkWidget();
+ if (index <= 0 || index >= this.items.size()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.items.remove(index);
+ this.redrawTables();
+ }
+
+ /**
+ * Removes the items from the receiver at the given zero-relative indices.
+ *
+ * @param indices the array of indices of the items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * <li>ERROR_NULL_ARGUMENT - if the indices array is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void remove(final int[] indices) {
+ this.checkWidget();
+ for (final int index : indices) {
+ if (index <= 0 || index >= this.items.size()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.items.remove(index);
+ }
+ this.redrawTables();
+ }
+
+ /**
+ * Removes the items from the receiver which are between the given
+ * zero-relative start and end indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if either the start or end are
+ * not between 0 and the number of elements in the list minus
+ * 1 (inclusive) or if start>end</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void remove(final int start, final int end) {
+ this.checkWidget();
+ if (start > end) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ for (int index = start; index <= end; index++) {
+ if (index <= 0 || index >= this.items.size()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.items.remove(index);
+ }
+ this.redrawTables();
+ }
+
+ /**
+ * Searches the receiver's list starting at the first item until an item is
+ * found that is equal to the argument, and removes that item from the list.
+ *
+ * @param item the item to remove
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item is not found in
+ * the list</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void remove(final DLItem item) {
+ this.checkWidget();
+ if (item == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (!this.items.contains(item)) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.items.remove(item);
+ this.redrawTables();
+ }
+
+ /**
+ * Removes all of the items from the receiver.
+ * <p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li> <li>ERROR_THREAD_INVALID_ACCESS - if not
+ * called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void removeAll() {
+ this.checkWidget();
+ this.items.clear();
+ this.redrawTables();
+ }
+
+ /**
+ * Selects the item at the given zero-relative index in the receiver's list.
+ * If the item at the index was already selected, it remains selected.
+ * Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void select(final int index) {
+ this.checkWidget();
+ if (index <= 0 || index >= this.items.size()) {
+ return;
+ }
+ this.selection.add(this.items.get(index));
+ this.fireEvents(this.items.get(index));
+ this.redrawTables();
+ }
+
+ /**
+ * Selects the items at the given zero-relative indices in the receiver. The
+ * current selection is not cleared before the new items are selected.
+ * <p>
+ * If the item at a given index is not selected, it is selected. If the item
+ * at a given index was already selected, it remains selected. Indices that
+ * are out of range and duplicate indices are ignored. If the receiver is
+ * single-select and multiple indices are specified, then all indices are
+ * ignored.
+ *
+ * @param indices the array of indices for the items to select
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of indices is null
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li> <li>ERROR_THREAD_INVALID_ACCESS - if not
+ * called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void select(final int[] indices) {
+ this.checkWidget();
+ if (indices == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ for (final int index : indices) {
+ if (index <= 0 || index >= this.items.size()) {
+ continue;
+ }
+ this.selection.add(this.items.get(index));
+ this.fireEvents(this.items.get(index));
+ }
+ this.redrawTables();
+ }
+
+ /**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive. The current
+ * selection is not cleared before the new items are selected.
+ * <p>
+ * If an item in the given range is not selected, it is selected. If an item
+ * in the given range was already selected, it remains selected. Indices
+ * that are out of range are ignored and no items will be selected if start
+ * is greater than end. If the receiver is single-select and there is more
+ * than one item in the given range, then all indices are ignored.
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li> <li>ERROR_THREAD_INVALID_ACCESS - if not
+ * called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see List#setSelection(int,int)
+ */
+ public void select(final int start, final int end) {
+ this.checkWidget();
+ if (start > end) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ for (int index = start; index <= end; index++) {
+ if (index <= 0 || index >= this.items.size()) {
+ continue;
+ }
+ this.selection.add(this.items.get(index));
+ this.fireEvents(this.items.get(index));
+ }
+ this.redrawTables();
+ }
+
+ /**
+ * Selects all of the items in the receiver.
+ * <p>
+ * If the receiver is single-select, do nothing.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li> <li>ERROR_THREAD_INVALID_ACCESS - if not
+ * called from the thread that created the receiver</li>
+ * </ul>
+ */
+ public void selectAll() {
+ this.checkWidget();
+ this.selection.addAll(this.items);
+ for (final DLItem item : this.items) {
+ this.fireEvents(item);
+ }
+ this.items.clear();
+ this.redrawTables();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#setBounds(int, int, int, int)
+ */
+ @Override
+ public void setBounds(final int x, final int y, final int width, final int height) {
+ super.setBounds(x, y, width, height);
+ final boolean itemsContainImage = this.itemsContainImage();
+ final Point itemsTableDefaultSize = this.itemsTable.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ final Point selectionTableDefaultSize = this.selectionTable.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+
+ int itemsTableSize = this.itemsTable.getSize().x;
+ if (itemsTableDefaultSize.y > this.itemsTable.getSize().y) {
+ itemsTableSize -= this.itemsTable.getVerticalBar().getSize().x;
+ }
+
+ int selectionTableSize = this.selectionTable.getSize().x;
+ if (selectionTableDefaultSize.y > this.selectionTable.getSize().y) {
+ selectionTableSize -= this.selectionTable.getVerticalBar().getSize().x;
+ }
+
+ if (itemsContainImage) {
+ this.itemsTable.getColumn(0).pack();
+ this.itemsTable.getColumn(1).setWidth(itemsTableSize - this.itemsTable.getColumn(0).getWidth());
+
+ this.selectionTable.getColumn(0).pack();
+ this.selectionTable.getColumn(1).setWidth(selectionTableSize - this.selectionTable.getColumn(0).getWidth());
+
+ } else {
+ this.itemsTable.getColumn(0).setWidth(itemsTableSize);
+ this.selectionTable.getColumn(0).setWidth(selectionTableSize);
+ }
+ }
+
+ /**
+ * @return <code>true</code> if any item contains an image
+ */
+ private boolean itemsContainImage() {
+ for (final DLItem item : this.items) {
+ if (item.getImage() != null) {
+ return true;
+ }
+ }
+
+ for (final DLItem item : this.selection) {
+ if (item.getImage() != null) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Sets the item in the receiver's list at the given zero-relative index to
+ * the item argument.
+ *
+ * @param index the index for the item
+ * @param item the new item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setItem(final int index, final DLItem item) {
+ this.checkWidget();
+ if (item == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (index <= 0 || index >= this.items.size()) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ this.items.set(index, item);
+ this.redrawTables();
+ }
+
+ /**
+ * Sets the receiver's items to be the given array of items.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the items array is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if an item in the items array
+ * is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setItems(final DLItem[] items) {
+ this.checkWidget();
+ if (items == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ final List<DLItem> temp = new ArrayList<DLItem>();
+ for (final DLItem item : items) {
+ if (item == null) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ temp.add(item);
+ }
+ this.items.clear();
+ this.items.addAll(temp);
+ this.redrawTables();
+ }
+
+ /**
+ * Sets the receiver's items to be the given list of items.
+ *
+ * @param items the list of items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the items list is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if an item in the items list
+ * is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setItems(final List<DLItem> items) {
+ this.checkWidget();
+ this.checkWidget();
+ if (items == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ final List<DLItem> temp = new ArrayList<DLItem>();
+ for (final DLItem item : items) {
+ if (item == null) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ temp.add(item);
+ }
+ this.items.clear();
+ this.items.addAll(temp);
+ this.redrawTables();
+ }
+
+ /**
+ * Redraws all tables that compose this widget
+ */
+ private void redrawTables() {
+ this.setRedraw(false);
+ this.redrawTable(this.itemsTable, false);
+ this.redrawTable(this.selectionTable, true);
+ this.setRedraw(true);
+ this.setBounds(this.getBounds());
+ }
+
+ /**
+ * Redraw a given table
+ *
+ * @param table table to be redrawned
+ * @param isSelected if <code>true</code>, fill the table with the
+ * selection. Otherwise, fill the table with the unselected
+ * items.
+ */
+ private void redrawTable(final Table table, final boolean isSelected) {
+ this.clean(table);
+ this.fillData(table, isSelected ? this.selection : this.items);
+ }
+
+ /**
+ * Cleans the content of a table
+ *
+ * @param table table to be emptied
+ */
+ private void clean(final Table table) {
+ if (table == null) {
+ return;
+ }
+
+ for (final TableItem item : table.getItems()) {
+ item.dispose();
+ }
+ }
+
+ /**
+ * Fill a table with data
+ *
+ * @param table table to be filled
+ * @param listOfData list of data
+ */
+ private void fillData(final Table table, final List<DLItem> listOfData) {
+ for (final DLItem item : listOfData) {
+ final TableItem tableItem = new TableItem(table, SWT.NONE);
+ tableItem.setData(item);
+
+ if (item.getBackground() != null) {
+ tableItem.setBackground(item.getBackground());
+ }
+
+ if (item.getForeground() != null) {
+ tableItem.setForeground(item.getForeground());
+ }
+
+ if (item.getImage() != null) {
+ tableItem.setImage(0, item.getImage());
+ }
+
+ if (item.getFont() != null) {
+ tableItem.setFont(item.getFont());
+ }
+
+ tableItem.setText(1, item.getText());
+ }
+
+ }
+
+ /**
+ * Move the selected item to the first position
+ */
+ protected void moveSelectionToFirstPosition() {
+ if (this.selectionTable.getSelectionCount() == 0) {
+ return;
+ }
+
+ int index = 0;
+ for (final TableItem tableItem : this.selectionTable.getSelection()) {
+ final DLItem item = (DLItem) tableItem.getData();
+ this.selection.remove(item);
+ this.selection.add(index++, item);
+ }
+
+ this.redrawTables();
+ this.selectionTable.select(0, index - 1);
+ this.selectionTable.forceFocus();
+ }
+
+ /**
+ * Select a given item
+ */
+ protected void selectItem() {
+ if (this.itemsTable.getSelectionCount() == 0) {
+ return;
+ }
+ for (final TableItem tableItem : this.itemsTable.getSelection()) {
+ final DLItem item = (DLItem) tableItem.getData();
+ this.selection.add(item);
+ this.items.remove(item);
+ }
+ this.redrawTables();
+ }
+
+ /**
+ * Move the selected item up
+ */
+ protected void moveUpItem() {
+ if (this.selectionTable.getSelectionCount() == 0) {
+ return;
+ }
+
+ for (final int index : this.selectionTable.getSelectionIndices()) {
+ if (index == 0) {
+ this.selectionTable.forceFocus();
+ return;
+ }
+ }
+
+ final int[] newSelection = new int[this.selectionTable.getSelectionCount()];
+ int newSelectionIndex = 0;
+ for (final TableItem tableItem : this.selectionTable.getSelection()) {
+ final int position = this.selection.indexOf(tableItem.getData());
+ this.swap(position, position - 1);
+ newSelection[newSelectionIndex++] = position - 1;
+ }
+
+ this.redrawTables();
+ this.selectionTable.select(newSelection);
+ this.selectionTable.forceFocus();
+ }
+
+ /**
+ * Deselect a given item
+ */
+ protected void deselectItem() {
+ if (this.selectionTable.getSelectionCount() == 0) {
+ return;
+ }
+ for (final TableItem tableItem : this.selectionTable.getSelection()) {
+ final DLItem item = (DLItem) tableItem.getData();
+ this.items.add(item);
+ this.selection.remove(item);
+ }
+ this.redrawTables();
+ }
+
+ /**
+ * Move the selected item down
+ */
+ protected void moveDownItem() {
+ if (this.selectionTable.getSelectionCount() == 0) {
+ return;
+ }
+
+ for (final int index : this.selectionTable.getSelectionIndices()) {
+ if (index == this.selectionTable.getItemCount() - 1) {
+ this.selectionTable.forceFocus();
+ return;
+ }
+ }
+
+ final int[] newSelection = new int[this.selectionTable.getSelectionCount()];
+ int newSelectionIndex = 0;
+ for (final TableItem tableItem : this.selectionTable.getSelection()) {
+ final int position = this.selection.indexOf(tableItem.getData());
+ this.swap(position, position + 1);
+ newSelection[newSelectionIndex++] = position + 1;
+ }
+
+ this.redrawTables();
+ this.selectionTable.select(newSelection);
+ this.selectionTable.forceFocus();
+
+ }
+
+ /**
+ * Swap 2 items
+ *
+ * @param first position of the first item to swap
+ * @param second position of the second item to swap
+ */
+ private void swap(final int first, final int second) {
+ final DLItem temp = this.selection.get(first);
+ this.selection.set(first, this.selection.get(second));
+ this.selection.set(second, temp);
+ }
+
+ /**
+ * Move the selected item to the last position
+ */
+ protected void moveSelectionToLastPosition() {
+ if (this.selectionTable.getSelectionCount() == 0) {
+ return;
+ }
+
+ final int numberOfSelectedElements = this.selectionTable.getSelectionCount();
+ for (final TableItem tableItem : this.selectionTable.getSelection()) {
+ final DLItem item = (DLItem) tableItem.getData();
+ this.selection.remove(item);
+ this.selection.add(item);
+ }
+
+ this.redrawTables();
+ final int numberOfElements = this.selectionTable.getItemCount();
+ this.selectionTable.select(numberOfElements - numberOfSelectedElements, numberOfElements - 1);
+ this.selectionTable.forceFocus();
+ }
+
+ /**
+ * Call all selection listeners
+ *
+ * @param item selected item
+ */
+ private void fireEvents(final DLItem item) {
+ if (this.eventTable == null) {
+ return;
+ }
+
+ final Event event = new Event();
+ event.button = 1;
+ event.display = this.getDisplay();
+ event.item = null;
+ event.widget = this;
+ event.data = item;
+ final SelectionEvent selectionEvent = new SelectionEvent(event);
+
+ for (final SelectionListener listener : this.eventTable) {
+ listener.widgetSelected(selectionEvent);
+ }
+
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/launcher/LLabel.java b/org.tizen.common.externals/src/org/mihalis/opal/launcher/LLabel.java
new file mode 100644
index 000000000..d6aa5e577
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/launcher/LLabel.java
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.launcher;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instance of this class are a button with text, image and a nice animation
+ * effect
+ */
+class LLabel extends Canvas {
+
+ private String text;
+ private Image image;
+ private Font font;
+
+ private static final int GAP = 12;
+ private static int DRAW_FLAGS = SWT.DRAW_MNEMONIC | SWT.DRAW_TAB | SWT.DRAW_TRANSPARENT | SWT.DRAW_DELIMITER;
+ private static final int DEFAULT_MARGIN = 5;
+ private final int leftMargin = DEFAULT_MARGIN;
+ private final int topMargin = DEFAULT_MARGIN;
+ private final int rightMargin = DEFAULT_MARGIN;
+ private final int bottomMargin = DEFAULT_MARGIN;
+ private Point textSize;
+
+ private static final int MAX_NUMBER_OF_STEPS = 10;
+ private int animationStep = 0;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ */
+ LLabel(final Composite parent, final int style) {
+ super(parent, style | SWT.BORDER | SWT.DOUBLE_BUFFERED);
+
+ final Font original = super.getFont();
+
+ this.font = new Font(getDisplay(), original.getFontData()[0].getName(), 18, SWT.BOLD);
+
+ addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(final PaintEvent event) {
+ onPaint(event);
+ }
+ });
+
+ addListener(SWT.Dispose, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ onDispose(event);
+ }
+ });
+ }
+
+ /**
+ * Draw the content of the LLabel
+ *
+ * @param event paintevent
+ */
+ private void onPaint(final PaintEvent event) {
+ final Rectangle rect = getClientArea();
+ if (rect.width == 0 || rect.height == 0) {
+ return;
+ }
+
+ final Image bufferImage = new Image(getDisplay(), Math.max(1, rect.width), Math.max(1, rect.height));
+
+ final GC gc = new GC(bufferImage);
+ gc.setForeground(getForeground());
+ gc.setBackground(getBackground());
+
+ gc.fillRectangle(rect);
+
+ final Point extent = getTotalSize(this.image.getBounds().width, this.image.getBounds().height);
+ final int xImage = (rect.width - this.image.getBounds().width) / 2;
+ final int yImage = (rect.height - extent.y) / 2;
+ gc.drawImage(this.image, xImage, yImage);
+
+ gc.setFont(this.font);
+ final int xText = (rect.width - this.textSize.x) / 2;
+ final int yText = yImage + this.image.getBounds().height + GAP - this.textSize.y / 2;
+ gc.drawString(this.text, xText, yText);
+
+ if (this.animationStep != 0) {
+ final float zoom = 1f + this.animationStep * (Math.max(extent.x, extent.y) - Math.max(this.image.getBounds().width, this.image.getBounds().height)) / MAX_NUMBER_OF_STEPS / 100f;
+
+ final int newSizeX = (int) (this.image.getBounds().width * zoom);
+ final int newSizeY = (int) (this.image.getBounds().height * zoom);
+
+ gc.setAntialias(SWT.ON);
+ gc.setInterpolation(SWT.HIGH);
+
+ gc.setAlpha(255 - 255 / MAX_NUMBER_OF_STEPS * this.animationStep);
+
+ final Point extentZoomedImage = getTotalSize(newSizeX, newSizeY);
+ final int xZoomedImage = (rect.width - newSizeX) / 2;
+ final int yZoomedImage = (rect.height - extentZoomedImage.y) / 2;
+ gc.drawImage(this.image, 0, 0, this.image.getBounds().width, this.image.getBounds().height, xZoomedImage, yZoomedImage, (int) (this.image.getBounds().width * zoom), (int) (this.image.getBounds().height * zoom));
+
+ }
+
+ gc.dispose();
+
+ event.gc.drawImage(bufferImage, 0, 0);
+
+ bufferImage.dispose();
+
+ }
+
+ /**
+ * Dispose elements when the widget is disposed
+ *
+ * @param event dispose event
+ */
+ private void onDispose(final Event event) {
+ SWTGraphicUtil.dispose(this.image);
+ SWTGraphicUtil.dispose(this.font);
+ this.text = null;
+ this.image = null;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
+ */
+ @Override
+ public Point computeSize(final int wHint, final int hHint, final boolean changed) {
+ checkWidget();
+ final Point e = getTotalSize(this.image.getBounds().width, this.image.getBounds().height);
+ if (wHint == SWT.DEFAULT) {
+ e.x += this.leftMargin + this.rightMargin;
+ } else {
+ e.x = wHint;
+ }
+ if (hHint == SWT.DEFAULT) {
+ e.y += this.topMargin + this.bottomMargin;
+ } else {
+ e.y = hHint;
+ }
+ return e;
+ }
+
+ /**
+ * Compute the size of the content (image + text + gap)
+ *
+ * @param imgWidth image width
+ * @param imgHeight image height
+ * @return the size of the content
+ */
+ private Point getTotalSize(final int imgWidth, final int imgHeight) {
+ final Point size = new Point(0, 0);
+
+ int textWidth = 0;
+ int textHeight = 0;
+
+ if (this.textSize == null) {
+ final GC gc = new GC(this);
+ gc.setFont(this.font);
+
+ this.textSize = gc.textExtent(this.text, DRAW_FLAGS);
+ gc.dispose();
+
+ }
+ textWidth = this.textSize.x;
+ textHeight = this.textSize.y;
+
+ size.x = Math.max(imgWidth, textWidth);
+ size.y = imgHeight + GAP + textHeight;
+
+ return size;
+ }
+
+ /**
+ * @return the text
+ */
+ String getText() {
+ return this.text;
+ }
+
+ /**
+ * @param text the text to set
+ */
+ void setText(final String text) {
+ this.text = text;
+ }
+
+ /**
+ * @return the image
+ */
+ Image getImage() {
+ return this.image;
+ }
+
+ /**
+ * @param image the image to set
+ */
+ void setImage(final Image image) {
+ this.image = image;
+ }
+
+ /**
+ * @return the font
+ */
+ @Override
+ public Font getFont() {
+ return this.font;
+ }
+
+ /**
+ * @param font the font to set
+ */
+ @Override
+ public void setFont(final Font font) {
+ SWTGraphicUtil.dispose(font);
+ this.font = font;
+ }
+
+ /**
+ * Increment the steps of the animation
+ *
+ * @return true if animation keeps running, false otherwise
+ */
+ boolean incrementAnimation() {
+ this.animationStep++;
+ final boolean stopAnimation = this.animationStep > MAX_NUMBER_OF_STEPS;
+
+ if (stopAnimation) {
+ this.animationStep = 0;
+ }
+ if (!isDisposed()) {
+ redraw();
+ }
+ return !stopAnimation;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/launcher/Launcher.java b/org.tizen.common.externals/src/org/mihalis/opal/launcher/Launcher.java
new file mode 100755
index 000000000..42bf7b1f8
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/launcher/Launcher.java
@@ -0,0 +1,428 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.launcher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are a launcher composed of buttons. When one clicks
+ * on the button, an animation is started and a selection event is fired
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ */
+public class Launcher extends Composite {
+
+ private final List<LauncherItem> items;
+ private final List<SelectionListener> selectionListeners;
+ private boolean needRedraw;
+ private int selection = -1;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ */
+ public Launcher(final Composite parent, final int style) {
+ super(parent, style | SWT.BORDER);
+ this.items = new ArrayList<LauncherItem>();
+ this.selectionListeners = new ArrayList<SelectionListener>();
+ this.needRedraw = true;
+ setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+
+ this.addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ drawLauncher();
+ }
+ });
+
+ this.addListener(SWT.KeyUp, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ OnKeyPressed(event);
+ }
+ });
+
+ }
+
+ /**
+ * Draw the launcher
+ */
+ private void drawLauncher() {
+ if (!this.needRedraw) {
+ return;
+ }
+
+ disposePreviousContent();
+ createButtons();
+ pack();
+
+ this.needRedraw = false;
+ }
+
+ /**
+ * Dispose the content before a redraw
+ */
+ private void disposePreviousContent() {
+ for (final Control c : this.getChildren()) {
+ c.dispose();
+ }
+ }
+
+ /**
+ * Create the buttons that will compose the launcher
+ */
+ private void createButtons() {
+ final GridLayout gridLayout = new GridLayout(this.items.size() / 2, true);
+ gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
+ this.setLayout(gridLayout);
+ for (final LauncherItem item : this.items) {
+ final LLabel label = new LLabel(this, SWT.CENTER);
+ label.setText(item.title);
+ label.setImage(SWTGraphicUtil.createImage(item.image));
+ label.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, false);
+ gd.widthHint = 192;
+ gd.heightHint = 220;
+ label.setLayoutData(gd);
+ item.label = label;
+
+ label.addListener(SWT.KeyUp, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ OnKeyPressed(event);
+ }
+ });
+
+ label.addListener(SWT.MouseUp, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ OnClick(event);
+ }
+ });
+
+ label.addListener(SWT.MouseDoubleClick, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ OnDoubleClick(event);
+ }
+ });
+
+ }
+ }
+
+ /**
+ * Code executed when a key is pressed
+ *
+ * @param event Event
+ */
+ private void OnKeyPressed(final Event event) {
+ switch (event.keyCode) {
+ case SWT.ARROW_LEFT:
+ if (this.selection == -1) {
+ this.selection = 0;
+ changeColor(this.selection, true);
+ return;
+ }
+
+ if (this.selection % 2 == 1) {
+ changeColor(this.selection, false);
+ this.selection--;
+ changeColor(this.selection, true);
+ }
+ break;
+ case SWT.ARROW_UP:
+ if (this.selection == -1) {
+ this.selection = 0;
+ changeColor(this.selection, true);
+ return;
+ }
+ if (this.selection >= 2) {
+ changeColor(this.selection, false);
+ this.selection -= 2;
+ changeColor(this.selection, true);
+ }
+ break;
+ case SWT.ARROW_RIGHT:
+ if (this.selection == -1) {
+ this.selection = 0;
+ changeColor(this.selection, true);
+ return;
+ }
+ if (this.selection % 2 == 0) {
+ changeColor(this.selection, false);
+ this.selection++;
+ changeColor(this.selection, true);
+ }
+ break;
+ case SWT.ARROW_DOWN:
+ if (this.selection == -1) {
+ this.selection = 0;
+ changeColor(this.selection, true);
+ return;
+ }
+ if (this.selection <= this.items.size() - 2) {
+ changeColor(this.selection, false);
+ this.selection += 2;
+ changeColor(this.selection, true);
+ }
+ break;
+ case SWT.HOME:
+ changeColor(this.selection, false);
+ this.selection = 0;
+ changeColor(this.selection, true);
+ break;
+ case SWT.END:
+ changeColor(this.selection, false);
+ this.selection = this.items.size() - 1;
+ changeColor(this.selection, true);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ /**
+ * Code executed when one clicks on the button
+ *
+ * @param event Event
+ */
+ private void OnClick(final Event event) {
+ for (int i = 0; i < this.items.size(); i++) {
+ final LauncherItem item = this.items.get(i);
+ if (item.label != null && item.label.equals(event.widget)) {
+ if (this.selection != i) {
+ changeColor(this.selection, false);
+ this.selection = i;
+ changeColor(this.selection, true);
+ }
+ return;
+ }
+ }
+ }
+
+ /**
+ * Change the background color of a given button
+ *
+ * @param index index of the button
+ * @param isSelected if <code>true</code>, the background is the light
+ * shadow. Otherwise, the background color is white
+ */
+ private void changeColor(final int index, final boolean isSelected) {
+ if (index != -1 && this.items.get(index).label != null) {
+ this.items.get(index).label.setBackground(isSelected ? getDisplay().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW) : getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ }
+ }
+
+ /**
+ * Code executed when one double-clicks on a button
+ *
+ * @param event Event
+ */
+ private void OnDoubleClick(final Event event) {
+ for (int i = 0; i < this.items.size(); i++) {
+ final LauncherItem item = this.items.get(i);
+ if (item.label != null && item.label.equals(event.widget)) {
+ if (this.selection != i) {
+ changeColor(this.selection, false);
+ this.selection = i;
+ changeColor(this.selection, true);
+ }
+ startAnimation(i, event);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Start the animation for a given button
+ *
+ * @param index index of the selected button
+ * @param event event (propagated to the selection listeners)
+ */
+ private void startAnimation(final int index, final Event event) {
+ final LLabel label = this.items.get(index).label;
+ getDisplay().timerExec(0, new Runnable() {
+
+ @Override
+ public void run() {
+ if (label.incrementAnimation()) {
+ getDisplay().timerExec(20, this);
+ } else {
+ fireSelectionListeners(event);
+ }
+ }
+ });
+
+ }
+
+ /**
+ * Fire the selection listeners
+ *
+ * @param originalEvent mouse event
+ * @return <code>true</code> if the selection could be changed,
+ * <code>false</code> otherwise
+ */
+ private boolean fireSelectionListeners(final Event originalEvent) {
+ for (final SelectionListener listener : this.selectionListeners) {
+ final Event event = new Event();
+
+ event.button = originalEvent.button;
+ event.display = this.getDisplay();
+ event.item = null;
+ event.widget = this;
+ event.data = null;
+ event.time = originalEvent.time;
+ event.x = originalEvent.x;
+ event.y = originalEvent.y;
+
+ final SelectionEvent selEvent = new SelectionEvent(event);
+ listener.widgetSelected(selEvent);
+ if (!selEvent.doit) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Add an item to the launcher
+ *
+ * @param title text associated to this item
+ * @param image image associated to this item
+ */
+ public void addItem(final String title, final String image) {
+ checkWidget();
+ this.items.add(new LauncherItem(title, image));
+ this.needRedraw = true;
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified
+ * when the control is selected by the user, by sending it one of the
+ * messages defined in the <code>SelectionListener</code> interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the control is selected by the
+ * user. <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ this.selectionListeners.add(listener);
+
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be
+ * notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ this.selectionListeners.remove(listener);
+ }
+
+ /**
+ * Return the selected button
+ *
+ * @return the index of the selected button
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ */
+ public int getSelection() {
+ checkWidget();
+ return this.selection;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/launcher/LauncherItem.java b/org.tizen.common.externals/src/org/mihalis/opal/launcher/LauncherItem.java
new file mode 100644
index 000000000..bb5dc13db
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/launcher/LauncherItem.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.launcher;
+
+/**
+ * Instances of this class are POJO to store information handled by the Launcher
+ * widget I could have used a inner class but I prefer this solution :)
+ */
+class LauncherItem {
+ String title;
+ String image;
+ LLabel label;
+
+ /**
+ * Constructor
+ *
+ * @param title text associated to the item
+ * @param image image associated to the item
+ */
+ LauncherItem(final String title, final String image) {
+ this.title = title;
+ this.image = image;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/login/LoginDialog.java b/org.tizen.common.externals/src/org/mihalis/opal/login/LoginDialog.java
new file mode 100644
index 000000000..b811971ab
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/login/LoginDialog.java
@@ -0,0 +1,511 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.login;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Path;
+import org.eclipse.swt.graphics.Pattern;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.mihalis.opal.opalDialog.Dialog;
+import org.mihalis.opal.utils.ResourceManager;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are Login Dialog box, which is composed of
+ * <p>
+ * <dl>
+ * <dt><b>A login</b></dt>
+ * <dt><b>A password</b></dt>
+ * <dt><b>An image</b></dt>
+ * <dd>(optional)</dd>
+ * <dt><b>A description</b></dt>
+ * <dd>(optional)</dd>
+ * <dt><b>A checkbox "remember the password"</b></dt>
+ * <dd>(optional)</dd>
+ * </dl>
+ * </p>
+ */
+public class LoginDialog {
+ private Image image;
+ private String description;
+ private String login;
+ private String password;
+ private List<String> autorizedLogin;
+ private boolean displayRememberPassword;
+ private boolean rememberPassword;
+ private LoginDialogVerifier verifier;
+
+ private Shell shell;
+ private boolean returnedValue;
+ private Button buttonOk;
+
+ /**
+ * Constructor
+ */
+ public LoginDialog() {
+ this.displayRememberPassword = true;
+ }
+
+ /**
+ * Open the Login box
+ *
+ * @return <code>true</code> if the authentication is OK, <code>false</code>
+ * if the user pressed on cancel.
+ */
+ public boolean open() {
+ if (this.verifier == null) {
+ throw new IllegalArgumentException("Please set a verifier before opening the dialog box");
+ }
+
+ buildDialog();
+ openShell();
+
+ return this.returnedValue;
+ }
+
+ /**
+ * Build the dialog box
+ */
+ private void buildDialog() {
+ buildShell();
+ buildImage();
+ buildDescription();
+ buildLogin();
+ buildPassword();
+ if (this.displayRememberPassword) {
+ buildRememberPassword();
+ }
+ buildButtons();
+ }
+
+ /**
+ * Build the shell
+ */
+ private void buildShell() {
+ this.shell = new Shell(SWT.SYSTEM_MODAL | SWT.TITLE | SWT.BORDER);
+ this.shell.setText(ResourceManager.getLabel(ResourceManager.LOGIN));
+ this.shell.setLayout(new GridLayout(4, false));
+ }
+
+ /**
+ * Build the image on top of the login box. If no image has been set, create
+ * a default image
+ */
+ private void buildImage() {
+ final Canvas canvas = new Canvas(this.shell, SWT.DOUBLE_BUFFERED);
+ final GridData gridData = new GridData(GridData.FILL, GridData.FILL, true, false, 4, 1);
+ gridData.widthHint = 400;
+ gridData.heightHint = 60;
+ canvas.setLayoutData(gridData);
+ canvas.addPaintListener(new PaintListener() {
+
+ @Override
+ public void paintControl(final PaintEvent e) {
+ e.gc.drawImage(LoginDialog.this.image == null ? createDefaultImage(e.width, e.height) : LoginDialog.this.image, 0, 0);
+ }
+ });
+
+ }
+
+ /**
+ * Create a default image. It is a port of the image used by the Login Box
+ * in the project SwingX
+ *
+ * @param w width
+ * @param h height
+ * @return a default image (blue wave)
+ */
+ private Image createDefaultImage(final int w, final int h) {
+ final Display display = Display.getCurrent();
+ final Color backgroundColor = new Color(display, 49, 121, 242);
+ final Color gradientColor1 = new Color(display, 155, 185, 245);
+ final Color gradientColor2 = new Color(display, 53, 123, 242);
+
+ final Image img = new Image(display, w, h);
+ final GC gc = new GC(img);
+ gc.setAdvanced(true);
+ gc.setAntialias(SWT.ON);
+ gc.setBackground(backgroundColor);
+ gc.fillRectangle(0, 0, w, h);
+
+ final Path curveShape = new Path(display);
+ curveShape.moveTo(0, h * .6f);
+ curveShape.cubicTo(w * .167f, h * 1.2f, w * .667f, h * -.5f, w, h * .75f);
+ curveShape.lineTo(w, h);
+ curveShape.lineTo(0, h);
+ curveShape.lineTo(0, h * .8f);
+ curveShape.close();
+
+ final Pattern pattern = new Pattern(display, 0, 0, 1, h * 1.2f, gradientColor1, gradientColor2);
+ gc.setBackgroundPattern(pattern);
+ gc.fillPath(curveShape);
+
+ final Font font = new Font(display, "Arial Bold", 30, SWT.NONE);
+ gc.setFont(font);
+ gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+ final Point textSize = gc.stringExtent(ResourceManager.getLabel(ResourceManager.LOGIN));
+ gc.drawString(ResourceManager.getLabel(ResourceManager.LOGIN), (int) (w * .05f), (h - textSize.y) / 2, true);
+
+ font.dispose();
+ curveShape.dispose();
+ pattern.dispose();
+ backgroundColor.dispose();
+ gradientColor1.dispose();
+ gradientColor2.dispose();
+ gc.dispose();
+ return img;
+ }
+
+ /**
+ * Build the description part of the box
+ */
+ private void buildDescription() {
+ final Label label = new Label(this.shell, SWT.NONE);
+ final GridData gridData = new GridData(GridData.FILL, GridData.BEGINNING, true, false, 4, 1);
+ gridData.verticalIndent = 5;
+ gridData.horizontalIndent = 5;
+ label.setLayoutData(gridData);
+ final Font bold = SWTGraphicUtil.buildFontFrom(label, SWT.BOLD);
+ label.setFont(bold);
+ label.addListener(SWT.Dispose, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ SWTGraphicUtil.dispose(bold);
+ }
+ });
+
+ if (this.description == null || this.description.trim().equals("")) {
+ label.setText(" ");
+ } else {
+ label.setText(this.description);
+ }
+ }
+
+ /**
+ * Build the login part of the box
+ */
+ private void buildLogin() {
+ final Label label = new Label(this.shell, SWT.NONE);
+ final GridData gridData = new GridData(GridData.END, GridData.END, false, false, 1, 1);
+ gridData.horizontalIndent = 35;
+ gridData.verticalIndent = 15;
+ label.setLayoutData(gridData);
+ label.setText(ResourceManager.getLabel(ResourceManager.NAME));
+
+ if (this.autorizedLogin != null && !this.autorizedLogin.isEmpty()) {
+ // Combo
+ final Combo combo = new Combo(this.shell, SWT.BORDER | SWT.READ_ONLY);
+
+ combo.setLayoutData(new GridData(GridData.FILL, GridData.END, true, false, 3, 1));
+ for (final String loginToAdd : this.autorizedLogin) {
+ combo.add(loginToAdd);
+ }
+ combo.setText(this.login == null ? "" : this.login);
+ combo.setFocus();
+ combo.addModifyListener(new ModifyListener() {
+
+ @Override
+ public void modifyText(final ModifyEvent e) {
+ LoginDialog.this.login = combo.getText();
+ changeButtonOkState();
+ }
+ });
+ } else {
+ // Text
+ final Text text = new Text(this.shell, SWT.BORDER);
+ text.setText(this.login == null ? "" : this.login);
+ text.setLayoutData(new GridData(GridData.FILL, GridData.END, true, false, 3, 1));
+ text.setFocus();
+ text.addModifyListener(new ModifyListener() {
+
+ @Override
+ public void modifyText(final ModifyEvent e) {
+ LoginDialog.this.login = text.getText();
+ changeButtonOkState();
+ }
+ });
+ }
+
+ }
+
+ /**
+ * Build the password part of the box
+ */
+ private void buildPassword() {
+ final Label label = new Label(this.shell, SWT.NONE);
+ final GridData gridData = new GridData(GridData.END, GridData.CENTER, false, false, 1, 1);
+ gridData.horizontalIndent = 35;
+ label.setLayoutData(gridData);
+ label.setText(ResourceManager.getLabel(ResourceManager.PASSWORD));
+
+ final Text text = new Text(this.shell, SWT.PASSWORD | SWT.BORDER);
+ text.setText(this.password == null ? "" : this.password);
+ text.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
+ text.addModifyListener(new ModifyListener() {
+
+ @Override
+ public void modifyText(final ModifyEvent e) {
+ LoginDialog.this.password = text.getText();
+ changeButtonOkState();
+ }
+ });
+
+ }
+
+ /**
+ * Enable/Disable the button when the login and the password is empty (or
+ * not)
+ */
+ private void changeButtonOkState() {
+ final boolean loginEntered = this.login != null && !this.login.trim().equals("");
+ final boolean passwordEntered = this.password != null && !this.password.trim().equals("");
+ this.buttonOk.setEnabled(loginEntered && passwordEntered);
+
+ }
+
+ /**
+ * Build the "remember password" part of the box
+ */
+ private void buildRememberPassword() {
+ final Button checkbox = new Button(this.shell, SWT.CHECK);
+ final GridData gridData = new GridData(GridData.BEGINNING, GridData.CENTER, true, false, 4, 1);
+ gridData.horizontalIndent = 35;
+ checkbox.setLayoutData(gridData);
+ checkbox.setText(ResourceManager.getLabel(ResourceManager.REMEMBER_PASSWORD));
+ checkbox.setSelection(this.rememberPassword);
+
+ }
+
+ /**
+ * Build the buttons
+ */
+ private void buildButtons() {
+ this.buttonOk = new Button(this.shell, SWT.PUSH);
+ final GridData gdOk = new GridData(GridData.END, GridData.CENTER, true, false, 3, 1);
+ gdOk.verticalIndent = 60;
+ gdOk.minimumWidth = 80;
+ this.buttonOk.setLayoutData(gdOk);
+ this.buttonOk.setText(ResourceManager.getLabel(ResourceManager.OK));
+ this.buttonOk.setEnabled(false);
+
+ this.buttonOk.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent selectionEvent) {
+ try {
+ LoginDialog.this.verifier.authenticate(LoginDialog.this.login, LoginDialog.this.password);
+ LoginDialog.this.returnedValue = true;
+ LoginDialog.this.shell.dispose();
+ } catch (final Exception e) {
+ Dialog.error(ResourceManager.getLabel(ResourceManager.LOGIN_FAILED), e.getMessage());
+ for (final Control control : LoginDialog.this.shell.getChildren()) {
+ if (control instanceof Text || control instanceof Combo) {
+ control.setFocus();
+ break;
+ }
+ }
+
+ }
+ }
+
+ });
+
+ final Button buttonCancel = new Button(this.shell, SWT.PUSH);
+ final GridData gdCancel = new GridData(GridData.FILL, GridData.CENTER, false, false);
+ gdCancel.widthHint = 80;
+ gdCancel.verticalIndent = 60;
+ buttonCancel.setLayoutData(gdCancel);
+ buttonCancel.setText(ResourceManager.getLabel(ResourceManager.CANCEL));
+ buttonCancel.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ LoginDialog.this.returnedValue = false;
+ LoginDialog.this.shell.dispose();
+ }
+
+ });
+
+ }
+
+ /**
+ * Open the shell
+ */
+ private void openShell() {
+ this.shell.setDefaultButton(this.buttonOk);
+ this.shell.pack();
+ this.shell.open();
+ SWTGraphicUtil.centerShell(this.shell);
+
+ while (!this.shell.isDisposed()) {
+ if (!this.shell.getDisplay().readAndDispatch()) {
+ this.shell.getDisplay().sleep();
+ }
+ }
+ }
+
+ // ------------- Getters & Setters
+ /**
+ * @return the image
+ */
+ public Image getImage() {
+ return this.image;
+ }
+
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * @return the login
+ */
+ public String getLogin() {
+ return this.login == null ? null : this.login.trim();
+ }
+
+ /**
+ * @return the password
+ */
+ public String getPassword() {
+ return this.password == null ? null : this.password.trim();
+ }
+
+ /**
+ * @return the list of autorized logins
+ */
+ public List<String> getAutorizedLogin() {
+ return this.autorizedLogin;
+ }
+
+ /**
+ * @return <code>true</code> if the checkbox "remember the password" is
+ * displayed, <code>false</code> otherwise
+ */
+ public boolean isDisplayRememberPassword() {
+ return this.displayRememberPassword;
+ }
+
+ /**
+ * @return <code>true</code> if the checkbox "remember the password" is
+ * checked, <code>false</code> otherwise
+ */
+ public boolean isRememberPassword() {
+ return this.rememberPassword;
+ }
+
+ /**
+ * @return the verifier associated to this box
+ */
+ public LoginDialogVerifier getVerifier() {
+ return this.verifier;
+ }
+
+ /**
+ * @param image the image to set
+ */
+ public void setImage(final Image image) {
+ this.image = image;
+ }
+
+ /**
+ * @param description the description to set
+ */
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ /**
+ * @param login the login to set
+ */
+ public void setLogin(final String login) {
+ this.login = login;
+ }
+
+ /**
+ * @param password the password to set
+ */
+ public void setPassword(final String password) {
+ this.password = password;
+ }
+
+ /**
+ * @param autorizedLogin the list of autorized logins to set
+ */
+ public void setAutorizedLogin(final List<String> autorizedLogin) {
+ this.autorizedLogin = autorizedLogin;
+ }
+
+ /**
+ * @param autorizedLogin the list of autorized logins to set
+ */
+ public void setAutorizedLogin(final String... autorizedLogin) {
+ this.autorizedLogin = Arrays.asList(autorizedLogin);
+ }
+
+ /**
+ * @param displayRememberPassword if <code>true</code>, the checkbox
+ * "remember the password" is displayed
+ */
+ public void setDisplayRememberPassword(final boolean displayRememberPassword) {
+ this.displayRememberPassword = displayRememberPassword;
+ }
+
+ /**
+ * @param rememberPassword if <code>true</code>, the checkbox
+ * "remember the password" is selected
+ */
+ public void setRememberPassword(final boolean rememberPassword) {
+ this.rememberPassword = rememberPassword;
+ }
+
+ /**
+ * @param verifier the verifier to set
+ */
+ public void setVerifier(final LoginDialogVerifier verifier) {
+ this.verifier = verifier;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/login/LoginDialogVerifier.java b/org.tizen.common.externals/src/org/mihalis/opal/login/LoginDialogVerifier.java
new file mode 100644
index 000000000..14ec22cb8
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/login/LoginDialogVerifier.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.login;
+
+/**
+ * This interface describes a verifier for the LoginDialogWidget
+ */
+public interface LoginDialogVerifier {
+ /**
+ * Check if the couple login/password is correct
+ *
+ * @param login login entered by the user
+ * @param password password entered by the user
+ * @throws Exception if the couple login/password is wrong. The description
+ * of the exception contains the error message that is gonna be
+ * displayed. For instance, an implementation can throw the
+ * exception *
+ * <code>new Exception("Unable to connect to the LDAP Server")</code>
+ */
+ void authenticate(String login, String password) throws Exception;
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/multiChoice/MultiChoice.java b/org.tizen.common.externals/src/org/mihalis/opal/multiChoice/MultiChoice.java
new file mode 100755
index 000000000..3a5cb0e6b
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/multiChoice/MultiChoice.java
@@ -0,0 +1,1195 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+
+package org.mihalis.opal.multiChoice;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.mihalis.opal.utils.SimpleSelectionAdapter;
+
+/**
+ * The MultiChoice class represents a selectable user interface object that
+ * combines a read-only text-field and a set of checkboxes.
+ *
+ * <p>
+ * Note that although this class is a subclass of <code>Composite</code>, it
+ * does not make sense to add children to it, or set a layout on it.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b>
+ * <dd>NONE</dd>
+ * <dt><b>Events:</b>
+ * <dd>Selection</dd>
+ * </dl>
+ *
+ * @param <T> Class of objects represented by this widget
+ */
+public class MultiChoice<T> extends Composite {
+
+ private Label text;
+ private Button arrow;
+ private Shell popup;
+ private Listener listener, filter;
+ private int numberOfColumns = 2;
+ private List<T> elements;
+ private Set<T> selection;
+ private List<Button> checkboxes;
+ private boolean hasFocus;
+ private MultiChoiceSelectionListener<T> selectionListener;
+ private T lastModified;
+ private Color foreground, background;
+ private Font font;
+ private String separator;
+
+ /**
+ * Constructs a new instance of this class given its parent.
+ *
+ * @param parent a widget which will be the parent of the new instance
+ * (cannot be null)
+ * @param style not used
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ */
+ public MultiChoice(final Composite parent, final int style) {
+ this(parent, style, null);
+ }
+
+ /**
+ * Constructs a new instance of this class given its parent.
+ *
+ * @param parent a widget which will be the parent of the new instance
+ * (cannot be null)
+ * @param style not used
+ * @param elements list of elements displayed by this widget
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ */
+ public MultiChoice(final Composite parent, final int style, final List<T> elements) {
+ super(parent, style);
+
+ final GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginWidth = gridLayout.marginHeight = 0;
+ this.setLayout(gridLayout);
+
+ this.text = new Label(this, SWT.SINGLE | SWT.READ_ONLY | SWT.BORDER);
+ this.text.setBackground(this.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+ this.text.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
+
+ this.arrow = new Button(this, SWT.ARROW | SWT.RIGHT);
+ this.arrow.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false));
+
+ this.listener = new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ if (MultiChoice.this.popup == event.widget) {
+ popupEvent(event);
+ return;
+ }
+
+ if (MultiChoice.this.arrow == event.widget) {
+ buttonEvent(event);
+ return;
+ }
+
+ if (MultiChoice.this == event.widget) {
+ multiChoiceEvent(event);
+ return;
+ }
+
+ if (getShell() == event.widget) {
+ getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (isDisposed()) {
+ return;
+ }
+ handleFocus(SWT.FocusOut);
+ }
+ });
+ }
+ }
+ };
+
+ final int[] multiChoiceEvent = { SWT.Dispose, SWT.Move, SWT.Resize };
+ for (int i = 0; i < multiChoiceEvent.length; i++) {
+ this.addListener(multiChoiceEvent[i], this.listener);
+ }
+
+ final int[] buttonEvents = { SWT.Selection, SWT.FocusIn };
+ for (int i = 0; i < buttonEvents.length; i++) {
+ this.arrow.addListener(buttonEvents[i], this.listener);
+ }
+
+ this.filter = new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ final Shell shell = ((Control) event.widget).getShell();
+ if (shell == MultiChoice.this.getShell()) {
+ handleFocus(SWT.FocusOut);
+ }
+ }
+ };
+
+ this.selection = new LinkedHashSet<T>();
+ this.elements = elements;
+ this.separator = ",";
+
+ createPopup();
+ setLabel();
+ }
+
+ /**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param values new item
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void add(final T value) {
+ checkWidget();
+ if (value == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.elements == null) {
+ this.elements = new ArrayList<T>();
+ }
+ this.elements.add(value);
+ refresh();
+ }
+
+ /**
+ * Adds the argument to the receiver's list at the given zero-relative
+ * index.
+ *
+ * @param values new item
+ * @param index the index for the item
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void add(final T value, final int index) {
+ checkWidget();
+ checkNullElement();
+ if (value == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ checkRange(index);
+
+ this.elements.add(index, value);
+ refresh();
+ }
+
+ /**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param values new items
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void addAll(final List<T> values) {
+ checkWidget();
+ if (values == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (this.elements == null) {
+ this.elements = new ArrayList<T>();
+ }
+ this.elements.addAll(values);
+ refresh();
+ }
+
+ /**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param values new items
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void addAll(final T[] values) {
+ checkWidget();
+ if (values == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (this.elements == null) {
+ this.elements = new ArrayList<T>();
+ }
+ for (final T value : values) {
+ this.elements.add(value);
+ }
+ refresh();
+ }
+
+ /**
+ * Returns the item at the given, zero-relative index in the receiver's
+ * list. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public T getItem(final int index) {
+ checkWidget();
+ checkNullElement();
+ checkRange(index);
+
+ return this.elements.get(index);
+ }
+
+ /**
+ * Returns the number of items contained in the receiver's list.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getItemCount() {
+ checkWidget();
+ if (this.elements == null) {
+ return 0;
+ }
+
+ return this.elements.size();
+
+ }
+
+ /**
+ * Returns the list of items in the receiver's list.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its list of items, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver's list
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public List<T> getItems() {
+ checkWidget();
+ if (this.elements == null) {
+ return null;
+ }
+ return new ArrayList<T>(this.elements);
+ }
+
+ /**
+ * Removes the item from the receiver's list at the given zero-relative
+ * index.
+ *
+ * @param index the index for the item
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void removeAt(final int index) {
+ checkWidget();
+ checkNullElement();
+ checkRange(index);
+ final Object removedElement = this.elements.remove(index);
+ this.selection.remove(removedElement);
+ refresh();
+ }
+
+ /**
+ * Searches the receiver's list starting at the first item until an item is
+ * found that is equal to the argument, and removes that item from the list.
+ *
+ * @param object the item to remove
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the object is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void remove(final T object) {
+ if (object == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ checkWidget();
+ checkNullElement();
+ this.elements.remove(object);
+ this.selection.remove(object);
+ refresh();
+ }
+
+ /**
+ * Remove all items of the receiver
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void removeAll() {
+ checkWidget();
+ checkNullElement();
+ if (this.elements != null) {
+ this.elements.clear();
+ }
+ this.selection.clear();
+ refresh();
+ }
+
+ /**
+ * Sets the selection of the receiver. If the item was already selected, it
+ * remains selected.
+ *
+ * @param selection the new selection
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the selection is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+
+ public void setSelection(final Set<T> selection) {
+ checkWidget();
+ checkNullElement();
+ if (selection == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ this.selection = selection;
+ updateSelection();
+ }
+
+ /**
+ * Selects all selected items in the receiver's list.
+ *
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void selectAll() {
+ checkWidget();
+ checkNullElement();
+ this.selection.addAll(this.elements);
+ updateSelection();
+ }
+
+ /**
+ * Selects the item at the given zero-relative index in the receiver's list.
+ * If the item at the index was already selected, it remains selected.
+ *
+ * @param index the index of the item to select
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void selectAt(final int index) {
+ checkWidget();
+ checkNullElement();
+ checkRange(index);
+ this.selection.add(this.elements.get(index));
+ updateSelection();
+ }
+
+ /**
+ * Selects an item the receiver's list. If the item was already selected, it
+ * remains selected.
+ *
+ * @param index the index of the item to select
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the selection is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void select(final T value) {
+ checkWidget();
+ checkNullElement();
+ if (!this.elements.contains(value)) {
+ throw new IllegalArgumentException("Value not present in the widget");
+ }
+ this.selection.add(value);
+ updateSelection();
+ }
+
+ /**
+ * Selects items in the receiver. If the items were already selected, they
+ * remain selected.
+ *
+ * @param index the indexes of the items to select
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the selection is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelectedIndex(final int[] index) {
+ checkWidget();
+ checkNullElement();
+ for (final int i : index) {
+ checkRange(i);
+ this.selection.add(this.elements.get(i));
+ }
+ updateSelection();
+ }
+
+ /**
+ * Returns the zero-relative indices of the items which are currently
+ * selected in the receiver. The order of the indices is unspecified. The
+ * array is empty if no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its selection, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return the array of indices of the selected items
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int[] getSelectedIndex() {
+ checkWidget();
+ checkNullElement();
+ final List<Integer> selectedIndex = new ArrayList<Integer>();
+ for (int i = 0; i < this.elements.size(); i++) {
+ if (this.selection.contains(this.elements.get(i))) {
+ selectedIndex.add(i);
+ }
+ }
+
+ final int[] returned = new int[selectedIndex.size()];
+ for (int i = 0; i < selectedIndex.size(); i++) {
+ returned[i] = selectedIndex.get(i);
+ }
+
+ return returned;
+ }
+
+ /**
+ * Returns an array of <code>Object</code>s that are currently selected in
+ * the receiver. The order of the items is unspecified. An empty array
+ * indicates that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its selection, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return an array representing the selection
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public List<T> getSelection() {
+ checkWidget();
+ checkNullElement();
+ return new ArrayList<T>(this.selection);
+ }
+
+ /**
+ * Deselects the item at the given zero-relative index in the receiver's
+ * list. If the item at the index was already deselected, it remains
+ * deselected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void deselectAt(final int index) {
+ checkWidget();
+ checkNullElement();
+
+ if (index < 0 || index >= this.elements.size()) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+
+ this.selection.remove(index);
+ updateSelection();
+ }
+
+ /**
+ * Deselects the item in the receiver's list. If the item at the index was
+ * already deselected, it remains deselected.
+ *
+ * @param value the item to deselect
+ * @exception NullPointerException if there is no item in the receiver
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0
+ * and the number of elements in the list minus 1 (inclusive)
+ * </li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void deselect(final T value) {
+ checkWidget();
+ checkNullElement();
+ this.selection.remove(value);
+ updateSelection();
+ }
+
+ /**
+ * Deselects all items in the receiver's list.
+ *
+ * @param value the item to deselect
+ * @exception NullPointerException if there is no item in the receiver
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void deselectAll() {
+ checkWidget();
+ checkNullElement();
+ this.selection.clear();
+ updateSelection();
+ }
+
+ /**
+ * @return the number of columns
+ */
+ public int getNumberOfColumns() {
+ checkWidget();
+ return this.numberOfColumns;
+ }
+
+ /**
+ * @param numberOfColumns the number of columns
+ */
+ public void setNumberOfColumns(final int numberOfColumns) {
+ checkWidget();
+ this.numberOfColumns = numberOfColumns;
+ this.popup.dispose();
+ this.popup = null;
+ createPopup();
+ }
+
+ /**
+ * @return the separator used in the text field. Default value is ","
+ */
+ public String getSeparator() {
+ return this.separator;
+ }
+
+ /**
+ * @param separator the new value of the separator
+ */
+ public void setSeparator(final String separator) {
+ this.separator = separator;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#getForeground()
+ */
+ @Override
+ public Color getForeground() {
+ return this.foreground;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#setForeground(org.eclipse.swt.graphics.Color)
+ */
+ @Override
+ public void setForeground(final Color foreground) {
+ this.foreground = foreground;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#getBackground()
+ */
+ @Override
+ public Color getBackground() {
+ return this.background;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics.Color)
+ */
+ @Override
+ public void setBackground(final Color background) {
+ this.background = background;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#getFont()
+ */
+ @Override
+ public Font getFont() {
+ return this.font;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#setFont(org.eclipse.swt.graphics.Font)
+ */
+ @Override
+ public void setFont(final Font font) {
+ this.font = font;
+ }
+
+ /**
+ * Refresh the widget (after the add of a new element for example)
+ */
+ public void refresh() {
+ checkWidget();
+ this.popup.dispose();
+ this.popup = null;
+ createPopup();
+ updateSelection();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
+ */
+ @Override
+ public Point computeSize(final int wHint, final int hHint, final boolean changed) {
+ checkWidget();
+ int width = 0, height = 0;
+
+ final GC gc = new GC(this.text);
+ final int spacer = gc.stringExtent(" ").x;
+ final int textWidth = gc.stringExtent(this.text.getText()).x;
+ gc.dispose();
+ final Point textSize = this.text.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed);
+ final Point arrowSize = this.arrow.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed);
+ final int borderWidth = getBorderWidth();
+
+ height = Math.max(textSize.y, arrowSize.y);
+ width = textWidth + 2 * spacer + arrowSize.x + 2 * borderWidth;
+ if (wHint != SWT.DEFAULT) {
+ width = wHint;
+ }
+ if (hHint != SWT.DEFAULT) {
+ height = hHint;
+ }
+ return new Point(width + 2 * borderWidth, height + 2 * borderWidth);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#setEnabled(boolean)
+ */
+ @Override
+ public void setEnabled(final boolean enabled) {
+ checkWidget();
+ this.arrow.setEnabled(enabled);
+ this.text.setEnabled(enabled);
+ super.setEnabled(enabled);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Control#setToolTipText(java.lang.String)
+ */
+ @Override
+ public void setToolTipText(final String txt) {
+ checkWidget();
+ this.text.setToolTipText(txt);
+ }
+
+ /**
+ * @return the selection listener
+ */
+ public SelectionListener getSelectionListener() {
+ checkWidget();
+ return this.selectionListener;
+ }
+
+ /**
+ * @param selectionListener the new selection listener
+ */
+ public void setSelectionListener(final MultiChoiceSelectionListener<T> selectionListener) {
+ checkWidget();
+ this.selectionListener = selectionListener;
+ refresh();
+ }
+
+ /**
+ * Update the selection
+ */
+ public void updateSelection() {
+ checkWidget();
+ if (isDisposed()) {
+ return;
+ }
+
+ if (this.popup == null || this.popup.isDisposed()) {
+ return;
+ }
+
+ for (int i = 0; i < this.checkboxes.size(); i++) {
+ final Button currentButton = this.checkboxes.get(i);
+ if (!currentButton.isDisposed()) {
+ final Object content = currentButton.getData();
+ currentButton.setSelection(this.selection.contains(content));
+ }
+ }
+ setLabel();
+
+ }
+
+ /**
+ * @return the last modified item
+ */
+ T getLastModified() {
+ return this.lastModified;
+ }
+
+ /**
+ * @return the popup
+ */
+ Shell getPopup() {
+ return this.popup;
+ }
+
+ /**
+ * Create the popup that contains all checkboxes
+ */
+ private void createPopup() {
+ this.popup = new Shell(getShell(), SWT.NO_TRIM | SWT.ON_TOP);
+ this.popup.setLayout(new GridLayout(this.numberOfColumns, true));
+
+ final int[] popupEvents = { SWT.Close, SWT.Paint, SWT.Deactivate, SWT.Dispose };
+ for (int i = 0; i < popupEvents.length; i++) {
+ this.popup.addListener(popupEvents[i], this.listener);
+ }
+
+ if (this.elements == null) {
+ return;
+ }
+
+ this.checkboxes = new ArrayList<Button>(this.elements.size());
+ for (final T o : this.elements) {
+ final Button checkBoxButton = new Button(this.popup, SWT.CHECK);
+
+ if (this.font != null) {
+ checkBoxButton.setFont(this.font);
+ }
+ if (this.foreground != null) {
+ checkBoxButton.setForeground(this.foreground);
+ }
+ if (this.background != null) {
+ checkBoxButton.setBackground(this.background);
+ }
+
+ checkBoxButton.setData(o);
+ checkBoxButton.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false));
+ checkBoxButton.setText(o.toString());
+ checkBoxButton.addSelectionListener(new SimpleSelectionAdapter() {
+ @Override
+ public void handle(final SelectionEvent e) {
+ if (checkBoxButton.getSelection()) {
+ MultiChoice.this.selection.add(o);
+ } else {
+ MultiChoice.this.selection.remove(o);
+ }
+ MultiChoice.this.lastModified = o;
+ setLabel();
+ }
+ });
+
+ if (this.selectionListener != null) {
+ checkBoxButton.addSelectionListener(this.selectionListener);
+ }
+
+ checkBoxButton.setSelection(this.selection.contains(o));
+ this.checkboxes.add(checkBoxButton);
+ }
+ this.popup.layout();
+ }
+
+ /**
+ * Set the value of the label, based on the selected items
+ */
+ private void setLabel() {
+ if (this.checkboxes == null) {
+ this.text.setText("");
+ return;
+ }
+
+ final List<String> values = new ArrayList<String>();
+ for (final Button current : this.checkboxes) {
+ if (current.getSelection()) {
+ values.add(current.getText());
+ }
+ }
+
+ final StringBuffer sb = new StringBuffer();
+ final Iterator<String> it = values.iterator();
+ while (it.hasNext()) {
+ sb.append(it.next());
+ if (it.hasNext()) {
+ sb.append(this.separator);
+ }
+ }
+
+ this.text.setText(sb.toString());
+ }
+
+ /**
+ * Handle a focus event
+ *
+ * @param type type of the event to handle
+ */
+ private void handleFocus(final int type) {
+ if (isDisposed()) {
+ return;
+ }
+ switch (type) {
+ case SWT.FocusIn: {
+ if (this.hasFocus) {
+ return;
+ }
+ this.hasFocus = true;
+ final Shell shell = getShell();
+ shell.removeListener(SWT.Deactivate, this.listener);
+ shell.addListener(SWT.Deactivate, this.listener);
+ final Display display = getDisplay();
+ display.removeFilter(SWT.FocusIn, this.filter);
+ display.addFilter(SWT.FocusIn, this.filter);
+ final Event e = new Event();
+ notifyListeners(SWT.FocusIn, e);
+ break;
+ }
+ case SWT.FocusOut: {
+ if (!this.hasFocus) {
+ return;
+ }
+ final Control focusControl = getDisplay().getFocusControl();
+ if (focusControl == this.arrow) {
+ return;
+ }
+ this.hasFocus = false;
+ final Shell shell = getShell();
+ shell.removeListener(SWT.Deactivate, this.listener);
+ final Display display = getDisplay();
+ display.removeFilter(SWT.FocusIn, this.filter);
+ final Event e = new Event();
+ notifyListeners(SWT.FocusOut, e);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Handle a multichoice event
+ *
+ * @param event event to handle
+ */
+ private void multiChoiceEvent(final Event event) {
+ switch (event.type) {
+ case SWT.Dispose:
+ if (this.popup != null && !this.popup.isDisposed()) {
+ this.popup.dispose();
+ }
+ final Shell shell = getShell();
+ shell.removeListener(SWT.Deactivate, this.listener);
+ final Display display = getDisplay();
+ display.removeFilter(SWT.FocusIn, this.filter);
+ this.popup = null;
+ this.arrow = null;
+ break;
+ case SWT.Move:
+ dropDown(false);
+ break;
+ case SWT.Resize:
+ if (isDropped()) {
+ dropDown(false);
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ /**
+ * Handle a button event
+ *
+ * @param event event to hangle
+ */
+ private void buttonEvent(final Event event) {
+ switch (event.type) {
+ case SWT.FocusIn: {
+ handleFocus(SWT.FocusIn);
+ break;
+ }
+ case SWT.Selection: {
+ dropDown(!isDropped());
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ /**
+ * @return <code>true</code> if the popup is visible and not dropped,
+ * <code>false</code> otherwise
+ */
+ private boolean isDropped() {
+ return !this.popup.isDisposed() && this.popup.getVisible();
+ }
+
+ /**
+ * Handle a popup event
+ *
+ * @param event event to handle
+ */
+ private void popupEvent(final Event event) {
+ switch (event.type) {
+ case SWT.Paint:
+ final Rectangle listRect = this.popup.getBounds();
+ final Color black = getDisplay().getSystemColor(SWT.COLOR_BLACK);
+ event.gc.setForeground(black);
+ event.gc.drawRectangle(0, 0, listRect.width - 1, listRect.height - 1);
+ break;
+ case SWT.Close:
+ event.doit = false;
+ dropDown(false);
+ break;
+ case SWT.Deactivate:
+ dropDown(false);
+ break;
+ case SWT.Dispose:
+ if (this.checkboxes != null) {
+ this.checkboxes.clear();
+ }
+ this.checkboxes = null;
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ /**
+ * Display/Hide the popup window
+ *
+ * @param drop if <code>true</code>, displays the popup window. If
+ * <code>false</code>, hide the popup window
+ */
+ private void dropDown(final boolean drop) {
+ if (drop == isDropped()) {
+ return;
+ }
+
+ if (!drop) {
+ this.popup.setVisible(false);
+ if (!isDisposed()) {
+ this.text.setFocus();
+ }
+ return;
+ }
+
+ if (getShell() != this.popup.getParent()) {
+ this.popup.dispose();
+ this.popup = null;
+ createPopup();
+ }
+
+ final Point arrowRect = this.arrow.toDisplay(this.arrow.getSize().x - 5, this.arrow.getSize().y + this.arrow.getBorderWidth() - 3);
+ int x = arrowRect.x;
+ int y = arrowRect.y;
+
+ final Rectangle displayRect = getMonitor().getClientArea();
+ final Rectangle parentRect = getDisplay().map(getParent(), null, getBounds());
+ this.popup.pack();
+ final int width = this.popup.getBounds().width;
+ final int height = this.popup.getBounds().height;
+
+ if (y + height > displayRect.y + displayRect.height) {
+ y = parentRect.y - height;
+ }
+ if (x + width > displayRect.x + displayRect.width) {
+ x = displayRect.x + displayRect.width - width;
+ }
+
+ this.popup.setLocation(x, y);
+ this.popup.setVisible(true);
+ this.popup.setFocus();
+ }
+
+ /**
+ * Check if the elements attributes is not null
+ *
+ * @exception NullPointerException if there is no item in the receiver
+ */
+ private void checkNullElement() {
+ if (this.elements == null) {
+ throw new NullPointerException("There is no element associated to this widget");
+ }
+ }
+
+ /**
+ * @param index
+ * @throws NullPointerException
+ * @throws IllegalArgumentException
+ */
+ private void checkRange(final int index) throws NullPointerException {
+ checkNullElement();
+ if (index < 0 || index >= this.elements.size()) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/multiChoice/MultiChoiceSelectionListener.java b/org.tizen.common.externals/src/org/mihalis/opal/multiChoice/MultiChoiceSelectionListener.java
new file mode 100644
index 000000000..ac5ca79c4
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/multiChoice/MultiChoiceSelectionListener.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+
+package org.mihalis.opal.multiChoice;
+
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Classes which extend this abstract class provide methods that deal with the
+ * events that are generated when selection occurs in a MultiChoice control.
+ */
+public abstract class MultiChoiceSelectionListener<T> implements SelectionListener {
+ private final MultiChoice<T> parent;
+
+ public MultiChoiceSelectionListener(final MultiChoice<T> parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public final void widgetSelected(final SelectionEvent e) {
+ final Button button = (Button) e.widget;
+ handle(this.parent, this.parent.getLastModified(), button.getSelection(), this.parent.getPopup());
+ }
+
+ /**
+ * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public final void widgetDefaultSelected(final SelectionEvent inutile) {
+ }
+
+ /**
+ * This method contains the code that is called when the selection has
+ * changed
+ *
+ * @param parent MultiChoice responsible of the event
+ * @param receiver Object modified
+ * @param selected If <code>true</code>, the check box has been checked
+ * @param popup the popup window that contains all checkboxes
+ */
+ public abstract void handle(MultiChoice<T> parent, T receiver, boolean selected, Shell popup);
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/notify/Notifier.java b/org.tizen.common.externals/src/org/mihalis/opal/notify/Notifier.java
new file mode 100644
index 000000000..014a19cec
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/notify/Notifier.java
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.notify;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.mihalis.opal.notify.NotifierColorsFactory.NotifierTheme;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * This class provides a notifier window, which is a window that appears in the
+ * bottom of the screen and slides.
+ */
+public class Notifier {
+ private static final int FONT_SIZE = 10;
+ private static final int MAX_DURATION_FOR_OPENING = 500;
+ private static final int DISPLAY_TIME = 4500;
+
+ private static final int FADE_TIMER = 50;
+ private static final int FADE_OUT_STEP = 8;
+
+ private static final int STEP = 5;
+
+ /**
+ * Starts a notification. A window will appear in the bottom of the screen,
+ * then will disappear after 4.5 s
+ *
+ * @param title the title of the popup window
+ * @param text the text of the notification
+ *
+ */
+ public static void notify(final String title, final String text) {
+ notify(null, title, text, NotifierTheme.YELLOW_THEME);
+ }
+
+ /**
+ * Starts a notification. A window will appear in the bottom of the screen,
+ * then will disappear after 4.5 s
+ *
+ * @param image the image to display (if <code>null</code>, a default image
+ * is displayed)
+ * @param title the title of the popup window
+ * @param text the text of the notification
+ *
+ */
+ public static void notify(final Image image, final String title, final String text) {
+ notify(image, title, text, NotifierTheme.YELLOW_THEME);
+
+ }
+
+ /**
+ * Starts a notification. A window will appear in the bottom of the screen,
+ * then will disappear after 4.5 s
+ *
+ * @param title the title of the popup window
+ * @param text the text of the notification
+ * @param theme the graphical theme. If <code>null</code>, the yellow theme
+ * is used
+ *
+ * @see NotifierTheme
+ */
+ public static void notify(final String title, final String text, final NotifierTheme theme) {
+ notify(null, title, text, theme);
+ }
+
+ /**
+ * Starts a notification. A window will appear in the bottom of the screen,
+ * then will disappear after 4.5 s
+ *
+ * @param image the image to display (if <code>null</code>, a default image
+ * is displayed)
+ * @param title the title of the popup window
+ * @param text the text of the notification
+ * @param theme the graphical theme. If <code>null</code>, the yellow theme
+ * is used
+ *
+ * @see NotifierTheme
+ */
+ public static void notify(final Image image, final String title, final String text, final NotifierTheme theme) {
+ final Shell shell = createNotificationWindow(image, title, text, NotifierColorsFactory.getColorsForTheme(theme));
+ makeShellAppears(shell);
+
+ }
+
+ /**
+ * Creates a notification window
+ *
+ * @param image image. If <code>null</code>, a default image is used
+ * @param title title, the title of the window
+ * @param text text of the window
+ * @param colors color set
+ * @return the notification window as a shell object
+ */
+ private static Shell createNotificationWindow(final Image image, final String title, final String text, final NotifierColors colors) {
+ final Shell shell = new Shell(SWT.NO_TRIM | SWT.NO_FOCUS);
+ shell.setLayout(new GridLayout(2, false));
+ shell.setBackgroundMode(SWT.INHERIT_FORCE);
+
+ createTitle(shell, title, colors);
+ createImage(shell, image);
+ createText(shell, text, colors);
+ createBackground(shell, colors);
+ createCloseAction(shell);
+
+ shell.addListener(SWT.Dispose, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ colors.dispose();
+ }
+ });
+
+ shell.pack();
+ shell.setMinimumSize(320, 100);
+ return shell;
+ }
+
+ /**
+ * Creates the title part of the window
+ *
+ * @param shell the window
+ * @param title the title
+ * @param colors the color set
+ */
+ private static void createTitle(final Shell shell, final String title, final NotifierColors colors) {
+ final Label titleLabel = new Label(shell, SWT.NONE);
+ final GridData gdLabel = new GridData(GridData.BEGINNING, GridData.BEGINNING, true, false, 2, 1);
+ gdLabel.horizontalIndent = 40;
+ titleLabel.setLayoutData(gdLabel);
+ final Color titleColor = colors.titleColor;
+ titleLabel.setForeground(titleColor);
+
+ final Font titleFont = SWTGraphicUtil.buildFontFrom(titleLabel, SWT.BOLD, FONT_SIZE);
+ titleLabel.setFont(titleFont);
+ titleLabel.setText(title);
+ SWTGraphicUtil.dispose(shell, titleFont);
+ }
+
+ /**
+ * Creates the image part of the window
+ *
+ * @param shell the window
+ * @param image the image
+ */
+ private static void createImage(final Shell shell, final Image image) {
+ final Label labelImage = new Label(shell, SWT.NONE);
+ final GridData gdImage = new GridData(GridData.CENTER, GridData.BEGINNING, false, true);
+ gdImage.horizontalIndent = 10;
+ labelImage.setLayoutData(gdImage);
+ if (image == null) {
+ final Image temp = SWTGraphicUtil.createImage("images/information.png");
+ labelImage.setImage(temp);
+ SWTGraphicUtil.dispose(shell, temp);
+ } else {
+ labelImage.setImage(image);
+ }
+
+ }
+
+ /**
+ * Creates the text part of the window
+ *
+ * @param shell the window
+ * @param text the text
+ * @param colors the color set
+ */
+ private static void createText(final Shell shell, final String text, final NotifierColors colors) {
+ final StyledText textLabel = new StyledText(shell, SWT.WRAP | SWT.READ_ONLY);
+ final GridData gdText = new GridData(GridData.FILL, GridData.FILL, true, true);
+ gdText.horizontalIndent = 15;
+ textLabel.setLayoutData(gdText);
+ textLabel.setEnabled(false);
+ final Font textFont = SWTGraphicUtil.buildFontFrom(textLabel, SWT.NONE, 10);
+ textLabel.setFont(textFont);
+
+ final Color textColor = colors.textColor;
+ textLabel.setForeground(textColor);
+
+ textLabel.setText("<html><body>" + text + "</body></html>");
+ SWTGraphicUtil.applyHTMLFormating(textLabel);
+
+ SWTGraphicUtil.dispose(shell, textFont);
+
+ }
+
+ /**
+ * Creates the background of the window
+ *
+ * @param shell the window
+ * @param colors the color set of the window
+ */
+ private static void createBackground(final Shell shell, final NotifierColors colors) {
+ shell.addListener(SWT.Resize, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ final Rectangle rect = shell.getClientArea();
+ final Image newImage = new Image(Display.getDefault(), Math.max(1, rect.width), rect.height);
+ final GC gc = new GC(newImage);
+ gc.setAntialias(SWT.ON);
+
+ final Color borderColor = colors.borderColor;
+ final Color fillColor1 = colors.leftColor;
+ final Color fillColor2 = colors.rightColor;
+
+ gc.setBackground(borderColor);
+ gc.fillRoundRectangle(0, 0, rect.width, rect.height, 8, 8);
+
+ gc.setBackground(fillColor1);
+ gc.fillRoundRectangle(1, 1, rect.width - 2, rect.height - 2, 8, 8);
+
+ gc.setBackground(fillColor2);
+ gc.fillRoundRectangle(30, 1, rect.width - 32, rect.height - 2, 8, 8);
+ gc.fillRectangle(30, 1, 10, rect.height - 2);
+
+ final Image closeImage = SWTGraphicUtil.createImage("images/close.png");
+ gc.drawImage(closeImage, rect.width - 21, 13);
+
+ gc.dispose();
+ closeImage.dispose();
+
+ shell.setBackgroundImage(newImage);
+
+ }
+ });
+
+ }
+
+ /**
+ * @param shell shell that will appear
+ */
+ private static void makeShellAppears(final Shell shell) {
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
+
+ final Rectangle clientArea = Display.getDefault().getActiveShell().getMonitor().getClientArea();
+ final int startX = clientArea.x + clientArea.width - shell.getSize().x;
+
+ final int stepForPosition = MAX_DURATION_FOR_OPENING / shell.getSize().y * STEP;
+ final int stepForAlpha = STEP * 255 / shell.getSize().y;
+
+ final int lastPosition = clientArea.y + clientArea.height - shell.getSize().y;
+
+ shell.setAlpha(0);
+ shell.setLocation(startX, clientArea.y + clientArea.height);
+ shell.open();
+
+ shell.getDisplay().timerExec(stepForPosition, new Runnable() {
+
+ @Override
+ public void run() {
+
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
+
+ shell.setLocation(startX, shell.getLocation().y - STEP);
+ shell.setAlpha(shell.getAlpha() + stepForAlpha);
+ if (shell.getLocation().y >= lastPosition) {
+ shell.getDisplay().timerExec(stepForPosition, this);
+ } else {
+ shell.setAlpha(255);
+ Display.getDefault().timerExec(DISPLAY_TIME, fadeOut(shell, false));
+ }
+ }
+ });
+
+ }
+
+ /**
+ * @param shell shell that will disappear
+ * @param fast if true, the fading is much faster
+ * @return a runnable
+ */
+ private static Runnable fadeOut(final Shell shell, final boolean fast) {
+ return new Runnable() {
+
+ @Override
+ public void run() {
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
+
+ int currentAlpha = shell.getAlpha();
+ currentAlpha -= FADE_OUT_STEP * (fast ? 8 : 1);
+
+ if (currentAlpha <= 0) {
+ shell.setAlpha(0);
+ shell.dispose();
+ return;
+ }
+
+ shell.setAlpha(currentAlpha);
+
+ Display.getDefault().timerExec(FADE_TIMER, this);
+
+ }
+
+ };
+ }
+
+ /**
+ * Add a listener to the shell in order to handle the clicks on the close
+ * button
+ *
+ * @param shell associated shell
+ */
+ private static void createCloseAction(final Shell shell) {
+ shell.addListener(SWT.MouseUp, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ final Rectangle rect = shell.getClientArea();
+ final int xUpperLeftCorner = rect.width - 21;
+ final int yUpperLeftCorner = 13;
+
+ if (event.x >= xUpperLeftCorner && event.x <= xUpperLeftCorner + 8 && event.y >= yUpperLeftCorner && event.y <= yUpperLeftCorner + 8) {
+ Display.getDefault().timerExec(0, fadeOut(shell, true));
+ }
+
+ }
+ });
+
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/notify/NotifierColors.java b/org.tizen.common.externals/src/org/mihalis/opal/notify/NotifierColors.java
new file mode 100644
index 000000000..ddde66343
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/notify/NotifierColors.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.notify;
+
+import org.eclipse.swt.graphics.Color;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * This class is a simple POJO that holds colors used by the Notifier widget
+ *
+ */
+class NotifierColors {
+ Color titleColor;
+ Color textColor;
+ Color borderColor;
+ Color leftColor;
+ Color rightColor;
+
+ void dispose() {
+ SWTGraphicUtil.dispose(this.titleColor);
+ SWTGraphicUtil.dispose(this.borderColor);
+ SWTGraphicUtil.dispose(this.leftColor);
+ SWTGraphicUtil.dispose(this.rightColor);
+ SWTGraphicUtil.dispose(this.textColor);
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/notify/NotifierColorsFactory.java b/org.tizen.common.externals/src/org/mihalis/opal/notify/NotifierColorsFactory.java
new file mode 100644
index 000000000..18390636b
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/notify/NotifierColorsFactory.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON 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: Laurent CARON (laurent.caron at gmail dot com) - initial API
+ * and implementation
+ *******************************************************************************/
+
+package org.mihalis.opal.notify;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * This class creates the colors associated to a given theme
+ *
+ */
+public class NotifierColorsFactory {
+
+ public enum NotifierTheme {
+ YELLOW_THEME, GRAY_THEME, BLUE_THEME
+ };
+
+ /**
+ * Constructor
+ */
+ private NotifierColorsFactory() {
+
+ }
+
+ /**
+ * @param theme a theme for the notifier widget
+ * @return the color set for the given theme
+ */
+ static NotifierColors getColorsForTheme(final NotifierTheme theme) {
+ final NotifierColors colors = new NotifierColors();
+ switch (theme) {
+ case BLUE_THEME:
+ colors.textColor = new Color(Display.getDefault(), 4, 64, 140);
+ colors.titleColor = Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
+ colors.borderColor = new Color(Display.getDefault(), 153, 188, 232);
+ colors.leftColor = new Color(Display.getDefault(), 210, 225, 244);
+ colors.rightColor = new Color(Display.getDefault(), 182, 207, 238);
+ break;
+ case GRAY_THEME:
+ colors.textColor = Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
+ colors.titleColor = Display.getDefault().getSystemColor(SWT.COLOR_DARK_RED);
+ colors.borderColor = new Color(Display.getDefault(), 208, 208, 208);
+ colors.leftColor = new Color(Display.getDefault(), 255, 255, 255);
+ colors.rightColor = new Color(Display.getDefault(), 208, 208, 208);
+ break;
+ default:
+ colors.textColor = Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
+ colors.titleColor = Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
+ colors.borderColor = new Color(Display.getDefault(), 218, 178, 85);
+ colors.leftColor = new Color(Display.getDefault(), 220, 220, 160);
+ colors.rightColor = new Color(Display.getDefault(), 255, 255, 191);
+ break;
+ }
+ return colors;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/ChoiceItem.java b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/ChoiceItem.java
new file mode 100644
index 000000000..cff7959c1
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/ChoiceItem.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ * Eugene Ryzhikov - Author of the Oxbow Project (http://code.google.com/p/oxbow/) - Inspiration
+ *******************************************************************************/
+package org.mihalis.opal.opalDialog;
+
+/**
+ * Instances of this class are choice items used by the choice widget
+ */
+public class ChoiceItem {
+
+ private final String instruction;
+ private final String text;
+
+ /**
+ * Constructor
+ *
+ * @param instruction instruction of the choice
+ * @param text text displayed under the instruction
+ */
+ public ChoiceItem(final String instruction, final String text) {
+ this.instruction = instruction;
+ this.text = text;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param instruction instruction
+ */
+ public ChoiceItem(final String instruction) {
+ this(instruction, null);
+ }
+
+ /**
+ * @return the instruction
+ */
+ public String getInstruction() {
+ return this.instruction;
+ }
+
+ /**
+ * @return the text
+ */
+ public String getText() {
+ return this.text;
+ };
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/ChoiceWidget.java b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/ChoiceWidget.java
new file mode 100644
index 000000000..24bcf992c
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/ChoiceWidget.java
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ * Eugene Ryzhikov - Author of the Oxbow Project (http://code.google.com/p/oxbow/) - Inspiration
+ *******************************************************************************/
+package org.mihalis.opal.opalDialog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instance of this class are composite that represents a choice like in Windows
+ * Vista and Seven. It is composed of a green arrow, instruction and text
+ */
+public class ChoiceWidget extends Composite {
+ private Image oldImage;
+
+ private ChoiceItem choiceItem;
+
+ private Label image;
+ private Label instruction;
+ private Label text;
+
+ private final List<SelectionListener> selectionListeners;
+
+ private boolean selection;
+ private boolean insideComposite;
+ private boolean insideImage;
+ private boolean insideText;
+ private boolean insideInstruction;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance
+ * (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ * @see Composite#Composite(Composite, int)
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_FOCUS
+ * @see SWT#NO_MERGE_PAINTS
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_RADIO_GROUP
+ * @see SWT#EMBEDDED
+ * @see SWT#DOUBLE_BUFFERED
+ * @see Widget#getStyle
+ */
+ public ChoiceWidget(final Composite parent, final int style) {
+ super(parent, style);
+
+ this.setBackgroundMode(SWT.INHERIT_DEFAULT);
+ this.setLayout(new GridLayout(2, false));
+
+ buildGreenArrow();
+ buildInstruction();
+ buildText();
+ addMouseListeners();
+
+ this.selectionListeners = new ArrayList<SelectionListener>();
+ this.addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ drawComposite();
+ }
+ });
+
+ }
+
+ /**
+ * Build the green arrow
+ */
+ private void buildGreenArrow() {
+ this.image = new Label(this, SWT.NONE);
+ this.image.setImage(SWTGraphicUtil.createImage("images/arrowGreenRight.png"));
+ this.image.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ this.image.setLayoutData(new GridData(GridData.CENTER, GridData.BEGINNING, false, false, 1, 2));
+ }
+
+ /**
+ * Build the instruction
+ */
+ private void buildInstruction() {
+ final Color color = new Color(Display.getCurrent(), 35, 107, 178);
+ addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(color);
+ }
+ });
+ this.instruction = new Label(this, SWT.NONE);
+ this.instruction.setForeground(color);
+ this.instruction.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false));
+ }
+
+ /**
+ * Build the panel
+ */
+ private void buildText() {
+ this.text = new Label(this, SWT.NONE);
+ this.text.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
+ this.text.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, true));
+ }
+
+ /**
+ * Add mouse listeners
+ */
+ private void addMouseListeners() {
+ final Listener mouseEnterListener = new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+
+ if (event.widget.equals(ChoiceWidget.this)) {
+ ChoiceWidget.this.insideComposite = true;
+ }
+
+ if (event.widget.equals(ChoiceWidget.this.image)) {
+ ChoiceWidget.this.insideImage = true;
+ }
+ if (event.widget.equals(ChoiceWidget.this.text)) {
+ ChoiceWidget.this.insideText = true;
+ }
+ if (event.widget.equals(ChoiceWidget.this.instruction)) {
+ ChoiceWidget.this.insideInstruction = true;
+ }
+
+ drawComposite();
+ }
+ };
+
+ final Listener mouseExitListener = new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ if (event.widget.equals(ChoiceWidget.this)) {
+ ChoiceWidget.this.insideComposite = false;
+ }
+
+ if (event.widget.equals(ChoiceWidget.this.image)) {
+ ChoiceWidget.this.insideImage = false;
+ }
+ if (event.widget.equals(ChoiceWidget.this.text)) {
+ ChoiceWidget.this.insideText = false;
+ }
+ if (event.widget.equals(ChoiceWidget.this.instruction)) {
+ ChoiceWidget.this.insideInstruction = false;
+ }
+ drawComposite();
+ }
+ };
+
+ final Listener mouseClickListener = new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ for (final SelectionListener selectionListener : ChoiceWidget.this.selectionListeners) {
+ selectionListener.widgetSelected(null);
+ }
+ }
+ };
+
+ addListener(SWT.MouseEnter, mouseEnterListener);
+ this.image.addListener(SWT.MouseEnter, mouseEnterListener);
+ this.text.addListener(SWT.MouseEnter, mouseEnterListener);
+ this.instruction.addListener(SWT.MouseEnter, mouseEnterListener);
+
+ addListener(SWT.MouseExit, mouseExitListener);
+ this.image.addListener(SWT.MouseExit, mouseExitListener);
+ this.text.addListener(SWT.MouseExit, mouseExitListener);
+ this.instruction.addListener(SWT.MouseExit, mouseExitListener);
+
+ addListener(SWT.MouseUp, mouseClickListener);
+ this.image.addListener(SWT.MouseUp, mouseClickListener);
+ this.text.addListener(SWT.MouseUp, mouseClickListener);
+ this.instruction.addListener(SWT.MouseUp, mouseClickListener);
+ }
+
+ /**
+ * Draw the composite
+ */
+ private void drawComposite() {
+
+ final Rectangle rect = this.getClientArea();
+ final Image newImage = new Image(getDisplay(), Math.max(1, rect.width), Math.max(1, rect.height));
+
+ final GC gc = new GC(newImage);
+
+ final boolean inside = this.insideComposite || this.insideImage || this.insideInstruction || this.insideText;
+
+ if (!inside && !this.selection) {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.drawRectangle(rect.x, rect.y, rect.width, rect.height);
+ } else {
+ // The mouse is over OR the item is selected
+ final Color gradientColor = inside ? new Color(getDisplay(), 220, 231, 243) : new Color(getDisplay(), 241, 241, 241);
+ final Color borderColor = inside ? new Color(getDisplay(), 35, 107, 178) : new Color(getDisplay(), 192, 192, 192);
+
+ gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ gc.setBackground(gradientColor);
+ gc.fillGradientRectangle(rect.x, rect.y, rect.width, rect.height, true);
+
+ gc.setForeground(borderColor);
+ gc.drawRoundRectangle(rect.x, rect.y, rect.width - 1, rect.height - 1, 2, 2);
+
+ gradientColor.dispose();
+ borderColor.dispose();
+ }
+ gc.dispose();
+
+ this.setBackgroundImage(newImage);
+ if (this.oldImage != null) {
+ this.oldImage.dispose();
+ }
+ this.oldImage = newImage;
+
+ }
+
+ /**
+ * @return the current choice item
+ */
+ public ChoiceItem getChoiceItem() {
+ return this.choiceItem;
+ }
+
+ /**
+ * @param choiceItem the choiceItem to set
+ */
+ public void setChoiceItem(final ChoiceItem choiceItem) {
+ this.choiceItem = choiceItem;
+ this.instruction.setText(choiceItem.getInstruction());
+ this.text.setText(choiceItem.getText());
+ }
+
+ /**
+ * Add a selection listener to this widget
+ *
+ * @param listener listener to add
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ this.selectionListeners.add(listener);
+ }
+
+ /**
+ * Remove a selection listener
+ *
+ * @param listener listener to remove
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ this.selectionListeners.remove(listener);
+ }
+
+ public void setSelection(final boolean selection) {
+ this.selection = selection;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/Dialog.java b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/Dialog.java
new file mode 100644
index 000000000..914ab1258
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/Dialog.java
@@ -0,0 +1,480 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ * Eugene Ryzhikov - Author of the Oxbow Project (http://code.google.com/p/oxbow/) - Inspiration
+ *******************************************************************************/
+package org.mihalis.opal.opalDialog;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.mihalis.opal.utils.ResourceManager;
+
+/**
+ * Instances of this class are dialog box
+ */
+public class Dialog {
+
+ /**
+ * Types of opal dialog
+ */
+ public enum OpalDialogType {
+ CLOSE, YES_NO, OK, OK_CANCEL, SELECT_CANCEL, NO_BUTTON, OTHER, NONE
+ }
+
+ private String title;
+ OpalDialogType buttonType;
+ private final MessageArea messageArea;
+ private final FooterArea footerArea;
+ final Shell shell;
+
+ private int minimumWidth = 300;
+ private int minimumHeight = 150;
+
+ /**
+ * Constructor
+ */
+ public Dialog() {
+ this(null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param parent parent shell
+ */
+ public Dialog(final Shell parent) {
+ if (parent == null) {
+ this.shell = new Shell(Display.getCurrent(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ } else {
+ this.shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ }
+ this.messageArea = new MessageArea(this);
+ this.footerArea = new FooterArea(this);
+ }
+
+ /**
+ * Show the dialog box
+ *
+ * @return the index of the selected button
+ */
+ public int show() {
+ final GridLayout gd = new GridLayout(1, true);
+ gd.horizontalSpacing = 0;
+ gd.verticalSpacing = 0;
+ gd.marginHeight = gd.marginWidth = 0;
+ this.shell.setLayout(gd);
+
+ this.messageArea.render();
+ this.footerArea.render();
+ if (this.title != null) {
+ this.shell.setText(this.title);
+ }
+ pack();
+ this.shell.open();
+
+ final Display display = this.shell.getDisplay();
+ while (!this.shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+
+ return this.footerArea.getSelectedButton();
+ }
+
+ /**
+ * Close the dialog box
+ */
+ public void close() {
+ this.shell.dispose();
+
+ }
+
+ /**
+ * Compute the size of the shell
+ */
+ void pack() {
+
+ final Point preferredSize = this.shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+
+ if (preferredSize.x < this.minimumWidth) {
+
+ preferredSize.x = this.minimumWidth;
+ }
+ if (preferredSize.y < this.minimumHeight) {
+ preferredSize.y = this.minimumHeight;
+ }
+
+ final Point displaySize = new Point(this.shell.getDisplay().getBounds().width, this.shell.getDisplay().getBounds().height);
+
+ final int centerX = (displaySize.x - preferredSize.x) / 2;
+ final int centerY = (displaySize.y - preferredSize.y) / 2;
+
+ this.shell.setBounds(centerX, centerY, preferredSize.x, preferredSize.y);
+ }
+
+ // ------------------------------------------- Convenient methods
+
+ /**
+ * Create a dialog box that asks a question
+ *
+ * @param title title of the dialog box
+ * @param text text of the question
+ * @param defaultValue default value of the input
+ * @return the value typed by the user
+ */
+ public static String ask(final String title, final String text, final String defaultValue) {
+ return ask(null, title, text, defaultValue);
+ }
+
+ /**
+ * Create a dialog box that asks a question
+ *
+ * @shell parent shell
+ * @param title title of the dialog box
+ * @param text text of the question
+ * @param defaultValue default value of the input
+ * @return the value typed by the user
+ */
+ public static String ask(final Shell shell, final String title, final String text, final String defaultValue) {
+ final Dialog dialog = new Dialog(shell);
+ dialog.setTitle(ResourceManager.getLabel(ResourceManager.INPUT));
+ dialog.getMessageArea().setTitle(title).setText(text).setIcon(Display.getCurrent().getSystemImage(SWT.ICON_INFORMATION)).addTextBox(defaultValue);
+ dialog.setButtonType(OpalDialogType.OK_CANCEL);
+ if (dialog.show() == 0) {
+ return dialog.getMessageArea().getTextBoxValue();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Create a dialog box that displays an error message
+ *
+ * @param title title of the dialog box
+ * @param errorMessage Error message
+ */
+ public static void error(final String title, final String errorMessage) {
+ error(null, title, errorMessage);
+ }
+
+ /**
+ * Create a dialog box that displays an error message
+ *
+ * @param shell parent shell
+ * @param title title of the dialog box
+ * @param errorMessage Error message
+ */
+ public static void error(final Shell shell, final String title, final String errorMessage) {
+ final Dialog dialog = new Dialog(shell);
+ dialog.setTitle(ResourceManager.getLabel(ResourceManager.APPLICATION_ERROR));
+ dialog.getMessageArea().setTitle(title).//
+ setText(errorMessage).//
+ setIcon(Display.getCurrent().getSystemImage(SWT.ICON_ERROR));
+ dialog.setButtonType(OpalDialogType.OK);
+ dialog.show();
+ }
+
+ /**
+ * Create a dialog box that inform the user
+ *
+ * @param title title of the dialog box
+ * @param text text to display
+ */
+ public static void inform(final String title, final String text) {
+ inform(null, title, text);
+ }
+
+ /**
+ * Create a dialog box that inform the user
+ *
+ * @param shell parent shell
+ * @param title title of the dialog box
+ * @param text text to display
+ */
+ public static void inform(final Shell shell, final String title, final String text) {
+ final Dialog dialog = new Dialog(shell);
+ dialog.setTitle(ResourceManager.getLabel(ResourceManager.INFORMATION));
+ dialog.getMessageArea().setTitle(title).setText(text).setIcon(Display.getCurrent().getSystemImage(SWT.ICON_INFORMATION));
+ dialog.setButtonType(OpalDialogType.CLOSE);
+ dialog.show();
+
+ }
+
+ /**
+ * Create a dialog box that asks the user a confirmation
+ *
+ * @param title title of the dialog box
+ * @param text text to display
+ * @return <code>true</code> if the user confirmed, <code>false</code>
+ * otherwise
+ */
+ public static boolean isConfirmed(final String title, final String text) {
+ return isConfirmed(null, title, text, -1);
+ }
+
+ /**
+ * Create a dialog box that asks the user a confirmation
+ *
+ * @param shell parent shell
+ * @param title title of the dialog box
+ * @param text text to display
+ * @return <code>true</code> if the user confirmed, <code>false</code>
+ * otherwise
+ */
+ public static boolean isConfirmed(final Shell shell, final String title, final String text) {
+ return isConfirmed(shell, title, text, -1);
+ }
+
+ /**
+ * Create a dialog box that asks the user a confirmation. The button "yes"
+ * is not enabled before timer seconds
+ *
+ * @param title title of the dialog box
+ * @param text text to display
+ * @param timer number of seconds before enabling the yes button
+ * @return <code>true</code> if the user confirmed, <code>false</code>
+ * otherwise
+ */
+ public static boolean isConfirmed(final String title, final String text, final int timer) {
+ return isConfirmed(null, title, text, timer);
+ }
+
+ /**
+ * Create a dialog box that asks the user a confirmation. The button "yes"
+ * is not enabled before timer seconds
+ *
+ * @param shell parent shell
+ * @param title title of the dialog box
+ * @param text text to display
+ * @param timer number of seconds before enabling the yes button
+ * @return <code>true</code> if the user confirmed, <code>false</code>
+ * otherwise
+ */
+ public static boolean isConfirmed(final Shell shell, final String title, final String text, final int timer) {
+ final Dialog dialog = new Dialog(shell);
+ dialog.setTitle(ResourceManager.getLabel(ResourceManager.WARNING));
+ dialog.getMessageArea().setTitle(title).setText(text).setIcon(Display.getCurrent().getSystemImage(SWT.ICON_WARNING));
+
+ dialog.getFooterArea().setTimer(timer).setTimerIndexButton(0);
+ dialog.setButtonType(OpalDialogType.YES_NO);
+ return dialog.show() == 0;
+ }
+
+ /**
+ * Create a dialog box with a radio choice
+ *
+ * @param title title of the dialog box
+ * @param text text to display
+ * @param defaultSelection index of the default selection
+ * @param values values to display
+ * @return the index of the selection
+ */
+ public static int radioChoice(final String title, final String text, final int defaultSelection, final String... values) {
+ return radioChoice(null, title, text, defaultSelection, values);
+ }
+
+ /**
+ * Create a dialog box with a radio choice
+ *
+ * @param shell parent shell
+ * @param title title of the dialog box
+ * @param text text to display
+ * @param defaultSelection index of the default selection
+ * @param values values to display
+ * @return the index of the selection
+ */
+ public static int radioChoice(final Shell shell, final String title, final String text, final int defaultSelection, final String... values) {
+ final Dialog dialog = new Dialog(shell);
+ dialog.setTitle(ResourceManager.getLabel(ResourceManager.CHOICE));
+ dialog.getMessageArea().setTitle(title).setText(text).setIcon(Display.getCurrent().getSystemImage(SWT.ICON_QUESTION)).addRadioButtons(defaultSelection, values);
+ dialog.setButtonType(OpalDialogType.SELECT_CANCEL);
+ if (dialog.show() == 0) {
+ return dialog.getMessageArea().getRadioChoice();
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * Display a dialog box with an exception
+ *
+ * @param exception exception to display
+ */
+ public static void showException(final Throwable exception) {
+ final Dialog dialog = new Dialog();
+ dialog.setTitle(ResourceManager.getLabel(ResourceManager.EXCEPTION));
+
+ final String msg = exception.getMessage();
+ final String className = exception.getClass().getName();
+ final boolean noMessage = msg == null || msg.trim().length() == 0;
+
+ dialog.getMessageArea().setTitle(noMessage ? className : msg).//
+ setText(noMessage ? "" : className).//
+ setIcon(Display.getCurrent().getSystemImage(SWT.ICON_ERROR)).//
+ setException(exception);
+
+ dialog.getFooterArea().setExpanded(true);
+
+ dialog.setButtonType(OpalDialogType.CLOSE);
+ dialog.show();
+ }
+
+ /**
+ * Create a dialog box with a choice
+ *
+ * @param title title of the dialog box
+ * @param text text to display
+ * @param defaultSelection index of the default selection
+ * @param items items to display
+ * @return the index of the selected value
+ */
+ public static int choice(final String title, final String text, final int defaultSelection, final ChoiceItem... items) {
+ return choice(null, title, text, defaultSelection, items);
+ }
+
+ /**
+ * Create a dialog box with a choice
+ *
+ * @param shell parent shell
+ * @param title title of the dialog box
+ * @param text text to display
+ * @param defaultSelection index of the default selection
+ * @param items items to display
+ * @return the index of the selected value
+ */
+ public static int choice(final Shell shell, final String title, final String text, final int defaultSelection, final ChoiceItem... items) {
+ final Dialog dialog = new Dialog(shell);
+ dialog.setTitle(ResourceManager.getLabel(ResourceManager.CHOICE));
+ dialog.getMessageArea().setTitle(title).setText(text).setIcon(Display.getCurrent().getSystemImage(SWT.ICON_QUESTION)).addChoice(defaultSelection, items);
+ dialog.setButtonType(OpalDialogType.NONE);
+ dialog.show();
+ return dialog.getMessageArea().getChoice();
+ }
+
+ // ------------------------------------------- Getters & Setters
+
+ /**
+ * @return the title
+ */
+ public String getTitle() {
+ return this.title;
+ }
+
+ /**
+ * @param title the title to set
+ */
+ public void setTitle(final String title) {
+ this.title = title;
+ }
+
+ /**
+ * @return the buttonType
+ */
+ public OpalDialogType getButtonType() {
+ return this.buttonType;
+ }
+
+ /**
+ * @param buttonType the buttonType to set
+ */
+ public void setButtonType(final OpalDialogType buttonType) {
+ this.buttonType = buttonType;
+
+ switch (buttonType) {
+ case CLOSE:
+ this.footerArea.setButtonLabels(ResourceManager.getLabel(ResourceManager.CLOSE)).setDefaultButtonIndex(0);
+ break;
+ case NO_BUTTON:
+ break;
+ case OK:
+ this.footerArea.setButtonLabels(ResourceManager.getLabel(ResourceManager.OK)).setDefaultButtonIndex(0);
+ break;
+ case OK_CANCEL:
+ this.footerArea.setButtonLabels(ResourceManager.getLabel(ResourceManager.OK), ResourceManager.getLabel(ResourceManager.CANCEL)).setDefaultButtonIndex(-1);
+ break;
+ case SELECT_CANCEL:
+ this.footerArea.setButtonLabels(ResourceManager.getLabel(ResourceManager.SELECT), ResourceManager.getLabel(ResourceManager.CANCEL)).setDefaultButtonIndex(-1);
+ break;
+ case YES_NO:
+ this.footerArea.setButtonLabels(ResourceManager.getLabel(ResourceManager.YES), ResourceManager.getLabel(ResourceManager.NO)).setDefaultButtonIndex(0);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ /**
+ * @return the messageArea
+ */
+ public MessageArea getMessageArea() {
+ return this.messageArea;
+ }
+
+ /**
+ * @return the footerArea
+ */
+ public FooterArea getFooterArea() {
+ return this.footerArea;
+ }
+
+ /**
+ * @return the shell
+ */
+ public Shell getShell() {
+ return this.shell;
+ }
+
+ /**
+ * @return the index of the selected button
+ */
+ public int getSelectedButton() {
+ return getFooterArea().getSelectedButton();
+ }
+
+ /**
+ * @return the selection state of the checkbox
+ */
+ public boolean getCheckboxValue() {
+ return this.footerArea.getCheckBoxValue();
+ }
+
+ /**
+ * @return the minimum width of the dialog box
+ */
+ public int getMinimumWidth() {
+ return this.minimumWidth;
+ }
+
+ /**
+ * @param minimumWidth the minimum width of the dialog box to set
+ */
+ public void setMinimumWidth(final int minimumWidth) {
+ this.minimumWidth = minimumWidth;
+ }
+
+ /**
+ * @return the minimum height of the dialog box
+ */
+ public int getMinimumHeight() {
+ return this.minimumHeight;
+ }
+
+ /**
+ * @param minimumHeight the minimum height of the dialog box to set
+ */
+ public void setMinimumHeight(final int minimumHeight) {
+ this.minimumHeight = minimumHeight;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/DialogArea.java b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/DialogArea.java
new file mode 100644
index 000000000..3e476930f
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/DialogArea.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ * Eugene Ryzhikov - Author of the Oxbow Project (http://code.google.com/p/oxbow/) - Inspiration
+ *******************************************************************************/
+package org.mihalis.opal.opalDialog;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * This abstract class if the mother of MessageArea and FooterArea classes
+ */
+abstract class DialogArea {
+ protected final Dialog parent;
+ private boolean initialised;
+
+ /**
+ * Constructor
+ *
+ * @param parent parent dialog
+ */
+ public DialogArea(final Dialog parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Render the content of an area
+ */
+ abstract void render();
+
+ /**
+ * @return the initialised field
+ */
+ boolean isInitialised() {
+ return this.initialised;
+ }
+
+ /**
+ * @param initialised the initialised value to set
+ */
+ void setInitialised(final boolean initialised) {
+ this.initialised = initialised;
+ }
+
+ /**
+ * @return the normal font used by the dialog box
+ */
+ protected Font getNormalFont() {
+ return getFont("Segoe UI", 9, SWT.NONE);
+ }
+
+ /**
+ * @return the bigger font used by the dialog box
+ */
+ protected Font getBiggerFont() {
+ return getFont("Segoe UI", 11, SWT.NONE);
+ }
+
+ /**
+ * Build a font
+ *
+ * @param name name of the font
+ * @param size size of the font
+ * @param style style of the font
+ * @return the font
+ */
+ private Font getFont(final String name, final int size, final int style) {
+ final Font font = new Font(Display.getCurrent(), name, size, style);
+ this.parent.shell.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(font);
+ }
+ });
+ return font;
+ }
+
+ /**
+ * @return the title's color (blue)
+ */
+ protected Color getTitleColor() {
+ final Color color = new Color(Display.getCurrent(), 35, 107, 178);
+ this.parent.shell.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(color);
+ }
+ });
+ return color;
+ }
+
+ /**
+ * @return the grey color
+ */
+ protected Color getGreyColor() {
+ final Color color = new Color(Display.getCurrent(), 240, 240, 240);
+ this.parent.shell.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(color);
+ }
+ });
+ return color;
+ }
+
+ /**
+ * @return the image "fewer details"
+ */
+ protected Image getFewerDetailsImage() {
+ return loadImage("images/fewerDetails.png");
+ }
+
+ /**
+ * @return the image "more details"
+ */
+ protected Image getMoreDetailsImage() {
+ return loadImage("images/moreDetails.png");
+ }
+
+ /**
+ * Loads an image
+ *
+ * @param fileName file name of the image
+ * @return the image
+ */
+ private Image loadImage(final String fileName) {
+ final Image image = SWTGraphicUtil.createImage(fileName);
+ this.parent.shell.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SWTGraphicUtil.dispose(image);
+ }
+ });
+ return image;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/FooterArea.java b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/FooterArea.java
new file mode 100644
index 000000000..66c7ecad2
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/FooterArea.java
@@ -0,0 +1,531 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ * Eugene Ryzhikov - Author of the Oxbow Project (http://code.google.com/p/oxbow/) - Inspiration
+ *******************************************************************************/
+package org.mihalis.opal.opalDialog;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.utils.ResourceManager;
+
+/**
+ * Instances of this class are message areas
+ */
+public class FooterArea extends DialogArea {
+ private Image icon;
+ private String footerText;
+
+ private List<String> buttonLabels;
+ private int defaultButtonIndex;
+
+ private int timer;
+ private int timerIndexButton;
+
+ private int selectedButtonIndex;
+
+ private String collapsedLabelText;
+ private String expandedLabelText;
+ private boolean expanded;
+ private String detailText;
+ private boolean details;
+ private Button disabledButton;
+
+ private String checkBoxLabel;
+ private boolean checkBoxValue;
+
+ private Label expandedPanel;
+ private Composite composite;
+
+ /**
+ * Constructor
+ *
+ * @param parent dialog that is composed of this footer area
+ */
+ public FooterArea(final Dialog parent) {
+ super(parent);
+ this.selectedButtonIndex = -1;
+ this.expandedLabelText = ResourceManager.getLabel(ResourceManager.FEWER_DETAILS);
+ this.collapsedLabelText = ResourceManager.getLabel(ResourceManager.MORE_DETAILS);
+ this.timer = -1;
+ this.timerIndexButton = -1;
+ }
+
+ /**
+ * Add a check box
+ *
+ * @param label label to display
+ * @param selection default value of the check box
+ * @return this footer area
+ */
+ public FooterArea addCheckBox(final String label, final boolean selection) {
+ this.checkBoxLabel = label;
+ this.checkBoxValue = selection;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @see org.mihalis.opal.OpalDialog.DialogArea#render()
+ */
+ @Override
+ void render() {
+ if (!this.isInitialised()) {
+ return;
+ }
+
+ this.createSeparator();
+
+ this.composite = new Composite(this.parent.shell, SWT.NONE);
+ this.composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
+ this.composite.setBackground(this.getGreyColor());
+
+ int numberOfColumns = this.buttonLabels == null ? 0 : this.buttonLabels.size();
+ if (this.details) {
+ numberOfColumns += 2;
+ }
+
+ final GridLayout gridLayout = new GridLayout(numberOfColumns, false);
+ gridLayout.marginHeight = gridLayout.marginWidth = 10;
+ this.composite.setLayout(gridLayout);
+
+ if (this.details) {
+ this.createDetails(numberOfColumns);
+ }
+
+ if (this.buttonLabels != null) {
+ this.createButtons();
+ }
+
+ if (this.details && this.parent.getMessageArea().getException() == null && this.expanded) {
+ this.createExpandedPanel(numberOfColumns);
+ }
+
+ if (this.checkBoxLabel != null) {
+ this.createCheckBox(numberOfColumns);
+ }
+
+ if (this.footerText != null) {
+ this.createFooter();
+
+ }
+
+ }
+
+ /**
+ * Create the buttons
+ */
+ private void createButtons() {
+ Button defaultButton = null;
+ for (int i = 0; i < this.buttonLabels.size(); i++) {
+ final Button button = new Button(this.composite, SWT.PUSH);
+ button.setText(this.buttonLabels.get(i));
+
+ final GridData gd = new GridData(GridData.END, GridData.CENTER, i == 0, false);
+ gd.minimumWidth = 70;
+ gd.widthHint = 70;
+ button.setLayoutData(gd);
+
+ if (i == this.defaultButtonIndex) {
+ defaultButton = button;
+ }
+
+ final Integer integer = new Integer(i);
+ button.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ FooterArea.this.parent.shell.dispose();
+ FooterArea.this.selectedButtonIndex = integer.intValue();
+ }
+
+ });
+
+ if (i == this.timerIndexButton && this.timer != -1) {
+ this.disabledButton = button;
+ button.setData(button.getText());
+ button.setText(button.getText() + " (" + this.timer + ")");
+ button.setEnabled(false);
+ }
+
+ }
+
+ if (this.timerIndexButton != -1 && this.timer != -1) {
+ Display.getCurrent().timerExec(1000, new Runnable() {
+
+ @Override
+ public void run() {
+ FooterArea.this.timer--;
+ if (FooterArea.this.disabledButton.isDisposed()) {
+ return;
+ }
+
+ if (FooterArea.this.timer == 0) {
+ FooterArea.this.disabledButton.setText((String) FooterArea.this.disabledButton.getData());
+ FooterArea.this.disabledButton.setEnabled(true);
+ } else {
+ FooterArea.this.disabledButton.setText(FooterArea.this.disabledButton.getData() + " (" + FooterArea.this.timer + ")");
+ Display.getCurrent().timerExec(1000, this);
+ }
+
+ }
+ });
+ }
+
+ this.parent.shell.setDefaultButton(defaultButton);
+ }
+
+ /**
+ * Create the details section
+ *
+ * @param numberOfColumns
+ */
+ private void createDetails(final int numberOfColumns) {
+ final Label icon = new Label(this.composite, SWT.NONE);
+ icon.setBackground(this.getGreyColor());
+ icon.setImage(this.isExpanded() ? this.getFewerDetailsImage() : this.getMoreDetailsImage());
+ icon.setLayoutData(new GridData(GridData.CENTER, GridData.CENTER, false, false));
+
+ final Label label = new Label(this.composite, SWT.NONE);
+ label.setBackground(this.getGreyColor());
+ label.setText(this.isExpanded() ? this.expandedLabelText : this.collapsedLabelText);
+ label.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false));
+
+ final int numberOfColumnsParam = numberOfColumns;
+
+ final Listener listener = new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ if (FooterArea.this.parent.getMessageArea().getException() != null) {
+ if (label.getText().equals(FooterArea.this.expandedLabelText)) {
+ label.setText(FooterArea.this.collapsedLabelText);
+ icon.setImage(FooterArea.this.getMoreDetailsImage());
+ FooterArea.this.parent.getMessageArea().hideException();
+ } else {
+ label.setText(FooterArea.this.expandedLabelText);
+ icon.setImage(FooterArea.this.getFewerDetailsImage());
+ FooterArea.this.parent.getMessageArea().showException();
+ }
+
+ } else {
+ if (label.getText().equals(FooterArea.this.expandedLabelText)) {
+ label.setText(FooterArea.this.collapsedLabelText);
+ icon.setImage(FooterArea.this.getMoreDetailsImage());
+ FooterArea.this.expandedPanel.dispose();
+ FooterArea.this.parent.pack();
+ } else {
+ label.setText(FooterArea.this.expandedLabelText);
+ icon.setImage(FooterArea.this.getFewerDetailsImage());
+ FooterArea.this.createExpandedPanel(numberOfColumnsParam);
+ FooterArea.this.parent.pack();
+ }
+ }
+ }
+ };
+
+ label.addListener(SWT.MouseUp, listener);
+ icon.addListener(SWT.MouseUp, listener);
+ }
+
+ /**
+ * Create a check box
+ *
+ * @param numberOfColumns
+ */
+ private void createCheckBox(final int numberOfColumns) {
+ final Button button = new Button(this.composite, SWT.CHECK);
+ button.setText(this.checkBoxLabel);
+ button.setSelection(this.checkBoxValue);
+ button.setBackground(this.getGreyColor());
+ button.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, true, false, numberOfColumns, 1));
+ button.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ FooterArea.this.checkBoxValue = button.getSelection();
+ }
+
+ });
+ }
+
+ /**
+ * Create footer section
+ */
+ private void createFooter() {
+ this.createSeparator();
+
+ final Composite informationComposite = new Composite(this.parent.shell, SWT.NONE);
+ informationComposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false));
+ informationComposite.setBackground(this.getGreyColor());
+
+ informationComposite.setLayout(new GridLayout(this.icon == null ? 1 : 2, false));
+
+ if (this.icon != null) {
+ final Label labelIcon = new Label(informationComposite, SWT.NONE);
+ labelIcon.setBackground(this.getGreyColor());
+ labelIcon.setImage(this.icon);
+ labelIcon.setLayoutData(new GridData(GridData.CENTER, GridData.CENTER, false, false));
+ }
+ final Label labelText = new Label(informationComposite, SWT.NONE);
+ labelText.setBackground(this.getGreyColor());
+ labelText.setText(this.footerText);
+ labelText.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false));
+ }
+
+ /**
+ * Create the expanded panel
+ *
+ * @param numberOfColumns
+ */
+ private void createExpandedPanel(final int numberOfColumns) {
+ this.expandedPanel = new Label(this.composite, SWT.BORDER);
+ this.expandedPanel.setText(this.detailText);
+ this.expandedPanel.setBackground(this.getGreyColor());
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, false, false, numberOfColumns, 1);
+ gd.minimumHeight = gd.heightHint = 150;
+ this.expandedPanel.setLayoutData(gd);
+ }
+
+ /**
+ * Create a separator
+ */
+ private void createSeparator() {
+ final Composite c = new Composite(this.parent.shell, SWT.NONE);
+ c.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
+ c.setBackground(this.getGreyColor());
+
+ final GridLayout gridLayout = new GridLayout(1, false);
+ gridLayout.marginHeight = gridLayout.marginWidth = 0;
+ c.setLayout(gridLayout);
+
+ final Label separator = new Label(c, SWT.SEPARATOR | SWT.HORIZONTAL);
+ separator.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
+
+ }
+
+ // ------------------------------------------- Getters & Setters
+
+ /**
+ * @return the icon
+ */
+ public Image getIcon() {
+ return this.icon;
+ }
+
+ /**
+ * @param icon the icon to set
+ * @return this footer area
+ */
+ public FooterArea setIcon(final Image icon) {
+ this.icon = icon;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the text
+ */
+ public String getFooterText() {
+ return this.footerText;
+ }
+
+ /**
+ * @param text the text to set
+ * @return this footer area
+ */
+ public FooterArea setFooterText(final String text) {
+ this.footerText = text;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the button labels
+ */
+ public List<String> getButtonLabels() {
+ return this.buttonLabels;
+ }
+
+ /**
+ * @param buttonLabels the button labels to set
+ * @return this footer area
+ */
+ public FooterArea setButtonLabels(final List<String> buttonLabels) {
+ this.buttonLabels = buttonLabels;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @param buttonLabels the button labels to set
+ * @return this footer area
+ */
+ public FooterArea setButtonLabels(final String... buttonLabels) {
+ this.buttonLabels = Arrays.asList(buttonLabels);
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the default button index
+ */
+ public int getDefaultButtonIndex() {
+ return this.defaultButtonIndex;
+ }
+
+ /**
+ * @param defaultButtonIndex the default button index to set
+ * @return this footer area
+ */
+ public FooterArea setDefaultButtonIndex(final int defaultButtonIndex) {
+ this.defaultButtonIndex = defaultButtonIndex;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the timer value
+ */
+ public int getTimer() {
+ return this.timer;
+ }
+
+ /**
+ * @param timer the timer value to set
+ * @return this footer area
+ */
+ public FooterArea setTimer(final int timer) {
+ this.timer = timer;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the timer index button
+ */
+ public int getTimerIndexButton() {
+ return this.timerIndexButton;
+ }
+
+ /**
+ * @param timerIndexButton the timer index button to set
+ * @return this footer area
+ */
+ public FooterArea setTimerIndexButton(final int timerIndexButton) {
+ this.timerIndexButton = timerIndexButton;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the selected button
+ */
+ int getSelectedButton() {
+ return this.selectedButtonIndex;
+ }
+
+ /**
+ * @return the collapsed label text
+ */
+ public String getCollapsedLabelText() {
+ return this.collapsedLabelText;
+ }
+
+ /**
+ * @param collapsedLabelText the collapsed label text to set
+ * @return this footer area
+ */
+ public FooterArea setCollapsedLabelText(final String collapsedLabelText) {
+ this.details = true;
+ this.collapsedLabelText = collapsedLabelText;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the expanded label text
+ */
+ public String getExpandedLabelText() {
+ return this.expandedLabelText;
+ }
+
+ /**
+ * @param expandedLabelText the expanded label text to set
+ * @return this footer area
+ */
+ public FooterArea setExpandedLabelText(final String expandedLabelText) {
+ this.details = true;
+ this.expandedLabelText = expandedLabelText;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the expanded flag
+ */
+ public boolean isExpanded() {
+ return this.expanded;
+ }
+
+ /**
+ * @param expanded the expanded flag to set
+ * @return this footer area
+ */
+ public FooterArea setExpanded(final boolean expanded) {
+ this.details = true;
+ this.expanded = expanded;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the detail text
+ */
+ public String getDetailText() {
+ return this.detailText;
+ }
+
+ /**
+ * @param detailText the detail text to set
+ * @return this footer area
+ */
+ public FooterArea setDetailText(final String detailText) {
+ this.details = true;
+ this.detailText = detailText;
+ this.setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the check box vqlue
+ */
+ public boolean getCheckBoxValue() {
+ return this.checkBoxValue;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/MessageArea.java b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/MessageArea.java
new file mode 100644
index 000000000..55cc9e82c
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/opalDialog/MessageArea.java
@@ -0,0 +1,541 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ * Eugene Ryzhikov - Author of the Oxbow Project (http://code.google.com/p/oxbow/) - Inspiration
+ *******************************************************************************/
+package org.mihalis.opal.opalDialog;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ProgressBar;
+import org.eclipse.swt.widgets.Text;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+import org.mihalis.opal.utils.StringUtil;
+
+/**
+ * Instances of this class are message areas
+ */
+public class MessageArea extends DialogArea {
+ // Main composite
+ private Composite composite;
+
+ // Informations for a simple dialog box
+ private String title;
+ private Image icon;
+ private String text;
+
+ // Informations for a radio choice dialog box
+ private int radioChoice;
+ private int radioDefaultSelection;
+ private String[] radioValues;
+
+ // Informations for a exception viewer dialog box
+ private Throwable exception;
+ private Text textException;
+
+ // Informations for an input dialog box
+ private String textBoxValue;
+
+ // Informations for a choice dialog box
+ private int choice;
+ private int choiceDefaultSelection;
+ private ChoiceItem[] choiceValues;
+
+ // Informations for a progress bar displayed in a dialog box
+ private ProgressBar progressBar;
+ private int progressBarMinimumValue;
+ private int progressBarMaximumValue;
+ private int progressBarValue;
+
+ /**
+ * Constructor
+ *
+ * @param parent dialog that is composed of this message area
+ */
+ public MessageArea(final Dialog parent) {
+ super(parent);
+ this.radioChoice = -1;
+ this.choice = -1;
+ this.progressBarValue = -1;
+ }
+
+ /**
+ * Add a choice
+ *
+ * @param defaultSelection default selection
+ * @param items a list of the choice item
+ * @return the current message area
+ */
+ public MessageArea addChoice(final int defaultSelection, final ChoiceItem... items) {
+ setInitialised(true);
+ this.choiceDefaultSelection = defaultSelection;
+ this.choiceValues = items;
+ return this;
+ }
+
+ /**
+ * Add a choice composed of radio buttons
+ *
+ * @param defaultSelection default selection
+ * @param values values
+ * @return the current message area
+ */
+ public MessageArea addRadioButtons(final int defaultSelection, final String... values) {
+ setInitialised(true);
+ this.radioDefaultSelection = defaultSelection;
+ this.radioValues = values;
+ return this;
+ }
+
+ /**
+ * Add a text box for input
+ *
+ * @param value defaut value of the textbox
+ * @return the current message area
+ */
+ public MessageArea addTextBox(final String value) {
+ setInitialised(true);
+ this.textBoxValue = value;
+ return this;
+ }
+
+ /**
+ * Add a progress bar
+ *
+ * @param mininum minimum value
+ * @param maximum maximum value
+ * @param value default value
+ * @return the current message area
+ */
+ public MessageArea addProgressBar(final int mininum, final int maximum, final int value) {
+ setInitialised(true);
+ this.progressBarMinimumValue = mininum;
+ this.progressBarMaximumValue = maximum;
+ this.progressBarValue = value;
+ return this;
+ }
+
+ /**
+ * @see org.mihalis.opal.OpalDialog.DialogArea#render()
+ */
+ @Override
+ public void render() {
+ if (!isInitialised()) {
+ return;
+ }
+
+ this.composite = new Composite(this.parent.shell, SWT.NONE);
+ this.composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
+ this.composite.setBackground(this.composite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+
+ final boolean hasIcon = this.icon != null;
+ final boolean hasTitle = !StringUtil.isEmpty(this.title);
+ final boolean hasText = !StringUtil.isEmpty(this.text);
+ final boolean hasRadio = this.radioValues != null;
+ final boolean hasException = this.exception != null;
+ final boolean hasTextbox = this.textBoxValue != null;
+ final boolean hasChoice = this.choiceValues != null;
+ final boolean hasProgressBar = this.progressBarValue != -1;
+
+ final int numberOfColumns = hasIcon ? 2 : 1;
+ int numberOfRows = hasTitle && hasText ? 2 : 1;
+
+ if (hasRadio) {
+ numberOfRows += this.radioValues.length;
+ }
+
+ if (hasChoice) {
+ numberOfRows += this.choiceValues.length;
+ }
+
+ if (hasException || hasTextbox) {
+ numberOfRows++;
+ }
+
+ if (hasProgressBar) {
+ numberOfRows++;
+ }
+
+ final GridLayout gridLayout = new GridLayout(numberOfColumns, false);
+ gridLayout.marginHeight = gridLayout.marginWidth = 0;
+ gridLayout.marginRight = 10;
+ gridLayout.marginLeft = 10;
+ gridLayout.marginTop = 10;
+ gridLayout.marginBottom = 10;
+ this.composite.setLayout(gridLayout);
+
+ if (hasIcon) {
+ createIcon(numberOfRows);
+ }
+
+ if (hasTitle) {
+ createTitle(hasIcon);
+ }
+
+ if (hasText) {
+ createText(hasIcon, hasTitle);
+ }
+
+ if (hasRadio) {
+ createRadioButtons();
+ }
+
+ if (hasException) {
+ createTextException();
+ }
+
+ if (hasTextbox) {
+ createTextBox();
+ }
+
+ if (hasChoice) {
+ createChoice();
+ }
+
+ if (hasProgressBar) {
+ createProgressBar();
+ }
+
+ }
+
+ /**
+ * Create the icon
+ *
+ * @param numberOfRows number of rows displayed
+ */
+ private void createIcon(final int numberOfRows) {
+ final Label label = new Label(this.composite, SWT.NONE);
+ label.setImage(this.icon);
+ label.setBackground(this.composite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ label.setLayoutData(new GridData(GridData.CENTER, GridData.BEGINNING, false, false, 1, numberOfRows));
+ }
+
+ /**
+ * Create the title
+ *
+ * @param hasIcon if <code>true</code> an icon is displayed
+ */
+ private void createTitle(final boolean hasIcon) {
+ final Label label = new Label(this.composite, SWT.NONE);
+ label.setText(this.title);
+ label.setFont(getBiggerFont());
+ label.setForeground(getTitleColor());
+ label.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ final GridData gd = new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false, 1, 1);
+
+ if (hasIcon) {
+ gd.horizontalIndent = 8;
+ } else {
+ gd.horizontalIndent = 10;
+ gd.verticalIndent = 10;
+ }
+
+ label.setLayoutData(gd);
+ }
+
+ /**
+ * Create the text
+ *
+ * @param hasIcon if <code>true</code> an icon is displayed
+ * @param hasTitle if <code>true</code> a title is displayed
+ */
+ private void createText(final boolean hasIcon, final boolean hasTitle) {
+ final StyledText label = new StyledText(this.composite, SWT.NONE);
+ label.setText("<html><body>" + this.text + "</body></html>");
+ SWTGraphicUtil.applyHTMLFormating(label);
+ label.setEnabled(false);
+ label.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ final GridData gd = new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false, 1, 1);
+
+ if (hasIcon) {
+ gd.horizontalIndent = 8;
+ } else {
+ gd.horizontalIndent = 20;
+ if (hasTitle) {
+ gd.verticalIndent = 8;
+ } else {
+ gd.verticalIndent = 20;
+ }
+ }
+
+ label.setLayoutData(gd);
+ }
+
+ /**
+ * Create radio buttons
+ */
+ private void createRadioButtons() {
+ for (int i = 0; i < this.radioValues.length; i++) {
+ final Button button = new Button(this.composite, SWT.RADIO);
+ button.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ button.setText(this.radioValues[i]);
+
+ final Integer index = new Integer(i);
+ button.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ if (button.getSelection()) {
+ MessageArea.this.radioChoice = index.intValue();
+ }
+ }
+
+ });
+
+ button.setSelection(i == this.radioDefaultSelection);
+ final GridData gd = new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false, 1, 1);
+ gd.horizontalIndent = 10;
+ button.setLayoutData(gd);
+ }
+ }
+
+ /**
+ * Create the text that displays an exception
+ */
+ private void createTextException() {
+ this.textException = new Text(this.composite, SWT.MULTI | SWT.READ_ONLY | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+ this.textException.setText(StringUtil.stackStraceAsString(this.exception));
+ this.textException.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, false, false, 1, 1);
+ gd.minimumHeight = 300;
+ this.textException.setLayoutData(gd);
+ }
+
+ /**
+ * Create a text box
+ */
+ private void createTextBox() {
+ final Text textbox = new Text(this.composite, SWT.SINGLE | SWT.BORDER);
+ textbox.setText(this.textBoxValue);
+ textbox.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1);
+ textbox.setLayoutData(gd);
+ textbox.addModifyListener(new ModifyListener() {
+
+ @Override
+ public void modifyText(final ModifyEvent e) {
+ MessageArea.this.textBoxValue = textbox.getText();
+ }
+ });
+ }
+
+ /**
+ * Create a choice selection
+ */
+ private void createChoice() {
+ for (int i = 0; i < this.choiceValues.length; i++) {
+ final ChoiceWidget choice = new ChoiceWidget(this.composite, SWT.RADIO);
+ choice.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ choice.setChoiceItem(this.choiceValues[i]);
+
+ final Integer index = new Integer(i);
+ choice.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ MessageArea.this.choice = index.intValue();
+ MessageArea.this.parent.shell.dispose();
+ }
+
+ });
+
+ choice.setSelection(i == this.choiceDefaultSelection);
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, false, false, 1, 1);
+ choice.setLayoutData(gd);
+ }
+ }
+
+ /**
+ * Create a progress bar
+ */
+ private void createProgressBar() {
+ this.progressBar = new ProgressBar(this.composite, SWT.SMOOTH | SWT.HORIZONTAL);
+ this.progressBar.setMinimum(this.progressBarMinimumValue);
+ this.progressBar.setMaximum(this.progressBarMaximumValue);
+ this.progressBar.setSelection(this.progressBarValue);
+ this.progressBar.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1);
+ this.progressBar.setLayoutData(gd);
+ }
+
+ /**
+ * Hide the exception panel
+ */
+ void hideException() {
+ this.textException.dispose();
+ this.parent.pack();
+
+ }
+
+ /**
+ * Show the exception panel
+ */
+ void showException() {
+ createTextException();
+ this.parent.pack();
+ }
+
+ // ------------------------------------------- Getters & Setters
+
+ /**
+ * @return the title
+ */
+ public String getTitle() {
+ return this.title;
+ }
+
+ /**
+ * @param title the title to set
+ * @return the current message area
+ */
+ public MessageArea setTitle(final String title) {
+ this.title = title;
+ setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the icon
+ */
+ public Image getIcon() {
+ return this.icon;
+ }
+
+ /**
+ * @param icon the icon to set
+ */
+ public MessageArea setIcon(final Image icon) {
+ this.icon = icon;
+ setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the text
+ */
+ public String getText() {
+ return this.text;
+ }
+
+ /**
+ * @param text the text to set
+ */
+ public MessageArea setText(final String text) {
+ this.text = text;
+ setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the radio choice
+ */
+ public int getRadioChoice() {
+ return this.radioChoice;
+ }
+
+ /**
+ * @return the exception
+ */
+ public Throwable getException() {
+ return this.exception;
+ }
+
+ /**
+ * @param exception the exception to set
+ * @return
+ */
+ public MessageArea setException(final Throwable exception) {
+ this.exception = exception;
+ setInitialised(true);
+ return this;
+ }
+
+ /**
+ * @return the choice
+ */
+ public int getChoice() {
+ return this.choice;
+ }
+
+ /**
+ * @return the value stored in the text box
+ */
+ public String getTextBoxValue() {
+ return this.textBoxValue;
+ }
+
+ /**
+ * @return the progress bar minimum value
+ */
+ public int getProgressBarMinimumValue() {
+ return this.progressBarMinimumValue;
+ }
+
+ /**
+ * @param progressBarMinimumValue the progress bar minimum value to set
+ */
+ public void setProgressBarMinimumValue(final int progressBarMinimumValue) {
+ this.progressBarMinimumValue = progressBarMinimumValue;
+ if (this.progressBar != null && !this.progressBar.isDisposed()) {
+ this.progressBar.setMinimum(progressBarMinimumValue);
+ }
+ }
+
+ /**
+ * @return the progress bar maximum value
+ */
+ public int getProgressBarMaximumValue() {
+ return this.progressBarMaximumValue;
+ }
+
+ /**
+ * @param progressBarMaximumValue the progress bar minimum value to set
+ */
+ public void setProgressBarMaximumValue(final int progressBarMaximumValue) {
+ this.progressBarMaximumValue = progressBarMaximumValue;
+ if (this.progressBar != null && !this.progressBar.isDisposed()) {
+ this.progressBar.setMaximum(progressBarMaximumValue);
+ }
+ }
+
+ /**
+ * @return the progress bar value
+ */
+ public int getProgressBarValue() {
+ return this.progressBarValue;
+ }
+
+ /**
+ * @param progressBarValue the progress bar value to set
+ */
+ public void setProgressBarValue(final int progressBarValue) {
+ this.progressBarValue = progressBarValue;
+ if (this.progressBar != null && !this.progressBar.isDisposed()) {
+ this.progressBar.setSelection(progressBarValue);
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/panels/BlurredPanel.java b/org.tizen.common.externals/src/org/mihalis/opal/panels/BlurredPanel.java
new file mode 100644
index 000000000..4d2b79d73
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/panels/BlurredPanel.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.panels;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are controls located on the top of a shell. They
+ * display a blurred version of the content of the shell
+ */
+public class BlurredPanel {
+ private final Shell parent;
+ private static final String BLURED_PANEL_KEY = "org.mihalis.opal.Panels.DarkPanel";
+ private int radius;
+ private Shell panel;
+ private Canvas canvas;
+
+ /**
+ * Constructs a new instance of this class given its parent.
+ *
+ * @param shell a shell that will be the parent of the new instance (cannot
+ * be null)
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the parent has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ */
+ public BlurredPanel(final Shell shell) {
+ if (shell == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (shell.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ this.parent = shell;
+ if (shell.getData(BLURED_PANEL_KEY) != null) {
+ throw new IllegalArgumentException("This shell has already an infinite panel attached on it !");
+ }
+ shell.setData(BLURED_PANEL_KEY, this);
+ this.radius = 2;
+ }
+
+ /**
+ * Show the blurred panel
+ */
+ public void show() {
+ if (this.parent.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ this.panel = new Shell(this.parent, SWT.APPLICATION_MODAL | SWT.NO_TRIM);
+ this.panel.setLayout(new FillLayout());
+
+ this.panel.addListener(SWT.KeyUp, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ event.doit = false;
+ }
+ });
+
+ this.canvas = new Canvas(this.panel, SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED);
+ this.canvas.addPaintListener(new PaintListener() {
+
+ @Override
+ public void paintControl(final PaintEvent e) {
+ paintCanvas(e);
+ }
+ });
+
+ this.panel.setBounds(this.panel.getDisplay().map(this.parent, null, this.parent.getClientArea()));
+ this.panel.open();
+
+ }
+
+ /**
+ * Paint the canvas that holds the panel
+ *
+ * @param e {@link PaintEvent}
+ */
+ private void paintCanvas(final PaintEvent e) {
+ // Paint the panel
+ e.gc.drawImage(createBlurredImage(), 0, 0);
+ }
+
+ private Image createBlurredImage() {
+ final GC gc = new GC(this.parent);
+ final Image image = new Image(this.parent.getDisplay(), this.parent.getSize().x, this.parent.getSize().y);
+ gc.copyArea(image, 0, 0);
+ gc.dispose();
+
+ return new Image(this.parent.getDisplay(), SWTGraphicUtil.blur(image.getImageData(), this.radius));
+
+ }
+
+ /**
+ * Hide the panel
+ */
+ public void hide() {
+ if (this.parent.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ if (this.panel == null || this.panel.isDisposed()) {
+ return;
+ }
+
+ this.panel.dispose();
+ }
+
+ /**
+ * @return the radius of the blur effect
+ */
+ public int getRadius() {
+ return this.radius;
+ }
+
+ /**
+ * @param radius the radius to set
+ */
+ public void setRadius(final int radius) {
+ this.radius = radius;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/panels/DarkPanel.java b/org.tizen.common.externals/src/org/mihalis/opal/panels/DarkPanel.java
new file mode 100644
index 000000000..ca681be14
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/panels/DarkPanel.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.panels;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Instances of this class are controls located on the top of a shell. They
+ * display a dark panel on this shell
+ */
+public class DarkPanel {
+ private final Shell parent;
+ private static final String DARK_PANEL_KEY = "org.mihalis.opal.BluredPanel.DarkPanel";
+ private int alpha;
+ private Shell panel;
+ private Canvas canvas;
+
+ /**
+ * Constructs a new instance of this class given its parent.
+ *
+ * @param shell a shell that will be the parent of the new instance (cannot
+ * be null)
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the parent has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ */
+ public DarkPanel(final Shell shell) {
+ if (shell == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (shell.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ this.parent = shell;
+ if (shell.getData(DARK_PANEL_KEY) != null) {
+ throw new IllegalArgumentException("This shell has already an infinite panel attached on it !");
+ }
+ shell.setData(DARK_PANEL_KEY, this);
+ this.alpha = 100;
+ }
+
+ /**
+ * Show the dark panel
+ */
+ public void show() {
+ if (this.parent.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ this.panel = new Shell(this.parent, SWT.APPLICATION_MODAL | SWT.NO_TRIM);
+ this.panel.setLayout(new FillLayout());
+ this.panel.setAlpha(this.alpha);
+
+ this.panel.addListener(SWT.KeyUp, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ event.doit = false;
+ }
+ });
+
+ this.canvas = new Canvas(this.panel, SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED);
+ this.canvas.addPaintListener(new PaintListener() {
+
+ @Override
+ public void paintControl(final PaintEvent e) {
+ paintCanvas(e);
+ }
+ });
+
+ this.panel.setBounds(this.panel.getDisplay().map(this.parent, null, this.parent.getClientArea()));
+ this.panel.open();
+
+ }
+
+ /**
+ * Paint the canvas that holds the panel
+ *
+ * @param e {@link PaintEvent}
+ */
+ private void paintCanvas(final PaintEvent e) {
+ // Paint the panel
+ final Rectangle clientArea = ((Canvas) e.widget).getClientArea();
+ final GC gc = e.gc;
+ gc.setBackground(this.panel.getDisplay().getSystemColor(SWT.COLOR_BLACK));
+ gc.fillRectangle(clientArea);
+ }
+
+ /**
+ * Hide the dark panel
+ */
+ public void hide() {
+ if (this.parent.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ if (this.panel == null || this.panel.isDisposed()) {
+ return;
+ }
+
+ this.panel.dispose();
+ }
+
+ /**
+ * @return the alpha value
+ */
+ public int getAlpha() {
+ return this.alpha;
+ }
+
+ /**
+ * @param alpha the alpha to set
+ */
+ public void setAlpha(final int alpha) {
+ this.alpha = alpha;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWContainer.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWContainer.java
new file mode 100644
index 000000000..17784f6ff
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWContainer.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow;
+
+import org.eclipse.swt.widgets.Composite;
+import org.mihalis.opal.preferenceWindow.widgets.PWWidget;
+
+/**
+ * Abstract class for "Containers" (row, group and tab)
+ *
+ */
+public abstract class PWContainer {
+
+ /**
+ * Add a container to the current element
+ *
+ * @param element element to add
+ * @return the container
+ */
+ public abstract PWContainer add(final PWContainer element);
+
+ /**
+ * Add a widget to the current element
+ *
+ * @param widget widget to add
+ * @return the container
+ */
+ public abstract PWContainer add(final PWWidget widget);
+
+ /**
+ * Build the content of the container
+ *
+ * @param parent parent composite
+ */
+ public abstract void build(final Composite parent);
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWGroup.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWGroup.java
new file mode 100644
index 000000000..ac0efb4aa
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWGroup.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.mihalis.opal.preferenceWindow.widgets.PWWidget;
+
+/**
+ * Instances of this class are groups
+ */
+public class PWGroup extends PWRowGroup {
+
+ private final String label;
+ private final boolean hasBorder;
+ private final List<PWRow> children;
+
+ /**
+ * Constructor
+ *
+ * @param hasBorder if <code>true</code>, the group has a border
+ */
+ public PWGroup(final boolean hasBorder) {
+ this(null, hasBorder);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param label label associated to the group
+ */
+ public PWGroup(final String label) {
+ this(label, true);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param label label associated to the group
+ * @param hasBorder if <code>true</code>, the group has a border
+ */
+ public PWGroup(final String label, final boolean hasBorder) {
+ this.label = label;
+ this.hasBorder = hasBorder;
+ this.children = new ArrayList<PWRow>();
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWContainer#add(org.mihalis.opal.preferenceWindow.PWContainer)
+ */
+ @Override
+ public PWContainer add(final PWContainer element) {
+ if (!(element instanceof PWRow)) {
+ throw new UnsupportedOperationException("Can only add a PWRow.");
+ }
+ this.children.add((PWRow) element);
+ return this;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWContainer#add(org.mihalis.opal.preferenceWindow.widgets.PWWidget)
+ */
+ @Override
+ public PWContainer add(final PWWidget widget) {
+ final PWRow row = new PWRow();
+ row.add(widget);
+ this.children.add(row);
+ return this;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWContainer#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public void build(final Composite parent) {
+ final Composite composite;
+ if (this.hasBorder) {
+ composite = new Group(parent, SWT.NONE);
+ if (this.label != null && !this.label.trim().equals("")) {
+ ((Group) composite).setText(this.label);
+ }
+ } else {
+ composite = new Composite(parent, SWT.BORDER);
+ }
+
+ final int numCol = computeNumberOfColumns();
+
+ composite.setLayout(new GridLayout(numCol, false));
+ composite.setLayoutData(new GridData(GridData.BEGINNING, GridData.FILL, false, false, this.parentNumberOfColums, 1));
+
+ for (final PWRow row : this.children) {
+ row.setParentNumberOfColumns(numCol);
+ row.build(composite);
+ }
+
+ }
+
+ /**
+ * @return
+ */
+ private int computeNumberOfColumns() {
+ int numberOfColumns = 1;
+ for (final PWRow row : this.children) {
+ numberOfColumns = Math.max(numberOfColumns, row.getNumberOfColums());
+ }
+ return numberOfColumns;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWRowGroup#checkParent(org.mihalis.opal.preferenceWindow.PWContainer)
+ */
+ @Override
+ protected void checkParent(final PWContainer parent) {
+ if (parent instanceof PWTab) {
+ return;
+ }
+ throw new UnsupportedOperationException("Bad parent, should be only PWTab ");
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWRowGroup#enableOrDisable()
+ */
+ @Override
+ public void enableOrDisable() {
+ if (this.enabler == null) {
+ return;
+ }
+
+ final boolean enabled = this.enabler.isEnabled();
+ for (final PWRow row : this.children) {
+ enableOrDisable(row, enabled);
+ }
+ }
+
+ /**
+ * Enable or disable a row
+ *
+ * @param row row to enable or disable
+ * @param enabled enable flag
+ */
+ private void enableOrDisable(final PWRow row, final boolean enabled) {
+ for (final PWWidget widget : row.widgets) {
+ final boolean widgetEnable = widget.enableOrDisable();
+
+ for (final Control c : widget.getControls()) {
+ if (!c.isDisposed()) {
+ c.setEnabled(enabled && widgetEnable);
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWRow.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWRow.java
new file mode 100644
index 000000000..e38abdc0e
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWRow.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.mihalis.opal.preferenceWindow.widgets.PWButton;
+import org.mihalis.opal.preferenceWindow.widgets.PWLabel;
+import org.mihalis.opal.preferenceWindow.widgets.PWWidget;
+
+/**
+ * Instances of this class are rows
+ */
+public class PWRow extends PWRowGroup {
+ protected final List<PWWidget> widgets;
+
+ /**
+ * Constructor
+ */
+ public PWRow() {
+ this.widgets = new ArrayList<PWWidget>();
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWContainer#add(org.mihalis.opal.preferenceWindow.widgets.PWWidget)
+ */
+ @Override
+ public PWContainer add(final PWWidget widget) {
+ this.widgets.add(widget);
+ addColumn(widget.getNumberOfColumns());
+ return this;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWContainer#add(org.mihalis.opal.preferenceWindow.PWContainer)
+ */
+ @Override
+ public PWContainer add(final PWContainer element) {
+ if (element instanceof PWRow || element instanceof PWGroup) {
+ return this.parent.add(element);
+ } else {
+ throw new UnsupportedOperationException("Can only add a PWGroup or a PWRow.");
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWContainer#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public void build(final Composite parent) {
+ final int size = this.widgets.size();
+ int columIndex = 0;
+ for (int i = 0; i < size; i++) {
+ final PWWidget widget = this.widgets.get(i);
+ final Control control = widget.checkAndBuild(parent);
+ if (control != null && control.getLayoutData() == null) {
+ final int colSpan;
+ final boolean grabExcessSpace;
+ final int alignment;
+ if (size == 1) {
+ if (widget.isSingleWidget()) {
+ colSpan = this.parentNumberOfColums;
+ } else {
+ colSpan = this.parentNumberOfColums - widget.getNumberOfColumns() + 1;
+ }
+ grabExcessSpace = true;
+ } else {
+ if (i == size - 1) {
+ colSpan = this.parentNumberOfColums - columIndex;
+ grabExcessSpace = widget.isGrabExcessSpace();
+ } else {
+ colSpan = 1;
+ grabExcessSpace = widget instanceof PWButton && i == 0 ? true : widget.isGrabExcessSpace();
+ }
+ }
+ columIndex += widget.getNumberOfColumns();
+
+ if (i == 0 && grabExcessSpace && size > 1) {
+ if (widget instanceof PWLabel || widget instanceof PWButton) {
+ alignment = GridData.END;
+ } else {
+ alignment = GridData.BEGINNING;
+ }
+ } else {
+ alignment = widget.getAlignment();
+ }
+
+ final GridData gd = new GridData(alignment, GridData.BEGINNING, grabExcessSpace, false, colSpan, 1);
+ gd.horizontalIndent = widget.getIndent();
+ gd.widthHint = widget.getWidth();
+ if (widget.getHeight() != -1) {
+ gd.heightHint = widget.getHeight();
+ }
+ control.setLayoutData(gd);
+ }
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWRowGroup#checkParent(org.mihalis.opal.preferenceWindow.PWContainer)
+ */
+ @Override
+ protected void checkParent(final PWContainer parent) {
+ if (parent instanceof PWTab || parent instanceof PWGroup) {
+ return;
+ }
+ throw new UnsupportedOperationException("Bad parent, should be only PWTab or PWGroup");
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWRowGroup#enableOrDisable()
+ */
+ @Override
+ public void enableOrDisable() {
+ if (this.enabler == null) {
+ return;
+ }
+
+ final boolean enabled = this.enabler.isEnabled();
+ for (final PWWidget widget : this.widgets) {
+ final boolean widgetEnable = widget.enableOrDisable();
+ for (final Control c : widget.getControls()) {
+ if (!c.isDisposed()) {
+ c.setEnabled(enabled && widgetEnable);
+ }
+ }
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWRowGroup.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWRowGroup.java
new file mode 100644
index 000000000..63674bc29
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWRowGroup.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow;
+
+import org.mihalis.opal.preferenceWindow.enabler.Enabler;
+
+/**
+ * Abstract class for both row and groups
+ */
+public abstract class PWRowGroup extends PWContainer {
+
+ protected int numberOfColumns;
+ protected int parentNumberOfColums;
+ protected PWContainer parent;
+ protected Enabler enabler;
+
+ /**
+ * Check if the parent is compatible with the object
+ *
+ * @param parent parent to check
+ * @throws UnsupportedOperationException if the parent is not compatible
+ * with the object
+ */
+ protected abstract void checkParent(PWContainer parent);
+
+ /**
+ * Enables or disables all elements stored in this group or row
+ */
+ public abstract void enableOrDisable();
+
+ /**
+ * Add a column to the current element
+ *
+ * @param number number of column to add
+ */
+ public void addColumn(final int number) {
+ this.numberOfColumns += number;
+ }
+
+ /**
+ * @return the number of columns of this group or row
+ */
+ public int getNumberOfColums() {
+ return this.numberOfColumns;
+ }
+
+ /**
+ * @param enabler the enabler to set
+ */
+ public PWRowGroup setEnabler(final Enabler enabler) {
+ this.enabler = enabler;
+ this.enabler.injectRowGroup(this);
+ return this;
+ }
+
+ /**
+ * @param parent the parent to set
+ */
+ public void setParent(final PWContainer parent) {
+ checkParent(parent);
+ this.parent = parent;
+ }
+
+ /**
+ * @param numberOfColumns the number of columns of the parent
+ */
+ public void setParentNumberOfColumns(final int numberOfColumns) {
+ this.parentNumberOfColums = numberOfColumns;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWTab.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWTab.java
new file mode 100644
index 000000000..03fc554be
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWTab.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.mihalis.opal.preferenceWindow.widgets.PWWidget;
+
+/**
+ * Instance of this class are tabs
+ *
+ */
+public class PWTab extends PWContainer {
+ private final Image image;
+ private final String text;
+ private final List<PWRowGroup> children;
+
+ /**
+ * Constructor
+ *
+ * @param image image associated to the tab
+ * @param text text associated to the tab
+ */
+ PWTab(final Image image, final String text) {
+ this.image = image;
+ this.text = text;
+ this.children = new ArrayList<PWRowGroup>();
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWContainer#add(org.mihalis.opal.preferenceWindow.PWContainer)
+ */
+ @Override
+ public PWContainer add(final PWContainer element) {
+ if (!(element instanceof PWGroup) && !(element instanceof PWRow)) {
+ throw new UnsupportedOperationException("Can only add a PWGroup or a PWRow.");
+ }
+ ((PWRowGroup) element).setParent(this);
+ this.children.add((PWRowGroup) element);
+ return this;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWContainer#add(org.mihalis.opal.preferenceWindow.widgets.PWWidget)
+ */
+ @Override
+ public PWContainer add(final PWWidget widget) {
+ final PWRow row = new PWRow();
+ row.setParent(this);
+ row.add(widget);
+ this.children.add(row);
+ return this;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.PWContainer#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public void build(final Composite parent) {
+ final int numberOfColumns = computeNumberOfColums();
+ parent.setLayout(new GridLayout(numberOfColumns, false));
+
+ for (final PWRowGroup rowGroup : this.children) {
+ rowGroup.setParentNumberOfColumns(numberOfColumns);
+ rowGroup.build(parent);
+ }
+
+ PreferenceWindow.getInstance().fireEnablers();
+
+ }
+
+ /**
+ * @return the total number of columns in this tab
+ */
+ private int computeNumberOfColums() {
+ int numberOfColumns = 1;
+ for (final PWRowGroup rowGroup : this.children) {
+ if (rowGroup instanceof PWRow) {
+ numberOfColumns = Math.max(numberOfColumns, rowGroup.getNumberOfColums());
+ }
+ }
+ return numberOfColumns;
+ }
+
+ /**
+ * @return the image associate to this tab
+ */
+ public Image getImage() {
+ return this.image;
+ }
+
+ /**
+ * @return the text associated to this tab
+ */
+ public String getText() {
+ return this.text;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWTabContainer.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWTabContainer.java
new file mode 100644
index 000000000..8bfe14c5f
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PWTabContainer.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.flatButton.FlatButton;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are a container that allows the user to select a tab
+ */
+class PWTabContainer extends Composite {
+
+ private final List<PWTab> tabs;
+ private Composite container;
+ private Image oldButtonContainerImage;
+ private final List<FlatButton> buttons;
+ private Composite buttonContainer;
+
+ /**
+ * Constructor
+ *
+ * @param parent parent composite
+ * @param style style (not used)
+ * @param tabs list of tabs
+ */
+ PWTabContainer(final Composite parent, final int style, final List<PWTab> tabs) {
+ super(parent, style);
+ this.tabs = new ArrayList<PWTab>();
+ this.tabs.addAll(tabs);
+
+ this.buttons = new ArrayList<FlatButton>();
+
+ final GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginWidth = gridLayout.marginHeight = 0;
+ gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
+ setLayout(gridLayout);
+
+ }
+
+ /**
+ * Build the container
+ */
+ void build() {
+ build(null);
+ }
+
+ void build(Color selectedTabColor) {
+
+ createButtonsContainer();
+ createButtons(selectedTabColor);
+ createContentContainer();
+
+ select(0);
+ }
+
+ /**
+ * Create the buttons container
+ */
+ private void createButtonsContainer() {
+ createContainer();
+ createButtonsContainerBackground();
+
+ }
+
+ /**
+ * Create the container
+ */
+ private void createContainer() {
+ this.buttonContainer = new Composite(this, SWT.NONE);
+ final GridData buttonContainerGridData = new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1);
+ //buttonContainerGridData.heightHint = 63; // Original size (32x32)
+ //buttonContainerGridData.heightHint = 79; // Tizen fit size (48x48)
+ this.buttonContainer.setLayoutData(buttonContainerGridData);
+
+ this.buttonContainer.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+
+ final GridLayout gridLayout = new GridLayout(this.tabs.size(), false);
+ gridLayout.marginWidth = gridLayout.marginHeight = 0;
+ gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
+ gridLayout.marginBottom = 2;
+ this.buttonContainer.setLayout(gridLayout);
+ }
+
+ /**
+ * Create the background of the container
+ */
+ private void createButtonsContainerBackground() {
+ this.buttonContainer.addListener(SWT.Resize, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ final Rectangle rect = PWTabContainer.this.buttonContainer.getClientArea();
+ final Image image = new Image(getDisplay(), Math.max(1, rect.width), Math.max(1, rect.height));
+ final GC gc = new GC(image);
+ final Color grey = new Color(getDisplay(), 204, 204, 204);
+ gc.setForeground(grey);
+ gc.drawLine(0, rect.height - 1, rect.width, rect.height - 1);
+ grey.dispose();
+ gc.dispose();
+ PWTabContainer.this.buttonContainer.setBackgroundImage(image);
+ if (PWTabContainer.this.oldButtonContainerImage != null) {
+ PWTabContainer.this.oldButtonContainerImage.dispose();
+ }
+ PWTabContainer.this.oldButtonContainerImage = image;
+
+ }
+ });
+ SWTGraphicUtil.dispose(this.buttonContainer, this.oldButtonContainerImage);
+ }
+
+// /**
+// * Create the buttons
+// */
+// private void createButtons() {
+// createButtons(null);
+// }
+
+ private void createButtons(Color selectedTabColor) {
+ for (int i = 0; i < this.tabs.size(); i++) {
+ final PWTab tab = this.tabs.get(i);
+ final FlatButton button = new FlatButton(this.buttonContainer, SWT.NONE);
+ button.setText(tab.getText());
+ button.setImage(tab.getImage());
+
+ if(selectedTabColor != null) {
+ button.setSelectedColor(selectedTabColor);
+ }
+ SWTGraphicUtil.dispose(button, tab.getImage());
+
+ final GridData gd;
+ if (i == this.tabs.size() - 1) {
+ gd = new GridData(GridData.BEGINNING, GridData.BEGINNING, true, false);
+ } else {
+ gd = new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false);
+ }
+ if (i == 0) {
+ gd.horizontalIndent = 5;
+ }
+ gd.widthHint = 75;
+ button.setLayoutData(gd);
+
+ final int index = i;
+ button.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ select(index);
+ }
+
+ });
+
+ this.buttons.add(button);
+
+ }
+ }
+
+ /**
+ * Select a given button
+ *
+ * @param index index of the selected button
+ */
+ private void select(final int index) {
+ for (final Control c : this.container.getChildren()) {
+ c.dispose();
+ }
+
+ this.tabs.get(index).build(this.container);
+ this.container.layout();
+
+ for (int i = 0; i < this.buttons.size(); i++) {
+ this.buttons.get(i).setSelection(i == index);
+ }
+ }
+
+ /**
+ * Create the content container, ie the composite that will contain all
+ * widgets
+ */
+ private void createContentContainer() {
+ this.container = new Composite(this, SWT.NONE);
+ final GridData tempContainer = new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1);
+
+ int defaultSize = 350;
+ int notebookSize = 280;
+
+ //tempContainer.widthHint = 700;
+ tempContainer.heightHint = defaultSize;
+
+ Rectangle bounds = Display.getCurrent().getBounds();
+ if (bounds.height <= (768 + defaultSize - notebookSize)) {
+ tempContainer.heightHint = notebookSize; // 280px is fitted on 768px display
+ }
+
+ this.container.setLayoutData(tempContainer);
+ }
+
+ public Composite getContainer() {
+ return this.container;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PreferenceWindow.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PreferenceWindow.java
new file mode 100644
index 000000000..01de51e67
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/PreferenceWindow.java
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.mihalis.opal.preferenceWindow.widgets.PWWidget;
+import org.mihalis.opal.utils.ResourceManager;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * This class is a preference window
+ *
+ */
+public class PreferenceWindow {
+ private final Map<String, ValueAndAssociatedWidgets> values;
+ private final List<PWTab> tabs;
+ private final Shell parentShell;
+ private boolean returnedValue;
+ private Shell shell;
+ private static PreferenceWindow instance;
+
+
+ /**
+ * Constructor
+ *
+ * @param parent parent shell (may be null)
+ * @param values a map that contains all values that will be displayed in
+ * widgets
+ */
+ private PreferenceWindow(final Shell parent, final Map<String, Object> values) {
+ this.parentShell = parent;
+ this.values = new HashMap<String, ValueAndAssociatedWidgets>(values.size());
+
+ for (final String key : values.keySet()) {
+ this.values.put(key, new ValueAndAssociatedWidgets(values.get(key)));
+ }
+
+ this.tabs = new ArrayList<PWTab>();
+ }
+
+ /**
+ * Create a preference window (a singleton)
+ *
+ * @param parent parent shell (may be null)
+ * @param values a map that contains all values that will be displayed in
+ * widgets
+ * @return
+ */
+ public static PreferenceWindow create(final Shell parent, final Map<String, Object> values) {
+ instance = new PreferenceWindow(parent, values);
+ return instance;
+ }
+
+ /**
+ * Create a preference window (a singleton)
+ *
+ * @param values a map that contains all values that will be displayed in
+ * widgets
+ * @return
+ */
+ public static PreferenceWindow create(final Map<String, Object> values) {
+ instance = new PreferenceWindow(null, values);
+ return instance;
+ }
+
+ /**
+ * @return an instance of the preference window
+ */
+ public static PreferenceWindow getInstance() {
+ if (instance == null) {
+ throw new NullPointerException("The instance of PreferenceWindow has not yet been created or has been destroyed.");
+ }
+ return instance;
+ }
+
+ /**
+ * Add a tab to the preference window
+ *
+ * @param image image associated to the tab
+ * @param text text associated to the image
+ * @return the
+ */
+ public PWTab addTab(final Image image, final String text) {
+ final PWTab tab = new PWTab(image, text);
+ this.tabs.add(tab);
+ return tab;
+ }
+
+ /**
+ * Add a widget that is linked to a given property
+ *
+ * @param propertyKey the property
+ * @param widget the widget
+ */
+ public void addWidgetLinkedTo(final String propertyKey, final PWWidget widget) {
+ if (!this.values.containsKey(propertyKey)) {
+ this.values.put(propertyKey, new ValueAndAssociatedWidgets(null));
+ }
+ this.values.get(propertyKey).addWidget(widget);
+ }
+
+ /**
+ * Add a row group that is linked to a given property
+ *
+ * @param propertyKey the property
+ * @param rowGroup the widget
+ */
+ public void addRowGroupLinkedTo(final String propertyKey, final PWRowGroup rowGroup) {
+ if (!this.values.containsKey(propertyKey)) {
+ this.values.put(propertyKey, new ValueAndAssociatedWidgets(null));
+ }
+ this.values.get(propertyKey).addRowGroup(rowGroup);
+ }
+
+ /**
+ * Open the preference window
+ *
+ * @return <code>true</code> if the user pressed on the Ok button,
+ * <code>false</code> if the user pressed on the Cancel button
+ */
+ public boolean open() {
+ if (this.parentShell == null) {
+ this.shell = new Shell(SWT.SHELL_TRIM);
+ } else {
+ this.shell = new Shell(instance.parentShell, SWT.SHELL_TRIM);
+ }
+
+ this.shell.addListener(SWT.Dispose, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ instance = null;
+ }
+ });
+
+ buildShell();
+ openShell();
+
+ return this.returnedValue;
+ }
+
+ /**
+ * Builds the shell
+ */
+ private void buildShell() {
+ this.shell.setText(ResourceManager.getLabel(ResourceManager.PREFERENCES));
+ final GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginWidth = gridLayout.marginHeight = 0;
+ gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
+ this.shell.setLayout(gridLayout);
+ final PWTabContainer container = new PWTabContainer(this.shell, SWT.NONE, this.tabs);
+ container.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1));
+ container.build();
+
+ final Label sep = new Label(this.shell, SWT.SEPARATOR | SWT.HORIZONTAL);
+ sep.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1));
+
+ buildButtons();
+
+ }
+
+ /**
+ * Builds the Tabs for inner composite
+ *
+ * @author Jihoon Song {@literal <jihoon80.song@samsung.com>} (S-Core)
+ */
+ public void buildTabs(Composite parent) {
+ buildTabs(parent, null);
+ }
+
+ public void buildTabs(Composite parent, Color selectedTabColor) {
+ final PWTabContainer container = new PWTabContainer(parent, SWT.BORDER, this.tabs);
+ container.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1));
+ container.build(selectedTabColor);
+ }
+
+ /**
+ * Builds the buttons
+ */
+ private void buildButtons() {
+ final Button buttonOK = new Button(this.shell, SWT.PUSH);
+ buttonOK.setText(ResourceManager.getLabel(ResourceManager.OK));
+ final GridData gridDataOk = new GridData(GridData.END, GridData.END, true, false);
+ gridDataOk.widthHint = 100;
+ buttonOK.setLayoutData(gridDataOk);
+ buttonOK.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ PreferenceWindow.this.returnedValue = true;
+ PreferenceWindow.this.shell.dispose();
+ }
+
+ });
+ this.shell.setDefaultButton(buttonOK);
+
+ final Button buttonCancel = new Button(this.shell, SWT.PUSH);
+ buttonCancel.setText(ResourceManager.getLabel(ResourceManager.CANCEL));
+ final GridData gridDataCancel = new GridData(GridData.BEGINNING, GridData.END, false, false);
+ gridDataCancel.widthHint = 100;
+ buttonCancel.setLayoutData(gridDataCancel);
+ buttonCancel.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ PreferenceWindow.this.returnedValue = false;
+ PreferenceWindow.this.shell.dispose();
+ }
+
+ });
+ }
+
+ /**
+ * Open the shell
+ */
+ private void openShell() {
+ this.shell.pack();
+ this.shell.open();
+ SWTGraphicUtil.centerShell(this.shell);
+
+ while (!this.shell.isDisposed()) {
+ if (!this.shell.getDisplay().readAndDispatch()) {
+ this.shell.getDisplay().sleep();
+ }
+ }
+
+ }
+
+ /**
+ * Fire all enablers
+ */
+ public void fireEnablers() {
+ for (final String key : this.values.keySet()) {
+ this.values.get(key).fireValueChanged();
+ }
+ }
+
+ /**
+ * @param key
+ * @return the value associated to the <i>key</i>
+ */
+ public Object getValueFor(final String key) {
+ if (this.values.containsKey(key)) {
+ return this.values.get(key).getValue();
+ }
+ return null;
+ }
+
+ /**
+ * @return the list of all values
+ */
+ public Map<String, Object> getValues() {
+ final Map<String, Object> returnedValues = new HashMap<String, Object>();
+ for (final String key : this.values.keySet()) {
+ returnedValues.put(key, this.values.get(key).getValue());
+ }
+ return returnedValues;
+ }
+
+ /**
+ * Store a value associated to the key
+ *
+ * @param key
+ * @param value
+ */
+ public void setValue(final String key, final Object value) {
+ if (this.values.containsKey(key)) {
+ this.values.get(key).setValue(value);
+ } else {
+ this.values.put(key, new ValueAndAssociatedWidgets(value));
+ }
+
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/ValueAndAssociatedWidgets.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/ValueAndAssociatedWidgets.java
new file mode 100644
index 000000000..5d13736fd
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/ValueAndAssociatedWidgets.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.mihalis.opal.preferenceWindow.widgets.PWWidget;
+
+/**
+ * This POJO contains a value a list of widgets that depends on a given property
+ *
+ */
+class ValueAndAssociatedWidgets {
+ private Object value;
+ private final List<PWWidget> widgets;
+ private final List<PWRowGroup> rowGroups;
+
+ /**
+ * Constructor
+ *
+ * @param value associated value
+ */
+ ValueAndAssociatedWidgets(final Object value) {
+ this.value = value;
+ this.widgets = new ArrayList<PWWidget>();
+ this.rowGroups = new ArrayList<PWRowGroup>();
+ }
+
+ /**
+ * @param widget dependant widget
+ */
+ void addWidget(final PWWidget widget) {
+ this.widgets.add(widget);
+ }
+
+ /**
+ * @param rowGroup dependant row or group
+ */
+ void addRowGroup(final PWRowGroup rowGroup) {
+ this.rowGroups.add(rowGroup);
+ }
+
+ /**
+ * @return the value stored in the instance
+ */
+ Object getValue() {
+ return this.value;
+ }
+
+ /**
+ * @param value new value stored in this instance
+ */
+ void setValue(final Object value) {
+ this.value = value;
+ fireValueChanged();
+ }
+
+ /**
+ * Fire events when the value has changed
+ */
+ void fireValueChanged() {
+ for (final PWRowGroup rowGroup : this.rowGroups) {
+ rowGroup.enableOrDisable();
+ }
+
+ for (final PWWidget widget : this.widgets) {
+ widget.enableOrDisable();
+ }
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfEquals.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfEquals.java
new file mode 100644
index 000000000..b29db9dce
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfEquals.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.enabler;
+
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * This enabler is used to enable a widget if a property is equal to a given
+ * value
+ */
+public class EnabledIfEquals extends Enabler {
+ private final Object value;
+
+ /**
+ * Constructor
+ *
+ * @param prop property to evaluate
+ * @param value condition value
+ */
+ public EnabledIfEquals(final String prop, final Object value) {
+ super(prop);
+ this.value = value;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.enabler.Enabler#isEnabled()
+ */
+ @Override
+ public boolean isEnabled() {
+ final Object propValue = PreferenceWindow.getInstance().getValueFor(this.prop);
+ if (this.value == null) {
+ return propValue == null;
+ }
+ return this.value.equals(propValue);
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfNotEquals.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfNotEquals.java
new file mode 100644
index 000000000..7f4e9c130
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfNotEquals.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.enabler;
+
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * This enabler is used to enable a widget if a property is not equal to a given
+ * value
+ */
+public class EnabledIfNotEquals extends Enabler {
+ private final Object value;
+
+ /**
+ * Constructor
+ *
+ * @param prop property to evaluate
+ * @param value condition value
+ */
+ public EnabledIfNotEquals(final String prop, final Object value) {
+ super(prop);
+ this.value = value;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.enabler.Enabler#isEnabled()
+ */
+ @Override
+ public boolean isEnabled() {
+ final Object propValue = PreferenceWindow.getInstance().getValueFor(this.prop);
+ if (this.value == null) {
+ return propValue == null;
+ }
+ return !this.value.equals(propValue);
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfTrue.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfTrue.java
new file mode 100644
index 000000000..969e2c58a
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/EnabledIfTrue.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.enabler;
+
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * This enabler is used to enable a widget if a boolean property is true
+ */
+public class EnabledIfTrue extends Enabler {
+
+ /**
+ * Constructor
+ *
+ * @param prop boolean property
+ */
+ public EnabledIfTrue(final String prop) {
+ super(prop);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.enabler.Enabler#isEnabled()
+ */
+ @Override
+ public boolean isEnabled() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(this.prop);
+
+ if (value != null && !(value instanceof Boolean)) {
+ throw new UnsupportedOperationException("Impossible to evaluate [" + this.prop + "] because it is not a Boolean !");
+ }
+
+ if (value == null) {
+ return true;
+ }
+
+ return ((Boolean) value).booleanValue();
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/Enabler.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/Enabler.java
new file mode 100644
index 000000000..3b0e04afd
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/enabler/Enabler.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.enabler;
+
+import org.mihalis.opal.preferenceWindow.PWRowGroup;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+import org.mihalis.opal.preferenceWindow.widgets.PWWidget;
+
+/**
+ * This is the abstract class of all Enablers. An enabler is an object used to
+ * enable or disable a widget depending on a value of a stored property.
+ */
+public abstract class Enabler {
+
+ protected String prop;
+
+ /**
+ * Constructor
+ *
+ * @param prop property linked to the enabler.
+ */
+ public Enabler(final String prop) {
+ this.prop = prop;
+ }
+
+ /**
+ * @return the evaluation condition
+ */
+ public abstract boolean isEnabled();
+
+ /**
+ * Link a widget to the enabler
+ *
+ * @param widget widget to link
+ */
+ public void injectWidget(final PWWidget widget) {
+ PreferenceWindow.getInstance().addWidgetLinkedTo(this.prop, widget);
+ }
+
+ /**
+ * Link a row or a group to the enabler
+ *
+ * @param rowGroup RowGroup to link
+ */
+ public void injectRowGroup(final PWRowGroup rowGroup) {
+ PreferenceWindow.getInstance().addRowGroupLinkedTo(this.prop, rowGroup);
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWButton.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWButton.java
new file mode 100644
index 000000000..4762b8050
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWButton.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Instances of this class are buttons
+ *
+ */
+public class PWButton extends PWWidget {
+ private final SelectionListener listener;
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param listener selection listener
+ */
+ public PWButton(final String label, final SelectionListener listener) {
+ super(label, null, 1, true);
+ this.listener = listener;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ final Button button = new Button(parent, SWT.PUSH);
+ addControl(button);
+ if (getLabel() == null) {
+ throw new UnsupportedOperationException("You need to set a label for a button");
+ } else {
+ button.setText(getLabel());
+ }
+ if (this.listener != null) {
+ button.addSelectionListener(this.listener);
+ }
+
+ return button;
+
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWCheckbox.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWCheckbox.java
new file mode 100644
index 000000000..8dc7f367e
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWCheckbox.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are checkboxes
+ */
+public class PWCheckbox extends PWWidget {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWCheckbox(final String label, final String propertyKey) {
+ super(label, propertyKey, 1, true);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ if (getLabel() == null) {
+ throw new UnsupportedOperationException("Please specify a label for a checkbox");
+ }
+ final Button button = new Button(parent, SWT.CHECK);
+ addControl(button);
+ button.setText(getLabel());
+ final boolean originalSelection = (Boolean) PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ button.setSelection(originalSelection);
+
+ button.addSelectionListener(new SelectionAdapter() {
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), button.getSelection());
+ }
+ });
+ return button;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), new Boolean(false));
+ } else {
+ if (!(value instanceof Boolean)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a Boolean because it is associated to a checkbox");
+ }
+ }
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWChooser.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWChooser.java
new file mode 100644
index 000000000..318215a50
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWChooser.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.mihalis.opal.utils.ResourceManager;
+
+/**
+ * Abstract class for chooser widgets
+ *
+ */
+public abstract class PWChooser extends PWWidget {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWChooser(final String label, final String propertyKey) {
+ super(label, propertyKey, 3, false);
+ setGrabExcessSpace(false);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ final Label label = new Label(parent, SWT.NONE);
+
+ if (getLabel() == null) {
+ throw new UnsupportedOperationException("You need to set a label for a directory or a dialog chooser");
+ } else {
+ label.setText(getLabel());
+ }
+ addControl(label);
+ final GridData labelGridData = new GridData(GridData.END, GridData.BEGINNING, false, false);
+ labelGridData.horizontalIndent = getIndent();
+ label.setLayoutData(labelGridData);
+
+ final Text text = new Text(parent, SWT.BORDER | SWT.READ_ONLY);
+ addControl(text);
+ final GridData textGridData = new GridData(GridData.FILL, GridData.BEGINNING, true, false);
+ text.setLayoutData(textGridData);
+
+ final Button button = new Button(parent, SWT.PUSH);
+ addControl(button);
+ final GridData buttonGridData = new GridData(GridData.FILL, GridData.BEGINNING, false, false);
+ buttonGridData.widthHint = 150;
+ button.setText(ResourceManager.getLabel(ResourceManager.CHOOSE) + "...");
+ button.setLayoutData(buttonGridData);
+
+ setButtonAction(text, button);
+
+ return button;
+
+ }
+
+ /**
+ * Code executed when the user presses the button
+ *
+ * @param text text box
+ * @param button associated button
+ */
+ protected abstract void setButtonAction(Text text, Button button);
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWColorChooser.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWColorChooser.java
new file mode 100644
index 000000000..0d3b1b327
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWColorChooser.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.ColorDialog;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are used to select a color
+ *
+ */
+public class PWColorChooser extends PWWidget {
+
+ private Color color;
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWColorChooser(final String label, final String propertyKey) {
+ super(label, propertyKey, label == null ? 1 : 2, false);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ final RGB rgb = (RGB) PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+
+ if (rgb == null) {
+ this.color = Display.getDefault().getSystemColor(SWT.COLOR_WHITE);
+ } else {
+ this.color = new Color(Display.getDefault(), rgb);
+ }
+
+ buildLabel(parent, GridData.CENTER);
+ final Button button = new Button(parent, SWT.PUSH);
+ addControl(button);
+
+ button.addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ drawButton(button);
+ }
+ });
+
+ button.addListener(SWT.Selection, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ final ColorDialog dialog = new ColorDialog(button.getShell());
+ final RGB result = dialog.open();
+ if (result != null) {
+ SWTGraphicUtil.dispose(PWColorChooser.this.color);
+ PWColorChooser.this.color = new Color(button.getDisplay(), result);
+ drawButton(button);
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), result);
+ }
+ }
+ });
+
+ button.addListener(SWT.Dispose, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ SWTGraphicUtil.dispose(PWColorChooser.this.color);
+ }
+ });
+
+ return button;
+ }
+
+ /**
+ * @param button button on which we draw the rectangle
+ */
+ protected void drawButton(final Button button) {
+ final int height = (int) button.getFont().getFontData()[0].height;
+ final int width = button.getBounds().width - 16;
+
+ final Image newImage = new Image(button.getDisplay(), Math.max(1, width), Math.max(1, height));
+
+ final GC gc = new GC(newImage);
+ gc.setBackground(PWColorChooser.this.color);
+ gc.fillRectangle(0, 0, width, height);
+
+ gc.setForeground(button.getDisplay().getSystemColor(SWT.COLOR_BLACK));
+ gc.drawRectangle(0, 0, width - 1, height - 1);
+
+ gc.dispose();
+
+ button.setImage(newImage);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), null);
+ } else {
+ if (!(value instanceof RGB)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a RGB because it is associated to a color chooser");
+ }
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWCombo.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWCombo.java
new file mode 100644
index 000000000..1960011bc
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWCombo.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are Combo
+ *
+ */
+public class PWCombo extends PWWidget {
+
+ private final List<Object> data;
+ private final boolean editable;
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWCombo(final String label, final String propertyKey, final Object... values) {
+ this(label, propertyKey, false, values);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWCombo(final String label, final String propertyKey, final boolean editable, final Object... values) {
+ super(label, propertyKey, label == null ? 1 : 2, false);
+ this.data = new ArrayList<Object>(Arrays.asList(values));
+ this.editable = editable;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ buildLabel(parent, GridData.CENTER);
+
+ final Combo combo = new Combo(parent, SWT.BORDER | (this.editable ? SWT.NONE : SWT.READ_ONLY));
+ addControl(combo);
+
+ for (int i = 0; i < this.data.size(); i++) {
+ final Object datum = this.data.get(i);
+ combo.add(datum.toString());
+ if (datum.equals(PreferenceWindow.getInstance().getValueFor(getPropertyKey()))) {
+ combo.select(i);
+ }
+ }
+
+ combo.addListener(SWT.Modify, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), PWCombo.this.data.get(combo.getSelectionIndex()));
+ }
+ });
+
+ return combo;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), null);
+ } else {
+ if (this.editable && !(value instanceof String)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a String because it is associated to an editable combo");
+ }
+
+ if (!this.data.isEmpty()) {
+ if (!value.getClass().equals(this.data.get(0).getClass())) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a " + this.data.get(0).getClass() + " because it is associated to a combo");
+ }
+ }
+
+ }
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWDirectoryChooser.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWDirectoryChooser.java
new file mode 100644
index 000000000..db0cd9b13
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWDirectoryChooser.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+import org.mihalis.opal.utils.ResourceManager;
+
+/**
+ * Instances of this class are used to select a directory
+ */
+public class PWDirectoryChooser extends PWChooser {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWDirectoryChooser(final String label, final String propertyKey) {
+ super(label, propertyKey);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWChooser#setButtonAction(org.eclipse.swt.widgets.Text,
+ * org.eclipse.swt.widgets.Button)
+ */
+ @Override
+ protected void setButtonAction(final Text text, final Button button) {
+
+ final String originalDirectory = (String) PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ text.setText(originalDirectory);
+
+ button.addListener(SWT.Selection, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ final DirectoryDialog dialog = new DirectoryDialog(text.getShell());
+ dialog.setMessage(ResourceManager.getLabel(ResourceManager.CHOOSE_DIRECTORY));
+ final String result = dialog.open();
+ if (result != null) {
+ text.setText(result);
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), result);
+ }
+
+ }
+ });
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), "");
+ } else {
+ if (!(value instanceof String)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a String because it is associated to a directory chooser");
+ }
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFileChooser.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFileChooser.java
new file mode 100644
index 000000000..421aa0e76
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFileChooser.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are used to select a file
+ */
+public class PWFileChooser extends PWChooser {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWFileChooser(final String label, final String propertyKey) {
+ super(label, propertyKey);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWChooser#setButtonAction(org.eclipse.swt.widgets.Text,
+ * org.eclipse.swt.widgets.Button)
+ */
+ @Override
+ protected void setButtonAction(final Text text, final Button button) {
+ final String originalFile = (String) PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ text.setText(originalFile);
+
+ button.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ final FileDialog dialog = new FileDialog(text.getShell(), SWT.OPEN);
+ final String result = dialog.open();
+ if (result != null) {
+ text.setText(result);
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), result);
+ }
+
+ }
+ });
+
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), "");
+ } else {
+ if (!(value instanceof String)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a String because it is associated to a file chooser");
+ }
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFloatText.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFloatText.java
new file mode 100644
index 000000000..db6446816
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFloatText.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+import org.mihalis.opal.utils.StringUtil;
+
+/**
+ * Instances of this class are text box to type floats
+ */
+public class PWFloatText extends PWText {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWFloatText(final String label, final String propertyKey) {
+ super(label, propertyKey);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#addVerifyListeners()
+ */
+ @Override
+ public void addVerifyListeners() {
+ this.text.addVerifyListener(new VerifyListener() {
+
+ @Override
+ public void verifyText(final VerifyEvent e) {
+ if (e.character != 0 && !Character.isDigit(e.character) && e.keyCode != SWT.BS && e.keyCode != SWT.DEL && e.character != '.' && e.character != ',') {
+ e.doit = false;
+ return;
+ }
+
+ e.doit = verifyEntry(e.text, e.keyCode);
+
+ }
+ });
+
+ }
+
+ /**
+ * Check if an entry is a float
+ *
+ * @param entry text typed by the user
+ * @param keyCode key code
+ * @return true if the user typed a float value, false otherwise
+ */
+ private boolean verifyEntry(final String entry, final int keyCode) {
+ final String work;
+ if (keyCode == SWT.DEL) {
+ work = StringUtil.removeCharAt(this.text.getText(), this.text.getCaretPosition());
+ } else if (keyCode == SWT.BS && this.text.getCaretPosition() == 0) {
+ work = StringUtil.removeCharAt(this.text.getText(), this.text.getCaretPosition() - 1);
+ } else if (keyCode == 0) {
+ work = entry;
+ } else {
+ work = StringUtil.insertString(this.text.getText(), entry, this.text.getCaretPosition());
+ }
+
+ try {
+ Double.parseDouble(work.replace(',', '.'));
+ } catch (final NumberFormatException nfe) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), new Float(0));
+ } else {
+ if (!(value instanceof Float)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a Float because it is associated to a float text widget");
+ }
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#convertValue()
+ */
+ @Override
+ public Object convertValue() {
+ return Float.parseFloat(this.text.getText());
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#getStyle()
+ */
+ @Override
+ public int getStyle() {
+ return SWT.NONE;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFontChooser.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFontChooser.java
new file mode 100644
index 000000000..5637fe2ea
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWFontChooser.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FontDialog;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+import org.mihalis.opal.utils.ResourceManager;
+
+/**
+ * Instances of this class are used to select a font
+ */
+public class PWFontChooser extends PWChooser {
+ private FontData fontData;
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWFontChooser(final String label, final String propertyKey) {
+ super(label, propertyKey);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), null);
+ } else {
+ if (!(value instanceof FontData)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a FontData because it is associated to a font chooser");
+ }
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWChooser#setButtonAction(org.eclipse.swt.widgets.Text,
+ * org.eclipse.swt.widgets.Button)
+ */
+ @Override
+ protected void setButtonAction(final Text text, final Button button) {
+ this.fontData = (FontData) PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+
+ button.addListener(SWT.Selection, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ final FontDialog dialog = new FontDialog(text.getShell());
+ final FontData result = dialog.open();
+ if (result != null && result.getName() != null && !"".equals(result.getName().trim())) {
+ PWFontChooser.this.fontData = result;
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), result);
+ text.setText(buildFontInformation());
+ }
+
+ }
+ });
+
+ }
+
+ /**
+ * @return a string that contains data about the choosen font
+ */
+ protected String buildFontInformation() {
+ final StringBuilder sb = new StringBuilder();
+ if (this.fontData != null) {
+ sb.append(this.fontData.getName()).append(",").append(this.fontData.getHeight()).append(" pt");
+ if ((this.fontData.getStyle() & SWT.BOLD) == SWT.BOLD) {
+ sb.append(", ").append(ResourceManager.getLabel(ResourceManager.BOLD));
+ }
+ if ((this.fontData.getStyle() & SWT.ITALIC) == SWT.ITALIC) {
+ sb.append(", ").append(ResourceManager.getLabel(ResourceManager.ITALIC));
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWIntegerText.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWIntegerText.java
new file mode 100644
index 000000000..8e681df17
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWIntegerText.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are text box to type Integers
+ */
+public class PWIntegerText extends PWText {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWIntegerText(final String label, final String propertyKey) {
+ super(label, propertyKey);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#addVerifyListeners()
+ */
+ @Override
+ public void addVerifyListeners() {
+ this.text.addListener(SWT.Verify, new Listener() {
+ @Override
+ public void handleEvent(final Event e) {
+ final String string = e.text;
+ final char[] chars = new char[string.length()];
+ string.getChars(0, chars.length, chars, 0);
+ for (int i = 0; i < chars.length; i++) {
+ if (!('0' <= chars[i] && chars[i] <= '9') && e.keyCode != SWT.BS && e.keyCode != SWT.DEL) {
+ e.doit = false;
+ return;
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), new Integer(0));
+ } else {
+ if (!(value instanceof Integer)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be an Integer because it is associated to a integer text widget");
+ }
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#convertValue()
+ */
+ @Override
+ public Object convertValue() {
+ return Integer.parseInt(this.text.getText());
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#getStyle()
+ */
+ @Override
+ public int getStyle() {
+ return SWT.NONE;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWLabel.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWLabel.java
new file mode 100644
index 000000000..bcffef7b8
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWLabel.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are labels, that could contain some HTML tags (B,I,U)
+ */
+public class PWLabel extends PWWidget {
+
+ private StyledText labelWidget;
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ */
+ public PWLabel(final String label) {
+ super(label, null, 1, true);
+ setAlignment(GridData.FILL);
+ setGrabExcessSpace(true);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ if (getLabel() == null) {
+ throw new UnsupportedOperationException("You need to set a description for a PWLabel object");
+ }
+ this.labelWidget = new StyledText(parent, SWT.WRAP | SWT.READ_ONLY);
+ this.labelWidget.setEnabled(false);
+ this.labelWidget.setBackground(parent.getBackground());
+ this.labelWidget.setText("<html><body>" + getLabel() + "</body></html>");
+ SWTGraphicUtil.applyHTMLFormating(this.labelWidget);
+ return this.labelWidget;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#enableOrDisable()
+ */
+ @Override
+ public boolean enableOrDisable() {
+ if (this.enabler == null) {
+ return true;
+ }
+
+ final boolean enabled = this.enabler.isEnabled();
+ if (!this.labelWidget.isDisposed()) {
+ if (enabled) {
+ this.labelWidget.setForeground(this.labelWidget.getDisplay().getSystemColor(SWT.COLOR_BLACK));
+ } else {
+ this.labelWidget.setForeground(this.labelWidget.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
+ }
+ }
+ return enabled;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWPasswordText.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWPasswordText.java
new file mode 100644
index 000000000..843b2882b
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWPasswordText.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are text box to type password
+ */
+public class PWPasswordText extends PWText {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWPasswordText(final String label, final String propertyKey) {
+ super(label, propertyKey);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#addVerifyListeners()
+ */
+ @Override
+ public void addVerifyListeners() {
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), "");
+ } else {
+ if (!(value instanceof String)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a String because it is associated to a password text box");
+ }
+ }
+
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#convertValue()
+ */
+ @Override
+ public Object convertValue() {
+ return this.text.getText();
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#getStyle()
+ */
+ @Override
+ public int getStyle() {
+ return SWT.PASSWORD;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWRadio.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWRadio.java
new file mode 100644
index 000000000..3dfee00df
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWRadio.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are a group of radio buttons
+ *
+ */
+public class PWRadio extends PWWidget {
+
+ private final List<Object> data;
+ private final List<Button> buttons;
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWRadio(final String label, final String prop, final Object... values) {
+ super(null, prop, label == null ? 1 : 2, false);
+ this.data = new ArrayList<Object>(Arrays.asList(values));
+ this.buttons = new ArrayList<Button>();
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ buildLabel(parent, GridData.BEGINNING);
+
+ final Composite composite = new Composite(parent, SWT.NONE);
+ final GridLayout gridLayout = new GridLayout();
+ gridLayout.marginHeight = gridLayout.marginWidth = 0;
+ composite.setLayout(gridLayout);
+
+ for (final Object datum : this.data) {
+ final Button button = new Button(composite, SWT.RADIO);
+ addControl(button);
+ button.setText(datum.toString());
+ button.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false));
+ button.setSelection(datum.equals(PreferenceWindow.getInstance().getValueFor(getPropertyKey())));
+ button.setData(datum);
+ button.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ if (button.getSelection()) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), button.getData());
+ }
+ }
+ });
+
+ this.buttons.add(button);
+ }
+ return composite;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), null);
+ } else {
+ if (!this.data.isEmpty()) {
+ if (!value.getClass().equals(this.data.get(0).getClass())) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a " + this.data.get(0).getClass() + " because it is associated to a combo");
+ }
+ }
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWScale.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWScale.java
new file mode 100644
index 000000000..a6bb64837
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWScale.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Scale;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are scales
+ */
+public class PWScale extends PWWidget {
+
+ private final int max;
+ private final int min;
+ private final int increment;
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ * @param min minimum value
+ * @param max maximum value
+ * @param increment increment value
+ */
+ public PWScale(final String label, final String propertyKey, final int min, final int max, final int increment) {
+ super(label, propertyKey, label == null ? 1 : 2, false);
+ this.min = min;
+ this.max = max;
+ this.increment = increment;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ buildLabel(parent, GridData.CENTER);
+ final Scale scale = new Scale(parent, SWT.HORIZONTAL);
+ addControl(scale);
+ scale.setIncrement(this.increment);
+ scale.setMinimum(this.min);
+ scale.setMaximum(this.max);
+ final Integer originalValue = (Integer) PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ scale.setSelection(originalValue.intValue());
+
+ scale.addListener(SWT.Modify, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), new Integer(scale.getSelection()));
+ }
+ });
+
+ return scale;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), new Integer(this.min));
+ } else {
+ if (!(value instanceof Integer)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be an Integer because it is associated to a iscale");
+ }
+
+ final int valueAsInt = ((Integer) value).intValue();
+ if (valueAsInt < this.min || valueAsInt > this.max) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' is out of range (value is " + valueAsInt + ", range is " + this.min + "-" + this.max + ")");
+ }
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWSeparator.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWSeparator.java
new file mode 100644
index 000000000..b24032ae4
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWSeparator.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.mihalis.opal.titledSeparator.TitledSeparator;
+
+/**
+ * Instances of this class are separators
+ *
+ */
+public class PWSeparator extends PWWidget {
+
+ private final Image image;
+
+ /**
+ * Constructor
+ *
+ */
+ public PWSeparator() {
+ this(null, null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ */
+ public PWSeparator(final String label) {
+ this(label, null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param image associated image
+ */
+ public PWSeparator(final String label, final Image image) {
+ super(label, null, 1, true);
+ this.image = image;
+ setAlignment(GridData.FILL);
+ setGrabExcessSpace(true);
+ setHeight(20);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ final TitledSeparator sep = new TitledSeparator(parent, SWT.NONE);
+ addControl(sep);
+ sep.setText(getLabel());
+ sep.setImage(this.image);
+ return sep;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWSpinner.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWSpinner.java
new file mode 100644
index 000000000..9fe4875d3
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWSpinner.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Spinner;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are spinners
+ */
+public class PWSpinner extends PWWidget {
+ private final int max;
+ private final int min;
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ * @param min minimum value
+ * @param max maximum value
+ */
+ public PWSpinner(final String label, final String propertyKey, final int min, final int max) {
+ super(label, propertyKey, label == null ? 1 : 2, false);
+ this.min = min;
+ this.max = max;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ buildLabel(parent, GridData.CENTER);
+ final Spinner spinner = new Spinner(parent, SWT.HORIZONTAL | SWT.BORDER);
+ addControl(spinner);
+ spinner.setMinimum(this.min);
+ spinner.setMaximum(this.max);
+ final Integer originalValue = (Integer) PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ spinner.setSelection(originalValue.intValue());
+
+ spinner.addListener(SWT.Modify, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), new Integer(spinner.getSelection()));
+ }
+ });
+
+ return spinner;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), new Integer(this.min));
+ } else {
+ if (!(value instanceof Integer)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be an Integer because it is associated to a spinner");
+ }
+
+ final int valueAsInt = ((Integer) value).intValue();
+ if (valueAsInt < this.min || valueAsInt > this.max) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' is out of range (value is " + valueAsInt + ", range is " + this.min + "-" + this.max + ")");
+ }
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWStringText.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWStringText.java
new file mode 100644
index 000000000..bc2301aa2
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWStringText.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are text box to type Strings
+ */
+public class PWStringText extends PWText {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWStringText(final String label, final String propertyKey) {
+ super(label, propertyKey);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#addVerifyListeners()
+ */
+ @Override
+ public void addVerifyListeners() {
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), "");
+ } else {
+ if (!(value instanceof String)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a String because it is associated to a stringtext");
+ }
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#convertValue()
+ */
+ @Override
+ public Object convertValue() {
+ return this.text.getText();
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#getStyle()
+ */
+ @Override
+ public int getStyle() {
+ return SWT.NONE;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWText.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWText.java
new file mode 100644
index 000000000..3d37a8606
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWText.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * This is the abstract class for all text widgets (except textarea)
+ */
+public abstract class PWText extends PWWidget {
+
+ protected Text text;
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated property key
+ */
+ public PWText(final String label, final String propertyKey) {
+ super(label, propertyKey, label == null ? 1 : 2, false);
+ setGrabExcessSpace(true);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ buildLabel(parent, GridData.CENTER);
+ this.text = new Text(parent, SWT.BORDER | getStyle());
+ addControl(this.text);
+ addVerifyListeners();
+ this.text.setText(PreferenceWindow.getInstance().getValueFor(getPropertyKey()).toString());
+ this.text.addListener(SWT.Modify, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), convertValue());
+ }
+ });
+ return this.text;
+ }
+
+ /**
+ * Add the verify listeners
+ */
+ public abstract void addVerifyListeners();
+
+ /**
+ * @return the value of the data typed by the user in the correct format
+ */
+ public abstract Object convertValue();
+
+ /**
+ * @return the style (SWT.NONE or SWT.PASSWORD)
+ */
+ public abstract int getStyle();
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWTextarea.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWTextarea.java
new file mode 100644
index 000000000..0521707b7
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWTextarea.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+
+/**
+ * Instances of this class are text areas
+ *
+ */
+public class PWTextarea extends PWWidget {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWTextarea(final String label, final String propertyKey) {
+ super(label, propertyKey, label == null ? 1 : 2, false);
+ setGrabExcessSpace(true);
+ setHeight(50);
+ setWidth(350);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#build(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public Control build(final Composite parent) {
+ buildLabel(parent, GridData.BEGINNING);
+
+ final Text text = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ addControl(text);
+ text.setText(PreferenceWindow.getInstance().getValueFor(getPropertyKey()).toString());
+ text.addListener(SWT.FocusOut, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), text.getText());
+ }
+ });
+
+ return text;
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), "");
+ } else {
+ if (!(value instanceof String)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a String because it is associated to a textarea");
+ }
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWURLText.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWURLText.java
new file mode 100644
index 000000000..ebb145afe
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWURLText.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.opalDialog.Dialog;
+import org.mihalis.opal.preferenceWindow.PreferenceWindow;
+import org.mihalis.opal.utils.ResourceManager;
+
+/**
+ * Instances of this class are text box used to type URL
+ */
+public class PWURLText extends PWText {
+
+ /**
+ * Constructor
+ *
+ * @param label associated label
+ * @param propertyKey associated key
+ */
+ public PWURLText(final String label, final String propertyKey) {
+ super(label, propertyKey);
+ setWidth(200);
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#addVerifyListeners()
+ */
+ @Override
+ public void addVerifyListeners() {
+ this.text.addListener(SWT.FocusOut, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ try {
+ new URL(PWURLText.this.text.getText());
+ } catch (final MalformedURLException e) {
+ Dialog.error(ResourceManager.getLabel(ResourceManager.APPLICATION_ERROR), ResourceManager.getLabel(ResourceManager.VALID_URL));
+ event.doit = false;
+ PWURLText.this.text.forceFocus();
+ }
+
+ }
+ });
+
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWWidget#check()
+ */
+ @Override
+ public void check() {
+ final Object value = PreferenceWindow.getInstance().getValueFor(getPropertyKey());
+ if (value == null) {
+ PreferenceWindow.getInstance().setValue(getPropertyKey(), "");
+ } else {
+ if (!(value instanceof String)) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has to be a String because it is associated to a URL text box");
+ }
+
+ try {
+ new URL((String) value);
+ } catch (final MalformedURLException e) {
+ throw new UnsupportedOperationException("The property '" + getPropertyKey() + "' has a value (" + value + ") that is not an URL");
+ }
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#convertValue()
+ */
+ @Override
+ public Object convertValue() {
+ return this.text.getText();
+ }
+
+ /**
+ * @see org.mihalis.opal.preferenceWindow.widgets.PWText#getStyle()
+ */
+ @Override
+ public int getStyle() {
+ return SWT.NONE;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWWidget.java b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWWidget.java
new file mode 100644
index 000000000..424cf0223
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/preferenceWindow/widgets/PWWidget.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.preferenceWindow.widgets;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.mihalis.opal.preferenceWindow.enabler.Enabler;
+
+/**
+ * This class is the root class for all widgets that take part of a preference
+ * window
+ *
+ */
+public abstract class PWWidget {
+ private final String propertyKey;
+ private final String label;
+ protected Enabler enabler;
+ private final List<Control> controls;
+
+ private int alignment = GridData.BEGINNING;
+ private int indent = 0;
+ private int width = 100;
+ private int height = -1;
+ protected int numberOfColumns = 1;
+ private boolean grabExcessSpace = false;
+
+ private boolean singleWidget = false;
+
+ /**
+ * Constructor
+ *
+ * @param label label associated to the widget
+ * @param propertyKey property key binded to the widget
+ * @param numberOfColumns number of columns taken by the widget
+ * @param singleWidget if true, the widget is supposed to be "alone" (used
+ * for placement)
+ */
+ protected PWWidget(final String label, final String propertyKey, final int numberOfColumns, final boolean singleWidget) {
+ this.label = label;
+ this.propertyKey = propertyKey;
+ this.numberOfColumns = numberOfColumns;
+ this.singleWidget = singleWidget;
+ this.controls = new ArrayList<Control>();
+ }
+
+ /**
+ * Build the widget
+ *
+ * @param parent parent composite
+ * @return the created control
+ */
+ protected abstract Control build(Composite parent);
+
+ /**
+ * Build the label associated to the widget
+ *
+ * @param parent parent composite
+ * @param verticalAlignment vertical alignment
+ */
+ protected void buildLabel(final Composite parent, final int verticalAlignment) {
+ if (getLabel() != null) {
+ final Label label = new Label(parent, SWT.NONE);
+ label.setText(getLabel());
+ final GridData labelGridData = new GridData(GridData.END, verticalAlignment, false, false);
+ labelGridData.horizontalIndent = getIndent();
+ label.setLayoutData(labelGridData);
+ addControl(label);
+ }
+ }
+
+ /**
+ * Check if the property can be binded to the widget
+ *
+ * @throws UnsupportedOperationException if the property could not be binded
+ * to the widget
+ */
+ protected abstract void check();
+
+ /**
+ * Check if the property can be binded to the widget, then build the widget
+ *
+ * @param parent parent composite
+ * @return the created control
+ */
+ public Control checkAndBuild(final Composite parent) {
+ check();
+ return build(parent);
+ }
+
+ /**
+ * Enable or disable the widget, depending on the associated enabler
+ */
+ public boolean enableOrDisable() {
+ if (this.enabler == null) {
+ return true;
+ }
+
+ final boolean enabled = this.enabler.isEnabled();
+ for (final Control c : this.controls) {
+ if (!c.isDisposed()) {
+ c.setEnabled(enabled);
+ }
+ }
+ return enabled;
+ }
+
+ // ------------------------------- getters & setters
+
+ /**
+ * @return the alignment (GridData.BEGINNING, GridData.CENTER, GridData.END,
+ * GridData.FILL)
+ */
+ public int getAlignment() {
+ return this.alignment;
+ }
+
+ /**
+ * @return the list of controls contained in the widget
+ */
+ public List<Control> getControls() {
+ return this.controls;
+ }
+
+ /**
+ * @return <code>true</code> if the widget should grab the excess space
+ */
+ public boolean isGrabExcessSpace() {
+ return this.grabExcessSpace;
+ }
+
+ /**
+ * @return the height of the widget
+ */
+ public int getHeight() {
+ return this.height;
+ }
+
+ /**
+ * @return the indentation space of the widget
+ */
+ public int getIndent() {
+ return this.indent;
+ }
+
+ /**
+ * @return the label associated to the widget (may be <code>null</code>)
+ */
+ public String getLabel() {
+ return this.label;
+ }
+
+ /**
+ * @return the number of columns associated to the widget
+ */
+ public int getNumberOfColumns() {
+ return this.numberOfColumns;
+ }
+
+ /**
+ * @return the propertyKey associated to the widget
+ */
+ String getPropertyKey() {
+ return this.propertyKey;
+ }
+
+ /**
+ * @return the width of the widget
+ */
+ public int getWidth() {
+ return this.width;
+ }
+
+ /**
+ * @return <code>true</code> if the widget is "alone"
+ */
+ public boolean isSingleWidget() {
+ return this.singleWidget;
+ }
+
+ /**
+ * Adds a control to the list of control contained in the widget
+ *
+ * @param control control to add
+ */
+ protected void addControl(final Control control) {
+ this.controls.add(control);
+ }
+
+ /**
+ * @param alignment the alignment to set (GridData.BEGINNING,
+ * GridData.CENTER, GridData.END, GridData.FILL)
+ * @return the widget
+ */
+ public PWWidget setAlignment(final int alignment) {
+ if (alignment != GridData.BEGINNING && alignment != GridData.CENTER && alignment != GridData.END && alignment != GridData.FILL) {
+ throw new UnsupportedOperationException("Value should be one of the following :GridData.BEGINNING, GridData.CENTER, GridData.END, GridData.FILL");
+ }
+ this.alignment = alignment;
+ return this;
+ }
+
+ /**
+ * @param enabler the enabler to set
+ * @return the widget
+ */
+ public PWWidget setEnabler(final Enabler enabler) {
+ this.enabler = enabler;
+ this.enabler.injectWidget(this);
+ return this;
+ }
+
+ /**
+ * @param grabExcessSpace true if you want the widget to grab the excess
+ * space
+ * @return the widget
+ */
+ public PWWidget setGrabExcessSpace(final boolean grabExcessSpace) {
+ this.grabExcessSpace = grabExcessSpace;
+ return this;
+ }
+
+ /**
+ * @param height the height to set
+ * @return the widget
+ */
+ public PWWidget setHeight(final int height) {
+ this.height = height;
+ return this;
+
+ }
+
+ /**
+ * @param indent the indentation space to set
+ * @return the widget
+ */
+ public PWWidget setIndent(final int indent) {
+ this.indent = indent;
+ return this;
+ }
+
+ /**
+ * @param width the width to set
+ * @return the widget
+ */
+ public PWWidget setWidth(final int width) {
+ this.width = width;
+ return this;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/BaseFocusControlListener.java b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/BaseFocusControlListener.java
new file mode 100644
index 000000000..35c65bed0
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/BaseFocusControlListener.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Peter Weishapl - Inspiration
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.promptSupport;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.promptSupport.PromptSupport.FocusBehavior;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Abstract class that contains code for the FocusLost, FocusGained and
+ * ControlResized events
+ *
+ */
+abstract class BaseFocusControlListener implements FocusListener, ControlListener {
+
+ protected Control control;
+ private boolean firstDraw;
+ private Font initialFont;
+ private Color initialBackgroundColor;
+ private Color initialForegroundColor;
+
+ /**
+ * Constructor
+ *
+ * @param control control on which this listener will be attached
+ */
+ BaseFocusControlListener(final Control control) {
+ this.control = control;
+ this.firstDraw = true;
+ }
+
+ /**
+ * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
+ */
+ @Override
+ public void focusGained(final FocusEvent e) {
+ if (isFilled()) {
+ // Widget not empty
+ return;
+ }
+
+ applyInitialLook();
+ if (PromptSupport.getFocusBehavior(this.control) == FocusBehavior.HIDE_PROMPT) {
+ hidePrompt();
+ } else {
+ highLightPrompt();
+ }
+ }
+
+ /**
+ * Apply the initial look of the widget
+ */
+ private void applyInitialLook() {
+ this.control.setFont(this.initialFont);
+ this.control.setBackground(this.initialBackgroundColor);
+ this.control.setForeground(this.initialForegroundColor);
+ }
+
+ /**
+ * Code when the focus behiaviour is "Hide"
+ */
+ protected abstract void hidePrompt();
+
+ /**
+ * Code when the focus behiaviour is "Highlight"
+ */
+ protected abstract void highLightPrompt();
+
+ /**
+ * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
+ */
+ @Override
+ public void focusLost(final FocusEvent e) {
+ if (isFilled()) {
+ return;
+ }
+
+ storeInitialLook();
+ applyForegroundColor();
+ applyBackgroundColor();
+ applyFontStyle();
+ fillPromptText();
+ }
+
+ /**
+ * @return <code>true</code> if the widget is filled, <code>false</code>
+ * otherwise
+ */
+ protected abstract boolean isFilled();
+
+ /**
+ * Apply the foreground color for the prompt
+ */
+ private void applyForegroundColor() {
+ this.control.setForeground(PromptSupport.getForeground(this.control));
+ }
+
+ /**
+ * Apply the background color for the prompt
+ */
+ private void applyBackgroundColor() {
+ this.control.setBackground(PromptSupport.getBackground(this.control));
+ }
+
+ /**
+ * Apply the font style to the prompt
+ */
+ private void applyFontStyle() {
+ final Font font = SWTGraphicUtil.buildFontFrom(this.control, PromptSupport.getFontStyle(this.control));
+ this.control.setFont(font);
+ this.control.addListener(SWT.Dispose, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ SWTGraphicUtil.dispose(font);
+ }
+ });
+ }
+
+ /**
+ * Fill the prompt text
+ */
+ protected abstract void fillPromptText();
+
+ /**
+ * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent)
+ */
+ @Override
+ public void controlMoved(final ControlEvent e) {
+ }
+
+ /**
+ * @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent)
+ */
+ @Override
+ public void controlResized(final ControlEvent e) {
+ if (this.firstDraw) {
+ storeInitialLook();
+ this.firstDraw = true;
+ focusLost(null);
+ }
+ }
+
+ /**
+ * Store the initial look of the widget
+ */
+ private void storeInitialLook() {
+ this.initialFont = this.control.getFont();
+ this.initialBackgroundColor = this.control.getBackground();
+ this.initialForegroundColor = this.control.getForeground();
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/CComboFocusControlListener.java b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/CComboFocusControlListener.java
new file mode 100644
index 000000000..5a2da0708
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/CComboFocusControlListener.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Peter Weishapl - Inspiration
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.promptSupport;
+
+import org.eclipse.swt.custom.CCombo;
+
+/**
+ * Focus/Control listener for a CCombo widget
+ */
+class CComboFocusControlListener extends BaseFocusControlListener {
+
+ /**
+ * Constructor
+ *
+ * @param control control on which this listener will be attached
+ */
+ public CComboFocusControlListener(final CCombo control) {
+ super(control);
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#hidePrompt()
+ */
+ @Override
+ protected void hidePrompt() {
+ ((CCombo) this.control).setText("");
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#highLightPrompt()
+ */
+ @Override
+ protected void highLightPrompt() {
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#fillPromptText()
+ */
+ @Override
+ protected void fillPromptText() {
+ final String promptText = PromptSupport.getPrompt(this.control);
+ if (promptText != null) {
+ ((CCombo) this.control).setText(promptText);
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#isFilled()
+ */
+ @Override
+ protected boolean isFilled() {
+ final String promptText = PromptSupport.getPrompt(this.control);
+ if (promptText != null && promptText.equals(((CCombo) this.control).getText().trim())) {
+ return false;
+ }
+ return !"".equals(((CCombo) this.control).getText().trim());
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/ComboFocusControlListener.java b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/ComboFocusControlListener.java
new file mode 100644
index 000000000..8e330f928
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/ComboFocusControlListener.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Peter Weishapl - Inspiration
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.promptSupport;
+
+import org.eclipse.swt.widgets.Combo;
+
+/**
+ * Focus/Control listener for a Combo widget
+ */
+class ComboFocusControlListener extends BaseFocusControlListener {
+
+ /**
+ * Constructor
+ *
+ * @param control control on which this listener will be attached
+ */
+ public ComboFocusControlListener(final Combo control) {
+ super(control);
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#hidePrompt()
+ */
+ @Override
+ protected void hidePrompt() {
+ ((Combo) this.control).setText("");
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#highLightPrompt()
+ */
+ @Override
+ protected void highLightPrompt() {
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#fillPromptText()
+ */
+ @Override
+ protected void fillPromptText() {
+ final String promptText = PromptSupport.getPrompt(this.control);
+ if (promptText != null) {
+ this.control.getDisplay().asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ ((Combo) ComboFocusControlListener.this.control).setText(promptText);
+ }
+ });
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#isFilled()
+ */
+ @Override
+ protected boolean isFilled() {
+ final String promptText = PromptSupport.getPrompt(this.control);
+ if (promptText != null && promptText.equals(((Combo) this.control).getText().trim())) {
+ return false;
+ }
+ return !"".equals(((Combo) this.control).getText().trim());
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/FocusControlListenerFactory.java b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/FocusControlListenerFactory.java
new file mode 100644
index 000000000..82671dbe4
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/FocusControlListenerFactory.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Peter Weishapl - Inspiration
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.promptSupport;
+
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * This is a factory of focus/control listeners
+ *
+ */
+class FocusControlListenerFactory {
+
+ /**
+ * @param control control on which the listener will be added
+ * @return a BaseControlFocus Listener that can be attached to the events
+ * focusLost, focusGained and controlResized
+ */
+ static BaseFocusControlListener getFocusControlListenerFor(final Control control) {
+ if (control instanceof Combo) {
+ return new ComboFocusControlListener((Combo) control);
+ }
+ if (control instanceof CCombo) {
+ return new CComboFocusControlListener((CCombo) control);
+ }
+
+ if (control instanceof Text) {
+ return new TextFocusControlListener((Text) control);
+ }
+
+ if (control instanceof StyledText) {
+ return new StyledTextFocusControlListener((StyledText) control);
+ }
+ throw new IllegalArgumentException("Control should be a Text, a Combo, a CCombo or a StyledText widget");
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/PromptSupport.java b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/PromptSupport.java
new file mode 100644
index 000000000..d04ade68d
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/PromptSupport.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Peter Weishapl - Inspiration
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.promptSupport;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * This utility class allows the user to add a prompt to a text or combo
+ * component (see http://designinginterfaces.com/Input_Prompt)
+ *
+ */
+public class PromptSupport {
+ public static enum FocusBehavior {
+ /**
+ * Highlight the prompt text as it would be selected.
+ */
+ HIGHLIGHT_PROMPT,
+ /**
+ * Hide the prompt text.
+ */
+ HIDE_PROMPT
+ };
+
+ private static final String KEY = "org.mihalis.opal.promptSupport.PromptSupport";
+ static final String BACKGROUND = KEY + ".background";
+ static final String FOREGROUND = KEY + ".foreground";
+ static final String STYLE = KEY + ".style";
+ static final String BEHAVIOR = KEY + ".behavior";
+ static final String PROMPT = KEY + ".prompt";
+ static final String SET = KEY + ".set";
+
+ /**
+ * <p>
+ * Convenience method to set the <code>promptText</code> and
+ * <code>promptTextColor</code> on a {@link Control}.
+ * </p>
+ *
+ * @param promptText Prompt Text
+ * @param promptForeground Foreground
+ * @param promptBackground Background
+ * @param control control
+ * @exception IllegalArgumentException if the control is not a Text Box, a
+ * Combo Box, a StyledText or a CCombo
+ */
+ public static void init(final String promptText, final Color promptForeground, final Color promptBackground, final Control control) {
+ if (promptText != null && promptText.length() > 0) {
+ setPrompt(promptText, control);
+ }
+ if (promptForeground != null) {
+ setForeground(promptForeground, control);
+ }
+ if (promptBackground != null) {
+ setBackground(promptBackground, control);
+ }
+ }
+
+ /**
+ * Get the background color of the <code>control</code>, when no text is
+ * present. If no color has been set, the <code>control</code> background
+ * color will be returned.
+ *
+ * @param textComponent
+ * @return the the background color of the text component, when no text is
+ * present
+ */
+ public static Color getBackground(final Control control) {
+ final Color temp = (Color) control.getData(BACKGROUND);
+ return temp == null ? control.getBackground() : temp;
+ }
+
+ /**
+ * <p>
+ * Sets the prompts background color on <code>control</code>. This
+ * background color will only be used when no text is present.
+ * </p>
+ *
+ * @param background
+ * @param control
+ * @exception IllegalArgumentException if the control is not a Text Box, a
+ * Combo Box, a StyledText or a CCombo
+ */
+ public static void setBackground(final Color color, final Control control) {
+ checkControl(control);
+ control.setData(BACKGROUND, color);
+ }
+
+ /**
+ * Get the {@link FocusBehavior} of <code>control</code>.
+ *
+ * @param control
+ * @return the {@link FocusBehavior} or {@link FocusBehavior#HIDE_PROMPT} if
+ * none is set
+ */
+ public static FocusBehavior getFocusBehavior(final Control control) {
+ final FocusBehavior temp = (FocusBehavior) control.getData(BEHAVIOR);
+ return temp == null ? FocusBehavior.HIDE_PROMPT : temp;
+
+ }
+
+ /**
+ * Sets the {@link FocusBehavior} on <code>control</code>, if it is the
+ * focus owner.
+ *
+ * @param focusBehavior
+ * @param control
+ * @exception IllegalArgumentException if the control is not a Text Box, a
+ * Combo Box, a StyledText or a CCombo
+ */
+ public static void setFocusBehavior(final FocusBehavior focusBehavior, final Control control) {
+ checkControl(control);
+ control.setData(BEHAVIOR, focusBehavior);
+ }
+
+ /**
+ * Returns the font style of the prompt text, which is a OR mix of
+ * SWT.ITALIC, SWT.NONE or SWT.BOLD
+ *
+ * @param control
+ * @return font style of the prompt text
+ */
+ public static int getFontStyle(final Control control) {
+ final Integer temp = (Integer) control.getData(STYLE);
+ return temp == null ? SWT.ITALIC : temp;
+
+ }
+
+ /**
+ * <p>
+ * Set the style of the prompt font, which is a OR mix of SWT.ITALIC,
+ * SWT.NONE or SWT.BOLD
+ * </p>
+ *
+ * @param fontStyle
+ * @param control
+ * @exception IllegalArgumentException if the control is not a Text Box, a
+ * Combo Box, a StyledText or a CCombo
+ */
+ public static void setFontStyle(final int fontStyle, final Control control) {
+ checkControl(control);
+ control.setData(STYLE, fontStyle);
+ }
+
+ /**
+ * Get the foreground color of the prompt text. If no color has been set,
+ * the <code>GREY</code> color will be returned.
+ *
+ * @param color
+ * @return the color of the prompt text or <code>GREY</code>if none is set
+ */
+ public static Color getForeground(final Control control) {
+ final Color temp = (Color) control.getData(FOREGROUND);
+ return temp == null ? control.getForeground() : temp;
+
+ }
+
+ /**
+ * Sets the foreground color of the prompt on <code>control</code>. This
+ * color will be used when no text is present.
+ *
+ * @param promptTextColor
+ * @param textComponent
+ * @exception IllegalArgumentException if the control is not a Text Box, a
+ * Combo Box, a StyledText or a CCombo
+ */
+ public static void setForeground(final Color color, final Control control) {
+ checkControl(control);
+ control.setData(FOREGROUND, color);
+ }
+
+ /**
+ * Get the prompt text of <code>control</code>.
+ *
+ * @param control
+ * @return the prompt text
+ */
+ public static String getPrompt(final Control control) {
+ return (String) control.getData(PROMPT);
+ }
+
+ /**
+ * <p>
+ * Sets the prompt text on <code>control</code>
+ * </p>
+ *
+ * @param promptText
+ * @param textComponent
+ * @exception IllegalArgumentException if the control is not a Text Box, a
+ * Combo Box, a StyledText or a CCombo
+ */
+ public static void setPrompt(final String promptText, final Control control) {
+ checkControl(control);
+
+ final boolean alreadySet = control.getData(SET) == null ? false : (Boolean) control.getData(SET);
+ if (alreadySet) {
+ throw new IllegalArgumentException("A prompt has already been set on this control !");
+ }
+ control.setData(PROMPT, promptText);
+
+ final BaseFocusControlListener bfl = FocusControlListenerFactory.getFocusControlListenerFor(control);
+ control.addFocusListener(bfl);
+ control.addControlListener(bfl);
+ control.setData(SET, true);
+ }
+
+ /**
+ * Check if the control is a Text, a Combo, a StyledText or a CCombo
+ *
+ * @param control control to check
+ */
+ private static void checkControl(final Control control) {
+ if (!(control instanceof Text) && !(control instanceof Combo) && !(control instanceof StyledText) && !(control instanceof CCombo)) {
+ throw new IllegalArgumentException("PromptSupport can only be used on a Text, a Combo, a StyledText or a CCombo widget.");
+ }
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/StyledTextFocusControlListener.java b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/StyledTextFocusControlListener.java
new file mode 100644
index 000000000..2be5bcaf4
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/StyledTextFocusControlListener.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Peter Weishapl - Inspiration
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.promptSupport;
+
+import org.eclipse.swt.custom.StyledText;
+
+/**
+ * Focus/Control listener for a StyledText widget
+ */
+class StyledTextFocusControlListener extends BaseFocusControlListener {
+
+ /**
+ * Constructor
+ *
+ * @param control control on which this listener will be attached
+ */
+ public StyledTextFocusControlListener(final StyledText control) {
+ super(control);
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#hidePrompt()
+ */
+ @Override
+ protected void hidePrompt() {
+ ((StyledText) this.control).setText("");
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#highLightPrompt()
+ */
+ @Override
+ protected void highLightPrompt() {
+ this.control.getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ ((StyledText) StyledTextFocusControlListener.this.control).selectAll();
+
+ }
+ });
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#fillPromptText()
+ */
+ @Override
+ protected void fillPromptText() {
+ final String promptText = PromptSupport.getPrompt(this.control);
+ if (promptText != null) {
+ ((StyledText) this.control).setText(promptText);
+ }
+
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#isFilled()
+ */
+ @Override
+ protected boolean isFilled() {
+ final String promptText = PromptSupport.getPrompt(this.control);
+ if (promptText != null && promptText.equals(((StyledText) this.control).getText().trim())) {
+ return false;
+ }
+ return !"".equals(((StyledText) this.control).getText().trim());
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/TextFocusControlListener.java b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/TextFocusControlListener.java
new file mode 100644
index 000000000..f90a975f5
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/promptSupport/TextFocusControlListener.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Peter Weishapl - Inspiration
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.promptSupport;
+
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Focus/Control listener for a Text widget
+ */
+class TextFocusControlListener extends BaseFocusControlListener {
+
+ /**
+ * Constructor
+ *
+ * @param control control on which this listener will be attached
+ */
+ public TextFocusControlListener(final Text control) {
+ super(control);
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#hidePrompt()
+ */
+ @Override
+ protected void hidePrompt() {
+ ((Text) this.control).setText("");
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#highLightPrompt()
+ */
+ @Override
+ protected void highLightPrompt() {
+ // If we do a select all directly, it's not working !
+ this.control.getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ ((Text) TextFocusControlListener.this.control).selectAll();
+ }
+ });
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#fillPromptText()
+ */
+ @Override
+ protected void fillPromptText() {
+ final String promptText = PromptSupport.getPrompt(this.control);
+ if (promptText != null) {
+ ((Text) this.control).setText(promptText);
+ }
+ }
+
+ /**
+ * @see org.mihalis.opal.promptSupport.BaseFocusControlListener#isFilled()
+ */
+ @Override
+ protected boolean isFilled() {
+ final String promptText = PromptSupport.getPrompt(this.control);
+ if (promptText != null && promptText.equals(((Text) this.control).getText().trim())) {
+ return false;
+ }
+ return !"".equals(((Text) this.control).getText().trim());
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/rangeSlider/RangeSlider.java b/org.tizen.common.externals/src/org/mihalis/opal/rangeSlider/RangeSlider.java
new file mode 100755
index 000000000..620042e0a
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/rangeSlider/RangeSlider.java
@@ -0,0 +1,1060 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.rangeSlider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class provide a separator with a title and/or an image.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER</dd>
+ * <dd>HORIZONTAL</dd>
+ * <dd>VERTICAL</dd> *
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * </p>
+ */
+public class RangeSlider extends Canvas {
+
+ private enum SELECTED_KNOB {
+ NONE, UPPER, LOWER
+ };
+
+ private int minimum;
+ private int maximum;
+ private int lowerValue;
+ private int upperValue;
+ private final List<SelectionListener> listeners;
+ private final Image slider, sliderHover, sliderDrag, sliderSelected;
+ private final Image vSlider, vSliderHover, vSliderDrag, vSliderSelected;
+ private int orientation;
+ private int increment;
+ private int pageIncrement;
+ private SELECTED_KNOB lastSelected;
+ private boolean dragInProgress;
+ private Point coordUpper;
+ private boolean upperHover;
+ private Point coordLower;
+ private boolean lowerHover;
+ private int previousUpperValue;
+ private int previousLowerValue;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ */
+ public RangeSlider(final Composite parent, final int style) {
+ super(parent, SWT.DOUBLE_BUFFERED | ((style & SWT.BORDER) == SWT.BORDER ? SWT.BORDER : SWT.NONE));
+ this.minimum = this.lowerValue = 0;
+ this.maximum = this.upperValue = 100;
+ this.listeners = new ArrayList<SelectionListener>();
+ this.increment = 1;
+ this.pageIncrement = 10;
+ this.lastSelected = SELECTED_KNOB.NONE;
+ this.slider = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/slider-normal.png"));
+ this.sliderHover = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/slider-hover.png"));
+ this.sliderDrag = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/slider-drag.png"));
+ this.sliderSelected = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/slider-selected.png"));
+
+ this.vSlider = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/h-slider-normal.png"));
+ this.vSliderHover = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/h-slider-hover.png"));
+ this.vSliderDrag = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/h-slider-drag.png"));
+ this.vSliderSelected = new Image(getDisplay(), this.getClass().getClassLoader().getResourceAsStream("images/h-slider-selected.png"));
+
+ if ((style & SWT.VERTICAL) == SWT.VERTICAL) {
+ this.orientation = SWT.VERTICAL;
+ } else {
+ this.orientation = SWT.HORIZONTAL;
+ }
+
+ addListener(SWT.Dispose, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ SWTGraphicUtil.dispose(RangeSlider.this.slider);
+ SWTGraphicUtil.dispose(RangeSlider.this.sliderHover);
+ SWTGraphicUtil.dispose(RangeSlider.this.sliderDrag);
+ SWTGraphicUtil.dispose(RangeSlider.this.sliderSelected);
+
+ SWTGraphicUtil.dispose(RangeSlider.this.vSlider);
+ SWTGraphicUtil.dispose(RangeSlider.this.vSliderHover);
+ SWTGraphicUtil.dispose(RangeSlider.this.vSliderDrag);
+ SWTGraphicUtil.dispose(RangeSlider.this.vSliderSelected);
+ }
+ });
+
+ addMouseListeners();
+ addListener(SWT.KeyDown, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ handleKeyDown(event);
+ }
+ });
+ addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(final PaintEvent e) {
+ drawWidget(e);
+
+ }
+ });
+
+ }
+
+ /**
+ * Add the mouse listeners (mouse up, mouse down, mouse move, mouse wheel)
+ */
+ private void addMouseListeners() {
+ addListener(SWT.MouseDown, new Listener() {
+ @Override
+ public void handleEvent(final Event e) {
+ handleMouseDown(e);
+ }
+ });
+
+ addListener(SWT.MouseUp, new Listener() {
+ @Override
+ public void handleEvent(final Event e) {
+ handleMouseUp(e);
+ }
+ });
+
+ addListener(SWT.MouseMove, new Listener() {
+ @Override
+ public void handleEvent(final Event e) {
+ handleMouseMove(e);
+ }
+ });
+
+ addListener(SWT.MouseWheel, new Listener() {
+ @Override
+ public void handleEvent(final Event e) {
+ handleMouseWheel(e);
+ }
+ });
+
+ }
+
+ /**
+ * Code executed when the mouse is down
+ *
+ * @param e event
+ */
+ private void handleMouseDown(final Event e) {
+
+ if (this.upperHover) {
+ this.dragInProgress = true;
+ this.lastSelected = SELECTED_KNOB.UPPER;
+ this.previousUpperValue = this.upperValue;
+ return;
+ }
+
+ if (this.lowerHover) {
+ this.dragInProgress = true;
+ this.lastSelected = SELECTED_KNOB.LOWER;
+ this.previousLowerValue = this.lowerValue;
+ return;
+ }
+
+ this.dragInProgress = false;
+ this.lastSelected = SELECTED_KNOB.NONE;
+ }
+
+ /**
+ * Code executed when the mouse is up
+ *
+ * @param e event
+ */
+ private void handleMouseUp(final Event e) {
+ if (!this.dragInProgress) {
+ return;
+ }
+ this.dragInProgress = false;
+ if (!fireSelectionListeners(e)) {
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ this.upperValue = this.previousUpperValue;
+ } else {
+ this.lowerValue = this.previousLowerValue;
+ }
+ redraw();
+ }
+ }
+
+ /**
+ * Fire all selection listeners
+ *
+ * @param event selection event
+ * @return <code>true</code> if no listener cancels the selection,
+ * <code>false</code> otherwise
+ */
+ private boolean fireSelectionListeners(final Event event) {
+ for (final SelectionListener selectionListener : this.listeners) {
+ final SelectionEvent selectionEvent = new SelectionEvent(event);
+ selectionListener.widgetSelected(selectionEvent);
+ if (!selectionEvent.doit) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Code executed when the mouse pointer is moving
+ *
+ * @param e event
+ */
+ private void handleMouseMove(final Event e) {
+ final int x = e.x, y = e.y;
+ final Image img = this.orientation == SWT.HORIZONTAL ? this.slider : this.vSlider;
+ this.upperHover = x >= this.coordUpper.x && x <= this.coordUpper.x + img.getBounds().width && y >= this.coordUpper.y && y <= this.coordUpper.y + img.getBounds().height;
+ this.lowerHover = x >= this.coordLower.x && x <= this.coordLower.x + img.getBounds().width && y >= this.coordLower.y && y <= this.coordLower.y + img.getBounds().height;
+
+ if (this.dragInProgress) {
+ if (this.orientation == SWT.HORIZONTAL) {
+ final int mouseValue = (int) ((x - 9f) / computePixelSizeForHorizonalSlider()) + this.minimum;
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ this.upperValue = (int) (Math.ceil(mouseValue / this.increment) * this.increment) - this.increment;
+ checkUpperValue();
+ } else {
+ this.lowerValue = (int) (Math.ceil(mouseValue / this.increment) * this.increment) - this.increment;
+ checkLowerValue();
+ }
+
+ } else {
+ final int mouseValue = (int) ((y - 9f) / computePixelSizeForVerticalSlider()) + this.minimum;
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ this.upperValue = (int) (Math.ceil(mouseValue / this.increment) * this.increment) - this.increment;
+ checkUpperValue();
+ } else {
+ this.lowerValue = (int) (Math.ceil(mouseValue / this.increment) * this.increment) - this.increment;
+ checkLowerValue();
+ }
+
+ }
+ }
+
+ redraw();
+ }
+
+ /**
+ * Code executed when the mouse wheel is activated
+ *
+ * @param e event
+ */
+ private void handleMouseWheel(final Event e) {
+ if (this.lastSelected == SELECTED_KNOB.NONE) {
+ return;
+ }
+
+ if (this.lastSelected == SELECTED_KNOB.LOWER) {
+ this.lowerValue += e.count * this.increment;
+ checkLowerValue();
+ redraw();
+ } else {
+ this.upperValue += e.count * this.increment;
+ checkUpperValue();
+ redraw();
+ }
+ }
+
+ /**
+ * Check if the lower value is in ranges
+ */
+ private void checkLowerValue() {
+ if (this.lowerValue < this.minimum) {
+ this.lowerValue = this.minimum;
+ }
+ if (this.lowerValue > this.maximum) {
+ this.lowerValue = this.maximum;
+ }
+ if (this.lowerValue > this.upperValue) {
+ this.lowerValue = this.upperValue;
+ }
+ }
+
+ /**
+ * Check if the upper value is in ranges
+ */
+ private void checkUpperValue() {
+ if (this.upperValue < this.minimum) {
+ this.upperValue = this.minimum;
+ }
+ if (this.upperValue > this.maximum) {
+ this.upperValue = this.maximum;
+ }
+ if (this.upperValue < this.lowerValue) {
+ this.upperValue = this.lowerValue;
+ }
+ }
+
+ /**
+ * Draws the widget
+ *
+ * @param e paint event
+ */
+ private void drawWidget(final PaintEvent e) {
+ final Rectangle rect = this.getClientArea();
+ if (rect.width == 0 || rect.height == 0) {
+ return;
+ }
+ e.gc.setAdvanced(true);
+ e.gc.setAntialias(SWT.ON);
+ if (this.orientation == SWT.HORIZONTAL) {
+ drawHorizontalRangeSlider(e.gc);
+ } else {
+ drawVerticalRangeSlider(e.gc);
+ }
+
+ }
+
+ /**
+ * Draw the range slider (horizontal)
+ *
+ * @param gc graphic context
+ */
+ private void drawHorizontalRangeSlider(final GC gc) {
+ drawBackgroundHorizontal(gc);
+ drawBarsHorizontal(gc);
+ this.coordUpper = drawHorizontalKnob(gc, this.upperValue, true);
+ this.coordLower = drawHorizontalKnob(gc, this.lowerValue, false);
+ }
+
+ /**
+ * Draw the background
+ *
+ * @param gc graphic context
+ */
+ private void drawBackgroundHorizontal(final GC gc) {
+ final Rectangle clientArea = this.getClientArea();
+
+ gc.setBackground(getBackground());
+ gc.fillRectangle(clientArea);
+
+ if (isEnabled()) {
+ gc.setForeground(getForeground());
+ } else {
+ gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
+ }
+ gc.drawRoundRectangle(9, 9, clientArea.width - 20, clientArea.height - 20, 3, 3);
+
+ final float pixelSize = computePixelSizeForHorizonalSlider();
+ final int startX = (int) (pixelSize * this.lowerValue);
+ final int endX = (int) (pixelSize * this.upperValue);
+ if (isEnabled()) {
+ gc.setBackground(getForeground());
+ } else {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
+ }
+ gc.fillRectangle(12 + startX, 9, endX - startX - 6, clientArea.height - 20);
+
+ }
+
+ /**
+ * @return how many pixels corresponds to 1 point of value
+ */
+ private float computePixelSizeForHorizonalSlider() {
+ return (getClientArea().width - 20f) / (this.maximum - this.minimum);
+ }
+
+ /**
+ * Draw the bars
+ *
+ * @param gc graphic context
+ */
+ private void drawBarsHorizontal(final GC gc) {
+ final Rectangle clientArea = this.getClientArea();
+ if (isEnabled()) {
+ gc.setForeground(getForeground());
+ } else {
+ gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
+ }
+
+ final float pixelSize = computePixelSizeForHorizonalSlider();
+ for (int i = 1; i < 10; i++) {
+ final int x = (int) (9 + pixelSize * (this.maximum - this.minimum) / 10 * i);
+ gc.drawLine(x, 4, x, 7);
+ gc.drawLine(x, clientArea.height - 6, x, clientArea.height - 9);
+ }
+
+ }
+
+ /**
+ * Draws an horizontal knob
+ *
+ * @param gc graphic context
+ * @param value corresponding value
+ * @param upper if <code>true</code>, draws the upper knob. If
+ * <code>false</code>, draws the lower knob
+ * @return the coordinate of the upper left corner of the knob
+ */
+ private Point drawHorizontalKnob(final GC gc, final int value, final boolean upper) {
+ final float pixelSize = computePixelSizeForHorizonalSlider();
+ final int x = (int) (pixelSize * value);
+ Image image;
+ if (upper) {
+ if (this.upperHover) {
+ image = this.dragInProgress ? this.sliderDrag : this.sliderHover;
+ } else if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ image = this.sliderSelected;
+ } else {
+ image = this.slider;
+ }
+ } else {
+ if (this.lowerHover) {
+ image = this.dragInProgress ? this.sliderDrag : this.sliderHover;
+ } else if (this.lastSelected == SELECTED_KNOB.LOWER) {
+ image = this.sliderSelected;
+ } else {
+ image = this.slider;
+ }
+ }
+ if (isEnabled()) {
+ gc.drawImage(image, x + 5, getClientArea().height / 2 - this.slider.getBounds().height / 2);
+ } else {
+ final Image temp = new Image(getDisplay(), image, SWT.IMAGE_DISABLE);
+ gc.drawImage(temp, x + 5, getClientArea().height / 2 - this.slider.getBounds().height / 2);
+ temp.dispose();
+ }
+ return new Point(x + 5, getClientArea().height / 2 - this.slider.getBounds().height / 2);
+ }
+
+ /**
+ * Draw the range slider (vertical)
+ *
+ * @param gc graphic context
+ */
+ private void drawVerticalRangeSlider(final GC gc) {
+ drawBackgroundVertical(gc);
+ drawBarsVertical(gc);
+ this.coordUpper = drawVerticalKnob(gc, this.upperValue, true);
+ this.coordLower = drawVerticalKnob(gc, this.lowerValue, false);
+ }
+
+ /**
+ * Draws the background
+ *
+ * @param gc graphic context
+ */
+ private void drawBackgroundVertical(final GC gc) {
+ final Rectangle clientArea = this.getClientArea();
+ gc.setBackground(getBackground());
+ gc.fillRectangle(clientArea);
+
+ if (isEnabled()) {
+ gc.setForeground(getForeground());
+ } else {
+ gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
+ }
+ gc.drawRoundRectangle(9, 9, clientArea.width - 20, clientArea.height - 20, 3, 3);
+
+ final float pixelSize = computePixelSizeForVerticalSlider();
+ final int startY = (int) (pixelSize * this.lowerValue);
+ final int endY = (int) (pixelSize * this.upperValue);
+ if (isEnabled()) {
+ gc.setBackground(getForeground());
+ } else {
+ gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
+ }
+ gc.fillRectangle(9, 12 + startY, clientArea.width - 20, endY - startY - 6);
+
+ }
+
+ /**
+ * @return how many pixels corresponds to 1 point of value
+ */
+ private float computePixelSizeForVerticalSlider() {
+ return (getClientArea().height - 20f) / (this.maximum - this.minimum);
+ }
+
+ /**
+ * Draws the bars
+ *
+ * @param gc graphic context
+ */
+ private void drawBarsVertical(final GC gc) {
+ final Rectangle clientArea = this.getClientArea();
+ if (isEnabled()) {
+ gc.setForeground(getForeground());
+ } else {
+ gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
+ }
+
+ final float pixelSize = computePixelSizeForVerticalSlider();
+ for (int i = 1; i < 10; i++) {
+ final int y = (int) (9 + pixelSize * (this.maximum - this.minimum) / 10 * i);
+ gc.drawLine(4, y, 7, y);
+ gc.drawLine(clientArea.width - 6, y, clientArea.width - 9, y);
+
+ }
+
+ }
+
+ /**
+ * Draws a vertical knob
+ *
+ * @param gc graphic context
+ * @param value corresponding value
+ * @param upper if <code>true</code>, draws the upper knob. If
+ * <code>false</code>, draws the lower knob
+ * @return the coordinate of the upper left corner of the knob
+ */
+ private Point drawVerticalKnob(final GC gc, final int value, final boolean upper) {
+ final float pixelSize = computePixelSizeForVerticalSlider();
+ final int y = (int) (pixelSize * value);
+
+ Image image;
+ if (upper) {
+ if (this.upperHover) {
+ image = this.dragInProgress ? this.vSliderDrag : this.vSliderHover;
+ } else if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ image = this.vSliderSelected;
+ } else {
+ image = this.vSlider;
+ }
+ } else {
+ if (this.lowerHover) {
+ image = this.dragInProgress ? this.vSliderDrag : this.vSliderHover;
+ } else if (this.lastSelected == SELECTED_KNOB.LOWER) {
+ image = this.vSliderSelected;
+ } else {
+ image = this.vSlider;
+ }
+ }
+
+ if (isEnabled()) {
+ gc.drawImage(image, getClientArea().width / 2 - 8, y + 2);
+ } else {
+ final Image temp = new Image(getDisplay(), image, SWT.IMAGE_DISABLE);
+ gc.drawImage(temp, getClientArea().width / 2 - 8, y + 2);
+ temp.dispose();
+
+ }
+ return new Point(getClientArea().width / 2 - 8, y + 2);
+ }
+
+ /**
+ * Code executed when a key is typed
+ *
+ * @param event event
+ */
+ private void handleKeyDown(final Event event) {
+
+ boolean needRedraw = false;
+
+ if (this.lastSelected == SELECTED_KNOB.NONE) {
+ this.lastSelected = SELECTED_KNOB.LOWER;
+ }
+
+ switch (event.keyCode) {
+ case SWT.HOME:
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ this.upperValue = this.minimum;
+ } else {
+ this.lowerValue = this.minimum;
+ }
+ needRedraw = true;
+ break;
+ case SWT.END:
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ this.upperValue = this.maximum;
+ } else {
+ this.upperValue = this.maximum;
+ }
+ needRedraw = true;
+ break;
+ case SWT.PAGE_UP:
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ this.upperValue += this.pageIncrement;
+ } else {
+ this.lowerValue += this.pageIncrement;
+ }
+ needRedraw = true;
+ break;
+ case SWT.PAGE_DOWN:
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ this.upperValue -= this.pageIncrement;
+ } else {
+ this.lowerValue -= this.pageIncrement;
+ }
+ needRedraw = true;
+ break;
+ case SWT.ARROW_LEFT:
+ case SWT.ARROW_UP:
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ this.upperValue -= this.increment;
+ } else {
+ this.lowerValue -= this.increment;
+ }
+ needRedraw = true;
+ break;
+ case SWT.ARROW_RIGHT:
+ case SWT.ARROW_DOWN:
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ this.upperValue += this.increment;
+ } else {
+ this.lowerValue += this.increment;
+ }
+ needRedraw = true;
+ break;
+ default:
+ break;
+ }
+
+ if (needRedraw) {
+ if (this.lastSelected == SELECTED_KNOB.UPPER) {
+ checkUpperValue();
+ } else {
+ checkLowerValue();
+ }
+ redraw();
+ }
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified
+ * when the user changes the receiver's value, by sending it one of the
+ * messages defined in the <code>SelectionListener</code> interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the user changes the
+ * receiver's value. <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.listeners.add(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
+ */
+ @Override
+ public Point computeSize(final int wHint, final int hHint, final boolean changed) {
+ final int width, height;
+ checkWidget();
+ if (this.orientation == SWT.HORIZONTAL) {
+ if (wHint < 100) {
+ width = 100;
+ } else {
+ width = wHint;
+ }
+
+ if (hHint < 30) {
+ height = 30;
+ } else {
+ height = hHint;
+ }
+ } else {
+ if (wHint < 30) {
+ width = 30;
+ } else {
+ width = wHint;
+ }
+
+ if (hHint < 100) {
+ height = 100;
+ } else {
+ height = hHint;
+ }
+ }
+
+ return new Point(width, height);
+ }
+
+ /**
+ * Returns the amount that the selected receiver's value will be modified by
+ * when the up/down (or right/left) arrows are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getIncrement() {
+ checkWidget();
+ return this.increment;
+ }
+
+ /**
+ * Returns the 'lower selection', which is the lower receiver's position.
+ *
+ * @return the selection
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getLowerValue() {
+ checkWidget();
+ return this.lowerValue;
+ }
+
+ /**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getMaximum() {
+ checkWidget();
+ return this.maximum;
+ }
+
+ /**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getMinimum() {
+ checkWidget();
+ return this.minimum;
+ }
+
+ /**
+ * Returns the amount that the selected receiver's value will be modified by
+ * when the page increment/decrement areas are selected.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getPageIncrement() {
+ checkWidget();
+ return this.pageIncrement;
+ }
+
+ /**
+ * Returns the 'selection', which is an array where the first element is the
+ * lower selection, and the second element is the upper selection
+ *
+ * @return the selection
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int[] getSelection() {
+ checkWidget();
+ final int[] selection = new int[2];
+ selection[0] = this.lowerValue;
+ selection[1] = this.upperValue;
+ return selection;
+ }
+
+ /**
+ * Returns the 'upper selection', which is the upper receiver's position.
+ *
+ * @return the selection
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getUpperValue() {
+ checkWidget();
+ return this.upperValue;
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be
+ * notified when the user changes the receiver's value.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.listeners.remove(listener);
+ }
+
+ /**
+ * Sets the amount that the selected receiver's value will be modified by
+ * when the up/down (or right/left) arrows are pressed to the argument,
+ * which must be at least one.
+ *
+ * @param increment the new increment (must be greater than zero)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setIncrement(final int increment) {
+ checkWidget();
+ this.increment = increment;
+ redraw();
+ }
+
+ /**
+ * Sets the 'lower selection', which is the receiver's lower value, to the
+ * argument which must be greater than or equal to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setLowerValue(final int value) {
+ checkWidget();
+ if (this.minimum <= value && value <= this.maximum && value <= this.upperValue) {
+ this.lowerValue = value;
+ }
+ redraw();
+ }
+
+ /**
+ * Sets the maximum value that the receiver will allow. This new value will
+ * be ignored if it is not greater than the receiver's current minimum
+ * value. If the new maximum is applied then the receiver's selection value
+ * will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current
+ * minimum
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setMaximum(final int value) {
+ checkWidget();
+ if (this.minimum <= value) {
+ this.maximum = value;
+ if (this.lowerValue >= this.maximum) {
+ this.lowerValue = this.maximum;
+ }
+ if (this.upperValue >= this.maximum) {
+ this.upperValue = this.maximum;
+ }
+ }
+ redraw();
+ }
+
+ /**
+ * Sets the minimum value that the receiver will allow. This new value will
+ * be ignored if it is negative or is not less than the receiver's current
+ * maximum value. If the new minimum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new
+ * range.
+ *
+ * @param value the new minimum, which must be nonnegative and less than the
+ * current maximum
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setMinimum(final int value) {
+ checkWidget();
+ if (this.maximum >= value) {
+ this.minimum = value;
+ if (this.lowerValue <= this.minimum) {
+ this.lowerValue = this.minimum;
+ }
+ if (this.upperValue <= this.minimum) {
+ this.upperValue = this.minimum;
+ }
+ }
+ redraw();
+ }
+
+ /**
+ * Sets the amount that the receiver's value will be modified by when the
+ * page increment/decrement areas are selected to the argument, which must
+ * be at least one.
+ *
+ * @param pageIncrement the page increment (must be greater than zero)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setPageIncrement(final int pageIncrement) {
+ checkWidget();
+ this.pageIncrement = pageIncrement;
+ }
+
+ /**
+ * Sets the 'selection', which is the receiver's value, to the argument
+ * which must be greater than or equal to zero.
+ *
+ * @param value the new selection (first value is lower value, second value
+ * is upper value)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelection(final int[] values) {
+ checkWidget();
+ setLowerValue(values[0]);
+ setUpperValue(values[1]);
+ checkUpperValue();
+ checkLowerValue();
+ redraw();
+ }
+
+ /**
+ * Sets the 'selection', which is the receiver's value, argument which must
+ * be greater than or equal to zero.
+ *
+ * @param lowerValue the new lower selection (must be zero or greater)
+ * @param upperValue the new upper selection (must be zero or greater)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelection(final int lowerValue, final int upperValue) {
+ checkWidget();
+ setLowerValue(lowerValue);
+ setUpperValue(upperValue);
+ }
+
+ /**
+ * Sets the 'upper selection', which is the upper receiver's value, argument
+ * which must be greater than or equal to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setUpperValue(final int value) {
+ checkWidget();
+ if (this.minimum <= value && value <= this.maximum && value >= this.lowerValue) {
+ this.upperValue = value;
+ }
+ redraw();
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/switchButton/SwitchButton.java b/org.tizen.common.externals/src/org/mihalis/opal/switchButton/SwitchButton.java
new file mode 100644
index 000000000..c3b0c3ce1
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/switchButton/SwitchButton.java
@@ -0,0 +1,938 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.switchButton;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are simple switch button.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ */
+public class SwitchButton extends Canvas {
+
+ /**
+ * Selection
+ */
+ private boolean selection;
+
+ /**
+ * Text displayed for the selected value (default = "On")
+ */
+ private String textForSelect;
+
+ /**
+ * Text displayed for the unselected value (default = "Off")
+ */
+ private String textForUnselect;
+
+ /**
+ * Text corresponding to the button (default is "")
+ */
+ private String text;
+
+ /**
+ * If true, display round rectangles instead of rectangles (default value is
+ * true)
+ */
+ private boolean round;
+
+ /**
+ * if not null, displays a rectangle (or a round rectangle) around the whole
+ * widget. Default value is null.
+ */
+ private Color borderColor;
+
+ /**
+ * if not null, displays a glow effect when the mouse is over the widget.
+ * Default value is null.
+ */
+ private Color focusColor;
+
+ /**
+ * Colors when the button is selected
+ */
+ private Color selectedForegroundColor, selectedBackgroundColor;
+
+ /**
+ * Colors when the button is not selected
+ */
+ private Color unselectedForegroundColor, unselectedBackgroundColor;
+
+ /**
+ * Colors for the button
+ */
+ private Color buttonBorderColor, buttonBackgroundColor1, buttonBackgroundColor2;
+
+ /**
+ * Gap between the button and the text (default value is 5)
+ */
+ private int gap;
+
+ /**
+ * Margin inside the button
+ */
+ private static final int INSIDE_BUTTON_MARGIN = 5;
+
+ /**
+ * Graphical context for this button
+ */
+ private GC gc;
+
+ /**
+ * List of selection listeners
+ */
+ private final List<SelectionListener> listOfSelectionListeners;
+
+ /**
+ * True when the mouse entered the widget
+ */
+ private boolean mouseInside;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ */
+ public SwitchButton(final Composite parent, final int style) {
+ super(parent, style | SWT.DOUBLE_BUFFERED);
+
+ this.selection = false;
+ this.textForSelect = "On";
+ this.textForUnselect = "Off";
+ this.round = true;
+ this.borderColor = null;
+ this.focusColor = this.getDisplay().getSystemColor(SWT.COLOR_YELLOW);
+ this.selectedForegroundColor = this.getDisplay().getSystemColor(SWT.COLOR_WHITE);
+ this.selectedBackgroundColor = new Color(this.getDisplay(), 0, 112, 195);
+ this.unselectedForegroundColor = this.getDisplay().getSystemColor(SWT.COLOR_BLACK);
+ this.unselectedBackgroundColor = new Color(this.getDisplay(), 203, 203, 203);
+
+ this.buttonBorderColor = new Color(this.getDisplay(), 96, 96, 96);
+ this.buttonBackgroundColor1 = new Color(this.getDisplay(), 254, 254, 254);
+ this.buttonBackgroundColor2 = new Color(this.getDisplay(), 192, 192, 192);
+
+ this.gap = 5;
+
+ this.listOfSelectionListeners = new ArrayList<SelectionListener>();
+
+ this.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ SwitchButton.this.selectedBackgroundColor.dispose();
+ SwitchButton.this.unselectedBackgroundColor.dispose();
+ SwitchButton.this.buttonBorderColor.dispose();
+ SwitchButton.this.buttonBackgroundColor1.dispose();
+ SwitchButton.this.buttonBackgroundColor2.dispose();
+ }
+ });
+
+ this.addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(final PaintEvent event) {
+ SwitchButton.this.onPaint(event);
+ }
+ });
+
+ this.addMouseListener(new MouseAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.MouseAdapter#mouseUp(org.eclipse.swt.events.MouseEvent)
+ */
+ @Override
+ public void mouseUp(final MouseEvent e) {
+ if (SwitchButton.this.fireSelectionListeners(e)) {
+ SwitchButton.this.selection = !SwitchButton.this.selection;
+ SwitchButton.this.redraw();
+ }
+ }
+
+ });
+
+ this.mouseInside = false;
+ this.addMouseTrackListener(new MouseTrackListener() {
+
+ @Override
+ public void mouseHover(final MouseEvent e) {
+ SwitchButton.this.mouseInside = true;
+ SwitchButton.this.redraw();
+ }
+
+ @Override
+ public void mouseExit(final MouseEvent e) {
+ SwitchButton.this.mouseInside = false;
+ SwitchButton.this.redraw();
+ }
+
+ @Override
+ public void mouseEnter(final MouseEvent e) {
+ SwitchButton.this.mouseInside = true;
+ SwitchButton.this.redraw();
+ }
+ });
+
+ }
+
+ /**
+ * Paint the widget
+ *
+ * @param event paint event
+ */
+ private void onPaint(final PaintEvent event) {
+ final Rectangle rect = this.getClientArea();
+ if (rect.width == 0 || rect.height == 0) {
+ return;
+ }
+ this.gc = event.gc;
+ this.gc.setAntialias(SWT.ON);
+
+ final Point buttonSize = this.computeButtonSize();
+ this.drawSwitchButton(buttonSize);
+ this.drawText(buttonSize);
+
+ if (this.borderColor != null) {
+ this.drawBorder();
+ }
+
+ }
+
+ /**
+ * Draw the switch button
+ *
+ * @param buttonSize size of the button
+ */
+ private void drawSwitchButton(final Point buttonSize) {
+ // Draw the background of the button
+ this.gc.setForeground(this.buttonBorderColor);
+ if (this.round) {
+ this.gc.drawRoundRectangle(2, 2, buttonSize.x, buttonSize.y, 3, 3);
+ } else {
+ this.gc.drawRectangle(2, 2, buttonSize.x, buttonSize.y);
+ }
+
+ this.drawRightPart(buttonSize);
+ this.drawLeftPart(buttonSize);
+ this.gc.setClipping(this.getClientArea());
+ this.drawToggleButton(buttonSize);
+ }
+
+ /**
+ * Draw the right part of the button
+ *
+ * @param buttonSize size of the button
+ */
+ private void drawRightPart(final Point buttonSize) {
+ this.gc.setForeground(this.selectedBackgroundColor);
+ this.gc.setBackground(this.selectedBackgroundColor);
+ this.gc.setClipping(3, 3, buttonSize.x / 2, buttonSize.y - 1);
+ if (this.round) {
+ this.gc.fillRoundRectangle(2, 2, buttonSize.x, buttonSize.y, 3, 3);
+ } else {
+ this.gc.fillRectangle(2, 2, buttonSize.x, buttonSize.y);
+ }
+ this.gc.setForeground(this.selectedForegroundColor);
+ final Point textSize = this.gc.textExtent(this.textForSelect);
+ this.gc.drawString(this.textForSelect, (buttonSize.x / 2 - textSize.x) / 2 + 3, (buttonSize.y - textSize.y) / 2 + 3);
+ }
+
+ /**
+ * Draw the left part of the button
+ *
+ * @param buttonSize size of the button
+ */
+ private void drawLeftPart(final Point buttonSize) {
+ this.gc.setForeground(this.unselectedBackgroundColor);
+ this.gc.setBackground(this.unselectedBackgroundColor);
+ this.gc.setClipping(buttonSize.x / 2 + 3, 3, buttonSize.x / 2, buttonSize.y - 1);
+ if (this.round) {
+ this.gc.fillRoundRectangle(2, 2, buttonSize.x, buttonSize.y, 3, 3);
+ } else {
+ this.gc.fillRectangle(2, 2, buttonSize.x, buttonSize.y);
+ }
+ this.gc.setForeground(this.unselectedForegroundColor);
+ final Point textSize = this.gc.textExtent(this.textForUnselect);
+
+ this.gc.drawString(this.textForUnselect, buttonSize.x / 2 + (buttonSize.x / 2 - textSize.x) / 2 + 3, (buttonSize.y - textSize.y) / 2 + 3);
+ }
+
+ /**
+ * Draw the toggle button
+ *
+ * @param buttonSize size of the button
+ */
+ private void drawToggleButton(final Point buttonSize) {
+ this.gc.setForeground(this.buttonBackgroundColor1);
+ this.gc.setBackground(this.buttonBackgroundColor2);
+ if (this.selection) {
+ this.gc.fillGradientRectangle(3, 3, buttonSize.x / 2, buttonSize.y, true);
+ } else {
+ this.gc.fillGradientRectangle(buttonSize.x / 2, 3, buttonSize.x / 2 + 2, buttonSize.y - 1, true);
+ }
+
+ this.gc.setForeground(this.buttonBorderColor);
+ if (this.selection) {
+ this.gc.drawRoundRectangle(2, 2, buttonSize.x / 2, buttonSize.y, 3, 3);
+ } else {
+ this.gc.drawRoundRectangle(buttonSize.x / 2, 2, buttonSize.x / 2 + 2, buttonSize.y, 3, 3);
+ }
+
+ if (this.focusColor != null && this.mouseInside) {
+ this.gc.setForeground(this.focusColor);
+ this.gc.setLineWidth(2);
+ if (this.selection) {
+ this.gc.drawRoundRectangle(3, 3, buttonSize.x / 2, buttonSize.y - 1, 3, 3);
+ } else {
+ this.gc.drawRoundRectangle(buttonSize.x / 2 + 1, 3, buttonSize.x / 2, buttonSize.y - 2, 3, 3);
+ }
+ this.gc.setLineWidth(1);
+ }
+
+ }
+
+ /**
+ * @return the button size
+ */
+ private Point computeButtonSize() {
+ // Compute size for the left part
+ final Point sizeForLeftPart = this.gc.stringExtent(this.textForSelect);
+ // Compute size for the right part
+ final Point sizeForRightPart = this.gc.stringExtent(this.textForUnselect);
+
+ // Compute whole size
+ final int width = Math.max(sizeForLeftPart.x, sizeForRightPart.x) * 2 + 2 * INSIDE_BUTTON_MARGIN;
+ final int height = Math.max(sizeForLeftPart.y, sizeForRightPart.y) + 2 * INSIDE_BUTTON_MARGIN;
+
+ return new Point(width, height);
+ }
+
+ /**
+ * Draws the text besides the button
+ *
+ * @param buttonSize whole size of the button
+ */
+ private void drawText(final Point buttonSize) {
+ this.gc.setForeground(this.getForeground());
+ this.gc.setBackground(this.getBackground());
+
+ final int widgetHeight = this.computeSize(0, 0, true).y;
+ final int textHeight = this.gc.stringExtent(this.text).y;
+ final int x = 2 + buttonSize.x + this.gap;
+
+ this.gc.drawString(this.text, x, (widgetHeight - textHeight) / 2);
+ }
+
+ /**
+ * Draw (eventually) the border around the button
+ */
+ private void drawBorder() {
+ if (this.borderColor == null) {
+ return;
+ }
+
+ this.gc.setForeground(this.borderColor);
+ final Point temp = this.computeSize(0, 0, false);
+ if (this.round) {
+ this.gc.drawRoundRectangle(0, 0, temp.x - 2, temp.y - 2, 3, 3);
+ } else {
+ this.gc.drawRectangle(0, 0, temp.x - 2, temp.y - 2);
+ }
+
+ }
+
+ /**
+ * Fire the selection listeners
+ *
+ * @param mouseEvent mouse event
+ * @return true if the selection could be changed, false otherwise
+ */
+ private boolean fireSelectionListeners(final MouseEvent mouseEvent) {
+ for (final SelectionListener listener : this.listOfSelectionListeners) {
+ final Event event = new Event();
+
+ event.button = mouseEvent.button;
+ event.display = this.getDisplay();
+ event.item = null;
+ event.widget = this;
+ event.data = null;
+ event.time = mouseEvent.time;
+ event.x = mouseEvent.x;
+ event.y = mouseEvent.y;
+
+ final SelectionEvent selEvent = new SelectionEvent(event);
+ listener.widgetSelected(selEvent);
+ if (!selEvent.doit) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified
+ * when the control is selected by the user, by sending it one of the
+ * messages defined in the <code>SelectionListener</code> interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the control is selected by the
+ * user. <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ this.checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ this.listOfSelectionListeners.add(listener);
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be
+ * notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ this.checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ this.listOfSelectionListeners.remove(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
+ */
+ @Override
+ public Point computeSize(final int wHint, final int hHint, final boolean changed) {
+ this.checkWidget();
+ boolean disposeGC = false;
+ if (this.gc == null) {
+ this.gc = new GC(this);
+ disposeGC = true;
+ }
+
+ final Point buttonSize = this.computeButtonSize();
+ int width = buttonSize.x;
+ int height = buttonSize.y;
+
+ if (this.text != null && this.text.trim().length() > 0) {
+ final Point textSize = this.gc.textExtent(this.text);
+ width += textSize.x + this.gap + 1;
+ }
+
+ width += 4;
+ height += 6;
+
+ if (disposeGC) {
+ this.gc.dispose();
+ }
+
+ return new Point(width, height);
+ }
+
+ /**
+ * @return the selection state of the button
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public boolean getSelection() {
+ this.checkWidget();
+ return this.selection;
+ }
+
+ /**
+ * @param selection the selection state of the button
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelection(final boolean selection) {
+ this.checkWidget();
+ this.selection = selection;
+ }
+
+ /**
+ * @return the text used to display the selection
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public String getTextForSelect() {
+ this.checkWidget();
+ return this.textForSelect;
+ }
+
+ /**
+ * @param textForSelect the text used to display the selection
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setTextForSelect(final String textForSelect) {
+ this.checkWidget();
+ this.textForSelect = textForSelect;
+ }
+
+ /**
+ * @return the text used to display the unselected option
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public String getTextForUnselect() {
+ this.checkWidget();
+ return this.textForUnselect;
+ }
+
+ /**
+ * @param textForUnselect the text used to display the unselected option
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setTextForUnselect(final String textForUnselect) {
+ this.checkWidget();
+ this.textForUnselect = textForUnselect;
+ }
+
+ /**
+ * @return the text displayed in the widget
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public String getText() {
+ this.checkWidget();
+ return this.text;
+ }
+
+ /**
+ * @param the text displayed in the widget
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setText(final String text) {
+ this.checkWidget();
+ this.text = text;
+ }
+
+ /**
+ * @return the round flag
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public boolean isRound() {
+ this.checkWidget();
+ return this.round;
+ }
+
+ /**
+ * @param round the round flag to set. If true, the widget is composed of
+ * round rectangle instead of rectangles
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setRound(final boolean round) {
+ this.checkWidget();
+ this.round = round;
+ }
+
+ /**
+ * @return the border's color. If null, no border is displayed
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getBorderColor() {
+ this.checkWidget();
+ return this.borderColor;
+ }
+
+ /**
+ * @param borderColor the border's color. If null, no border is displayed.
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setBorderColor(final Color borderColor) {
+ this.checkWidget();
+ this.borderColor = borderColor;
+ }
+
+ /**
+ * @return the focus color. If null, no focus effect is displayed.
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getFocusColor() {
+ this.checkWidget();
+ return this.focusColor;
+ }
+
+ /**
+ * @param focusColor the focus color to set. If null, no focus effect is
+ * displayed.
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setFocusColor(final Color focusColor) {
+ this.checkWidget();
+ this.focusColor = focusColor;
+ }
+
+ /**
+ * @return the foreground color of the left part of the widget (selection is
+ * on)
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getSelectedForegroundColor() {
+ this.checkWidget();
+ return this.selectedForegroundColor;
+ }
+
+ /**
+ * @param the foreground color of the left part of the widget (selection is
+ * on)
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelectedForegroundColor(final Color selectedForegroundColor) {
+ this.checkWidget();
+ this.selectedForegroundColor = selectedForegroundColor;
+ }
+
+ /**
+ * @return the background color of the left part of the widget (selection is
+ * on)
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getSelectedBackgroundColor() {
+ this.checkWidget();
+ return this.selectedBackgroundColor;
+ }
+
+ /**
+ * @param the background color of the left part of the widget (selection is
+ * on)
+ */
+ public void setSelectedBackgroundColor(final Color selectedBackgroundColor) {
+ this.checkWidget();
+ this.selectedBackgroundColor = selectedBackgroundColor;
+ }
+
+ /**
+ * @return the foreground color of the left part of the widget (selection is
+ * on)
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getUnselectedForegroundColor() {
+ this.checkWidget();
+ return this.unselectedForegroundColor;
+ }
+
+ /**
+ * @param unselectedForegroundColor the foreground color of the left part of
+ * the widget (selection is on)
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setUnselectedForegroundColor(final Color unselectedForegroundColor) {
+ this.checkWidget();
+ this.unselectedForegroundColor = unselectedForegroundColor;
+ }
+
+ /**
+ * @return the background color of the left part of the widget (selection is
+ * on)
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getUnselectedBackgroundColor() {
+ this.checkWidget();
+ return this.unselectedBackgroundColor;
+ }
+
+ /**
+ * @param unselectedBackgroundColor the background color of the left part of
+ * the widget (selection is on)
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setUnselectedBackgroundColor(final Color unselectedBackgroundColor) {
+ this.checkWidget();
+ this.unselectedBackgroundColor = unselectedBackgroundColor;
+ }
+
+ /**
+ * @return the border color of the switch button
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getButtonBorderColor() {
+ this.checkWidget();
+ return this.buttonBorderColor;
+ }
+
+ /**
+ * @param buttonBorderColor the border color of the switch button
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setButtonBorderColor(final Color buttonBorderColor) {
+ this.checkWidget();
+ this.buttonBorderColor = buttonBorderColor;
+ }
+
+ /**
+ * @return the first color of the toggle button
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getButtonBackgroundColor1() {
+ this.checkWidget();
+ return this.buttonBackgroundColor1;
+ }
+
+ /**
+ * @param buttonBackgroundColor1 the first color of the toggle button
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setButtonBackgroundColor1(final Color buttonBackgroundColor1) {
+ this.checkWidget();
+ this.buttonBackgroundColor1 = buttonBackgroundColor1;
+ }
+
+ /**
+ * @return the second color of the toggle button
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Color getButtonBackgroundColor2() {
+ this.checkWidget();
+ return this.buttonBackgroundColor2;
+ }
+
+ /**
+ * @param buttonBackgroundColor2 the second color of the toggle button
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setButtonBackgroundColor2(final Color buttonBackgroundColor2) {
+ this.checkWidget();
+ this.buttonBackgroundColor2 = buttonBackgroundColor2;
+ }
+
+ /**
+ * @return the gap value
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public int getGap() {
+ this.checkWidget();
+ return this.gap;
+ }
+
+ /**
+ * @param gap the gap value to set
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setGap(final int gap) {
+ this.checkWidget();
+ this.gap = gap;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/textAssist/TextAssist.java b/org.tizen.common.externals/src/org/mihalis/opal/textAssist/TextAssist.java
new file mode 100755
index 000000000..08bcebc73
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/textAssist/TextAssist.java
@@ -0,0 +1,694 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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 (Snippet 320)
+ * Laurent CARON (laurent.caron@gmail.com) - Make a widget from the snippet
+ *******************************************************************************/
+package org.mihalis.opal.textAssist;
+
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Instances of this class are selectable user interface objects that allow the
+ * user to enter and modify text. The difference with the Text widget is that
+ * when the user types something, some propositions are displayed.
+ *
+ * @see org.eclipse.swt.widgets.Text
+ */
+public class TextAssist extends Composite {
+
+ private final Text text;
+ private final Shell popup;
+ private final Table table;
+ private TextAssistContentProvider contentProvider;
+ private int numberOfLines;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ * @param contentProvider the content provider
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * <li>ERROR_INVALID_SUBCLASS - if this class is not an
+ * allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#READ_ONLY
+ * @see SWT#WRAP
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see SWT#PASSWORD
+ * @see SWT#SEARCH
+ * @see SWT#ICON_SEARCH
+ * @see SWT#ICON_CANCEL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+ public TextAssist(final Composite parent, final int style, final TextAssistContentProvider contentProvider) {
+ super(parent, style);
+ this.contentProvider = contentProvider;
+ this.contentProvider.setTextAssist(this);
+
+ this.setLayout(new FillLayout());
+ this.numberOfLines = 10;
+ this.text = new Text(this, style);
+ this.popup = new Shell(this.getDisplay(), SWT.ON_TOP);
+ this.popup.setLayout(new FillLayout());
+ this.table = new Table(this.popup, SWT.SINGLE);
+
+ this.text.addListener(SWT.KeyDown, createKeyDownListener());
+ this.text.addListener(SWT.Modify, createModifyListener());
+ this.text.addListener(SWT.FocusOut, createFocusOutListener());
+
+ this.table.addListener(SWT.DefaultSelection, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ TextAssist.this.text.setText(TextAssist.this.table.getSelection()[0].getText());
+ TextAssist.this.popup.setVisible(false);
+ }
+ });
+ this.table.addListener(SWT.KeyDown, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ if (event.keyCode == SWT.ESC) {
+ TextAssist.this.popup.setVisible(false);
+ }
+ }
+ });
+
+ this.table.addListener(SWT.FocusOut, createFocusOutListener());
+
+ getShell().addListener(SWT.Move, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ TextAssist.this.popup.setVisible(false);
+ }
+ });
+ }
+
+ /**
+ * @return a listener for the keydown event
+ */
+ private Listener createKeyDownListener() {
+ return new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ switch (event.keyCode) {
+ case SWT.ARROW_DOWN:
+ int index = (TextAssist.this.table.getSelectionIndex() + 1) % TextAssist.this.table.getItemCount();
+ TextAssist.this.table.setSelection(index);
+ event.doit = false;
+ break;
+ case SWT.ARROW_UP:
+ index = TextAssist.this.table.getSelectionIndex() - 1;
+ if (index < 0) {
+ index = TextAssist.this.table.getItemCount() - 1;
+ }
+ TextAssist.this.table.setSelection(index);
+ event.doit = false;
+ break;
+ case SWT.CR:
+ if (TextAssist.this.popup.isVisible() && TextAssist.this.table.getSelectionIndex() != -1) {
+ TextAssist.this.text.setText(TextAssist.this.table.getSelection()[0].getText());
+ TextAssist.this.popup.setVisible(false);
+ }
+ break;
+ case SWT.ESC:
+ TextAssist.this.popup.setVisible(false);
+ break;
+
+ default:
+ break;
+ }
+ }
+ };
+ }
+
+ /**
+ * @return a listener for the modify event
+ */
+ private Listener createModifyListener() {
+ return new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ final String string = TextAssist.this.text.getText();
+ if (string.length() == 0) {
+ TextAssist.this.popup.setVisible(false);
+ return;
+ }
+
+ List<String> values = TextAssist.this.contentProvider.getContent(string);
+ if (values == null || values.isEmpty()) {
+ TextAssist.this.popup.setVisible(false);
+ return;
+ }
+
+ if (values.size() > TextAssist.this.numberOfLines) {
+ values = values.subList(0, TextAssist.this.numberOfLines);
+ }
+
+ TextAssist.this.table.removeAll();
+ final int numberOfRows = Math.min(values.size(), TextAssist.this.numberOfLines);
+ for (int i = 0; i < numberOfRows; i++) {
+ final TableItem tableItem = new TableItem(TextAssist.this.table, SWT.NONE);
+ tableItem.setText(values.get(i));
+ }
+
+ final Point point = TextAssist.this.text.toDisplay(TextAssist.this.text.getLocation().x, TextAssist.this.text.getSize().y + TextAssist.this.text.getBorderWidth() - 3);
+ int x = point.x;
+ int y = point.y;
+
+ final Rectangle displayRect = getMonitor().getClientArea();
+ final Rectangle parentRect = getDisplay().map(getParent(), null, getBounds());
+ TextAssist.this.popup.pack();
+ final int width = TextAssist.this.popup.getBounds().width;
+ final int height = TextAssist.this.popup.getBounds().height;
+
+ if (y + height > displayRect.y + displayRect.height) {
+ y = parentRect.y - height;
+ }
+ if (x + width > displayRect.x + displayRect.width) {
+ x = displayRect.x + displayRect.width - width;
+ }
+
+ TextAssist.this.popup.setLocation(x, y);
+ TextAssist.this.popup.setVisible(true);
+
+ }
+ };
+ }
+
+ /**
+ * @return a listener for the FocusOut event
+ */
+ private Listener createFocusOutListener() {
+ return new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ /* async is needed to wait until focus reaches its new Control */
+ TextAssist.this.getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (TextAssist.this.getDisplay().isDisposed()) {
+ return;
+ }
+ final Control control = TextAssist.this.getDisplay().getFocusControl();
+ if (control == null || control != TextAssist.this.text && control != TextAssist.this.table) {
+ TextAssist.this.popup.setVisible(false);
+ }
+ }
+ });
+ }
+ };
+ }
+
+ /**
+ * @return the contentProvider
+ */
+ public TextAssistContentProvider getContentProvider() {
+ checkWidget();
+ return this.contentProvider;
+ }
+
+ /**
+ * @param contentProvider the contentProvider to set
+ */
+ public void setContentProvider(final TextAssistContentProvider contentProvider) {
+ checkWidget();
+ this.contentProvider = contentProvider;
+ }
+
+ /**
+ * @return the numberOfLines
+ */
+ public int getNumberOfLines() {
+ checkWidget();
+ return this.numberOfLines;
+ }
+
+ /**
+ * @param numberOfLines the numberOfLines to set
+ */
+ public void setNumberOfLines(final int numberOfLines) {
+ checkWidget();
+ this.numberOfLines = numberOfLines;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#addModifyListener(org.eclipse.swt.events.ModifyListener)
+ */
+ public void addModifyListener(final ModifyListener listener) {
+ checkWidget();
+ this.text.addModifyListener(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#addSelectionListener(org.eclipse.swt.events.SelectionListener)
+ */
+ public void addSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.text.addSelectionListener(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#addVerifyListener(org.eclipse.swt.events.VerifyListener)
+ */
+ public void addVerifyListener(final VerifyListener listener) {
+ checkWidget();
+ this.text.addVerifyListener(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#append(java.lang.String)
+ */
+ public void append(final String string) {
+ checkWidget();
+ this.text.append(string);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#clearSelection()
+ */
+ public void clearSelection() {
+ checkWidget();
+ this.text.clearSelection();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#computeSize(int, int, boolean)
+ */
+ @Override
+ public Point computeSize(final int wHint, final int hHint, final boolean changed) {
+ checkWidget();
+ return this.text.computeSize(wHint, hHint, changed);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#computeTrim(int, int, int, int)
+ */
+ @Override
+ public Rectangle computeTrim(final int x, final int y, final int width, final int height) {
+ checkWidget();
+ return super.computeTrim(x, y, width, height);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#copy()
+ */
+ public void copy() {
+ checkWidget();
+ this.text.copy();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#cut()
+ */
+ public void cut() {
+ checkWidget();
+ this.text.cut();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getCaretLineNumber()
+ */
+ public int getCaretLineNumber() {
+ checkWidget();
+ return this.text.getCaretLineNumber();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getCaretLocation()
+ */
+ public Point getCaretLocation() {
+ checkWidget();
+ return this.text.getCaretLocation();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getCaretPosition()
+ */
+ public int getCaretPosition() {
+ checkWidget();
+ return this.text.getCaretPosition();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getCharCount()
+ */
+ public int getCharCount() {
+ checkWidget();
+ return this.text.getCharCount();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getDoubleClickEnabled()
+ */
+ public boolean getDoubleClickEnabled() {
+ checkWidget();
+ return this.text.getDoubleClickEnabled();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getEchoChar()
+ */
+ public char getEchoChar() {
+ checkWidget();
+ return this.text.getEchoChar();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getEditable()
+ */
+ public boolean getEditable() {
+ checkWidget();
+ return this.text.getEditable();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getLineCount()
+ */
+ public int getLineCount() {
+ checkWidget();
+ return this.text.getLineCount();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getLineDelimiter()
+ */
+ public String getLineDelimiter() {
+ checkWidget();
+ return this.text.getLineDelimiter();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getLineHeight()
+ */
+ public int getLineHeight() {
+ checkWidget();
+ return this.text.getLineHeight();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getMessage()
+ */
+ public String getMessage() {
+ checkWidget();
+ return this.text.getMessage();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getOrientation()
+ */
+ public int getOrientation() {
+ checkWidget();
+ return this.text.getOrientation();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getSelection()
+ */
+ public Point getSelection() {
+ checkWidget();
+ return this.text.getSelection();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getSelectionCount()
+ */
+ public int getSelectionCount() {
+ checkWidget();
+ return this.text.getSelectionCount();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getSelectionText()
+ */
+ public String getSelectionText() {
+ checkWidget();
+ return this.text.getSelectionText();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getTabs()
+ */
+ public int getTabs() {
+ checkWidget();
+ return this.text.getTabs();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getText()
+ */
+ public String getText() {
+ checkWidget();
+ return this.text.getText();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getText(int, int)
+ */
+ public String getText(final int start, final int end) {
+ checkWidget();
+ return this.text.getText(start, end);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getTextLimit()
+ */
+ public int getTextLimit() {
+ checkWidget();
+ return this.text.getTextLimit();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getTopIndex()
+ */
+ public int getTopIndex() {
+ checkWidget();
+ return this.text.getTopIndex();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#getTopPixel()
+ */
+ public int getTopPixel() {
+ checkWidget();
+ return this.text.getTopPixel();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#insert(java.lang.String)
+ */
+ public void insert(final String string) {
+ checkWidget();
+ this.text.insert(string);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#paste()
+ */
+ public void paste() {
+ checkWidget();
+ this.text.paste();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#removeModifyListener(org.eclipse.swt.events.ModifyListener)
+ */
+ public void removeModifyListener(final ModifyListener listener) {
+ checkWidget();
+ this.text.removeModifyListener(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#removeSelectionListener(org.eclipse.swt.events.SelectionListener)
+ */
+ public void removeSelectionListener(final SelectionListener listener) {
+ checkWidget();
+ this.text.removeSelectionListener(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#removeVerifyListener(org.eclipse.swt.events.VerifyListener)
+ */
+ public void removeVerifyListener(final VerifyListener listener) {
+ checkWidget();
+ this.text.removeVerifyListener(listener);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#selectAll()
+ */
+ public void selectAll() {
+ checkWidget();
+ this.text.selectAll();
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setDoubleClickEnabled(boolean)
+ */
+ public void setDoubleClickEnabled(final boolean doubleClick) {
+ checkWidget();
+ this.text.setDoubleClickEnabled(doubleClick);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setEchoChar(char)
+ */
+ public void setEchoChar(final char echo) {
+ checkWidget();
+ this.text.setEchoChar(echo);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setEditable(boolean)
+ */
+ public void setEditable(final boolean editable) {
+ checkWidget();
+ this.text.setEditable(editable);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setFont(org.eclipse.swt.graphics.Font)
+ */
+ @Override
+ public void setFont(final Font font) {
+ checkWidget();
+ this.text.setFont(font);
+ this.table.setFont(font);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setMessage(java.lang.String)
+ */
+ public void setMessage(final String string) {
+ checkWidget();
+ this.text.setMessage(string);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setOrientation(int)
+ */
+ public void setOrientation(final int orientation) {
+ checkWidget();
+ this.text.setOrientation(orientation);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setRedraw(boolean)
+ */
+ @Override
+ public void setRedraw(final boolean redraw) {
+ checkWidget();
+ this.text.setRedraw(redraw);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setSelection(int, int)
+ */
+ public void setSelection(final int start, final int end) {
+ checkWidget();
+ this.text.setSelection(start, end);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setSelection(int)
+ */
+ public void setSelection(final int start) {
+ checkWidget();
+ this.text.setSelection(start);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setSelection(org.eclipse.swt.graphics.Point)
+ */
+ public void setSelection(final Point selection) {
+ checkWidget();
+ this.text.setSelection(selection);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setTabs(int)
+ */
+ public void setTabs(final int tabs) {
+ checkWidget();
+ this.text.setTabs(tabs);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setText(java.lang.String)
+ */
+ public void setText(final String text) {
+ checkWidget();
+ this.text.setText(text);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setTextLimit(int)
+ */
+ public void setTextLimit(final int textLimit) {
+ checkWidget();
+ this.text.setTextLimit(textLimit);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#setTopIndex(int)
+ */
+ public void setTopIndex(final int topIndex) {
+ checkWidget();
+ this.text.setTopIndex(topIndex);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Text#showSelection()
+ */
+ public void showSelection() {
+ checkWidget();
+ this.text.showSelection();
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/textAssist/TextAssistContentProvider.java b/org.tizen.common.externals/src/org/mihalis/opal/textAssist/TextAssistContentProvider.java
new file mode 100644
index 000000000..313fb6803
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/textAssist/TextAssistContentProvider.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.textAssist;
+
+import java.util.List;
+
+/**
+ * This class is a content provider for the TextAssist widget. When the user
+ * types something, an instance returns an arraylist of proposition based on the
+ * typed text.
+ *
+ */
+public abstract class TextAssistContentProvider {
+ private TextAssist textAssist;
+
+ /**
+ * Provides the content
+ *
+ * @param entry text typed by the user
+ * @return an array list of String that contains propositions for the entry
+ * typed by the user
+ */
+ public abstract List<String> getContent(final String entry);
+
+ /**
+ * @param textAssist the textAssist to set
+ */
+ protected void setTextAssist(final TextAssist textAssist) {
+ this.textAssist = textAssist;
+ }
+
+ /**
+ * @return the max number of propositions.
+ */
+ protected int getMaxNumberOfLines() {
+ return this.textAssist.getNumberOfLines();
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/tipOfTheDay/TipOfTheDay.java b/org.tizen.common.externals/src/org/mihalis/opal/tipOfTheDay/TipOfTheDay.java
new file mode 100755
index 000000000..4ec53c7c7
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/tipOfTheDay/TipOfTheDay.java
@@ -0,0 +1,524 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.tipOfTheDay;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.mihalis.opal.header.Header;
+import org.mihalis.opal.utils.ResourceManager;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class are a "Tip of Day" box, which is composed of
+ * <p>
+ * <dl>
+ * <dt><b>A tip</b></dt>
+ * <dt><b>2 buttons to navigate between types</b></dt>
+ * <dt><b>A close button</b></dt>
+ * <dt><b>A checkbox "show tip on startup"</b></dt>
+ * <dd>(optional)</dd>
+ * <dt><b>A checkbox "remember the password"</b></dt>
+ * <dd>(optional)</dd>
+ * </dl>
+ * </p>
+ */
+public class TipOfTheDay {
+
+ /**
+ * Types of opal dialog
+ */
+ public enum TipStyle {
+ TWO_COLUMNS, TWO_COLUMNS_LARGE, HEADER
+ }
+
+ private final List<String> tips;
+ private boolean displayShowOnStartup = true;
+ private boolean showOnStartup = true;
+ private Shell shell;
+ private Button close;
+ private int index;
+ private Browser tipArea;
+ private String fontName;
+ private TipStyle style;
+ private Image image;
+
+ /**
+ * Constructor
+ */
+ public TipOfTheDay() {
+ this.tips = new ArrayList<String>();
+ this.index = -1;
+ final Font temp = Display.getDefault().getSystemFont();
+ final FontData[] fontData = temp.getFontData();
+ if (fontData != null && fontData.length > 0) {
+ this.fontName = fontData[0].getName();
+ } else {
+ this.fontName = "Arial";
+ }
+ this.style = TipStyle.TWO_COLUMNS;
+
+ }
+
+ /**
+ * Open the "tip of the day" box
+ *
+ * @param parent the parent shell
+ */
+ public void open(final Shell parent) {
+ if (this.index == -1) {
+ this.index = new Random().nextInt(this.tips.size());
+ }
+ buildShell(parent);
+ if (this.style == TipStyle.HEADER) {
+ buildHeader();
+ } else {
+ buildLeftColumn();
+ }
+ buildTip();
+ buildButtons();
+ openShell();
+ }
+
+ /**
+ * Build the shell
+ *
+ * @param parent parent shell
+ */
+ private void buildShell(final Shell parent) {
+ this.shell = new Shell(parent, SWT.SYSTEM_MODAL | SWT.TITLE | SWT.BORDER | SWT.CLOSE | SWT.RESIZE);
+ this.shell.setText(ResourceManager.getLabel(ResourceManager.TIP_OF_THE_DAY));
+ this.shell.setLayout(new GridLayout(this.style == TipStyle.HEADER ? 1 : 2, false));
+
+ this.shell.addListener(SWT.Traverse, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ switch (event.detail) {
+ case SWT.TRAVERSE_ESCAPE:
+ TipOfTheDay.this.shell.dispose();
+ event.detail = SWT.TRAVERSE_NONE;
+ event.doit = false;
+ break;
+ default:
+ break;
+ }
+ }
+ });
+ }
+
+ /**
+ * Build the header
+ */
+ private void buildHeader() {
+ final Header header = new Header(this.shell, SWT.NONE);
+ final GridData gd = new GridData(GridData.FILL, GridData.BEGINNING, true, false);
+ gd.heightHint = 80;
+ header.setLayoutData(gd);
+ header.setTitle(ResourceManager.getLabel(ResourceManager.DID_YOU_KNOW));
+ if (this.image == null) {
+ final Image img = SWTGraphicUtil.createImage("images/light2.png");
+ header.setImage(img);
+ this.shell.addListener(SWT.Dispose, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ img.dispose();
+
+ }
+ });
+ } else {
+ header.setImage(this.image);
+ }
+ }
+
+ /**
+ * Build the left column
+ */
+ private void buildLeftColumn() {
+ final Composite composite = new Composite(this.shell, SWT.NONE);
+ int numberOfRows = 1;
+ if (this.style == TipStyle.TWO_COLUMNS_LARGE) {
+ numberOfRows = this.displayShowOnStartup ? 5 : 4;
+ }
+
+ final GridData gd = new GridData(GridData.FILL, GridData.BEGINNING, false, true, 1, numberOfRows);
+ composite.setLayoutData(gd);
+ final FillLayout compositeLayout = new FillLayout();
+ compositeLayout.marginWidth = 2;
+ composite.setLayout(compositeLayout);
+ final Label label = new Label(composite, SWT.NONE);
+ if (this.image == null) {
+ final Image img = SWTGraphicUtil.createImage("images/light1.png");
+ label.setImage(img);
+ this.shell.addListener(SWT.Dispose, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ img.dispose();
+ }
+ });
+ } else {
+ label.setImage(this.image);
+ }
+ }
+
+ /**
+ * Build the tip area
+ */
+ private void buildTip() {
+ if (this.style == TipStyle.TWO_COLUMNS) {
+ final Group group = new Group(this.shell, SWT.NONE);
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, true);
+ gd.widthHint = 300;
+ gd.heightHint = 120;
+ group.setLayoutData(gd);
+ group.setText(ResourceManager.getLabel(ResourceManager.DID_YOU_KNOW));
+ final FillLayout fillLayout = new FillLayout();
+ fillLayout.marginWidth = 15;
+ group.setLayout(fillLayout);
+
+ this.tipArea = new Browser(group, SWT.BORDER);
+ } else if (this.style == TipStyle.TWO_COLUMNS_LARGE) {
+ final Label title = new Label(this.shell, SWT.NONE);
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, false);
+ gd.verticalIndent = 15;
+ title.setLayoutData(gd);
+ final Font tempFont = SWTGraphicUtil.buildFontFrom(title, SWT.BOLD, 16);
+ title.setText(ResourceManager.getLabel(ResourceManager.TIP_OF_THE_DAY));
+ title.setFont(tempFont);
+ this.shell.addListener(SWT.Dispose, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ tempFont.dispose();
+ }
+ });
+ final Label separator = new Label(this.shell, SWT.SEPARATOR | SWT.HORIZONTAL);
+ separator.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
+
+ this.tipArea = new Browser(this.shell, SWT.BORDER);
+ final GridData gdTipArea = new GridData(GridData.FILL, GridData.FILL, true, true);
+ gdTipArea.heightHint = 120;
+ this.tipArea.setLayoutData(gdTipArea);
+
+ } else {
+ this.tipArea = new Browser(this.shell, SWT.BORDER);
+ final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, true);
+ gd.heightHint = 120;
+ this.tipArea.setLayoutData(gd);
+ }
+ fillTipArea();
+
+ }
+
+ /**
+ * Fill the tip area with the selected tip
+ */
+ private void fillTipArea() {
+ this.tipArea.setText("<html><body bgcolor=\"#ffffff\" text=\"#000000\"><p style=\"font-family:" + this.fontName + ";font-size=12px\">" //
+ + this.tips.get(this.index) + "</p></body></html>");
+ }
+
+ /**
+ * Build the button (checkbox, previous tip, next tip, close)
+ */
+ private void buildButtons() {
+ final Composite composite = new Composite(this.shell, SWT.NONE);
+ int numberOfColumns;
+ if (this.style == TipStyle.HEADER) {
+ numberOfColumns = 1;
+ } else if (this.style == TipStyle.TWO_COLUMNS) {
+ numberOfColumns = 2;
+ } else {
+ numberOfColumns = 1;
+ }
+
+ final GridData gd = new GridData(GridData.FILL, GridData.BEGINNING, false, false, numberOfColumns, 1);
+ composite.setLayoutData(gd);
+ final GridLayout gridLayout = new GridLayout();
+ gridLayout.marginWidth = 2;
+ if (this.style == TipStyle.TWO_COLUMNS_LARGE) {
+ composite.setLayout(new GridLayout(3, false));
+ } else {
+ composite.setLayout(new GridLayout(this.displayShowOnStartup ? 4 : 3, false));
+ }
+
+ final GridData gridShowOnStartup, gridPrevious, gridNext, gridClose;
+ if (this.style == TipStyle.TWO_COLUMNS_LARGE) {
+ gridShowOnStartup = new GridData(GridData.BEGINNING, GridData.BEGINNING, true, false, 3, 1);
+
+ gridPrevious = new GridData(GridData.END, GridData.CENTER, true, false);
+ gridPrevious.widthHint = 120;
+
+ gridNext = new GridData(GridData.CENTER, GridData.CENTER, false, false);
+ gridNext.widthHint = 120;
+
+ gridClose = new GridData(GridData.BEGINNING, GridData.CENTER, true, false);
+ gridClose.widthHint = 120;
+
+ } else {
+ gridShowOnStartup = new GridData(GridData.BEGINNING, GridData.CENTER, true, false);
+
+ gridPrevious = new GridData(GridData.END, GridData.CENTER, this.showOnStartup ? false : true, false);
+ gridPrevious.widthHint = 120;
+
+ gridNext = new GridData(GridData.FILL, GridData.CENTER, false, false);
+ gridNext.widthHint = 120;
+
+ gridClose = new GridData(GridData.FILL, GridData.CENTER, false, false);
+ gridClose.widthHint = 120;
+ }
+
+ if (this.displayShowOnStartup) {
+ buildShowOnStartup(composite, gridShowOnStartup);
+ }
+
+ buildPreviousButton(composite, gridPrevious);
+ buildNextButton(composite, gridNext);
+ buildCloseButton(composite, gridClose);
+
+ }
+
+ /**
+ * Build the "show on startup" checkbox
+ *
+ * @param composite parent composite
+ * @param gridData associated grid data
+ */
+ private void buildShowOnStartup(final Composite composite, final GridData gridData) {
+ final Button checkBox = new Button(composite, SWT.CHECK);
+ checkBox.setLayoutData(gridData);
+ checkBox.setText(ResourceManager.getLabel(ResourceManager.SHOW_TIP_AT_STARTUP));
+ checkBox.setSelection(this.showOnStartup);
+ checkBox.addListener(SWT.Selection, new Listener() {
+
+ @Override
+ public void handleEvent(final Event event) {
+ TipOfTheDay.this.showOnStartup = checkBox.getSelection();
+ }
+ });
+
+ }
+
+ /**
+ * Build the "previous tip" button
+ *
+ * @param composite parent composite
+ * @param gridData associated grid data
+ */
+ private void buildPreviousButton(final Composite composite, final GridData gridData) {
+ final Button previous = new Button(composite, SWT.PUSH);
+ previous.setText(ResourceManager.getLabel(ResourceManager.PREVIOUS_TIP));
+ previous.setLayoutData(gridData);
+ previous.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ if (TipOfTheDay.this.index == 0) {
+ setIndex(TipOfTheDay.this.tips.size() - 1);
+ } else {
+ setIndex(TipOfTheDay.this.index - 1);
+ }
+ }
+
+ });
+
+ }
+
+ /**
+ * Build the "next tip" button
+ *
+ * @param composite parent composite
+ * @param gridData associated grid data
+ */
+ private void buildNextButton(final Composite composite, final GridData gridData) {
+ final Button next = new Button(composite, SWT.PUSH);
+ next.setText(ResourceManager.getLabel(ResourceManager.NEXT_TIP));
+
+ next.setLayoutData(gridData);
+ next.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ if (TipOfTheDay.this.index == TipOfTheDay.this.tips.size() - 1) {
+ setIndex(0);
+ } else {
+ setIndex(TipOfTheDay.this.index + 1);
+ }
+ }
+
+ });
+ }
+
+ /**
+ * Build the "close" button
+ *
+ * @param composite parent composite
+ * @param gridData associated grid data
+ */
+ private void buildCloseButton(final Composite composite, final GridData gridData) {
+ this.close = new Button(composite, SWT.PUSH);
+ this.close.setText(ResourceManager.getLabel(ResourceManager.CLOSE));
+
+ this.close.setLayoutData(gridData);
+ this.close.addSelectionListener(new SelectionAdapter() {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ TipOfTheDay.this.shell.dispose();
+ }
+
+ });
+
+ }
+
+ /**
+ * Open the shell
+ */
+ private void openShell() {
+ this.shell.setDefaultButton(this.close);
+ this.shell.pack();
+ this.shell.open();
+ SWTGraphicUtil.centerShell(this.shell);
+
+ while (!this.shell.isDisposed()) {
+ if (!this.shell.getDisplay().readAndDispatch()) {
+ this.shell.getDisplay().sleep();
+ }
+ }
+
+ }
+
+ /**
+ * Add a tip
+ *
+ * @param tip tip to add
+ * @return the current object
+ */
+ public TipOfTheDay addTip(final String tip) {
+ this.tips.add(tip);
+ return this;
+ }
+
+ /**
+ * @return the image
+ */
+ public Image getImage() {
+ return this.image;
+ }
+
+ /**
+ * @return the index of the current tip
+ */
+ public int getIndex() {
+ return this.index;
+ }
+
+ /**
+ * @return the style of the window
+ */
+ public TipStyle getStyle() {
+ return this.style;
+ }
+
+ /**
+ * @return all the the tips
+ */
+ public List<String> getTips() {
+ return this.tips;
+ }
+
+ /**
+ * @return if <code>true</code>, the "Show On Startup" checkbox is displayed
+ */
+ public boolean isDisplayShowOnStartup() {
+ return this.displayShowOnStartup;
+ }
+
+ /**
+ * @return the value of the checkbox "Show On Startup"
+ */
+ public boolean isShowOnStartup() {
+ return this.showOnStartup;
+ }
+
+ /**
+ * @param if <code>true</code>, the checkbox "Show on startup" is displayed
+ */
+ public void setDisplayShowOnStartup(final boolean displayShowOnStartup) {
+ this.displayShowOnStartup = displayShowOnStartup;
+ }
+
+ /**
+ * @param index the index of the selected tip. By default, the tip is chosen
+ * randomly
+ */
+ public void setIndex(final int index) {
+ if (index < 0 || index >= this.tips.size() || this.tips.get(index) == null) {
+ throw new IllegalArgumentException("Index should be between 0 and " + (this.tips.size() - 1) + " (entered value:" + index + ")");
+ }
+
+ this.index = index;
+ if (this.tipArea != null && !this.tipArea.isDisposed()) {
+ fillTipArea();
+ }
+ }
+
+ /**
+ * @param image the image to set
+ */
+ public void setImage(final Image image) {
+ this.image = image;
+ }
+
+ /**
+ * @param the value of the checkbox "Show on startup"
+ */
+ public void setShowOnStartup(final boolean showOnStartup) {
+ this.showOnStartup = showOnStartup;
+ }
+
+ /**
+ * @param style the style of the window
+ */
+ public void setStyle(final TipStyle style) {
+ this.style = style;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/titledSeparator/TitledSeparator.java b/org.tizen.common.externals/src/org/mihalis/opal/titledSeparator/TitledSeparator.java
new file mode 100644
index 000000000..12f708b7f
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/titledSeparator/TitledSeparator.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.titledSeparator;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.mihalis.opal.utils.SWTGraphicUtil;
+
+/**
+ * Instances of this class provide a separator with a title and/or an image.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * </p>
+ */
+public class TitledSeparator extends Composite {
+
+ private int alignment;
+ private Image image;
+ private String text;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ */
+ public TitledSeparator(final Composite parent, final int style) {
+ super(parent, style);
+ this.alignment = SWT.LEFT;
+
+ final Color originalColor = new Color(getDisplay(), 0, 88, 150);
+ setForeground(originalColor);
+
+ final Font originalFont;
+ final FontData[] fontData = getFont().getFontData();
+ if (fontData != null && fontData.length > 0) {
+ final FontData fd = fontData[0];
+ fd.setStyle(SWT.BOLD);
+ originalFont = new Font(getDisplay(), fd);
+ setFont(originalFont);
+ } else {
+ originalFont = null;
+ }
+
+ this.addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ redrawComposite();
+ }
+ });
+
+ this.addListener(SWT.Dispose, new Listener() {
+ @Override
+ public void handleEvent(final Event event) {
+ SWTGraphicUtil.dispose(originalColor);
+ SWTGraphicUtil.dispose(originalFont);
+ }
+ });
+
+ }
+
+ /**
+ * Redraw the composite
+ */
+ private void redrawComposite() {
+ // Dispose previous content
+ for (final Control c : this.getChildren()) {
+ c.dispose();
+ }
+
+ int numberOfColumns = 1;
+
+ if (this.text != null) {
+ numberOfColumns++;
+ }
+ if (this.image != null) {
+ numberOfColumns++;
+ }
+
+ if (this.alignment == SWT.CENTER) {
+ numberOfColumns++;
+ }
+
+ super.setLayout(new GridLayout(numberOfColumns, false));
+ createContent();
+ }
+
+ /**
+ * Create the content
+ */
+ private void createContent() {
+ switch (this.alignment) {
+ case SWT.CENTER:
+ createSeparator();
+ createTitle();
+ break;
+ case SWT.LEFT:
+ createTitle();
+ createSeparator();
+ break;
+ default:
+ createSeparator();
+ createTitle();
+ break;
+ }
+
+ }
+
+ /**
+ * Create a separator
+ */
+ private void createSeparator() {
+ final Label separator = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL);
+ separator.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false));
+ separator.setBackground(getBackground());
+ }
+
+ /**
+ * Create the title
+ */
+ private void createTitle() {
+
+ if (this.image != null) {
+ final Label imageLabel = createLabel();
+ imageLabel.setImage(this.image);
+ }
+
+ if (this.text != null && !this.text.trim().equals("")) {
+ final Label textLabel = createLabel();
+ textLabel.setText(this.text);
+
+ }
+
+ }
+
+ /**
+ * @return a SWT label
+ */
+ private Label createLabel() {
+ final Label label = new Label(this, SWT.NONE);
+ label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false));
+ label.setFont(getFont());
+ label.setForeground(getForeground());
+ label.setBackground(getBackground());
+ return label;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#setLayout(org.eclipse.swt.widgets.Layout)
+ */
+ @Override
+ public void setLayout(final Layout layout) {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ /**
+ * Returns a value which describes the position of the text or image in the
+ * receiver. The value will be one of <code>LEFT</code>, <code>RIGHT</code>
+ * or <code>CENTER</code>.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+
+ public int getAlignment() {
+ checkWidget();
+ return this.alignment;
+ }
+
+ /**
+ * Returns the receiver's image if it has one, or null if it does not.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public Image getImage() {
+ checkWidget();
+ return this.image;
+ }
+
+ /**
+ * Returns the receiver's text.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public String getText() {
+ checkWidget();
+ return this.text;
+ }
+
+ /**
+ * Controls how text will be displayed in the receiver. The argument should
+ * be one of <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>.
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setAlignment(final int alignment) {
+ checkWidget();
+ this.alignment = alignment;
+ }
+
+ /**
+ * Sets the receiver's image to the argument, which may be null indicating
+ * that no image should be displayed.
+ *
+ * @param image the image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been
+ * disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setImage(final Image image) {
+ checkWidget();
+ this.image = image;
+ }
+
+ /**
+ * Sets the receiver's text.
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setText(final String text) {
+ checkWidget();
+ this.text = text;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/DownUpAppearTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/DownUpAppearTransition.java
new file mode 100644
index 000000000..56f826540
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/DownUpAppearTransition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * In this transition, the second control is behind, the first control is
+ * sliding from down to up
+ */
+public class DownUpAppearTransition extends VerticalTransition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.VerticalTransition#getCoeff()
+ */
+ @Override
+ protected int getCoeff() {
+ return -1;
+ }
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.VerticalTransition#secondIsBehind()
+ */
+ @Override
+ protected boolean secondIsBehind() {
+ return false;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/DownUpTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/DownUpTransition.java
new file mode 100644
index 000000000..2844d8210
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/DownUpTransition.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * In this transition, both control are sliding (vertical movement, down to up)
+ */
+public class DownUpTransition extends VerticalTransition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.VerticalTransition#getCoeff()
+ */
+ @Override
+ protected int getCoeff() {
+ return -1;
+ }
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.VerticalTransition#secondIsBehind()
+ */
+ @Override
+ protected boolean secondIsBehind() {
+ return true;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/HorizontalTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/HorizontalTransition.java
new file mode 100644
index 000000000..a68403d6f
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/HorizontalTransition.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Instances of this class are horizontal transitions (right>left,
+ * left>right...)
+ */
+public abstract class HorizontalTransition implements Transition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.Transition#performTransition(org.eclipse.swt.widgets.Control,
+ * org.eclipse.swt.widgets.Control)
+ */
+ @Override
+ public void performTransition(final Control first, final Control second) {
+ if (first.isDisposed() || second.isDisposed()) {
+ return;
+ }
+
+ final int[] currentPosition = new int[1];
+ currentPosition[0] = 0;
+ final int maxValue = first.getParent().getClientArea().width;
+
+ first.setBounds(0, 0, first.getBounds().width, first.getBounds().height);
+ second.setBounds(0, -1 * second.getBounds().width, second.getBounds().width, second.getBounds().height);
+
+ first.moveAbove(second);
+ second.setVisible(true);
+
+ if (first.isDisposed() || first.getDisplay().isDisposed()) {
+ return;
+ }
+ first.getDisplay().timerExec(0, new Runnable() {
+
+ @Override
+ public void run() {
+
+ if (first.isDisposed() || second.isDisposed()) {
+ return;
+ }
+
+ currentPosition[0] = currentPosition[0] + 10;
+ if (currentPosition[0] > maxValue) {
+ first.setVisible(false);
+ second.setVisible(true);
+ second.setBounds(0, 0, first.getBounds().width, first.getBounds().height);
+ return;
+ }
+
+ first.setBounds(getCoeff() * currentPosition[0], 0, first.getBounds().width, first.getBounds().height);
+
+ if (secondIsBehind()) {
+ second.setBounds(-1 * getCoeff() * (maxValue - currentPosition[0]), 0, second.getBounds().width, second.getBounds().height);
+ }
+
+ if (!first.isDisposed() && !first.getDisplay().isDisposed()) {
+ first.getDisplay().timerExec(10, this);
+ }
+ }
+
+ });
+
+ }
+
+ /**
+ * @return the multiplicator coefficient
+ */
+ protected abstract int getCoeff();
+
+ /**
+ * @return <code>true</code> if the second composite is behind the first
+ * one, <code>false</code> otherwise
+ */
+ protected abstract boolean secondIsBehind();
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/LeftRightAppearTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/LeftRightAppearTransition.java
new file mode 100644
index 000000000..55239df39
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/LeftRightAppearTransition.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * In this transition, the second control is behind, the first control is
+ * sliding from left to right
+ */
+public class LeftRightAppearTransition extends HorizontalTransition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.HorizontalTransition#getCoeff()
+ */
+ @Override
+ protected int getCoeff() {
+ return 1;
+ }
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.HorizontalTransition#secondIsBehind()
+ */
+ @Override
+ protected boolean secondIsBehind() {
+ return false;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/LeftRightTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/LeftRightTransition.java
new file mode 100644
index 000000000..a7df75243
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/LeftRightTransition.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * In this transition, both control are sliding (vertical movement, left to
+ * right)
+ */
+public class LeftRightTransition extends HorizontalTransition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.HorizontalTransition#getCoeff()
+ */
+ @Override
+ protected int getCoeff() {
+ return 1;
+ }
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.HorizontalTransition#secondIsBehind()
+ */
+ @Override
+ protected boolean secondIsBehind() {
+ return true;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/NoTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/NoTransition.java
new file mode 100644
index 000000000..cbdee8eb4
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/NoTransition.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * This transition is simple, because there is no effect :)
+ *
+ */
+class NoTransition implements Transition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.Transition#performTransition(org.eclipse.swt.widgets.Control,
+ * org.eclipse.swt.widgets.Control)
+ */
+ @Override
+ public void performTransition(final Control first, final Control second) {
+ first.setVisible(false);
+ second.setVisible(true);
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/RightLeftAppearTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/RightLeftAppearTransition.java
new file mode 100644
index 000000000..94a38bb6f
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/RightLeftAppearTransition.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * In this transition, the second control is behind, the first control is
+ * sliding from right to left
+ */
+public class RightLeftAppearTransition extends HorizontalTransition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.HorizontalTransition#getCoeff()
+ */
+ @Override
+ protected int getCoeff() {
+ return -1;
+ }
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.HorizontalTransition#secondIsBehind()
+ */
+ @Override
+ protected boolean secondIsBehind() {
+ return false;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/RightLeftTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/RightLeftTransition.java
new file mode 100644
index 000000000..cf3c80341
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/RightLeftTransition.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * In this transition, both control are sliding (vertical movement, right to
+ * left)
+ */
+public class RightLeftTransition extends HorizontalTransition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.HorizontalTransition#getCoeff()
+ */
+ @Override
+ protected int getCoeff() {
+ return -1;
+ }
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.HorizontalTransition#secondIsBehind()
+ */
+ @Override
+ protected boolean secondIsBehind() {
+ return true;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TRANSITIONS.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TRANSITIONS.java
new file mode 100644
index 000000000..0a7785621
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TRANSITIONS.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * This enumeration is a list of transitions
+ */
+public enum TRANSITIONS {
+ LEFT_TO_RIGHT, LEFT_TO_RIGHT_AND_APPEAR, RIGHT_TO_LEFT, RIGHT_TO_LEFT_AND_APPEAR, UP_TO_DOWN, UP_TO_DOWN_AND_APPEAR, DOWN_TO_UP, DOWN_TO_UP_AND_APPEAR, NONE
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/Transition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/Transition.java
new file mode 100644
index 000000000..2921698ec
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/Transition.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * This interface describes a transition
+ */
+interface Transition {
+
+ /**
+ * Performs a transition between 2 controls of a TransitionComposite
+ *
+ * @param first first control
+ * @param second second control
+ */
+ void performTransition(Control first, Control second);
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TransitionComposite.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TransitionComposite.java
new file mode 100644
index 000000000..93ac865b0
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TransitionComposite.java
@@ -0,0 +1,274 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Instances of this class provide a multi-part composite. You can perform
+ * transitions when you move from one part to another
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * </p>
+ */
+public class TransitionComposite extends Composite {
+
+ private final List<Control> controls;
+ private int selection = 0;
+ private TRANSITIONS transition = TRANSITIONS.NONE;
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in class
+ * <code>SWT</code> which is applicable to instances of this class, or must
+ * be built by <em>bitwise OR</em>'ing together (that is, using the
+ * <code>int</code> "|" operator) two or more of those <code>SWT</code>
+ * style constants. The class description lists the style constants that are
+ * applicable to the class. Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the parent</li>
+ * </ul>
+ *
+ */
+ public TransitionComposite(final Composite parent, final int style) {
+ super(parent, style);
+ this.controls = new ArrayList<Control>();
+
+ addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(final Event e) {
+ TransitionComposite.this.controls.get(TransitionComposite.this.selection).setBounds(getClientArea());
+ }
+ });
+ }
+
+ /**
+ * Add a control to this composite
+ *
+ * @param control control to add
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void addControl(final Control control) {
+ checkWidget();
+ this.controls.add(control);
+ if (this.controls.size() == 1) {
+ control.setVisible(true);
+ } else {
+ control.setVisible(false);
+ }
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
+ */
+ @Override
+ public Point computeSize(final int wHint, final int hHint, final boolean changed) {
+ int width = 0, height = 0;
+ for (final Control control : this.controls) {
+ final Point point = control.computeSize(wHint, hHint, changed);
+ width = Math.max(width, point.x);
+ height = Math.max(height, point.y);
+ }
+ return new Point(Math.max(width, wHint), Math.max(height, hHint));
+ }
+
+ /**
+ * @return the current transition
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public TRANSITIONS getTransition() {
+ checkWidget();
+ return this.transition;
+ }
+
+ /**
+ * Move selection to the first control
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void moveToFirst() {
+ checkWidget();
+ changeSelectionTo(0);
+ }
+
+ /**
+ * Move selection to the last control
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void moveToLast() {
+ checkWidget();
+ changeSelectionTo(this.controls.size() - 1);
+ }
+
+ /**
+ * Move selection to the next control
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void moveToNext() {
+ checkWidget();
+ final int index = this.selection + 1;
+ if (index == this.controls.size()) {
+ return;
+ }
+ changeSelectionTo(index);
+ }
+
+ /**
+ * Move selection to the previous control
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void moveToPrevious() {
+ checkWidget();
+ final int index = this.selection - 1;
+ if (index < 0) {
+ return;
+ }
+ changeSelectionTo(index);
+ }
+
+ /**
+ * Move selection to a given index
+ *
+ * @param index index of the new selection
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelection(final int index) {
+ checkWidget();
+ if (index < 0 || index > this.controls.size() - 1) {
+ return;
+ }
+ changeSelectionTo(index);
+ }
+
+ /**
+ * Change current selection
+ *
+ * @param index index of the new selection
+ */
+ private void changeSelectionTo(final int index) {
+
+ final Transition t = TransitionFactory.getTransitionFor(this.transition);
+ t.performTransition(this.controls.get(this.selection), this.controls.get(index));
+
+ this.selection = index;
+ this.controls.get(this.selection).setBounds(getClientArea());
+ }
+
+ /**
+ * Move selection to a given control
+ *
+ * @param control control newly selected
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+ public void setSelection(final Control control) {
+ checkWidget();
+ for (int i = 0; i < this.controls.size(); i++) {
+ if (this.controls.get(i) != null && this.controls.get(i).equals(control)) {
+ changeSelectionTo(i);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Move selection to the first control
+ *
+ * @param transition new transition
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been
+ * disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
+ * thread that created the receiver</li>
+ * </ul>
+ */
+
+ public void setTransition(final TRANSITIONS transition) {
+ checkWidget();
+ this.transition = transition;
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TransitionFactory.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TransitionFactory.java
new file mode 100755
index 000000000..ef73b8b49
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/TransitionFactory.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * This class is a transition factory
+ */
+public class TransitionFactory {
+
+ /**
+ * @param transition transition to get
+ * @return a transition corresponding to the <code>transition</code>
+ * parameter
+ */
+ public static Transition getTransitionFor(final TRANSITIONS transition) {
+ switch (transition) {
+ case DOWN_TO_UP:
+ return new DownUpTransition();
+ case DOWN_TO_UP_AND_APPEAR:
+ return new DownUpAppearTransition();
+ case LEFT_TO_RIGHT:
+ return new LeftRightTransition();
+ case LEFT_TO_RIGHT_AND_APPEAR:
+ return new LeftRightAppearTransition();
+ case NONE:
+ return new NoTransition();
+ case RIGHT_TO_LEFT:
+ return new RightLeftTransition();
+ case RIGHT_TO_LEFT_AND_APPEAR:
+ return new RightLeftAppearTransition();
+ case UP_TO_DOWN:
+ return new UpDownTransition();
+ case UP_TO_DOWN_AND_APPEAR:
+ return new UpDownAppearTransition();
+ default:
+ return null;
+ }
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/UpDownAppearTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/UpDownAppearTransition.java
new file mode 100644
index 000000000..b849657d3
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/UpDownAppearTransition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * In this transition, the second control is behind, the first control is
+ * sliding from up to down
+ */
+public class UpDownAppearTransition extends VerticalTransition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.VerticalTransition#getCoeff()
+ */
+ @Override
+ protected int getCoeff() {
+ return 1;
+ }
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.VerticalTransition#secondIsBehind()
+ */
+ @Override
+ protected boolean secondIsBehind() {
+ return false;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/UpDownTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/UpDownTransition.java
new file mode 100644
index 000000000..e352a59bf
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/UpDownTransition.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+/**
+ * In this transition, both control are sliding (vertical movement, up to down)
+ */
+public class UpDownTransition extends VerticalTransition {
+
+ @Override
+ protected int getCoeff() {
+ return 1;
+ }
+
+ @Override
+ protected boolean secondIsBehind() {
+ return true;
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/VerticalTransition.java b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/VerticalTransition.java
new file mode 100644
index 000000000..ffe09424c
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/transitionComposite/VerticalTransition.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.transitionComposite;
+
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Instances of this class are vertical transitions (down>up, up>down...)
+ */
+abstract class VerticalTransition implements Transition {
+
+ /**
+ * @see org.mihalis.opal.transitionComposite.Transition#performTransition(org.eclipse.swt.widgets.Control,
+ * org.eclipse.swt.widgets.Control)
+ */
+ @Override
+ public void performTransition(final Control first, final Control second) {
+ if (first.isDisposed() || second.isDisposed()) {
+ return;
+ }
+
+ final int[] currentPosition = new int[1];
+ currentPosition[0] = 0;
+ final int maxValue = first.getParent().getClientArea().height;
+
+ first.setBounds(0, 0, first.getBounds().width, first.getBounds().height);
+ second.setBounds(0, -1 * second.getBounds().width, second.getBounds().width, second.getBounds().height);
+
+ first.moveAbove(second);
+ second.setVisible(true);
+
+ if (first.isDisposed() || first.getDisplay().isDisposed()) {
+ return;
+ }
+
+ first.getDisplay().timerExec(0, new Runnable() {
+
+ @Override
+ public void run() {
+
+ if (first.isDisposed() || second.isDisposed()) {
+ return;
+ }
+
+ currentPosition[0] = currentPosition[0] + 10;
+ if (currentPosition[0] > maxValue) {
+ first.setVisible(false);
+ second.setBounds(0, 0, first.getBounds().width, first.getBounds().height);
+
+ return;
+ }
+
+ first.setBounds(0, getCoeff() * currentPosition[0], first.getBounds().width, first.getBounds().height);
+ if (secondIsBehind()) {
+ second.setBounds(0, -1 * getCoeff() * (maxValue - currentPosition[0]), second.getBounds().width, second.getBounds().height);
+ }
+ if (!first.isDisposed() && !first.getDisplay().isDisposed()) {
+ first.getDisplay().timerExec(15, this);
+ }
+ }
+
+ });
+
+ }
+
+ /**
+ * @return the multiplicator coefficient
+ */
+ protected abstract int getCoeff();
+
+ /**
+ * @return <code>true</code> if the second composite is behind the first
+ * one, <code>false</code> otherwise
+ */
+ protected abstract boolean secondIsBehind();
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/utils/FileToolbox.java b/org.tizen.common.externals/src/org/mihalis/opal/utils/FileToolbox.java
new file mode 100644
index 000000000..7201ffc28
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/utils/FileToolbox.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+package org.mihalis.opal.utils;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class FileToolbox {
+
+ /**
+ * Loads a file into a stream
+ *
+ * @param fileName file name
+ * @return a stream composed of this file
+ */
+ public static InputStream getInputStream(final String fileName) {
+ if (fileName.startsWith("jar:")) {
+ URL url;
+ try {
+ url = new URL(fileName);
+ return url.openStream();
+ } catch (final MalformedURLException e) {
+ throw new RuntimeException(e);
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ try {
+ return new FileInputStream(fileName);
+ } catch (final FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/utils/HTMLStyledTextParser.java b/org.tizen.common.externals/src/org/mihalis/opal/utils/HTMLStyledTextParser.java
new file mode 100644
index 000000000..d92804794
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/utils/HTMLStyledTextParser.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.utils;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.html.HTML.Tag;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.HTMLEditorKit.ParserCallback;
+import javax.swing.text.html.parser.ParserDelegator;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+
+/**
+ * Instances of this class are used to convert HTML content of a styled text
+ * into style ranges
+ */
+public class HTMLStyledTextParser extends ParserCallback {
+
+ private final List<StyleRange> listOfStyles;
+ private final StyledText styledText;
+ private int position;
+ private final StringBuilder outputString;
+
+ private StyleRange currentStyleRange;
+ private TagType currentTagType;
+ private int currentPosition;
+
+ private enum TagType {
+ B, U, I
+ };
+
+ /**
+ * Constructor
+ *
+ * @param styledText styled text to analyze
+ */
+ HTMLStyledTextParser(final StyledText styledText) {
+ super();
+ this.styledText = styledText;
+ this.position = -1;
+ this.listOfStyles = new ArrayList<StyleRange>();
+ this.currentStyleRange = null;
+ this.currentTagType = null;
+ this.currentPosition = 0;
+ this.outputString = new StringBuilder();
+ }
+
+ /**
+ * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleStartTag(javax.swing.text.html.HTML.Tag,
+ * javax.swing.text.MutableAttributeSet, int)
+ */
+ @Override
+ public void handleStartTag(final Tag t, final MutableAttributeSet a, final int pos) {
+ if (t == Tag.B) {
+ this.currentStyleRange = new StyleRange();
+ this.currentTagType = TagType.B;
+ this.currentPosition = this.position;
+ }
+ if (t == Tag.I) {
+ this.currentStyleRange = new StyleRange();
+ this.currentTagType = TagType.I;
+ this.currentPosition = this.position;
+ }
+ if (t == Tag.U) {
+ this.currentStyleRange = new StyleRange();
+ this.currentTagType = TagType.U;
+ this.currentPosition = this.position;
+ }
+
+ }
+
+ /**
+ * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleEndTag(javax.swing.text.html.HTML.Tag,
+ * int)
+ */
+ @Override
+ public void handleEndTag(final Tag t, final int pos) {
+
+ if (t != Tag.B && t != Tag.I && t != Tag.U) {
+ return;
+ }
+
+ int style;
+ boolean underline;
+ if (t == Tag.B) {
+ if (TagType.B != this.currentTagType) {
+ throw new RuntimeException("Error parsing [" + this.styledText.getText() + "] : bad syntax");
+ }
+ style = SWT.BOLD;
+ underline = false;
+ } else if (t == Tag.I) {
+ if (TagType.I != this.currentTagType) {
+ throw new RuntimeException("Error parsing [" + this.styledText.getText() + "] : bad syntax");
+ }
+ style = SWT.ITALIC;
+ underline = false;
+ } else if (t == Tag.U) {
+ if (TagType.U != this.currentTagType) {
+ throw new RuntimeException("Error parsing [" + this.styledText.getText() + "] : bad syntax");
+ }
+ style = SWT.NORMAL;
+ underline = true;
+ } else {
+ style = SWT.NORMAL;
+ underline = false;
+ }
+
+ this.currentStyleRange.start = this.currentPosition;
+ this.currentStyleRange.length = this.position - this.currentPosition + 1;
+ this.currentStyleRange.fontStyle = style;
+ this.currentStyleRange.underline = underline;
+ this.listOfStyles.add(this.currentStyleRange);
+
+ this.currentStyleRange = null;
+ this.currentTagType = null;
+ }
+
+ /**
+ * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleError(java.lang.String,
+ * int)
+ */
+ @Override
+ public void handleError(final String errorMsg, final int pos) {
+ throw new RuntimeException("Parsing error: " + errorMsg + " at " + pos);
+ }
+
+ /**
+ * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleText(char[],
+ * int)
+ */
+ @Override
+ public void handleText(final char[] data, final int pos) {
+ this.outputString.append(data);
+ this.position += data.length;
+ }
+
+ /**
+ * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleSimpleTag(javax.swing.text.html.HTML.Tag,
+ * javax.swing.text.MutableAttributeSet, int)
+ */
+ @Override
+ public void handleSimpleTag(final Tag t, final MutableAttributeSet a, final int pos) {
+ if (t == Tag.BR) {
+ this.outputString.append("\n");
+ this.position += t.toString().length();
+
+ }
+ }
+
+ /**
+ * Parse the content, build the list of style ranges and apply them to the
+ * styled text widget
+ *
+ * @throws IOException
+ */
+ public void parse() throws IOException {
+ final HTMLEditorKit.Parser parser = new ParserDelegator();
+ parser.parse(new StringReader(this.styledText.getText()), this, true);
+ this.styledText.setText(this.outputString.toString());
+ this.styledText.setStyleRanges(this.listOfStyles.toArray(new StyleRange[this.listOfStyles.size()]));
+
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/utils/ResourceManager.java b/org.tizen.common.externals/src/org/mihalis/opal/utils/ResourceManager.java
new file mode 100644
index 000000000..da60f64a5
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/utils/ResourceManager.java
@@ -0,0 +1,56 @@
+package org.mihalis.opal.utils;
+
+import java.util.ResourceBundle;
+
+public class ResourceManager {
+ private static final ResourceBundle RSC = ResourceBundle.getBundle("resources/opal");
+
+ public static final String OK = "Ok";
+ public static final String CANCEL = "Cancel";
+ public static final String CLOSE = "Close";
+ public static final String YES = "Yes";
+ public static final String NO = "No";
+
+ public static final String MEGABYTES = "megabytes";
+ public static final String PERFORM_GC = "performGC";
+
+ public static final String LOGIN = "login";
+ public static final String NAME = "name";
+ public static final String PASSWORD = "password";
+ public static final String REMEMBER_PASSWORD = "rememberPassword";
+ public static final String LOGIN_FAILED = "loginFailed";
+
+ public static final String INPUT = "Input";
+ public static final String APPLICATION_ERROR = "ApplicationError";
+ public static final String INFORMATION = "Information";
+ public static final String WARNING = "Warning";
+ public static final String CHOICE = "Choice";
+ public static final String EXCEPTION = "Exception";
+ public static final String SELECT = "Select";
+ public static final String FEWER_DETAILS = "FewerDetails";
+ public static final String MORE_DETAILS = "MoreDetails";
+
+ public static final String TIP_OF_THE_DAY = "tipOfTheDay";
+ public static final String DID_YOU_KNOW = "didYouKnow";
+ public static final String SHOW_TIP_AT_STARTUP = "showTipAtStartup";
+ public static final String PREVIOUS_TIP = "previousTip";
+ public static final String NEXT_TIP = "nextTip";
+
+ public static final String CHOOSE = "choose";
+ public static final String PREFERENCES = "preferences";
+ public static final String VALID_URL = "validURL";
+ public static final String CHOOSE_DIRECTORY = "chooseDirectory";
+ public static final String ITALIC = "italic";
+ public static final String BOLD = "bold";
+
+ /**
+ * Get a translated label
+ *
+ * @param key key to get
+ * @return the translated value of the key
+ */
+ public static String getLabel(final String key) {
+ return RSC.getString(key);
+ }
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/utils/SWTGraphicUtil.java b/org.tizen.common.externals/src/org/mihalis/opal/utils/SWTGraphicUtil.java
new file mode 100644
index 000000000..e28dd529b
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/utils/SWTGraphicUtil.java
@@ -0,0 +1,463 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.utils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.Transform;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Monitor;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * This class is a singleton that provides useful methods
+ */
+public class SWTGraphicUtil {
+
+ /**
+ * Constructor
+ */
+ private SWTGraphicUtil() {
+ }
+
+ /**
+ * Dispose safely any SWT resource when a control is disposed
+ *
+ * @param r the resource to dispose
+ */
+ public static void dispose(final Control control, final Resource r) {
+ control.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(final DisposeEvent e) {
+ dispose(r);
+ }
+ });
+ }
+
+ /**
+ * Dispose safely any SWT resource
+ *
+ * @param r the resource to dispose
+ */
+ public static void dispose(final Resource r) {
+ if (r != null && !r.isDisposed()) {
+ r.dispose();
+ }
+ }
+
+ /**
+ * Loads an image and create a SWT Image corresponding to this file
+ *
+ * @param fileName file name of the image
+ * @return an image
+ * @see org.eclipse.swt.graphics.Image
+ */
+ public static Image createImage(final String fileName) {
+ return new Image(Display.getCurrent(), SWTGraphicUtil.class.getClassLoader().getResourceAsStream(fileName));
+ }
+
+ /**
+ * Create a reflected image of a source Inspired by Daniel Spiewak
+ * (http://www.eclipsezone.com/eclipse/forums/t91013.html)
+ *
+ * @param source source to be reflected
+ * @return the source image with a reflection
+ */
+ public static Image createReflectedImage(final Image source) {
+ if (source == null) {
+ return null;
+ }
+
+ if (source.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ // Create a new image
+ final Rectangle sourceBounds = source.getBounds();
+ final Image newImage = new Image(source.getDevice(), new Rectangle(0, 0, sourceBounds.width, (int) (sourceBounds.height * 1.5)));
+ final GC gc = new GC(newImage);
+ gc.setAdvanced(true);
+
+ gc.drawImage(source, 0, 0);
+
+ // Add the reflection
+ final Transform t = new Transform(source.getDevice());
+ t.setElements(1, 0, 0, -.5f, 0, sourceBounds.height + sourceBounds.height / 2);
+ gc.setTransform(t);
+
+ gc.drawImage(source, 0, 0);
+
+ t.dispose();
+ gc.dispose();
+
+ // And add the alpha mask
+ final ImageData imgData = newImage.getImageData();
+ final int width = imgData.width;
+ final int height = imgData.height;
+ final byte[] alphaData = new byte[height * width];
+
+ final byte[] noAlpha = new byte[width];
+ for (int x = 0; x < width; x++) {
+ noAlpha[x] = (byte) 255;
+ }
+
+ for (int y = 0; y < height; y++) {
+ final byte[] alphaRow = new byte[width];
+ if (y < sourceBounds.height) {
+ System.arraycopy(noAlpha, 0, alphaData, y * width, width);
+ } else {
+ for (int x = 0; x < width; x++) {
+ alphaRow[x] = (byte) (255 - 255 * y / height);
+ }
+ System.arraycopy(alphaRow, 0, alphaData, y * width, width);
+ }
+
+ }
+ imgData.alphaData = alphaData;
+ return new Image(source.getDevice(), imgData);
+ }
+
+ /**
+ * Returns a new scaled image.
+ *
+ * @param source the image to be scaled
+ * @param newWidth new width of the image
+ * @param newHeight new height of the image
+ * @return a scaled image of the source
+ */
+ public static Image resize(final Image source, final int newWidth, final int newHeight) {
+
+ if (source == null) {
+ return null;
+ }
+
+ if (source.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ final Image scaledImage = new Image(source.getDevice(), newWidth, newHeight);
+ final GC gc = new GC(scaledImage);
+ gc.setAntialias(SWT.ON);
+ gc.setInterpolation(SWT.HIGH);
+ gc.drawImage(source, 0, 0, source.getBounds().width, source.getBounds().height, 0, 0, newWidth, newHeight);
+ gc.dispose();
+
+ return scaledImage;
+ }
+
+ /**
+ * Create a reflected and resized version of an image
+ *
+ * @param source source image to be scaled and reflected
+ * @param newWidth new width of the scaled image
+ * @param newHeight new height of the scaled image
+ * @return the resized and reflected image
+ */
+ public static Image createReflectedResizedImage(final Image source, final int newWidth, final int newHeight) {
+ if (source == null) {
+ return null;
+ }
+
+ if (source.isDisposed()) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ final Image newImage = new Image(source.getDevice(), newWidth, (int) (newHeight * 1.5));
+ final GC gc = new GC(newImage);
+ gc.setAntialias(SWT.ON);
+ gc.setInterpolation(SWT.HIGH);
+ gc.drawImage(source, 0, 0, source.getBounds().width, source.getBounds().height, 0, 0, newWidth, newHeight);
+
+ // Add the reflection
+ final Transform t = new Transform(source.getDevice());
+ t.setElements(1, 0, 0, -.5f, 0, (float) (newHeight * 1.5));
+ gc.setTransform(t);
+
+ gc.drawImage(source, 0, 0, source.getBounds().width, source.getBounds().height, 0, 0, newWidth, newHeight);
+
+ t.dispose();
+ gc.dispose();
+
+ // And add the alpha mask
+ final ImageData imgData = newImage.getImageData();
+ final int width = imgData.width;
+ final int height = imgData.height;
+ final byte[] alphaData = new byte[height * width];
+
+ final byte[] noAlpha = new byte[width];
+ for (int x = 0; x < width; x++) {
+ noAlpha[x] = (byte) 255;
+ }
+
+ for (int y = 0; y < height; y++) {
+ final byte[] alphaRow = new byte[width];
+ if (y < newHeight) {
+ System.arraycopy(noAlpha, 0, alphaData, y * width, width);
+ } else {
+ for (int x = 0; x < width; x++) {
+ alphaRow[x] = (byte) (255 - 255 * y / height);
+ }
+ System.arraycopy(alphaRow, 0, alphaData, y * width, width);
+ }
+
+ }
+ imgData.alphaData = alphaData;
+ return new Image(source.getDevice(), imgData);
+
+ }
+
+ /**
+ * Center a shell on the screen
+ *
+ * @param shell shell to center
+ */
+ public static void centerShell(final Shell shell) {
+ final Monitor primary = shell.getDisplay().getPrimaryMonitor();
+ final Rectangle bounds = primary.getBounds();
+ final Rectangle rect = shell.getBounds();
+ final int x = bounds.x + (bounds.width - rect.width) / 2;
+ final int y = bounds.y + (bounds.height - rect.height) / 2;
+ shell.setLocation(x, y);
+ }
+
+ /**
+ * Apply a very basic HTML formating to a text stored in a StyledText
+ * widget. Supported tags are <B>, <I> and <U>
+ *
+ * @param styledText styled text that contains an HTML text
+ */
+ public static void applyHTMLFormating(final StyledText styledText) {
+ try {
+ new HTMLStyledTextParser(styledText).parse();
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @param originalImageData The ImageData to be average blurred.
+ * Transparency information will be ignored.
+ * @param radius the number of radius pixels to consider when blurring
+ * image.
+ * @return A blurred copy of the image data, or null if an error occured.
+ * @author Nicholas Rajendram
+ * @see http://www.jasonwaltman.com/thesis/filter-blur.html
+ * @see http://www.blackpawn.com/texts/blur/default.html
+ */
+ public static ImageData blur(final ImageData originalImageData, int radius) {
+ /*
+ * This method will vertically blur all the pixels in a row at once.
+ * This blurring is performed incrementally to each row.
+ *
+ * In order to vertically blur any given pixel, maximally (radius * 2 +
+ * 1) pixels must be examined. Since each of these pixels exists in the
+ * same column, they span across a series of consecutive rows. These
+ * rows are horizontally blurred before being cached and used as input
+ * for the vertical blur. Blurring a pixel horizontally and then
+ * vertically is equivalent to blurring the pixel with both its
+ * horizontal and vertical neighbours at once.
+ *
+ * Pixels are blurred under the notion of a 'summing scope'. A certain
+ * scope of pixels in a column are summed then averaged to determine a
+ * target pixel's resulting RGB value. When the next lower target pixel
+ * is being calculated, the topmost pixel is removed from the summing
+ * scope (by subtracting its RGB) and a new pixel is added to the bottom
+ * of the scope (by adding its RGB). In this sense, the summing scope is
+ * moving downward.
+ */
+ if (radius < 1) {
+ return originalImageData;
+ }
+ // prepare new image data with 24-bit direct palette to hold blurred
+ // copy of image
+ final ImageData newImageData = new ImageData(originalImageData.width, originalImageData.height, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000));
+ if (radius >= newImageData.height || radius >= newImageData.width) {
+ radius = Math.min(newImageData.height, newImageData.width) - 1;
+ }
+ // initialize cache
+ final ArrayList<RGB[]> rowCache = new ArrayList<RGB[]>();
+ final int cacheSize = radius * 2 + 1 > newImageData.height ? newImageData.height : radius * 2 + 1; // number
+ // of
+ // rows
+ // of
+ // imageData
+ // we
+ // cache
+ int cacheStartIndex = 0; // which row of imageData the cache begins with
+ for (int row = 0; row < cacheSize; row++) {
+ // row data is horizontally blurred before caching
+ rowCache.add(rowCache.size(), blurRow(originalImageData, row, radius));
+ }
+ // sum red, green, and blue values separately for averaging
+ final RGB[] rowRGBSums = new RGB[newImageData.width];
+ final int[] rowRGBAverages = new int[newImageData.width];
+ int topSumBoundary = 0; // current top row of summed values scope
+ int targetRow = 0; // row with RGB averages to be determined
+ int bottomSumBoundary = 0; // current bottom row of summed values scope
+ int numRows = 0; // number of rows included in current summing scope
+ for (int i = 0; i < newImageData.width; i++) {
+ rowRGBSums[i] = new RGB(0, 0, 0);
+ }
+ while (targetRow < newImageData.height) {
+ if (bottomSumBoundary < newImageData.height) {
+ do {
+ // sum pixel RGB values for each column in our radius scope
+ for (int col = 0; col < newImageData.width; col++) {
+ rowRGBSums[col].red += rowCache.get(bottomSumBoundary - cacheStartIndex)[col].red;
+ rowRGBSums[col].green += rowCache.get(bottomSumBoundary - cacheStartIndex)[col].green;
+ rowRGBSums[col].blue += rowCache.get(bottomSumBoundary - cacheStartIndex)[col].blue;
+ }
+ numRows++;
+ bottomSumBoundary++; // move bottom scope boundary lower
+ if (bottomSumBoundary < newImageData.height && bottomSumBoundary - cacheStartIndex > radius * 2) {
+ // grow cache
+ rowCache.add(rowCache.size(), blurRow(originalImageData, bottomSumBoundary, radius));
+ }
+ } while (bottomSumBoundary <= radius); // to initialize
+ // rowRGBSums at start
+ }
+ if (targetRow - topSumBoundary > radius) {
+ // subtract values of top row from sums as scope of summed
+ // values moves down
+ for (int col = 0; col < newImageData.width; col++) {
+ rowRGBSums[col].red -= rowCache.get(topSumBoundary - cacheStartIndex)[col].red;
+ rowRGBSums[col].green -= rowCache.get(topSumBoundary - cacheStartIndex)[col].green;
+ rowRGBSums[col].blue -= rowCache.get(topSumBoundary - cacheStartIndex)[col].blue;
+ }
+ numRows--;
+ topSumBoundary++; // move top scope boundary lower
+ rowCache.remove(0); // remove top row which is out of summing
+ // scope
+ cacheStartIndex++;
+ }
+ // calculate each column's RGB-averaged pixel
+ for (int col = 0; col < newImageData.width; col++) {
+ rowRGBAverages[col] = newImageData.palette.getPixel(new RGB(rowRGBSums[col].red / numRows, rowRGBSums[col].green / numRows, rowRGBSums[col].blue / numRows));
+ }
+ // replace original pixels
+ newImageData.setPixels(0, targetRow, newImageData.width, rowRGBAverages, 0);
+ targetRow++;
+ }
+ return newImageData;
+ }
+
+ /**
+ * Average blurs a given row of image data. Returns the blurred row as a
+ * matrix of separated RGB values.
+ */
+ private static RGB[] blurRow(final ImageData originalImageData, final int row, final int radius) {
+ final RGB[] rowRGBAverages = new RGB[originalImageData.width]; // resulting
+ // rgb
+ // averages
+ final int[] lineData = new int[originalImageData.width];
+ originalImageData.getPixels(0, row, originalImageData.width, lineData, 0);
+ int r = 0, g = 0, b = 0; // sum red, green, and blue values separately
+ // for averaging
+ int leftSumBoundary = 0; // beginning index of summed values scope
+ int targetColumn = 0; // column of RGB average to be determined
+ int rightSumBoundary = 0; // ending index of summed values scope
+ int numCols = 0; // number of columns included in current summing scope
+ RGB rgb;
+ while (targetColumn < lineData.length) {
+ if (rightSumBoundary < lineData.length) {
+ // sum RGB values for each pixel in our radius scope
+ do {
+ rgb = originalImageData.palette.getRGB(lineData[rightSumBoundary]);
+ r += rgb.red;
+ g += rgb.green;
+ b += rgb.blue;
+ numCols++;
+ rightSumBoundary++;
+ } while (rightSumBoundary <= radius); // to initialize summing
+ // scope at start
+ }
+ // subtract sum of left pixel as summing scope moves right
+ if (targetColumn - leftSumBoundary > radius) {
+ rgb = originalImageData.palette.getRGB(lineData[leftSumBoundary]);
+ r -= rgb.red;
+ g -= rgb.green;
+ b -= rgb.blue;
+ numCols--;
+ leftSumBoundary++;
+ }
+ // calculate RGB averages
+ rowRGBAverages[targetColumn] = new RGB(r / numCols, g / numCols, b / numCols);
+ targetColumn++;
+ }
+ return rowRGBAverages;
+ }
+
+ /**
+ * Enable/disable all widgets of a control
+ *
+ * @param control control to enable/disable
+ * @param enable <code>true</code> to enable, <code>false</code> to disable
+ */
+ public static void enable(final Control control, final boolean enable) {
+ if (control instanceof Composite) {
+ for (final Control c : ((Composite) control).getChildren()) {
+ enable(c, enable);
+ }
+ }
+ control.setEnabled(enable);
+ }
+
+ /**
+ * Build a font from a given control. Useful if we just want a bold label
+ * for example
+ *
+ * @param control control that handle the default font
+ * @param style new style
+ * @return a font with the given style
+ */
+ public static Font buildFontFrom(final Control control, final int style) {
+ final Font temp = control.getFont();
+ final FontData[] fontData = temp.getFontData();
+ if (fontData == null || fontData.length == 0) {
+ return temp;
+ }
+ return new Font(control.getDisplay(), fontData[0].getName(), fontData[0].getHeight(), style);
+ }
+
+ /**
+ * Build a font from a given control. Useful if we just want a bold label
+ * for example
+ *
+ * @param control control that handle the default font
+ * @param style new style
+ * @return a font with the given style
+ */
+ public static Font buildFontFrom(final Control control, final int style, final int size) {
+ final Font temp = control.getFont();
+ final FontData[] fontData = temp.getFontData();
+ if (fontData == null || fontData.length == 0) {
+ return temp;
+ }
+ return new Font(control.getDisplay(), fontData[0].getName(), size, style);
+ }
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/utils/SimpleSelectionAdapter.java b/org.tizen.common.externals/src/org/mihalis/opal/utils/SimpleSelectionAdapter.java
new file mode 100644
index 000000000..1299df6b2
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/utils/SimpleSelectionAdapter.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON.
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation
+ *******************************************************************************/
+
+package org.mihalis.opal.utils;
+
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+
+/**
+ * This class is an adapter for the SelectionListener. Both behaviours (DefaultSelected and Selected) are doing the same thing
+ */
+public abstract class SimpleSelectionAdapter implements SelectionListener {
+
+ /**
+ * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetDefaultSelected(final SelectionEvent e) {
+ this.handle(e);
+
+ }
+
+ /**
+ * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ this.handle(e);
+
+ }
+
+ /**
+ * Sent when selection occurs in the control.
+ *
+ * @param e - an event containing information about the selection
+ */
+ public abstract void handle(SelectionEvent e);
+
+}
diff --git a/org.tizen.common.externals/src/org/mihalis/opal/utils/StringUtil.java b/org.tizen.common.externals/src/org/mihalis/opal/utils/StringUtil.java
new file mode 100644
index 000000000..7c1994c86
--- /dev/null
+++ b/org.tizen.common.externals/src/org/mihalis/opal/utils/StringUtil.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Laurent CARON
+ * 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:
+ * Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
+ *******************************************************************************/
+package org.mihalis.opal.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * This class provides useful String manipulation methods
+ *
+ */
+public class StringUtil {
+ /**
+ * Check if a string is empty or null
+ *
+ * @param source source string
+ * @return <code>true</code> is the string is empty or null,
+ * <code>false</code> otherwise
+ */
+ public static boolean isEmpty(final String source) {
+ return source == null || source.trim().isEmpty();
+ }
+
+ /**
+ * Converts exception stack trace as string
+ *
+ * @param exception exception to convert
+ * @return a string that contains the exception
+ */
+ public static final String stackStraceAsString(final Throwable exception) {
+ final StringWriter stringWriter = new StringWriter();
+ exception.printStackTrace(new PrintWriter(stringWriter));
+ return stringWriter.toString();
+ }
+
+ /**
+ * Insert a string in a middle of another string
+ *
+ * @param source source string
+ * @param newEntry string to insert into source
+ * @param position position to insert source
+ * @return the new string
+ */
+ public static String insertString(final String source, final String newEntry, final int position) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(source.substring(0, position)).append(newEntry).append(source.substring(position));
+ return sb.toString();
+ }
+
+ /**
+ * Remove a character in a String
+ *
+ * @param source source string
+ * @param position position of the character to remove
+ * @return the string without the character
+ */
+ public static String removeCharAt(final String source, final int position) {
+ final StringBuilder sb = new StringBuilder();
+ if (position == source.length()) {
+ return source;
+ }
+ sb.append(source.substring(0, position)).append(source.substring(position + 1));
+ return sb.toString();
+ }
+}
diff --git a/org.tizen.common.externals/src/org/tizen/common/externals/ExternalsPlugin.java b/org.tizen.common.externals/src/org/tizen/common/externals/ExternalsPlugin.java
new file mode 100644
index 000000000..208ca6df5
--- /dev/null
+++ b/org.tizen.common.externals/src/org/tizen/common/externals/ExternalsPlugin.java
@@ -0,0 +1,50 @@
+package org.tizen.common.externals;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class ExternalsPlugin extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.tizen.common.extras"; //$NON-NLS-1$
+
+ // The shared instance
+ private static ExternalsPlugin plugin;
+
+ /**
+ * The constructor
+ */
+ public ExternalsPlugin() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static ExternalsPlugin getDefault() {
+ return plugin;
+ }
+
+}