blob: febe18f6966db85dfb8107be0277896819e2826c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2022 Simeon Andreev and Others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Simeon Andreev - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.ide;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.PROMPT_EDITOR_PREFERENCE_VALUE;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.disableDefaultLimit;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.getConfiguredExtensionTypes;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.getDefaultLimit;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.getDisabledExtensionTypes;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.getFileLimitsForExtension;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.isDefaultLimitEnabled;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.isLargeDocumentLegacyPreferenceSet;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.isPromptPreferenceValue;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.removeFileLimitsForExtension;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.restoreDefaults;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.setConfiguredExtensionTypes;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.setDefaultLimit;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.setDisabledExtensionTypes;
import static org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.setFileLimitsForExtension;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_ColumnHeader_Editor;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_ColumnHeader_Size;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_DefaultLimitGroup_Label;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_DefaultPreference_Label;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_DisabledPageText;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditEditorButton_Label;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorDialog_Error_DuplicateSize;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorDialog_Error_NoEditorSelected;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorDialog_Label_Editor;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorDialog_Label_FileSize;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorDialog_Message;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorDialog_Radio_Prompt;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorDialog_Radio_Specific;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorDialog_ShellTitle;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorDialog_Title;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_EditorTable_DialogPrompt;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_ExtensionDialog_Error_WildcardAndDot;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_ExtensionDialog_Label;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_ExtensionDialog_Message;
import static org.eclipse.ui.internal.ide.IDEWorkbenchMessages.LargeFileAssociationsPreferencePage_ExtensionsTable_DisabledClarification;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.PlainMessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.layout.LayoutConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.dialogs.EditorSelectionDialog;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.internal.IPreferenceConstants;
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
import org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.FileLimit;
import org.eclipse.ui.internal.WorkbenchImages;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.dialogs.DialogUtil;
import org.eclipse.ui.internal.registry.EditorDescriptor;
import org.eclipse.ui.internal.util.PrefUtil;
/**
* Preference page to configure large file editors based on file type and file
* size.
*/
public class LargeFileAssociationsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, Listener {
private static final String DATA_EDITOR = "editor"; //$NON-NLS-1$
private static final String DATA_PROMPT = "prompt"; //$NON-NLS-1$
private static final String DIALOG_PROMPT_EDITOR_TABLE_TEXT = LargeFileAssociationsPreferencePage_EditorTable_DialogPrompt;
private static final int EDITOR_TABLE_CELL_INDEX_EDITOR = 0;
private static final int EDITOR_TABLE_CELL_INDEX_SIZE = 1;
private static final String[] SIZE_UNITS = { "B", "KB", "MB", "GB" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
private static final int MEGABYTE_UNIT_INDEX = 2;
private static final long B = 1L;
private static final long KB = 1024L;
private static final long MB = KB * KB;
private static final long GB = MB * KB;
private static final long[] SIZE_MULTIPLIERS = { B, KB, MB, GB };
private static final String SIZE_TEXT_PREFIX = "> "; //$NON-NLS-1$
private static final int DEFAULT_SIZE_UNIT = MEGABYTE_UNIT_INDEX;
private static final Comparator<EditorForSize> EDITOR_COMPARATOR = LargeFileAssociationsPreferencePage::compareEditors;
private Table resourceTypeTable;
private Button addResourceTypeButton;
private Button removeResourceTypeButton;
private Table editorTable;
private Button addEditorButton;
private Button editEditorButton;
private Button removeEditorButton;
private Button enableDefaultPreference;
private Text defaultPreferenceFileSize;
private Combo defaultPreferenceUnit;
private Label editorLabel;
private IWorkbench workbench;
private List<Image> imagesToDispose;
private Map<IEditorDescriptor, Image> editorsToImages;
/**
* Add a new resource type to the collection shown in the top of the page. This
* is typically called after the extension dialog is shown to the user.
*
* @param newExtension the new extension
*/
public void addResourceType(String newExtension) {
Assert.isTrue(newExtension != null && newExtension.length() != 0);
// Find the index at which to insert the new entry.
LargeFileAssociation association;
TableItem[] items = resourceTypeTable.getItems();
boolean found = false;
int i = 0;
while (i < items.length && !found) {
association = (LargeFileAssociation) items[i].getData();
int result = newExtension.compareToIgnoreCase(association.extension);
if (result == 0) {
// Same resource type not allowed!
PlainMessageDialog.getBuilder(getShell(), WorkbenchMessages.FileEditorPreference_existsTitle)
.image(SWT.ICON_INFORMATION).message(WorkbenchMessages.FileEditorPreference_existsMessage)
.build().open();
return;
}
if (result < 0) {
found = true;
} else {
i++;
}
}
// Create the new type and insert it
association = new LargeFileAssociation(newExtension);
// per default add a value for an editor prompt
EditorForSize defaultPromptEditor = defaultPromptEditor();
association.addEditor(defaultPromptEditor);
TableItem item = newResourceTableItem(association, i, true);
resourceTypeTable.setFocus();
resourceTypeTable.showItem(item);
fillEditorTable();
}
/**
* Creates the page's UI content.
*/
@Override
protected Control createContents(Composite parent) {
boolean isLegacyPreferenceSet = isLargeDocumentLegacyPreferenceSet();
Composite pageComponent = new Composite(parent, SWT.NONE);
if (isLegacyPreferenceSet) {
createDisabledPreferencePageContents(pageComponent);
} else {
createPreferencePageContents(pageComponent);
}
workbench.getHelpSystem().setHelp(parent, IWorkbenchHelpContextIds.LARGE_FILE_ASSOCIATIONS_PREFERENCE_PAGE);
return pageComponent;
}
private static void createDisabledPreferencePageContents(Composite pageComponent) {
pageComponent.setLayout(new FillLayout());
String disabledPageText = NLS.bind(LargeFileAssociationsPreferencePage_DisabledPageText,
IPreferenceConstants.LARGE_DOC_SIZE_FOR_EDITORS);
Label legacyPreferenceSetLabel = new Label(pageComponent, SWT.NONE);
legacyPreferenceSetLabel.setText(disabledPageText);
}
private void createPreferencePageContents(Composite pageComponent) {
imagesToDispose = new ArrayList<>();
editorsToImages = new HashMap<>(50);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginWidth = 0;
layout.marginHeight = 0;
pageComponent.setLayout(layout);
GridData data = new GridData();
data.verticalAlignment = GridData.FILL;
data.horizontalAlignment = GridData.FILL;
pageComponent.setLayoutData(data);
Group defaultLimitGroup = new Group(pageComponent, SWT.NONE);
defaultLimitGroup.setText(LargeFileAssociationsPreferencePage_DefaultLimitGroup_Label);
GridLayout groupLayout = new GridLayout();
groupLayout.marginWidth = 0;
groupLayout.marginHeight = 0;
groupLayout.numColumns = 3;
defaultLimitGroup.setLayout(groupLayout);
data = new GridData();
data.verticalAlignment = GridData.FILL;
data.horizontalAlignment = GridData.FILL;
data.horizontalSpan = 2;
defaultLimitGroup.setLayoutData(data);
enableDefaultPreference = new Button(defaultLimitGroup, SWT.CHECK);
enableDefaultPreference.setText(LargeFileAssociationsPreferencePage_DefaultPreference_Label);
defaultPreferenceFileSize = createFileSizeText(defaultLimitGroup);
data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.grabExcessHorizontalSpace = true;
data.minimumWidth = 6;
defaultPreferenceFileSize.setLayoutData(data);
defaultPreferenceUnit = createSizeUnitCombo(defaultLimitGroup);
enableDefaultPreference.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
updateDefaultPreferenceWidgetsEnabledState();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
updateDefaultPreferenceWidgetsEnabledState();
}
});
setDefaultPreferenceWidgetValues();
// layout the top table & its buttons
Label label = new Label(pageComponent, SWT.LEFT);
label.setText(WorkbenchMessages.FileEditorPreference_fileTypes);
data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.horizontalSpan = 2;
label.setLayoutData(data);
resourceTypeTable = new Table(pageComponent, SWT.CHECK | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
resourceTypeTable.addListener(SWT.Selection, this);
resourceTypeTable.addListener(SWT.DefaultSelection, this);
data = new GridData(GridData.FILL_HORIZONTAL);
int availableRows = DialogUtil.availableRows(pageComponent);
data.heightHint = resourceTypeTable.getItemHeight() * (availableRows / 16);
resourceTypeTable.setLayoutData(data);
resourceTypeTable.addListener(SWT.Selection, event -> {
if (event.detail == SWT.CHECK) {
TableItem item = (TableItem) event.item;
LargeFileAssociation association = (LargeFileAssociation) item.getData();
boolean newEnabled = item.getChecked();
boolean oldEnabled = association.enabled;
association.enabled = newEnabled;
if (oldEnabled != newEnabled) {
String extensionText = getExtensionText(association);
item.setText(extensionText);
fillEditorTable();
}
}
});
Composite groupComponent = new Composite(pageComponent, SWT.NONE);
groupLayout = new GridLayout();
groupLayout.marginWidth = 0;
groupLayout.marginHeight = 0;
groupComponent.setLayout(groupLayout);
data = new GridData();
data.verticalAlignment = GridData.FILL;
data.horizontalAlignment = GridData.FILL;
groupComponent.setLayoutData(data);
addResourceTypeButton = new Button(groupComponent, SWT.PUSH);
addResourceTypeButton.setText(WorkbenchMessages.FileEditorPreference_add);
addResourceTypeButton.addListener(SWT.Selection, this);
setButtonLayoutData(addResourceTypeButton);
removeResourceTypeButton = new Button(groupComponent, SWT.PUSH);
removeResourceTypeButton.setText(WorkbenchMessages.FileEditorPreference_remove);
removeResourceTypeButton.addListener(SWT.Selection, this);
setButtonLayoutData(removeResourceTypeButton);
// Spacer
label = new Label(pageComponent, SWT.LEFT);
data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.horizontalSpan = 2;
label.setLayoutData(data);
// layout the bottom table & its buttons
editorLabel = new Label(pageComponent, SWT.LEFT);
editorLabel.setText(WorkbenchMessages.FileEditorPreference_associatedEditors);
data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.horizontalSpan = 2;
editorLabel.setLayoutData(data);
editorTable = new Table(pageComponent, SWT.MULTI | SWT.BORDER);
TableColumn editorColumn = new TableColumn(editorTable, SWT.NONE);
editorColumn.setText(LargeFileAssociationsPreferencePage_ColumnHeader_Editor);
editorColumn.setWidth(300);
TableColumn sizeColumn = new TableColumn(editorTable, SWT.NONE);
sizeColumn.setText(LargeFileAssociationsPreferencePage_ColumnHeader_Size);
sizeColumn.setWidth(100);
editorTable.addListener(SWT.Selection, this);
editorTable.addListener(SWT.DefaultSelection, this);
data = new GridData(GridData.FILL_BOTH);
data.heightHint = editorTable.getItemHeight() * 7;
editorTable.setLayoutData(data);
editorTable.setHeaderVisible(true);
groupComponent = new Composite(pageComponent, SWT.NONE);
groupLayout = new GridLayout();
groupLayout.marginWidth = 0;
groupLayout.marginHeight = 0;
groupComponent.setLayout(groupLayout);
data = new GridData();
data.verticalAlignment = GridData.FILL;
data.horizontalAlignment = GridData.FILL;
groupComponent.setLayoutData(data);
addEditorButton = new Button(groupComponent, SWT.PUSH);
addEditorButton.setText(WorkbenchMessages.FileEditorPreference_addEditor);
addEditorButton.addListener(SWT.Selection, this);
addEditorButton.setLayoutData(data);
setButtonLayoutData(addEditorButton);
editEditorButton = new Button(groupComponent, SWT.PUSH);
editEditorButton.setText(LargeFileAssociationsPreferencePage_EditEditorButton_Label);
editEditorButton.addListener(SWT.Selection, this);
editEditorButton.setLayoutData(data);
setButtonLayoutData(editEditorButton);
removeEditorButton = new Button(groupComponent, SWT.PUSH);
removeEditorButton.setText(WorkbenchMessages.FileEditorPreference_removeEditor);
removeEditorButton.addListener(SWT.Selection, this);
setButtonLayoutData(removeEditorButton);
fillResourceTypeTable();
if (resourceTypeTable.getItemCount() > 0) {
resourceTypeTable.setSelection(0);
}
fillEditorTable();
updateEnabledState();
applyDialogFont(pageComponent);
}
private void updateDefaultPreferenceWidgetsEnabledState() {
boolean enabled = enableDefaultPreference.getSelection();
defaultPreferenceFileSize.setEnabled(enabled);
defaultPreferenceUnit.setEnabled(enabled);
}
private void setDefaultPreferenceWidgetValues() {
enableDefaultPreference.setSelection(isDefaultLimitEnabled());
SizeAndUnit sizeAndUnit = defaultLimit();
defaultPreferenceFileSize.setText(sizeAndUnit.sizeString);
defaultPreferenceUnit.select(sizeAndUnit.unitIndex);
updateDefaultPreferenceWidgetsEnabledState();
}
/**
* The preference page is going to be disposed. So deallocate all allocated SWT
* resources that aren't disposed automatically by disposing the page (i.e
* fonts, cursors, etc). Subclasses should re-implement this method to release
* their own allocated SWT resources.
*/
@Override
public void dispose() {
super.dispose();
if (imagesToDispose != null) {
for (Image image : imagesToDispose) {
image.dispose();
}
imagesToDispose = null;
}
if (editorsToImages != null) {
for (Image image : editorsToImages.values()) {
image.dispose();
}
editorsToImages = null;
}
}
/**
* Hook method to get a page specific preference store. Reimplement this method
* if a page don't want to use its parent's preference store.
*/
@Override
protected IPreferenceStore doGetPreferenceStore() {
return WorkbenchPlugin.getDefault().getPreferenceStore();
}
/**
* Populate the large file editors for the selected file type.
*/
protected void fillEditorTable() {
editorTable.removeAll();
LargeFileAssociation association = getSelectedLargeFileAssociation();
if (association != null) {
editorTable.setEnabled(association.enabled);
if (association.enabled) {
for (EditorForSize editorForSize : association.editors) {
TableItem item = new TableItem(editorTable, SWT.NONE);
String label;
if (editorForSize.isPrompt) {
label = DIALOG_PROMPT_EDITOR_TABLE_TEXT;
item.setData(DATA_PROMPT, DATA_PROMPT);
} else {
label = editorForSize.editor.getLabel();
item.setData(DATA_EDITOR, editorForSize.editor);
item.setImage(getImage(editorForSize.editor));
}
String[] text = { label, getSizeText(editorForSize.size) };
item.setText(text); // $NON-NLS-1$
}
}
}
}
/**
* Populate the table with file types that have configured large file editors.
*/
protected void fillResourceTypeTable() {
resourceTypeTable.removeAll();
String[] configured = getConfiguredExtensionTypes();
String[] disabled = getDisabledExtensionTypes();
List<String> extensions = new ArrayList<>();
extensions.addAll(Arrays.asList(configured));
extensions.addAll(Arrays.asList(disabled));
Set<String> disabledSet = new HashSet<>(Arrays.asList(disabled));
List<LargeFileAssociation> associations = new ArrayList<>();
for (String extension : extensions) {
List<FileLimit> fileLimits = getFileLimitsForExtension(extension);
LargeFileAssociation association = new LargeFileAssociation(extension);
association.enabled = !disabledSet.contains(extension);
long lowestPromptSize = Long.MAX_VALUE;
for (FileLimit fileLimit : fileLimits) {
long size = fileLimit.fileSize;
String editorIdString = fileLimit.editorId;
SizeAndUnit promptSize = null;
IEditorDescriptor editorDescriptor = findEditor(editorIdString);
if (editorDescriptor != null) {
SizeAndUnit sizeAndUnit = getSizeAndUnit(size);
EditorForSize editorForSize = new EditorForSize(editorDescriptor, sizeAndUnit);
association.addEditor(editorForSize);
} else if (isPromptPreferenceValue(editorIdString)) {
// use the smallest size for the "prompt for editor" entry
long newSize = Long.valueOf(size);
if (newSize < lowestPromptSize) {
lowestPromptSize = newSize;
promptSize = getSizeAndUnit(size);
}
}
if (promptSize != null) {
EditorForSize promptEditor = new EditorForSize(promptSize);
association.addEditor(promptEditor);
}
}
associations.add(association);
}
int index = 0;
for (LargeFileAssociation association : associations) {
newResourceTableItem(association, index, false);
++index;
}
}
/**
* Returns the image associated with the given editor.
*/
protected Image getImage(IEditorDescriptor editor) {
Image image = editorsToImages.get(editor);
if (image == null) {
image = editor.getImageDescriptor().createImage();
editorsToImages.put(editor, image);
}
return image;
}
protected LargeFileAssociation getSelectedLargeFileAssociation() {
TableItem[] items = resourceTypeTable.getSelection();
if (items.length == 1) {
return (LargeFileAssociation) items[0].getData();
}
return null;
}
protected IEditorDescriptor[] getAssociatedEditors() {
if (getSelectedLargeFileAssociation() == null) {
return null;
}
if (editorTable.getItemCount() > 0) {
List<IEditorDescriptor> editorList = new ArrayList<>();
for (int i = 0; i < editorTable.getItemCount(); i++) {
IEditorDescriptor editorDescriptor = (IEditorDescriptor) editorTable.getItem(i).getData(DATA_EDITOR);
if (editorDescriptor != null) {
editorList.add(editorDescriptor);
}
}
return editorList.toArray(new IEditorDescriptor[editorList.size()]);
}
return null;
}
@Override
public void handleEvent(Event event) {
if (event.widget == addResourceTypeButton) {
promptForResourceType();
} else if (event.widget == removeResourceTypeButton) {
removeSelectedResourceType();
} else if (event.widget == addEditorButton) {
promptForEditor();
} else if (event.widget == editEditorButton) {
editSelectedEditor();
} else if (event.widget == removeEditorButton) {
removeSelectedEditor();
} else if (event.widget == resourceTypeTable) {
fillEditorTable();
}
updateEnabledState();
}
/**
* @see IWorkbenchPreferencePage
*/
@Override
public void init(IWorkbench aWorkbench) {
this.workbench = aWorkbench;
}
/**
* Create a new <code>TableItem</code> to represent the resource type editor
* description supplied.
*/
protected TableItem newResourceTableItem(LargeFileAssociation association, int index, boolean selected) {
IEditorRegistry editorRegistry = workbench.getEditorRegistry();
ImageDescriptor imageDescriptor = editorRegistry.getImageDescriptor("tmp." + association.extension); //$NON-NLS-1$
if (imageDescriptor == null) {
imageDescriptor = getImageDescriptor();
}
Image image = imageDescriptor.createImage(false);
if (image != null) {
imagesToDispose.add(image);
}
TableItem item = new TableItem(resourceTypeTable, SWT.NONE, index);
if (image != null) {
item.setImage(image);
}
String extensionText = getExtensionText(association);
item.setText(extensionText);
item.setChecked(association.enabled);
item.setData(association);
if (selected) {
resourceTypeTable.setSelection(index);
}
return item;
}
@Override
public boolean performOk() {
updateDefaultPreference();
updateExtensionPreferences();
PrefUtil.savePrefs();
return true;
}
@Override
public void performDefaults() {
restoreDefaults();
setDefaultPreferenceWidgetValues();
fillResourceTypeTable();
fillEditorTable();
updateEnabledState();
}
private void updateDefaultPreference() {
boolean isDefaultPreferenceEnabled = enableDefaultPreference.getSelection();
if (isDefaultPreferenceEnabled) {
SizeAndUnit size = getSizeAndUnit(defaultPreferenceFileSize, defaultPreferenceUnit);
setDefaultLimit(size.bytes);
} else {
disableDefaultLimit();
}
}
private void updateExtensionPreferences() {
String[] previousConfiguredExtensions = getConfiguredExtensionTypes();
String[] previousDisabledExtensions = getDisabledExtensionTypes();
List<String> configuredExtensions = new ArrayList<>();
List<String> disabledExtensions = new ArrayList<>();
List<String> newExtensions = new ArrayList<>();
TableItem[] items = resourceTypeTable.getItems();
for (TableItem item : items) {
LargeFileAssociation association = (LargeFileAssociation) (item.getData());
String extension = association.extension;
if (!association.enabled) {
disabledExtensions.add(extension);
}
List<FileLimit> fileLimits = new ArrayList<>();
for (EditorForSize editorForSize : association.editors) {
String editorId;
if (editorForSize.isPrompt) {
editorId = PROMPT_EDITOR_PREFERENCE_VALUE;
} else {
editorId = editorForSize.editor.getId();
}
long fileSize = editorForSize.size.bytes;
FileLimit fileLimit = new FileLimit(editorId, fileSize);
fileLimits.add(fileLimit);
}
if (!fileLimits.isEmpty()) {
if (association.enabled) {
configuredExtensions.add(extension);
}
newExtensions.add(extension);
setFileLimitsForExtension(extension, fileLimits);
}
}
setConfiguredExtensionTypes(configuredExtensions.toArray(String[]::new));
setDisabledExtensionTypes(disabledExtensions.toArray(String[]::new));
Set<String> removedExtensions = new HashSet<>();
removedExtensions.addAll(Arrays.asList(previousConfiguredExtensions));
removedExtensions.addAll(Arrays.asList(previousDisabledExtensions));
removedExtensions.removeAll(newExtensions);
for (String removedExtension : removedExtensions) {
removeFileLimitsForExtension(removedExtension);
}
}
/**
* Prompt for editor above a file size.
*/
public void promptForEditor() {
// prevent duplicate editors
IEditorDescriptor[] filteredEditors = getAssociatedEditors();
// prevent input of duplicate file sizes for the same extension
long[] configuredFileSizes = getConfiguredFileSizes();
Shell shell = getControl().getShell();
EditorForSize initialValues = defaultPromptEditor();
String extension = getSelectedLargeFileAssociation().extension;
EditorForSizeDialog editorForSizeDialog = new EditorForSizeDialog(shell, filteredEditors, configuredFileSizes,
initialValues, extension);
if (editorForSizeDialog.open() == Window.OK) {
addEditor(editorForSizeDialog.chosenValues);
}
}
void editSelectedEditor() {
LargeFileAssociation association = getSelectedLargeFileAssociation();
int selectionIndex = editorTable.getSelectionIndex();
TableItem item = editorTable.getItem(selectionIndex);
String editorIdString = item.getText(EDITOR_TABLE_CELL_INDEX_EDITOR);
boolean promptForEditor = LargeFileAssociationsPreferencePage_EditorTable_DialogPrompt.equals(editorIdString);
String sizeString = item.getText(EDITOR_TABLE_CELL_INDEX_SIZE);
SizeAndUnit selectedSize = parseSizeString(sizeString);
// prevent duplicate editors
IEditorDescriptor[] filteredEditors = getAssociatedEditors();
IEditorDescriptor selectedEditor = (IEditorDescriptor) item.getData(DATA_EDITOR);
if (selectedEditor != null) {
IEditorDescriptor[] filteredEditorsWithoutSelected = Arrays.stream(filteredEditors)
.filter(e -> e != selectedEditor).toArray(IEditorDescriptor[]::new);
filteredEditors = filteredEditorsWithoutSelected;
}
// prevent input of duplicate file sizes for the same extension
long[] configuredFileSizes = getConfiguredFileSizes();
long[] filteredFileSizes = Arrays.stream(configuredFileSizes).filter(l -> l != selectedSize.bytes).toArray();
EditorForSize initialValues = new EditorForSize(selectedEditor, promptForEditor, selectedSize);
String extension = getSelectedLargeFileAssociation().extension;
Shell shell = getControl().getShell();
EditorForSizeDialog editorForSizeDialog = new EditorForSizeDialog(shell, filteredEditors, filteredFileSizes,
initialValues, extension);
if (editorForSizeDialog.open() == Window.OK) {
EditorDescriptor previousEditor = (EditorDescriptor) item.getData(DATA_EDITOR);
Object promptData = item.getData(DATA_PROMPT);
if (previousEditor != null) {
association.removeEditor(previousEditor);
} else if (promptData != null) {
association.removePromptEditor();
}
editorTable.remove(selectionIndex);
addEditor(editorForSizeDialog.chosenValues);
}
}
private void addEditor(EditorForSize editorForSize) {
LargeFileAssociation association = getSelectedLargeFileAssociation();
if (!editorForSize.isPrompt) {
association.addEditor(editorForSize);
} else {
int promptIndex = getIndexOfPromptItem();
if (promptIndex != -1) {
editorTable.remove(promptIndex);
}
association.setPromptEditorSize(editorForSize.size);
}
int index = association.indexOfEditor(editorForSize);
TableItem item;
if (index >= editorTable.getItemCount()) {
item = new TableItem(editorTable, SWT.NONE);
} else {
item = new TableItem(editorTable, SWT.NONE, index);
}
String editorText;
if (!editorForSize.isPrompt) {
item.setData(DATA_EDITOR, editorForSize.editor);
item.setImage(getImage(editorForSize.editor));
editorText = editorForSize.editor.getLabel();
} else {
item.setData(DATA_PROMPT, DATA_PROMPT);
editorText = DIALOG_PROMPT_EDITOR_TABLE_TEXT;
}
String[] text = { editorText, getSizeText(editorForSize.size) };
item.setText(text);
editorTable.setSelection(index);
editorTable.setFocus();
}
private static EditorDescriptor promptForEditorWithDialog(Shell shell, IEditorDescriptor[] filteredEditors,
String extension) {
EditorDescriptor selectedEditor = null;
EditorSelectionDialog editorSelectionDialog = new EditorSelectionDialog(shell);
editorSelectionDialog.setEditorsToFilter(filteredEditors);
editorSelectionDialog.setMessage(
NLS.bind(WorkbenchMessages.Choose_the_editor_for_file, extension));
if (editorSelectionDialog.open() == Window.OK) {
selectedEditor = (EditorDescriptor) editorSelectionDialog.getSelectedEditor();
}
return selectedEditor;
}
private IEditorDescriptor findEditor(String editorIdString) {
IEditorDescriptor editorDescriptor = workbench.getEditorRegistry().findEditor(editorIdString);
return editorDescriptor;
}
private int getIndexOfPromptItem() {
int promptIndex = -1;
TableItem[] editorTableItems = editorTable.getItems();
for (int j = 0; j < editorTableItems.length; ++j) {
TableItem editorTableItem = editorTableItems[j];
if (editorTableItem.getData(DATA_PROMPT) != null) {
promptIndex = j;
break;
}
}
return promptIndex;
}
private long[] getConfiguredFileSizes() {
LargeFileAssociation association = getSelectedLargeFileAssociation();
int numberOfSizes = association.editors.size();
long[] configuredFileSizes = new long[numberOfSizes];
int index = 0;
for (EditorForSize editor : association.editors) {
configuredFileSizes[index] = editor.size.bytes;
++index;
}
return configuredFileSizes;
}
/**
* Prompt for resource type.
*/
public void promptForResourceType() {
ExtensionDialog dialog = new ExtensionDialog(getControl().getShell());
if (dialog.open() == Window.OK) {
String extension = dialog.getExtension();
addResourceType(extension);
}
}
/**
* Remove the editor from the table
*/
public void removeSelectedEditor() {
TableItem[] items = editorTable.getSelection();
if (items.length > 0) {
for (TableItem item : items) {
LargeFileAssociation association = getSelectedLargeFileAssociation();
IEditorDescriptor editorDescriptor = (IEditorDescriptor) item.getData(DATA_EDITOR);
if (editorDescriptor != null) {
association.removeEditor(editorDescriptor);
} else if (item.getData(DATA_PROMPT) != null) {
association.removePromptEditor();
}
item.dispose();
}
}
editorTable.deselectAll();
}
/**
* Remove the type from the table
*/
public void removeSelectedResourceType() {
for (TableItem item : resourceTypeTable.getSelection()) {
item.dispose();
}
// Clear out the editors too
editorTable.removeAll();
}
/**
* Update the enabled state.
*/
public void updateEnabledState() {
// Update enabled state
int selectedResources = resourceTypeTable.getSelectionCount();
removeResourceTypeButton.setEnabled(selectedResources != 0);
editorLabel.setEnabled(selectedResources == 1);
addEditorButton.setEnabled(selectedResources == 1);
int selectedEditors = editorTable.getSelectionCount();
int editorsCount = editorTable.getItemCount();
boolean removeEditorsEnabled = editorsCount > 1 && selectedEditors > 0;
editEditorButton.setEnabled(selectedEditors == 1);
removeEditorButton.setEnabled(removeEditorsEnabled);
}
private static ImageDescriptor getImageDescriptor() {
return WorkbenchImages.getImageDescriptor(ISharedImages.IMG_OBJ_FILE);
}
private static String getExtensionText(LargeFileAssociation association) {
String text = association.extension;
if (!association.enabled) {
text += " " + LargeFileAssociationsPreferencePage_ExtensionsTable_DisabledClarification; //$NON-NLS-1$
}
return text;
}
private static String getSizeText(SizeAndUnit size) {
String sizeText = SIZE_TEXT_PREFIX + size.sizeString;
sizeText += getSizeSuffix(size.unitIndex);
return sizeText;
}
private static Text createFileSizeText(Composite parent) {
Text text = new Text(parent, SWT.BORDER);
text.addVerifyListener(new NumberVerifyListener());
text.addModifyListener(new NumberModifyListener());
text.setText(defaultLimit().sizeString);
return text;
}
private static Combo createSizeUnitCombo(Composite parent) {
Combo sizeUnitCombo = new Combo(parent, SWT.READ_ONLY);
for (String unit : SIZE_UNITS) {
sizeUnitCombo.add(unit);
}
sizeUnitCombo.select(DEFAULT_SIZE_UNIT);
return sizeUnitCombo;
}
private static SizeAndUnit getSizeAndUnit(Text fileSizeText, Combo sizeUnitCombo) {
String fileSizeString = fileSizeText.getText();
int sizeUnitSelectionIndex = sizeUnitCombo.getSelectionIndex();
SizeAndUnit size = new SizeAndUnit(fileSizeString, sizeUnitSelectionIndex);
return size;
}
private static SizeAndUnit getSizeAndUnit(long bytes) {
long largestSizeMultiplier = 1L;
int sizeUnitIndex = 0;
for (int i = 0; i < SIZE_UNITS.length; ++i) {
long sizeMultiplier = SIZE_MULTIPLIERS[i];
if (bytes % sizeMultiplier == 0) {
if (largestSizeMultiplier < sizeMultiplier) {
largestSizeMultiplier = sizeMultiplier;
sizeUnitIndex = i;
}
}
}
long sizeInUnit = bytes / largestSizeMultiplier;
String sizeString = String.valueOf(sizeInUnit);
SizeAndUnit sizeAndUnit = new SizeAndUnit(sizeString, sizeUnitIndex);
return sizeAndUnit;
}
private static long computeSize(String sizeString, int unitIndex) {
long bytesWithoutUnit = Long.valueOf(sizeString);
long unitMultiplier = SIZE_MULTIPLIERS[unitIndex];
long size = bytesWithoutUnit * unitMultiplier;
return size;
}
private static SizeAndUnit parseSizeString(String sizeString) {
if (sizeString.startsWith(SIZE_TEXT_PREFIX)) {
sizeString = sizeString.substring(SIZE_TEXT_PREFIX.length());
}
long sizeMultiplier = 1L;
// remove leading/trailing empty spaces if present
sizeString = sizeString.strip();
int unitIndex = 0;
// handle 'KB', 'MB', etc. in the size string
for (int i = 0; i < SIZE_UNITS.length; ++i) {
String sizeSuffix = getSizeSuffix(i);
if (sizeString.endsWith(sizeSuffix)) {
int newLength = sizeString.length() - sizeSuffix.length();
sizeString = sizeString.substring(0, newLength);
unitIndex = i;
break;
}
}
sizeMultiplier = SIZE_MULTIPLIERS[unitIndex];
// remove leading/trailing empty spaces if present
sizeString = sizeString.strip();
long size = Long.valueOf(sizeString);
size *= sizeMultiplier;
return new SizeAndUnit(sizeString, unitIndex, size);
}
private static String getSizeSuffix(int unitIndex) {
return " " + SIZE_UNITS[unitIndex]; //$NON-NLS-1$
}
private static int compareEditors(EditorForSize e1, EditorForSize e2) {
return Long.compare(e1.size.bytes, e2.size.bytes);
}
private static EditorForSize defaultPromptEditor() {
SizeAndUnit size = defaultLimit();
EditorForSize defaultPromptEditor = new EditorForSize(size);
return defaultPromptEditor;
}
private static SizeAndUnit defaultLimit() {
return getSizeAndUnit(getDefaultLimit());
}
private static class NumberVerifyListener implements VerifyListener {
@Override
public void verifyText(VerifyEvent e) {
Text text = (Text) e.getSource();
String oldText = text.getText();
String prefix = oldText.substring(0, e.start);
String suffix = oldText.substring(e.end);
String newText = prefix + e.text + suffix;
// only allow non-negative integers or empty string
if (newText.startsWith("0") && newText.length() > 1) { //$NON-NLS-1$
e.doit = false;
} else if (newText.startsWith("-") || newText.startsWith("+")) { //$NON-NLS-1$ //$NON-NLS-2$
e.doit = false;
} else if (!newText.isEmpty()) {
try {
long size = Long.parseLong(newText);
if (size < 0) {
e.doit = false;
}
} catch (NumberFormatException ex) {
e.doit = false;
}
}
}
}
private static class NumberModifyListener implements ModifyListener {
@Override
public void modifyText(ModifyEvent e) {
Text text = (Text) e.widget;
String contents = text.getText();
if (contents.isBlank()) {
// to allow deleting selected text, set a '0' for empty text field
text.setText("0"); //$NON-NLS-1$
}
}
}
private static class ExtensionDialog extends TitleAreaDialog {
private static final String ASTERIX_PREFIX = "*."; //$NON-NLS-1$
private Button okButton;
private Text extensionText;
private String extension = ""; //$NON-NLS-1$
ExtensionDialog(Shell shell) {
super(shell);
setShellStyle(getShellStyle() | SWT.SHEET);
}
@Override
protected void configureShell(Shell shell) {
super.configureShell(shell);
shell.setText(WorkbenchMessages.FileExtension_shellTitle);
}
@Override
protected Control createDialogArea(Composite parent) {
Composite parentComposite = (Composite) super.createDialogArea(parent);
Composite contents = new Composite(parentComposite, SWT.NONE);
contents.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
setTitle(WorkbenchMessages.FileExtension_shellTitle);
setMessage(LargeFileAssociationsPreferencePage_ExtensionDialog_Message);
new Label(contents, SWT.LEFT).setText(LargeFileAssociationsPreferencePage_ExtensionDialog_Label);
extensionText = new Text(contents, SWT.SINGLE | SWT.BORDER);
extensionText.addModifyListener(event -> {
if (event.widget == extensionText) {
extension = extensionText.getText().trim();
okButton.setEnabled(validateExtension());
}
});
extensionText.setFocus();
Dialog.applyDialogFont(parentComposite);
Point defaultMargins = LayoutConstants.getMargins();
GridLayoutFactory.fillDefaults().numColumns(2).margins(defaultMargins.x, defaultMargins.y)
.generateLayout(contents);
return contents;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
okButton.setEnabled(false);
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
}
private boolean validateExtension() {
if (extension.isEmpty()) {
setErrorMessage(WorkbenchMessages.FileExtension_extensionEmptyMessage);
return false;
}
int dotIndex = extension.indexOf('.');
int asterixIndex = extension.indexOf('*');
if (dotIndex != -1 || asterixIndex != -1) {
if (!extension.startsWith(ASTERIX_PREFIX) || extension.equals(ASTERIX_PREFIX)) {
setErrorMessage(LargeFileAssociationsPreferencePage_ExtensionDialog_Error_WildcardAndDot);
return false;
}
}
setErrorMessage(null);
return true;
}
String getExtension() {
if (extension.startsWith(ASTERIX_PREFIX)) {
return extension.substring(ASTERIX_PREFIX.length());
}
return extension;
}
@Override
protected boolean isResizable() {
return true;
}
}
private static class EditorForSizeDialog extends TitleAreaDialog {
private final long[] filteredFileSizes;
private final IEditorDescriptor[] filteredEditors;
private final EditorForSize initialValues;
private final String extension;
private Text sizeText;
private Combo sizeUnitCombo;
private Button promptEditorOnOpen;
private Button chooseEditorWithDialog;
private Button okButton;
private IEditorDescriptor selectedEditor;
EditorForSize chosenValues;
EditorForSizeDialog(Shell shell, IEditorDescriptor[] filteredEditors, long[] filteredFileSizes,
EditorForSize initialValues, String extension) {
super(shell);
setShellStyle(getShellStyle() | SWT.SHEET);
this.filteredFileSizes = filteredFileSizes;
this.filteredEditors = filteredEditors;
this.initialValues = initialValues;
this.extension = extension;
selectedEditor = initialValues.editor;
chosenValues = initialValues;
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(LargeFileAssociationsPreferencePage_EditorDialog_ShellTitle);
}
@Override
protected Control createDialogArea(Composite parent) {
Composite parentComposite = (Composite) super.createDialogArea(parent);
Composite contents = new Composite(parentComposite, SWT.NONE);
contents.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
setTitle(NLS.bind(LargeFileAssociationsPreferencePage_EditorDialog_Title, extension));
setMessage(NLS.bind(LargeFileAssociationsPreferencePage_EditorDialog_Message, extension));
Group editorTypeGroup = new Group(contents, SWT.NONE);
editorTypeGroup.setText(LargeFileAssociationsPreferencePage_EditorDialog_Label_Editor);
editorTypeGroup.setLayout(new GridLayout(2, false));
editorTypeGroup.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
promptEditorOnOpen = new Button(editorTypeGroup, SWT.RADIO);
promptEditorOnOpen.setSelection(initialValues.isPrompt);
promptEditorOnOpen.setText(LargeFileAssociationsPreferencePage_EditorDialog_Radio_Prompt);
GridData data = new GridData();
data.horizontalSpan = 2;
promptEditorOnOpen.setLayoutData(data);
chooseEditorWithDialog = new Button(editorTypeGroup, SWT.RADIO);
chooseEditorWithDialog.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false));
chooseEditorWithDialog.setSelection(!initialValues.isPrompt);
Hyperlink chooseEditorLink = new Hyperlink(editorTypeGroup, SWT.NONE);
chooseEditorLink.setUnderlined(true);
chooseEditorLink.setFont(JFaceResources.getDialogFont());
if (selectedEditor != null) {
chooseEditorLink.setText(selectedEditor.getLabel());
} else {
chooseEditorLink.setText(LargeFileAssociationsPreferencePage_EditorDialog_Radio_Specific);
}
chooseEditorLink.setForeground(JFaceColors.getHyperlinkText(chooseEditorLink.getDisplay()));
chooseEditorLink.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
chooseEditorLink.setEnabled(!initialValues.isPrompt);
data = new GridData();
data.horizontalAlignment = SWT.FILL;
data.grabExcessHorizontalSpace = true;
chooseEditorLink.setLayoutData(data);
chooseEditorWithDialog.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean selectEditorWithDialog = chooseEditorWithDialog.getSelection();
chooseEditorLink.setEnabled(selectEditorWithDialog);
okButton.setEnabled(validateValues());
}
});
chooseEditorLink.addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
selectedEditor = promptForEditorWithDialog(getShell(), filteredEditors, extension);
if (selectedEditor != null) {
chooseEditorLink.setText(selectedEditor.getLabel());
} else {
chooseEditorLink.setText(LargeFileAssociationsPreferencePage_EditorDialog_Radio_Specific);
}
okButton.setEnabled(validateValues());
}
});
Group fileSizeGroup = new Group(contents, SWT.NONE);
fileSizeGroup.setText(LargeFileAssociationsPreferencePage_EditorDialog_Label_FileSize);
fileSizeGroup.setLayout(new FillLayout(SWT.HORIZONTAL));
fileSizeGroup.setLayoutData(new GridData(SWT.LEFT, SWT.BEGINNING, true, false));
sizeText = createFileSizeText(fileSizeGroup);
sizeText.setText(initialValues.size.sizeString);
sizeUnitCombo = createSizeUnitCombo(fileSizeGroup);
sizeUnitCombo.select(initialValues.size.unitIndex);
sizeText.setFocus();
sizeText.addModifyListener(event -> {
if (event.widget == sizeText) {
okButton.setEnabled(validateValues());
}
});
sizeUnitCombo.addModifyListener(event -> {
if (event.widget == sizeUnitCombo) {
okButton.setEnabled(validateValues());
}
});
Dialog.applyDialogFont(contents);
Point defaultMargins = LayoutConstants.getMargins();
GridLayoutFactory.fillDefaults().numColumns(1).margins(defaultMargins.x, defaultMargins.y)
.generateLayout(contents);
return contents;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
okButton.setEnabled(validateSize());
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
}
@Override
protected void okPressed() {
boolean promptForEditor = promptEditorOnOpen.getSelection();
SizeAndUnit size = getSizeAndUnit(sizeText, sizeUnitCombo);
chosenValues = new EditorForSize(selectedEditor, promptForEditor, size);
super.okPressed();
}
@Override
protected boolean isResizable() {
return true;
}
private boolean validateValues() {
if (!validateSelectedEditor()) {
return false;
}
if (!validateSize()) {
return false;
}
return true;
}
private boolean validateSelectedEditor() {
boolean selectEditorWithDialog = chooseEditorWithDialog.getSelection();
if (selectEditorWithDialog && selectedEditor == null) {
setErrorMessage(LargeFileAssociationsPreferencePage_EditorDialog_Error_NoEditorSelected);
return false;
}
setErrorMessage(null);
return true;
}
private boolean validateSize() {
SizeAndUnit currentSize = getSizeAndUnit(sizeText, sizeUnitCombo);
long currentFileSize = currentSize.bytes;
boolean editorConfiguredForBytes = false;
for (long configuredFileSize : filteredFileSizes) {
if (currentFileSize == configuredFileSize) {
editorConfiguredForBytes = true;
break;
}
}
if (editorConfiguredForBytes) {
setErrorMessage(LargeFileAssociationsPreferencePage_EditorDialog_Error_DuplicateSize);
return false;
}
setErrorMessage(null);
return true;
}
}
private static class LargeFileAssociation {
private final String extension;
private final List<EditorForSize> editors;
private boolean enabled;
LargeFileAssociation(String extension) {
this.extension = extension;
editors = new ArrayList<>();
enabled = true;
}
void addEditor(EditorForSize editor) {
int index = indexOfEditor(editor);
editors.add(index, editor);
}
int indexOfEditor(EditorForSize editor) {
int index = Collections.binarySearch(editors, editor, EDITOR_COMPARATOR);
if (index < 0) {
index = -index - 1;
}
return index;
}
void removeEditor(IEditorDescriptor editor) {
if (editor != null) {
editors.removeIf(e -> e.editor != null && e.editor.equals(editor));
}
}
void removePromptEditor() {
editors.removeIf(e -> e.isPrompt);
}
void setPromptEditorSize(SizeAndUnit size) {
removePromptEditor();
EditorForSize promptEditor = new EditorForSize(size);
addEditor(promptEditor);
}
}
private static class EditorForSize {
final IEditorDescriptor editor;
final boolean isPrompt;
final SizeAndUnit size;
EditorForSize(SizeAndUnit size) {
this(null, true, size);
}
EditorForSize(IEditorDescriptor editor, SizeAndUnit size) {
this(editor, false, size);
}
private EditorForSize(IEditorDescriptor editor, boolean isPrompt, SizeAndUnit size) {
this.editor = editor;
this.isPrompt = isPrompt;
this.size = size;
}
}
private static class SizeAndUnit {
final String sizeString;
final int unitIndex;
final long bytes;
SizeAndUnit(String sizeString, int unitIndex) {
this(sizeString, unitIndex, computeSize(sizeString, unitIndex));
}
SizeAndUnit(String sizeString, int unitIndex, long bytes) {
this.sizeString = sizeString;
this.unitIndex = unitIndex;
this.bytes = bytes;
}
}
}