package semorg.gui;

import java.sql.SQLException;
import java.sql.Timestamp;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;

import semorg.gui.list.CompanyInternalPresentationListWindow;
import semorg.gui.util.AssociationTabControl;
import semorg.gui.util.CalendarControl;
import semorg.gui.util.ForeignKeyConstraintSelector;
import semorg.gui.util.ItemListener;
import semorg.gui.util.Messages;
import semorg.gui.util.TimeControl;
import semorg.gui.util.CalendarControl.SWTCalendarEvent;
import semorg.gui.util.CalendarControl.SWTCalendarListener;
import semorg.gui.util.TimeControl.TimeChangeListener;
import semorg.sql.tables.AbstractTable;
import semorg.sql.tables.Client;
import semorg.sql.tables.Company;
import semorg.sql.tables.CompanyBooking;
import semorg.sql.tables.CompanyInternalPresentation;
import semorg.sql.tables.Enumeration;
import semorg.sql.tables.SeminarType;
import semorg.sql.tables.SimpleIDKey;
import semorg.sql.util.Utility;

/** The window for editing new or existing company internal presentation records. */
public class CompanyInternalPresentationWindow {

    /**
     * Inner class which provides a listener reacting on changes of the input in
     * the {@link CompanyInternalPresentationWindow}.
     */
    class InputChangedListener implements ModifyListener, SelectionListener,
	    SWTCalendarListener, TimeChangeListener, ItemListener {

	/**
	 * Appends to the title of the window an asterisk (*) if the input has
	 * changed. Furthermore it sets the flag {@link #inputChanged} to
	 * <tt>true</tt>.
	 */
	private void inputChanged() {
	    if (!settingInput && !inputChanged) {
		inputChanged = true;
		shell.setText(shell.getText() + "*");
	    }
	}

	/** Invokes {@link #inputChanged()} if a text has been changed. */
	public void modifyText(ModifyEvent e) {
	    inputChanged();
	}

	/** Invokes {@link #inputChanged()} if a widget has been selected. */
	public void widgetSelected(SelectionEvent e) {
	    inputChanged();
	}

	/** Invokes {@link #inputChanged()} if a doubleclick has occurred. */
	public void widgetDefaultSelected(SelectionEvent e) {
	    inputChanged();
	}

	/** Invokes {@link #inputChanged()} if a date has been changed. */
	public void dateChanged(SWTCalendarEvent event) {
	    inputChanged();
	}

	/** Invokes {@link #inputChanged()} if a time has been changed. */
	public void timeChanged() {
	    inputChanged();
	}

	/**
	 * Invokes {@link #inputChanged()} if a item in the
	 * {@link AssociationTabControl} has changed.
	 */
	public void itemChanged() {
	    inputChanged();
	}
    }

    /**
     * Holds the data of the actual displayed {@link CompanyBookingWindow}
     * record. If a new record is entered it is set to <tt>null</tt> until the
     * changes have been committed.
     */
    private CompanyInternalPresentation input;

    /**
     * Is set to <tt>true</tt> if the data from the database (or corresponding
     * from {@link #input}) is to be set into the window form, otherwise
     * <tt>false</tt>. <br>
     * <br>
     * That is needed to prevent the ModifyListener from firing when the data is
     * load into the window form by using the .setText() methods of the gui
     * elements.
     */
    private boolean settingInput = false;

    /**
     * Is set to <tt>true</tt> if the input has been changed and not committed
     * yet, otherwise it is set to <tt>false</tt>.
     */
    private boolean inputChanged;

    /**
     * <tt>true</tt> if the editing of the input (i.e. the elements of the
     * form) has been enabled, otherwise it is <tt>false</tt>. <br>
     * <br>
     * This flag indicates whether the actual displayed record has been locked
     * by the actual editing window or not. This avoids the releasing of records
     * which are locked by other editing windows.
     */
    private boolean inputEditingEnabled;

    /** Listener instance added to the most elements of the window. */
    private InputChangedListener inputChangedListener = new InputChangedListener();

    /* ********** GUI PROPERTIES ********* */
    /** The editing window. */
    private Shell shell;

    /** The height of the title bar. */
    private int titleBarHeight;

    /* Text- and Combofields, CalendarControls and Buttons */
    private final Label numberLabel;
    private final Text numberText;
    private final Text durationText;
    private final CalendarControl beginningDayCalendar;
    private final CalendarControl endingDayCalendar;
    private final TimeControl startingTimeSpinner;
    private final TimeControl endingTimeSpinner;
    private final TimeControl firstStartingTimeSpinner;
    private final TimeControl lastEndingTimeSpinner;
    private final Text locationText;
    private final Text streetText;
    private final Text zipCodeText;
    private final Text cityText;
    private final Combo countryCombo;
    private final Combo annexCombo;
    private final Button cancelChecker;

    /**
     * The control widget to manage the mandatory association between
     * presentation and seminartype.
     */
    private final ForeignKeyConstraintSelector semTypeSelector;
    private final Text packagePriceText;
    private final Text minSemTypeEntrantsText;
    private final Text maxSemTypeEntrantsText;
    private Text maxEntrantsText;

    /** The control widget to manage the association supervisor. */
    private AssociationTabControl supervisorControl;

    /** The control widget to manage the association instructor. */
    private AssociationTabControl instructorControl;

    /**
     * The control widget to manage the association between
     * {@link CompanyInternalPresentation} and {@link CompanyBooking}.
     */
    private AssociationTabControl bookingControl;

    private final Button okButton;
    private final Button applyButton;
    private final Button newButton;
    private final Button abortButton;
    private final Button prevButton;
    private final Button nextButton;

    /** The button for getting the the list of participants (not implemented). */
    private final Button listOfParticipantsButton;

    /** The button to create the certificates (not implemented). */
    private final Button certificateButton;

    /** The button to create fee messages (not implemented). */
    private final Button feeMessageButton;

    /** The button to cancel a presentation (not implemented). */
    private final Button cancelationButton;

