Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Background color is modified when enabling flat scroll bars #94

Closed
PyvesB opened this issue Apr 30, 2020 · 4 comments
Closed

Background color is modified when enabling flat scroll bars #94

PyvesB opened this issue Apr 30, 2020 · 4 comments

Comments

@PyvesB
Copy link
Contributor

PyvesB commented Apr 30, 2020

Hello hello,

I was playing around with a custom theme and I noticed that enabling flat scroll bars may change the background colour of the different UI elements.

Consider the following simple bit of CSS to reproduce the problem:

Composite * {
  background-color: red;
}

Tree {
  background-color: blue;
  flat-scroll-bar: false;
}

The background colour of my tree appears as blue. However, when I switch flat-scroll-bar to true, background-color: blue no longer takes precedences or may simply be ignored, the background colour of my tree turns to red.

Any idea on what might be happening? Do you know of any CSS trick that would force the background to stay blue?

Thanks in advance!

@fappel
Copy link
Owner

fappel commented Apr 30, 2020

Hm, interesting. I have a vague idea. If I remember correctly, Flat Scrollbars on trees and tables are implemented using a ScrollableAdapter which basically extends a Composite and wraps the tree or table instance at runtime. It's a bit of a 'children don't do this at home' concept. I guess that the ScrollableAdapter composite applies the Composite style setting instead of the tree background color and the tree inherits the color from the parent or something like this. Which would be a bug. of course. However, I must dig into to the code, because I currently can't remember where the css style application takes place...

@fappel
Copy link
Owner

fappel commented Apr 30, 2020

The mechanism described in my last comment might be located somewhere in com.codeaffine.eclipse.ui.swt.theme.ColorApplicator class in the swt.theme module

@PyvesB
Copy link
Contributor Author

PyvesB commented May 2, 2020

Thanks for the response!

I had a quick dig around the ColorApplicator and ScrollableAdapterContribution classes and found nothing obviously wrong. I then set a breakpoint here:

This breakpoint was only ever hit with red or white.

I noticed that there was an adapter-background CSS property defined in ScrollableAdapterContribution and modified my CSS to the following:

Composite * {
  background-color: red;
}

Tree {
  adapter-background: blue;
  flat-scroll-bar: true;
}

The breakpoint started being hit with blue through the Xiliary code, but was then hit again with red, overriding the blue colour. The call stack for red is purely Eclipse though:

