Improved ${cursor} handling in HTML and TPL (smarty) files
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpeclipse / ui / overlaypages / OverlayPage.java
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 org.eclipse.core.resources.IResource;
14 import org.eclipse.core.runtime.CoreException;
15 import org.eclipse.core.runtime.QualifiedName;
16 import org.eclipse.jface.preference.IPreferenceNode;
17 import org.eclipse.jface.preference.IPreferencePage;
18 import org.eclipse.jface.preference.IPreferenceStore;
19 import org.eclipse.jface.preference.PreferenceDialog;
20 import org.eclipse.jface.preference.PreferenceManager;
21 import org.eclipse.jface.preference.PreferenceNode;
22 import org.eclipse.jface.resource.ImageDescriptor;
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.custom.BusyIndicator;
25 import org.eclipse.swt.custom.CTabFolder;
26 import org.eclipse.swt.events.SelectionAdapter;
27 import org.eclipse.swt.events.SelectionEvent;
28 import org.eclipse.swt.layout.GridData;
29 import org.eclipse.swt.layout.GridLayout;
30 import org.eclipse.swt.widgets.Button;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Control;
33 import org.eclipse.swt.widgets.TabFolder;
34 import org.eclipse.ui.dialogs.PropertyPage;
35 import org.eclipse.ui.part.PageBook;
36
37 /**
38  * @author Berthold Daum
39  */
40 public abstract class OverlayPage extends PropertyPage {
41
42         /*** Name of resource property for the selection of workbench or project settings ***/
43         public static final String USEPROJECTSETTINGS = "useProjectSettings"; //$NON-NLS-1$
44         
45         private static final String FALSE = "false"; //$NON-NLS-1$
46         private static final String TRUE = "true"; //$NON-NLS-1$
47
48         // Additional buttons for property pages
49         private Button useWorkspaceSettingsButton,
50                 useProjectSettingsButton,
51                 configureButton;
52
53         // Overlay preference store for property pages
54         private PropertyStore overlayStore;
55
56         // The image descriptor of this pages title image
57         private ImageDescriptor image;
58
59         // Cache for page id
60         private String pageId;
61
62         // Container for subclass controls
63         private Composite contents;
64
65         /**
66          * Constructor
67          */
68         public OverlayPage() {
69                 super();
70         }
71
72         /**
73          * Constructor
74          * @param title - title string
75          */
76         public OverlayPage(String title) {
77                 super();
78                 setTitle(title);
79         }
80
81         /**
82          * Constructor
83          * @param title - title string
84          * @param image - title image
85          */
86         public OverlayPage(String title, ImageDescriptor image) {
87                 super();
88                 setTitle(title);
89                 setImageDescriptor(image);
90                 this.image = image;
91         }
92
93         /**
94          * Returns the id of the current preference page as defined in plugin.xml
95          * Subclasses must implement. 
96          * 
97          * @return - the qualifier
98          */
99         protected abstract String getPageId();
100
101         /**
102          * Returns true if this instance represents a property page
103          * @return - true for property pages, false for preference pages
104          */
105         public boolean isPropertyPage() {
106                 return getElement() != null;
107         }
108
109         /**
110          *  We need to implement createContents method. In case of property pages we insert two radio buttons
111          * and a push button at the top of the page. Below this group we create a new composite for the contents
112          * created by subclasses.
113          * 
114          * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
115          */
116         protected Control createContents(Composite parent) {
117                 if (isPropertyPage())
118                         createSelectionGroup(parent);
119                 contents = new Composite(parent, SWT.NONE);
120                 GridLayout layout = new GridLayout();
121                 layout.marginHeight = 0;
122                 layout.marginWidth = 0;
123                 contents.setLayout(layout);
124                 contents.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
125                 return contents;
126         }
127
128         /**
129          * Creates and initializes a selection group with two choice buttons and one push button.
130          * @param parent - the parent composite
131          */
132         private void createSelectionGroup(Composite parent) {
133                 Composite comp = new Composite(parent, SWT.NONE);
134                 GridLayout layout = new GridLayout(2, false);
135                 layout.marginHeight = 0;
136                 layout.marginWidth = 0;
137                 comp.setLayout(layout);
138                 comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
139                 Composite radioGroup = new Composite(comp, SWT.NONE);
140                 radioGroup.setLayout(new GridLayout());
141                 radioGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
142                 useWorkspaceSettingsButton = createRadioButton(radioGroup, Messages.getString("OverlayPage.Use_Workspace_Settings")); //$NON-NLS-1$
143                 useProjectSettingsButton = createRadioButton(radioGroup, Messages.getString("OverlayPage.Use_Project_Settings")); //$NON-NLS-1$
144                 configureButton = new Button(comp, SWT.PUSH);
145                 configureButton.setText(Messages.getString("OverlayPage.Configure_Workspace_Settings")); //$NON-NLS-1$
146                 configureButton.addSelectionListener(new SelectionAdapter() {
147                         public void widgetSelected(SelectionEvent e) {
148                                 configureWorkspaceSettings();
149                         }
150                 });
151                 // Set workspace/project radio buttons
152                 try {
153                         String use =
154                                 ((IResource) getElement()).getPersistentProperty(
155                                         new QualifiedName(pageId, USEPROJECTSETTINGS));
156                         if (TRUE.equals(use)) {
157                                 useProjectSettingsButton.setSelection(true);
158                                 configureButton.setEnabled(false);
159                         } else
160                                 useWorkspaceSettingsButton.setSelection(true);
161                 } catch (CoreException e) {
162                         useWorkspaceSettingsButton.setSelection(true);
163                 }
164         }
165
166         /**
167          * Convenience method creating a radio button
168          * @param parent - the parent composite
169          * @param label - the button label
170          * @return - the new button
171          */
172         private Button createRadioButton(Composite parent, String label) {
173                 final Button button = new Button(parent, SWT.RADIO);
174                 button.setText(label);
175                 button.addSelectionListener(new SelectionAdapter() {
176                         public void widgetSelected(SelectionEvent e) {
177                                 configureButton.setEnabled(
178                                         button == useWorkspaceSettingsButton);
179                                 setControlsEnabled();
180                         }
181                 });
182                 return button;
183         }
184
185         /**
186          * In case of property pages we create a new PropertyStore as local overlay store.
187          * After all controls have been create, we enable/disable these controls
188          * 
189          * @see org.eclipse.jface.preference.PreferencePage#createControl()
190          */
191         public void createControl(Composite parent) {
192                 // Special treatment for property pages
193                 if (isPropertyPage()) {
194                         // Cache the page id
195                         pageId = getPageId();
196                         // Create an overlay preference store and fill it with properties
197                         overlayStore =
198                                 new PropertyStore(
199                                         (IResource) getElement(),
200                                         super.getPreferenceStore(),
201                                         pageId);
202                         // Set overlay store as current preference store
203                 }
204                 super.createControl(parent);
205                 // Update enablement of all subclass controls
206                 if (isPropertyPage())
207                         setControlsEnabled();
208         }
209
210         /* 
211          * Returns in case of property pages the overlay store - otherwise the standard preference store
212          * @see org.eclipse.jface.preference.PreferencePage#getPreferenceStore()
213          */
214         public IPreferenceStore getPreferenceStore() {
215                 if (isPropertyPage())
216                         return overlayStore;
217                 return super.getPreferenceStore();
218         }
219
220         /**
221          * Enables or disables the controls of this page
222          */
223         private void setControlsEnabled() {
224                 boolean enabled = useProjectSettingsButton.getSelection();
225                 setControlsEnabled(enabled);
226         }
227
228         /**
229          * Enables or disables the controls of this page
230          * Subclasses may override.
231          * 
232          * @param enabled - true if controls shall be enabled
233          */
234         protected void setControlsEnabled(boolean enabled) {
235                 setControlsEnabled(contents, enabled);
236         }
237
238         /**
239          * Enables or disables a tree of controls starting at the specified root. 
240          * We spare tabbed notebooks and pagebooks to allow for user navigation.
241          * 
242          * @param root - the root composite
243          * @param enabled - true if controls shall be enabled
244          */
245         private void setControlsEnabled(Composite root, boolean enabled) {
246                 Control[] children = root.getChildren();
247                 for (int i = 0; i < children.length; i++) {
248                         Control child = children[i];
249                         if (!(child instanceof CTabFolder) && !(child instanceof TabFolder) && !(child instanceof PageBook))
250                                 child.setEnabled(enabled);
251                         if (child instanceof Composite)
252                                 setControlsEnabled((Composite) child, enabled);
253                 }
254         }
255
256         /** 
257          * We override the performOk method. In case of property pages 
258          * we save the state of the radio buttons.
259          * 
260          * @see org.eclipse.jface.preference.IPreferencePage#performOk()
261          */
262         public boolean performOk() {
263                 boolean result = super.performOk();
264                 if (result && isPropertyPage()) {
265                         // Save state of radiobuttons in project properties
266                         IResource resource = (IResource) getElement();
267                         try {
268                                 String value =
269                                         (useProjectSettingsButton.getSelection()) ? TRUE : FALSE;
270                                 resource.setPersistentProperty(
271                                         new QualifiedName(pageId, USEPROJECTSETTINGS),
272                                         value);
273                         } catch (CoreException e) {
274                         }
275                 }
276                 return result;
277         }
278
279         /**
280          * We override the performDefaults method. In case of property pages we
281          * switch back to the workspace settings and disable the page controls.
282          * 
283          * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
284          */
285         protected void performDefaults() {
286                 if (isPropertyPage()) {
287                         useWorkspaceSettingsButton.setSelection(true);
288                         useProjectSettingsButton.setSelection(false);
289                         configureButton.setEnabled(true);
290                         setControlsEnabled();
291                 }
292                 super.performDefaults();
293         }
294
295         /**
296          * Creates a new preferences page and opens it
297          * @see com.bdaum.SpellChecker.preferences.SpellCheckerPreferencePage#configureWorkspaceSettings()
298          */
299         protected void configureWorkspaceSettings() {
300                 try {
301                         // create a new instance of the current class
302                         IPreferencePage page =
303                                 (IPreferencePage) this.getClass().newInstance();
304                         page.setTitle(getTitle());
305                         page.setImageDescriptor(image);
306                         // and show it
307                         showPreferencePage(pageId, page);
308                 } catch (InstantiationException e) {
309                         e.printStackTrace();
310                 } catch (IllegalAccessException e) {
311                         e.printStackTrace();
312                 }
313         }
314
315         /**
316          * Show a single preference pages
317          * @param id - the preference page identification
318          * @param page - the preference page
319          */
320         protected void showPreferencePage(String id, IPreferencePage page) {
321                 final IPreferenceNode targetNode = new PreferenceNode(id, page);
322                 PreferenceManager manager = new PreferenceManager();
323                 manager.addToRoot(targetNode);
324                 final PreferenceDialog dialog =
325                         new PreferenceDialog(getControl().getShell(), manager);
326                 BusyIndicator.showWhile(getControl().getDisplay(), new Runnable() {
327                         public void run() {
328                                 dialog.create();
329                                 dialog.setMessage(targetNode.getLabelText());
330                                 dialog.open();
331                         }
332                 });
333         }
334
335 }