Skip to content

Commit 44d3cf6

Browse files
committed
Add some visual separation between toolchain settings
- groups around the global and per-toolchain settings with labels - whitespace between different toolchain settings - new logic that shows which projects + build configs are using each displayed toolchain - added links on the project properties pages back to the global and workspace preferences - updated the descriptions in the pages The change in XpackDirectoryNotStrictFieldEditor fixes the implementation to allow doFillIntoGrid to be called multiple times. This is how the other field editors handle it. This is needed now because of how the layout is now being handled with the extra layer of UI hierarchy. Fixes #574
1 parent 1949b0d commit 44d3cf6

File tree

11 files changed

+897
-178
lines changed

11 files changed

+897
-178
lines changed

plugins/org.eclipse.embedcdt.managedbuild.cross.arm.ui/src/org/eclipse/embedcdt/internal/managedbuild/cross/arm/ui/Messages.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2011, 2013 Marc-Andre Laperle and others.
2+
* Copyright (c) 2011, 2023 Marc-Andre Laperle and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -64,10 +64,26 @@ public class Messages extends NLS {
6464
public static String ToolchainPaths_label;
6565
public static String ToolchainName_label;
6666

67+
public static String ProjectToolchainsPathPropertiesPage_GlobalSettings_link;
68+
69+
public static String ProjectToolchainsPathPropertiesPage_ToolchainMessageAllConfigs_label;
70+
71+
public static String ProjectToolchainsPathPropertiesPage_ToolchainMessageSomeConfigs_label;
72+
73+
public static String ProjectToolchainsPathPropertiesPage_WorkspaceSettings_link;
74+
6775
public static String ProjectToolchainsPathsPropertiesPage_description;
6876
public static String WorkspaceToolchainsPathsPreferencesPage_description;
6977
public static String GlobalToolchainsPathsPreferencesPage_description;
7078

79+
public static String GlobalToolchainsPathsPreferencesPage_ToolchainDefaultGroup_label;
80+
81+
public static String GlobalToolchainsPathsPreferencesPage_ToolchainMessageDefault_label;
82+
83+
public static String GlobalToolchainsPathsPreferencesPage_ToolchainMessageWithProjects_label;
84+
85+
public static String GlobalToolchainsPathsPreferencesPage_ToolchainPathGroup_label;
86+
7187
public static String SetCrossCommandWizardPage_text;
7288

7389
// ------------------------------------------------------------------------

plugins/org.eclipse.embedcdt.managedbuild.cross.arm.ui/src/org/eclipse/embedcdt/internal/managedbuild/cross/arm/ui/messages.properties

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
###############################################################################
2-
# Copyright (c) 2011, 2013 Marc-Andre Laperle
2+
# Copyright (c) 2011, 2023 Marc-Andre Laperle and others.
33
#
44
# This program and the accompanying materials
55
# are made available under the terms of the Eclipse Public License 2.0
@@ -64,29 +64,41 @@ ToolsPaths_ToolchainName_label=Toolchain name:
6464
ToolchainPaths_label=Toolchain folder:
6565
ToolchainName_label=Default toolchain:
6666

67+
ProjectToolchainsPathPropertiesPage_GlobalSettings_link=<a>Configure Global Settings...</a>
68+
ProjectToolchainsPathPropertiesPage_ToolchainMessageAllConfigs_label=Toolchain used in this project by all configurations
69+
ProjectToolchainsPathPropertiesPage_ToolchainMessageSomeConfigs_label=Toolchain used in this project by the following configurations: {0}
70+
ProjectToolchainsPathPropertiesPage_WorkspaceSettings_link=<a>Configure Workspace Settings...</a>\n
6771
ProjectToolchainsPathsPropertiesPage_description=\
6872
Configure the location where various GNU Arm toolchains are installed. \
69-
The values are stored in the workspace (not in the project). \
70-
They are used for all build configurations of this project, \
71-
and override the workspace or global paths. \
73+
A path specified on this page is stored in the project and override the workspace or global paths.\n\
74+
As the toolchain locations specified here are stored in the project, it is generally not a good idea to \
75+
specify paths here. Instead prefer to specify toolchain locations either at the Workspace or Global \
76+
preferences.\n\
77+
Only the toolchains in use by this project are shown on this page.\
7278
\n
7379

7480
WorkspaceToolchainsPathsPreferencesPage_description=\
7581
Configure the locations where various GNU Arm toolchains are installed. \
76-
The paths are stored in the workspace and override the global paths. \
82+
A path specified on this page is stored in the workspace and override the global paths. \
7783
Unless redefined per project, they are used for all \
78-
projects in this workspace. \
84+
projects in this workspace.\n\
85+
Only the toolchains in use by projects in the workspace are shown on this page. \
7986
\n
8087

8188
GlobalToolchainsPathsPreferencesPage_description=\
8289
Configure the locations where various GNU Arm toolchains are installed. \
8390
The values are stored within Eclipse. \
8491
Unless redefined more specifically, they are used for all \
85-
projects in all workspaces. \
92+
projects in all workspaces.\n\
93+
Only the toolchains in use by projects in the workspace are shown on this page. \
8694
\n
95+
GlobalToolchainsPathsPreferencesPage_ToolchainDefaultGroup_label=Select the default toolchain to be used when creating new projects
96+
GlobalToolchainsPathsPreferencesPage_ToolchainMessageDefault_label=Toolchain used by default for new projects
97+
GlobalToolchainsPathsPreferencesPage_ToolchainMessageWithProjects_label=Toolchain used by the following projects: {0}
98+
GlobalToolchainsPathsPreferencesPage_ToolchainPathGroup_label=Specify toolchain paths for in use toolchains
8799

88100
SetCrossCommandWizardPage_text=\
89101
On macOS use Shift+Cmd+'.' to show the hidden folders while browsing the file system. \
90-
xpm uses a .content folder to store the binaries.\n
102+
xpm uses a .content folder to store the binaries.
91103

92104

plugins/org.eclipse.embedcdt.managedbuild.cross.arm.ui/src/org/eclipse/embedcdt/internal/managedbuild/cross/arm/ui/preferences/GlobalToolchainsPathsPreferencesPage.java

Lines changed: 135 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2015 Liviu Ionescu.
2+
* Copyright (c) 2015, 2023 Liviu Ionescu and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -15,8 +15,12 @@
1515

1616
package org.eclipse.embedcdt.internal.managedbuild.cross.arm.ui.preferences;
1717

18-
import java.util.HashSet;
18+
import java.util.Comparator;
19+
import java.util.Map;
1920
import java.util.Set;
21+
import java.util.TreeMap;
22+
import java.util.TreeSet;
23+
import java.util.stream.Collectors;
2024

2125
import org.eclipse.cdt.managedbuilder.core.BuildException;
2226
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
@@ -35,10 +39,15 @@
3539
import org.eclipse.embedcdt.managedbuild.cross.core.preferences.PersistentPreferences;
3640
import org.eclipse.embedcdt.ui.LabelFakeFieldEditor;
3741
import org.eclipse.embedcdt.ui.XpackDirectoryNotStrictFieldEditor;
42+
import org.eclipse.jface.layout.PixelConverter;
3843
import org.eclipse.jface.preference.FieldEditor;
3944
import org.eclipse.jface.preference.FieldEditorPreferencePage;
45+
import org.eclipse.osgi.util.NLS;
4046
import org.eclipse.swt.SWT;
4147
import org.eclipse.swt.layout.GridData;
48+
import org.eclipse.swt.layout.GridLayout;
49+
import org.eclipse.swt.widgets.Composite;
50+
import org.eclipse.swt.widgets.Group;
4251
import org.eclipse.swt.widgets.Label;
4352
import org.eclipse.ui.IWorkbench;
4453
import org.eclipse.ui.IWorkbenchPreferencePage;
@@ -97,21 +106,22 @@ public void init(IWorkbench workbench) {
97106
*/
98107
@Override
99108
protected void createFieldEditors() {
109+
final Composite parent = getFieldEditorParent();
110+
final GridLayout layout = new GridLayout();
111+
layout.marginWidth = 0;
112+
parent.setLayout(layout);
100113

101-
boolean isStrict;
102-
103-
FieldEditor toolchainNameField = new ToolchainsFieldEditor(PersistentPreferences.TOOLCHAIN_ID_KEY,
104-
Messages.ToolchainName_label, getFieldEditorParent());
105-
addField(toolchainNameField);
106-
107-
Set<ToolchainDefinition> toolchains = new HashSet<>();
114+
Map<ToolchainDefinition, Map<String, Set<String>>> toolchains = new TreeMap<>(
115+
Comparator.comparing(ToolchainDefinition::getName));
108116

109117
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
110-
for (int i = 0; i < projects.length; ++i) {
111-
IConfiguration[] configs = EclipseUtils.getConfigurationsForProject(projects[i]);
118+
for (IProject project : projects) {
119+
IConfiguration[] configs = EclipseUtils.getConfigurationsForProject(project);
120+
boolean allConfigsUseSameToolchain = true;
121+
ToolchainDefinition toolchainInUse = null;
112122
if (configs != null) {
113-
for (int j = 0; j < configs.length; ++j) {
114-
IToolChain toolchain = configs[j].getToolChain();
123+
for (IConfiguration config : configs) {
124+
IToolChain toolchain = config.getToolChain();
115125
if (toolchain == null) {
116126
continue;
117127
}
@@ -120,7 +130,16 @@ protected void createFieldEditors() {
120130
try {
121131
String toolchainId = optionId.getStringValue();
122132
int ix = ToolchainDefinition.findToolchainById(toolchainId);
123-
toolchains.add(ToolchainDefinition.getToolchain(ix));
133+
134+
ToolchainDefinition toolchainDefinition = ToolchainDefinition.getToolchain(ix);
135+
if (toolchainInUse == null) {
136+
toolchainInUse = toolchainDefinition;
137+
} else if (!toolchainInUse.equals(toolchainDefinition)) {
138+
allConfigsUseSameToolchain = false;
139+
}
140+
var projectMap = toolchains.computeIfAbsent(toolchainDefinition, x -> new TreeMap<>());
141+
var buildConfigsSet = projectMap.computeIfAbsent(project.getName(), x -> new TreeSet<>());
142+
buildConfigsSet.add(config.getName());
124143
continue;
125144
} catch (BuildException e) {
126145
} catch (IndexOutOfBoundsException e) {
@@ -131,20 +150,36 @@ protected void createFieldEditors() {
131150
try {
132151
String toolchainName = optionName.getStringValue();
133152
int ix = ToolchainDefinition.findToolchainByName(toolchainName);
134-
toolchains.add(ToolchainDefinition.getToolchain(ix));
153+
154+
ToolchainDefinition toolchainDefinition = ToolchainDefinition.getToolchain(ix);
155+
if (toolchainInUse == null) {
156+
toolchainInUse = toolchainDefinition;
157+
} else if (!toolchainInUse.equals(toolchainDefinition)) {
158+
allConfigsUseSameToolchain = false;
159+
}
160+
var projectMap = toolchains.computeIfAbsent(toolchainDefinition, x -> new TreeMap<>());
161+
var buildConfigsSet = projectMap.computeIfAbsent(project.getName(), x -> new TreeSet<>());
162+
buildConfigsSet.add(config.getName());
135163
} catch (BuildException e) {
136164
} catch (IndexOutOfBoundsException e) {
137165
}
138166
}
139167
}
140168
}
169+
170+
if (allConfigsUseSameToolchain && toolchainInUse != null) {
171+
Set<String> set = toolchains.get(toolchainInUse).get(project.getName());
172+
// If all the configurations use the same toolchain, don't display
173+
// any of the configurations in the UI
174+
set.clear();
175+
}
141176
}
142177

143178
if (toolchains.isEmpty()) {
144179
try {
145180
String toolchainId = fPersistentPreferences.getToolchainId();
146181
int ix = ToolchainDefinition.findToolchainById(toolchainId);
147-
toolchains.add(ToolchainDefinition.getToolchain(ix));
182+
toolchains.computeIfAbsent(ToolchainDefinition.getToolchain(ix), x -> Map.of());
148183
} catch (IndexOutOfBoundsException e) {
149184
}
150185
}
@@ -153,37 +188,111 @@ protected void createFieldEditors() {
153188
try {
154189
String toolchainName = fPersistentPreferences.getToolchainName();
155190
int ix = ToolchainDefinition.findToolchainByName(toolchainName);
156-
toolchains.add(ToolchainDefinition.getToolchain(ix));
191+
toolchains.computeIfAbsent(ToolchainDefinition.getToolchain(ix), x -> Map.of());
157192
} catch (IndexOutOfBoundsException e) {
158193
}
159194
}
160195

161196
if (toolchains.isEmpty()) {
162197
int ix = ToolchainDefinition.getDefault();
163-
toolchains.add(ToolchainDefinition.getToolchain(ix));
198+
toolchains.computeIfAbsent(ToolchainDefinition.getToolchain(ix), x -> Map.of());
164199
}
165200

166-
for (ToolchainDefinition toolchain : toolchains) {
201+
final Group group = new Group(parent, SWT.NONE);
202+
group.setText(Messages.GlobalToolchainsPathsPreferencesPage_ToolchainPathGroup_label);
203+
GridLayout groupLayout = new GridLayout(4, false);
204+
group.setLayout(groupLayout);
205+
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
206+
207+
boolean first = true;
208+
for (var entry : toolchains.entrySet()) {
209+
if (first) {
210+
first = false;
211+
} else {
212+
Label verticalSpacer = new Label(group, SWT.NONE);
213+
GridData layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1);
214+
verticalSpacer.setLayoutData(layoutData);
215+
verticalSpacer.setText("");
216+
}
217+
218+
ToolchainDefinition toolchain = entry.getKey();
219+
var projectToConfigsMap = entry.getValue();
220+
221+
Label message = new Label(group, SWT.WRAP);
222+
GridData layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1);
223+
message.setLayoutData(layoutData);
224+
if (projectToConfigsMap.isEmpty()) {
225+
message.setText(Messages.GlobalToolchainsPathsPreferencesPage_ToolchainMessageDefault_label);
226+
} else {
227+
String collected = projectToConfigsMap.entrySet().stream().map(e -> {
228+
String projectName = e.getKey();
229+
Set<String> configNames = e.getValue();
230+
if (configNames.isEmpty()) {
231+
return projectName;
232+
} else {
233+
return projectName + " (" + String.join(", ", configNames) + ")";
234+
}
235+
}).collect(Collectors.joining(", "));
236+
message.setText(NLS.bind(
237+
Messages.GlobalToolchainsPathsPreferencesPage_ToolchainMessageWithProjects_label, collected));
238+
239+
}
240+
PixelConverter pixelConverter = new PixelConverter(message);
241+
layoutData.widthHint = pixelConverter
242+
.convertWidthInCharsToPixels(Math.min(message.getText().length(), 100));
167243

168244
FieldEditor labelField = new LabelFakeFieldEditor(toolchain.getFullName(),
169-
Messages.ToolsPaths_ToolchainName_label, getFieldEditorParent());
245+
Messages.ToolsPaths_ToolchainName_label, group);
246+
labelField.fillIntoGrid(group, 4);
170247
addField(labelField);
171248

172-
isStrict = fDefaultPreferences.getBoolean(PersistentPreferences.WORKSPACE_TOOLCHAIN_PATH_STRICT, true);
249+
boolean isStrict = fDefaultPreferences.getBoolean(PersistentPreferences.WORKSPACE_TOOLCHAIN_PATH_STRICT,
250+
true);
173251

174252
String[] xpackNames = fDefaultPreferences.getToolchainXpackNames(toolchain.getId(), toolchain.getName());
175253

176254
String key = PersistentPreferences.getToolchainKey(toolchain.getId(), toolchain.getName());
177255
FieldEditor toolchainPathField = new XpackDirectoryNotStrictFieldEditor(xpackNames, key,
178-
Messages.ToolchainPaths_label, getFieldEditorParent(), isStrict);
179-
256+
Messages.ToolchainPaths_label, group, isStrict);
257+
toolchainPathField.fillIntoGrid(group, 4);
180258
addField(toolchainPathField);
181259
}
182260

183-
Label message = new Label(getFieldEditorParent(), SWT.NONE);
261+
Label verticalSpacer = new Label(group, SWT.NONE);
184262
GridData layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1);
185-
message.setLayoutData(layoutData);
186-
message.setText(Messages.SetCrossCommandWizardPage_text);
263+
verticalSpacer.setLayoutData(layoutData);
264+
verticalSpacer.setText("");
265+
266+
Label macOSMessage = new Label(group, SWT.NONE);
267+
layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1);
268+
macOSMessage.setLayoutData(layoutData);
269+
macOSMessage.setText(Messages.SetCrossCommandWizardPage_text);
270+
271+
// Layout need to be reset after fields are added
272+
group.setLayout(groupLayout);
273+
274+
final Group group1 = new Group(parent, SWT.NONE);
275+
group1.setText(Messages.GlobalToolchainsPathsPreferencesPage_ToolchainDefaultGroup_label);
276+
GridLayout group1Layout = new GridLayout(2, false);
277+
group1.setLayout(group1Layout);
278+
group1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
279+
280+
FieldEditor toolchainNameField = new ToolchainsFieldEditor(PersistentPreferences.TOOLCHAIN_ID_KEY,
281+
Messages.ToolchainName_label, group1);
282+
toolchainNameField.fillIntoGrid(group1, 2);
283+
// ComboFieldEditor does not grab excess space (like StringFieldEditor does) therefore
284+
// we need to specify that here. ComboFieldEditor also doesn't provide an equivalent
285+
// to StringFieldEditor.getTextControl, hence the need to get control's layout data
286+
// like this
287+
((GridData) group1.getChildren()[1].getLayoutData()).grabExcessHorizontalSpace = true;
288+
addField(toolchainNameField);
289+
// Layout need to be reset after fields are added
290+
group1.setLayout(group1Layout);
291+
}
292+
293+
@Override
294+
protected void adjustGridLayout() {
295+
// do nothing as we are manually handling the grid layout in createFieldEditors
187296
}
188297

189298
// ------------------------------------------------------------------------

0 commit comments

Comments
 (0)