//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.hoese; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.awt.geom.*; import java.util.*; import javax.swing.border.*; import viewer.HoeseViewer; import java.awt.image.*; import tools.Reporter; /** * A Swing JComponent that represent a Layer in the layerstack */ public class Layer extends JComponent { /** All the graph. objects that are accociated with this Layer */ private Vector GeoObjects; /** The object that mangages the layer */ private GraphWindow owner; /** This butto controls the on/off status */ public JToggleButton button; /** the world boundingbox of this layer */ Rectangle2D.Double boundsWC; /** True if the selected object is in this layer */ boolean Selected = false; /** the internal no. of this layer */ int LayerNo; /** * Default Construktor * @see Source */ public Layer () { GeoObjects = new Vector(20); } /** * Construktor for a layer, which should display the objects in obj within owner gw * @param Vector obj * @param GraphWindow gw * @see Source */ public Layer (Vector obj, GraphWindow gw) { owner = gw; GeoObjects = (Vector)obj.clone(); setDoubleBuffered(true); calcBounds(); } /** Calculates world-bounding box for this layer * @see Source */ public void calcBounds () { boundsWC=null; try{ ListIterator li = GeoObjects.listIterator(); while (li.hasNext()) { Rectangle2D.Double bds = null; // null sp. entf DsplGraph dg = ((DsplGraph)li.next()); dg.setLayer(this); bds = dg.getBounds(); if(bds != null){ // not an empty object if (boundsWC == null) boundsWC = bds; else boundsWC = (Rectangle2D.Double)boundsWC.createUnion(bds); } } // enlarge bounding boxes of size 0 double enlargeSize = 0.000001; if(boundsWC.getWidth()<=0){ boundsWC.x -= enlargeSize; boundsWC.width = 2*enlargeSize; } if(boundsWC.getHeight()<=0){ boundsWC.x -= enlargeSize; boundsWC.height = 2*enlargeSize; } } catch(Exception e){ Reporter.writeError("Exception in Layer.calcBounds "+e); Reporter.debug(e); } } /** * Removes a graph. object from this layer * @param dg A graph. object * @see Source */ public void removeGO (DsplGraph dg) { if(dg!=null){ GeoObjects.remove(dg); calcBounds(); } } /** *Adds a graph. object to this layer at position index * @param index if ==-1 then dg is added at the end * @param dg The object to add * @see Source */ public void addGO (int index, DsplGraph dg) { if(dg!=null){ if ((index < 0) || (index >= GeoObjects.size())) GeoObjects.add(dg); else GeoObjects.add(index, dg); calcBounds(); } } /** * Sets whether the button should be set as selected or not. * @param b True when button should be selected * @see Source */ public void setSelectedButton (boolean b) { Selected = b; button.repaint(); } /** * Calculates an unique index for an object in the layerlist, so that its height is comparable to * other objects height in the layer-stack * @param dg A graph. object * @return A double value * @see Source */ public double getObjIndex (DsplGraph dg) { int index = GeoObjects.indexOf(dg); int size = GeoObjects.size(); if (index < 0) index = size++; return LayerNo + (double)index/(double)size; } /** * Gets the actual transformation, which is the parent transformation * @return Transformation * @see Source */ public AffineTransform getProjection () { return owner.getProjection(); } /** * * @return the world-boundinbox of this layer. * @see Source */ public Rectangle2D.Double getWorldCoordBounds () { return boundsWC; } /** * Creates the Layerswichbutton for turning on/off * @param al The ActionListener that manages the layer-toggling * @param lnr The intern layer nr * @return A new Switchbutton * @see Source */ public JToggleButton CreateLayerButton (ActionListener al, int lnr) { LayerNo = lnr; button = new LayerToggle(); button.setSelected(true); button.setAlignmentX(Component.CENTER_ALIGNMENT); //button.setBorder(new LineBorder(Color.blue,1)); button.setPreferredSize(new Dimension(10, 10)); //button.setSize(10,10); button.addActionListener(al); button.setActionCommand(Integer.toString(lnr)); return button; } /** Returns the categories of all object including the given point **/ TreeSet getCats(Point2D.Double position, double scalex, double scaley, boolean onlyFirst){ TreeSet res = new TreeSet(); boolean done = false; double x = position.getX(); double y = position.getY(); for(int i=0;iSource */ public Vector getGeoObjects () { return GeoObjects; } /** * * @return The application's actual time * @see Source */ public double getActualTime () { return CurrentState.ActualTime; } /** paint one of the given icons to g2 */ private static void drawIcon(BufferedImage original, BufferedImage scaled, Rectangle2D box, boolean resize, Graphics2D g, AffineTransform at){ double x = box.getX(); double y = box.getY(); double w = box.getWidth(); double h = box.getHeight(); if(w<=0 || h<=0){ Reporter.debug("invalid value for iconbox "); return; } // the current implementation ignores the scaled image if(resize){ g.drawImage(original,(int)x,(int)y,(int)w,(int)h,null); } else { double dx = (w-original.getWidth())/2; double dy = (h-original.getHeight())/2; g.drawImage(original,(int)(x+dx),(int)(y+dy),null); } } /** The draw function using the transformation from getProjection **/ public void draw(DsplGraph dg,Graphics g,double time) { draw(dg,g,time,getProjection()); } /** * This method draws the RenderObject with ist viewattributes collected in the category * @param g The graphic context to draw in. */ public static void draw(DsplGraph dg,Graphics g,double time, AffineTransform af2) { if(dg==null){ Reporter.writeError("try to draw null"); return; } Shape sh=null; // transformed renderobject Rectangle2D bounds=null; Graphics2D g2 = (Graphics2D)g; int num = dg.numberOfShapes(); Category cat = dg.getCategory(); Paint fillStyle = cat.getFillStyle(dg.getRenderAttribute(),time); for(int i=0;i 0.0f) || (dg.getSelected())){ g2.setStroke(cat.getLineStroke(dg.getRenderAttribute(),time)); if(sh!=null){ g2.draw(sh); } } } } if(bounds!=null){ drawLabel(dg,g2, bounds,time,af2); } // special treatment for non shape objects if(dg instanceof DisplayComplex){ if (fillStyle != null ){ g2.setPaint(fillStyle); } ((DisplayComplex)dg).draw(g,time,af2); } } public static void drawLabel (DsplGraph dg, Graphics g, Rectangle2D r, double time, AffineTransform af2) { drawLabel(dg,g,r,time,af2,null); } /** * The draw method for the label. * @param g The graphic context to draw in. * @param r The bounding box of the object to label. */ public static void drawLabel (DsplGraph dg, Graphics g, Rectangle2D r, double time, AffineTransform af2,Color C) { if(r==null){ Reporter.writeError("drawLabel with null-bounding box called !!"); return; } String LabelText = dg.getLabelText(time); if (LabelText == null || LabelText.trim().equals("")){ // no label return; } drawLabel(dg,g,r,time,af2,C,LabelText); } public static void drawLabel (DsplGraph dg, Graphics g, Rectangle2D r, double time, AffineTransform af2,Color C, String LabelText) { Graphics2D g2 = (Graphics2D)g; Point2D.Double p = new Point2D.Double(r.getX() + r.getWidth()/2, r.getY() + r.getHeight()/2); af2.transform(p, p); float x = (float)(p.getX()+dg.getLabPosOffset().getX()); float y = (float)(p.getY()+dg.getLabPosOffset().getY()); Rectangle2D re = g2.getFont().getStringBounds(LabelText, g2.getFontRenderContext()); x -= re.getWidth()/2.0; y += re.getHeight()/2.0; if (dg.getSelected()) { g2.setPaint(new Color(255, 128, 255, 255)); g2.fill3DRect((int)x,(int)(y+re.getY()),(int)re.getWidth(), (int)re.getHeight(), true); } if(C==null){ Category cat = dg.getCategory(); g2.setPaint(cat.getLineColor(null,0, false)); } else { g2.setPaint(C); } g2.drawString(LabelText, x,y); } /** * Sets a new Category to paint the next object to the graphics context. * @param dg: the object to drawn * @param g2: the graphics context which is used * @param num: the shape wich is to drawn, an negative number means that the * getRenderObject method is used instead of using this number as index for the array returned by the getRenderObjects() method **/ private static void setCategory(DsplGraph dg,Graphics2D g2, int num){ // ensure to have all required information if(dg==null){ Reporter.writeError("Try to set a category for an object whith value null"); return; } if(g2==null){ Reporter.writeError("try to set a Category without a graphics context"); return; } Category Cat = dg.getCategory(); if(Cat==null) { Reporter.writeError("try to set a category which has value null"); return; } AffineTransform af2 = CurrentState.transform; Shape shp; boolean isPointType; boolean isLineType; Shape render = dg.getRenderObject(num,af2); if(render==null) return; Shape sh = af2.createTransformedShape(render); if(sh==null) return; if(!dg.isLineType(num)){ g2.setComposite(Cat.getAlphaStyle()); } else{ g2.setComposite(HoeseViewer.emptyStyle); } g2.setStroke(Cat.getLineStroke(dg.getRenderAttribute(),CurrentState.ActualTime)); Paint P = Cat.getFillStyle(dg.getRenderAttribute(),CurrentState.ActualTime); g2.setPaint(P); if(P==null) return; if (dg.isPointType(num)) { if (P instanceof TexturePaint){ BufferedImage bi = ((TexturePaint)P).getImage(); if(bi==null) return; g2.setPaint(new TexturePaint(bi,sh.getBounds2D())); } else if (P instanceof GradientPaint) g2.setPaint(new GradientPaint((float)sh.getBounds().getX(),(float)sh.getBounds().getY(), ((GradientPaint)P).getColor1(),(float)(sh.getBounds().getX()+sh.getBounds().getWidth()), (float)(sh.getBounds().getY()+sh.getBounds().getHeight()),((GradientPaint)P).getColor2(),false)); } } /** * Paints the layer with its graph. object. The selected object is not drawn here. * @param g The graphic context * @see Source */ public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D)g; try { TileManager tileManager = new TileManager(GeoObjects); if(tileManager != null) { tileManager.updateObjects(); } if(Selected) { for(int i = 0; i < GeoObjects.size(); i++) { DsplGraph dg = (DsplGraph)GeoObjects.get(i); if(dg.getVisible() == true && dg.getSelected() == false) { draw(dg, g2, CurrentState.ActualTime); } } } else { for(int i = 0; i < GeoObjects.size(); i++) { DsplGraph dg = (DsplGraph)GeoObjects.get(i); if(dg.getVisible() == true) { draw(dg, g2, CurrentState.ActualTime); } } } } catch(Exception e) { Reporter.writeError("Exception "+e); Reporter.debug(e); } } /** A special JToggleButton, that draws a selection area * @see Source */ class LayerToggle extends JToggleButton { public void paintComponent (Graphics g) { if (isSelected()) g.setColor(Color.green); else g.setColor(Color.lightGray); Insets insets = getInsets(); int currentWidth = getWidth(); //- insets.left - insets.right; int currentHeight = getHeight(); // - insets.top - insets.bottom; g.fillRect(0, 0, currentWidth, currentHeight); if (Selected) { g.setColor(Color.red); g.fillRect(3, 3, 3, 4); } } } }