1 /******************************************************************************* 2 * Copyright (c) 2003 Berthold Daum. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Common Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/cpl-v10.html 7 * 8 * Contributors: 9 * Berthold Daum 10 *******************************************************************************/ 11 package net.sourceforge.phpeclipse.ui.overlaypages; 12 13 import java.util.ArrayList; 14 import java.util.Iterator; 15 import java.util.List; 16 17 import org.eclipse.core.resources.IResource; 18 import org.eclipse.core.runtime.CoreException; 19 import org.eclipse.core.runtime.IAdaptable; 20 import org.eclipse.core.runtime.QualifiedName; 21 import org.eclipse.jface.preference.FieldEditor; 22 import org.eclipse.jface.preference.FieldEditorPreferencePage; 23 import org.eclipse.jface.preference.IPreferenceNode; 24 import org.eclipse.jface.preference.IPreferencePage; 25 import org.eclipse.jface.preference.IPreferenceStore; 26 import org.eclipse.jface.preference.PreferenceDialog; 27 import org.eclipse.jface.preference.PreferenceManager; 28 import org.eclipse.jface.preference.PreferenceNode; 29 import org.eclipse.jface.resource.ImageDescriptor; 30 import org.eclipse.swt.SWT; 31 import org.eclipse.swt.custom.BusyIndicator; 32 import org.eclipse.swt.events.SelectionAdapter; 33 import org.eclipse.swt.events.SelectionEvent; 34 import org.eclipse.swt.layout.GridData; 35 import org.eclipse.swt.layout.GridLayout; 36 import org.eclipse.swt.widgets.Button; 37 import org.eclipse.swt.widgets.Composite; 38 import org.eclipse.swt.widgets.Control; 39 import org.eclipse.ui.IWorkbenchPropertyPage; 40 41 /** 42 * @author Berthold Daum 43 */ 44 public abstract class FieldEditorOverlayPage extends FieldEditorPreferencePage 45 implements IWorkbenchPropertyPage { 46 /** 47 * * Name of resource property for the selection of workbench or project 48 * settings ** 49 */ 50 public static final String USEPROJECTSETTINGS = "useProjectSettings"; //$NON-NLS-1$ 51 52 private static final String FALSE = "false"; //$NON-NLS-1$ 53 54 private static final String TRUE = "true"; //$NON-NLS-1$ 55 56 private boolean fUseFileSettings = false; 57 58 // Stores all created field editors 59 private List editors = new ArrayList(); 60 61 // Stores owning element of properties 62 private IAdaptable element; 63 64 // Additional buttons for property pages 65 private Button useWorkspaceSettingsButton, useProjectSettingsButton, 66 configureButton; 67 68 // Overlay preference store for property pages 69 private IPreferenceStore overlayStore; 70 71 // The image descriptor of this pages title image 72 private ImageDescriptor image; 73 74 // Cache for page id 75 private String pageId; 76 77 /** 78 * Constructor 79 * 80 * @param style - 81 * layout style 82 */ FieldEditorOverlayPage(int style)83 public FieldEditorOverlayPage(int style) { 84 super(style); 85 } 86 87 /** 88 * Constructor 89 * 90 * @param style - 91 * layout style 92 */ FieldEditorOverlayPage(int style, boolean isFileSettings)93 public FieldEditorOverlayPage(int style, boolean isFileSettings) { 94 super(style); 95 fUseFileSettings = isFileSettings; 96 } 97 98 /** 99 * Constructor 100 * 101 * @param title - 102 * title string 103 * @param style - 104 * layout style 105 */ FieldEditorOverlayPage(String title, int style)106 public FieldEditorOverlayPage(String title, int style) { 107 super(title, style); 108 } 109 FieldEditorOverlayPage(String title, int style, boolean isFileSettings)110 public FieldEditorOverlayPage(String title, int style, 111 boolean isFileSettings) { 112 super(title, style); 113 fUseFileSettings = isFileSettings; 114 } 115 116 /** 117 * Constructor 118 * 119 * @param title - 120 * title string 121 * @param image - 122 * title image 123 * @param style - 124 * layout style 125 */ FieldEditorOverlayPage(String title, ImageDescriptor image, int style)126 public FieldEditorOverlayPage(String title, ImageDescriptor image, int style) { 127 super(title, image, style); 128 this.image = image; 129 } 130 131 /** 132 * Returns the id of the current preference page as defined in plugin.xml 133 * Subclasses must implement. 134 * 135 * @return - the qualifier 136 */ getPageId()137 protected abstract String getPageId(); 138 139 /** 140 * Receives the object that owns the properties shown in this property page. 141 * 142 * @see org.eclipse.ui.IWorkbenchPropertyPage#setElement(org.eclipse.core.runtime.IAdaptable) 143 */ setElement(IAdaptable element)144 public void setElement(IAdaptable element) { 145 this.element = element; 146 } 147 148 /** 149 * Delivers the object that owns the properties shown in this property page. 150 * 151 * @see org.eclipse.ui.IWorkbenchPropertyPage#getElement() 152 */ getElement()153 public IAdaptable getElement() { 154 return element; 155 } 156 157 /** 158 * Returns true if this instance represents a property page 159 * 160 * @return - true for property pages, false for preference pages 161 */ isPropertyPage()162 public boolean isPropertyPage() { 163 return getElement() != null; 164 } 165 166 /** 167 * We override the addField method. This allows us to store each field 168 * editor added by subclasses in a list for later processing. 169 * 170 * @see org.eclipse.jface.preference.FieldEditorPreferencePage#addField(org.eclipse.jface.preference.FieldEditor) 171 */ addField(FieldEditor editor)172 protected void addField(FieldEditor editor) { 173 editors.add(editor); 174 super.addField(editor); 175 } 176 177 /** 178 * We override the createControl method. In case of property pages we create 179 * a new PropertyStore as local preference store. After all control have 180 * been create, we enable/disable these controls. 181 * 182 * @see org.eclipse.jface.preference.PreferencePage#createControl() 183 */ createControl(Composite parent)184 public void createControl(Composite parent) { 185 // Special treatment for property pages 186 if (isPropertyPage()) { 187 // Cache the page id 188 pageId = getPageId(); 189 // Create an overlay preference store and fill it with properties 190 overlayStore = new PropertyStore((IResource) getElement(), super 191 .getPreferenceStore(), pageId); 192 // Set overlay store as current preference store 193 } 194 super.createControl(parent); 195 // Update state of all subclass controls 196 if (isPropertyPage()) 197 updateFieldEditors(); 198 } 199 200 /** 201 * We override the createContents method. In case of property pages we 202 * insert two radio buttons at the top of the page. 203 * 204 * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite) 205 */ createContents(Composite parent)206 protected Control createContents(Composite parent) { 207 if (isPropertyPage()) 208 createSelectionGroup(parent); 209 return super.createContents(parent); 210 } 211 212 /** 213 * Creates and initializes a selection group with two choice buttons and one 214 * push button. 215 * 216 * @param parent - 217 * the parent composite 218 */ createSelectionGroup(Composite parent)219 private void createSelectionGroup(Composite parent) { 220 Composite comp = new Composite(parent, SWT.NONE); 221 GridLayout layout = new GridLayout(2, false); 222 layout.marginHeight = 0; 223 layout.marginWidth = 0; 224 comp.setLayout(layout); 225 comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 226 Composite radioGroup = new Composite(comp, SWT.NONE); 227 radioGroup.setLayout(new GridLayout()); 228 radioGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 229 useWorkspaceSettingsButton = createRadioButton(radioGroup, Messages 230 .getString("OverlayPage.Use_Workspace_Settings")); //$NON-NLS-1$ 231 if (fUseFileSettings) { 232 useProjectSettingsButton = createRadioButton(radioGroup, Messages 233 .getString("OverlayPage.Use_File_Settings")); //$NON-NLS-1$ 234 } else { 235 useProjectSettingsButton = createRadioButton(radioGroup, Messages 236 .getString("OverlayPage.Use_Project_Settings")); //$NON-NLS-1$ 237 } 238 configureButton = new Button(comp, SWT.PUSH); 239 configureButton.setText(Messages 240 .getString("OverlayPage.Configure_Workspace_Settings")); //$NON-NLS-1$ 241 configureButton.addSelectionListener(new SelectionAdapter() { 242 public void widgetSelected(SelectionEvent e) { 243 configureWorkspaceSettings(); 244 } 245 }); 246 // Set workspace/project radio buttons 247 try { 248 String use = ((IResource) getElement()) 249 .getPersistentProperty(new QualifiedName(pageId, 250 USEPROJECTSETTINGS)); 251 if (TRUE.equals(use)) { 252 useProjectSettingsButton.setSelection(true); 253 configureButton.setEnabled(false); 254 } else 255 useWorkspaceSettingsButton.setSelection(true); 256 } catch (CoreException e) { 257 useWorkspaceSettingsButton.setSelection(true); 258 } 259 } 260 261 /** 262 * Convenience method creating a radio button 263 * 264 * @param parent - 265 * the parent composite 266 * @param label - 267 * the button label 268 * @return - the new button 269 */ createRadioButton(Composite parent, String label)270 private Button createRadioButton(Composite parent, String label) { 271 final Button button = new Button(parent, SWT.RADIO); 272 button.setText(label); 273 button.addSelectionListener(new SelectionAdapter() { 274 public void widgetSelected(SelectionEvent e) { 275 configureButton 276 .setEnabled(button == useWorkspaceSettingsButton); 277 updateFieldEditors(); 278 } 279 }); 280 return button; 281 } 282 283 /** 284 * Returns in case of property pages the overlay store, in case of 285 * preference pages the standard preference store 286 * 287 * @see org.eclipse.jface.preference.PreferencePage#getPreferenceStore() 288 */ getPreferenceStore()289 public IPreferenceStore getPreferenceStore() { 290 if (isPropertyPage()) 291 return overlayStore; 292 return super.getPreferenceStore(); 293 } 294 295 /* 296 * Enables or disables the field editors and buttons of this page 297 */ updateFieldEditors()298 private void updateFieldEditors() { 299 // We iterate through all field editors 300 boolean enabled = useProjectSettingsButton.getSelection(); 301 updateFieldEditors(enabled); 302 } 303 304 /** 305 * Enables or disables the field editors and buttons of this page Subclasses 306 * may override. 307 * 308 * @param enabled - 309 * true if enabled 310 */ updateFieldEditors(boolean enabled)311 protected void updateFieldEditors(boolean enabled) { 312 Composite parent = getFieldEditorParent(); 313 Iterator it = editors.iterator(); 314 while (it.hasNext()) { 315 FieldEditor editor = (FieldEditor) it.next(); 316 editor.setEnabled(enabled, parent); 317 } 318 } 319 320 /** 321 * We override the performOk method. In case of property pages we copy the 322 * values in the overlay store into the property values of the selected 323 * project. We also save the state of the radio buttons. 324 * 325 * @see org.eclipse.jface.preference.IPreferencePage#performOk() 326 */ performOk()327 public boolean performOk() { 328 boolean result = super.performOk(); 329 if (result && isPropertyPage()) { 330 // Save state of radiobuttons in project properties 331 IResource resource = (IResource) getElement(); 332 try { 333 String value = (useProjectSettingsButton.getSelection()) ? TRUE 334 : FALSE; 335 resource.setPersistentProperty(new QualifiedName(pageId, 336 USEPROJECTSETTINGS), value); 337 } catch (CoreException e) { 338 } 339 } 340 return result; 341 } 342 343 /** 344 * We override the performDefaults method. In case of property pages we 345 * switch back to the workspace settings and disable the field editors. 346 * 347 * @see org.eclipse.jface.preference.PreferencePage#performDefaults() 348 */ performDefaults()349 protected void performDefaults() { 350 if (isPropertyPage()) { 351 useWorkspaceSettingsButton.setSelection(true); 352 useProjectSettingsButton.setSelection(false); 353 configureButton.setEnabled(true); 354 updateFieldEditors(); 355 } 356 super.performDefaults(); 357 } 358 359 /** 360 * Creates a new preferences page and opens it 361 * 362 * @see com.bdaum.SpellChecker.preferences.SpellCheckerPreferencePage#configureWorkspaceSettings() 363 */ configureWorkspaceSettings()364 protected void configureWorkspaceSettings() { 365 try { 366 // create a new instance of the current class 367 IPreferencePage page = (IPreferencePage) this.getClass() 368 .newInstance(); 369 page.setTitle(getTitle()); 370 page.setImageDescriptor(image); 371 // and show it 372 showPreferencePage(pageId, page); 373 } catch (InstantiationException e) { 374 e.printStackTrace(); 375 } catch (IllegalAccessException e) { 376 e.printStackTrace(); 377 } 378 } 379 380 /** 381 * Show a single preference pages 382 * 383 * @param id - 384 * the preference page identification 385 * @param page - 386 * the preference page 387 */ showPreferencePage(String id, IPreferencePage page)388 protected void showPreferencePage(String id, IPreferencePage page) { 389 final IPreferenceNode targetNode = new PreferenceNode(id, page); 390 PreferenceManager manager = new PreferenceManager(); 391 manager.addToRoot(targetNode); 392 final PreferenceDialog dialog = new PreferenceDialog(getControl() 393 .getShell(), manager); 394 BusyIndicator.showWhile(getControl().getDisplay(), new Runnable() { 395 public void run() { 396 dialog.create(); 397 dialog.setMessage(targetNode.getLabelText()); 398 dialog.open(); 399 } 400 }); 401 } 402 } 403