/******************************************************************************* * Copyright (c) 2009, 2017 xored software, Inc. 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: * xored software, Inc. - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.internal.databinging; import java.util.Map; import org.eclipse.core.databinding.observable.Diffs; import org.eclipse.core.databinding.observable.value.AbstractObservableValue; import org.eclipse.jface.databinding.swt.DisplayRealm; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Listener; public class RadioButtonListValue<V> extends AbstractObservableValue { private final Class<V> valueType; private final Map<Button, V> buttons; private V selectionValue; private Listener updateListener = event -> { V oldSelectionValue = selectionValue; selectionValue = getSelection(); notifyIfChanged(oldSelectionValue, selectionValue); }; private Listener disposeListener = e -> RadioButtonListValue.this.dispose(); private V getSelection() { for (Map.Entry<Button, V> entry : buttons.entrySet()) { if (entry.getKey().getSelection()) { return entry.getValue(); } } return null; } /** * @param button */ public RadioButtonListValue(Class<V> valueType, Map<Button, V> buttons) { super(DisplayRealm.getRealm(buttons.keySet().iterator().next().getDisplay())); this.valueType = valueType; this.buttons = buttons; init(); } private void init() { for (Button button : buttons.keySet()) { button.addListener(SWT.Selection, updateListener); button.addListener(SWT.DefaultSelection, updateListener); button.addListener(SWT.Dispose, disposeListener); } } @Override @SuppressWarnings("unchecked") public void doSetValue(final Object value) { V oldSelectionValue = selectionValue; selectionValue = (V) value; boolean buttonUpdated = false; for (Map.Entry<Button, V> entry : buttons.entrySet()) { if (entry.getValue() == selectionValue) { entry.getKey().setSelection(true); buttonUpdated = true; break; } } if (!buttonUpdated) { for (Button button : buttons.keySet()) { button.setSelection(false); } } notifyIfChanged(oldSelectionValue, selectionValue); } @Override public Object doGetValue() { return getSelection(); } @Override public Object getValueType() { return valueType; } @Override public synchronized void dispose() { super.dispose(); for (Button button : buttons.keySet()) { if (!button.isDisposed()) { button.removeListener(SWT.Selection, updateListener); button.removeListener(SWT.DefaultSelection, updateListener); } } } /** * Notifies consumers with a value change event only if a change occurred. * * @param oldValue * @param newValue */ private void notifyIfChanged(V oldValue, V newValue) { if (oldValue != newValue) { fireValueChange(Diffs.createValueDiff(oldValue, newValue)); } } }