/** * Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.codesourcery.jasm16.ide.ui.viewcontainers; import java.awt.Color; import java.awt.Dimension; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; import javax.swing.event.InternalFrameListener; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import de.codesourcery.jasm16.ide.IApplicationConfig; import de.codesourcery.jasm16.ide.ui.MenuManager; import de.codesourcery.jasm16.ide.ui.MenuManager.MenuEntry; import de.codesourcery.jasm16.ide.ui.utils.SizeAndLocation; import de.codesourcery.jasm16.ide.ui.utils.UIUtils; import de.codesourcery.jasm16.ide.ui.views.IView; import de.codesourcery.jasm16.ide.ui.views.IViewStateListener; /** * A view container that inherits from {@link JFrame} and uses {@link JInternalFrame}s to display * it's children. * * @author tobias.gierke@code-sourcery.de */ public class Perspective extends JFrame implements IViewContainer { private static final Logger LOG = Logger.getLogger(Perspective.class); private final JDesktopPane desktop = new JDesktopPane(); private final List<InternalFrameWithView> views = new ArrayList<InternalFrameWithView>(); private final String id; private final ViewContainerHelper helper = new ViewContainerHelper(); private final ViewContainerManager viewContainerManager; private final IApplicationConfig applicationConfig; private final MenuManager menuManager = new MenuManager() { @Override public void menuBarChanged() { setJMenuBar( menuManager.getMenuBar() ); } }; protected final class InternalFrameWithView { public final JInternalFrame frame; public final IView view; private final InternalFrameListener frameListener; public InternalFrameWithView(JInternalFrame frame,final IView view) { this.view = view; this.frame = frame; if ( view instanceof IViewStateListener ) { frameListener = new InternalFrameAdapter() { @Override public void internalFrameActivated(InternalFrameEvent e) { ((IViewStateListener) view).viewVisible(); } @Override public void internalFrameDeactivated(InternalFrameEvent e) { ((IViewStateListener) view).viewHidden(); } }; frame.addInternalFrameListener( frameListener ); } else { frameListener = null; } } public void dispose() { final SizeAndLocation sizeAndLoc = new SizeAndLocation( frame.getLocation() , frame.getSize() ); applicationConfig.storeViewCoordinates( getUniqueID( view ) , sizeAndLoc ); frame.dispose(); if ( frameListener != null ) { frame.removeInternalFrameListener( frameListener ); } LOG.debug("dispose(): Disposing "+view); view.dispose(); } } private final String getUniqueID(IView view) { return getID()+"."+view.getID(); } @Override public void setBlockAllUserInput(boolean yesNo) { UIUtils.setBlockAllUserInput( this , yesNo ); } @Override public final void dispose() { disposeHook(); final SizeAndLocation sizeAndLoc = new SizeAndLocation( getLocation() , getSize() ); applicationConfig.storeViewCoordinates( getID() , sizeAndLoc ); final List<InternalFrameWithView> views = new ArrayList<InternalFrameWithView>(this.views); for ( InternalFrameWithView v : views) { disposeView( v.view ); } super.dispose(); viewContainerManager.disposeAllExcept( this ); helper.fireViewContainerClosed( this ); try { this.applicationConfig.saveConfiguration(); } catch (IOException e) { LOG.error("dispose(): Failed to save view coordinates",e); } } protected void disposeHook() { } public Perspective(String id , final ViewContainerManager viewContainerManager , IApplicationConfig appConfig) { super("jASM16 DCPU emulator V"+de.codesourcery.jasm16.compiler.Compiler.getVersionNumber() ); if ( viewContainerManager == null ) { throw new IllegalArgumentException("viewContainerManager must not be null"); } if (appConfig == null) { throw new IllegalArgumentException("appConfig must not be null"); } if (StringUtils.isBlank(id)) { throw new IllegalArgumentException("ID must not be NULL/blank."); } this.viewContainerManager = viewContainerManager; this.id = id; this.applicationConfig = appConfig; setPreferredSize( new Dimension(400,200 ) ); getContentPane().add( desktop ); setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE ); setBackground( Color.BLACK ); setForeground( Color.GREEN ); desktop.setBackground( Color.BLACK ); desktop.setForeground( Color.GREEN ); menuManager.addEntry( new MenuEntry("File/Quit") { @Override public void onClick() { dispose(); try { applicationConfig.saveConfiguration(); } catch (IOException e) { e.printStackTrace(); } finally { System.exit(0); } } } ); final SizeAndLocation sizeAndLoc = applicationConfig.getViewCoordinates( getID() ); if ( sizeAndLoc != null ) { setLocation( sizeAndLoc.getLocation() ); setSize( sizeAndLoc.getSize() ); setPreferredSize( sizeAndLoc.getSize() ); } else { setPreferredSize( new Dimension(600,800 ) ); pack(); } setJMenuBar( menuManager.getMenuBar() ); } @Override public void disposeView(IView view) { for (Iterator<InternalFrameWithView> it = this.views.iterator(); it.hasNext();) { InternalFrameWithView frame = it.next(); if ( frame.view == view ) { frame.dispose(); it.remove(); return; } } } @Override public IView addView(final IView view) { if (view == null) { throw new IllegalArgumentException("view must not be NULL"); } final JInternalFrame internalFrame = new JInternalFrame( view.getTitle(),true, true, true, true); internalFrame.setBackground(Color.BLACK); internalFrame.setForeground( Color.GREEN ); internalFrame.getContentPane().add( view.getPanel(this) ); SizeAndLocation sizeAndLoc = applicationConfig.getViewCoordinates( getUniqueID( view ) ); if ( sizeAndLoc != null ) { internalFrame.setSize( sizeAndLoc.getSize() ); internalFrame.setLocation( sizeAndLoc.getLocation() ); } else { internalFrame.setSize(200, 150); internalFrame.setLocation( 0 , 0 ); internalFrame.pack(); } internalFrame.setVisible( true ); final InternalFrameWithView frameAndView = new InternalFrameWithView( internalFrame , view ); final InternalFrameListener listener = new InternalFrameAdapter() { @Override public void internalFrameClosing(InternalFrameEvent e) { disposeView( view ); } }; internalFrame.setDefaultCloseOperation( JInternalFrame.DO_NOTHING_ON_CLOSE ); internalFrame.addInternalFrameListener( listener ); views.add( frameAndView ); desktop.add(internalFrame); return view; } @Override public List<IView> getViews() { final List<IView> result = new ArrayList<IView>(); for (InternalFrameWithView frame : this.views) { result.add( frame.view ); } return result; } @Override public void setTitle(IView view, String title) { for (InternalFrameWithView frame : this.views) { if ( frame.view == view ) { frame.frame.setTitle( title ); break; } } } @Override public IView getViewByID(String viewId) { if (StringUtils.isBlank(viewId)) { throw new IllegalArgumentException("viewId must not be blank/null"); } for (InternalFrameWithView frame : this.views) { if ( frame.view.getID().equals( viewId ) ) { return frame.view; } } return null; } @Override public final void toFront(IView view) { for (InternalFrameWithView frame : this.views) { if ( frame.view.getID().equals( view.getID() ) ) { frame.frame.toFront(); return; } } } @Override public MenuManager getMenuManager() { return menuManager; } @Override public final String getID() { return id; } @Override public void addViewContainerListener(IViewContainerListener listener) { helper.addViewContainerListener( listener ); } @Override public void removeViewContainerListener(IViewContainerListener listener) { helper.removeViewContainerListener( listener ); } }