View | Details | Raw Unified | Return to bug 272416 | Differences between
and this patch

Collapse All | Expand All

(-)plugin.xml (-1 / +11 lines)
Lines 675-681 Link Here
675
            class="org.eclipse.cdt.make.ui.dialogs.GCCPerProjectSCDProfilePage"
675
            class="org.eclipse.cdt.make.ui.dialogs.GCCPerProjectSCDProfilePage"
676
            name="%MBSPerProjectProfile.name"
676
            name="%MBSPerProjectProfile.name"
677
            profileId="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"/>
677
            profileId="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"/>
678
   </extension>  
678
   </extension>
679
     <extension
680
           point="org.eclipse.cdt.ui.workingSetConfigurations">
681
        <projectConfigurationFactory
682
              class="org.eclipse.cdt.managedbuilder.internal.ui.workingsets.MBSProjectConfigurationFactory"
683
              id="org.eclipse.cdt.managedbuilder.ui.mbsProjectConfigurationFactory">
684
           <projectNature
685
                 id="org.eclipse.cdt.managedbuilder.core.managedBuildNature">
686
           </projectNature>
687
        </projectConfigurationFactory>
688
     </extension>  
679
   
689
   
680
 
690
 
681
   
691
   
(-)META-INF/MANIFEST.MF (-1 / +2 lines)
Lines 6-12 Link Here
6
Bundle-Activator: org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIPlugin
6
Bundle-Activator: org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIPlugin
7
Bundle-Vendor: %providerName
7
Bundle-Vendor: %providerName
8
Bundle-Localization: plugin
8
Bundle-Localization: plugin
9
Export-Package: org.eclipse.cdt.managedbuilder.ui.actions,
9
Export-Package: org.eclipse.cdt.managedbuilder.internal.ui.workingsets,
10
 org.eclipse.cdt.managedbuilder.ui.actions,
10
 org.eclipse.cdt.managedbuilder.ui.properties,
11
 org.eclipse.cdt.managedbuilder.ui.properties,
11
 org.eclipse.cdt.managedbuilder.ui.wizards
12
 org.eclipse.cdt.managedbuilder.ui.wizards
