/******************************************************************************* * Copyright (c) 2000, 2009 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.jdt.internal.ui.preferences; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.resources.IProject; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.PixelConverter; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.window.Window; import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; import org.eclipse.jdt.core.JavaConventions; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.ui.JavaElementImageDescriptor; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jdt.ui.PreferenceConstants; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.JavaPluginImages; import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider; import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener; import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener; import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter; import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil; import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField; /** * The page for setting the organize import settings. */ public class ImportOrganizeConfigurationBlock extends OptionsConfigurationBlock { private static final Key PREF_IMPORTORDER= getJDTUIKey(PreferenceConstants.ORGIMPORTS_IMPORTORDER); private static final Key PREF_ONDEMANDTHRESHOLD= getJDTUIKey(PreferenceConstants.ORGIMPORTS_ONDEMANDTHRESHOLD); private static final Key PREF_IGNORELOWERCASE= getJDTUIKey(PreferenceConstants.ORGIMPORTS_IGNORELOWERCASE); private static final Key PREF_STATICONDEMANDTHRESHOLD= getJDTUIKey(PreferenceConstants.ORGIMPORTS_STATIC_ONDEMANDTHRESHOLD); private static final String DIALOGSETTING_LASTLOADPATH= JavaUI.ID_PLUGIN + ".importorder.loadpath"; //$NON-NLS-1$ private static final String DIALOGSETTING_LASTSAVEPATH= JavaUI.ID_PLUGIN + ".importorder.savepath"; //$NON-NLS-1$ private static Key[] getAllKeys() { return new Key[] { PREF_IMPORTORDER, PREF_ONDEMANDTHRESHOLD, PREF_STATICONDEMANDTHRESHOLD, PREF_IGNORELOWERCASE }; } public static class ImportOrderEntry { public final String name; public final boolean isStatic; public ImportOrderEntry(String name, boolean isStatic) { this.name= name; this.isStatic= isStatic; } public String serialize() { return isStatic ? '#' + name : name; } public static ImportOrderEntry fromSerialized(String str) { if (str.length() > 0 && str.charAt(0) == '#') { return new ImportOrderEntry(str.substring(1), true); } return new ImportOrderEntry(str, false); } } private static class ImportOrganizeLabelProvider extends LabelProvider { private final Image PCK_ICON; private final Image STATIC_CLASS_ICON; public ImportOrganizeLabelProvider() { PCK_ICON= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_PACKAGE); STATIC_CLASS_ICON= JavaElementImageProvider.getDecoratedImage(JavaPluginImages.DESC_MISC_PUBLIC, JavaElementImageDescriptor.STATIC, JavaElementImageProvider.SMALL_SIZE); } public Image getImage(Object element) { return ((ImportOrderEntry) element).isStatic ? STATIC_CLASS_ICON : PCK_ICON; } public String getText(Object element) { ImportOrderEntry entry= (ImportOrderEntry) element; String name= entry.name; if (name.length() > 0) { return BasicElementLabels.getJavaElementName(name); } if (entry.isStatic) { return PreferencesMessages.ImportOrganizeConfigurationBlock_other_static; } return PreferencesMessages.ImportOrganizeConfigurationBlock_other_normal; } } private class ImportOrganizeAdapter implements IListAdapter, IDialogFieldListener { private boolean canEdit(ListDialogField field) { List selected= field.getSelectedElements(); return selected.size() == 1; } public void customButtonPressed(ListDialogField field, int index) { doButtonPressed(index); } public void selectionChanged(ListDialogField field) { fOrderListField.enableButton(IDX_EDIT, canEdit(field)); } public void dialogFieldChanged(DialogField field) { doDialogFieldChanged(field); } public void doubleClicked(ListDialogField field) { if (canEdit(field)) { doButtonPressed(IDX_EDIT); } } } private static final int IDX_ADD= 0; private static final int IDX_ADD_STATIC= 1; private static final int IDX_EDIT= 2; private static final int IDX_REMOVE= 3; private static final int IDX_UP= 5; private static final int IDX_DOWN= 6; private ListDialogField fOrderListField; private StringDialogField fThresholdField; private StringDialogField fStaticThresholdField; private SelectionButtonDialogField fIgnoreLowerCaseTypesField; private SelectionButtonDialogField fExportButton; private SelectionButtonDialogField fImportButton; private PixelConverter fPixelConverter; public ImportOrganizeConfigurationBlock(IStatusChangeListener context, IProject project, IWorkbenchPreferenceContainer container) { super(context, project, getAllKeys(), container); String[] buttonLabels= new String[] { PreferencesMessages.ImportOrganizeConfigurationBlock_order_add_button, PreferencesMessages.ImportOrganizeConfigurationBlock_order_add_static_button, PreferencesMessages.ImportOrganizeConfigurationBlock_order_edit_button, PreferencesMessages.ImportOrganizeConfigurationBlock_order_remove_button, /* 4 */ null, PreferencesMessages.ImportOrganizeConfigurationBlock_order_up_button, PreferencesMessages.ImportOrganizeConfigurationBlock_order_down_button, }; ImportOrganizeAdapter adapter= new ImportOrganizeAdapter(); fOrderListField= new ListDialogField(adapter, buttonLabels, new ImportOrganizeLabelProvider()); fOrderListField.setDialogFieldListener(adapter); fOrderListField.setLabelText(PreferencesMessages.ImportOrganizeConfigurationBlock_order_label); fOrderListField.setUpButtonIndex(IDX_UP); fOrderListField.setDownButtonIndex(IDX_DOWN); fOrderListField.setRemoveButtonIndex(IDX_REMOVE); fOrderListField.enableButton(IDX_EDIT, false); fImportButton= new SelectionButtonDialogField(SWT.PUSH); fImportButton.setDialogFieldListener(adapter); fImportButton.setLabelText(PreferencesMessages.ImportOrganizeConfigurationBlock_order_load_button); fExportButton= new SelectionButtonDialogField(SWT.PUSH); fExportButton.setDialogFieldListener(adapter); fExportButton.setLabelText(PreferencesMessages.ImportOrganizeConfigurationBlock_order_save_button); fThresholdField= new StringDialogField(); fThresholdField.setDialogFieldListener(adapter); fThresholdField.setLabelText(PreferencesMessages.ImportOrganizeConfigurationBlock_threshold_label); fStaticThresholdField= new StringDialogField(); fStaticThresholdField.setDialogFieldListener(adapter); fStaticThresholdField.setLabelText(PreferencesMessages.ImportOrganizeConfigurationBlock_staticthreshold_label); fIgnoreLowerCaseTypesField= new SelectionButtonDialogField(SWT.CHECK); fIgnoreLowerCaseTypesField.setDialogFieldListener(adapter); fIgnoreLowerCaseTypesField.setLabelText(PreferencesMessages.ImportOrganizeConfigurationBlock_ignoreLowerCase_label); updateControls(); } protected Control createContents(Composite parent) { setShell(parent.getShell()); fPixelConverter= new PixelConverter(parent); Composite composite= new Composite(parent, SWT.NONE); composite.setFont(parent.getFont()); GridLayout layout= new GridLayout(); layout.numColumns= 2; layout.marginWidth= 0; layout.marginHeight= 0; composite.setLayout(layout); fOrderListField.doFillIntoGrid(composite, 3); LayoutUtil.setHorizontalSpan(fOrderListField.getLabelControl(null), 2); LayoutUtil.setWidthHint(fOrderListField.getLabelControl(null), fPixelConverter.convertWidthInCharsToPixels(60)); LayoutUtil.setHorizontalGrabbing(fOrderListField.getListControl(null)); Composite importExportComp= new Composite(composite, SWT.NONE); importExportComp.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1)); layout= new GridLayout(); layout.numColumns= 2; layout.marginWidth= 0; layout.marginHeight= 0; importExportComp.setLayout(layout); fImportButton.doFillIntoGrid(importExportComp, 1); fExportButton.doFillIntoGrid(importExportComp, 1); fThresholdField.doFillIntoGrid(composite, 2); ((GridData) fThresholdField.getTextControl(null).getLayoutData()).grabExcessHorizontalSpace= false; fStaticThresholdField.doFillIntoGrid(composite, 2); fIgnoreLowerCaseTypesField.doFillIntoGrid(composite, 2); Dialog.applyDialogFont(composite); return composite; } private boolean doThresholdChanged(String thresholdString) { StatusInfo status= new StatusInfo(); try { int threshold= Integer.parseInt(thresholdString); if (threshold < 0) { status.setError(PreferencesMessages.ImportOrganizeConfigurationBlock_error_invalidthreshold); } } catch (NumberFormatException e) { status.setError(PreferencesMessages.ImportOrganizeConfigurationBlock_error_invalidthreshold); } updateStatus(status); return status.isOK(); } private void doButtonPressed(int index) { if (index == IDX_ADD || index == IDX_ADD_STATIC) { // add new List existing= fOrderListField.getElements(); ImportOrganizeInputDialog dialog= new ImportOrganizeInputDialog(getShell(), existing, index == IDX_ADD_STATIC); if (dialog.open() == Window.OK) { List selectedElements= fOrderListField.getSelectedElements(); if (selectedElements.size() == 1) { int insertionIndex= fOrderListField.getIndexOfElement(selectedElements.get(0)) + 1; fOrderListField.addElement(dialog.getResult(), insertionIndex); } else { fOrderListField.addElement(dialog.getResult()); } } } else if (index == IDX_EDIT) { // edit List selected= fOrderListField.getSelectedElements(); if (selected.isEmpty()) { return; } ImportOrderEntry editedEntry= (ImportOrderEntry) selected.get(0); List existing= fOrderListField.getElements(); existing.remove(editedEntry); ImportOrganizeInputDialog dialog= new ImportOrganizeInputDialog(getShell(), existing, editedEntry.isStatic); dialog.setInitialSelection(editedEntry); if (dialog.open() == Window.OK) { fOrderListField.replaceElement(editedEntry, dialog.getResult()); } } } /* * The import order file is a property file. The keys are * "0", "1" ... last entry. The values must be valid package names. */ private List loadFromProperties(Properties properties) { ArrayList res= new ArrayList(); int nEntries= properties.size(); for (int i= 0 ; i < nEntries; i++) { String curr= properties.getProperty(String.valueOf(i)); if (curr != null) { ImportOrderEntry entry= ImportOrderEntry.fromSerialized(curr); if (entry.name.length() == 0 || !JavaConventions.validatePackageName(entry.name, JavaCore.VERSION_1_3, JavaCore.VERSION_1_5).matches(IStatus.ERROR)) { res.add(entry); } else { return null; } } else { return res; } } return res; } private List loadImportOrder() { IDialogSettings dialogSettings= JavaPlugin.getDefault().getDialogSettings(); FileDialog dialog= new FileDialog(getShell(), SWT.OPEN); dialog.setText(PreferencesMessages.ImportOrganizeConfigurationBlock_loadDialog_title); dialog.setFilterExtensions(new String[] {"*.importorder", "*.*"}); //$NON-NLS-1$ //$NON-NLS-2$ String lastPath= dialogSettings.get(DIALOGSETTING_LASTLOADPATH); if (lastPath != null) { dialog.setFilterPath(lastPath); } String fileName= dialog.open(); if (fileName != null) { dialogSettings.put(DIALOGSETTING_LASTLOADPATH, dialog.getFilterPath()); Properties properties= new Properties(); FileInputStream fis= null; try { fis= new FileInputStream(fileName); properties.load(fis); List res= loadFromProperties(properties); if (res != null) { return res; } } catch (IOException e) { JavaPlugin.log(e); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) {} } } String title= PreferencesMessages.ImportOrganizeConfigurationBlock_loadDialog_error_title; String message= PreferencesMessages.ImportOrganizeConfigurationBlock_loadDialog_error_message; MessageDialog.openError(getShell(), title, message); } return null; } private void saveImportOrder(List elements) { IDialogSettings dialogSettings= JavaPlugin.getDefault().getDialogSettings(); FileDialog dialog= new FileDialog(getShell(), SWT.SAVE); dialog.setText(PreferencesMessages.ImportOrganizeConfigurationBlock_saveDialog_title); dialog.setFilterExtensions(new String[] {"*.importorder", "*.*"}); //$NON-NLS-1$ //$NON-NLS-2$ dialog.setFileName("example"); //$NON-NLS-1$ String lastPath= dialogSettings.get(DIALOGSETTING_LASTSAVEPATH); if (lastPath != null) { dialog.setFilterPath(lastPath); } String fileName= dialog.open(); if (fileName != null) { dialogSettings.put(DIALOGSETTING_LASTSAVEPATH, dialog.getFilterPath()); Properties properties= new Properties(); for (int i= 0; i < elements.size(); i++) { ImportOrderEntry entry= (ImportOrderEntry) elements.get(i); properties.setProperty(String.valueOf(i), entry.serialize()); } FileOutputStream fos= null; try { fos= new FileOutputStream(fileName); properties.store(fos, "Organize Import Order"); //$NON-NLS-1$ } catch (IOException e) { JavaPlugin.log(e); String title= PreferencesMessages.ImportOrganizeConfigurationBlock_saveDialog_error_title; String message= PreferencesMessages.ImportOrganizeConfigurationBlock_saveDialog_error_message; MessageDialog.openError(getShell(), title, message); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) {} } } } } private void updateStatus(IStatus status) { fContext.statusChanged(status); } /* (non-Javadoc) * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(java.lang.String, java.lang.String) */ protected void validateSettings(Key changedKey, String oldValue, String newValue) { // no validation } /* (non-Javadoc) * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls() */ protected void updateControls() { ImportOrderEntry[] importOrder= getImportOrderPreference(); int threshold= getImportNumberThreshold(PREF_ONDEMANDTHRESHOLD); int staticThreshold= getImportNumberThreshold(PREF_STATICONDEMANDTHRESHOLD); boolean ignoreLowerCase= Boolean.valueOf(getValue(PREF_IGNORELOWERCASE)).booleanValue(); fOrderListField.removeAllElements(); for (int i= 0; i < importOrder.length; i++) { fOrderListField.addElement(importOrder[i]); } fThresholdField.setText(String.valueOf(threshold)); fStaticThresholdField.setText(String.valueOf(staticThreshold)); fIgnoreLowerCaseTypesField.setSelection(ignoreLowerCase); } protected final void doDialogFieldChanged(DialogField field) { // set values in working copy if (field == fOrderListField) { setValue(PREF_IMPORTORDER, packOrderList(fOrderListField.getElements())); } else if (field == fThresholdField) { if (doThresholdChanged(fThresholdField.getText())) { setValue(PREF_ONDEMANDTHRESHOLD, fThresholdField.getText()); } } else if (field == fStaticThresholdField) { if (doThresholdChanged(fStaticThresholdField.getText())) { setValue(PREF_STATICONDEMANDTHRESHOLD, fStaticThresholdField.getText()); } } else if (field == fIgnoreLowerCaseTypesField) { setValue(PREF_IGNORELOWERCASE, fIgnoreLowerCaseTypesField.isSelected()); } else if (field == fImportButton) { List order= loadImportOrder(); if (order != null) { fOrderListField.setElements(order); } } else if (field == fExportButton) { saveImportOrder(fOrderListField.getElements()); } } /* (non-Javadoc) * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean) */ protected String[] getFullBuildDialogStrings(boolean workspaceSettings) { return null; // no build required } private static ImportOrderEntry[] unpackOrderList(String str) { ArrayList res= new ArrayList(); int start= 0; do { int end= str.indexOf(';', start); if (end == -1) { end= str.length(); } res.add(ImportOrderEntry.fromSerialized(str.substring(start, end))); start= end + 1; } while (start < str.length()); return (ImportOrderEntry[]) res.toArray(new ImportOrderEntry[res.size()]); } private static String packOrderList(List orderList) { StringBuffer buf= new StringBuffer(); for (int i= 0; i < orderList.size(); i++) { ImportOrderEntry entry= (ImportOrderEntry) orderList.get(i); buf.append(entry.serialize()); buf.append(';'); } return buf.toString(); } private ImportOrderEntry[] getImportOrderPreference() { String str= getValue(PREF_IMPORTORDER); if (str != null) { return unpackOrderList(str); } return new ImportOrderEntry[0]; } private int getImportNumberThreshold(Key key) { String thresholdStr= getValue(key); try { int threshold= Integer.parseInt(thresholdStr); if (threshold < 0) { threshold= Integer.MAX_VALUE; } return threshold; } catch (NumberFormatException e) { return Integer.MAX_VALUE; } } }