package tutorial.core.basics;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import tutorial.support.JTutorialFrame;
import tutorial.support.Tutorial;
import bibliothek.extension.gui.dock.theme.BubbleTheme;
import bibliothek.gui.DockController;
import bibliothek.gui.DockTheme;
import bibliothek.gui.dock.DefaultDockable;
import bibliothek.gui.dock.FlapDockStation;
import bibliothek.gui.dock.ScreenDockStation;
import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.station.split.SplitDockGrid;
import bibliothek.gui.dock.themes.ThemeManager;
import bibliothek.gui.dock.util.BackgroundAlgorithm;
import bibliothek.gui.dock.util.BackgroundComponent;
import bibliothek.gui.dock.util.BackgroundPaint;
import bibliothek.gui.dock.util.BackgroundPanel;
import bibliothek.gui.dock.util.ConfiguredBackgroundPanel;
import bibliothek.gui.dock.util.PaintableComponent;
import bibliothek.gui.dock.util.Transparency;
@Tutorial( id="Transparency", title="Transparency" )
public class TransparencyExample {
/* (Almost) all components of the framework use a special strategy to paint their content. Clients
* can replace that algorithm and paint the components in any way the like. They can also configure
* most of the components to be transparent. This might not make sense for all components, but this example
* shows how to configure all components anyway */
public static void main( String[] args ) throws IOException{
/* setting up frame and controller as usual */
JTutorialFrame frame = new JTutorialFrame( TransparencyExample.class );
DockController controller = new DockController();
controller.setRootWindow( frame );
frame.destroyOnClose( controller );
/* The background image we are going to use, it will shine through the application */
BufferedImage image = ImageIO.read( BackgroundPanel.class.getResource( "/data/tutorial/shadowsAndLight_GregMartin.jpg" ) );
ImagePanel contentPane = new ImagePanel( image );
frame.add( contentPane );
/* There are several possibilities how to apply our custom background. The easiest one is to use the properties
* to replace the default strategy. */
controller.getProperties().set( DockTheme.BACKGROUND_PAINT, new CustomPaint() );
/* By accessing the ThemeManager we can set a strategy that is used by only one type of component. In this case
* we set a custom identifier which will later be used by our "BackgroundDockable" which is shown later in this
* example. */
controller.getThemeManager().setBackgroundPaint( ThemeManager.BACKGROUND_PAINT + ".custom", new CustomPaint() );
/* We can apply different themes. Depending on the theme we might need to make some additional addjustements
* to create a good looking application. */
// controller.setTheme( new EclipseTheme() );
controller.setTheme( new BubbleTheme() );
// controller.setTheme( new BasicTheme() );
// controller.setTheme( new FlatTheme() );
/* And now we set up different DockStations and Dockables */
SplitDockStation splitDockStation = new SplitDockStation();
controller.add( splitDockStation );
contentPane.add( splitDockStation, BorderLayout.CENTER );
SplitDockGrid grid = new SplitDockGrid();
grid.addDockable( 0, 0, 100, 20, new BackgroundDockable( "Red", Color.RED ));
grid.addDockable( 0, 20, 30, 50, new BackgroundDockable( "Blue", Color.BLUE ));
grid.addDockable( 0, 70, 30, 30, new BackgroundDockable( "Yellow", Color.YELLOW ));
grid.addDockable( 30, 20, 80, 80, new BackgroundDockable( "White", Color.WHITE ));
grid.addDockable( 30, 20, 80, 80, new BackgroundDockable( "Black", Color.BLACK ));
splitDockStation.dropTree( grid.toTree() );
FlapDockStation flapDockStation = new FlapDockStation();
controller.add( flapDockStation );
flapDockStation.add( new BackgroundDockable( "Green", Color.GREEN ));
contentPane.add( flapDockStation.getComponent(), BorderLayout.NORTH );
ScreenDockStation screenDockStation = new ScreenDockStation( controller.getRootWindowProvider() );
controller.add( screenDockStation );
/* Now we make all frames and windows visible. */
frame.setVisible( true );
screenDockStation.setShowing( true );
}
/* We use this JPanel to paint an interesting background */
private static class ImagePanel extends JPanel{
private BufferedImage image;
public ImagePanel( BufferedImage image ){
super( new BorderLayout() );
this.image = image;
}
@Override
protected void paintComponent( Graphics g ){
super.paintComponent( g );
int width = getWidth();
int height = getHeight();
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
int x = (imageWidth - width) / 2;
int y = (imageHeight - height) / 2;
g.drawImage( image, 0, 0, width, height, x, y, x+width, y+height, this );
}
}
/* This is our custom painting algorithm. We do not actually paint something new, we just use the interface
* to configure the existing components. */
private static class CustomPaint implements BackgroundPaint{
public void install( BackgroundComponent component ){
/* Any component that is using this algorithm is configured to be transparent */
component.setTransparency( Transparency.TRANSPARENT );
}
public void uninstall( BackgroundComponent component ){
/* We should undo a configuration once we no longer manage a component */
component.setTransparency( Transparency.DEFAULT );
}
public void paint( BackgroundComponent background, PaintableComponent paintable, Graphics g ){
// we do not need to do anything here
}
}
/* This is a specialized Dockable, it contains a single panel. If that panel would not be transparent, then
* it would show a color. */
private static class BackgroundDockable extends DefaultDockable{
private BackgroundPanel panel;
private BackgroundAlgorithm background;
public BackgroundDockable( String title, Color color ){
super( title );
/* We use a ConfiguredBackgroundPanel: it already offers methods to use a replaceable strategy
* for painting and supports transparency. */
panel = new ConfiguredBackgroundPanel( Transparency.SOLID );
panel.setBackground( color );
add( panel );
/* And we need a connection between our panel and the framework. The connection has a
* type (called "kind") and a unique identifier. The identifier matches the one identifier we
* used to register our speical background algorithm. */
background = new BackgroundAlgorithm( BackgroundComponent.KIND.append( "custom" ), ThemeManager.BACKGROUND_PAINT + ".custom" ){
public Component getComponent(){
return panel;
}
};
panel.setBackground( background );
}
@Override
public void setController( DockController controller ){
super.setController( controller );
/* The connection between panel and framework needs to know the current DockController in
* order to work. */
background.setController( controller );
}
}
}