Skip to content

Commit fd62f0b

Browse files
authored
Merge pull request #575 from jonahgraham/toolchain-preferences
Add some visual separation between toolchain settings
2 parents 1949b0d + 44d3cf6 commit fd62f0b

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)