Package de.hwrberlin.it11.tsp.gui.components

Source Code of de.hwrberlin.it11.tsp.gui.components.DrawComposite$AntPaintListener

/**
* Copyright (c) 2012 mops� Productions
*/
package de.hwrberlin.it11.tsp.gui.components;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DecimalFormat;
import java.util.List;

import net.miginfocom.swt.MigLayout;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Scale;

import de.hwrberlin.it11.tsp.constant.PropertyChangeTypes;
import de.hwrberlin.it11.tsp.controller.AntController;
import de.hwrberlin.it11.tsp.gui.dialog.NewNodeDialog;
import de.hwrberlin.it11.tsp.gui.updatestrategy.ZoomFactorModelToTargetUpdateStrategy;
import de.hwrberlin.it11.tsp.gui.updatestrategy.ZoomFactorTargetToModelUpdateStrategy;
import de.hwrberlin.it11.tsp.gui.widgets.AntScale;
import de.hwrberlin.it11.tsp.model.AntProject;
import de.hwrberlin.it11.tsp.model.Node;
import de.hwrberlin.it11.tsp.model.Preferences;
import de.hwrberlin.it11.tsp.model.Result;

/**
* In diesem Composite wird der Fortschritt des Ameisenprojektes gemalt.
*/
public class DrawComposite extends ADataBindableComposite implements PropertyChangeListener {

  /**
   * Die Breite des Randes, die zwischen dem Rand des Canvas und der Malfl�che gelassen wird. So wird verhindert, dass der Punkt der Nodes, die sich
   * zum Beispiel an Koordinate 0 befinden, halb abgeschnitten wird.
   */
  private static final int BORDER_WIDTH = 25;

  /** Das benutzte DecimalFormat um Dezimalzahlen in einen String zu konvertieren */
  private static final DecimalFormat FORMAT = new DecimalFormat("#.000");

  /** Die momentan ausgew�hlte Node */
  private Node _selectedNode;

  /** Die Fl�che, auf der der ganze Spa� gemalt wird */
  private Canvas _canvas;

  /** Die Scale, mit der sich der Zoomfaktor einstellen l�sst */
  private AntScale _zoomFactor;

  /** Gibt an, ob die Maus gedr�ckt ist, w�hrend sie sich bewegt */
  private boolean _drag;

  /** Das ScrolledComposite scrollt den Canvas */
  private ScrolledComposite _scrolledComposite;

  /** Hier werden verschiedene Statusmeldungen angezeigt */
  private Label _statusLabel;



