Package de.chris_soft.fyllgen.widget

Source Code of de.chris_soft.fyllgen.widget.FamilyCompositePainter

/**
* FyLLGen - A Java based tool for collecting and distributing family data
*
* Copyright (C) 2007-2011 Christian Packenius
*
* This program 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
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package de.chris_soft.fyllgen.widget;

import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

import de.chris_soft.fyllgen.data.Family;
import de.chris_soft.fyllgen.data.OptionData;
import de.chris_soft.fyllgen.data.Person;
import de.chris_soft.fyllgen.data.Relationship;
import de.chris_soft.fyllgen.data.RelationshipParentChild;
import de.chris_soft.fyllgen.data.RelationshipPartners;
import de.chris_soft.fyllgen.utilities.SwtConsts;

/**
* Hier k�mmert man sich lediglich um das Zeichnen der Verbindungslinien
* zwischen den dargestellten Personen.
* @author Christian Packenius, Juli 2008.
*/
public class FamilyCompositePainter implements PaintListener {
  /**
   * Liste aller darzustellenden Personen.
   */
  private final List<Person> listAllPersons;

  /**
   * Liste aller Widgets zu den darzustellenden Personen.
   */
  private final List<PersonView> listAllPersonComposites;

  /**
   * Aktuelle Person.
   */
  private Person currentMainPerson;

  /**
   * Konstruktor.
   * @param listAllPersons Liste aller darzustellenden Personen.
   * @param listAllPersonComposites Zu jeder darzustellenden Person das
   *          entsprechende Widget.
   */
  public FamilyCompositePainter(List<Person> listAllPersons, List<PersonView> listAllPersonComposites) {
    this.listAllPersons = listAllPersons;
    this.listAllPersonComposites = listAllPersonComposites;
  }

  /**
   * Alle bestehenden Verbindungen zwischen Personen einzeichnen.
   * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
   */
  public void paintControl(PaintEvent e) {
    // Erst alles in ein Image malen und dann in einem Zug in das Control
    // zeichnen.
    GC egc = e.gc;
    Control widget = (Control) e.widget;
    Point size = widget.computeSize(SWT.DEFAULT, SWT.DEFAULT);
    Image image = new Image(Display.getDefault(), size.x, size.y);
    GC gc = new GC(image);
    gc.setBackground(widget.getBackground());
    gc.fillRectangle(0, 0, size.x, size.y);

    currentMainPerson = Family.instance.getCurrentPerson();

    // Zu allen Personen Partner und Kinder anzeigen.
    for (Person person : listAllPersons) {
      // Alle Kinder anzeigen.
      Person[] children = person.getChildren();
      int childrenLength = children.length;
      for (int i = 0; i < childrenLength; i++) {
        Person child = children[i];
        PersonView pc1 = listAllPersonComposites.get(listAllPersons.indexOf(person));
        int childIndex = listAllPersons.indexOf(child);
        if (childIndex >= 0) {
          PersonView pc2 = listAllPersonComposites.get(childIndex);
          drawConnection(gc, pc1, pc2);
        }
      }

      // Alle Partner anzeigen.
      Person[] partners = person.getPartner();
      for (Person partner : partners) {
        PersonView pc1 = listAllPersonComposites.get(listAllPersons.indexOf(person));
        int partnerIndex = listAllPersons.indexOf(partner);
        if (partnerIndex >= 0) {
          PersonView pc2 = listAllPersonComposites.get(partnerIndex);
          drawConnection(gc, pc1, pc2);
        }
      }
    }

    gc.dispose();
    egc.drawImage(image, 0, 0);
    image.dispose();
  }