Thread [main] (Suspended (breakpoint at line 299 in TreeAdapter))	
	TreeAdapter.setBackground(Color) line: 299	
	CSSSWTColorHelper.setBackground(Control, Color) line: 357	
	CSSPropertyBackgroundSWTHandler.applyCSSPropertyBackgroundColor(Object, CSSValue, String, CSSEngine) line: 77	
	CSSPropertyBackgroundSWTHandler(AbstractCSSPropertyBackgroundHandler).applyCSSProperty(Object, String, CSSValue, String, CSSEngine) line: 35	
	CSSPropertyBackgroundSWTHandler.applyCSSProperty(Object, String, CSSValue, String, CSSEngine) line: 43	
	CSSSWTEngineImpl(AbstractCSSEngine).applyCSSProperty(Object, String, CSSValue, String) line: 766	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyleDeclaration(Object, CSSStyleDeclaration, String) line: 552	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean, boolean) line: 426	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean) line: 367	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean, boolean) line: 443	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean) line: 367	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean, boolean) line: 443	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean) line: 367	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean, boolean) line: 443	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean) line: 367	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean, boolean) line: 443	
	CSSSWTEngineImpl(AbstractCSSEngine).applyStyles(Object, boolean) line: 367	
	ThemeEngine.applyStyles(Object, boolean) line: 507	
	PartRenderingEngine$7.setClassnameAndId(Object, String, String) line: 1322	
	StackRenderer(SWTPartRenderer).setCSSInfo(MUIElement, Object) line: 111	
	StackRenderer(SWTPartRenderer).styleElement(MUIElement, boolean) line: 81	
	StackRenderer.subscribeTopicActivateChanged(Event) line: 525	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 498	
	MethodRequestor.execute() line: 55	
	UIEventObjectSupplier$UIEventHandler$1.run() line: 64	
	UISynchronizer(Synchronizer).syncExec(Runnable) line: 233	
	UISynchronizer.syncExec(Runnable) line: 144	
	Display.syncExec(Runnable) line: 4889	
	E4Application$1.syncExec(Runnable) line: 212	
	UIEventObjectSupplier$UIEventHandler.handleEvent(Event) line: 61	
	EventHandlerWrapper.handleEvent(Event, Permission) line: 201	
	EventHandlerTracker.dispatchEvent(EventHandlerWrapper, Permission, int, Event) line: 197	
	EventHandlerTracker.dispatchEvent(Object, Object, int, Object) line: 1	
	EventManager.dispatchEvent(Set<Entry<K,V>>, EventDispatcher<K,V,E>, int, E) line: 230	
	ListenerQueue<K,V,E>.dispatchEventSynchronous(int, E) line: 148	
	EventAdminImpl.dispatchEvent(Event, boolean) line: 135	
	EventAdminImpl.sendEvent(Event) line: 78	
	EventComponent.sendEvent(Event) line: 39	
	EventBroker.send(String, Object) line: 52	
	UIEvents.publishEvent(String, Map<String,Object>) line: 375	
	UIEvents.publishEvent(String, MUIElement) line: 344	
	PartServiceImpl.activate(MPart, boolean, boolean) line: 757	
	PartServiceImpl.switchPerspective(MPerspective) line: 640	
	PerspectiveStackRenderer.showTab(MUIElement) line: 102	
	PerspectiveStackRenderer(LazyStackRenderer).postProcess(MUIElement) line: 97	
	PerspectiveStackRenderer.postProcess(MUIElement) line: 61	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 679	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 767	
	PartRenderingEngine.access$0(PartRenderingEngine, MUIElement) line: 738	
	PartRenderingEngine$2.run() line: 732	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 716	
	SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 69	
	SashRenderer.processContents(MElementContainer<MUIElement>) line: 137	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 675	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 767	
	PartRenderingEngine.access$0(PartRenderingEngine, MUIElement) line: 738	
	PartRenderingEngine$2.run() line: 732	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 716	
	WBWRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 69	
	WBWRenderer.processContents(MElementContainer<MUIElement>) line: 704	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 675	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 767	
	PartRenderingEngine.access$0(PartRenderingEngine, MUIElement) line: 738	
	PartRenderingEngine$2.run() line: 732	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 716	
	PartRenderingEngine$5.run() line: 1076	
	Realm.runWithDefault(Realm, Runnable) line: 336	
	PartRenderingEngine.run(MApplicationElement, IEclipseContext) line: 1039	
	E4Workbench.createAndRunUI(MApplicationElement) line: 153	
	Workbench.lambda$3(Display, WorkbenchAdvisor, int[]) line: 680	
	1217741734.run() line: not available	
	Realm.runWithDefault(Realm, Runnable) line: 336	
	Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 594	
	PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 148	
	IDEApplication.start(IApplicationContext) line: 151	
	EclipseAppHandle.run(Object) line: 196	
	EclipseAppLauncher.runApplication(Object) line: 134	
	EclipseAppLauncher.start(Object) line: 104	
	EclipseStarter.run(Object) line: 388	
	EclipseStarter.run(String[], Runnable) line: 243	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 498	
	Main.invokeFramework(String[], URL[]) line: 653	
	Main.basicRun(String[]) line: 590	
	Main.run(String[]) line: 1499	
	Main.main(String[]) line: 1472	

Two conclusions so far:

  • Eclipse's CSS engine does not treat Xiliary's custom adapted tree as a proper Tree, as it does not try to apply the background-color: blue; from my initial CSS fragment.
  • there is an ordering problem with the revised CSS, where background-color: red; from Composite * is applied after adapter-background: blue;. Unsure what heuristics Eclipse uses to define the ordering in which it applies different CSS properties, and whether these can be influenced in the CSS.

I then used the E4 CSS Spy tool and noticed that the widget name displayed was TreeAdapter, there was no mention of plain Tree anywhere. This is consistent with your statement "it wraps the tree or table instance at runtime", however in CSS land one could say it "replaces it". So I tried the following:

Composite * {
  background-color: red;
}

Tree {
  flat-scroll-bar: true;
}

TreeAdapter {
  background-color: blue;
}

And that gave the expected result! 🎉

I haven't tried other scrollable objects but I'm hoping a similar trick will just work.

In the end, not sure whether there's any bug here. Eclipse does its job in an opinionated way, but does it correctly. Xiliary does the job correctly on its own side. The two just don't quite line up in the desired way in this specific case. Unless you have an easy idea to force adapter-background to be applied after background-color, I've got a feeling that trying to solve this via code is not worth the effort. Maybe a mention in the Readme would be beneficial though?

As a side note, do you remember off hand what the difference between adapter-background and adapter-background-top-level is?

@fappel
Copy link
Owner

fappel commented May 7, 2020

Sorry for answering late, but it has been a busy week so far. And thanks for digging into the issue. Well, to me your proposal seems fair enough and accordingly I've mentioned the particular configuration scenario in the README file.

With respect to your side note: as far as I remember, the adapter-background-top-level is somehow applicable on shells that do not have a parent shell. Hence the top-level notion. Somewhere in the depths of my brain I seem to remember that this has to do something with dialog's background color of trees, for example in the preference dialog. It might be that this way it is possible to have a tree background color on the top-level shell, that is not used on a Dialog window. It might be one of the desperate measures I have done to get this thing of the ground on windows...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants