Package jsynoptic.builtin

Source Code of jsynoptic.builtin.TextArrayShape$TextArrayShapePropertiesNames

/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2003, by :
*     Corporate:
*         Astrium SAS
*         EADS CRC
*     Individual:
*         Nicolas Brodu
*
* $Id: TextArrayShape.java,v 1.30 2009/01/08 15:23:40 ogor Exp $
*
* Changes
* -------
* 16-Oct-2003 : Initial version (NB);
*
*/
package jsynoptic.builtin;

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.util.Vector;

import javax.swing.undo.CompoundEdit;

import jsynoptic.base.ContextualActionProvider;
import jsynoptic.base.DataSourceConsumer;
import jsynoptic.base.Linkable;
import jsynoptic.builtin.ui.TextArrayPropertiesPanel;
import jsynoptic.ui.JSynoptic;
import jsynoptic.ui.LongAction;
import simtools.data.DataSource;
import simtools.data.DataSourceCollection;
import simtools.data.EndNotificationListener;
import simtools.diagram.Resizable;
import simtools.shapes.AbstractShape;
import simtools.shapes.ui.AbstractShapePropertiesDialogBox;
import simtools.ui.JPropertiesPanel;
import simtools.ui.ResourceFinder;

/**
* An array of text shapes
*/
public class TextArrayShape extends AbstractShape implements Resizable, ContextualActionProvider, Linkable,
        EndNotificationListener, DataSourceConsumer {
    static final long serialVersionUID = 1320844024842187479L;

    public static ResourceBundle resources = ResourceFinder.get(TextArrayShape.class);

    // Linkable shape
    protected String link;

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }

    /**
     * @return Returns the cells.
     */
    public Vector getCells() {
        return cells;
    }

    /**
     * If true, this shapes auto-resizes when its content changes. Default is
     * false
     */
    // protected boolean autoresize; // deprecated : delete it ?
    /** The array cells are of type TextShape */
    protected Vector cells;

    protected boolean forceSameFont = false;

    /**
     * For subclasses to override. Does nothing
     */
    protected TextArrayShape() {
        super();
    }

    public TextArrayShape(String text, int width, int height) {
        this(text, 0, 0, width, height);
    }
   
    /**
     * Construct a new text array with the given size, and only one cell with
     * the given text.
     */
    public TextArrayShape(String text, int ox, int oy, int width, int height) {
        super(ox, oy);
       
        cells = new Vector();
        TextShape ts = createTextShape(text, width, height);
        cells.add(ts);
        ts.setDelegateEndNotificationListener(this);
       
        // TextArray width shall depend on cells width values
        _w = ts.getBounds().width;
        if (_w < TextShape.MIN_WIDTH) {
            _w = TextShape.MIN_WIDTH;
        }
       
        _h = height;
        if (_h < TextShape.MIN_HEIGHT) {
            _h = TextShape.MIN_HEIGHT;
        }
       
        _y = height;
       
        ts.setAnchor(_ox, _oy + _y);
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.shapes.AbstractShape#translate(int, int)
     */
    public void translate(int dx, int dy) {
        super.translate(dx, dy);
        for (Iterator it = cells.iterator(); it.hasNext();) {
            ((TextShape) it.next()).translate(dx, dy);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.shapes.AbstractShape#setAnchor(int, int)
     */
    public void setAnchor(int ox, int oy) {
        super.setAnchor(ox, oy);
        positionCells();
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.shapes.AbstractShape#draw(java.awt.Graphics2D)
     */
    public void draw(Graphics2D g) {
        for (Iterator it = cells.iterator(); it.hasNext();) {
            ((TextShape) it.next()).draw(g);
        }
    }

    /**
     * Unify the fonts of all the text shapes, so they have a common font.
     */
    public void unifyFonts() {
        if (forceSameFont) {
            double minx = Double.POSITIVE_INFINITY;
            double miny = Double.POSITIVE_INFINITY;
            double innerw = _w - 2 * TextShape.MARGINX;
            double innerh = _h / cells.size() - 2 * TextShape.MARGINY;
            if ((innerw <= 0) || (innerh <= 0)) {
                return;
            }
            TextShape tsmin = null;
            // Get min size so all fonts will fit
            for (int i = 0; i < cells.size(); ++i) {
                TextShape ts = (TextShape) cells.get(i);
                double scaleX = innerw / ts.referenceFontMetrics.stringWidth(ts.getText());
                double scaleY = innerh
                        / (ts.referenceFontMetrics.getMaxAscent() + ts.referenceFontMetrics.getMaxDescent());
                minx = Math.min(scaleX, minx);
                if (scaleY < miny) {
                    tsmin = ts;
                    miny = scaleY;
                }
            }
            if (tsmin == null) {
                return;
            }
            int baseline = (int) (tsmin.referenceFontMetrics.getMaxDescent() * innerh)
                    / (tsmin.referenceFontMetrics.getMaxAscent() + tsmin.referenceFontMetrics.getMaxDescent());
            Font commonFont = tsmin.referenceFont.deriveFont(AffineTransform.getScaleInstance(minx, miny));
            // Apply min size to all
            for (int i = 0; i < cells.size(); ++i) {
                TextShape ts = (TextShape) cells.get(i);
                ts.setFont(commonFont);
                ts.baseline = baseline;
                ts.setLockedFont(true);
            }
        }
    }

    /**
     * This function supposes dimensions are correct, it will not check that
     * Also, it does not notify changes.
     */
    protected void positionCells() {
        int cellHeight = _h / cells.size();
        for (int i = 0; i < cells.size(); ++i) {
            TextShape ts = (TextShape) cells.get(i);
            ts.setAnchor(_ox, _oy + (i + 1) * cellHeight);
            ts.setDimensions(_w, cellHeight);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.diagram.Resizable#resize(int, int)
     */
    public void resize(int dx, int dy) {
        _w += dx;
        _h += dy;
        if (_w < TextShape.MIN_WIDTH) {
            _w = TextShape.MIN_WIDTH;
        }
        // round _h to the nearest multiple of the number of cells so each cell
        // has equal height
        int cellHeight = (int) Math.rint((double) _h / (double) cells.size());
        if (cellHeight < TextShape.MIN_HEIGHT) {
            cellHeight = TextShape.MIN_HEIGHT;
        }
        _h = cellHeight * cells.size();
        _oy += _y - _h;
        _y = _h;
        positionCells();
    }

    /*
     * (non-Javadoc)
     *
     * @see jsynoptic.base.ContextualActionProvider#getActions(double, double,
     *      java.lang.Object, int)
     */
    public String[] getActions(double x, double y, Object o, int context) {
        if (context == MOUSE_OVER_CONTEXT) {
            return null;
        }
        if (context == MOUSE_OUT_CONTEXT) {
            return null;
        }
        if (context == MOUSE_PRESSED_CONTEXT) {
            return null;
        }
        if (context == EDITOR_CONTEXT) {
        }
        Vector v = new Vector();
        v.add(resources.getString("Properties..."));
        v.add(resources.getString("NewCell"));
       
        if (o instanceof DataSource && canAddDataSource(((DataSource) o))) {
            for (int i = 0; i < cells.size(); ++i) {
                v.add(resources.getString("SetSourceForCell") + (i + 1));
            }
            v.add(resources.getString("AddSourceAsCell") + (cells.size() + 1));
        }
        if (o instanceof DataSourceCollection) {
            v.add(resources.getString("SetOneCellPerSource"));
            v.add(resources.getString("CreateNewCellsForEachSource"));
        }
        return (String[]) v.toArray(new String[v.size()]);
    }

    /*
     * (non-Javadoc)
     *
     * @see jsynoptic.base.ContextualActionProvider#doAction(double, double,
     *      java.lang.Object, java.lang.String)
     */
    public boolean doAction(double x, double y, Object o, String action, CompoundEdit undoableEdit) {
       
        //TODO make those actions undoable
       
        if (action.equals(resources.getString("Properties..."))) {
            new LongAction(LongAction.LONG_ACTION_SHAPE, null, this) {
                protected void doAction() {
                    JPropertiesPanel panel = createPanel();

                    /**
                     * Only one shape properties dialog box can be displayed at
                     * once When user opens a dialog box properties while
                     * another one is still displayed: this last dislaog box is
                     * closed
                     */
                    Point oldLocation = null;
                    if (currentDialogBox != null) {
                        oldLocation = currentDialogBox.getBounds().getLocation();
                        currentDialogBox.dispose();
                    }
                    ArrayList shapes = new ArrayList();
                    shapes.add(TextArrayShape.this);
                   
                    AbstractShapePropertiesDialogBox optionDialog = new AbstractShapePropertiesDialogBox(JSynoptic.gui
                            .getOwner(), panel, panel.getShapeName() + resources.getString("propertiesTitle"),
                            shapes , JSynoptic.gui.getActiveComponent());
                    if (oldLocation != null) {
                        optionDialog.setLocation(oldLocation);
                    }
                    currentDialogBox = optionDialog;
                    // Show dialog box
                    optionDialog.setVisible(true);
                }
            }.start();
            return true;
        }
       
        if (action.equals(resources.getString("NewCell"))) {
            int cellSize = _h / cells.size();
            TextShape ts = new TextShape(Builtin.resources.getString("Text"), _w, cellSize);
            ts.setDelegateEndNotificationListener(this);
            cells.add(ts);
            _h += cellSize;
            _y = _h;
            positionCells();
            unifyFonts();
            notifyChange();
            return true;
        }
       
        if (action.startsWith(resources.getString("AddSourceAsCell"))) {
            return addDataSource((DataSource) o);
        }
       
        if (action.startsWith(resources.getString("SetSourceForCell"))) {
            int i = (int) Long.parseLong(action.substring(resources.getString("SetSourceForCell").length()));
            ((TextShape) cells.get(i - 1)).setSource((DataSource) o);
            notifyChange();
            return true;
        }
       
        if (action.equals(resources.getString("SetOneCellPerSource"))) {
            DataSourceCollection dsc = (DataSourceCollection) o;
            int cellSize = _h / cells.size();
            for (Iterator it = cells.iterator(); it.hasNext();) {
                TextShape ts = (TextShape) it.next();
                ts.setDelegateEndNotificationListener(ts); // remove ourselves
                // as listener
            }
            Vector newCells = new Vector();
            for (int i = 0; i < dsc.size(); ++i) {
                TextShape ts = new TextShape("", _w, cellSize);
                ts.setDelegateEndNotificationListener(this);
                ts.setSource((DataSource) dsc.get(i));
                newCells.add(ts);
            }
            cells = newCells;
            Rectangle bounds = getBounds();
            _h = cellSize * cells.size();
            _y = _h;
            positionCells();
            bounds.add(getBounds()); // enclose largest array to update()
            notifyChange(bounds);
            return true;
        }
       
        if (action.equals(resources.getString("CreateNewCellsForEachSource"))) {
            DataSourceCollection dsc = (DataSourceCollection) o;
            int cellSize = _h / cells.size();
            for (int i = 0; i < dsc.size(); ++i) {
                TextShape ts = new TextShape("", _w, cellSize);
                ts.setDelegateEndNotificationListener(this);
                ts.setSource((DataSource) dsc.get(i));
                cells.add(ts);
            }
            _h = cellSize * cells.size();
            _y = _h;
            positionCells();
            notifyChange();
            return true;
        }
       
        return false;
    }

    /*
     * (non-Javadoc)
     *
     * @see jsynoptic.builtin.Abstract1DShape#createPanel()
     */
    public JPropertiesPanel createPanel() {
        return new TextArrayPropertiesPanel(Builtin.resources.getString("TextArray"), true);
    }

    /* (non-Javadoc)
     * @see simtools.shapes.AbstractShape#getShapeName()
     */
    public String getShapeName(){
        return Builtin.resources.getString("TextArray");
    }
   
    /*
     * (non-Javadoc)
     *
     * @see jsynoptic.base.ContextualActionProvider#canDoAction(double, double,
     *      java.lang.Object, java.lang.String, int)
     */
    public boolean canDoAction(double x, double y, Object o, String action, int context) {
        return true;
    }

    /**
     * By overwriting this method, it is possible to create different kind of text cells
     * @param name
     * @param width
     * @param height
     * @return a text shape belonging to text array
     */
    protected TextShape createTextShape(String name, int width, int height) {
        return new TextShape(name, width, height);
    }

    /*
     * (non-Javadoc)
     *
     * @see jsynoptic.base.DataSourceConsumer#addDataSource(simtools.data.DataSource)
     */
    public boolean addDataSource(DataSource d) {
        int cellSize = _h / cells.size();
        TextShape ts = createTextShape(Builtin.resources.getString("Text"), _w, cellSize);
        ts.setDelegateEndNotificationListener(this);
      
        ts.addDataSource(d);
       
        cells.add(ts);
        _h += cellSize;
        _y = _h;
        positionCells();
        unifyFonts();
        notifyChange();
        return true;
    }

    public void setCells(Vector cellsProperties) {
        int cellHeight = _h / cells.size();
        if (cellHeight < TextShape.MIN_HEIGHT) {
            cellHeight = TextShape.MIN_HEIGHT;
        }
        cells.clear();
        _h = 0;
        _w = 0;
        for (int i = 0; i < cellsProperties.size(); i++) {
            TextShape ts = createTextShape(Builtin.resources.getString("Text"), _w, cellHeight);
            ts.setDelegateEndNotificationListener(this);
            Vector cellProperties = (Vector) cellsProperties.get(i);
            // Apply properties to each cells
            for (int j = 0; j < cellProperties.size(); j++) {
                Object[] property = (Object[]) cellProperties.get(j);
                String pname = (String) property[0];
                Object value = property[1];
                ts.setPropertyValue(pname, value);
            }
            // Update text array width only when cell width is highter
            int width = ts.getBounds().width;
            if (width > _w) {
                _w = width;
            }
            cells.add(ts);
            _h += cellHeight;
        }
        _y = _h;
        positionCells();
        unifyFonts();
        notifyChange();
    }

    /*
     * (non-Javadoc)
     *
     * @see jsynoptic.base.DataSourceConsumer#canAddDataSource(simtools.data.DataSource)
     */
    public boolean canAddDataSource(DataSource d) {
        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.shapes.AbstractShape#cloneShape()
     */
    protected AbstractShape cloneShape() {
        TextArrayShape tas = (TextArrayShape) super.cloneShape();
        tas.cells = new Vector();
        for (Iterator it = cells.iterator(); it.hasNext();) {
            tas.cells.add(((TextShape) it.next()).cloneShape());
            ((TextShape) tas.cells.lastElement()).setDelegateEndNotificationListener(tas);
        }
        tas.positionCells();
        tas.unifyFonts();
        return tas;
    }

    // Restore unique font at de-serialization.
    private void readObject(java.io.ObjectInputStream in) throws java.lang.ClassNotFoundException, java.io.IOException {
        in.defaultReadObject();
        if (forceSameFont) {
            unifyFonts();
        }
        for (Iterator it = cells.iterator(); it.hasNext();) {
            TextShape ts = (TextShape) it.next();
            ts.setDelegateEndNotificationListener(this);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.shapes.AbstractShape#setPropertyValue(java.lang.String,
     *      java.lang.Object)
     */
    public void setPropertyValue(String name, Object value) {
        super.setPropertyValue(name, value);
        if (name.equalsIgnoreCase("TEXT_ARRAY_CELL_LIST")) {
            if (value instanceof Vector) {
                setCells((Vector) value);
            }
        } else if (name.equalsIgnoreCase("SAME_FONT")) {
            boolean b = ((Boolean) value).booleanValue();
            if (b != forceSameFont) {
                forceSameFont = b;
                unifyFonts();
            }
        }
    }

    public Object getPropertyValue(String name) {
        Object res = super.getPropertyValue(name);
        if (name.equalsIgnoreCase("TEXT_ARRAY_CELL_LIST")) {
            Vector cellsProperties = new Vector();
            // For each cell, give an array containing cell properties
            for (int i = 0; i < cells.size(); i++) {
                TextShape textShape = (TextShape) cells.get(i);
                Vector cellProperties = new Vector();
                String[] props = textShape.getPropertyNames();
                if (props != null) {
                    for (int j = 0; j < props.length; j++) {
                        // Each property has a name and a value
                        Object[] property = new Object[2];
                        String pname = props[j];
                        Object value = textShape.getPropertyValue(pname);
                        property[0] = pname;
                        property[1] = value;
                        cellProperties.add(property);
                    }
                }
                cellsProperties.add(cellProperties);
            }
            res = cellsProperties;
        } else if (name.equalsIgnoreCase("SAME_FONT")) {
            res = new Boolean(forceSameFont);
        }
        return res;
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.data.EndNotificationListener#notificationEnd(java.lang.Object)
     */
    public void notificationEnd(Object referer) {
        // We receive notification for all the text shapes. This keep the end
        // notification event
        // unique as this object is registred by all shapes thanks to
        // setDelegateEndNotificationListener
        Rectangle dirtyRectangle = null;
        for (Iterator it = cells.iterator(); it.hasNext();) {
            TextShape ts = (TextShape) it.next();
            ts.setDirtyState(false);
            // This won't repaint as this shape is not connected to any shape
            // listener
            // Also, there are tests in the shape so if it hasn't changed,
            // nothing happens
            ts.notificationEnd(referer);
            // But the dirty field would be updated
            if (ts.isDirtyState()) {
                if (dirtyRectangle == null) {
                    dirtyRectangle = ts.getBounds();
                } else {
                    dirtyRectangle.add(ts.getBounds());
                }
            }
        }
        if (forceSameFont) {
            unifyFonts();
        }
        notifyChange(dirtyRectangle);
    }
   
   
    /* (non-Javadoc)
     * @see simtools.shapes.AbstractShape#subscribeToDataNotifications()
     */
    public void processShapeRestoring(){
        for (Iterator it = cells.iterator(); it.hasNext();) {
            TextShape ts = (TextShape) it.next();
            ts.processShapeRestoring();
        }
       
        super.processShapeRestoring();
    }


    /* (non-Javadoc)
     * @see simtools.shapes.AbstractShape#unsubscribeToDataNotifications()
     */
    public void processShapeRemoving(){
        for (Iterator it = cells.iterator(); it.hasNext();) {
            TextShape ts = (TextShape) it.next();
            ts.processShapeRemoving();
        }
       
        super.processShapeRemoving();
    }

    public String[] getPropertyNames() {
        if (_propertyNames == null) {
            _propertyNames = new TextArrayShapePropertiesNames().getPropertyNames();
        }
        return _propertyNames;
    }

    public static class TextArrayShapePropertiesNames extends AbstractShapePropertiesNames {
        private static transient String[] props = new String[] { "TEXT_ARRAY_CELL_LIST", "SAME_FONT" };

        public TextArrayShapePropertiesNames() {
            super();
            for (int i = 0; i < props.length; i++) {
                propertyNames.add(props[i]);
            }
        }
    }
}
TOP

Related Classes of jsynoptic.builtin.TextArrayShape$TextArrayShapePropertiesNames

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.