/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 *******************************************************************************/ package org.ebayopensource.turmeric.eclipse.repositorysystem.ui.pref; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.ebayopensource.turmeric.eclipse.repositorysystem.preferences.core.PreferenceConstants; import org.ebayopensource.turmeric.eclipse.repositorysystem.ui.RepositorySystemUIActivator; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.preference.FieldEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; 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.Group; import org.eclipse.swt.widgets.Label; /** * A field editor for an enumeration type preference. The choices are presented * as a list of radio buttons. * * @author yayu */ public class CustomRadioGroupFieldEditor extends FieldEditor { /** The Constant SUB_VALUE. */ public static final String SUB_VALUE = "field_editor_sub_value";//$NON-NLS-1$ private String[][] labelsAndValues; /** * The first level key is repo ID, the second level key is org ID/Name, then * the value is org display name */ private Map<String, Map<String, String>> organizations; private int numColumns; private int indent = HORIZONTAL_GAP; private String value; private String subPreferenceName; private String subValue; private Composite chooseArea; private Button[] radioButtons; private boolean useGroup; private Map<FieldEditor, Composite> subFieldEditors = new ConcurrentHashMap<FieldEditor, Composite>(); private Map<String, List<Button>> subButtons = new ConcurrentHashMap<String, List<Button>>(); /** * Instantiates a new custom radio group field editor. * * @param name the name * @param labelText the label text * @param numColumns the num columns * @param labelAndValues the label and values * @param organizations the organizations * @param parent the parent */ public CustomRadioGroupFieldEditor(String name, String labelText, int numColumns, String[][] labelAndValues, Map<String, Map<String, String>> organizations, Composite parent) { this(name, labelText, numColumns, labelAndValues, organizations, parent, false); } /** * Instantiates a new custom radio group field editor. * * @param name the name * @param labelText the label text * @param numColumns the num columns * @param labelAndValues the label and values * @param organizations the organizations * @param parent the parent * @param useGroup the use group */ public CustomRadioGroupFieldEditor(String name, String labelText, int numColumns, String[][] labelAndValues, Map<String, Map<String, String>> organizations, Composite parent, boolean useGroup) { setPreferenceStore(RepositorySystemUIActivator.getDefault().getPreferenceStore()); init(name, labelText); Assert.isTrue(validateKeyValuePair(labelAndValues)); Assert.isNotNull(organizations); this.subPreferenceName = PreferenceConstants.PREF_ORGANIZATION; this.labelsAndValues = labelAndValues; this.organizations = organizations; this.numColumns = numColumns; this.useGroup = useGroup; createControl(parent); } /** * {@inheritDoc} */ @Override protected void doLoad() { String value = getPreferenceStore().getString(getPreferenceName()); updateValue(value); setSubButtonsEnabled(value); updateSubValue(value, getPreferenceStore().getString(getSubPreferenceName())); } /** * {@inheritDoc} */ @Override protected void doLoadDefault() { String value = getPreferenceStore().getDefaultString( getPreferenceName()); updateValue(value); updateSubValue(value, getPreferenceStore().getDefaultString(getSubPreferenceName())); } /** * Gets the sub preference name. * * @return the sub preference name */ public String getSubPreferenceName() { return subPreferenceName; } /** * {@inheritDoc} */ @Override protected void doStore() { if (value == null) { getPreferenceStore().setToDefault(getPreferenceName()); return; } getPreferenceStore().setValue(getPreferenceName(), value); if (subValue == null) { getPreferenceStore().setToDefault(getSubPreferenceName()); return; } getPreferenceStore().setValue(getSubPreferenceName(), subValue); } /** * {@inheritDoc} */ @Override public int getNumberOfControls() { return 1; } private void createChooseArea(Composite parent) { Font font = parent.getFont(); if (useGroup) { Group group = new Group(parent, SWT.NONE); group.setFont(font); String text = getLabelText(); if (text != null) { group.setText(text); } chooseArea = group; GridLayout layout = new GridLayout(); layout.horizontalSpacing = HORIZONTAL_GAP; layout.numColumns = numColumns; chooseArea.setLayout(layout); } else { chooseArea = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; layout.horizontalSpacing = HORIZONTAL_GAP; layout.numColumns = numColumns; chooseArea.setLayout(layout); chooseArea.setFont(font); } } /** * {@inheritDoc} */ @Override protected void adjustForNumColumns(int numColumns) { Control control = getLabelControl(); if (control != null) { ((GridData) control.getLayoutData()).horizontalSpan = numColumns; } ((GridData) chooseArea.getLayoutData()).horizontalSpan = numColumns; } private boolean validateKeyValuePair(String[][] keyValuePair) { if (keyValuePair == null) { return false; } for (int i = 0; i < keyValuePair.length; i++) { String[] array = keyValuePair[i]; if (array == null || array.length != 2) { return false; } } return true; } /** * {@inheritDoc} */ @Override protected void doFillIntoGrid(Composite parent, int numColumns) { if (useGroup == true) { Control control = getRadioBoxControl(parent); GridData data = new GridData(GridData.FILL_HORIZONTAL); control.setLayoutData(data); } else { Control control = getLabelControl(parent); GridData data = new GridData(); data.horizontalSpan = numColumns; control.setLayoutData(data); control = getRadioBoxControl(parent); data = new GridData(); data.horizontalSpan = numColumns; data.horizontalIndent = indent; control.setLayoutData(data); } } /** * Gets the radio box control. * * @param parent the parent * @return the radio box control */ public Composite getRadioBoxControl(Composite parent) { if (chooseArea != null) { checkParent(chooseArea, parent); return chooseArea; } createChooseArea(parent); Font font = parent.getFont(); radioButtons = new Button[labelsAndValues.length]; for (int i = 0; i < labelsAndValues.length; i++) { final Button radio = new Button(chooseArea, SWT.RADIO | SWT.LEFT); radioButtons[i] = radio; String[] labelAndValue = labelsAndValues[i]; radio.setText(labelAndValue[0]); radio.setData(labelAndValue[1]); radio.setFont(font); radio.setEnabled(organizations.size() > 1); radio.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { CustomRadioGroupFieldEditor.this.clearErrorMessage(); String oldValue = value; value = (String) event.widget.getData(); setPresentsDefaultValue(false); setSubButtonsEnabled(value); fireValueChanged(VALUE, oldValue, value); } }); final Composite composite = new Composite(chooseArea, SWT.NONE); final GridLayout layout = new GridLayout(1, true); composite.setLayout(layout); List<Button> buttons = new ArrayList<Button>(); subButtons.put(labelAndValue[1], buttons); for (String orgId : organizations.get(labelAndValue[1]).keySet()) { final Button radio1 = new Button(composite, SWT.RADIO | SWT.LEFT); GridData data = new GridData(); data.horizontalIndent = 30; radio1.setLayoutData(data); radio1.setText(organizations.get(labelAndValue[1]).get(orgId)); radio1.setData(orgId); radio1.setFont(font); radio1.setEnabled(organizations.get(labelAndValue[1]).size() > 1); radio1.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { CustomRadioGroupFieldEditor.this.clearErrorMessage(); String oldValue = subValue; subValue = (String) event.widget.getData(); setPresentsDefaultValue(false); fireValueChanged(SUB_VALUE, oldValue, subValue); } }); buttons.add(radio1); } final Composite panel = new Composite(chooseArea, SWT.NONE); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = numColumns; panel.setLayoutData(data); panel.setLayout(new GridLayout(2, false)); final FieldEditor fieldEditor = createChoiceSubFieldEditor(panel, radio); if (fieldEditor != null) { Label label = fieldEditor.getLabelControl(panel); data = new GridData(); data.horizontalIndent = 15; label.setLayoutData(data); subFieldEditors.put(fieldEditor, panel); fieldEditor.setEnabled( radio.getText().equals( getPreferenceStore().getString( getPreferenceName())), panel); radio.addSelectionListener(new SelectionAdapter() { @Override public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } @Override public void widgetSelected(SelectionEvent e) { setSubFieldEditorEnabled(false); fieldEditor.setEnabled(radio.getSelection(), panel); fieldEditor.setFocus(); } }); } } chooseArea.addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent event) { chooseArea = null; radioButtons = null; } }); return chooseArea; } private void setSubButtonsEnabled(String id) { for (String key : subButtons.keySet()) { for (Button btn : subButtons.get(key)) { btn.setEnabled(id.equals(key)); btn.setSelection(false); } } updateSubValue(id, ""); } /** * Creates the choice sub field editor. * * @param parent the parent * @param radioBtn the radio btn * @return the field editor */ protected FieldEditor createChoiceSubFieldEditor(final Composite parent, final Button radioBtn) { return null; } private void setSubFieldEditorEnabled(boolean enabled) { for (FieldEditor fieldEditor : this.subFieldEditors.keySet()) { fieldEditor.setEnabled(enabled, this.subFieldEditors.get(fieldEditor)); } } /** * Sets the indent used for the first column of the radion button matrix. * * @param indent * the indent (in pixels) */ public void setIndent(int indent) { if (indent < 0) { this.indent = 0; } else { this.indent = indent; } } private void updateValue(String newValue) { this.value = newValue; if (radioButtons == null) { return; } if (this.value != null) { boolean found = false; for (int i = 0; i < radioButtons.length; i++) { Button radio = radioButtons[i]; boolean selection = false; if (((String) radio.getData()).equals(this.value)) { selection = true; found = true; } radio.setSelection(selection); } if (found) { return; } } // if valie is not found, the first radio button will be selected. if (radioButtons.length > 0) { radioButtons[0].setSelection(true); this.value = (String) radioButtons[0].getData(); } return; } private void updateSubValue(String firstValue, String selectedValue) { this.subValue = selectedValue; if (subButtons == null) { return; } if (this.subValue != null) { boolean found = false; for (Button radio : subButtons.get(this.value)) { boolean selection = false; if (((String) radio.getData()).equals(this.subValue)) { selection = true; found = true; } radio.setSelection(selection); radio.setEnabled(this.organizations.get(this.value).size() > 1); } if (found) { return; } } // if value is not found, the first radio button will be selected. if (subButtons.get(firstValue).isEmpty() == false) { subButtons.get(firstValue).get(0).setSelection(true); this.subValue = (String) subButtons.get(firstValue).get(0) .getData(); } return; } /** * {@inheritDoc} */ @Override public void setEnabled(boolean enabled, Composite parent) { if (useGroup == false) { super.setEnabled(enabled, parent); } for (int i = 0; i < radioButtons.length; i++) { radioButtons[i].setEnabled(enabled); } } }