Theme Troubles

Hi there.

I’m have a great deal of trouble getting the look I desire. I’m really struggling to find my way around themes as the structure of them is not intuitive to me.

I wish to base it off of the Flat theme. Changing the position of the tabs was easy enough, but I am really struggling to do the following:-
Change the default icons
Make a rounded border (where do I set the border factory?)
Get rid of the bar on the left when views are stacked
Make the title bars slightly thinner
Get rid of the border shadow
Lessen the spacing between views slightly

While it is understandable that some of these things would require an override, such as changing the way the border is drawn, others seem like they should be relatively simple to change, but I can’t see any way without overriding lots of stuff.

Which of these things actually are trivial matters and which require a little more? How should I go about tackling these?

Many thanks.

Some things will be harder than other things, but all of this can be done. I did not test everything that I just wrote, so if something does not work, or you don’t understand it, ask again.

I assume you have an own Theme-class (perhaps extending FlatTheme).

Change the default icons

DockController.getIcons() gives you the IconManager. Call “setIconTheme” from your “DockTheme.install” method to set new icons. Have a look at the file “src/data/icons.ini” (in Core) and to “src/data/bibliothek/gui/dock/icons/icons.ini” (Common) to get all the keys that are used.

Get rid of the bar on the left when views are stacked

Use the NoStackTheme: instead of “setTheme( myTheme )” you call “setTheme( new NoStackTheme( myTheme ))”.

Make the title bars slightly thinner

The size of the title depends on the icons (which you replaced) and the font. Call DockController.getFonts() to get access to all the fonts. All the keys for fonts are stored in the interface “DockFont”.

You could also implement a new “DockTitle”. Several titles already exist and you may want to subclass one of them. In the newest guide for Core there is a chapter dealing with how to replace titles.

I can write you some sample code, because this is perhaps the hardest item on this page.

Lessen the spacing between views slightly

SplitDockStation.setDividerSize(…)

Make a rounded border (where do I set the border factory?)
Get rid of the border shadow

These belong together, the shadow is part of the border.
Have a look at “FlatDisplayerFactory” and how it creates DockableDisplayers. Now create your own factory which sets up a DockableDisplayer with your new border. On your “MyTheme extends FlatTheme” call “setDisplayerFactory” and “setSplitDisplayFactory” to replace the normal factory.

Thanks Beni.

I’ve changed the font and icons, narrowed the spacing and made it a NoStackTheme.

I’m still struggling with the other issues. The title bars have not narrowed, and this seems to be because the preferredSize of buttons is hardcoded in FlatMenu.Button. Would the only way around this be to extend several classes and make several overrides to change this? Would it make it easier to switch to extending BasicTheme?

My head is hurting a bit from trying to get around it all, so I need to take a break from this for now, so I haven’t looked too much into changing the border, yet. :stuck_out_tongue:

I did not remember that tiny detail :frowning: . In some future Version I have to get rid of this minimum size, but for now you have to use a workaround. Have a look at the „CustomTheme“ in this example, it replaces the buttons:


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import bibliothek.extension.gui.dock.theme.FlatTheme;
import bibliothek.gui.DockController;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.action.ActionType;
import bibliothek.gui.dock.action.DropDownAction;
import bibliothek.gui.dock.action.view.ActionViewConverter;
import bibliothek.gui.dock.action.view.ViewGenerator;
import bibliothek.gui.dock.action.view.ViewTarget;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.FontMap;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.intern.theme.CFlatTheme;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.themes.basic.action.BasicButtonModel;
import bibliothek.gui.dock.themes.basic.action.BasicDropDownButtonHandler;
import bibliothek.gui.dock.themes.basic.action.BasicTitleViewItem;
import bibliothek.gui.dock.themes.basic.action.BasicTrigger;
import bibliothek.gui.dock.themes.basic.action.buttons.BasicMiniButton;
import bibliothek.gui.dock.themes.basic.action.buttons.DropDownMiniButton;
import bibliothek.gui.dock.themes.basic.action.buttons.MiniButton;
import bibliothek.gui.dock.util.font.GenericFontModifier;

public class Dock11 {

	public static SingleCDockable createDockable( String title, Color color ){
		JPanel panel = new JPanel();
		panel.setOpaque(true);
		panel.setBackground(color);
		DefaultSingleCDockable dockable = new DefaultSingleCDockable(title, title, panel);

		dockable.setDefaultLocation(ExtendedMode.MINIMIZED, CLocation.base().minimalEast());
		dockable.setDefaultLocation(ExtendedMode.EXTERNALIZED, CLocation.external(0, 0, 300, 300));

		GenericFontModifier font = new GenericFontModifier();
		font.setSizeDelta(true);
		font.setSize(-4);
		
		dockable.getFonts().setFont( FontMap.FONT_KEY_TITLE, font );
		dockable.getFonts().setFont( FontMap.FONT_KEY_TITLE_FOCUSED, font );
		
		return dockable;
	}

