/**
* 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.dialog;
import java.util.ArrayList;
import java.util.StringTokenizer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import de.chris_soft.fyllgen.GUI;
import de.chris_soft.fyllgen.Statics;
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.PersonListSort;
import de.chris_soft.fyllgen.utilities.SwtConsts;
import de.chris_soft.fyllgen.utilities.SwtUtilities;
/**
* Eine Person wurde schon �bernommen. Nun gibt es eine Beziehung zu einer
* anderen Person (Kind, Elternteil, Partner), die allerdings noch nicht
* �bernommen wurde (weder die Person noch die Beziehung). Hier wird nun die
* �bernommene Person angezeigt und man kann w�hlen, welche der Personen als
* Beziehung �bernommen werden sollen. Hierf�r ben�tigt man eine Liste aller
* Personen in der aktuellen Familie, die diese Person darstellen k�nnten.
* @author Christian Packenius, Juli 2008.
*/
public class MergeChoiceRelationshipPersonDialog extends Dialog implements SelectionListener {
/**
* Das eigentliche Fenster-Objekt.
*/
private final Shell shell;
/**
* Push-Buttons.
*/
private final Button buttonNew;
private final Button buttonRemoveRelationship;
private final Button buttonRemovePerson;
private final Button buttonTakePerson;
private final Button buttonCancel;
/**
* Liste, in der die in der Familie schon vorhandenen und eventuell passenden
* Personen eingetragen sind.
*/
private final List list;
/**
* Alle Personen aus der angezeigten Liste.
*/
private final java.util.List<Person> persons = new ArrayList<Person>();
/**
* Beziehung, um die es geht.
*/
private final Relationship relationship;
/**
* Person dieser Beziehung, die schon �bernommen wurde.
*/
public Person mergedPerson;
/**
* Person dieser Beziehung, die noch nicht �bernommen wurde.
*/
public Person otherPerson;
/**
* true, sobald der User "�bernommen" angeklickt hat.
*/
public boolean finished = false;
/**
* true, sobald der User "Neu" angeklickt hat.
*/
public boolean finishedNew = false;
/**
* Die vom User gew�hlte Person (nur wenn finished==true).
*/
public Person oldPerson;
/**
* Name der "gesuchten" Person.
*/
private String otherPersonName;
/**
* Konstruktor. Erzeugt das Fenster, ohne es anzuzeigen.
* @param parent Parent-Shell, �ber der dieser Dialog angezeigt wird.
* @param relship Beziehung zu einer noch nicht �bernommenen Person.
*/
public MergeChoiceRelationshipPersonDialog(Shell parent, Relationship relship) {
super(parent, 0);
mergedPerson = relship.partner1.isFinishedMerge() ? relship.partner1 : relship.partner2;
relationship = relship;
shell = new Shell(parent, SWT.CLOSE | SWT.TITLE | SWT.APPLICATION_MODAL);
shell.setImage(GUI.instance.shellIcon);
shell.setText("Person zuordnen");
shell.setSize(650, 400);
// Noch mittig/rechts unten ins vorhandene Fenster setzen.
if (OptionData.instance.getBoolean(OptionData.MERGE_DIALOG_IN_CORNER)) {
SwtUtilities.setRightBottom(shell);
}
else {
SwtUtilities.centerInParent(shell, parent);
}
// Shell hat innen einen Rahmen.
FormLayout shellLayout = new FormLayout();
shellLayout.marginBottom = shellLayout.marginLeft = shellLayout.marginRight = shellLayout.marginTop = 5;
shell.setLayout(shellLayout);
// Innen ein Composite.
Composite inner = new Composite(shell, 0);
FormLayout innerLayout = new FormLayout();
inner.setLayout(innerLayout);
FormData fd = new FormData();
fd.top = new FormAttachment(0, 0);
fd.left = new FormAttachment(0, 0);
fd.right = new FormAttachment(100, 0);
fd.bottom = new FormAttachment(100, 0);
inner.setLayoutData(fd);
// Hinweis oben.
Label label1 = new Label(inner, SWT.WRAP);
String label1text = getLabel1Text(mergedPerson, relship);
label1.setText(label1text);
fd = new FormData();
fd.top = new FormAttachment(0, 0);
fd.left = new FormAttachment(0, 0);
fd.right = new FormAttachment(100, 0);
label1.setLayoutData(fd);
// Unten die Buttonleiste.
Composite compButtons = new Composite(inner, 0);
compButtons.setLayout(new GridLayout(5, true));
fd = new FormData();
fd.right = new FormAttachment(100, 0);
fd.bottom = new FormAttachment(100, 0);
compButtons.setLayoutData(fd);
GridData gd;
buttonNew = new Button(compButtons, SWT.PUSH);
buttonNew.setText("Neu");
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
buttonNew.setLayoutData(gd);
buttonNew.addSelectionListener(this);
buttonRemoveRelationship = new Button(compButtons, SWT.PUSH);
buttonRemoveRelationship.setText("Beziehung l�schen");
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
buttonRemoveRelationship.setLayoutData(gd);
buttonRemoveRelationship.addSelectionListener(this);
buttonRemovePerson = new Button(compButtons, SWT.PUSH);
buttonRemovePerson.setText("Person l�schen");
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
buttonRemovePerson.setLayoutData(gd);
buttonRemovePerson.addSelectionListener(this);
buttonTakePerson = new Button(compButtons, SWT.PUSH);
buttonTakePerson.setText("Person �bernehmen");
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
buttonTakePerson.setLayoutData(gd);
buttonTakePerson.addSelectionListener(this);
buttonCancel = new Button(compButtons, SWT.PUSH);
buttonCancel.setText("Abbrechen");
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
buttonCancel.setLayoutData(gd);
buttonCancel.addSelectionListener(this);
// Die Liste erh�lt den restlichen Platz.
list = new List(inner, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL);
fd = new FormData();
fd.top = new FormAttachment(label1, 5, SWT.BOTTOM);
fd.bottom = new FormAttachment(compButtons, -5, SWT.TOP);
fd.left = new FormAttachment(0, 0);
fd.right = new FormAttachment(100, 0);
list.setLayoutData(fd);
list.addSelectionListener(this);
// M�gliche Personen ermitteln.
createPersonsList(relship);
if (persons.get(0) == null) {
persons.remove(0);
}
// Personen in die Liste f�llen, eventuell schon gefundene Person
// vormarkieren.
boolean bFoundShowName = false;
for (Person p : persons) {
String showName = p == null ? "" : p.toString();
list.add(showName);
if (showName.equals(otherPersonName)) {
if (!bFoundShowName) {
bFoundShowName = true;
list.setSelection(list.getItemCount() - 1);
}
else {
list.deselectAll();
}
}
}
// Widgets en-/disablen.
setWidgets();
}
/**
* Erzeugt intern die Liste der anzuzeigenden Personen (mit Reihenfolge).
*/
private void createPersonsList(Relationship relship) {
// Erstmal schon ohnehin zugeordnete Personen in die Liste werfen.
Person originalPerson = Family.instance.getPersonFromXREFID(mergedPerson.getValue(Person.XREFID));
Relationship[] relships;
if (relship instanceof RelationshipParentChild) {
if (relship.partner1 == mergedPerson) {
relships = originalPerson.getChildRelationships();
}
else {
relships = originalPerson.getParentRelationships();
}
}
else {
relships = originalPerson.getPartnerRelationships();
}
for (Relationship relationship : relships) {
Person nextPerson = relationship.getOtherPerson(originalPerson);
addPersonToList(nextPerson);
}
// Dann alle Personen einf�gen, die eine Namensgleichheit besitzen.
String lowName = otherPersonName.toLowerCase();
Person[] originalPersons = Family.instance.getPersonsArray();
java.util.List<java.util.List<Person>> addList = new ArrayList<java.util.List<Person>>();
for (Person person : originalPersons) {
if (!persons.contains(person)) {
// Jeder passende Namensteil bringt die zu pr�fende Person weiter nach
// oben.
StringTokenizer sTok = new StringTokenizer(person.getValueView(Person.NAME).toLowerCase());
int count = 10;
while (sTok.hasMoreTokens()) {
if (lowName.indexOf(sTok.nextToken()) >= 0) {
count++;
}
}
// Identische Datumswerte (und sei es auch nur das Jahr) bringen den
// Vergleich auch weiter.
count += compareDates(person.getValueView(Person.BIRTHDAY), otherPerson.getValueView(Person.BIRTHDAY));
count += compareDates(person.getValueView(Person.DEATHDAY), otherPerson.getValueView(Person.DEATHDAY));
// Ungleiches Geschlecht bringt es weit nach hinten.
String bs1 = person.getValueView(Person.SEX);
String bs2 = otherPerson.getValueView(Person.SEX);
if (!bs1.equals(bs2) && !bs1.equals(Person.UNKNOWN) && !bs2.equals(Person.UNKNOWN)) {
count -= 5;
}
// Falls eine entsprechend "hohe" Liste noch nicht existiert, einf�gen.
while (addList.size() <= count) {
addList.add(new ArrayList<Person>());
}
// Person der korrekten Liste zuordnen.
addList.get(count).add(person);
}
}
// Je mehr Namen passen, desto weiter oben soll die Person erscheinen.
for (int i = addList.size() - 1; i >= 0; i--) {
java.util.List<Person> plist = addList.get(i);
PersonListSort.sort(plist);
addPersonToList(null);
// Bei den ganz abwegigen Personen auch eine L�cke nach oben hin lassen.
if (i == 0) {
persons.add(null);
persons.add(null);
}
// Alle gefundenen Personen in die Liste einf�gen.
for (Person person : plist) {
addPersonToList(person);
}
}
}
/**
* Vergleicht Geburts- oder Todestag zweier Personen und bewertet sie.
*/
private int compareDates(String bd1, String bd2) {
if (bd1.equals(bd2)) {
return 2;
}
int p1 = bd1.lastIndexOf('.');
int p2 = bd2.lastIndexOf('.');
if (p1 < 0 || p2 < 0) {
return 0;
}
if (bd1.substring(p1 + 1).equals(bd2.substring(p2 + 1))) {
return 1;
}
return 0;
}
private void addPersonToList(Person person) {
// Keine zwei Leerzeilen hintereinander.
if (person == null && persons.size() > 0 && persons.get(persons.size() - 1) == null) {
return;
}
// Person/Leerzeile hinzuf�gen.
persons.add(person);
}
/**
* Erzeugt den langen Hinweis oben im Fenster.
* @param mergedPerson
* @param relship
* @return Text f�r das Label.
*/
private String getLabel1Text(Person mergedPerson, Relationship relship) {
Person realMergedPerson = Family.instance.getPersonFromXREFID(mergedPerson.getXREFID());
String realMergedPersonSex = realMergedPerson.getValueView(Person.SEX);
String realMergedPersonName = realMergedPerson.toString();
otherPerson = relship.getOtherPerson(mergedPerson);
String otherPersonSex = otherPerson.getValueView(Person.SEX);
otherPersonName = otherPerson.toString();
String s;
if (relship instanceof RelationshipPartners) {
if (realMergedPersonSex.equals(Person.MALE)) {
if (otherPersonSex.equals(Person.MALE)) {
s = realMergedPersonName + " ist Partner seines im Folgenden festzulegenden Partners\r\n\r\n"
+ otherPersonName + ".";
}
else if (otherPersonSex.equals(Person.FEMALE)) {
s = realMergedPersonName + " ist Partner seiner im Folgenden festzulegenden Partnerin\r\n\r\n"
+ otherPersonName + ".";
}
else {
s = realMergedPersonName
+ " ist Partner seines/seiner im Folgenden festzulegenden Partners/Partnerin\r\n\r\n" + otherPersonName
+ ".";
}
}
else if (realMergedPersonSex.equals(Person.FEMALE)) {
if (otherPersonSex.equals(Person.MALE)) {
s = realMergedPersonName + " ist Partnerin ihres im Folgenden festzulegenden Partners\r\n\r\n"
+ otherPersonName + ".";
}
else if (otherPersonSex.equals(Person.FEMALE)) {
s = realMergedPersonName + " ist Partner ihrer im Folgenden festzulegenden Partnerin\r\n\r\n"
+ otherPersonName + ".";
}
else {
s = realMergedPersonName + " ist Partner des/der im Folgenden festzulegenden Partnern/Partnerin\r\n\r\n"
+ otherPersonName + ".";
}
}
else {
s = realMergedPersonName + " ist Partner der im Folgenden festzulegenden Person\r\n\r\n" + otherPersonName
+ ".";
}
}
else if (relship instanceof RelationshipParentChild && relship.partner1 == mergedPerson) {
if (realMergedPersonSex.equals(Person.MALE)) {
if (otherPersonSex.equals(Person.MALE)) {
s = realMergedPersonName + " ist Vater seines im Folgenden festzulegenden Sohns\r\n\r\n" + otherPersonName
+ ".";
}
else if (otherPersonSex.equals(Person.FEMALE)) {
s = realMergedPersonName + " ist Vater seiner im Folgenden festzulegenden Tochter\r\n\r\n" + otherPersonName
+ ".";
}
else {
s = realMergedPersonName + " ist Vater seines im Folgenden festzulegenden Kindes\r\n\r\n" + otherPersonName
+ ".";
}
}
else if (realMergedPersonSex.equals(Person.FEMALE)) {
if (otherPersonSex.equals(Person.MALE)) {
s = realMergedPersonName + " ist Mutter ihres im Folgenden festzulegenden Sohns\r\n\r\n" + otherPersonName
+ ".";
}
else if (otherPersonSex.equals(Person.FEMALE)) {
s = realMergedPersonName + " ist Mutter ihrer im Folgenden festzulegenden Tochter\r\n\r\n" + otherPersonName
+ ".";
}
else {
s = realMergedPersonName + " ist Mutter ihres im Folgenden festzulegenden Kindes\r\n\r\n" + otherPersonName
+ ".";
}
}
else {
if (otherPersonSex.equals(Person.MALE)) {
s = realMergedPersonName + " ist Elternteil des im Folgenden festzulegenden Sohns\r\n\r\n" + otherPersonName
+ ".";
}
else if (otherPersonSex.equals(Person.FEMALE)) {
s = realMergedPersonName + " ist Elternteil der im Folgenden festzulegenden Tochter\r\n\r\n"
+ otherPersonName + ".";
}
else {
s = realMergedPersonName + " ist Elternteil des im Folgenden festzulegenden Kindes\r\n\r\n" + otherPersonName
+ ".";
}
}
}
else {
if (realMergedPersonSex.equals(Person.MALE)) {
if (otherPersonSex.equals(Person.MALE)) {
s = realMergedPersonName + " ist Sohn seines im Folgenden festzulegenden Vaters\r\n\r\n" + otherPersonName
+ ".";
}
else if (otherPersonSex.equals(Person.FEMALE)) {
s = realMergedPersonName + " ist Sohn seiner im Folgenden festzulegenden Mutter\r\n\r\n" + otherPersonName
+ ".";
}
else {
s = realMergedPersonName + " ist Sohn seines im Folgenden festzulegenden Elternteils\r\n\r\n"
+ otherPersonName + ".";
}
}
else if (realMergedPersonSex.equals(Person.FEMALE)) {
if (otherPersonSex.equals(Person.MALE)) {
s = realMergedPersonName + " ist Tochter ihres im Folgenden festzulegenden Vaters\r\n\r\n" + otherPersonName
+ ".";
}
else if (otherPersonSex.equals(Person.FEMALE)) {
s = realMergedPersonName + " ist Tochter ihrer im Folgenden festzulegenden Mutter\r\n\r\n" + otherPersonName
+ ".";
}
else {
s = realMergedPersonName + " ist Tochter ihres im Folgenden festzulegenden Elternteils\r\n\r\n"
+ otherPersonName + ".";
}
}
else {
if (otherPersonSex.equals(Person.MALE)) {
s = realMergedPersonName + " ist Kind des im Folgenden festzulegenden Vaters\r\n\r\n" + otherPersonName + ".";
}
else if (otherPersonSex.equals(Person.FEMALE)) {
s = realMergedPersonName + " ist Kind der im Folgenden festzulegenden Mutter\r\n\r\n" + otherPersonName + ".";
}
else {
s = realMergedPersonName + " ist Kind des im Folgenden festzulegenden Elternteils\r\n\r\n" + otherPersonName
+ ".";
}
}
}
return s;
}
/**
* Enabled oder disabled die Widgets.
*/
private void setWidgets() {
boolean bListSelection = list.getSelectionIndex() >= 0 && persons.get(list.getSelectionIndex()) != null;
buttonTakePerson.setEnabled(bListSelection);
shell.setDefaultButton(bListSelection ? buttonTakePerson : buttonNew);
}
/**
* Shell sichtbar machen.
*/
public void open() {
shell.open();
list.forceFocus();
// Ereignis-Liste abarbeiten.
while (!shell.isDisposed()) {
if (!SwtConsts.display.readAndDispatch()) {
SwtConsts.display.sleep();
}
}
}
/**
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
if (e.widget == list && persons.get(list.getSelectionIndex()) != null) {
takePerson();
}
else {
widgetSelected(e);
}
}
/**
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
if (e.widget == buttonCancel) {
shell.dispose();
return;
}
if (e.widget == buttonNew) {
createNewPerson();
return;
}
if (e.widget == buttonTakePerson) {
takePerson();
return;
}
if (e.widget == buttonRemoveRelationship) {
if (SwtUtilities
.askYesNo(
shell,
"Soll die Beziehung zwischen diesen beiden Personen wirklich gel�scht werden?\r\n(Die im Stammbaum bestehenden Beziehungen bleiben hiervon unber�hrt.)",
"Beziehung l�schen?")) {
otherPerson.removeRelationship(relationship);
shell.dispose();
return;
}
}
if (e.widget == buttonRemovePerson) {
if (SwtUtilities.askYesNo(shell, "Soll die Person \"" + otherPerson.toString()
+ "\" wirklich gel�scht werden?\r\n(Die im Stammbaum bestehenden Personen bleiben hiervon unber�hrt.)",
"Person l�schen?")) {
Statics.mergeFamily.removePerson(otherPerson);
shell.dispose();
return;
}
}
setWidgets();
}
/**
* Person wird neu erzeugt.
*/
private void createNewPerson() {
finishedNew = true;
shell.dispose();
}
/**
* Person wird �bernommen.
*/
private void takePerson() {
finished = true;
oldPerson = persons.get(list.getSelectionIndex());
Family.instance.setCurrentPerson(oldPerson, 2);
shell.dispose();
}
}