Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2015 Angelo Zerr and others.
* Copyright (c) 2008, 2026 Angelo Zerr and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -96,6 +96,15 @@ public static boolean hasColorDefinitionAsValue(CSSValue value) {
return false;
}

/**
* Returns whether the value looks like a color definition reference but
* resolves neither to a color, such as an SWT system color, nor to a definition.
*/
public static boolean isUnresolvedColorDefinition(CSSValue value) {
return hasColorDefinitionAsValue(value) && getRGBA(value) == null
&& findColorByDefinition(((CssText) value).value()) == null;
}

public static boolean hasColorDefinitionAsValue(String name) {
if (name.startsWith(COLOR_DEFINITION_MARKER)) {
return !HEX_COLOR_VALUE_PATTERN.matcher(name).matches();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,44 @@ public static CSS2FontProperties resolveRelativeSize(CSS2FontProperties fontProp
return resolved;
}

/**
* Returns the properties unchanged unless the family references an unresolved
* font definition; then returns the font the element had before it was styled,
* with the size, weight and style set in CSS applied on top.
*/
public static CSS2FontProperties resolveUnresolvedFontDefinition(CSS2FontProperties fontProperties,
CSSElementContext context, Widget widget) {
if (!hasFontDefinitionAsFamily(fontProperties)
|| findFontDataByDefinition((CssText) fontProperties.getFamily()).length > 0) {
return fontProperties;
}
// not the current font, which may carry styling of another state such as :selected
FontData baseFontData = getBaseFontData(context);
if (baseFontData == null) {
baseFontData = getFirstFontData(getFont(widget));
}
if (baseFontData == null) {
return fontProperties;
}
int baseStyle = baseFontData.getStyle();
CSS2FontProperties resolved = new CSS2FontPropertiesImpl();
resolved.setFamily(new CssText(CssText.Kind.STRING, baseFontData.getName()));
resolved.setSize(new CssDimension(baseFontData.getHeight(), CssUnit.PT));
resolved.setSizeFromCSS(true);
resolved.setWeight(new CssText(CssText.Kind.IDENT, (baseStyle & SWT.BOLD) != 0 ? "bold" : "normal"));
resolved.setStyle(new CssText(CssText.Kind.IDENT, (baseStyle & SWT.ITALIC) != 0 ? "italic" : "normal"));
if (fontProperties.isSizeFromCSS()) {
resolved.setSize(fontProperties.getSize());
}
if (fontProperties.getWeight() != null) {
resolved.setWeight(fontProperties.getWeight());
}
if (fontProperties.getStyle() != null) {
resolved.setStyle(fontProperties.getStyle());
}
return resolved;
}

private static boolean isRelativeSize(CssPrimitive size) {
if (isKeyword(size, "larger") || isKeyword(size, "smaller")) {
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2014 Angelo Zerr and others.
* Copyright (c) 2008, 2026 Angelo Zerr and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -44,6 +44,10 @@ public CSSValueSWTColorConverterImpl() {
@Override
public Color convert(CSSValue value, CSSEngine engine, Object context)
throws DOMException {
if (CSSSWTColorHelper.isUnresolvedColorDefinition(value)) {
// treated like unset, so the widget keeps its default color instead of black
return null;
Comment on lines +47 to +49
}
Display display = (Display) context;
Color color = CSSSWTColorHelper.getSWTColor(value, display);
if (color == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2015 Angelo Zerr and others.
* Copyright (c) 2008, 2026 Angelo Zerr and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -86,6 +86,11 @@ public void applyCSSPropertyBackgroundColor(Object element, CSSValue value,
if (grad == null) {
return; // warn?
}
if (grad.getRGBs().isEmpty()) {
// no stop resolved, treated like unset
resetGradient(widget, pseudo);
return;
}
if (widget instanceof CTabItem) {
CTabFolder folder = ((CTabItem) widget).getParent();
Color[] colors = CSSSWTColorHelper.getSWTColors(grad,
Expand All @@ -105,6 +110,20 @@ public void applyCSSPropertyBackgroundColor(Object element, CSSValue value,
}
}

private static void resetGradient(Widget widget, String pseudo) {
if (widget instanceof CTabItem item) {
if ("selected".equals(pseudo)) {
item.getParent().setSelectionBackground(null, null, true);
} else {
item.getParent().setBackground(null, null, true);
}
} else if (widget instanceof Control control) {
GradientBackgroundListener.remove(control);
CSSSWTColorHelper.setBackground(control, null);
CompositeElement.setBackgroundOverriddenByCSSMarker(widget);
}
}

@Override
public void applyCSSPropertyBackgroundImage(Object element, CSSValue value,
String pseudo, CSSEngine engine) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ private static void setFont(Widget widget, Font font) {

/**
* Resolves a relative font size against the font the element had before it was
* styled, so that reapplying a style does not scale an already scaled font.
* styled, and an unresolved font definition against the widget's own font.
*/
private static CSS2FontProperties resolveRelativeSize(CSS2FontProperties fontProperties,
CSSElementContext context) {
return CSSSWTFontHelper.resolveRelativeSize(fontProperties, CSSSWTFontHelper.getBaseFontData(context));
private static CSS2FontProperties resolve(CSS2FontProperties fontProperties, CSSElementContext context,
Widget widget) {
CSS2FontProperties resolved = CSSSWTFontHelper.resolveRelativeSize(fontProperties,
CSSSWTFontHelper.getBaseFontData(context));
return CSSSWTFontHelper.resolveUnresolvedFontDefinition(resolved, context, widget);
}

private static void updateChildrenFonts(CTabFolder folder, Font font) {
Expand Down Expand Up @@ -234,7 +236,7 @@ public void onAllCSSPropertiesApplied(Object element, CSSEngine engine)
if (fontProperties == null) {
return;
}
Font font = (Font) engine.convert(resolveRelativeSize(fontProperties, context), Font.class, widget);
Font font = (Font) engine.convert(resolve(fontProperties, context, widget), Font.class, widget);
setFont(widget, font);
}

Expand Down Expand Up @@ -323,7 +325,7 @@ private void applyStyles(CSSStyleDeclaration styleDeclaration,
try {
// set the font
Font font = (Font) engine.convert(
resolveRelativeSize(fontProperties, engine.getCSSElementContext(item)),
resolve(fontProperties, engine.getCSSElementContext(item), item),
Font.class, item);
setFont(item, font);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010, 2019 IBM Corporation and others.
* Copyright (c) 2010, 2026 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -14,38 +14,34 @@
package org.eclipse.e4.ui.internal.css.swt;

import org.eclipse.e4.ui.internal.css.swt.definition.IColorAndFontProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;

public class ColorAndFontUtil {

static IColorAndFontProvider colorAndFontProvider = null;
private static final IColorAndFontProvider DEFAULT_PROVIDER = new JFaceColorAndFontProvider();

static {
if (FrameworkUtil.getBundle(ColorAndFontUtil.class).getBundleContext() != null) {
ServiceTracker<IColorAndFontProvider, IColorAndFontProvider> colorAndFontProviderTracker = new ServiceTracker<>(
FrameworkUtil.getBundle(ColorAndFontUtil.class).getBundleContext(),
IColorAndFontProvider.class.getName(), null) {
@Override
public IColorAndFontProvider addingService(ServiceReference<IColorAndFontProvider> reference) {
// this is needed so that the unit test can exchange the color and font provider
// with a mocked version
colorAndFontProvider = super.addingService(reference);
return colorAndFontProvider;
}
};
colorAndFontProviderTracker.open();
private static final ServiceTracker<IColorAndFontProvider, IColorAndFontProvider> TRACKER = openTracker();

private static ServiceTracker<IColorAndFontProvider, IColorAndFontProvider> openTracker() {
BundleContext context = FrameworkUtil.getBundle(ColorAndFontUtil.class).getBundleContext();
if (context == null) {
return null;
}
ServiceTracker<IColorAndFontProvider, IColorAndFontProvider> tracker = new ServiceTracker<>(context,
IColorAndFontProvider.class, null);
tracker.open();
return tracker;
}

/**
* Util method to access the OSGI immediate component IColorAndFontProvider
* defined in the same bundle as we do life in the same bundle we do not track
* its life-cycle (as it is the same as our life-cycle)
* Returns the registered {@link IColorAndFontProvider} service, or a provider
* backed by the JFace registries if none is registered.
*/
public static IColorAndFontProvider getColorAndFontProvider() {
return colorAndFontProvider;
IColorAndFontProvider provider = TRACKER != null ? TRACKER.getService() : null;
return provider != null ? provider : DEFAULT_PROVIDER;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2013, 2016 IBM Corporation and others.
* Copyright (c) 2013, 2026 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -10,34 +10,30 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
******************************************************************************/

package org.eclipse.ui.internal.themes;
*******************************************************************************/
package org.eclipse.e4.ui.internal.css.swt;

import org.eclipse.e4.ui.internal.css.swt.definition.IColorAndFontProvider;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.ui.internal.Workbench;
import org.eclipse.ui.themes.ITheme;
import org.osgi.service.component.annotations.Component;

/**
* @since 3.5
* Resolves color and font definitions from the JFace registries, which the
* workbench keeps in sync with its current theme.
*/
@Component
public class ColorAndFontProviderImpl implements IColorAndFontProvider {
class JFaceColorAndFontProvider implements IColorAndFontProvider {

@Override
public FontData[] getFont(String symbolicName) {
return getCurrentTheme().getFontRegistry().getFontData(symbolicName);
FontRegistry registry = JFaceResources.getFontRegistry();
// getFontData returns the default font for unknown keys
return registry.hasValueFor(symbolicName) ? registry.getFontData(symbolicName) : null;
}

@Override
public RGB getColor(String symbolicName) {
return getCurrentTheme().getColorRegistry().getRGB(symbolicName);
}

private ITheme getCurrentTheme() {
return Workbench.getInstance().getThemeManager().getCurrentTheme();
return JFaceResources.getColorRegistry().getRGB(symbolicName);
}
}
3 changes: 1 addition & 2 deletions bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -139,5 +139,4 @@ Automatic-Module-Name: org.eclipse.ui.workbench
Service-Component: OSGI-INF/org.eclipse.ui.internal.BindingToModelProcessor.xml,
OSGI-INF/org.eclipse.ui.internal.CommandToModelProcessor.xml,
OSGI-INF/org.eclipse.ui.internal.ContextToModelProcessor.xml,
OSGI-INF/org.eclipse.ui.internal.WindowsDefenderConfigurator.xml,
OSGI-INF/org.eclipse.ui.internal.themes.ColorAndFontProviderImpl.xml
OSGI-INF/org.eclipse.ui.internal.WindowsDefenderConfigurator.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2017 IBM Corporation and others.
* Copyright (c) 2004, 2026 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -96,12 +96,13 @@ public static synchronized void disposeManager() {
private ITheme currentTheme;

private final IPropertyChangeListener currentThemeListener = event -> {
firePropertyChange(event);
// JFace first, as the CSS engine resolves definitions from the JFace registries
if (event.getSource() instanceof FontRegistry) {
JFaceResources.getFontRegistry().put(event.getProperty(), (FontData[]) event.getNewValue());
} else if (event.getSource() instanceof ColorRegistry) {
JFaceResources.getColorRegistry().put(event.getProperty(), (RGB) event.getNewValue());
}
firePropertyChange(event);
};

private ColorRegistry defaultThemeColorRegistry;
Expand Down Expand Up @@ -337,7 +338,6 @@ public void setCurrentTheme(String id) {
init();
ITheme oldTheme = currentTheme;
if (WorkbenchThemeManager.getInstance().doSetCurrentTheme(id)) {
firePropertyChange(CHANGE_CURRENT_THEME, oldTheme, getCurrentTheme());
if (oldTheme != null) {
oldTheme.removePropertyChangeListener(currentThemeListener);
}
Expand All @@ -361,6 +361,7 @@ public void setCurrentTheme(String id) {
for (String key : themeFonts.getKeySet()) {
jfaceFonts.put(key, themeFonts.getFontData(key));
}
firePropertyChange(CHANGE_CURRENT_THEME, oldTheme, getCurrentTheme());
if (oldTheme != null && eventBroker != null) {
eventBroker.send(UIEvents.UILifeCycle.THEME_CHANGED, null);
eventBroker.send(UIEvents.UILifeCycle.THEME_DEFINITION_CHANGED, context.get(MApplication.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.e4.ui.css.core.css2.CSS2FontHelper;
Expand All @@ -32,13 +33,22 @@
import org.eclipse.e4.ui.internal.css.swt.definition.IColorAndFontProvider;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;
import org.junit.jupiter.api.AfterEach;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;

public abstract class CSSSWTHelperTestCase {

protected static final String CSS_ITALIC = CSS2FontHelper.getFontStyle(true);
protected static final String CSS_BOLD = CSS2FontHelper.getFontWeight(true);

private final List<ServiceRegistration<IColorAndFontProvider>> registrations = new ArrayList<>();

@AfterEach
void unregisterProviders() {
registrations.forEach(ServiceRegistration::unregister);
}

protected void registerFontProviderWith(String expectedSymbolicName, String family, int size, int style) {
IColorAndFontProvider provider = mock(IColorAndFontProvider.class);
doReturn(new FontData[] { new FontData(family, size, style) }).when(provider).getFont(expectedSymbolicName);
Expand All @@ -49,12 +59,11 @@ protected void registerColorProviderWith(String expectedSymbolicName, RGB rgb) {
IColorAndFontProvider provider = mock(IColorAndFontProvider.class);
doReturn(rgb).when(provider).getColor(expectedSymbolicName);
registerProvider(provider);

}

private void registerProvider(final IColorAndFontProvider provider) {
FrameworkUtil.getBundle(getClass()).getBundleContext().registerService(IColorAndFontProvider.class, provider,
null);
registrations.add(FrameworkUtil.getBundle(getClass()).getBundleContext()
.registerService(IColorAndFontProvider.class, provider, null));
}

protected CSS2FontProperties fontProperties(String family) {
Expand Down
Loading
Loading