    /**
     * Creates a {@link CompanyInternalPresentationWindow} instance with the
     * given shell as the parent shell. <br>
     * <br>
     * It also adds a listener which reacts on closing events. It checks if
     * changes have been made and if so it opens a dialog which informs the user
     * and asks for a decision (confirm/discard). Finally it releases the locked
     * record (if one is displayed and it is locked by this editing window).
     * 
     * @param parent
     *                Shell instance used the as parent shell of the
     *                {@link CompanyInternalPresentationWindow}
     */
    private CompanyInternalPresentationWindow(Shell parent) {

	shell = new Shell(parent, SWT.CLOSE);

	shell.addListener(SWT.Close, new Listener() {
	    public void handleEvent(Event event) {
		if (inputChanged) {
		    if (confirmClose()) {
			if (inputEditingEnabled && input != null)
			    CompanyInternalPresentation.lockedIds
				    .remove(new Integer(input.getId()));
		    } else
			event.doit = false;
		} else if (input != null && inputEditingEnabled)
		    CompanyInternalPresentation.lockedIds.remove(new Integer(
			    input.getId()));
	    }
	});

	shell.setLayout(new GridLayout(1, false));
	shell.setSize(865, 505);
	shell.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"CompanyInternalPresentationWindow");

	GridData mgd = new GridData();
	mgd.horizontalAlignment = GridData.FILL;
	mgd.verticalAlignment = GridData.FILL;
	mgd.grabExcessHorizontalSpace = true;
	mgd.grabExcessVerticalSpace = true;

	final Group mainForm = new Group(shell, SWT.NULL);
	mainForm.setLayoutData(mgd);
	mainForm.setLayout(new GridLayout(2, false));

