/* This file is part of the source code for 3D-XplorMath-J, Version 1.0 (January 2008).
* Copyright (c) 2008 The 3D-XplorMath Consortium (http://3d-xplormath.org).
* This source code is released under a BSD License, which allows redistribution
* in source and binary form, with or without modification, provided copyright
* and license information are included, and with no warranty or guarantee of
* any kind. For details, see http://3d-xplormath.org/j/source/BSDLicense.txt
*/
package vmm3d.xm3d;
import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.TreeSet;
import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import vmm3d.core.Exhibit;
import vmm3d.core.I18n;
import vmm3d.core.Prefs;
public class Galleries {
private GalleryItemList defaultGallery;
private ArrayList items; // GalleryItemLists, and nulls to indicate separators
private GalleryItemList currentGallery;
private String currentGalleryName;
static class GalleryItem {
String name;
String title;
}
static class ExhibitItem extends GalleryItem {
boolean isXML;
String classname; // for xml, this is the resource file name
}
private static class GalleryItemList extends GalleryItem{
String nodeType; // "gallery", "gallery_group", "exhibit_group"
ArrayList items; // nulls indicate separators
}
private class SelectGalleryAction extends AbstractAction {
JMenu exhibitMenu;
GalleryItemList gallery;
Menus menus;
SelectGalleryAction(Menus menus, GalleryItemList gallery, JMenu exhibitMenu) {
super(gallery.title);
this.menus = menus;
this.gallery = gallery;
this.exhibitMenu = exhibitMenu;
}
public void actionPerformed(ActionEvent evt) {
currentGalleryName = gallery.name;
menus.installExhibit(null);
setUpExhibitMenu(menus, exhibitMenu, gallery);
}
}
private class SelectExhibitAction extends AbstractAction {
Menus menus;
ExhibitItem exhibitItem;
SelectExhibitAction(Menus menus, ExhibitItem exhibitItem) {
super(exhibitItem.title);
this.menus = menus;
this.exhibitItem = exhibitItem;
}
public void actionPerformed(ActionEvent evt) {
menus.installExhibit(exhibitItem);
}
}
public Galleries() throws IOException {
this("vmm3d/xm3d/galleries.xml");
}
public Galleries(String resourceName) throws IOException {
InputStream input;
try {
ClassLoader cl = Galleries.class.getClassLoader();
URL resourceURL = cl.getResource(resourceName);
input = resourceURL.openStream();
}
catch (Exception e) {
throw new IOException(I18n.tr("3dxm.galleries.error.CantRead"));
}
readStream(input);
}
public Galleries(InputStream xmlStream) throws IOException {
readStream(xmlStream);
}
public String currentGalleryName() {
return currentGalleryName;
}
public void selectGalleryByName(String name, Menus menus, JMenu exhibitMenu) {
if (name == null) {
currentGalleryName = null;
return;
}
for (int i = 0; i < items.size(); i++) {
GalleryItemList item = items.get(i);
if (item.nodeType.equals("gallery")) {
if (item.name.equals(name)) {
setUpExhibitMenu(menus,exhibitMenu,item);
return;
}
}
else {
for (int j = 0; j < item.items.size(); j++) {
GalleryItemList subitem = (GalleryItemList)item.items.get(j);
if (subitem.name.equals(name)) {
setUpExhibitMenu(menus,exhibitMenu,subitem);
return;
}
}
}
}
currentGalleryName = null;
}
String findGalleryForExhibit(Exhibit exhibit) {
String classname = exhibit.getClass().getName();
for (GalleryItemList gallery : items) {
if (gallery == null)
continue;
if (gallery.nodeType.equals("gallery_group")) {
for (GalleryItem gg : gallery.items) {
if (gg == null)
continue;
assert gg instanceof GalleryItemList && ((GalleryItemList)gg).nodeType.equals("gallery");
if (findGalleryHelper(classname,(GalleryItemList)gg)) // must be a gallery
return gg.name;
}
}
else {
if (findGalleryHelper(classname,gallery))
return gallery.name;
}
}
return null;
}
private boolean findGalleryHelper(String classname, GalleryItemList group) {
for (GalleryItem item : group.items) {
if (item == null)
continue;
assert item instanceof ExhibitItem || (item instanceof GalleryItemList && ((GalleryItemList)item).nodeType.equals("exhbit_group"));
if (item instanceof GalleryItemList) { // must be an exhbit_group
for (GalleryItem exhibitItem : ((GalleryItemList)item).items)
if (exhibitItem != null && classname.equals(((ExhibitItem)exhibitItem).classname))
return true;
}
else { // must be an ExhibitItem
if (classname.equals(((ExhibitItem)item).classname))
return true;
}
}
return false;
}
public void setUpGalleryMenu(final Menus menus, JMenu galleryMenu, final JMenu exhibitMenu) {
for (int i = 0; i < items.size(); i++) {
if (items.get(i) == null)
galleryMenu.addSeparator();
else if ( items.get(i).nodeType.equals("gallery") ) {
GalleryItemList gallery = items.get(i);
galleryMenu.add( new SelectGalleryAction(menus,gallery,exhibitMenu) );
}
else { // must be a gallery_group
GalleryItemList gallery_group = items.get(i);
ArrayList subgallery = gallery_group.items;
JMenu submenu = new JMenu(gallery_group.title);
for (int j = 0; j < subgallery.size(); j++) {
if (subgallery.get(j) == null)
submenu.addSeparator();
else {
GalleryItemList gallery = (GalleryItemList)subgallery.get(j);
submenu.add( new SelectGalleryAction(menus,gallery,exhibitMenu) );
}
}
galleryMenu.add(submenu);
}
}
setUpExhibitMenu(menus, exhibitMenu, defaultGallery);
}
void setUpExhibitMenu(Menus menus, JMenu exhibitMenu) {
setUpExhibitMenu(menus,exhibitMenu,null);
}
private void setUpExhibitMenu(final Menus menus, JMenu exhibitMenu, GalleryItemList gallery) {
if (gallery == null)
gallery = currentGallery;
if (gallery == null)
gallery = defaultGallery;
currentGallery = gallery;
currentGalleryName = gallery.name;
exhibitMenu.removeAll();
exhibitMenu.setText(gallery.title);
for (int i = 0; i < gallery.items.size(); i++) {
if (gallery.items.get(i) == null)
exhibitMenu.addSeparator();
else if ( gallery.items.get(i) instanceof ExhibitItem ) {
exhibitMenu.add( new SelectExhibitAction(menus,(ExhibitItem)gallery.items.get(i)) );
}
else { // an array of strings, representing a submenu
GalleryItemList exhibitGroup = (GalleryItemList)gallery.items.get(i);
ArrayList items = exhibitGroup.items;
JMenu submenu = new JMenu(exhibitGroup.title);
for (int j = 0; j < items.size(); j++) {
if (items.get(j) == null)
submenu.addSeparator();
else
submenu.add( new SelectExhibitAction(menus,(ExhibitItem)items.get(j)));
}
exhibitMenu.add(submenu);
}
}
}
/*
* Syntax for galleries.xml document:
* -- Main element is
* -- can contain , , and
* -- can contain , , , and
* -- can contain and
* -- can contain and
* -- and are empty elements
* -- , and require a "name" attribute and have
* an optional "title" attribute giving a human-readable name for use in a menu. If not
* title is given, the title is obtained by applying I18n.tr() to the name.
* -- requires a "class" attribute whose value is the name of the class for the exhibit.
* Optional "name" attribute whose value defaults to the same as the class.
* Optional "title" attribute whose value to defaults to I18n.tr() applied to the name.
* -- requires a "file" attribue whose value is the resource file name
* of a saved settings file.
* Optional "name" attribute whose value defaults to the same as the resource file name.
* Optional "title" attribute whose value to defaults to I18n.tr() applied to the name.
* -- can have the attribute default="yes" to mark the default gallery
*/
private void readStream(InputStream xmlStream) throws IOException {
DocumentBuilder reader;
Document doc;
Element galleriesElement;
try {
reader = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
catch (Exception e) {
throw new IOException(I18n.tr("3dxm.galleries.error.CantDoXML"));
}
try {
doc = reader.parse(xmlStream);
}
catch (SAXException e) {
throw new IOException(I18n.tr("3dxm.galleries.error.NotXML",e.getMessage()));
}
catch (IOException e) {
throw new IOException(I18n.tr("3dxm.galleries.error.CantRead",e.getMessage()));
}
galleriesElement = doc.getDocumentElement();
if (! galleriesElement.getTagName().equals("galleries"))
throw new IOException(I18n.tr("3dxm.galleries.error.WrongXML",galleriesElement.getTagName()));
NodeList children = galleriesElement.getChildNodes();
items = new ArrayList();
for (int i = 0; i < children.getLength(); i++) {
if (children.item(i) instanceof Element) {
Element itemElement = (Element)children.item(i);
if (itemElement.getTagName().equals("gallery")) {
items.add(buildGallery(itemElement));
}
else if (itemElement.getTagName().equals("gallery_group")) {
items.add(buildGalleryGroup(itemElement));
}
else
throw new IOException(I18n.tr("3dxm.galleries.error.WrongXML",galleriesElement.getTagName()));
}
}
}
private GalleryItemList buildGallery(Element galleryElement) throws IOException {
String name = galleryElement.getAttribute("name").trim();
if (name.length() == 0)
throw new IOException(I18n.tr("3dxm.galleries.error.MissingAttribute", "name", "gallery"));
String title = galleryElement.getAttribute("title").trim();
if (title.length() == 0)
title = I18n.tr(name);
NodeList itemElements = galleryElement.getChildNodes();
int itemCount = itemElements.getLength();
ArrayList items = new ArrayList();
for (int i = 0; i < itemCount; i++) {
if (itemElements.item(i) instanceof Element) {
Element itemElement = (Element)itemElements.item(i);
String tagName = itemElement.getTagName();
if (tagName.equals("separator"))
items.add(null);
else if (tagName.equals("exhibit"))
items.add(buildGalleryItem(itemElement));
else if (tagName.equals("xml_exhibit"))
items.add(buildXMLGalleryItem(itemElement));
else if (tagName.equals("exhibit_group"))
items.add(buildGalleryItemGroup(itemElement));
else
throw new IOException(I18n.tr("3dxm.galleries.error.WrongXML",tagName));
}
}
GalleryItemList g = new GalleryItemList();
g.nodeType = "gallery";
g.name = name;
g.title = title;
g.items = items;
String isDefault = galleryElement.getAttribute("default").trim();
if (isDefault.equals("yes") || defaultGallery == null)
defaultGallery = g;
return g;
}
private GalleryItemList buildGalleryGroup(Element galleryGroupElement) throws IOException {
String name = galleryGroupElement.getAttribute("name").trim();
if (name.length() == 0)
throw new IOException(I18n.tr("3dxm.galleries.error.MissingAttribute", "name", "gallery_group"));
String title = galleryGroupElement.getAttribute("title").trim();
if (title.length() == 0)
title = I18n.tr(name);
NodeList itemElements = galleryGroupElement.getChildNodes();
int itemCount = itemElements.getLength();
ArrayList galleries = new ArrayList();
for (int i = 0; i < itemCount; i++) {
if (itemElements.item(i) instanceof Element) {
Element itemElement = (Element)itemElements.item(i);
String tagName = itemElement.getTagName();
if (tagName.equals("gallery"))
galleries.add(buildGallery(itemElement));
else if (tagName.equals("separator"))
galleries.add(null);
else
throw new IOException(I18n.tr("3dxm.galleries.error.WrongXML",tagName));
}
}
GalleryItemList g = new GalleryItemList();
g.nodeType = "gallery_group";
g.name = name;
g.title = title;
g.items = galleries;
return g;
}
private ExhibitItem buildGalleryItem(Element exhibitElement) throws IOException {
String classname = exhibitElement.getAttribute("class").trim();
if (classname.length() == 0)
throw new IOException(I18n.tr("3dxm.galleries.error.MissingAttribute", "class", "exhibit"));
String name = exhibitElement.getAttribute("name").trim();
if (name.length() == 0)
name = classname;
String title = exhibitElement.getAttribute("title").trim();
if (title.length() == 0)
title = I18n.tr(name);
ExhibitItem g = new ExhibitItem();
g.classname = classname;
g.name = name;
g.title = title;
g.isXML = false;
return g;
}
private ExhibitItem buildXMLGalleryItem(Element exhibitElement) throws IOException {
String classname = exhibitElement.getAttribute("file").trim();
if (classname.length() == 0)
throw new IOException(I18n.tr("3dxm.galleries.error.MissingAttribute", "file", "xml_exhibit"));
String name = exhibitElement.getAttribute("name").trim();
if (name.length() == 0)
name = classname;
String title = exhibitElement.getAttribute("title").trim();
if (title.length() == 0)
title = I18n.tr(name);
ExhibitItem g = new ExhibitItem();
g.classname = classname;
g.name = name;
g.title = title;
g.isXML = true;
return g;
}
private GalleryItemList buildGalleryItemGroup(Element exhibitGroupElement) throws IOException {
String name = exhibitGroupElement.getAttribute("name").trim();
if (name.length() == 0)
throw new IOException(I18n.tr("3dxm.galleries.error.MissingAttribute", "name", "exhibit_group"));
String title = exhibitGroupElement.getAttribute("title").trim();
if (title.length() == 0)
title = I18n.tr(name);
NodeList itemElements = exhibitGroupElement.getChildNodes();
int itemCount = itemElements.getLength();
ArrayList items = new ArrayList();
for (int i = 0; i < itemCount; i++) {
if (itemElements.item(i) instanceof Element) {
Element itemElement = (Element)itemElements.item(i);
String tagName = itemElement.getTagName();
if (tagName.equals("exhibit"))
items.add(buildGalleryItem(itemElement));
else if (tagName.equals("separator"))
items.add(null);
else
throw new IOException(I18n.tr("3dxm.galleries.error.WrongXML",tagName));
}
}
GalleryItemList g = new GalleryItemList();
g.nodeType = "exhibit_group";
g.name = name;
g.title = title;
g.items = items;
return g;
}
//----- static methods for managing the documentation location -------
private static String documentationLocation;
private static TreeSet documentationFileList;
private static Menus waitingForDocInfo;
private static int setDocLocationCount;
synchronized static void setDocumentationLocation() {
final String docLoc = Prefs.get("3dxm.docprefs.documentationBaseURL",
I18n.tr("3dxm.DocPrefsDialog.DefaultDocumentationLocation"));
if (docLoc.equals(documentationLocation))
return;
documentationLocation = docLoc;
documentationFileList = null;
setDocLocationCount++;
final int ct = setDocLocationCount;
Thread reader = new Thread() {
public void run() {
TreeSet files = new TreeSet();
try {
URL url;
if (docLoc.startsWith("http://")) {
String doc;
if (docLoc.endsWith("/"))
doc = docLoc + "doclist.txt";
else
doc = docLoc + "/" + "doclist.txt";
url = new URL(doc);
}
else {
File docFile = new File(docLoc, "doclist.txt");
url = docFile.getAbsoluteFile().toURI().toURL();
}
BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream(), "ISO-8859-1"));
while (true) {
String line = in.readLine();
if (line == null)
break;
files.add(line);
}
in.close();
}
catch (Exception e) {
System.out.println("Error reading documentation file list.\n" + e);
}
finally {
gotDocInfo(files,ct);
}
}
};
reader.start();
}
synchronized private static void gotDocInfo(TreeSet files, int idCount) {
if (idCount != setDocLocationCount)
return;
documentationFileList = files;
if (waitingForDocInfo != null) {
waitingForDocInfo.gotDocumnetationFileList(files);
waitingForDocInfo = null;
}
}
synchronized static boolean documentationFileExists(Menus requester, String fileName) {
if (documentationFileList == null) {
waitingForDocInfo = requester;
return false;
}
return documentationFileList.contains(fileName);
}
static {
setDocumentationLocation();
}
}
Ads help maintain this website.