//This file is part of SECONDO.
//Copyright (C) 2004, University in Hagen, Department of Computer Science,
//Database Systems for New Applications.
//SECONDO 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.
//SECONDO 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 SECONDO; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package viewer;
import gui.MainWindow;
import gui.SecondoObject;
import gui.ViewerControl;
import gui.idmanager.ID;
import gui.idmanager.IDManager;
import java.awt.BasicStroke;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
import java.util.ListIterator;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.ListModel;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.MouseInputAdapter;
import project.Projection;
import sj.lang.ListExpr;
import sj.lang.ServerErrorCodes;
import tools.Reporter;
import viewer.hoese.Background;
import viewer.hoese.Category;
import viewer.hoese.CategoryEditor;
import viewer.hoese.CurrentState;
import viewer.hoese.DsplBase;
import viewer.hoese.DsplGraph;
import viewer.hoese.GraphWindow;
import viewer.hoese.HoeseOnlineDialog;
import viewer.hoese.ImageBackground;
import viewer.hoese.Interval;
import viewer.hoese.LEUtils;
import viewer.hoese.LabelAttrDlg;
import viewer.hoese.Layer;
import viewer.hoese.LayerMgmt;
import viewer.hoese.ManualLinkPool;
import viewer.hoese.OSMBackground;
import viewer.hoese.OSMDialog;
import viewer.hoese.ProjectionManager;
import viewer.hoese.QueryResult;
import viewer.hoese.ScalableImage;
import viewer.hoese.SimpleBackground;
import viewer.hoese.TextWindow;
import viewer.hoese.TimeInputDialog;
import viewer.hoese.TimePanel;
import viewer.hoese.Timed;
import viewer.hoese.algebras.Dsplpointsequence;
import viewer.hoese.algebras.continuousupdate.AnimSimulationCtrlListener;
import viewer.hoese.algebras.continuousupdate.OnlineResultsReceiver;
import components.ChangeValueEvent;
import components.ChangeValueListener;
import components.LongScrollBar;
import java.awt.image.BufferedImage;
import javax.imageio.*;
/**
* this is a viewer for spatial and temporal spatial objects but this viewer can
* display other query results
*/
public class HoeseViewer extends SecondoViewer {
/**
* Holds the value for additional time in the TimeSlider in percent.
**/
public static final double TIMEBORDER = 3;
private JOptionPane MessageControl = new JOptionPane();
private MenuVector MenuExtension = new MenuVector();
private QueryListSelectionListener DoQuerySelection;
private JSplitPane VisualPanel;
private JSplitPane VisComPanel;
private JPanel dummy = new JPanel(); // a place holder for timepanel
/** The top-right component for graph. objects in layer */
public GraphWindow GraphDisplay;
/** The left component for alphanumeric query-output */
public TextWindow TextDisplay;
private JPanel SpatioTempPanel;
/** A link to the last query-result */
public QueryResult CurrentQueryResult;
private TimePanel TimeDisplay;
private SelMouseAdapter SelectionControl;
private Interval TimeBounds;
private LongScrollBar TimeSlider;
/** The list of categories present in the app. */
public Vector Cats;
/**
* The component which contains the togglebuttons for the layer at the left
* side of GraphWindow
*/
public JPanel LayerSwitchBar;
/** Rectangle of the WorldBoundingBox */
public Rectangle2D.Double BBoxWC = new Rectangle2D.Double(0, 0, 0, 0);
/** Rectangle of the Device-coordinates */
public Rectangle BBoxDC = new Rectangle(0, 0, 0, 0);
private int oldDL;
private boolean isMouseSelected = false;
private DsplGraph selGraphObj;
private DsplBase selBaseObj;
/** The rectangle where device-coords are clipped. */
public Rectangle ClipRect = null;
private JLabel MouseKoordLabel;
private JLabel actTimeLabel;
private JButton DecrementSpeedBtn;
private JButton IncrementSpeedBtn;
private JButton OnlineBtn;
public JScrollPane GeoScrollPane;
private final static String CONFIGURATION_FILE = "GBS.cfg";
private final static int NOT_ERROR_CODE = ServerErrorCodes.NOT_ERROR_CODE;
/** The maximum length of a number for the mousekoordlabel */
private static final int MAX_COORD_LENGTH = 12;
/**
* Ensure that the next constant contains at least MAX_COORD_LENGTH
* whitespaces
*/
private static final String COORD_EXT = " ";
/** The main configuration parameter hash-table */
public static Properties configuration;
/** Set of known types **/
private TreeSet validTypes = new TreeSet();
/* Dialog for asking for a scxale factor */
private viewer.hoese.ScaleFactorDialog scaleFactorDialog;
/* File-Menu */
private javax.swing.JMenu jMenu1;
private javax.swing.JMenuItem jMenu_NewSession;
private javax.swing.JMenuItem jMenu_OpenSession;
private javax.swing.JMenuItem jMenu_CloseSession;
private javax.swing.JMenuItem jMenu_SaveSession;
private javax.swing.JMenuItem jMenu_SaveSessionAs;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JMenuItem jMenu_Browse;
private javax.swing.JSeparator jSeparator2;
private javax.swing.JMenuItem MI_SaveAttrCatLink;
private javax.swing.JMenuItem MI_LoadAttrCatLink;
private javax.swing.JMenuItem MI_AppendAttrCatLink;
/* settings-menu */
private javax.swing.JMenu jMenuGui;
private JMenuItem jMenuNoBackground;
private JMenuItem jMenuBackgroundColor;
private static boolean changeAllBackgrounds = false;
private javax.swing.JMenuItem MINewCat;
private JMenu Menu_Prj;
private JMenuItem MI_PrjSettings;
private ProjectionSelector PrjSelector;
private JRadioButtonMenuItem catManual;
private JRadioButtonMenuItem catAuto;
private JRadioButtonMenuItem catByName;
private JMenuItem selectSequenceCat;
private JRadioButtonMenuItem create_Rectangle_MI;
private boolean enablePointSequence = true;
private JMenu createMenu;
private JRadioButtonMenuItem create_PointSequence_MI;
private JRadioButtonMenuItem create_FilledPointSequence_MI;
private JRadioButtonMenuItem create_Points_MI;
private JRadioButtonMenuItem create_Line_MI;
private JRadioButtonMenuItem create_Point_MI;
private JRadioButtonMenuItem create_Region_MI;
private JCheckBoxMenuItem create_show_direct;
private JCheckBoxMenuItem storeInRelation_MI;
private JMenuItem setRelationName_MI;
private JMenuItem createRelation_MI;
private javax.swing.JSeparator jSeparator5;
private javax.swing.JMenuItem jMIShowCE;
private javax.swing.JMenuItem MIQueryRep;
private javax.swing.JCheckBoxMenuItem MIEnableSound;
private javax.swing.JMenuItem MILayerMgmt;
/** Object Menu */
private javax.swing.JMenu MenuObject;
private javax.swing.JMenuItem MIHideObject;
private javax.swing.JMenuItem MIShowObject;
private javax.swing.JMenuItem MILabelAttr;
private javax.swing.JMenuItem jMenuItem8;
private javax.swing.JMenuItem MIMoveTop;
private javax.swing.JMenuItem MIMoveUp;
private javax.swing.JMenuItem MIMoveDown;
private javax.swing.JMenuItem MIMoveBottom;
private JMenuItem MIZoomOut;
private JMenuItem MIZoomMinus;
private JMenuItem MIZoomPlus;
private JRadioButtonMenuItem RBMICustTI;
private AbstractAction AAZoomOut;
private AbstractAction AACatEdit;
private AbstractAction AAViewCat;
private AbstractAction AASetBackground;
private AbstractAction AAOSMBackground;
private JMenuItem preloadBackground;
private AbstractAction AACaptureBackground;
private AbstractAction AALabelAttr;
private String tok, PickTok;
private JButton ctrls[];
/** a FileChooser for Sessions */
private JFileChooser FC_Session = new JFileChooser();
/** a FileChooser for Categories */
private JFileChooser FC_Category = new JFileChooser();
/** a FileChooser for References Attribute value -> Category */
private JFileChooser FC_References = new JFileChooser();
/** a FileChooser for sving images as pong graphics */
private JFileChooser FC_Images = new JFileChooser();
private final static String pngTitle = "Save PNG-Image";
private final static String psTitle = "Save Encapsulated PostScript file";
private javax.swing.filechooser.FileFilter pngFilter, psFilter;
/** a dialog to input a time value */
TimeInputDialog TimeInput = new TimeInputDialog(this.getMainFrame());
private String TexturePath;
private String SoundPath;
private String CatPath;
private String FileSeparator;
/** the maximum number of pixels for capturing the background */
private long MAXCAPTUREPIXELS = 10000000L;
/** set the border when capturing the visible rectangle */
private int CaptureBorder = 200;
/**
* a point value for shipping data between this class and the
* ProjectionManager
**/
static java.awt.geom.Point2D.Double aPoint = new java.awt.geom.Point2D.Double();
/** an empty style for painting line objects */
public static Composite emptyStyle = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, 0.0f);
/** a button for creating a point sequence **/
private JButton createPointSequenceBtn;
private boolean createPointSequenceActivated = false;
private CreatePointSequenceListener createPointSequenceListener;
private OnlineResultsReceiver onlineReceiver;
/**
* Creates a MainWindow with all its components, initializes Secondo-Server,
* loads the standard-categories, etc.
*/
public HoeseViewer() {
Properties SystemProps = System.getProperties();
FileSeparator = SystemProps.getProperty("file.separator");
if (FileSeparator == null) {
FileSeparator = "/";
Reporter.writeError("i can't determine the Systems file separator");
}
TexturePath = FileSeparator;
SoundPath = FileSeparator;
initComponents();
init();
Cats = new Vector(30, 10);
Cats.add(Category.getDefaultCat());
// Load S Categories
String Catfiles = configuration.getProperty("StandardCats");
if (Catfiles != null) {
StringTokenizer ST = new StringTokenizer(Catfiles, " \n\t");
while (ST.hasMoreTokens()) {
String FileName = CatPath + ST.nextToken().trim();
ListExpr le = new ListExpr();
File F1 = new File(FileName);
if (!F1.exists()) {
Reporter.writeError("i can't find the StandardCategoryFile "
+ FileName);
} else if (le.readFromFile(FileName) != 0) {
Reporter.writeError("i can't load the file " + FileName);
} else {
if (!readAllCats(le))
Reporter.writeError("no categories in file " + FileName);
}
}
}
MouseKoordLabel = new JLabel("-------/-------");
MouseKoordLabel.setFont(new Font("Monospaced", Font.PLAIN, 12));
MouseKoordLabel.setForeground(Color.black);
actTimeLabel = new JLabel("No Time");
actTimeLabel.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() != 2) {
return;
}
if (TimeBounds == null) {
JOptionPane.showMessageDialog(null,
"Only available, if temporal objects are included",
"Error", JOptionPane.ERROR_MESSAGE);
return;
}
String inputValue = JOptionPane.showInputDialog(null,
"Please input the new time value",
LEUtils.convertTimeToString(CurrentState.ActualTime));
if (inputValue == null) {
return;
}
Double t = LEUtils.convertStringToTime(inputValue);
if (t == null) {
JOptionPane.showMessageDialog(null, "Invalid Time Value",
"Error", JOptionPane.ERROR_MESSAGE);
return;
}
setTime(t.doubleValue());
}
});
actTimeLabel.setFont(new Font("Monospaced", Font.PLAIN, 12));
actTimeLabel.setForeground(Color.black);
String Button_File = configuration.getProperty("FasterIcon");
ImageIcon icon;
if (Button_File != null) {
icon = new ImageIcon(ClassLoader.getSystemResource(Button_File));
if (icon.getImage() != null) {
IncrementSpeedBtn = new JButton(icon);
icon.setImage(icon.getImage().getScaledInstance(18, 18,
Image.SCALE_DEFAULT));
} else
IncrementSpeedBtn = new JButton("+");
} else
IncrementSpeedBtn = new JButton("+");
Button_File = configuration.getProperty("SlowerIcon");
if (Button_File != null) {
icon = new ImageIcon(ClassLoader.getSystemResource(Button_File));
if (icon.getImage() != null) {
DecrementSpeedBtn = new JButton(icon);
icon.setImage(icon.getImage().getScaledInstance(18, 18,
Image.SCALE_DEFAULT));
} else
DecrementSpeedBtn = new JButton("-");
} else
DecrementSpeedBtn = new JButton("-");
OnlineBtn = new JButton("online");
createPointSequenceBtn = new JButton();
createPointSequenceBtn.setOpaque(true);
ActionListener createPointSequenceAL = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Object src = evt.getSource();
if (!(src instanceof JButton))
return;
JButton Butt = (JButton) src;
if (HoeseViewer.this.createPointSequenceActivated) {
// finish the input
if (!src.equals(lastSrc)) // ignore messages from the other
// button
return;
Butt.setBackground(Butt.getParent().getBackground());
createPointSequenceActivated = false;
GraphDisplay
.removeMouseListener(createPointSequenceListener);
GraphDisplay
.removeMouseMotionListener(createPointSequenceListener);
createPointSequenceListener.closeSequence();
SelectionControl.enableSelection(true);
GraphDisplay.repaint();
create_Rectangle_MI.setEnabled(true);
create_Points_MI.setEnabled(true);
create_Line_MI.setEnabled(true);
create_PointSequence_MI.setEnabled(true);
create_Point_MI.setEnabled(true);
create_FilledPointSequence_MI.setEnabled(true);
create_Region_MI.setEnabled(true);
} else { // start input
lastSrc = src;
Butt.setBackground(aColor);
createPointSequenceActivated = true;
SelectionControl.enableSelection(false);
GraphDisplay.addMouseListener(createPointSequenceListener);
GraphDisplay
.addMouseMotionListener(createPointSequenceListener);
create_Rectangle_MI.setEnabled(false);
create_Points_MI.setEnabled(false);
create_Line_MI.setEnabled(false);
create_PointSequence_MI.setEnabled(false);
create_FilledPointSequence_MI.setEnabled(false);
create_Point_MI.setEnabled(false);
create_Region_MI.setEnabled(false);
}
}
Color aColor = Color.GREEN;
// Color dColor = Color.LIGHT_GRAY;
Object lastSrc;
};
createPointSequenceBtn.addActionListener(createPointSequenceAL);
ActionListener SpeedControlListener = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Object src = evt.getSource();
long ui = TimeSlider.getUnitIncrement();
if (src.equals(DecrementSpeedBtn)) {
ui = Math.max(ui / 2, 1);
} else if (src.equals(IncrementSpeedBtn)) {
ui = ui * 2;
}
TimeSlider.setUnitIncrement(ui);
TimeSlider.setBlockIncrement(ui * 60);
};
};
for (ActionListener al : OnlineBtn.getActionListeners()) {
OnlineBtn.removeActionListener(al);
}
OnlineBtn.addActionListener(new RunOnlineListnerDisabled());
DecrementSpeedBtn.addActionListener(SpeedControlListener);
IncrementSpeedBtn.addActionListener(SpeedControlListener);
IncrementSpeedBtn.setPreferredSize(new Dimension(22, 22));
DecrementSpeedBtn.setPreferredSize(new Dimension(22, 22));
JToolBar SpeedControlPanel = new JToolBar();
SpeedControlPanel
.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
SpeedControlPanel.setFloatable(false);
SpeedControlPanel.add(DecrementSpeedBtn);
SpeedControlPanel.add(new JLabel("speed"));
SpeedControlPanel.add(IncrementSpeedBtn);
SpeedControlPanel.add(OnlineBtn);
JToolBar jtb = new JToolBar();
jtb.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
jtb.setFloatable(false);
ctrls = new JButton[6];
Button_File = configuration.getProperty("PlayIcon");
if (Button_File != null)
ctrls[0] = new JButton(new ImageIcon(
ClassLoader.getSystemResource(Button_File)));
else
ctrls[0] = new JButton(">");
Button_File = configuration.getProperty("ReverseIcon");
if (Button_File != null)
ctrls[1] = new JButton(new ImageIcon(
ClassLoader.getSystemResource(Button_File)));
else
ctrls[1] = new JButton("<");
Button_File = configuration.getProperty("PlayDefIcon");
if (Button_File != null)
ctrls[2] = new JButton(new ImageIcon(
ClassLoader.getSystemResource(Button_File)));
else
ctrls[2] = new JButton(">:");
Button_File = configuration.getProperty("ToendIcon");
if (Button_File != null)
ctrls[3] = new JButton(new ImageIcon(
ClassLoader.getSystemResource(Button_File)));
else
ctrls[3] = new JButton(">|");
Button_File = configuration.getProperty("TostartIcon");
if (Button_File != null)
ctrls[4] = new JButton(new ImageIcon(
ClassLoader.getSystemResource(Button_File)));
else
ctrls[4] = new JButton("|<");
Button_File = configuration.getProperty("StopIcon");
if (Button_File != null)
ctrls[5] = new JButton(new ImageIcon(
ClassLoader.getSystemResource(Button_File)));
else
ctrls[5] = new JButton("[]");
JPanel AnimControlPanel = new JPanel(new GridLayout(1, 9));
ActionListener al = new AnimCtrlListener();
for (int i = 0; i < ctrls.length; i++) {
ctrls[i].setActionCommand(Integer.toString(i));
ctrls[i].addActionListener(al);
if (i != 2) { // ignore the playdef button
AnimControlPanel.add(ctrls[i]);
}
}
JPanel ControlPanel = new JPanel(new GridLayout(2, 1));
ControlPanel.add(AnimControlPanel);
ControlPanel.add(SpeedControlPanel);
AnimControlPanel.setPreferredSize(new Dimension(100, 15));
jtb.add(ControlPanel);
jtb.addSeparator();
TimeSlider = new LongScrollBar(0, 0, 1);
TimeSlider.addChangeValueListener(new TimeChangeListener());
TimeSlider.setPreferredSize(new Dimension(400, 20));
TimeSlider.setUnitIncrement(1000); // 1 sec
TimeSlider.setBlockIncrement(60000); // 1 min
JPanel PositionsPanel = new JPanel(new GridLayout(1, 2));
PositionsPanel.add(actTimeLabel);
PositionsPanel.add(MouseKoordLabel);
JPanel aPanel = new JPanel(new GridLayout(2, 1));
aPanel.add(createPointSequenceBtn);
aPanel.add(new JLabel());
JPanel TimeSliderAndLabels = new JPanel(new BorderLayout());
TimeSliderAndLabels.add(TimeSlider, BorderLayout.NORTH);
TimeSliderAndLabels.add(PositionsPanel, BorderLayout.SOUTH);
actTimeLabel.setHorizontalAlignment(SwingConstants.CENTER);
MouseKoordLabel.setHorizontalAlignment(SwingConstants.CENTER);
jtb.add(TimeSliderAndLabels);
jtb.add(aPanel);
TextDisplay = new TextWindow(this);
DoQuerySelection = new QueryListSelectionListener();
LayerSwitchBar = new JPanel();
GraphDisplay = new GraphWindow(this);
Color bgColor = getBackground();
GraphDisplay.setBackgroundObject(new SimpleBackground(bgColor));
GraphDisplay.setOpaque(true); // needed for background-color
MouseKoordLabel.setOpaque(true);
MouseKoordLabel.setHorizontalAlignment(SwingConstants.RIGHT);
GraphDisplay.addMouseMotionListener(new MouseMotionListener() {
public void mouseMoved(MouseEvent e) {
// Koordinaten in Weltkoordinaten umwandeln
Point2D.Double p = new Point2D.Double();
try {
p = (Point2D.Double) CurrentState.transform
.inverseTransform(e.getPoint(), p);
} catch (Exception ex) {
}
// compute the inverse projection if possible
if (!ProjectionManager.isReversible()) {
MouseKoordLabel.setBackground(Color.PINK);
MouseKoordLabel.setText(Double.toString(p.getX())
+ " / "
+ Double.toString(p.getY()).concat(COORD_EXT)
.substring(0, MAX_COORD_LENGTH));
} else {
MouseKoordLabel.setBackground(getBackground());
double px = p.getX();
double py = p.getY();
if (ProjectionManager.getOrig(px, py, aPoint)) {
double x = aPoint.x;
double y = aPoint.y;
MouseKoordLabel.setText(("" + x)
+ " / "
+ ("" + y).concat(COORD_EXT).substring(0,
MAX_COORD_LENGTH));
} else {
MouseKoordLabel.setBackground(Color.RED);
MouseKoordLabel.setText(("" + px)
+ " / "
+ ("" + py).concat(COORD_EXT).substring(0,
MAX_COORD_LENGTH));
}
}
}
public void mouseDragged(MouseEvent evt) {
mouseMoved(evt);
}
});
SelectionControl = new SelMouseAdapter();
GraphDisplay.addMouseListener(SelectionControl);
SpatioTempPanel = new JPanel(new BorderLayout());
LayerSwitchBar.setPreferredSize(new Dimension(10, 10));
LayerSwitchBar
.setLayout(new BoxLayout(LayerSwitchBar, BoxLayout.Y_AXIS));
GeoScrollPane = new JScrollPane(GraphDisplay);
SpatioTempPanel.add(GeoScrollPane, BorderLayout.CENTER);
SpatioTempPanel.add(LayerSwitchBar, BorderLayout.WEST);
VisComPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
SpatioTempPanel, dummy);
VisComPanel.setOneTouchExpandable(true);
VisComPanel.setResizeWeight(1);
TimeDisplay = new TimePanel(this);
VisualPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, TextDisplay,
VisComPanel);
VisualPanel.setOneTouchExpandable(true);
VisualPanel.setPreferredSize(new Dimension(800, 600));
VisualPanel.setResizeWeight(0);
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout());
pane.add(jtb, BorderLayout.NORTH);
pane.add(VisualPanel, BorderLayout.CENTER);
pane.setPreferredSize(new Dimension(800, 600));
setLayout(new BorderLayout());
add(pane, BorderLayout.CENTER);
setDivider();
/* initialize the file chooser for saving images */
FC_Images.setDialogTitle(pngTitle);
pngFilter = new javax.swing.filechooser.FileFilter() {
public boolean accept(File PathName) {
if (PathName == null)
return false;
if (PathName.isDirectory())
return true;
if (PathName.getName().endsWith(".png"))
return true;
else
return false;
}
public String getDescription() {
return "PNG images";
}
};
psFilter = new javax.swing.filechooser.FileFilter() {
public boolean accept(File PathName) {
if (PathName == null)
return false;
if (PathName.isDirectory())
return true;
if (PathName.getName().endsWith(".eps"))
return true;
else
return false;
}
public String getDescription() {
return "eps images";
}
};
FC_Images.setFileFilter(pngFilter);
if (changeAllBackgrounds) {
setAllOpaque(this, false);
}
if (enablePointSequence) {
create_PointSequence_MI.setSelected(true);
} else {
create_Point_MI.setSelected(true);
}
setDefaultBackground();
}
/* sets all contained componenets to be opaque */
public static void setAllOpaque(Component C, boolean enable) {
if (C instanceof JComponent)
((JComponent) C).setOpaque(enable);
if (C instanceof Container) {
Component[] Comps = ((Container) C).getComponents();
if (Comps != null) {
for (int i = 0; i < Comps.length; i++) {
setAllOpaque(Comps[i], enable);
}
}
}
}
/* sets all contained componenets to the desired background */
public static void setAllBackgrounds(Component C, Color color) {
C.setBackground(color);
if (C instanceof Container) {
Component[] Comps = ((Container) C).getComponents();
if (Comps != null) {
for (int i = 0; i < Comps.length; i++) {
setAllBackgrounds(Comps[i], color);
}
}
}
}
/**
* Sets the divider between split-components
*
* @see Category");
MI_SaveAttrCatLink.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (ManualLinkPool.numberOfLinks() == 0) {
Reporter.showError("no references defined");
return;
}
if (FC_References.showSaveDialog(HoeseViewer.this) == JFileChooser.APPROVE_OPTION) {
ListExpr LE = ManualLinkPool.toListExpr();
File f = FC_References.getSelectedFile();
if (LE.writeToFile(f.getPath()) != 0)
Reporter.showError("saves references failed");
else
Reporter.showError("save references successful");
}
}
});
MI_LoadAttrCatLink.setText("Load Attribute -> Category");
MI_LoadAttrCatLink.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (FC_References.showOpenDialog(HoeseViewer.this) == JFileChooser.APPROVE_OPTION)
if (loadReferences(FC_References.getSelectedFile())) {
Reporter.showInfo("load references successful");
} else {
Reporter.showError("load references failed");
}
}
});
MI_AppendAttrCatLink.setText("Append Attribute -> Category");
MI_AppendAttrCatLink.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Reporter.showError("this function is not implemented");
}
});
jMenu1.add(new JSeparator());
jMenu1.add(MI_SaveAttrCatLink);
jMenu1.add(MI_LoadAttrCatLink);
// jMenu1.add(MI_AppendAttrCatLink);
JMenuItem SaveGraph = new JMenuItem("Save Graphic");
SaveGraph.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// JComponent comp = GraphDisplay;
JComponent comp = GeoScrollPane.getViewport();
// create the image
Rectangle2D R = comp.getBounds();
//Reporter.writeWarning("Restrict the size of the image !!!");
BufferedImage bi = new BufferedImage((int) R.getWidth(),
(int) R.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi.createGraphics();
comp.printAll(g);
if (FC_Images.showSaveDialog(HoeseViewer.this) == JFileChooser.APPROVE_OPTION) {
File F = FC_Images.getSelectedFile();
try {
javax.imageio.ImageIO.write(bi, "png", F);
} catch (Exception e) {
Reporter.showError("Error in saving image ");
}
}
g.dispose();
System.gc();
System.runFinalization();
}
});
JMenuItem exportGraph = new JMenuItem("Export Graphic as PS");
exportGraph.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//JComponent comp = GraphDisplay;
JComponent comp = GeoScrollPane.getViewport();
Rectangle2D R = comp.getBounds();
R.setRect(0, 0, R.getWidth(), R.getHeight());
FC_Images.setDialogTitle(psTitle);
FC_Images.setFileFilter(psFilter);
int res = FC_Images.showSaveDialog(HoeseViewer.this);
File F = FC_Images.getSelectedFile();
FC_Images.setDialogTitle(pngTitle);
FC_Images.setFileFilter(pngFilter);
if (res == JFileChooser.APPROVE_OPTION) {
try {
if (F.exists()
&& Reporter
.showQuestion("File already exits\n Overwrite it?") != Reporter.YES) {
return;
}
if (!extern.psexport.PSCreator.export(comp, F)) {
Reporter.showError("Error in exporting to file ");
}
} catch (Exception e) {
Reporter.debug(e);
Reporter.showError("Error in exporting image");
}
}
}
});
jMenu1.addSeparator();
jMenu1.add(SaveGraph);
jMenu1.add(exportGraph);
MenuExtension.addMenu(jMenu1);
jMenuGui.setText("Settings");
jMenuGui.add(Menu_Prj);
MI_PrjSettings.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
ProjectionManager.showSettings();
}
});
JMenuItem menuItem_Scale = new JMenuItem("Scale factor");
jMenuGui.add(menuItem_Scale);
scaleFactorDialog = new viewer.hoese.ScaleFactorDialog(null);
menuItem_Scale.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
scaleFactorDialog.setVisible(true);
}
});
jMenuGui.add(new JSeparator());
jMenuGui.add(catManual);
jMenuGui.add(catAuto);
jMenuGui.add(catByName);
jMenuGui.add(new JSeparator());
createMenu = new JMenu("Object Creation");
createMenu.setPreferredSize(new Dimension(130, 20));
// jMenuGui.add(createMenu); // moved into the main menu
selectSequenceCat = new JMenuItem("Select Category");
createMenu.add(selectSequenceCat);
create_Rectangle_MI = new JRadioButtonMenuItem("Rectangle");
create_PointSequence_MI = new JRadioButtonMenuItem("Point sequence");
create_FilledPointSequence_MI = new JRadioButtonMenuItem(
"Filled point sequence");
create_Points_MI = new JRadioButtonMenuItem("Points");
create_Point_MI = new JRadioButtonMenuItem("Point");
create_Line_MI = new JRadioButtonMenuItem("Line");
create_Region_MI = new JRadioButtonMenuItem("Region");
createPointSequenceListener = new CreatePointSequenceListener();
create_show_direct = new JCheckBoxMenuItem("Show Directly");
create_show_direct.setSelected(true);
createPointSequenceListener.setShowDirect(true);
create_show_direct.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
JCheckBoxMenuItem source = (JCheckBoxMenuItem) e.getSource();
createPointSequenceListener.setShowDirect(source.isSelected());
}
});
createMenu.add(create_Rectangle_MI);
if (enablePointSequence) {
createMenu.add(create_PointSequence_MI);
createMenu.add(create_FilledPointSequence_MI);
}
createMenu.add(create_Points_MI);
createMenu.add(create_Point_MI);
createMenu.add(create_Line_MI);
createMenu.add(create_Region_MI);
createMenu.addSeparator();
createMenu.add(create_show_direct);
createMenu.addSeparator();
storeInRelation_MI = new JCheckBoxMenuItem("Store in relation");
setRelationName_MI = new JMenuItem("Set name of relation");
createRelation_MI = new JMenuItem("Create relation");
createMenu.add(storeInRelation_MI);
createMenu.add(setRelationName_MI);
createMenu.add(createRelation_MI);
storeInRelation_MI.setSelected(false);
setRelationName_MI.setEnabled(false);
createRelation_MI.setEnabled(false);
createPointSequenceListener.storeInRelation(false);
createPointSequenceListener.setRelationName(null);
setRelationName_MI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
createPointSequenceListener.askForRelationName();
}
});
createRelation_MI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
createPointSequenceListener.createRelation();
}
});
storeInRelation_MI.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
JCheckBoxMenuItem source = (JCheckBoxMenuItem) e.getSource();
boolean enable = source.isSelected();
createPointSequenceListener.storeInRelation(enable);
setRelationName_MI.setEnabled(enable);
createRelation_MI.setEnabled(enable);
}
});
ButtonGroup createTypes = new ButtonGroup();
createTypes.add(create_Rectangle_MI);
createTypes.add(create_PointSequence_MI);
createTypes.add(create_FilledPointSequence_MI);
createTypes.add(create_Points_MI);
createTypes.add(create_Point_MI);
createTypes.add(create_Line_MI);
createTypes.add(create_Region_MI);
// add an changeListener for inrforming the createPointSequnceListener
// when needed
ChangeListener cL = new ChangeListener() {
public void stateChanged(ChangeEvent evt) {
if (create_Rectangle_MI.isSelected())
createPointSequenceListener
.setMode(CreatePointSequenceListener.RECTANGLE_MODE);
if (create_PointSequence_MI.isSelected())
createPointSequenceListener
.setMode(CreatePointSequenceListener.POINT_SEQUENCE_MODE);
if (create_FilledPointSequence_MI.isSelected())
createPointSequenceListener
.setMode(CreatePointSequenceListener.FILLED_POINT_SEQUENCE_MODE);
if (create_Points_MI.isSelected())
createPointSequenceListener
.setMode(CreatePointSequenceListener.POINTS_MODE);
if (create_Point_MI.isSelected())
createPointSequenceListener
.setMode(CreatePointSequenceListener.POINT_MODE);
if (create_Line_MI.isSelected())
createPointSequenceListener
.setMode(CreatePointSequenceListener.LINE_MODE);
if (create_Region_MI.isSelected())
createPointSequenceListener
.setMode(CreatePointSequenceListener.REGION_MODE);
}
};
create_Rectangle_MI.addChangeListener(cL);
create_PointSequence_MI.addChangeListener(cL);
create_FilledPointSequence_MI.addChangeListener(cL);
create_Points_MI.addChangeListener(cL);
create_Point_MI.addChangeListener(cL);
create_Line_MI.addChangeListener(cL);
create_Region_MI.addChangeListener(cL);
selectSequenceCat.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (Cats == null || Cats.size() == 0) {
Reporter.showError("No categories available");
return;
}
Category[] catarray = new Category[Cats.size()];
Category lastcat = createPointSequenceListener.getCat();
for (int i = 0; i < catarray.length; i++) {
catarray[i] = (Category) Cats.get(i);
}
Object res = JOptionPane.showInputDialog(HoeseViewer.this,
"Select a category", "CategorySelector",
JOptionPane.YES_NO_OPTION, null, // icon
catarray, lastcat);
if (res != null) {
createPointSequenceListener.setCategory((Category) res);
if (createPointSequenceActivated && !res.equals(lastcat)) {
GraphDisplay.repaint();
}
}
}
});
MIQueryRep = new JMenuItem("Query representation");
MIQueryRep.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
QueryResult qr = (QueryResult) TextDisplay.getQueryCombo()
.getSelectedItem();
if (qr != null) {
GraphDisplay.newQueryRepresentation(qr.getGraphObjects());
GraphDisplay.repaint();
}
}
});
MIEnableSound = new JCheckBoxMenuItem("Enable sound");
MIEnableSound.setSelected(false);
MIEnableSound.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent evt) {
GraphDisplay.enableSound(MIEnableSound.isSelected());
}
});
jMenuGui.add(MIQueryRep);
jMenuGui.add(MIEnableSound);
jMenuGui.add(jSeparator5);
AACatEdit = new AbstractAction("Category editor") {
public void actionPerformed(java.awt.event.ActionEvent evt) {
new CategoryEditor(HoeseViewer.this, true).show();
GraphDisplay.repaint();
}
};
jMIShowCE = jMenuGui.add(AACatEdit);
JMenu BGMenu = new JMenu("BackGround");
AASetBackground = new AbstractAction("Image: Import...") {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Background background = GraphDisplay.getBackgroundObject();
if (!(background instanceof ImageBackground)) {
background = new ImageBackground();
GraphDisplay.setBackgroundObject(background);
}
preloadBackground.setEnabled(GraphDisplay.getBackgroundObject()
.supportsPreload());
background.showConfigDialog(null);
GraphDisplay.updateBackground();
}
};
AAOSMBackground = new AbstractAction("TiledMap (OSM, GoogleMaps)...") {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Background background = GraphDisplay.getBackgroundObject();
if (!(background instanceof OSMBackground)) {
background = new OSMBackground();
}
background.showConfigDialog(null);
GraphDisplay.setBackgroundObject(background);
GraphDisplay.updateBackground();
preloadBackground.setEnabled(GraphDisplay.getBackgroundObject()
.supportsPreload());
}
};
AACaptureBackground = new AbstractAction("Image: Capture All") {
public void actionPerformed(java.awt.event.ActionEvent evt) {
// get the current bounding box
Rectangle2D r1 = GraphDisplay.getBounds();
Rectangle2D R = new Rectangle2D.Double(r1.getX(), r1.getY(),
r1.getWidth(), r1.getHeight());
double w = R.getWidth();
double h = R.getHeight();
if (w <= 0 | h <= 0) {
Reporter.showError("Cannot capture the background.");
return;
}
try {
// create a new Buffered Image from the current content of
// the
// GraphDisplay
// check whether the image is larger than allowed
boolean scale = false; // image to scale ?
double sf = 1.0; // the scale factor
long MAXPIXELS = MAXCAPTUREPIXELS;
if ((long) (w * h) > MAXPIXELS) {
sf = Math.sqrt(MAXPIXELS
/ ((R.getWidth() * R.getHeight())));
w = (w * sf);
h = (h * sf);
scale = true;
}
BufferedImage bi = new BufferedImage((int) w, (int) h,
BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = bi.createGraphics();
if (scale) {
AffineTransform sdat = new AffineTransform();
sdat.setToScale(sf, sf);
g.setTransform(sdat);
}
GraphDisplay.printAll(g);
ImageBackground background = new ImageBackground();
background.setImage(bi);
AffineTransform at = (AffineTransform) CurrentState.transform
.clone();
// convert the bounding box of the GraphDisplay into
// world coordinates.
try {
R.setRect(0, 0, R.getWidth(), R.getHeight());
R = at.createInverse().createTransformedShape(R)
.getBounds2D();
} catch (Exception e) {
Reporter.showError("Cannot determine the bounding box of this image");
}
background.setBBox(new Rectangle2D.Double(R.getX(), R
.getY(), R.getWidth(), R.getHeight()));
g.dispose();
GraphDisplay.setBackgroundObject(background);
GraphDisplay.updateBackground();
preloadBackground.setEnabled(GraphDisplay
.getBackgroundObject().supportsPreload());
} catch (Exception e) {
// because large sized data are processed, a OutOfMemory
// error is possible
Reporter.showError("An error occured while capturing the background.");
}
System.gc();
System.runFinalization();
}
};
AbstractAction AACaptureRect = new AbstractAction(
"Image: Capture Visible") {
public void actionPerformed(java.awt.event.ActionEvent evt) {
try {
// we will not scale it beacuse the maximum size is
// restricted by
// the screen size
Rectangle VisRect = GeoScrollPane.getBounds();
if (VisRect.getHeight() <= 0 || VisRect.getWidth() <= 0) {
Reporter.showError("Cannot capture the rectangle.");
}
int border = CaptureBorder; // later change for setting by
// the user
int vw = (int) VisRect.getWidth() + 2 * border;
int vh = (int) VisRect.getHeight() + 2 * border;
Rectangle2D R = GraphDisplay.getBounds();
BufferedImage bi = new BufferedImage(vw, vh,
BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = bi.createGraphics();
g.setBackground(GraphDisplay.getBackground());
g.clearRect(0, 0, vw, vh);
AffineTransform trans = new AffineTransform();
double x = R.getX() + border;
double y = R.getY() + border;
trans.setToTranslation(x, y);
g.setTransform(trans);
GraphDisplay.printAll(g);
ImageBackground background = new ImageBackground();
background.setImage(bi);
// convert the bounding bocx of the GraphDisplay into
// world coordinates.
Rectangle2D R2 = new Rectangle2D.Double();
AffineTransform at = (AffineTransform) CurrentState.transform
.clone();
try {
R2.setRect(-x, -y, vw, vh);
R2 = at.createInverse().createTransformedShape(R2)
.getBounds2D();
} catch (Exception e) {
Reporter.showError("Cannot determine the bounding box of this image.");
}
background.setBBox(new Rectangle2D.Double(R2.getX(), R2
.getY(), R2.getWidth(), R2.getHeight()));
g.dispose();
GraphDisplay.setBackgroundObject(background);
GraphDisplay.updateBackground();
preloadBackground.setEnabled(GraphDisplay
.getBackgroundObject().supportsPreload());
} catch (Exception e) {
// because large sized data are processed, a OutOfMemory
// error is possible
Reporter.showError("An error occured while capturing the background.");
}
System.gc();
System.runFinalization();
}
};
JMenu SelectBorder = new JMenu("Select Bordersize");
JRadioButtonMenuItem Border_0 = new JRadioButtonMenuItem("0");
SelectBorder.add(Border_0);
JRadioButtonMenuItem Border_30 = new JRadioButtonMenuItem("30");
SelectBorder.add(Border_30);
JRadioButtonMenuItem Border_50 = new JRadioButtonMenuItem("50");
SelectBorder.add(Border_50);
JRadioButtonMenuItem Border_100 = new JRadioButtonMenuItem("100");
SelectBorder.add(Border_100);
JRadioButtonMenuItem Border_200 = new JRadioButtonMenuItem("200");
SelectBorder.add(Border_200);
JRadioButtonMenuItem Border_500 = new JRadioButtonMenuItem("500");
SelectBorder.add(Border_500);
ButtonGroup SelectBorderGroup = new ButtonGroup();
SelectBorderGroup.add(Border_0);
SelectBorderGroup.add(Border_30);
SelectBorderGroup.add(Border_50);
SelectBorderGroup.add(Border_100);
SelectBorderGroup.add(Border_200);
SelectBorderGroup.add(Border_500);
CaptureBorder = 30;
Border_30.setSelected(true);
ActionListener SelectBorderListener = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Object src = evt.getSource();
if (!(src instanceof JMenuItem))
return;
String Label = ((JMenuItem) src).getText().trim();
try {
CaptureBorder = Integer.parseInt(Label);
} catch (Exception e) {
Reporter.showError("Cannot determine the size of the border.");
}
}
};
Border_0.addActionListener(SelectBorderListener);
Border_30.addActionListener(SelectBorderListener);
Border_50.addActionListener(SelectBorderListener);
Border_100.addActionListener(SelectBorderListener);
Border_200.addActionListener(SelectBorderListener);
Border_500.addActionListener(SelectBorderListener);
BGMenu.add(jMenuNoBackground);
BGMenu.add(jMenuBackgroundColor);
BGMenu.add(AASetBackground);
BGMenu.add(AACaptureBackground);
BGMenu.add(AACaptureRect);
BGMenu.add(SelectBorder);
BGMenu.add(AAOSMBackground);
preloadBackground = new JMenuItem("preload Background");
preloadBackground.setEnabled(false);
BGMenu.add(preloadBackground);
preloadBackground.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
GraphDisplay.startPreload();
}
});
jMenuGui.add(BGMenu);
AAZoomOut = new AbstractAction("Zoom out") {
public void actionPerformed(java.awt.event.ActionEvent evt) {
double zf = 1 / CurrentState.getZoomFactor();
ClipRect = null;
Point p = GeoScrollPane.getViewport().getViewPosition();
updateViewParameter(true);
GeoScrollPane.getViewport()
.setViewPosition(
new Point((int) (p.getX() * zf), (int) (p
.getY() * zf)));
}
};
MIZoomOut = jMenuGui.add(AAZoomOut);
MIZoomOut.setAccelerator(KeyStroke.getKeyStroke("alt Z"));
MIZoomMinus = new JMenuItem("Zoom -");
MIZoomMinus.setAccelerator(KeyStroke.getKeyStroke("alt MINUS"));
MIZoomMinus.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
double zf = 1 / GraphDisplay.getBackgroundObject()
.getZoomStep();
zoom(zf);
GraphDisplay.repaint();
}
});
jMenuGui.add(MIZoomMinus);
MIZoomPlus = new JMenuItem("Zoom +");
MIZoomPlus.setAccelerator(KeyStroke.getKeyStroke("alt E"));
MIZoomPlus.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
double zf = GraphDisplay.getBackgroundObject().getZoomStep();
zoom(zf);
GraphDisplay.repaint();
}
});
jMenuGui.add(MIZoomPlus);
MILayerMgmt.setText("Layer management");
jMenuGui.add(MILayerMgmt);
MILayerMgmt.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
new LayerMgmt(HoeseViewer.this, GraphDisplay.getComponents())
.show();
GraphDisplay.repaint();
}
});
jMenuGui.add(new JSeparator());
String TextPar[] = { "ms/s", "s/m", "m/h", "h/d", "d/w", "w/M", "M/Y" };
JRadioButtonMenuItem RBMITimeFrame[] = new JRadioButtonMenuItem[TextPar.length];
ButtonGroup bg = new ButtonGroup();
/*
* final int SliderPar[] = { 1, 60, 1440, 7*1440, 30*1440,
* (int)(365.25*1440) };
*/
// ms s min h d week month year
final long SliderPar[] = { 1, 1000, 60000, 3600000, 86400000,
604800000, 2678400000L, 31536000000L };
ActionListener TimeFrameListener = new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
int index = Integer.parseInt(evt.getActionCommand());
TimeSlider.setUnitIncrement(SliderPar[index]);
TimeSlider.setBlockIncrement(SliderPar[index + 1]);
}
};
tok = "time";
for (int i = 0; i < RBMITimeFrame.length; i++) {
RBMITimeFrame[i] = new JRadioButtonMenuItem(tok + " " + TextPar[i]);
RBMITimeFrame[i].setActionCommand(Integer.toString(i));
RBMITimeFrame[i].addActionListener(TimeFrameListener);
jMenuGui.add(RBMITimeFrame[i]);
bg.add(RBMITimeFrame[i]);
}
RBMITimeFrame[1].setSelected(true);
RBMICustTI.setText(tok + " =");
jMenuGui.add(RBMICustTI);
bg.add(RBMICustTI);
RBMICustTI.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
/*
* String input =
* JOptionPane.showInputDialog("Insert a time increment in msec."
* ); long l = 1; try { l = Long.parseLong(input); } catch
* (NumberFormatException n) {} RBMICustTI.setText(tok + " = " +
* l + " msec."); TimeSlider.setUnitIncrement(l);
* TimeSlider.setBlockIncrement(l);
*/
if (TimeInput.inputTime() == TimeInputDialog.OK) {
RBMICustTI.setText(tok + " = " + TimeInput.getTimeString());
long t = TimeInput.getTime();
TimeSlider.setUnitIncrement(t);
TimeSlider.setBlockIncrement(t);
}
}
});
// RBMITimeFrame
MenuExtension.addMenu(jMenuGui);
MenuExtension.addMenu(createMenu);
MenuObject.setText("Object");
MIHideObject.setText("Hide");
MIHideObject.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
QueryResult qr = null;
qr = (QueryResult) TextDisplay.getQueryCombo()
.getSelectedItem();
if (qr != null) {
Object o = qr.getSelectedValue();
if (o instanceof DsplBase) {
qr.clearSelection();
((DsplBase) o).setVisible(false);
GraphDisplay.repaint();
} else
Reporter.showError("No DsplBase object selected!");
} else
Reporter.showError("No query selected!");
}
});
MenuObject.add(MIHideObject);
MIShowObject.setText("Show");
MIShowObject.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
QueryResult qr = null;
qr = (QueryResult) TextDisplay.getQueryCombo()
.getSelectedItem();
if (qr != null) {
Object o = qr.getSelectedValue();
if (o instanceof DsplBase) {
((DsplBase) o).setVisible(true);
GraphDisplay.repaint();
TextDisplay.repaint();
} else
Reporter.showError("No DsplBase object selected!");
} else
Reporter.showError("No query selected!");
}
});
MenuObject.add(MIShowObject);
AAViewCat = new AbstractAction("Change category") {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (selGraphObj == null) {
Reporter.showError("No DsplGraph object selected!");
return;
}
CategoryEditor ce = new CategoryEditor(HoeseViewer.this, true,
selGraphObj.getCategory());
ce.show();
if (ce.getActualCategory() != null) {
selGraphObj.setCategory(ce.getActualCategory());
GraphDisplay.repaint();
}
}
};
MINewCat = MenuObject.add(AAViewCat);
AALabelAttr = new AbstractAction("Label attributes") {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (selGraphObj == null) {
Reporter.showError("No DsplGraph object selected!");
return;
}
new LabelAttrDlg(HoeseViewer.this, selGraphObj).show();
GraphDisplay.repaint();
}
};
MILabelAttr = MenuObject.add(AALabelAttr);
MenuObject.add(new JSeparator());
MIMoveTop.setText("Move to top");
MIMoveTop.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (selGraphObj == null) {
Reporter.showError("No DsplGraph object selected!");
return;
}
// oldLayer.getGeoObjects().remove(selGraphObj);
int newno = GraphDisplay.highestLayer();
Component[] Comps = GraphDisplay.getComponentsInLayer(newno);
Layer oldLayer = selGraphObj.getLayer();
oldLayer.setSelectedButton(false);
oldLayer.removeGO(selGraphObj);
Layer newLayer = (Layer) Comps[0];
// selGraphObj.getSelected = false;
selGraphObj.setLayer(newLayer);
newLayer.addGO(-1, selGraphObj);
newLayer.setSelectedButton(true);
GraphDisplay.repaint();
}
});
MenuObject.add(MIMoveTop);
MIMoveUp.setText("Move layer up");
MIMoveUp.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (selGraphObj == null) {
Reporter.showError("No DsplGraph object selected!");
return;
}
// oldLayer.getGeoObjects().remove(selGraphObj);
Layer oldLayer = selGraphObj.getLayer();
int aktno = GraphDisplay.getIndexOf(oldLayer);
if (aktno > 0)
aktno--;
oldLayer.setSelectedButton(false);
oldLayer.removeGO(selGraphObj);
Layer newLayer = (Layer) GraphDisplay.getComponent(aktno);
// selGraphObj.getSelected = false;
selGraphObj.setLayer(newLayer);
newLayer.addGO(-1, selGraphObj);
newLayer.setSelectedButton(true);
GraphDisplay.repaint();
}
});
MenuObject.add(MIMoveUp);
MIMoveDown.setText("Move layer down");
MIMoveDown.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (selGraphObj == null) {
Reporter.showError("No DsplGraph object selected!");
return;
}
// oldLayer.getGeoObjects().remove(selGraphObj);
int min = 1;
Layer oldLayer = selGraphObj.getLayer();
int aktno = GraphDisplay.getIndexOf(oldLayer);
if (aktno < GraphDisplay.getComponentCount() - min)
aktno++;
oldLayer.setSelectedButton(false);
oldLayer.removeGO(selGraphObj);
Layer newLayer = (Layer) GraphDisplay.getComponent(aktno);
// selGraphObj.getSelected = false;
selGraphObj.setLayer(newLayer);
newLayer.addGO(0, selGraphObj);
newLayer.setSelectedButton(true);
GraphDisplay.repaint();
}
});
MenuObject.add(MIMoveDown);
MIMoveBottom.setText("Move to bottom");
MIMoveBottom.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (selGraphObj == null) {
Reporter.showError("No DsplGraph object selected!");
return;
}
int min = 1;
Layer oldLayer = selGraphObj.getLayer();
oldLayer.setSelectedButton(false);
oldLayer.removeGO(selGraphObj);
Layer newLayer = (Layer) GraphDisplay.getComponent(GraphDisplay
.getComponentCount() - min);
// selGraphObj.getSelected = false;
selGraphObj.setLayer(newLayer);
newLayer.addGO(0, selGraphObj);
newLayer.setSelectedButton(true);
GraphDisplay.repaint();
}
});
MenuObject.add(MIMoveBottom);
MenuExtension.addMenu(MenuObject);
}
/**
* returns the index of qr in TextDisplay-ComboBox, if qr not in this box
* then -1 is returned
**/
private int getQueryIndex1(QueryResult qr) {
JComboBox CB = TextDisplay.getQueryCombo();
int count = CB.getItemCount();
int pos = -1;
boolean found = false;
for (int i = 0; i < count && !found; i++)
if (qr.equals(CB.getItemAt(i))) {
pos = i;
found = true;
}
return pos;
}
private int getQueryIndex(SecondoObject so) {
JComboBox CB = TextDisplay.getQueryCombo();
int count = CB.getItemCount();
int pos = -1;
boolean found = false;
ID id = so.getID();
for (int i = 0; i < count && !found; i++)
if (((QueryResult) (CB.getItemAt(i))).hasId(id)) {
pos = i;
found = true;
}
return pos;
}
public void zoom(double zf) {
if (zf <= 0) {
return;
}
// compute the center point of the view
Point p = GeoScrollPane.getViewport().getViewPosition();
Rectangle VP = GeoScrollPane.getViewport().getViewRect();
int x = (int) p.getX() + VP.width / 2;
int y = (int) p.getY() + VP.height / 2;
double m[] = new double[6];
CurrentState.transform.getMatrix(m);
m[0] *= zf;
m[3] *= zf;
m[4] *= zf;
m[5] *= zf;
CurrentState.transform.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);
BBoxDC.setSize((int) (BBoxDC.getWidth() * zf),
(int) (BBoxDC.getHeight() * zf));
GraphDisplay.updateLayersSize(BBoxDC);
x = (int) (x * zf - VP.width / 2);
y = (int) (y * zf - VP.height / 2);
GeoScrollPane.getViewport().setViewPosition(new Point(x, y));
}
public MenuVector getMenuVector() {
return MenuExtension;
}
private boolean loadReferences(File F) {
if (!F.exists())
return false;
ListExpr LE = new ListExpr();
if (LE.readFromFile(F.getPath()) != 0) {
return false;
}
if (!ManualLinkPool.readFromListExpr(LE))
return false;
return true;
}
/** Removes a SecondoObject */
public void removeObject(SecondoObject o) {
if (!canDisplay(o)) { // ensure the possibility that this object is
// shown
return;
}
// QueryResult qr = new QueryResult(o);
int index = getQueryIndex(o);
if (index >= 0) {
JComboBox CB = TextDisplay.getQueryCombo();
QueryResult qr = (QueryResult) CB.getItemAt(index); // we need the
// original
qr.clearSelection();
// clear graphicDisplay
ListIterator li = qr.getGraphObjects().listIterator();
while (li.hasNext()) {
DsplGraph dg = (DsplGraph) li.next();
Layer l = dg.getLayer();
Vector go = l.getGeoObjects();
go.remove(dg);
if (go.isEmpty()) {
LayerSwitchBar.remove(l.button);
GraphDisplay.remove(l);
}
}
qr.getGraphObjects().clear();
VisComPanel.setBottomComponent(dummy);
qr.setListData(new Vector());
qr.revalidate();
qr.repaint();
// remove from ComboBox
CB.removeItemAt(index);
if (CB.getItemCount() == 0) {
TextDisplay.clearComboBox();
}
CB = TextDisplay.getQueryCombo();
if (CB.getItemCount() == 0) {
CB.setSelectedIndex(-1);
} else {
CB.setSelectedIndex(0);
}
updateViewParameter(true);
}
}
/** add a Projection with given ClassName */
public boolean addProjection(String Name) {
Name = "project." + Name.trim();
Class cls;
try {
cls = Class.forName(Name);
Object P;
P = cls.newInstance();
if (!(P instanceof Projection))
return false;
PrjSelector.addProjection((Projection) P);
return true;
} catch (Exception e) {
Reporter.debug(e);
return false;
}
}
/** remove all containing objects */
public void removeAll() {
on_jMenu_NewSession(null);
}
/** return true if o is displayed false otherwise */
public boolean isDisplayed(SecondoObject o) {
int index = getQueryIndex(o);
return index >= 0;
}
/** select o */
public boolean selectObject(SecondoObject o) {
int index = getQueryIndex(o);
if (index < 0)
return false;
else {
JComboBox CB = TextDisplay.getQueryCombo();
CB.setSelectedIndex(index);
return true;
}
}
/** all query results can be displayed (see work of Th.Hoese) **/
public boolean canDisplay(SecondoObject o) {
ListExpr LE = o.toListExpr();
if (LE == null)
return false;
else {
if (LE.listLength() != 2) {
return false;
}
ListExpr Type = LE.first();
while (Type.atomType() == ListExpr.NO_ATOM) {
if (Type.isEmpty()) {
return false;
}
Type = Type.first();
}
if (Type.atomType() != ListExpr.SYMBOL_ATOM) {
return false;
}
String type = Type.symbolValue();
if (validTypes.contains(type)) {
return true;
}
try {
Class.forName("viewer.hoese.algebras.Dspl" + type);
validTypes.add(type);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
public double getDisplayQuality(SecondoObject so) {
if (!this.canDisplay(so)) {
return 0;
}
String type = so.toListExpr().second().toString();
if (type.contains("region") || type.contains("point") || type.contains("line")
|| type.contains("mpoint") || type.contains("mregion")) {
// optimized for relation with spatial or spatial temporal attributes
return 0.9;
}
return 0.55;
}
/**
* Adds a new QueryResult qr to the Textwindow
*
* @param qr
* @return True if no error has occured
* @see Source
*/
public boolean addQueryResult(QueryResult qr, boolean changeZoom) {
CurrentQueryResult = qr;
CurrentQueryResult.addListSelectionListener(DoQuerySelection);
ListExpr displayErrorList = TextDisplay
.newQueryResult(CurrentQueryResult);
int displayErrorCode = displayErrorList.first().intValue();
// If an error happened when showing the query result, shows the error
// message.
if (displayErrorCode != NOT_ERROR_CODE) {
Reporter.showError("add queryresult failed");
return false;
} else {
updateViewParameter(changeZoom);
return true;
// QueryResultList.add (CurrentQueryResult);
}
}
/** return the name of this Viewer */
public String getName() {
return "Hoese-Viewer";
}
/** adds a new SecondoObject to this Viewer **/
public boolean addObject(SecondoObject o) {
return addObject(o, true);
}
/**
* adds a new secondo object to this viewer. The boolean parameter describes
* if (when the object has a spatial extend, the zoom should be changed to
* display the whole scene.
*/
public boolean addObject(SecondoObject o, boolean changeZoom) {
if (getQueryIndex(o) >= 0)
return false;
else {
QueryResult qr = new QueryResult(o);
if (addQueryResult(qr, changeZoom)) {
if (!CurrentQueryResult.getGraphObjects().isEmpty()) {
addSwitch(GraphDisplay.addLayerObjects(CurrentQueryResult,
changeZoom), -1);
}
CurrentQueryResult.setSelectedIndex(0);
}
return true;
}
}
/** switchs to the testmode **/
public void enableTestmode(boolean on) {
if (on) {
setCatSelectionMode(CurrentState.CATEGORY_AUTO);
}
}
/** sets the mode for selection categories **/
private void setCatSelectionMode(int mode) {
switch (mode) {
case CurrentState.CATEGORY_MANUAL: {
CurrentState.setCatSelectionMode(mode);
catManual.setSelected(true);
break;
}
case CurrentState.CATEGORY_AUTO: {
CurrentState.setCatSelectionMode(mode);
catAuto.setSelected(true);
break;
}
case CurrentState.CATEGORY_BY_NAME: {
CurrentState.setCatSelectionMode(mode);
catByName.setSelected(true);
break;
}
default:
Reporter.writeError("invalid value for category selection mode");
}
}
/**
*
* @return The selected grph. object
* @see Source
*/
public DsplGraph getSelGO() {
return selGraphObj;
}
/**
* Sets actual global timeinterval
*
* @param in
* Interval
* @param modifyActualTime Reset the actual Time
* @see Source
*/
public void setActualTime(Interval in, Boolean modifyActualTime) {
TimeBounds = in;
if (in == null) {
TimeSlider.setValues(0, 0, 1);
actTimeLabel.setText("no time");
// TimeSlider.setVisible(false);
CurrentState.ActualTime = 0;
} else {
TimeBounds.increase(TIMEBORDER);
TimeSlider.setVisible(true);
if (modifyActualTime) {
CurrentState.ActualTime = TimeBounds.getStart();
TimeSlider.setValues(
(long) Math.round(in.getStart() * 86400000),
(long) Math.round(in.getStart() * 86400000),
(long) Math.round(in.getEnd() * 86400000) + 1);
} else {
TimeSlider.setValues(TimeSlider.getValue(),
(long) Math.round(in.getStart() * 86400000),
(long) Math.round(in.getEnd() * 86400000) + 1);
}
actTimeLabel.setText(LEUtils
.convertTimeToString(CurrentState.ActualTime));
}
}
/**
* Sets the current time to the given value. If the giuven time is outside
* the current time interval, the time is set to the nearest boder of the
* time interval.
**/
public boolean setTime(double time) {
if (TimeBounds == null) {
return false;
}
if (time < TimeBounds.getStart()) {
time = TimeBounds.getStart();
}
if (time > TimeBounds.getEnd()) {
time = TimeBounds.getEnd();
}
TimeSlider.setVisible(true);
TimeSlider.setValue((long) Math.round(time * 86400000));
actTimeLabel.setText(LEUtils
.convertTimeToString(CurrentState.ActualTime));
return true;
}
/**
* optional
*
* @param evt
* @see Source
*/
private void on_jMenu_Browse(java.awt.event.ActionEvent evt) { // GEN-FIRST:event_on_jMenu_Browse
// Add your handling code here:
} // GEN-LAST:event_on_jMenu_Browse
/**
* Save session to selected file
*/
private void on_jMenu_SaveSession(java.awt.event.ActionEvent evt) { // GEN-FIRST:event_on_jMenu_SaveSession
// Add your handling code here:
FC_Session.setDialogTitle("Save Session");
int returnVal = FC_Session.showSaveDialog(HoeseViewer.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = FC_Session.getSelectedFile();
// File file=new File("Session");
String DirName = FC_Session.getCurrentDirectory().getAbsolutePath();
ListExpr le = ListExpr.fiveElemList(ListExpr.symbolAtom("session"),
ProjectionManager.toListExpr(), GraphDisplay
.getBackgroundObject().toListExpr(DirName),
writeAllCats(), TextDisplay.convertAllQueryResults());
String suc;
if (le.writeToFile(file.getPath()) == 0)
Reporter.showInfo("session written");
else
Reporter.showError("save session failed");
}
}
/**
* Loads session from a file
*/
private void on_jMenu_OpenSession(java.awt.event.ActionEvent evt) { // GEN-FIRST:event_on_jMenu_OpenSession
FC_Session.setDialogTitle("Open Session");
int returnVal = FC_Session.showOpenDialog(HoeseViewer.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
on_jMenu_NewSession(evt);
File file = FC_Session.getSelectedFile();
ListExpr le = null;
boolean ok = true;
// try to load the ListExpr
try {
le = ListExpr.getListExprFromFile(file.getPath());
if (le == null)
ok = false;
} catch (Exception e) {
ok = false;
}
if (!ok) {
Reporter.showError("I can't load the file");
return;
}
// check ListExprFormat
int listlength = le.listLength();
if ((listlength != 4) && (listlength != 5)) {
Reporter.showError(" The file contains not a session.");
return;
}
ListExpr type = le.first();
if (!type.isAtom() || !(type.atomType() == ListExpr.SYMBOL_ATOM)
|| !type.symbolValue().equals("session")) {
Reporter.showError(" The file contains no session.");
le.destroy();
return;
}
le = le.rest();
type.destroy();
if (ProjectionManager.readFromList(le.first())) { // try to restore
// ProjectionManager
// settings:
PrjSelector.selectProjection(ProjectionManager
.getActualProjection());
le = le.rest();
}
Cats = new Vector(10, 5);
String DirName = FC_Session.getCurrentDirectory().getAbsolutePath();
Background background = Background.createFromListExpr(le.first(),
DirName);
GraphDisplay.setBackgroundObject(background);
preloadBackground.setEnabled(GraphDisplay.getBackgroundObject()
.supportsPreload());
readAllCats(le.second());
if (!Cats.contains(Category.getDefaultCat())) {
Cats.add(Category.getDefaultCat());
}
le.first().destroy();
le.second().destroy();
TextDisplay.readAllQueryResults(le.third());
// inform the ViewerControl over the new Objects
if (VC != null) {
JComboBox CB = TextDisplay.getQueryCombo();
int count = CB.getItemCount();
SecondoObject SO;
QueryResult QR;
for (int i = 0; i < count; i++) {
QR = (QueryResult) CB.getItemAt(i);
SO = new SecondoObject(QR.getId());
String name = QR.getCommand();
SO.setName(name);
SO.fromList(QR.getListExpr());
VC.addObject(SO);
String name2 = SO.getName(); // may be changed because of
// name conflicts
if (!name.equals(name2)) {
QR.setCommand(name2);
VC.updateMarks();
}
}
}
GraphDisplay.updateBackground();
}
// Add your handling code here:
} // GEN-LAST:event_on_jMenu_OpenSession
/**
* Creates new session by constructing a new instance of mainWindow
*
* @param evt
* @return A new MainWindow
*/
private void on_jMenu_NewSession(java.awt.event.ActionEvent evt) { // GEN-FIRST:event_on_jMenu_NewSession
// remove querys
JComboBox CB = TextDisplay.getQueryCombo();
// all queries
int count = CB.getItemCount();
QueryResult qr = null;
while (count != 0) {
qr = (QueryResult) CB.getItemAt(0);
qr.clearSelection();
ListIterator li = qr.getGraphObjects().listIterator();
while (li.hasNext()) {
DsplGraph dg = (DsplGraph) li.next();
Layer l = dg.getLayer();
Vector go = l.getGeoObjects();
go.remove(dg);
if (go.isEmpty()) {
LayerSwitchBar.remove(l.button);
GraphDisplay.remove(l);
}
}
qr.getGraphObjects().clear();
updateViewParameter(true);
TextDisplay.getQueryCombo().removeItem(qr);
CB = TextDisplay.getQueryCombo();
count = CB.getItemCount();
}
if (qr != null)
qr.setListData(new Vector());
CB.removeAllItems();
TextDisplay.clearComboBox();
// remove the categorys
Cats = new Vector(30, 10);
Cats.add(Category.getDefaultCat());
VisComPanel.setBottomComponent(dummy);
String Catfile = configuration.getProperty("StandardCat");
if (Catfile != null) {
ListExpr le = new ListExpr();
le.readFromFile(Catfile);
readAllCats(le);
}
} // GEN-LAST:event_on_jMenu_NewSession
/**
* Calc. the projection that all objects fit into visible window with border
*
* @return Thecalc. transformation
* @see Source
*/
private AffineTransform calcProjection() {
double extra = 30; // extra portion at every border of 30 pix
Rectangle2D.Double BBWC = BBoxWC;
double wp1x = BBWC.getX();
double wp1y = BBWC.getY();
double wpw = BBWC.getWidth();
double wph = BBWC.getHeight();
double w = ClipRect.getWidth(); // (double)
// GeoScrollPane.getViewport().getWidth();
double h = ClipRect.getHeight(); // (double)
// GeoScrollPane.getViewport().getHeight();
// ClipRect.setSize((int)w,(int)h);
// if no objects or only a single point,line is visible
if ((wpw == 0) && (wph == 0)) {
return new AffineTransform(1, 0, 0, -1, -wp1x + extra, -wp1y
+ extra);
} else if (wpw == 0)
wpw = 1;
else if (wph == 0)
wph = 1;
// now division by zero impossible
double m00, m11;
if (w / wpw > h / wph) { // keep aspect ratio
// h-=60;
m11 = (2 * extra - h) / wph;
m00 = -m11;
} else {
// w-=60;
m00 = (w - 2 * extra) / wpw;
m11 = -m00;
}
double m02 = extra - m00 * wp1x;
double m12 = extra - (wph + wp1y) * m11;
double m01 = 0.0;
double m10 = 0.0;
return new AffineTransform(m00, m10, m01, m11, m02, m12);
}
/**
* When new objects are added or old areremoved or the context has change
* this method must be called to calc. Layersize and transformation again.
* Moves the timeslider to the beginning of the possibly changed interval.
*
* @see Source
*/
public void updateViewParameter(boolean changeZoom) {
updateViewParameter(changeZoom, true);
}
/**
* When new objects are added or old areremoved or the context has change
* this method must be called to calc. Layersize and transformation again.
* Also allows to choose if the timeSlider should be moved to the beginning.
*
* @see Source
*/
public void updateViewParameter(boolean changeZoom, boolean resetTimeSlider){
GraphDisplay.updateBoundingBox(); // fuer neue oder geloeschte Objekte
if (ClipRect == null) {
double w = (double) GeoScrollPane.getViewport().getWidth();
double h = (double) GeoScrollPane.getViewport().getHeight();
ClipRect = new Rectangle(0, 0, (int) w, (int) h);
}
if (changeZoom) {
CurrentState.transform.setTransform(calcProjection());
}
Rectangle2D rDC = (Rectangle2D) CurrentState.transform
.createTransformedShape(BBoxWC).getBounds();
double x = rDC.getX();
double y = rDC.getY();
double w = rDC.getWidth();
double h = rDC.getHeight();
w += 60; // plus extra space
h += 60;
BBoxDC = new Rectangle(0, 0, (int) w, (int) h);
GraphDisplay.updateLayersSize(BBoxDC);
GraphDisplay.repaint();
// compute the bounds of all contained Timed objects
ListModel listModel = TextDisplay.getQueryCombo().getModel();
int size = listModel.getSize();
Interval interval = null;
for (int i = 0; i < size; i++) {
QueryResult qr = (QueryResult) listModel.getElementAt(i);
Interval qrInterval = qr.getBoundingInterval();
if (qrInterval != null) {
if (interval == null) {
interval = qrInterval.copy();
} else {
interval.unionInternal(qrInterval);
}
}
}
setActualTime(interval,resetTimeSlider);
}
/**
* The selected object should be visible even when it moves. This method
* keeps GO visible
*/
public void makeSelectionVisible() {
if (selGraphObj == null)
return;
Rectangle2D r = null;
int num = selGraphObj.numberOfShapes();
// compute the bounds of the selected object
for (int i = 0; i < num; i++) {
Shape s = selGraphObj.getRenderObject(i, CurrentState.transform);
if (s != null) {
if (r == null) {
r = s.getBounds2D();
} else {
r.add(s.getBounds2D());
}
}
}
if (r == null) // an emtpy spatial object or an undefined timed object
return;
// try{
Shape s = CurrentState.transform.createTransformedShape(r);
r = s.getBounds2D();
if (!isMouseSelected) {
double w = (double) GeoScrollPane.getViewport().getWidth();
double h = (double) GeoScrollPane.getViewport().getHeight();
double x = (double) -GraphDisplay.getX();
double y = (double) -GraphDisplay.getY();
double rmid_x = r.getX() + r.getWidth() / 2;
double rmid_y = r.getY() + r.getHeight() / 2;
int border = 60;
if (rmid_x - x < border || // left
rmid_x > x + w - border || // right
rmid_y - y < border || // above
rmid_y > y + h - border) { // under
GeoScrollPane.getHorizontalScrollBar().setValue(
(int) (rmid_x - w / 2));
GeoScrollPane.getVerticalScrollBar().setValue(
(int) (rmid_y - h / 2));
}
}
isMouseSelected = false;
}
/**
* Adds a layer-switch to LayerSwitchbar
*
* @param tb
* The button
* @param index
* The position
*/
public void addSwitch(JToggleButton tb, int index) {
if (index < 0)
LayerSwitchBar.add(tb);
else
LayerSwitchBar.add(tb, index);
LayerSwitchBar.revalidate();
LayerSwitchBar.repaint();
}
/**
* Start the receiving of continous tuples from the secondo server
*
* @param relationName
* Relation which sould be watched
* @param filter
* The filter command to be used within all queries
* @param modelLimit
* The maximum size of the ListModel used in the queries
* @param updateRate
* The rate (in ms) at which the GUI should be updated
*/
private void runOnlineResults(String relationName, String filter,
Integer tupleLimit, Integer updateRate, String remotePort, Boolean isSimulation,
Date currentTime, int currentTimeOffset, double speedFactor) {
// Set tail function, if tupleLimit > 0
String tail = tupleLimit > 0 ? "tail[" + tupleLimit + "]" : "";
// Query the Relation, to get the inital Results
if (((MainWindow) getMainFrame()).execUserCommand("query "
+ relationName + " feed " + filter + " " + tail + " consume")) {
// If we received any tuples from the Query start the continuous
// updates
if (CurrentQueryResult.getListExpr().second().listLength() > 0) {
CurrentQueryResult.reduceModels(tupleLimit, this);
onlineReceiver = new OnlineResultsReceiver(this, filter,
tupleLimit, updateRate, remotePort, OnlineBtn, CurrentQueryResult);
// Update the Button Listeners
for (ActionListener al : OnlineBtn.getActionListeners()) {
OnlineBtn.removeActionListener(al);
}
OnlineBtn.addActionListener(new RunOnlineListnerEnabled());
// If the Simulationmode is enabled, replace the ActionListener
// for the Buttons and disable them (excluding start/stop)
if (isSimulation) {
ActionListener al = new AnimSimulationCtrlListener(this,
currentTime, currentTimeOffset, speedFactor);
for (int i = 0; i < ctrls.length; i++) {
for (ActionListener a : ctrls[i].getActionListeners()) {
ctrls[i].removeActionListener(a);
}
ctrls[i].addActionListener(al);
}
DecrementSpeedBtn.setEnabled(false);
IncrementSpeedBtn.setEnabled(false);
ctrls[1].setEnabled(false);
ctrls[2].setEnabled(false);
ctrls[3].setEnabled(false);
ctrls[4].setEnabled(false);
}
} else {
// Display ErrorMessage
JOptionPane
.showMessageDialog(getMainFrame(),
"Relation needs at least one entry.\nFilter argument wrong?");
}
}
}
/**
* Disables the continues Updates
*/
private void stopOnlineResults() {
onlineReceiver.disable();
for (ActionListener al : OnlineBtn.getActionListeners()) {
OnlineBtn.removeActionListener(al);
}
OnlineBtn.addActionListener(new RunOnlineListnerDisabled());
// In Simulationmode the listener was replaced
// lets reset it
AnimCtrlListener al = new AnimCtrlListener();
for (int i = 0; i < ctrls.length; i++) {
for (ActionListener a : ctrls[i].getActionListeners()) {
if(a instanceof AnimSimulationCtrlListener){
((AnimSimulationCtrlListener)a).stop();
}
ctrls[i].removeActionListener(a);
}
ctrls[i].addActionListener(al);
}
DecrementSpeedBtn.setEnabled(true);
IncrementSpeedBtn.setEnabled(true);
ctrls[1].setEnabled(true);
ctrls[2].setEnabled(true);
ctrls[3].setEnabled(true);
ctrls[4].setEnabled(true);
}
/**
* ActionListner for the Online-Button in disabled State
*
*/
class RunOnlineListnerDisabled implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
HoeseOnlineDialog dialog = new HoeseOnlineDialog(HoeseViewer.this);
dialog.setVisible(true);
if (dialog.getResult() == HoeseOnlineDialog.OK) {
runOnlineResults(dialog.getRelationName(),
dialog.getFilterCommand(), dialog.getMaxTuples(),
dialog.getUpdateRate(), dialog.getRemotePort(), dialog.isSimulation(),
dialog.getCurrentTime(), dialog.getCurrentTimeOffset(),
dialog.getSpeedFactor());
}
}
}
/**
* ActionListner for the Online-Button in enabled State
*
*/
class RunOnlineListnerEnabled implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
stopOnlineResults();
}
}
/**
* Listens to a selection change in a query list
*
* @see Source
*/
class QueryListSelectionListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
Object o;
if (e.getValueIsAdjusting()) {
return;
}
QueryResult theList = (QueryResult) e.getSource();
if (selBaseObj != null) {
selBaseObj.setSelected(false);
if (selBaseObj.getFrame() != null) {
selBaseObj.getFrame().select(null);
// selBaseObj.getFrame().show(false);
}
selBaseObj = null;
}
if (selGraphObj != null) {
selGraphObj.getLayer().setSelectedButton(false);
selGraphObj.setSelected(false);
selGraphObj = null;
// selGraphObj.getLayer().repaint();
}
if (theList.getModel().getSize() < 1) {// an empty list
GraphDisplay.repaint(); // remove an old selection
return;
}
o = theList.getSelectedValue();
if (o instanceof Timed) {
TimeDisplay.setTimeObject((Timed) o);
oldDL = VisComPanel.getLastDividerLocation();
VisComPanel.setBottomComponent(TimeDisplay);
VisComPanel.setDividerLocation(0.8);
} else
// showCommandPanel()
;
if (o instanceof DsplGraph) {
DsplGraph dgorig = (DsplGraph) o;
dgorig.setSelected(true);
dgorig.getLayer().setSelectedButton(true);
selGraphObj = dgorig;
if (!isMouseSelected && (selGraphObj instanceof Timed)) {
Interval tb = ((Timed) selGraphObj).getBoundingInterval();
if (tb != null)
TimeSlider
.setValue((long) Math.round(tb.getStart() * 86400000));
}
makeSelectionVisible();
GraphDisplay.repaint();
} else if (o instanceof DsplBase) {
selBaseObj = (DsplBase) o;
selBaseObj.setSelected(true);
if (selBaseObj.getFrame() != null) {
selBaseObj.getFrame().select(o);
// selBaseObj.getFrame().show(true);
}
} else {
GraphDisplay.repaint();
}
}
}
/**
* Manages mouseclicks in the GraphWindow. It is placed here for
* textual-interaction
*/
class SelMouseAdapter extends MouseAdapter implements MouseMotionListener {
private int startX; // start-x of selection rectangle
private int startY; // start-y of selection rectangle
private int targetX; // last end-x position of selection rectangle
private int targetY; // last end-y position of selection rectangle
private boolean isPainting = false; // is the selection rectangle
// painted ?
private boolean isEnabled = false;
private boolean selectionEnabled = true;
private BasicStroke rstroke = new BasicStroke(2.0f);
/** draws a rectangle
*/
public synchronized void drawRectangle(boolean remove) {
//public void drawRectangle() {
if (!isEnabled) {
return;
}
if(remove){
GraphDisplay.removeSelection();
return;
}
int x1 = startX;
int x2 = targetX;
int y1 = startY;
int y2 = targetY;
int x = Math.min(x1, x2);
int w = Math.abs(x1 - x2);
int y = Math.min(y1, y2);
int h = Math.abs(y1 - y2);
GraphDisplay.setSelection(x,y,w,h);
}
/** enabled or disables the sleection of objects **/
public void enableSelection(boolean enable) {
if (enable == selectionEnabled)
return;
selectionEnabled = enable;
JComboBox cb = TextDisplay.getQueryCombo();
QueryResult qr = (QueryResult) cb.getSelectedItem();
if (qr != null)
qr.clearSelection();
}
public void mouseReleased(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
& isEnabled) {
{
if (isPainting)
drawRectangle(true); // remove the old rectangle
isPainting = false;
int x = Math.min(startX, targetX);
int wi = Math.abs(startX - targetX);
int y = Math.min(startY, targetY);
int he = Math.abs(startY - targetY);
Rectangle2D r = new Rectangle2D.Double(x, y, wi, he);
GraphDisplay.removeMouseMotionListener(this);
if ((r.getHeight() < 1) || (r.getWidth() < 1))
return;
double w = (double) GeoScrollPane.getViewport().getWidth();
double h = (double) GeoScrollPane.getViewport().getHeight();
double zf = Math.min(w / r.getWidth(), h / r.getHeight());
// setZoomFactor(ZoomFactor * zf);
double m[] = new double[6];
CurrentState.transform.getMatrix(m);
// double z=ZoomFactor;
m[0] *= zf;
m[3] *= zf;
m[4] *= zf;
m[5] *= zf;
CurrentState.transform.setTransform(m[0], m[1], m[2], m[3],
m[4], m[5]);
BBoxDC.setSize((int) (BBoxDC.getWidth() * zf),
(int) (BBoxDC.getHeight() * zf));
GraphDisplay.updateLayersSize(BBoxDC);
GraphDisplay.scrollRectToVisible(new Rectangle((int) (r
.getX() * zf), (int) (r.getY() * zf), (int) w,
(int) h));
// GeoScrollPane.getViewport().setViewPosition(new
// Point((int)(r.getX()*zf),(int)(r.getY()*zf)));
GraphDisplay.repaint();
isEnabled = false;
}
}
}
public void mousePressed(MouseEvent e) {
// Koordinaten in Weltkoordinaten umwandeln
if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {
startX = e.getX();
startY = e.getY();
targetX = startX;
targetY = startY;
drawRectangle(false);
isPainting = true;
isEnabled = true;
GraphDisplay.addMouseMotionListener(this);
}
}
public void mouseDragged(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
& isEnabled) {
if (isPainting)
drawRectangle(true);
targetX = e.getX();
targetY = e.getY();
drawRectangle(false);
}
}
public void mouseMoved(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
if (!selectionEnabled)
return;
if (!((e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK))
return;
Point2D.Double p = new Point2D.Double();
try {
p = (Point2D.Double) CurrentState.transform.inverseTransform(
e.getPoint(), p);
} catch (Exception ex) {
}
// int hits = 0;
double SelIndex = 10000, BestIndex = -1, TopIndex = -1;
// boolean selectionfound = false;
DsplGraph Obj2sel = null, top = null;
int ComboIndex = -1, TopComboIndex = -1;
double scalex = 1 / Math.abs(CurrentState.transform.getScaleX());
double scaley = 1 / Math.abs(CurrentState.transform.getScaleY());
// ListIterator li=QueryResultList.listIterator();
if ((selGraphObj != null)
&& (selGraphObj
.contains(p.getX(), p.getY(), scalex, scaley)))
SelIndex = selGraphObj.getLayer().getObjIndex(selGraphObj);
JComboBox cb = TextDisplay.getQueryCombo();
for (int j = 0; j < cb.getItemCount(); j++) {
ListIterator li2 = ((QueryResult) cb.getItemAt(j))
.getGraphObjects().listIterator();
while (li2.hasNext()) {
DsplGraph dg = (DsplGraph) li2.next();
if (!dg.getVisible())
continue;
if (dg.contains(p.getX(), p.getY(), scalex, scaley)) {
double AktIndex = (dg.getSelected()) ? SelIndex : dg
.getLayer().getObjIndex(dg);
// top is the topmost GO
if (AktIndex > TopIndex) {
TopIndex = AktIndex;
top = dg;
TopComboIndex = j;
}
if ((selGraphObj != null) && (AktIndex < SelIndex)
&& (AktIndex > BestIndex)) {
// the next GO smaller than selindex and greater
// than best until now
Obj2sel = dg;
BestIndex = AktIndex;
ComboIndex = j;
}
}
}
}
if (Obj2sel == null) {
Obj2sel = top;
ComboIndex = TopComboIndex;
}
QueryResult qr;
if (Obj2sel == null) {
qr = (QueryResult) cb.getSelectedItem();
if (qr != null)
qr.clearSelection();
} else {
if (Obj2sel.getSelected())
return;
isMouseSelected = true;
cb.setSelectedIndex(ComboIndex);
qr = (QueryResult) cb.getSelectedItem();
// qr.clearSelection();
qr.setSelectedValue(Obj2sel, true);
TextDisplay.ensureSelectedIndexIsVisible();
}
}
}
/**
* This class controls movement of the timeslider
*
* @see Source
*/
class TimeChangeListener implements ChangeValueListener {
public void valueChanged(ChangeValueEvent e) {
if (TimeBounds == null) {
TimeSlider.setValue(0);
return;
}
long v = e.getValue();
double anf;
if (v == TimeSlider.getMinimum())
anf = TimeBounds.getStart();
else {
anf = (double) v / 86400000.0;
if (anf > TimeBounds.getEnd())
anf = TimeBounds.getEnd();
}
if (anf == CurrentState.ActualTime) {
return;
}
GraphDisplay.setIgnorePaint(true);
CurrentState.ActualTime = anf;
actTimeLabel.setText(LEUtils
.convertTimeToString(CurrentState.ActualTime));
makeSelectionVisible();
GraphDisplay.setIgnorePaint(false);
GraphDisplay.repaint();
SelectionControl.drawRectangle(false);
}
}
private void init() {
// Once the address of the configuration file is known, it tries to
configuration = new Properties();
File CF = new File(CONFIGURATION_FILE);
if (!CF.exists()) {
Reporter.showError("HoeseViewer : configuration file not found");
return;
}
try {
FileInputStream Cfg = new FileInputStream(CF);
configuration.load(Cfg);
Cfg.close();
} catch (Exception e) {
Reporter.debug(e);
return;
}
CatPath = "";
String SessionPath = "";
String ReferencePath = "";
TexturePath = "";
SoundPath = "";
String guiHome = (new File(".")).getAbsolutePath();
String dataHome = guiHome + FileSeparator + "data";
String HoeseHome = dataHome + FileSeparator + "hoese" + FileSeparator;
CatPath = HoeseHome + "categories";
SessionPath = HoeseHome + "sessions";
TexturePath = HoeseHome + "textures";
SoundPath = HoeseHome + "sound";
ReferencePath = HoeseHome + "references";
String enablePointSequenceString = configuration
.getProperty("USE_POINTSEQUENCE");
if (enablePointSequenceString != null) {
if (enablePointSequenceString.trim().toLowerCase().equals("false")) {
enablePointSequence = false;
createMenu.remove(create_PointSequence_MI);
createMenu.remove(create_FilledPointSequence_MI);
}
}
// set special category path
String TmpCatPath = configuration.getProperty("CATEGORY_PATH");
if (TmpCatPath != null)
CatPath = TmpCatPath.trim();
if (!CatPath.endsWith(FileSeparator))
CatPath += FileSeparator;
File F;
F = new File(CatPath);
if (!F.exists())
Reporter.writeError("wrong categorypath " + CatPath);
else
FC_Category.setCurrentDirectory(new File(CatPath));
String TMPSessionPath = configuration.getProperty("SESSION_PATH");
if (TMPSessionPath != null)
SessionPath = TMPSessionPath.trim();
F = new File(SessionPath);
if (!F.exists())
Reporter.writeError("wrong SessionPath " + SessionPath);
else
FC_Session.setCurrentDirectory(new File(SessionPath));
String TMPTexturePath = configuration.getProperty("TEXTURE_PATH");
if (TMPTexturePath != null) {
TexturePath = TMPTexturePath.trim();
}
if (!TexturePath.endsWith(FileSeparator)) {
TexturePath += FileSeparator;
}
F = new File(TexturePath);
if (!F.exists()) {
Reporter.writeWarning("the TEXTURE_PATH in " + CONFIGURATION_FILE
+ " is setted to a non existing Path");
Reporter.writeWarning("please set this variable to a existing non relative pathname");
} else {
CategoryEditor.setTextureDirectory(new File(TexturePath));
Reporter.writeInfo("set TexturePath to " + TexturePath);
Category.setTexturePath(TexturePath);
}
String tmpSoundPath = configuration.getProperty("SOUND_PATH");
if (tmpSoundPath != null) {
tmpSoundPath = tmpSoundPath.trim();
F = new File(tmpSoundPath);
if (!F.exists()) {
Reporter.writeWarning("the SOUND_PATH in " + CONFIGURATION_FILE
+ " is setted to a non existing Path");
Reporter.writeWarning("please set this variable to a existing non relative pathname");
} else {
SoundPath = tmpSoundPath;
}
}
CategoryEditor.setSoundDirectory(new File(SoundPath));
Reporter.writeInfo("set SoundPath to " + SoundPath);
Category.setSoundPath(SoundPath);
String MaxPixels = configuration.getProperty("MAXPIXELS");
if (MaxPixels != null) {
MaxPixels = MaxPixels.trim();
try {
long mp = Long.parseLong(MaxPixels);
ScalableImage.setMaxPixels(mp);
} catch (Exception e) {
Reporter.writeError("Error in reading MaxPixels");
}
}
String MaxCapPixels = configuration.getProperty("MAXCAPTUREPIXELS");
if (MaxCapPixels != null) {
MaxCapPixels = MaxCapPixels.trim();
try {
long mp = Long.parseLong(MaxCapPixels);
MAXCAPTUREPIXELS = mp;
} catch (Exception e) {
Reporter.writeError("Error in readng MaxCapturePixels");
}
}
String TMPReferencePath = configuration.getProperty("REFERENCE_PATH");
if (TMPReferencePath != null)
ReferencePath = TMPReferencePath;
if (!ReferencePath.endsWith(FileSeparator))
ReferencePath += FileSeparator;
F = new File(ReferencePath);
if (!F.exists())
Reporter.writeError("wrong ReferencePath " + ReferencePath);
else
FC_References.setCurrentDirectory(new File(ReferencePath));
String StdRef = configuration.getProperty("STD_REFERENCE");
if (StdRef != null) {
F = new File(ReferencePath + StdRef);
if (!F.exists())
Reporter.writeError("the Reference-File " + StdRef
+ " not exists");
else if (!loadReferences(F))
Reporter.writeError("i can't load the reference file :"
+ StdRef);
}
String Prjs = configuration.getProperty("PROJECTIONS");
if (Prjs == null)
Reporter.writeWarning("PROJECTIONS not found in "
+ CONFIGURATION_FILE);
else {
boolean ok = true;
String Errors = "";
StringTokenizer ST = new StringTokenizer(Prjs.trim());
while (ST.hasMoreTokens()) {
String name = ST.nextToken();
if (!addProjection(name)) {
ok = false;
Errors += " " + name;
}
}
if (!ok) {
Reporter.showError("not all projections loaded \n errors in \n"
+ Errors);
}
}
String defaultProj = configuration.getProperty("DEFAULTPROJECTION");
try{
if(defaultProj!=null){
Projection p = PrjSelector.getProjection(defaultProj.trim());
if(p==null){
Reporter.writeWarning("Projection " + defaultProj + " not loaded");
}
PrjSelector.selectProjection(p);
Reporter.writeInfo("use Projection " + defaultProj);
}
} catch(Exception e){
Reporter.debug(e);
}
// category selection mode
boolean catSelDone = false;
String catSel = configuration.getProperty("CATEGORY_SELECTION");
if (catSel != null) {
catSel = catSel.trim().toUpperCase();
if (catSel.equals("MANUAL")) {
setCatSelectionMode(CurrentState.CATEGORY_MANUAL);
catSelDone = true;
} else if (catSel.equals("AUTO")) {
setCatSelectionMode(CurrentState.CATEGORY_AUTO);
catSelDone = true;
} else if (catSel.equals("BY_NAME")) {
setCatSelectionMode(CurrentState.CATEGORY_BY_NAME);
catSelDone = true;
} else {
Reporter.writeError("invalid value for category selection mode \n"
+ " valid are MANUAL, AUTO , and BY_NAME");
setCatSelectionMode(CurrentState.CATEGORY_MANUAL);
catSelDone = true;
}
}
String autocat = configuration.getProperty("AUTOCAT");
if (!catSelDone && autocat != null) {
Reporter.writeWarning("using deprecated AUTOCAT in configuration file \n"
+ "use CATEGORY_SELECTION instead");
if (autocat.trim().toUpperCase().equals("TRUE")) {
setCatSelectionMode(CurrentState.CATEGORY_AUTO);
} else {
setCatSelectionMode(CurrentState.CATEGORY_MANUAL);
}
catSelDone = true;
}
if (!catSelDone) {
Reporter.writeInfo("using default category selection mode");
setCatSelectionMode(CurrentState.CATEGORY_MANUAL);
}
String WorldBB = configuration.getProperty("WORLD_BOUNDING_BOX");
if (WorldBB == null) {
Reporter.writeWarning("no bounding box of the world found in configuration");
} else {
WorldBB = WorldBB.trim();
StringTokenizer st = new StringTokenizer(WorldBB);
double[] box = new double[4];
boolean error = false;
for (int i = 0; i < 4 && !error; i++) {
if (!st.hasMoreElements()) {
Reporter.showError("unsufficient values given for bounding box");
error = true;
} else {
String n = st.nextToken();
try {
box[i] = Double.parseDouble(n);
} catch (Exception e) {
Reporter.showError("invalid value in bounding box definition found");
error = true;
}
}
}
if (!error) { // 4 values read
if (box[2] <= 0 || box[3] <= 0) {
Reporter.showError("width or height of the bounding box "
+ "smaller than zero in configuiration file");
} else {
Rectangle2D.Double wbox = new Rectangle2D.Double(box[0],
box[1], box[2], box[3]);
Reporter.writeInfo("set bounding box to " + wbox);
CurrentState.setWorldBB(wbox);
}
}
}
}
/**
* This class manages animation-events * @see Source
*
* @see Source
*/
class AnimCtrlListener implements ActionListener {
long inc = 1;
boolean forward = true;
boolean onlyDefined;
Vector TimeObjects;
Timer AnimTimer = new Timer(50, new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
long v = TimeSlider.getValue();
if (onlyDefined) {
v++;
long min = Long.MAX_VALUE;
ListIterator li = TimeObjects.listIterator();
while (li.hasNext()) {
Timed t = (Timed) li.next();
min = Math.min(Interval.getMinGT(t.getIntervals(),
(double) v / 86400000.0), min);
}
if (min < Long.MAX_VALUE) {
TimeSlider.setValue(min);
AnimTimer.setDelay((1000 - TimeObjects.size() < 50) ? 50
: 1000 - TimeObjects.size());
} else
AnimTimer.stop();
} else {
// inc = (dir*TimeSlider.getUnitIncrement());
// TimeSlider.setValue(v + inc);
if (forward && !TimeSlider.next()) {
AnimTimer.stop();
}
if (!forward && !TimeSlider.back()) {
AnimTimer.stop();
}
}
}
});
public void actionPerformed(java.awt.event.ActionEvent evt) {
switch (Integer.parseInt(evt.getActionCommand())) {
case 0: // play
onlyDefined = false;
forward = true;
AnimTimer.start();
break;
case 1: // reverse
onlyDefined = false;
forward = false;
AnimTimer.start();
break;
case 2: // show at defined Times
TimeObjects = new Vector(50, 10);
JComboBox cb = TextDisplay.getQueryCombo();
for (int j = 0; j < cb.getItemCount(); j++) {
ListIterator li2 = ((QueryResult) cb.getItemAt(j))
.getGraphObjects().listIterator();
while (li2.hasNext()) {
Object o = li2.next();
if ((o instanceof DsplGraph) && (o instanceof Timed))
TimeObjects.add(o);
}
}
onlyDefined = true;
forward = true;
AnimTimer.start();
break;
case 3: // to end
TimeSlider.setValue(TimeSlider.getMaximum());
break;
case 4: // to start
TimeSlider.setValue(TimeSlider.getMinimum());
break;
case 5: // stop
AnimTimer.stop();
break;
// StartButton.setSelected(!StartButton.isSelected());
}
}
}
private class ProjectionSelector implements ActionListener {
public ProjectionSelector(JMenu M) {
Menu = M;
}
private int indexOf(Projection p) {
String c = p.getClass().getName();
for (int i = 0; i < Projections.size(); i++) {
if (Projections.get(i).getClass().getName().equals(c)) {
return i;
}
}
return -1;
}
public boolean addProjection(Projection P) {
if (P == null) {
return false;
}
if (indexOf(P) >= 0) {
return false;
}
String Name = P.getName();
JCheckBoxMenuItem MI = new JCheckBoxMenuItem(Name);
Menu.add(MI);
if (Projections.size() == 0) {
MI.setState(true);
selectedIndex = 0;
}
MI.addActionListener(this);
MenuItems.add(MI);
Projections.add(P);
return true;
}
public void selectProjection(Projection p) {
if (p == null) {
return;
}
addProjection(p); // be sure that this projection is available
// mark the correct item within the menu
if (selectedIndex >= 0) {
((JCheckBoxMenuItem) MenuItems.get(selectedIndex))
.setState(false);
}
selectedIndex = indexOf(p);
((JCheckBoxMenuItem) MenuItems.get(selectedIndex)).setState(true);
ProjectionManager.setProjection(Projections.get(selectedIndex));
}
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
int index = MenuItems.indexOf(source);
if (index < 0) {
return;
}
if (index == selectedIndex) {
return;
}
ProjectionManager.setProjection(Projections.get(index));
if (selectedIndex >= 0) {
((JCheckBoxMenuItem) MenuItems.get(selectedIndex))
.setState(false);
}
selectedIndex = index;
((JCheckBoxMenuItem) source).setState(true);
}
public Projection getProjection(String name){
if(name==null) return null;
for(int i=0;i Projections = new Vector();
private Vector MenuItems = new Vector();
private JMenu Menu;
private int selectedIndex = -1;
}
public ViewerControl getViewerControl() {
return VC;
}
class CreatePointSequenceListener extends MouseInputAdapter {
/**
* Will be called if an mouse click is performed. This event is
* evaluated when the current mode is unequal to the rectangle mode
* which have a special treatment. In all other modes. the new point is
* added to the current point sequence.
**/
public void mouseClicked(MouseEvent evt) {
if (mode == RECTANGLE_MODE) {
return;
}
if (evt.getButton() != MouseEvent.BUTTON1)
return;
if (!computeOrig(evt.getPoint(), aPoint)) {
Reporter.showError("Error in computing Projection");
return;// ignore this point
}
double x = aPoint.x;
double y = aPoint.y;
if (mode == POINT_MODE) {
ListExpr pointList = ListExpr.twoElemList(
ListExpr.symbolAtom("point"),
ListExpr.twoElemList(ListExpr.realAtom(x),
ListExpr.realAtom(y)));
String Name = getNameFromUser();
if (Name != null) {
processSecondoObject(Name, "point", pointList);
}
return;
}
if (ps.isEmpty()) {
points = new Vector();
}
Point2D.Double thePoint = new Point2D.Double(x, y);
if (mode == REGION_MODE) {
if (haveIntersections(points, thePoint)) {
Reporter.showError("Intersection detected");
return;
}
}
boolean repchanged = ps.add(x, y)
|| mode == FILLED_POINT_SEQUENCE_MODE
|| mode == REGION_MODE;
GraphDisplay.paintAdditional(ps);
if (repchanged) {
GraphDisplay.repaint();
}
points.add(thePoint);
Graphics2D G = (Graphics2D) GraphDisplay.getGraphics();
Layer.draw(ps, G, CurrentState.ActualTime, CurrentState.transform);
}
/**
* This function computes the coordinates in the 'world' from the given
* mouse coordinates.
**/
private boolean computeOrig(java.awt.Point orig,
java.awt.geom.Point2D.Double result) {
// first compute the virtual screen coordinates
Point2D.Double p = new Point2D.Double();
try {
p = (Point2D.Double) CurrentState.transform.inverseTransform(
orig, p);
} catch (Exception e) {
}
double x = p.getX();
double y = p.getY();
return ProjectionManager.estimateOrig(x, y, result);
}
/**
* Sets the current point sequnce to be empty. And removes a rectangle
* if there is one.
**/
public void reset() {
ps.reset();
points = null;
GraphDisplay.paintAdditional(null);
if (isPainted) {
GraphDisplay.removeSelection();
}
rectangle_start = false;
isPainted = false;
}
/**
* Sets the category for a point sequence. The drawing of a rectangle is
* not affected by this method
**/
public void setCategory(Category cat) {
ps.setCategory(cat);
}
/**
* Returns the category which is curretly used for painting a point
* sequence
**/
public Category getCat() {
return ps.getCategory();
}
/**
* Will be called when the mouse is pressed. This event is only
* processed in the rectangle mode. It starts the painting and creating
* of a single rectangle.
*/
public void mousePressed(MouseEvent evt) {
if (mode != RECTANGLE_MODE) {
return;
}
if (evt.getButton() != MouseEvent.BUTTON1) {
return;
}
x1 = evt.getX();
y1 = evt.getY();
rectangle_start = true;
}
/**
* Will be called if the mouse is released. This event is only processed
* in rectangle mode. The user is asked for a name of the created
* rectangle. From the name and the rectangle, a SecondoObject instance
* will be created and stored in the object list and the database.
*/
public void mouseReleased(MouseEvent evt) {
if (mode != RECTANGLE_MODE) {
return;
}
if (evt.getButton() != MouseEvent.BUTTON1) {
return;
}
if (!rectangle_start) {
return;
}
GraphDisplay.removeSelection();
isPainted = false;
x2 = evt.getX();
y2 = evt.getY();
rectangle_start = false;
// ask for the object name
if (x1 == x2 || y1 == y2) {// not a rectangle
return;
}
String Name = getNameFromUser();
if (Name != null) {
Point p1 = new Point(Math.min(x1, x2), Math.min(y1, y2));
Point p2 = new Point(Math.max(x1, x2), Math.max(y1, y2));
if (!computeOrig(p1, aPoint)) {
Reporter.showError("Error in computing a point from mouse coordinates");
return;
}
double dx1 = aPoint.x;
double dy1 = aPoint.y;
if (!computeOrig(p2, aPoint)) {
Reporter.showError("Error in computing a point from mouse coordinates");
return;
}
double dx2 = aPoint.x;
double dy2 = aPoint.y;
ListExpr value = ListExpr.fourElemList(
ListExpr.realAtom(Math.min(dx1, dx2)),
ListExpr.realAtom(Math.max(dx1, dx2)),
ListExpr.realAtom(Math.min(dy1, dy2)),
ListExpr.realAtom(Math.max(dy1, dy2)));
ListExpr result = ListExpr.twoElemList(
ListExpr.symbolAtom("rect"), value);
processSecondoObject(Name, "rect", result);
}
reset();
}
/**
* Called when the mouse is dragged. This event is for the rectangle
* mode only. A rectangle from the starting coordinates up to the
* current coordinates will be drawn.
*/
public void mouseDragged(MouseEvent evt) {
if (mode != RECTANGLE_MODE) {
return;
}
if (!rectangle_start) {
return;
}
x2 = evt.getX();
y2 = evt.getY();
paintRectangle();
isPainted = true;
}
private void paintRectangle() {
int x = Math.min(x1, x2);
int w = Math.abs(x1 - x2);
int y = Math.min(y1, y2);
int h = Math.abs(y1 - y2);
GraphDisplay.setSelection(x,y,w,h);
}
/**
* Checks whether the given vector of points is a simple Region.
**/
private boolean isPolygon(Vector points) {
// in the pointvector cannot be intersection segments
int size = points.size();
if (size < 3) {
return false;
}
if (haveIntersections(points, (Point2D.Double) points.get(0))) {
return false;
}
// missing check for building a region (points not on a single
// segment
return true;
}
/**
* Checks whether the segment from the last point in the points vector
* has an intersection with a segment in the pointsequence represented
* by points.
**/
private boolean haveIntersections(Vector points, Point2D.Double p) {
int size = points.size();
if (size < 2) {// no segments in points
return false;
}
Point2D.Double p1 = (Point2D.Double) points.get(size - 1);
Point2D.Double p2;
// create the line from the last point to the new point
Line2D.Double line = new Line2D.Double(p1.x, p1.y, p.x, p.y);
// iterate over all segments in points
p1 = (Point2D.Double) points.get(0);
for (int i = 1; i < points.size() - 1; i++) {
p2 = (Point2D.Double) points.get(i);
if (line.intersectsLine(p1.x, p1.y, p2.x, p2.y)) {
return true;
}
p1 = p2;
}
return false;
}
/**
* Closed a Point sequence. The user will be asked for an object name.
* From the name and the current point sequence, an object is created.
* The type of the object depends on the current mode. After creating
* the object, it is stored in the object list and in the database. In
* the rectangle mode, this method will be have no effect.
**/
public void closeSequence() {
if (mode == RECTANGLE_MODE || mode == POINT_MODE) {
return;
}
if (points != null) { // points are available
ListExpr value = new ListExpr();
ListExpr last = null;
Point2D.Double P;
if (mode != LINE_MODE) {
if (points.size() > 0) {
P = (Point2D.Double) points.get(0);
value.destroy();
value = ListExpr.oneElemList(ListExpr.twoElemList(
ListExpr.realAtom(P.getX()),
ListExpr.realAtom(P.getY())));
last = value;
}
for (int i = 1; i < points.size(); i++) {
P = (Point2D.Double) points.get(i);
last = ListExpr.append(
last,
ListExpr.twoElemList(
ListExpr.realAtom(P.getX()),
ListExpr.realAtom(P.getY())));
}
}
if (mode == LINE_MODE) {
if (points.size() > 2) {
double lastx;
double lasty;
double x, y;
P = (Point2D.Double) points.get(0);
lastx = P.x;
lasty = P.y;
boolean first = true;
// ListExpr last; // the last list element
for (int i = 1; i < points.size(); i++) {
P = (Point2D.Double) points.get(i);
x = P.x;
y = P.y;
if (x != lastx || y != lasty) {
ListExpr Segment = ListExpr.fourElemList(
ListExpr.realAtom(lastx),
ListExpr.realAtom(lasty),
ListExpr.realAtom(x),
ListExpr.realAtom(y));
lastx = x;
lasty = y;
if (first) {
value.destroy();
value = ListExpr.oneElemList(Segment);
last = value;
first = false;
} else {
last = ListExpr.append(last, Segment);
}
}
} // for
} // more than two points
} // LINE_MODE
if (mode == REGION_MODE) {
// first component, face
if (points.size() < 3) {
Reporter.showError("Points don't build a valid polygon.");
reset();
return;
}
value = ListExpr.oneElemList(ListExpr.oneElemList(value));
}
String Name = getNameFromUser();
if (Name != null) {
String TypeName = getTypeName();
ListExpr result = ListExpr.twoElemList(
ListExpr.symbolAtom(TypeName), value);
processSecondoObject(Name, TypeName, result);
}
} // points available
reset();
}
private String getTypeName() {
String TypeName = null;
switch (mode) {
case POINT_SEQUENCE_MODE:
TypeName = "pointsequence";
break;
case FILLED_POINT_SEQUENCE_MODE:
TypeName = "pointsequence";
break;
case LINE_MODE:
TypeName = "line";
break;
case POINT_MODE:
TypeName = "point";
break;
case POINTS_MODE:
TypeName = "points";
break;
case REGION_MODE:
TypeName = "region";
break;
default:
TypeName = "unknown";
Reporter.writeError("invalid mode detected");
}
return TypeName;
}
private boolean processSecondoObject(String Name, String typeName,
ListExpr content) {
SecondoObject o = new SecondoObject(IDManager.getNextID());
o.setName(Name);
o.fromList(content);
if (VC != null) {
VC.addObject(o);
if (showDirect) {
addObject(o, false);
}
String cmd = null;
String constValue = "[const " + typeName + " value "
+ content.second() + "]";
if (storeInRelation) {
if (relName == null) {
askForRelationName();
if (relName == null) {
return false;
}
}
cmd = "query " + relName + " inserttuple [\"" + Name
+ "\" , " + constValue + "] count";
} else {
cmd = "let " + Name + " = " + constValue;
}
sj.lang.IntByReference errorCode = new sj.lang.IntByReference(0);
ListExpr resultList = ListExpr.theEmptyList();
StringBuffer errorMessage = new StringBuffer();
if (!VC.execCommand(cmd, errorCode, resultList, errorMessage)) {
Reporter.showError("Error in storing"
+ typeName
+ "\n"
+ sj.lang.ServerErrorCodes
.getErrorMessageText(errorCode.value)
+ "\n" + errorMessage);
return false;
}
return true;
}
return false;
}
/** Asks the user for a name until the name is a correct symbol **/
private String getNameFromUser() {
String Name = null;
do {
Name = JOptionPane
.showInputDialog("Please enter a name for the object");
if (Name != null)
Name = Name.trim();
} while (Name != null && !LEUtils.isIdent(Name));
return Name;
}
public void setMode(int mode) {
if (mode >= 0 && mode < 7) {
this.mode = mode;
if (mode == POINT_SEQUENCE_MODE) {
ps.setPaintMode(Dsplpointsequence.LINE_MODE);
}
if (mode == FILLED_POINT_SEQUENCE_MODE) {
ps.setPaintMode(Dsplpointsequence.AREA_MODE);
}
if (mode == POINTS_MODE) {
ps.setPaintMode(Dsplpointsequence.POINTS_MODE);
}
if (mode == LINE_MODE) {
ps.setPaintMode(Dsplpointsequence.LINE_MODE);
}
if (mode == POINT_MODE) {
ps.setPaintMode(Dsplpointsequence.POINTS_MODE);
}
if (mode == REGION_MODE) {
ps.setPaintMode(Dsplpointsequence.AREA_MODE);
}
}
}
public int getMode() {
return mode;
}
public void setShowDirect(boolean enable) {
showDirect = enable;
}
public boolean getShowDirect() {
return showDirect;
}
public boolean setRelationName(String relName) {
if (relName == null) {
this.relName = null;
setRelationName_MI.setText("Set name for relation (null)");
return true;
} else {
if (!relName.matches("[a-zA-Z_][a-zA-Z_0-9]*")
|| relName.length() > 48) {
JOptionPane.showMessageDialog(null,
"invalid name for a Secondo object");
return false;
}
this.relName = relName;
setRelationName_MI.setText("Set name for relation (" + relName
+ ")");
return true;
}
}
public void storeInRelation(boolean on) {
storeInRelation = on;
}
public void askForRelationName() {
String name = JOptionPane
.showInputDialog(
null,
"Select a name for the relation \n "
+ "It must have the schema (Name : string, Value : type)\n"
+ "where type depends on the type of the object to create.");
if (name != null) {
setRelationName(name);
}
}
public void createRelation() {
if (relName == null) {
JOptionPane.showMessageDialog(null, "No relation name given");
return;
}
String typeName = getTypeName();
String command = "let " + relName
+ " = [const rel(tuple([Name : string, Value : " + typeName
+ "])) value () ]";
sj.lang.IntByReference errorCode = new sj.lang.IntByReference(0);
ListExpr resultList = ListExpr.theEmptyList();
StringBuffer errorMessage = new StringBuffer();
if (!VC.execCommand(command, errorCode, resultList, errorMessage)) {
Reporter.showError("Error in creating relation\n"
+ sj.lang.ServerErrorCodes
.getErrorMessageText(errorCode.value) + "\n"
+ errorMessage);
} else {
Reporter.showInfo("Relation successful created");
}
}
private Dsplpointsequence ps = new Dsplpointsequence();
private Vector points = null;
private int mode = RECTANGLE_MODE;
// points for the rectangle
private int x1;
private int y1;
private int x2;
private int y2;
private boolean rectangle_start = false;
private boolean isPainted = false; // true if an rectangle is painted
private boolean active = false;
private boolean showDirect = false;
private String relName = null;
private boolean storeInRelation = false;
private static final int POINT_SEQUENCE_MODE = 0;
private static final int RECTANGLE_MODE = 1;
private static final int FILLED_POINT_SEQUENCE_MODE = 2;
private static final int POINTS_MODE = 3;
private static final int LINE_MODE = 4;
private static final int POINT_MODE = 5;
private static final int REGION_MODE = 6;
}
void setDefaultBackground(){
try{
String bg = configuration.getProperty("BACKGROUND");
if(bg==null){
return;
}
bg = bg.trim();
StringTokenizer st = new StringTokenizer(bg," \t,;()");
if(st.hasMoreTokens()){
String bgMode = st.nextToken().trim().toLowerCase();
int t = st.countTokens();
if(bgMode.equals("color")){
if(t==1){
String color = st.nextToken().trim().toLowerCase();
setColorBG(color);
return;
} else if(t==4){
try{
String rgb = st.nextToken().trim().toLowerCase();
if(!rgb.equals("rgb")){
throw new Exception("invalid color definition");
}
Color c = new Color( Integer.parseInt(st.nextToken()),
Integer.parseInt(st.nextToken()),
Integer.parseInt(st.nextToken()));
setAllBackgrounds(HoeseViewer.this,c);
GraphDisplay.setBackgroundObject(new SimpleBackground(c));
Reporter.writeInfo("Set background to color " + c);
return;
} catch(Exception e1){
Reporter.debug(e1);
Reporter.writeWarning("invalid color definition" + bg);
return;
}
} else {
Reporter.writeWarning("invalid number of arguments to color background");
return;
}
} else if(bgMode.equals("image")){
if(st.countTokens()!=7){
Reporter.writeWarning("expected 7 arguments to image background");
return;
}
try{
File in = new File(st.nextToken());
Reporter.writeInfo("try to read background image from " + in.getAbsolutePath());
BufferedImage img = ImageIO.read(in);
double x = Double.parseDouble(st.nextToken());
double y = Double.parseDouble(st.nextToken());
double w = Double.parseDouble(st.nextToken());
double h = Double.parseDouble(st.nextToken());
boolean useForBBox = Boolean.parseBoolean(st.nextToken());
Color c = str2Color(st.nextToken());
ImageBackground ibg = new ImageBackground();
ibg.setConfiguration(img,x,y,w,h,useForBBox,c);
GraphDisplay.setBackgroundObject(ibg);
Reporter.writeInfo("set image background");
return;
} catch(Exception e1){
Reporter.debug(e1);
Reporter.writeWarning("Invalid image background spcififation: " + bg);
return;
}
} else if(bgMode.equals("map")){
String name = bg.substring(3).trim();
OSMBackground map = new OSMBackground();
OSMDialog dia = map.getDialog();
int index = dia.getItemIndex(name);
if(index < 0){
Reporter.writeWarning("Tiled Map name " + name + " not known");
return;
}
Reporter.writeInfo("Set background to map : " + name);
Properties props = new Properties();
dia.setSelectedIndex(index);
dia.storeSettingsToProperties(props);
map.setConfiguration(props,".");
GraphDisplay.setBackgroundObject(map);
return;
} else {
Reporter.writeWarning("invalid background mode " + bgMode);
}
} else {
Reporter.writeWarning("BACKGROUND without specifying it");
}
} catch(Exception e){
Reporter.debug(e);
}
}
private void setColorBG(String color){
Color c = str2Color(color);
if(c==null){
return;
}
setAllBackgrounds(HoeseViewer.this,c);
GraphDisplay.setBackgroundObject(new SimpleBackground(c));
Reporter.writeInfo("Set background to color " + c);
return;
}
Color str2Color(String color){
try{
Color c = null;
if(color.equals("black")){
c = Color.BLACK;
} else if(color.equals("blue")){
c = Color.BLUE;
} else if(color.equals("cyan")){
c = Color.CYAN;
} else if(color.equals("dark_gray")){
c = Color.DARK_GRAY;
} else if(color.equals("gray")){
c = Color.GRAY;
} else if(color.equals("green")){
c = Color.GREEN;
} else if(color.equals("light_gray")){
c = Color.LIGHT_GRAY;
} else if(color.equals("magenta")){
c = Color.MAGENTA;
} else if(color.equals("orange")){
c = Color.ORANGE;
} else if(color.equals("pink")){
c = Color.PINK;
} else if(color.equals("red")){
c = Color.RED;
} else if(color.equals("white")){
c = Color.WHITE;
} else if(color.equals("yellow")){
c = Color.YELLOW;
}
if(c==null){
StringTokenizer st = new StringTokenizer(color," \t,();");
if(st.countTokens()!=4){
return null;
}
String rgb = st.nextToken().trim().toLowerCase();
if(!rgb.equals("rgb")){
return null;
}
return new Color( Integer.parseInt(st.nextToken()),
Integer.parseInt(st.nextToken()),
Integer.parseInt(st.nextToken()));
}
return c;
} catch(Exception e){
Reporter.debug(e);
return null;
}
}
}