Skip to content

Commit fe1a1b4

Browse files
committed
Support new SWT dirty indicator in StackRenderer
Adds a preference to enable the new bullet-style dirty indicator for tabs, which overlays the close button. - StackRenderer now calls setDirtyIndicatorStyle on CTabFolder level. - CTabItem.setShowDirty is updated on individual items. - Preference change at runtime is handled to update all visible stacks. - Asterisk prefix is skipped if the new indicator is enabled. - Reflection is used for the new SWT methods for compatibility. Fixes #2568
1 parent dceb45a commit fe1a1b4

5 files changed

Lines changed: 87 additions & 1 deletion

File tree

bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CTabRendering.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ public class CTabRendering extends CTabFolderRenderer implements ICTabRendering,
7676
*/
7777
public static final boolean SHOW_FULL_TEXT_FOR_VIEW_TABS_DEFAULT = false;
7878

79+
/**
80+
* A named preference for setting CTabFolder's to be rendered with dirty
81+
* indicator overlay on close button
82+
* <p>
83+
* The default value for this preference is: <code>false</code> (do not show
84+
* dirty indicator)
85+
* </p>
86+
*/
87+
public static final String SHOW_DIRTY_INDICATOR_ON_TABS = "SHOW_DIRTY_INDICATOR_ON_TABS"; //$NON-NLS-1$
88+
89+
/**
90+
* Default value for "dirty indicator" preference for tabs
91+
*/
92+
public static final boolean SHOW_DIRTY_INDICATOR_ON_TABS_DEFAULT = false;
93+
7994
private static int MIN_VIEW_CHARS = 1;
8095
private static int MAX_VIEW_CHARS = Integer.MAX_VALUE;
8196

bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.eclipse.e4.ui.internal.workbench.renderers.swt.SWTRenderersMessages;
4949
import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
5050
import org.eclipse.e4.ui.internal.workbench.swt.CSSConstants;
51+
import org.eclipse.e4.ui.model.application.MApplication;
5152
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
5253
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
5354
import org.eclipse.e4.ui.model.application.ui.MUIElement;
@@ -164,6 +165,8 @@ public class StackRenderer extends LazyStackRenderer {
164165
@Preference(nodePath = CTabRendering.PREF_QUALIFIER_ECLIPSE_E4_UI_WORKBENCH_RENDERERS_SWT)
165166
private IEclipsePreferences preferences;
166167

168+
private IEclipsePreferences.IPreferenceChangeListener dirtyIndicatorListener;
169+
167170
@Inject
168171
@Named(WorkbenchRendererFactory.SHARED_ELEMENTS_STORE)
169172
Map<MUIElement, Set<MPlaceholder>> renderedMap;
@@ -443,6 +446,11 @@ void subscribeTopicChildrenMoved(@UIEventTopic(UIEvents.ElementContainer.TOPIC_C
443446

444447
CTabItem newItem = new CTabItem(tabFolder, (showClose ? SWT.CLOSE : SWT.NONE), newIndex);
445448
newItem.setText(text);
449+
MPart part = movedElement instanceof MPart p ? p
450+
: (MPart) ((MPlaceholder) movedElement).getRef();
451+
if (part != null) {
452+
newItem.setShowDirty(part.isDirty() && getShowDirtyIndicatorForTabsFromPreferences());
453+
}
446454
newItem.setImage(image);
447455
newItem.setToolTipText(toolTipText);
448456
newItem.setFont(font);
@@ -704,6 +712,39 @@ protected boolean requiresFocus(MPart element) {
704712
@PostConstruct
705713
public void init() {
706714
super.init(eventBroker);
715+
dirtyIndicatorListener = e -> {
716+
if (CTabRendering.SHOW_DIRTY_INDICATOR_ON_TABS.equals(e.getKey())) {
717+
synchronize.asyncExec(this::updateDirtyIndicatorStyle);
718+
}
719+
};
720+
preferences.addPreferenceChangeListener(dirtyIndicatorListener);
721+
}
722+
723+
private void updateDirtyIndicatorStyle() {
724+
MApplication app = context.get(MApplication.class);
725+
if (app == null) {
726+
return;
727+
}
728+
List<MPartStack> stacks = modelService.findElements(app, null, MPartStack.class, null);
729+
for (MPartStack stack : stacks) {
730+
Object widget = stack.getWidget();
731+
if (widget instanceof CTabFolder tabFolder) {
732+
boolean showDirtyIndicator = getShowDirtyIndicatorForTabsFromPreferences();
733+
tabFolder.setDirtyIndicatorStyle(showDirtyIndicator);
734+
for (CTabItem item : tabFolder.getItems()) {
735+
MUIElement element = (MUIElement) item.getData(OWNING_ME);
736+
if (element == null) {
737+
continue;
738+
}
739+
MPart part = element instanceof MPart p ? p : (MPart) ((MPlaceholder) element).getRef();
740+
if (part == null) {
741+
continue;
742+
}
743+
item.setShowDirty(part.isDirty() && showDirtyIndicator);
744+
item.setText(getLabel(part, part.getLocalizedLabel()));
745+
}
746+
}
747+
}
707748
}
708749

709750
protected void updateTab(CTabItem cti, MPart part, String attName, Object newValue) {
@@ -715,6 +756,7 @@ protected void updateTab(CTabItem cti, MPart part, String attName, Object newVal
715756
break;
716757
case UIEvents.Dirtyable.DIRTY:
717758
cti.setText(getLabel(part, part.getLocalizedLabel()));
759+
cti.setShowDirty(part.isDirty() && getShowDirtyIndicatorForTabsFromPreferences());
718760
break;
719761
case UIEvents.UILabel.ICONURI:
720762
changePartTabImage(part, cti);
@@ -741,6 +783,7 @@ private void changePartTabImage(MPart part, CTabItem item) {
741783

742784
@PreDestroy
743785
public void contextDisposed() {
786+
preferences.removePreferenceChangeListener(dirtyIndicatorListener);
744787
super.contextDisposed(eventBroker);
745788
}
746789

@@ -751,7 +794,8 @@ private String getLabel(MUILabel itemPart, String newName) {
751794
newName = LegacyActionTools.escapeMnemonics(newName);
752795
}
753796

754-
if (itemPart instanceof MDirtyable && ((MDirtyable) itemPart).isDirty()) {
797+
if (itemPart instanceof MDirtyable && ((MDirtyable) itemPart).isDirty()
798+
&& !getShowDirtyIndicatorForTabsFromPreferences()) {
755799
newName = '*' + newName;
756800
}
757801
return newName;
@@ -794,6 +838,7 @@ public Object createWidget(MUIElement element, Object parent) {
794838
new DropTarget(dropZone, drop);
795839
}
796840
tabFolder.setMRUVisible(getMRUValue());
841+
tabFolder.setDirtyIndicatorStyle(getShowDirtyIndicatorForTabsFromPreferences());
797842

798843
// Adjust the minimum chars based on the location
799844
if (isInSharedArea) {
@@ -895,6 +940,11 @@ private boolean getMRUValueFromPreferences() {
895940
return preferences.getBoolean(MRU_KEY, initialMRUValue);
896941
}
897942

943+
private boolean getShowDirtyIndicatorForTabsFromPreferences() {
944+
return preferences.getBoolean(CTabRendering.SHOW_DIRTY_INDICATOR_ON_TABS,
945+
CTabRendering.SHOW_DIRTY_INDICATOR_ON_TABS_DEFAULT);
946+
}
947+
898948
private void updateMRUValue(CTabFolder tabFolder) {
899949
boolean actualMRUValue = getMRUValue();
900950
tabFolder.setMRUVisible(actualMRUValue);
@@ -1060,6 +1110,7 @@ protected void createTab(MElementContainer<MUIElement> stack, MUIElement element
10601110

10611111
tabItem.setData(OWNING_ME, element);
10621112
tabItem.setText(getLabel(part, part.getLocalizedLabel()));
1113+
tabItem.setShowDirty(part.isDirty() && getShowDirtyIndicatorForTabsFromPreferences());
10631114
tabItem.setImage(getImage(part));
10641115

10651116
String toolTip = getToolTip(part);

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/WorkbenchMessages.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,8 @@ public class WorkbenchMessages extends NLS {
489489
public static String ViewsPreference_viewTabs_icons_and_titles_label;
490490
public static String ViewsPreference_showFullTextForViewTabs;
491491
public static String ViewsPreference_hideIconsForViewTabs;
492+
public static String ViewsPreference_viewTabs_dirty_indicator_label;
493+
public static String ViewsPreference_showDirtyIndicatorForTabs;
492494
public static String ToggleFullScreenMode_ActivationPopup_Description;
493495
public static String ToggleFullScreenMode_ActivationPopup_Description_NoKeybinding;
494496
public static String ToggleFullScreenMode_ActivationPopup_DoNotShowAgain;

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/dialogs/ViewsPreferencePage.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ public class ViewsPreferencePage extends PreferencePage implements IWorkbenchPre
121121
private Button hideIconsForViewTabs;
122122
private Button showFullTextForViewTabs;
123123

124+
private Button showDirtyIndicatorForTabs;
125+
124126
@Override
125127
protected Control createContents(Composite parent) {
126128
initializeDialogUnits(parent);
@@ -198,6 +200,8 @@ protected Control createContents(Composite parent) {
198200
createHideIconsForViewTabs(comp);
199201
createDependency(showFullTextForViewTabs, hideIconsForViewTabs);
200202

203+
createShowDirtyIndicatorForTabs(comp);
204+
201205
createRescaleAtRuntimeCheckButton(comp);
202206

203207
if (currentTheme != null) {
@@ -270,6 +274,15 @@ protected void createHideIconsForViewTabs(Composite composite) {
270274
actualValue);
271275
}
272276

277+
protected void createShowDirtyIndicatorForTabs(Composite composite) {
278+
boolean actualValue = getSwtRendererPreference(CTabRendering.SHOW_DIRTY_INDICATOR_ON_TABS,
279+
CTabRendering.SHOW_DIRTY_INDICATOR_ON_TABS_DEFAULT);
280+
createLabel(composite, ""); //$NON-NLS-1$
281+
createLabel(composite, WorkbenchMessages.ViewsPreference_viewTabs_dirty_indicator_label);
282+
showDirtyIndicatorForTabs = createCheckButton(composite,
283+
WorkbenchMessages.ViewsPreference_showDirtyIndicatorForTabs, actualValue);
284+
}
285+
273286
private boolean getSwtRendererPreference(String prefName, boolean defaultValue) {
274287
return Platform.getPreferencesService().getBoolean(CTabRendering.PREF_QUALIFIER_ECLIPSE_E4_UI_WORKBENCH_RENDERERS_SWT,
275288
prefName, defaultValue, null);
@@ -455,6 +468,7 @@ public boolean performOk() {
455468
}
456469
prefs.putBoolean(CTabRendering.HIDE_ICONS_FOR_VIEW_TABS, hideIconsForViewTabs.getSelection());
457470
prefs.putBoolean(CTabRendering.SHOW_FULL_TEXT_FOR_VIEW_TABS, showFullTextForViewTabs.getSelection());
471+
prefs.putBoolean(CTabRendering.SHOW_DIRTY_INDICATOR_ON_TABS, showDirtyIndicatorForTabs.getSelection());
458472
}
459473

460474
IPreferenceStore apiStore = PrefUtil.getAPIPreferenceStore();
@@ -605,6 +619,8 @@ protected void performDefaults() {
605619
showFullTextForViewTabs.setSelection(defaultPrefs.getBoolean(CTabRendering.SHOW_FULL_TEXT_FOR_VIEW_TABS,
606620
CTabRendering.SHOW_FULL_TEXT_FOR_VIEW_TABS_DEFAULT));
607621
showFullTextForViewTabs.notifyListeners(SWT.Selection, null);
622+
showDirtyIndicatorForTabs.setSelection(defaultPrefs.getBoolean(CTabRendering.SHOW_DIRTY_INDICATOR_ON_TABS,
623+
CTabRendering.SHOW_DIRTY_INDICATOR_ON_TABS_DEFAULT));
608624
}
609625
IPreferenceStore apiStore = PrefUtil.getAPIPreferenceStore();
610626
useColoredLabels.setSelection(apiStore.getDefaultBoolean(IWorkbenchPreferenceConstants.USE_COLORED_LABELS));

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/messages.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,8 @@ ViewsPreference_enableMRU = Show &most recently used tabs
434434
ViewsPreference_showFullTextForViewTabs = Always show full titles
435435
ViewsPreference_hideIconsForViewTabs = Hide icons
436436
ViewsPreference_viewTabs_icons_and_titles_label = Tab icons and titles in view areas:
437+
ViewsPreference_viewTabs_dirty_indicator_label = Dirty indicator for view and editor tabs:
438+
ViewsPreference_showDirtyIndicatorForTabs = Indicate unsaved changes by overlaying the close button
437439
ToggleFullScreenMode_ActivationPopup_Description=You have gone full screen. Use the Toggle Full Screen command ({0}) to deactivate.
438440
ToggleFullScreenMode_ActivationPopup_Description_NoKeybinding=You have gone full screen. Use the Toggle Full Screen command to deactivate.
439441
ToggleFullScreenMode_ActivationPopup_DoNotShowAgain=Do not show again

0 commit comments

Comments
 (0)