Skip to content

Commit 8c6a0b7

Browse files
authored
IEP-1669 Automatically Run IDF Activation Script on Terminal Startup (#1388)
* feat: using activation scrip for esp-idf terminal * fix: adding mementoHandler back * fix: change assertTrue to see actual test output * fix: add smart check for encoding in tests * feat: added color presets to the terminal * feat: added assert to restore check to provide user friendly msg
1 parent d27a7c5 commit 8c6a0b7

19 files changed

Lines changed: 501 additions & 382 deletions

bundles/com.espressif.idf.terminal.connector/META-INF/MANIFEST.MF

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.cdt.core;resolution:=optional,
1414
org.eclipse.terminal.view.ui;bundle-version="[1.0.0,2.0.0)",
1515
org.eclipse.terminal.view.core;bundle-version="[1.0.0,2.0.0)",
1616
org.eclipse.terminal.connector.process;bundle-version="[1.0.0,2.0.0)",
17-
org.eclipse.terminal.control;bundle-version="[1.0.0,2.0.0)"
17+
org.eclipse.terminal.control;bundle-version="[1.0.0,2.0.0)",
18+
com.google.gson
1819
Bundle-RequiredExecutionEnvironment: JavaSE-17
1920
Bundle-ActivationPolicy: lazy
2021
Bundle-Localization: plugin

bundles/com.espressif.idf.terminal.connector/plugin.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<!-- uses process connector -->
77
<extension point="org.eclipse.terminal.control.connectors">
88
<connector
9-
class="org.eclipse.terminal.connector.process.ProcessConnector"
9+
class="com.espressif.idf.terminal.connector.launcher.IDFTerminalProcessConnector"
1010
hidden="true"
1111
id="com.espressif.idf.terminal.connector.espidfConnector"
1212
name="%TerminalConnector.local"/>
@@ -21,4 +21,4 @@
2121
</delegate>
2222
</extension>
2323

24-
</plugin>
24+
</plugin>

bundles/com.espressif.idf.terminal.connector/src/com/espressif/idf/terminal/connector/controls/IDFConsoleWizardConfigurationPanel.java

Lines changed: 146 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,65 @@
1212
*******************************************************************************/
1313
package com.espressif.idf.terminal.connector.controls;
1414

15+
import java.util.ArrayList;
16+
import java.util.List;
1517
import java.util.Map;
1618
import java.util.Optional;
1719

1820
import org.eclipse.core.resources.IProject;
1921
import org.eclipse.core.resources.ResourcesPlugin;
2022
import org.eclipse.core.runtime.CoreException;
2123
import org.eclipse.core.runtime.Platform;
24+
import org.eclipse.core.runtime.preferences.InstanceScope;
2225
import org.eclipse.jface.dialogs.IDialogSettings;
26+
import org.eclipse.jface.preference.IPreferenceStore;
27+
import org.eclipse.jface.resource.JFaceResources;
2328
import org.eclipse.swt.SWT;
2429
import org.eclipse.swt.layout.GridData;
2530
import org.eclipse.swt.layout.GridLayout;
31+
import org.eclipse.swt.widgets.Button;
2632
import org.eclipse.swt.widgets.Combo;
2733
import org.eclipse.swt.widgets.Composite;
34+
import org.eclipse.swt.widgets.Group;
2835
import org.eclipse.swt.widgets.Label;
2936
import org.eclipse.terminal.view.core.ITerminalsConnectorConstants;
3037
import org.eclipse.terminal.view.ui.launcher.AbstractExtendedConfigurationPanel;
3138
import org.eclipse.terminal.view.ui.launcher.IConfigurationPanelContainer;
3239
import org.eclipse.ui.WorkbenchEncoding;
40+
import org.eclipse.ui.preferences.ScopedPreferenceStore;
3341

3442
import com.espressif.idf.core.IDFProjectNature;
3543
import com.espressif.idf.core.logging.Logger;
44+
import com.espressif.idf.terminal.connector.controls.themes.EspressifDarkTheme;
45+
import com.espressif.idf.terminal.connector.controls.themes.EspressifLightTheme;
46+
import com.espressif.idf.terminal.connector.controls.themes.ITerminalTheme;
47+
import com.espressif.idf.terminal.connector.controls.themes.PowerShellTheme;
48+
import com.espressif.idf.terminal.connector.controls.themes.ResetTheme;
3649
import com.espressif.idf.ui.EclipseUtil;
3750

3851
/**
3952
* IDF console wizard configuration panel implementation.
4053
*/
4154
public class IDFConsoleWizardConfigurationPanel extends AbstractExtendedConfigurationPanel {
4255

56+
private static final String PREF_THEME_SELECTION = "IDF_CONSOLE_THEME_SELECTION"; //$NON-NLS-1$
57+
private static final String TERMINAL_PREF_NODE = "org.eclipse.terminal.control"; //$NON-NLS-1$
58+
4359
private Combo projectCombo;
60+
private final List<ITerminalTheme> themes = new ArrayList<>();
61+
private final List<Button> themeButtons = new ArrayList<>();
4462

4563
/**
4664
* Constructor.
47-
*
4865
* @param container The configuration panel container or <code>null</code>.
4966
*/
5067
public IDFConsoleWizardConfigurationPanel(IConfigurationPanelContainer container) {
5168
super(container);
69+
70+
themes.add(new ResetTheme());
71+
themes.add(new EspressifLightTheme());
72+
themes.add(new EspressifDarkTheme());
73+
themes.add(new PowerShellTheme());
5274
}
5375

5476
@Override
@@ -58,11 +80,10 @@ public void setupPanel(Composite parent) {
5880
panel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
5981

6082
createProjectCombo(panel);
61-
// Create the encoding selection combo
6283
createEncodingUI(panel, false);
84+
createThemeUI(panel);
6385

64-
// Set the default encoding:
65-
// Default UTF-8 on Mac or Windows for Local, Preferences:Platform encoding otherwise
86+
// Set the default encoding based on OS
6687
if (Platform.OS_MACOSX.equals(Platform.getOS()) || Platform.OS_WIN32.equals(Platform.getOS())) {
6788
setEncoding("UTF-8"); //$NON-NLS-1$
6889
} else {
@@ -71,8 +92,7 @@ public void setupPanel(Composite parent) {
7192
setEncoding(encoding);
7293
}
7394

74-
// Fill the rest of the panel with a label to be able to
75-
// set a height and width hint for the dialog
95+
// Fill the rest of the panel with a spacer
7696
Label label = new Label(panel, SWT.HORIZONTAL);
7797
GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
7898
layoutData.widthHint = 300;
@@ -82,8 +102,126 @@ public void setupPanel(Composite parent) {
82102
setControl(panel);
83103
}
84104

85-
private void createProjectCombo(Composite parent) {
105+
/**
106+
* Dynamically creates radio buttons for each loaded ITerminalTheme strategy.
107+
*/
108+
private void createThemeUI(Composite parent) {
109+
Group group = new Group(parent, SWT.NONE);
110+
group.setText(Messages.IDFConsoleWizardConfigurationPanel_TerminalColorPresetsLbl);
111+
group.setLayout(new GridLayout(1, false));
112+
group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
113+
114+
themeButtons.clear();
115+
116+
for (ITerminalTheme theme : themes) {
117+
Button btn = new Button(group, SWT.RADIO);
118+
btn.setText(theme.getLabel());
119+
btn.setData(theme);
120+
themeButtons.add(btn);
121+
}
122+
123+
Label noteLabel = new Label(group, SWT.WRAP);
124+
noteLabel.setText(Messages.IDFConsoleWizardConfigurationPanel_TerminalColorPresetsNote);
125+
noteLabel.setFont(JFaceResources.getFontRegistry().getItalic(JFaceResources.DIALOG_FONT));
126+
GridData noteData = new GridData(SWT.FILL, SWT.CENTER, true, false);
127+
noteData.verticalIndent = 5;
128+
noteLabel.setLayoutData(noteData);
129+
}
130+
131+
@Override
132+
public void extractData(Map<String, Object> data) {
133+
data.put(ITerminalsConnectorConstants.PROP_TERMINAL_CONNECTOR_ID,
134+
"com.espressif.idf.terminal.connector.espidfConnector"); //$NON-NLS-1$
135+
136+
data.put(ITerminalsConnectorConstants.PROP_ENCODING, getEncoding());
137+
138+
if (projectCombo != null && !projectCombo.isDisposed() && !projectCombo.getText().isEmpty()) {
139+
IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(projectCombo.getText());
140+
if (p != null && p.exists() && p.getLocation() != null) {
141+
data.put(ITerminalsConnectorConstants.PROP_PROCESS_WORKING_DIR, p.getLocation().toOSString());
142+
data.put(ITerminalsConnectorConstants.PROP_TITLE, p.getName());
143+
}
144+
}
145+
146+
for (Button btn : themeButtons) {
147+
if (btn != null && !btn.isDisposed() && btn.getSelection()) {
148+
ITerminalTheme strategy = (ITerminalTheme) btn.getData();
149+
if (strategy != null) {
150+
applyThemeStrategy(strategy);
151+
}
152+
break;
153+
}
154+
}
155+
}
156+
157+
/**
158+
* Instantiates the Preference Store and delegates the coloring logic
159+
* to the selected strategy.
160+
*/
161+
private void applyThemeStrategy(ITerminalTheme theme) {
162+
IPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, TERMINAL_PREF_NODE);
163+
164+
theme.apply(store);
86165

166+
if (store instanceof ScopedPreferenceStore preferenceStore) {
167+
try {
168+
preferenceStore.save();
169+
} catch (Exception ex) {
170+
Logger.log(ex);
171+
}
172+
}
173+
}
174+
175+
@Override
176+
public void doSaveWidgetValues(IDialogSettings settings, String idPrefix) {
177+
// Save encoding settings
178+
doSaveEncodingsWidgetValues(settings, idPrefix);
179+
180+
// Save selected theme ID
181+
if (settings != null) {
182+
for (Button btn : themeButtons) {
183+
if (btn.getSelection()) {
184+
ITerminalTheme theme = (ITerminalTheme) btn.getData();
185+
settings.put(PREF_THEME_SELECTION, theme.getId());
186+
break;
187+
}
188+
}
189+
}
190+
}
191+
192+
@Override
193+
public void doRestoreWidgetValues(IDialogSettings settings, String idPrefix) {
194+
doRestoreEncodingsWidgetValues(settings, idPrefix);
195+
196+
// Restore theme selection
197+
if (settings != null) {
198+
String savedId = settings.get(PREF_THEME_SELECTION);
199+
200+
boolean found = false;
201+
// Iterate over buttons to find the one matching the saved ID
202+
for (Button btn : themeButtons) {
203+
ITerminalTheme theme = (ITerminalTheme) btn.getData();
204+
if (theme.getId().equals(savedId)) {
205+
btn.setSelection(true);
206+
found = true;
207+
} else {
208+
btn.setSelection(false);
209+
}
210+
}
211+
212+
// Fallback: If no setting saved (or ID not found), select the first one (Restore Defaults)
213+
if (!found && !themeButtons.isEmpty()) {
214+
themeButtons.get(0).setSelection(true);
215+
}
216+
} else {
217+
// No settings at all? Default to the first option
218+
if (!themeButtons.isEmpty()) {
219+
themeButtons.get(0).setSelection(true);
220+
}
221+
}
222+
}
223+
224+
private void createProjectCombo(Composite parent) {
87225
Composite panel = new Composite(parent, SWT.NONE);
88226
GridLayout layout = new GridLayout(2, false);
89227
layout.marginHeight = 0;
@@ -119,29 +257,11 @@ private void createProjectCombo(Composite parent) {
119257
public void setupData(Map<String, Object> data) {
120258
if (data == null)
121259
return;
122-
123260
String value = (String) data.get(ITerminalsConnectorConstants.PROP_ENCODING);
124261
if (value != null)
125262
setEncoding(value);
126263
}
127264

128-
@Override
129-
public void extractData(Map<String, Object> data) {
130-
131-
data.put(ITerminalsConnectorConstants.PROP_TERMINAL_CONNECTOR_ID,
132-
"com.espressif.idf.terminal.connector.espidfConnector"); //$NON-NLS-1$
133-
134-
data.put(ITerminalsConnectorConstants.PROP_ENCODING, getEncoding());
135-
136-
if (projectCombo != null && !projectCombo.isDisposed() && !projectCombo.getText().isEmpty()) {
137-
IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(projectCombo.getText());
138-
if (p != null && p.exists() && p.getLocation() != null) {
139-
data.put(ITerminalsConnectorConstants.PROP_PROCESS_WORKING_DIR, p.getLocation().toOSString());
140-
data.put(ITerminalsConnectorConstants.PROP_TITLE, p.getName());
141-
}
142-
}
143-
}
144-
145265
@Override
146266
protected void fillSettingsForHost(String host) {
147267
}
@@ -155,18 +275,6 @@ public boolean isValid() {
155275
return true;
156276
}
157277

158-
@Override
159-
public void doSaveWidgetValues(IDialogSettings settings, String idPrefix) {
160-
// Save the encodings widget values
161-
doSaveEncodingsWidgetValues(settings, idPrefix);
162-
}
163-
164-
@Override
165-
public void doRestoreWidgetValues(IDialogSettings settings, String idPrefix) {
166-
// Restore the encodings widget values
167-
doRestoreEncodingsWidgetValues(settings, idPrefix);
168-
}
169-
170278
@Override
171279
protected String getHostFromSettings() {
172280
return null;
@@ -176,4 +284,4 @@ protected String getHostFromSettings() {
176284
public boolean isWithHostList() {
177285
return false;
178286
}
179-
}
287+
}

bundles/com.espressif.idf.terminal.connector/src/com/espressif/idf/terminal/connector/controls/Messages.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ private Messages() {
1414

1515
public static String IDFConsoleWizardConfigurationPanel_MissingProjectErrorMsg;
1616
public static String IDFConsoleWizardConfigurationPanel_IDFConsoleWizardConfigurationPanel_ProjectLabel;
17+
public static String IDFConsoleWizardConfigurationPanel_TerminalColorPresetsLbl;
18+
public static String IDFConsoleWizardConfigurationPanel_TerminalColorPresetsNote;
1719
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
IDFConsoleWizardConfigurationPanel_MissingProjectErrorMsg=Please create and select an ESP-IDF Project first.
2-
IDFConsoleWizardConfigurationPanel_IDFConsoleWizardConfigurationPanel_ProjectLabel=Project name:
2+
IDFConsoleWizardConfigurationPanel_IDFConsoleWizardConfigurationPanel_ProjectLabel=Project name:
3+
IDFConsoleWizardConfigurationPanel_TerminalColorPresetsLbl=Terminal Color Presets
4+
IDFConsoleWizardConfigurationPanel_TerminalColorPresetsNote=Note: This setting applies globally to all Terminal views in the workspace.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.espressif.idf.terminal.connector.controls.themes;
2+
3+
import java.util.EnumMap;
4+
import java.util.Map;
5+
6+
import org.eclipse.jface.preference.IPreferenceStore;
7+
import org.eclipse.terminal.model.TerminalColor;
8+
9+
/**
10+
* Base class for defining a terminal theme using a Map.
11+
*/
12+
public class CustomTheme implements ITerminalTheme {
13+
14+
private final String id;
15+
private final String label;
16+
protected final Map<TerminalColor, String> colorMap = new EnumMap<>(TerminalColor.class);
17+
18+
public CustomTheme(String id, String label) {
19+
this.id = id;
20+
this.label = label;
21+
loadDefaults();
22+
configure();
23+
}
24+
25+
/**
26+
* Subclasses should override this to set their specific colors.
27+
*/
28+
protected void configure() {
29+
// Default implementation does nothing
30+
}
31+
32+
@Override
33+
public String getId() {
34+
return id;
35+
}
36+
37+
@Override
38+
public String getLabel() {
39+
return label;
40+
}
41+
42+
/**
43+
* Helper to set a color.
44+
*/
45+
protected void set(TerminalColor color, int r, int g, int b) {
46+
colorMap.put(color, r + "," + g + "," + b); //$NON-NLS-1$ //$NON-NLS-2$
47+
}
48+
49+
@Override
50+
public void apply(IPreferenceStore store) {
51+
for (Map.Entry<TerminalColor, String> entry : colorMap.entrySet()) {
52+
store.setValue(entry.getKey().name(), entry.getValue());
53+
}
54+
}
55+
56+
private void loadDefaults() {
57+
set(TerminalColor.BLACK, 0, 0, 0);
58+
set(TerminalColor.RED, 205, 0, 0);
59+
set(TerminalColor.GREEN, 0, 205, 0);
60+
set(TerminalColor.YELLOW, 205, 205, 0);
61+
set(TerminalColor.BLUE, 0, 0, 238);
62+
set(TerminalColor.MAGENTA, 205, 0, 205);
63+
set(TerminalColor.CYAN, 0, 205, 205);
64+
set(TerminalColor.WHITE, 229, 229, 229);
65+
66+
set(TerminalColor.BRIGHT_BLACK, 0, 0, 0);
67+
set(TerminalColor.BRIGHT_RED, 255, 0, 0);
68+
set(TerminalColor.BRIGHT_GREEN, 0, 255, 0);
69+
set(TerminalColor.BRIGHT_YELLOW, 255, 255, 0);
70+
set(TerminalColor.BRIGHT_BLUE, 92, 92, 255);
71+
set(TerminalColor.BRIGHT_MAGENTA, 255, 0, 255);
72+
set(TerminalColor.BRIGHT_CYAN, 0, 255, 255);
73+
set(TerminalColor.BRIGHT_WHITE, 255, 255, 255);
74+
}
75+
}

0 commit comments

Comments
 (0)