/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ /** * */ package org.xmind.ui.properties; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.viewers.IOpenListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.OpenEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.RGB; 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.Shell; import org.eclipse.swt.widgets.Text; import org.xmind.ui.color.ColorPicker; import org.xmind.ui.color.ColorPickerConfigurer; import org.xmind.ui.color.ColorSelection; import org.xmind.ui.resources.ColorUtils; /** * @author Frank Shaka */ public class ColorPropertyEditor extends PropertyEditor { private static final int DEFAULT_TEXT_STYLE = SWT.SINGLE | SWT.BORDER; private static final String COLOR_NONE_VALUE = "none"; //$NON-NLS-1$ private int textStyle; private ColorPickerConfigurer configurer; private Text text; private ToolBarManager toolBar; private ColorPicker picker; private boolean modifying = false; /** * */ public ColorPropertyEditor() { this(DEFAULT_TEXT_STYLE, new ColorPickerConfigurer()); } public ColorPropertyEditor(ColorPickerConfigurer colorPickerConfigurer) { this(DEFAULT_TEXT_STYLE, colorPickerConfigurer); } /** * @param parent * @param style */ public ColorPropertyEditor(int textStyle, ColorPickerConfigurer colorPickerConfigurer) { Assert.isNotNull(colorPickerConfigurer); this.textStyle = textStyle; this.configurer = colorPickerConfigurer; } @Override protected Control createControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.marginWidth = 0; layout.marginHeight = 0; layout.verticalSpacing = 0; layout.horizontalSpacing = 3; composite.setLayout(layout); Control textControl = createText(composite); GridData textData = new GridData(SWT.FILL, SWT.CENTER, true, true); textData.widthHint = SWT.DEFAULT; textData.heightHint = SWT.DEFAULT; textControl.setLayoutData(textData); Control toolBarControl = createToolBar(composite); GridData toolBarData = new GridData(SWT.FILL, SWT.CENTER, false, true); toolBarData.widthHint = SWT.DEFAULT; toolBarData.heightHint = SWT.DEFAULT; toolBarControl.setLayoutData(toolBarData); return composite; } private Control createText(Composite parent) { text = new Text(parent, textStyle); text.setTextLimit(7); text.addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { Display.getCurrent().asyncExec(new Runnable() { public void run() { if (text == null || text.isDisposed()) return; if (isAncestorShell(text.getShell(), Display .getCurrent().getActiveShell())) return; textEditingFinished(); } }); } public void focusGained(FocusEvent e) { } }); text.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_ESCAPE) { fireCancelEditing(); e.doit = false; } else if (e.detail == SWT.TRAVERSE_RETURN) { textEditingFinished(); e.doit = false; } } }); text.addVerifyListener(new VerifyListener() { public void verifyText(VerifyEvent e) { if (e.keyCode == 27 && e.stateMask == 0) { fireCancelEditing(); e.doit = false; } else if (e.keyCode == 13) { textEditingFinished(); e.doit = false; } else { if (COLOR_NONE_VALUE.equals(e.text)) { return; } char[] charArray = e.text.toCharArray(); for (char character : charArray) { boolean isValid = character == '#' || (character >= 'A' && character <= 'F') || (character >= 'a' && character <= 'f') || (character >= '0' && character <= '9'); if (!isValid) { e.doit = false; return; } } } } }); text.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { if (modifying) return; String value = text.getText(); if ((value == null || value.lastIndexOf('#') != 0) && !COLOR_NONE_VALUE.equals(value)) { value = ""; //$NON-NLS-1$ } changeValue("".equals(value) ? null : value); //$NON-NLS-1$ } }); text.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (e.character == '\r') { textEditingFinished(); e.doit = false; } } }); return text; } private boolean isAncestorShell(Shell ancestor, Shell shell) { if (ancestor == null || shell == null || shell == ancestor) return false; Composite parent = shell.getParent(); if (parent == ancestor) return true; if (parent instanceof Shell) return isAncestorShell(ancestor, (Shell) parent); return false; } private void textEditingFinished() { String value = text.getText(); if ((value == null || value.length() != 7) && !COLOR_NONE_VALUE.equals(value)) text.setText(""); //$NON-NLS-1$ setValueToPicker(value); fireApplyEditorValue(); } private Control createToolBar(Composite parent) { toolBar = new ToolBarManager(); picker = new ColorPicker(configurer.getPopupStyle(), configurer.getPalette()); configureColorPicker(picker); toolBar.add(picker); toolBar.createControl(parent); return toolBar.getControl(); } /** * @param picker */ private void configureColorPicker(ColorPicker picker) { picker.setAutoColor(configurer.getAutoColor()); picker.addOpenListener(new IOpenListener() { public void open(OpenEvent event) { ColorSelection selection = (ColorSelection) event .getSelection(); Object value; if (selection.isNone()) { value = configurer.getNoneValue(); } else if (selection.isAutomatic()) { value = configurer.getAutoValue(); } else { RGB color = selection.getColor(); value = color == null ? null : ColorUtils.toString(color); } setValueToText(value); changeValue(value); fireApplyEditorValue(); } }); } /* * (non-Javadoc) * * @see * org.xmind.ui.properties.PropertyEditor#setBackground(org.eclipse.swt. * graphics.Color) */ @Override public void setBackground(Color color) { super.setBackground(color); if (getControl() != null && !getControl().isDisposed()) getControl().setBackground(color); if (toolBar != null && toolBar.getControl() != null && !toolBar.getControl().isDisposed()) toolBar.getControl().setBackground(color); } /* * (non-Javadoc) * * @see * org.xmind.ui.properties.PropertyEditor#setForeground(org.eclipse.swt. * graphics.Color) */ @Override public void setForeground(Color color) { super.setForeground(color); if (getControl() != null && !getControl().isDisposed()) { getControl().setForeground(color); } } /* * (non-Javadoc) * * @see * org.xmind.ui.properties.PropertyEditor#setFont(org.eclipse.swt.graphics * .Font) */ @Override public void setFont(Font font) { super.setFont(font); if (getControl() != null && !getControl().isDisposed()) { getControl().setFont(font); } } /* * (non-Javadoc) * * @see org.xmind.ui.properties.PropertyEditor#setFocus() */ @Override public void setFocus() { if (text != null && !text.isDisposed()) { text.setFocus(); } else { super.setFocus(); } } /* * (non-Javadoc) * * @see org.xmind.ui.properties.PropertyEditor#activateWidget() */ @Override protected void activateWidget() { super.activateWidget(); Display.getCurrent().asyncExec(new Runnable() { public void run() { if (toolBar == null || toolBar.getControl() == null || toolBar.getControl().isDisposed()) return; picker.open(); } }); } /* * (non-Javadoc) * * @see * org.xmind.ui.properties.PropertyEditor#setValueToWidget(java.lang.Object) */ @Override protected void setValueToWidget(Object value) { setValueToText(value); setValueToPicker(value); } private void setValueToText(Object value) { if (value instanceof String) { text.setText((String) value); } else if (value instanceof RGB) { text.setText(ColorUtils.toString((RGB) value)); } else if (value == null) { text.setText(""); //$NON-NLS-1$ } else { text.setText(value.toString()); } } private void setValueToPicker(Object value) { ISelection selection; if (configurer.isNoneValueSet() && (configurer.getNoneValue() == value || (configurer .getNoneValue() != null && configurer.getNoneValue() .equals(value)))) { selection = new ColorSelection(ColorSelection.NONE); } else if (configurer.isAutoValueSet() && (configurer.getAutoValue() == value || (configurer .getAutoValue() != null && configurer.getAutoValue() .equals(value)))) { selection = new ColorSelection(ColorSelection.AUTO); } else if (value instanceof String) { RGB color = ColorUtils.toRGB((String) value); selection = color == null ? ColorSelection.EMPTY : new ColorSelection(color); } else if (value instanceof RGB) { selection = new ColorSelection((RGB) value); } else { selection = ColorSelection.EMPTY; } picker.setSelection(selection); } }