/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.internal.ui.ridgets.swt; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import org.eclipse.core.databinding.BindingException; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.conversion.Converter; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.jface.databinding.swt.ISWTObservableValue; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.riena.ui.ridgets.ICComboRidget; import org.eclipse.riena.ui.ridgets.IRidget; import org.eclipse.riena.ui.ridgets.swt.AbstractComboRidget; /** * Ridget for {@link CCombo} widgets. */ public class CComboRidget extends AbstractComboRidget implements ICComboRidget { private static final String ORIGINAL_BACKGROUND_KEY = "CCR.orBaKe"; //$NON-NLS-1$ private final ModifyListener modifyListener; public CComboRidget() { modifyListener = new CComboModifyListener(); addPropertyChangeListener(IRidget.PROPERTY_ENABLED, new PropertyChangeListener() { public void propertyChange(final PropertyChangeEvent evt) { if (getUIControl() != null) { final boolean isEnabled = ((Boolean) evt.getNewValue()).booleanValue(); updateBgColor(isEnabled); } } }); } @Override public CCombo getUIControl() { return (CCombo) super.getUIControl(); } @Override protected void addSelectionListener(final org.eclipse.swt.events.SelectionListener listener) { getUIControl().addSelectionListener(listener); } @Override protected void addTextModifyListener() { getUIControl().addModifyListener(modifyListener); } @Override protected void bindUIControl() { super.bindUIControl(); if (getUIControl() != null) { updateBgColor(isEnabled()); } } @Override protected void addConverter(final UpdateValueStrategy targetToModelStrategy, final IObservableValue selectionValue) { final Object selectionType = selectionValue.getValueType(); targetToModelStrategy.setConverter(new Converter(Object.class, selectionType) { public Object convert(final Object fromObject) { if (fromObject == null) { return null; } if (fromObject.getClass() == getToType()) { return fromObject; } if (fromObject.toString().isEmpty()) { return null; } return fromObject; } }); } @Override protected void checkUIControl(final Object uiControl) { checkType(uiControl, CCombo.class); if (uiControl != null) { final int style = ((CCombo) uiControl).getStyle(); if ((style & SWT.READ_ONLY) == 0) { throw new BindingException("Combo must be READ_ONLY"); //$NON-NLS-1$ } } } @Override protected void clearUIControlListSelection() { getUIControl().deselectAll(); // Workaround for an SWT feature: when the user clicks in the list, // an asynchronous selection event is added to the end of the event // queue, which will silenty an item. We asynchronously clear the list // as well getUIControl().getDisplay().asyncExec(new Runnable() { public void run() { final CCombo combo = getUIControl(); if (combo != null && !combo.isDisposed()) { combo.clearSelection(); // this does not change the text } } }); } @Override protected String[] getUIControlItems() { return getUIControl().getItems(); } @Override protected IObservableList getUIControlItemsObservable() { return SWTObservables.observeItems(getUIControl()); } @Override protected ISWTObservableValue getUIControlSelectionObservable() { return SWTObservables.observeSelection(getUIControl()); } @Override protected String getUIControlText() { return getUIControl().getText(); } @Override protected int indexOfInUIControl(final String item) { return getUIControl().indexOf(item); } @Override protected void removeAllFromUIControl() { getUIControl().removeAll(); } @Override protected void removeSelectionListener(final SelectionListener listener) { getUIControl().removeSelectionListener(listener); } @Override protected void removeTextModifyListener() { getUIControl().removeModifyListener(modifyListener); } @Override protected void selectInUIControl(final int index) { getUIControl().select(index); } @Override protected void setItemsToControl(final String[] arrItems) { getUIControl().setItems(arrItems); } @Override protected void setItemsToControl(final Object[] arrItems) { setItemsToControl(getStringArray(arrItems)); } @Override protected void setTextToControl(final String text) { getUIControl().setText(text); } @Override protected void updateEditable() { // unused } // helping methods ////////////////// /** * This was introduced as to address Bug 323449. * <p> * The Text/CCombo widgets will not change their background to gray when disabled, once a non-null background color has been used in the enabled state. */ private void updateBgColor(final boolean isEnabled) { // pre-condition: control is known to be != null final CCombo control = getUIControl(); if (isEnabled) { if (control.getData(ORIGINAL_BACKGROUND_KEY) != null) { control.setBackground((Color) control.getData(ORIGINAL_BACKGROUND_KEY)); control.setData(ORIGINAL_BACKGROUND_KEY, null); } } else { if (control.getData(ORIGINAL_BACKGROUND_KEY) == null) { control.setData(ORIGINAL_BACKGROUND_KEY, control.getBackground()); } final Color disabledBg = control.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); // note: the DisabledPainter will paint the DISABLED_MARKER_BACKGROUND over this, so we are good control.setBackground(disabledBg); } updateMarkers(); } // helping classes ////////////////// /** * Keeps the ridget's text value in-sync with the widget's text value */ private final class CComboModifyListener implements ModifyListener { public void modifyText(final ModifyEvent e) { if (!isOutputOnly()) { setText(getUIControlText()); } } } }