diff --git a/net.certiv.tools.indentguide.plugin/plugin.xml b/net.certiv.tools.indentguide.plugin/plugin.xml index a6e632a..492a0b7 100644 --- a/net.certiv.tools.indentguide.plugin/plugin.xml +++ b/net.certiv.tools.indentguide.plugin/plugin.xml @@ -5,8 +5,8 @@ point="org.eclipse.ui.preferencePages"> diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/Activator.java b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/Activator.java index 33c14be..ab66613 100644 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/Activator.java +++ b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/Activator.java @@ -25,7 +25,7 @@ import org.eclipse.ui.themes.ColorUtil; import org.osgi.framework.BundleContext; -import net.certiv.tools.indentguide.preferences.Settings; +import net.certiv.tools.indentguide.preferences.Pref; public class Activator extends AbstractUIPlugin { @@ -36,7 +36,9 @@ public class Activator extends AbstractUIPlugin { private static Activator plugin; private final IEclipsePreferences[] editorScopes = new IEclipsePreferences[] { - InstanceScope.INSTANCE.getNode(EditorsID), DefaultScope.INSTANCE.getNode(EditorsID) }; + InstanceScope.INSTANCE.getNode(EditorsID), // + DefaultScope.INSTANCE.getNode(EditorsID) // + }; private final IPropertyChangeListener themeChange = event -> { disposeLineColor(); @@ -74,9 +76,9 @@ public void stop(BundleContext context) throws Exception { public Color getColor() { if (color == null) { - String key = Settings.LINE_COLOR; + String key = Pref.LINE_COLOR; if (isDarkTheme()) { - key += Settings.DARK; + key += Pref.DARK; } String spec = getPreferenceStore().getString(key); color = new Color(PlatformUI.getWorkbench().getDisplay(), ColorUtil.getColorValue(spec)); diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/IndentGuidePainter.java b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/IndentGuidePainter.java index 98d3f67..a3a59f2 100644 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/IndentGuidePainter.java +++ b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/IndentGuidePainter.java @@ -28,7 +28,7 @@ import org.eclipse.swt.graphics.LineAttributes; import org.eclipse.swt.graphics.Point; -import net.certiv.tools.indentguide.preferences.Settings; +import net.certiv.tools.indentguide.preferences.Pref; /** * A painter for drawing visible indent guide lines. @@ -57,10 +57,10 @@ public class IndentGuidePainter implements IPainter, PaintListener { private int lineShift; private boolean drawLeftEnd; private boolean drawBlankLine; - private boolean skipCommentBlock; + private boolean drawCommentBlock; private final IPropertyChangeListener propertyWatcher = event -> { - if (event.getProperty().startsWith(Settings.KEY)) { + if (event.getProperty().startsWith(Pref.KEY)) { update(); redrawAll(); } @@ -117,8 +117,7 @@ public void paint(int reason) { if (widgetOffset >= 0 && redrawLength > 0) { widget.redrawRange(widgetOffset, redrawLength, true); } - } - catch (BadLocationException e) {} + } catch (BadLocationException e) {} } } @@ -142,13 +141,13 @@ public void paintControl(PaintEvent event) { } private void update() { - lineAlpha = store.getInt(Settings.LINE_ALPHA); - lineStyle = store.getInt(Settings.LINE_STYLE); - lineWidth = store.getInt(Settings.LINE_WIDTH); - lineShift = store.getInt(Settings.LINE_SHIFT); - drawLeftEnd = store.getBoolean(Settings.DRAW_LEFT_END); - drawBlankLine = store.getBoolean(Settings.DRAW_BLANK_LINE); - skipCommentBlock = store.getBoolean(Settings.SKIP_COMMENT_BLOCK); + lineAlpha = store.getInt(Pref.LINE_ALPHA); + lineStyle = store.getInt(Pref.LINE_STYLE); + lineWidth = store.getInt(Pref.LINE_WIDTH); + lineShift = store.getInt(Pref.LINE_SHIFT); + drawLeftEnd = store.getBoolean(Pref.DRAW_LEFT_EDGE); + drawBlankLine = store.getBoolean(Pref.DRAW_BLANK_LINE); + drawCommentBlock = store.getBoolean(Pref.DRAW_COMMENT_BLOCK); } // Draw characters in view range. @@ -195,7 +194,7 @@ private void drawLineRange(GC gc, int begLine, int endLine, int x, int w) { if (!isFoldedLine(content.getLineAtOffset(offset))) { String text = widget.getLine(line); int extend = 0; - if (skipCommentBlock && assumeCommentBlock(text, tabWidth)) { + if (!drawCommentBlock && assumeCommentBlock(text, tabWidth)) { extend -= tabWidth; } if (drawBlankLine && text.trim().length() == 0) { diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/Starter.java b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/Starter.java index 227be7c..04685f7 100644 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/Starter.java +++ b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/Starter.java @@ -43,9 +43,9 @@ import net.certiv.tools.indentguide.adaptors.PartAdaptor; import net.certiv.tools.indentguide.adaptors.WindowAdaptor; -import net.certiv.tools.indentguide.preferences.Settings; -import net.certiv.tools.indentguide.util.Prefs; +import net.certiv.tools.indentguide.preferences.Pref; import net.certiv.tools.indentguide.util.Utils; +import net.certiv.tools.indentguide.util.Utils.Delta; public class Starter implements IStartup { @@ -58,7 +58,8 @@ public class Starter implements IStartup { private static final String SOURCE_VIEWER = "getSourceViewer"; // $NON-NLS-1$ private IPreferenceStore store; - private Set contentTypes; + // excluded content types + private Set excludedTypeIds; // row=window; col=page/editor; val=painter private HashMap> paintMap = new HashMap<>(); @@ -92,7 +93,7 @@ private void initWorkbenchWindow(IWorkbenchWindow window) { IWorkbenchPage page = window.getActivePage(); if (page != null) { IWorkbenchPart part = page.getActivePart(); - Activator.log("workbench page '%s'", name(part)); + Activator.log("workbench page [%s]", name(part)); if (part instanceof MultiPageEditorPart) { IEditorPart editor = activeEditor((MultiPageEditorPart) part); @@ -108,8 +109,8 @@ private void initWorkbenchWindow(IWorkbenchWindow window) { } private void installPainter(IEditorPart part, IWorkbenchPart window) { - if (!store.getBoolean(Settings.ENABLED)) return; - Activator.log("inspecting editor '%s'", name(part)); + if (!store.getBoolean(Pref.ENABLED)) return; + Activator.log("inspecting editor [%s]", name(part)); if (part instanceof AbstractTextEditor) { AbstractTextEditor editor = (AbstractTextEditor) part; @@ -175,7 +176,7 @@ private boolean validType(AbstractTextEditor editor) { Activator.log("painter disallowed for '%s' [%s]", srcname, UNKNOWN); return false; } - if (contentTypes.contains(type.getId())) { + if (!excludedTypeIds.contains(type.getId())) { Activator.log("installing painter on '%s' [%s]", srcname, type.getName()); return true; } @@ -185,7 +186,7 @@ private boolean validType(AbstractTextEditor editor) { } private void updateContentTypes() { - contentTypes = Prefs.asLinkedSet(store.getString(Settings.CONTENT_TYPES)); + excludedTypeIds = Utils.undelimit(store.getString(Pref.CONTENT_TYPES)); } private String name(IWorkbenchPart part) { @@ -249,19 +250,16 @@ private class StoreWatcher implements IPropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { - if (evt.getProperty().startsWith(Settings.KEY)) { + if (evt.getProperty().startsWith(Pref.KEY)) { String property = evt.getProperty(); Object old = evt.getOldValue(); Object now = evt.getNewValue(); - if (property.equals(Settings.CONTENT_TYPES)) { + if (property.equals(Pref.CONTENT_TYPES)) { updateContentTypes(); - Set prev = Prefs.asLinkedSet((String) old); - Set pres = Prefs.asLinkedSet((String) now); - Set rmved = Utils.subtract(prev, pres); - Set added = Utils.subtract(pres, prev); - if (!rmved.isEmpty()) Activator.log("property change '%s' removed %s", property, rmved); - if (!added.isEmpty()) Activator.log("property change '%s' added %s", property, added); + Delta delta = Utils.delta(Utils.undelimit((String) old), Utils.undelimit((String) now)); + if (!delta.rmved.isEmpty()) Activator.log("property change '%s' removed %s", property, delta.rmved); + if (!delta.added.isEmpty()) Activator.log("property change '%s' added %s", property, delta.added); } else { Activator.log("property change '%s' [%s] => [%s]", property, old, now); diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/SettingsPage.java b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/GuidePage.java similarity index 61% rename from net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/SettingsPage.java rename to net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/GuidePage.java index c0426bf..85a55c0 100644 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/SettingsPage.java +++ b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/GuidePage.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.content.IContentType; @@ -36,40 +37,46 @@ import org.eclipse.ui.IWorkbenchPreferencePage; import net.certiv.tools.indentguide.Activator; -import net.certiv.tools.indentguide.util.Prefs; import net.certiv.tools.indentguide.util.Utils; +import net.certiv.tools.indentguide.util.Utils.Delta; -public class SettingsPage extends PreferencePage implements IWorkbenchPreferencePage { +public class GuidePage extends PreferencePage implements IWorkbenchPreferencePage { - private static final String[] STYLES = { Messages.Guide_style_solid, Messages.Guide_style_dash, - Messages.Guide_style_dot, Messages.Guide_style_dash_dot, Messages.Guide_style_dash_dot_dot }; + private static final String[] STYLES = { Messages.style_solid, Messages.style_dash, Messages.style_dot, + Messages.style_dash_dot, Messages.style_dash_dot_dot }; private final List blocks = new LinkedList<>(); private final List parts = new LinkedList<>(); + private final IContentTypeManager mgr; + // platform 'text' content type - private IContentType txtType; + private final IContentType txtType; - // initial or last OKd content type ids - private Set current; + // explicitly excluded content types; current as of plugin startup or last OKd values + private Set excludeTypes; - public SettingsPage() { + public GuidePage() { setPreferenceStore(Activator.getDefault().getPreferenceStore()); + + mgr = Platform.getContentTypeManager(); + txtType = mgr.getContentType(IContentTypeManager.CT_TEXT); + + Set exclude = Utils.undelimit(getPreferenceStore().getString(Pref.CONTENT_TYPES)); + excludeTypes = exclude.stream().map(e -> mgr.getContentType(e)).filter(t -> !t.equals(txtType)) + .collect(Collectors.toCollection(LinkedHashSet::new)); } @Override - public void init(IWorkbench workbench) { - txtType = Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT); - current = Prefs.asLinkedSet(getPreferenceStore().getString(Settings.CONTENT_TYPES)); - } + public void init(IWorkbench workbench) {} @Override protected Control createContents(Composite parent) { initializeDialogUnits(parent); Composite comp = new Composite(parent, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(comp); GridLayoutFactory.fillDefaults().applyTo(comp); - applyDialogFont(comp); createEnabledCheckBox(comp); @@ -77,11 +84,12 @@ protected Control createContents(Composite parent) { createDrawingGroup(comp); createContentTypesGroup(comp); + applyDialogFont(comp); return comp; } private void createEnabledCheckBox(Composite comp) { - Button btn = createLabeledCheckbox(comp, Messages.Guide_enabled_label, Settings.ENABLED); + Button btn = createLabeledCheckbox(comp, Messages.enabled_label, Pref.ENABLED); btn.addSelectionListener(new SelectionAdapter() { @Override @@ -98,27 +106,27 @@ public void widgetSelected(final SelectionEvent e) { } private void createAttributeGroup(Composite parent) { - Composite comp = createGroup(parent, Messages.Guide_attribute_group_label, false, 2); + Composite comp = createGroup(parent, Messages.attribute_group_label, false, 3); blocks.add(comp); - createLabeledSpinner(comp, Messages.Guide_alpha_label, 0, 255, Settings.LINE_ALPHA); - createLabeledCombo(comp, Messages.Guide_style_label, STYLES, Settings.LINE_STYLE); - createLabeledSpinner(comp, Messages.Guide_width_label, 1, 8, Settings.LINE_WIDTH); - createLabeledSpinner(comp, Messages.Guide_shift_label, 0, 8, Settings.LINE_SHIFT); - createLabeledColorEditor(comp, Messages.Guide_color_label, colorKey()); + createLabeledSpinner(comp, Messages.alpha_label1, Messages.alpha_label2, 0, 255, Pref.LINE_ALPHA); + createLabeledCombo(comp, Messages.style_label1, Messages.style_label2, STYLES, Pref.LINE_STYLE); + createLabeledSpinner(comp, Messages.width_label1, Messages.width_label2, 1, 8, Pref.LINE_WIDTH); + createLabeledSpinner(comp, Messages.shift_label1, Messages.shift_label2, 0, 8, Pref.LINE_SHIFT); + createLabeledColorEditor(comp, Messages.color_label1, Messages.color_label2, colorKey()); } private void createDrawingGroup(Composite parent) { - Composite comp = createGroup(parent, Messages.Guide_drawing_group_label, false, 1); + Composite comp = createGroup(parent, Messages.drawing_group_label, false, 1); blocks.add(comp); - createLabeledCheckbox(comp, Messages.Guide_draw_left_end_label, Settings.DRAW_LEFT_END); - createLabeledCheckbox(comp, Messages.Guide_draw_blank_line_label, Settings.DRAW_BLANK_LINE); - createLabeledCheckbox(comp, Messages.Guide_skip_comment_block_label, Settings.SKIP_COMMENT_BLOCK); + createLabeledCheckbox(comp, Messages.draw_start_edge_label, Pref.DRAW_LEFT_EDGE); + createLabeledCheckbox(comp, Messages.draw_blank_line_label, Pref.DRAW_BLANK_LINE); + createLabeledCheckbox(comp, Messages.draw_comment_block_label, Pref.DRAW_COMMENT_BLOCK); } private void createContentTypesGroup(Composite parent) { - Composite comp = createGroup(parent, Messages.Guide_contenttype_group_label, true, 1); + Composite comp = createGroup(parent, Messages.contenttype_group_label, true, 1); blocks.add(comp); CheckboxTreeViewer viewer = new CheckboxTreeViewer(comp, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); @@ -136,44 +144,53 @@ private void createContentTypesGroup(Composite parent) { viewer.collapseAll(); viewer.expandToLevel(2); - TypesContentProvider provider = (TypesContentProvider) viewer.getContentProvider(); + // init all to checked + for (Object item : Utils.platformTextTypes()) { + viewer.setChecked(item, true); + viewer.setGrayed(item, false); + } + + // remove excluded + for (IContentType exType : excludeTypes) { + viewer.setChecked(exType, false); + updateCheckState(viewer, exType, false); + } + viewer.addCheckStateListener(evt -> { IContentType type = (IContentType) evt.getElement(); - updateCheckState(viewer, provider, type); - Activator.log("state change %s [%s]", type, viewer.getChecked(type)); + boolean state = viewer.getChecked(type); + updateCheckState(viewer, type, state); + Activator.log("state change %s [%s]", type, state); }); - - initCheckState(viewer, provider); } private Composite createGroup(Composite parent, String label, boolean vert, int cols) { Group group = new Group(parent, SWT.NONE); + group.setText(label); GridLayoutFactory.fillDefaults().applyTo(group); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, vert).applyTo(group); - group.setText(label); Composite comp = new Composite(group, SWT.NONE); - GridLayoutFactory.fillDefaults().numColumns(cols).margins(5, 5).applyTo(comp); + GridLayoutFactory.fillDefaults().numColumns(cols).equalWidth(false).margins(5, 5).applyTo(comp); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, vert).indent(5, 0).applyTo(comp); return comp; } - /** Creates a vertical spacer. */ private void createVerticalSpacer(Composite comp, int lines) { createVerticalSpacer(comp, lines, 1); } - /** Creates a vertical spacer. */ private void createVerticalSpacer(Composite comp, int lines, int span) { - Label lbl = new Label(comp, SWT.NONE); - int height = Prefs.lineHeight(comp, lines); - GridDataFactory.fillDefaults().hint(SWT.DEFAULT, height).grab(true, false).span(span, 1).applyTo(lbl); + Label spacer = new Label(comp, SWT.NONE); + int height = Utils.lineHeight(comp, lines); + GridDataFactory.fillDefaults().hint(SWT.DEFAULT, height).grab(true, false).span(span, 1).applyTo(spacer); } private Label createLabel(Composite comp, String text) { Label label = new Label(comp, SWT.NONE); label.setText(text); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).applyTo(label); return label; } @@ -182,182 +199,197 @@ private Button createLabeledCheckbox(Composite comp, String label, String key) { btn.setText(label); btn.setData(key); btn.setSelection(getPreferenceStore().getBoolean(key)); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).applyTo(btn); + parts.add(btn); return btn; } - private Combo createLabeledCombo(Composite comp, String label, String[] styles, String key) { + private Combo createLabeledCombo(Composite comp, String label, String trail, String[] styles, String key) { createLabel(comp, label); Combo combo = new Combo(comp, SWT.READ_ONLY); combo.setData(key); combo.setItems(styles); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).indent(9, 0).applyTo(combo); int idx = getPreferenceStore().getInt(key) - 1; idx = (idx >= 0 && idx < styles.length) ? idx : 0; combo.setText(styles[idx]); + createLabel(comp, trail); + parts.add(combo); return combo; } - private Spinner createLabeledSpinner(Composite comp, String label, int min, int max, String key) { + private Spinner createLabeledSpinner(Composite comp, String label, String trail, int min, int max, String key) { createLabel(comp, label); + Spinner spin = new Spinner(comp, SWT.BORDER); spin.setData(key); spin.setMinimum(min); spin.setMaximum(max); spin.setSelection(getPreferenceStore().getInt(key)); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).indent(9, 0).applyTo(spin); + + createLabel(comp, trail); + parts.add(spin); return spin; } - private void createLabeledColorEditor(Composite comp, String label, String key) { - ColorFieldEditor editor = new ColorFieldEditor(key, Messages.Guide_color_label, comp); + private void createLabeledColorEditor(Composite comp, String label, String trail, String key) { + createLabel(comp, label); + + // required to constrain the layout expansiveness of the field editor + Composite inner = new Composite(comp, SWT.NONE); + GridLayoutFactory.fillDefaults().applyTo(inner); + GridDataFactory.fillDefaults().applyTo(inner); + + ColorFieldEditor editor = new ColorFieldEditor(key, "", inner); editor.setPreferenceStore(getPreferenceStore()); editor.load(); + + createLabel(comp, trail); + parts.add(editor); } @Override - public boolean performOk() { + protected void performDefaults() { IPreferenceStore store = getPreferenceStore(); for (Object part : parts) { if (part instanceof Button) { Button btn = ((Button) part); String key = (String) btn.getData(); - store.setValue(key, btn.getSelection()); + btn.setSelection(store.getDefaultBoolean(key)); } else if (part instanceof Combo) { Combo combo = ((Combo) part); String key = (String) combo.getData(); - store.setValue(key, combo.getSelectionIndex() + 1); + int idx = store.getDefaultInt(key) - 1; + combo.setText(STYLES[idx]); } else if (part instanceof Spinner) { Spinner spin = ((Spinner) part); String key = (String) spin.getData(); - store.setValue(key, spin.getSelection()); + spin.setSelection(store.getDefaultInt(key)); } else if (part instanceof ColorFieldEditor) { ColorFieldEditor editor = (ColorFieldEditor) part; - editor.store(); + editor.loadDefault(); Activator.getDefault().setColor(editor.getColorSelector().getColorValue()); } else if (part instanceof CheckboxTreeViewer) { CheckboxTreeViewer viewer = (CheckboxTreeViewer) part; - current = getCheckState(viewer); - store.setValue(Settings.CONTENT_TYPES, Prefs.delimited(current)); - Set alltypes = Prefs.asLinkedSet(store.getDefaultString(Settings.CONTENT_TYPES)); - Set disabled = Utils.subtract(alltypes, current); - if (!disabled.isEmpty()) Activator.log("content types disabled: %s", disabled); + excludeTypes.clear(); + for (Object type : Utils.platformTextTypes()) { + if (!viewer.getChecked(type)) { + viewer.setChecked(type, true); + // viewer.setGrayed(type, false); + } + } } } - return super.performOk(); + super.performDefaults(); } @Override - protected void performDefaults() { + public boolean performOk() { IPreferenceStore store = getPreferenceStore(); for (Object part : parts) { if (part instanceof Button) { Button btn = ((Button) part); String key = (String) btn.getData(); - btn.setSelection(store.getDefaultBoolean(key)); + store.setValue(key, btn.getSelection()); } else if (part instanceof Combo) { Combo combo = ((Combo) part); String key = (String) combo.getData(); - int idx = store.getDefaultInt(key) - 1; - combo.setText(STYLES[idx]); + store.setValue(key, combo.getSelectionIndex() + 1); } else if (part instanceof Spinner) { Spinner spin = ((Spinner) part); String key = (String) spin.getData(); - spin.setSelection(store.getDefaultInt(key)); + store.setValue(key, spin.getSelection()); } else if (part instanceof ColorFieldEditor) { ColorFieldEditor editor = (ColorFieldEditor) part; - editor.loadDefault(); + editor.store(); Activator.getDefault().setColor(editor.getColorSelector().getColorValue()); } else if (part instanceof CheckboxTreeViewer) { CheckboxTreeViewer viewer = (CheckboxTreeViewer) part; + Set unchecked = getUnChecked(viewer); - for (Object item : viewer.getCheckedElements()) { - viewer.setChecked(item, false); - viewer.setGrayed(item, false); + Delta delta = Utils.delta(excludeTypes, unchecked); + if (!delta.added.isEmpty()) { + Activator.log("content types excluded: %s", delta.added); } - - IContentTypeManager mgr = Platform.getContentTypeManager(); - TypesContentProvider provider = (TypesContentProvider) viewer.getContentProvider(); - - current = Prefs.asLinkedSet(store.getDefaultString(Settings.CONTENT_TYPES)); - for (String id : current) { - IContentType type = mgr.getContentType(id); - if (!type.equals(txtType)) { - viewer.setChecked(type, true); - updateCheckState(viewer, provider, type); - } + if (!delta.rmved.isEmpty()) { + Activator.log("content types restored: %s", delta.rmved); } + + excludeTypes = unchecked; + store.setValue(Pref.CONTENT_TYPES, Utils.delimitTypes(excludeTypes)); } } - super.performDefaults(); + return super.performOk(); } - private void initCheckState(CheckboxTreeViewer viewer, TypesContentProvider provider) { - IContentTypeManager mgr = Platform.getContentTypeManager(); - for (String elem : current) { - IContentType type = mgr.getContentType(elem); - if (type != null && !type.equals(txtType)) { - viewer.setChecked(type, true); - updateCheckState(viewer, provider, type); - } - } + /** + * Returns the types of the checked, and optionally not grayed, elements in the tree viewer. + * + * @param viewer the tree viewer + * @param grayed include grayed if {@code true}; exclude grayed if {@code false} + * @return the checked, and optionally not grayed, types + */ + private Set getChecked(CheckboxTreeViewer viewer, boolean grayed) { + Set checked = Arrays.stream(viewer.getCheckedElements()).map(e -> (IContentType) e) + .collect(Collectors.toCollection(LinkedHashSet::new)); + + if (grayed) return checked; + return checked.stream().filter(t -> !viewer.getGrayed(t)).collect(Collectors.toCollection(LinkedHashSet::new)); } - /* Returns the id of checked, but not grayed, elements in the tree viewer */ - private Set getCheckState(CheckboxTreeViewer viewer) { - Set checked = new LinkedHashSet<>(); - for (Object item : viewer.getCheckedElements()) { - if (!viewer.getGrayed(item)) { - checked.add(((IContentType) item).getId()); - } - } - return checked; + /** Returns the types of the unchecked tree viewer items */ + private Set getUnChecked(CheckboxTreeViewer viewer) { + return Utils.subtract(Utils.platformTextTypes(), getChecked(viewer, true)); } - private void updateCheckState(CheckboxTreeViewer viewer, TypesContentProvider provider, IContentType type) { - boolean state = viewer.getChecked(type); + private void updateCheckState(CheckboxTreeViewer viewer, IContentType type, boolean state) { + viewer.setGrayed(type, false); - // adj child states to match the current item state + // adjust child states to match the current item state + TypesContentProvider provider = (TypesContentProvider) viewer.getContentProvider(); for (Object child : provider.getChildren(type)) { viewer.setChecked(child, state); } - viewer.setGrayed(type, false); // adj parent hierarchy states to reflect the current item state IContentType parent = (IContentType) provider.getParent(type); while (parent != null) { LinkedList children = new LinkedList<>(Arrays.asList(provider.getChildren(parent))); - boolean allchecked = children.stream().allMatch(e -> viewer.getChecked(e)); - boolean onechecked = children.stream().anyMatch(e -> viewer.getChecked(e)); + boolean all = children.stream().allMatch(e -> viewer.getChecked(e)); + boolean any = children.stream().anyMatch(e -> viewer.getChecked(e)); - viewer.setGrayed(parent, onechecked && !allchecked); - viewer.setChecked(parent, allchecked || onechecked); + viewer.setChecked(parent, all || any); + viewer.setGrayed(parent, any && !all); parent = parent.getBaseType(); } } private String colorKey() { - String key = Settings.LINE_COLOR; + String key = Pref.LINE_COLOR; if (Activator.getDefault().isDarkTheme()) { - key += Settings.DARK; + key += Pref.DARK; } return key; } diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Initializer.java b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Initializer.java index a7eeae9..d977688 100644 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Initializer.java +++ b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Initializer.java @@ -13,7 +13,6 @@ import org.eclipse.swt.SWT; import net.certiv.tools.indentguide.Activator; -import net.certiv.tools.indentguide.util.Prefs; /** Initialize default preference values. */ public class Initializer extends AbstractPreferenceInitializer { @@ -25,16 +24,16 @@ public class Initializer extends AbstractPreferenceInitializer { public void initializeDefaultPreferences() { IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - store.setDefault(Settings.ENABLED, true); - store.setDefault(Settings.LINE_ALPHA, 50); - store.setDefault(Settings.LINE_STYLE, SWT.LINE_SOLID); - store.setDefault(Settings.LINE_WIDTH, 1); - store.setDefault(Settings.LINE_SHIFT, 2); - store.setDefault(Settings.LINE_COLOR, BLACK); - store.setDefault(Settings.LINE_COLOR + Settings.DARK, LIGHT); - store.setDefault(Settings.DRAW_LEFT_END, false); - store.setDefault(Settings.DRAW_BLANK_LINE, true); - store.setDefault(Settings.SKIP_COMMENT_BLOCK, true); - store.setDefault(Settings.CONTENT_TYPES, Prefs.delimited(Prefs.platformTextTypes())); + store.setDefault(Pref.ENABLED, true); + store.setDefault(Pref.LINE_ALPHA, 50); + store.setDefault(Pref.LINE_STYLE, SWT.LINE_SOLID); + store.setDefault(Pref.LINE_WIDTH, 1); + store.setDefault(Pref.LINE_SHIFT, 2); + store.setDefault(Pref.LINE_COLOR, BLACK); + store.setDefault(Pref.LINE_COLOR + Pref.DARK, LIGHT); + store.setDefault(Pref.DRAW_LEFT_EDGE, false); + store.setDefault(Pref.DRAW_BLANK_LINE, true); + store.setDefault(Pref.DRAW_COMMENT_BLOCK, false); + store.setDefault(Pref.CONTENT_TYPES, ""); } } diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Messages.java b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Messages.java index 86cc118..7dd503b 100644 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Messages.java +++ b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Messages.java @@ -14,24 +14,29 @@ public class Messages extends NLS { private static final String BUNDLE_NAME = Messages.class.getName(); - public static String Guide_description; - public static String Guide_enabled_label; - public static String Guide_attribute_group_label; - public static String Guide_alpha_label; - public static String Guide_style_label; - public static String Guide_style_solid; - public static String Guide_style_dash; - public static String Guide_style_dot; - public static String Guide_style_dash_dot; - public static String Guide_style_dash_dot_dot; - public static String Guide_width_label; - public static String Guide_shift_label; - public static String Guide_color_label; - public static String Guide_drawing_group_label; - public static String Guide_draw_left_end_label; - public static String Guide_draw_blank_line_label; - public static String Guide_skip_comment_block_label; - public static String Guide_contenttype_group_label; + public static String description; + public static String enabled_label; + public static String attribute_group_label; + public static String alpha_label1; + public static String alpha_label2; + public static String width_label1; + public static String width_label2; + public static String shift_label1; + public static String shift_label2; + public static String color_label1; + public static String color_label2; + public static String style_label1; + public static String style_label2; + public static String style_solid; + public static String style_dash; + public static String style_dot; + public static String style_dash_dot; + public static String style_dash_dot_dot; + public static String drawing_group_label; + public static String draw_start_edge_label; + public static String draw_blank_line_label; + public static String draw_comment_block_label; + public static String contenttype_group_label; static { NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Messages.properties b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Messages.properties index e67ba0e..d0f5499 100644 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Messages.properties +++ b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Messages.properties @@ -1,18 +1,23 @@ -Guide_description=Settings for IndentGuide -Guide_enabled_label=Enable the indent guide -Guide_attribute_group_label=Line attributes -Guide_alpha_label=Alpha (0=transparent to 255=opaque): -Guide_style_label=Style: -Guide_style_solid=Solid -Guide_style_dash=Dash -Guide_style_dot=Dot -Guide_style_dash_dot=DashDot -Guide_style_dash_dot_dot=DashDotDot -Guide_width_label=Width (1 to 8 pixels): -Guide_shift_label=Shift (0 to 8 pixels): -Guide_color_label=Color: -Guide_drawing_group_label=Drawing options -Guide_draw_left_end_label=Draw guide on column 1 -Guide_draw_blank_line_label=Draw guide on blank lines -Guide_skip_comment_block_label=Skip if followed by " * " or " */" -Guide_contenttype_group_label=Content types +description=Settings for IndentGuide +enabled_label=Enable the indent guide +attribute_group_label=Line attributes +alpha_label1=Alpha +alpha_label2=(0=transparent to 255=opaque) +width_label1=Width +width_label2=(1 to 8 pixels) +shift_label1=Shift +shift_label2=(0 to 8 pixels) +color_label1=Color +color_label2= +style_label1=Style +style_label2= +style_solid=Solid +style_dash=Dash +style_dot=Dot +style_dash_dot=DashDot +style_dash_dot_dot=DashDotDot +drawing_group_label=Drawing options +draw_start_edge_label=Draw guide on column one +draw_blank_line_label=Draw guide on blank lines +draw_comment_block_label=Draw guide for C-style block comments +contenttype_group_label=Content types diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Settings.java b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Pref.java similarity index 88% rename from net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Settings.java rename to net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Pref.java index 3af4110..7df390d 100644 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Settings.java +++ b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/preferences/Pref.java @@ -9,7 +9,7 @@ package net.certiv.tools.indentguide.preferences; /** Constant definitions for plug-in preferences */ -public class Settings { +public class Pref { public static final String KEY = "indentguide."; //$NON-NLS-1$ public static final String DARK = ".dark"; //$NON-NLS-1$ @@ -22,8 +22,8 @@ public class Settings { public static final String LINE_SHIFT = KEY + "line_shift"; //$NON-NLS-1$ public static final String LINE_COLOR = KEY + "line_color"; //$NON-NLS-1$ - public static final String DRAW_LEFT_END = KEY + "draw_left_end"; //$NON-NLS-1$ + public static final String DRAW_LEFT_EDGE = KEY + "draw_left_edge"; //$NON-NLS-1$ public static final String DRAW_BLANK_LINE = KEY + "draw_blank_line"; //$NON-NLS-1$ - public static final String SKIP_COMMENT_BLOCK = KEY + "skip_comment_block"; //$NON-NLS-1$ + public static final String DRAW_COMMENT_BLOCK = KEY + "draw_comment_block"; //$NON-NLS-1$ public static final String CONTENT_TYPES = KEY + "content_types"; //$NON-NLS-1$ } diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/util/Prefs.java b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/util/Prefs.java deleted file mode 100644 index dc012d5..0000000 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/util/Prefs.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.certiv.tools.indentguide.util; - -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.StringTokenizer; - -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.core.runtime.content.IContentTypeManager; -import org.eclipse.jface.layout.PixelConverter; -import org.eclipse.swt.widgets.Control; - -public class Prefs { - - private static final String DELIM = "|"; // $NON-NLS-1$ - - private Prefs() {} - - /** - * Returns the text content type identifiers known to the platform. - * - * @return the text content type identifiers known to the platform. - */ - public static Set platformTextTypes() { - IContentTypeManager mgr = Platform.getContentTypeManager(); - IContentType text = mgr.getContentType(IContentTypeManager.CT_TEXT); - - Set types = new LinkedHashSet<>(); - for (IContentType type : mgr.getAllContentTypes()) { - if (type.isKindOf(text)) { - types.add(type.getId()); - } - } - return types; - } - - public static Set asLinkedSet(String delimited) { - Set types = new LinkedHashSet<>(); - StringTokenizer tokens = new StringTokenizer(delimited, DELIM); - while (tokens.hasMoreTokens()) { - types.add(tokens.nextToken()); - } - return types; - } - - public static String delimited(Set terms) { - return String.join(DELIM, terms); - } - - /** - * Returns the height in pixels of the given number of lines for the given control. - * - * @param comp the component to examine - * @param lines number of lines to measure - * @return number of pixels vertical - */ - public static int lineHeight(Control comp, int lines) { - PixelConverter pc = new PixelConverter(comp); - return pc.convertVerticalDLUsToPixels(lines > 0 ? lines : 1); - } -} diff --git a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/util/Utils.java b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/util/Utils.java index 0635a8c..30fa090 100644 --- a/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/util/Utils.java +++ b/net.certiv.tools.indentguide.plugin/src/net/certiv/tools/indentguide/util/Utils.java @@ -2,31 +2,112 @@ import java.util.Arrays; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.StringTokenizer; import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; +import org.eclipse.jface.layout.PixelConverter; +import org.eclipse.swt.widgets.Control; public class Utils { + private static final String DELIM = "|"; // $NON-NLS-1$ + + private static Set allTypes; + private Utils() {} /** - * Convert the given array to an {@code ArrayList} of the same type. - * + * Returns the height in pixels of the given number of lines for the given control. + * + * @param comp the component to examine + * @param lines number of lines to measure + * @return number of pixels vertical + */ + public static int lineHeight(Control comp, int lines) { + PixelConverter pc = new PixelConverter(comp); + return pc.convertVerticalDLUsToPixels(lines > 0 ? lines : 1); + } + + /** + * Returns the text content type identifiers known to the platform at plugin startup. + * + * @return the known text content type identifiers + */ + public static Set platformTextTypes() { + if (allTypes == null) { + IContentTypeManager mgr = Platform.getContentTypeManager(); + IContentType txtType = mgr.getContentType(IContentTypeManager.CT_TEXT); + allTypes = Stream.of(mgr.getAllContentTypes()).filter(t -> t.isKindOf(txtType)) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + return allTypes; + } + + public static String delimitTypes(Set types) { + if (types.isEmpty()) return ""; + Set terms = types.stream().map(IContentType::getId).collect(Collectors.toSet()); + return delimit(terms); + } + + /** + * Convert a set of preference terms to a delimited string. + * + * @param terms set containing the individual terms + * @return a delimited string of preference terms + */ + public static String delimit(Set terms) { + return String.join(DELIM, terms); + } + + /** + * Convert a delimited string to a {@code LinkedHashSet}. + * + * @param delimited a delimited string of preference terms + * @return set containing the individual terms + */ + public static Set undelimit(String delimited) { + Set types = new LinkedHashSet<>(); + StringTokenizer tokens = new StringTokenizer(delimited, DELIM); + while (tokens.hasMoreTokens()) { + types.add(tokens.nextToken()); + } + return types; + } + + /** + * Convert the given array to an {@code LinkedList} of the same type. + * * @param array the source array to convert * @return a list containing the array elements */ public static List toList(T[] array) { - return Arrays.stream(array).collect(Collectors.toList()); + return Arrays.stream(array).collect(Collectors.toCollection(LinkedList::new)); } /** - * Subtracts from set A all elements in common with set B. + * Convert the given array to an {@code LinkedHashSet} of the same type. + * + * @param array the source array to convert + * @return a set containing the array elements + */ + public static Set toSet(T[] array) { + return Arrays.stream(array).collect(Collectors.toCollection(LinkedHashSet::new)); + } + + /** + * Subtracts from set A all elements in common with those in set B. *

* [0,1,2], [1,2,3] -> [0] */ - public static Set subtract(Set a, Set b) { - Set res = new LinkedHashSet<>(a); + public static Set subtract(Set a, Set b) { + Set res = new LinkedHashSet<>(a); res.removeAll(b); return res; } @@ -36,10 +117,35 @@ public static Set subtract(Set a, Set b) { *

* [0,1,2], [1,2,3] -> [0,3] */ - public static Set disjoint(Set a, Set b) { - Set res = new LinkedHashSet<>(); + public static Set disjoint(Set a, Set b) { + Set res = new LinkedHashSet<>(); res.addAll(subtract(a, b)); res.addAll(subtract(b, a)); return res; } + + /** + * Returns the delta between an initial set A and final set B. + *

+ * [0,1,2], [1,2,3] -> added [3] & removed [0] + */ + public static Delta delta(Set a, Set b) { + return new Delta<>(subtract(b, a), subtract(a, b)); + } + + public static class Delta { + + public Set added; + public Set rmved; + + public Delta(Set added, Set rmved) { + this.added = added; + this.rmved = rmved; + } + + /** Returns {@code true} if both added and removed sets are empty. */ + public boolean isEmpty() { + return added.isEmpty() & rmved.isEmpty(); + } + } }