package org.openswing.swing.mdi.client;
import java.beans.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.filechooser.FileFilter;
import org.openswing.swing.util.client.*;
import org.openswing.swing.util.java.*;
/**
* <p>Title: OpenSwing Framework</p>
* <p>Description: Desktop panel used to contain internal frames.
* <p>Copyright: Copyright (C) 2006 Mauro Carniel</p>
*
* <p> This file is part of OpenSwing Framework.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the (LGPL) Lesser General Public
* License as published by the Free Software Foundation;
*
* GNU LESSER GENERAL PUBLIC LICENSE
* Version 2.1, February 1999
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* The author may be contacted at:
* maurocarniel@tin.it</p>
*
* @author Mauro Carniel
* @version 1.0
*/
public class DesktopPane extends JDesktopPane implements InternalFrameListener {
/** background image */
private Image background = null;
/** file related to custom background image */
private String backgroundFileName = null;
/** flag used to manage modal internal frames */
private boolean modal;
/** modal panel */
protected JPanel modalPane = new JPanel();
/** layering component */
protected Component layeringComp;
public DesktopPane() {
this.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
setOpaque(true);
this.setBackground(Color.lightGray);
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount()==1 && SwingUtilities.isRightMouseButton(e)) {
JPopupMenu popup = new JPopupMenu();
JMenuItem selBack = new JMenuItem(ClientSettings.getInstance().getResources().getResource("change background"));
popup.add(selBack);
selBack.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
selectBackground();
}
});
JMenuItem clearBack = new JMenuItem(ClientSettings.getInstance().getResources().getResource("reset background"));
popup.add(clearBack);
clearBack.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
resetBackground();
}
});
popup.show(DesktopPane.this,e.getY(),e.getY());
}
}
});
initModalPane();
}
/**
* Initialize modal pane, in case of modal internal frames.
*/
private void initModalPane() {
modalPane.setSize(java.awt.Toolkit.getDefaultToolkit().getScreenSize());
modalPane.setOpaque(false);
modalPane.setVisible(true);
// add mouse listener to modal internal frame,
// in order to generate a beep when clicking on it...
modalPane.addMouseListener(new MouseListener () {
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
Toolkit.getDefaultToolkit().beep();
}
public void mouseReleased(MouseEvent e) {
}
});
}
/**
*
* @param modal boolean
*/
public final void setModal(boolean modal) {
if (this.modal!=modal)
setModal(getSelectedFrame(), modal);
}
/**
* Set modal state to the specified internal frame.
* @param modalDialog internal frame whose modal state must be changed
* @param modal modal state
*/
public final void setModal(javax.swing.JInternalFrame modalDialog, boolean modal) {
this.modal=modal;
if (this.modal) {
this.add(modalPane);
this.setLayer(modalPane, JLayeredPane.PALETTE_LAYER.intValue());
javax.swing.JInternalFrame[] frames=this.getAllFrames();
int defaultLayer=JLayeredPane.DEFAULT_LAYER.intValue();
for (int i=0;i<frames.length;i++) {
if (frames[i].getLayer()!=defaultLayer) {
this.setLayer(frames[i], defaultLayer);
}
}
this.setLayer(modalDialog, JLayeredPane.MODAL_LAYER.intValue());
modalDialog.moveToFront();
} else {
this.remove(modalPane);
javax.swing.JInternalFrame[] frames=this.getAllFrames();
int defaultLayer=JLayeredPane.DEFAULT_LAYER.intValue();
for (int i=0;i<frames.length;i++) {
if (frames[i].getLayer()!=defaultLayer) {
this.setLayer(frames[i], defaultLayer);
}
}
}
}
/**
* @return <code>true</code> if there exists a modal internal frame or <code>false</code> otherwise
*/
public final boolean isModal() {
return this.modal;
}
/**
* Select an image to use as MDI background.
*/
private void selectBackground() {
JFileChooser f = new JFileChooser();
f.setDialogTitle(ClientSettings.getInstance().getResources().getResource("image selection"));
f.setFileSelectionMode(f.FILES_ONLY);
f.setFileFilter(new FileFilter() {
public boolean accept(File f) {
return f.isDirectory() ||
f.getName().toLowerCase().endsWith(".gif") ||
f.getName().toLowerCase().endsWith(".jpg");
}
/**
* The description of this filter. For example: "JPG and GIF Images"
* @see FileView#getName
*/
public String getDescription() {
return "Image Files (*.gif;*.jpg)";
}
});
int res = f.showOpenDialog(MDIFrame.getInstance());
if (res==f.APPROVE_OPTION) {
// image file selected: it will be set into image panel...
backgroundFileName = f.getSelectedFile().getAbsolutePath();
setBackgroundImageFromFile();
// save config file...
saveUserProfile();
}
}
/**
* Reset the image to use as MDI background and restore the default one.
*/
private void resetBackground() {
backgroundFileName = null;
background = ClientUtils.getImage(ClientSettings.BACKGROUND);
repaint();
// save config file...
saveUserProfile();
}
/**
* Set custom background image from file.
*/
private boolean setBackgroundImageFromFile() {
BufferedInputStream in = null;
try {
File file = new File(backgroundFileName);
in = new BufferedInputStream(new FileInputStream(file));
byte[] bytes = new byte[(int)file.length()];
in.read(bytes);
background = new ImageIcon(bytes).getImage();
repaint();
return true;
}
catch (Exception ex) {
ex.printStackTrace();
return false;
}
finally {
try {
if (in!=null)
in.close();
}
catch (Exception ex1) {
}
}
}
/**
* Save user profile.
*/
private void saveUserProfile() {
try {
Properties p = new Properties();
if (backgroundFileName==null)
backgroundFileName = "";
p.setProperty("backgroundFileName",backgroundFileName);
String file = System.getProperty("user.home").replace('\\','/');
if (!file.endsWith("/"))
file += "/";
file += "profiles/"+MDIFrame.getInstance().getTitle()+".cfg";
p.store(new FileOutputStream(new File(file)),"User Properties");
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* @return <code>true</code> if user profile was found and a background image has been setted, <code>false</code> otherwise
*/
private boolean loadUserProfile(MDIController client) {
String file = System.getProperty("user.home").replace('\\','/');
if (!file.endsWith("/"))
file += "/";
file += "profiles/"+client.getMDIFrameTitle()+".cfg";
File confFile = new File(file);
if (!confFile.exists())
return false;
Properties p = new Properties();
try {
p.load(new FileInputStream(confFile));
backgroundFileName = p.getProperty("backgroundFileName");
if (backgroundFileName!=null && !backgroundFileName.equals(""))
return setBackgroundImageFromFile();
return false;
}
catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
public void init(MDIController client) {
if (!loadUserProfile(client)) {
if (ClientSettings.BACKGROUND!=null)
background = ClientUtils.getImage(ClientSettings.BACKGROUND);
}
}
/**
* Paint background image.
*/
public final void paintComponent(Graphics g) {
super.paintComponent(g);
if (background!=null) {
if (ClientSettings.BACK_IMAGE_DISPOSITION==Consts.BACK_IMAGE_REPEATED) {
// image must be repeated...
int imgWidth = background.getWidth(this);
int imgHeight = background.getHeight(this);
for(int i=this.getWidth();i>0;i=i-imgWidth)
for(int j=0;j<this.getHeight();j=j+imgHeight)
g.drawImage(background,i-imgWidth,j,this);
} else if (ClientSettings.BACK_IMAGE_DISPOSITION==Consts.BACK_IMAGE_CENTERED) {
// image must be centered...
int imgWidth = background.getWidth(this);
int imgHeight = background.getHeight(this);
int x = (this.getWidth()-imgWidth)/2;
int y = (this.getHeight()-imgHeight)/2;
g.drawImage(background,x,y,this);
} else if (ClientSettings.BACK_IMAGE_DISPOSITION==Consts.BACK_IMAGE_STRETCHED) {
// image must be streched...
g.drawImage(background,0,0,getWidth(),getHeight(),this);
}
}
if (ClientSettings.BACKGROUND_PAINTER!=null) {
ClientSettings.BACKGROUND_PAINTER.paint(this, g);
}
}
/**
* Add an internal frame to the desktop.
* Add an internal frame listener.
* @param frame internal frame to add
* @param maximum flag used to set that the internal frame will be maximized
*/
public final void add(final InternalFrame frame,boolean maximum) {
try {
super.add(frame);
int w = this.getVisibleRect().width;
int h = this.getVisibleRect().height;
// System.out.println(this.getVisibleRect()+" "+this.getSize()+" "+this.getPreferredSize()+" "+this.getMinimumSize());
if (w==0)
w = this.getSize().width;
if (h==0)
h = this.getSize().width;
if (maximum) {
frame.setSize(new Dimension(w,h));
frame.setLocation(0,0);
}
if (!frame.isMaximum()) {
frame.setLocation(
(Math.max(w-frame.getWidth(),0))/2,
(Math.max(h-frame.getHeight(),0))/2
);
}
if (ClientSettings.STORE_INTERNAL_FRAME_PROFILE)
loadState(frame);
if (!frame.isVisible())
frame.setVisible(true);
if (!frame.isSelected())
frame.setSelected(true);
frame.addInternalFrameListener(new InternalFrameAdapter() {
public void internalFrameClosed(InternalFrameEvent e) {
if (ClientSettings.STORE_INTERNAL_FRAME_PROFILE)
saveState(frame);
if (DesktopPane.this.getSelectedFrame()==null &&
DesktopPane.this.getAllFrames().length>0) {
JInternalFrame frame = DesktopPane.this.getAllFrames()[0];
try {
frame.toFront();
frame.setSelected(true);
}
catch (PropertyVetoException ex) {
}
}
}
});
if (ClientSettings.SHOW_SCROLLBARS_IN_MDI) {
Container c = this;
while(c!=null && !(c instanceof JScrollPane))
c = c.getParent();
if (c!=null) {
final JScrollPane scrollPane = (JScrollPane) c;
frame.addComponentListener(new ComponentAdapter() {
/**
* Invoked when the component's position changes.
*/
public void componentMoved(final ComponentEvent e) {
if (e.getComponent().getLocation().x+e.getComponent().getSize().width>DesktopPane.this.getWidth() ||
e.getComponent().getLocation().y+e.getComponent().getSize().height>DesktopPane.this.getHeight()) {
final int locx = e.getComponent().getLocation().x;
final int locy = e.getComponent().getLocation().y;
int x = Math.max(e.getComponent().getLocation().x+e.getComponent().getSize().width,DesktopPane.this.getWidth());
int y = Math.max(e.getComponent().getLocation().y+e.getComponent().getSize().height,DesktopPane.this.getHeight());
DesktopPane.this.setPreferredSize(new Dimension(x,y));
DesktopPane.this.setSize(new Dimension(x,y));
scrollPane.getViewport().setViewSize(new Dimension(x,y));
scrollPane.getViewport().setSize(new Dimension(x,y));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// scrollPane.getHorizontalScrollBar().setValue(e.getComponent().getLocation().x);
// scrollPane.getVerticalScrollBar().setValue(e.getComponent().getLocation().y);
scrollPane.getHorizontalScrollBar().setValue(locx);
scrollPane.getVerticalScrollBar().setValue(locy);
}
});
}
}
});
}
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Sets the layer attribute for the specified component and also sets its position within that layer.
* @param c the Component to set the layer for
* @param layer an int specifying the layer to set, where
* lower numbers are closer to the bottom
* @param position an int specifying the position within the
* layer, where 0 is the topmost position and -1
* is the bottommost position
*/
public final void setLayer(Component c, int layer, int position) {
if (layeringComp!=c) {
layeringComp=c;
super.setLayer(c, layer, position);
layeringComp=null;
}
}
/**
* Method overrided in order to inject modal state to internal frames.
* @param comp componente to add
* @param constraints constraints to apply to the specified component
* @param index component position
*/
protected final void addImpl(Component comp, Object constraints, int index) {
DesktopManager manager=null;
if (comp instanceof javax.swing.JInternalFrame) {
javax.swing.JInternalFrame frame=(javax.swing.JInternalFrame)comp;
EventListener[] listeners=frame.getListeners(InternalFrameListener.class);
int i=0;
for (i=0;i<listeners.length;i++) {
if (listeners[i]==this) {
break;
}
}
if (i>=listeners.length) {
frame.addInternalFrameListener(this);
}
if (comp.getParent()==this) {
return;
}
if (layeringComp!=comp) {
manager=getDesktopManager();
}
}
super.addImpl(comp, constraints, index);
if (manager!=null) {
manager.openFrame((javax.swing.JInternalFrame)comp);
}
}
public final void internalFrameActivated(InternalFrameEvent e) {
EventListener[] listeners=listenerList.getListeners(InternalFrameListener.class);
for (int i=0;i<listeners.length;i++) {
InternalFrameListener listener=(InternalFrameListener)listeners[i];
listener.internalFrameActivated(e);
}
}
public final void internalFrameClosed(InternalFrameEvent e) {
if (this.modal) {
// removed internal frame modal state...
setModal(false);
}
EventListener[] listeners=listenerList.getListeners(InternalFrameListener.class);
for (int i=0;i<listeners.length;i++) {
InternalFrameListener listener=(InternalFrameListener)listeners[i];
listener.internalFrameClosed(e);
}
}
public final void internalFrameClosing(InternalFrameEvent e) {
EventListener[] listeners=listenerList.getListeners(InternalFrameListener.class);
for (int i=0;i<listeners.length;i++) {
InternalFrameListener listener=(InternalFrameListener)listeners[i];
listener.internalFrameClosing(e);
}
}
public final void internalFrameDeactivated(InternalFrameEvent e) {
EventListener[] listeners=listenerList.getListeners(InternalFrameListener.class);
for (int i=0;i<listeners.length;i++) {
InternalFrameListener listener=(InternalFrameListener)listeners[i];
listener.internalFrameDeactivated(e);
}
}
public final void internalFrameDeiconified(InternalFrameEvent e) {
EventListener[] listeners=listenerList.getListeners(InternalFrameListener.class);
for (int i=0;i<listeners.length;i++) {
InternalFrameListener listener=(InternalFrameListener)listeners[i];
listener.internalFrameDeiconified(e);
}
}
public final void internalFrameIconified(InternalFrameEvent e) {
EventListener[] listeners=listenerList.getListeners(InternalFrameListener.class);
for (int i=0;i<listeners.length;i++) {
InternalFrameListener listener=(InternalFrameListener)listeners[i];
listener.internalFrameIconified(e);
}
}
public final void internalFrameOpened(InternalFrameEvent e) {
EventListener[] listeners=listenerList.getListeners(InternalFrameListener.class);
for (int i=0;i<listeners.length;i++) {
InternalFrameListener listener=(InternalFrameListener)listeners[i];
listener.internalFrameOpened(e);
}
}
/**
* Store frame location and size to a local profile file.
*/
private void saveState(InternalFrame frame) {
if (frame.isMaximum()) {
try {
frame.setMaximum(false);
}
catch (PropertyVetoException ex) {
}
}
Dimension size = frame.getSize();
Point position = frame.getLocation();
String userHome = System.getProperty("user.home").replace('\\', '/');
if (!userHome.endsWith("/")) {
userHome += "/";
}
userHome += "profiles";
File dir = new File(userHome);
dir.mkdirs();
String[] str = System.getProperty("user.dir").split("\\\\");
String project = str[str.length - 1].trim();
String frameName = frame.getClass().getName().replace(' ', '_').replace('.', '_');
if (getName()!=null)
frameName += getName()+"_";
File f = new File(userHome + "/" + project.replace(' ', '_') + "_" + frameName + "_" + System.getProperty("user.name").replace(' ', '_') + ".ini");
if (f.exists())
f.delete();
PrintWriter pw = null;
try {
pw = new PrintWriter(new FileOutputStream(f));
pw.println(size.width);
pw.println(size.height);
pw.println(position.x);
pw.println(position.y);
} catch (Throwable ex) {
} finally {
try {
pw.close();
} catch (Exception ex1) {
}
}
}
/**
* Load frame location and size from a profile file and set them to this frame.
*/
private void loadState(InternalFrame frame) {
String userHome = System.getProperty("user.home").replace('\\', '/');
if (!userHome.endsWith("/")) {
userHome += "/";
}
userHome += "profiles";
File dir = new File(userHome);
dir.mkdirs();
String[] str = System.getProperty("user.dir").split("\\\\");
String project = str[str.length - 1].trim();
String frameName = frame.getClass().getName().replace(' ', '_').replace('.', '_');
if (getName()!=null)
frameName += getName()+"_";
File f = new File(userHome + "/" + project.replace(' ', '_') + "_" + frameName + "_" + System.getProperty("user.name").replace(' ', '_') + ".ini");
if (!f.exists())
return;
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
int width = Integer.parseInt(br.readLine());
int height = Integer.parseInt(br.readLine());
int x = Integer.parseInt(br.readLine());
int y = Integer.parseInt(br.readLine());
frame.setSize(width,height);
frame.setLocation(x,y);
} catch (Throwable ex) {
} finally {
try {
br.close();
} catch (Exception ex1) {
}
}
}
}