Changing the ColorScheme at runtime

Hi,

I’m using common project with eclipse theme. I have customized the eclipse theme and especially the ECLIPSE_COLOR_SCHEME, as below

 
control.putProperty(EclipseTheme.**[SIZE=2]ECLIPSE_COLOR_SCHEME[/SIZE]**, **[SIZE=2]new[/SIZE]** ColorSchemeExtension());

The color scheme customized extension is built upon some color provided by the “look and feel”. In my case I’m using [Synthetica look and feel].

How can I update the color scheme extension each time the user at runtime change the look and feel?

Thank you

Either extend from the AbstractColorScheme and override the “updateUI” method, or use “DockUI.getDefaultDockUI().addLookAndFeelColorsListener( listener );” to register a LookAndFeelColorsListener. This is the way all the default ColorSchemes work.

Using only classes from the JDK: you can add a PropertyChangeListener directly to the UIManager:

        UIManager.addPropertyChangeListener( new PropertyChangeListener(){
            public void propertyChange( PropertyChangeEvent evt ) {
                if( "lookAndFeel".equals( evt.getPropertyName() )){
                    <update>
                }
            }            
        });```

Hi,

When using the glass extension, the color are not being updated. Could you please advice?

Below is a very simple example, It contains a button and a dockable. When clicking on the button the colors of the tab and the text should be updated


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JButton;

import bibliothek.extension.gui.dock.theme.EclipseTheme;
import bibliothek.extension.gui.dock.theme.eclipse.EclipseColorScheme;
import bibliothek.extension.gui.dock.theme.eclipse.rex.RexSystemColor;
import bibliothek.gui.dock.common.CContentArea;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.theme.ThemeMap;
import tutorial.support.ColorSingleCDockable;
import tutorial.support.JTutorialFrame;

public class SingleDockables {
	private static String TAB_COLOR = "tab";
	private static String TEXT_COLOR = "text";
	public Map<String, Color> colorMap = new HashMap<String, Color>();
	
	public SingleDockables() {
		colorMap.put(TAB_COLOR, Color.YELLOW);
		colorMap.put(TEXT_COLOR, Color.RED);
		JTutorialFrame frame = new JTutorialFrame( SingleDockables.class );
		final CControl control = new CControl( frame );
		control.putProperty(EclipseTheme.ECLIPSE_COLOR_SCHEME, new GlassCustomEclipseColorScheme());
		control.setTheme(ThemeMap.KEY_ECLIPSE_THEME);
		CContentArea contentArea = control.getContentArea();
		ColorSingleCDockable white = new ColorSingleCDockable("White", Color.WHITE);
		CGrid grid = new CGrid(control);
	    grid.add(0, 0, 1, 0.25, white);
	    contentArea.deploy(grid);
	    
	    JButton button = new JButton("Change Look & Feel");
	    button.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				colorMap.put(TAB_COLOR, Color.ORANGE);
				colorMap.put(TEXT_COLOR, Color.BLUE);
				((GlassCustomEclipseColorScheme) control.getProperty(EclipseTheme.ECLIPSE_COLOR_SCHEME)).updateUI();
				
			}
		});
	    frame.add(button, BorderLayout.WEST);
		frame.destroyOnClose( control );
		frame.add(contentArea);
		frame.setVisible(true);
	}
	
	public static void main( String[] args ){
		new SingleDockables();
	}
	
	class GlassCustomEclipseColorScheme extends EclipseColorScheme {
	    @Override
	    public void updateUI() {
	        super.updateUI();
	        setColor("stack.tab.border.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.border.selected.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.border.selected.focused.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.border.selected.focuslost.glass", colorMap.get(TAB_COLOR));

	        setColor("stack.tab.top.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.top.selected.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.top.selected.focused.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.top.selected.focuslost.glass", colorMap.get(TAB_COLOR));

	        setColor("stack.tab.text.glass", colorMap.get(TEXT_COLOR));
	        setColor("stack.tab.text.selected.glass", colorMap.get(TEXT_COLOR));
	        setColor("stack.tab.text.selected.focused.glass", colorMap.get(TEXT_COLOR));
	        setColor("stack.tab.text.selected.focuslost.glass", colorMap.get(TEXT_COLOR));

	        setColor("glass.selected.center", colorMap.get(TAB_COLOR));
	        setColor("glass.selected.light", colorMap.get(TAB_COLOR));
	        setColor("glass.selected.boundary", colorMap.get(TAB_COLOR));

	        setColor("glass.focused.center", colorMap.get(TAB_COLOR));
	        setColor("glass.focused.light", colorMap.get(TAB_COLOR));
	        setColor("glass.focused.boundary", colorMap.get(TAB_COLOR));

	        setColor("stack.border.glass", Color.GRAY);
	        setColor("selection.border.glass", RexSystemColor.getBorderColor());

	        setColor("glass.paint.divider", Color.BLACK);
	        setColor("glass.paint.insertion", Color.GRAY);
	        setColor("glass.paint.line", Color.GRAY);
	    }
	}
}

Thank you

The issue is, that the Glass extension is an extension. As such it takes higher precedence than any setting that is made by the framework - and your ColorScheme looks as if it was made by the framework. There are different solutions of this problem:

  • Write an extension like in the example below. Since your extension is registered the latest it gets the highest possible precedence and will override anything else.
  • Directly access the ColorManager (DockController.getColors()) and register your changes there. You can either set a ColorScheme with Priority=CLIENT or directly override some entries. If you use a ColorScheme make sure that it does not extend EclipseColorScheme and does return values only for the colors you really want to override.
  • Don’t extend from EclipseColorScheme but from DefaultColorScheme and copy the colors from the EclipseColorScheme (if possible by the application, not manually).

You have to decide for yourself which solution fits best. I would not advice the last one because it involves copying values around, but the other solutions are all good solutions.


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;

import tutorial.support.ColorSingleCDockable;
import tutorial.support.JTutorialFrame;
import bibliothek.extension.gui.dock.theme.EclipseTheme;
import bibliothek.extension.gui.dock.theme.eclipse.EclipseColorScheme;
import bibliothek.extension.gui.dock.theme.eclipse.rex.RexSystemColor;
import bibliothek.gui.DockController;
import bibliothek.gui.dock.common.CContentArea;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.theme.ThemeMap;
import bibliothek.gui.dock.themes.ColorScheme;
import bibliothek.gui.dock.themes.color.DefaultColorScheme;
import bibliothek.gui.dock.util.extension.Extension;
import bibliothek.gui.dock.util.extension.ExtensionName;

public class Dock59 {
	private static String TAB_COLOR = "tab";
	private static String TEXT_COLOR = "text";
	public Map<String, Color> colorMap = new HashMap<String, Color>();
	private GlassCustomEclipseColorScheme scheme = new GlassCustomEclipseColorScheme();
	
	public Dock59() {
		colorMap.put(TAB_COLOR, Color.YELLOW);
		colorMap.put(TEXT_COLOR, Color.RED);
		JTutorialFrame frame = new JTutorialFrame( Dock59.class );
		final CControl control = new CControl( frame );
		
//		control.putProperty(EclipseTheme.ECLIPSE_COLOR_SCHEME, new GlassCustomEclipseColorScheme());
		
		control.getController().getExtensions().add( new GlassCustomExtension() );
		
		control.setTheme(ThemeMap.KEY_ECLIPSE_THEME);
		
		CContentArea contentArea = control.getContentArea();
		ColorSingleCDockable white = new ColorSingleCDockable("White", Color.WHITE);
		CGrid grid = new CGrid(control);
	    grid.add(0, 0, 1, 0.25, white);
	    contentArea.deploy(grid);
	    
	    JButton button = new JButton("Change Look & Feel");
	    button.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				colorMap.put(TAB_COLOR, Color.ORANGE);
				colorMap.put(TEXT_COLOR, Color.BLUE);
				
				scheme.updateUI();
				
				
			}
		});
	    frame.add(button, BorderLayout.WEST);
		frame.destroyOnClose( control );
		frame.add(contentArea);
		frame.setVisible(true);
	}
	
	public static void main( String[] args ){
		new Dock59();
	}
	
	private class GlassCustomExtension implements Extension{
		@Override
		public void install( DockController controller ){
			// ignore
		}

		@Override
		public <E> Collection<E> load( DockController controller, ExtensionName<E> extension ){
			List<E> result = new ArrayList<E>();
			
			if( extension.getName().equals( ColorScheme.EXTENSION_NAME )){
				Object parameterValue = extension.get( ColorScheme.COLOR_SCHEME_PARAMETER );
				if( parameterValue instanceof EclipseColorScheme ){
					result.add( (E)scheme );
				}
			}
			
			return result;
		}

		@Override
		public void uninstall( DockController controller ){
			// ignore
		}
	}
	
	private class GlassCustomEclipseColorScheme extends DefaultColorScheme {
	    @Override
	    public void updateUI() {
	        super.updateUI();
	        setColor("stack.tab.border.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.border.selected.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.border.selected.focused.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.border.selected.focuslost.glass", colorMap.get(TAB_COLOR));

	        setColor("stack.tab.top.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.top.selected.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.top.selected.focused.glass", colorMap.get(TAB_COLOR));
	        setColor("stack.tab.top.selected.focuslost.glass", colorMap.get(TAB_COLOR));

	        setColor("stack.tab.text.glass", colorMap.get(TEXT_COLOR));
	        setColor("stack.tab.text.selected.glass", colorMap.get(TEXT_COLOR));
	        setColor("stack.tab.text.selected.focused.glass", colorMap.get(TEXT_COLOR));
	        setColor("stack.tab.text.selected.focuslost.glass", colorMap.get(TEXT_COLOR));

	        setColor("glass.selected.center", colorMap.get(TAB_COLOR));
	        setColor("glass.selected.light", colorMap.get(TAB_COLOR));
	        setColor("glass.selected.boundary", colorMap.get(TAB_COLOR));

	        setColor("glass.focused.center", colorMap.get(TAB_COLOR));
	        setColor("glass.focused.light", colorMap.get(TAB_COLOR));
	        setColor("glass.focused.boundary", colorMap.get(TAB_COLOR));

	        setColor("stack.border.glass", Color.GRAY);
	        setColor("selection.border.glass", RexSystemColor.getBorderColor());

	        setColor("glass.paint.divider", Color.BLACK);
	        setColor("glass.paint.insertion", Color.GRAY);
	        setColor("glass.paint.line", Color.GRAY);
	    }
	}
}```