/*
This file is part of leafdigital leafChat.
leafChat is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
leafChat is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with leafChat. If not, see <http://www.gnu.org/licenses/>.
Copyright 2012 Samuel Marshall.
*/
package com.leafdigital.ui;
import java.awt.Dimension;
import java.beans.*;
import javax.swing.*;
import com.leafdigital.ui.api.*;
import leafchat.core.api.BugException;
/**
* Implements SplitPanel
*/
public class SplitPanelImp extends JSplitPane
{
/** One of the SIDE_xxx constants */
private int side;
/** Size in pixels */
private int splitSize;
/** Widgets inside */
private InternalWidget main,split;
/** Constructs. */
public SplitPanelImp()
{
externalInterface.setSide(SplitPanel.SIDE_EAST);
externalInterface.setSplitSize(100);
setBorder(BorderFactory.createEmptyBorder());
addPropertyChangeListener(DIVIDER_LOCATION_PROPERTY,new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent evt)
{
switch(side)
{
case SplitPanel.SIDE_NORTH:
case SplitPanel.SIDE_WEST:
splitSize=getDividerLocation();
break;
case SplitPanel.SIDE_EAST:
splitSize=getWidth()-getDividerLocation();
// Swing doesn't let people set 0px. Argh! This handles it by
// making 1 -> 0.
if(splitSize==getDividerSize()+1) setDividerLocation(getWidth()-getDividerSize());
break;
case SplitPanel.SIDE_SOUTH:
splitSize=getHeight()-getDividerLocation();
break;
}
}
});
setOneTouchExpandable(true);
}
/**
* @return Interface giving limited public access
*/
SplitPanel getInterface()
{
return externalInterface;
}
@Override
public void setBounds(int x,int y,int width,int height)
{
boolean changed=width!=getWidth();
int splitSizeBefore=splitSize;
super.setBounds(x,y,width,height);
if(changed) externalInterface.setSplitSize(splitSizeBefore);
}
/** Interface available to public */
private SplitPanel externalInterface=new SplitPanelInterface();
/** Interface available to public */
class SplitPanelInterface extends BasicWidget implements SplitPanel,InternalWidget
{
@Override
public int getContentType() { return CONTENT_NAMEDSLOTS; }
@Override
public void setMain(Widget w)
{
final InternalWidget iw=(InternalWidget)w;
iw.setParent(this);
main=iw;
UISingleton.runInSwing(new Runnable()
{
@Override
public void run()
{
JComponent jc=(iw==null ? null : iw.getJComponent());
switch(side)
{
case SIDE_NORTH: setBottomComponent(jc); break;
case SIDE_EAST: setLeftComponent(jc); break;
case SIDE_SOUTH: setTopComponent(jc); break;
case SIDE_WEST: setRightComponent(jc); break;
}
}
});
}
@Override
public void setSplit(Widget w)
{
final InternalWidget iw=(InternalWidget)w;
iw.setParent(this);
split=iw;
UISingleton.runInSwing(new Runnable()
{
@Override
public void run()
{
JComponent jc=(iw==null ? null : iw.getJComponent());
if(jc.getPreferredSize().width==0)
jc.setPreferredSize( new Dimension(iw.getPreferredWidth(),
iw.getPreferredHeight(iw.getPreferredWidth())));
switch(side)
{
case SIDE_NORTH: setTopComponent(jc); break;
case SIDE_EAST: setRightComponent(jc); break;
case SIDE_SOUTH: setBottomComponent(jc); break;
case SIDE_WEST: setLeftComponent(jc); break;
}
}
});
}
@Override
public void setSide(final int side)
{
SplitPanelImp.this.side=side;
UISingleton.runInSwing(new Runnable()
{
@Override
public void run()
{
switch(side)
{
case SIDE_NORTH:
setOrientation(JSplitPane.VERTICAL_SPLIT);
setResizeWeight(0.0);
break;
case SIDE_EAST:
setOrientation(JSplitPane.HORIZONTAL_SPLIT);
setResizeWeight(1.0);
break;
case SIDE_SOUTH:
setOrientation(JSplitPane.VERTICAL_SPLIT);
setResizeWeight(1.0);
break;
case SIDE_WEST:
setOrientation(JSplitPane.HORIZONTAL_SPLIT);
setResizeWeight(0.0);
break;
default:
throw new IllegalArgumentException("Side value not supported");
}
}
});
}
@Override
public void setSplitSize(final int size)
{
SplitPanelImp.this.splitSize=size;
UISingleton.runInSwing(new Runnable()
{
@Override
public void run()
{
if(getWidth()==0) return; // Don't bother
switch(side)
{
case SIDE_NORTH:
case SIDE_WEST:
setDividerLocation(size);
break;
case SIDE_EAST:
if(splitSize==getDividerSize()+1)
splitSize=getDividerSize();
setDividerLocation(getWidth()-splitSize);
break;
case SIDE_SOUTH:
setDividerLocation(getHeight()-size);
break;
}
}
});
}
@Override
public int getSplitSize()
{
return splitSize;
}
@Override
public JComponent getJComponent()
{
return SplitPanelImp.this;
}
@Override
public int getPreferredWidth()
{
int iMainWidth=(main==null || !main.isVisible() ? 0 : main.getPreferredWidth());
int iSplitWidth=(split==null || !split.isVisible() ? 0 : split.getPreferredWidth());
switch(side)
{
case SIDE_NORTH:
case SIDE_SOUTH:
return Math.max(iMainWidth,iSplitWidth);
case SIDE_EAST:
case SIDE_WEST:
return iMainWidth+splitSize+getDividerSize();
default:
throw new Error("Invalid side value");
}
}
@Override
public int getPreferredHeight(int width)
{
if(width==0) return 0;
switch(side)
{
case SIDE_NORTH:
case SIDE_SOUTH:
return splitSize+getDividerSize()+
(main==null || !main.isVisible() ? 0 : main.getPreferredHeight(width));
case SIDE_EAST:
case SIDE_WEST:
return Math.max(
(main==null || !main.isVisible() ? 0 : main.getPreferredHeight(width-splitSize)),
(split==null || !split.isVisible() ? 0 : split.getPreferredHeight(splitSize)));
default:
throw new Error("Invalid side value");
}
}
@Override
public void addXMLChild(String slotName, Widget child)
{
if(slotName.equals("main")) setMain(child);
else if(slotName.equals("split")) setSplit(child);
else throw new BugException(
"Slot name invalid, expecting 'split' or 'main': "+slotName);
}
@Override
public void setBorder(final int border)
{
UISingleton.runInSwing(new Runnable()
{
@Override
public void run()
{
SplitPanelImp.this.setBorder(
BorderFactory.createEmptyBorder(border,border,border,border));
}
});
}
@Override
public Widget[] getWidgets()
{
if(main == null && split == null)
{
return new Widget[0];
}
else if(main == null)
{
return new Widget[] { split };
}
else if(split == null)
{
return new Widget[] { main };
}
else
{
return new Widget[] { main, split };
}
}
@Override
public void remove(Widget c)
{
if(c==main) setMain(null);
else if(c==split) setSplit(null);
}
@Override
public void removeAll()
{
setMain(null);
setSplit(null);
}
};
}