/* 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.*; import java.awt.image.BufferedImage; import java.beans.PropertyVetoException; import javax.swing.*; import javax.swing.event.*; import util.PlatformUtils; /** * Handles a FrameContents inside the main application window. */ public class FrameInside extends MacFixInternalFrame implements FrameHolder { /** Owning desktop */ private InternalDesktop owner; /** Contents of frame */ private WindowImp wi; private boolean active=false; private void trackActive() { active=true; wi.informActive(true); owner.informActive(this); } private boolean pastStartup=false; FrameInside(InternalDesktop owner,WindowImp contents,final boolean initialScreen,final Point initial,final boolean minimized) { this.owner=owner; this.wi=contents; contents.setFrame(this); UISingleton.runInSwing(new Runnable() { @Override public void run() { JComponent pContents=wi.getContents(); getContentPane().setLayout(new BorderLayout()); JPanel spacer=new JPanel(); spacer.setPreferredSize(new Dimension( pContents.getSize())); getContentPane().add(spacer,BorderLayout.CENTER); pack(); getContentPane().remove(spacer); getContentPane().add(pContents,BorderLayout.CENTER); setClosable(true); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); setIconifiable(true); setMaximizable(true); setResizable(true); FrameInside.this.owner.addFrame(FrameInside.this,initialScreen,initial); setFrameIcon(null); if(!minimized) { setVisible(true); wi.getInterface().activate(); } addInternalFrameListener(new InternalFrameListener() { @Override public void internalFrameOpened(InternalFrameEvent ife) { } @Override public void internalFrameClosing(InternalFrameEvent ife) { if(handleClosing()) { dispose(); } } @Override public void internalFrameClosed(InternalFrameEvent ife) { handleClose(); } @Override public void internalFrameIconified(InternalFrameEvent ife) { try { setIcon(false); } catch(PropertyVetoException e) { } handleMinimize(); } @Override public void internalFrameDeiconified(InternalFrameEvent ife) { } @Override public void internalFrameActivated(InternalFrameEvent ife) { trackActive(); } @Override public void internalFrameDeactivated(InternalFrameEvent ife) { active=false; if(wi!=null) wi.informActive(false); } }); pastStartup=true; } }); } WindowImp getContents() { return wi; } // void setActive(boolean bActive) // { // wi.setActive(bActive); // } /** @return Size of contents of this frame */ public Dimension getContentSize() { return wi.getContents().getSize(); } @Override public void focusFrame() { if(!isVisible()) setVisible(true); try { setSelected(true); } catch(PropertyVetoException e) { } moveToFront(); wi.focus(); // This needs to be called later because otherwise, it can get run in the // constructor - before subclass constructors have been called. This // causes confusing behaviour if callbacks are called before constructor. SwingUtilities.invokeLater(new Runnable() { @Override public void run() { trackActive(); } }); } /** @return True if frame is focused */ boolean isFocused() { return isVisible() && wi.isActive(); } /** * Called when window is being closed. * @return True if it's OK for window to close */ public boolean handleClosing() { if(wi!=null) return wi.informClosing(); else return true; } @Override public void handleClose() { owner.removeFrame(this); if(wi!=null) wi.informClosed(); } @Override public void setIcon(Image i) { setFrameIcon(new ImageIcon(i)); } @Override public Image getIcon() { if(getFrameIcon()==null) return null; else { Icon i=getFrameIcon(); if(i instanceof ImageIcon) { return ((ImageIcon)i).getImage(); } else { // May be a Windows ScalableIcon or something, so use standard icon // paint method. BufferedImage bi=new BufferedImage(i.getIconWidth(),i.getIconHeight(),BufferedImage.TYPE_INT_ARGB); i.paintIcon(null,bi.getGraphics(),0,0); return bi; } } } @Override public void handleMinimize() { if(!isVisible()) return; boolean wasFocused=isFocused(); setVisible(false); if(sb!=null) sb.informChanged(); if(wasFocused) { owner.reassignFocus(); } } @Override public boolean isMinimized() { return !isVisible(); } /** Called when window is being restored. */ public void handleRestore() { if(isVisible()) return; setVisible(true); if(sb!=null) sb.informChanged(); } @Override public void setTitle(String title) { super.setTitle(title); if(sb!=null) sb.informChanged(); } @Override public void attention() { if(sb!=null) sb.attention(); } @Override public long getAttentionTime() { if(sb != null) { return sb.getAttentionTime(); } return 0; } boolean isReasonablyVisible() { return owner.isReasonablyVisible(this); } boolean canClearAttention() { return wi.canClearAttention(); } @Override public void setBounds(int x,int y,int w,int h) { super.setBounds(x,y,w,h); if(pastStartup && wi!=null) wi.informMoved(false,x,y); if(sb!=null) sb.informMoved(); } void setSwitchButton(SwitchBar.SwitchButton sb) { this.sb=sb; } /** Keep track of our button */ private SwitchBar.SwitchButton sb; @Override public void killSilently() { wi=null; dispose(); } @Override public void initialiseFrom(FrameHolder fh) { setTitle(fh.getTitle()); if(fh.getIcon()!=null) setIcon(fh.getIcon()); setResizable(fh.isResizable()); setClosable(fh.isClosable()); if(fh.isMinimized()) handleMinimize(); } @Override public boolean isActive() { return active; } @Override public boolean isHidden() { return !isShowing() || PlatformUtils.isMacAppHidden(); } }