  /**
   * Erstellt ein neues DrawComposite.
   *
   * @param pParent
   *            das Eltern-Composite
   * @param pStyle
   *            der Style des Composite
   * @param pController
   *            der Controller dieses DrawComposite
   */
  public DrawComposite(Composite pParent, int pStyle, AntController pController) {
    super(pParent, pStyle, pController);

    AntProject project = getController().getProject();
    project.addPropertyChangeListener(this);
    project.getParameter().addPropertyChangeListener(this);
    project.getTSPData().addPropertyChangeListener(this);
    Preferences.getInstance().addPropertyChangeListener(this);

    _scrolledComposite = new ScrolledComposite(this, SWT.H_SCROLL | SWT.V_SCROLL);
    _scrolledComposite.setLayoutData("hmin 0, wmin 0, grow, push");
    _scrolledComposite.setExpandHorizontal(true);
    _scrolledComposite.setExpandVertical(true);

    _canvas = new Canvas(_scrolledComposite, SWT.DOUBLE_BUFFERED);

    _zoomFactor = new AntScale(new Scale(this, SWT.VERTICAL), getController().getProject());
    _zoomFactor.getScale().setLayoutData("hmin 0, wmin pref, growy");
    _zoomFactor.getScale().setMinimum(5);
    _zoomFactor.getScale().setMaximum(300);
    _zoomFactor.setTooltipText("Hier k�nnen Sie den Zoom-Faktor einstellen, mit dem die Knoten und Kanten dargestellt werden.");

    _canvas.addPaintListener(new AntPaintListener());
    _canvas.addMouseListener(new MouseAdapter() {

      @Override
      public void mouseDown(MouseEvent pE) {
        if (pE.button == 1) {
          if (_selectedNode != null) {
            _selectedNode.removePropertyChangeListener(DrawComposite.this);
          }
          double zoomFactor = getController().getProject().getParameter().getZoomFactor();
          double x = (pE.x - BORDER_WIDTH) / zoomFactor;
          double y = (pE.y - BORDER_WIDTH) / zoomFactor;
          _selectedNode = getController().getProject().getNodeForCoordinates((int) x, (int) y);
          if (_selectedNode != null) {
            _selectedNode.addPropertyChangeListener(DrawComposite.this);
            _drag = true;
          }
          _canvas.redraw();
        }
      }



      @Override
      public void mouseUp(MouseEvent pE) {
        if (pE.button == 1) {
          _drag = false;
        }
      }



      @Override
      public void mouseDoubleClick(MouseEvent pE) {
        if (pE.button == 1) {
          if (pE.x - BORDER_WIDTH >= 0 && pE.y - BORDER_WIDTH >= 0 && !getController().isRunning()) {
            if (_selectedNode != null) {
              _selectedNode.removePropertyChangeListener(DrawComposite.this);
              _drag = false;
              _selectedNode = null;
            }
            AntProject project = getController().getProject();
            double zoomFactor = project.getParameter().getZoomFactor();
            NewNodeDialog newNodeDialog = new NewNodeDialog(getShell(), project, (pE.x - BORDER_WIDTH) / zoomFactor,
                (pE.y - BORDER_WIDTH) / zoomFactor);
            Node newNode = newNodeDialog.open();
            if (newNode != null) {
              project.getTSPData().addNode(newNode);
            }
          }
        }
      }
    });

    _canvas.addMouseMoveListener(new MouseMoveListener() {

      @Override
      public void mouseMove(MouseEvent pE) {
        double zoomFactor = getController().getProject().getParameter().getZoomFactor();
        if (_drag && _selectedNode != null && !getController().isRunning()) {
          _selectedNode.setxCoordinate(pE.x >= BORDER_WIDTH ? (int) ((pE.x - BORDER_WIDTH) / zoomFactor) : 0);
          _selectedNode.setyCoordinate(pE.y >= BORDER_WIDTH ? (int) ((pE.y - BORDER_WIDTH) / zoomFactor) : 0);
        }
        getController().getProject().setStatusText(
            "X: " + FORMAT.format((pE.x - BORDER_WIDTH) / zoomFactor) + ", Y: " + FORMAT.format((pE.y - BORDER_WIDTH) / zoomFactor));
      }
    });

    _canvas.addKeyListener(new KeyAdapter() {

      @Override
      public void keyPressed(KeyEvent pE) {
        if (pE.keyCode == SWT.DEL) {
          if (_selectedNode != null && !getController().isRunning()) {
            getController().getProject().getTSPData().removeNode(_selectedNode);
            _selectedNode = null;
          }
        }
      }

    });

    Composite statusComp = new Composite(this, SWT.NONE);
    statusComp.setLayout(new MigLayout("fill, ins 0 5 0 0"));
    statusComp.setLayoutData("newline, hmin pref, wmin pref, spanx, growx");

    _statusLabel = new Label(statusComp, SWT.NONE);
    _statusLabel.setLayoutData("hmin pref, wmin pref, grow");

    _scrolledComposite.setContent(_canvas);

    resetBinding();
  }



