| /******************************************************************************* |
| * Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Soyatec - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.xwt.css; |
| |
| import java.io.InputStream; |
| import java.io.StringReader; |
| import java.lang.reflect.Method; |
| import java.net.URL; |
| |
| import org.eclipse.e4.ui.css.core.engine.CSSEngine; |
| import org.eclipse.e4.ui.css.core.engine.CSSErrorHandler; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.xwt.IStyle; |
| import org.eclipse.xwt.XWT; |
| import org.eclipse.xwt.XWTException; |
| |
| /** |
| * Base class for CSS Style. |
| * |
| * @author yyang |
| * @author <a href="mailto:angelo.zerr@gmail.com">Angelo ZERR</a> |
| */ |
| public abstract class AbstractCSSStyle implements IStyle, CSSErrorHandler { |
| protected URL url; |
| protected String content; |
| |
| private CSSEngine engine; |
| private Display display; |
| |
| private Class<?> jfaceViewerClass; |
| private Method getControl; |
| |
| public AbstractCSSStyle() { |
| this((String) null); |
| } |
| |
| public AbstractCSSStyle(URL url) { |
| this.url = url; |
| init(); |
| } |
| |
| public AbstractCSSStyle(String content) { |
| this.content = content; |
| init(); |
| } |
| |
| public AbstractCSSStyle(CSSEngine engine) { |
| this.engine = engine; |
| init(); |
| } |
| |
| /** |
| * Initialize class and method of JFace Viewer. |
| * |
| */ |
| private void init() { |
| try { |
| // FIXME : Yves, jfaceViewerClass and getControl, can be cached, or |
| // is it OSGI constraint? |
| jfaceViewerClass = Class |
| .forName("org.eclipse.jface.viewers.Viewer"); //$NON-NLS-1$ |
| getControl = jfaceViewerClass.getMethod("getControl"); |
| } catch (Throwable e) { |
| } |
| } |
| |
| public void initializeIfNeed(Control control) { |
| Display display = control.getDisplay(); |
| if (this.display != null && this.display == display) { |
| // CSS engine was already initalized, return. |
| return; |
| |
| } |
| this.display = display; |
| try { |
| // Instantiate SWT CSS Engine |
| if (engine == null) { |
| // Search engine into Shell |
| engine = CSSXWT.getCSSEngine(control); |
| if (engine == null) { |
| // Create it and register it into Shell |
| engine = createCSSEngine(display); |
| CSSXWT.setCSSEngine(control.getShell(), engine); |
| } |
| } |
| engine.setErrorHandler(this); |
| |
| // Load style sheet content |
| if (content != null) { |
| // Style sheet come from String content |
| engine.parseStyleSheet(new StringReader(content)); |
| } else { |
| // Style sheet come from URL |
| |
| // Get URL |
| Method urlResolver = null; |
| try { |
| Class<?> fileLocatorClass = loadClass("org.eclipse.core.runtime.FileLocator"); //$NON-NLS-1$ |
| urlResolver = fileLocatorClass.getMethod( |
| "resolve", new Class[] { URL.class }); //$NON-NLS-1$ |
| } catch (Throwable e) { |
| } |
| |
| URL contentURL = url; |
| if (urlResolver != null) { |
| try { |
| contentURL = (URL) urlResolver.invoke(null, |
| new Object[] { contentURL }); |
| } catch (Throwable e) { |
| |
| } |
| } |
| |
| // Parse style sheet |
| InputStream stream = contentURL.openStream(); |
| engine.parseStyleSheet(stream); |
| stream.close(); |
| } |
| } catch (Throwable e) { |
| System.err |
| .println("Warning - could not initialize CSS styling : " + e.toString()); //$NON-NLS-1$ |
| } |
| } |
| |
| public URL getUrl() { |
| return url; |
| } |
| |
| public void setUrl(URL url) { |
| if (this.url == url || (this.url != null && this.url.equals(url))) { |
| return; |
| } |
| this.url = url; |
| reset(); |
| } |
| |
| public String getContent() { |
| return content; |
| } |
| |
| public void setContent(String content) { |
| if (this.content == content |
| || (this.content != null && this.content.equals(content))) { |
| return; |
| } |
| this.content = content; |
| reset(); |
| } |
| |
| protected void reset() { |
| display = null; |
| if (engine != null) { |
| engine.reset(); |
| engine = null; |
| } |
| } |
| |
| public void applyStyle(Object target) { |
| if (url == null && content == null && engine == null) { |
| return; |
| } |
| |
| String name = XWT.getElementName(target); |
| Control control = null; |
| if (target instanceof Control) { |
| control = (Control) target; |
| } else if (getControl != null && jfaceViewerClass.isInstance(target)) { |
| try { |
| control = (Control) getControl.invoke(target); |
| } catch (Throwable e) { |
| throw new XWTException(e); |
| } |
| } |
| if (control != null) { |
| initializeIfNeed(control); |
| if (name != null) { |
| control.setData("org.eclipse.e4.ui.css.id", name); |
| } |
| try { |
| engine.applyStyles(control, false, true); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| public CSSEngine getEngine() { |
| return engine; |
| } |
| |
| public void error(Exception e) { |
| throw new XWTException(e); |
| } |
| |
| protected Class<?> loadClass(String className) |
| throws ClassNotFoundException { |
| try { |
| return Class.forName(className); //$NON-NLS-1$ |
| } catch (ClassNotFoundException e) { |
| return Thread.currentThread().getContextClassLoader().loadClass( |
| className); |
| } |
| } |
| |
| /** |
| * Create CSS engine from {@link Display}. |
| * |
| * @param display |
| * @return |
| */ |
| protected abstract CSSEngine createCSSEngine(Display display); |
| } |