/** * Copyright (c) 2013 Andreas Mihm 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: * Andreas Mihm - initial API and implementation */ package org.eclipse.gyrex.admin.ui.context.internal; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.eclipse.gyrex.admin.ui.internal.widgets.NonBlockingStatusDialog; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.DialogField; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.IDialogFieldListener; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.LayoutUtil; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.Separator; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.StringDialogField; import org.eclipse.gyrex.context.definitions.IRuntimeContextDefinitionManager; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.UnhandledException; /** * The Class represents RAP UI non blocking status dialog to maintain the * preferences of a context. */ public class EditContextPrefsDialog extends NonBlockingStatusDialog { /** * Helper class to hold the preferences and provide them to the table view */ private class KeyValuePair { public String name; public String value; public KeyValuePair(final String name, final String value) { this.name = name; this.value = value; } } /** * Comparator to enable sorting of the table view */ private static final class KeyValuePairComparator extends ViewerComparator implements Comparator<KeyValuePair> { /** serialVersionUID */ private static final long serialVersionUID = 1L; private final boolean ascending; private final int property; public KeyValuePairComparator(final int property, final boolean ascending) { this.property = property; this.ascending = ascending; } @Override public int compare(final KeyValuePair pair1, final KeyValuePair pair22) { int result = 0; if (property == COL_NAME) { result = pair1.name.compareTo(pair22.name); } else if (property == COL_VALUE) { result = pair1.value.compareTo(pair22.value); } if (!ascending) { result = result * -1; } return result; } @Override public int compare(final Viewer viewer, final Object object1, final Object object2) { return compare((KeyValuePair) object1, (KeyValuePair) object2); } @Override public boolean isSorterProperty(final Object elem, final String property) { return true; } } /** * ContentProvider class for binding the List of Preferences to the table * view */ private static final class PrefsContentProvider implements IStructuredContentProvider { Object[] elements; @Override public void dispose() { // do nothing } @Override public Object[] getElements(final Object inputElement) { return elements; } @Override public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) { if (newInput == null) { elements = new Object[0]; } else { final List<?> preferenceList = (List<?>) newInput; elements = preferenceList.toArray(); } } } /** * Label provider for the table view */ private class PrefsLabelProvider extends ColumnLabelProvider { /** serialVersionUID */ private static final long serialVersionUID = 1L; private final int columnIndex; public PrefsLabelProvider(final int columnIndex) { this.columnIndex = columnIndex; } @Override public String getText(final Object element) { final KeyValuePair pref = (KeyValuePair) element; String result = pref.toString(); switch (columnIndex) { case COL_NAME: result = pref.name; break; case COL_VALUE: result = pref.value; break; } return result; } } /** serialVersionUID */ private static final long serialVersionUID = 1L; private static final int COL_NAME = 0; private static final int COL_VALUE = 1; /** * sort method for sorting the preference table view * * @param viewer * @param property * @param ascending */ @SuppressWarnings("unchecked") private static void sort(final TableViewer viewer, final int property, final boolean ascending) { if ((viewer.getControl().getStyle() & SWT.VIRTUAL) != 0) { final List<KeyValuePair> input = (List<KeyValuePair>) viewer.getInput(); Collections.sort(input, new KeyValuePairComparator(property, ascending)); viewer.refresh(); } else { viewer.setComparator(new KeyValuePairComparator(property, ascending)); } } /** * change sort direction * * @param column * @return */ private static int updateSortDirection(final TableColumn column) { final Table table = column.getParent(); if (column == table.getSortColumn()) { if (table.getSortDirection() == SWT.UP) { table.setSortDirection(SWT.DOWN); } else { table.setSortDirection(SWT.UP); } } else { table.setSortColumn(column); table.setSortDirection(SWT.DOWN); } return table.getSortDirection(); } /** The name field. */ private final StringDialogField nameField = new StringDialogField(); /** The value field. */ private final StringDialogField valueField = new StringDialogField(); private final StringDialogField qualifierField = new StringDialogField(); /** The registry impl. */ private final IRuntimeContextDefinitionManager registryImpl = null; /** input list for the preferences table */ private List<KeyValuePair> prefSettings; /** input list for the qualifiers drop down */ private List<Preferences> prefQualifiers; /** the table view for the preferences */ private TableViewer viewer; private TableViewerColumn nameColumn; private TableViewerColumn valueColumn; private final Preferences prefRootNode; private Preferences currentPrefNode; private Button addOrUpdateButton; private Button deleteButton; private Button addQualifierButton; private Combo qualifierCombo; private Label label; /** * Creates a new instance. * * @param parent * the parent UI element * @param registryImpl * the registry impl */ public EditContextPrefsDialog(final Shell parent, final Preferences prefNode) { super(parent); prefRootNode = prefNode; currentPrefNode = prefNode; prefSettings = new ArrayList<KeyValuePair>(); prefQualifiers = new ArrayList<Preferences>(); initContent(); //setTitle("View and Edit Context Preferences in " + prefNode.absolutePath()); setTitle("View and Edit Context Preferences"); setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL); } /** * Button action for adding or updating a preference */ protected void addOrUpdateButtonPressed() { final Preferences node; final String qualifier = qualifierField.getText(); if (StringUtils.isEmpty(qualifier)) { currentPrefNode = prefRootNode; } else { currentPrefNode = prefRootNode.node(qualifier); } final String name = nameField.getText(); String value = valueField.getText(); if (StringUtils.isEmpty(name)) return; if (StringUtils.isEmpty(value)) { value = ""; } currentPrefNode.put(name, value); try { currentPrefNode.flush(); fillQualifierCombo(); } catch (final BackingStoreException e) { e.printStackTrace(); throw new UnhandledException(e); } changePreferencesQualifier(qualifier); nameField.setText(""); valueField.setText(""); } /** * action on changing the qualifiers drop down selection, which updates the * preferences in the table view * * @param text */ protected void changePreferencesQualifier(String text) { if (StringUtils.isEmpty(text)) { text = ".settings"; } qualifierCombo.setText(text); try { Preferences node = null; if (text.equals(".settings")) { node = prefRootNode; qualifierField.setText(""); } else { node = prefRootNode.node(text); qualifierField.setText(text); } if (node != null) { currentPrefNode = node; prefSettings = new ArrayList<KeyValuePair>(); final String[] settingNames = node.keys(); for (final String settingName : settingNames) { final KeyValuePair pair = new KeyValuePair(settingName, node.get(settingName, null)); prefSettings.add(pair); } viewer.setInput(prefSettings); } } catch (final BackingStoreException e) { e.printStackTrace(); throw new UnhandledException(e); } } /** * Creates the button. * * @param buttons * the buttons * @param buttonLabel * the button label * @return the button */ private Button createButton(final Composite buttons, final String buttonLabel) { final Button b = new Button(buttons, SWT.NONE); b.setText(buttonLabel); b.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); return b; } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ @Override protected Control createDialogArea(final Composite parent) { final Composite composite = (Composite) super.createDialogArea(parent); final GridData gd = (GridData) composite.getLayoutData(); gd.minimumHeight = convertVerticalDLUsToPixels(200); gd.minimumWidth = convertHorizontalDLUsToPixels(400); gd.widthHint = convertHorizontalDLUsToPixels(400); gd.heightHint = convertHorizontalDLUsToPixels(250); qualifierField.setLabelText("Preference Qualifier/Group"); nameField.setLabelText("Preference Name"); valueField.setLabelText("Preference Value"); final Text warning = new Text(composite, SWT.WRAP | SWT.READ_ONLY | SWT.WRAP); warning.setText("All preference settings in the context " + prefRootNode.absolutePath() + " are listed below. You can add new preferences or delete or edit existing ones. Please note, that Preferences in a Gyrex Context can be grouped by qualifiers. You can select the qualifier/group in the drop down list. To create a new qualifier, just add a preference and enter a new qualifier."); warning.setLayoutData(new GridData(SWT.CENTER, SWT.LEFT, false, false)); warning.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); label = new Label(composite, SWT.NONE); label.setText("Select Preference Qualifier/Group"); qualifierCombo = new Combo(composite, SWT.NONE); try { fillQualifierCombo(); qualifierCombo.select(0); } catch (final BackingStoreException e) { e.printStackTrace(); throw new UnhandledException(e); } qualifierCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent event) { changePreferencesQualifier(qualifierCombo.getText()); } }); viewer = new TableViewer(composite, SWT.NONE | SWT.BORDER); viewer.setContentProvider(new PrefsContentProvider()); nameColumn = createNameColumn(); valueColumn = createValueColumn(); viewer.setInput(prefSettings); viewer.setItemCount(prefSettings.size()); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { final KeyValuePair selectedValue = getSelectedPreferenceFromTable(); if (selectedValue == null) return; nameField.setText(selectedValue.name); valueField.setText(selectedValue.value); updateStatus(Status.OK_STATUS); } }); viewer.getTable().setHeaderVisible(true); final GridData tableData = new GridData(SWT.FILL, SWT.FILL, true, true); tableData.horizontalSpan = 3; viewer.getTable().setLayoutData(tableData); final IDialogFieldListener validateListener = new IDialogFieldListener() { @Override public void dialogFieldChanged(final DialogField field) { validate(); } }; nameField.setDialogFieldListener(validateListener); LayoutUtil.doDefaultLayout(composite, new DialogField[] { new Separator(), qualifierField, nameField, valueField }, false); LayoutUtil.setHorizontalGrabbing(nameField.getTextControl(null)); LayoutUtil.setHorizontalGrabbing(valueField.getTextControl(null)); final GridLayout masterLayout = (GridLayout) composite.getLayout(); masterLayout.marginWidth = 5; masterLayout.marginHeight = 5; LayoutUtil.setHorizontalSpan(warning, masterLayout.numColumns); addOrUpdateButton = createButton(composite, "Add/Update Preference"); addOrUpdateButton.addSelectionListener(new SelectionAdapter() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void widgetSelected(final SelectionEvent event) { addOrUpdateButtonPressed(); } }); deleteButton = createButton(composite, "Delete Preference"); deleteButton.addSelectionListener(new SelectionAdapter() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void widgetSelected(final SelectionEvent event) { deleteButtonPressed(); } }); return composite; } /** * another long method for just creating a column, should be simplier * * @return */ private TableViewerColumn createNameColumn() { final TableViewerColumn result = new TableViewerColumn(viewer, SWT.NONE); result.setLabelProvider(new PrefsLabelProvider(COL_NAME)); final TableColumn column = result.getColumn(); column.setText("Name"); column.setWidth(370); column.setMoveable(true); column.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent event) { final int sortDirection = updateSortDirection((TableColumn) event.widget); sort(viewer, COL_NAME, sortDirection == SWT.DOWN); } }); return result; } /** * another long method for just creating a column, should be simplier * * @return */ private TableViewerColumn createValueColumn() { final TableViewerColumn result = new TableViewerColumn(viewer, SWT.NONE); result.setLabelProvider(new PrefsLabelProvider(COL_VALUE)); final TableColumn column = result.getColumn(); column.setText("Value"); column.setWidth(170); column.setMoveable(true); column.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent event) { final int sortDirection = updateSortDirection((TableColumn) event.widget); sort(viewer, COL_VALUE, sortDirection == SWT.DOWN); } }); return result; } /** * button action to delete a selected preference */ protected void deleteButtonPressed() { final KeyValuePair selectedValue = getSelectedPreferenceFromTable(); if (selectedValue == null) { setError("Please select a preference!"); return; } currentPrefNode.remove(selectedValue.name); try { currentPrefNode.flush(); } catch (final BackingStoreException e) { e.printStackTrace(); throw new UnhandledException(e); } prefSettings.remove(selectedValue); viewer.setInput(prefSettings); } /** * re reads the qualifiers of the context and updates the qualifiers Drop * down list * * @throws BackingStoreException */ private void fillQualifierCombo() throws BackingStoreException { prefQualifiers = new ArrayList<Preferences>(); // add the root preferences node to list prefQualifiers.add(prefRootNode); final String[] childrenNames = prefRootNode.childrenNames(); for (final String childNode : childrenNames) { final Preferences node = prefRootNode.node(childNode); prefQualifiers.add(node); } qualifierCombo.setItems(toStringArray(prefQualifiers)); } /** * @return the selected Preferences row from table */ private KeyValuePair getSelectedPreferenceFromTable() { final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); if (!selection.isEmpty() && (selection.getFirstElement() instanceof KeyValuePair)) return (KeyValuePair) selection.getFirstElement(); return null; } /** * init method to read the content required before creating the controls */ private void initContent() { try { final String[] settingNames = prefRootNode.keys(); for (final String settingName : settingNames) { System.out.println(" ZK Pref " + settingName + ":" + prefRootNode.get(settingName, null)); final KeyValuePair pair = new KeyValuePair(settingName, prefRootNode.get(settingName, null)); prefSettings.add(pair); } } catch (final BackingStoreException e) { e.printStackTrace(); throw new UnhandledException(e); } } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#okPressed() */ @Override protected void okPressed() { super.okPressed(); } /** * Sets the error. * * @param message * the new error */ void setError(final String message) { updateStatus(new Status(IStatus.ERROR, ContextUiActivator.SYMBOLIC_NAME, message)); getShell().pack(true); } /** * Sets the info. * * @param message * the new info */ void setInfo(final String message) { updateStatus(new Status(IStatus.INFO, ContextUiActivator.SYMBOLIC_NAME, message)); } /** * Sets the warning. * * @param message * the new warning */ void setWarning(final String message) { updateStatus(new Status(IStatus.WARNING, ContextUiActivator.SYMBOLIC_NAME, message)); } /** * @param prefQualifiers2 * @return */ private String[] toStringArray(final List<Preferences> prefQualifiers2) { final ArrayList<String> list = new ArrayList<String>(); for (final Preferences preferences : prefQualifiers2) { list.add(preferences.name()); } return list.toArray(new String[0]); } /** * Validate entered values. */ void validate() { updateStatus(Status.OK_STATUS); } }