package net.xoetrope.swing.app;
import java.awt.Color;
import net.xoetrope.xui.XContentHolder;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.SystemColor;
import java.util.ArrayList;
import java.util.Hashtable;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import net.xoetrope.swing.docking.XDockable;
import net.xoetrope.swing.docking.XDockingPanel;
import net.xoetrope.swing.util.XRoundOnTopBorder;
import net.xoetrope.xui.XProject;
import net.xoetrope.xui.XProjectManager;
import net.xoetrope.xui.helper.XTranslator;
import net.xoetrope.xui.style.XStyle;
import net.xoetrope.xui.style.XStyleEx;
import net.xoetrope.xui.style.XStyleManager;
/**
* A wrapper for a docking components. Represents a target window
* see http://www.javalobby.org/java/forums/t52990.html and
* https://flexdock.dev.java.net/
* <p>Copyright: Copyright (c) Xoetrope Ltd., 1998-2005<br>
* License: see license.txt
* @version $Revision: 1.1 $
*/
public class XDockableFrame extends XDockingPanel implements XContentHolder
{
// private String content;
private String iconName;
private String title;
private String sidebar;
private boolean minimized, maximized, clearState;
private boolean canClose, canDock, canDrag, canZoom, canMinimize, hasDockingTitle;
private Dimension preferredSize;
private Hashtable nextAttributes;
private XProject currentProject;
private ArrayList dockables;
/**
* Creates a new instance of XDockableFrame
*/
public XDockableFrame()
{
super( null );
currentProject = XProjectManager.getCurrentProject();
clearState = true;
// Style the panel
XStyleManager sm = currentProject.getStyleManager();
if ( sm.hasStyle( "dockingPanel" )) {
XStyle dockingStyle = sm.getStyle( "dockingPanel" );
if ( dockingStyle instanceof XStyleEx ) {
XStyleEx exStyle = (XStyleEx)dockingStyle;
int idx = exStyle.getStyleIndex( "border" );
if ( idx > 0 ) {
Color borderColor = dockingStyle.getStyleAsColor( XStyle.COLOR_FORE );
Object obj = exStyle.getStyleValue( idx );
if ( obj != null ) {
String borderStyle = (String)obj.toString();
if ( "1".equals( borderStyle ))
setBorder( new XRoundOnTopBorder( borderColor ));
}
}
}
}
else
setBorder( new XRoundOnTopBorder( Color.black ));//new LineBorder( Color.black, 1 ));
canClose = canDock = canDrag = canMinimize = hasDockingTitle = true;
dockables = new ArrayList();
}
/**
* Set the content for the component
* @param pageName the new contents
*/
public void setContent( String pageName )
{
// content = pageName;
}
/**
* Set the attributes for the next component being added
* @param attribs a table of attributes
*/
public void setNextAttributes( Object attribs )
{
nextAttributes = (Hashtable)attribs;
}
/**
* Setup the container
* @param name set the container name
* @param preferredWidth the desired width
* @param preferredHeight the desired height
* @param params extra parameters for the target
* <ul>
* <li>icon - the name of the icon file for the icon displayed in the docked panel's header</li>
* <li>title - the title of the docked panel</li>
* <li>sidebar - the id of the sidebar to which this panel docks</li>
* <li>constraint - the name of the region into which this component is docked,
* the region is managed by teh multisplitlayout</li>
* <li>minimized - true if the panel is initially minimized</li>
* <li>maximized - true if the panel is initially maximized</li>
* <li>canClose - false to prvent closing the dialog</li>
* <li>canDock - false to prevent docking</li>
* <li>canZoom - false to prevent maximization</li>
* <li>canMinimize - false to prevent minimization</li>
* <li>hasDockingTitle - true if a title is to be shown on the sidebar when
* the component is minimized, otherwise just the icon is shown if one is
* present</li>
* <li>clearState - true if the panel should clear the minimized/maximized
* state when a page is shown. If false the frame will maximize if an page is
* shown in the content area, and similarly for the minimized state. By
* default this value is true </li>
* </ul>
*/
public void setup( String name, int preferredWidth, int preferredHeight, Hashtable params )
{
setName( name );
if ( params != null ) {
iconName = (String)params.get( "icon" );
title = (String)params.get( "title" );
sidebar = (String)params.get( "sidebar" );
String constraint = (String)params.get( "constraint" );
if ( constraint != null )
setConstraint( constraint );
else
setConstraint( name );
String s = (String)params.get( "minimized" );
if ( s != null )
minimized = s.equals( "true" );
s = (String)params.get( "maximized" );
if ( s != null )
maximized = s.equals( "true" );
s = (String)params.get( "canClose" );
if ( s != null )
canClose = "true".equals( s );
s = (String)params.get( "canDock" );
if ( s != null )
canDock = "true".equals( s );
s = (String)params.get( "canDrag" );
if ( s != null )
canDrag = "true".equals( s );
s = (String)params.get( "canZoom" );
if ( s != null )
canZoom = "true".equals( s );
s = (String)params.get( "canMinimize" );
if ( s != null )
canMinimize = "true".equals( s );
s = (String)params.get( "hasDockingTitle" );
if ( s != null )
hasDockingTitle = "true".equals( s );
s = (String)params.get( "clearState" );
if ( s != null )
clearState = "true".equals( s );
}
else
setConstraint( name );
preferredSize = new Dimension( preferredWidth, preferredHeight );
}
public Dimension getPreferredSize()
{
return preferredSize;
}
/**
* Get a child component
* @param i the index of the child within the container
* @return the child component
*/
public Object getChildComponent( int i )
{
return contentPane.getComponent( i );
}
/**
* Remove a child component
* @param c the child component
*/
public void remove( Object c )
{
;//contentPane.remove( (Component)c );
}
public Component add( Component comp )
{
return comp;//contentPane.add( comp );
}
/**
* Add a page to the container. Typically this method is called by the
* XApplicationContext during a showPage call. The method uses a hashtable of
* attributes passed to the XPageManager as part of the showPage call. These
* attributes include:
* <ul>
* <li>title - the title of the new page as displayed on the associated tab</li>
* <li>sidebar - the name of the sidebar into which this page docks</li>
* <li>icon - the file name of the icon displayed for this new page</li>
* <li>canMinimize - a flag controlling the minimization/docking of the page,
* true to show a minimize/dock icon and to allow minimization to the sidebar</li>
* <li>canClose - a flag controlling the closing of the page, true to allow
* the page to be closed</li>
* <li>canDock - a flag to control docking of the page, if false a minimized
* page will not be able to dock back into the application frame</li>
* <li>canDrag - a flag to control dragging of the pages, if false a page
* cannot be dragged from one target area to another
* <li>hasDockingTitle - true to display a title when docked to the sidebar</li>
* <li>replace - true to replace the existing content of the target area</li>
* <li>state - the initial state of the new page (minimized|maximized)</li>
* </ul>
* @param comp the new page
* @param constraint the layout constraint for the new page
*/
public void add( Object comp, Object constraint )
{
if ( nextAttributes != null ) {
String s = (String)nextAttributes.get( "title" );
if ( s != null )
title = s;
s = (String)nextAttributes.get( "sidebar" );
if ( s != null )
sidebar = (String)nextAttributes.get( "sidebar" );
s = (String)nextAttributes.get( "icon" );
if ( s != null )
iconName = s;
}
XDockable dockable = findDockable( comp );
if ( dockable == null )
dockable = new XDockable( getDockingApp().getSidebar( sidebar != null ? sidebar : getName()),
title != null ? currentProject.getTranslator().translate( title ) : getName());
dockables.add( dockable );
dockable.content = (Container)comp;
boolean doReplace = true;
dockable.canClose = canClose;
dockable.canMinimize = canMinimize;
dockable.canDock = canDock;
dockable.canDrag = canDrag;
dockable.canZoom = canZoom;
dockable.hasDockingTitle = hasDockingTitle;
if ( nextAttributes != null ) {
String s = (String)nextAttributes.get( "canMinimize" );
if (( s != null ) && ( s.length() > 0 ))
dockable.canMinimize = "true".equals( s );
s = (String)nextAttributes.get( "canClose" );
if (( s != null ) && ( s.length() > 0 ))
dockable.canClose = "true".equals( s );
s = (String)nextAttributes.get( "canDock" );
if (( s != null ) && ( s.length() > 0 ))
dockable.canDock = "true".equals( s );
s = (String)nextAttributes.get( "canDrag" );
if (( s != null ) && ( s.length() > 0 ))
dockable.canDrag = "true".equals( s );
s = (String)nextAttributes.get( "canZoom" );
if (( s != null ) && ( s.length() > 0 ))
dockable.canZoom = "true".equals( s );
s = (String)nextAttributes.get( "hasDockingTitle" );
if (( s != null ) && ( s.length() > 0 ))
dockable.hasDockingTitle = "true".equals( s );
s = (String)nextAttributes.get( "replace" );
if (( s != null ) && ( s.length() > 0 ))
doReplace = "true".equals( s );
s = (String)nextAttributes.get( "state" );
if ( s != null ) {
if ( s.equals( "minimized" )) {
minimized = true;
maximized = false;
}
else if ( s.equals( "maximized" )) {
maximized = true;
minimized = false;
}
}
}
if (( iconName != null ) && ( iconName.length() > 0 ))
dockable.icon = (ImageIcon)currentProject.getIcon( iconName );
// Setup the coloring
Color[] colors = new Color[ 5 ];
colors[ 0 ] = SystemColor.control.brighter(); // headerBkColor
colors[ 1 ] = SystemColor.controlText; // headerTextColor
colors[ 2 ] = Color.orange; // activeColor - the stripe under the active component
colors[ 3 ] = colors[ 2 ];// activeTextColor
colors[ 4 ] = Color.red;// pressedTextColor
XTranslator translator = currentProject.getTranslator();
XStyleManager sm = currentProject.getStyleManager();
if ( sm.hasStyle( "dockingHeader" )) {
XStyle xstyle = sm.getStyle( "dockingHeader" );
colors[ 0 ] = xstyle.getStyleAsColor( XStyle.COLOR_BACK );
colors[ 1 ] = xstyle.getStyleAsColor( XStyle.COLOR_FORE );
XStyle xstyleActive = sm.getStyle( "dockingHeader/active" );
colors[ 2 ] = xstyleActive.getStyleAsColor( XStyle.COLOR_BACK );
colors[ 3 ] = xstyleActive.getStyleAsColor( XStyle.COLOR_FORE );
}
// Setup the tooltips
String[] tooltips = new String[ 3 ];
tooltips[ 0 ] = ( translator != null ? translator.translate( "Minimize" ) : "Minimize" );
tooltips[ 1 ] = ( translator != null ? translator.translate( "Zoom/Restore" ) : "Zoom/Restore" );
tooltips[ 2 ] = ( translator != null ? translator.translate( "Close" ) : "Close" );
super.addDockable( dockable, colors, tooltips );
if ( doReplace ) {
if ( contentPane.getComponentCount() > 0 ) {
XDockable docked = findDockable( contentPane.getComponent( 0 ));
if (( docked != null ) && ( docked != dockable ))
super.removeDockable( docked, false );
else if ( minimized )
dockable.dockedContainer.setVisible( true );
}
}
final XDockable thisDockable = dockable;
SwingUtilities.invokeLater( new Runnable() {
public void run()
{
if ( minimized ) {
thisDockable.dockedContainer.removeDockable( thisDockable, true );
if ( clearState )
minimized = false;
}
else if ( maximized ) {
thisDockable.header.zoomPanel();
if ( clearState )
maximized = false;
}
}
});
}
/**
* Find the dockable containing the reference object
* @param c the docked component, header or panel.
*/
public XDockable findDockable( Object c )
{
int numDockables = dockables.size();
for ( int i = 0; i < numDockables; i++ ) {
XDockable dockable = (XDockable)dockables.get( i );
if (( dockable.content == c ) || ( dockable.dockedContainer == c ) || ( dockable.header == c ))
return dockable;
}
return null;
}
/**
* Zoom in in a panel or dockable
* @param c the docked component, header or panel.
*/
public void zoomDockable( Object c )
{
XDockable d = findDockable( c );
d.header.zoomPanel();
}
public XDockingApp getDockingApp()
{
Container cont = getParent();
while (( cont != null ) && !( cont instanceof XDockingApp ))
cont = cont.getParent();
return (XDockingApp)cont;
}
/**
* Is this component the parent of the child c
* @param c the child to test
* @return true if this container is a parent of the component, otherwise
* false if the component belongs to some other heirarchy or does not
* participate in the hierarchy (if it isn't attached to a container)
*/
public boolean isParentOf( Component c )
{
Container cont = c.getParent();
while ( cont != null ) {
if ( cont == this )
return true;
cont = cont.getParent();
}
return false;
}
}