dhbw.ka.mwi.businesshorizon2.ui.initialscreen.projectlist.ProjectListViewImpl.java Source code

Java tutorial

Introduction

Here is the source code for dhbw.ka.mwi.businesshorizon2.ui.initialscreen.projectlist.ProjectListViewImpl.java

Source

/*******************************************************************************
 * BusinessHorizon2
 *
 * Copyright (C) 
 * 2012-2013 Christian Gahlert, Florian Stier, Kai Westerholz,
 * Timo Belz, Daniel Dengler, Katharina Huber, Christian Scherer, Julius Hacker
 * 2013-2014 Marcel Rosenberger, Mirko Gpfrich, Annika Weis, Katharina Narlock, 
 * Volker Meier
 * 
 *
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

package dhbw.ka.mwi.businesshorizon2.ui.initialscreen.projectlist;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.NavigableSet;

import javax.annotation.PostConstruct;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.dialogs.ConfirmDialog;

import com.mvplite.event.EventBus;
import com.vaadin.data.validator.StringLengthValidator;
import com.vaadin.event.MouseEvents;
import com.vaadin.event.MouseEvents.ClickListener;
import com.vaadin.terminal.Sizeable;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Upload;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.VerticalSplitPanel;
import com.vaadin.ui.Window;
import com.vaadin.ui.Window.Notification;

import dhbw.ka.mwi.businesshorizon2.models.Project;
import dhbw.ka.mwi.businesshorizon2.models.Period.Period;
import dhbw.ka.mwi.businesshorizon2.services.persistence.Downloader;
import dhbw.ka.mwi.businesshorizon2.services.persistence.UploadReceiver;

/**
 * Dies ist die Vaadin-Implementierung der PeriodListView. Die Rahmendarstellung
 * wird in der generateUi Methode visuell dargestellt. Die einzelnen Projekte
 * mit Namen, Perioden, Aenderungsdatum und Loeschmethode werde in den Methoden
 * setProjects und generateSingleProject erzeugt. Die Click-Events verschiedener
 * werden gesammelt in der Methode buttonClick verwertet und falls Logik von
 * noeten ist vom Presenter weiter ausgefuehrt. Die Auswahl eines Projekts wird
 * hier mittels der layoutClick Methode realisiert und fuehrt zum
 * Projekt-Wizard.
 * 
 * @author Christian Scherer, Mirko Gpfrich
 * 
 */