	final TabFolder tabs = new TabFolder(shell, SWT.FLAT);
	tabs.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "Tabs");
	GridData tgd = new GridData();
	tgd.heightHint = 130;
	tgd.horizontalAlignment = GridData.FILL;
	tgd.grabExcessHorizontalSpace = true;
	tabs.setLayoutData(tgd);

	final Composite leftColumn = new Composite(mainForm, SWT.NULL);
	leftColumn.setLayout(new GridLayout(1, false));
	GridData lcgd = new GridData();
	lcgd.horizontalAlignment = GridData.FILL;
	lcgd.grabExcessHorizontalSpace = true;
	lcgd.verticalAlignment = GridData.BEGINNING;
	leftColumn.setLayoutData(lcgd);

	final Composite rightColumn = new Composite(mainForm, SWT.NULL);
	rightColumn.setLayout(new GridLayout(1, false));
	GridData rightColumnGridData = new GridData();
	rightColumnGridData.horizontalAlignment = GridData.FILL;
	rightColumnGridData.grabExcessHorizontalSpace = true;
	rightColumnGridData.verticalAlignment = GridData.BEGINNING;
	rightColumn.setLayoutData(rightColumnGridData);

	final Composite timesComposite = new Composite(leftColumn, SWT.NULL);
	timesComposite.setLayout(new GridLayout(4, false));

	numberLabel = new Label(timesComposite, SWT.READ_ONLY);
	numberLabel.setText(Messages
		.getString("GUIText.PresentationNumberText"));

	numberText = new Text(timesComposite, SWT.SINGLE | SWT.BORDER
		| SWT.READ_ONLY);
	numberText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "NumberText");
	Utility.setLength(numberText, 10);
	numberText.addModifyListener(inputChangedListener);
	numberText.setToolTipText(Messages.getString("GUIText.NumberToolTip"));

	final Label durationLabel = new Label(timesComposite, SWT.READ_ONLY);
	durationLabel.setText(Messages.getString("GUIText.DurationText"));

	durationText = new Text(timesComposite, SWT.SINGLE | SWT.BORDER);
	durationText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "DurationText");
	Utility.setLength(durationText, 8);
	durationText.addModifyListener(inputChangedListener);
	durationText.addFocusListener(Utility.checkCorrectIntListener);
	durationText.setToolTipText(Messages
		.getString("GUIText.DurationToolTip"));

	final Label beginningDayLabel = new Label(timesComposite, SWT.READ_ONLY);
	beginningDayLabel.setText(Messages
		.getString("GUIText.BeginningDayText"));

	beginningDayCalendar = new CalendarControl(timesComposite,
		titleBarHeight);
	beginningDayCalendar.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"BeginningDayCalendar");
	beginningDayCalendar.addSWTCalendarlistener(inputChangedListener);
	beginningDayCalendar.setToolTipText(Messages
		.getString("GUIText.BeginningDayToolTip"));

	final Label endingDayLabel = new Label(timesComposite, SWT.READ_ONLY);
	endingDayLabel.setText(Messages.getString("GUIText.EndingDayText"));

	endingDayCalendar = new CalendarControl(timesComposite, titleBarHeight);
	endingDayCalendar.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"EndingDayCalendar");
	endingDayCalendar.addSWTCalendarlistener(inputChangedListener);
	endingDayCalendar.setToolTipText(Messages
		.getString("GUIText.EndingDayToolTip"));

	final Label startingTimeLabel = new Label(timesComposite, SWT.READ_ONLY);
	startingTimeLabel.setText(Messages
		.getString("GUIText.StartingTimeText"));

	startingTimeSpinner = new TimeControl(timesComposite);
	startingTimeSpinner.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"StartingTimeSpinner");
	startingTimeSpinner.addTimeChangeListener(inputChangedListener);
	startingTimeSpinner.setToolTipText(Messages
		.getString("GUIText.StartingTimeToolTip"));

	final Label endingTimeLabel = new Label(timesComposite, SWT.READ_ONLY);
	endingTimeLabel.setText(Messages.getString("GUIText.EndingTimeText"));

	endingTimeSpinner = new TimeControl(timesComposite);
	endingTimeSpinner.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"EndingTimeSpinner");
	endingTimeSpinner.addTimeChangeListener(inputChangedListener);
	endingTimeSpinner.setToolTipText(Messages
		.getString("GUIText.EndingTimeToolTip"));

	final Label firstStartingTimeLabel = new Label(timesComposite,
		SWT.READ_ONLY);
	firstStartingTimeLabel.setText(Messages
		.getString("GUIText.FirstDayStartingTimeText"));

	firstStartingTimeSpinner = new TimeControl(timesComposite);
	firstStartingTimeSpinner.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"FirstStartingTimeSpinner");
	firstStartingTimeSpinner.addTimeChangeListener(inputChangedListener);
	firstStartingTimeSpinner.setToolTipText(Messages
		.getString("GUIText.FirstDayStartingTimeToolTip"));

	final Label lastEndingTimeLabel = new Label(timesComposite,
		SWT.READ_ONLY);
	lastEndingTimeLabel.setText(Messages
		.getString("GUIText.LastDayEndingTimeText"));

	lastEndingTimeSpinner = new TimeControl(timesComposite);
	lastEndingTimeSpinner.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"LastEndingTimeSpinner");
	lastEndingTimeSpinner.addTimeChangeListener(inputChangedListener);
	lastEndingTimeSpinner.setToolTipText(Messages
		.getString("GUIText.LastDayEndingTimeToolTip"));

	final Label locationLabel = new Label(timesComposite, SWT.READ_ONLY);
	locationLabel.setText(Messages.getString("GUIText.LocationText"));

	locationText = new Text(timesComposite, SWT.SINGLE | SWT.BORDER);
	locationText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "LocationText");
	locationText.addModifyListener(inputChangedListener);
	GridData locGrid = new GridData();
	locGrid.horizontalSpan = 3;
	locationText.setLayoutData(locGrid);
	Utility.setLength(locationText, 50);
	locationText.setToolTipText(Messages
		.getString("GUIText.LocationToolTip"));

	final Group addressField = new Group(leftColumn, SWT.NULL);
	addressField.setText(Messages
		.getString("GUIText.PresentationAddressFieldText"));
	addressField.setLayout(new GridLayout(2, false));
	GridData addressFieldGridData = new GridData();
	addressFieldGridData.horizontalAlignment = GridData.FILL;
	addressFieldGridData.grabExcessHorizontalSpace = true;
	addressField.setLayoutData(addressFieldGridData);

	final Label streetLabel = new Label(addressField, SWT.READ_ONLY);
	streetLabel.setText(Messages.getString("GUIText.StreetText"));
	Utility.alignRight(streetLabel);

	streetText = new Text(addressField, SWT.SINGLE | SWT.BORDER);
	streetText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "StreetText");
	Utility.setLength(streetText, 50);
	streetText.setToolTipText(Messages.getString("GUIText.StreetToolTip"));
	streetText.addModifyListener(inputChangedListener);

	final Label cityLabel = new Label(addressField, SWT.READ_ONLY);
	cityLabel.setText(Messages.getString("GUIText.CityZipCodeText"));
	Utility.alignRight(cityLabel);

	Composite cityRowCompletion = new Composite(addressField, SWT.NULL);

	GridLayout rcgl = new GridLayout(3, false);
	rcgl.marginWidth = 0;
	rcgl.marginHeight = 0;
	cityRowCompletion.setLayout(rcgl);

	zipCodeText = new Text(cityRowCompletion, SWT.SINGLE | SWT.BORDER);
	zipCodeText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "ZipCodeText");
	Utility.setLength(zipCodeText, 5);
	zipCodeText
		.setToolTipText(Messages.getString("GUIText.ZipCodeToolTip"));
	zipCodeText.addModifyListener(inputChangedListener);

	cityText = new Text(cityRowCompletion, SWT.SINGLE | SWT.BORDER);
	cityText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CityText");
	Utility.setLength(cityText, 30);
	cityText.setToolTipText(Messages.getString("GUIText.CityToolTip"));
	cityText.addModifyListener(inputChangedListener);

	final Label countryLabel = new Label(addressField, SWT.READ_ONLY);
	countryLabel.setText(Messages.getString("GUIText.CountryText"));
	Utility.alignRight(countryLabel);

	Composite countryRowCompletion = new Composite(addressField, SWT.NULL);
	countryRowCompletion.setLayout(rcgl);

	countryCombo = new Combo(countryRowCompletion, SWT.DROP_DOWN
		| SWT.BORDER);
	countryCombo.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CountryCombo");
	Enumeration.addCountryEnums(countryCombo);
	Utility.setLength(countryCombo, 13);
	countryCombo.addModifyListener(inputChangedListener);
	countryCombo.setToolTipText(Messages
		.getString("GUIText.CountryToolTip"));

	final Label annexLabel = new Label(countryRowCompletion, SWT.READ_ONLY);
	annexLabel.setText(Messages.getString("GUIText.AnnexText"));

	annexCombo = new Combo(countryRowCompletion, SWT.DROP_DOWN | SWT.BORDER);
	annexCombo.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "AnnexCombo");
	Enumeration.addAnnexEnums(annexCombo);
	Utility.setLength(annexCombo, 13);
	annexCombo.setToolTipText(Messages.getString("GUIText.AnnexToolTip"));
	annexCombo.addModifyListener(inputChangedListener);

	Composite additionalComponents = new Composite(rightColumn, SWT.NULL);
	additionalComponents.setLayout(new GridLayout(2, false));
	GridData additionalComponentsGridData = new GridData(
		GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
	additionalComponentsGridData.grabExcessHorizontalSpace = true;
	additionalComponents.setLayoutData(additionalComponentsGridData);

	Group seminarTypeGroup = new Group(additionalComponents, SWT.NULL);
	GridData seminarTypeGroupGridData = new GridData(
		GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
	seminarTypeGroupGridData.grabExcessHorizontalSpace = true;
	seminarTypeGroupGridData.horizontalSpan = 2;
	seminarTypeGroup.setLayoutData(seminarTypeGroupGridData);
	seminarTypeGroup.setLayout(new GridLayout(2, false));
	seminarTypeGroup.setText(Messages
		.getString("GUIText.PresentationSeminarTypeText"));

	final Label seminarTypeLabel = new Label(seminarTypeGroup,
		SWT.READ_ONLY);
	GridData seminarTypeLabelGridData = new GridData();
	seminarTypeLabelGridData.widthHint = 100;
	seminarTypeLabel.setLayoutData(seminarTypeLabelGridData);
	seminarTypeLabel.setText(Messages
		.getString("GUIText.PresentationSeminarTypeText"));
	seminarTypeLabel.setAlignment(SWT.RIGHT);

	semTypeSelector = new ForeignKeyConstraintSelector(seminarTypeGroup,
		ForeignKeyConstraintSelector.FK_SEMINARTYPE);
	semTypeSelector.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"SemTypeSelector");
	semTypeSelector.addModifyListener(inputChangedListener);

	final Label minSemTypeEntrantsLabel = new Label(seminarTypeGroup,
		SWT.READ_ONLY);
	minSemTypeEntrantsLabel.setText(Messages
		.getString("GUIText.MinEntrantsText"));
	Utility.alignRight(minSemTypeEntrantsLabel);

	minSemTypeEntrantsText = new Text(seminarTypeGroup, SWT.BORDER);
	Utility.setLength(minSemTypeEntrantsText, 5);
	minSemTypeEntrantsText.setEnabled(false);
	minSemTypeEntrantsText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"MinSemTypeEntrantsText");

	final Label maxSemTypeEntrantsLabel = new Label(seminarTypeGroup,
		SWT.READ_ONLY);
	maxSemTypeEntrantsLabel.setText(Messages
		.getString("GUIText.MaxEntrantsText"));
	Utility.alignRight(maxSemTypeEntrantsLabel);

	maxSemTypeEntrantsText = new Text(seminarTypeGroup, SWT.BORDER);
	Utility.setLength(maxSemTypeEntrantsText, 5);
	maxSemTypeEntrantsText.setEnabled(false);
	maxSemTypeEntrantsText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"MaxSemTypeEntrantsText");

	final Label cancelLabel = new Label(additionalComponents, SWT.READ_ONLY);
	cancelLabel.setText(Messages.getString("GUIText.CancelText"));

	cancelChecker = new Button(additionalComponents, SWT.CHECK);
	cancelChecker
		.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CancelChecker");
	cancelChecker.addSelectionListener(inputChangedListener);
	cancelChecker.setToolTipText(Messages
		.getString("GUIText.CancelToolTip"));

	final Label packagePriceLabel = new Label(additionalComponents,
		SWT.READ_ONLY);
	packagePriceLabel.setText(Messages
		.getString("GUIText.PackagePrizeText"));

	packagePriceText = new Text(additionalComponents, SWT.SINGLE
		| SWT.BORDER);
	packagePriceText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"PackagePriceText");
	Utility.setLength(packagePriceText, 10);
	packagePriceText.addModifyListener(inputChangedListener);
	packagePriceText.addFocusListener(Utility.checkCorrectFloatListener);
	packagePriceText.setToolTipText(Messages
		.getString("GUIText.PackagePrizeToolTip"));

	final Label maxEntrantsLabel = new Label(additionalComponents,
		SWT.READ_ONLY);
	maxEntrantsLabel
		.setText(Messages
			.getString("GUIText.CompanyInternalPresentationMaxEntrantsText"));
	Utility.alignRight(maxSemTypeEntrantsLabel);

	maxEntrantsText = new Text(additionalComponents, SWT.BORDER);
	Utility.setLength(maxEntrantsText, 10);
	maxEntrantsText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"MaxEntrantsText");
	maxEntrantsText.addFocusListener(Utility.checkCorrectIntListener);
	maxEntrantsText
		.setToolTipText(Messages
			.getString("GUIText.CompanyInternalPresentationMaxEntrantsToolTip"));

	TabItem supervisorItem = new TabItem(tabs, SWT.NULL);
	supervisorItem.setText(Messages.getString("GUIText.SupervisorText"));
	supervisorControl = new AssociationTabControl(tabs,
		AssociationTabControl.TYPE_LECTURER_SUPERVISOR, shell);
	supervisorControl.addItemListener(inputChangedListener);
	supervisorControl.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"SupervisorControl");
	supervisorItem.setControl(supervisorControl);

	TabItem instructorItem = new TabItem(tabs, SWT.NULL);
	instructorItem.setText(Messages.getString("GUIText.InstructorText"));
	instructorControl = new AssociationTabControl(tabs,
		AssociationTabControl.TYPE_LECTURER_INSTRUCTOR, shell);
	instructorControl.addItemListener(inputChangedListener);
	instructorControl.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"InstructorControl");
	instructorItem.setControl(instructorControl);

	TabItem bookingItem = new TabItem(tabs, SWT.NULL);
	bookingItem.setText(Messages.getString("GUIText.CompanyBookingText"));
	bookingControl = new AssociationTabControl(tabs,
		AssociationTabControl.TYPE_COMPANYBOOKING_PRESENTATION, shell);
	bookingControl.addItemListener(inputChangedListener);
	bookingControl.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"BookingControl");
	bookingItem.setControl(bookingControl);

	final Composite buttons = new Composite(shell, shell.getStyle());
	buttons.setLayout(new GridLayout(11, false));

	okButton = new Button(buttons, SWT.PUSH);
	okButton.setText(Messages.getString("GUIText.OkButtonText"));
	okButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
		| GridData.GRAB_VERTICAL));

	applyButton = new Button(buttons, SWT.PUSH);
	applyButton.setText(Messages.getString("GUIText.ApplyButtonText"));
	applyButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
		| GridData.GRAB_VERTICAL));

	newButton = new Button(buttons, SWT.PUSH);
	newButton.setText(Messages.getString("GUIText.NewButtonText"));
	newButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
		| GridData.GRAB_VERTICAL));

	abortButton = new Button(buttons, SWT.PUSH);
	abortButton.setText(Messages.getString("GUIText.AbortButtonText"));
	abortButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
		| GridData.GRAB_VERTICAL));

	GridData arrowButtonGridData = new GridData();
	arrowButtonGridData.verticalAlignment = GridData.FILL;
	arrowButtonGridData.grabExcessVerticalSpace = true;
	arrowButtonGridData.widthHint = 23;

	prevButton = new Button(buttons, SWT.ARROW | SWT.LEFT);
	prevButton.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "Previous");
	prevButton.setLayoutData(arrowButtonGridData);

	nextButton = new Button(buttons, SWT.ARROW | SWT.RIGHT);
	nextButton.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "Next");
	nextButton.setLayoutData(arrowButtonGridData);

	/*
	 * This button is just for seperating the control buttons from the
	 * following buttons.
	 */
	Button padding = new Button(buttons, SWT.ARROW | SWT.RIGHT);
	padding.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
		| GridData.GRAB_HORIZONTAL));
	padding.setVisible(false);

	listOfParticipantsButton = new Button(buttons, SWT.PUSH);
	listOfParticipantsButton.setText(Messages
		.getString("GUIText.ListOfParticipantsButtonText"));
	listOfParticipantsButton.setLayoutData(new GridData(
		GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));

	certificateButton = new Button(buttons, SWT.PUSH);
	certificateButton.setText(Messages
		.getString("GUIText.CertificatesButtonText"));
	certificateButton.setLayoutData(new GridData(
		GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));

	feeMessageButton = new Button(buttons, SWT.PUSH);
	feeMessageButton.setText(Messages
		.getString("GUIText.FeeMessageButtonText"));
	feeMessageButton.setLayoutData(new GridData(
		GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));

	cancelationButton = new Button(buttons, SWT.PUSH);
	cancelationButton.setText(Messages
		.getString("GUIText.CancelationButtonText"));
	cancelationButton.setLayoutData(new GridData(
		GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));

    }

    /**
     * Creates an instance of this class, sets the input and finally opens it.
     * 
     * @param parent
     *                the parent shell to which this window belongs
     * @param input
     *                the data object to be displayed in the window
     * @param caller
     *                the {@link AssociationTabControl} instance which calls the
     *                constructor.
     */
    public CompanyInternalPresentationWindow(Shell parent,
	    CompanyInternalPresentation input,
	    final AssociationTabControl caller) {
	this(parent);

	createButtonListener(caller);
	setInput(input);

	shell.open();
    }

    /**
     * Creates an instance of this class, sets the input and finally opens it.
     * 
     * @param parent
     *                the parent shell to which this window belongs
     * @param input
     *                the data object to be displayed in the window
     * @param caller
     *                the {@link ForeignKeyConstraintSelector} instance which
     *                calls the constructor.
     */
    public CompanyInternalPresentationWindow(Shell parent,
	    CompanyInternalPresentation input,
	    final ForeignKeyConstraintSelector caller) {
	this(parent);

	createButtonListener(caller);
	setInput(input);

	shell.open();
    }

    /**
     * Loads a given {@link CompanyInternalPresentation} record into the window
     * form of initialize the elements of the form the empty string/null if no
     * data is given.
     * 
     * @param presentation
     *                {@link CompanyInternalPresentation} instance which
     *                contains the data to be displayed or <tt>null</tt> if a
     *                completely new record is to be edited.
     */
    private void setInput(CompanyInternalPresentation presentation) {
	/* STEP 1: switch off the listeners */
	settingInput = true;

	/* STEP 2: unlock the actually displayed data record (if exists) */
	if (this.input != null && inputEditingEnabled)
	    CompanyInternalPresentation.lockedIds.remove(new Integer(this.input
		    .getId()));

	/*
	 * STEP 3: loading the given (new) data instance into the window form
	 * (if not null else initialize the elements)
	 */
	if (presentation != null) {
	    numberLabel.setEnabled(true);
	    numberText.setText(new Integer(presentation.getId()).toString());
	    durationText.setFocus();

	    if (presentation.getDuration() != null)
		durationText.setText(presentation.getDuration().toString());
	    else
		durationText.setText("");
	    if (presentation.getBeginningDay() != null)
		beginningDayCalendar.setDate(presentation.getBeginningDay());
	    else
		beginningDayCalendar.setDate(null);
	    if (presentation.getEndingDay() != null)
		endingDayCalendar.setDate(presentation.getEndingDay());
	    else
		endingDayCalendar.setDate(null);

	    startingTimeSpinner.setTime(presentation.getStartingTime());
	    endingTimeSpinner.setTime(presentation.getEndingTime());
	    firstStartingTimeSpinner.setTime(presentation
		    .getFirstStartingTime());
	    lastEndingTimeSpinner.setTime(presentation.getLastEndingTime());

	    locationText.setText(presentation.getLocation());
	    streetText.setText(presentation.getStreet());
	    zipCodeText.setText(presentation.getZipCode());
	    cityText.setText(presentation.getCity());
	    countryCombo.setText(presentation.getCountry());
	    annexCombo.setText(presentation.getAnnex());

	    cancelChecker.setSelection(presentation.isCancelled());
	    semTypeSelector.setSelectedId(presentation.getSeminarTypeId());
	    if (presentation.getPackagePrice() != null)
		packagePriceText.setText(Utility.createFloatText(presentation
			.getPackagePrice()));
	    else
		packagePriceText.setText("");

	    if (presentation.getMaxEntrants() != null)
		maxEntrantsText.setText(presentation.getMaxEntrants()
			.toString());
	    else
		maxEntrantsText.setText("");

	    try {
		SeminarType semType = SeminarType
			.getSeminarTypeFromDB(presentation.getSeminarTypeId());

		if (semType.getMinEntrants() != null)
		    minSemTypeEntrantsText.setText(semType.getMinEntrants()
			    .toString());
		else
		    minSemTypeEntrantsText.setText("");

		if (semType.getMaxEntrants() != null)
		    maxSemTypeEntrantsText.setText(semType.getMaxEntrants()
			    .toString());
		else
		    maxSemTypeEntrantsText.setText("");

	    } catch (SQLException e) {
		minSemTypeEntrantsText.setText("");
		maxSemTypeEntrantsText.setText("");
	    }

	    try {
		supervisorControl.setInput(presentation.getId());
		instructorControl.setInput(presentation.getId());
		bookingControl.setInput(presentation.getId());
	    } catch (SQLException e) {/* TODO */
	    }

	} else {
	    // no data given (client == null): initialize elements
	    numberLabel.setEnabled(false);
	    numberText.setText("");
	    durationText.setSelection(0);
	    durationText.setFocus();

	    beginningDayCalendar.setDate(null);
	    endingDayCalendar.setDate(null);

	    startingTimeSpinner.setTime(null);
	    endingTimeSpinner.setTime(null);
	    firstStartingTimeSpinner.setTime(null);
	    lastEndingTimeSpinner.setTime(null);

	    locationText.setText("");
	    streetText.setText("");
	    zipCodeText.setText("");
	    cityText.setText("");
	    countryCombo.setText("");
	    annexCombo.setText("");

	    cancelChecker.setSelection(false);
	    semTypeSelector.setSelectedId(AbstractTable.NULL_ID);

	    try {
		supervisorControl.setInput(AbstractTable.NULL_ID);
		instructorControl.setInput(AbstractTable.NULL_ID);
		bookingControl.setInput(AbstractTable.NULL_ID);
	    } catch (SQLException e) {/* TODO */
	    }

	    packagePriceText.setText("");
	    maxEntrantsText.setText("");

	    minSemTypeEntrantsText.setText("");
	    maxSemTypeEntrantsText.setText("");
	}

	/*
	 * STEP 4: Check if the given record is already locked, i.e. it is
	 * already edited (if data object is not null, else enable the
	 * elements). -> yes: disable the form elements -> no: enable them and
	 * lock the new record
	 */
	if (presentation != null) {
	    boolean alreadyEditing = CompanyInternalPresentation.lockedIds
		    .contains(new Integer(presentation.getId()));
	    setInputComponentsEnabled(!alreadyEditing);

	    if (!alreadyEditing) {
		CompanyInternalPresentation.lockedIds.add(new Integer(
			presentation.getId()));
	    }
	}

	// completely new data record
	else
	    setInputComponentsEnabled(true);

	/*
	 * STEP 5: set input to the new data object, inputChanged to true and
	 * enable next/prev buttons
	 */
	this.input = presentation;
	inputChanged = (presentation == null);

	prevButton.setEnabled(this.input != null);
	nextButton.setEnabled(this.input != null);

	/* STEP 6: set the window title */
	String shellText;
	if (input == null)
	    shellText = Messages.getString("GUIText.NewItemWindowTitleText");
	else
	    shellText = new Integer(input.getId()).toString();

	shellText += Messages
		.getString("GUIText.CompanyInternalPresentationWindowTitleText");
	if (input == null)
	    shellText += "*";
	shell.setText(shellText);

	/* STEP 7: switch on the listeners */
	settingInput = false;
    }

    /**
     * According to the value of the given parameter (<tt>true</tt>/<tt>false</tt>)
     * this method enables / disables the widgets of the window form.<br>
     * <br>
     * 
     * <i>Note:</i> It also sets the member {@link #inputEditingEnabled} to the
     * value of the parameter to signal that editing of the input has been
     * enabled or not.
     * 
     * @param enabled
     *                if equals <tt>true</tt> the widgets are enabled
     *                otherwise the widgets get disabled.
     */
    private void setInputComponentsEnabled(boolean enabled) {
	numberText.setEnabled(enabled);

	durationText.setEnabled(enabled);

	beginningDayCalendar.setEnabled(enabled);
	endingDayCalendar.setEnabled(enabled);
	startingTimeSpinner.setEnabled(enabled);
	endingTimeSpinner.setEnabled(enabled);
	firstStartingTimeSpinner.setEnabled(enabled);
	lastEndingTimeSpinner.setEnabled(enabled);

	locationText.setEnabled(enabled);
	streetText.setEnabled(enabled);
	zipCodeText.setEnabled(enabled);
	cityText.setEnabled(enabled);
	countryCombo.setEnabled(enabled);
	annexCombo.setEnabled(enabled);
	semTypeSelector.setEnabled(enabled);
	packagePriceText.setEnabled(enabled);
	maxEntrantsText.setEnabled(enabled);

	cancelChecker.setEnabled(enabled);

	supervisorControl.setEnabled(enabled);
	instructorControl.setEnabled(enabled);
	bookingControl.setEnabled(enabled);

	okButton.setEnabled(enabled);
	applyButton.setEnabled(enabled);
	newButton.setEnabled(enabled);
	abortButton.setEnabled(enabled);
	prevButton.setEnabled(enabled);
	nextButton.setEnabled(enabled);

	inputEditingEnabled = enabled;

    }

    /**
     * Adds a listener to several buttons of the window form.<br>
     * <br>
     * 
     * This involves at the moment the buttons {@link #okButton},
     * {@link #abortButton}, {@link #applyButton}, {@link #newButton},
     * {@link #prevButton}, {@link #nextButton}.
     * 
     * @param caller
     *                {@link AssociationTabControl} instance which called the
     *                constructor which itself calls this method.
     */
    private void createButtonListener(final AssociationTabControl caller) {

	if (caller == null) { // normal mode, no caller

	    okButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
		    if (onSave())
			shell.close();
		}
	    });
	    applyButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event arg0) {
		    onSave();
		}
	    });
	} else {// caller mode

	    okButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
		    if (onSave()) {
			caller.addSelectedIds(new SimpleIDKey[] { input },
				false);
			shell.close();
		    }
		}
	    });
	    applyButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event arg0) {
		    if (onSave()) {
			caller.addSelectedIds(new SimpleIDKey[] { input },
				false);
		    }
		}
	    });
	}

	newButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		if (onSave())
		    setInput(null);
	    }
	});

	abortButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		shell.close();
	    }
	});

	prevButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		if (inputChanged) {
		    if (confirmClose())
			setInput(CompanyInternalPresentation.getPrevious(input
				.getId()));
		} else
		    setInput(CompanyInternalPresentation.getPrevious(input
			    .getId()));
	    }
	});

	nextButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		if (inputChanged) {
		    if (confirmClose())
			setInput(CompanyInternalPresentation.getNext(input
				.getId()));
		} else
		    setInput(CompanyInternalPresentation.getNext(input.getId()));
	    }
	});

	listOfParticipantsButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		MessageDialog
			.openInformation(
				shell,
				Messages
					.getString("GUIText.NotImplementedMessageDialogWindowTitle"),
				Messages
					.getString("GUIText.NotImplementedMessageDialogHintText"));
	    }
	});

	certificateButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		MessageDialog
			.openInformation(
				shell,
				Messages
					.getString("GUIText.NotImplementedMessageDialogWindowTitle"),
				Messages
					.getString("GUIText.NotImplementedMessageDialogHintText"));
	    }
	});

	feeMessageButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		MessageDialog
			.openInformation(
				shell,
				Messages
					.getString("GUIText.NotImplementedMessageDialogWindowTitle"),
				Messages
					.getString("GUIText.NotImplementedMessageDialogHintText"));
	    }
	});

	cancelationButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		MessageDialog
			.openInformation(
				shell,
				Messages
					.getString("GUIText.NotImplementedMessageDialogWindowTitle"),
				Messages
					.getString("GUIText.NotImplementedMessageDialogHintText"));
	    }
	});
    }

    /**
     * Adds a listener to several buttons of the window form.<br>
     * <br>
     * 
     * This involves at the moment the buttons {@link #okButton},
     * {@link #abortButton}, {@link #applyButton}, {@link #newButton},
     * {@link #prevButton}, {@link #nextButton}.
     * 
     * @param caller
     *                {@link ForeignKeyConstraintSelector} instance which called
     *                the constructor which itself calls this method.
     */
    private void createButtonListener(final ForeignKeyConstraintSelector caller) {

	if (caller == null) { // normal mode, no caller

	    okButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
		    if (onSave())
			shell.close();
		}
	    });
	    applyButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event arg0) {
		    onSave();
		}
	    });
	} else {// caller mode

	    okButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
		    if (onSave()) {
			caller.setSelectedId(input.getId());
			shell.close();
		    }
		}
	    });
	    applyButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event arg0) {
		    if (onSave()) {
			caller.setSelectedId(input.getId());
		    }
		}
	    });
	}

	newButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		if (onSave())
		    setInput(null);
	    }
	});

	abortButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		shell.close();
	    }
	});

	prevButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		if (inputChanged) {
		    if (confirmClose())
			setInput(CompanyInternalPresentation.getPrevious(input
				.getId()));
		} else
		    setInput(CompanyInternalPresentation.getPrevious(input
			    .getId()));
	    }
	});

	nextButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		if (inputChanged) {
		    if (confirmClose())
			setInput(CompanyInternalPresentation.getNext(input
				.getId()));
		} else
		    setInput(CompanyInternalPresentation.getNext(input.getId()));
	    }
	});

	listOfParticipantsButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		MessageDialog
			.openInformation(
				shell,
				Messages
					.getString("GUIText.NotImplementedMessageDialogWindowTitle"),
				Messages
					.getString("GUIText.NotImplementedMessageDialogHintText"));
	    }
	});

	certificateButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		MessageDialog
			.openInformation(
				shell,
				Messages
					.getString("GUIText.NotImplementedMessageDialogWindowTitle"),
				Messages
					.getString("GUIText.NotImplementedMessageDialogHintText"));
	    }
	});

	feeMessageButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		MessageDialog
			.openInformation(
				shell,
				Messages
					.getString("GUIText.NotImplementedMessageDialogWindowTitle"),
				Messages
					.getString("GUIText.NotImplementedMessageDialogHintText"));
	    }
	});

	cancelationButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		MessageDialog
			.openInformation(
				shell,
				Messages
					.getString("GUIText.NotImplementedMessageDialogWindowTitle"),
				Messages
					.getString("GUIText.NotImplementedMessageDialogHintText"));
	    }
	});
    }

    /**
     * Checks if all obligatory attributes of a
     * {@link CompanyInternalPresentation} record are entered into the window
     * form and if the entered fees are correct float numbers.
     * 
     * @return <tt>true</tt> if all mandatory fields are set and the fee
     *         values are valid float numbers (if entered), otherwise
     *         <tt>false</tt>.
     * 
     * @see semorg.sql.util.Utility#isCorrectFloat(String)
     * @see semorg.sql.util.Utility#isCorrectInteger(String)
     */
    protected boolean checkInput() {
	boolean inputOK = true;
	String errorMessage = "";
	if (semTypeSelector.getSelectedId() == AbstractTable.NULL_ID) {
	    errorMessage += Messages
		    .getString("GUIText.ErrorMessageDialogMandatoryAssociationSeminarType");
	    inputOK = false;
	}
	if (!Utility.isCorrectFloat(packagePriceText.getText())) {
	    errorMessage += Messages
		    .getString("GUIText.ErrorMessageDialogIncorrectFloatPackagePrize");
	    inputOK = false;
	}
	if (!Utility.isCorrectInteger(durationText.getText())) {
	    errorMessage += Messages
		    .getString("GUIText.ErrorMessageDialogIncorrectNumberDuration");
	    inputOK = false;
	}
	if (!Utility.isCorrectInteger(maxEntrantsText.getText())) {
	    errorMessage += Messages
		    .getString("GUIText.ErrorMessageDialogIncorrectNumberMaxEntrants");
	    inputOK = false;
	}

	if (!inputOK) {
	    MessageDialog
		    .openInformation(
			    shell,
			    Messages
				    .getString("GUIText.ErrorMessageDialogMandatoryFieldWindowTitle"),
			    errorMessage);
	}

	return inputOK;
    }

    /**
     * Reads the data from the window form elements, sets the values to a
     * {@link CompanyInternalPresentation} instance and commits the changes /
     * the new record into the database.
     * 
     * Furthermore the member {@link #input} is set to the new values.
     * 
     */
    protected void commitInputToDB() {

	if (input == null) {
	    // new record into the db
	    CompanyInternalPresentation newInput;
	    try {
		newInput = new CompanyInternalPresentation(
			CompanyInternalPresentation.NULL_ID, semTypeSelector
				.getSelectedId(), Utility
				.parseInteger(durationText.getText()),
			beginningDayCalendar.getDate(), endingDayCalendar
				.getDate(), startingTimeSpinner.getTime(),
			endingTimeSpinner.getTime(), firstStartingTimeSpinner
				.getTime(), lastEndingTimeSpinner.getTime(),
			locationText.getText(), streetText.getText(),
			zipCodeText.getText(), cityText.getText(), countryCombo
				.getText(), annexCombo.getText(), cancelChecker
				.getSelection(), Utility
				.parseFloat(packagePriceText.getText()),
			Utility.parseInteger(maxEntrantsText.getText()),
			new Timestamp(System.currentTimeMillis()),
			new Timestamp(System.currentTimeMillis()));

	    } catch (SQLException e1) {
		// DB error, SeminarType not in the DB ?
		e1.printStackTrace();
		return;
	    }
	    input = newInput;
	    try {
		int id = input.insertIntoDB();
		numberText.setText(new Integer(id).toString());
	    } catch (SQLException e) {
		e.printStackTrace();
	    }
	} else {

	    // update an existing record
	    input.setDuration(Utility.parseInteger(durationText.getText()));
	    input.setBeginningDay(beginningDayCalendar.getDate());
	    input.setEndingDay(endingDayCalendar.getDate());
	    input.setStartingTime(startingTimeSpinner.getTime());
	    input.setEndingTime(endingTimeSpinner.getTime());
	    input.setFirstStartingTime(firstStartingTimeSpinner.getTime());
	    input.setLastEndingTime(lastEndingTimeSpinner.getTime());
	    input.setLocation(locationText.getText());

	    input.setStreet(streetText.getText());
	    input.setZipCode(zipCodeText.getText());
	    input.setCity(cityText.getText());
	    input.setCountry(countryCombo.getText());
	    input.setAnnex(annexCombo.getText());

	    input.setCancelled(cancelChecker.getSelection());
	    input.setSeminarTypeId(semTypeSelector.getSelectedId());

	    input.setPackagePrice(Utility
		    .parseFloat(packagePriceText.getText()));
	    input.setMaxEntrants(Utility
		    .parseInteger(maxEntrantsText.getText()));

	    try {
		input.updateDB();
	    } catch (SQLException e) {
		e.printStackTrace();
	    }
	}

	try {
	    bookingControl.commitIntoDB(input.getId());
	} catch (SQLException e) {
	    e.printStackTrace();
	}

	try {
	    instructorControl.commitIntoDB(input.getId());
	} catch (SQLException e) {
	    e.printStackTrace();
	}

	try {
	    supervisorControl.commitIntoDB(input.getId());
	} catch (SQLException e) {
	    e.printStackTrace();
	}

	CompanyInternalPresentationListWindow.instance.update();
    }

    /**
     * Creates a message dialog if the data in the window form has been changed
     * (or was entered newly) and these changes haven't been confirmed (e.g. by
     * clicking the ok button) or discarded so far. It also receives the
     * decision of the user (confirm/discard changes or abort the window
     * closing) and handles it.
     * 
     * In the positive case (confirmation of the changes) it invokes the method
     * {@link #onSave()}.
     * 
     * @return <tt>true</tt> if the shell can be closed and <tt>false</tt>
     *         otherwise.
     */
    private boolean confirmClose() {

	MessageDialog dlg;

	if (input == null) {
	    dlg = new MessageDialog(
		    shell,
		    Messages
			    .getString("GUIText.SaveNewItemMessageDialogWindowTitle"),
		    null,
		    Messages
			    .getString("GUIText.SaveNewItemMessageDialogQuestionText"),
		    MessageDialog.QUESTION,
		    new String[] {
			    Messages
				    .getString("GUIText.SaveNewItemMessageDialogYesButtonText"), Messages.getString("GUIText.SaveNewItemMessageDialogNoButtonText"), //$NON-NLS-2$
			    Messages
				    .getString("GUIText.SaveNewItemMessageDialogAbortButtonText") },
		    0);
	} else {
	    dlg = new MessageDialog(
		    shell,
		    Messages
			    .getString("GUIText.SaveChangesMessageDialogWindowTitle"),
		    null,
		    Messages
			    .getString("GUIText.SaveChangesMessageDialogQuestionText"),
		    MessageDialog.QUESTION,
		    new String[] {
			    Messages
				    .getString("GUIText.SaveChangesMessageDialogYesButtonText"), Messages.getString("GUIText.SaveChangesMessageDialogNoButtonText"), //$NON-NLS-2$
			    Messages
				    .getString("GUIText.SaveChangesMessageDialogAbortButtonText") },
		    0);
	}
	switch (dlg.open()) {
	case 0:
	    return onSave();
	case 1:
	    return true;
	case 2:
	    return false;
	default:
	    return true;
	}
    }

    /**
     * Checks whether the input has been changed (i.e. inputChanged equals
     * <tt>true</tt>) or not. If changes have been done, it firstly checks if
     * the changes are valid ({@link #checkInput()}), secondly invokes the
     * method {@link #commitInputToDB()} to commit the changes and thirdly
     * updates the GUI by invoking the method
     * {@link #setInput(CompanyInternalPresentation)}.
     * 
     * @return <tt>true</tt> if nothing has changed or the commit of the
     *         changes to the database was successful, <tt>false</tt>
     *         otherwise.
     */
    private boolean onSave() {
	if (!inputChanged)
	    return true;
	if (checkInput()) {
	    commitInputToDB();
	    setInput(input);
	    return true;
	} else
	    return false;
    }
}
