package watch.sound.swing.ui.cdi;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JInternalFrame;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
/**
* the regular internal frame which has a system popupmenu
* that can be configured and extended
*
* @author Hanning Ni
* @reviewer
*/
public class CDIInternalFrame extends JInternalFrame implements VetoableChangeListener, PopupMenuListener{
private static final long serialVersionUID = 1L;
private static String IMAGE_DIR = "smile/me/control/mdi/resource" + java.io.File.separator;
private static ImageIcon DEFAULT_FRAME_ICON = new ImageIcon(IMAGE_DIR+"default.gif");
private CDIDesktop _desktop;
protected JPopupMenu optionMenu;
protected Action tearOffAction, closeAction, disembleAction;
protected JCheckBoxMenuItem mergeMode;
protected boolean forceClose;
private CDIFrameProperties properties = new CDIFrameProperties();
public CDIInternalFrame( CDIDesktop desktop) {
this("", true, true, true, true, desktop);
}
public CDIInternalFrame(String title,CDIDesktop desktop) {
this(title, true, true, true, true, desktop);
}
public CDIInternalFrame(String title, boolean resizable,CDIDesktop desktop) {
this(title, resizable, true, true, true, desktop);
}
public CDIInternalFrame(String title, boolean resizable, boolean closable,CDIDesktop desktop) {
this(title, resizable, closable, true, true, desktop);
}
public CDIInternalFrame(String title, boolean resizable, boolean closable,
boolean maximizable,CDIDesktop desktop) {
this(title, resizable, closable, maximizable, true, desktop);
}
public CDIInternalFrame(String title, boolean resizable, boolean closable,
boolean maximizable, boolean iconifiable,CDIDesktop desktop) {
super(title,resizable, closable, maximizable, iconifiable);
addVetoableChangeListener(this);
this._desktop = desktop;
setFrameIcon(DEFAULT_FRAME_ICON);
properties.setId( desktop.getNextAvailableId());
properties.setTitle(title);
optionMenu = new JPopupMenu();
//add tearOff, merge, disemsemble, close
tearOffAction = new AbstractAction("Tear Off"){
public void actionPerformed(ActionEvent e) {
_desktop.tearOff(CDIInternalFrame.this);
}};
optionMenu.add(tearOffAction);
mergeMode = new JCheckBoxMenuItem("Mergable");
mergeMode.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent e) {
setMergable(mergeMode.isSelected());
}});
optionMenu.add(mergeMode);
disembleAction = new AbstractAction("Disemble"){
public void actionPerformed(ActionEvent e) {
_desktop.disemble(CDIInternalFrame.this);
}};
optionMenu.add(disembleAction);
closeAction = new AbstractAction("Close"){
public void actionPerformed(ActionEvent e) {
if( isClosable()) {
close();
}
}};
optionMenu.add(closeAction);
optionMenu.addPopupMenuListener(this);
}
public void setFrameIcon(Icon icon) {
super.setFrameIcon(icon);
if(properties != null)
properties.setFrameIcon(icon);
}
/**
* close the frame.
*/
public void close(){
forceClose = true;
doDefaultCloseAction();
}
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
// place to start merge of internal frames
SwingUtilities.invokeLater(new Runnable(){
public void run() {
if(isMergable())
_desktop.tryMerge(CDIInternalFrame.this);
}});
}
/**
* current frame is mergable or not
* @return
*/
public boolean isMergable(){
return properties.isMergable();
}
/**
* set current frame's mergable status
* @param b
*/
public void setMergable(boolean b){
properties.setMergable(b);
}
/**
* unique id of the frame. originally created by SmileDestkop
* @return
*/
public String getId(){
return properties.getId();
}
public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
if(evt.getPropertyName().equals(IS_ICON_PROPERTY)){
SwingUtilities.invokeLater(new Runnable(){
public void run() {
_desktop.addIconifiedFrame(CDIInternalFrame.this );
}});
throw new PropertyVetoException("override iconify", evt);
}
if(evt.getPropertyName().equals(IS_CLOSED_PROPERTY)){
if(forceClose)
return;
if(this.isIcon)
return;
if (optionMenu.isVisible()) {
optionMenu.setVisible(false);
return;
}
SwingUtilities.invokeLater(new Runnable(){
public void run() {
optionMenu.show( CDIInternalFrame.this,
CDIInternalFrame.this.getWidth() - optionMenu.getWidth(), 0);
}});
throw new PropertyVetoException("override close", evt);
}
}
/////////////////popup related event handle/////////////////
public void popupMenuCanceled(PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
/**
* API user should overwrite this method to configure system popupmenu
*/
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
tearOffAction.setEnabled(isClosable());
disembleAction.setEnabled(isMergedStatus());
mergeMode.setSelected( isMergable() );
}
/**
* if current frame is a merged frame
* @return
*/
public boolean isMergedStatus() {
return properties.isMergeStatus();
}
/**
* set current frame merge status
* @param mergedStatus
*/
public void setMergedStatus(boolean mergedStatus) {
properties.setMergeStatus(mergedStatus);
}
/**
* a set of properties related to internalframe
* @return
*/
public CDIFrameProperties getProperties() {
return properties;
}
/**
* set current properties and configure current frame based on
* the new properties
* @param properties
*/
public void setProperties(CDIFrameProperties properties) {
this.properties = properties;
setTitle(properties.getTitle());
setMergable(properties.isMergable());
setMergedStatus(properties.isMergeStatus());
setFrameIcon(properties.getFrameIcon());
}
}