Skip to main content
summaryrefslogtreecommitdiffstats
blob: 7c65b91378b163f4dd06d7c1362d2a19cf04a512 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* 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:
*    Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation

*******************************************************************************/

package org.eclipse.imp.preferences;


import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;


/**
 * A multi-tab preferences page for IMP-supported languages.
 * The various tabs nominally represent the same sets of preferences
 * as set on different levels (default, workspace configuration,
 * workspace instance, and project).
 * 
 * @author suttons@us.ibm.com
 */
public abstract class TabbedPreferencesPage extends PreferencePage implements IWorkbenchPreferencePage {
	
	// To hold tabs created by specializations of this class;
	// used below in methods that respond to buttons
	PreferencesTab[] tabs = new PreferencesTab[4];

	// To be provided by a language-specific preferences page
	// that is specialized from this one
	protected IPreferencesService prefService = null;

	
	public TabbedPreferencesPage() {
		this.noDefaultAndApplyButton();
	}

	protected Control createContents(Composite parent) {
		
		// Create a tab folder to put onto the page
		final TabFolder tabFolder = new TabFolder(parent, SWT.NONE);
        final GridData gd= new GridData(SWT.FILL, SWT.CENTER, true, false);
        gd.widthHint= 0;
        gd.heightHint= SWT.DEFAULT;
        gd.horizontalSpan= 1;
        tabFolder.setLayoutData(gd);

        // Create the tabs that go into the tab folder	
        tabs = createTabs(prefService, this, tabFolder);
        setInitialStateForTabs();

        // The validity of the page depends on the validity of its tabs,
        // so refresh the valid state of the page now that all of the
        // tabs have been created
        notifyState(true);

        // Set the font on the page
		Dialog.applyDialogFont(parent);

        // If there's more than 1 tab, start out by selecting the 2nd tab
        // (usually the "Workspace" tab), rather than the "Project" tab,
        // which doesn't even show values until the user selects a project.
		if (tabs.length > 1) {
		    int idx= -1;
		    for(int i= 0; i < tabs.length; i++) {
		        if (tabs[i].getLevel().equals(IPreferencesService.INSTANCE_LEVEL)) {
		            idx= i;
		        }
		    }
		    if (idx > 0) {
		        tabFolder.setSelection(idx);
		    }
		}
		return tabFolder;
	}

	
	/**
	 * Assure that the enabled state of conditionally enabled
	 * tabs is set appropriately.
	 * 
	 * When a tab is newly created with some fields that are supposed to
	 * be enabled depending on the value of other (boolean) fields, it
	 * seems that the enabled state of the conditional fields does not
	 * get set properly.  This happens despite explicit attempts to set
	 * the appropriate enabled state (perhaps due to race conditions?).
	 * Toggling of the condition fields once the tab has been created
	 * does cause the enabled state of conditional fields to be set
	 * correctly.  This method automates that activity, which can be
	 * emulated on the default tab by restoring and applying the default
	 * field values.  However, changes on the default tab can affect
	 * lower levels in the preferences hierarchy--values inherited from
	 * the default level do not change, but the fact that the default
	 * values have been restored causes inherited values to be marked as
	 * modified.  To clear the modified marks from lower levels of the
	 * preferences hierarchy, the tabs for those levels are also applied,
	 * in a top-down order.  On the project level default values are
	 * restored before being applied; this assures that the fields are
	 * empty, as they should be, because there should be no project
	 * selected at this point.
	 *
	 */
	protected void setInitialStateForTabs() {
	    // Assure that all tabs are initialized properly
	    // and reflect an unmodified state
	    for (int i = 0; i < tabs.length; i++) {
	    	if (tabs[i] instanceof DefaultPreferencesTab) {
	    		tabs[i].performDefaults();
	    		tabs[i].performApply();
	    		break;
	    	}
	    }
	    for (int i = 0; i < tabs.length; i++) {
	    	if (tabs[i] instanceof ConfigurationPreferencesTab) {
	    		tabs[i].performApply();
	    		break;
	    	}
	    }
	    for (int i = 0; i < tabs.length; i++) {
	    	if (tabs[i] instanceof InstancePreferencesTab) {
	    		tabs[i].performApply();
	    		break;
	    	}
	    }
	    for (int i = 0; i < tabs.length; i++) {
	    	if (tabs[i] instanceof ProjectPreferencesTab) {
	    		tabs[i].performDefaults();
	    		tabs[i].performApply();
	    		break;
	    	}
	    }
	}
	
