/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.rubypeople.rdt.internal.ui.preferences;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.ColorSelector;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.RGB;
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.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.rubypeople.rdt.core.RubyCore;
import org.rubypeople.rdt.internal.corext.util.Messages;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.rubyeditor.RubySourceViewer;
import org.rubypeople.rdt.internal.ui.text.IRubyColorConstants;
import org.rubypeople.rdt.internal.ui.text.IRubyPartitions;
import org.rubypeople.rdt.internal.ui.text.PreferencesAdapter;
import org.rubypeople.rdt.internal.ui.text.RubyColorManager;
import org.rubypeople.rdt.internal.ui.text.SimpleRubySourceViewerConfiguration;
import org.rubypeople.rdt.internal.ui.util.ExceptionHandler;
import org.rubypeople.rdt.internal.ui.util.PixelConverter;
import org.rubypeople.rdt.internal.ui.util.SWTUtil;
import org.rubypeople.rdt.ui.PreferenceConstants;
import org.rubypeople.rdt.ui.RubyUI;
import org.rubypeople.rdt.ui.text.IColorManager;
/**
* Configures Ruby Editor hover preferences.
*
* @since 0.9.0
*/
class RubyEditorColoringConfigurationBlock extends AbstractConfigurationBlock {
private static final String DIALOGSTORE_LASTLOADPATH= RubyUI.ID_PLUGIN + ".syntaxcoloring.loadpath"; //$NON-NLS-1$
private static final String DIALOGSTORE_LASTSAVEPATH= RubyUI.ID_PLUGIN + ".syntaxcoloring.savepath"; //$NON-NLS-1$
/**
* Item in the highlighting color list.
*
* @since 0.9.0
*/
public static class HighlightingColorListItem {
/** Display name */
private String fDisplayName;
/** Color preference key */
private String fColorKey;
/** Bold preference key */
private String fBoldKey;
/** Background preference key */
private String fBackgroundKey;
/** Italic preference key */
private String fItalicKey;
/**
* Strikethrough preference key.
* @since 0.9.0
*/
private String fStrikethroughKey;
/**
* Underline preference key.
* @since 0.9.0
*/
private String fUnderlineKey;
/**
* Background enablement key.
* @since 1.0.0
*/
private String fBackgroundEnabledKey;
/**
* Initialize the item with the given values.
* @param displayName the display name
* @param colorKey the color preference key
* @param bgColorKey the color preference key
* @param bgEnabledKey whetehr the custom background color is enabled
* @param boldKey the bold preference key
* @param italicKey the italic preference key
* @param strikethroughKey the strikethrough preference key
* @param underlineKey the underline preference key
*/
public HighlightingColorListItem(String displayName, String colorKey, String bgColorKey, String bgEnabledKey, String boldKey, String italicKey, String strikethroughKey, String underlineKey) {
fDisplayName= displayName;
fColorKey= colorKey;
fBackgroundKey = bgColorKey;
fBackgroundEnabledKey = bgEnabledKey;
fBoldKey= boldKey;
fItalicKey= italicKey;
fStrikethroughKey= strikethroughKey;
fUnderlineKey= underlineKey;
}
/**
* @return the bold preference key
*/
public String getBoldKey() {
return fBoldKey;
}
/**
* @return the background preference key
*/
public String getBackgroundKey() {
return fBackgroundKey;
}
/**
* @return the bold preference key
*/
public String getItalicKey() {
return fItalicKey;
}
/**
* @return the strikethrough preference key
* @since 3.1
*/
public String getStrikethroughKey() {
return fStrikethroughKey;
}
/**
* @return the underline preference key
* @since 3.1
*/
public String getUnderlineKey() {
return fUnderlineKey;
}
/**
* @return the color preference key
*/
public String getColorKey() {
return fColorKey;
}
/**
* @return the display name
*/
public String getDisplayName() {
return fDisplayName;
}
public String getBackgroundEnabledKey() {
return fBackgroundEnabledKey;
}
}
private static class SemanticHighlightingColorListItem extends HighlightingColorListItem {
/** Enablement preference key */
private final String fEnableKey;
/**
* Initialize the item with the given values.
* @param displayName the display name
* @param colorKey the color preference key
* @param bgColorKey the color preference key
* @param bgEnabledKey
* @param boldKey the bold preference key
* @param italicKey the italic preference key
* @param strikethroughKey the strikethroughKey preference key
* @param underlineKey the underlineKey preference key
* @param enableKey the enable preference key
*/
public SemanticHighlightingColorListItem(String displayName, String colorKey, String bgColorKey, String bgEnabledKey, String boldKey, String italicKey, String strikethroughKey, String underlineKey, String enableKey) {
super(displayName, colorKey, bgColorKey, bgEnabledKey, boldKey, italicKey, strikethroughKey, underlineKey);
fEnableKey= enableKey;
}
/**
* @return the enablement preference key
*/
public String getEnableKey() {
return fEnableKey;
}
}
/**
* Color list label provider.
*
* @since 3.0
*/
private class ColorListLabelProvider extends LabelProvider {
/*
* @see org.eclipse.jface.viewers.ILabelProvider#getText(ruby.lang.Object)
*/
public String getText(Object element) {
if (element instanceof String)
return (String) element;
return ((HighlightingColorListItem)element).getDisplayName();
}
}
/**
* Color list content provider.
*
* @since 3.0
*/
private class ColorListContentProvider implements ITreeContentProvider {
/*
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(ruby.lang.Object)
*/
public Object[] getElements(Object inputElement) {
return new String[] {fRubyCategory};
}
/*
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
public void dispose() {
}
/*
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, ruby.lang.Object, ruby.lang.Object)
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof String) {
String entry= (String) parentElement;
if (fRubyCategory.equals(entry))
return fListModel.toArray();
}
return new Object[0];
}
public Object getParent(Object element) {
if (element instanceof String)
return null;
return fRubyCategory;
}
public boolean hasChildren(Object element) {
return element instanceof String;
}
}
private static final String BOLD= PreferenceConstants.EDITOR_BOLD_SUFFIX;
private static final String BACKGROUND= PreferenceConstants.EDITOR_BG_SUFFIX;
private static final String BACKGROUND_ENABLED= PreferenceConstants.EDITOR_BG_ENABLED_SUFFIX;
/**
* Preference key suffix for italic preferences.
* @since 0.9.0
*/
private static final String ITALIC= PreferenceConstants.EDITOR_ITALIC_SUFFIX;
/**
* Preference key suffix for strikethrough preferences.
* @since 0.9.0
*/
private static final String STRIKETHROUGH= PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX;
/**
* Preference key suffix for underline preferences.
* @since 0.9.0
*/
private static final String UNDERLINE= PreferenceConstants.EDITOR_UNDERLINE_SUFFIX;
private static final String COMPILER_TASK_TAGS= RubyCore.COMPILER_TASK_TAGS;
/**
* The keys of the overlay store.
*/
private final String[][] fSyntaxColorListModel= new String[][] {
{ PreferencesMessages.RubyEditorPreferencePage_multiLineComment, IRubyColorConstants.RUBY_MULTI_LINE_COMMENT },
{ PreferencesMessages.RubyEditorPreferencePage_singleLineComment, IRubyColorConstants.RUBY_SINGLE_LINE_COMMENT },
{ PreferencesMessages.RubyEditorPreferencePage_rubyCommentTaskTags, IRubyColorConstants.TASK_TAG },
{ PreferencesMessages.RubyEditorPreferencePage_keywords, IRubyColorConstants.RUBY_KEYWORD },
{ PreferencesMessages.RubyEditorPreferencePage_strings, IRubyColorConstants.RUBY_STRING },
{ PreferencesMessages.RubyEditorPreferencePage_characters, IRubyColorConstants.RUBY_CHARACTER },
{ PreferencesMessages.RubyEditorPreferencePage_commands, IRubyColorConstants.RUBY_COMMAND },
{ PreferencesMessages.RubyEditorPreferencePage_fixnums, IRubyColorConstants.RUBY_FIXNUM },
{ PreferencesMessages.RubyEditorPreferencePage_globals, IRubyColorConstants.RUBY_GLOBAL },
{ PreferencesMessages.RubyEditorPreferencePage_regular_expressions, IRubyColorConstants.RUBY_REGEXP },
{ PreferencesMessages.RubyEditorPreferencePage_symbols, IRubyColorConstants.RUBY_SYMBOL },
{ PreferencesMessages.RubyEditorPreferencePage_instance_variables, IRubyColorConstants.RUBY_INSTANCE_VARIABLE },
{ PreferencesMessages.RubyEditorPreferencePage_class_variables, IRubyColorConstants.RUBY_CLASS_VARIABLE },
{ PreferencesMessages.RubyEditorPreferencePage_others, IRubyColorConstants.RUBY_DEFAULT }
};
private final String fRubyCategory= PreferencesMessages.RubyEditorPreferencePage_coloring_category_ruby;
private ColorSelector fSyntaxForegroundColorEditor;
private ColorSelector fSyntaxBackgroundColorEditor;
private Label fColorEditorLabel;
private Button fBoldCheckBox;
private Button fEnableCheckbox;
/**
* Check box for italic preference.
* @since 3.0
*/
private Button fItalicCheckBox;
/**
* Check box for strikethrough preference.
* @since 3.1
*/
private Button fStrikethroughCheckBox;
/**
* Check box for underline preference.
* @since 3.1
*/
private Button fUnderlineCheckBox;
/**
* Highlighting color list
* @since 3.0
*/
private final java.util.List fListModel= new ArrayList();
/**
* Highlighting color list viewer
* @since 3.0
*/
private StructuredViewer fListViewer;
/**
* The previewer.
* @since 3.0
*/
private RubySourceViewer fPreviewViewer;
/**
* The color manager.
* @since 3.1
*/
private IColorManager fColorManager;
/**
* The font metrics.
* @since 3.1
*/
private FontMetrics fFontMetrics;
private Button fLoadButton;
private Button fSaveButton;
private Composite fComposite;
private Button fEnableBackgroundCheckbox;
public RubyEditorColoringConfigurationBlock(OverlayPreferenceStore store) {
super(store);
fColorManager= new RubyColorManager(false);
for (int i= 0, n= fSyntaxColorListModel.length; i < n; i++)
fListModel.add(new HighlightingColorListItem (fSyntaxColorListModel[i][0], fSyntaxColorListModel[i][1], fSyntaxColorListModel[i][1] + BACKGROUND, fSyntaxColorListModel[i][1] + BACKGROUND_ENABLED, fSyntaxColorListModel[i][1] + BOLD, fSyntaxColorListModel[i][1] + ITALIC, fSyntaxColorListModel[i][1] + STRIKETHROUGH, fSyntaxColorListModel[i][1] + UNDERLINE));
store.addKeys(createOverlayStoreKeys());
}
private OverlayPreferenceStore.OverlayKey[] createOverlayStoreKeys() {
ArrayList overlayKeys= new ArrayList();
for (int i= 0, n= fListModel.size(); i < n; i++) {
HighlightingColorListItem item= (HighlightingColorListItem) fListModel.get(i);
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, item.getColorKey()));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, item.getBackgroundKey()));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, item.getBackgroundEnabledKey()));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, item.getBoldKey()));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, item.getItalicKey()));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, item.getStrikethroughKey()));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, item.getUnderlineKey()));
if (item instanceof SemanticHighlightingColorListItem)
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ((SemanticHighlightingColorListItem) item).getEnableKey()));
}
OverlayPreferenceStore.OverlayKey[] keys= new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
overlayKeys.toArray(keys);
return keys;
}
/**
* Creates page for hover preferences.
*
* @param parent the parent composite
* @return the control for the preference page
*/
public Control createControl(Composite parent) {
initializeDialogUnits(parent);
return createSyntaxPage(parent);
}
/**
* Returns the number of pixels corresponding to the width of the given
* number of characters.
* <p>
* This method may only be called after <code>initializeDialogUnits</code>
* has been called.
* </p>
* <p>
* Clients may call this framework method, but should not override it.
* </p>
*
* @param chars
* the number of characters
* @return the number of pixels
*/
private int convertWidthInCharsToPixels(int chars) {
// test for failure to initialize for backward compatibility
if (fFontMetrics == null)
return 0;
return Dialog.convertWidthInCharsToPixels(fFontMetrics, chars);
}
/**
* Returns the number of pixels corresponding to the height of the given
* number of characters.
* <p>
* This method may only be called after <code>initializeDialogUnits</code>
* has been called.
* </p>
* <p>
* Clients may call this framework method, but should not override it.
* </p>
*
* @param chars
* the number of characters
* @return the number of pixels
*/
private int convertHeightInCharsToPixels(int chars) {
// test for failure to initialize for backward compatibility
if (fFontMetrics == null)
return 0;
return Dialog.convertHeightInCharsToPixels(fFontMetrics, chars);
}
public void initialize() {
super.initialize();
fListViewer.setInput(fListModel);
fListViewer.setSelection(new StructuredSelection(fRubyCategory));
}
public void performDefaults() {
super.performDefaults();
handleSyntaxColorListSelection();
fPreviewViewer.invalidateTextPresentation();
}
/*
* @see org.eclipse.jdt.internal.ui.preferences.IPreferenceConfigurationBlock#dispose()
*/
public void dispose() {
fColorManager.dispose();
super.dispose();
}
private void handleSyntaxColorListSelection() {
HighlightingColorListItem item= getHighlightingColorListItem();
if (item == null) {
fEnableCheckbox.setEnabled(false);
fSyntaxForegroundColorEditor.getButton().setEnabled(false);
fSyntaxBackgroundColorEditor.getButton().setEnabled(false);
fColorEditorLabel.setEnabled(false);
fBoldCheckBox.setEnabled(false);
fItalicCheckBox.setEnabled(false);
fStrikethroughCheckBox.setEnabled(false);
fUnderlineCheckBox.setEnabled(false);
return;
}
RGB rgb= PreferenceConverter.getColor(getPreferenceStore(), item.getColorKey());
fSyntaxForegroundColorEditor.setColorValue(rgb);
rgb= PreferenceConverter.getColor(getPreferenceStore(), item.getBackgroundKey());
// TODO If we get back default color, show the default text editor bg color.
fSyntaxBackgroundColorEditor.setColorValue(rgb);
fBoldCheckBox.setSelection(getPreferenceStore().getBoolean(item.getBoldKey()));
fItalicCheckBox.setSelection(getPreferenceStore().getBoolean(item.getItalicKey()));
fStrikethroughCheckBox.setSelection(getPreferenceStore().getBoolean(item.getStrikethroughKey()));
fUnderlineCheckBox.setSelection(getPreferenceStore().getBoolean(item.getUnderlineKey()));
if (item instanceof SemanticHighlightingColorListItem) {
fEnableCheckbox.setEnabled(true);
boolean enable= getPreferenceStore().getBoolean(((SemanticHighlightingColorListItem) item).getEnableKey());
fEnableCheckbox.setSelection(enable);
fSyntaxForegroundColorEditor.getButton().setEnabled(enable);
fColorEditorLabel.setEnabled(enable);
fBoldCheckBox.setEnabled(enable);
fItalicCheckBox.setEnabled(enable);
fStrikethroughCheckBox.setEnabled(enable);
fUnderlineCheckBox.setEnabled(enable);
fEnableBackgroundCheckbox.setEnabled(enable);
boolean bgEnabled = getPreferenceStore().getBoolean(((SemanticHighlightingColorListItem) item).getBackgroundEnabledKey());
fEnableBackgroundCheckbox.setSelection(bgEnabled);
fSyntaxBackgroundColorEditor.getButton().setEnabled(bgEnabled);
} else {
fSyntaxForegroundColorEditor.getButton().setEnabled(true);
fColorEditorLabel.setEnabled(true);
fBoldCheckBox.setEnabled(true);
fItalicCheckBox.setEnabled(true);
fStrikethroughCheckBox.setEnabled(true);
fUnderlineCheckBox.setEnabled(true);
fEnableCheckbox.setEnabled(false);
fEnableCheckbox.setSelection(true);
fEnableBackgroundCheckbox.setEnabled(true);
boolean bgEnabled = getPreferenceStore().getBoolean(item.getBackgroundEnabledKey());
fEnableBackgroundCheckbox.setSelection(bgEnabled);
fSyntaxBackgroundColorEditor.getButton().setEnabled(bgEnabled);
}
}
private Control createSyntaxPage(final Composite parent) {
Composite colorComposite= new Composite(parent, SWT.NONE);
fComposite = colorComposite;
GridLayout layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
colorComposite.setLayout(layout);
Link link= new Link(colorComposite, SWT.NONE);
link.setText(PreferencesMessages.RubyEditorColoringConfigurationBlock_link);
link.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
PreferencesUtil.createPreferenceDialogOn(parent.getShell(), e.text, null, null);
}
});
// TODO replace by link-specific tooltips when
// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=88866 gets fixed
// link.setToolTipText(PreferencesMessages.RubyEditorColoringConfigurationBlock_link_tooltip);
GridData gridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false);
gridData.widthHint= 150; // only expand further if anyone else requires it
gridData.horizontalSpan= 2;
link.setLayoutData(gridData);
addFiller(colorComposite, 1);
final Composite group= createComposite(colorComposite, 4);
final GridData groupData= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
groupData.horizontalSpan= 4;
group.setLayoutData(groupData);
fLoadButton= createButton(group, "Import", GridData.HORIZONTAL_ALIGN_END);
fSaveButton= createButton(group, "Export", GridData.HORIZONTAL_ALIGN_END);
new ButtonController();
Label label;
label= new Label(colorComposite, SWT.LEFT);
label.setText(PreferencesMessages.RubyEditorPreferencePage_coloring_element);
label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Composite editorComposite= new Composite(colorComposite, SWT.NONE);
layout= new GridLayout();
layout.numColumns= 2;
layout.marginHeight= 0;
layout.marginWidth= 0;
editorComposite.setLayout(layout);
GridData gd= new GridData(SWT.FILL, SWT.BEGINNING, true, false);
editorComposite.setLayoutData(gd);
fListViewer= new TreeViewer(editorComposite, SWT.SINGLE | SWT.BORDER);
fListViewer.setLabelProvider(new ColorListLabelProvider());
fListViewer.setContentProvider(new ColorListContentProvider());
fListViewer.setSorter(new ViewerSorter() {
public int category(Object element) {
// don't sort the top level categories
if (fRubyCategory.equals(element))
return 0;
// to sort semantic settings after partition based ones:
// if (element instanceof SemanticHighlightingColorListItem)
// return 1;
return 0;
}
});
gd= new GridData(SWT.BEGINNING, SWT.BEGINNING, false, true);
gd.heightHint= convertHeightInCharsToPixels(9);
int maxWidth= 0;
for (Iterator it= fListModel.iterator(); it.hasNext();) {
HighlightingColorListItem item= (HighlightingColorListItem) it.next();
maxWidth= Math.max(maxWidth, convertWidthInCharsToPixels(item.getDisplayName().length()));
}
ScrollBar vBar= ((Scrollable) fListViewer.getControl()).getVerticalBar();
if (vBar != null)
maxWidth += vBar.getSize().x * 3; // scrollbars and tree indentation guess
gd.widthHint= maxWidth;
fListViewer.getControl().setLayoutData(gd);
Composite stylesComposite= new Composite(editorComposite, SWT.NONE);
layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
layout.numColumns= 2;
stylesComposite.setLayout(layout);
stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
fEnableCheckbox= new Button(stylesComposite, SWT.CHECK);
fEnableCheckbox.setText(PreferencesMessages.RubyEditorPreferencePage_enable);
gd= new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalAlignment= GridData.BEGINNING;
gd.horizontalSpan= 2;
fEnableCheckbox.setLayoutData(gd);
fColorEditorLabel= new Label(stylesComposite, SWT.LEFT);
fColorEditorLabel.setText(PreferencesMessages.RubyEditorPreferencePage_color);
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalIndent= 20;
fColorEditorLabel.setLayoutData(gd);
fSyntaxForegroundColorEditor= new ColorSelector(stylesComposite);
Button foregroundColorButton= fSyntaxForegroundColorEditor.getButton();
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
foregroundColorButton.setLayoutData(gd);
// Background color
// TODO Create an enable/system default checkbox for background
fEnableBackgroundCheckbox= new Button(stylesComposite, SWT.CHECK | SWT.LEFT);
fEnableBackgroundCheckbox.setText(PreferencesMessages.RubyEditorPreferencePage_background_color);
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalIndent= 20;
fEnableBackgroundCheckbox.setLayoutData(gd);
fEnableBackgroundCheckbox.setEnabled(false);
fSyntaxBackgroundColorEditor= new ColorSelector(stylesComposite);
Button backgroundColorButton= fSyntaxBackgroundColorEditor.getButton();
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
backgroundColorButton.setLayoutData(gd);
fBoldCheckBox= new Button(stylesComposite, SWT.CHECK);
fBoldCheckBox.setText(PreferencesMessages.RubyEditorPreferencePage_bold);
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalIndent= 20;
gd.horizontalSpan= 2;
fBoldCheckBox.setLayoutData(gd);
fItalicCheckBox= new Button(stylesComposite, SWT.CHECK);
fItalicCheckBox.setText(PreferencesMessages.RubyEditorPreferencePage_italic);
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalIndent= 20;
gd.horizontalSpan= 2;
fItalicCheckBox.setLayoutData(gd);
fStrikethroughCheckBox= new Button(stylesComposite, SWT.CHECK);
fStrikethroughCheckBox.setText(PreferencesMessages.RubyEditorPreferencePage_strikethrough);
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalIndent= 20;
gd.horizontalSpan= 2;
fStrikethroughCheckBox.setLayoutData(gd);
fUnderlineCheckBox= new Button(stylesComposite, SWT.CHECK);
fUnderlineCheckBox.setText(PreferencesMessages.RubyEditorPreferencePage_underline);
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalIndent= 20;
gd.horizontalSpan= 2;
fUnderlineCheckBox.setLayoutData(gd);
label= new Label(colorComposite, SWT.LEFT);
label.setText(PreferencesMessages.RubyEditorPreferencePage_preview);
label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Control previewer= createPreviewer(colorComposite);
gd= new GridData(GridData.FILL_BOTH);
gd.widthHint= convertWidthInCharsToPixels(20);
gd.heightHint= convertHeightInCharsToPixels(5);
previewer.setLayoutData(gd);
fListViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
handleSyntaxColorListSelection();
}
});
foregroundColorButton.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
// do nothing
}
public void widgetSelected(SelectionEvent e) {
HighlightingColorListItem item= getHighlightingColorListItem();
PreferenceConverter.setValue(getPreferenceStore(), item.getColorKey(), fSyntaxForegroundColorEditor.getColorValue());
}
});
backgroundColorButton.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
// do nothing
}
public void widgetSelected(SelectionEvent e) {
HighlightingColorListItem item= getHighlightingColorListItem();
PreferenceConverter.setValue(getPreferenceStore(), item.getBackgroundKey(), fSyntaxBackgroundColorEditor.getColorValue());
}
});
fBoldCheckBox.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
// do nothing
}
public void widgetSelected(SelectionEvent e) {
HighlightingColorListItem item= getHighlightingColorListItem();
getPreferenceStore().setValue(item.getBoldKey(), fBoldCheckBox.getSelection());
}
});
fItalicCheckBox.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
// do nothing
}
public void widgetSelected(SelectionEvent e) {
HighlightingColorListItem item= getHighlightingColorListItem();
getPreferenceStore().setValue(item.getItalicKey(), fItalicCheckBox.getSelection());
}
});
fStrikethroughCheckBox.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
// do nothing
}
public void widgetSelected(SelectionEvent e) {
HighlightingColorListItem item= getHighlightingColorListItem();
getPreferenceStore().setValue(item.getStrikethroughKey(), fStrikethroughCheckBox.getSelection());
}
});
fUnderlineCheckBox.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
// do nothing
}
public void widgetSelected(SelectionEvent e) {
HighlightingColorListItem item= getHighlightingColorListItem();
getPreferenceStore().setValue(item.getUnderlineKey(), fUnderlineCheckBox.getSelection());
}
});
fEnableCheckbox.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
// do nothing
}
public void widgetSelected(SelectionEvent e) {
HighlightingColorListItem item= getHighlightingColorListItem();
if (item instanceof SemanticHighlightingColorListItem) {
boolean enable= fEnableCheckbox.getSelection();
getPreferenceStore().setValue(((SemanticHighlightingColorListItem) item).getEnableKey(), enable);
fEnableCheckbox.setSelection(enable);
fEnableBackgroundCheckbox.setEnabled(enable);
fSyntaxForegroundColorEditor.getButton().setEnabled(enable);
fSyntaxBackgroundColorEditor.getButton().setEnabled(enable);
fColorEditorLabel.setEnabled(enable);
fBoldCheckBox.setEnabled(enable);
fItalicCheckBox.setEnabled(enable);
fStrikethroughCheckBox.setEnabled(enable);
fUnderlineCheckBox.setEnabled(enable);
}
}
});
fEnableBackgroundCheckbox.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
HighlightingColorListItem item= getHighlightingColorListItem();
boolean enable= fEnableBackgroundCheckbox.getSelection();
getPreferenceStore().setValue(item.getBackgroundEnabledKey(), enable);
fSyntaxBackgroundColorEditor.getButton().setEnabled(enable);
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
colorComposite.layout(false);
return colorComposite;
}
private Composite createComposite(Composite parent, int numColumns) {
final Composite composite = new Composite(parent, SWT.NONE);
composite.setFont(parent.getFont());
final GridLayout layout = new GridLayout(numColumns, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
composite.setLayout(layout);
return composite;
}
private static Button createButton(Composite composite, String text, final int style) {
final Button button= new Button(composite, SWT.PUSH);
button.setFont(composite.getFont());
button.setText(text);
final GridData gd= new GridData(style);
gd.widthHint= SWTUtil.getButtonWidthHint(button);
button.setLayoutData(gd);
return button;
}
private void addFiller(Composite composite, int horizontalSpan) {
PixelConverter pixelConverter= new PixelConverter(composite);
Label filler= new Label(composite, SWT.LEFT );
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= horizontalSpan;
gd.heightHint= pixelConverter.convertHeightInCharsToPixels(1) / 2;
filler.setLayoutData(gd);
}
private Control createPreviewer(Composite parent) {
IPreferenceStore generalTextStore= EditorsUI.getPreferenceStore();
IPreferenceStore store= new ChainedPreferenceStore(new IPreferenceStore[] { getPreferenceStore(), new PreferencesAdapter(createTemporaryCorePreferenceStore()), generalTextStore });
fPreviewViewer= new RubySourceViewer(parent, null, null, false, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER, store);
SimpleRubySourceViewerConfiguration configuration= new SimpleRubySourceViewerConfiguration(fColorManager, store, null, IRubyPartitions.RUBY_PARTITIONING, false);
fPreviewViewer.configure(configuration);
Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT);
fPreviewViewer.getTextWidget().setFont(font);
new RubySourcePreviewerUpdater(fPreviewViewer, configuration, store);
fPreviewViewer.setEditable(false);
String content= loadPreviewContentFromFile("ColorSettingPreviewCode.txt"); //$NON-NLS-1$
IDocument document= new Document(content);
RubyPlugin.getDefault().getRubyTextTools().setupRubyDocumentPartitioner(document, IRubyPartitions.RUBY_PARTITIONING);
fPreviewViewer.setDocument(document);
return fPreviewViewer.getControl();
}
private Preferences createTemporaryCorePreferenceStore() {
Preferences result= new Preferences();
result.setValue(COMPILER_TASK_TAGS, "TASK,TODO"); //$NON-NLS-1$
return result;
}
private String loadPreviewContentFromFile(String filename) {
String line;
String separator= System.getProperty("line.separator"); //$NON-NLS-1$
StringBuffer buffer= new StringBuffer(512);
BufferedReader reader= null;
try {
reader= new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(filename)));
while ((line= reader.readLine()) != null) {
buffer.append(line);
buffer.append(separator);
}
} catch (IOException io) {
RubyPlugin.log(io);
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException e) {}
}
}
return buffer.toString();
}
/**
* Returns the current highlighting color list item.
*
* @return the current highlighting color list item
* @since 3.0
*/
private HighlightingColorListItem getHighlightingColorListItem() {
IStructuredSelection selection= (IStructuredSelection) fListViewer.getSelection();
Object element= selection.getFirstElement();
if (element instanceof String)
return null;
return (HighlightingColorListItem) element;
}
/**
* Initializes the computation of horizontal and vertical dialog units based
* on the size of current font.
* <p>
* This method must be called before any of the dialog unit based conversion
* methods are called.
* </p>
*
* @param testControl
* a control from which to obtain the current font
*/
private void initializeDialogUnits(Control testControl) {
// Compute and store a font metric
GC gc = new GC(testControl);
gc.setFont(JFaceResources.getDialogFont());
fFontMetrics = gc.getFontMetrics();
gc.dispose();
}
private class ButtonController implements SelectionListener {
public ButtonController() {
fLoadButton.addSelectionListener(this);
fSaveButton.addSelectionListener(this);
}
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
final Button button= (Button)e.widget;
if (button == fSaveButton)
saveButtonPressed();
else if (button == fLoadButton)
loadButtonPressed();
}
private void loadButtonPressed() {
final FileDialog dialog= new FileDialog(fComposite.getShell(), SWT.OPEN);
dialog.setText("Load Profile");
dialog.setFilterExtensions(new String [] {"*.xml"}); //$NON-NLS-1$
final String lastPath= RubyPlugin.getDefault().getDialogSettings().get(DIALOGSTORE_LASTLOADPATH);
if (lastPath != null) {
dialog.setFilterPath(lastPath);
}
final String path= dialog.open();
if (path == null)
return;
RubyPlugin.getDefault().getDialogSettings().put(DIALOGSTORE_LASTLOADPATH, dialog.getFilterPath());
final File file= new File(path);
Map<String, String> profiles= null;
try {
profiles= SyntaxColoringStore.readFromFile(file);
} catch (CoreException e) {
final String title= "Import Profile";
final String message= "Could not import the profile";
ExceptionHandler.handle(e, fComposite.getShell(), title, message);
}
if (profiles == null || profiles.isEmpty())
return;
// apply the colors to the current settings
for (String key : profiles.keySet()) {
getPreferenceStore().setValue(key, profiles.get(key));
}
performDefaults();
}
private void saveButtonPressed() {
final FileDialog dialog= new FileDialog(fComposite.getShell(), SWT.SAVE);
dialog.setText("Export profile");
dialog.setFilterExtensions(new String [] {"*.xml"}); //$NON-NLS-1$
final String lastPath= RubyPlugin.getDefault().getDialogSettings().get(DIALOGSTORE_LASTSAVEPATH);
if (lastPath != null) {
dialog.setFilterPath(lastPath);
}
final String path= dialog.open();
if (path == null)
return;
RubyPlugin.getDefault().getDialogSettings().put(DIALOGSTORE_LASTSAVEPATH, dialog.getFilterPath());
final File file= new File(path);
if (file.exists() && !MessageDialog.openQuestion(fComposite.getShell(), "Export profile", Messages.format("{0} already exists. Do you want to replace it?", path))) {
return;
}
try{
SyntaxColoringStore.write(fListModel, file);
} catch (CoreException e) {
final String title= "Export Profile";
final String message= "Could not export the profiles.";
ExceptionHandler.handle(e, fComposite.getShell(), title, message);
}
}
}
}