Package freegressi.graphics

Source Code of freegressi.graphics.GraphicModel$GraphicListener

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    Copyright (C) 2011-2013  Marchand Eric <ricoh51@free.fr>
   
    This file is part of Freegressi.

    Freegressi 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 3 of the License, or
    (at your option) any later version.

    Freegressi 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 Freegressi.  If not, see <http://www.gnu.org/licenses/>.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package freegressi.graphics;


import freegressi.fit.Fit;
import freegressi.fit.FitListener;
import freegressi.fit.FitModel;
import freegressi.fit.FitModel.TendanceChangedEvent;
import freegressi.fit.FitModel.TendanceCreatedEvent;
import freegressi.fit.FitModel.TendanceDeletedEvent;
import freegressi.main.FreegressiEvent;
import freegressi.tableur.Colonne;
import freegressi.tableur.SpreadSheets;
import freegressi.tableur.SpreadSheets.ActiveSheetChangedEvent;
import freegressi.tableur.SpreadSheets.SheetAddedEvent;
import freegressi.tableur.SpreadSheets.SheetDeletedEvent;
import freegressi.tableur.SpreadSheets.SheetDescriptionChangedEvent;
import freegressi.tableur.SpreadSheets.SheetsAngleChangedEvent;
import freegressi.tableur.SpreadSheets.SheetsCSChangedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnAddedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnDeletedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnModifiedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnMovedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnSortedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnsEditedEvent;
import freegressi.tableur.SpreadSheets.SheetsListener;
import freegressi.tableur.SpreadSheets.SheetsRenamedEvent;
import freegressi.tableur.Tableur;
import freegressi.tableur.Tableur.SheetCellChangedEvent;
import freegressi.tableur.Tableur.SheetLinesAddedEvent;
import freegressi.tableur.Tableur.SheetLinesDeletedEvent;
import freegressi.tableur.Tableur.TableurChangeListener;
import java.awt.*;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.EventObject;
import java.util.List;
import javax.swing.event.EventListenerList;

