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
1515
1616package 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 ;
1920import java .util .Set ;
21+ import java .util .TreeMap ;
22+ import java .util .TreeSet ;
23+ import java .util .stream .Collectors ;
2024
2125import org .eclipse .cdt .managedbuilder .core .BuildException ;
2226import org .eclipse .cdt .managedbuilder .core .IConfiguration ;
3539import org .eclipse .embedcdt .managedbuild .cross .core .preferences .PersistentPreferences ;
3640import org .eclipse .embedcdt .ui .LabelFakeFieldEditor ;
3741import org .eclipse .embedcdt .ui .XpackDirectoryNotStrictFieldEditor ;
42+ import org .eclipse .jface .layout .PixelConverter ;
3843import org .eclipse .jface .preference .FieldEditor ;
3944import org .eclipse .jface .preference .FieldEditorPreferencePage ;
45+ import org .eclipse .osgi .util .NLS ;
4046import org .eclipse .swt .SWT ;
4147import 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 ;
4251import org .eclipse .swt .widgets .Label ;
4352import org .eclipse .ui .IWorkbench ;
4453import 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