/**
* 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.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Point;
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.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;
import de.chris_soft.fyllgen.GUI;
import de.chris_soft.fyllgen.data.AtomData;
import de.chris_soft.fyllgen.data.Family;
import de.chris_soft.fyllgen.data.Person;
import de.chris_soft.fyllgen.utilities.SwtUtilities;
import de.chris_soft.fyllgen.utilities.TagManagement;
/**
* Running some reports.
* @author Christian Packenius, 20110930.
*/
public class ReportCreationDialog extends Dialog implements ShellListener, SelectionListener {
/**
* Dialog window.
*/
private final Shell shell;
/**
* Zu jedem Radio-Button wird hier die �bergeordnete Checkbox gespeichert.
*/
private Map<Button, Button> radio2check = new HashMap<Button, Button>();
/**
* Zu jeder Checkbox wird hier die Liste der Radio-Buttons gespeichert.
*/
private Map<Button, List<Button>> check2radiolist = new HashMap<Button, List<Button>>();
/**
* Liste aller Checkboxen in der angezeigten Reihenfolge.
*/
private List<Button> checklist = new ArrayList<Button>();
/**
* Der OK-Button.
*/
private final Button ok;
/**
* Der Radio-Button f�r "AND"-Verkn�pfungen.
*/
private final Button radioAND;
/**
* Der Radio-Button f�r "OR"-Verkn�pfungen.
*/
private final Button radioOR;
/**
* Constructor.
* @param parent The parent shell for this dialog.
*/
public ReportCreationDialog(Shell parent) {
super(parent, 0);
// Fenster administrieren.
shell = new Shell(parent, SWT.CLOSE | SWT.TITLE | SWT.APPLICATION_MODAL);
shell.setImage(GUI.instance.shellIcon);
shell.addShellListener(this);
shell.setText("Reports erstellen");
shell.setSize(500, 300);
shell.setLayout(new FormLayout());
FormData fd;
Composite compRadios = new Composite(shell, 0);
compRadios.setLayout(new GridLayout(1, false));
fd = new FormData();
fd.bottom = new FormAttachment(100, 0);
fd.left = new FormAttachment(0, 0);
compRadios.setLayoutData(fd);
radioAND = new Button(compRadios, SWT.RADIO);
radioAND.setText("alles zutreffend");
radioAND.setSelection(true);
radioAND.setLayoutData(new GridData(SWT.BEGINNING, 0, true, false));
radioOR = new Button(compRadios, SWT.RADIO);
radioOR.setText("mindestens eines zutreffend");
radioOR.setSelection(false);
radioOR.setLayoutData(new GridData(SWT.BEGINNING, 0, true, false));
ok = new Button(shell, SWT.PUSH);
ok.setText("Exportieren...");
ok.addSelectionListener(this);
fd = new FormData();
fd.bottom = new FormAttachment(100, 0);
fd.left = new FormAttachment(compRadios, 5, SWT.RIGHT);
fd.top = new FormAttachment(compRadios, 5, SWT.TOP);
fd.right = new FormAttachment(100, 0);
ok.setLayoutData(fd);
// Scroll-Bereich erzeugen.
ScrolledComposite scroller = new ScrolledComposite(shell, SWT.V_SCROLL | SWT.H_SCROLL);
fd = new FormData();
fd.left = fd.top = new FormAttachment(0, 0);
fd.right = new FormAttachment(100, 0);
fd.bottom = new FormAttachment(compRadios, -5, SWT.TOP);
scroller.setLayoutData(fd);
// Scrollbereich mit Leben f�llen.
createScrollContent(scroller);
// Noch mittig ins vorhandene Fenster setzen.
SwtUtilities.centerInParent(shell, parent);
}
/**
* F�llt den Scrollbereich mit Leben.
*/
private void createScrollContent(ScrolledComposite scroller) {
Composite comp = new Composite(scroller, 0);
scroller.setContent(comp);
comp.setLayout(new GridLayout(1, false));
// Alle Personendaten ins Fenster einf�gen.
addPersonFields(comp);
// Alle Markierungen ins Fenster einf�gen.
addTags(comp);
// Composite im Scroller auf die korrekte Gr��e bringen.
resize(comp, scroller);
}
/**
* Komponente in Ihrer Gr��e anpassen, aber die Breite maximieren.
*/
private void resize(Composite comp, ScrolledComposite scroller) {
Point size = comp.computeSize(SWT.DEFAULT, SWT.DEFAULT);
size.x = Math.max(size.x, scroller.getClientArea().width);
comp.setSize(size);
}
/**
* Alle Tags auflisten.
*/
private void addTags(Composite comp) {
for (String tag : TagManagement.instance.getTagList()) {
Button checkbox = new Button(comp, SWT.CHECK);
checkbox.setText("Markierung: " + tag);
checklist.add(checkbox);
addLineGrid(comp, checkbox, new String[] { "gesetzt", "nicht gesetzt" });
}
}
/**
* Alle Personenfelder auflisten.
*/
private void addPersonFields(Composite comp) {
for (AtomData ad : Person.atomData) {
String title = ad.title;
title = title.trim();
if (title.endsWith(":")) {
title = title.substring(0, title.length() - 1);
}
Button checkbox = new Button(comp, SWT.CHECK);
checkbox.setText("Feld: " + title);
checkbox.addSelectionListener(this);
checklist.add(checkbox);
if (ad.type.equals("text")) {
addLineGrid(comp, checkbox, new String[] { "mit Inhalt", "ohne Inhalt" });
}
else if (ad.type.equals("option")) {
addLineGrid(comp, checkbox, new String[] { "gesetzt", "nicht gesetzt" });
}
else if (ad.type.equals("date")) {
addLineGrid(comp, checkbox, new String[] { "vollst�ndig", "leer", "teilweise gef�llt" });
}
else {
throw new RuntimeException("Typ " + ad.type + " nicht beachtet!");
}
}
}
/**
* F�gt eine Zeile mit Entscheidungen ein.
*/
private void addLineGrid(Composite comp, Button checkbox, String[] choices) {
List<Button> radios = new ArrayList<Button>();
Composite decision = new Composite(comp, 0);
decision.setLayout(new GridLayout(choices.length + 1, false));
Label empty = new Label(decision, 0);
empty.setText(" ");
for (String choice : choices) {
Button radio = new Button(decision, SWT.RADIO);
radio.addSelectionListener(this);
radio.setText(choice);
radios.add(radio);
radio2check.put(radio, checkbox);
}
check2radiolist.put(checkbox, radios);
}
/**
* Open this dialog.
*/
public void open() {
shell.open();
// Ereignis-Liste abarbeiten.
eventQueue();
}
/**
* SWT event queue.
*/
private void eventQueue() {
Display display = Display.getDefault();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellActivated(ShellEvent e) {
// Ignorieren.
}
/**
* @see org.eclipse.swt.events.ShellListener#shellClosed(org.eclipse.swt.events.ShellEvent)
*/
public void shellClosed(ShellEvent e) {
// Ignorieren.
}
/**
* @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeactivated(ShellEvent e) {
// Ignorieren.
}
/**
* @see org.eclipse.swt.events.ShellListener#shellDeiconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeiconified(ShellEvent e) {
// Ignorieren.
}
/**
* @see org.eclipse.swt.events.ShellListener#shellIconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellIconified(ShellEvent e) {
// Ignorieren.
}
/**
* @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) {
Widget widget = e.widget;
List<Button> radiolist = check2radiolist.get(widget);
Button checkbox = radio2check.get(widget);
if (radiolist != null) {
Button check = (Button) widget;
if (check.getSelection()) {
radiolist.get(0).setSelection(true);
}
else {
for (Button radio : radiolist) {
radio.setSelection(false);
}
}
}
else if (checkbox != null) {
Button radio = (Button) e.widget;
if (radio.getSelection()) {
checkbox.setSelection(true);
}
}
else if (widget.equals(ok)) {
List<Person> persons = getPersonList();
if (persons.size() == 0) {
SwtUtilities.sayInfo(shell, "Die mit diesen Merkmalen erzeugte Personenliste ist leer.");
}
else {
ReportChoiceDialog reportChoiceDialog = new ReportChoiceDialog(shell, persons);
reportChoiceDialog.open();
}
}
}
/**
* Personenliste erzeugen.
*/
private List<Person> getPersonList() {
List<Person> list = null;
boolean andSelected = radioAND.getSelection();
if (andSelected) {
list = Family.instance.getPersonsList();
}
else {
list = new ArrayList<Person>();
}
Set<Person> listDels = new HashSet<Person>();
Set<Person> listAdds = new HashSet<Person>();
// Schleife �ber alle Felder.
for (int i = 0; i < Person.atomData.length; i++) {
AtomData ad = Person.atomData[i];
Button checkbox = checklist.get(i);
// Nur Regeln pr�fen, die auch angehakt wurden.
if (checkbox.getSelection()) {
// Alle zu pr�fenden Personen bestimmen.
List<Person> list2check = andSelected ? list : Family.instance.getPersonsList();
int listSize = list2check.size();
// Alle zu pr�fenden Personen durchgehen.
for (int j = 0; j < listSize; j++) {
Person p2 = list2check.get(j);
fillAddDelLists(listDels, listAdds, ad, checkbox, p2);
}
if (andSelected) {
list.removeAll(listDels);
}
else {
list.addAll(listAdds);
}
}
}
return list;
}
private void fillAddDelLists(Set<Person> listDels, Set<Person> listAdds, AtomData ad, Button checkbox, Person p2) {
String value = p2.getValueView(ad.name);
// Text?
List<Button> radiolistFromCheckbox = check2radiolist.get(checkbox);
Button radio1 = radiolistFromCheckbox.get(1);
boolean radio1selection = radio1.getSelection();
if (ad.type.equals("text")) {
// Wie gefordert.
if (radio1selection == value.equals("")) {
listAdds.add(p2);
}
// Wie nicht gefordert.
else {
listDels.add(p2);
}
}
// Option?
else if (ad.type.equals("option")) {
// Wie gefordert.
if (radio1selection == value.equals("?")) {
listAdds.add(p2);
}
// Wie nicht gefordert.
else {
listDels.add(p2);
}
}
// Datum?
else if (ad.type.equals("date")) {
// Wie gefordert.
Button radio0 = radiolistFromCheckbox.get(0);
Button radio2 = radiolistFromCheckbox.get(2);
boolean radio0selection = radio0.getSelection();
boolean radio2selection = radio2.getSelection();
if (
// Alles gesetzt?
radio0selection && !value.contains("?") ||
// Alles leer?
radio1selection && value.equals("?.?.?") ||
// Teilweise gef�llt?
radio2selection && !value.equals("?.?.?") && value.contains("?")) {
listAdds.add(p2);
}
// Wie nicht gefordert.
else {
listDels.add(p2);
}
}
// Programmierfehler.
else {
throw new RuntimeException("Typ vergessen?!");
}
}
}