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..13d631e8276 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); + createAlignMultiPageEditorTabs(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..9674ff37d44 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,20 @@ public interface IWorkbenchPreferenceConstants { */ String DISABLE_OPEN_EDITOR_IN_PLACE = "DISABLE_OPEN_EDITOR_IN_PLACE"; //$NON-NLS-1$ + /** + * Workbench preference id for the position of the tabs in the multi-page + * editor. + * + * Integer-valued: {@link SWT#TOP} for tabs on the top, and {@link SWT#BOTTOM} + * for tabs at the bottom. + *

+ * The default value for this preference is: {@link SWT#BOTTOM} + *

+ * + * @since 3.133 + */ + String ALIGN_MULTI_PAGE_EDITOR_TABS = "ALIGN_MULTI_PAGE_EDITOR_TABS"; //$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..4f285064053 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,9 @@ public class WorkbenchMessages extends NLS { public static String WorkbenchPreference_stickyCycleButton; public static String WorkbenchPreference_RunInBackgroundButton; public static String WorkbenchPreference_RunInBackgroundToolTip; + public static String WorkbenchPreference_AlignMultiPageEditorTabs; + public static String WorkbenchPreference_AlignMultiPageEditorTabs_Top; + public static String WorkbenchPreference_AlignMultiPageEditorTabs_Bottom; // --- Appearance --- public static String ViewsPreferencePage_Theme; diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPreferenceInitializer.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPreferenceInitializer.java index 66fff649148..349dc1e744b 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPreferenceInitializer.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPreferenceInitializer.java @@ -102,6 +102,7 @@ public void initializeDefaultPreferences() { // Heap status preferences is stored in different node IEclipsePreferences heapNode = context.getNode("org.eclipse.ui"); //$NON-NLS-1$ heapNode.putBoolean(IWorkbenchPreferenceConstants.SHOW_MEMORY_MONITOR, false); + heapNode.putInt(IWorkbenchPreferenceConstants.ALIGN_MULTI_PAGE_EDITOR_TABS, SWT.BOTTOM); node.putInt(IHeapStatusConstants.PREF_UPDATE_INTERVAL, 500); node.putBoolean(IHeapStatusConstants.PREF_SHOW_MAX, false); node.putBoolean(IPreferenceConstants.OVERRIDE_PRESENTATION, false); 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..ce12f666602 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 @@ -18,6 +18,10 @@ import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.preference.ComboFieldEditor; import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IntegerFieldEditor; @@ -72,6 +76,8 @@ public class EditorsPreferencePage extends PreferencePage implements IWorkbenchP private Button allowInplaceEditor; + private ComboFieldEditor multiPageEditorTabPositionComboField; + @Override protected Control createContents(Composite parent) { Composite composite = createComposite(parent); @@ -130,6 +136,23 @@ protected void createPromptWhenStillOpenPref(Composite composite) { setButtonLayoutData(promptWhenStillOpenEditor); } + protected void createAlignMultiPageEditorTabs(Composite parent) { + Composite comboComposite = new Composite(parent, SWT.NONE); + comboComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).create()); + comboComposite.setLayoutData(GridDataFactory.fillDefaults().create()); + String name = IWorkbenchPreferenceConstants.ALIGN_MULTI_PAGE_EDITOR_TABS; + String label = WorkbenchMessages.WorkbenchPreference_AlignMultiPageEditorTabs; + String[][] namesAndValues = { + { Action.removeMnemonics(WorkbenchMessages.WorkbenchPreference_AlignMultiPageEditorTabs_Top), + String.valueOf(SWT.TOP) }, + { Action.removeMnemonics(WorkbenchMessages.WorkbenchPreference_AlignMultiPageEditorTabs_Bottom), + String.valueOf(SWT.BOTTOM) } }; + multiPageEditorTabPositionComboField = new ComboFieldEditor(name, label, namesAndValues, comboComposite); + multiPageEditorTabPositionComboField.setPreferenceStore(getAPIPreferenceStore()); + multiPageEditorTabPositionComboField.setPage(this); + multiPageEditorTabPositionComboField.load(); + } + protected Composite createComposite(Composite parent) { Composite composite = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(); @@ -158,11 +181,13 @@ protected void performDefaults() { reuseEditorsThreshold.getLabelControl(editorReuseThresholdGroup).setEnabled(reuseEditors.getSelection()); reuseEditorsThreshold.getTextControl(editorReuseThresholdGroup).setEnabled(reuseEditors.getSelection()); recentFilesEditor.loadDefault(); + multiPageEditorTabPositionComboField.loadDefault(); } @Override public boolean performOk() { IPreferenceStore store = getPreferenceStore(); + multiPageEditorTabPositionComboField.store(); 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..0c1c1dc2bd0 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,9 @@ 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_AlignMultiPageEditorTabs= &Align multi-page editor tabs: +WorkbenchPreference_AlignMultiPageEditorTabs_Top= &Top +WorkbenchPreference_AlignMultiPageEditorTabs_Bottom= &Bottom # --- Appearance --- @@ -493,10 +496,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..c08023634cd 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 -> { + if (isUpdateRequired(event)) { + updateContainer(); + } + }); + } + + /** + * Determines whether an update is required based on a property change event. + * + * @param event the {@link PropertyChangeEvent} triggered by a change in the + * preference store + * @since 3.133 + */ + protected boolean isUpdateRequired(PropertyChangeEvent event) { + if (event.getProperty().equals(IWorkbenchPreferenceConstants.ALIGN_MULTI_PAGE_EDITOR_TABS)) { + return true; + } + return false; } /** @@ -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, getTabStyle() | SWT.FLAT); newContainer.addSelectionListener(widgetSelectedAdapter(e -> { int newPageIndex = newContainer.indexOf((CTabItem) e.item); pageChange(newPageIndex); @@ -291,6 +317,29 @@ protected CTabFolder createContainer(Composite parent) { return newContainer; } + /** + * Determines the 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. + * @since 3.133 + */ + protected int getTabStyle() { + return getAPIPreferenceStore().getInt(IWorkbenchPreferenceConstants.ALIGN_MULTI_PAGE_EDITOR_TABS); + } + + /** + * @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 +1279,23 @@ public void run() { }); } } + + /** + * Updates the tab position of the container in the multi-page editor. + * + *

+ * This method retrieves the current container and sets the tab position based + * on the user preference. + *

+ * + * @since 3.133 + */ + protected void updateContainer() { + Composite container = getContainer(); + if (container instanceof CTabFolder tabFolder) { + tabFolder.setTabPosition(getTabStyle()); + tabFolder.requestLayout(); + } + } + }