/*
* This file is part of Caliph & Emir.
*
* Caliph & Emir 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 2 of the License, or
* (at your option) any later version.
*
* Caliph & Emir 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 Caliph & Emir; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Copyright statement:
* --------------------
* (c) 2002-2005 by Mathias Lux (mathias@juggle.at)
* http://www.juggle.at, http://caliph-emir.sourceforge.net
*/
package at.lux.fotoannotation;
import at.knowcenter.caliph.objectcatalog.semanticscreator.IMBeeApplicationPanel;
import at.lux.components.ImageThumbPanel;
import at.lux.components.StatusBar;
import at.lux.fotoannotation.dialogs.*;
import at.lux.fotoannotation.mpeg7.Mpeg7ImageDescription;
import at.lux.fotoannotation.mpeg7.Mpeg7ThumbnailMediaProfile;
import at.lux.fotoannotation.panels.*;
import at.lux.fotoannotation.utils.TextChangesListener;
import at.lux.splash.SplashScreen;
import at.wklieber.LoggerInit;
import com.jgoodies.looks.BorderStyle;
import com.jgoodies.looks.HeaderStyle;
import com.jgoodies.looks.Options;
import com.jgoodies.looks.plastic.PlasticLookAndFeel;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.DecimalFormat;
import java.util.Properties;
/**
* This Class is the main JFrame where the application is started.
*
* @author Mathias Lux, mathias@juggle.at
* @version 0.9 alpha
*/
public class AnnotationFrame extends JFrame implements ActionListener, StatusBar {
public static final boolean DEBUG = false;
public static boolean DIRTY = false;
public static String TITLE_BAR = AnnotationToolkit.PROGRAM_NAME + " " + AnnotationToolkit.PROGRAM_VERSION;
private AnnotationFrameProperties properties;
private ImageThumbPanel imagePanel;
private MetadataDescriptionPanel mdPanel;
private QualityPanel qualityPanel;
private TextDescriptionPanel textPanel;
private ShapePanel shapePanel;
// private AgentComboBoxModel agentsModel;
private File currentFile = null;
private JSplitPane lrSplit, tbSplit;
private JTabbedPane tabs;
private CreationPanel creationPanel;
private DecimalFormat df;
private JLabel status;
private IMBeeApplicationPanel beePanel;
private ColorLayoutPanel colorPanel;
private JPanel gridPanel1;
private JProgressBar garbageState;
private GarbageTracker gtracker;
private FileTreeModel fileTreeModel = new FileTreeModel();
private JTree fileTree = new JTree(fileTreeModel);
private JComboBox fileComboBox;
private Properties currentFileProperties = new Properties();
private boolean autopilot = false;
private boolean systemExitOnWindowClosing = true;
public AnnotationFrame() {
super(TITLE_BAR);
init();
}
public AnnotationFrame(boolean systemExitOnWindowClosing) {
super(TITLE_BAR);
this.systemExitOnWindowClosing = systemExitOnWindowClosing;
init();
}
private void init() {
try {
LoggerInit.configureLog4j("log4j.properties", "INFO");
this.setIconImage(ImageIO.read(AnnotationFrame.class.getResource("data/caliph-icon.png")));
// this.setIconImage(ImageIO.read(AnnotationFrame.class.getResource("data/icon.gif")));
} catch (Exception e) {
debug("Couldn't set Icon: IOException " + e.getMessage());
}
df = (DecimalFormat) DecimalFormat.getInstance();
df.setMaximumFractionDigits(2);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
super.windowClosing(event);
exitApplication();
}
});
// -------------------------------------------------------------------------------
// Ueberpruefung ob das agent file existiert, sonst muss es angelegt werden ...
// Eine sicherheitskopie befindet sich im package ...
// -------------------------------------------------------------------------------
debug("Checking if agentfile is here ...");
File agentsFile = new File(AnnotationToolkit.AGENTS_FILE);
if (!agentsFile.exists()) {
try {
debug("Generating sample agents file");
Document d = new SAXBuilder().build(AnnotationFrame.class.getResource("data/agents.mp7.xml"));
FileOutputStream fos = new FileOutputStream(agentsFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
new XMLOutputter(Format.getPrettyFormat()).output(d, osw);
osw.close();
fos.close();
debug("Finished generating sample agents file");
} catch (Exception e) {
debug("Error generating sample agents file " + e.toString() + ", " + e.getMessage());
}
} else {
debug("agentfile found :)");
}
debug("reading configurationfile ... ");
// -------------------------------------------------------------------------------
// Ueberpruefung ob das base-object file existiert, sonst muss es angelegt werden.
// Eine sicherheitskopie befindet sich im package ...
// -------------------------------------------------------------------------------
debug("Checking if agentfile is here ...");
File baseobjectsFile = new File("base-objects.mp7.xml");
if (!baseobjectsFile.exists()) {
try {
debug("Generating sample base-objects file");
Document d = new SAXBuilder().build(AnnotationFrame.class.getResource("data/base-objects.mp7.xml"));
FileOutputStream fos = new FileOutputStream(baseobjectsFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
new XMLOutputter(Format.getPrettyFormat()).output(d, osw);
osw.close();
fos.close();
debug("Finished generating sample base-objects file");
} catch (Exception e) {
debug("Error generating sample base-objects file " + e.toString() + ", " + e.getMessage());
}
} else {
debug("base-objects file found :)");
}
debug("reading configurationfile ... ");
// -------------------------------------------------------------------------------
// Ueberpruefung ob das property file existiert, sonst muss es angelegt werden ...
// Eine sicherheitskopie befindet sich im package ...
// -------------------------------------------------------------------------------
File pFile = new File("properties.xml");
if (!pFile.exists()) {
try {
debug("Generating sample property file");
Document d = new SAXBuilder().build(AnnotationFrame.class.getResource("data/properties.xml"));
FileOutputStream fos = new FileOutputStream(pFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
new XMLOutputter(Format.getPrettyFormat()).output(d, osw);
osw.close();
fos.close();
debug("Finished generating sample property file");
} catch (Exception e) {
debug("Error generating sample property file " + e.toString() + ", " + e.getMessage());
}
}
properties = new AnnotationFrameProperties(new File("properties.xml"), this);
debug("finished reading configurationfile");
JMenuBar menuBar = properties.getMenuBar();
// For JGoodies Look & Feel:
menuBar.putClientProperty(Options.HEADER_STYLE_KEY, HeaderStyle.BOTH);
menuBar.putClientProperty(PlasticLookAndFeel.BORDER_STYLE_KEY, BorderStyle.SEPARATOR);
this.setJMenuBar(menuBar);
debug("finished creating menu");
fileTree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent tse) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tse.getNewLeadSelectionPath().getLastPathComponent();
if (node.getUserObject() instanceof FileNodeObject) {
File f = ((FileNodeObject) node.getUserObject()).getContent();
if (!f.isDirectory()) {
try {
setCurrentFile(f);
} catch (IOException e) {
System.err.println("Error opening file: " + f.toString());
System.err.println(e.toString());
// e.printStackTrace();
}
}
}
}
});
setToCurrentLocation(fileTree);
// -------------------------------------
// Initialising main Objects ...
// -------------------------------------
// TextChangeListener intialization for detecting changes of the document.
TextChangesListener.createInstance(this);
// -------------------------------------
// Adding Components
// -------------------------------------
beePanel = new IMBeeApplicationPanel(this);
colorPanel = new ColorLayoutPanel();
lrSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
lrSplit.setBorder(BorderFactory.createEmptyBorder());
lrSplit.setDividerSize(3);
tbSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
tbSplit.setBorder(BorderFactory.createEmptyBorder());
tbSplit.setDividerSize(3);
mdPanel = new MetadataDescriptionPanel(new AgentComboBoxModel(this));
imagePanel = new ImageThumbPanel();
// fp = new FilePanel(new File("."), this);
qualityPanel = new QualityPanel(new AgentComboBoxModel(this));
textPanel = new TextDescriptionPanel(this);
creationPanel = new CreationPanel(new AgentComboBoxModel(this));
shapePanel = new ShapePanel(this);
JPanel qualTextPanel = new JPanel(new BorderLayout());
qualTextPanel.add(qualityPanel, BorderLayout.SOUTH);
qualTextPanel.add(textPanel, BorderLayout.CENTER);
gridPanel1 = new JPanel(new GridLayout(0, 2));
JPanel _leftPanel1 = new JPanel(new BorderLayout());
// gridPanel2.add(textPanel);
_leftPanel1.add(qualTextPanel, BorderLayout.CENTER);
_leftPanel1.add(mdPanel, BorderLayout.SOUTH);
gridPanel1.add(_leftPanel1);
gridPanel1.add(creationPanel);
JPanel gridPanel3 = new JPanel(new GridLayout(0, 1));
gridPanel3.add(colorPanel);
// gridPanel3.add(qualTextPanel);
tabs = new JTabbedPane(JTabbedPane.TOP);
tabs.setBorder(BorderFactory.createEmptyBorder());
tabs.add("Image Information", gridPanel1);
tabs.add("Semantics", beePanel);
tabs.add("Shape", shapePanel);
tabs.add("Visuals", gridPanel3);
// file tree ....
// ---------------
JScrollPane fileTreeScrollPane = new JScrollPane(fileTree);
JPanel filePanel = new JPanel(new BorderLayout());
filePanel.add(fileTreeScrollPane, BorderLayout.CENTER);
// TODO: remove error here ...
fileComboBox = new JComboBox(File.listRoots());
fileComboBox.setActionCommand("rootChanged");
fileComboBox.addActionListener(this);
filePanel.add(fileComboBox, BorderLayout.NORTH);
tbSplit.add(filePanel, JSplitPane.TOP);
tbSplit.add(imagePanel, JSplitPane.BOTTOM);
lrSplit.add(tbSplit, JSplitPane.LEFT);
lrSplit.add(tabs, JSplitPane.RIGHT);
lrSplit.setDividerLocation(properties.getLrSplit());
tbSplit.setDividerLocation(properties.getTbSplit());
status = new JLabel(TITLE_BAR);
status.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
garbageState = new JProgressBar(JProgressBar.HORIZONTAL, 0, 100);
garbageState.setStringPainted(true);
garbageState.setPreferredSize(new Dimension(100, 18));
garbageState.setToolTipText("This bar shows the memory allocated by the VM and how much of it is already in use.");
garbageState.setBorder(BorderFactory.createEmptyBorder());
gtracker = new GarbageTracker(garbageState);
JPanel sgcPanel = new JPanel(new BorderLayout());
sgcPanel.add(garbageState, BorderLayout.EAST);
sgcPanel.add(status, BorderLayout.CENTER);
this.getContentPane().add(lrSplit, BorderLayout.CENTER);
this.getContentPane().add(sgcPanel, BorderLayout.SOUTH);
this.setSize(properties.getFrameWidth(), properties.getFrameHeigth());
this.setLocation(properties.getFrameLocationX(), properties.getFrameLocationY());
beePanel.reArrange();
//beePanel.revalidate();
gtracker.start();
// call init from global configuration while splash is on screen :)
IconCache.getInstance();
}
private void setToCurrentLocation(JTree fileTree) {
// Todo select the node with the current location and show and select it.
// TreePath p = new TreePath(pathObjects);
// fileTree.setSelectionPath(p);
// fileTree.treeDidChange();
}
/**
* Main method used to embedGraph Caliph
*
* @param args
*/
public static void main(String[] args) {
JWindow w = new JWindow();
try {
w = new JWindow();
BufferedImage img = ImageIO.read(AnnotationFrame.class.getResourceAsStream("data/SplashCaliph.png"));
FullSizeImagePanel panel = new FullSizeImagePanel(img);
w.getContentPane().add(panel, BorderLayout.CENTER);
w.pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
w.setLocation((screenSize.width - w.getWidth()) / 2, (screenSize.height - w.getHeight()) / 2);
w.setVisible(true);
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
UIManager.put("Application.useSystemFontSettings", Boolean.TRUE);
// PlasticLookAndFeel.setTabStyle(PlasticLookAndFeel.TAB_STYLE_METAL_VALUE);
try {
UIManager.setLookAndFeel(new PlasticLookAndFeel());
} catch (Exception e) {
System.err.println("Could not set Look & Feel: " + e.toString());
}
boolean showSplash = true;
// get config file from splashscreen class
File splashProps = new File(SplashScreen.LICENSE_ACCEPTED_FILENAME);
// look if exists
if (splashProps.exists()) {
// load props
try {
Properties licenseAcceptedProps = new Properties();
licenseAcceptedProps.load(new FileInputStream(splashProps));
// if property is set we do not have to show the splashscreen:
String tmp = licenseAcceptedProps.getProperty("license.accepted");
if (tmp != null && tmp.equals("true")) {
showSplash = false;
}
} catch (IOException e) {
System.err.println("Warn: Could not read license properties file.");
}
}
// if there is some problem starting Caliph the program exits
// and gives some error message:
try {
AnnotationFrame frame = new AnnotationFrame();
if (showSplash) {
// now show the splash screen if this has not been done before.
SplashScreen splash = new SplashScreen(frame);
splash.setVisible(true);
}
if (w != null) w.setVisible(false);
frame.setVisible(true);
} catch (Exception e) {
JOptionPane.showConfirmDialog(null, "Error: " + e.toString(), "Error starting Caliph!", JOptionPane.OK_OPTION, JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
System.exit(0);
}
}
/**
* implemented from Interface ActionListener
*/
public void actionPerformed(ActionEvent event) {
// gtracker.run();
String actionCommand = event.getActionCommand();
if (actionCommand.equals("exitApplication")) {
exitApplication();
} else if (actionCommand.equals("openFile")) {
debug("open file operation initiated");
openFile();
debug("open file operation ended");
} else if (actionCommand.equals("showAbout")) {
AboutDialog adialog = new AboutDialog(this);
adialog.pack();
adialog.setResizable(false);
Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
adialog.setLocation((ss.width - adialog.getWidth()) / 2, (ss.height - adialog.getHeight()) / 2);
adialog.setVisible(true);
} else if (actionCommand.equals("visitHomepage")) {
openUrlInBrowser(properties.getUrlHomepage());
} else if (actionCommand.equals("showHelpOnline")) {
String helpURL = properties.getUrlHelp();
openUrlInBrowser(helpURL);
} else if (actionCommand.equals("showHelp")) {
HelpDialog adialog = new HelpDialog(this);
// adialog.pack();
Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
adialog.setLocation((ss.width - adialog.getWidth()) / 2, (ss.height - adialog.getHeight()) / 2);
adialog.setVisible(true);
} else if (actionCommand.equals("saveFileAs")) {
JOptionPane.showMessageDialog(this, "not implemented yet");
} else if (actionCommand.equals("gc")) {
debug("Mem: "
+ df.format(Runtime.getRuntime().freeMemory() / (1024.0 * 1024.0)) + "MB of "
+ df.format(Runtime.getRuntime().totalMemory() / (1024.0 * 1024.0)) + "MB free");
debug("starting garbage collector ...");
System.gc();
debug("finished collecting garbage!");
debug("Mem: "
+ df.format(Runtime.getRuntime().freeMemory() / (1024.0 * 1024.0)) + "MB of "
+ df.format(Runtime.getRuntime().totalMemory() / (1024.0 * 1024.0)) + "MB free");
status.setText("Garbage collection finished: "
+ df.format(Runtime.getRuntime().freeMemory() / (1024.0 * 1024.0)) + "MB of "
+ df.format(Runtime.getRuntime().totalMemory() / (1024.0 * 1024.0)) + "MB free");
// gtracker.embedGraph();
} else if (actionCommand.equals("viewXML")) {
if (getCurrentFile() == null) {
JOptionPane.showMessageDialog(this, "No image has been selected.", "Error", JOptionPane.WARNING_MESSAGE);
return;
}
TextPreviewDialog preview = new TextPreviewDialog(this, createDocument());
preview.setSize(properties.getTextViewWidth(), properties.getTextViewHeight());
Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
preview.setLocation((ss.width - preview.getWidth()) / 2, (ss.height - preview.getHeight()) / 2);
preview.setVisible(true);
properties.setTextViewHeight(preview.getHeight());
properties.setTextViewWidth(preview.getWidth());
} else if (actionCommand.equals("saveFile")) {
if (currentFile != null) {
saveFile();
} else {
JOptionPane.showMessageDialog(this, "No image selected!");
}
} else if (actionCommand.equals("viewExternal")) {
if (currentFile != null && properties.getExternalViewer() != null) {
try {
debug("Run: " + properties.getExternalViewer() + " \"" + currentFile.getCanonicalPath() + "\"");
Runtime.getRuntime().exec(properties.getExternalViewer() + " \"" + currentFile.getCanonicalPath() + "\"");
} catch (IOException e) {
debug("Error with external viewer - " + e.toString() + ": " + e.getMessage());
}
}
} else if (actionCommand.equals("setExternal")) {
ExternalViewerSelectDialog d = new ExternalViewerSelectDialog(this, properties.getExternalViewer());
d.pack();
Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
d.setLocation((ss.width - d.getWidth()) / 2, (ss.height - d.getHeight()) / 2);
d.setVisible(true);
properties.setExternalViewer(d.getExternalViewer());
} else if (actionCommand.equals("autoPilot")) {
if (currentFile != null) {
startAutoPilot();
}
} else if (actionCommand.equals("rootChanged")) {
File f = (File) fileComboBox.getSelectedItem();
fileTreeModel.setRoot(f);
} else if (actionCommand.equals("delAgent")) {
DeleteAgentDialog d = new DeleteAgentDialog(this);
d.pack();
Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
d.setLocation((ss.width - d.getWidth()) / 2, (ss.height - d.getHeight()) / 2);
d.setVisible(true);
} else {
JOptionPane.showMessageDialog(this, "Not Implemented!");
}
}
private void openUrlInBrowser(String url) {
String osName = System.getProperty("os.name");
// take linux settings
String browserCmd = properties.getBrowserLinux();
// or windows in case of windows :)
if (osName.toLowerCase().indexOf("windows") > -1) {
browserCmd = properties.getBrowserWindows();
}
browserCmd = browserCmd.replace("{url}", url);
try {
Runtime.getRuntime().exec(browserCmd);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Could not start browser. Please surf to "
+ url + " to visit the online help.");
}
}
/**
* is called when applikation is exited ...
* saving properties and closing app.
* todo: save file? dialog
*/
private void exitApplication() {
properties.setFrameHeigth(this.getHeight());
properties.setFrameWidth(this.getWidth());
properties.setFrameLocationX(this.getLocation().x);
properties.setFrameLocationY(this.getLocation().y);
properties.setTbSplit(tbSplit.getDividerLocation());
properties.setLrSplit(lrSplit.getDividerLocation());
debug("saving configuration ...");
properties.saveConfiguration();
debug("finished saving configuration");
debug("saving semantic objects ...");
beePanel.saveCatalog();
debug("semantic objects saved");
if (DIRTY) {
if (askIfSave()) {
if (systemExitOnWindowClosing) {
System.exit(0);
} else {
setVisible(false);
}
}
} else {
if (systemExitOnWindowClosing) {
System.exit(0);
} else {
setVisible(false);
}
}
}
private boolean askIfSave() {
int returnVal = JOptionPane.showConfirmDialog(this, "Would you like to save your changes? Otherwise your changes will be lost.", "Save description?", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (returnVal == JOptionPane.YES_OPTION) {
debug("Save file ...");
saveFile();
return true;
} else if (returnVal == JOptionPane.NO_OPTION) {
debug("Quit without saving ...");
return true;
} else {
debug("no quitting, no saving :)");
return false;
}
}
private void startAutoPilot() {
AutoPilotThread t = new AutoPilotThread(this, currentFile);
t.start();
}
/**
* is called when a file is explicitely openend, meanwhile not used :)
*/
private void openFile() {
JFileChooser jfc = new JFileChooser(properties.getLastDir());
// jfc.setCurrentDirectory(new File(properties.getLastDir()));
if (JFileChooser.APPROVE_OPTION == jfc.showOpenDialog(this)) {
debug("opening file: " + jfc.getSelectedFile().toString());
properties.setLastDir(jfc.getCurrentDirectory().toString());
debug("saving path: " + jfc.getCurrentDirectory().toString());
try {
setCurrentFile(jfc.getSelectedFile());
} catch (IOException e) {
debug("Error reading File: " + e.toString());
}
}
// System.gc();
}
/**
* Set the "dirty" trag if information has changed :) needed for
* bugging the user with questions like: Do you want to save the
* file? or Unsaved changes will be lost :)
*
* @param isDirty
*/
public static void setDirty(boolean isDirty) {
DIRTY = isDirty;
}
/**
* set a new Image to edit ... thread-based ...
*/
public void setCurrentFile(File f) throws IOException {
boolean loadIt = true;
if (DIRTY) {
loadIt = askIfSave();
}
if (loadIt) {
ImageLoader t = new ImageLoader(status, this, f, imagePanel, creationPanel, textPanel, mdPanel, qualityPanel,
beePanel, colorPanel, shapePanel);
shapePanel.setDescriptor(null);
t.start();
currentFile = f;
}
}
/**
* loadCurrentFile is the not thread based method to load a file, it's used
* by the autopilot
*
* @param f defines the file to open
* @throws IOException
*/
public void loadCurrentFile(File f) throws IOException {
ImageLoader t = new ImageLoader(status, this, f, imagePanel, creationPanel, textPanel, mdPanel, qualityPanel,
beePanel, colorPanel, shapePanel);
t.run();
currentFile = f;
}
public void saveFile() {
if (currentFile != null) {
try {
XMLOutputter op = new XMLOutputter(Format.getPrettyFormat());
String imgName = currentFile.getCanonicalPath();
String fname = imgName.substring(0, imgName.lastIndexOf("."));
fname = fname + ".mp7.xml";
File saveFile = new File(fname);
// check if file is arleady in existence and ask if we should overwrite:
// boolean write = false;
// if (saveFile.exists()) {
// if (JOptionPane.showConfirmDialog(this,
// "Overwrite existing file?", "Overwrite?",
// JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
// write = true;
// }
// } else {
// write = true;
// }
if (true) {
FileOutputStream fos = new FileOutputStream(saveFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
op.output(createDocument(), osw);
osw.close();
fos.close();
debug("File written to " + saveFile.toString());
status.setText("File written to " + saveFile.toString());
setDirty(false);
if (getTitle().indexOf('*') > -1)
setTitle(getTitle().substring(2));
}
} catch (IOException e) {
debug("Exception while saving " + e.toString());
}
}
}
/**
* This is the method where all the information is collected and put together. The result is valid
* MPEG-7 Description
*/
public Document createDocument() {
Element mediaFormat, creation, tmp, semantics;
tmp = creationPanel.createXML();
mediaFormat = (Element) tmp.getChild("MediaFormat", tmp.getNamespace()).detach();
creation = (Element) tmp.getChild("CreationInformation", tmp.getNamespace()).detach();
tmp = beePanel.getSemanticsDocument().getRootElement();
semantics = ((Element) tmp.getChild("Description", tmp.getNamespace()).getChild("Semantics",
tmp.getNamespace()).clone());
semantics.setName("Semantic");
File thumbFile = AnnotationToolkit.generateThumbnail(currentFile);
Element thumbNailProfile = null;
Mpeg7ThumbnailMediaProfile thumbnail = null;
thumbnail = new Mpeg7ThumbnailMediaProfile(thumbFile, 120, 120);
thumbNailProfile = thumbnail.createDocument();
Mpeg7ImageDescription m7id = new Mpeg7ImageDescription(creation, mdPanel.createXML(), mediaFormat,
AnnotationToolkit.getMpeg7MediaInstance(currentFile),
qualityPanel.createXML(), thumbNailProfile, semantics, textPanel.createXML(), colorPanel.createXML());
Document document = m7id.createDocument();
// TODO: add shape here ...
Element shape = shapePanel.createXML();
java.util.List results = AnnotationToolkit.xpathQuery(shape, "//Image/SpatialDecomposition", null);
if (results.size() > 0) {
shape = (Element) ((Element) results.get(0)).detach();
java.util.List result = AnnotationToolkit.xpathQuery(document.getRootElement(), "//Image", null);
if (result.size() > 0) ((Element) result.get(0)).addContent(shape);
}
return document;
}
private void debug(String message) {
if (DEBUG) System.out.println("[at.lux.fotoannotation.AnnotationFrame] " + message);
}
public void setStatus(String message) {
status.setText(message);
}
public String getSemanticAgentsNames() {
String[] names = beePanel.getSemanticAgentsNames();
return createStringFromArray(names);
}
private String createStringFromArray(String[] names) {
StringWriter sw = new StringWriter(names.length * 32);
for (int i = 0; i < names.length; i++) {
sw.append(names[i]);
if (i < names.length - 1) sw.append(", ");
}
return sw.toString();
}
public String getSemanticEventsNames() {
String[] names = beePanel.getSemanticEventsNames();
return createStringFromArray(names);
}
public String getSemanticTimesNames() {
String[] names = beePanel.getSemanticTimesNames();
return createStringFromArray(names);
}
public String getSemanticPlacesNames() {
String[] names = beePanel.getSemanticPlacesNames();
return createStringFromArray(names);
}
/**
* Getter for the file which is currently annotated.
*
* @return the File which is currently annotated.
*/
public File getCurrentFile() {
return currentFile;
}
public BufferedImage getImage() {
return imagePanel.getImage();
}
public boolean isAutopilot() {
return autopilot;
}
public void setAutopilot(boolean autopilot) {
this.autopilot = autopilot;
}
public Properties getCurrentFileProperties() {
return currentFileProperties;
}
}