/**
* 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.utilities.PersonListSort;
import de.chris_soft.fyllgen.utilities.SwtConsts;
import de.chris_soft.fyllgen.utilities.SwtUtilities;
/**
* Dialog, um zu einer zu mergenden Person eine vorhandene Person zu w�hlen oder
* eine neue Person zu erzeugen.
* @author Christian Packenius, Juli 2008.
*/
public class MergeChoiceDialog extends Dialog implements SelectionListener {
/**
* Das eigentliche Fenster-Objekt.
*/
private final Shell shell;
/**
* List-Widgets.
*/
private final List listRight;
private final List listLeft;
/**
* Push-Buttons.
*/
// TODO - Noch einen L�schen-Button, mit dem man die linke Person l�schen
// kann.
private final Button buttonCancel;
private final Button buttonNew;
private final Button buttonSet;
/**
* Liste aller in der rechten Liste dargestellter Personen.
*/
private java.util.List<Person> rightPersonList;
/**
* Feld wird auf true gesetzt, wenn der Dialog mit "�bernehmen" beendet wurde.
* In diesem Fall werden auch "newPerson" und "oldPerson" gesetzt.
*/
public boolean finished = false;
/**
* Person aus der zu �bernehmenden Familie.
*/
public Person newPerson = null;
/**
* Die gleiche Person in der schon existierenden Familie.
*/
public Person oldPerson = null;
/**
* Liste aller Personen in der linken Liste.
*/
private final java.util.List<Person> listLeftPersons = new java.util.ArrayList<Person>();
/**
* Konstruktor. Erzeugt das Fenster, ohne es anzuzeigen.
* @param parent Parent-Shell, �ber der dieser Dialog angezeigt wird.
*/
public MergeChoiceDialog(Shell parent) {
super(parent, 0);
shell = new Shell(parent, SWT.CLOSE | SWT.TITLE | SWT.APPLICATION_MODAL);
shell.setImage(GUI.instance.shellIcon);
shell.setText("Personen zuordnen");
shell.setSize(500, 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 = "Bitte weisen Sie einer einzuf�genden Person (links) eine vorhandene Person (rechts) zu";
label1text += " oder erzeugen Sie einen neuen Eintrag.";
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(3, 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);
buttonSet = new Button(compButtons, SWT.PUSH);
buttonSet.setText("�bernehmen");
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
buttonSet.setLayoutData(gd);
buttonSet.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);
listLeft = 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(50, -2);
listLeft.setLayoutData(fd);
listLeft.addSelectionListener(this);
listRight = 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(50, 3);
fd.right = new FormAttachment(100, 0);
listRight.setLayoutData(fd);
listRight.addSelectionListener(this);
// Alle "neuen" Personen in die linke Liste einordnen.
Person[] persons = Statics.mergeFamily.getPersonsArray();
for (Person person : persons) {
if (!person.isFinishedMerge()) {
listLeftPersons.add(person);
listLeft.add(person.toString());
}
}
// Widgets en-/disablen.
setWidgets();
}
/**
* Enabled oder disabled die Widgets.
*/
private void setWidgets() {
// Ist in der linken/rechten Liste etwas angew�hlt?
boolean bLeftChoice = listLeft.getSelectionIndex() >= 0;
boolean bRightChoice = listRight.getSelectionIndex() >= 0;
// Widgets en-/disablen.
listLeft.setEnabled(listLeft.getItemCount() > 0);
listRight.setEnabled(bLeftChoice);
buttonNew.setEnabled(bLeftChoice);
buttonSet.setEnabled(bRightChoice);
// Default-Button festlegen.
if (bRightChoice) {
shell.setDefaultButton(buttonSet);
}
else if (bLeftChoice) {
shell.setDefaultButton(buttonNew);
}
}
/**
* Shell sichtbar machen. Vorher aber alle Personen in die Liste einf�gen.
*/
public void open() {
shell.open();
// 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) {
widgetSelected(e);
}
/**
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
int leftSelectionIndex = listLeft.getSelectionIndex();
int rightSelectionIndex = listRight.getSelectionIndex();
if (e.widget == listLeft) {
if (leftSelectionIndex >= 0) {
// Nun in der rechten Liste die Personen nach Wahrscheinlichkeit der
// �bereinstimmung ordnen.
weightRightPersons();
listRight.deselectAll();
}
}
else if (e.widget == buttonCancel) {
shell.dispose();
return;
}
else if (e.widget == buttonSet) {
finished = true;
newPerson = listLeftPersons.get(leftSelectionIndex);
oldPerson = rightPersonList.get(rightSelectionIndex);
shell.dispose();
return;
}
else if (e.widget == buttonNew) {
Person person = Statics.mergeFamily.getPersonFromIndex(leftSelectionIndex);
Person personClone = person.clone();
person.setValue(Person.XREFID, personClone.getValue(Person.XREFID));
Family.instance.addNewPerson(personClone);
Family.instance.setCurrentPerson(personClone, 2);
shell.dispose();
return;
}
// So oder so die Widgets neu setzen.
setWidgets();
}
/**
* Alle in der Familie vorhandenen Personen zur angegebenen Person hin
* gewichten.
*/
private void weightRightPersons() {
// Alle "alten" Personen vorsortieren.
listRight.removeAll();
Person[] persons = Family.instance.getPersonsArray();
java.util.List<Person> list = new ArrayList<Person>();
for (Person person : persons) {
list.add(person);
}
PersonListSort.sort(list);
// Links angew�hlte Person holen.
Person choice = listLeftPersons.get(listLeft.getSelectionIndex());
String choiceName = " " + choice.getValueView(Person.NAME) + " ";
String lowerChoice = choiceName.toLowerCase();
// TODO - Die �hnlichsten Personen rechts nach oben schieben.
// Identische Namen nach oben.
int listsize = list.size();
for (int i = 0; i < listsize; i++) {
Person person = list.get(i);
boolean bUp = true;
String fullname = person.getValueView(Person.NAME).toLowerCase();
StringTokenizer strtok = new StringTokenizer(fullname);
while (strtok.hasMoreTokens()) {
String partname = strtok.nextToken();
bUp &= lowerChoice.indexOf(" " + partname + " ") >= 0;
}
if (bUp) {
list.add(0, list.remove(i));
}
}
// Personen in rechte Liste eintragen.
for (Person person : list) {
listRight.add(person.toString());
}
rightPersonList = list;
}
}