/**
* 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.ArrayList;
import java.util.List;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import de.chris_soft.fyllgen.data.OptionData;
import de.chris_soft.fyllgen.data.Person;
/**
* Dies ist das Standard-Familien-Modell. Es nimmt sich die aktuelle Person und
* stellt mehrere Generationen von Vor- und Nachfahren zu dieser dar, wobei jede
* Generation eine eigene Spalte enth�lt.
* @author Christian Packenius, Juli 2008.
*/
public class FamilyModelStandard extends FamilyViewWithColumns implements FamilyModel {
/**
* Ma�e, werden bei jeder Neu-Anzeige aus den Optionen ermittelt.
*/
private int personWidth;
private int personHeight;
private int personMinHorizontalGap;
/**
* Aktuell zu bearbeitende Person.
*/
private Person currentMainPerson = null;
/**
* Konstruktor.
* @param familyComposite
*/
public FamilyModelStandard(FamilyComposite familyComposite) {
super(familyComposite);
}
/**
* L�scht alle Child-Widgets und baut alles neu auf.
* @param currentMainPerson Person, die aktuell bearbeitet wird.
* @param bounds
*/
public void rebuildPersons(Person currentMainPerson, Rectangle bounds) {
// Person merken.
// Diese Sicherheitsabfragt darf nicht sein, da sonst keine Aktualisierung
// m�glich ist!
// if (currentMainPerson == this.currentMainPerson) {
// return;
// }
this.currentMainPerson = currentMainPerson;
// Alles l�schen, wird hier neu aufgebaut.
listGenerationsToView.clear();
listWidgetsLists.clear();
// Ohne Hauptperson keine Anzeige!
if (currentMainPerson == null) {
return;
}
// Hier soll sp�ter stehen, welche Generationen angezeigt werden sollen.
// 0 = Hauptperson und Partner, -1 = Eltern, +1 = Kindern und so weiter.
int minGeneration = 0;
int maxGeneration = 0;
// Nun herauskriegen, wie breit Hauptperson, Eltern und Kinder insgesamt
// sind.
if (currentMainPerson.getParents().length > 0) {
minGeneration = -1;
}
if (currentMainPerson.getChildren().length > 0) {
maxGeneration = 1;
}
// Extrem einfache Ermittlung, wie viele Generationen angezeigt werden
// sollen.
int xAnz = maxGeneration - minGeneration + 1;
personWidth = OptionData.instance.getInt(OptionData.PERSON_WIDTH);
personHeight = OptionData.instance.getInt(OptionData.PERSON_HEIGHT);
personMinHorizontalGap = OptionData.instance.getInt(OptionData.PERSON_MIN_HORIZONTAL_GAP);
int xPlus = bounds.width - xAnz * personWidth - (xAnz - 1) * personMinHorizontalGap;
int moreGenerationsAllowed = xPlus / (personWidth + personMinHorizontalGap) / 2;
// Festlegen, bis zu welchen Generationen man anzeigen m�chte.
minGeneration -= moreGenerationsAllowed;
maxGeneration += moreGenerationsAllowed;
int maxAnc = OptionData.instance.getInt(OptionData.MAX_ANCESTOR_VIEW);
int maxDesc = OptionData.instance.getInt(OptionData.MAX_DESCENDANT_VIEW);
if (-minGeneration > maxAnc) {
maxGeneration += -maxAnc - minGeneration;
minGeneration = -maxAnc;
}
if (maxGeneration > maxDesc) {
maxGeneration = maxDesc;
}
// Eine Gesamtliste aller Personen sowie eine Liste je Generation leer
// erzeugen.
listAllPersons.clear();
listAllPersonComposites.clear();
for (int i = minGeneration; i <= maxGeneration; i++) {
// Liste mit der neuen Generation anlegen.
ArrayList<Person> listSingleGeneration = new ArrayList<Person>();
listGenerationsToView.add(listSingleGeneration);
}
// Hauptperson alleine in eine Generation stecken.
List<Person> listSingleGeneration = listGenerationsToView.get(-minGeneration);
listSingleGeneration.add(currentMainPerson);
listAllPersons.add(currentMainPerson);
// Noch alle Partner der Hauptperson hinzuf�gen.
Person[] partners = currentMainPerson.getPartner();
for (Person partner : partners) {
addSinglePersonToLists(listSingleGeneration, partner);
}
// Alle Eltern und Kinder in allen anzuzeigenden Generationen hinzuf�gen.
addFamily(minGeneration, maxGeneration);
// Leere Listen entfernen.
for (int i = listGenerationsToView.size() - 1; i >= 0; i--) {
List<Person> personlist = listGenerationsToView.get(i);
if (personlist.size() == 0) {
listGenerationsToView.remove(i);
}
}
// Noch die Liste der Composite-Objekte zu den Personen vorbereiten.
for (int i = 0; i < listAllPersons.size(); i++) {
listAllPersonComposites.add(null);
}
// Alle Widgets f�r die Personen erzeugen.
showAllPersons();
}
/**
* Zeigt alle Generationen an, indem die PersonComposite-Objekte erzeugt
* werden.
*/
private void showAllPersons() {
// Farben allokieren.
Color colorBorderCurrentPerson = OptionData.instance.getColor(OptionData.COLOR_BORDER_CURRENT_PERSON);
Color colorBorderNearPerson = OptionData.instance.getColor(OptionData.COLOR_BORDER_NEAR_PERSON);
Color colorBorderOtherPerson = OptionData.instance.getColor(OptionData.COLOR_BORDER_OTHER_PERSON);
// Erzeugt f�r alle Personen der angegebenen Liste jeweils ein Widget.
for (List<Person> personlist : listGenerationsToView) {
List<PersonView> pcList = new ArrayList<PersonView>();
listWidgetsLists.add(pcList);
for (Person person : personlist) {
PersonView pc = new PersonView(familyComposite, person);
pc.setSize(personWidth, personHeight);
// pc.setName(person.getValue(Person.NAME, "text"));
// pc.setDate(person.getShortDate());
if (person == currentMainPerson) {
pc.setBackground(colorBorderCurrentPerson);
}
else if (person.hasConnectionWith(currentMainPerson)) {
pc.setBackground(colorBorderNearPerson);
}
else {
pc.setBackground(colorBorderOtherPerson);
}
pcList.add(pc);
// Der Person das entsprechende Widget zuordnen.
int pi = listAllPersons.indexOf(person);
listAllPersonComposites.set(pi, pc);
}
}
// Farben wieder frei geben.
colorBorderCurrentPerson.dispose();
colorBorderNearPerson.dispose();
colorBorderOtherPerson.dispose();
}
/**
* F�gt den Listen alle Eltern und Kinder in den angegebenen Generationen
* hinzu.
*/
private void addFamily(int minGeneration, int maxGeneration) {
// System.out.println("addFamily-1");
// Nach unten alle Eltern durchgehen.
for (int i = 0; i > minGeneration; i--) {
List<Person> listSingleGeneration = listGenerationsToView.get(i - minGeneration);
for (int k = 0; k < listSingleGeneration.size(); k++) {
Person person = listSingleGeneration.get(k);
addToLists(listGenerationsToView.get(i - 1 - minGeneration), listAllPersons, person.getParents());
}
}
// System.out.println("addFamily-2");
// Nach oben alle Kinder durchgehen.
for (int i = 0; i < maxGeneration; i++) {
List<Person> listSingleGeneration = listGenerationsToView.get(i - minGeneration);
for (int k = 0; k < listSingleGeneration.size(); k++) {
Person person = listSingleGeneration.get(k);
addToLists(listGenerationsToView.get(i + 1 - minGeneration), listAllPersons, person.getChildren());
}
}
}
/**
* F�gt beiden angegebenen Listen die angegebenen Personen hinzu, wenn die
* Person nicht schon in der zweiten existiert. Au�erdem werden auch alle
* Partner der angegebenen Personen hinzugef�gt, falls sie noch nicht
* vorhanden sein sollten.
*/
private void addToLists(List<Person> singlePersonList, List<Person> listAllPersons, Person[] personArray) {
// System.out.println("addToLists");
for (Person person : personArray) {
addSinglePersonToLists(singlePersonList, person);
// Noch alle Partner dieser Person hinzuf�gen.
if (OptionData.instance.getBoolean(OptionData.SHOW_PARTNERS)) {
Person[] partners = person.getPartner();
for (Person partner : partners) {
addSinglePersonToLists(singlePersonList, partner);
}
}
}
}
/**
* F�gt die angegebene Person in beide Listen ein, falls noch nicht vorhanden.
*/
private void addSinglePersonToLists(List<Person> singlePersonList, Person person) {
if (!listAllPersons.contains(person)) {
// System.out.println("addSinglePersonToLists - " + person);
listAllPersons.add(person);
singlePersonList.add(person);
}
}
/**
* L�scht alle Inhalte des Modells.
* @see de.chris_soft.fyllgen.widget.FamilyModel#clear()
*/
public void clear() {
listAllPersonComposites.clear();
listAllPersons.clear();
listGenerationsToView.clear();
listWidgetsLists.clear();
}
}