From 35bd90cc9bc2773f23a128aa3cbd7d23920d47b7 Mon Sep 17 00:00:00 2001 From: Phillipus Date: Thu, 10 Aug 2023 12:41:24 +0100 Subject: [PATCH] [Hints] Refactor HintsView and render dark theme - JS in Hints has to be enabled in Archi's preferences for dark theme to work - Mac kludge no longer needed --- com.archimatetool.canvas/help/hints/style.css | 5 + com.archimatetool.help/hints/style.css | 5 + .../archimatetool/help/hints/HintsView.java | 145 +++++++----------- 3 files changed, 65 insertions(+), 90 deletions(-) diff --git a/com.archimatetool.canvas/help/hints/style.css b/com.archimatetool.canvas/help/hints/style.css index 5a8e85c3b..8fe76f325 100644 --- a/com.archimatetool.canvas/help/hints/style.css +++ b/com.archimatetool.canvas/help/hints/style.css @@ -3,6 +3,11 @@ body, table { font-size: 13px; } +.dark-mode { + background-color: rgb(78, 78, 78); + color: rgb(226, 226, 226); +} + h1 { font-size: 16px; } diff --git a/com.archimatetool.help/hints/style.css b/com.archimatetool.help/hints/style.css index 5a8e85c3b..8fe76f325 100644 --- a/com.archimatetool.help/hints/style.css +++ b/com.archimatetool.help/hints/style.css @@ -3,6 +3,11 @@ body, table { font-size: 13px; } +.dark-mode { + background-color: rgb(78, 78, 78); + color: rgb(226, 226, 226); +} + h1 { font-size: 16px; } diff --git a/com.archimatetool.help/src/com/archimatetool/help/hints/HintsView.java b/com.archimatetool.help/src/com/archimatetool/help/hints/HintsView.java index 70636a20f..8a5205886 100644 --- a/com.archimatetool.help/src/com/archimatetool/help/hints/HintsView.java +++ b/com.archimatetool.help/src/com/archimatetool/help/hints/HintsView.java @@ -30,9 +30,7 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; import org.eclipse.swt.browser.Browser; -import org.eclipse.swt.browser.LocationAdapter; -import org.eclipse.swt.browser.LocationEvent; -import org.eclipse.swt.browser.ProgressEvent; +import org.eclipse.swt.browser.LocationListener; import org.eclipse.swt.browser.ProgressListener; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.graphics.Color; @@ -41,7 +39,6 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; @@ -53,9 +50,9 @@ import com.archimatetool.editor.preferences.IPreferenceConstants; import com.archimatetool.editor.ui.IArchiImages; import com.archimatetool.editor.ui.IHelpHintProvider; +import com.archimatetool.editor.ui.ThemeUtils; import com.archimatetool.editor.ui.services.ComponentSelectionManager; import com.archimatetool.editor.ui.services.IComponentSelectionListener; -import com.archimatetool.editor.utils.PlatformUtils; import com.archimatetool.editor.utils.StringUtils; import com.archimatetool.help.ArchiHelpPlugin; import com.archimatetool.model.IArchimateConcept; @@ -69,13 +66,14 @@ * * @author Phillip Beauvoir */ +@SuppressWarnings("nls") public class HintsView extends ViewPart implements IContextProvider, IHintsView, ISelectionListener, IComponentSelectionListener { // CSS string - private String cssString = ""; //$NON-NLS-1$ + private String cssString = ""; private Browser fBrowser; @@ -90,8 +88,6 @@ public class HintsView private CLabel fTitleLabel; - private boolean fPageLoaded; - private static class PinAction extends Action { PinAction() { super(Messages.HintsView_0, IAction.AS_CHECK_BOX); @@ -114,10 +110,9 @@ private static class Hint { } public HintsView() { - // Load CSS String + // Load CSS for Hint Providers try { - File cssFile = new File(ArchiHelpPlugin.INSTANCE.getHintsFolder(), "style.css"); //$NON-NLS-1$ - cssString = new String(Files.readAllBytes(cssFile.toPath())); + cssString = Files.readString(java.nio.file.Path.of(ArchiHelpPlugin.INSTANCE.getHintsFolder().getPath(), "style.css")); } catch(IOException ex) { ex.printStackTrace(); @@ -132,17 +127,19 @@ public void createPartControl(Composite parent) { layout.verticalSpacing = 0; parent.setLayout(layout); - if(!JFaceResources.getFontRegistry().hasValueFor("HintsTitleFont")) { //$NON-NLS-1$ + if(!JFaceResources.getFontRegistry().hasValueFor("HintsTitleFont")) { FontData[] fontData = JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT).getFontData(); fontData[0].setHeight(fontData[0].getHeight() + 4); - JFaceResources.getFontRegistry().put("HintsTitleFont", fontData); //$NON-NLS-1$ + JFaceResources.getFontRegistry().put("HintsTitleFont", fontData); } fTitleLabel = new CLabel(parent, SWT.NULL); - fTitleLabel.setFont(JFaceResources.getFont("HintsTitleFont")); //$NON-NLS-1$ - // Use CSS styling for label color in case of Dark Theme - fTitleLabel.setData("style", "background-color: RGB(220, 235, 235); color: #000;"); //$NON-NLS-1$ //$NON-NLS-2$ - // fTitleLabel.setBackground(ColorFactory.get(220, 235, 235)); + fTitleLabel.setFont(JFaceResources.getFont("HintsTitleFont")); + + // Use CSS styling for label color + if(!ThemeUtils.isDarkTheme()) { + fTitleLabel.setData("style", "background-color: RGB(220, 235, 235); color: #000;"); + } GridData gd = new GridData(GridData.FILL_HORIZONTAL); fTitleLabel.setLayoutData(gd); @@ -165,18 +162,6 @@ public void createPartControl(Composite parent) { gd = new GridData(GridData.FILL_BOTH); fBrowser.setLayoutData(gd); - // Listen to Loading progress - fBrowser.addProgressListener(new ProgressListener() { - @Override - public void completed(ProgressEvent event) { - fPageLoaded = true; - } - - @Override - public void changed(ProgressEvent event) { - } - }); - // Listen to Diagram Editor Selections ComponentSelectionManager.INSTANCE.addSelectionListener(this); @@ -206,22 +191,27 @@ public void changed(ProgressEvent event) { * Create the Browser if possible */ private Browser createBrowser(Composite parent) { - Browser browser = null; try { - browser = new Browser(parent, SWT.NONE); + final Browser browser = new Browser(parent, SWT.NONE); // Don't allow external hosts if set - browser.addLocationListener(new LocationAdapter() { - @Override - public void changing(LocationEvent e) { - if(!ArchiPlugin.PREFERENCES.getBoolean(IPreferenceConstants.HINTS_BROWSER_EXTERNAL_HOSTS_ENABLED)) { - e.doit = e.location != null && - (e.location.startsWith("file:") //$NON-NLS-1$ - || e.location.startsWith("data:") //$NON-NLS-1$ - || e.location.startsWith("about:")); //$NON-NLS-1$ - } + browser.addLocationListener(LocationListener.changingAdapter(e -> { + if(!ArchiPlugin.PREFERENCES.getBoolean(IPreferenceConstants.HINTS_BROWSER_EXTERNAL_HOSTS_ENABLED)) { + e.doit = isLocalURL(e.location); // can link to local locations + } + })); + + browser.addProgressListener(ProgressListener.completedAdapter(e -> { + // If this is a local URL and we're using dark theme apply dark css + if(browser.getJavascriptEnabled() && ThemeUtils.isDarkTheme() && isLocalURL(browser.getUrl())) { + browser.execute("document.body.classList.add('dark-mode');"); } - }); + })); + + // Start with skeleton html + browser.setText(makeHTMLEntry("")); + + return browser; } catch(SWTError error) { error.printStackTrace(); @@ -232,21 +222,13 @@ public void changing(LocationEvent e) { child.dispose(); } } + + return null; } - - return browser; } @Override public void setFocus() { - /* - * Need to do this otherwise we get a: - * - * "java.lang.RuntimeException: WARNING: Prevented recursive attempt to activate part org.eclipse.ui.views.PropertySheet - * while still in the middle of activating part *.hintsView" - * - * But on Windows this leads to a SWTException if closing this View by shortcut key (Alt-4) - */ if(fBrowser != null) { fBrowser.setFocus(); } @@ -291,7 +273,7 @@ private void showHintForSelected(Object source, Object selected) { } } - String title = "", content = null, path = null; //$NON-NLS-1$ + String title = "", content = null, path = null; Hint hint = getHintForObject(actualObject); // We have a hint so these are the defaults @@ -317,32 +299,25 @@ private void showHintForSelected(Object source, Object selected) { // Set Title fTitleLabel.setText(title); - // Enable JS + // Enable/Disable JS fBrowser.setJavascriptEnabled(ArchiPlugin.PREFERENCES.getBoolean(IPreferenceConstants.HINTS_BROWSER_JS_ENABLED)); // We have some content if(content != null) { fBrowser.setText(content); - fLastPath = ""; //$NON-NLS-1$ + fLastPath = ""; } // We have a hint path else if(path != null) { if(fLastPath != path) { // optimise - // Load page - fPageLoaded = false; - fBrowser.setUrl("file:///" + path); //$NON-NLS-1$ + fBrowser.setUrl("file:///" + path); fLastPath = path; - - // Kludge for Mac/Safari when displaying hint on mouse rollover menu item in MagicConnectionCreationTool - if(PlatformUtils.isMac() && source instanceof MenuItem) { - _doMacWaitKludge(); - } } } // Blank else { - fBrowser.setText(""); //$NON-NLS-1$ - fLastPath = ""; //$NON-NLS-1$ + fBrowser.setText(""); + fLastPath = ""; } } @@ -375,54 +350,44 @@ private Hint getHintForObject(Object object) { */ private String makeHTMLEntry(String text) { if(text == null) { - return ""; //$NON-NLS-1$ + return ""; } StringBuffer html = new StringBuffer(); - html.append(""); //$NON-NLS-1$ + html.append(""); - html.append(""); //$NON-NLS-1$ + html.append(""); - html.append(""); //$NON-NLS-1$ + html.append(""); - html.append(""); //$NON-NLS-1$ + html.append(""); html.append(text); - html.append(""); //$NON-NLS-1$ + html.append(""); - html.append(""); //$NON-NLS-1$ + html.append(""); return html.toString(); } /** - * If we are displaying a hint from a menu rollover in MagicConnectionCreationTool then the threading is different - * and the Browser does not update. So we need to wait for a few sleep cycles. + * @return true if URL is a local file or text */ - private void _doMacWaitKludge() { - // This works on Carbon and Cocoa...usually needs about 4-7 sleep cycles - fBrowser.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - int i = 0; - while(!fPageLoaded && i++ < 20) { // Set an upper getout limit for safety - fBrowser.getDisplay().sleep(); - } - } - }); + private boolean isLocalURL(String url) { + return url != null && (url.startsWith("file:") || url.startsWith("data:") || url.startsWith("about:")); } private void createFileMap() { IExtensionRegistry registry = Platform.getExtensionRegistry(); for(IConfigurationElement configurationElement : registry.getConfigurationElementsFor(EXTENSION_POINT_ID)) { - String className = configurationElement.getAttribute("className"); //$NON-NLS-1$ - String fileName = configurationElement.getAttribute("file"); //$NON-NLS-1$ - String title = configurationElement.getAttribute("title"); //$NON-NLS-1$ - String key = configurationElement.getAttribute("key"); //$NON-NLS-1$ + String className = configurationElement.getAttribute("className"); + String fileName = configurationElement.getAttribute("file"); + String title = configurationElement.getAttribute("title"); + String key = configurationElement.getAttribute("key"); String id = configurationElement.getNamespaceIdentifier(); Bundle bundle = Platform.getBundle(id); - URL url = FileLocator.find(bundle, new Path("$nl$/" + fileName), null); //$NON-NLS-1$ + URL url = FileLocator.find(bundle, new Path("$nl$/" + fileName), null); try { url = FileLocator.resolve(url);