	/**
	 * Create the tabs that represent the different levels of preferences
	 * shown on this page.  Nominally these are the default, workspace configuraiton,
	 * workspace instance, and project levels.
	 * 
	 * @param prefService	The service that manages the preferences by level
	 * @param page			The page on which the tabs are to be created (that is, this page)
	 * @param tabFolder		The tab folder, on this page, that will contain the created tabs
	 * @return				An array containing the created tabs
	 */
	protected abstract PreferencesTab[] createTabs(
			IPreferencesService prefService, TabbedPreferencesPage page, TabFolder tabFolder);	 
	

	
	/**
	 * 
	 */
	public boolean notifyState(boolean state) {
		boolean allValid = true;
		for (int i = 0; i < tabs.length && allValid; i++) {
			allValid = allValid && tabs[i] != null && tabs[i].isValid();
		}
		setValid(allValid);
		return allValid;
	}
	
	
	/*
	 * The following four operations provide a page-level response to the pressing of
	 * buttons on the page.  Note, though, that a preference page may not have all of
	 * these buttons--buttons not present on the page may instead be present on individual
	 * tabs on the page.
	 */
	

	/**
	 * Respond to pressing of the Apply button by saving the prevailing preferences.
	 * 
	 * Note:  In a system of multiple preference levels with preference-value
	 * inheritance, this may only save values on the levels on which they
	 * are stored, i.e., not on levels where they apply through inheritance only.
	 * 
	 * @see org.eclipse.jface.preference.PreferencePage#performApply()
	 */
	public void performApply()
	{
		for (int i = 0; i < tabs.length; i++) {
			tabs[i].performApply();
		}
	}
	
	
	/**
	 * Respond to pressing of Cancel button by cancelling in-progress
	 * preference updates on each level.
	 * 
	 * @see org.eclipse.jface.preference.IPreferencePage#performCancel()
	 */
    public boolean performCancel()
    {
    	// SMS 4 Dec 2006
    	// Previously just used to return true; now trying to
    	// allow for a negative return
    	boolean result = true;
		for (int i = 0; i < tabs.length; i++) {
		    // If there was a problem initializing the tabs, one or more might be null now.
			if (tabs[i] != null) {
				result = result && tabs[i].performCancel();
			}
		}

        return result;
    }

    
    /**
     * Respond to pressing of Restore Defaults button by restoring default
     * values on each level.
     * 
     * Note:  In a system of multiple preference levels with preference-value
     * inheritance, the default value on levels other than the default level
     * may be considered to be the level inherited from the next higher level,
     * so this may entail removing the preferences stored on each level other
     * than the default level.  On the default level, the programmed default
     * values should be restored.
     * 
     * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
     */
	public void performDefaults()
	{
		// SMS 4 Dec 2006
		// Need to check visibility of a composite that contains the tab;
		// be sure that the right one is checked here ...
		for (int i = 0; i < tabs.length; i++) {
			if (tabs[i].getTabItem().getControl().isVisible())
				tabs[i].performDefaults();
		}	

	}

	
	/**
	 * Respond to pressing of the Save button by saving the prevailing preferences.
	 * 
	 * Note:  In a system of multiple preference levels with preference-value
	 * inheritance, this may only save values on the levels on which they
	 * are stored, i.e., not on levels where they apply through inheritance only.
	 * 
	 * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
	 */
	public boolean performOk()
	{
		// SMS 4 Dec 2006
		// Not sure of the effect of returning false, but
		// should probably allow for that	
		boolean result = true;
		for (int i = tabs.length-1; i >= 0; i--) {
			result = result && tabs[i].performOk();
		}
		
		return result;
	}
	

	
	/**
	 * For IWorkbenchPreferencePage
	 * 
	 * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
	 */
	public void init(IWorkbench workbench) {
	}

	
	/**
	 * Get the tabs used on this preference page
	 * 
	 * @return	The tabs used on this preference page
	 */
	protected PreferencesTab[] getTabs() {
		return tabs;
	}

	
	
	/**
	 * Should be overridden in language-specific tabbed preferences page
	 * to make use of language-specific preference initializer.
	 * 
	 * @return 	The preference initializer to be used to initialize
	 * 			preferences in this tab
	 */
	// TODO:  Probably should make this an abstract method
	public PreferencesInitializer getPreferenceInitializer() {
		// TODO:  Override in subclass where the language-specific
		// initializer should be known
		System.out.println("TabbedPreferencesPage.getPreferenceInitializar():  unimplemented; should be overridden with language-specific implementation");
		return null;
	}



}

Back to the top