/******************************************************************************* * Copyright (c) 2000, 2008 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.wst.jsdt.internal.ui.preferences.formatter; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Observable; import java.util.Observer; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.preferences.DefaultScope; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.StatusDialog; 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.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.wst.jsdt.core.JavaScriptCore; import org.eclipse.wst.jsdt.internal.corext.util.Messages; import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin; import org.eclipse.wst.jsdt.internal.ui.preferences.PreferencesAccess; import org.eclipse.wst.jsdt.internal.ui.preferences.PreferencesMessages; import org.eclipse.wst.jsdt.internal.ui.preferences.formatter.ProfileManager.CustomProfile; import org.eclipse.wst.jsdt.internal.ui.preferences.formatter.ProfileManager.Profile; import org.eclipse.wst.jsdt.internal.ui.util.ExceptionHandler; import org.eclipse.wst.jsdt.internal.ui.util.PixelConverter; import org.eclipse.wst.jsdt.internal.ui.util.SWTUtil; import org.eclipse.wst.jsdt.ui.JavaScriptUI; import org.osgi.service.prefs.BackingStoreException; public abstract class ProfileConfigurationBlock { private class StoreUpdater implements Observer { public StoreUpdater() { fProfileManager.addObserver(this); } public void update(Observable o, Object arg) { try { fPreferenceListenerEnabled= false; final int value= ((Integer)arg).intValue(); switch (value) { case ProfileManager.PROFILE_DELETED_EVENT: case ProfileManager.PROFILE_RENAMED_EVENT: case ProfileManager.PROFILE_CREATED_EVENT: case ProfileManager.SETTINGS_CHANGED_EVENT: try { fProfileStore.writeProfiles(fProfileManager.getSortedProfiles(), fInstanceScope); // update profile store fProfileManager.commitChanges(fCurrContext); } catch (CoreException x) { JavaScriptPlugin.log(x); } break; case ProfileManager.SELECTION_CHANGED_EVENT: fProfileManager.commitChanges(fCurrContext); break; } } finally { fPreferenceListenerEnabled= true; } } } class ProfileComboController implements Observer, SelectionListener { private final List fSortedProfiles; public ProfileComboController() { fSortedProfiles= fProfileManager.getSortedProfiles(); fProfileCombo.addSelectionListener(this); fProfileManager.addObserver(this); updateProfiles(); updateSelection(); } public void widgetSelected(SelectionEvent e) { final int index= fProfileCombo.getSelectionIndex(); fProfileManager.setSelected((Profile)fSortedProfiles.get(index)); } public void widgetDefaultSelected(SelectionEvent e) {} public void update(Observable o, Object arg) { if (arg == null) return; final int value= ((Integer)arg).intValue(); switch (value) { case ProfileManager.PROFILE_CREATED_EVENT: case ProfileManager.PROFILE_DELETED_EVENT: case ProfileManager.PROFILE_RENAMED_EVENT: updateProfiles(); updateSelection(); break; case ProfileManager.SELECTION_CHANGED_EVENT: updateSelection(); break; } } private void updateProfiles() { fProfileCombo.setItems(fProfileManager.getSortedDisplayNames()); } private void updateSelection() { fProfileCombo.setText(fProfileManager.getSelected().getName()); } } class ButtonController implements Observer, SelectionListener { public ButtonController() { fProfileManager.addObserver(this); fNewButton.addSelectionListener(this); fEditButton.addSelectionListener(this); fDeleteButton.addSelectionListener(this); fLoadButton.addSelectionListener(this); update(fProfileManager, null); } public void update(Observable o, Object arg) { Profile selected= ((ProfileManager)o).getSelected(); final boolean notBuiltIn= !selected.isBuiltInProfile(); fDeleteButton.setEnabled(notBuiltIn); } public void widgetSelected(SelectionEvent e) { final Button button= (Button)e.widget; if (button == fEditButton) modifyButtonPressed(); else if (button == fDeleteButton) deleteButtonPressed(); else if (button == fNewButton) newButtonPressed(); else if (button == fLoadButton) loadButtonPressed(); } public void widgetDefaultSelected(SelectionEvent e) { } private void modifyButtonPressed() { final StatusDialog modifyDialog= createModifyDialog(fComposite.getShell(), fProfileManager.getSelected(), fProfileManager, fProfileStore, false); modifyDialog.open(); } private void deleteButtonPressed() { if (MessageDialog.openQuestion( fComposite.getShell(), FormatterMessages.CodingStyleConfigurationBlock_delete_confirmation_title, Messages.format(FormatterMessages.CodingStyleConfigurationBlock_delete_confirmation_question, fProfileManager.getSelected().getName()))) { fProfileManager.deleteSelected(); } } private void newButtonPressed() { final CreateProfileDialog p= new CreateProfileDialog(fComposite.getShell(), fProfileManager, fProfileVersioner); if (p.open() != Window.OK) return; if (!p.openEditDialog()) return; final StatusDialog modifyDialog= createModifyDialog(fComposite.getShell(), p.getCreatedProfile(), fProfileManager, fProfileStore, true); modifyDialog.open(); } private void loadButtonPressed() { final FileDialog dialog= new FileDialog(fComposite.getShell(), SWT.OPEN); dialog.setText(FormatterMessages.CodingStyleConfigurationBlock_load_profile_dialog_title); dialog.setFilterExtensions(new String [] {"*.xml"}); //$NON-NLS-1$ final String lastPath= JavaScriptPlugin.getDefault().getDialogSettings().get(fLastSaveLoadPathKey + ".loadpath"); //$NON-NLS-1$ if (lastPath != null) { dialog.setFilterPath(lastPath); } final String path= dialog.open(); if (path == null) return; JavaScriptPlugin.getDefault().getDialogSettings().put(fLastSaveLoadPathKey + ".loadpath", dialog.getFilterPath()); //$NON-NLS-1$ final File file= new File(path); Collection profiles= null; try { profiles= fProfileStore.readProfilesFromFile(file); } catch (CoreException e) { final String title= FormatterMessages.CodingStyleConfigurationBlock_load_profile_error_title; final String message= FormatterMessages.CodingStyleConfigurationBlock_load_profile_error_message; ExceptionHandler.handle(e, fComposite.getShell(), title, message); } if (profiles == null || profiles.isEmpty()) return; final CustomProfile profile= (CustomProfile)profiles.iterator().next(); if (!fProfileVersioner.getProfileKind().equals(profile.getKind())) { final String title= FormatterMessages.CodingStyleConfigurationBlock_load_profile_error_title; final String message= Messages.format(FormatterMessages.ProfileConfigurationBlock_load_profile_wrong_profile_message, new String[] {fProfileVersioner.getProfileKind(), profile.getKind()}); MessageDialog.openError(fComposite.getShell(), title, message); return; } if (profile.getVersion() > fProfileVersioner.getCurrentVersion()) { final String title= FormatterMessages.CodingStyleConfigurationBlock_load_profile_error_too_new_title; final String message= FormatterMessages.CodingStyleConfigurationBlock_load_profile_error_too_new_message; MessageDialog.openWarning(fComposite.getShell(), title, message); } if (fProfileManager.containsName(profile.getName())) { final AlreadyExistsDialog aeDialog= new AlreadyExistsDialog(fComposite.getShell(), profile, fProfileManager); if (aeDialog.open() != Window.OK) return; } fProfileVersioner.update(profile); fProfileManager.addProfile(profile); } } /** * The GUI controls */ private Composite fComposite; private Combo fProfileCombo; private Button fEditButton; private Button fDeleteButton; private Button fNewButton; private Button fLoadButton; private PixelConverter fPixConv; /** * The ProfileManager, the model of this page. */ private final ProfileManager fProfileManager; private final IScopeContext fCurrContext; private final IScopeContext fInstanceScope; private final ProfileStore fProfileStore; private final IProfileVersioner fProfileVersioner; private final String fLastSaveLoadPathKey; private IPreferenceChangeListener fPreferenceListener; private final PreferencesAccess fPreferenceAccess; private boolean fPreferenceListenerEnabled; public ProfileConfigurationBlock(IProject project, final PreferencesAccess access, String lastSaveLoadPathKey) { fPreferenceAccess= access; fLastSaveLoadPathKey= lastSaveLoadPathKey; fProfileVersioner= createProfileVersioner(); fProfileStore= createProfileStore(fProfileVersioner); fInstanceScope= access.getInstanceScope(); if (project != null) { fCurrContext= access.getProjectScope(project); } else { fCurrContext= fInstanceScope; } List profiles= null; try { profiles= fProfileStore.readProfiles(fInstanceScope); } catch (CoreException e) { JavaScriptPlugin.log(e); } if (profiles == null) { try { // bug 129427 profiles= fProfileStore.readProfiles(new DefaultScope()); } catch (CoreException e) { JavaScriptPlugin.log(e); } } if (profiles == null) profiles= new ArrayList(); fProfileManager= createProfileManager(profiles, fCurrContext, access, fProfileVersioner); new StoreUpdater(); fPreferenceListenerEnabled= true; fPreferenceListener= new IPreferenceChangeListener() { public void preferenceChange(PreferenceChangeEvent event) { if (fPreferenceListenerEnabled) { preferenceChanged(event); } } }; access.getInstanceScope().getNode(JavaScriptUI.ID_PLUGIN).addPreferenceChangeListener(fPreferenceListener); } protected void preferenceChanged(PreferenceChangeEvent event) { } protected abstract IProfileVersioner createProfileVersioner(); protected abstract ProfileStore createProfileStore(IProfileVersioner versioner); protected abstract ProfileManager createProfileManager(List profiles, IScopeContext context, PreferencesAccess access, IProfileVersioner profileVersioner); protected abstract ModifyDialog createModifyDialog(Shell shell, Profile profile, ProfileManager profileManager, ProfileStore profileStore, boolean newProfile); protected abstract void configurePreview(Composite composite, int numColumns, ProfileManager profileManager); private static Button createButton(Composite composite, String text, final int style) { final Button button= new Button(composite, SWT.PUSH); button.setFont(composite.getFont()); button.setText(text); final GridData gd= new GridData(style); gd.widthHint= SWTUtil.getButtonWidthHint(button); button.setLayoutData(gd); return button; } /** * Create the contents * @param parent Parent composite * @return Created control */ public Composite createContents(Composite parent) { final int numColumns = 5; fPixConv = new PixelConverter(parent); fComposite = createComposite(parent, numColumns); Label profileLabel= new Label(fComposite, SWT.NONE); profileLabel.setText(PreferencesMessages.CleanUpPreferencePage_Description); GridData data= new GridData(SWT.FILL, SWT.FILL, true, false); data.horizontalSpan= numColumns; profileLabel.setLayoutData(data); fProfileCombo= createProfileCombo(fComposite, 3, fPixConv.convertWidthInCharsToPixels(20)); fEditButton= createButton(fComposite, FormatterMessages.CodingStyleConfigurationBlock_edit_button_desc, GridData.HORIZONTAL_ALIGN_BEGINNING); fDeleteButton= createButton(fComposite, FormatterMessages.CodingStyleConfigurationBlock_remove_button_desc, GridData.HORIZONTAL_ALIGN_BEGINNING); fNewButton= createButton(fComposite, FormatterMessages.CodingStyleConfigurationBlock_new_button_desc, GridData.HORIZONTAL_ALIGN_BEGINNING); fLoadButton= createButton(fComposite, FormatterMessages.CodingStyleConfigurationBlock_load_button_desc, GridData.HORIZONTAL_ALIGN_END); createLabel(fComposite, "", 3); //$NON-NLS-1$ configurePreview(fComposite, numColumns, fProfileManager); new ButtonController(); new ProfileComboController(); return fComposite; } private static Combo createProfileCombo(Composite composite, int span, int widthHint) { final GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = span; gd.widthHint= widthHint; final Combo combo= new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY ); combo.setFont(composite.getFont()); combo.setLayoutData(gd); return combo; } protected static Label createLabel(Composite composite, String text, int numColumns) { final GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gd.horizontalSpan = numColumns; gd.widthHint= 0; final Label label = new Label(composite, SWT.WRAP); label.setFont(composite.getFont()); label.setText(text); label.setLayoutData(gd); return label; } private Composite createComposite(Composite parent, int numColumns) { final Composite composite = new Composite(parent, SWT.NONE); composite.setFont(parent.getFont()); final GridLayout layout = new GridLayout(numColumns, false); layout.marginHeight = 0; layout.marginWidth = 0; composite.setLayout(layout); return composite; } public final boolean hasProjectSpecificOptions(IProject project) { if (project != null) { return fProfileManager.hasProjectSpecificSettings(new ProjectScope(project)); } return false; } public boolean performOk() { return true; } public void performApply() { try { fCurrContext.getNode(JavaScriptUI.ID_PLUGIN).flush(); fCurrContext.getNode(JavaScriptCore.PLUGIN_ID).flush(); if (fCurrContext != fInstanceScope) { fInstanceScope.getNode(JavaScriptUI.ID_PLUGIN).flush(); fInstanceScope.getNode(JavaScriptCore.PLUGIN_ID).flush(); } } catch (BackingStoreException e) { JavaScriptPlugin.log(e); } } public void performDefaults() { Profile profile= fProfileManager.getDefaultProfile(); if (profile != null) { int defaultIndex= fProfileManager.getSortedProfiles().indexOf(profile); if (defaultIndex != -1) { fProfileManager.setSelected(profile); } } } public void dispose() { if (fPreferenceListener != null) { fPreferenceAccess.getInstanceScope().getNode(JavaScriptUI.ID_PLUGIN).removePreferenceChangeListener(fPreferenceListener); fPreferenceListener= null; } } public void enableProjectSpecificSettings(boolean useProjectSpecificSettings) { if (useProjectSpecificSettings) { fProfileManager.commitChanges(fCurrContext); } else { fProfileManager.clearAllSettings(fCurrContext); } } }