/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2007, by :
* Corporate:
* EADS Astrium
* Individual:
* Claude Cazenave
*
* $Id: UniversePool.java,v 1.7 2008/12/17 22:37:53 cazenave Exp $
*
* Changes
* -------
* 6 janv. 08 : Initial public release
*
*/
package jsynoptic.plugins.java3d;
import java.awt.Component;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Node;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
import jsynoptic.ui.JSynoptic;
import simtools.util.CurrentPathProvider;
import simtools.util.FileSerializer;
/**
* A pool to contain and retrieve the used Universe
*/
public class UniversePool {
public static final String JAVA_3D_FILE_EXT = ".j3d";
/**
* A global pool for all to use
*/
private static UniversePool _global;
/**
* A global file chooser
*/
private static JFileChooser _chooser = null;
private class PoolEntry{
File f;
Universe u;
};
/**
* A list reflecting creation order of universe
*/
private ArrayList<PoolEntry> _list;
/** a list of listener */
ArrayList<Listener> _listeners;
/**
* A counter to compute new universe name
*/
private int _counter;
private Universe _currentUniverse;
public static UniversePool getGlobal() {
if (_global == null) {
_global = new UniversePool();
}
return _global;
}
private static BranchGroup createSimpleSceneGraph() {
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
// Create the TransformGroup node and initialize it to the
// identity. Enable the TRANSFORM_WRITE capability so that
// our behavior code can modify it at run time. Add it to
// the root of the subgraph.
TransformGroup objTrans = new TransformGroup();
Transform3D t3dTrans = new Transform3D();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objTrans.setTransform(t3dTrans);
objRoot.addChild(objTrans);
BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
100.0);
// Set up the ambient light
Color3f ambientColor = new Color3f(0.3f, 0.3f, 0.3f);
AmbientLight ambientLightNode = new AmbientLight(ambientColor);
ambientLightNode.setInfluencingBounds(bounds);
objRoot.addChild(ambientLightNode);
// Set up one directional lights
Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
Vector3f light1Direction = new Vector3f(1.0f, 1.0f, 1.0f);
DirectionalLight light1 = new DirectionalLight(light1Color,
light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
return objRoot;
}
public UniversePool() {
_list = new ArrayList<PoolEntry>();
_counter = 1;
_currentUniverse = null;
_listeners = new ArrayList<Listener>();
}
public Universe getCurrentUniverse() {
if (_currentUniverse == null) {
if (_list.size() > 0) {
_currentUniverse = _list.get(0).u;
}
}
// if none create one
if (_currentUniverse == null) {
_currentUniverse = createUniverse();
}
return _currentUniverse;
}
public void setCurrentUniverse(Universe u) {
_currentUniverse = u;
}
public void addListner(Listener l) {
_listeners.add(l);
}
public void removeListner(Listener l) {
_listeners.remove(l);
}
public interface Listener {
public void notifyChange();
}
public Universe[] getSortedList() {
Universe[] res=new Universe[_list.size()];
int i=0;
for(PoolEntry e : _list){
res[i++]=e.u;
}
return res;
}
public ArrayList<Node> getNodes(Class<? extends Node> nodeClass){
ArrayList<Node> res=new ArrayList<Node>();
for(PoolEntry e : _list){
res.addAll(e.u.getNodes(nodeClass));
}
return res;
}
public Universe createUniverse() {
Universe u = new Universe();
u.addBranchGraph(createSimpleSceneGraph());
addUniverse(u, new File("Universe" + _counter + JAVA_3D_FILE_EXT));
_counter++;
return u;
}
public void removeUniverse(Universe u) throws IOException {
int i=0;
for(PoolEntry p : _list){
if(p.u==u){
break;
}
i++;
}
if(i<_list.size()){
// check if already in use
if (_list.get(i).u._viewers.size() > 0) {
throw new IOException("Can not overwrite universe in use");
}
_list.remove(i);
for (Listener l : _listeners) {
l.notifyChange();
}
}
if (_currentUniverse == u) {
_currentUniverse = null;
}
}
public void saveUniverse(Universe u, Component parent) throws IOException {
if (!u.getFile().exists()) {
File f = selectFile(parent, true);
if (f != null) {
addUniverse(u, f);
u.write(u.getFile());
}
} else {
u.write(u.getFile());
}
}
public Universe loadUniverse(File f) throws IOException {
int i=0;
for(PoolEntry p : _list){
if(p.f.equals(f)){
break;
}
i++;
}
if(i<_list.size()){
// check if already in use
if (_list.get(i).u._viewers.size() > 0) {
throw new IOException("Can not overwrite universe in use");
}
_list.remove(i);
}
Universe nu = new Universe();
nu.read(f);
addUniverse(nu, f);
return nu;
}
public File getFile(Universe u) {
for(PoolEntry p : _list){
if(p.u==u){
return p.f;
}
}
return null;
}
public Universe getUniverse(File f) {
for(PoolEntry p : _list){
if(p.f.equals(f)){
return p.u;
}
}
return null;
}
/**
* Universe serialization helper
*/
public Universe readUniverse(ObjectInputStream in) throws IOException {
FileSerializer fs = new FileSerializer();
File res;
try {
res = fs.read(in, CurrentPathProvider.currentPathProvider
.getCurrentPath());
} catch (ClassNotFoundException e) {
throw new IOException(e.getMessage());
}
Universe u = getUniverse(res);
if (u == null) {
return loadUniverse(res);
} else {
return u;
}
}
/**
* Universe serialization helper
*/
public void writeUniverse(ObjectOutputStream out, Universe u)
throws IOException {
saveUniverse(u, JSynoptic.gui.getOwner());
FileSerializer fs = new FileSerializer();
fs.write(out, u.getFile(), CurrentPathProvider.currentPathProvider
.getCurrentPath());
}
/**
* Add a universe or just rename it if it exists
*
* @param u
* the universe
* @param f
* the file to use
* @return true if universe has been renamed
*/
private boolean addUniverse(Universe u, File f) {
boolean renamed = false;
int i=0;
for(PoolEntry p : _list){
if(p.u==u){
break;
}
i++;
}
if(i<_list.size()){
_list.get(i).f=f;
renamed=true;
}
if (!renamed) {
PoolEntry p=new PoolEntry();
p.u=u;
p.f=f;
_list.add(p);
}
for (Listener l : _listeners) {
l.notifyChange();
}
return renamed;
}
public static File selectFile(Component parent, boolean save) {
if (_chooser == null) {
_chooser = createChooser();
}
if (save) {
if (_chooser.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) {
// check if no extension
File f = _chooser.getSelectedFile();
if (!f.getName().endsWith(JAVA_3D_FILE_EXT)) {
String name = f.getName();
int k = name.lastIndexOf('.');
if (k < 0) {
name = name + JAVA_3D_FILE_EXT;
} else {
name = name.substring(0, k) + JAVA_3D_FILE_EXT;
}
f = new File(f.getParentFile(), name);
}
return f;
}
} else {
if (_chooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
return _chooser.getSelectedFile();
}
}
return null;
}
private static JFileChooser createChooser() {
JFileChooser chooser = new JFileChooser();
// to prevent a deadlock (using Java6) make a copy of the File
chooser.setCurrentDirectory(new File(CurrentPathProvider.currentPathProvider.getCurrentPath().getAbsolutePath()));
chooser.setFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
return f.getName().endsWith(JAVA_3D_FILE_EXT);
}
@Override
public String getDescription() {
// TODO i18n
return "Java3D serialization file";
}
}); // don't want all
return chooser;
}
}