/****************************************************************************** * Copyright (c) 2002, 2006 IBM Corporation 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: * IBM Corporation - initial API and implementation ****************************************************************************/ package org.eclipse.gmf.runtime.common.ui.dialogs; import java.util.ArrayList; import java.util.Iterator; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.IInputValidator; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; 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.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Text; import org.eclipse.gmf.runtime.common.core.util.Log; import org.eclipse.gmf.runtime.common.core.util.StringStatics; import org.eclipse.gmf.runtime.common.core.util.Trace; import org.eclipse.gmf.runtime.common.ui.internal.CommonUIDebugOptions; import org.eclipse.gmf.runtime.common.ui.internal.CommonUIPlugin; import org.eclipse.gmf.runtime.common.ui.internal.CommonUIStatusCodes; import org.eclipse.gmf.runtime.common.ui.internal.l10n.CommonUIMessages; import org.eclipse.gmf.runtime.common.ui.util.WindowUtil; /** * The common Show Related Elements Predefined Queries Composite. It contains a * list of queries you may select from. * * @author Wayne Diu, wdiu */ public class ShowRelatedElementsPredefinedComposite extends Composite { /** * Save As button */ protected Button saveAs; /** * Delete button */ protected Button delete; /** * Details button */ protected Button details; /** * Show Details button */ protected IShowRelatedElementsWithDetails showDetails; /** * Root SelectableElement */ protected SelectableElement rootElement; /** * If the Details is displayed */ protected boolean isDetails = false; /** * Predefined list */ protected List predefinedBox; /** * Data for the predefined queries */ protected java.util.List predefined = new ArrayList(); /** * Data for the hardcoded queries */ protected java.util.List queries; /** * Dialog settings for storing presets. */ protected final IDialogSettings dialogSettings = CommonUIPlugin .getDefault().getDialogSettings(); /** * Tree viewer control's height for the hint */ public static int VIEWER_HEIGHT = 225; /** * Viewer width hint for the listbox viewer */ protected int viewerWidth = 175; /** * Max length of preset name */ private static int PRESET_NAME_LENGTH = 256; static { try { VIEWER_HEIGHT = Integer.parseInt( CommonUIMessages.ShowRelatedElementsDialog_VIEWER_HEIGHT); } catch (NumberFormatException e) { Trace.catching(CommonUIPlugin.getDefault(), CommonUIDebugOptions.EXCEPTIONS_CATCHING, CommonUIPlugin .getDefault().getClass(), "NumberFormatException", e); //$NON-NLS-1$ /* already initialized with defaults */ Log .error( CommonUIPlugin.getDefault(), CommonUIStatusCodes.RESOURCE_FAILURE, "Failed to parse Show Related Elements Composite's localized size", e); //$NON-NLS-1$ } } /** * Save as dialog. Cached. */ protected InputDialog saveAsDialog = new InputDialog( Display.getDefault().getActiveShell(), CommonUIMessages.ShowRelatedElementsPredefinedComposite_SaveAs_Title, CommonUIMessages.ShowRelatedElementsPredefinedComposite_ChooseName, StringStatics.BLANK, new IInputValidator() { public String isValid(String newText) { if (containsSpecialCharacter(newText) || newText.length() == 0) { return CommonUIMessages.ShowRelatedElementsPredefinedComposite_SpecialCharacter; } return null; } }) { protected Control createDialogArea(Composite parent) { Control control = super.createDialogArea(parent); Text text = getText(); assert null != text; text.setTextLimit(30); text.setTextLimit(PRESET_NAME_LENGTH); return control; } }; /** * Opening a hardcoded query's display name */ protected static final String SPECIAL_OPENING = "["; //$NON-NLS-1$ /** * Closing a hardcoded query's display name */ protected static final String SPECIAL_CLOSING = "]"; //$NON-NLS-1$ /** * Dialog settings key */ protected static final String DIALOG_SETTINGS_KEY = "ShowRelatedElementsPresets"; //$NON-NLS-1$ /** * Default string */ protected static final String DEFAULT_STRING = SPECIAL_OPENING + CommonUIMessages.ShowRelatedElementsPredefinedComposite_DefaultQuery + SPECIAL_CLOSING; /** * Constructor * * @param parent * the parent Composite that we will add our composite into * @param sreWithDetails * for sending updated events * @param root * SelectableElement root * @param queriesList * list of hardcoded queries * @param width * int Width of composite to show * @param detailsShown * boolean true if details are shown, false if not shown */ public ShowRelatedElementsPredefinedComposite(Composite parent, IShowRelatedElementsWithDetails sreWithDetails, SelectableElement root, java.util.List queriesList, int width, boolean detailsShown) { super(parent, SWT.NULL); showDetails = sreWithDetails; rootElement = root; this.queries = queriesList; this.viewerWidth = width; this.isDetails = detailsShown; createContents(); } /** * Set the text of the show or hide details button depending on whether or * not the details are shown. */ private void setDetailsText() { assert null != details; if (!isDetails) { details .setText(CommonUIMessages.ShowRelatedElementsPredefinedComposite_ShowDetails); } else { details .setText(CommonUIMessages.ShowRelatedElementsPredefinedComposite_HideDetails); } } /** * Creates content for this composite. This includes the List of predefined * queries and several. */ protected void createContents() { this.setLayoutData(new GridData(GridData.FILL_BOTH)); this.setLayout(new GridLayout(1, false)); new Label(this, SWT.NULL) .setText(CommonUIMessages.ShowRelatedElementsPredefinedComposite_CustomQuery); predefinedBox = new List(this, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); GridData gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = 2; gd.heightHint = VIEWER_HEIGHT; gd.widthHint = viewerWidth; predefinedBox.setLayoutData(gd); Composite buttons; if (showDetails == null) { buttons = new Composite(this, SWT.NONE); buttons.setLayout(new GridLayout(2, true)); gd = new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_END); gd.horizontalSpan = 2; buttons.setLayoutData(gd); makePredefinedSettingsButtons(buttons); } else { Composite moreButtons = new Composite(this, SWT.NONE); GridLayout gridLayout = new GridLayout(2, false); gridLayout.marginWidth = 0; moreButtons.setLayout(gridLayout); moreButtons.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_END)); buttons = new Composite(moreButtons, SWT.NONE); gridLayout = new GridLayout(2, true); gridLayout.marginWidth = 0; buttons.setLayout(gridLayout); buttons.setLayoutData(new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING)); makePredefinedSettingsButtons(buttons); details = new Button(moreButtons, SWT.PUSH); setDetailsText(); details.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.GRAB_HORIZONTAL)); details.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { isDetails = !isDetails; saveAs.setEnabled(isDetails); showDetails.showOrHideDetails(); handlePredefinedBoxSelection(); setDetailsText(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); gd = WindowUtil.makeButtonData(details); gd.horizontalAlignment = GridData.END; gd.grabExcessHorizontalSpace = true; details.setLayoutData(gd); } //delete made by makePredefinedSettingsButtons assert null != delete; delete.setEnabled(false); contributeComposite(this); predefinedBox.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { handlePredefinedBoxSelection(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); contributeToList(); predefinedBox.select(predefinedBox.getItemCount() - 1); } /** * Handle when the user clicks on something in the predefined queries List. * * It could involve sending a message to update the details. Also update the * delete button enablement. */ protected void handlePredefinedBoxSelection() { if (predefinedBox.getSelectionIndex() == predefinedBox.getItemCount() - 1) { if (showDetails != null) showDetails.updateRelationships(null); delete.setEnabled(false); } else if (predefinedBox.getSelectionIndex() != predefinedBox .getItemCount() - 1) { String string = predefinedBox.getSelection()[0]; ShowRelatedElementsPreset preset = ShowRelatedElementsPresetHelper .findPresetFromList(predefined, string); if (preset == null) { preset = ShowRelatedElementsPresetHelper.findPresetFromList( queries, string.substring(0, string .indexOf(StringStatics.SPACE + DEFAULT_STRING))); } assert null != preset; if (showDetails != null) showDetails.updateRelationships(preset); //do not allow delete for anything with [ or ] //just need to check one of them delete.setEnabled(!containsSpecialCharacter(string)); } } /** * Contribute to the predefined queries List. Read in data. Add items to the * List. */ protected void contributeToList() { //clear the model predefined.clear(); //clear the ui predefinedBox.removeAll(); java.util.List readPresets = readPresets(null); predefined.addAll(readPresets); //do not sort //add the hardcoded queries Iterator it; if (queries != null) { it = queries.iterator(); while (it.hasNext()) { Object obj = it.next(); assert (obj instanceof ShowRelatedElementsPreset); predefinedBox.add(((ShowRelatedElementsPreset) obj).getName() + StringStatics.SPACE + DEFAULT_STRING); } } //add the user's predefined queries it = predefined.iterator(); while (it.hasNext()) { Object obj = it.next(); assert (obj instanceof ShowRelatedElementsPreset); predefinedBox.add(((ShowRelatedElementsPreset) obj).getName()); } //do not use messageformat since the ordering must be like this for //consistency with the rest predefinedBox .add(CommonUIMessages.ShowRelatedElementsPredefinedComposite_UserCustomQuery + StringStatics.SPACE + SPECIAL_OPENING + CommonUIMessages.ShowRelatedElementsPredefinedComposite_DefaultQuery + SPECIAL_CLOSING); } /** * Returns if the text string contains a special character. * * @param text * string to check for special characters * @return true if it contains a special character, false if it doesn't */ protected boolean containsSpecialCharacter(String text) { return (text.indexOf(ShowRelatedElementsPresetHelper.KEY_SEPARATOR) != -1 || text.indexOf(ShowRelatedElementsPresetHelper.VALUE_SEPARATOR) != -1 || text.indexOf(SPECIAL_CLOSING) != -1 || text .indexOf(SPECIAL_OPENING) != -1); } /** * Return a list of ShowRelatedElementsPreset objects. * * @param nameToIgnore * ignore this name when reading in the presets. Can be null if * you do not want to ignore anything and read everything in. * @return List of the presets. Items in the List are * ShowRelatedElementsPreset objects */ protected java.util.List readPresets(String nameToIgnore) { return ShowRelatedElementsPresetHelper.readPresets(nameToIgnore, dialogSettings.getArray(DIALOG_SETTINGS_KEY), null); } /** * Convert the presets to a string array used for serializing * * @param presets * List of ShowRelatedElementsPresets objects * @return String array that contains the data of the presets */ protected String[] convertPresetsToString(java.util.List presets) { return ShowRelatedElementsPresetHelper.convertPresetsToString(presets, null); } /** * Handle a save as for a predefined setting. */ protected void saveAs() { assert null != showDetails; if (saveAsDialog.open() == Window.OK) { //save as //name;ids,ids,ids;custom,custom,custom;typeint;int" java.util.List presets = readPresets(saveAsDialog.getValue()); //serialize it back out ShowRelatedElementsPreset newPreset = showDetails .getCurrentSettings(); assert null != newPreset; newPreset.setName(saveAsDialog.getValue()); presets.add(newPreset); dialogSettings.put(DIALOG_SETTINGS_KEY, convertPresetsToString(presets)); //TODO will be more efficient to just do the delta instead of // complete refresh contributeToList(); predefinedBox.select(predefinedBox.getItemCount() - 2); delete.setEnabled(true); } } /** * Make the buttons for the predefined settings list. * * @param buttons * composite I will be adding the buttons to. */ protected void makePredefinedSettingsButtons(Composite buttons) { saveAs = new Button(buttons, SWT.PUSH); saveAs.setText(CommonUIMessages.ShowRelatedElementsPredefinedComposite_SaveAs); saveAs.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { saveAs(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); saveAs.setLayoutData(WindowUtil.makeButtonData(saveAs)); delete = new Button(buttons, SWT.PUSH); delete.setText(CommonUIMessages.ShowRelatedElementsPredefinedComposite_Delete); delete.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { delete(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); delete.setLayoutData(WindowUtil.makeButtonData(delete)); } /** * Handle a delete button press to delete the predefined setting. */ protected void delete() { //do not allow deleting anything with [ in the name //handled by change selection assert (predefinedBox.getSelection().length != 0); String selectedText = predefinedBox.getSelection()[0]; ShowRelatedElementsPreset preset = ShowRelatedElementsPresetHelper .findPresetFromList(predefined, selectedText); assert (selectedText.indexOf(SPECIAL_OPENING) == -1); assert null != preset; //more efficient than rereading it and redoing entire ui //delete it from the model predefined.remove(preset); //delete it from the ui predefinedBox.remove(predefinedBox.getSelectionIndex()); dialogSettings.put(DIALOG_SETTINGS_KEY, convertPresetsToString(predefined)); //go back to the default query predefinedBox.setSelection(predefinedBox.getItemCount() - 1); delete.setEnabled(false); showDetails.updateRelationships(null); } /** * Contribute a composite to the expansion group * * @param parent * the parent expansion group composite that we are going to * contribute to. */ protected void contributeComposite(Composite parent) { //do nothing, subclasses may override } /** * Details were changed, so update the predefined box to select the first * item. */ protected void detailsChanged() { predefinedBox.select(predefinedBox.getItemCount() - 1); //do not showDetails.updateRelationships(null); //because the user is in the middle of updating it } }