12
Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.2.0,4.0.0)",
13
Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.2.0,4.0.0)",
(-)src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectConfiguration.java (+121 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.managedbuilder.internal.ui.workingsets;
13
14
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
15
import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetConfiguration;
16
import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProjectConfiguration;
17
import org.eclipse.cdt.internal.ui.workingsets.WorkingSetProjectConfiguration;
18
import org.eclipse.cdt.internal.ui.workingsets.WorkspaceSnapshot;
19
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
20
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
21
import org.eclipse.cdt.ui.CUIPlugin;
22
import org.eclipse.core.runtime.CoreException;
23
import org.eclipse.core.runtime.IProgressMonitor;
24
import org.eclipse.core.runtime.IStatus;
25
import org.eclipse.core.runtime.Status;
26
import org.eclipse.core.runtime.SubMonitor;
27
import org.eclipse.osgi.util.NLS;
28
29
/**
30
 * A managed-build implementation of the working set project configuration. It
31
 * knows how to build the selected configuration without activating it.
32
 * 
33
 * @author Christian W. Damus (cdamus)
34
 * 
35
 * @since 6.0
36
 */
37
class MBSProjectConfiguration extends WorkingSetProjectConfiguration {
38
39
	/**
40
	 * Initializes me.
41
	 * 
42
	 * @param parent
43
	 *            my parent working set configuration
44
	 */
45
	public MBSProjectConfiguration(IWorkingSetConfiguration parent) {
46
		super(parent);
47
	}
48
49
	@Override
50
	public IStatus build(IProgressMonitor monitor) {
51
		return MBSProjectConfiguration.build(this, monitor);
52
	}
53
54
	/**
55
	 * Builds the MBS configuration selected by the specified working set
56
	 * project configuration.
57
	 * 
58
	 * @param projectConfig
59
	 *            a project configuration to build
60
	 * @param monitor
61
	 *            for reporting build progress
62
	 * 
63
	 * @return the result of the MBS build
64
	 */
65
	static IStatus build(IWorkingSetProjectConfiguration projectConfig,
66
			IProgressMonitor monitor) {
67
		
68
		IStatus result = Status.OK_STATUS;
69
70
		ICConfigurationDescription config = projectConfig
71
				.resolveSelectedConfiguration();
72
		IConfiguration mbsConfig = (config == null) ? null
73
				: ManagedBuildManager.getConfigurationForDescription(config);
74
75
		if (mbsConfig == null) {
76
			result = new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID, NLS.bind(
77
					"No configuration selected for project \"{0}\".",
78
					projectConfig.getProjectName()));
79
		} else {
80
			monitor = SubMonitor.convert(monitor);
81
82
			try {
83
				ManagedBuildManager.buildConfigurations(
84
						new IConfiguration[] { mbsConfig }, monitor);
85
			} catch (CoreException e) {
86
				result = e.getStatus();
87
			}
88
		}
89
90
		return result;
91
	}
92
93
	@Override
94
	public ISnapshot createSnapshot(
95
			IWorkingSetConfiguration.ISnapshot workingSetConfig,
96
			WorkspaceSnapshot workspace) {
97
98
		return new Snapshot(workingSetConfig, this, workspace);
99
	}
100
101
	//
102
	// Nested classes
103
	//
104
105
	/**
106
	 * A mutable working-copy snapshot for MBS projects.
107
	 */
108
	static class Snapshot extends WorkingSetProjectConfiguration.Snapshot {
109
		protected Snapshot(IWorkingSetConfiguration parent,
110
				IWorkingSetProjectConfiguration projectConfig,
111
				WorkspaceSnapshot workspace) {
112
113
			super(parent, projectConfig, workspace);
114
		}
115
116
		@Override
117
		public IStatus build(IProgressMonitor monitor) {
118
			return MBSProjectConfiguration.build(this, monitor);
119
		}
120
	}
121
}
(-)src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectConfigurationFactory.java (+43 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.managedbuilder.internal.ui.workingsets;
13
14
import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetConfiguration;
15
import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProjectConfigurationFactory;
16
import org.eclipse.cdt.internal.ui.workingsets.WorkingSetProjectConfiguration;
17
18
/**
19
 * Working set project configuration factory for MBS projects.
20
 * 
21
 * @author Christian W. Damus (cdamus)
22
 * 
23
 * @since 6.0
24
 * 
25
 */
26
public class MBSProjectConfigurationFactory extends
27
		IWorkingSetProjectConfigurationFactory.Registry.Default {
28
29
	/**
30
	 * Initializes me.
31
	 */
32
	public MBSProjectConfigurationFactory() {
33
		super();
34
	}
35
36
	@Override
37
	protected WorkingSetProjectConfiguration createProjectConfiguration(
38
			IWorkingSetConfiguration parent) {
39
40
		return new MBSProjectConfiguration(parent);
41
	}
42
43
}
(-)plugin.properties (-2 / +5 lines)
Lines 1-5 Link Here
1
###############################################################################
1
###############################################################################
2
# Copyright (c) 2003, 2008 IBM Corporation and others.
2
# Copyright (c) 2003, 2009 IBM Corporation, QNX Software Systems, and others.
3
# All rights reserved. This program and the accompanying materials
3
# All rights reserved. This program and the accompanying materials
4
# are made available under the terms of the Eclipse Public License v1.0
4
# are made available under the terms of the Eclipse Public License v1.0
5
# which accompanies this distribution, and is available at
5
# which accompanies this distribution, and is available at
Lines 10-15 Link Here
10
#     Markus Schorn (Wind River Systems)
10
#     Markus Schorn (Wind River Systems)
11
#     Anton Leherbauer (Wind River Systems)
11
#     Anton Leherbauer (Wind River Systems)
12
#     Sergey Prigogin (Google)
12
#     Sergey Prigogin (Google)
13
#     QNX Software Systems - [272416] Rework the working set configurations
13
###############################################################################
14
###############################################################################
14
pluginName=C/C++ Development Tools UI
15
pluginName=C/C++ Development Tools UI
15
providerName=Eclipse.org
16
providerName=Eclipse.org
Lines 508-514 Link Here
508
cElementHyperlinkDetector= C/C++ Elements
509
cElementHyperlinkDetector= C/C++ Elements
509
510
510
keybinding.MSVS= Microsoft Visual Studio
511
keybinding.MSVS= Microsoft Visual Studio
511
wsselection= Configs for Working set
512
wsselection= Manage Working Sets...
513
buildWorkingSetConfig.label=Build Working Set
514
workingSetConfigurationsExtensionPoint=Working Set Configurations
512
515
513
# Keywords for Preferences
516
# Keywords for Preferences
514
preferenceKeywords.common=c cpp cplusplus cdt
517
preferenceKeywords.common=c cpp cplusplus cdt
(-)plugin.xml (-21 / +62 lines)
Lines 24-29 Link Here
24
   <extension-point id="quickFixProcessors" name="%quickFixProcessorExtensionPoint" schema="schema/quickFixProcessors.exsd"/>
24
   <extension-point id="quickFixProcessors" name="%quickFixProcessorExtensionPoint" schema="schema/quickFixProcessors.exsd"/>
25
   <extension-point id="quickAssistProcessors" name="%quickAssistProcessorExtensionPoint" schema="schema/quickAssistProcessors.exsd"/>
25
   <extension-point id="quickAssistProcessors" name="%quickAssistProcessorExtensionPoint" schema="schema/quickAssistProcessors.exsd"/>
26
   <extension-point id="DocCommentOwner" name="%DocCommentOwner.name" schema="schema/DocCommentOwner.exsd"/>
26
   <extension-point id="DocCommentOwner" name="%DocCommentOwner.name" schema="schema/DocCommentOwner.exsd"/>
27
   <extension-point id="workingSetConfigurations" name="%workingSetConfigurationsExtensionPoint" schema="schema/workingSetConfigurations.exsd"/>
27
28
28
   <extension
29
   <extension
29
         point="org.eclipse.core.runtime.adapters">
30
         point="org.eclipse.core.runtime.adapters">
Lines 1116-1121 Link Here
1116
            contentMergeViewerId="org.eclipse.cdt.ui.compare.AsmContentViewerCreator"/>
1117
            contentMergeViewerId="org.eclipse.cdt.ui.compare.AsmContentViewerCreator"/>
1117
   </extension>
1118
   </extension>
1118
   <extension
1119
   <extension
1120
         point="org.eclipse.ui.menus">
1121
      <menuContribution
1122
            locationURI="menu:project?after=build">
1123
         <menu
1124
               id="org.eclipse.cdt.ui.prjmenu"
1125
               label="%Configurations.menu">
1126
            <separator
1127
                  name="gm1" visible="false">
1128
            </separator>
1129
            <separator
1130
                  name="s2" visible="true">
1131
            </separator>
1132
            <separator
1133
                  name="gm2" visible="false">
1134
            </separator>
1135
            <separator
1136
                  name="s3" visible="true">
1137
            </separator>
1138
            <separator
1139
                  name="gm3" visible="false">
1140
            </separator>
1141
            <separator
1142
                  name="gm4" visible="false">
1143
            </separator>
1144
         </menu>
1145
      </menuContribution>
1146
      <menuContribution
1147
            locationURI="menu:org.eclipse.cdt.ui.prjmenu?before=gm4">
1148
         <dynamic
1149
               class="org.eclipse.cdt.ui.actions.BuildWorkingSetConfigsContribution"
1150
               id="org.eclipse.cdt.ui.buildWorkingSetConfigs">
1151
            <visibleWhen>
1152
               <with
1153
                     variable="activeContexts">
1154
                  <iterate
1155
                        ifEmpty="false"
1156
                        operator="or">
1157
                     <equals
1158
                           value="org.eclipse.cdt.ui.buildConfigActionSet">
1159
                     </equals>
1160
                  </iterate>
1161
               </with>
1162
            </visibleWhen>
1163
         </dynamic>
1164
      </menuContribution>
1165
   </extension>
1166
   <extension
1119
         point="org.eclipse.ui.actionSets">
1167
         point="org.eclipse.ui.actionSets">
1120
      <actionSet
1168
      <actionSet
1121
            label="%CodingActionSet.label"
1169
            label="%CodingActionSet.label"
Lines 1287-1312 Link Here
1287
           id="org.eclipse.cdt.ui.buildConfigActionSet"
1335
           id="org.eclipse.cdt.ui.buildConfigActionSet"
1288
           label="%BuildConfigActionSet.label"
1336
           label="%BuildConfigActionSet.label"
1289
           visible="false">
1337
           visible="false">
1290
        <menu
1291
              id="org.eclipse.cdt.ui.prjmenu"
1292
              label="%Configurations.menu"
1293
              path="project/build">
1294
           <groupMarker
1295
                 name="gm1">
1296
           </groupMarker>
1297
           <separator
1298
                 name="s2">
1299
           </separator>
1300
           <groupMarker
1301
                 name="gm2">
1302
           </groupMarker>
1303
           <separator
1304
                 name="s3">
1305
           </separator>
1306
           <groupMarker
1307
                 name="gm3">
1308
           </groupMarker>
1309
        </menu>
1310
        <action
1338
        <action
1311
              class="org.eclipse.cdt.ui.actions.ChangeBuildConfigMenuAction"
1339
              class="org.eclipse.cdt.ui.actions.ChangeBuildConfigMenuAction"
1312
              disabledIcon="icons/dlcl16/config-tool.gif"
1340
              disabledIcon="icons/dlcl16/config-tool.gif"
Lines 1353-1359 Link Here
1353
              class="org.eclipse.cdt.ui.actions.WorkingSetConfigAction"
1381
              class="org.eclipse.cdt.ui.actions.WorkingSetConfigAction"
1354
              id="org.eclipse.cdt.ui.wsselection"
1382
              id="org.eclipse.cdt.ui.wsselection"
1355
              label="%wsselection"
1383
              label="%wsselection"
1356
              menubarPath="project/org.eclipse.cdt.ui.prjmenu/gm3"
1384
              menubarPath="project/org.eclipse.cdt.ui.prjmenu/gm4"
1357
              style="push"
1385
              style="push"
1358
              />
1386
              />
1359
     </actionSet>
1387
     </actionSet>
Lines 3018-3022 Link Here
3018
         </selection>
3046
         </selection>
3019
      </wizard>
3047
      </wizard>
3020
   </extension>
3048
   </extension>
3049
   <extension
3050
         point="org.eclipse.cdt.ui.workingSetConfigurations">
3051
      <projectConfigurationFactory
3052
            class="org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProjectConfigurationFactory$Registry$Default"
3053
            id="org.eclipse.cdt.ui.defaultWorkingSetProjectConfigFactory">
3054
         <projectNature
3055
               id="org.eclipse.cdt.core.cnature">
3056
         </projectNature>
3057
         <projectNature
3058
               id="org.eclipse.cdt.core.ccnature">
3059
         </projectNature>
3060
      </projectConfigurationFactory>
3061
   </extension>
3021
3062
3022
</plugin>
3063
</plugin>
(-)src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.properties (-1 / +41 lines)
Lines 1-5 Link Here
1
###############################################################################
1
###############################################################################
2
# Copyright (c) 2000, 2008 IBM Corporation and others.
2
# Copyright (c) 2000, 2009 IBM Corporation, QNX Software Systems, and others.
3
# All rights reserved. This program and the accompanying materials
3
# All rights reserved. This program and the accompanying materials
4
# are made available under the terms of the Eclipse Public License v1.0
4
# are made available under the terms of the Eclipse Public License v1.0
5
# which accompanies this distribution, and is available at
5
# which accompanies this distribution, and is available at
Lines 8-13 Link Here
8
# Contributors:
8
# Contributors:
9
#     IBM Corporation - initial API and implementation
9
#     IBM Corporation - initial API and implementation
10
#     Anton Leherbauer (Wind River Systems)
10
#     Anton Leherbauer (Wind River Systems)
11
#     QNX Software Systems - [272416] Rework the working set configurations
11
###############################################################################
12
###############################################################################
12
13
13
CElementWorkingSetPage_title= C/C++ Working Set
14
CElementWorkingSetPage_title= C/C++ Working Set
Lines 18-20 Link Here
18
CElementWorkingSetPage_warning_nameMustNotBeEmpty= The name must not be empty.
19
CElementWorkingSetPage_warning_nameMustNotBeEmpty= The name must not be empty.
19
CElementWorkingSetPage_warning_workingSetExists= A working set with that name already exists.
20
CElementWorkingSetPage_warning_workingSetExists= A working set with that name already exists.
20
CElementWorkingSetPage_warning_resourceMustBeChecked= At least one resource must be checked.
21
CElementWorkingSetPage_warning_resourceMustBeChecked= At least one resource must be checked.
22
23
WSConfig_build_problems=Problems occurred in building the working set.
24
WSConfig_build_task=Building working set "{0}"
25
26
WSConfigDialog_activate_label=Set Active
27
WSConfigDialog_active_config={0} (active)
28
WSConfigDialog_add_label=Add...
29
WSConfigDialog_buildPrompt_message=Some projects have had their active configurations changed, and need to be re-built.  Build them now?
30
WSConfigDialog_buildPrompt_title=Build New Configuration
31
WSConfigDialog_implicit_config=(active)
32
WSConfigDialog_projTree_accessible_name=Project configuration selection tree
33
WSConfigDialog_projTree_label=Project configurations:
34
WSConfigDialog_remove_label=Remove
35
WSConfigDialog_rename_label=Rename...
36
WSConfigDialog_title=Manage Working Set Configurations
37
WSConfigDialog_wsTree_accessible_name=Working sets and configurations tree
38
WSConfigDialog_wsTree_label=Working set configurations:
39
40
WSConfigManager_closeFailed=Failed to close working set configurations file.
41
WSConfigManager_loadFailed=Failed to load working set configurations.
42
WSConfigManager_save_job=Saving working set configurations
43
WSConfigManager_saveFailed=Failed to save working set configurations.
44
45
WSConfigsController_addDlg_defaultName=NewConfiguration
46
WSConfigsController_addDlg_emptyName=The name must not be empty.
47
WSConfigsController_addDlg_msg=Enter a name for the new configuration.
48
WSConfigsController_addDlg_nameExists=A configuration with that name already exists.
49
WSConfigsController_addDlg_title=Add Working Set Configuration
50
WSConfigsController_renameDlg_msg=Enter a new name for the configuration.
51
WSConfigsController_renameDlg_title=Rename Working Set Configuration
52
53
WSProjConfig_activatedWarning=Set configuration "{0}" active in project "{1}".
54
WSProjConfig_buildProblem=Problems occurred in building project "{0}".
55
WSProjConfig_noConfig=No configuration selected for project "{0}".
56
57
WSProjConfigFactory_badFactory=Invalid project configuration factory in plug-in {0}.  Expected an IWorkingSetProjectConfigurationFactory.
58
WSProjConfigFactory_factoryFailed=Failed to create project configuration factory.
59
WSProjConfigFactory_noFactoryID=Missing ID in project configuration factory extension in plug-in {0}
60
WSProjConfigFactory_noNatureID=Missing nature ID in project configuration factory in plug-in {0}.
(-)src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.java (-1 / +41 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2009 IBM Corporation, QNX Software Systems, and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     QNX Software Systems - [272416] Rework the working set configurations
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.cdt.internal.ui.workingsets;
12
package org.eclipse.cdt.internal.ui.workingsets;
12
13
Lines 28-33 Link Here
28
	public static String CElementWorkingSetPage_warning_workingSetExists;
29
	public static String CElementWorkingSetPage_warning_workingSetExists;
29
	public static String CElementWorkingSetPage_warning_resourceMustBeChecked;
30
	public static String CElementWorkingSetPage_warning_resourceMustBeChecked;
30
31
32
	public static String WSConfig_build_problems;
33
	public static String WSConfig_build_task;
34
	
35
	public static String WSConfigDialog_activate_label;
36
	public static String WSConfigDialog_active_config;
37
	public static String WSConfigDialog_add_label;
38
	public static String WSConfigDialog_buildPrompt_message;
39
	public static String WSConfigDialog_buildPrompt_title;
40
	public static String WSConfigDialog_implicit_config;
41
	public static String WSConfigDialog_projTree_accessible_name;
42
	public static String WSConfigDialog_projTree_label;
43
	public static String WSConfigDialog_remove_label;
44
	public static String WSConfigDialog_rename_label;
45
	public static String WSConfigDialog_title;
46
	public static String WSConfigDialog_wsTree_accessible_name;
47
	public static String WSConfigDialog_wsTree_label;
48
49
	public static String WSConfigManager_closeFailed;
50
	public static String WSConfigManager_loadFailed;
51
	public static String WSConfigManager_save_job;
52
	public static String WSConfigManager_saveFailed;
53
	
54
	public static String WSConfigsController_addDlg_defaultName;
55
	public static String WSConfigsController_addDlg_emptyName;
56
	public static String WSConfigsController_addDlg_msg;
57
	public static String WSConfigsController_addDlg_nameExists;
58
	public static String WSConfigsController_addDlg_title;
59
	public static String WSConfigsController_renameDlg_msg;
60
	public static String WSConfigsController_renameDlg_title;
61
	
62
	public static String WSProjConfig_activatedWarning;
63
	public static String WSProjConfig_buildProblem;
64
	public static String WSProjConfig_noConfig;
65
	
66
	public static String WSProjConfigFactory_badFactory;
67
	public static String WSProjConfigFactory_factoryFailed;
68
	public static String WSProjConfigFactory_noFactoryID;
69
	public static String WSProjConfigFactory_noNatureID;
70
31
	static {
71
	static {
32
		NLS.initializeMessages(BUNDLE_NAME, WorkingSetMessages.class);
72
		NLS.initializeMessages(BUNDLE_NAME, WorkingSetMessages.class);
33
	}
73
	}
(-)src/org/eclipse/cdt/ui/newui/CDTPrefUtil.java (+12 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Intel Corporation - initial API and implementation
9
 *     Intel Corporation - initial API and implementation
10
 *     QNX Software Systems - [272416] Rework the working set configurations
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.cdt.ui.newui;
12
package org.eclipse.cdt.ui.newui;
12
13
Lines 22-27 Link Here
22
23
23
import org.eclipse.cdt.ui.CUIPlugin;
24
import org.eclipse.cdt.ui.CUIPlugin;
24
25
26
import org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager;
27
25
/**
28
/**
26
 * @noextend This class is not intended to be subclassed by clients.
29
 * @noextend This class is not intended to be subclassed by clients.
27
 * @noinstantiate This class is not intended to be instantiated by clients.
30
 * @noinstantiate This class is not intended to be instantiated by clients.
Lines 226-234 Link Here
226
		return s1;
229
		return s1;
227
	}
230
	}
228
	
231
	
232
	/**
233
	 * @deprecated Use the {@link WorkingSetConfigurationManager} class, instead.
234
	 */
235
	@Deprecated
229
	public static List<String> readConfigSets() {
236
	public static List<String> readConfigSets() {
230
		return new LinkedList<String>(Arrays.asList(getStr(KEY_CONFSET).split(CONFSETDEL)));
237
		return new LinkedList<String>(Arrays.asList(getStr(KEY_CONFSET).split(CONFSETDEL)));
231
	}
238
	}
239
	
240
	/**
241
	 * @deprecated Use the {@link WorkingSetConfigurationManager} class, instead.
242
	 */
243
	@Deprecated
232
	public static void saveConfigSets(List<String> out) {
244
	public static void saveConfigSets(List<String> out) {
233
		StringBuilder b = new StringBuilder(); 
245
		StringBuilder b = new StringBuilder(); 
234
		for (String s : out) {
246
		for (String s : out) {
(-)src/org/eclipse/cdt/ui/newui/PluginResources.properties (-22 / +2 lines)
Lines 1-5 Link Here
1
###############################################################################
1
###############################################################################
2
# Copyright (c) 2000, 2008 IBM Corporation and others.
2
# Copyright (c) 2000, 2009 IBM Corporation, QNX Software Systems, and others.
3
# All rights reserved. This program and the accompanying materials
3
# All rights reserved. This program and the accompanying materials
4
# are made available under the terms of the Eclipse Public License v1.0
4
# are made available under the terms of the Eclipse Public License v1.0
5
# which accompanies this distribution, and is available at
5
# which accompanies this distribution, and is available at
Lines 7-12 Link Here
7
#
7
#
8
# Contributors:
8
# Contributors:
9
# IBM - Initial API and implementation
9
# IBM - Initial API and implementation
10
# QNX Software Systems - [272416] Rework the working set configurations
10
###############################################################################
11
###############################################################################
11
12
12
# ----------- Configuration Selection Page -----------
13
# ----------- Configuration Selection Page -----------
Lines 530-555 Link Here
530
CDTMainWizardPage.1=Project category is selected. Expand the category and select a concrete project type.
531
CDTMainWizardPage.1=Project category is selected. Expand the category and select a concrete project type.
531
CProjectWizard.0=Add C Project Nature
532
CProjectWizard.0=Add C Project Nature
532
CCProjectWizard.0=Add CC Project Nature
533
CCProjectWizard.0=Add CC Project Nature
533
WorkingSetConfigAction.0=Symbols '
534
WorkingSetConfigAction.1=Choose active configs for Working Sets
535
WorkingSetConfigAction.10=-- CURRENT --
536
WorkingSetConfigAction.11=Config Set Name:
537
WorkingSetConfigAction.12=Configuration set already exists: 
538
WorkingSetConfigAction.13=Wrong configuration set data : 
539
WorkingSetConfigAction.14=' should not be in the name
540
WorkingSetConfigAction.15=Config Set '
541
WorkingSetConfigAction.16=' already exists \!
542
WorkingSetConfigAction.17=Configurations list
543
WorkingSetConfigAction.18=New...
544
WorkingSetConfigAction.19=Rename...
545
WorkingSetConfigAction.2=Working Sets
546
WorkingSetConfigAction.20=Save, Build and Exit
547
WorkingSetConfigAction.21=Building project 
534
WorkingSetConfigAction.21=Building project 
548
WorkingSetConfigAction.22=Build error
535
WorkingSetConfigAction.22=Build error
549
WorkingSetConfigAction.3=- NO WORKING SETS -
550
WorkingSetConfigAction.4=Config Sets
551
WorkingSetConfigAction.5=Projects and configurations
552
WorkingSetConfigAction.6=Update config set
553
WorkingSetConfigAction.7=Create config set
554
WorkingSetConfigAction.8=Rename config set
555
WorkingSetConfigAction.9=Delete config set
(-)src/org/eclipse/cdt/ui/actions/WorkingSetConfigAction.java (-569 / +7 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2008 Intel Corporation and others.
2
 * Copyright (c) 2008, 2009 Intel Corporation, QNX Software Systems, and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-94 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Intel Corporation - initial API and implementation
9
 *     Intel Corporation - initial API and implementation
10
 *     QNX Software Systems - [272416] Rework the config sets dialog 
10
 *******************************************************************************/
11
 *******************************************************************************/
11
/**
12
 * 
13
 */
14
package org.eclipse.cdt.ui.actions;
12
package org.eclipse.cdt.ui.actions;
15
13
16
import java.util.ArrayList;
17
import java.util.LinkedHashMap;
18
import java.util.Map;
19
20
import org.eclipse.core.resources.IProject;
21
import org.eclipse.core.resources.IncrementalProjectBuilder;
22
import org.eclipse.core.resources.ResourcesPlugin;
23
import org.eclipse.core.runtime.CoreException;
24
import org.eclipse.core.runtime.IAdaptable;
25
import org.eclipse.core.runtime.IProgressMonitor;
26
import org.eclipse.core.runtime.IStatus;
27
import org.eclipse.core.runtime.Status;
28
import org.eclipse.core.runtime.jobs.Job;
29
import org.eclipse.jface.action.IAction;
14
import org.eclipse.jface.action.IAction;
30
import org.eclipse.jface.dialogs.IDialogConstants;
31
import org.eclipse.jface.dialogs.IInputValidator;
32
import org.eclipse.jface.dialogs.InputDialog;
33
import org.eclipse.jface.dialogs.TrayDialog;
34
import org.eclipse.jface.util.IPropertyChangeListener;
15
import org.eclipse.jface.util.IPropertyChangeListener;
35
import org.eclipse.jface.util.PropertyChangeEvent;
16
import org.eclipse.jface.util.PropertyChangeEvent;
36
import org.eclipse.jface.viewers.ISelection;
17
import org.eclipse.jface.viewers.ISelection;
37
import org.eclipse.jface.window.Window;
38
import org.eclipse.swt.SWT;
39
import org.eclipse.swt.accessibility.AccessibleAdapter;
40
import org.eclipse.swt.accessibility.AccessibleEvent;
41
import org.eclipse.swt.custom.SashForm;
42
import org.eclipse.swt.events.SelectionAdapter;
43
import org.eclipse.swt.events.SelectionEvent;
44
import org.eclipse.swt.events.SelectionListener;
45
import org.eclipse.swt.events.TreeEvent;
46
import org.eclipse.swt.events.TreeListener;
47
import org.eclipse.swt.graphics.Image;
48
import org.eclipse.swt.layout.GridData;
49
import org.eclipse.swt.layout.GridLayout;
50
import org.eclipse.swt.widgets.Button;
51
import org.eclipse.swt.widgets.Composite;
52
import org.eclipse.swt.widgets.Control;
53
import org.eclipse.swt.widgets.Label;
54
import org.eclipse.swt.widgets.List;
55
import org.eclipse.swt.widgets.MessageBox;
56
import org.eclipse.swt.widgets.Shell;
57
import org.eclipse.swt.widgets.Tree;
58
import org.eclipse.swt.widgets.TreeItem;
59
import org.eclipse.ui.IWorkbenchWindow;
18
import org.eclipse.ui.IWorkbenchWindow;
60
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
19
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
61
import org.eclipse.ui.IWorkingSet;
20
import org.eclipse.ui.IWorkingSet;
62
import org.eclipse.ui.IWorkingSetManager;
21
import org.eclipse.ui.IWorkingSetManager;
63
import org.eclipse.ui.PlatformUI;
64
22
65
import org.eclipse.cdt.core.model.CoreModel;
66
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
67
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
68
import org.eclipse.cdt.ui.CUIPlugin;
23
import org.eclipse.cdt.ui.CUIPlugin;
69
import org.eclipse.cdt.ui.newui.CDTHelpContextIds;
70
import org.eclipse.cdt.ui.newui.CDTPrefUtil;
71
import org.eclipse.cdt.ui.newui.UIMessages;
72
24
73
import org.eclipse.cdt.internal.ui.CPluginImages;
25
import org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationDialog;
74
26
75
/**
27
/**
76
 */
28
 */
77
public class WorkingSetConfigAction implements IWorkbenchWindowActionDelegate, IPropertyChangeListener {
29
public class WorkingSetConfigAction implements IWorkbenchWindowActionDelegate, IPropertyChangeListener {
78
	private static final String DELIMITER = " "; //$NON-NLS-1$
79
	private static final String EMPTY_STR = ""; //$NON-NLS-1$
80
	private static final String CURRENT = UIMessages.getString("WorkingSetConfigAction.10"); //$NON-NLS-1$
81
	public static final Image IMG_PROJ = CPluginImages.get(CPluginImages.IMG_OBJS_CFOLDER);
82
	public static final Image IMG_CONF = CPluginImages.get(CPluginImages.IMG_OBJS_CONFIG);
83
	private static final Shell sh = CUIPlugin.getDefault().getShell();
84
	private static final IWorkingSetManager wsm = CUIPlugin.getDefault().getWorkbench().getWorkingSetManager();  
30
	private static final IWorkingSetManager wsm = CUIPlugin.getDefault().getWorkbench().getWorkingSetManager();  
85
	private LinkedHashMap<String, IWorkingSet> workingSetsMap;
86
	private LinkedHashMap<String, ConfigSet> configSetMap;
87
	private boolean enabled = true;
31
	private boolean enabled = true;
88
	
32
	
33
	private IWorkbenchWindow window;
34
	
89
	public void run(IAction action) {
35
	public void run(IAction action) {
90
		LocalDialog dlg = new LocalDialog(sh);		
36
		new WorkingSetConfigurationDialog(window.getShell()).open();
91
		dlg.open();
92
	}
37
	}
93
	
38
	
94
	public void selectionChanged(IAction action, ISelection selection) {
39
	public void selectionChanged(IAction action, ISelection selection) {
Lines 101-106 Link Here
101
		
46
		
102
	}
47
	}
103
	public void init(IWorkbenchWindow window) {
48
	public void init(IWorkbenchWindow window) {
49
		this.window = window;
104
		wsm.addPropertyChangeListener(this);
50
		wsm.addPropertyChangeListener(this);
105
		checkWS();
51
		checkWS();
106
	}
52
	}
Lines 112-627 Link Here
112
		enabled = w.length > 0;
58
		enabled = w.length > 0;
113
		return w;
59
		return w;
114
	}
60
	}
115
	
116
	private String[] getWSnames() {
117
		IWorkingSet[] w = checkWS();
118
		workingSetsMap = new LinkedHashMap<String, IWorkingSet>(w.length); 
119
		for (IWorkingSet ws : w)
120
			workingSetsMap.put(ws.getLabel(), ws);
121
		return workingSetsMap.keySet().toArray(new String[w.length]);
122
	}
123
61
124
	public void propertyChange(PropertyChangeEvent event) {
62
	public void propertyChange(PropertyChangeEvent event) {
125
		checkWS();
63
		checkWS();
126
	}
64
	}
127
	
128
	private class LocalDialog extends TrayDialog {
129
		private List wsets;
130
		private List csets;
131
		private Tree tree;
132
		private Button b1, b2, b3, b4, bb;
133
		
134
		LocalDialog(Shell parentShell) {
135
			super(parentShell);
136
			setHelpAvailable(false);
137
			setShellStyle(getShellStyle()|SWT.RESIZE);
138
		}
139
		@Override
140
		protected void buttonPressed(int buttonId) {
141
			if (buttonId == IDialogConstants.OK_ID) {
142
				saveConfigSets();
143
				saveActiveConfigs();
144
			} else {}
145
			super.buttonPressed(buttonId);
146
		}
147
148
		private void saveConfigSets() {
149
			ArrayList<String> out = new ArrayList<String>(configSetMap.size());
150
			for (ConfigSet cs : configSetMap.values()) 
151
				if (cs.isValid() && !cs.name.equals(CURRENT))
152
					out.add(cs.toString());
153
			CDTPrefUtil.saveConfigSets(out);
154
		}
155
		
156
		private void saveActiveConfigs() {
157
			for (TreeItem ti : tree.getItems()) {
158
				ICProjectDescription pd = (ICProjectDescription)ti.getData();
159
				for (TreeItem ti1: ti.getItems()) {
160
					if (!ti1.getChecked())
161
						continue;
162
					((ICConfigurationDescription)ti1.getData()).setActive();
163
					break;
164
				}
165
				try {
166
					CoreModel.getDefault().setProjectDescription(pd.getProject(), pd);
167
				} catch (CoreException e) {
168
					e.printStackTrace();
169
					CUIPlugin.log(e);
170
				}
171
			}
172
		}
173
		
174
		@Override
175
		protected void configureShell(Shell shell) {
176
			super.configureShell(shell);
177
			shell.setText(UIMessages.getString("WorkingSetConfigAction.1")); //$NON-NLS-1$
178
		}
179
		 
180
		@Override
181
		protected Control createDialogArea(Composite parent) {
182
			PlatformUI.getWorkbench().getHelpSystem().setHelp( getShell(), CDTHelpContextIds.MAN_PROJ_BUILD_PROP);
183
184
			Composite comp = new Composite(parent, SWT.NULL);
185
			comp.setFont(parent.getFont());
186
			comp.setLayout(new GridLayout(2, false));
187
			comp.setLayoutData(new GridData(GridData.FILL_BOTH));
188
189
			// Create the sash form
190
			SashForm sashForm = new SashForm(comp, SWT.NONE);
191
			sashForm.setOrientation(SWT.VERTICAL);
192
			GridData gd = new GridData(GridData.FILL_VERTICAL);
193
			gd.verticalSpan = 3;
194
			sashForm.setLayoutData(gd);
195
196
			Composite ws = new Composite(sashForm, SWT.NULL);
197
			ws.setLayoutData(new GridData(GridData.FILL_BOTH));
198
			ws.setLayout(new GridLayout(1, false));
199
			Label l1 = new Label(ws, SWT.NONE);
200
			l1.setText(UIMessages.getString("WorkingSetConfigAction.2")); //$NON-NLS-1$
201
			l1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
202
			wsets = new List(ws, SWT.SINGLE | SWT.BORDER);
203
			wsets.setLayoutData(new GridData(GridData.FILL_BOTH));
204
			wsets.setItems(getWSnames());
205
206
			wsets.addSelectionListener(new SelectionListener() {
207
				public void widgetDefaultSelected(SelectionEvent e) {
208
					workingSetChanged();
209
				}
210
				public void widgetSelected(SelectionEvent e) {
211
					workingSetChanged();
212
				}});
213
214
			if (wsets.getItemCount() == 0) {
215
				wsets.add(UIMessages.getString("WorkingSetConfigAction.3")); //$NON-NLS-1$
216
				wsets.setEnabled(false);
217
			} else {
218
				IWorkingSet[] w = wsm.getRecentWorkingSets();
219
				if (w == null || w.length == 0)
220
					wsets.setSelection(0);
221
				else {
222
					String s = w[0].getLabel();
223
					String[] ss = wsets.getItems();
224
					for (int i=0; i<ss.length; i++) {
225
						if (ss[i].equals(s)) {
226
							wsets.setSelection(i);
227
							break;
228
						}
229
					}
230
				}
231
			}
232
233
			Composite cs = new Composite(sashForm, SWT.NULL);
234
			cs.setLayoutData(new GridData(GridData.FILL_BOTH));
235
			cs.setLayout(new GridLayout(1, false));
236
			l1 = new Label(cs, SWT.NONE);
237
			l1.setText(UIMessages.getString("WorkingSetConfigAction.4")); //$NON-NLS-1$
238
			l1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
239
			csets = new List(cs, SWT.SINGLE | SWT.BORDER);
240
			csets.setLayoutData(new GridData(GridData.FILL_BOTH));
241
			csets.addSelectionListener(new SelectionListener() {
242
				public void widgetDefaultSelected(SelectionEvent e) {
243
					configSetChanged();
244
				}
245
				public void widgetSelected(SelectionEvent e) {
246
					configSetChanged();
247
				}});
248
249
			sashForm.setWeights(new int[]{50, 50});
250
251
			
252
			l1 = new Label(comp, SWT.NONE);
253
			l1.setText(UIMessages.getString("WorkingSetConfigAction.5")); //$NON-NLS-1$
254
			gd = new GridData(GridData.FILL_HORIZONTAL);
255
			gd.verticalIndent = 5;
256
			l1.setLayoutData(gd);
257
			
258
			tree = new Tree(comp, SWT.SINGLE | SWT.CHECK | SWT.BORDER);
259
			gd = new GridData(GridData.FILL_BOTH);
260
			gd.heightHint = 200;
261
			gd.widthHint  = 200;
262
			tree.setLayoutData(gd);
263
			tree.getAccessible().addAccessibleListener(
264
				new AccessibleAdapter() {                       
265
					@Override
266
					public void getName(AccessibleEvent e) {
267
						e.result = UIMessages.getString("WorkingSetConfigAction.17"); //$NON-NLS-1$
268
					}
269
				}
270
			);
271
			tree.addSelectionListener(new SelectionAdapter() {
272
				@Override
273
				public void widgetSelected(SelectionEvent e) {
274
					if (((e.detail & SWT.CHECK) == SWT.CHECK) && 
275
						 (e.item != null && (e.item instanceof TreeItem))) {
276
						TreeItem sel = (TreeItem)e.item;
277
						if (sel.getData() instanceof ICProjectDescription) {
278
							sel.setChecked(false); // do not check projects !
279
						} else {
280
							// If current item is checked, uncheck remaining ones.
281
							// If current item is unchecked, check the 1st instead.
282
							String txt = sel.getChecked() ? sel.getText() : EMPTY_STR;  
283
							for (TreeItem obj : sel.getParentItem().getItems()) {
284
								if (txt == null)
285
									obj.setChecked(false);
286
								else if (txt == EMPTY_STR || txt.equals(obj.getText())) {
287
									obj.setChecked(true);
288
									txt = null; // do not perform further checks.
289
								} else  
290
									obj.setChecked(false); 
291
							}
292
						}
293
					}
294
				}
295
			});
296
297
			tree.addTreeListener(new TreeListener() {
298
				public void treeCollapsed(TreeEvent e) {
299
				}
300
				public void treeExpanded(TreeEvent e) {
301
				}});
302
			
303
			// Buttons pane
304
			Composite c = new Composite(comp, SWT.NONE);
305
			c.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
306
			c.setLayout(new GridLayout(2, true));
307
308
			b2 = new Button(c, SWT.PUSH);
309
			b2.setText(UIMessages.getString("WorkingSetConfigAction.7")); //$NON-NLS-1$
310
			b2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
311
			b2.addSelectionListener(new SelectionAdapter() {
312
				@Override
313
				public void widgetSelected(SelectionEvent e) {
314
					String newS = getString(UIMessages.getString("WorkingSetConfigAction.18"), null); //$NON-NLS-1$ 
315
				    if (newS == null)
316
				    	return;
317
				    String key = wsets.getSelection()[0] + DELIMITER + newS;
318
					if (configSetMap.containsKey(key))
319
						// error message
320
						return;
321
					ConfigSet cs = new ConfigSet(newS, wsets.getSelection()[0], tree);
322
					configSetMap.put(key, cs);
323
					csets.add(newS);
324
					csets.setSelection(csets.getItemCount() - 1);
325
					updateButtons();
326
				}});
327
328
			b1 = new Button(c, SWT.PUSH);
329
			b1.setText(UIMessages.getString("WorkingSetConfigAction.6")); //$NON-NLS-1$
330
			b1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
331
			b1.addSelectionListener(new SelectionAdapter() {
332
				@Override
333
				public void widgetSelected(SelectionEvent e) {
334
					String oldS = csets.getItem(csets.getSelectionIndex());
335
					ConfigSet cs = new ConfigSet(oldS, wsets.getSelection()[0], tree);
336
					configSetMap.put(wsets.getSelection()[0] + DELIMITER + oldS, cs); // overwrite
337
				}});
338
339
			b3 = new Button(c, SWT.PUSH);
340
			b3.setText(UIMessages.getString("WorkingSetConfigAction.8")); //$NON-NLS-1$
341
			b3.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
342
			b3.addSelectionListener(new SelectionAdapter() {
343
				@Override
344
				public void widgetSelected(SelectionEvent e) {
345
					int n = csets.getSelectionIndex();
346
					if (n > 0) {
347
						String oldS = csets.getItem(n);
348
						String newS = getString(UIMessages.getString("WorkingSetConfigAction.19"), oldS);  //$NON-NLS-1$
349
					    if (newS == null)
350
					    	return;
351
						if (oldS.equals(newS)) // nothing to do
352
							return;
353
						String key = wsets.getSelection()[0] + DELIMITER + newS;
354
						if (configSetMap.containsKey(key)) {
355
							ExistsMessage(newS);
356
							return;
357
						}
358
						ConfigSet cs = configSetMap.get(wsets.getSelection()[0] + DELIMITER + oldS);
359
						configSetMap.remove(cs);
360
						cs.name = newS;
361
						configSetMap.put(key, cs);
362
						csets.setItem(n, newS);
363
					}
364
				}});
365
366
			b4 = new Button(c, SWT.PUSH);
367
			b4.setText(UIMessages.getString("WorkingSetConfigAction.9")); //$NON-NLS-1$
368
			b4.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
369
			b4.addSelectionListener(new SelectionAdapter() {
370
				@Override
371
				public void widgetSelected(SelectionEvent e) {
372
					String[] ss = csets.getSelection();
373
					if (ss != null && ss.length > 0) {
374
						configSetMap.remove(wsets.getSelection()[0] + DELIMITER + ss[0]);
375
						csets.remove(ss[0]);
376
						csets.setSelection(0);
377
						updateButtons();
378
					}
379
				}});
380
381
	        bb = new Button(c, SWT.PUSH);
382
	        bb.setText(UIMessages.getString("WorkingSetConfigAction.20")); //$NON-NLS-1$
383
	        gd = new GridData(GridData.FILL_HORIZONTAL);
384
	        gd.horizontalSpan = 2;
385
        	bb.setLayoutData(gd);
386
			bb.addSelectionListener(new SelectionAdapter() {
387
				@Override
388
				public void widgetSelected(SelectionEvent e) {
389
					build();
390
					LocalDialog.this.close();
391
				}});
392
			
393
			initData();
394
			return comp;
395
		}
396
397
		private void initData() {
398
			configSetMap = new LinkedHashMap<String, ConfigSet>();
399
			for (String s : CDTPrefUtil.readConfigSets()) {
400
				ConfigSet cs = new ConfigSet(s);
401
				if (cs.isValid())
402
					configSetMap.put(cs.workingSetLabel + DELIMITER + cs.name, cs);
403
			}
404
			workingSetChanged();
405
		}
406
		
407
		private void updateButtons() {
408
			Button ok =	this.getButton(IDialogConstants.OK_ID);
409
			boolean en = csets.getSelectionIndex() > 0;
410
			if (! wsets.getEnabled()) {
411
				b2.setEnabled(false); // new
412
				if (ok != null)
413
					ok.setEnabled(false); // OK
414
				en = false;
415
			}
416
			b1.setEnabled(en); // update
417
			b3.setEnabled(en); // rename
418
			b4.setEnabled(en); // delete
419
			bb.setEnabled(wsets.getEnabled());
420
		}
421
		private void workingSetChanged() {
422
//			tree.setRedraw(false);
423
			tree.removeAll();
424
			String[] ss = wsets.getSelection();
425
			if (ss == null || ss.length == 0)
426
				return;
427
			IWorkingSet ws = workingSetsMap.get(ss[0]);
428
			fillTree(ws);
429
			tree.setRedraw(true);
430
//			csets.setRedraw(false);
431
			csets.removeAll();
432
			csets.add(CURRENT);
433
			csets.setSelection(0);
434
			
435
			configSetMap.remove(CURRENT); // previous default object, if any
436
			for (Map.Entry<String, ConfigSet> me : configSetMap.entrySet()) {
437
				if (me.getValue().workingSetLabel.equals(ws.getLabel()))
438
					csets.add(me.getValue().name);
439
			}
440
			configSetMap.put(CURRENT, new ConfigSet(CURRENT, ws.getLabel(), tree));
441
			csets.setRedraw(true);
442
			updateButtons();
443
			
444
			// calls from FillTree does not work...
445
			for (TreeItem ti : tree.getItems())
446
				ti.setExpanded(true);
447
		}
448
		
449
		/**
450
		 * Update projects tree for selected working set.
451
		 * @param ws - working set selected.
452
		 */
453
		private void fillTree(IWorkingSet ws) {
454
			if (ws == null) 
455
				return;
456
			for (IAdaptable ad : ws.getElements()) {
457
				IProject p = (IProject)ad.getAdapter(IProject.class);
458
				if (p == null) 
459
					continue;
460
				ICProjectDescription prjd = CoreModel.getDefault().getProjectDescription(p, true);
461
				if (prjd == null)
462
					continue;
463
				ICConfigurationDescription[] cfgs = prjd.getConfigurations();
464
				if (cfgs == null || cfgs.length == 0)
465
					continue;
466
				TreeItem ti = new TreeItem(tree, SWT.NONE);
467
				ti.setText(prjd.getName());
468
				ti.setImage(IMG_PROJ);
469
				ti.setData(prjd);
470
				for (ICConfigurationDescription c : cfgs) {
471
					TreeItem ti1 = new TreeItem(ti, SWT.NONE);
472
					ti1.setText(c.getName());
473
					ti1.setImage(IMG_CONF);
474
					ti1.setChecked(c.isActive());
475
					ti1.setData(c);
476
				}
477
			}
478
		}
479
		
480
		private void configSetChanged() {
481
			int i = csets.getSelectionIndex();
482
			if (i >= 0) {
483
				String key = (i == 0) ? CURRENT : wsets.getSelection()[0] + DELIMITER + csets.getItem(i);
484
				ConfigSet cs = configSetMap.get(key);
485
				if (cs != null && cs.isValid()) {
486
					for (TreeItem ti : tree.getItems()) {
487
						ICProjectDescription prjd = (ICProjectDescription)ti.getData();
488
						String cid = cs.data.get(prjd.getName());
489
						if (cid == null)
490
							continue; // the project not in the list
491
						for (TreeItem ti1 : ti.getItems()) {
492
							ICConfigurationDescription cfg = (ICConfigurationDescription)ti1.getData();
493
							ti1.setChecked(cid.equals(cfg.getId()));
494
						}
495
					}
496
				}
497
			}
498
			updateButtons();
499
		}
500
501
		private String getString(String title, String value) { 
502
			InputDialog d = new InputDialog(sh, title, 
503
					UIMessages.getString("WorkingSetConfigAction.11"), //$NON-NLS-1$ 
504
					value, new IInputValidator() {
505
						public String isValid(String newText) {
506
							if (newText.indexOf(CDTPrefUtil.CONFSETDEL) >= 0)
507
								return UIMessages.getString("WorkingSetConfigAction.0") + CDTPrefUtil.CONFSETDEL + UIMessages.getString("WorkingSetConfigAction.14"); //$NON-NLS-1$ //$NON-NLS-2$
508
							if (configSetMap.containsKey(wsets.getSelection()[0] + DELIMITER + newText))
509
								return UIMessages.getString("WorkingSetConfigAction.15") + newText + UIMessages.getString("WorkingSetConfigAction.16"); //$NON-NLS-1$ //$NON-NLS-2$
510
							return null;
511
						}}); 
512
			if (d.open() == Window.OK) 
513
				return d.getValue().replace(' ', '_'); // space is delimiter.
514
			return null;
515
		}
516
		
517
		private void ExistsMessage(String s) {
518
			MessageBox box = new MessageBox(sh, SWT.ICON_ERROR);
519
			box.setMessage(UIMessages.getString("WorkingSetConfigAction.12") + s); //$NON-NLS-1$
520
			box.open();
521
		}
522
		
523
		private void build() {
524
			saveConfigSets();
525
			saveActiveConfigs();
526
			IProject[] ps = new IProject[tree.getItemCount()];
527
			int cnt = 0;
528
			for (TreeItem ti : tree.getItems()) 
529
				ps[cnt++] = ((ICProjectDescription)ti.getData()).getProject();
530
			Job buildJob = new BuildJob(ps);
531
			buildJob.schedule();
532
		}
533
	}
534
535
	private static final class BuildJob extends Job {
536
		IProject[] ps;
537
		
538
		BuildJob(IProject[] _ps) {
539
			super(UIMessages.getString("WorkingSetConfigAction.21")); //$NON-NLS-1$
540
			ps = _ps;
541
		}
542
543
		/* (non-Javadoc)
544
		 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
545
		 */
546
		@Override
547
		protected IStatus run(IProgressMonitor monitor) {
548
			for (IProject p:ps) 
549
				try {
550
					setName(UIMessages.getString("WorkingSetConfigAction.21") + p.getName()); //$NON-NLS-1$
551
					p.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);
552
			} catch (CoreException e) {
553
				return new Status(IStatus.ERROR, UIMessages.getString("WorkingSetConfigAction.22"), e.getLocalizedMessage()); //$NON-NLS-1$
554
			}
555
			if (monitor.isCanceled()) {
556
				return Status.CANCEL_STATUS;
557
			}
558
			monitor.done();
559
			return Status.OK_STATUS;
560
		}
561
562
		@Override
563
		public boolean belongsTo(Object family) {
564
			return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
565
		}
566
567
	}
568
	
569
	private static class ConfigSet {
570
		String name;
571
		String workingSetLabel;
572
		LinkedHashMap<String, String> data;
573
		
574
		private ConfigSet(String s) {
575
			data = new LinkedHashMap<String, String>();
576
			String[] ss = s.split(DELIMITER);
577
			if (ss == null || ss.length < 4 || ss.length %2 == 1) {
578
				CUIPlugin.getDefault().logErrorMessage(UIMessages.getString("WorkingSetConfigAction.13") + s); //$NON-NLS-1$
579
				return; // not valid
580
			}
581
			name = ss[0];
582
			workingSetLabel = ss[1];
583
			int n = (ss.length - 2) / 2;
584
			for (int i=0; i<n; i++) 
585
				data.put(ss[2 + i * 2], ss[3 + i * 2]);
586
		}
587
		
588
		private ConfigSet(String n, String w, Tree t) {
589
			data = new LinkedHashMap<String, String>();
590
			name = n;
591
			workingSetLabel = w;
592
			for (TreeItem ti : t.getItems()) {
593
				ICProjectDescription prjd = (ICProjectDescription)ti.getData();
594
				for (TreeItem ti1 : ti.getItems()) {
595
					if (ti1.getChecked()) {
596
						ICConfigurationDescription cfg = (ICConfigurationDescription)ti1.getData();
597
						data.put(prjd.getName(), cfg.getId());
598
						break;
599
					}
600
				}
601
			}
602
603
		}
604
		
605
		private boolean isValid() {
606
			return data.size() > 0;
607
		}
608
		
609
		@Override
610
		public String toString() {
611
			if (!isValid())
612
				return EMPTY_STR;
613
			StringBuilder b = new StringBuilder();
614
			b.append(name);
615
			b.append(DELIMITER);
616
			b.append(workingSetLabel);
617
			b.append(DELIMITER);
618
			for (Map.Entry<String, String> me : data.entrySet()) {
619
				b.append(me.getKey());
620
				b.append(DELIMITER);
621
				b.append(me.getValue());
622
				b.append(DELIMITER);
623
			}
624
			return b.toString().trim();
625
		}
626
	}
627
}
65
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/ProjectConfigsController.java (+328 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.util.Map;
15
16
import org.eclipse.jface.viewers.CheckStateChangedEvent;
17
import org.eclipse.jface.viewers.CheckboxTreeViewer;
18
import org.eclipse.jface.viewers.ICheckStateListener;
19
import org.eclipse.jface.viewers.ILabelProvider;
20
import org.eclipse.jface.viewers.ITreeContentProvider;
21
import org.eclipse.jface.viewers.LabelProvider;
22
import org.eclipse.jface.viewers.StructuredSelection;
23
import org.eclipse.jface.viewers.Viewer;
24
import org.eclipse.swt.events.DisposeEvent;
25
import org.eclipse.swt.events.DisposeListener;
26
import org.eclipse.swt.graphics.Image;
27
28
/**
29
 * View controller for the project configurations pane of the working set configurations dialog. It takes care
30
 * of coordinating the user gestures in that pane with the working-set configuration model and vice-versa.
31
 * 
32
 * @author Christian W. Damus (cdamus)
33
 * 
34
 * @since 6.0
35
 * 
36
 */
37
class ProjectConfigsController implements ICheckStateListener, DisposeListener {
38
	private CheckboxTreeViewer tree;
39
40
	private IWorkingSetConfiguration.ISnapshot workingSet;
41
	private WorkingSetConfigsController workingSetController;
42
43
	private ControllerContext controllerContext;
44
45
	private ILabelProvider labelProvider = new DelegatingLabelProvider();
46
	private ITreeContentProvider contentProvider = new DelegatingContentProvider();
47
48
	/**
49
	 * Initializes me.
50
	 */
51
	ProjectConfigsController() {
52
		super();
53
	}
54
55
	/**
56
	 * Assigns the tree viewer that I control.
57
	 * 
58
	 * @param tree
59
	 *            my tree viewer
60
	 */
61
	void setTreeViewer(CheckboxTreeViewer tree) {
62
		if (this.tree != null) {
63
			this.tree.getTree().removeDisposeListener(this);
64
			this.tree.removeCheckStateListener(this);
65
			this.tree.setLabelProvider(null);
66
			this.tree.setContentProvider(null);
67
		}
68
69
		this.tree = tree;
70
71
		if (this.tree != null) {
72
			this.tree.setUseHashlookup(true);
73
			this.tree.setContentProvider(contentProvider);
74
			this.tree.setLabelProvider(labelProvider);
75
			this.tree.addCheckStateListener(this);
76
			this.tree.getTree().addDisposeListener(this);
77
		}
78
	}
79
80
	/**
81
	 * Injects the current selection of a working set from the Working Set Configurations pane. This changes
82
	 * the project configurations that I show in my own tree.
83
	 * 
84
	 * @param config
85
	 *            the new working set configuration selection. May be <code>null</code> if there is no
86
	 *            selection
87
	 */
88
	void setWorkingSetConfiguration(IWorkingSetConfiguration.ISnapshot config) {
89
		if ((tree != null) && (config != workingSet)) {
90
			this.workingSet = config;
91
92
			tree.setSelection(new StructuredSelection());
93
			
94
			if (config != null) {
95
				controllerContext = new ControllerContext();
96
				tree.setInput(config);
97
				tree.getTree().setEnabled(true);
98
				updateCheckState(config);
99
				tree.expandToLevel(2);
100
			} else {
101
				tree.getTree().setEnabled(false);
102
				tree.setInput(config);
103
				controllerContext.dispose();
104
				controllerContext = null;
105
			}
106
		}
107
	}
108
109
	/**
110
	 * Queries the current working set configuration that I show in my tree.
111
	 * 
112
	 * @return the working set configuration, or <code>null</code> if none
113
	 */
114
	IWorkingSetConfiguration.ISnapshot getWorkingSetConfiguration() {
115
		return workingSet;
116
	}
117
118
	public void checkStateChanged(CheckStateChangedEvent event) {
119
		Object element = event.getElement();
120
		IWorkingSetProjectConfigurationController controller = controllerContext
121
				.controllerForElement(element);
122
123
		if (controller != null) {
124
			controller.checkStateChanged(element, event.getChecked(), controllerContext);
125
126
		} else {
127
			// controller unknown? Cannot change the check-state
128
			tree.setChecked(element, !event.getChecked());
129
		}
130
	}
131
132
	public void widgetDisposed(DisposeEvent e) {
133
		dispose();
134
	}
135
136
	/**
137
	 * Computes the initial check-box settings for my tree according to the current state of the specified
138
	 * working set configuration.
139
	 * 
140
	 * @param config
141
	 *            a working set configuration that I am now showing
142
	 */
143
	private void updateCheckState(IWorkingSetConfiguration.ISnapshot config) {
144
		for (IWorkingSetProjectConfiguration project : config.getProjectConfigurations()) {
145
			IWorkingSetProjectConfigurationController controller = controllerContext
146
					.controllerForElement(project);
147
148
			if (controller != null) {
149
				controller.updateCheckState(controllerContext);
150
			}
151
		}
152
	}
153
154
	/**
155
	 * Connects me to the controller of the working set configurations pane.
156
	 * 
157
	 * @param controller
158
	 *            the working-set configs controller
159
	 */
160
	void setWorkingSetConfigurationsController(WorkingSetConfigsController controller) {
161
		workingSetController = controller;
162
	}
163
164
	void dispose() {
165
		if (controllerContext != null) {
166
			controllerContext.dispose();
167
			controllerContext = null;
168
		}
169
	}
170
171
	//
172
	// Nested classes
173
	//
174
175
	private class ControllerContext implements IWorkingSetProjectConfigurationController.IControllerContext {
176
177
		private Map<Object, IWorkingSetProjectConfigurationController> elementToControllerMap;
178
179
		private Map<IWorkingSetProjectConfigurationController, ITreeContentProvider> contentProviders;
180
		private Map<IWorkingSetProjectConfigurationController, ILabelProvider> labelProviders;
181
182
		ControllerContext() {
183
			elementToControllerMap = new java.util.IdentityHashMap<Object, IWorkingSetProjectConfigurationController>();
184
			contentProviders = new java.util.HashMap<IWorkingSetProjectConfigurationController, ITreeContentProvider>();
185
			labelProviders = new java.util.HashMap<IWorkingSetProjectConfigurationController, ILabelProvider>();
186
187
			for (IWorkingSetProjectConfiguration next : getWorkingSetConfiguration()
188
					.getProjectConfigurations()) {
189
190
				IWorkingSetProjectConfiguration.ISnapshot project = (IWorkingSetProjectConfiguration.ISnapshot) next;
191
192
				IWorkingSetProjectConfigurationController controller = IWorkingSetProjectConfigurationFactory.Registry.INSTANCE
193
						.getFactory(project.resolveProject()).createProjectConfigurationController(project);
194
195
				if (controller == null) {
196
					// can only supply the default behaviour, then
197
					controller = new ProjectConfigurationController(project);
198
				}
199
200
				elementToControllerMap.put(project, controller);
201
				contentProviders.put(controller, controller.getContentProvider());
202
				labelProviders.put(controller, controller.getLabelProvider());
203
204
				discoverElements(controller, project, contentProviders.get(controller));
205
			}
206
		}
207
208
		private void discoverElements(IWorkingSetProjectConfigurationController controller, Object element,
209
				ITreeContentProvider provider) {
210
			Object[] children = provider.getChildren(element);
211
212
			for (Object next : children) {
213
				elementToControllerMap.put(next, controller);
214
				discoverElements(controller, next, provider);
215
			}
216
		}
217
218
		IWorkingSetProjectConfigurationController controllerForElement(Object element) {
219
			return elementToControllerMap.get(element);
220
		}
221
222
		ITreeContentProvider contentProviderForElement(Object element) {
223
			return contentProviders.get(elementToControllerMap.get(element));
224
		}
225
226
		ILabelProvider labelProviderForElement(Object element) {
227
			return labelProviders.get(elementToControllerMap.get(element));
228
		}
229
230
		public void activationStateChanged(IWorkingSetProjectConfiguration projectConfiguration) {
231
			workingSetController.projectSelectionsChanged(projectConfiguration);
232
		}
233
234
		public boolean isReadOnly() {
235
			return getWorkingSetConfiguration().isReadOnly();
236
		}
237
238
		public void setChecked(Object element, boolean checked) {
239
			tree.setChecked(element, checked);
240
		}
241
242
		public void update(Object element) {
243
			if ((element instanceof IWorkingSetConfiguration) || (element instanceof IWorkingSetProxy)) {
244
				// TODO: Talk to the WS controller
245
			} else if (controllerForElement(element) != null) {
246
				// only need to update if we have actually accessed this
247
				// element, yet, in order to display it
248
				tree.update(element, null);
249
			}
250
		}
251
252
		public void dispose() {
253
			elementToControllerMap = null;
254
255
			if (contentProviders != null) {
256
				for (ITreeContentProvider next : contentProviders.values()) {
257
					next.dispose();
258
				}
259
				contentProviders = null;
260
			}
261
262
			if (labelProviders != null) {
263
				for (ILabelProvider next : labelProviders.values()) {
264
					next.dispose();
265
				}
266
				labelProviders = null;
267
			}
268
		}
269
	}
270
271
	private class DelegatingLabelProvider extends LabelProvider {
272
		@Override
273
		public String getText(Object element) {
274
			ILabelProvider delegate = delegateFor(element);
275
276
			return (delegate != null) ? delegate.getText(element) : super.getText(element);
277
		}
278
279
		@Override
280
		public Image getImage(Object element) {
281
			ILabelProvider delegate = delegateFor(element);
282
283
			return (delegate != null) ? delegate.getImage(element) : super.getImage(element);
284
		}
285
286
		private ILabelProvider delegateFor(Object element) {
287
			return (controllerContext == null) ? null : controllerContext.labelProviderForElement(element);
288
		}
289
	}
290
291
	private class DelegatingContentProvider implements ITreeContentProvider {
292
		private final Object[] NO_OBJECTS = new Object[0];
293
294
		public Object[] getChildren(Object parentElement) {
295
			ITreeContentProvider delegate = delegateFor(parentElement);
296
297
			return (delegate != null) ? delegate.getChildren(parentElement) : NO_OBJECTS;
298
		}
299
300
		public Object getParent(Object element) {
301
			ITreeContentProvider delegate = delegateFor(element);
302
303
			return (delegate != null) ? delegate.getParent(element) : null;
304
		}
305
306
		public boolean hasChildren(Object element) {
307
			ITreeContentProvider delegate = delegateFor(element);
308
309
			return (delegate != null) && delegate.hasChildren(element);
310
		}
311
312
		public Object[] getElements(Object inputElement) {
313
			return getWorkingSetConfiguration().getProjectConfigurations().toArray();
314
		}
315
316
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
317
			// nothing to do
318
		}
319
320
		public void dispose() {
321
			// nothing of my own to dispose
322
		}
323
324
		private ITreeContentProvider delegateFor(Object element) {
325
			return (controllerContext == null) ? null : controllerContext.contentProviderForElement(element);
326
		}
327
	}
328
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetProjectConfiguration.java (+284 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import static org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager.ATTR_CONFIG;
15
import static org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager.ATTR_NAME;
16
17
import java.util.Arrays;
18
import java.util.Collection;
19
import java.util.Collections;
20
21
import org.eclipse.core.resources.IProject;
22
import org.eclipse.core.resources.IncrementalProjectBuilder;
23
import org.eclipse.core.resources.ResourcesPlugin;
24
import org.eclipse.core.runtime.CoreException;
25
import org.eclipse.core.runtime.IProgressMonitor;
26
import org.eclipse.core.runtime.IStatus;
27
import org.eclipse.core.runtime.MultiStatus;
28
import org.eclipse.core.runtime.Status;
29
import org.eclipse.core.runtime.SubMonitor;
30
import org.eclipse.osgi.util.NLS;
31
import org.eclipse.ui.IMemento;
32
33
import org.eclipse.cdt.core.model.CoreModel;
34
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
35
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
36
import org.eclipse.cdt.ui.CUIPlugin;
37
38
/**
39
 * Default implementation of the {@link IWorkingSetProjectConfiguration} interface. Clients may extend this
40
 * class to implement additional project configuration settings.
41
 * 
42
 * @author Christian W. Damus (cdamus)
43
 * 
44
 * @since 6.0
45
 * 
46
 */
47
public class WorkingSetProjectConfiguration implements IWorkingSetProjectConfiguration {
48
	private final IWorkingSetConfiguration workingSetConfig;
49
	private String projectName;
50
	private String selectedConfiguration;
51
52
	/**
53
	 * Initializes me with my parent working set configuration.
54
	 * 
55
	 * @param parent
56
	 *            my parent working set configuration
57
	 */
58
	protected WorkingSetProjectConfiguration(IWorkingSetConfiguration parent) {
59
		this.workingSetConfig = parent;
60
	}
61
62
	public IWorkingSetConfiguration getWorkingSetConfiguration() {
63
		return workingSetConfig;
64
	}
65
66
	public String getProjectName() {
67
		return projectName;
68
	}
69
70
	/**
71
	 * Sets my project name. Note that this <b>does not</b> change the name of the project that I represent.
72
	 * Rather, it changes <i>which</i> project I represent.
73
	 * 
74
	 * @param projectName
75
	 *            my new project name
76
	 */
77
	protected void setProjectName(String projectName) {
78
		this.projectName = projectName;
79
	}
80
81
	public IProject resolveProject() {
82
		IProject result = ResourcesPlugin.getWorkspace().getRoot().getProject(getProjectName());
83
84
		if ((result != null) && !result.isAccessible()) {
85
			result = null;
86
		}
87
88
		return result;
89
	}
90
91
	public String getSelectedConfigurationID() {
92
		return selectedConfiguration;
93
	}
94
95
	public void setSelectedConfigurationID(String id) {
96
		this.selectedConfiguration = id;
97
	}
98
99
	public ICConfigurationDescription resolveSelectedConfiguration() {
100
		ICConfigurationDescription result = null;
101
102
		IProject project = resolveProject();
103
		if (project != null) {
104
			ICProjectDescription desc = CoreModel.getDefault().getProjectDescription(project);
105
106
			if (desc != null) {
107
				result = desc.getConfigurationById(getSelectedConfigurationID());
108
			}
109
		}
110
111
		return result;
112
	}
113
114
	public Collection<ICConfigurationDescription> resolveConfigurations() {
115
		ICConfigurationDescription[] result = null;
116
117
		IProject project = resolveProject();
118
		if (project != null) {
119
			ICProjectDescription desc = CoreModel.getDefault().getProjectDescription(project);
120
121
			if (desc != null) {
122
				result = desc.getConfigurations();
123
			}
124
		}
125
126
		return (result == null) ? Collections.<ICConfigurationDescription> emptyList() : Arrays
127
				.asList(result);
128
	}
129
130
	public boolean isActive() {
131
		ICConfigurationDescription desc = resolveSelectedConfiguration();
132
133
		return (desc != null) && desc.isActive();
134
	}
135
136
	public void activate() {
137
		ICConfigurationDescription config = resolveSelectedConfiguration();
138
139
		if (config != null) {
140
			ICProjectDescription desc = config.getProjectDescription();
141
142
			if (desc.getActiveConfiguration() != config) {
143
				try {
144
					IProject project = desc.getProject();
145
					desc.setActiveConfiguration(config);
146
					CoreModel.getDefault().setProjectDescription(project, desc);
147
				} catch (CoreException e) {
148
					CUIPlugin.log(e);
149
				}
150
			}
151
		}
152
	}
153
154
	public IStatus build(IProgressMonitor monitor) {
155
		IStatus result = Status.OK_STATUS;
156
157
		ICConfigurationDescription config = resolveSelectedConfiguration();
158
159
		if (config == null) {
160
			result = new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID, NLS.bind(
161
					WorkingSetMessages.WSProjConfig_noConfig, getProjectName()));
162
		} else {
163
			if (!isActive()) {
164
				activate();
165
				result = new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID, NLS.bind(
166
						WorkingSetMessages.WSProjConfig_activatedWarning, config.getName(), getProjectName()));
167
			}
168
169
			monitor = SubMonitor.convert(monitor);
170
171
			try {
172
				resolveProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);
173
			} catch (CoreException e) {
174
				if (result.isOK()) {
175
					result = e.getStatus();
176
				} else {
177
					result = new MultiStatus(CUIPlugin.PLUGIN_ID, 0, new IStatus[] { result, e.getStatus() },
178
							NLS.bind(WorkingSetMessages.WSProjConfig_buildProblem, getProjectName()), null);
179
				}
180
			}
181
		}
182
183
		return result;
184
	}
185
186
	public void saveState(IMemento memento) {
187
		memento.putString(ATTR_NAME, getProjectName());
188
189
		if (getSelectedConfigurationID() != null) {
190
			memento.putString(ATTR_CONFIG, getSelectedConfigurationID());
191
		}
192
	}
193
194
	public void loadState(IMemento memento) {
195
		projectName = memento.getString(ATTR_NAME);
196
		selectedConfiguration = memento.getString(ATTR_CONFIG);
197
	}
198
199
	public ISnapshot createSnapshot(IWorkingSetConfiguration.ISnapshot workingSetConfig,
200
			WorkspaceSnapshot workspace) {
201
202
		return new Snapshot(workingSetConfig, this, workspace);
203
	}
204
205
	//
206
	// Nested classes
207
	//
208
209
	/**
210
	 * Default implementation of the mutable project configuration snapshot.
211
	 * 
212
	 * @author Christian W. Damus (cdamus)
213
	 * 
214
	 * @since 6.0
215
	 */
216
	public static class Snapshot extends WorkingSetProjectConfiguration implements
217
			IWorkingSetProjectConfiguration.ISnapshot {
218
219
		private final IProject project;
220
		private final WorkspaceSnapshot workspace;
221
222
		/**
223
		 * Initializes me with the project that I represent and the workspace snapshot. I discover the
224
		 * currently defined configurations for my project and initially select the one that is currently
225
		 * active, or the first available if none is active (which would be odd).
226
		 * 
227
		 * @param parent
228
		 *            my parent working set configuration
229
		 * @param projectConfig
230
		 *            the project configuration to copy
231
		 * @param workspace
232
		 *            the current workspace snapshot
233
		 */
234
		protected Snapshot(IWorkingSetConfiguration parent, IWorkingSetProjectConfiguration projectConfig,
235
				WorkspaceSnapshot workspace) {
236
237
			super(parent);
238
239
			this.project = projectConfig.resolveProject();
240
			this.workspace = workspace;
241
242
			String selected = projectConfig.getSelectedConfigurationID();
243
			if (selected == null) {
244
				selected = workspace.getOriginalActiveConfigurationID(project);
245
			}
246
			setSelectedConfigurationID(selected);
247
		}
248
249
		@Override
250
		public IWorkingSetConfiguration.ISnapshot getWorkingSetConfiguration() {
251
			return (IWorkingSetConfiguration.ISnapshot) super.getWorkingSetConfiguration();
252
		}
253
254
		@Override
255
		public final IProject resolveProject() {
256
			return project;
257
		}
258
259
		@Override
260
		public final String getProjectName() {
261
			return resolveProject().getName();
262
		}
263
264
		@Override
265
		public boolean isActive() {
266
			return workspace.isActive(this);
267
		}
268
269
		@Override
270
		public void activate() {
271
			workspace.activate(resolveProject(), getSelectedConfigurationID());
272
		}
273
274
		@Override
275
		public Collection<ICConfigurationDescription> resolveConfigurations() {
276
			return workspace.getConfigurations(resolveProject());
277
		}
278
279
		@Override
280
		public ICConfigurationDescription resolveSelectedConfiguration() {
281
			return workspace.getConfiguration(resolveProject(), getSelectedConfigurationID());
282
		}
283
	}
284
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetProxy.java (+279 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import static org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager.ATTR_NAME;
15
import static org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager.KEY_CONFIG;
16
17
import java.util.Collection;
18
import java.util.Map;
19
import java.util.Set;
20
21
import org.eclipse.core.resources.IProject;
22
import org.eclipse.core.runtime.IAdaptable;
23
import org.eclipse.ui.IMemento;
24
import org.eclipse.ui.IWorkingSet;
25
26
/**
27
 * Default implementation of the {@link IWorkingSetProxy} interface.
28
 * 
29
 * @noextend This class is not intended to be subclassed by clients.
30
 * 
31
 * @author Christian W. Damus (cdamus)
32
 * 
33
 * @since 6.0
34
 */
35
public class WorkingSetProxy implements IWorkingSetProxy {
36
	private String name;
37
	private Map<String, IWorkingSetConfiguration> configurations;
38
39
	/**
40
	 * Initializes me.
41
	 */
42
	public WorkingSetProxy() {
43
		super();
44
	}
45
46
	public String getName() {
47
		return name;
48
	}
49
50
	/**
51
	 * Sets my name. This <b>does not</b> change the name of the working set that I represent. Rather, it
52
	 * changes <i>which</i> working set I represent.
53
	 * 
54
	 * @param name
55
	 *            my new name
56
	 */
57
	void setName(String name) {
58
		this.name = name;
59
	}
60
61
	public IWorkingSet resolve() {
62
		return WorkingSetConfigurationManager.WS_MGR.getWorkingSet(name);
63
	}
64
65
	public Collection<IProject> resolveProjects() {
66
		Set<IProject> result = new java.util.HashSet<IProject>();
67
68
		IWorkingSet resolvedWS = resolve();
69
		if (resolvedWS != null) {
70
			for (IAdaptable next : resolvedWS.getElements()) {
71
				IProject proj = (IProject) next.getAdapter(IProject.class);
72
73
				if (proj != null) {
74
					result.add(proj);
75
				}
76
			}
77
		}
78
79
		return result;
80
	}
81
82
	public boolean isValid() {
83
		return !resolveProjects().isEmpty();
84
	}
85
86
	private Map<String, IWorkingSetConfiguration> getConfigurationsMap() {
87
		if (configurations == null) {
88
			configurations = new java.util.HashMap<String, IWorkingSetConfiguration>();
89
		}
90
91
		return configurations;
92
	}
93
94
	public IWorkingSetConfiguration getConfiguration(String name) {
95
		return getConfigurationsMap().get(name);
96
	}
97
98
	public Collection<IWorkingSetConfiguration> getConfigurations() {
99
		return getConfigurationsMap().values();
100
	}
101
102
	public void saveState(IMemento memento) {
103
		memento.putString(ATTR_NAME, getName());
104
105
		for (IWorkingSetConfiguration next : getConfigurations()) {
106
			if (!isTransient(next)) {
107
				next.saveState(memento.createChild(KEY_CONFIG));
108
			}
109
		}
110
	}
111
112
	/**
113
	 * Queries whether the specified configuration is transient, meaning that it should not be persisted in
114
	 * the working set configuration store. The default implementation just returns <code>false</code>;
115
	 * subclasses may redefine as required.
116
	 * 
117
	 * @param config
118
	 *            a working set configuration
119
	 * @return whether it should be omitted from persistence
120
	 */
121
	protected boolean isTransient(IWorkingSetConfiguration config) {
122
		return false;
123
	}
124
125
	public void loadState(IMemento memento) {
126
		setName(memento.getString(ATTR_NAME));
127
128
		for (IMemento next : memento.getChildren(KEY_CONFIG)) {
129
			IWorkingSetConfiguration config = createWorkingSetConfiguration();
130
			config.loadState(next);
131
			getConfigurationsMap().put(config.getName(), config);
132
		}
133
	}
134
135
	/**
136
	 * Creates a new child working set configuration element. Subclasses may override to create custom
137
	 * implementations.
138
	 * 
139
	 * @return the new working set configuration
140
	 */
141
	protected IWorkingSetConfiguration createWorkingSetConfiguration() {
142
		return new WorkingSetConfiguration(this);
143
	}
144
145
	/**
146
	 * Provides simple access to the child configurations, to remove the specified configuration.
147
	 * 
148
	 * @param config
149
	 *            a configuration to remove
150
	 */
151
	protected void basicRemoveConfiguration(IWorkingSetConfiguration config) {
152
		getConfigurationsMap().remove(config.getName());
153
	}
154
155
	/**
156
	 * Provides simple access to the child configurations, to add the specified configuration.
157
	 * 
158
	 * @param config
159
	 *            a configuration to add
160
	 */
161
	protected void basicAddConfiguration(IWorkingSetConfiguration config) {
162
		getConfigurationsMap().put(config.getName(), config);
163
	}
164
165
	public ISnapshot createSnapshot(WorkspaceSnapshot workspace) {
166
		Snapshot result = new Snapshot(this, workspace);
167
		
168
		result.updateActiveConfigurations();
169
		
170
		return result;
171
	}
172
173
	//
174
	// Nested classes
175
	//
176
177
	/**
178
	 * The default implementation of a mutable working set snapshot.
179
	 * 
180
	 * @noextend This class is not intended to be subclassed by clients.
181
	 * 
182
	 * @author Christian W. Damus (cdamus)
183
	 * 
184
	 * @since 6.0
185
	 */
186
	public static class Snapshot extends WorkingSetProxy implements IWorkingSetProxy.ISnapshot {
187
		private final WorkspaceSnapshot workspace;
188
		private IWorkingSetConfiguration.ISnapshot readOnlyConfig;
189
190
		/**
191
		 * Initializes me with the current workspace snapshot.
192
		 * 
193
		 * @param workingSet
194
		 *            the original working set element to copy
195
		 * @param workspace
196
		 *            the workspace snapshot
197
		 */
198
		protected Snapshot(IWorkingSetProxy workingSet, WorkspaceSnapshot workspace) {
199
			super();
200
201
			this.workspace = workspace;
202
203
			setName(workingSet.getName());
204
205
			for (IWorkingSetConfiguration next : workingSet.getConfigurations()) {
206
				basicAddConfiguration(next.createSnapshot(this, workspace));
207
			}
208
		}
209
210
		public IWorkingSetConfiguration.ISnapshot createConfiguration(String name) {
211
			if ((name == null) || (name.length() == 0)) {
212
				throw new IllegalArgumentException("name is empty"); //$NON-NLS-1$
213
			}
214
			if (getConfiguration(name) != null) {
215
				throw new IllegalArgumentException("name is already in use"); //$NON-NLS-1$
216
			}
217
218
			IWorkingSetConfiguration.ISnapshot result = createWorkingSetConfiguration();
219
			result.setName(name);
220
			basicAddConfiguration(result);
221
			updateActiveConfigurations();
222
223
			return result;
224
		}
225
226
		/**
227
		 * I create working-set configuration snapshots that are mutable, as I am.
228
		 */
229
		@Override
230
		protected IWorkingSetConfiguration.ISnapshot createWorkingSetConfiguration() {
231
			return new WorkingSetConfiguration.Snapshot(this, workspace);
232
		}
233
234
		public void removeConfiguration(IWorkingSetConfiguration config) {
235
			if (WorkingSetConfiguration.isReadOnly(config)) {
236
				throw new IllegalArgumentException("config is read-only"); //$NON-NLS-1$
237
			}
238
239
			basicRemoveConfiguration(config);
240
		}
241
242
		public boolean updateActiveConfigurations() {
243
			boolean result = getConfigurations().isEmpty();
244
245
			boolean hasActiveConfig = false;
246
			for (IWorkingSetConfiguration next : getConfigurations()) {
247
				if (next.isActive() && !WorkingSetConfiguration.isReadOnly(next)) {
248
					hasActiveConfig = true;
249
					break;
250
				}
251
			}
252
253
			if (hasActiveConfig) {
254
				if (readOnlyConfig != null) {
255
					basicRemoveConfiguration(readOnlyConfig);
256
					result = true;
257
				}
258
				readOnlyConfig = null;
259
			} else {
260
				WorkingSetConfiguration.Snapshot ro = new WorkingSetConfiguration.Snapshot(this, workspace,
261
						true);
262
				ro.basicSetName(""); // don't want to validate this name //$NON-NLS-1$
263
				readOnlyConfig = ro;
264
				basicAddConfiguration(readOnlyConfig);
265
				result = true;
266
			}
267
268
			return result;
269
		}
270
271
		/**
272
		 * Read-only working set configuration snapshots are transient.
273
		 */
274
		@Override
275
		protected boolean isTransient(IWorkingSetConfiguration config) {
276
			return WorkingSetConfiguration.isReadOnly(config);
277
		}
278
	}
279
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetConfigsController.java (+351 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.util.Collection;
15
16
import org.eclipse.core.resources.IProject;
17
import org.eclipse.jface.dialogs.IDialogConstants;
18
import org.eclipse.jface.dialogs.IInputValidator;
19
import org.eclipse.jface.dialogs.InputDialog;
20
import org.eclipse.jface.viewers.ISelectionChangedListener;
21
import org.eclipse.jface.viewers.IStructuredSelection;
22
import org.eclipse.jface.viewers.SelectionChangedEvent;
23
import org.eclipse.jface.viewers.StructuredSelection;
24
import org.eclipse.jface.viewers.TreeViewer;
25
import org.eclipse.swt.events.SelectionEvent;
26
import org.eclipse.swt.events.SelectionListener;
27
import org.eclipse.swt.widgets.Button;
28
import org.eclipse.swt.widgets.TreeItem;
29
import org.eclipse.ui.IWorkingSet;
30
31
/**
32
 * The view controller for the working set configurations pane in the dialog. It takes care of coordinating
33
 * the user gestures in the pane with the working set configuration model, and vice-versa. It also implements
34
 * the handling of the action buttons.
35
 * 
36
 * @author Christian W. Damus (cdamus)
37
 * 
38
 * @since 6.0
39
 * 
40
 */
41
class WorkingSetConfigsController implements SelectionListener, ISelectionChangedListener {
42
43
	private TreeViewer tree;
44
	private Button addButton;
45
	private Button removeButton;
46
	private Button renameButton;
47
	private Button activateButton;
48
49
	private IWorkingSetProxy.ISnapshot initialWorkingSet;
50
	private IWorkingSetProxy.ISnapshot currentWorkingSet;
51
	private IWorkingSetConfiguration.ISnapshot currentConfig;
52
53
	private final WorkspaceSnapshot workspace;
54
55
	private ProjectConfigsController projectsController;
56
57
	/**
58
	 * Initializes me.
59
	 */
60
	WorkingSetConfigsController(WorkspaceSnapshot workspace) {
61
		this.workspace = workspace;
62
63
		IWorkingSet[] recent = WorkingSetConfigurationManager.WS_MGR.getRecentWorkingSets();
64
		if ((recent != null) && (recent.length > 0)) {
65
			initialWorkingSet = workspace.getWorkingSet(recent[0].getName());
66
		}
67
	}
68
69
	/**
70
	 * Assigns the tree viewer that I control.
71
	 * 
72
	 * @param tree
73
	 *            my tree viewer
74
	 */
75
	void setTreeViewer(TreeViewer tree) {
76
		if (this.tree != null) {
77
			this.tree.removeSelectionChangedListener(this);
78
		}
79
80
		this.tree = tree;
81
82
		if (this.tree != null) {
83
			this.tree.addSelectionChangedListener(this);
84
85
			this.tree.setInput(workspace.getWorkingSets());
86
			if (initialWorkingSet != null) {
87
				this.tree.setSelection(new StructuredSelection(initialWorkingSet));
88
				this.tree.expandToLevel(initialWorkingSet, 1);
89
			} else if (!workspace.getWorkingSets().isEmpty()) {
90
				final TreeItem initialItem = tree.getTree().getItem(0);
91
				tree.getTree().getDisplay().asyncExec(new Runnable() {
92
93
					public void run() {
94
						WorkingSetConfigsController.this.tree.setSelection(new StructuredSelection(
95
								initialItem.getData()));
96
						WorkingSetConfigsController.this.tree.expandToLevel(initialItem.getData(), 1);
97
					}
98
				});
99
			}
100
		}
101
	}
102
103
	private Button updateButton(Button oldButton, Button newButton) {
104
		if (oldButton != null) {
105
			oldButton.removeSelectionListener(this);
106
		}
107
108
		if (newButton != null) {
109
			newButton.addSelectionListener(this);
110
		}
111
112
		return newButton;
113
	}
114
115
	/**
116
	 * Assigns me my "Add..." button.
117
	 * 
118
	 * @param addButton
119
	 *            my add button
120
	 */
121
	void setAddButton(Button addButton) {
122
		this.addButton = updateButton(this.addButton, addButton);
123
	}
124
125
	/**
126
	 * Assigns me my "Remove" button.
127
	 * 
128
	 * @param removeButton
129
	 *            my remove button
130
	 */
131
	void setRemoveButton(Button removeButton) {
132
		this.removeButton = updateButton(this.removeButton, removeButton);
133
	}
134
135
	/**
136
	 * Assigns me my "Rename..." button.
137
	 * 
138
	 * @param renameButton
139
	 *            my rename button
140
	 */
141
	void setRenameButton(Button renameButton) {
142
		this.renameButton = updateButton(this.renameButton, renameButton);
143
	}
144
145
	/**
146
	 * Assigns me my "Activate" button.
147
	 * 
148
	 * @param activateButton
149
	 *            my activate button
150
	 */
151
	void setActivateButton(Button activateButton) {
152
		this.activateButton = updateButton(this.activateButton, activateButton);
153
	}
154
155
	/**
156
	 * Connects me to the controller for the project configurations pane, into which I inject the currently
157
	 * selected working set configuration.
158
	 * 
159
	 * @param controller
160
	 *            my project configurations controller
161
	 */
162
	void setProjectConfigsController(ProjectConfigsController controller) {
163
		this.projectsController = controller;
164
		
165
		if (controller != null) {
166
			controller.setWorkingSetConfiguration(currentConfig);
167
		}
168
	}
169
170
	public void widgetDefaultSelected(SelectionEvent e) {
171
		// not interesting
172
	}
173
174
	/**
175
	 * Handles button presses in the working set configurations pane.
176
	 */
177
	public void widgetSelected(SelectionEvent e) {
178
		// handle button press
179
		if (e.widget == addButton) {
180
			addConfig();
181
		} else if (e.widget == removeButton) {
182
			removeConfig();
183
		} else if (e.widget == renameButton) {
184
			renameConfig();
185
		} else if (e.widget == activateButton) {
186
			activateConfig();
187
		}
188
	}
189
190
	/**
191
	 * Handles selection of working sets and their configurations. Among potentially other actions, this
192
	 * injects the working-set configuration selection into the project configurations controller and updates
193
	 * the enablement of the buttons.
194
	 */
195
	public void selectionChanged(SelectionChangedEvent event) {
196
		currentConfig = null;
197
		currentWorkingSet = null;
198
199
		if (event.getSelection() instanceof IStructuredSelection) {
200
			IStructuredSelection sel = (IStructuredSelection) event.getSelection();
201
202
			if (!sel.isEmpty()) {
203
				Object first = sel.getFirstElement();
204
205
				if (first instanceof IWorkingSetConfiguration) {
206
					currentConfig = (IWorkingSetConfiguration.ISnapshot) first;
207
					currentWorkingSet = currentConfig.getWorkingSet();
208
				} else if (first instanceof IWorkingSetProxy) {
209
					currentWorkingSet = (IWorkingSetProxy.ISnapshot) first;
210
				}
211
			}
212
		}
213
214
		if (projectsController != null) {
215
			// tell the project controller
216
			projectsController.setWorkingSetConfiguration(currentConfig);
217
		}
218
		
219
		updateButtons();
220
	}
221
222
	/**
223
	 * Handler for the "Add..." button.
224
	 */
225
	private void addConfig() {
226
		InputDialog dlg = new InputDialog(tree.getTree().getShell(), WorkingSetMessages.WSConfigsController_addDlg_title,
227
				WorkingSetMessages.WSConfigsController_addDlg_msg, WorkingSetMessages.WSConfigsController_addDlg_defaultName, new IInputValidator() {
228
229
					public String isValid(String newText) {
230
						if (currentWorkingSet.getConfiguration(newText) != null) {
231
							return WorkingSetMessages.WSConfigsController_addDlg_nameExists;
232
						}
233
						if (newText.length() == 0) {
234
							return WorkingSetMessages.WSConfigsController_addDlg_emptyName;
235
						}
236
						return null;
237
					}
238
				});
239
240
		if (dlg.open() == IDialogConstants.OK_ID) {
241
			IWorkingSetConfiguration.ISnapshot newConfig = currentWorkingSet.createConfiguration(dlg.getValue());
242
			tree.refresh(currentWorkingSet);
243
			tree.setSelection(new StructuredSelection(newConfig), true);
244
			currentConfig = newConfig;
245
			currentWorkingSet = currentConfig.getWorkingSet();
246
			
247
			// this is a "recently used" working set
248
			IWorkingSet ws = currentWorkingSet.resolve();
249
			if (ws != null) {
250
				WorkingSetConfigurationManager.WS_MGR.addRecentWorkingSet(ws);
251
			}
252
		}
253
	}
254
255
	/**
256
	 * Handler for the "Remove" button.
257
	 */
258
	private void removeConfig() {
259
		currentWorkingSet.removeConfiguration(currentConfig);
260
		tree.refresh(currentWorkingSet);
261
	}
262
263
	/**
264
	 * Handler for the "Rename..." button.
265
	 */
266
	private void renameConfig() {
267
		InputDialog dlg = new InputDialog(tree.getTree().getShell(), WorkingSetMessages.WSConfigsController_renameDlg_title,
268
				WorkingSetMessages.WSConfigsController_renameDlg_msg, currentConfig.getName(), new IInputValidator() {
269
270
					public String isValid(String newText) {
271
						if (newText.equals(currentConfig.getName())) {
272
							return ""; //$NON-NLS-1$
273
						}
274
						if (currentWorkingSet.getConfiguration(newText) != null) {
275
							return WorkingSetMessages.WSConfigsController_addDlg_nameExists;
276
						}
277
						if (newText.length() == 0) {
278
							return WorkingSetMessages.WSConfigsController_addDlg_emptyName;
279
						}
280
						return null;
281
					}
282
				});
283
284
		if (dlg.open() == IDialogConstants.OK_ID) {
285
			currentConfig.setName(dlg.getValue());
286
			tree.refresh(currentWorkingSet);
287
		}
288
	}
289
290
	/**
291
	 * Handler for the "Activate" button.
292
	 */
293
	private void activateConfig() {
294
		currentConfig.activate();
295
296
		// update all working-set configs that intersect this config
297
		Collection<IWorkingSetProxy.ISnapshot> unaffectedWorkingSets = new java.util.HashSet<IWorkingSetProxy.ISnapshot>(workspace.getWorkingSets());
298
299
		for (IProject project : currentConfig.getWorkingSet().resolveProjects()) {
300
			for (IWorkingSetProxy.ISnapshot next : unaffectedWorkingSets) {
301
				if (next.resolveProjects().contains(project)) {
302
					unaffectedWorkingSets.remove(next);
303
304
					if (next.updateActiveConfigurations()) {
305
						// major change. Refresh it altogether
306
						tree.refresh(next);
307
					} else {
308
						// lighter-weight updates of its configs
309
						for (IWorkingSetConfiguration config : next.getConfigurations()) {
310
							tree.update(config, null);
311
						}
312
					}
313
					break;
314
				}
315
			}
316
		}
317
318
		updateButtons();
319
	}
320
321
	/**
322
	 * Updates the enablement state of the action buttons according to the current selection.
323
	 */
324
	private void updateButtons() {
325
		if (addButton != null) {
326
			addButton.setEnabled(currentWorkingSet != null);
327
		}
328
		if (removeButton != null) {
329
			removeButton.setEnabled((currentConfig != null) && !currentConfig.isReadOnly());
330
		}
331
		if (renameButton != null) {
332
			renameButton.setEnabled((currentConfig != null) && !currentConfig.isReadOnly());
333
		}
334
		if (activateButton != null) {
335
			activateButton.setEnabled((currentConfig != null) && !currentConfig.isActive());
336
		}
337
	}
338
339
	/**
340
	 * Notification that the selection of configuration(s) in some project in the current working set
341
	 * configuration has changed. I accordingly update the visuals of the working-set configuration to
342
	 * indicate whether it is active or not.
343
	 * 
344
	 * @param project
345
	 *            the project configuration whose active configuration selections have changed
346
	 */
347
	void projectSelectionsChanged(IWorkingSetProjectConfiguration project) {
348
		tree.update(currentConfig, null);
349
		updateButtons(); // depends on whether the ws config is active
350
	}
351
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfiguration.java (+170 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.util.Collection;
15
16
import org.eclipse.core.resources.IProject;
17
import org.eclipse.core.resources.IResource;
18
import org.eclipse.core.runtime.IProgressMonitor;
19
import org.eclipse.core.runtime.IStatus;
20
21
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
22
23
/**
24
 * <p>
25
 * The protocol for project configurations in a working set configuration. At a minimum, the project
26
 * configuration specifies which build configuration is {@linkplain #getSelectedConfigurationID() selected} to
27
 * be set as the project's active configuration. Implementations are free to add more configuration
28
 * information than the selected build configuration.
29
 * </p>
30
 * <p>
31
 * Note that project configurations are owned by working set configurations. Thus, different configurations of
32
 * the same (or different) working set may specify different settings for the same project.
33
 * </p>
34
 * 
35
 * @author Christian W. Damus (cdamus)
36
 * 
37
 * @since 6.0
38
 */
39
public interface IWorkingSetProjectConfiguration extends IWorkingSetConfigurationElement {
40
	/**
41
	 * Obtains the working set configuration element that owns me.
42
	 * 
43
	 * @return my working set configuration
44
	 */
45
	IWorkingSetConfiguration getWorkingSetConfiguration();
46
47
	/**
48
	 * Queries the name of the project that I configure.
49
	 * 
50
	 * @return my project name
51
	 */
52
	String getProjectName();
53
54
	/**
55
	 * Resolves my project name to the actual project resource in the workspace.
56
	 * 
57
	 * @return my referenced project, or <code>null</code> if the project is not
58
	 *         {@linkplain IResource#isAccessible() accessible} in the workspace
59
	 */
60
	IProject resolveProject();
61
62
	/**
63
	 * Queries the ID of the build configuration that is currently selected for my project.
64
	 * 
65
	 * @return my selected build configuration ID
66
	 */
67
	String getSelectedConfigurationID();
68
69
	/**
70
	 * Sets the ID of the build configuration that is currently selected for my project.
71
	 * 
72
	 * @param id
73
	 *            my selected build configuration ID
74
	 */
75
	void setSelectedConfigurationID(String id);
76
77
	/**
78
	 * <p>
79
	 * Resolves my selected configuration reference to the C model's description handle for it.
80
	 * </p>
81
	 * <p>
82
	 * <b>Note</b> that, in the general case, it is possible for the configuration to resolve to a different
83
	 * object from one call to the next, but always representing the same configuration. However, in the case
84
	 * of a working-copy {@linkplain IWorkingSetProjectConfiguration.ISnapshot snapshot} of me, the result
85
	 * will always be the same object.
86
	 * </p>
87
	 * 
88
	 * @return the C model representation of my selected build configuration
89
	 * 
90
	 * @see #resolveConfigurations()
91
	 */
92
	ICConfigurationDescription resolveSelectedConfiguration();
93
94
	/**
95
	 * <p>
96
	 * Resolves the set of available configurations of my project.
97
	 * </p>
98
	 * <p>
99
	 * <b>Note</b> that, in the general case, it is possible for these configurations to resolve to different
100
	 * objects from one call to the next, but always representing the same configurations. However, in the
101
	 * case of a working-copy {@linkplain IWorkingSetProjectConfiguration.ISnapshot snapshot} of me, the
102
	 * results will always be the same objects.
103
	 * </p>
104
	 * 
105
	 * @return the C model representation of my selected available build configurations
106
	 * 
107
	 * @see #resolveSelectedConfiguration()
108
	 */
109
	Collection<ICConfigurationDescription> resolveConfigurations();
110
111
	/**
112
	 * Queries whether my project currently has my selected configuration active in the workspace.
113
	 * 
114
	 * @return whether I am my project's active configuration
115
	 * 
116
	 * @see #getSelectedConfigurationID()
117
	 * @see #activate()
118
	 */
119
	boolean isActive();
120
121
	/**
122
	 * Activates my selected configuration in the workspace, for my project.
123
	 * 
124
	 * @see #getSelectedConfigurationID()
125
	 * @see #setSelectedConfigurationID(String)
126
	 * @see #isActive()
127
	 */
128
	void activate();
129
130
	/**
131
	 * Builds my selected configuration in the workspace, for my project. If building the configuration
132
	 * actually requires activating it, and it was not already active, then it would be a good idea to return
133
	 * a warning status indicating that the active configuration had to be changed in order to effect the
134
	 * build.
135
	 * 
136
	 * @param monitor
137
	 *            a progress monitor to report build progress
138
	 * @return a status indicating any error or warning conditions in the invocation of the build
139
	 */
140
	IStatus build(IProgressMonitor monitor);
141
142
	/**
143
	 * Creates a <i>snapshot</i> (also known as a "working copy") of myself, providing a mutable view suitable
144
	 * for editing.
145
	 * 
146
	 * @param workingSetConfig
147
	 *            my parent working set configuration snapshot
148
	 * @param workspace
149
	 *            a workspace snapshot that captures the baseline state of the workspace and the working set
150
	 *            configurations that are to be edited
151
	 * 
152
	 * @return a working-copy snapshot of myself
153
	 */
154
	ISnapshot createSnapshot(IWorkingSetConfiguration.ISnapshot workingSetConfig, WorkspaceSnapshot workspace);
155
156
	//
157
	// Nested types
158
	//
159
160
	/**
161
	 * The snapshot ("working copy") view of a working set project configuration.
162
	 * 
163
	 * @author Christian W. Damus (cdamus)
164
	 * 
165
	 * @since 6.0
166
	 */
167
	interface ISnapshot extends IWorkingSetProjectConfiguration {
168
		IWorkingSetConfiguration.ISnapshot getWorkingSetConfiguration();
169
	}
170
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/WorkspaceSnapshot.java (+419 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.util.Arrays;
15
import java.util.Collection;
16
import java.util.Collections;
17
import java.util.Map;
18
19
import org.eclipse.core.resources.IProject;
20
import org.eclipse.core.resources.IWorkspaceRoot;
21
import org.eclipse.core.resources.ResourcesPlugin;
22
import org.eclipse.core.runtime.CoreException;
23
import org.eclipse.ui.IWorkingSet;
24
25
import org.eclipse.cdt.core.model.CoreModel;
26
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
27
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
28
import org.eclipse.cdt.ui.CUIPlugin;
29
30
/**
31
 * <p>
32
 * A snapshot of the working set configurations and project configurations across the workspace at the time
33
 * when it was created. The snapshot maintains a delta from that original state to the current state, for such
34
 * comparison operations as determining which projects need to be re-built because their active configurations
35
 * have changed. The snapshot provides mutable working-copy views of the working set configurations at the
36
 * time of snapshot creation.
37
 * </p>
38
 * <p>
39
 * To make changes to working set configurations, first
40
 * {@linkplain WorkingSetConfigurationManager#createWorkspaceSnapshot() obtain a snapshot} from the
41
 * {@link WorkingSetConfigurationManager}. Then make edits to the various snapshots of the configuration
42
 * elements and {@linkplain #save() save} the snapshot
43
 * </p>
44
 * 
45
 * @author Christian W. Damus (cdamus)
46
 * 
47
 * @since 6.0
48
 * 
49
 */
50
public class WorkspaceSnapshot {
51
	private Map<String, IWorkingSetProxy.ISnapshot> workingSets = new java.util.HashMap<String, IWorkingSetProxy.ISnapshot>();
52
	private Map<IProject, ProjectState> projectStates = new java.util.HashMap<IProject, ProjectState>();
53
54
	/**
55
	 * Initializes me. I capture the current C/C++ active configuration state of the projects in the
56
	 * workspace.
57
	 */
58
	WorkspaceSnapshot() {
59
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
60
61
		for (IProject next : root.getProjects()) {
62
			ICProjectDescription desc = CoreModel.getDefault().getProjectDescription(next);
63
64
			if (desc != null) {
65
				projectStates.put(next, createProjectState(next, desc));
66
			}
67
		}
68
	}
69
70
	/**
71
	 * Creates a project state using the registered factory, if possible.
72
	 * 
73
	 * @param project
74
	 *            a workspace project
75
	 * @param desc
76
	 *            its CDT project description
77
	 * 
78
	 * @return its state capture (will never be <code>null</code>)
79
	 */
80
	private static ProjectState createProjectState(IProject project, ICProjectDescription desc) {
81
		ProjectState result = null;
82
		IWorkingSetProjectConfigurationFactory factory = IWorkingSetProjectConfigurationFactory.Registry.INSTANCE
83
				.getFactory(project);
84
85
		if (factory != null) {
86
			result = factory.createProjectState(project, desc);
87
		}
88
89
		if (result == null) {
90
			// the default-default
91
			result = new ProjectState(project, desc);
92
		}
93
94
		return result;
95
	}
96
97
	/**
98
	 * Initializes me with the specified working sets to copy for editing.
99
	 * 
100
	 * @param workingSets
101
	 *            the working sets to copy
102
	 * @return myself
103
	 */
104
	WorkspaceSnapshot initialize(Map<String, IWorkingSetProxy> workingSets) {
105
		for (IWorkingSet next : WorkingSetConfigurationManager.WS_MGR.getWorkingSets()) {
106
			IWorkingSetProxy workingSet = workingSets.get(next.getName());
107
108
			if (workingSet == null) {
109
				workingSet = new WorkingSetProxy();
110
				((WorkingSetProxy) workingSet).setName(next.getName());
111
			}
112
113
			if (workingSet.isValid()) {
114
				this.workingSets.put(workingSet.getName(), workingSet.createSnapshot(this));
115
			}
116
		}
117
118
		return this;
119
	}
120
121
	/**
122
	 * Obtains a mutable snapshot of the named working set.
123
	 * 
124
	 * @param name
125
	 *            the working set to retrieve
126
	 * 
127
	 * @return the working set snapshot, or <code>null</code> if there is no working set by this name
128
	 * 
129
	 * @see #getWorkingSets()
130
	 */
131
	public IWorkingSetProxy.ISnapshot getWorkingSet(String name) {
132
		return workingSets.get(name);
133
	}
134
135
	/**
136
	 * Obtains snapshots of all of the working sets currently defined by the workbench.
137
	 * 
138
	 * @return the working set snapshots
139
	 * 
140
	 * @see #getWorkingSet(String)
141
	 */
142
	public Collection<IWorkingSetProxy.ISnapshot> getWorkingSets() {
143
		return workingSets.values();
144
	}
145
146
	/**
147
	 * Obtains the project state recording the initial configuration of the specified <tt>project</tt> at the
148
	 * time that this snapshot was taken.
149
	 * 
150
	 * @param project
151
	 *            a project
152
	 * @return its snapshot/delta state
153
	 */
154
	public ProjectState getState(IProject project) {
155
		return projectStates.get(project);
156
	}
157
158
	/**
159
	 * Queries the ID of the configuration of the specified project that was active when the workspace
160
	 * snapshot was taken.
161
	 * 
162
	 * @param project
163
	 *            a project
164
	 * @return its active configuration ID at the time of the snapshot
165
	 */
166
	String getOriginalActiveConfigurationID(IProject project) {
167
		String result = null;
168
		ProjectState state = getState(project);
169
170
		if (state != null) {
171
			result = state.getOriginalActiveConfigurationID();
172
		}
173
174
		return result;
175
	}
176
177
	/**
178
	 * Queries whether the configuration selected by the given project in a working set configuration is
179
	 * currently active in the workspace.
180
	 * 
181
	 * @param project
182
	 *            a project configuration element in a working set configuration
183
	 * 
184
	 * @return whether the project's selected configuration is active
185
	 * 
186
	 * @see #activate(IProject, String)
187
	 */
188
	boolean isActive(IWorkingSetProjectConfiguration project) {
189
		boolean result = false;
190
		ProjectState state = getState(project.resolveProject());
191
192
		if (state != null) {
193
			result = state.isActive(project.getSelectedConfigurationID());
194
		}
195
196
		return result;
197
	}
198
199
	/**
200
	 * Activates, in the workspace, the specified configuration of a project. This method has no effect if the
201
	 * given configuration is already active.
202
	 * 
203
	 * @param project
204
	 *            the project for which to set the active configuration
205
	 * @param configID
206
	 *            the ID of the configuration to activate
207
	 * 
208
	 * @see #isActive(IWorkingSetProjectConfiguration)
209
	 */
210
	void activate(IProject project, String configID) {
211
		ProjectState state = getState(project);
212
213
		if (state != null) {
214
			state.activate(configID);
215
		}
216
	}
217
218
	/**
219
	 * Obtains the configurations of the specified project, as known at the time that this snapshot was taken.
220
	 * 
221
	 * @param project
222
	 *            a project
223
	 * 
224
	 * @return its configurations, which may be an empty collection if the project is not a C/C++ project
225
	 */
226
	public Collection<ICConfigurationDescription> getConfigurations(IProject project) {
227
		Collection<ICConfigurationDescription> result;
228
		ProjectState state = getState(project);
229
230
		if (state == null) {
231
			result = Collections.emptyList();
232
		} else {
233
			result = state.getConfigurations();
234
		}
235
236
		return result;
237
	}
238
239
	/**
240
	 * Obtains the specified configuration of a project, as known at the time that this snapshot was taken.
241
	 * 
242
	 * @param project
243
	 *            a project
244
	 * @param id
245
	 *            the ID of a configuration
246
	 * 
247
	 * @return the configuration, or <code>null</code> if there is none such by this ID
248
	 */
249
	public ICConfigurationDescription getConfiguration(IProject project, String id) {
250
		ProjectState state = getState(project);
251
		return (state == null) ? null : state.getConfiguration(id);
252
	}
253
254
	/**
255
	 * Queries the projects that need to be built because their active configurations have been changed since
256
	 * this snapshot was taken.
257
	 * 
258
	 * @return the projects needing to be re-built
259
	 */
260
	public Collection<IProject> getProjectsToBuild() {
261
		Collection<IProject> result = new java.util.ArrayList<IProject>();
262
263
		for (ProjectState next : projectStates.values()) {
264
			if (next.needsBuild()) {
265
				result.add(next.getProject());
266
			}
267
		}
268
269
		return result;
270
	}
271
272
	/**
273
	 * Saves my working set configuration settings.
274
	 */
275
	public void save() {
276
		WorkingSetConfigurationManager.getDefault().save(this);
277
	}
278
279
	//
280
	// Nested classes
281
	//
282
283
	/**
284
	 * Capture of the current state of a project at the time when a {@linkplain WorkspaceSnapshot workspace
285
	 * snapshot} was taken, and its delta from that original state. This tracks at least the C/C++ project
286
	 * description (if any) and the original active configuration. Subclasses may track additional
287
	 * configuration details.
288
	 * 
289
	 * @author Christian W. Damus (cdamus)
290
	 * 
291
	 * @since 6.0
292
	 */
293
	public static class ProjectState {
294
		private final IProject project;
295
		private final ICProjectDescription projectDescription;
296
		private final String originalConfigID;
297
		private String currentConfigID;
298
299
		/**
300
		 * Initializes me with a project and its description.
301
		 * 
302
		 * @param project
303
		 *            the project whose state I track
304
		 * @param desc
305
		 *            the project's description, from which I capture the initial state snapshot
306
		 */
307
		protected ProjectState(IProject project, ICProjectDescription desc) {
308
			this.project = project;
309
			this.projectDescription = desc;
310
311
			if (desc != null) {
312
				ICConfigurationDescription config = desc.getActiveConfiguration();
313
				this.originalConfigID = (config == null) ? "" : config.getId(); //$NON-NLS-1$
314
			} else {
315
				this.originalConfigID = ""; //$NON-NLS-1$
316
			}
317
318
			this.currentConfigID = this.originalConfigID;
319
		}
320
321
		/**
322
		 * Obtains the project that I track.
323
		 * 
324
		 * @return my project
325
		 */
326
		public final IProject getProject() {
327
			return project;
328
		}
329
330
		/**
331
		 * Obtains the project description that was current when the snapshot was taken.
332
		 * 
333
		 * @return my project description
334
		 */
335
		protected final ICProjectDescription getProjectDescription() {
336
			return projectDescription;
337
		}
338
339
		/**
340
		 * Queries whether my project needs to be re-built because its active configuration has been changed
341
		 * since the snapshot was taken.
342
		 * 
343
		 * @return whether I need to be re-built
344
		 */
345
		public boolean needsBuild() {
346
			return !currentConfigID.equals(originalConfigID);
347
		}
348
349
		/**
350
		 * Queries whether the specified configuration is currently active in the workspace for my project.
351
		 * 
352
		 * @param configID
353
		 *            the ID of a project build configuration
354
		 * @return whether it is my project's active configuration
355
		 */
356
		public boolean isActive(String configID) {
357
			return currentConfigID.equals(configID);
358
		}
359
360
		/**
361
		 * Queries the ID of the configuration of my project that was active when the workspace snapshot was
362
		 * taken.
363
		 * 
364
		 * @return its active configuration ID at the time of the snapshot
365
		 */
366
		protected String getOriginalActiveConfigurationID() {
367
			return originalConfigID;
368
		}
369
370
		/**
371
		 * Sets my project's active configuration to the specified configuration. This method has no effect if
372
		 * this configuration is already active.
373
		 * 
374
		 * @param configID
375
		 *            the ID of the configuration to activate
376
		 */
377
		protected void activate(String configID) {
378
			if (!currentConfigID.equals(configID) && (projectDescription != null)) {
379
				try {
380
					ICConfigurationDescription realConfig = projectDescription.getConfigurationById(configID);
381
					realConfig.setActive();
382
					CoreModel.getDefault().setProjectDescription(project, projectDescription);
383
					currentConfigID = configID;
384
				} catch (CoreException e) {
385
					CUIPlugin.log(e);
386
				}
387
			}
388
		}
389
390
		/**
391
		 * Obtains the configurations of my project that were defined at the time that the snapshot was taken.
392
		 * 
393
		 * @return my project's configurations, which may be empty if it is not a C/C++ project
394
		 */
395
		protected Collection<ICConfigurationDescription> getConfigurations() {
396
			Collection<ICConfigurationDescription> result;
397
398
			if (projectDescription == null) {
399
				result = Collections.emptyList();
400
			} else {
401
				result = Arrays.asList(projectDescription.getConfigurations());
402
			}
403
404
			return result;
405
		}
406
407
		/**
408
		 * Obtains the specified configuration of my project as it was defined at the time that the snapshot
409
		 * was taken.
410
		 * 
411
		 * @param id
412
		 *            a configuration ID
413
		 * @return the matching configuration, or <code>null</code> if it did not exist
414
		 */
415
		protected ICConfigurationDescription getConfiguration(String id) {
416
			return (projectDescription == null) ? null : projectDescription.getConfigurationById(id);
417
		}
418
	}
419
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetConfigurationManager.java (+415 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.io.File;
15
import java.io.FileReader;
16
import java.io.FileWriter;
17
import java.io.IOException;
18
import java.util.Collection;
19
import java.util.HashMap;
20
import java.util.List;
21
import java.util.Map;
22
23
import org.eclipse.core.runtime.IPath;
24
import org.eclipse.core.runtime.IProgressMonitor;
25
import org.eclipse.core.runtime.IStatus;
26
import org.eclipse.core.runtime.Status;
27
import org.eclipse.core.runtime.jobs.ISchedulingRule;
28
import org.eclipse.core.runtime.jobs.Job;
29
import org.eclipse.jface.util.IPropertyChangeListener;
30
import org.eclipse.jface.util.PropertyChangeEvent;
31
import org.eclipse.ui.IMemento;
32
import org.eclipse.ui.IWorkingSet;
33
import org.eclipse.ui.IWorkingSetManager;
34
import org.eclipse.ui.XMLMemento;
35
36
import org.eclipse.cdt.ui.CUIPlugin;
37
import org.eclipse.cdt.ui.newui.CDTPrefUtil;
38
39
/**
40
 * The purveyor of working set configurations. It provides a current view of the {@linkplain IWorkingSetProxy
41
 * working set configurations} defined in the workspace, as well as a working-copy
42
 * {@linkplain WorkspaceSnapshot snapshot} of the same for making modifications.
43
 * 
44
 * @author Christian W. Damus (cdamus)
45
 * 
46
 * @since 6.0
47
 * 
48
 */
49
public class WorkingSetConfigurationManager {
50
51
	static final String TYPE_WORKING_SET_CONFIGS = "org.eclipse.cdt.ui.workingSetConfigurations"; //$NON-NLS-1$
52
	static final String KEY_WORKING_SET = "workingSet"; //$NON-NLS-1$
53
	static final String ATTR_NAME = "name"; //$NON-NLS-1$
54
	static final String KEY_CONFIG = "config"; //$NON-NLS-1$
55
	static final String KEY_PROJECT = "project"; //$NON-NLS-1$
56
	static final String ATTR_CONFIG = "config"; //$NON-NLS-1$
57
	static final String ATTR_FACTORY = "factory"; //$NON-NLS-1$
58
59
	static IWorkingSetManager WS_MGR = CUIPlugin.getDefault().getWorkbench().getWorkingSetManager();
60
61
	private static final WorkingSetConfigurationManager INSTANCE = new WorkingSetConfigurationManager();
62
63
	private Map<String, IWorkingSetProxy> workingSets;
64
65
	private final Object storeLock = new Object();
66
	private IMemento store;
67
68
	private final ISchedulingRule saveRule = new ISchedulingRule() {
69
70
		public boolean isConflicting(ISchedulingRule rule) {
71
			return rule == this;
72
		}
73
74
		public boolean contains(ISchedulingRule rule) {
75
			return rule == this;
76
		}
77
	};
78
79
	/**
80
	 * Not instantiable by clients.
81
	 */
82
	private WorkingSetConfigurationManager() {
83
		store = loadMemento();
84
		new WorkingSetChangeTracker();
85
	}
86
87
	/**
88
	 * Obtains the default working set configuration manager.
89
	 * 
90
	 * @return the working set configuration manager
91
	 */
92
	public static WorkingSetConfigurationManager getDefault() {
93
		return INSTANCE;
94
	}
95
96
	private Map<String, IWorkingSetProxy> getWorkingSetMap() {
97
		Map<String, IWorkingSetProxy> result;
98
99
		synchronized (storeLock) {
100
			if (workingSets == null) {
101
				load();
102
			}
103
			result = workingSets;
104
		}
105
106
		return result;
107
	}
108
109
	/**
110
	 * Obtains the current immutable view of the specified working set's configurations. These configurations
111
	 * may be {@linkplain IWorkingSetConfiguration#activate() activated} to apply their settings to the
112
	 * workspace, but they cannot be modified.
113
	 * 
114
	 * @param name
115
	 *            the name of the working set to retrieve
116
	 * @return the named working set, or <code>null</code> if there is none available by that name
117
	 */
118
	public IWorkingSetProxy getWorkingSet(String name) {
119
		return getWorkingSetMap().get(name);
120
	}
121
122
	/**
123
	 * Obtains the current immutable view of all available working set configurations. These configurations
124
	 * may be {@linkplain IWorkingSetConfiguration#activate() activated} to apply their settings to the
125
	 * workspace, but they cannot be modified.
126
	 * 
127
	 * @return the working set configurations
128
	 */
129
	public Collection<IWorkingSetProxy> getWorkingSets() {
130
		return getWorkingSetMap().values();
131
	}
132
133
	/**
134
	 * Creates a new mutable snapshot of the current working set configurations. This snapshot accepts
135
	 * modifications and can be {@linkplain WorkspaceSnapshot#save() saved} to persist the changes.
136
	 * 
137
	 * @return a working-copy of the working set configurations
138
	 */
139
	public WorkspaceSnapshot createWorkspaceSnapshot() {
140
		return new WorkspaceSnapshot().initialize(getWorkingSetMap());
141
	}
142
143
	/**
144
	 * <p>
145
	 * Loads the working set configurations from storage.
146
	 * </p>
147
	 * <p>
148
	 * <b>Note</b> that this method must only be called within the <tt>storeLock</tt> monitor.
149
	 * </p>
150
	 */
151
	private void load() {
152
		workingSets = new java.util.HashMap<String, IWorkingSetProxy>();
153
154
		for (IMemento next : store.getChildren(KEY_WORKING_SET)) {
155
			WorkingSetProxy ws = new WorkingSetProxy();
156
			
157
			ws.loadState(next);
158
			
159
			if (ws.isValid()) {
160
				workingSets.put(ws.getName(), ws);
161
			}
162
		}
163
	}
164
165
	/**
166
	 * <p>
167
	 * Forgets the current view of the working set configurations.
168
	 * </p>
169
	 * <p>
170
	 * <b>Note</b> that this method must only be called within the <tt>storeLock</tt> monitor.
171
	 * </p>
172
	 */
173
	private void clear() {
174
		workingSets = null;
175
	}
176
177
	/**
178
	 * Saves the working set configurations to storage.
179
	 * 
180
	 * @param snapshot
181
	 *            the snapshot to save
182
	 */
183
	void save(WorkspaceSnapshot snapshot) {
184
		final XMLMemento memento = XMLMemento.createWriteRoot(TYPE_WORKING_SET_CONFIGS);
185
186
		for (IWorkingSetConfigurationElement next : snapshot.getWorkingSets()) {
187
			next.saveState(memento.createChild(KEY_WORKING_SET));
188
		}
189
190
		save(memento);
191
	}
192
193
	/**
194
	 * Records the specified memento as our new store and asynchronously saves it in a job.
195
	 * 
196
	 * @param memento
197
	 *            the new store
198
	 */
199
	private void save(final XMLMemento memento) {
200
		synchronized (storeLock) {
201
			store = memento;
202
			clear();
203
		}
204
205
		new Job(WorkingSetMessages.WSConfigManager_save_job) {
206
			{
207
				setRule(saveRule);
208
				setSystem(true);
209
			}
210
211
			@Override
212
			protected IStatus run(IProgressMonitor monitor) {
213
214
				File file = getStorage();
215
				FileWriter writer = null;
216
				try {
217
					writer = new FileWriter(file);
218
					memento.save(writer);
219
					writer.close();
220
				} catch (IOException e) {
221
					if (writer != null) {
222
						try {
223
							writer.close();
224
						} catch (IOException e2) {
225
							// no recovery
226
							CUIPlugin.log(WorkingSetMessages.WSConfigManager_closeFailed, e);
227
						}
228
					}
229
230
					file.delete(); // it is corrupt; we won't be able to load it, later
231
232
					CUIPlugin.log(WorkingSetMessages.WSConfigManager_saveFailed, e);
233
				}
234
				return Status.OK_STATUS;
235
			}
236
		}.schedule();
237
	}
238
239
	/**
240
	 * Gets the file in which we persist the working set configurations.
241
	 * 
242
	 * @return the file store
243
	 */
244
	private File getStorage() {
245
		IPath path = CUIPlugin.getDefault().getStateLocation().append("workingSetConfigs.xml"); //$NON-NLS-1$
246
		return path.toFile();
247
	}
248
249
	/**
250
	 * Loads the working set configurations from storage. For compatibility, if the XML file is not available,
251
	 * we load from the old preference setting format.
252
	 * 
253
	 * @return the working set configuration store
254
	 */
255
	private IMemento loadMemento() {
256
		IMemento result = null;
257
258
		File file = getStorage();
259
260
		if (file.exists()) {
261
			FileReader reader = null;
262
			try {
263
				reader = new FileReader(file);
264
				result = XMLMemento.createReadRoot(reader);
265
				reader.close();
266
			} catch (Exception e) {
267
				result = null;
268
269
				if (reader != null) {
270
					try {
271
						reader.close();
272
					} catch (IOException e2) {
273
						// no recovery
274
						CUIPlugin.log(WorkingSetMessages.WSConfigManager_closeFailed, e);
275
					}
276
				}
277
278
				CUIPlugin.log(WorkingSetMessages.WSConfigManager_loadFailed, e);
279
			}
280
		}
281
282
		if (result == null) {
283
			// fake one from the old preference storage format. This also
284
			// handles the case of no working set configurations ever being made
285
			@SuppressWarnings("deprecation")
286
			List<String> configSetStrings = CDTPrefUtil.readConfigSets();
287
			result = XMLMemento.createWriteRoot(TYPE_WORKING_SET_CONFIGS);
288
289
			// collect the unordered entries by working set
290
			Map<String, IMemento> configMap = new HashMap<String, IMemento>();
291
			for (String next : configSetStrings) {
292
				String[] bits = next.split(" "); //$NON-NLS-1$
293
294
				if (bits.length >= 2) {
295
					String configName = bits[0];
296
					String wsName = bits[1];
297
298
					IMemento workingSet = configMap.get(wsName);
299
					if (workingSet == null) {
300
						workingSet = result.createChild(KEY_WORKING_SET);
301
						configMap.put(wsName, workingSet);
302
					}
303
304
					workingSet.putString(ATTR_NAME, wsName);
305
306
					IMemento config = workingSet.createChild(KEY_CONFIG);
307
					config.putString(ATTR_NAME, configName);
308
309
					int limit = bits.length - (bits.length % 2);
310
					for (int i = 2; i < limit; i += 2) {
311
						IMemento project = config.createChild(KEY_PROJECT);
312
						project.putString(ATTR_NAME, bits[i]);
313
						project.putString(ATTR_CONFIG, bits[i + 1]);
314
					}
315
				}
316
			}
317
		}
318
319
		return result;
320
	}
321
322
	//
323
	// Nested classes
324
	//
325
326
	/**
327
	 * A working set manager listener that tracks name changes and removals of working sets to keep our
328
	 * configurations in synch as much as possible. It updates the memento store directly in response to
329
	 * changes in the working sets.
330
	 * 
331
	 * @author Christian W. Damus (cdamus)
332
	 * 
333
	 * @since 6.0
334
	 */
335
	private class WorkingSetChangeTracker extends java.util.IdentityHashMap<IWorkingSet, String> implements
336
			IPropertyChangeListener {
337
338
		WorkingSetChangeTracker() {
339
			for (IWorkingSet next : WS_MGR.getWorkingSets()) {
340
				put(next, next.getName());
341
			}
342
343
			WS_MGR.addPropertyChangeListener(this);
344
		}
345
346
		public void propertyChange(PropertyChangeEvent event) {
347
			String property = event.getProperty();
348
349
			if (IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE.equals(property)) {
350
				handleNameChange((IWorkingSet) event.getNewValue());
351
			} else if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE.equals(property)) {
352
				handleRemove((IWorkingSet) event.getOldValue());
353
			} else if (IWorkingSetManager.CHANGE_WORKING_SET_ADD.equals(property)) {
354
				handleAdd((IWorkingSet) event.getNewValue());
355
			}
356
		}
357
358
		private void handleNameChange(IWorkingSet workingSet) {
359
			synchronized (storeLock) {
360
				String oldName = get(workingSet);
361
				IMemento wsMemento = null;
362
				if (oldName != null) {
363
					for (IMemento next : store.getChildren(KEY_WORKING_SET)) {
364
						if (oldName.equals(next.getString(ATTR_NAME))) {
365
							wsMemento = next;
366
							break;
367
						}
368
					}
369
				}
370
371
				if (wsMemento != null) {
372
					// update the memento with the new name
373
					wsMemento.putString(ATTR_NAME, workingSet.getName());
374
375
					// clone it
376
					XMLMemento newStore = XMLMemento.createWriteRoot(TYPE_WORKING_SET_CONFIGS);
377
					newStore.putMemento(store);
378
379
					// save it asynchronously
380
					save(newStore);
381
				}
382
383
				// and update our mapping
384
				put(workingSet, workingSet.getName());
385
			}
386
		}
387
388
		private void handleRemove(IWorkingSet workingSet) {
389
			synchronized (storeLock) {
390
				String name = get(workingSet);
391
				if (name != null) {
392
					// remove the memento from the store
393
					XMLMemento newStore = XMLMemento.createWriteRoot(TYPE_WORKING_SET_CONFIGS);
394
					for (IMemento next : store.getChildren(KEY_WORKING_SET)) {
395
						if (!name.equals(next.getString(ATTR_NAME))) {
396
							newStore.createChild(KEY_WORKING_SET).putMemento(next);
397
						}
398
					}
399
400
					// save asynchronously
401
					save(newStore);
402
				}
403
404
				// and update our mapping
405
				remove(workingSet);
406
			}
407
		}
408
409
		private void handleAdd(IWorkingSet workingSet) {
410
			synchronized (storeLock) {
411
				put(workingSet, workingSet.getName());
412
			}
413
		}
414
	}
415
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfigurationController.java (+144 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import org.eclipse.jface.viewers.IBaseLabelProvider;
15
import org.eclipse.jface.viewers.IContentProvider;
16
import org.eclipse.jface.viewers.ILabelProvider;
17
import org.eclipse.jface.viewers.ITreeContentProvider;
18
19
/**
20
 * Protocol for the view controller for the project configurations pane of the working set configurations
21
 * dialog. It takes care of coordinating the user gestures in that pane with the working-set configuration
22
 * model and vice-versa.
23
 * 
24
 * @author Christian W. Damus (cdamus)
25
 * 
26
 * @since 6.0
27
 * 
28
 */
29
public interface IWorkingSetProjectConfigurationController {
30
	/**
31
	 * Queries the project configuration in the Working Set Configurations pane that I control.
32
	 * 
33
	 * @return the new working set configuration selection. May be <code>null</code> if there is no selection
34
	 */
35
	IWorkingSetProjectConfiguration.ISnapshot getProjectConfiguration();
36
37
	/**
38
	 * Notifies me that the check state of some element that I control in the sub-tree of my
39
	 * {@linkplain #getProjectConfiguration() project configuration} has changed its check-state. The
40
	 * controller context can be used to pass back reactions such as to veto the check-state change or to
41
	 * signal that some level of UI refresh is required.
42
	 * 
43
	 * @param element
44
	 *            an element that has been checked or unchecked
45
	 * @param checked
46
	 *            whether the <tt>element</tt> is now checked
47
	 * @param context
48
	 *            the controller context, used to communicate vetos, refreshes, etc.
49
	 */
50
	void checkStateChanged(Object element, boolean checked, IControllerContext context);
51
52
	/**
53
	 * Computes the initial check-box settings for my tree according to the current state of my
54
	 * {@linkplain #getProjectConfiguration() project configuration}.
55
	 * 
56
	 * @param context
57
	 *            context in which I can set initial check-states of my elements
58
	 */
59
	void updateCheckState(IControllerContext context);
60
61
	/**
62
	 * Obtains a content provider for the structure rooted at my {@linkplain #getProjectConfiguration()
63
	 * project configuration}. Note that this method will only be called once, and that the caller takes
64
	 * responsibility for {@linkplain IContentProvider#dispose() disposing} the content provider.
65
	 * 
66
	 * @return my content provider
67
	 */
68
	ITreeContentProvider getContentProvider();
69
70
	/**
71
	 * Obtains a label provider for the structure rooted at my {@linkplain #getProjectConfiguration() project
72
	 * configuration}. Note that this method will only be called once, and that the caller takes
73
	 * responsibility for {@linkplain IBaseLabelProvider#dispose() disposing} the label provider.
74
	 * 
75
	 * @return my label provider
76
	 */
77
	ILabelProvider getLabelProvider();
78
79
	//
80
	// Nested types
81
	//
82
83
	/**
84
	 * An interface provided by the Manage Working Set Configurations dialog infrastructure to
85
	 * {@link IWorkingSetProjectConfigurationController}s for communication of state changes
86
	 * back to the UI.
87
	 * 
88
	 * @noimplement This interface is not intended to be implemented by clients.
89
	 * @noextend This interface is not intended to be extended by clients.
90
	 * 
91
	 * @author Christian W. Damus (damus)
92
	 * 
93
	 * @since 6.0
94
	 */
95
	interface IControllerContext {
96
		/**
97
		 * Queries whether the current working set configuration context is a read-only one. In such cases, I
98
		 * should probably disallow check-state changes and other editing.
99
		 * 
100
		 * @return whether the current working set configuration is read-only
101
		 * 
102
		 * @see IWorkingSetConfiguration.ISnapshot#isReadOnly()
103
		 */
104
		boolean isReadOnly();
105
106
		/**
107
		 * Sets the check state of an element in the Project Configurations pane under the authority of the
108
		 * controller. This is particularly useful for setting the
109
		 * {@linkplain IWorkingSetProjectConfigurationController#updateCheckState(IControllerContext) initial
110
		 * check state} of a controller and for
111
		 * {@linkplain IWorkingSetProjectConfigurationController#checkStateChanged(Object, boolean, IControllerContext)
112
		 * vetoing check state changes}.
113
		 * 
114
		 * @param element
115
		 *            the element to update checked
116
		 * @param checked
117
		 *            whether the element should be checked
118
		 * 
119
		 * @see IWorkingSetProjectConfigurationController#checkStateChanged(Object, boolean,
120
		 *      IControllerContext)
121
		 * @see IWorkingSetProjectConfigurationController#updateCheckState(IControllerContext)
122
		 */
123
		void setChecked(Object element, boolean checked);
124
125
		/**
126
		 * Requests an update of the visual appearance of the specified element. The element may be any
127
		 * element under my control, or even the {@link IWorkingSetConfiguration} or {@link IWorkingSetProxy}
128
		 * that owns my project configuration.
129
		 * 
130
		 * @param element
131
		 *            an element to update
132
		 */
133
		void update(Object element);
134
135
		/**
136
		 * Notifies that the specified project configuration's activation state has changed. That is, that it
137
		 * is now activated when previously it was not, or vice-versa.
138
		 * 
139
		 * @param project
140
		 *            configuration the project configuration that changed
141
		 */
142
		void activationStateChanged(IWorkingSetProjectConfiguration projectConfiguration);
143
	}
144
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetConfiguration.java (+380 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import static org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager.ATTR_NAME;
15
import static org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager.KEY_PROJECT;
16
17
import java.util.List;
18
import java.util.Map;
19
20
import org.eclipse.core.resources.IProject;
21
import org.eclipse.core.runtime.IProgressMonitor;
22
import org.eclipse.core.runtime.IStatus;
23
import org.eclipse.core.runtime.MultiStatus;
24
import org.eclipse.core.runtime.Status;
25
import org.eclipse.core.runtime.SubMonitor;
26
import org.eclipse.osgi.util.NLS;
27
import org.eclipse.ui.IMemento;
28
import org.eclipse.ui.IWorkingSet;
29
30
import org.eclipse.cdt.ui.CUIPlugin;
31
32
/**
33
 * Default implementation of the {@link IWorkingSetConfiguration} interface.
34
 * 
35
 * @noextend This class is not intended to be subclassed by clients.
36
 * 
37
 * @author Christian W. Damus (cdamus)
38
 * 
39
 * @since 6.0
40
 * 
41
 */
42
public class WorkingSetConfiguration implements IWorkingSetConfiguration {
43
	private final IWorkingSetProxy workingSet;
44
	private String name;
45
46
	private Map<String, IWorkingSetProjectConfiguration> projects;
47
48
	/**
49
	 * Initializes me with my parent working set.
50
	 * 
51
	 * @param workingSet
52
	 *            my parent working set
53
	 */
54
	protected WorkingSetConfiguration(IWorkingSetProxy workingSet) {
55
		this.workingSet = workingSet;
56
	}
57
58
	/**
59
	 * Obtains my parent working set.
60
	 * 
61
	 * @return my parent
62
	 */
63
	public IWorkingSetProxy getWorkingSet() {
64
		return workingSet;
65
	}
66
67
	/**
68
	 * Obtains my name.
69
	 * 
70
	 * @return my name
71
	 */
72
	public String getName() {
73
		return name;
74
	}
75
76
	/**
77
	 * Sets my name.
78
	 * 
79
	 * @param name
80
	 *            my new name
81
	 * 
82
	 * @throws IllegalArgumentException
83
	 *             if the specified name is <code>null</code> or empty, or if it is already used by another
84
	 *             configuration in my warking set
85
	 */
86
	void setName(String name) {
87
		if ((name == null) || (name.length() == 0)) {
88
			throw new IllegalArgumentException("name is empty"); //$NON-NLS-1$
89
		}
90
91
		if (!name.equals(getName())) {
92
			if (getWorkingSet().getConfiguration(name) != null) {
93
				throw new IllegalArgumentException("name is already in use"); //$NON-NLS-1$
94
			}
95
96
			basicSetName(name);
97
		}
98
	}
99
100
	/**
101
	 * Provides simple access to the name for setting it.
102
	 * 
103
	 * @param name
104
	 *            my new name
105
	 */
106
	protected void basicSetName(String name) {
107
		this.name = name;
108
	}
109
110
	private Map<String, IWorkingSetProjectConfiguration> getProjects() {
111
		if (projects == null) {
112
			projects = new java.util.HashMap<String, IWorkingSetProjectConfiguration>();
113
114
			for (IProject next : workingSet.resolveProjects()) {
115
				IWorkingSetProjectConfiguration child = createProjectConfiguration(next);
116
117
				// the project may not be a C/C++ project
118
				if (child != null) {
119
					basicAddProjectConfiguration(child);
120
				}
121
			}
122
		}
123
124
		return projects;
125
	}
126
127
	protected void basicAddProjectConfiguration(IWorkingSetProjectConfiguration projectConfig) {
128
		if (projects == null) {
129
			projects = new java.util.HashMap<String, IWorkingSetProjectConfiguration>();
130
		}
131
		
132
		projects.put(projectConfig.getProjectName(), projectConfig);
133
	}
134
135
	public IWorkingSetProjectConfiguration getProjectConfiguration(String projectName) {
136
		return getProjects().get(projectName);
137
	}
138
139
	public java.util.Collection<IWorkingSetProjectConfiguration> getProjectConfigurations() {
140
		return getProjects().values();
141
	}
142
143
	public boolean isActive() {
144
		boolean result = !getProjects().isEmpty();
145
146
		if (result) {
147
			for (IWorkingSetProjectConfiguration next : getProjectConfigurations()) {
148
				if (!next.isActive()) {
149
					result = false;
150
					break;
151
				}
152
			}
153
		}
154
155
		return result;
156
	}
157
158
	public void activate() {
159
		if (!isActive()) {
160
			for (IWorkingSetProjectConfiguration next : getProjectConfigurations()) {
161
				next.activate();
162
			}
163
		}
164
165
		// this is a "recently used" working set
166
		IWorkingSet ws = getWorkingSet().resolve();
167
		if (ws != null) {
168
			WorkingSetConfigurationManager.WS_MGR.addRecentWorkingSet(ws);
169
		}
170
	}
171
172
	public IStatus build(IProgressMonitor monitor) {
173
		MultiStatus result = new MultiStatus(CUIPlugin.PLUGIN_ID, 0,
174
				WorkingSetMessages.WSConfig_build_problems, null);
175
176
		List<IWorkingSetProjectConfiguration> toBuild = new java.util.ArrayList<IWorkingSetProjectConfiguration>(
177
				getProjectConfigurations().size());
178
		for (IWorkingSetProjectConfiguration next : getProjectConfigurations()) {
179
			IProject project = next.resolveProject();
180
181
			if ((project != null) && (project.isAccessible())) {
182
				toBuild.add(next);
183
			}
184
		}
185
186
		SubMonitor progress = SubMonitor.convert(monitor, NLS.bind(WorkingSetMessages.WSConfig_build_task,
187
				getWorkingSet().getName()), toBuild.size());
188
189
		try {
190
			for (IWorkingSetProjectConfiguration next : toBuild) {
191
				if (progress.isCanceled()) {
192
					result.add(Status.CANCEL_STATUS);
193
					break;
194
				}
195
196
				IStatus status = next.build(progress.newChild(1));
197
198
				if ((status != null && !status.isOK())) {
199
					result.add(status);
200
				}
201
			}
202
		} finally {
203
			if (monitor != null) {
204
				monitor.done();
205
			}
206
		}
207
208
		return result.isOK() ? Status.OK_STATUS : result;
209
	}
210
211
	public void saveState(IMemento memento) {
212
		memento.putString(ATTR_NAME, getName());
213
214
		for (IWorkingSetProjectConfiguration next : getProjectConfigurations()) {
215
			next.saveState(memento.createChild(KEY_PROJECT));
216
		}
217
	}
218
219
	public void loadState(IMemento memento) {
220
		setName(memento.getString(ATTR_NAME));
221
222
		Map<String, IMemento> projectMementos = new java.util.HashMap<String, IMemento>();
223
		for (IMemento next : memento.getChildren(KEY_PROJECT)) {
224
			projectMementos.put(next.getString(ATTR_NAME), next);
225
		}
226
227
		for (IWorkingSetProjectConfiguration next : getProjectConfigurations()) {
228
			IMemento state = projectMementos.get(next.getProjectName());
229
			if (state != null) {
230
				next.loadState(state);
231
			}
232
		}
233
	}
234
235
	/**
236
	 * Creates a new project configuration for the specified project. May be overridden by subclasses to
237
	 * create a different implementation.
238
	 * 
239
	 * @param project
240
	 *            a workspace project
241
	 * @return a new project configuration element for it
242
	 */
243
	protected IWorkingSetProjectConfiguration createProjectConfiguration(IProject project) {
244
		IWorkingSetProjectConfiguration result = null;
245
246
		IWorkingSetProjectConfigurationFactory factory = IWorkingSetProjectConfigurationFactory.Registry.INSTANCE
247
				.getFactory(project);
248
		if (factory != null) {
249
			result = factory.createProjectConfiguration(this, project);
250
		}
251
252
		return result;
253
	}
254
255
	public ISnapshot createSnapshot(IWorkingSetProxy.ISnapshot workingSet, WorkspaceSnapshot workspace) {
256
257
		return new Snapshot(workingSet, this, workspace);
258
	}
259
260
	/**
261
	 * Utility method to query whether the specified configuration is a read-only snapshot.
262
	 * 
263
	 * @param config
264
	 *            a working set configuration
265
	 * @return whether it is a read-only snapshot
266
	 * 
267
	 * @see IWorkingSetConfiguration.ISnapshot#isReadOnly()
268
	 */
269
	static boolean isReadOnly(IWorkingSetConfiguration config) {
270
		return (config instanceof WorkingSetConfiguration.Snapshot)
271
				&& ((WorkingSetConfiguration.Snapshot) config).isReadOnly();
272
	}
273
274
	//
275
	// Nested classes
276
	//
277
278
	/**
279
	 * Default implementation of the mutable working set configuration snapshot.
280
	 * 
281
	 * @author Christian W. Damus (cdamus)
282
	 * 
283
	 * @noextend This class is not intended to be subclassed by clients.
284
	 * 
285
	 * @since 6.0
286
	 */
287
	public static class Snapshot extends WorkingSetConfiguration implements
288
			IWorkingSetConfiguration.ISnapshot {
289
290
		private final boolean readOnly;
291
		private final WorkspaceSnapshot workspace;
292
293
		/**
294
		 * Initializes me with the current workspace snapshot.
295
		 * 
296
		 * @param workingSet
297
		 *            my parent working set
298
		 * @param workspace
299
		 *            the current workspace snapshot
300
		 */
301
		protected Snapshot(IWorkingSetProxy workingSet, WorkspaceSnapshot workspace) {
302
			this(workingSet, workspace, false);
303
		}
304
305
		/**
306
		 * Initializes me as a special read-only configuration that shows what is the current active
307
		 * configuration of the projects in a working set when none of its named configurations is active.
308
		 * 
309
		 * @param workingSet
310
		 *            my parent working set
311
		 * @param workspace
312
		 *            the current workspace snapshot
313
		 * @param readOnly
314
		 *            whether I am read-only. A read-only configuration cannot be modified in the dialog
315
		 */
316
		protected Snapshot(IWorkingSetProxy workingSet, WorkspaceSnapshot workspace, boolean readOnly) {
317
			super(workingSet);
318
319
			this.readOnly = readOnly;
320
			this.workspace = workspace;
321
		}
322
323
		/**
324
		 * Initializes me with the current workspace snapshot.
325
		 * 
326
		 * @param workingSet
327
		 *            my parent working set
328
		 * @param config
329
		 *            the working set configuration that I copy
330
		 * @param workspace
331
		 *            the current workspace snapshot
332
		 */
333
		protected Snapshot(IWorkingSetProxy workingSet, IWorkingSetConfiguration config,
334
				WorkspaceSnapshot workspace) {
335
			this(workingSet, workspace);
336
337
			setName(config.getName());
338
339
			for (IWorkingSetProjectConfiguration next : config.getProjectConfigurations()) {
340
				basicAddProjectConfiguration(next.createSnapshot(this, workspace));
341
			}
342
		}
343
344
		@Override
345
		public final IWorkingSetProxy.ISnapshot getWorkingSet() {
346
			return (IWorkingSetProxy.ISnapshot) super.getWorkingSet();
347
		}
348
349
		/**
350
		 * Queries whether I am a read-only view of the current active configurations of my working set's
351
		 * projects.
352
		 * 
353
		 * @return whether I am read-only
354
		 */
355
		public final boolean isReadOnly() {
356
			return readOnly;
357
		}
358
359
		@Override
360
		public void setName(String name) {
361
			super.setName(name);
362
		}
363
364
		/**
365
		 * I create project configurations that are mutable, as I am.
366
		 */
367
		@Override
368
		protected IWorkingSetProjectConfiguration createProjectConfiguration(IProject project) {
369
			IWorkingSetProjectConfiguration result = null;
370
371
			IWorkingSetProjectConfigurationFactory factory = IWorkingSetProjectConfigurationFactory.Registry.INSTANCE
372
					.getFactory(project);
373
			if (factory != null) {
374
				result = factory.createProjectConfiguration(this, project).createSnapshot(this, workspace);
375
			}
376
377
			return result;
378
		}
379
	}
380
}
(-)schema/workingSetConfigurations.exsd (+149 lines)
Added Link Here
1
<?xml version='1.0' encoding='UTF-8'?>
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.cdt.ui" xmlns="http://www.w3.org/2001/XMLSchema">
4
<annotation>
5
      <appInfo>
6
         <meta.schema plugin="org.eclipse.cdt.ui" id="workingSetConfigurations" name="Working Set Configurations"/>
7
      </appInfo>
8
      <documentation>
9
         &lt;p&gt;
10
&lt;b&gt;This extension point is internal to the CDT plug-in family.&lt;/b&gt;
11
&lt;/p&gt;&lt;p&gt;
12
Extension point for registration of project configuration factories for handling extended configuration options for custom project natures, in working set configurations.  These factories are responsible for creating the project configuration elements and the UI controllers for the Manage Working Set Configurations dialog.
13
&lt;/p&gt;
14
      </documentation>
15
   </annotation>
16
17
   <element name="extension">
18
      <annotation>
19
         <appInfo>
20
            <meta.element />
21
         </appInfo>
22
      </annotation>
23
      <complexType>
24
         <sequence minOccurs="1" maxOccurs="unbounded">
25
            <element ref="projectConfigurationFactory"/>
26
         </sequence>
27
         <attribute name="point" type="string" use="required">
28
            <annotation>
29
               <documentation>
30
                  
31
               </documentation>
32
            </annotation>
33
         </attribute>
34
         <attribute name="id" type="string">
35
            <annotation>
36
               <documentation>
37
                  
38
               </documentation>
39
            </annotation>
40
         </attribute>
41
         <attribute name="name" type="string">
42
            <annotation>
43
               <documentation>
44
                  
45
               </documentation>
46
               <appInfo>
47
                  <meta.attribute translatable="true"/>
48
               </appInfo>
49
            </annotation>
50
         </attribute>
51
      </complexType>
52
   </element>
53
54
   <element name="projectConfigurationFactory">
55
      <annotation>
56
         <documentation>
57
            Registration of a factory for project configuration elements in working set configurations.  Factories are registered against project natures via nested &lt;tt&gt;&amp;lt;nature&amp;gt;&lt;/tt&gt; elements.
58
         </documentation>
59
      </annotation>
60
      <complexType>
61
         <sequence minOccurs="1" maxOccurs="unbounded">
62
            <element ref="projectNature"/>
63
         </sequence>
64
         <attribute name="id" type="string" use="required">
65
            <annotation>
66
               <documentation>
67
                  A unique identifier for the project configuration factory.
68
               </documentation>
69
            </annotation>
70
         </attribute>
71
         <attribute name="class" type="string" use="required">
72
            <annotation>
73
               <documentation>
74
                  Fully qualified name of the factory class.  It must implement the &lt;tt&gt;IWorkingSetProjectConfigurationFactory&lt;/tt&gt; interface.
75
               </documentation>
76
               <appInfo>
77
                  <meta.attribute kind="java" basedOn=":org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProjectConfigurationFactory"/>
78
               </appInfo>
79
            </annotation>
80
         </attribute>
81
      </complexType>
82
   </element>
83
84
   <element name="projectNature">
85
      <annotation>
86
         <documentation>
87
            A reference to a project nature.
88
         </documentation>
89
      </annotation>
90
      <complexType>
91
         <attribute name="id" type="string" use="required">
92
            <annotation>
93
               <documentation>
94
                  The referenced project nature ID.
95
               </documentation>
96
               <appInfo>
97
                  <meta.attribute kind="identifier" basedOn="org.eclipse.core.resources.natures/@id"/>
98
               </appInfo>
99
            </annotation>
100
         </attribute>
101
      </complexType>
102
   </element>
103
104
   <annotation>
105
      <appInfo>
106
         <meta.section type="since"/>
107
      </appInfo>
108
      <documentation>
109
         6.0
110
      </documentation>
111
   </annotation>
112
113
   <annotation>
114
      <appInfo>
115
         <meta.section type="examples"/>
116
      </appInfo>
117
      <documentation>
118
         &lt;pre&gt;
119
&lt;extension point=&quot;org.eclipse.cdt.ui.workingSetConfigurations&quot;&gt;
120
  &lt;projectConfigurationFactory
121
        id=&quot;org.example.myProject&quot;
122
        class=&quot;org.example.MyProjectConfigurationFactory&quot;&gt;
123
    &lt;nature id=&quot;org.example.myProjectNature&quot;/&gt;
124
  &lt;/projectConfigurationFactory&gt;
125
&lt;/extension&gt;
126
&lt;/pre&gt;
127
      </documentation>
128
   </annotation>
129
130
   <annotation>
131
      <appInfo>
132
         <meta.section type="apiinfo"/>
133
      </appInfo>
134
      <documentation>
135
         Registered project configuration factories are required to implement the &lt;tt&gt;org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProjectConfigurationFactory&lt;/tt&gt; interface.
136
      </documentation>
137
   </annotation>
138
139
140
   <annotation>
141
      <appInfo>
142
         <meta.section type="copyright"/>
143
      </appInfo>
144
      <documentation>
145
         Copyright (c) 2009 QNX Software Systems and others.  All rights reserved.
146
      </documentation>
147
   </annotation>
148
149
</schema>
(-)src/org/eclipse/cdt/internal/ui/workingsets/BuildJob.java (+102 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008, 2009 Intel Corporation, QNX Software Systems, and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Intel Corporation - initial API and implementation
10
 *     QNX Software Systems - [272416] Rework the working set configurations
11
 *******************************************************************************/
12
13
package org.eclipse.cdt.internal.ui.workingsets;
14
15
import java.util.Collection;
16
17
import org.eclipse.core.resources.IProject;
18
import org.eclipse.core.resources.IncrementalProjectBuilder;
19
import org.eclipse.core.resources.ResourcesPlugin;
20
import org.eclipse.core.runtime.CoreException;
21
import org.eclipse.core.runtime.IProgressMonitor;
22
import org.eclipse.core.runtime.IStatus;
23
import org.eclipse.core.runtime.MultiStatus;
24
import org.eclipse.core.runtime.Status;
25
import org.eclipse.core.runtime.jobs.Job;
26
27
import org.eclipse.cdt.ui.CUIPlugin;
28
import org.eclipse.cdt.ui.newui.UIMessages;
29
30
/**
31
 * A job that builds a bunch of workspace projects or a working set configuration.
32
 */
33
public final class BuildJob extends Job {
34
	private Collection<IProject> projects;
35
	private IWorkingSetConfiguration workingSetConfig;
36
37
	/**
38
	 * Initializes me with a bunch projects to build in their active configurations.
39
	 * 
40
	 * @param projects
41
	 *            the projects to build
42
	 */
43
	public BuildJob(Collection<IProject> projects) {
44
		super(UIMessages.getString("WorkingSetConfigAction.21")); //$NON-NLS-1$
45
		this.projects = new java.util.ArrayList<IProject>(projects);
46
	}
47
48
	/**
49
	 * Initializes me with a working set configuration to build.
50
	 * 
51
	 * @param workingSetConfig
52
	 *            the working set configuration to build
53
	 */
54
	public BuildJob(IWorkingSetConfiguration workingSetConfig) {
55
		super(UIMessages.getString("WorkingSetConfigAction.21")); //$NON-NLS-1$
56
		this.workingSetConfig = workingSetConfig;
57
	}
58
59
	@Override
60
	protected IStatus run(IProgressMonitor monitor) {
61
		if (projects != null) {
62
			return buildProjects(monitor);
63
		} else {
64
			return buildWorkingSetConfig(monitor);
65
		}
66
	}
67
68
	private IStatus buildProjects(IProgressMonitor monitor) {
69
		try {
70
			for (IProject p : projects) {
71
				try {
72
					setName(UIMessages.getString("WorkingSetConfigAction.21") + p.getName()); //$NON-NLS-1$
73
					p.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);
74
				} catch (CoreException e) {
75
					return new MultiStatus(CUIPlugin.PLUGIN_ID, 0, new IStatus[] { e.getStatus() },
76
							UIMessages.getString("WorkingSetConfigAction.22"), //$NON-NLS-1$
77
							null);
78
				}
79
				if (monitor.isCanceled()) {
80
					return Status.CANCEL_STATUS;
81
				}
82
			}
83
		} finally {
84
			monitor.done();
85
		}
86
		return Status.OK_STATUS;
87
	}
88
89
	private IStatus buildWorkingSetConfig(IProgressMonitor monitor) {
90
		try {
91
			return workingSetConfig.build(monitor);
92
		} finally {
93
			monitor.done();
94
		}
95
	}
96
97
	@Override
98
	public boolean belongsTo(Object family) {
99
		return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
100
	}
101
102
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetConfigurationDialog.java (+424 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.util.Collection;
15
16
import org.eclipse.core.resources.IProject;
17
import org.eclipse.jface.dialogs.IDialogConstants;
18
import org.eclipse.jface.dialogs.MessageDialog;
19
import org.eclipse.jface.dialogs.TrayDialog;
20
import org.eclipse.jface.layout.GridDataFactory;
21
import org.eclipse.jface.layout.GridLayoutFactory;
22
import org.eclipse.jface.resource.FontDescriptor;
23
import org.eclipse.jface.resource.JFaceResources;
24
import org.eclipse.jface.resource.LocalResourceManager;
25
import org.eclipse.jface.resource.ResourceManager;
26
import org.eclipse.jface.viewers.CheckboxTreeViewer;
27
import org.eclipse.jface.viewers.IFontProvider;
28
import org.eclipse.jface.viewers.ITreeContentProvider;
29
import org.eclipse.jface.viewers.LabelProvider;
30
import org.eclipse.jface.viewers.TreeViewer;
31
import org.eclipse.jface.viewers.Viewer;
32
import org.eclipse.jface.viewers.ViewerComparator;
33
import org.eclipse.jface.window.IShellProvider;
34
import org.eclipse.osgi.util.NLS;
35
import org.eclipse.swt.SWT;
36
import org.eclipse.swt.accessibility.AccessibleAdapter;
37
import org.eclipse.swt.accessibility.AccessibleEvent;
38
import org.eclipse.swt.custom.SashForm;
39
import org.eclipse.swt.graphics.Font;
40
import org.eclipse.swt.graphics.Image;
41
import org.eclipse.swt.layout.GridData;
42
import org.eclipse.swt.widgets.Button;
43
import org.eclipse.swt.widgets.Composite;
44
import org.eclipse.swt.widgets.Control;
45
import org.eclipse.swt.widgets.Label;
46
import org.eclipse.swt.widgets.Shell;
47
import org.eclipse.ui.model.WorkbenchLabelProvider;
48
49
import org.eclipse.cdt.internal.ui.CPluginImages;
50
import org.eclipse.cdt.internal.ui.dialogs.OptionalMessageDialog;
51
52
/**
53
 * A dialog for management of working set configurations. These collect the selection of project
54
 * configurations for the member projects of the working sets into named presets.
55
 * 
56
 * @author Christian W. Damus (cdamus)
57
 */
58
public class WorkingSetConfigurationDialog extends TrayDialog {
59
60
	private static final String BUILD_PROMPT_DIALOG_ID = "workingsets.build.prompt"; //$NON-NLS-1$
61
	private static final int BUILD_PROMPT_DIALOG_NO = 0;
62
	private static final int BUILD_PROMPT_DIALOG_CANCEL = 1;
63
	private static final int BUILD_PROMPT_DIALOG_YES = 2;
64
65
	private WorkspaceSnapshot workspace;
66
	private WorkingSetConfigsController controller;
67
68
	/**
69
	 * Initializes me with my shell.
70
	 * 
71
	 * @param shell
72
	 */
73
	public WorkingSetConfigurationDialog(Shell shell) {
74
		super(shell);
75
	}
76
77
	/**
78
	 * Initializes me with my shell provider.
79
	 * 
80
	 * @param parentShell
81
	 */
82
	public WorkingSetConfigurationDialog(IShellProvider parentShell) {
83
		super(parentShell);
84
	}
85
86
	@Override
87
	protected boolean isResizable() {
88
		return true;
89
	}
90
91
	@Override
92
	protected void configureShell(Shell newShell) {
93
		setHelpAvailable(false);
94
95
		super.configureShell(newShell);
96
97
		newShell.setText(WorkingSetMessages.WSConfigDialog_title);
98
	}
99
100
	@Override
101
	protected Control createDialogArea(Composite parent) {
102
		Composite result = (Composite) super.createDialogArea(parent);
103
104
		SashForm sashForm = new SashForm(result, SWT.VERTICAL | SWT.SMOOTH);
105
		sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
106
107
		GridLayoutFactory layoutFactory = GridLayoutFactory.fillDefaults();
108
		createWorkingSetConfigsArea(sashForm, layoutFactory.extendedMargins(0, 0, 0,
109
				convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN)));
110
		createProjectConfigsArea(sashForm, layoutFactory.extendedMargins(0, 0,
111
				convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN), 0));
112
113
		sashForm.setWeights(new int[] { 1, 1 });
114
115
		return result;
116
	}
117
118
	/**
119
	 * Creates the "working set configurations" pane in the upper part of the sash form.
120
	 * 
121
	 * @param parent
122
	 *            the parent composite
123
	 * @param layoutFactory
124
	 *            a layout-factory to use to lay out the composite in a grid, possibly pre-configured. Its use
125
	 *            is optional
126
	 * 
127
	 * @return the working set configurations pane
128
	 */
129
	protected Composite createWorkingSetConfigsArea(Composite parent, GridLayoutFactory layoutFactory) {
130
		Composite result = new Composite(parent, SWT.NONE);
131
		layoutFactory.numColumns(2).applyTo(result);
132
133
		GridDataFactory layoutDataFactory = GridDataFactory.fillDefaults();
134
135
		Label label = new Label(result, SWT.NONE);
136
		label.setText(WorkingSetMessages.WSConfigDialog_wsTree_label);
137
		layoutDataFactory.span(2, 1).applyTo(label);
138
139
		workspace = WorkingSetConfigurationManager.getDefault().createWorkspaceSnapshot();
140
		controller = new WorkingSetConfigsController(workspace);
141
142
		TreeViewer tree = new TreeViewer(result);
143
		layoutDataFactory.span(1, 1).align(SWT.FILL, SWT.FILL).grab(true, true).hint(250, SWT.DEFAULT)
144
				.applyTo(tree.getControl());
145
146
		tree.setContentProvider(new WSConfigsContentProvider());
147
		tree.setLabelProvider(new WSConfigsLabelProvider(tree));
148
		controller.setTreeViewer(tree);
149
150
		tree.setComparator(new ViewerComparator() {
151
			@Override
152
			public int category(Object element) {
153
				if (element instanceof IWorkingSetConfiguration.ISnapshot) {
154
					IWorkingSetConfiguration.ISnapshot config = (IWorkingSetConfiguration.ISnapshot) element;
155
					if (config.isReadOnly()) {
156
						return 0;
157
					}
158
				}
159
				return 1;
160
			}
161
		});
162
163
		tree.getTree().getAccessible().addAccessibleListener(new AccessibleAdapter() {
164
			@Override
165
			public void getName(AccessibleEvent e) {
166
				e.result = WorkingSetMessages.WSConfigDialog_wsTree_accessible_name;
167
			}
168
		});
169
170
		Composite buttons = new Composite(result, SWT.NONE);
171
		layoutDataFactory.grab(false, false).hint(SWT.DEFAULT, SWT.DEFAULT).applyTo(buttons);
172
		layoutFactory.numColumns(1).extendedMargins(0, 0, 0, 0).applyTo(buttons);
173
174
		Button button = new Button(buttons, SWT.PUSH);
175
		layoutDataFactory.align(SWT.FILL, SWT.BEGINNING).applyTo(button);
176
		button.setText(WorkingSetMessages.WSConfigDialog_add_label);
177
		controller.setAddButton(button);
178
179
		button = new Button(buttons, SWT.PUSH);
180
		layoutDataFactory.applyTo(button);
181
		button.setText(WorkingSetMessages.WSConfigDialog_remove_label);
182
		controller.setRemoveButton(button);
183
184
		button = new Button(buttons, SWT.PUSH);
185
		layoutDataFactory.applyTo(button);
186
		button.setText(WorkingSetMessages.WSConfigDialog_rename_label);
187
		controller.setRenameButton(button);
188
189
		button = new Button(buttons, SWT.PUSH);
190
		layoutDataFactory.applyTo(button);
191
		button.setText(WorkingSetMessages.WSConfigDialog_activate_label);
192
		controller.setActivateButton(button);
193
194
		return result;
195
	}
196
197
	/**
198
	 * Creates the "project configurations" pane in the lower part of the sash form.
199
	 * 
200
	 * @param parent
201
	 *            the parent composite
202
	 * @param layoutFactory
203
	 *            a layout-factory to use to lay out the composite in a grid, possibly pre-configured. Its use
204
	 *            is optional
205
	 * 
206
	 * @return the project configurations pane
207
	 */
208
	protected Composite createProjectConfigsArea(Composite parent, GridLayoutFactory layoutFactory) {
209
		Composite result = new Composite(parent, SWT.NONE);
210
		layoutFactory.numColumns(1).applyTo(result);
211
212
		GridDataFactory layoutDataFactory = GridDataFactory.fillDefaults();
213
214
		Label label = new Label(result, SWT.NONE);
215
		label.setText(WorkingSetMessages.WSConfigDialog_projTree_label);
216
		layoutDataFactory.applyTo(label);
217
218
		ProjectConfigsController projectsController = new ProjectConfigsController();
219
		CheckboxTreeViewer tree = new CheckboxTreeViewer(result);
220
		layoutDataFactory.span(1, 1).align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(tree.getControl());
221
222
		controller.setProjectConfigsController(projectsController);
223
		projectsController.setWorkingSetConfigurationsController(controller);
224
225
		projectsController.setTreeViewer(tree);
226
227
		tree.setComparator(new ViewerComparator());
228
229
		tree.getTree().getAccessible().addAccessibleListener(new AccessibleAdapter() {
230
			@Override
231
			public void getName(AccessibleEvent e) {
232
				e.result = WorkingSetMessages.WSConfigDialog_projTree_accessible_name;
233
			}
234
		});
235
236
		return result;
237
	}
238
239
	@Override
240
	protected void buttonPressed(int buttonId) {
241
		if (buttonId == IDialogConstants.OK_ID) {
242
			if (!build()) {
243
				// user cancelled: don't save, and don't close the dialog
244
				return;
245
			}
246
247
			save();
248
		}
249
250
		super.buttonPressed(buttonId);
251
	}
252
253
	/**
254
	 * Saves the working set configurations to storage.
255
	 */
256
	protected void save() {
257
		workspace.save();
258
	}
259
260
	/**
261
	 * Builds the projects that were reconfigured by the dialog, if any. The user is prompted (if prompting is
262
	 * not disabled via the preference) before building. The user has the options to build, not build, or
263
	 * cancel. The result indicates cancellation.
264
	 * 
265
	 * @return <code>true</code> if the user opted to save changes and exit the dialog (with or without
266
	 *         build); <code>false</code> if the user cancelled and the dialog should remain open and unsaved
267
	 */
268
	protected boolean build() {
269
		boolean result = true;
270
		Collection<IProject> projects = workspace.getProjectsToBuild();
271
272
		if (!projects.isEmpty()) {
273
			int defaultButton = OptionalMessageDialog.getDialogDetail(BUILD_PROMPT_DIALOG_ID);
274
			if (defaultButton == OptionalMessageDialog.NO_DETAIL) {
275
				defaultButton = BUILD_PROMPT_DIALOG_YES; // yes button is the default-default
276
			}
277
278
			int button = OptionalMessageDialog.open(BUILD_PROMPT_DIALOG_ID, getShell(),
279
					WorkingSetMessages.WSConfigDialog_buildPrompt_title, null,
280
					WorkingSetMessages.WSConfigDialog_buildPrompt_message, MessageDialog.QUESTION,
281
					new String[] { IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL,
282
							IDialogConstants.YES_LABEL }, defaultButton);
283
284
			if (button == OptionalMessageDialog.NOT_SHOWN) {
285
				// handle the case where the dialog was suppressed. Get the current default
286
				button = defaultButton;
287
			} else if (button != BUILD_PROMPT_DIALOG_CANCEL) {
288
				// store non-cancel selection as the new default answer
289
				OptionalMessageDialog.setDialogDetail(BUILD_PROMPT_DIALOG_ID, button);
290
			}
291
292
			switch (button) {
293
			case BUILD_PROMPT_DIALOG_YES:
294
				// do the build
295
				new BuildJob(projects).schedule();
296
				break;
297
			case BUILD_PROMPT_DIALOG_NO:
298
				// just don't build
299
				break;
300
			default: // BUILD_PROMPT_DIALOG_CANCEL
301
				result = false;
302
				break;
303
			}
304
		}
305
306
		return result;
307
	}
308
309
	//
310
	// Nested classes
311
	//
312
313
	/**
314
	 * Simple content provider for the working set configurations tree.
315
	 * 
316
	 * @author Christian W. Damus (cdamus)
317
	 */
318
	private static class WSConfigsContentProvider implements ITreeContentProvider {
319
		private Collection<IWorkingSetProxy> workingSets;
320
321
		public Object[] getChildren(Object parentElement) {
322
			if (parentElement == workingSets) {
323
				return workingSets.toArray();
324
			} else if (parentElement instanceof IWorkingSetProxy) {
325
				return ((IWorkingSetProxy) parentElement).getConfigurations().toArray();
326
			} else {
327
				return new Object[0];
328
			}
329
		}
330
331
		public Object getParent(Object element) {
332
			return (element instanceof IWorkingSetConfiguration) ? ((IWorkingSetConfiguration) element)
333
					.getWorkingSet() : null;
334
		}
335
336
		public boolean hasChildren(Object element) {
337
			return (element != null) && !(element instanceof IWorkingSetConfiguration);
338
		}
339
340
		public Object[] getElements(Object inputElement) {
341
			return getChildren(inputElement);
342
		}
343
344
		public void dispose() {
345
			// nothing to dispose
346
		}
347
348
		@SuppressWarnings("unchecked")
349
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
350
			workingSets = (Collection<IWorkingSetProxy>) newInput;
351
		}
352
353
	}
354
355
	/**
356
	 * Label provider for working sets and their configurations. The active configuration is highlighted in
357
	 * bold and affixed with an "(active)" decoration. The special read-only configuration is further
358
	 * differentiated with an italic font.
359
	 * 
360
	 * @author Christian W. Damus (cdamus)
361
	 */
362
	private static class WSConfigsLabelProvider extends LabelProvider implements IFontProvider {
363
		private WorkbenchLabelProvider wbLabels = new WorkbenchLabelProvider();
364
		private Image configImage = CPluginImages.get(CPluginImages.IMG_OBJS_CONFIG);
365
		private Font defaultFont;
366
367
		private ResourceManager fonts = new LocalResourceManager(JFaceResources.getResources());
368
369
		WSConfigsLabelProvider(Viewer viewer) {
370
			defaultFont = viewer.getControl().getFont();
371
		}
372
373
		@Override
374
		public String getText(Object element) {
375
			if (element instanceof IWorkingSetConfiguration) {
376
				IWorkingSetConfiguration config = (IWorkingSetConfiguration) element;
377
378
				if (config.isActive()) {
379
					return WorkingSetConfiguration.isReadOnly(config)
380
							? WorkingSetMessages.WSConfigDialog_implicit_config : NLS.bind(
381
									WorkingSetMessages.WSConfigDialog_active_config, config.getName());
382
				}
383
				return config.getName();
384
			} else if (element instanceof IWorkingSetProxy) {
385
				return ((IWorkingSetProxy) element).resolve().getLabel();
386
			}
387
388
			return wbLabels.getText(element);
389
		}
390
391
		@Override
392
		public Image getImage(Object element) {
393
			if (element instanceof IWorkingSetConfiguration) {
394
				return configImage;
395
			} else if (element instanceof IWorkingSetProxy) {
396
				return wbLabels.getImage(((IWorkingSetProxy) element).resolve());
397
			}
398
399
			return wbLabels.getImage(element);
400
		}
401
402
		@Override
403
		public void dispose() {
404
			wbLabels.dispose();
405
			fonts.dispose();
406
			super.dispose();
407
		}
408
409
		public Font getFont(Object element) {
410
			if (element instanceof IWorkingSetConfiguration) {
411
				IWorkingSetConfiguration config = (IWorkingSetConfiguration) element;
412
				if (config.isActive()) {
413
					FontDescriptor desc = FontDescriptor.createFrom(defaultFont);
414
415
					desc = WorkingSetConfiguration.isReadOnly(config) ? desc.withStyle(SWT.BOLD | SWT.ITALIC)
416
							: desc.withStyle(SWT.BOLD);
417
					return (Font) fonts.get(desc);
418
				}
419
			}
420
421
			return wbLabels.getFont(element);
422
		}
423
	}
424
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProxy.java (+161 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.util.Collection;
15
16
import org.eclipse.core.resources.IProject;
17
import org.eclipse.core.resources.IResource;
18
import org.eclipse.ui.IWorkingSet;
19
20
/**
21
 * The protocol for elements representing working sets, providing proxies for the workbench's actual
22
 * {@link IWorkingSet}s. A working set may have zero or more {@linkplain IWorkingSetConfiguration
23
 * configurations} that aggregate configuration settings for the C/C++ projects in the working set.
24
 * 
25
 * @noimplement This interface is not intended to be implemented by clients.
26
 * @noextend This interface is not intended to be extended by clients.
27
 * 
28
 * @author Christian W. Damus (cdamus)
29
 * 
30
 * @since 6.0
31
 * 
32
 */
33
public interface IWorkingSetProxy extends IWorkingSetConfigurationElement {
34
	/**
35
	 * Queries my name. This is the {@link IWorkingSet#getName() name} of my referenced working set, not its
36
	 * {@link IWorkingSet#getLabel() label}. As my referenced working set's name changes, so does my name.
37
	 * 
38
	 * @return my working set's name
39
	 */
40
	String getName();
41
42
	/**
43
	 * Resolves me to the actual working set as maintained by the workbench.
44
	 * 
45
	 * @return my referenced working set, or <code>null</code> if it no longer exists
46
	 */
47
	IWorkingSet resolve();
48
49
	/**
50
	 * Resolves the actual existing projects in my working set, that are currently
51
	 * {@linkplain IResource#isAccessible() accessible} in the workspace.
52
	 * 
53
	 * @return my projects
54
	 */
55
	Collection<IProject> resolveProjects();
56
57
	/**
58
	 * Queries whether I am a valid working set proxy, to be displayed to and manipulated by the user. This
59
	 * should at least check that the proxy {@linkplain #resolve() resolves} to an existing working set and
60
	 * that it includes at least one {@linkplain #resolveProjects() project}.
61
	 * 
62
	 * @return whether I am a valid working set proxy
63
	 */
64
	boolean isValid();
65
66
	/**
67
	 * Obtains the named configuration of my working set.
68
	 * 
69
	 * @param name
70
	 *            a configuration name
71
	 * 
72
	 * @return the matching configuration, or <code>null</code> if there is none such
73
	 */
74
	IWorkingSetConfiguration getConfiguration(String name);
75
76
	/**
77
	 * Obtains all of the configurations currently defined for my working set. If I am a working-copy
78
	 * {@linkplain IWorkingSetProxy.ISnapshot snapshot}, then these may include a special
79
	 * {@linkplain IWorkingSetConfiguration.ISnapshot#isReadOnly() read-only} configuration indicating the
80
	 * active configurations of my projects, if none of my named configurations is
81
	 * {@linkplain IWorkingSetConfiguration#isActive() active}.
82
	 * 
83
	 * @return my configurations
84
	 */
85
	Collection<IWorkingSetConfiguration> getConfigurations();
86
87
	/**
88
	 * Creates a <i>snapshot</i> (also known as a "working copy") of myself, providing a mutable view suitable
89
	 * for editing.
90
	 * 
91
	 * @param workspace
92
	 *            a workspace snapshot that captures the baseline state of the workspace and the working set
93
	 *            configurations that are to be edited
94
	 * 
95
	 * @return a working-copy snapshot of myself
96
	 */
97
	ISnapshot createSnapshot(WorkspaceSnapshot workspace);
98
99
	//
100
	// Nested types
101
	//
102
103
	/**
104
	 * The snapshot ("working copy") view of a working set proxy. It has additional API for modifying
105
	 * configurations, which can then be {@linkplain WorkspaceSnapshot#save() saved} for posterity.
106
	 * 
107
	 * @noimplement This interface is not intended to be implemented by clients.
108
	 * @noextend This interface is not intended to be extended by clients.
109
	 * 
110
	 * @author Christian W. Damus (cdamus)
111
	 * 
112
	 * @since 6.0
113
	 */
114
	interface ISnapshot extends IWorkingSetProxy {
115
		/**
116
		 * Creates a new configuration with the specified name.
117
		 * 
118
		 * @param name
119
		 *            a new configuration name
120
		 * 
121
		 * @return the new configuration
122
		 * 
123
		 * @throws IllegalArgumentException
124
		 *             if the new name is <code>null</code> or empty, or if it is already used by another
125
		 *             configuration of the same working set
126
		 */
127
		IWorkingSetConfiguration.ISnapshot createConfiguration(String name);
128
129
		/**
130
		 * Removes the specified configuration from me.
131
		 * 
132
		 * @param config
133
		 *            a configuration to remove
134
		 * 
135
		 * @throws IllegalArgumentException
136
		 *             if the configuration to be removed is
137
		 *             {@linkplain IWorkingSetConfiguration.ISnapshot#isReadOnly() read-only}
138
		 */
139
		void removeConfiguration(IWorkingSetConfiguration config);
140
141
		/**
142
		 * <p>
143
		 * Updates me according to the (assumed to have changed) activation state of my configurations. If any
144
		 * named configurations are active and I currently have a "fake"
145
		 * {@linkplain IWorkingSetConfiguration.ISnapshot#isReadOnly() read-only} configuration, then it is
146
		 * removed and I signal a "major change."
147
		 * </p>
148
		 * <p>
149
		 * If I have no named configurations that are active, and currently have not got a read-only
150
		 * configuration to show the active configuration, then I create it and signal a "major change."
151
		 * </p>
152
		 * <p>
153
		 * It is assumed that the UI will refresh the tree structure rooted in me when I signal a major
154
		 * change.
155
		 * </p>
156
		 * 
157
		 * @return whether this update results in a "major change" to my child configuration structure
158
		 */
159
		boolean updateActiveConfigurations();
160
	}
161
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetConfigurationElement.java (+34 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import org.eclipse.ui.IMemento;
15
import org.eclipse.ui.IPersistable;
16
17
/**
18
 * The protocol for elements of the working-set configuration model, which can
19
 * be persisted via {@linkplain IMemento mementos}.
20
 *
21
 * @author Christian W. Damus (cdamus)
22
 * 
23
 * @since 6.0
24
 * 
25
 */
26
public interface IWorkingSetConfigurationElement extends IPersistable {
27
	/**
28
	 * Loads me from the specified memento.
29
	 * 
30
	 * @param memento
31
	 *            a memento in which I am persisted
32
	 */
33
	void loadState(IMemento memento);
34
}
(-)src/org/eclipse/cdt/ui/actions/BuildWorkingSetConfigsContribution.java (+134 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.ui.actions;
13
14
import java.util.Collection;
15
import java.util.List;
16
17
import org.eclipse.jface.action.Action;
18
import org.eclipse.jface.action.ActionContributionItem;
19
import org.eclipse.jface.action.IContributionItem;
20
import org.eclipse.jface.action.MenuManager;
21
import org.eclipse.ui.IWorkingSet;
22
import org.eclipse.ui.IWorkingSetManager;
23
import org.eclipse.ui.actions.CompoundContributionItem;
24
25
import org.eclipse.cdt.ui.CUIPlugin;
26
27
import org.eclipse.cdt.internal.ui.workingsets.BuildJob;
28
import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetConfiguration;
29
import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProxy;
30
import org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager;
31
32
/**
33
 * A dynamic contribution of sub-menus to build configurations of working sets.
34
 *
35
 * @author Christian W. Damus (cdamus)
36
 * 
37
 * @since 6.0
38
 */
39
public class BuildWorkingSetConfigsContribution extends CompoundContributionItem {
40
41
	private IWorkingSetManager workingSetManager;
42
43
	/**
44
	 * Initializes me.
45
	 */
46
	public BuildWorkingSetConfigsContribution() {
47
		super();
48
	}
49
50
	/**
51
	 * Initializes me with my identifier.
52
	 *
53
	 * @param id my identifier
54
	 */
55
	public BuildWorkingSetConfigsContribution(String id) {
56
		super(id);
57
	}
58
59
	@Override
60
	protected IContributionItem[] getContributionItems() {
61
		// at most 5 recent working sets
62
		List<IContributionItem> result = new java.util.ArrayList<IContributionItem>(5);
63
		
64
		for (IWorkingSet recent : getWorkingsetManager().getRecentWorkingSets()) {
65
			IWorkingSetProxy proxy = WorkingSetConfigurationManager.getDefault().getWorkingSet(recent.getName());
66
			
67
			if (proxy != null) {
68
				result.add(createMenu(proxy));
69
			}
70
		}
71
		
72
		return result.toArray(new IContributionItem[result.size()]);
73
	}
74
	
75
	private IWorkingSetManager getWorkingsetManager() {
76
		if (workingSetManager == null) {
77
			workingSetManager = CUIPlugin.getDefault().getWorkbench().getWorkingSetManager();
78
		}
79
		
80
		return workingSetManager;
81
	}
82
	
83
	private IContributionItem createMenu(IWorkingSetProxy workingSet) {
84
		IContributionItem result;
85
		Collection<IWorkingSetConfiguration> configs = workingSet.getConfigurations();
86
		
87
		if (configs.isEmpty()) {
88
			result = new ActionContributionItem(new BuildWorkingSetAction(workingSet));
89
		} else {
90
			MenuManager submenu = new MenuManager(workingSet.resolve().getLabel());
91
			result = submenu;
92
			
93
			for (IWorkingSetConfiguration next : configs) {
94
				submenu.add(new BuildConfigAction(next));
95
			}
96
		}
97
		
98
		return result;
99
	}
100
101
	//
102
	// Nested classes
103
	//
104
105
	private static class BuildWorkingSetAction extends Action {
106
		private IWorkingSetProxy workingSet;
107
108
		BuildWorkingSetAction(IWorkingSetProxy workingSet) {
109
			super(workingSet.resolve().getLabel());
110
			
111
			this.workingSet = workingSet;
112
		}
113
114
		@Override
115
		public void run() {
116
			new BuildJob(workingSet.resolveProjects()).schedule();
117
		}
118
	}
119
120
	private static class BuildConfigAction extends Action {
121
		private IWorkingSetConfiguration workingSetConfig;
122
123
		BuildConfigAction(IWorkingSetConfiguration workingSetConfig) {
124
			super(workingSetConfig.getName());
125
			
126
			this.workingSetConfig = workingSetConfig;
127
		}
128
129
		@Override
130
		public void run() {
131
			new BuildJob(workingSetConfig).schedule();
132
		}
133
	}
134
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetConfiguration.java (+181 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.util.Collection;
15
16
import org.eclipse.core.resources.IResource;
17
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.core.runtime.IStatus;
19
20
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
21
22
/**
23
 * <p>
24
 * The protocol for working set configurations. A working set configuration specifies, at a minimum, a
25
 * {@linkplain ICConfigurationDescription build configuration} for each C/C++ project in the working set.
26
 * {@linkplain #activate() activating} the configuration applies these build configurations to the respective
27
 * projects as their active build configurations.
28
 * </p>
29
 * <p>
30
 * Implementations of this interface may choose to manage more configuration settings than are captured by the
31
 * active build configuration. They are, then, responsible for persistence, editing, and application of these
32
 * settings.
33
 * </p>
34
 * <p>
35
 * A working set configuration is considered to be {@linkplain #isActive() active} if all of the projects in
36
 * the working set are configured to build according to the configuration specified by the working set
37
 * configuration. It is an implementation detail (i.e., unspecified) what it means for a working set that has
38
 * recorded settings for projects that are not currently {@linkplain IResource#isAccessible() accessible} in
39
 * the workspace. However, for projects that are accessible and are included in the working set, but for which
40
 * the working set configuration has no settings, such projects are implicitly in the working set
41
 * configuration and it specifies their current configuration settings. Thus, in the extreme case, a
42
 * working-set configuration that includes none of the projects that currently are members of the working set,
43
 * is active.
44
 * </p>
45
 * 
46
 * @noimplement This interface is not intended to be implemented by clients.
47
 * @noextend This interface is not intended to be extended by clients.
48
 * 
49
 * @author Christian W. Damus (cdamus)
50
 * 
51
 * @since 6.0
52
 */
53
public interface IWorkingSetConfiguration extends IWorkingSetConfigurationElement {
54
	/**
55
	 * Obtains the working set element that contains me.
56
	 * 
57
	 * @return my working set
58
	 */
59
	IWorkingSetProxy getWorkingSet();
60
61
	/**
62
	 * Queries my name.
63
	 * 
64
	 * @return my name
65
	 */
66
	String getName();
67
68
	/**
69
	 * Obtains the project configuration element for the specified project.
70
	 * 
71
	 * @param projectName
72
	 *            a project name
73
	 * 
74
	 * @return that project's configuration element
75
	 * 
76
	 * @throws IllegalArgumentException
77
	 *             if the specified project is not a member of my working set
78
	 * 
79
	 * @see #getProjectConfigurations()
80
	 */
81
	IWorkingSetProjectConfiguration getProjectConfiguration(String projectName);
82
83
	/**
84
	 * Obtains the configuration elements for all of the projects in my working set. These include any
85
	 * projects that were not in my working set when I was last updated, and does not include any projects
86
	 * that were in my working set when I was last updated but that no longer are.
87
	 * 
88
	 * @return my project configuration elements
89
	 */
90
	Collection<IWorkingSetProjectConfiguration> getProjectConfigurations();
91
92
	/**
93
	 * Queries whether I am currently active in the workspace. I am active if and only if for every the
94
	 * projects in my working set, its active configuration is the one that I specify for it. As a special
95
	 * case, the configurations of an empty working set can never be active.
96
	 * 
97
	 * @return whether I am currently active in the workspace
98
	 * 
99
	 * @see #activate()
100
	 */
101
	boolean isActive();
102
103
	/**
104
	 * Updates the workspace to set, for each project in my working set, the active configuration that I
105
	 * specify for it. This method has no effect if I am already active.
106
	 * 
107
	 * @see #isActive()
108
	 */
109
	void activate();
110
111
	/**
112
	 * Builds my project configurations in the workspace.
113
	 * 
114
	 * @param monitor
115
	 *            for reporting progress of the working-set build
116
	 * @return the aggregate status of the individual
117
	 *         {@linkplain IWorkingSetProjectConfiguration#build(IProgressMonitor) project builds}
118
	 */
119
	IStatus build(IProgressMonitor monitor);
120
121
	/**
122
	 * Creates a <i>snapshot</i> (also known as a "working copy") of myself, providing a mutable view suitable
123
	 * for editing.
124
	 * 
125
	 * @param workingSet
126
	 *            my parent working set snapshot
127
	 * @param workspace
128
	 *            a workspace snapshot that captures the baseline state of the workspace and the working set
129
	 *            configurations that are to be edited
130
	 * 
131
	 * @return a working-copy snapshot of myself
132
	 */
133
	ISnapshot createSnapshot(IWorkingSetProxy.ISnapshot workingSet, WorkspaceSnapshot workspace);
134
135
	//
136
	// Nested types
137
	//
138
139
	/**
140
	 * The snapshot ("working copy") view of a working set configuration. It defines additional API for the
141
	 * manipulation of working set configurations.
142
	 * 
143
	 * @noimplement This interface is not intended to be implemented by clients.
144
	 * @noextend This interface is not intended to be extended by clients.
145
	 * 
146
	 * @author Christian W. Damus (cdamus)
147
	 * 
148
	 * @since 6.0
149
	 */
150
	interface ISnapshot extends IWorkingSetConfiguration {
151
		IWorkingSetProxy.ISnapshot getWorkingSet();
152
153
		/**
154
		 * <p>
155
		 * Queries whether I am read-only. Read-only working set configurations are used for the special case
156
		 * of showing what is the active configuration of the projects in a working set when none of the named
157
		 * working set configurations is active. Thus, a working set that has no user-defined named
158
		 * configurations does, at least, have its read-only active configuration.
159
		 * </p>
160
		 * <p>
161
		 * A working set only ever has at most one read-only configuration, though it may have multiple active
162
		 * configurations if some of its configurations are equivalent.
163
		 * </p>
164
		 * 
165
		 * @return whether I am the read-only active configuration of my working set
166
		 */
167
		boolean isReadOnly();
168
169
		/**
170
		 * Sets my name, which must be unique amongst the configurations in my working set.
171
		 * 
172
		 * @param name
173
		 *            my new, unique name
174
		 * 
175
		 * @throws IllegalArgumentException
176
		 *             if the new name is <code>null</code> or empty, or if it is already used by another
177
		 *             configuration of the same working set
178
		 */
179
		void setName(String name);
180
	}
181
}
(-)src/org/eclipse/cdt/ui/actions/BuildWorkingSetConfigAction.java (+220 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.ui.actions;
13
14
import java.util.Collection;
15
16
import org.eclipse.jface.action.IAction;
17
import org.eclipse.jface.action.IMenuCreator;
18
import org.eclipse.jface.util.IPropertyChangeListener;
19
import org.eclipse.jface.util.PropertyChangeEvent;
20
import org.eclipse.jface.viewers.ISelection;
21
import org.eclipse.swt.SWT;
22
import org.eclipse.swt.events.MenuAdapter;
23
import org.eclipse.swt.events.MenuEvent;
24
import org.eclipse.swt.events.SelectionAdapter;
25
import org.eclipse.swt.events.SelectionEvent;
26
import org.eclipse.swt.widgets.Control;
27
import org.eclipse.swt.widgets.Menu;
28
import org.eclipse.swt.widgets.MenuItem;
29
import org.eclipse.ui.IWorkbenchWindow;
30
import org.eclipse.ui.IWorkbenchWindowPulldownDelegate2;
31
import org.eclipse.ui.IWorkingSet;
32
import org.eclipse.ui.IWorkingSetManager;
33
import org.eclipse.ui.actions.ActionDelegate;
34
35
import org.eclipse.cdt.internal.ui.workingsets.BuildJob;
36
import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetConfiguration;
37
import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProxy;
38
import org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager;
39
40
/**
41
 * A dynamic sub-menu action that provides access to working-set configurations
42
 * to build them.
43
 * 
44
 * @author Christian W. Damus (cdamus)
45
 * 
46
 * @since 6.0
47
 * 
48
 */
49
public class BuildWorkingSetConfigAction extends ActionDelegate implements IWorkbenchWindowPulldownDelegate2,
50
		IMenuCreator {
51
	
52
	private IWorkingSetManager workingSetManager;
53
54
	private IAction action;
55
56
	private Menu menu;
57
58
	private IPropertyChangeListener wsmListener;
59
60
	/**
61
	 * Initializes me.
62
	 */
63
	public BuildWorkingSetConfigAction() {
64
		super();
65
	}
66
67
	public Menu getMenu(Menu parent) {
68
		return initMenu(new Menu(parent));
69
	}
70
71
	public Menu getMenu(Control parent) {
72
		return initMenu(new Menu(parent));
73
	}
74
75
	@Override
76
	public void init(IAction action) {
77
		this.action = action;
78
79
		if (workingSetManager != null) {
80
			updateEnablement();
81
		}
82
83
		action.setMenuCreator(this);
84
	}
85
86
	public void init(IWorkbenchWindow window) {
87
		workingSetManager = window.getWorkbench().getWorkingSetManager();
88
89
		wsmListener = new IPropertyChangeListener() {
90
91
			public void propertyChange(PropertyChangeEvent event) {
92
				updateEnablement();
93
			}
94
		};
95
		workingSetManager.addPropertyChangeListener(wsmListener);
96
		updateEnablement();
97
	}
98
	
99
	@Override
100
	public void selectionChanged(IAction action, ISelection selection) {
101
		updateEnablement();
102
	}
103
104
	private void updateEnablement() {
105
		if (action != null) {
106
			action.setEnabled(workingSetManager.getRecentWorkingSets().length > 0);
107
		}
108
	}
109
	
110
	private Menu initMenu(final Menu menu) {
111
		this.menu = menu;
112
		
113
		menu.addMenuListener(new MenuAdapter(){
114
			@Override
115
			public void menuShown(MenuEvent e) {
116
				fillMenu(menu);
117
			}
118
		});
119
		
120
		return menu;
121
	}
122
123
	private Menu fillMenu(Menu menu) {
124
		clearMenu(menu);
125
126
		for (IWorkingSet next : workingSetManager.getRecentWorkingSets()) {
127
			createWorkingSetSubMenu(menu, next);
128
		}
129
130
		return this.menu;
131
	}
132
133
	private MenuItem createWorkingSetSubMenu(Menu parentMenu, IWorkingSet workingSet) {
134
		MenuItem result = null;
135
		IWorkingSetProxy configHolder = WorkingSetConfigurationManager.getDefault().getWorkingSet(
136
				workingSet.getName());
137
138
		if (configHolder != null) {
139
			Collection<IWorkingSetConfiguration> configs = configHolder.getConfigurations();
140
141
			if (configs.isEmpty()) {
142
				// just build whatever projects are in the set, at their current configuration
143
				result = new MenuItem(parentMenu, SWT.PUSH);
144
				result.addSelectionListener(new BuildWorkingSetAction(configHolder));
145
			} else {
146
				// sub-menu for specific configurations
147
				result = new MenuItem(parentMenu, SWT.CASCADE);
148
				Menu submenu = new Menu(result);
149
				result.setMenu(submenu);
150
151
				for (IWorkingSetConfiguration config : configs) {
152
					createWorkingSetConfigItem(submenu, config);
153
				}
154
			}
155
			
156
			result.setText(workingSet.getLabel());
157
		}
158
159
		return result;
160
	}
161
	
162
	private MenuItem createWorkingSetConfigItem(Menu parentMenu, IWorkingSetConfiguration config) {
163
		MenuItem result = new MenuItem(parentMenu, SWT.PUSH);
164
		result.setText(config.getName());
165
		result.addSelectionListener(new BuildConfigAction(config));
166
		return result;
167
	}
168
169
	private void clearMenu(Menu menu) {
170
		MenuItem[] items = menu.getItems();
171
		for (MenuItem next : items) {
172
			next.dispose();
173
		}
174
	}
175
176
	@Override
177
	public void dispose() {
178
		if (menu != null) {
179
			menu.dispose();
180
			menu = null;
181
		}
182
183
		if (wsmListener != null) {
184
			workingSetManager.removePropertyChangeListener(wsmListener);
185
			wsmListener = null;
186
		}
187
188
		super.dispose();
189
	}
190
191
	//
192
	// Nested classes
193
	//
194
195
	private static class BuildWorkingSetAction extends SelectionAdapter {
196
		private IWorkingSetProxy workingSet;
197
198
		BuildWorkingSetAction(IWorkingSetProxy workingSet) {
199
			this.workingSet = workingSet;
200
		}
201
202
		@Override
203
		public void widgetSelected(SelectionEvent e) {
204
			new BuildJob(workingSet.resolveProjects()).schedule();
205
		}
206
	}
207
208
	private static class BuildConfigAction extends SelectionAdapter {
209
		private IWorkingSetConfiguration workingSetConfig;
210
211
		BuildConfigAction(IWorkingSetConfiguration workingSetConfig) {
212
			this.workingSetConfig = workingSetConfig;
213
		}
214
215
		@Override
216
		public void widgetSelected(SelectionEvent e) {
217
			new BuildJob(workingSetConfig).schedule();
218
		}
219
	}
220
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfigurationFactory.java (+394 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.util.Arrays;
15
import java.util.Comparator;
16
import java.util.Map;
17
import java.util.Set;
18
19
import org.eclipse.core.resources.IProject;
20
import org.eclipse.core.resources.IProjectNatureDescriptor;
21
import org.eclipse.core.resources.IWorkspace;
22
import org.eclipse.core.resources.ResourcesPlugin;
23
import org.eclipse.core.runtime.CoreException;
24
import org.eclipse.core.runtime.IConfigurationElement;
25
import org.eclipse.core.runtime.IExecutableExtension;
26
import org.eclipse.core.runtime.IExtension;
27
import org.eclipse.core.runtime.IExtensionRegistry;
28
import org.eclipse.core.runtime.IStatus;
29
import org.eclipse.core.runtime.MultiStatus;
30
import org.eclipse.core.runtime.Platform;
31
import org.eclipse.core.runtime.Status;
32
import org.eclipse.osgi.util.NLS;
33
34
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
35
import org.eclipse.cdt.ui.CUIPlugin;
36
37
import org.eclipse.cdt.internal.ui.workingsets.WorkspaceSnapshot.ProjectState;
38
39
/**
40
 * Protocol for a factory of {@link IWorkingSetProjectConfiguration}s. Factories are {@linkplain Registry
41
 * registered} against project natures.
42
 * 
43
 * @author Christian W. Damus (cdamus)
44
 * 
45
 * @since 6.0
46
 */
47
public interface IWorkingSetProjectConfigurationFactory {
48
	/**
49
	 * Queries my factory ID. The ID is persisted in the working set configuration data so that the same
50
	 * factory can be used to reconstruct project configurations when loading the working set configurations.
51
	 * 
52
	 * @return my unique identifier
53
	 */
54
	String getID();
55
56
	/**
57
	 * Creates a new project configuration element.
58
	 * 
59
	 * @param parent
60
	 *            the working set configuration that owns the new project configuration
61
	 * @param project
62
	 *            the workspace project for which to create the configuration
63
	 * 
64
	 * @return the new project configuration
65
	 */
66
	IWorkingSetProjectConfiguration createProjectConfiguration(IWorkingSetConfiguration parent,
67
			IProject project);
68
69
	/**
70
	 * Creates a UI controller to support editing the specified project configuration snapshot, which should
71
	 * have been obtained from a configuration that I previously
72
	 * {@linkplain #createProjectConfiguration(org.eclipse.cdt.internal.ui.workingsets.IWorkingSetConfiguration, IProject)
73
	 * created}, myself.
74
	 * 
75
	 * @param config
76
	 *            a project configuration snapshot that I created
77
	 * 
78
	 * @return a suitable controller for it. Must not be <code>null</code>
79
	 */
80
	IWorkingSetProjectConfigurationController createProjectConfigurationController(
81
			IWorkingSetProjectConfiguration.ISnapshot config);
82
83
	/**
84
	 * Creates a snapshot of the configuration state of a project in the workspace. This may capture
85
	 * additional build meta-data beyond just the "active configuration."
86
	 * 
87
	 * @param project
88
	 *            a project to capture in a {@link WorkspaceSnapshot}
89
	 * @param desc
90
	 *            the project description, from which to capture the initial configuration data
91
	 * 
92
	 * @return the project state capture. Must not be <code>null</code>
93
	 */
94
	WorkspaceSnapshot.ProjectState createProjectState(IProject project, ICProjectDescription desc);
95
96
	//
97
	// Nested types
98
	//
99
100
	/**
101
	 * A registry of {@linkplain IWorkingSetProjectConfigurationFactory project configuration factories}
102
	 * contributed on the <tt>org.eclipse.cdt.ui.workingSetConfigurations</tt> extension point.
103
	 * 
104
	 * @author Christian W. Damus (cdamus)
105
	 * 
106
	 * @since 6.0
107
	 */
108
	class Registry {
109
		private static final String EXT_PT_ID = "workingSetConfigurations"; //$NON-NLS-1$
110
		private static final String E_FACTORY = "projectConfigurationFactory"; //$NON-NLS-1$
111
		private static final String E_NATURE = "projectNature"; //$NON-NLS-1$
112
		private static final String A_ID = "id"; //$NON-NLS-1$
113
		private static final String A_CLASS = "class"; //$NON-NLS-1$
114
115
		/**
116
		 * The shared project configuration factory registry.
117
		 */
118
		public static Registry INSTANCE = new Registry();
119
120
		private final IWorkingSetProjectConfigurationFactory defaultFactory = new Default();
121
		private final Map<String, IWorkingSetProjectConfigurationFactory> factoriesByID = new java.util.HashMap<String, IWorkingSetProjectConfigurationFactory>();
122
		private final Map<String, IWorkingSetProjectConfigurationFactory> factoriesByNature = new java.util.HashMap<String, IWorkingSetProjectConfigurationFactory>();
123
124
		private Map<String, Set<String>> projectNaturePartOrdering;
125
126
		private Registry() {
127
			super();
128
129
			projectNaturePartOrdering = computeProjectNaturePartOrdering();
130
131
			loadExtensions();
132
		}
133
134
		public IWorkingSetProjectConfigurationFactory getFactory(String id) {
135
			IWorkingSetProjectConfigurationFactory result = get(factoriesByID, id);
136
137
			if (result == null) {
138
				result = defaultFactory;
139
			}
140
141
			return result;
142
		}
143
144
		public IWorkingSetProjectConfigurationFactory getFactory(IProject project) {
145
			IWorkingSetProjectConfigurationFactory result = null;
146
147
			for (String nature : getPartOrderedNatureIDs(project)) {
148
				result = get(factoriesByNature, nature);
149
150
				if (result != null) {
151
					break;
152
				}
153
			}
154
155
			return result;
156
		}
157
158
		private IWorkingSetProjectConfigurationFactory get(
159
				Map<?, IWorkingSetProjectConfigurationFactory> map, Object key) {
160
			return map.get(key);
161
		}
162
163
		private String[] getPartOrderedNatureIDs(IProject project) {
164
			String[] result;
165
166
			try {
167
				result = project.getDescription().getNatureIds();
168
			} catch (CoreException e) {
169
				CUIPlugin.log(e.getStatus());
170
				result = new String[0];
171
			}
172
173
			if (result.length > 0) {
174
				Arrays.sort(result, new Comparator<String>() {
175
					public int compare(String nature1, String nature2) {
176
						Set<String> required1 = projectNaturePartOrdering.get(nature1);
177
						Set<String> required2 = projectNaturePartOrdering.get(nature2);
178
179
						if (required1.contains(nature2)) {
180
							return -1; // required1 precedes required2
181
						} else if (required2.contains(nature1)) {
182
							return +1; // required2 precedes required1
183
						} else if (nature1.startsWith("org.eclipse.cdt.") //$NON-NLS-1$
184
								&& !nature2.startsWith("org.eclipse.cdt.")) { //$NON-NLS-1$
185
							return +1; // lower priority to CDT natures
186
						} else if (nature2.startsWith("org.eclipse.cdt.") //$NON-NLS-1$
187
								&& !nature1.startsWith("org.eclipse.cdt.")) { //$NON-NLS-1$
188
							return -1; // lower priority to CDT natures
189
						}
190
191
						return 0; // not partially comparable
192
					}
193
				});
194
			}
195
196
			return result;
197
		}
198
199
		private Map<String, Set<String>> computeProjectNaturePartOrdering() {
200
			Map<String, Set<String>> result = new java.util.HashMap<String, Set<String>>();
201
202
			// first pass to populate the map with immediate requireds
203
			IWorkspace ws = ResourcesPlugin.getWorkspace();
204
			for (IProjectNatureDescriptor next : ws.getNatureDescriptors()) {
205
				result.put(next.getNatureId(), new java.util.HashSet<String>(Arrays.asList(next
206
						.getRequiredNatureIds())));
207
			}
208
209
			// now, iterate to add transitive requireds
210
			boolean loopAgain;
211
			do {
212
				loopAgain = false;
213
214
				for (Map.Entry<String, Set<String>> next : result.entrySet()) {
215
					Set<String> requireds = next.getValue();
216
					Set<String> newRequireds = new java.util.HashSet<String>(requireds);
217
218
					boolean changed = false;
219
220
					for (String required : requireds) {
221
						changed |= newRequireds.addAll(result.get(required));
222
					}
223
224
					if (changed) {
225
						loopAgain = true;
226
						next.setValue(newRequireds);
227
					}
228
				}
229
			} while (loopAgain);
230
231
			return result;
232
		}
233
234
		private void loadExtensions() {
235
			IExtensionRegistry registry = Platform.getExtensionRegistry();
236
			for (IExtension ext : registry.getExtensionPoint(CUIPlugin.PLUGIN_ID, EXT_PT_ID).getExtensions()) {
237
				for (IConfigurationElement element : ext.getConfigurationElements()) {
238
					if (E_FACTORY.equals(element.getName())) {
239
						try {
240
							Descriptor desc = new Descriptor(element);
241
242
							synchronized (factoriesByID) {
243
								factoriesByID.put(desc.getID(), desc);
244
							}
245
246
							synchronized (factoriesByNature) {
247
								for (IConfigurationElement nature : element.getChildren(E_NATURE)) {
248
									String natureID = nature.getAttribute(A_ID);
249
250
									if (natureID != null) {
251
										factoriesByNature.put(natureID, desc);
252
									} else {
253
										CUIPlugin.log(NLS.bind(
254
												WorkingSetMessages.WSProjConfigFactory_noNatureID, ext
255
														.getContributor().getName()), null);
256
									}
257
								}
258
							}
259
						} catch (CoreException e) {
260
							CUIPlugin.log(e.getStatus());
261
						}
262
					}
263
				}
264
			}
265
		}
266
267
		//
268
		// Nested classes
269
		//
270
271
		/**
272
		 * A self-resolving descriptor for lazy instantiation of a factory.
273
		 */
274
		private class Descriptor implements IWorkingSetProjectConfigurationFactory {
275
			private final IConfigurationElement extension;
276
			private final String id;
277
278
			Descriptor(IConfigurationElement extension) throws CoreException {
279
				this.extension = extension;
280
				id = extension.getAttribute(A_ID);
281
282
				if (id == null) {
283
					throw new CoreException(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, NLS.bind(
284
							WorkingSetMessages.WSProjConfigFactory_noFactoryID, extension.getContributor()
285
									.getName())));
286
				}
287
			}
288
289
			public String getID() {
290
				return id;
291
			}
292
293
			public IWorkingSetProjectConfiguration createProjectConfiguration(
294
					IWorkingSetConfiguration parent, IProject project) {
295
				return resolve().createProjectConfiguration(parent, project);
296
			}
297
298
			public IWorkingSetProjectConfigurationController createProjectConfigurationController(
299
					IWorkingSetProjectConfiguration.ISnapshot config) {
300
301
				return resolve().createProjectConfigurationController(config);
302
			}
303
304
			public ProjectState createProjectState(IProject project, ICProjectDescription desc) {
305
				return resolve().createProjectState(project, desc);
306
			}
307
308
			private IWorkingSetProjectConfigurationFactory resolve() {
309
				IWorkingSetProjectConfigurationFactory result = null;
310
311
				try {
312
					result = (IWorkingSetProjectConfigurationFactory) extension
313
							.createExecutableExtension(A_CLASS);
314
				} catch (ClassCastException e) {
315
					CUIPlugin.log(NLS.bind(WorkingSetMessages.WSProjConfigFactory_badFactory, extension
316
							.getContributor().getName()), e);
317
				} catch (CoreException e) {
318
					CUIPlugin.log(new MultiStatus(CUIPlugin.PLUGIN_ID, 0, new IStatus[] { e.getStatus() },
319
							WorkingSetMessages.WSProjConfigFactory_factoryFailed, null));
320
				}
321
322
				if (result == null) {
323
					result = defaultFactory;
324
				}
325
326
				// replace the descriptor in the maps
327
				synchronized (factoriesByID) {
328
					factoriesByID.put(getID(), result);
329
				}
330
				synchronized (factoriesByNature) {
331
					for (Map.Entry<String, IWorkingSetProjectConfigurationFactory> next : factoriesByNature
332
							.entrySet()) {
333
						if (next.getValue().getID().equals(getID())) {
334
							next.setValue(result);
335
						}
336
					}
337
				}
338
339
				return result;
340
			}
341
		}
342
343
		/**
344
		 * The default project configuration factory. Clients may extend this class to implement custom
345
		 * factories for their project natures.
346
		 * 
347
		 * @author Christian W. Damus (cdamus)
348
		 * 
349
		 * @since 6.0
350
		 */
351
		public static class Default implements IWorkingSetProjectConfigurationFactory, IExecutableExtension {
352
353
			private String id;
354
355
			public Default() {
356
				super();
357
			}
358
359
			public IWorkingSetProjectConfiguration createProjectConfiguration(
360
					IWorkingSetConfiguration parent, IProject project) {
361
362
				WorkingSetProjectConfiguration result = createProjectConfiguration(parent);
363
				result.setProjectName(project.getName());
364
				return result;
365
			}
366
367
			protected WorkingSetProjectConfiguration createProjectConfiguration(
368
					IWorkingSetConfiguration parent) {
369
				return new WorkingSetProjectConfiguration(parent);
370
			}
371
372
			public IWorkingSetProjectConfigurationController createProjectConfigurationController(
373
					IWorkingSetProjectConfiguration.ISnapshot config) {
374
375
				return new ProjectConfigurationController(config);
376
			}
377
378
			public ProjectState createProjectState(IProject project, ICProjectDescription desc) {
379
				return new WorkspaceSnapshot.ProjectState(project, desc);
380
			}
381
382
			public String getID() {
383
				return id;
384
			}
385
386
			public void setInitializationData(IConfigurationElement config, String propertyName, Object data)
387
					throws CoreException {
388
389
				this.id = config.getAttribute(A_ID);
390
			}
391
392
		}
393
	}
394
}
(-)src/org/eclipse/cdt/internal/ui/workingsets/ProjectConfigurationController.java (+174 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.cdt.internal.ui.workingsets;
13
14
import java.util.Set;
15
16
import org.eclipse.jface.viewers.ILabelProvider;
17
import org.eclipse.jface.viewers.ITreeContentProvider;
18
import org.eclipse.jface.viewers.Viewer;
19
import org.eclipse.swt.graphics.Image;
20
import org.eclipse.ui.model.WorkbenchLabelProvider;
21
22
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
23
24
import org.eclipse.cdt.internal.ui.CPluginImages;
25
import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProjectConfiguration.ISnapshot;
26
27
/**
28
 * Default implementation of the working set project configuration controller protocol.
29
 * 
30
 * @author Christian W. Damus (cdamus)
31
 * 
32
 * @since 6.0
33
 * 
34
 */
35
public class ProjectConfigurationController implements IWorkingSetProjectConfigurationController {
36
	
37
	private IWorkingSetProjectConfiguration.ISnapshot config;
38
39
	/**
40
	 * Initializes me with my project configuration.
41
	 * 
42
	 * @param config
43
	 *            my project configuration
44
	 */
45
	public ProjectConfigurationController(IWorkingSetProjectConfiguration.ISnapshot config) {
46
		this.config = config;
47
	}
48
49
	public ISnapshot getProjectConfiguration() {
50
		return config;
51
	}
52
53
	public void checkStateChanged(Object element, boolean checked, IControllerContext context) {
54
		if (!context.isReadOnly() && (element instanceof ICConfigurationDescription)) {
55
56
			ICConfigurationDescription newSel = (ICConfigurationDescription) element;
57
			ICConfigurationDescription oldSel = getProjectConfiguration().resolveSelectedConfiguration();
58
59
			boolean oldActive = getProjectConfiguration().isActive();
60
61
			if (checked) {
62
				if (newSel != oldSel) {
63
					getProjectConfiguration().setSelectedConfigurationID(newSel.getId());
64
65
					if (oldSel != null) {
66
						context.setChecked(oldSel, false);
67
					}
68
				}
69
			} else if (newSel == oldSel) {
70
				// cannot just uncheck the current selection
71
				context.setChecked(oldSel, true);
72
			}
73
74
			boolean newActive = getProjectConfiguration().isActive();
75
			if (oldActive != newActive) {
76
				context.activationStateChanged(getProjectConfiguration());
77
			}
78
		} else {
79
			// cannot change the check-state of these nodes
80
			context.setChecked(element, !checked);
81
		}
82
	}
83
84
	public void updateCheckState(IControllerContext context) {
85
		ICConfigurationDescription sel = getProjectConfiguration().resolveSelectedConfiguration();
86
87
		if (sel != null) {
88
			context.setChecked(sel, true);
89
		}
90
	}
91
92
	public ITreeContentProvider getContentProvider() {
93
		return new ContentProvider(getProjectConfiguration());
94
	}
95
96
	public ILabelProvider getLabelProvider() {
97
		return new LabelProvider();
98
	}
99
100
	//
101
	// Nested classes
102
	//
103
104
	private static class ContentProvider implements ITreeContentProvider {
105
		private static final Object[] NO_OBJECTS = new Object[0];
106
107
		private IWorkingSetProjectConfiguration project;
108
		private Set<ICConfigurationDescription> configs;
109
110
		ContentProvider(IWorkingSetProjectConfiguration project) {
111
			this.project = project;
112
			this.configs = new java.util.HashSet<ICConfigurationDescription>(project.resolveConfigurations());
113
		}
114
115
		public Object[] getChildren(Object parentElement) {
116
			return (parentElement == project) ? project.resolveConfigurations().toArray() : NO_OBJECTS;
117
		}
118
119
		public Object getParent(Object element) {
120
			return (element == project) ? null : configs.contains(element) ? project : null;
121
		}
122
123
		public boolean hasChildren(Object element) {
124
			return element == project;
125
		}
126
127
		public Object[] getElements(Object inputElement) {
128
			return new Object[] { project };
129
		}
130
131
		public void dispose() {
132
			// nothing to dispose
133
		}
134
135
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
136
			// nothing to do
137
		}
138
139
	}
140
	
141
	private static class LabelProvider extends org.eclipse.jface.viewers.LabelProvider {
142
		private WorkbenchLabelProvider wbLabels = new WorkbenchLabelProvider();
143
		private Image configImage = CPluginImages.get(CPluginImages.IMG_OBJS_CONFIG);
144
145
		@Override
146
		public String getText(Object element) {
147
			if (element instanceof ICConfigurationDescription) {
148
				return ((ICConfigurationDescription) element).getName();
149
			} else if (element instanceof IWorkingSetProjectConfiguration) {
150
				return wbLabels.getText(((IWorkingSetProjectConfiguration) element).resolveProject());
151
			}
152
153
			return wbLabels.getText(element);
154
		}
155
156
		@Override
157
		public Image getImage(Object element) {
158
			if (element instanceof ICConfigurationDescription) {
159
				return configImage;
160
			} else if (element instanceof IWorkingSetProjectConfiguration) {
161
				return wbLabels.getImage(((IWorkingSetProjectConfiguration) element).resolveProject());
162
			}
163
164
			return wbLabels.getImage(element);
165
		}
166
167
		@Override
168
		public void dispose() {
169
			wbLabels.dispose();
170
			super.dispose();
171
		}
172
	}
173
174
}

Return to bug 272416