From ed84633ad56182961013512e98e8536964e10650 Mon Sep 17 00:00:00 2001 From: Sandro Marques Date: Sun, 22 Dec 2019 16:56:00 +0000 Subject: [PATCH] Finished settings menu --- images/settings.gif | Bin 353 -> 1021 bytes .../iscde/minimap/internal/MinimapView.java | 71 +++++++--- .../minimap/internal/SettingsDialog.java | 130 +++++++++++++++--- .../minimap/internal/SettingsManager.java | 30 ++-- .../iscde/minimap/internal/SettingsTool.java | 14 +- .../internal/extension/ExtensionRule.java | 22 ++- .../minimap/internal/parser/AstVisitor.java | 3 +- 7 files changed, 209 insertions(+), 61 deletions(-) diff --git a/images/settings.gif b/images/settings.gif index 9d050885be6d125c6f3a8ee61f770af463945b9d..8c728cc1610d496b873966bf417250b0fb8e22ae 100644 GIT binary patch literal 1021 zcmZ?wbhEHb6krfw_|Cv^>B`NmJN9qdy2m#%BPzQtI;Xy4$|ARrB#*EZuZT3y@Km3u zjIZB+x`rgh7q`Y0wKVk2PAF*&PAT?|N-t`f@Zrn%w;w(&+Pp8Sv^BG3a(sDfdgFwu zzF8&hlRD?Fc=Gnsk<;hnD%w1vQ*%0|C)IT3bWE$6FspCTnx-jpCoS7Bd;QL-D>lvB zv}e)Q{d-ScymaT`)%#DLzkVB9+7evU7*pLDm{So`)!~(t8&}hn-agGeHr+Em(<>p% zFD0*N;)1-MS-IUavpc3`v`$KE>Q8O#iz==QNGr%_nV8-@A+515xvnd*x;?JEIWWD@ zKPAsEIk$AmqQd^UdEGO!+9qeVPD-ioj<0BmDQyVOEY5717@A!gl2sC2R2!C47MxL( z+c7n^xHi9Ia^sA}p=B+>#f{kFRVA%_;Lu$_`8~SiSqu zh6Bfal5>JGi$Zfs<7?Xdb4s%MX8LCp1?3b!fB(@tyT~ImKf8ZgL`z%U`VFZQC+_(F zfA|0Yd;kAG@c;kO|NoEu|DQZ#+P43Hw*CLR>fM`VFP?QDJ+$@z@6CUH^qoGo>Hqi5 zf4;8!_HNqcGxML`+Wh~^;t!9OetNRu|EH<1uFrXMYxV!P|NsAI7zIR!fZ|UUMh1r2 z3_2hkpgh6Aaf`v6Q)UNChlm=puvUnX(<#wb0cVkp2MrBu9nLFK4kjF*xYVoL$i~B2 zwbMZ{IHll607vjL#|b|y9EwwfIW;Z%o-i6bIL2Z#Md{+r2a8WE(=fgl;c?;lq-B1aCD(+hLLR4D91E3NId!eK jWgKLh=+b@D;A)gO-Np~iFvL`S|+%=I;6M_51hw{q^|!_xbz#{Qb_)#h93po0^aQ{qLrshuzn@qo0bO zoQ<`rez2#3tE7ef^v}n&am2H8!LfI}u6envd;RmzwUHwpwUQ&cmnQt@qn>#drhyu! zf*PfQ8m@{T``v??bQ6=_0Wg0d`2+y~05AY7000005C9MW00w?Qm~coe8jmOAXUW81 zPL?F`GpG&(f|AK%G7&+Ma75Dbct|8qYZ!vKAy^g*wNep9fP9|8NV!r)BMyUv4-YRB zMH>f4LO}pKjQ66q diff --git a/src/pa/iscde/minimap/internal/MinimapView.java b/src/pa/iscde/minimap/internal/MinimapView.java index f69f3b0..4574403 100644 --- a/src/pa/iscde/minimap/internal/MinimapView.java +++ b/src/pa/iscde/minimap/internal/MinimapView.java @@ -44,6 +44,7 @@ public class MinimapView implements PidescoView { private static final Logger LOGGER = Logger.getLogger(MinimapView.class); + public static final String VIEW_ID = "pt.iscte.pidesco.minimap.minimap"; public static final String EXT_POINT_INSPECTION = "pt.iscte.pidesco.minimap.inspection"; @@ -58,6 +59,8 @@ public class MinimapView implements PidescoView { private final Collection extensions; private final Collection activeRules; + private File activeFile = null; + /* SWT Components */ private Composite root; private ScrolledComposite scroll; @@ -93,7 +96,15 @@ private void loadInspections() { this.extensions.add(extension); this.activeRules.addAll(extension.rules); - extension.rules.forEach(rule -> SettingsManager.isEnabled(rule.id)); + // Load rule stat + for (ExtensionRule rule : extension.rules) { + if (rule.isErrored()) { + rule.setEnabled(false); + SettingsManager.setEnabled(rule); + } else { + rule.setEnabled(SettingsManager.isEnabled(rule)); + } + } } catch (Exception e) { LOGGER.error("Error loading extension '" + ext.getSimpleIdentifier() + "'", e); } @@ -163,43 +174,61 @@ public Composite getRoot() { return root; } - private class Listener implements JavaEditorListener { + public Collection getExtensions() { + return extensions; + } - @Override - public void fileOpened(File file) { - LOGGER.info("File opened: " + file); + public File getActiveFile() { + return activeFile; + } + + public void parseFile(File file) { + this.activeFile = file; - // TODO: do this in a worker thread - // TODO: implement way to enable/disable rules - Collection lines = new MinimapFile(file).parse(javaEditorServices, activeRules); + if (file == null) { + this.scroll.getContent().dispose(); + return; + } - createScrollComponent(lines); + // TODO: do this in a worker thread + // TODO: implement way to enable/disable rules + Collection lines = new MinimapFile(file).parse(javaEditorServices, activeRules); + createScrollComponent(lines); -// StyledText text = new StyledText(scroll, SWT.BORDER); -// text.setText("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); +// StyledText text = new StyledText(scroll, SWT.BORDER); +// text.setText("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); // -// FontData data = text.getFont().getFontData()[0]; -// Font font1 = new Font(scroll.getDisplay(), data.getName(), data.getHeight(), data.getStyle()); +// FontData data = text.getFont().getFontData()[0]; +// Font font1 = new Font(scroll.getDisplay(), data.getName(), data.getHeight(), data.getStyle()); // -// StyleRange style1 = new StyleRange(); -// style1.start = 0; -// style1.length = 10; -// style1.fontStyle = SWT.BOLD; -// style1.font = font1; -// style1.background = Colors.PURPLE; -// text.setStyleRange(style1); +// StyleRange style1 = new StyleRange(); +// style1.start = 0; +// style1.length = 10; +// style1.fontStyle = SWT.BOLD; +// style1.font = font1; +// style1.background = Colors.PURPLE; +// text.setStyleRange(style1); + } + + private class Listener implements JavaEditorListener { + + @Override + public void fileOpened(File file) { + LOGGER.info("File opened: " + file); + parseFile(file); } @Override public void fileClosed(File file) { LOGGER.debug("File closed: " + file); + parseFile(null); } @Override public void fileSaved(File file) { LOGGER.debug("File saved: " + file); - // TODO reload/reparse file + parseFile(file); } } diff --git a/src/pa/iscde/minimap/internal/SettingsDialog.java b/src/pa/iscde/minimap/internal/SettingsDialog.java index 19d142b..9574190 100644 --- a/src/pa/iscde/minimap/internal/SettingsDialog.java +++ b/src/pa/iscde/minimap/internal/SettingsDialog.java @@ -1,5 +1,6 @@ package pa.iscde.minimap.internal; +import org.apache.log4j.Logger; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.swt.SWT; @@ -7,15 +8,18 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import pa.iscde.minimap.internal.extension.Extension; +import pa.iscde.minimap.internal.extension.ExtensionRule; public class SettingsDialog extends TitleAreaDialog { - private Text txtFirstName; + private static final Logger LOGGER = Logger.getLogger(SettingsDialog.class); + + private Tree tree; - private String firstName; /** * Instantiate a new title area dialog. @@ -29,8 +33,8 @@ public SettingsDialog(Shell parentShell) { @Override public void create() { super.create(); - setTitle("Custom dialog"); - setMessage("This is a TitleAreaDialog", IMessageProvider.INFORMATION); + setTitle("Settings"); + setMessage("Enable your desired inspection rules.", IMessageProvider.NONE); } @Override @@ -38,24 +42,103 @@ protected Control createDialogArea(Composite parent) { Composite area = (Composite) super.createDialogArea(parent); Composite container = new Composite(area, SWT.NONE); container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - GridLayout layout = new GridLayout(2, false); - container.setLayout(layout); + container.setLayout(new GridLayout(1, false)); - createFirstName(container); + tree = new Tree(container, SWT.CHECK | SWT.BORDER); + tree.setLayoutData(container.getLayoutData()); + fillTree(tree); return area; } - private void createFirstName(Composite container) { - Label lbtFirstName = new Label(container, SWT.NONE); - lbtFirstName.setText("First Name"); + /** + * Helper method to fill a tree with data + * + * @param tree the tree to fill + */ + private void fillTree(Tree tree) { + // Turn off drawing to avoid flicker + tree.setRedraw(false); + + tree.addListener(SWT.Selection, event -> { + TreeItem item = (TreeItem) event.item; + LOGGER.debug((event.detail == SWT.CHECK ? "CHECK" : "SELECT") + " EVENT: " + item); + + if (event.detail != SWT.CHECK) { + return; + } + + // Set checked state for himself and all it's children + setCheckedState(item, item.getChecked()); + + // Refresh checked state for it's parent + if (item.getParentItem() != null) { + item.getParentItem().setChecked(getCheckedState(item.getParentItem())); + } + }); + + for (Extension ext : MinimapView.getInstance().getExtensions()) { + TreeItem item = new TreeItem(tree, SWT.NONE); + item.setText(ext.name + " [" + ext.id + ']'); + item.setData(ext); + item.setExpanded(true); + + for (ExtensionRule rule : ext.rules) { + TreeItem child = new TreeItem(item, SWT.NONE); + child.setText(rule.name + " [" + rule.id + ']'); + child.setData(rule); + + if (rule.isErrored()) { + child.setGrayed(true); + child.setChecked(false); + } else { + child.setChecked(SettingsManager.isEnabled(rule)); + } + } + + item.setChecked(getCheckedState(item)); + } + + tree.setRedraw(true); + } + + private void setCheckedState(TreeItem item, boolean checked) { + item.setChecked(checked); + for (TreeItem child : item.getItems()) { + setCheckedState(child, checked); + } + } + + /** + * Find the checked state based on it's children's state. + * + * @param item The item to find the checked state + * @return {@code true} if at least one of it's children is checked, {@code false} otherwise + */ + private boolean getCheckedState(TreeItem item) { + if (item.getItems().length < 1) { + return item.getChecked(); + } - GridData dataFirstName = new GridData(); - dataFirstName.grabExcessHorizontalSpace = true; - dataFirstName.horizontalAlignment = GridData.FILL; + for (TreeItem child : item.getItems()) { + if (getCheckedState(child)) { + return true; + } + } - txtFirstName = new Text(container, SWT.BORDER); - txtFirstName.setLayoutData(dataFirstName); + return false; + } + + private void save(TreeItem item) { + if (item.getData() instanceof ExtensionRule) { + ExtensionRule rule = (ExtensionRule) item.getData(); + rule.setEnabled(item.getChecked()); + SettingsManager.setEnabled(rule); + } + + for (TreeItem child : item.getItems()) { + save(child); + } } @Override @@ -65,9 +148,18 @@ protected void cancelPressed() { @Override protected void okPressed() { - firstName = txtFirstName.getText(); + for (TreeItem item : tree.getItems()) { + save(item); + } + + boolean changed = SettingsManager.save(); + + if (changed) { + MinimapView view = MinimapView.getInstance(); + view.parseFile(view.getActiveFile()); + } + super.okPressed(); - SettingsManager.save(); } @Override diff --git a/src/pa/iscde/minimap/internal/SettingsManager.java b/src/pa/iscde/minimap/internal/SettingsManager.java index 68910e4..ecf0314 100644 --- a/src/pa/iscde/minimap/internal/SettingsManager.java +++ b/src/pa/iscde/minimap/internal/SettingsManager.java @@ -12,8 +12,10 @@ import java.util.stream.Collectors; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import org.apache.log4j.Logger; +import pa.iscde.minimap.internal.extension.ExtensionRule; public class SettingsManager { @@ -22,7 +24,7 @@ public class SettingsManager { /** path in which the settings file is stored */ private static final Path SETTINGS_PATH = Paths.get("minimap.ini"); - private static final Gson GSON = new Gson(); + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private static final Type SETTINGS_TYPE = new TypeToken>(){}.getType(); /** the state that new extension rules will have */ @@ -49,10 +51,10 @@ public static void load() { } } - public static void save() { + public static boolean save() { if (!dirty) { LOGGER.debug("Settings unchanged"); - return; + return false; } try { @@ -67,17 +69,29 @@ public static void save() { dirty = false; LOGGER.info("Saved settings for " + settings.size() + " rules"); } + + return true; } - public static boolean isEnabled(String ruleId) { - return settings.computeIfAbsent(ruleId, key -> { + public static boolean isEnabled(ExtensionRule rule) { + if (rule == null) { + return false; + } + + return settings.computeIfAbsent(rule.id, key -> { dirty = true; return DEFAULT_STATE; }); } - public static void setEnabled(String ruleId, boolean enabled) { - settings.put(ruleId, enabled); - dirty = true; + public static void setEnabled(ExtensionRule rule) { + if (rule == null) { + return; + } + + Boolean prev = settings.put(rule.id, rule.isEnabled()); + + // Only mark dirty if the value changed + dirty |= !((Boolean) rule.isEnabled()).equals(prev); } } diff --git a/src/pa/iscde/minimap/internal/SettingsTool.java b/src/pa/iscde/minimap/internal/SettingsTool.java index 7900f9e..f729ae7 100644 --- a/src/pa/iscde/minimap/internal/SettingsTool.java +++ b/src/pa/iscde/minimap/internal/SettingsTool.java @@ -1,29 +1,25 @@ package pa.iscde.minimap.internal; +import org.apache.log4j.Logger; import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.MessageBox; import pt.iscte.pidesco.extensibility.PidescoTool; public class SettingsTool implements PidescoTool { + private static final Logger LOGGER = Logger.getLogger(SettingsTool.class); + @Override public void run(boolean selected) { -// Activator.getContext(); -// ProjectBrowserActivator.getInstance().refreshWorkspace(); - MinimapView minimap = MinimapView.getInstance(); SettingsDialog dialog = new SettingsDialog(minimap.getRoot().getShell()); int returnCode = dialog.open(); if (returnCode == IDialogConstants.OK_ID) { - System.out.println("OK clicked"); + LOGGER.debug("OK clicked"); } else if (returnCode == IDialogConstants.CANCEL_ID) { - System.out.println("CANCEL clicked"); - } else { - System.out.println("UNK: " + returnCode); + LOGGER.debug("CANCEL clicked"); } } diff --git a/src/pa/iscde/minimap/internal/extension/ExtensionRule.java b/src/pa/iscde/minimap/internal/extension/ExtensionRule.java index ef324bd..44a345e 100644 --- a/src/pa/iscde/minimap/internal/extension/ExtensionRule.java +++ b/src/pa/iscde/minimap/internal/extension/ExtensionRule.java @@ -6,6 +6,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import pa.iscde.minimap.extensibility.MinimapInspection; +import pa.iscde.minimap.internal.SettingsManager; import static pa.iscde.minimap.extensibility.inspections.NoopInspection.NOOP; @@ -16,9 +17,10 @@ public class ExtensionRule { public final String id; public final String name; public final String description; - public final MinimapInspection rule; + private final MinimapInspection rule; - public final boolean errored; + private final boolean errored; + private boolean enabled; public ExtensionRule(Extension ext, String id, String name, String description, MinimapInspection rule) { this.id = ext.id + ":" + id; @@ -46,6 +48,22 @@ private static MinimapInspection loadRule(Extension ext, IConfigurationElement c } } + public MinimapInspection getRule() { + return isEnabled() ? rule : NOOP; + } + + public boolean isErrored() { + return errored; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/pa/iscde/minimap/internal/parser/AstVisitor.java b/src/pa/iscde/minimap/internal/parser/AstVisitor.java index 0875fb9..7239034 100644 --- a/src/pa/iscde/minimap/internal/parser/AstVisitor.java +++ b/src/pa/iscde/minimap/internal/parser/AstVisitor.java @@ -63,11 +63,10 @@ private void inspect(final ASTNode node) { for (ExtensionRule extRule : rules) { try { - extRule.rule.inspect(node, context); + extRule.getRule().inspect(node, context); } catch (Exception e) { LOGGER.error("Error running inspection rule: " + extRule.id, e); } - } }