	public static void main( String[] args ){
		SwingUtilities.invokeLater(new Runnable(){
			public void run(){
				JFrame frame = new JFrame("Demo");
				CControl control = new CControl(frame);

				// ignore @deprecated
				control.setTheme(new CFlatTheme(control, new CustomTheme()));
				
				frame.add(control.getContentArea(), BorderLayout.CENTER);

				CGrid grid = new CGrid(control);

				grid = new CGrid(control);
				grid.add(0, 0, 1, 1, createDockable("Yellow", Color.YELLOW));
				grid.add(0, 1, 1, 1, createDockable("Red", Color.RED));
				control.getContentArea().deploy(grid);

				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setBounds(20, 20, 400, 400);
				frame.setVisible(true);
			}
		});
	}

	private static class CustomTheme extends FlatTheme{
		@Override
		public void install( DockController controller ){
			super.install(controller);
	        controller.getActionViewConverter().putTheme( ActionType.DROP_DOWN, ViewTarget.TITLE,
	                new ViewGenerator<DropDownAction, BasicTitleViewItem<JComponent>>(){
	            public BasicTitleViewItem<JComponent> create( ActionViewConverter converter, DropDownAction action, Dockable dockable ){
	                BasicDropDownButtonHandler handler = new BasicDropDownButtonHandler( action, dockable );
	                DropDownMiniButton button = new DropDownMiniButton( handler );
	                
	                // here
	                button.setPreferredSize(new Dimension(10, 5));
	                
	                handler.setModel( button.getModel() );
	                button.setMouseOverBorder( BorderFactory.createEtchedBorder() );
	                return handler;
	            }
	        });
		}
		
		@Override
		protected MiniButton<BasicButtonModel> createTitleMiniButton( BasicTrigger trigger ){
	        BasicMiniButton button = new BasicMiniButton( trigger );
	        button.setMouseOverBorder( BorderFactory.createEtchedBorder() );
	        button.setNormalSelectedBorder( BorderFactory.createEtchedBorder() );
	        
	        // here
	        button.setPreferredSize(new Dimension(5, 5)); 
	        
	        return button;
		}
	}
}```

And this is an example with a custom border. I know, it is not very intuitive… the borders were never intended to be replaceable and therefore they need some “convincing”.


import java.awt.BorderLayout;
import java.awt.Color;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;

import bibliothek.extension.gui.dock.theme.FlatTheme;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.FontMap;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.intern.theme.CFlatTheme;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.station.DockableDisplayer.Location;
import bibliothek.gui.dock.themes.basic.BasicDisplayerFactory;
import bibliothek.gui.dock.themes.basic.BasicDockableDisplayer;
import bibliothek.gui.dock.title.DockTitle;
import bibliothek.gui.dock.util.font.GenericFontModifier;

public class Dock13 {

	public static SingleCDockable createDockable( String title, Color color ){
		JPanel panel = new JPanel();
		panel.setOpaque(true);
		panel.setBackground(color);
		DefaultSingleCDockable dockable = new DefaultSingleCDockable(title, title, panel);

		dockable.setDefaultLocation(ExtendedMode.MINIMIZED, CLocation.base().minimalEast());
		dockable.setDefaultLocation(ExtendedMode.EXTERNALIZED, CLocation.external(0, 0, 300, 300));

		GenericFontModifier font = new GenericFontModifier();
		font.setSizeDelta(true);
		font.setSize(-4);

		dockable.getFonts().setFont(FontMap.FONT_KEY_TITLE, font);
		dockable.getFonts().setFont(FontMap.FONT_KEY_TITLE_FOCUSED, font);

		return dockable;
	}

	public static void main( String[] args ){
		SwingUtilities.invokeLater(new Runnable(){
			public void run(){
				JFrame frame = new JFrame("Demo");
				CControl control = new CControl(frame);

				// ignore @deprecated
				control.setTheme(new CFlatTheme(control, new CustomTheme()));

				frame.add(control.getContentArea(), BorderLayout.CENTER);

				CGrid grid = new CGrid(control);

				grid = new CGrid(control);
				grid.add(0, 0, 1, 1, createDockable("Yellow", Color.YELLOW));
				grid.add(0, 1, 1, 1, createDockable("Red", Color.RED));
				control.getContentArea().deploy(grid);

				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setBounds(20, 20, 400, 400);
				frame.setVisible(true);
			}
		});
	}

	private static class CustomTheme extends FlatTheme {
		public CustomTheme(){
			setSplitDisplayFactory(new CustomDisplayerFactory());
		}
	}

	private static class CustomDisplayerFactory extends BasicDisplayerFactory {
		@Override
		protected BasicDockableDisplayer create( DockStation station, Dockable dockable, DockTitle title, Location location ){
			BasicDockableDisplayer displayer = new BasicDockableDisplayer(station, dockable, title, location){
				@Override
				protected Border getDefaultBorder(){
					return BorderFactory.createLineBorder( Color.BLUE, 5 );
				}
			};
			return displayer;
		}
	}
}```

Beni, this has been a huge help. Thank you!