  /**
   * Zeichnet die Verbindung zwischen den beiden Composite-Objekten ein.
   */
  private void drawConnection(GC gc, PersonView pc1, PersonView pc2) {
    // Farben holen und allokieren.
    Color colorLineCurrentPerson = OptionData.instance.getColor(OptionData.COLOR_LINE_CURRENT_PERSON);
    Color colorLineOtherPerson = OptionData.instance.getColor(OptionData.COLOR_LINE_OTHER_PERSON);

    // Bei einer Ehe und einem leiblichen Kind wird die Linie durchgezeichnet,
    // sonst gestrichelt.
    Relationship relship = pc1.person.getRelationship(pc2.person);
    boolean bFullLine = relship.getValue(Relationship.TYPE, "option").equals(RelationshipPartners.MARRIAGE);
    bFullLine |= relship.getValue(Relationship.TYPE, "option").equals(RelationshipParentChild.BIOLOGICAL);

    // Grenzen der beiden Composites holen, die miteinander verbunden werden
    // sollen.
    Rectangle rc1 = pc1.getBounds();
    Rectangle rc2 = pc2.getBounds();

    // Die aktuelle Person sowie die ihr direkt zugeordneten blau zeichnen, die
    // anderen normal schwarz.
    if (pc1.person == currentMainPerson || pc2.person == currentMainPerson) {
      gc.setForeground(colorLineCurrentPerson);
    }
    else {
      gc.setForeground(colorLineOtherPerson);
    }

    // Strichart setzen.
    if (bFullLine) {
      gc.setLineStyle(SWT.LINE_SOLID);
    }
    else {
      gc.setLineStyle(SWT.LINE_DASH);
    }

    // Beziehungslinienstil setzen.
    String sLineStyle = Integer.toString(SWT.LINE_SOLID);
    String relType = relship.getType();
    if (relship instanceof RelationshipPartners) {
      if (relType.equals(RelationshipPartners.MARRIAGE)) {
        sLineStyle = OptionData.instance.getComboKey(OptionData.LINE_TYPE_PARTNER_MARRIAGE);
      }
      else if (relType.equals(RelationshipPartners.ENGAGEMENT)) {
        sLineStyle = OptionData.instance.getComboKey(OptionData.LINE_TYPE_PARTNER_ENGAGEMENT);
      }
      else if (relType.equals(RelationshipPartners.DIVORCE)) {
        sLineStyle = OptionData.instance.getComboKey(OptionData.LINE_TYPE_PARTNER_DIVORCE);
      }
      else if (relType.equals(RelationshipPartners.FRIENDSHIP)) {
        sLineStyle = OptionData.instance.getComboKey(OptionData.LINE_TYPE_PARTNER_FRIENDSHIP);
      }
    }
    else if (relship instanceof RelationshipParentChild) {
      if (relType.equals(RelationshipParentChild.BIOLOGICAL)) {
        sLineStyle = OptionData.instance.getComboKey(OptionData.LINE_TYPE_PARENT_CHILD_BIOLOGICAL);
      }
      else if (relType.equals(RelationshipParentChild.ADOPTIVE)) {
        sLineStyle = OptionData.instance.getComboKey(OptionData.LINE_TYPE_PARENT_CHILD_ADOPTIVE);
      }
      else if (relType.equals(RelationshipParentChild.STEP)) {
        sLineStyle = OptionData.instance.getComboKey(OptionData.LINE_TYPE_PARENT_CHILD_STEP);
      }
      else if (relType.equals(RelationshipParentChild.FOSTER)) {
        sLineStyle = OptionData.instance.getComboKey(OptionData.LINE_TYPE_PARENT_CHILD_FOSTER);
      }
    }
    gc.setLineStyle(Integer.parseInt(sLineStyle));

    // Vom ersten Composite rechts Mitte, vom zweiten links Mitte.
    Point p1 = new Point(rc1.x + rc1.width, rc1.y + rc1.height / 2);
    Point p2 = new Point(rc2.x, rc2.y + rc2.height / 2);

    // Falls die Composites teilweise untereinander stehen, an der rechten Seite
    // verbinden.
    if (p1.x >= rc2.x) {
      drawPartnersLine(gc, p1, p2, rc1, rc2);
    }
    else {
      drawParentChildLine(gc, p1, p2);
    }

    // Farben wieder freigeben.
    colorLineCurrentPerson.dispose();
    colorLineOtherPerson.dispose();
  }

  /**
   * Zeichnet eine Linie zwischen zwei Partnern.
   */
  private void drawPartnersLine(GC gc, Point p1, Point p2, Rectangle rc1, Rectangle rc2) {
    // p2 soll nun unter p1 sein!
    if (p1.y > p2.y) {
      Point ph = p1;
      p1 = p2;
      p2 = ph;
    }

    // TODO - Je nach Art der Partnerschaft stricheln oder punkten. Beispiel:
    // Ehe: Durchgezogen.
    // Geschieden: Gepunktet.

    // Der zweite Punkt soll dann auch rechts Mitte liegen.
    p2 = new Point(rc2.x + rc2.width, rc2.y + rc2.height / 2);
    int maxX = Math.max(p1.x, p2.x) + 10;
    int dx1 = maxX - p1.x;
    int dx2 = maxX - p2.x;
    int dy = p2.y - p1.y;
    if (OptionData.instance.getBoolean(OptionData.DRAW_STRAIGHT_LINES_FOR_PARTNERS)) {
      gc.drawLine(p1.x, p1.y, p1.x + dx1, p1.y);
      gc.drawLine(p1.x + dx1, p1.y, p1.x + dx1, p2.y);
      gc.drawLine(p2.x, p2.y, p1.x + dx1, p2.y);
    }
    else {
      gc.drawArc(p1.x - dx1, p1.y, dx1 + dx1, dy, 0, 90);
      gc.drawArc(p2.x - dx2, p1.y, dx2 + dx2, dy, 270, 90);
    }
  }

  /**
   * Zeichnet eine Linie vom Elternteil zum Kind.
   */
  private void drawParentChildLine(GC gc, Point p1, Point p2) {
    // Nun von links nach rechts verbinden.
    // pc1 muss links von pc2 sein!
    // Au�erdem sollten alle PersonComposites gleich gro� sein!
    if (p1.x > p2.x) {
      Point ph = p1;
      p1 = p2;
      p2 = ph;
    }

    // TODO - Per Option eine andere Darstellung erlauben:
    // - Biologische Eltern oder Adoptiveltern nicht jeweils mit einer Linie
    // versehen, sondern mit der Partnerschaftslinie
    // verbinden.
    // - Stief- oder Pflegeeltern "normal" mit einzelner Linie anzeigen,
    // allerdings gepunktet (Pflegeeltern) oder
    // gestrichelt
    // (Stiefeltern).

    if (Math.abs(p1.y - p2.y) < 6 || OptionData.instance.getBoolean(OptionData.DRAW_STRAIGHT_LINES_FOR_CHILDREN)) {
      gc.drawLine(p1.x, p1.y, p2.x, p2.y);
    }
    else {
      int width = p2.x - p1.x;

      // Ersetzen der Kurven unten? Versuch!
      Path path = new Path(SwtConsts.display);
      path.moveTo(p1.x, p1.y);
      path.cubicTo(p1.x + width / 2, p1.y, p2.x - width / 2, p2.y, p2.x, p2.y);
      gc.drawPath(path);
      path.dispose();
    }
  }
}
TOP

Related Classes of de.chris_soft.fyllgen.widget.FamilyCompositePainter

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.