public class ProjectListViewImpl extends VerticalSplitPanel
        implements ProjectListViewInterface, Button.ClickListener, ClickListener {

    private static final long serialVersionUID = 1L;

    private static final Logger logger = Logger.getLogger("ProjectListViewImpl.class");

    @Autowired
    private ProjectListPresenter presenter;

    private Project project;
    private List<Project> projects;

    NavigableSet<Period> periodList;

    Iterator<Project> iterator;

    private HorizontalLayout projectListHead;
    private VerticalLayout projectListPanel;

    private Panel singleProject;
    private List<Panel> singleProjectPanelList;

    //Buttons, um ein Projekt hinzuzufgen
    private Button addProjectBtn;
    private Button dialogAddBtn;

    //Upload Button + Receiver, um ein Projekt zu importieren
    private UploadReceiver receiver;
    private Upload upload;

    //Button, um ein Projekt zu exportieren
    private Button exportProjectBtn;

    //Buttons, um ein Projekt zu bearbeiten
    private Button dialogEditBtn;

    private List<Button> editBtnList;
    private int indexEditBtn;
    private List<Button> dialogEditBtnList;

    private List<Button> removeBtnList;

    //private Label projectName;
    private Label lastChanged;
    private Label title;
    private Label projectTypAndPeriods;

    private TextField tfName;
    private TextArea taDescription;

    private Window addDialog;
    private Window editDialog;

    @Autowired
    private EventBus eventBus;

    /**
     * Dies ist der Konstruktor, der von Spring nach der Initialierung der
     * Dependencies aufgerufen wird. Er registriert sich selbst beim Presenter
     * und initialisiert die View-Komponenten. Danach wird die durch die
     * generateUi Methode die festen Bestandteile der Projektliste erzeugt
     * (Ueberschrift, leeres ProjectListPanel und Hinzufuegebutton)
     * 
     * @author Christian Scherer
     */
    @PostConstruct
    public void init() {
        presenter.setView(this);
        generateUI();
        logger.debug("UI-Initialisierung beendet");
    }

    /**
     * Konkrete Ausprogrammierung der festen UI Elemente (Ueberschrift, leeres
     * ProjectListPanel und Hinzufuegebutton). Erst spaeter wird durch die
     * Methode setProjects das ProjectListPanel mit konkreten Projekten
     * gefuellt.
     * 
     * @author Mirko Gpfrich
     */
    private void generateUI() {
        //setMargin(true);

        //Teilt die View vertikal in zwei Bereiche auf und erstellt eine horizontale Trennlinie (nicht verstellbar).
        setSizeFull();
        setSplitPosition(60, Sizeable.UNITS_PIXELS);
        setLocked(true);
        setStyleName("small");
        logger.debug("Neues Vertikales SplitPanel erstellt");

        //Layout fr oberes Panel erstellen
        projectListHead = new HorizontalLayout();
        projectListHead.setSizeFull();
        setFirstComponent(projectListHead);

        //Layout fr unteres Panel erstellen
        projectListPanel = new VerticalLayout();
        setSecondComponent(projectListPanel);
        projectListPanel.setSpacing(false);

        logger.debug("Leeres ProjektList Panel erstellt");

        //berschrift im oberen Panel hinzufgen
        title = new Label("<h1>Meine Projekte</h1>");
        title.setContentMode(Label.CONTENT_XHTML);
        projectListHead.addComponent(title);
        logger.debug("Ueberschrift erstellt");

        //Upload/Import-Button im oberen Panel hinzufgen + intialisieren
        receiver = new UploadReceiver(eventBus);
        upload = new Upload(null, receiver);
        upload.setImmediate(true);
        upload.setButtonCaption("Import");
        projectListHead.addComponent(upload);
        logger.debug("Upload Button erzeugt");
        projectListHead.setComponentAlignment(upload, Alignment.MIDDLE_RIGHT);
        upload.addListener(receiver);

        //Export-Button im oberen Panel hinzufgen
        exportProjectBtn = new Button("Projekte exportieren", this);
        projectListHead.addComponent(exportProjectBtn);
        logger.debug("Export-Button erzeugt");
        projectListHead.setComponentAlignment(exportProjectBtn, Alignment.MIDDLE_RIGHT);

        //Hinzufgen-Button im oberen Panel hinzufgen
        addProjectBtn = new Button("Projekt hinzufgen", this);
        projectListHead.addComponent(addProjectBtn);
        logger.debug("Hinzufuege-Button erzeugt");
        projectListHead.setComponentAlignment(addProjectBtn, Alignment.MIDDLE_RIGHT);

        logger.debug("Feste UI Elemente dem Fenster hinzugefuegt");
    }

    /**
     * 
     * Aufruf durch den Presenter (bei Ersterstellung oder Aenderungen durch
     * Buttonclicks) - wobei zunchst die Projektliste aktualisiert wird.
     * Zunaechst werden - falls vorhanden - die derzeitg existenten Elemente des
     * projectListPanel geloescht und die Liste der Projekt Layouts und
     * Loeschbuttons neu erstellt. Darauf folgt dann in der Schleife die
     * Erzeugung der einzelnen VadinKomponenten fuer jedes Projekt durch die
     * Methode generateSingleProjectUi.
     * 
     * @author Christian Scherer, Mirko Gpfrich
     */
    @Override
    public void setProjects(List<Project> projects) {

        this.projects = projects;
        logger.debug("Projektliste aktualisiert");
        projectListPanel.removeAllComponents();
        logger.debug("Projekt-Element-Liste geleert");

        singleProjectPanelList = new ArrayList<Panel>();

        //?
        removeBtnList = new ArrayList<Button>();
        editBtnList = new ArrayList<Button>();
        dialogEditBtnList = new ArrayList<Button>();

        for (int i = 0; i < projects.size(); i++) {
            project = projects.get(i);

            singleProjectPanelList.add(generateSingleProjectUI(project, i));
            projectListPanel.addComponent(singleProjectPanelList.get(i));
            //projectListPanel.setComponentAlignment(singleProjectPanelList.get(i), Alignment.MIDDLE_CENTER);

        }

        logger.debug("Projekt-Element-Liste erzeugt");
    }

    /**
     * Konkrete Ausprogrammierung der der Darstellung eines einzlenen Projekts
     * (Name, Anzahl Perioden mit Jahren, Aenderungsdatum, Loeschbutton). Diese
     * wird sowohl bei der ersten Erstellung des UIs fuer jedes Projekt
     * ausgefuehrt. Die Loeschbuttons werden einer Liste an Loeschbuttons
     * hinzufgefuegt umd spaeter eine identifikation der Buttons in der Methode
     * buttonClick zu gewaehrleisten. Zum Schluss wird dem Layout noch ein
     * Listener hinzugefuegt, der durch die Methode LayoutClick auf Klicks auf
     * ein jeweiliges Projekt reagiert und in die Prozesssicht des einzelnen
     * Projekts wechselt und das VerticalLayout dem projectListPanel
     * hinzgefuegt.
     * 
     * @author Christian Scherer, Mirko Gpfrich
     * @param project
     *            das darzustellende Projekt und der aktuelle Index der Liste
     * @param i
     *            der Index der zu erstellenden Komponente (besonders fuer den
     *            Loeschbutton relevant)
     * @return ein VerticalLayout Objekt, das zur Eingliederung in das UI dient
     */
    private Panel generateSingleProjectUI(Project project, int i) {

        //erzeugt eine Panel fr ein Projekt
        singleProject = new Panel(project.getName());
        singleProject.setStyleName("borderless light projectlist");

        //Legt ein Layout fr das Projekt-Panel fest
        HorizontalLayout panelContent = new HorizontalLayout();
        //panelContent.setSizeFull();
        singleProject.setContent(panelContent);
        singleProject.setSizeFull();
        panelContent.addStyleName("projectListPanel");

        //Legt ein linkes und ein rechtes Layout innerhalb des Panels an.
        VerticalLayout panelContentLeft = new VerticalLayout();
        HorizontalLayout panelContentRight = new HorizontalLayout();
        panelContent.addComponent(panelContentLeft);
        panelContent.addComponent(panelContentRight);
        panelContent.setComponentAlignment(panelContentLeft, Alignment.BOTTOM_LEFT);
        panelContent.setComponentAlignment(panelContentRight, Alignment.BOTTOM_RIGHT);
        panelContentLeft.setWidth("340px");

        periodList = (NavigableSet<Period>) project.getPeriods();

        // String fuer saubere Periodenausgabe erstellen.

        String periodString;
        int numbersOfPeriods;
        numbersOfPeriods = project.getTotalPeriods();

        if (numbersOfPeriods == 0) {
            periodString = "Noch keine Perioden eingetragen";
        } else {
            periodString = "" + numbersOfPeriods + " Perioden";
        }

        String typMethod;
        typMethod = project.getTypMethod();

        projectTypAndPeriods = new Label(typMethod + ": " + periodString);

        // String fuer Ausgabe des letzten Aenderungsdatum
        String lastChangedString;
        if (project.getLastChanged() == null) {
            Date d = new Date();
            lastChangedString = "Zuletzt gendert: " + d.toString();
        } else {
            lastChangedString = "Zuletzt gendert: " + project.getLastChanged().toString();
        }
        lastChanged = new Label(lastChangedString);

        //Buttons erstellen
        final Button removeBtn = new Button("");
        final Button editBtn = new Button("");

        //Button formatieren
        removeBtn.addStyleName("borderless");
        removeBtn.setIcon(new ThemeResource("images/icons/trash.png"));
        editBtn.addStyleName("borderless");
        editBtn.setIcon(new ThemeResource("images/icons/pen.png"));

        //Button-Listener hinzufgen
        removeBtn.addListener(new Button.ClickListener() {
            private static final long serialVersionUID = 1L;

            public void buttonClick(ClickEvent event) {
                final int index3 = removeBtnList.indexOf(event.getButton());

                logger.debug(
                        "Projekt-loeschen Button aus dem Hauptfenster aufgerufen. Projektnummer: " + (index3 + 1));

                ConfirmDialog.show(getWindow(), projects.get(index3).getName() + " lschen?",
                        "Wollen sie das Projekt wirklich lschen?", "Ja", "Nein", new ConfirmDialog.Listener() {
                            /**
                             * 
                             */
                            private static final long serialVersionUID = 1L;

                            @Override
                            public void onClose(ConfirmDialog dialog) {
                                if (dialog.isConfirmed()) {
                                    presenter.removeProject(projects.get(index3));
                                } else {

                                }
                            }
                        });
            }
        });

        editBtn.addListener(new Button.ClickListener() {
            private static final long serialVersionUID = 1L;

            public void buttonClick(ClickEvent event) {
                indexEditBtn = editBtnList.indexOf(event.getButton());

                logger.debug("Projekt-bearbeiten Button aus dem Hauptfenster aufgerufen. Projektnummer: "
                        + (indexEditBtn + 1));
                presenter.editProjectDialog(projects.get(indexEditBtn));
            }
        });

        // Liste fr Buttons zur spaeteren Identifikation
        removeBtnList.add(removeBtn);
        editBtnList.add(editBtn);
        dialogEditBtnList.add(dialogEditBtn);

        //Inhalt dem Panel hinzufgen
        panelContentLeft.addComponent(projectTypAndPeriods);
        panelContentLeft.addComponent(lastChanged);
        panelContentRight.addComponent(removeBtnList.get(i));
        panelContentRight.addComponent(editBtnList.get(i));

        logger.debug("Edit-Button " + i + " hinzugefuegt");

        //CLick-Listener fr das Panel hinzufgen
        singleProject.addListener(this);
        projectListPanel.addComponent(singleProject);
        logger.debug("Einzelnes Projektelement erzeugt");

        return singleProject;
    }

    /**
     * Zeige das Projekt-Hinzufuegen-Dialogfenster, bei dem ein Eingabefeld fuer
     * den Namen des Projekts und ein Hinzfuege-Button vorhanden ist. Funktion
     * bei geklicktem Button siehe Clicklistener in dieser Klasse. Das
     * horizontale Layout zur Darstellung besitzt ein Formlayout und den Button,
     * die nebeneinander dargestellt werden.
     * 
     * @author Christian Scherer, Mirko Gpfrich
     */
    @Override
    public void showAddProjectDialog() {
        addDialog = new Window("Projekt hinzufgen");
        addDialog.setModal(true);
        addDialog.setWidth(410, UNITS_PIXELS);
        addDialog.setResizable(false);
        addDialog.setDraggable(false);

        VerticalLayout layout = new VerticalLayout();
        layout.setSpacing(false);

        FormLayout formLayout = new FormLayout();
        formLayout.setMargin(true);
        formLayout.setSpacing(true);

        //TextFeld fr Name dem Formular hinzufgen
        tfName = new TextField("Name whlen:");
        tfName.setRequired(true);
        tfName.addValidator(new StringLengthValidator("Der Projektname muss zwischen 2 und 20 Zeichen lang sein.",
                2, 20, false));
        tfName.setRequiredError("Pflichtfeld");
        tfName.setSizeFull();
        formLayout.addComponent(tfName);

        //TextArea fr Beschreibung dem Formular hinzufgen
        taDescription = new TextArea("Beschreibung whlen");
        taDescription.setSizeFull();
        formLayout.addComponent(taDescription);

        //Formular dem Layout hinzufgen
        layout.addComponent(formLayout);

        //Hinzufge-Button erstllen und dem Layout hinzufgen
        dialogAddBtn = new Button("Hinzufgen", this);
        layout.addComponent(dialogAddBtn);

        //Layout dem Dialog-Fenster hinzufgen
        addDialog.addComponent(layout);

        //Dialog dem Hauptfenster hinzufgen
        getWindow().addWindow(addDialog);
        logger.debug("Hinzufuege-Dialog erzeugt");
    }

    /**Methode zur Implementierung des Dialogfensters fr Projekt-nderungen.
     * 
     */
    @Override
    public void showEditProjectDialog(Project project) {
        editDialog = new Window("Projekt bearbeiten");
        editDialog.setModal(true);
        editDialog.setWidth(410, UNITS_PIXELS);
        editDialog.setResizable(false);
        editDialog.setDraggable(false);

        VerticalLayout layout = new VerticalLayout();
        layout.setSpacing(true);

        FormLayout formLayout = new FormLayout();
        formLayout.setMargin(true);
        formLayout.setSpacing(true);

        //TextFeld fr Name dem Formular hinzufgen
        tfName = new TextField("Name ndern:", project.getName());
        tfName.setRequired(true);
        tfName.addValidator(new StringLengthValidator("Der Projektname muss zwischen 2 und 20 Zeichen lang sein.",
                2, 20, false));
        tfName.setRequiredError("Pflichtfeld");
        tfName.setSizeFull();
        formLayout.addComponent(tfName);

        //TextArea fr Beschreibung dem Formular hinzufgen
        taDescription = new TextArea("Beschreibung ndern:", project.getDescription());
        taDescription.setSizeFull();
        formLayout.addComponent(taDescription);

        //Formular dem Layout hinzufgen
        layout.addComponent(formLayout);

        //Speichern-Button erstllen und dem Layout hinzufgen
        //TODO: ist das korrekt?
        dialogEditBtn = new Button("Speichern");
        layout.addComponent(dialogEditBtn);

        dialogEditBtn.addListener(new Button.ClickListener() {
            private static final long serialVersionUID = 1L;

            public void buttonClick(ClickEvent event) {

                if (tfName.isValid()) {
                    boolean succed = presenter.editProject(projects.get(indexEditBtn), (String) tfName.getValue(),
                            (String) taDescription.getValue());
                    if (succed) {
                        getWindow().removeWindow(editDialog);
                        logger.debug("Projekt-bearbeiten Dialog geschlossen");

                    }

                } else {
                    getWindow().showNotification("",
                            "Projektname ist ein Pflichtfeld. Bitte geben Sie einen Projektnamen an",
                            Notification.TYPE_ERROR_MESSAGE);
                }
            }
        });

        //Layout dem Dialog-Fenster hinzufgen
        editDialog.addComponent(layout);

        //Dialog dem Hauptfenster hinzufgen
        getWindow().addWindow(editDialog);
        logger.debug("Bearbeiten-Dialog erzeugt");

    }

    /**
     * ClickListner Methode fuer die Reaktion auf Buttonclicks. Hier wird
     * entsprechend auf die Button-Clicks fuer das Erzeugen weiterer Projekte
     * reagiert, wie auch auf jene die Projekte loeschen. In der ersten
     * If-Abfrage werden die vom Hauptfenster ausgeloeten Clicks zum Hinzufuegen
     * eines neuen Objektes behandelt, in der zweiten If-Abfrage wird die im
     * Dialogfenster ausgeloesten Clickst behandelt (Hierbei wird noch geprueft
     * ob das auf "required" gesetzte Textfeld auch ausgefuellt wurde - falls
     * nicht wird eine Fehlermeldung angezeigt) und in der Else-Verzweigung dann
     * die Loesch-Clicks fuer das jeweilige Projekt behandelt. Hierbei wird
     * zunchst durch das Event in der Loesch-Buttonliste der Index
     * identifiziert, also welches Projekt zu loeschen ist. Die jeweils folgende
     * Logid ist in der je aufgerufen Methode des Presenters zu finden.
     * 
     * @author Christian Scherer, Mirko Gpfrich
     * @param event
     *            Klick-event des Buttons
     */
    @Override
    public void buttonClick(ClickEvent event) {

        if (event.getButton() == addProjectBtn) {
            logger.debug("Projekt-hinzufgen Button aus dem Hauptfenster aufgerufen");
            presenter.addProjectDialog();

        } else if (event.getButton() == dialogAddBtn) {
            logger.debug("Projekt-hinzufgen Button aus dem Dialogfenster aufgerufen");

            if (tfName.isValid()) {
                presenter.addProject((String) tfName.getValue(), (String) taDescription.getValue());
                //TODO: Fenster nur schlieen, wenn das Hinzufgen erfolgreich war (s. Projekt Bearbeiten).
                getWindow().removeWindow(addDialog);
                logger.debug("Projekt-hinzufgen Dialog geschlossen");
            } else {
                getWindow().showNotification("",
                        "Projektname ist ein Pflichtfeld. Bitte geben Sie einen Projektnamen an",
                        Notification.TYPE_ERROR_MESSAGE);
            }
        } else if (event.getButton() == exportProjectBtn) {
            logger.debug("Export-Button Click Event aufgerufen");
            File exportFile;
            exportFile = presenter.exportProjects();
            //Download-Anforderung
            event.getButton().getWindow().open(new Downloader(exportFile, getApplication()));
            logger.debug("Download-Anforderung abgeschlossen");
        }
    }

    /**
     * LayoutClickListner Methode fuer die Reaktion auf Clicks auf die einzelnen
     * Projekte reagiert. Konkret wird hier die Verbindung zur Prozesssicht
     * geschaffen. Zunaechst wird geprueft von welchem Projekt der Klick kommt,
     * und dann dieses dem Presenter uebergeben, in welchem dann das Event fuer
     * das Anzeigen der Prozesssicht ausgeloest wird.
     * 
     * @author Christian Scherer
     * @param event
     *            - Event des Layoutclicks
     */

    @Override
    public void click(MouseEvents.ClickEvent event) {
        int index = singleProjectPanelList.indexOf(event.getComponent());
        logger.debug("Projekt ausgewaehlt. Projektnummer: " + (index + 1));
        presenter.projectSelected(projects.get(index));
    }

    public void showErrorMessage(String message) {
        Window.Notification notif = new Notification((String) "", message, Notification.TYPE_WARNING_MESSAGE);
        notif.setPosition(Window.Notification.POSITION_CENTERED_TOP);
        getWindow().showNotification(notif);
    }

}