From 34072524758628b2a71313e7ef399093e7b4571e Mon Sep 17 00:00:00 2001 From: "Praveen S.K" Date: Tue, 27 Aug 2024 10:16:06 +0530 Subject: [PATCH] Added dynamic tab alignment support in MultiPageEditorPart - Added a new preference for multi-page editor tab alignment. - Added a preference change listener to MultiPageEditorPart. - Updated tab style based on the user's preference. --- .../ide/dialogs/IDEEditorsPreferencePage.java | 1 + .../ui/IWorkbenchPreferenceConstants.java | 15 +++++ .../ui/internal/WorkbenchMessages.java | 1 + .../dialogs/EditorsPreferencePage.java | 15 +++++ .../eclipse/ui/internal/messages.properties | 5 +- .../eclipse/ui/part/MultiPageEditorPart.java | 64 ++++++++++++++++++- 6 files changed, 97 insertions(+), 4 deletions(-) diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/IDEEditorsPreferencePage.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/IDEEditorsPreferencePage.java index 3283f29d763..cfa0ff1cb5f 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/IDEEditorsPreferencePage.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/IDEEditorsPreferencePage.java @@ -62,6 +62,7 @@ protected Control createContents(Composite parent) { createUseIPersistablePref(composite); createPromptWhenStillOpenPref(composite); createEditorReuseGroup(composite); + createAlignMultiPageEditorTabsOnTop(composite); applyDialogFont(composite); diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/IWorkbenchPreferenceConstants.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/IWorkbenchPreferenceConstants.java index 2df7267e907..da6e03f528b 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/IWorkbenchPreferenceConstants.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/IWorkbenchPreferenceConstants.java @@ -624,6 +624,21 @@ public interface IWorkbenchPreferenceConstants { */ String DISABLE_OPEN_EDITOR_IN_PLACE = "DISABLE_OPEN_EDITOR_IN_PLACE"; //$NON-NLS-1$ + /** + * Workbench preference id for whether the tabs in the multi-page editor is + * displayed on top. Note that tabs will be shown in the top only if this + * preference is true. + * + * Boolean-valued: true show the tabs on the top, and + * false if shown at the bottom. + *

+ * The default value for this preference is: false + *

+ * + * @since 3.133 + */ + String ALIGN_MULTI_PAGE_EDITOR_TABS_ON_TOP = "ALIGN_MULTI_PAGE_EDITOR_TABS_ON_TOP"; //$NON-NLS-1$ + /** * Workbench preference id for indicating the size of the list of most recently * used working sets. diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java index dbddbbb6b6b..a07e38ef4ba 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java @@ -452,6 +452,7 @@ public class WorkbenchMessages extends NLS { public static String WorkbenchPreference_stickyCycleButton; public static String WorkbenchPreference_RunInBackgroundButton; public static String WorkbenchPreference_RunInBackgroundToolTip; + public static String WorkbenchPreference_AlignMultiPageEditorTabsOnTopButton; // --- Appearance --- public static String ViewsPreferencePage_Theme; diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/EditorsPreferencePage.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/EditorsPreferencePage.java index 401b1fc62e0..c1ead32ece9 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/EditorsPreferencePage.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/EditorsPreferencePage.java @@ -72,6 +72,8 @@ public class EditorsPreferencePage extends PreferencePage implements IWorkbenchP private Button allowInplaceEditor; + private Button alignMultiPageEditorTabsOnTop; + @Override protected Control createContents(Composite parent) { Composite composite = createComposite(parent); @@ -130,6 +132,15 @@ protected void createPromptWhenStillOpenPref(Composite composite) { setButtonLayoutData(promptWhenStillOpenEditor); } + protected void createAlignMultiPageEditorTabsOnTop(Composite composite) { + alignMultiPageEditorTabsOnTop = new Button(composite, SWT.CHECK); + alignMultiPageEditorTabsOnTop + .setText(WorkbenchMessages.WorkbenchPreference_AlignMultiPageEditorTabsOnTopButton); + alignMultiPageEditorTabsOnTop.setSelection( + getAPIPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.ALIGN_MULTI_PAGE_EDITOR_TABS_ON_TOP)); + setButtonLayoutData(alignMultiPageEditorTabsOnTop); + } + protected Composite createComposite(Composite parent) { Composite composite = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(); @@ -150,6 +161,8 @@ protected void performDefaults() { IPreferenceStore store = getPreferenceStore(); allowInplaceEditor.setSelection( !getAPIPreferenceStore().getDefaultBoolean(IWorkbenchPreferenceConstants.DISABLE_OPEN_EDITOR_IN_PLACE)); + alignMultiPageEditorTabsOnTop.setSelection(getAPIPreferenceStore() + .getDefaultBoolean(IWorkbenchPreferenceConstants.ALIGN_MULTI_PAGE_EDITOR_TABS_ON_TOP)); useIPersistableEditor.setSelection(store.getDefaultBoolean(IPreferenceConstants.USE_IPERSISTABLE_EDITORS)); promptWhenStillOpenEditor.setSelection(getAPIPreferenceStore() .getDefaultBoolean(IWorkbenchPreferenceConstants.PROMPT_WHEN_SAVEABLE_STILL_OPEN)); @@ -163,6 +176,8 @@ protected void performDefaults() { @Override public boolean performOk() { IPreferenceStore store = getPreferenceStore(); + getAPIPreferenceStore().setValue(IWorkbenchPreferenceConstants.ALIGN_MULTI_PAGE_EDITOR_TABS_ON_TOP, + alignMultiPageEditorTabsOnTop.getSelection()); getAPIPreferenceStore().setValue(IWorkbenchPreferenceConstants.DISABLE_OPEN_EDITOR_IN_PLACE, !allowInplaceEditor.getSelection()); store.setValue(IPreferenceConstants.USE_IPERSISTABLE_EDITORS, useIPersistableEditor.getSelection()); diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties index 62751910b19..c78d341fd5c 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties @@ -419,6 +419,7 @@ WorkbenchPreference_RunInBackgroundButton=Always r&un in background WorkbenchPreference_RunInBackgroundToolTip=Run long operations in the background where possible WorkbenchPreference_HeapStatusButton = Sho&w heap status WorkbenchPreference_HeapStatusButtonToolTip = Show the heap status area on the bottom of the window +WorkbenchPreference_AlignMultiPageEditorTabsOnTopButton= &Align multi-page editor tabs on top # --- Appearance --- @@ -493,10 +494,10 @@ OpenPerspectiveDialogAction_tooltip=Open Perspective #---- General Preferences---- PreferencePage_noDescription = (No description available) -PreferencePageParameterValues_pageLabelSeparator = \ >\ +PreferencePageParameterValues_pageLabelSeparator = \ >\ ThemingEnabled = E&nable theming ThemeChangeWarningText = Restart for the theme changes to take full effect -ThemeChangeWarningTitle = Theme Changed +ThemeChangeWarningTitle = Theme Changed # --- Workbench ----- WorkbenchPreference_openMode=Open mode WorkbenchPreference_doubleClick=D&ouble click diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/part/MultiPageEditorPart.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/part/MultiPageEditorPart.java index 68508e010ae..fe41eee7cf8 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/part/MultiPageEditorPart.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/part/MultiPageEditorPart.java @@ -17,6 +17,7 @@ import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter; +import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import org.eclipse.core.commands.AbstractHandler; @@ -32,7 +33,9 @@ import org.eclipse.jface.dialogs.IPageChangeProvider; import org.eclipse.jface.dialogs.IPageChangedListener; import org.eclipse.jface.dialogs.PageChangedEvent; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; @@ -56,6 +59,7 @@ import org.eclipse.ui.IPartService; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.IWorkbenchPreferenceConstants; import org.eclipse.ui.PartInitException; import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.internal.PartSite; @@ -63,6 +67,7 @@ import org.eclipse.ui.internal.misc.Policy; import org.eclipse.ui.internal.services.INestable; import org.eclipse.ui.internal.services.IServiceLocatorCreator; +import org.eclipse.ui.internal.util.PrefUtil; import org.eclipse.ui.services.IDisposable; import org.eclipse.ui.services.IServiceLocator; @@ -149,10 +154,31 @@ public abstract class MultiPageEditorPart extends EditorPart implements IPageCha private ListenerList pageChangeListeners = new ListenerList<>(ListenerList.IDENTITY); /** - * Creates an empty multi-page editor with no pages. + * Creates an empty multi-page editor with no pages and registers a + * {@link PropertyChangeListener} to listen for changes to the editor's + * preference.. */ protected MultiPageEditorPart() { super(); + getAPIPreferenceStore().addPropertyChangeListener(event -> { + handlePropertyChange(event); + }); + } + + /** + * Handles property change events related to editor preferences. + * + *

