Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Trying to theme SWT (CSS?)(Want to create a dark mode look for my SWT application)
Trying to theme SWT (CSS?) [message #1821946] |
Mon, 24 February 2020 05:46  |
Eclipse User |
|
|
|
Hi all,
I have a standalone SWT app that I would like to create a dark theme for, I can see there is some CSS support for GTK (org.eclipse.swt.internal.gtk.css) but I cant see anyway to implement using Windows. I also see that eclipse on Windows appears to support themes so was just wondering if there is anything that anybody can point me to, to help create a windows theme?
Any help/advice welcome. Thank you
|
|
|
Re: Trying to theme SWT (CSS?) [message #1822100 is a reply to message #1821946] |
Thu, 27 February 2020 04:42   |
Eclipse User |
|
|
|
I also need standalone swt css styling.
I fetched some jars from eclipse plugin directory and tried with CSSSWTEngineImpl class but no luck.
I know that usually this is used with e4 RCP.
But I'd like to use this function with standalone SWT/JFace app.
The following is the code I tried. (usual black label appears)
import java.io.IOException;
import java.io.StringReader;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.core.runtime.spi.IRegistryProvider;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.core.engine.CSSErrorHandler;
import org.eclipse.e4.ui.css.swt.engine.CSSSWTEngineImpl;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
public class _CSSTest {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell();
shell.setLayout(new GridLayout());
try {
RegistryFactory.setDefaultRegistryProvider(new IRegistryProvider() {
final IExtensionRegistry r = RegistryFactory.createRegistry(null, null, null);
@Override
public IExtensionRegistry getRegistry() {
return r;
}
});
} catch (CoreException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
Label label = new Label(shell, SWT.LEAD);
label.setText("Hello world!");
label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
CSSEngine engine = new CSSSWTEngineImpl(display);
try {
engine.parseStyleSheet(new StringReader("Label { color: blue; }"));
} catch (IOException e1) {
e1.printStackTrace();
}
engine.setErrorHandler(new CSSErrorHandler() {
public void error(Exception e) {
e.printStackTrace();
}
});
// applying styles to the child nodes means that the engine
// should recurse downwards, in this example, the engine
// should style the children of the Shell
engine.applyStyles(shell, /* applyStylesToChildNodes */ true);
shell.setSize(400, 300);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
[Updated on: Thu, 27 February 2020 04:42] by Moderator
|
|
| |
Re: Trying to theme SWT (CSS?) [message #1822125 is a reply to message #1822114] |
Thu, 27 February 2020 11:04   |
Eclipse User |
|
|
|
Now it seems working.
I had to manually set ElementProvider and PropertyHandler.
This page might have some information about handlers.
https://github.com/eclipse/eclipse.platform.ui/blob/master/bundles/org.eclipse.e4.ui.css.swt/plugin.xml
The following code only works for background-color property.
Jars I'm using:
SWT
swt-win64.jar
JFace
com.ibm.icu_64.2.0.v20190507-1337.jar
org.eclipse.core.commands_3.9.400.v20190516-1358.jar
org.eclipse.core.jobs_3.10.400.v20190506-1457.jar
org.eclipse.core.runtime_3.15.300.v20190508-0543.jar
org.eclipse.equinox.common_3.10.400.v20190516-1504.jar
org.eclipse.equinox.registry_3.8.400.v20190516-1504.jar
org.eclipse.jface_3.16.0.v20190528-0922.jar
org.eclipse.jface.databinding_1.9.0.v20190519-0933.jar
org.eclipse.jface.text_3.15.200.v20190519-2344.jar
org.eclipse.osgi_3.14.0.v20190517-1309.jar
org.eclipse.text_3.8.200.v20190519-2344.jar
org.eclipse.ui.forms_3.8.0.v20190519-1034.jar
org.eclipse.ui.workbench_3.115.0.v20190521-1602.jar
SWT CSS
org.apache.batik.css_1.11.0.v20190515-0436.jar
org.apache.batik.i18n_1.11.0.v20190515-0436.jar
org.apache.batik.util_1.11.0.v20190515-0436.jar
org.eclipse.e4.ui.css.core_0.12.900.v20191106-1716.jar
org.eclipse.e4.ui.css.swt_0.13.700.v20191113-1031.jar
org.eclipse.e4.ui.css.swt.theme_0.12.500.v20191125-1011.jar
org.w3c.css.sac_1.3.1.v200903091627.jar
import java.io.IOException;
import java.io.StringReader;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.core.runtime.spi.IRegistryProvider;
import org.eclipse.e4.ui.css.core.dom.properties.css2.ICSSPropertyBackgroundHandler;
import org.eclipse.e4.ui.css.core.dom.properties.providers.CSSPropertyHandlerSimpleProviderImpl;
import org.eclipse.e4.ui.css.core.engine.CSSErrorHandler;
import org.eclipse.e4.ui.css.swt.dom.SWTElementProvider;
import org.eclipse.e4.ui.css.swt.engine.CSSSWTEngineImpl;
import org.eclipse.e4.ui.css.swt.properties.css2.CSSPropertyBackgroundSWTHandler;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
public class _CSSTest {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell();
shell.setLayout(new GridLayout());
try {
RegistryFactory.setDefaultRegistryProvider(new IRegistryProvider() {
final IExtensionRegistry r = RegistryFactory.createRegistry(null, null, null);
@Override
public IExtensionRegistry getRegistry() {
return r;
}
});
} catch (CoreException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
Label label = new Label(shell, SWT.LEAD);
label.setText("Hello world!");
label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
var engine = new CSSSWTEngineImpl(display);
engine.setElementProvider(new SWTElementProvider());
engine.registerCSSPropertyHandlerProvider(new CSSPropertyHandlerSimpleProviderImpl());
engine.registerCSSPropertyHandler(ICSSPropertyBackgroundHandler.class, CSSPropertyBackgroundSWTHandler.INSTANCE);
try {
engine.parseStyleSheet(new StringReader("Label { background-color: blue; }"));
} catch (IOException e1) {
e1.printStackTrace();
}
engine.setErrorHandler(new CSSErrorHandler() {
public void error(Exception e) {
e.printStackTrace();
}
});
// applying styles to the child nodes means that the engine
// should recurse downwards, in this example, the engine
// should style the children of the Shell
engine.applyStyles(label, /* applyStylesToChildNodes */ true);
shell.setSize(400, 300);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
|
|
|
Re: Trying to theme SWT (CSS?) [message #1822152 is a reply to message #1822125] |
Thu, 27 February 2020 22:41   |
Eclipse User |
|
|
|
I struggled a bit, and finally made a working example.
This example downloads plugin.xml from GITHUB, and parse it.
So what you need is just SWT / JFace / e4 CSS Jars in your classpath.
import java.util.function.BiFunction;
import java.util.function.Function;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import org.eclipse.core.internal.registry.ExtensionRegistry;
import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.core.runtime.spi.RegistryContributor;
import org.eclipse.e4.ui.css.core.engine.CSSErrorHandler;
import org.eclipse.e4.ui.css.core.impl.engine.RegistryCSSPropertyHandlerProvider;
import org.eclipse.e4.ui.css.swt.engine.CSSSWTEngineImpl;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;
public class _SWTStandaloneCSS {
public static void main(String[] args) {
var registry = new ExtensionRegistry(null, null, null);
var dummyContributor = new RegistryContributor("", "", "", "");
registry.addExtensionPoint("org.eclipse.e4.ui.css.core.elementProvider", dummyContributor, true, null, null, null);
registry.addExtensionPoint("org.eclipse.e4.ui.css.core.propertyHandler", dummyContributor, true, null, null, null);
try {
registry.addContribution(pluginXMLStream(), dummyContributor, true, null, null, null);
RegistryFactory.setDefaultRegistryProvider(() -> registry);
} catch (Exception e) {
e.printStackTrace();
}
SWTBoilerplate.show(composite -> {
var engine = new CSSSWTEngineImpl(composite.getDisplay());
initCSSEngine(engine, registry);
var content = createContent(composite);
try {
engine.parseStyleSheet(new StringReader("Label { color : red; background-color: blue; }"));
} catch (IOException e1) {
e1.printStackTrace();
}
engine.applyStyles(composite.getShell(), /* applyStylesToChildNodes */ true);
return content;
});
}
static FileInputStream pluginXMLStream() {
File f = download("https://raw.githubusercontent.com/eclipse/eclipse.platform.ui/master/bundles/org.eclipse.e4.ui.css.swt/plugin.xml", "swt_css_plugin.xml");
try {
return new FileInputStream(f);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
static File download(String url, String destFilePath) {
var f = new File(destFilePath);
if( f.exists() ) return f;
URL website;
try {
website = new URL(url);
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destFilePath);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
return f;
}
static void initCSSEngine(CSSSWTEngineImpl engine, ExtensionRegistry registry) {
engine.registerCSSPropertyHandlerProvider(new RegistryCSSPropertyHandlerProvider(registry));
engine.setErrorHandler(new CSSErrorHandler() {
public void error(Exception e) {
e.printStackTrace();
}
});
}
static Control createContent(Composite comp) {
Label label = new Label(comp, SWT.LEAD);
label.setText("Hello world!");
return label;
}
}
class SWTBoilerplate {
private final Display display;
private Shell shell;
public SWTBoilerplate() {
if( Display.getCurrent() == null) {
display = new Display();
} else {
display = Display.getCurrent();
}
}
public static void show(Image image) {
SWTBoilerplate app = new SWTBoilerplate();
var com = app.launch();
Label l = new Label(com, SWT.NONE);
l.setImage(image);
app.loop(true);
}
public static void show(Function<Composite, Control> creator) {
SWTBoilerplate app = new SWTBoilerplate();
var com = app.launch();
creator.apply(com);
app.loop(true);
}
public static void show(BiFunction<Composite, Shell, Control> creator) {
SWTBoilerplate app = new SWTBoilerplate();
var com = app.launch();
creator.apply(com, com.getShell());
app.loop(true);
}
public Composite launch() {
return launch(new FillLayout(), SWT.SHELL_TRIM);
}
public Composite launch( Layout layout , int shellStyle) {
shell = new Shell(display, shellStyle);
shell.setLayout(new FillLayout());
shell.setSize(800,600);
Composite comp = new Composite(shell, SWT.None);
comp.setLayout( layout );
return comp;
}
public void loop() {
loop(false);
}
public void loop(boolean pack) {
if( shell == null ) {
shell = Display.getCurrent().getShells()[0];
}
shell.open();
if(pack) shell.pack();
while( !shell.isDisposed() ) {
if( !display.readAndDispatch() ) {
display.sleep();
}
}
display.dispose();
}
public static void nloop() {
new SWTBoilerplate().loop();
}
}
[Updated on: Thu, 27 February 2020 22:47] by Moderator
|
|
| | | | | | | |
Re: Trying to theme SWT (CSS?) [message #1822208 is a reply to message #1822184] |
Sat, 29 February 2020 19:47  |
Eclipse User |
|
|
|
If you extends Composite or Shell, simple class name is used as Element name.
Composite or Shell selectors are not applied.
CustomWidget {
background-color: red;
}
If you want a custom property, perhaps standard way in RCP is using extension points.
But you can find properties programmatically easily, no need to use extension points and no need to modify plugin.xml one by one.
public static String property(Widget w, String property) {
var engine = getEngine(w.getDisplay());
var element = engine.getElement(w);
var style = engine.getViewCSS().getComputedStyle(element, null);
if( style == null ) {
System.out.println("style is null : " + element);
return null;
}
var cssVal = style.getPropertyCSSValue(property);
return cssVal != null ? cssVal.getCssText() : null;
}
|
|
|
Goto Forum:
Current Time: Tue Jul 08 13:43:47 EDT 2025
Powered by FUDForum. Page generated in 0.06138 seconds
|