/**
* Le modèle des graphiques, cette classe est un singleton qui s'occupe
* de tous les calculs de la zone de dessin.
*
* @author marchand
*/
public class GraphicModel implements SheetsListener, TableurChangeListener
        ,FitListener{
  /** La liste des objets à dessiner */
  private List<GraphicObject> objects = new ArrayList<>();
  /** La liste des écouteurs */
  private EventListenerList listeners;
  /** La seule instance de GraphicModel */
  private static GraphicModel graphicModel = null;
  /** La feuille courante */
  private Tableur sheet = null;
  /** L'axe du bas */
  private Axis axisX1;
  /** L'axe du haut */
  private Axis axisX2;
  /** L'axe de gauche */
  private Axis axisY1;
  /** L'axe de droite */
  private Axis axisY2;
  /** La largeur de la zone de dessin */
  private int width = -1;
  /** La hauteur de la zone de dessin */
  private int height = -1;
  /** La police de caractères des axes */
  private Font axisFont = new Font("Courier", Font.BOLD, 20);
  /**  */
  private Font gradFont = new Font("hj", Font.PLAIN, 15);
  /**  */
  private Graphics2D g2 = null;
  /** Le Shape en surbrillance sous la souris */
  private Shape hilight = null;
  /** La couleur de surbrillance */
  private Color hilightColor = new Color(255, 125, 0);
  /** Le style du graphique qui contient tous les réglages */
  private GraphicStyle graphicStyle;
  /** La largeur (ou hauteur) minimum d'un axe */
  private int AXIS_MINWIDTH = 10;
  /** Flag qui dit si l'initialisation du chargement d'un fichier est terminée */
  private boolean initializing = true;


  /**
   * Constructeur privé pour singleton
   */
  private GraphicModel() {
    listeners = new EventListenerList();
  }

  /**
   *
   * @return La seule instance de GraphicModel
   */
  public static GraphicModel getInstance() {
    if (graphicModel == null) {
      graphicModel = new GraphicModel();
    }
    return graphicModel;
  }
 
  public void setInitializing(boolean initializing) {
    this.initializing = initializing;
    if (!initializing){
      updateAxisAndCurves();
      fireGraphicChanged();
    }
  } 
 

  public Tableur getSheet() {
    return sheet;
 
 
  /**
   * Méthode spéciale pour pouvoir exécuter des tests
   */
  public void initForTests(){
    createDefaultGraphicStyle();
  }

  /**
   *
   * @return la zone de dessin des courbes, hors zones d'axes
   */
  public Rectangle getRectangle(){
    if (graphicStyle == null){
      return null;
    }
    return new Rectangle(axisY1.getAxisWidth() - 1, axisX2.getAxisHeight() - 1,
            width - axisY2.getAxisWidth() - axisY1.getAxisWidth() + 1,
            height - axisX1.getAxisHeight() - axisX2.getAxisHeight() + 1);
  }

  /**
   *
   * @return Le GraphicStyle cad tous les réglages du graphique
   */
  public GraphicStyle getGraphicStyle() {
    return graphicStyle;
  }

  /**
   *
   * @param graphic
   */
  public void setGraphicStyle(GraphicStyle graphic) { 
    //sheet = SpreadSheets.getInstance().getActiveSheet();
    System.out.println("----------- setGraphicStyle " + graphic + " ------- sheet " + sheet);
   
    if (graphic == null){
      createDefaultGraphicStyle();
    } else {
     
      this.graphicStyle = graphic;
      axisX1 = graphicStyle.getaX1();
      axisY1 = graphicStyle.getaY1();
      axisX2 = graphicStyle.getaX2();
      axisY2 = graphicStyle.getaY2();      
    }
  }

  /**
   *
   * @return la liste des objets graphiques à dessiner
   */
  public List<GraphicObject> getObjects() {
    return objects;
  }
 
  /**
   *
   * @return le Shape correspondant à l'objet en surbrillance
   */
  public Shape getHilight() {
    return hilight;
  }
 
  /**
   *
   * @return la couleur de l'objet en surbrillance
   */
  public Color getHilightColor(){
    return hilightColor;
  }
 
  /**
   *
   * @return le contexte graphique de la zone de dessin
   */
  public Graphics2D getG2() {
    return g2;
  }

  /**
   * Définit le contexte graphique de la zone de dessin.
   * Utile pour calculer les dimensions des textes
   * @param g2
   */
  public void setG2(Graphics2D g2) {
    this.g2 = g2;
    updateAxisAndCurves();
  }
 
  /**
   *
   * @param font
   * @param str
   * @return la largeur d'un texte dans la zone de dessin
   */
  public int textWidth(Font font, String str) {
    if (g2 == null){
      return 0;
    }
    Font save = g2.getFont();
    g2.setFont(font);
    FontMetrics fm = g2.getFontMetrics();
    int result = fm.stringWidth(str);
    g2.setFont(save);
    return result;
  }

  /**
   *
   * @param font
   * @param str
   * @return la hauteur d'un texte dans la zone de dessin
   */
  public int textHeight(Font font, String str) {
    if (g2 == null){
      return 0;
    }
    Font save = g2.getFont();
    g2.setFont(font);
    int result = g2.getFontMetrics().getHeight();
    g2.setFont(save);
    return result;
  }

  /**
   *
   * @param font
   * @param str
   * @return
   */
  public int textDescent(Font font, String str) {
    if (g2 == null){
      return 0;
    }
    Font save = g2.getFont();
    g2.setFont(font);
    int result = g2.getFontMetrics().getDescent();
    g2.setFont(save);
    return result;
  }
 
  /**
   *
   * @param font
   * @param str
   * @return
   */
  public int textAscent(Font font, String str) {
    if (g2 == null){
      return 0;
    }
    Font save = g2.getFont();
    g2.setFont(font);
    int result = g2.getFontMetrics().getAscent();
    g2.setFont(save);
    return result;
  }

  /**
   * Renvoit un tableau d'entiers correspondant aux valeurs en pixel
   * des points d'une courbe
   * @param x les valeurs réelles
   * @param x1 le min de l'axe (en pixel)
   * @param x2 le max de l'axe (en pixel)
   * @param min le min de x
   * @param max le max de x
   * @return le tableau d'entiers
   */
  private int[] getIntArray(double[] x, int x1, int x2, double min, double max){
    int[] result = new int[x.length];
    double a = (x2 - x1) / (max - min);
    double b = (x1 * max - x2 * min) / (max - min);
    for (int i = 0; i < x.length; i++){
      if (Double.isNaN(x[i])){
        result[i] = Integer.MAX_VALUE;
      }else{
        result[i] = (int)Math.round(a * x[i] + b);
      }
    }
    return result;
  }
 
  /**
   * Répond à l'évenement "La feuille active a changée"
   * @param event
   */
  @Override
  public void activeSheetChanged(ActiveSheetChangedEvent event) {
    System.out.println("GraphicModel : activeSheetChanged");
    sheet = event.getNewActiveSheet();
    if (graphicStyle == null){
      //createDefaultGraphicStyle();
      System.out.println("GraphicModel ActiveSheetChanged graphicStyle == null");
      return;
    }
    if (sheet == null){
      System.out.println("GraphicModel ActiveSheetChanged sheet == null");
      createDefaultGraphicStyle();
      //return;
    }   
   
    setMinMax(sheet);
    notifyGraphicStyleChanged(graphicStyle, false);
  }

  @Override
  public void sheetAdded(SheetAddedEvent event) {
    // rien à faire, le graphique changera avec activeSheetChanged()
  }

  @Override
  public void sheetDeleted(SheetDeletedEvent event) {
    // rien à faire, le graphique changera avec activeSheetChanged()
    //System.out.println("GraphicModel : Sheet deleted");
  }

  @Override
  public void sheetRenamed(SheetsRenamedEvent event) {
    // rien à faire, le graphique ne change pas
  }

  @Override
  public void columnAdded(SheetsColumnAddedEvent event) {
    // rien à faire, le graphique ne change pas
  }

  /**
   * Répond à l'évenement "Une ou plusieurs colonnes ont été
   * supprimées"
   * @param event
   */
  @Override
  public void columnDeleted(SheetsColumnDeletedEvent event) {
   
    List<Colonne> list = event.getColonnes().get(0);
    String name;
    boolean flag = false;
    for (Colonne col : list){
      name = col.getColonneDescription().getNom();
      for (int i = graphicStyle.getCurves().size() - 1; i > -1; i--){
        Curve curve = graphicStyle.getCurves().get(i);
        if (curve.getxName().equals(name) || curve.getyName().equals(name)){
          flag = true;
          break;
          //graphicStyle.getCurves().remove(i);
        }
      }
    }
    if (flag){
      GraphicStyle gs = createDefaultGraphicStyle2();
      //createDefaultGraphicStyle();
      notifyGraphicStyleChanged(gs, true);
    }
  }

  @Override
  public void angleChanged(SheetsAngleChangedEvent event) {
    if (sheet == null || graphicStyle == null){
      return;
    }
    setMinMax(sheet);
    notifyGraphicStyleChanged(graphicStyle, false);
  }
 
 
 
  /**
   * Répond à l'évenement "une colonne a été modifiée"
   * @param event
   */
  @Override
  public void columnModified(SheetsColumnModifiedEvent event) {
    String oldName = event.getAncienNom();
    for (Curve curve : graphicStyle.getCurves()){
      if (curve.useName(oldName)){
        GraphicStyle gs = createDefaultGraphicStyle2();
        notifyGraphicStyleChanged(gs, true);
        return;
      }
    }
  }

  @Override
  public void columnMoved(SheetsColumnMovedEvent event) {
   
  }

  @Override
  public void columnSorted(SheetsColumnSortedEvent event) {
    notifyGraphicStyleChanged(graphicStyle, false); // @TODO à vérifier
  }

  @Override
  public void columnsEdited(SheetsColumnsEditedEvent event) {
    System.out.println("GraphicModel : SheetsColumnEdited *******************");
    GraphicStyle gs = createDefaultGraphicStyle2();
    notifyGraphicStyleChanged(gs, true);   
  }

  @Override
  public void sheetDescriptionChanged(SheetDescriptionChangedEvent event) {
   
  }

  @Override
  public void sheetsCSChanged(SheetsCSChangedEvent event) {
  
  }

  /**
   * Répond à l'évenement "une cellule a changé"
   * @param event
   */
  @Override
  public void sheetCellChanged(SheetCellChangedEvent event) {
    Colonne col = sheet.donneColonne(event.getColonne() - 1);
    setMinMax(col);
    notifyGraphicStyleChanged(graphicStyle, false);
  }
 
  /**
   * Recalcule les min et max de toutes les colonnes de la feuille en cours
   * pour les axes en échelle automatique
   * @param sheet
   */
  private void setMinMax(Tableur sheet){
    if (sheet == null){
      return;
    }
    for (Colonne col : sheet.getListeColonnes()){
      setMinMax(col);
    }
  }

  /**
   * Trouve la liste de noms de variables associées à un axe
   * @param axis
   * @return
   */
  private List<String> namesOnAxis(Axis axis){
    List<String> names = new ArrayList<>();
    for (Curve curve : graphicStyle.getCurves()){
      if (curve.getAxisX().equals(axis)){
        names.add(curve.getxName());
      }
      if (curve.getAxisY().equals(axis)){
        names.add(curve.getyName());
      }     
    }
    return names;
  }
 
 
  /**
   * Recalcule les min et max de la colonne col
   * pour les axes en échelle automatique
   * @param col
   */
  private void setMinMax(Colonne col){
    String name = col.getColonneDescription().getNom();
    // Trouver les axes
    boolean b = false, t = false, l = false, r = false;
    for (Curve curve : graphicStyle.getCurves()){ 
      if (curve.getxName().equals(name)){
        switch (curve.getAxisX().getAxisStyle().getPosition()){
          case BOTTOM : b = true; break;
          case TOP : t = true; break;
          case LEFT : l = true; break;
          case RIGHT : r = true; break;
        }
        switch (curve.getAxisY().getAxisStyle().getPosition()){
          case BOTTOM : b = true; break;
          case TOP : t = true; break;
          case LEFT : l = true; break;
          case RIGHT : r = true; break;
        }       
      } else if (curve.getyName().equals(name)){
        switch (curve.getAxisX().getAxisStyle().getPosition()){
          case BOTTOM : b = true; break;
          case TOP : t = true; break;
          case LEFT : l = true; break;
          case RIGHT : r = true; break;
        }
        switch (curve.getAxisY().getAxisStyle().getPosition()){
          case BOTTOM : b = true; break;
          case TOP : t = true; break;
          case LEFT : l = true; break;
          case RIGHT : r = true; break;
        }       
      }
     
    }
    List<String> names;
    if (b){
      names = namesOnAxis(axisX1);
      minmaxAxis(axisX1, names);
    }   
    if (l){
      names = namesOnAxis(axisY1);
      minmaxAxis(axisY1, names);
    }
    if (r){
      names = namesOnAxis(axisY2);
      minmaxAxis(axisY2, names);
   
    if (t){
      names = namesOnAxis(axisX2);
      minmaxAxis(axisX2, names);
    }   
   
  }
 
  /**
   * Utilisée dans setMinMax
   * @param axis
   * @param names
   */
  private void minmaxAxis(Axis axis, List<String> names){
    Colonne c;
    double min = Double.MAX_VALUE, max = Double.MIN_VALUE;
    for (String n : names){
      c = sheet.donneColonne(n);
      if (c.getMin() < min) { min = c.getMin();}
      if (c.getMax() > max) { max = c.getMax();}
    }
    axis.getAxisStyle().reInitMinMax(min, max);   
  }

  /**
   * Répond à l'évenement "des lignes ont été ajoutées"
   * @param event
   */ 
  @Override
  public void sheetLinesAdded(SheetLinesAddedEvent event) {
    setMinMax(sheet);
    notifyGraphicStyleChanged(graphicStyle, false);
  }

  /**
   * Répond à l'évenement "des lignes ont été supprimées"
   * @param event
   */
  @Override
  public void sheetLinesDeleted(SheetLinesDeletedEvent event) {
    setMinMax(sheet);
    notifyGraphicStyleChanged(graphicStyle, false);
  }

  /**
   * Réinitialisation des objets graphiques
   */
  private void initGraphic(){
    objects.clear();
    hilight = null;
    objects.add(axisX1);
    objects.add(axisY1);
    objects.add(axisX2);
    objects.add(axisY2);
  }

  /**
   * Fabrique un GraphicStyle par défaut avec les deux premières
   * colonnes du tableur
   * @return
   */
  private GraphicStyle createDefaultGraphicStyle2(){
    GraphicStyle gs = new GraphicStyle();
    Tableur sh = SpreadSheets.getInstance().getActiveSheet();
    if (sh != null && sh.donneNombreColonne() > 0){
      Colonne col1, col2;
      col1 = sh.donneColonne(0);
      String xName = col1.getColonneDescription().getNom();
      gs.setAbscissa(xName);
      gs.getaX1().setAll(xName, xName, true, col1.getMin(), col1.getMax(), Position.RIGHT);
      if (sh.donneNombreColonne() > 1){
        col2 = sh.donneColonne(1);
      } else {
        col2 = col1;
      }
      String yName = col2.getColonneDescription().getNom();
      gs.getaY1().setAll(yName, yName, true, col2.getMin(), col2.getMax(), Position.TOP);
      PointLineStyle pls = new PointLineStyle(Color.BLACK, PointStyle.CIRCLE, 5, LineStyle.NONE, 2);
      Curve curve = new Curve(xName, yName, gs.getaX1(), gs.getaY1(), pls);
      gs.getCurves().add(curve);
    }   
    return gs;
  }
 
  /**
   * Il n'y a pas encore de graphique, on en crée un par défault avec
   * les deux premières colonnes des tableurs
   */
  private void createDefaultGraphicStyle(){
    graphicStyle = createDefaultGraphicStyle2();
    axisX1 = graphicStyle.getaX1();
    axisY1 = graphicStyle.getaY1();
    axisX2 = graphicStyle.getaX2();
    axisY2 = graphicStyle.getaY2();   
  }

  private double[] listToArray(List<Double> doubles){
    double[] d = new double[doubles.size()];
    for (int i = 0; i < doubles.size(); i++){
      d[i] = doubles.get(i);
    }
    return d;
  }
 
  /**
   * Met à jour la liste des courbes de tendance.
   */
  private void updateFitCurves(){
    System.out.println("********** updateFitCurves");
    if (graphicStyle == null){
      return;
    }
    List<Fit> fits = FitModel.getInstance().getListTendances();
    List<Curve> curves = graphicStyle.getCurves();
    List<Curve> fitCurves = graphicStyle.getFitCurves();
    for (Curve fitCurve : fitCurves){
      objects.remove(fitCurve);
    }
    fitCurves.clear();
    Curve fitCurve;
    int xmin = axisX1.getAxisX();
    int xmax = axisX1.getAxisX() + axisX1.getAxisWidth() - 1;
    int ymax = axisY1.getAxisY();
    int ymin = axisY1.getAxisY() + axisY1.getAxisHeight() - 1;   
    for (Fit fit : fits){
      for (Curve curve : curves){
        if (fit.getNomX().equals(curve.getxName()) && fit.getNomY().equals(curve.getyName())){
          PointLineStyle pls = new PointLineStyle(curve.getForeGround(), null, 0, LineStyle.CONTINUE, curve.getLineWidth());
          fitCurve = new Curve(fit.getNomX(), fit.getNomY(), null, null, pls);
          double[] xd = listToArray(fit.getListeX());
          double[] yd = listToArray(fit.getListeY());
          int[] x = getIntArray(xd, xmin, xmax, fit.getMinX(), fit.getMaxX());
          int[] y = getIntArray(yd, ymin, ymax, fit.getMinY(), fit.getMaxY());
          fitCurve.update(x, y);
          fitCurves.add(fitCurve);
          objects.add(fitCurve);
          break;
        }
      }
    }
  }
 
  @Override
  public void tendanceChanged(TendanceChangedEvent event) {
    updateFitCurves();
    notifyGraphicStyleChanged(graphicStyle, false);
  }

  @Override
  public void tendanceCreated(TendanceCreatedEvent event) {
    updateFitCurves();
    notifyGraphicStyleChanged(graphicStyle, false);
  }

  @Override
  public void tendanceDeleted(TendanceDeletedEvent event) {
    updateFitCurves();
    notifyGraphicStyleChanged(graphicStyle, false);
  }

  /**
   * Classe qui définit l'évenement "la taille du graphique a changé"
   */
  public class GraphicSizeChangedEvent extends EventObject {
    private final int newWidth;
    private final int newHeight;

    public GraphicSizeChangedEvent(Object source, int newWidth, int newHeight) {
      super(source);
      this.newWidth = newWidth;
      this.newHeight = newHeight;
    }

    public int getNewHeight() {
      return newHeight;
    }

    public int getNewWidth() {
      return newWidth;
    }
  }

  /**
   * Recalcule tous les axes et les courbes
   */
  private void updateAxisAndCurves(){
    if (initializing){
      return;
    }
    initGraphic();

    if (graphicStyle == null){
      System.out.println("updateAxisAndCurves graphicStyle == null");
      return;
    }
    if (width < 5 || height < 5){
      System.out.println("updateAxisAndCurves taille trop petite");
      return;
    }
    if (g2 == null){
      System.out.println("updateAxisAndCurves pas de g2");
      return;
    }   
    System.out.println("GraphicModel updateAxisAndCurves " + width + " " + height);
    int numberHeight = textHeight(gradFont, "1E1");
    String largerY1, largerY2;
    int heightTitleX1, heightTitleX2, heightTitleY1, heightTitleY2;
    int axisY1Width = AXIS_MINWIDTH, axisY2Width = AXIS_MINWIDTH,
            axisX1Height, axisX2Height;
    if ( !axisY1.getTitle().equals("")){
      largerY1 = Axis.getLargerGrad(height, axisY1.getMin(), axisY1.getMax());
      heightTitleY1 = textHeight(axisFont, axisY1.getTitle());
      axisY1Width = heightTitleY1 + textWidth(gradFont, largerY1) + Axis.getGradSize();
    }
    axisY1.setAxisWidth(axisY1Width);

    if (!axisY2.getTitle().equals("")){
      largerY2 = Axis.getLargerGrad(height, axisY2.getMin(), axisY2.getMax());
      heightTitleY2 = textHeight(axisFont, axisY2.getTitle());
      axisY2Width = heightTitleY2 + textWidth(gradFont, largerY2) + Axis.getGradSize();
    }else{
      //axisY2Width = 1;
    }
    axisY2.setAxisWidth(axisY2Width);

    if (!axisX1.getTitle().equals("")){
      heightTitleX1 = textHeight(axisFont, axisX1.getTitle());
      axisX1Height = heightTitleX1 + numberHeight + Axis.getGradSize();
    }else{
      heightTitleX1 = AXIS_MINWIDTH;
      axisX1Height = heightTitleX1;
    }

    axisX1.setAxisHeight(axisX1Height);
    axisX1.setAxisWidth(width - axisY1Width - axisY2Width);
    axisX1.setAxisX(axisY1Width - 1);
    axisX1.setAxisY(height - 1 - axisX1Height);
    axisX1.update(width, height/*, min, max*/);

    if (!axisX2.getTitle().equals("")){
      heightTitleX2 = textHeight(axisFont, axisX2.getTitle());
      axisX2Height = heightTitleX2 + numberHeight + Axis.getGradSize();
    }else{
      heightTitleX2 = AXIS_MINWIDTH;
      axisX2Height = heightTitleX2;
    }

    axisX2.setAxisHeight(axisX2Height);
    axisX2.setAxisWidth(width - axisY1Width - axisY2Width);
    axisX2.setAxisX(axisY1Width - 1);
    axisX2.setAxisY(0);
    axisX2.update(width, height);

    axisY1.setAxisHeight(height - axisX1Height - axisX2Height);
    axisY1.setAxisX(0);
    axisY1.setAxisY(axisX2Height - 1);
    axisY1.update(width, height);

    axisY2.setAxisHeight(height - axisX1Height - axisX2Height);
    axisY2.setAxisX(width - axisY2Width - 1);
    axisY2.setAxisY(axisX2Height - 1);
    axisY2.update(width, height);

    for (Curve curve : graphicStyle.getCurves()){
      //Colonne colX = SpreadSheets.getInstance().getActiveSheet().donneColonne(curve.getAxisX().getAxisStyle().getName());
      Colonne colX = sheet.donneColonne(curve.getxName());
      double minX = curve.getAxisX().getMin();
      double maxX = curve.getAxisX().getMax();
      int x1 = axisX1.getAxisX();
      int x2 = axisX1.getAxisX() + axisX1.getAxisWidth() - 1;
      int[] x = getIntArray(colX.getTableauDouble(), x1, x2, minX, maxX);
      //Colonne colY = SpreadSheets.getInstance().getActiveSheet().donneColonne(curve.getAxisY().getAxisStyle().getName());
      //Colonne colY = sheet.donneColonne(curve.getAxisY().getAxisStyle().getName());
      Colonne colY = sheet.donneColonne(curve.getyName());
//      if (colY == null){
//        System.out.println("colY == null");
//      }
      double minY = curve.getAxisY().getMin();
      double maxY = curve.getAxisY().getMax();
      int y1 = axisY1.getAxisY() + axisY1.getAxisHeight() - 1;
      int y2 = axisY1.getAxisY();
      int[] y = getIntArray(colY.getTableauDouble(), y1, y2, minY, maxY);
      curve.update(x, y);
      objects.add(curve);
    }
   
    for (Curve curve : graphicStyle.getFitCurves()){
      objects.add(curve);
    }
   
  }

  /**
   * La taille de la zone de dessin a changé, il faut redessiner le graphique
   * @param newWidth la nouvelle largeur
   * @param newHeight la nouvelle hauteur
   */
  public void notifySizeChanged(int newWidth, int newHeight){
    if (width == newWidth && height == newHeight){
      return;
    }
    System.out.println("GraphicModel notifySizeChanged " + newWidth + " " + newHeight);
    width = newWidth;
    height = newHeight;
    updateAxisAndCurves();
    updateFitCurves();
    fireSizeChanged(width, height);
  }

  /**
   * Informe tous les écouteurs que la taille de la zone de dessin a changé
   * @param newWidth
   * @param newHeight
   */
  private void fireSizeChanged(int newWidth, int newHeight) {
    GraphicListener[] listenerList = (GraphicListener[]) listeners.getListeners(GraphicListener.class);
    for (GraphicListener listener : listenerList) {
      listener.graphicSizeChanged(new GraphicSizeChangedEvent(this, newWidth, newHeight));
    }
  }

  /**
   * Classe qui définit l'évenement "le graphique a changé"
   */
  public class GraphicChangedEvent extends EventObject {
    public GraphicChangedEvent(Object source) {
      super(source);
    }
  }
 
  /**
   * La souris a été déplacée, il faut redessiner le graphique
   */
  public void notifyGraphicChanged(){
    fireGraphicChanged();
  }

  /**
   * Informe tous les écouteurs que la souris a été déplacée
   */
  private void fireGraphicChanged() {
    GraphicListener[] listenerList = (GraphicListener[]) listeners.getListeners(GraphicListener.class);
    for (GraphicListener listener : listenerList) {
      listener.graphicChanged(new GraphicChangedEvent(this));
    }
  }
  /**
   * Ajoute un écouteur à la liste
   * @param listener l'écouteur à ajouter
   */
  public void addGraphicListener(GraphicListener listener) {
    listeners.add(GraphicListener.class, listener);
  }

  /**
   * Retire un écouteur de la liste
   * @param listener l'écouteur à retirer
   */
  public void removeGraphicListener(GraphicListener listener) {
    listeners.remove(GraphicListener.class, listener);
  }
  public interface GraphicListener extends EventListener {
    public void graphicSizeChanged(GraphicSizeChangedEvent event);
    public void graphicChanged(GraphicChangedEvent event);
    public void graphicStyleChanged(GraphicStyleChangedEvent event);
  }

  /**
   * La souris a bougé
   * @param newX
   * @param newY
   */
  public void notifyMouseMoved(int newX, int newY){
    // retirer le dernier ob
    boolean found = false;
    Shape shape;
    for (GraphicObject object : objects){
      if (object != null && object.contains(newX, newY)){
        shape = object.getHilight();
        found = true;
        if (shape.equals(hilight)){
          // ne rien faire
        }else{
          // changer l'objet hilighted
          hilight = shape;
          notifyGraphicChanged();
        }
        break;
      }

    }
    if (!found && hilight != null){
      hilight = null;
      notifyGraphicChanged();
    }
  }

  /**
   * La souris a quitté la zone de dessin
   */
  public void notifyMouseExited(){
    if (hilight != null){
      hilight = null;
      notifyGraphicChanged();
    }
  }

  /**
   * Crée un texte XML correspondant au graphique en vue de l'enregistrement
   * sur le disque.
   * @param tab le nombre de tabulations devant chaque ligne
   * @return le XML du graphique
   */
  public String toXML(String tab){
    String tab2 = tab + "\t";
    String str = tab + "<graphic>\n";

    str += graphicStyle.toXML(tab2);

    str += tab + "</graphic>\n";

    return str;
  }

  /**
   *
   * @param color
   * @return
   */
  public static String encodeColor(Color color){
    return "#" + Integer.toHexString((color.getRGB() & 0xffffff) | 0x1000000).substring(1) ;
  }

  /**
   * La classe qui définit l'évenement "le style du graphique a changé"
   */
  public class GraphicStyleChangedEvent extends FreegressiEvent {
    private final GraphicStyle oldGS;
    private final GraphicStyle newGS;

    public GraphicStyleChangedEvent(Object source, GraphicStyle oldGS, GraphicStyle newGS,  boolean undoable) {
      super(source);
      this.newGS = newGS;
      this.undoable = undoable;
      this.oldGS = oldGS;
    }

    @Override
    public boolean isUndoable() {
      return undoable;
    }

    public GraphicStyle getNewGS() {
      return newGS;
    }

    public GraphicStyle getOldGS() {
      return oldGS;
    }

    @Override
    public String getText() {
      return "Changer le graphique";
    }

    @Override
    public void undo() {
      notifyGraphicStyleChanged(oldGS, false);
    }

    @Override
    public void redo() {
      notifyGraphicStyleChanged(newGS, false);
    }

  }

  /**
   * Le style du graphique a changé
   * @param graphicStyle le nouveau style
   * @param undoable
   */
  public void notifyGraphicStyleChanged(GraphicStyle graphicStyle, boolean undoable){
    System.out.println("GraphicModel notifyGraphicStyleChanged");
    //sheet = SpreadSheets.getInstance().getActiveSheet();
    GraphicStyle oldGS = this.graphicStyle;
    setGraphicStyle(graphicStyle);
    updateAxisAndCurves();
    fireGraphicStyleChanged(oldGS, graphicStyle, undoable);
  }
 
  /**
   * Informer les écouteurs que le style du graphique a changé
   * @param oldGS
   * @param newGS
   * @param undoable
   */
  private void fireGraphicStyleChanged(GraphicStyle oldGS, GraphicStyle newGS, boolean undoable) {
    GraphicStyleChangedEvent event = new GraphicStyleChangedEvent(this, oldGS, newGS,undoable);
    GraphicListener[] listenerList = (GraphicListener[]) listeners.getListeners(GraphicListener.class);
    for (GraphicListener listener : listenerList) {
      listener.graphicStyleChanged(event);
    }
  }
}
TOP

Related Classes of freegressi.graphics.GraphicModel$GraphicListener

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.
ew'); d', 'pageview');