/** * <copyright> * </copyright> * * */ package org.dresdenocl.language.ocl.resource.ocl.ui; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.jface.preference.ColorSelector; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.preference.PreferencePage; 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.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; 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.Label; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.Scrollable; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; /** * <p> * Preference page for configuring syntax coloring. * </p> * <p> * <p><i>Parts of the code were taken from the JDT Java Editor</i> * </p> */ public class OclSyntaxColoringPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { private final static Map<String, List<HighlightingColorListItem>> content = new LinkedHashMap<String, List<HighlightingColorListItem>>(); private final static Collection<IChangedPreference> changedPreferences = new ArrayList<IChangedPreference>(); public OclSyntaxColoringPreferencePage() { super(); org.dresdenocl.language.ocl.resource.ocl.mopp.OclMetaInformation metaInformation = new org.dresdenocl.language.ocl.resource.ocl.mopp.OclMetaInformation(); String languageId = metaInformation.getSyntaxName(); List<HighlightingColorListItem> terminals = new ArrayList<HighlightingColorListItem>(); String[] tokenNames = metaInformation.getSyntaxHighlightableTokenNames(); for (int i = 0; i < tokenNames.length; i++) { HighlightingColorListItem item = new HighlightingColorListItem(languageId, tokenNames[i]); terminals.add(item); } Collections.sort(terminals); content.put(languageId, terminals); setPreferenceStore(org.dresdenocl.language.ocl.resource.ocl.ui.OclUIPlugin.getDefault().getPreferenceStore()); setDescription("Configure syntax coloring for ." + languageId + " files."); } private interface IChangedPreference { public void apply(IPreferenceStore store); } private abstract static class AbstractChangedPreference implements IChangedPreference { private String key; public AbstractChangedPreference(String key) { super(); this.key = key; } public String getKey() { return key; } } private static class ChangedBooleanPreference extends AbstractChangedPreference { private boolean newValue; public ChangedBooleanPreference(String key, boolean newValue) { super(key); this.newValue = newValue; } public void apply(IPreferenceStore store) { store.setValue(getKey(), newValue); } } private static class ChangedRGBPreference extends AbstractChangedPreference { private RGB newValue; public ChangedRGBPreference(String key, RGB newValue) { super(key); this.newValue = newValue; } public void apply(IPreferenceStore store) { PreferenceConverter.setValue(store, getKey(), newValue); } } /** * Item in the highlighting color list. */ private static class HighlightingColorListItem implements Comparable<HighlightingColorListItem> { /** * Display name */ private String fDisplayName; /** * Color preference key */ private String fColorKey; /** * Bold preference key */ private String fBoldKey; /** * Italic preference key */ private String fItalicKey; /** * Strikethrough preference key. */ private String fStrikethroughKey; /** * Underline preference key. */ private String fUnderlineKey; private String fEnableKey; /** * Initializes a new item with the given values. */ public HighlightingColorListItem(String languageID, String tokenName) { fDisplayName = tokenName; fColorKey = org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.getPreferenceKey(languageID, tokenName, org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.StyleProperty.COLOR); fBoldKey = org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.getPreferenceKey(languageID, tokenName, org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.StyleProperty.BOLD); fItalicKey = org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.getPreferenceKey(languageID, tokenName, org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.StyleProperty.ITALIC); fStrikethroughKey = org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.getPreferenceKey(languageID, tokenName, org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.StyleProperty.STRIKETHROUGH); fUnderlineKey = org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.getPreferenceKey(languageID, tokenName, org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.StyleProperty.UNDERLINE); fEnableKey = org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.getPreferenceKey(languageID, tokenName, org.dresdenocl.language.ocl.resource.ocl.ui.OclSyntaxColoringHelper.StyleProperty.ENABLE); } /** * * @return the bold preference key */ public String getBoldKey() { return fBoldKey; } /** * * @return the italic preference key */ public String getItalicKey() { return fItalicKey; } /** * * @return the strikethrough preference key */ public String getStrikethroughKey() { return fStrikethroughKey; } /** * * @return the underline preference key */ 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 getEnableKey() { return fEnableKey; } public int compareTo(HighlightingColorListItem o) { return fDisplayName.compareTo(o.getDisplayName()); } } /** * Color list label provider. */ private class ColorListLabelProvider extends LabelProvider { public String getText(Object element) { if (element instanceof String) { return (String) element; } String displayName = ((HighlightingColorListItem) element).getDisplayName(); if (displayName.startsWith("QUOTED_")) { String[] parts = displayName.split("_"); if (parts.length == 3) { if (parts[1].length() == 2 && parts[2].length() == 2) { // Convert decimal ascii codes to string try { char prefix = (char) Integer.parseInt(parts[1]); char suffix = (char) Integer.parseInt(parts[2]); displayName = prefix + "..." + suffix; } catch (NumberFormatException nfe) { // ignore } } } } return displayName; } } /** * Color list content provider. */ private class ColorListContentProvider implements ITreeContentProvider { public ColorListContentProvider() { super(); } public Object[] getElements(Object inputElement) { List<HighlightingColorListItem> contentsList = new ArrayList<HighlightingColorListItem>(); for (List<HighlightingColorListItem> l : content.values()) { contentsList.addAll(l); } return contentsList.toArray(); } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } public Object[] getChildren(Object parentElement) { return new Object[0]; } public Object getParent(Object element) { return null; } public boolean hasChildren(Object element) { return false; } } private ColorSelector fSyntaxForegroundColorEditor; private Label fColorEditorLabel; private Button fBoldCheckBox; private Button fEnableCheckbox; /** * Check box for italic preference. */ private Button fItalicCheckBox; /** * Check box for strikethrough preference. */ private Button fStrikethroughCheckBox; /** * Check box for underline preference. */ private Button fUnderlineCheckBox; private Button fForegroundColorButton; /** * Highlighting color list viewer */ private StructuredViewer fListViewer; public void dispose() { super.dispose(); } private void handleSyntaxColorListSelection() { HighlightingColorListItem item = getHighlightingColorListItem(); if (item == null) { fEnableCheckbox.setEnabled(false); fSyntaxForegroundColorEditor.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); fBoldCheckBox.setSelection(getPreferenceStore().getBoolean(item.getBoldKey())); fItalicCheckBox.setSelection(getPreferenceStore().getBoolean(item.getItalicKey())); fStrikethroughCheckBox.setSelection(getPreferenceStore().getBoolean(item.getStrikethroughKey())); fUnderlineCheckBox.setSelection(getPreferenceStore().getBoolean(item.getUnderlineKey())); fEnableCheckbox.setEnabled(true); boolean enable = getPreferenceStore().getBoolean(item.getEnableKey()); fEnableCheckbox.setSelection(enable); fSyntaxForegroundColorEditor.getButton().setEnabled(enable); fColorEditorLabel.setEnabled(enable); fBoldCheckBox.setEnabled(enable); fItalicCheckBox.setEnabled(enable); fStrikethroughCheckBox.setEnabled(enable); fUnderlineCheckBox.setEnabled(enable); } private Control createSyntaxPage(final Composite parent) { Composite colorComposite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; colorComposite.setLayout(layout); addFiller(colorComposite, 1); Label label = new Label(colorComposite, SWT.LEFT); label.setText("Element:"); label.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false)); Composite editorComposite = createEditorComposite(colorComposite); createListViewer(editorComposite); createStylesComposite(editorComposite); addListenersToStyleButtons(); colorComposite.layout(false); handleSyntaxColorListSelection(); return colorComposite; } private Composite createEditorComposite(Composite colorComposite) { GridLayout layout; 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(GridData.FILL, GridData.FILL, true, true); editorComposite.setLayoutData(gd); return editorComposite; } private void createListViewer(Composite editorComposite) { fListViewer = new TreeViewer(editorComposite, SWT.SINGLE | SWT.BORDER); fListViewer.setLabelProvider(new ColorListLabelProvider()); fListViewer.setContentProvider(new ColorListContentProvider()); GridData gd = new GridData(GridData.FILL, GridData.FILL, true, true); gd.heightHint = convertHeightInCharsToPixels(26); int maxWidth = 0; for (Iterator<List<HighlightingColorListItem>> it = content.values().iterator(); it.hasNext();) { for (Iterator<HighlightingColorListItem> j = it.next().iterator(); j.hasNext();) { HighlightingColorListItem item = j.next(); maxWidth = Math.max(maxWidth, convertWidthInCharsToPixels(item.getDisplayName().length())); } } ScrollBar vBar = ((Scrollable) fListViewer.getControl()).getVerticalBar(); if (vBar != null) { // scrollbars and tree indentation guess maxWidth += vBar.getSize().x * 3; } gd.widthHint = maxWidth; fListViewer.getControl().setLayoutData(gd); fListViewer.setInput(content); fListViewer.setSelection(new StructuredSelection(content.values().iterator().next())); fListViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { handleSyntaxColorListSelection(); } }); } private void addListenersToStyleButtons() { fForegroundColorButton.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { // do nothing } public void widgetSelected(SelectionEvent e) { HighlightingColorListItem item = getHighlightingColorListItem(); changedPreferences.add(new ChangedRGBPreference(item.getColorKey(), fSyntaxForegroundColorEditor.getColorValue())); } }); fBoldCheckBox.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { // do nothing } public void widgetSelected(SelectionEvent e) { HighlightingColorListItem item = getHighlightingColorListItem(); changedPreferences.add(new ChangedBooleanPreference(item.getBoldKey(), fBoldCheckBox.getSelection())); } }); fItalicCheckBox.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { // do nothing } public void widgetSelected(SelectionEvent e) { HighlightingColorListItem item = getHighlightingColorListItem(); changedPreferences.add(new ChangedBooleanPreference(item.getItalicKey(), fItalicCheckBox.getSelection())); } }); fStrikethroughCheckBox.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { // do nothing } public void widgetSelected(SelectionEvent e) { HighlightingColorListItem item = getHighlightingColorListItem(); changedPreferences.add(new ChangedBooleanPreference(item.getStrikethroughKey(), fStrikethroughCheckBox.getSelection())); } }); fUnderlineCheckBox.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { // do nothing } public void widgetSelected(SelectionEvent e) { HighlightingColorListItem item = getHighlightingColorListItem(); changedPreferences.add(new ChangedBooleanPreference(item.getUnderlineKey(), fUnderlineCheckBox.getSelection())); } }); fEnableCheckbox.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { // do nothing } public void widgetSelected(SelectionEvent e) { HighlightingColorListItem item = getHighlightingColorListItem(); boolean enable = fEnableCheckbox.getSelection(); changedPreferences.add(new ChangedBooleanPreference(item.getEnableKey(), enable)); fEnableCheckbox.setSelection(enable); fSyntaxForegroundColorEditor.getButton().setEnabled(enable); fColorEditorLabel.setEnabled(enable); fBoldCheckBox.setEnabled(enable); fItalicCheckBox.setEnabled(enable); fStrikethroughCheckBox.setEnabled(enable); fUnderlineCheckBox.setEnabled(enable); // uninstallSemanticHighlighting(); // installSemanticHighlighting(); } }); } private void createStylesComposite(Composite editorComposite) { GridLayout layout; GridData 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.END, GridData.FILL, false, true)); fEnableCheckbox = new Button(stylesComposite, SWT.CHECK); fEnableCheckbox.setText("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("Color:"); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalIndent = 20; fColorEditorLabel.setLayoutData(gd); fSyntaxForegroundColorEditor = new ColorSelector(stylesComposite); fForegroundColorButton = fSyntaxForegroundColorEditor.getButton(); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); fForegroundColorButton.setLayoutData(gd); fBoldCheckBox = new Button(stylesComposite, SWT.CHECK); fBoldCheckBox.setText("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("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("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("Underlined"); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalIndent = 20; gd.horizontalSpan = 2; fUnderlineCheckBox.setLayoutData(gd); } private void addFiller(Composite composite, int horizontalSpan) { org.dresdenocl.language.ocl.resource.ocl.ui.OclPixelConverter pixelConverter = new org.dresdenocl.language.ocl.resource.ocl.ui.OclPixelConverter(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); } /** * Returns the current highlighting color list item. */ private HighlightingColorListItem getHighlightingColorListItem() { IStructuredSelection selection = (IStructuredSelection) fListViewer.getSelection(); Object element = selection.getFirstElement(); if (element instanceof String) { return null; } return (HighlightingColorListItem) element; } public void init(IWorkbench workbench) { } protected Control createContents(Composite parent) { Control content = createSyntaxPage(parent); return content; } public boolean performOk() { if (!super.performOk()) { return false; } performApply(); return true; } public boolean performCancel() { if (!super.performCancel()) { return false; } // discard all changes that were made changedPreferences.clear(); return true; } protected void performApply() { for (IChangedPreference changedPreference : changedPreferences) { changedPreference.apply(getPreferenceStore()); } changedPreferences.clear(); updateActiveEditor(); } public void performDefaults() { super.performDefaults(); IPreferenceStore preferenceStore = getPreferenceStore(); // reset all preferences to their default values for (String languageID : content.keySet()) { List<HighlightingColorListItem> items = content.get(languageID); for (HighlightingColorListItem item : items) { restoreDefaultBooleanValue(preferenceStore, item.getBoldKey()); restoreDefaultBooleanValue(preferenceStore, item.getEnableKey()); restoreDefaultBooleanValue(preferenceStore, item.getItalicKey()); restoreDefaultBooleanValue(preferenceStore, item.getStrikethroughKey()); restoreDefaultBooleanValue(preferenceStore, item.getUnderlineKey()); restoreDefaultStringValue(preferenceStore, item.getColorKey()); } } handleSyntaxColorListSelection(); updateActiveEditor(); } private void restoreDefaultBooleanValue(IPreferenceStore preferenceStore, String key) { preferenceStore.setValue(key, preferenceStore.getDefaultBoolean(key)); } private void restoreDefaultStringValue(IPreferenceStore preferenceStore, String key) { preferenceStore.setValue(key, preferenceStore.getDefaultString(key)); } private void updateActiveEditor() { IWorkbench workbench = org.eclipse.ui.PlatformUI.getWorkbench(); IEditorPart editor = workbench.getActiveWorkbenchWindow().getActivePage().getActiveEditor(); if (editor != null && editor instanceof org.dresdenocl.language.ocl.resource.ocl.ui.OclEditor) { org.dresdenocl.language.ocl.resource.ocl.ui.OclEditor emfTextEditor = (org.dresdenocl.language.ocl.resource.ocl.ui.OclEditor) editor; emfTextEditor.invalidateTextRepresentation(); } } }