blob: 39c40c921424cb770831f16b1e8d98c018b554f6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Patrik Suzzi <psuzzi@gmail.com> - Bug 489250
*******************************************************************************/
package org.eclipse.ui.internal.ide.dialogs;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
/**
* The FileStatesPage is the page used to set the file states sizes for the workbench.
*/
public class FileStatesPage extends PreferencePage implements
IWorkbenchPreferencePage, Listener {
private static final int FAILED_VALUE = -1;
//Set the length of the day as we have to convert back and forth
private static final long DAY_LENGTH = 86400000;
private static final long MEGABYTES = 1024 * 1024;
private Text longevityText;
private Text maxStatesText;
private Text maxStateSizeText;
private Button applyPolicyButton;
private Button keepDerivedStateButton;
private ArrayList<Control> dependentControls = new ArrayList<>();
//Choose a maximum to prevent OutOfMemoryErrors
private int FILE_STATES_MAXIMUM = 10000;
private long STATE_SIZE_MAXIMUM = 100;
private static final int INDENT = 20;
/**
* This method takes the string for the title of a text field and the value for the
* text of the field.
* @return org.eclipse.swt.widgets.Text
* @param labelString java.lang.String
* @param textValue java.lang.String
* @param parent Composite
*/
private Text addDependentLabelAndText(String labelString, String textValue,
Composite parent) {
Label label = new Label(parent, SWT.LEFT);
label.setText(labelString);
dependentControls.add(label);
Text text = new Text(parent, SWT.LEFT | SWT.BORDER);
GridData data = new GridData();
text.addListener(SWT.Modify, this);
data.horizontalAlignment = GridData.FILL;
data.grabExcessHorizontalSpace = true;
data.verticalAlignment = GridData.CENTER;
data.grabExcessVerticalSpace = false;
text.setLayoutData(data);
text.setText(textValue);
dependentControls.add(text);
return text;
}
private Button addCheckBox(String label, boolean selected, Composite parent) {
Button button = new Button(parent, SWT.CHECK | SWT.LEFT);
button.addListener(SWT.Selection, this);
GridData data = new GridData();
data.horizontalSpan = 2;
data.horizontalIndent= -INDENT;
button.setLayoutData(data);
button.setText(label);
button.setSelection(selected);
return button;
}
/**
* Recomputes the page's error state by validating all
* the fields.
*/
private void checkState() {
// Assume invalid if the controls not created yet
if (longevityText == null || maxStatesText == null || maxStateSizeText == null || applyPolicyButton == null
|| keepDerivedStateButton == null) {
setValid(false);
return;
}
boolean newState= applyPolicyButton.getSelection();
Iterator<Control> iter = dependentControls.iterator();
while (iter.hasNext())
iter.next().setEnabled(newState);
if (validateLongTextEntry(longevityText, DAY_LENGTH) == FAILED_VALUE) {
setValid(false);
return;
}
if (validateMaxFileStates() == FAILED_VALUE) {
setValid(false);
return;
}
if (validateMaxFileStateSize() == FAILED_VALUE) {
setValid(false);
return;
}
setValid(true);
setErrorMessage(null);
}
/*
* Create the contents control for the workspace file states.
* @returns Control
* @param parent Composite
*/
@Override
protected Control createContents(Composite parent) {
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent,
IIDEHelpContextIds.FILE_STATES_PREFERENCE_PAGE);
IWorkspaceDescription description = getWorkspaceDescription();
//Get the current value and make sure we get at least one day out of it.
long days = description.getFileStateLongevity() / DAY_LENGTH;
if (days < 1) {
days = 1;
}
long megabytes = description.getMaxFileStateSize() / MEGABYTES;
if (megabytes < 1) {
megabytes = 1;
}
// button group
Composite composite= new Composite(parent, SWT.NONE);
GridLayout layout= new GridLayout();
layout.numColumns= 2;
layout.marginLeft= INDENT;
layout.marginWidth= 0;
composite.setLayout(layout);
this.keepDerivedStateButton = addCheckBox(IDEWorkbenchMessages.FileHistory_keepDerivedState,
description.isKeepDerivedState(), composite);
this.applyPolicyButton = addCheckBox(IDEWorkbenchMessages.FileHistory_applyPolicy, description
.isApplyFileStatePolicy(), composite);
this.longevityText= addDependentLabelAndText(IDEWorkbenchMessages.FileHistory_longevity, String
.valueOf(days), composite);
this.maxStatesText= addDependentLabelAndText(IDEWorkbenchMessages.FileHistory_entries, String
.valueOf(description.getMaxFileStates()), composite);
this.maxStateSizeText= addDependentLabelAndText(IDEWorkbenchMessages.FileHistory_diskSpace,
String.valueOf(megabytes), composite);
checkState();
//Create a spacing label to breakup the note from the fields
Label spacer = new Label(composite, SWT.NONE);
GridData spacerData = new GridData();
spacerData.horizontalSpan = 2;
spacer.setLayoutData(spacerData);
Composite noteComposite = createNoteComposite(parent.getFont(),
composite, IDEWorkbenchMessages.Preference_note, IDEWorkbenchMessages.FileHistory_restartNote);
GridData noteData = new GridData();
noteData.horizontalSpan = 2;
noteComposite.setLayoutData(noteData);
dependentControls.addAll(Arrays.asList(noteComposite.getChildren()));
applyDialogFont(composite);
return composite;
}
/**
* Get the Workspace Description this page is operating on.
* @return org.eclipse.core.resources.IWorkspaceDescription
*/
private IWorkspaceDescription getWorkspaceDescription() {
return ResourcesPlugin.getWorkspace().getDescription();
}
/**
* Sent when an event that the receiver has registered for occurs.
*
* @param event the event which occurred
*/
@Override
public void handleEvent(Event event) {
checkState();
}
/**
* Initializes this preference page for the given workbench.
* <p>
* This method is called automatically as the preference page is being created
* and initialized. Clients must not call this method.
* </p>
*
* @param workbench the workbench
*/
@Override
public void init(org.eclipse.ui.IWorkbench workbench) {
}
/**
* Performs special processing when this page's Defaults button has been pressed.
* Reset the entries to their default values.
*/
@Override
protected void performDefaults() {
super.performDefaults();
Preferences prefs = ResourcesPlugin.getPlugin().getPluginPreferences();
long days = prefs
.getDefaultLong(ResourcesPlugin.PREF_FILE_STATE_LONGEVITY)
/ DAY_LENGTH;
long megabytes = prefs
.getDefaultLong(ResourcesPlugin.PREF_MAX_FILE_STATE_SIZE)
/ MEGABYTES;
this.longevityText.setText(String.valueOf(days));
this.maxStatesText.setText(prefs
.getDefaultString(ResourcesPlugin.PREF_MAX_FILE_STATES));
this.maxStateSizeText.setText(String.valueOf(megabytes));
this.keepDerivedStateButton.setSelection(prefs.getDefaultBoolean(ResourcesPlugin.PREF_KEEP_DERIVED_STATE));
this.applyPolicyButton.setSelection(prefs
.getDefaultBoolean(ResourcesPlugin.PREF_APPLY_FILE_STATE_POLICY));
checkState();
}
/**
* Perform the result of the OK from the receiver.
*/
@Override
public boolean performOk() {
long longevityValue = validateLongTextEntry(longevityText, DAY_LENGTH);
int maxFileStates = validateMaxFileStates();
long maxStateSize = validateMaxFileStateSize();
boolean keepDerivedState = keepDerivedStateButton.getSelection();
boolean applyPolicy = applyPolicyButton.getSelection();
if (longevityValue == FAILED_VALUE || maxFileStates == FAILED_VALUE
|| maxStateSize == FAILED_VALUE) {
return false;
}
IWorkspaceDescription description = getWorkspaceDescription();
description.setFileStateLongevity(longevityValue * DAY_LENGTH);
description.setMaxFileStates(maxFileStates);
description.setMaxFileStateSize(maxStateSize * MEGABYTES);
description.setKeepDerivedState(keepDerivedState);
description.setApplyFileStatePolicy(applyPolicy);
try {
//As it is only a copy save it back in
ResourcesPlugin.getWorkspace().setDescription(description);
} catch (CoreException exception) {
ErrorDialog.openError(getShell(), IDEWorkbenchMessages.FileHistory_exceptionSaving, exception
.getMessage(), exception.getStatus());
return false;
}
return true;
}
/**
* Validate a text entry for an integer field. Return the result if there are
* no errors, otherwise return -1 and set the entry field error.
* @return int
*/
private int validateIntegerTextEntry(Text text) {
int value;
try {
value = Integer.parseInt(text.getText());
} catch (NumberFormatException exception) {
setErrorMessage(MessageFormat.format(IDEWorkbenchMessages.FileHistory_invalid,
exception.getLocalizedMessage()));
return FAILED_VALUE;
}
//Be sure all values are non zero and positive
if (value <= 0) {
setErrorMessage(IDEWorkbenchMessages.FileHistory_mustBePositive);
return FAILED_VALUE;
}
return value;
}
/**
* Validate a text entry for a long field. Return the result if there are
* no errors, otherwise return -1 and set the entry field error.
* @param scale the scale (factor by which the value is multiplied when it is persisted)
* @return long
*/
private long validateLongTextEntry(Text text, long scale) {
long value;
try {
String string = text.getText();
value = Long.parseLong(string);
if (value * scale / scale != value)
throw new NumberFormatException(string);
} catch (NumberFormatException exception) {
setErrorMessage(MessageFormat.format(IDEWorkbenchMessages.FileHistory_invalid,
exception.getLocalizedMessage()));
return FAILED_VALUE;
}
//Be sure all values are non zero and positive
if (value <= 0) {
setErrorMessage(IDEWorkbenchMessages.FileHistory_mustBePositive);
return FAILED_VALUE;
}
return value;
}
/**
* Validate the maximum file states.
* Return the value if successful, otherwise
* return FAILED_VALUE.
* Set the error message if it fails.
* @return int
*/
private int validateMaxFileStates() {
int maxFileStates = validateIntegerTextEntry(this.maxStatesText);
if (maxFileStates == FAILED_VALUE) {
return maxFileStates;
}
if (maxFileStates > FILE_STATES_MAXIMUM) {
setErrorMessage(NLS.bind(IDEWorkbenchMessages.FileHistory_aboveMaxEntries, String.valueOf(FILE_STATES_MAXIMUM)));
return FAILED_VALUE;
}
return maxFileStates;
}
/**
* Validate the maximum file state size.
* Return the value if successful, otherwise
* return FAILED_VALUE.
* Set the error message if it fails.
* @return long
*/
private long validateMaxFileStateSize() {
long maxFileStateSize = validateLongTextEntry(this.maxStateSizeText, MEGABYTES);
if (maxFileStateSize == FAILED_VALUE) {
return maxFileStateSize;
}
if (maxFileStateSize > STATE_SIZE_MAXIMUM) {
setErrorMessage(NLS.bind(IDEWorkbenchMessages.FileHistory_aboveMaxFileSize, String.valueOf(STATE_SIZE_MAXIMUM)));
return FAILED_VALUE;
}
return maxFileStateSize;
}
}