+ * This method is invoked when a property change occurs in the preference store. + *

+ * + * @param event the {@link PropertyChangeEvent} triggered by a change in the + * preference store + */ + private void handlePropertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(IWorkbenchPreferenceConstants.ALIGN_MULTI_PAGE_EDITOR_TABS_ON_TOP)) { + updateContainer(); + } } /** @@ -264,7 +290,7 @@ protected CTabFolder createContainer(Composite parent) { // use SWT.FLAT style so that an extra 1 pixel border is not reserved // inside the folder parent.setLayout(new FillLayout()); - final CTabFolder newContainer = new CTabFolder(parent, SWT.BOTTOM | SWT.FLAT); + final CTabFolder newContainer = new CTabFolder(parent, getPreferredTabStyle()); newContainer.addSelectionListener(widgetSelectedAdapter(e -> { int newPageIndex = newContainer.indexOf((CTabItem) e.item); pageChange(newPageIndex); @@ -291,6 +317,31 @@ protected CTabFolder createContainer(Composite parent) { return newContainer; } + /** + * Determines the preferred tab style based on user preferences. + *

+ * This method retrieves the user preference for aligning multi-page editor tabs + * on top or bottom, and returns the corresponding SWT style constant. + *

+ * + * @return {@code SWT.TOP} if the user prefers tabs to be aligned on top, + * {@code SWT.BOTTOM} if the user prefers tabs to be aligned on the + * bottom. + */ + private int getPreferredTabStyle() { + boolean alignTabsOnTop = getAPIPreferenceStore() + .getBoolean(IWorkbenchPreferenceConstants.ALIGN_MULTI_PAGE_EDITOR_TABS_ON_TOP); + int style = alignTabsOnTop ? SWT.TOP : SWT.BOTTOM; + return style; + } + + /** + * @since 3.133 + */ + protected IPreferenceStore getAPIPreferenceStore() { + return PrefUtil.getAPIPreferenceStore(); + } + /** * Creates a tab item at the given index and places the given control in the new * item. The item is a CTabItem with no style bits set. @@ -1230,4 +1281,13 @@ public void run() { }); } } + + private void updateContainer() { + Composite container = getContainer(); + if (container instanceof CTabFolder tabFolder) { + tabFolder.setTabPosition(getPreferredTabStyle()); + tabFolder.requestLayout(); + } + } + }