  @Override
  protected void bindValues(DataBindingContext pDBC, Realm pRealm) {
    // ZoomFactor-Scale binden
    pDBC.bindValue(SWTObservables.observeSelection(_zoomFactor.getScale()),
        BeansObservables.observeValue(pRealm, getController().getProject().getParameter(), PropertyChangeTypes.PARAMETER_ZOOMFACTOR),
        new ZoomFactorTargetToModelUpdateStrategy(), new ZoomFactorModelToTargetUpdateStrategy());
    // Statustext binden
    pDBC.bindValue(SWTObservables.observeText(_statusLabel),
        BeansObservables.observeValue(pRealm, getController().getProject(), PropertyChangeTypes.PROJECT_STATUSTEXT));
  }



  @Override
  public void propertyChange(PropertyChangeEvent pEvt) {
    if (pEvt != null) {
      String propertyName = pEvt.getPropertyName();

      // Auf folgende Events eine Neuberechnung der gr��ten Koordinaten mit anschlie�endem redraw asuf�hren:
      if (PropertyChangeTypes.TSPDATA_NODELIST.equals(propertyName) // Die NodeList des Projektes wurde neu gesetzt
          || PropertyChangeTypes.PROJECT_TSPDATA.equals(propertyName) // TSP Daten des Projektes wurden neu gesetzt
          || PropertyChangeTypes.NODE_XCOORDINATE.equals(propertyName) // Es wurde die X Koordinate einer Node ver�ndert
          || PropertyChangeTypes.NODE_YCOORDINATE.equals(propertyName) // Es wurde die Y Koordinate einer Node ver�ndert
          || PropertyChangeTypes.TSPDATA_NODELIST_ADD.equals(propertyName) // Es wurde eine Node zur Knotenliste hinzugef�gt
          || PropertyChangeTypes.TSPDATA_NODELIST_REMOVE.equals(propertyName) // Es wurde eine Node von der Knotenliste entfernt
          || PropertyChangeTypes.PARAMETER_ZOOMFACTOR.equals(propertyName)) { // Der Zoom-Faktor hat sich ver�ndert
        double maxX = 0;
        double maxY = 0;
        AntProject project = getController().getProject();
        for (Node node : project.getTSPData().getNodeList()) {
          if (node.getxCoordinate() > maxX) {
            maxX = node.getxCoordinate();
          }
          if (node.getyCoordinate() > maxY) {
            maxY = node.getyCoordinate();
          }
        }

        double zoomFactor = project.getParameter().getZoomFactor();
        int preferredWidth = (int) (maxX * zoomFactor) + BORDER_WIDTH * 2;
        int preferredHeight = (int) (maxY * zoomFactor) + BORDER_WIDTH * 2;

        _scrolledComposite.setMinSize(preferredWidth, preferredHeight);

        _canvas.redraw();
      }

      // Einen gesyncten redraw auf folgende Events ausf�hren:
      if (PropertyChangeTypes.PROJECT_ITERATIONFINISHED.equals(propertyName)) { // Eine Iteration ist vorbei
        if (((Integer) pEvt.getNewValue()).intValue() % Preferences.getInstance().getRedrawInterval() == 0) {
          // Dieses Event kommt nicht aus dem UI-Thread, deswegen muss der Redraw mit Display.syncExec() ausgef�hrt werden
          Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
              if (!_canvas.isDisposed()) {
                _canvas.redraw();
              }
            }
          });
        }
      }

      // Einen normalen redraw auf folgende Events ausf�hren:
      if (PropertyChangeTypes.PREFERENCES_ANTIALIAS.equals(propertyName) // Die Antialiasingeinstellung hat sich ver�ndert
          || PropertyChangeTypes.PREFERENCES_BACKGROUNDCOLOR.equals(propertyName) // Die Hintergrundfarbeneinstellung hat sich ver�ndert
          || PropertyChangeTypes.PREFERENCES_BESTTOURGLOBALCOLOR.equals(propertyName) // Die Farbeinstellung der globalen besten Tour hat
                                                // sich ver�ndert
          || PropertyChangeTypes.PREFERENCES_BESTTOURITERATIONCOLOR.equals(propertyName) // die Farbeinstellung der besten Tour der
                                                  // Iteration hat sich ver�ndert
          || PropertyChangeTypes.PREFERENCES_CURRENTNODECOLOR.equals(propertyName) // Die Farbeinstellung der ausgew�hlten Knoten hat sich
                                                // ver�ndert
          || PropertyChangeTypes.PREFERENCES_NODECOLOR.equals(propertyName)) { // Die farbeinstellung der Knoten hat sich ver�ndert
        _canvas.redraw();
      }

      // Auf folgende Events das Databinding erneuern:
      if (PropertyChangeTypes.PROJECT_PARAMETER.equals(propertyName)) { // Parameter des Projektes wurden neu gesetzt
        getController().getProject().getParameter().addPropertyChangeListener(this);
        resetBinding();
      }

      if (PropertyChangeTypes.PROJECT_TSPDATA.equals(propertyName)) {
        getController().getProject().getTSPData().addPropertyChangeListener(this);
      }
    }
  }



  /**
   * Diese Klasse ist der �bersicht halber etwas ausgelagert. Sie �bernimmt das Zeichnen der Nodes und Touren auf den Canvas.
   *
   * @author Patrick Szostack
   *
   */
  private class AntPaintListener implements PaintListener {

    @Override
    public void paintControl(PaintEvent pE) {
      AntProject project = getController().getProject();
      List<Node> nodeList = project.getTSPData().getNodeList();
      double zoomFactor = project.getParameter().getZoomFactor();

      Result result = project.getResult();
      Preferences preferences = Preferences.getInstance();

      if (preferences.isAntialias()) {
        pE.gc.setAntialias(SWT.ON);
      }

      _canvas.setBackground(preferences.getBackgroundColor());

      // Beste Tour Iteration
      pE.gc.setForeground(preferences.getBestTourIterationColor());
      for (int i = 0; i < result.getBestTourIteration().size() - 1; i++) {
        Node node = result.getBestTourIteration().get(i);
        Node otherNode = result.getBestTourIteration().get(i + 1);
        pE.gc.drawLine((int) (node.getxCoordinate() * zoomFactor) + BORDER_WIDTH, (int) (node.getyCoordinate() * zoomFactor) + BORDER_WIDTH,
            (int) (otherNode.getxCoordinate() * zoomFactor) + BORDER_WIDTH, (int) (otherNode.getyCoordinate() * zoomFactor)
                + BORDER_WIDTH);
      }
      // Beste Tour global
      pE.gc.setForeground(preferences.getBestTourGlobalColor());
      for (int i = 0; i < result.getBestTourGlobal().size() - 1; i++) {
        Node node = result.getBestTourGlobal().get(i);
        Node otherNode = result.getBestTourGlobal().get(i + 1);
        pE.gc.drawLine((int) (node.getxCoordinate() * zoomFactor) + BORDER_WIDTH, (int) (node.getyCoordinate() * zoomFactor) + BORDER_WIDTH,
            (int) (otherNode.getxCoordinate() * zoomFactor) + BORDER_WIDTH, (int) (otherNode.getyCoordinate() * zoomFactor)
                + BORDER_WIDTH);
      }
      // Nodes
      pE.gc.setBackground(preferences.getNodeColor());
      for (Node node : nodeList) {
        if (node == _selectedNode) {
          pE.gc.setBackground(preferences.getCurrentNodeColor());
        }
        pE.gc.fillOval((int) (node.getxCoordinate() * zoomFactor) - 5 + BORDER_WIDTH, (int) (node.getyCoordinate() * zoomFactor) - 5
            + BORDER_WIDTH, 10, 10);
        if (node == _selectedNode) {
          pE.gc.setBackground(preferences.getNodeColor());
        }
      }
    }

  }
}
TOP

Related Classes of de.hwrberlin.it11.tsp.gui.components.DrawComposite$AntPaintListener

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.