From c24d1eaeeb1974347be53bb247e1cc95775a0429 Mon Sep 17 00:00:00 2001
From: Nils Christian Ehmke <nie@informatik.uni-kiel.de>
Date: Wed, 17 Oct 2012 10:09:42 +0200
Subject: [PATCH] Started with the dynamic dashboard of the cockpit editor.

---
 .../beans/view/CurrentCockpitEditorBean.java  | 129 ++++++++++++++----
 .../beans/view/CurrentControllerBean.java     |   1 +
 .../lang/AnalysisEditorPage_de.properties     |   6 -
 .../lang/AnalysisEditorPage_en.properties     |   6 -
 .../main/resources/lang/Common_de.properties  |   5 +
 .../main/resources/lang/Common_en.properties  |   5 +
 .../src/main/webapp/AnalysisEditorPage.xhtml  |   8 +-
 .../src/main/webapp/CockpitEditorPage.xhtml   |  49 ++++---
 .../src/main/webapp/ProjectOverviewPage.xhtml |   2 +-
 9 files changed, 144 insertions(+), 67 deletions(-)

diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentCockpitEditorBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentCockpitEditorBean.java
index 929d33c2..40e78198 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentCockpitEditorBean.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentCockpitEditorBean.java
@@ -23,12 +23,14 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
+import javax.faces.application.Application;
 import javax.faces.application.FacesMessage;
 import javax.faces.bean.ManagedBean;
 import javax.faces.bean.ManagedProperty;
 import javax.faces.bean.ViewScoped;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIInput;
+import javax.faces.component.html.HtmlOutputText;
 import javax.faces.context.FacesContext;
 
 import kieker.analysis.display.annotation.Display;
@@ -50,8 +52,14 @@ import kieker.webgui.common.exception.NewerProjectException;
 import kieker.webgui.common.exception.ProjectLoadException;
 import kieker.webgui.common.exception.ProjectNotExistingException;
 
+import org.primefaces.component.dashboard.Dashboard;
+import org.primefaces.component.panel.Panel;
 import org.primefaces.context.RequestContext;
 import org.primefaces.event.TabChangeEvent;
+import org.primefaces.model.DashboardColumn;
+import org.primefaces.model.DashboardModel;
+import org.primefaces.model.DefaultDashboardColumn;
+import org.primefaces.model.DefaultDashboardModel;
 
 /**
  * The {@link CurrentCockpitEditorBean} contains the necessary data behind an instance of the cockpit editor.
@@ -63,43 +71,87 @@ import org.primefaces.event.TabChangeEvent;
 @ManagedBean
 @ViewScoped
 public final class CurrentCockpitEditorBean {
-	/**
-	 * This is the log for errors, exceptions etc.
-	 */
+
+	private static final int NUMBER_COLUMNS = 2;
 	private static final Log LOG = LogFactory.getLog(CurrentCockpitEditorBean.class);
-	/**
-	 * This is the factory which will be used to create new components for the project.
-	 */
+
 	private final MIAnalysisMetaModelFactory factory = new MAnalysisMetaModelFactory();
-	/**
-	 * This is the name of the stored project. It can be used as an identifier within the FS-Manager
-	 */
+	private final IProjectManagerFacade projectManagerFacade = ProjectManagerFacade.getInstance();
+	private ClassAndMethodContainer classAndMethodContainer;
+
+	private long timeStamp;
 	private String projectName;
-	/**
-	 * This is the actual model instance. It is the in-memory-model of the current (session) user.
-	 */
 	private MIProject project;
-	/**
-	 * This is the time stamp of the moment, the project was loaded or last saved. It can be used to check whether the project has been modified in the meanwhile.
-	 */
-	private long timeStamp;
-	/**
-	 * This is the currently selected view.
-	 */
 	private MIView activeView;
+	private ClassLoader classLoader;
+	private Dashboard dashboard;
 
 	@ManagedProperty(value = "#{projectsBean}")
 	private ProjectsBean projectsBean;
 
-	private final IProjectManagerFacade projectManagerFacade = ProjectManagerFacade.getInstance();
-	private ClassAndMethodContainer classAndMethodContainer;
-	private ClassLoader classLoader;
-
 	/**
 	 * Creates a new instance of this class. <b>Do not call this constructor manually. It will only be accessed by JSF.</b>
 	 */
 	public CurrentCockpitEditorBean() {
-		// No code necessary
+		this.createDashboard();
+	}
+
+	private void createDashboard() {
+		final FacesContext fc = FacesContext.getCurrentInstance();
+		final Application application = fc.getApplication();
+
+		// Create the primefaces dashboard
+		this.dashboard = (Dashboard) application.createComponent(fc, "org.primefaces.component.Dashboard", "org.primefaces.component.DashboardRenderer");
+		this.dashboard.setId("dashboard");
+
+		// Create the model and add the columns
+		final DashboardModel model = new DefaultDashboardModel();
+		for (int i = 0; i < CurrentCockpitEditorBean.NUMBER_COLUMNS; i++) {
+			final DashboardColumn column = new DefaultDashboardColumn();
+			model.addColumn(column);
+		}
+		this.dashboard.setModel(model);
+	}
+
+	private void fillDashboard() {
+		// Dump the old entries
+		this.clearDashboard();
+
+		// Now add the entries from the current view
+		if (this.activeView != null) {
+			final FacesContext fc = FacesContext.getCurrentInstance();
+			final Application application = fc.getApplication();
+
+			// Add a panel for every display connector we have
+			final List<MIDisplayConnector> connectors = this.activeView.getDisplayConnectors();
+			int i = 0;
+			for (final MIDisplayConnector connector : connectors) {
+				final Panel panel = (Panel) application.createComponent(fc, "org.primefaces.component.Panel", "org.primefaces.component.PanelRenderer");
+				panel.setId("displayConnectorPanel_" + i);
+				panel.setHeader(connector.getName());
+				panel.setClosable(true);
+				panel.setToggleable(false);
+
+				this.getDashboard().getChildren().add(panel);
+				final DashboardColumn column = this.dashboard.getModel().getColumn(i % CurrentCockpitEditorBean.NUMBER_COLUMNS);
+				column.addWidget(panel.getId());
+				final HtmlOutputText text = new HtmlOutputText();
+				text.setValue("N/A");
+
+				panel.getChildren().add(text);
+				i++;
+			}
+		}
+	}
+
+	private void clearDashboard() {
+		// Run through all columns of the dashboard and remove the items
+		final List<DashboardColumn> columns = this.dashboard.getModel().getColumns();
+		for (final DashboardColumn column : columns) {
+			column.getWidgets().clear();
+		}
+		// Now run through the dashboard itself and remove the items as well
+		this.dashboard.getChildren().clear();
 	}
 
 	/**
@@ -138,6 +190,7 @@ public final class CurrentCockpitEditorBean {
 						// Update the class loader and the specific classes used within various methods in this bean
 						this.reloadClassLoader();
 						this.reloadClassesAndMethods();
+						this.fillDashboard();
 					}
 				}
 			} catch (final ProjectLoadException ex) {
@@ -349,6 +402,8 @@ public final class CurrentCockpitEditorBean {
 	public void setActiveView(final MIView view) {
 		synchronized (this) {
 			this.activeView = view;
+
+			this.fillDashboard();
 		}
 	}
 
@@ -365,6 +420,24 @@ public final class CurrentCockpitEditorBean {
 				connector.setDisplay(display);
 				connector.setName(UUID.randomUUID().toString());
 				this.activeView.getDisplayConnectors().add(connector);
+
+				// Now add it to the dashboard as well
+				final FacesContext fc = FacesContext.getCurrentInstance();
+				final Application application = fc.getApplication();
+
+				final Panel panel = (Panel) application.createComponent(fc, "org.primefaces.component.Panel", "org.primefaces.component.PanelRenderer");
+				panel.setId("displayConnectorPanel_" + (this.dashboard.getChildCount() + 1));
+				panel.setHeader(connector.getName());
+				panel.setClosable(true);
+				panel.setToggleable(false);
+
+				this.getDashboard().getChildren().add(panel);
+				final DashboardColumn column = this.dashboard.getModel().getColumn(CurrentCockpitEditorBean.NUMBER_COLUMNS - 1);
+				column.addWidget(panel.getId());
+				final HtmlOutputText text = new HtmlOutputText();
+				text.setValue("N/A");
+
+				panel.getChildren().add(text);
 			}
 		}
 	}
@@ -426,4 +499,12 @@ public final class CurrentCockpitEditorBean {
 		}
 	}
 
+	public Dashboard getDashboard() {
+		return this.dashboard;
+	}
+
+	public void setDashboard(final Dashboard dashboard) {
+		this.dashboard = dashboard;
+	}
+
 }
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java
index 864df7ce..ce755eb5 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java
@@ -55,6 +55,7 @@ public final class CurrentControllerBean {
 	private final IProjectManagerFacade projectManagerFacade = ProjectManagerFacade.getInstance();
 	private final List<String> logEntries = new ArrayList<String>();
 	private String projectName;
+
 	@ManagedProperty(value = "#{projectsBean}")
 	private ProjectsBean projectsBean;
 
diff --git a/Kieker.WebGUI/src/main/resources/lang/AnalysisEditorPage_de.properties b/Kieker.WebGUI/src/main/resources/lang/AnalysisEditorPage_de.properties
index 04c380d0..5c386367 100644
--- a/Kieker.WebGUI/src/main/resources/lang/AnalysisEditorPage_de.properties
+++ b/Kieker.WebGUI/src/main/resources/lang/AnalysisEditorPage_de.properties
@@ -16,8 +16,6 @@ autoLayout = Auto-Layout
 disable = Deaktivieren
 enable = Aktivieren
 
-noPropertiesAvailable = Keine Eigenschaften vorhanden
-
 name = Name
 className = ClassName
 
@@ -38,10 +36,6 @@ repositoryPorts = Repositoryports
 					   
 msgProjectModified = Das Projekt wurde in der Zwischenzeit au\u00dferhalb dieses Editors modifiziert. Wollen Sie die \u00c4nderungen \u00fcberschreiben?
 
-properties = Eigenschaften
-property = Eigenschaft
-value = Wert
-
 libraries = Bibliotheken
 fileName = Dateiname
 fileSize = Gr\u00f6\u00dfe
diff --git a/Kieker.WebGUI/src/main/resources/lang/AnalysisEditorPage_en.properties b/Kieker.WebGUI/src/main/resources/lang/AnalysisEditorPage_en.properties
index d0169ee3..4e5c3c68 100644
--- a/Kieker.WebGUI/src/main/resources/lang/AnalysisEditorPage_en.properties
+++ b/Kieker.WebGUI/src/main/resources/lang/AnalysisEditorPage_en.properties
@@ -16,8 +16,6 @@ autoLayout = Auto-Layout
 disable = Disable
 enable = Enable
 
-noPropertiesAvailable = No properties available
-
 name = Name
 className = ClassName
 
@@ -38,10 +36,6 @@ repositoryPorts = Repository Ports
 					   
 msgProjectModified = The project has been modified externally in the meanwhile. Do you want to overwrite the changes?
 
-properties = Properties
-property = Property
-value = Value
-
 libraries = Libraries
 fileName = Filename
 fileSize = Size
diff --git a/Kieker.WebGUI/src/main/resources/lang/Common_de.properties b/Kieker.WebGUI/src/main/resources/lang/Common_de.properties
index d44232df..edcc9c75 100644
--- a/Kieker.WebGUI/src/main/resources/lang/Common_de.properties
+++ b/Kieker.WebGUI/src/main/resources/lang/Common_de.properties
@@ -31,6 +31,11 @@ closeProject = Projekt schlie\u00dfen
 
 noRecordsFound = Keine Einträge vorhanden.
 
+properties = Eigenschaften
+property = Eigenschaft
+value = Wert
+noPropertiesAvailable = Keine Eigenschaften vorhanden
+
 #------------------------------------------------------------------------------
 #
 # These are the messages for the settings dialog.
diff --git a/Kieker.WebGUI/src/main/resources/lang/Common_en.properties b/Kieker.WebGUI/src/main/resources/lang/Common_en.properties
index 5b4af740..8e8211b5 100644
--- a/Kieker.WebGUI/src/main/resources/lang/Common_en.properties
+++ b/Kieker.WebGUI/src/main/resources/lang/Common_en.properties
@@ -31,6 +31,11 @@ closeProject = Close Project
 
 noRecordsFound = No records found.
 
+properties = Properties
+property = Property
+value = Value
+noPropertiesAvailable = No properties available
+
 #------------------------------------------------------------------------------
 #
 # These are the messages for the settings dialog.
diff --git a/Kieker.WebGUI/src/main/webapp/AnalysisEditorPage.xhtml b/Kieker.WebGUI/src/main/webapp/AnalysisEditorPage.xhtml
index f9c018c6..c6a17944 100644
--- a/Kieker.WebGUI/src/main/webapp/AnalysisEditorPage.xhtml
+++ b/Kieker.WebGUI/src/main/webapp/AnalysisEditorPage.xhtml
@@ -136,10 +136,10 @@
             </p:layoutUnit> 
 
             <!-- This is the component presenting the available properties. -->
-            <p:layoutUnit style="font-size: 12px" position="south" size="150" header="#{localizedAnalysisEditorPageMessages.properties}" resizable="true" collapsible="true">
+            <p:layoutUnit style="font-size: 12px" position="south" size="150" header="#{localizedMessages.properties}" resizable="true" collapsible="true">
                 <h:form id="propertiesForm" >
-                    <p:dataTable editable="true" value="#{currentAnalysisEditorBean.advancedPluginProperties}" var="property" rowIndexVar="rowIndex" emptyMessage="No properties available" rendered="#{not empty currentAnalysisEditorBean.selectedPlugin}">
-                        <p:column headerText="#{localizedAnalysisEditorPageMessages.property}" style="width:125px">
+                    <p:dataTable editable="true" value="#{currentAnalysisEditorBean.advancedPluginProperties}" var="property" rowIndexVar="rowIndex" emptyMessage="#{localizedMessages.noPropertiesAvailable}" rendered="#{not empty currentAnalysisEditorBean.selectedPlugin}">
+                        <p:column headerText="#{localizedMessages.property}" style="width:125px">
                             <!-- The first property is always the classname, the second one always the normal name. After that, other properties can follow. -->
                             <h:outputText id="classNameProperty" value="#{localizedAnalysisEditorPageMessages.className}" rendered="#{rowIndex == 0}"/>
                             <h:outputText id="nameProperty" value="#{localizedAnalysisEditorPageMessages.name}" rendered="#{rowIndex == 1}"/>
@@ -150,7 +150,7 @@
                         </p:column>
 
                         <!-- The classname is not editable, the name is editable with a specific target, other properies are editable normally. -->
-                        <p:column headerText="#{localizedAnalysisEditorPageMessages.value}" style="width:125px">
+                        <p:column headerText="#{localizedMessages.value}" style="width:125px">
                             <h:outputText id="className" value="#{currentAnalysisEditorBean.selectedPlugin.classname}" rendered="#{rowIndex == 0}"/>
                             <p:inplace id="nameEditor" editor="true" rendered="#{rowIndex == 1}" >  
                                 <p:inputText value="#{currentAnalysisEditorBean.selectedPlugin.name}" />
diff --git a/Kieker.WebGUI/src/main/webapp/CockpitEditorPage.xhtml b/Kieker.WebGUI/src/main/webapp/CockpitEditorPage.xhtml
index 4d185292..6dfdcb19 100644
--- a/Kieker.WebGUI/src/main/webapp/CockpitEditorPage.xhtml
+++ b/Kieker.WebGUI/src/main/webapp/CockpitEditorPage.xhtml
@@ -32,16 +32,16 @@
                         <p:toolbarGroup align="right">
                             <p:commandButton styleClass="perspective-button" icon="ui-icon-home" action="ProjectOverview.xhtml" />
                             <p:separator/>
-                            <p:button styleClass="perspective-button" icon="ui-icon-wrench" value="Analysis Editor" style="white-space: none" outcome="AnalysisEditor.xhtml">
+                            <p:button styleClass="perspective-button" icon="ui-icon-wrench" value="Analysis Editor" style="white-space: none" outcome="AnalysisEditorPage.xhtml">
                                 <f:param name="projectName" value="#{currentCockpitEditorBean.projectName}" />
                             </p:button>
-                            <p:button styleClass="perspective-button" icon="ui-icon-circle-triangle-e" value="Analysis" style="white-space: none" outcome="Controller.xhtml">
+                            <p:button styleClass="perspective-button" icon="ui-icon-circle-triangle-e" value="Analysis" style="white-space: none" outcome="ControllerPage.xhtml">
                                 <f:param name="projectName" value="#{currentCockpitEditorBean.projectName}" />
                             </p:button>
                             <p:separator/>
                             <p:button styleClass="perspective-button" icon="ui-icon-wrench" value="Cockpit Editor" style="white-space: none" disabled="true">
                             </p:button>
-                            <p:button styleClass="perspective-button" icon="ui-icon-image" value="Cockpit" style="white-space: none" outcome="Cockpit.xhtml">
+                            <p:button styleClass="perspective-button" icon="ui-icon-image" value="Cockpit" style="white-space: none" outcome="CockpitPage.xhtml">
                                 <f:param name="projectName" value="#{currentCockpitEditorBean.projectName}" />
                             </p:button>
                         </p:toolbarGroup>
@@ -101,30 +101,27 @@
 
             <p:layoutUnit position="center">
                 <h:form id="centerForm">
-                    <h:outputText value="Number of Columns: "/><br/>
-                    <h:outputText value="Description: " />  
-                    <p:inplace id="basic" editor="true">  
-                        <p:inputText value="#{currentCockpitEditorBean.activeView.description}" />  
-                    </p:inplace>  
-                    <br/>
-                    <hr/>
-                    <p:dataTable value="#{currentCockpitEditorBean.activeView.displayConnectors}" var="dispConn">
-                        <p:column headerText="Plugin" style="text-align: center">
-                            #{dispConn.display.parent.name}
-                        </p:column>
-                        <p:column headerText="Display Name" style="text-align: center">
-                            #{dispConn.display.name}
-                        </p:column>
-                        <p:column headerText="Name" style="text-align: center">
-                            <p:inplace id="basic" editor="true">  
-                                <p:inputText value="#{dispConn.name}" validator="#{currentCockpitEditorBean.validateDisplayConnectorName}" />
-                            </p:inplace>  
-                        </p:column>
-                        <p:column headerText="Column" style="text-align: center">
-                        </p:column>
-                        <p:column style="text-align: center; width: 50px" >
-                            <p:commandButton icon="ui-icon-trash" disabled="true"/>
+                    <ui:fragment rendered="#{not empty currentCockpitEditorBean.activeView}">
+                        <h:outputText value="Description: "/>  
+                        <p:inplace id="basic" editor="true">  
+                            <p:inputText value="#{currentCockpitEditorBean.activeView.description}" />  
+                        </p:inplace>  
+                        <br/>
+                        <hr/>
+                        <p:dashboard id="dynamicDashboard" binding="#{currentCockpitEditorBean.dashboard}"/>
+                    </ui:fragment>
+                </h:form>
+            </p:layoutUnit>
+
+            <!-- This is the component presenting the available properties. -->
+            <p:layoutUnit style="font-size: 12px" position="south" size="150" header="#{localizedMessages.properties}" resizable="true" collapsible="true">
+                <h:form id="propertiesForm" >
+                    <p:dataTable editable="true" var="property" rowIndexVar="rowIndex" emptyMessage="#{localizedMessages.noPropertiesAvailable}">
+                        <p:column headerText="#{localizedMessages.property}" style="width:125px"> 
                         </p:column>
+
+                        <p:column headerText="#{localizedMessages.value}" style="width:125px">
+                        </p:column>                       
                     </p:dataTable>
                 </h:form>
             </p:layoutUnit>
diff --git a/Kieker.WebGUI/src/main/webapp/ProjectOverviewPage.xhtml b/Kieker.WebGUI/src/main/webapp/ProjectOverviewPage.xhtml
index e7a2d9cb..47c1ed38 100644
--- a/Kieker.WebGUI/src/main/webapp/ProjectOverviewPage.xhtml
+++ b/Kieker.WebGUI/src/main/webapp/ProjectOverviewPage.xhtml
@@ -77,7 +77,7 @@
                                 <p:menuitem icon="ui-icon-analysis" id="controlAnalysis"  styleClass="element-with-whitespace" value="  #{localizedMessages.analysis}" ajax="false" url="controller?projectName=#{project}" />
                                 <p:separator/>
 
-                                <p:menuitem icon="ui-icon-cockpitEditor" id="editAnalysisViews"  styleClass="element-with-whitespace" value="  #{localizedMessages.cockpitEditor}" ajax="false" disabled="true" />
+                                <p:menuitem icon="ui-icon-cockpitEditor" id="editAnalysisViews"  styleClass="element-with-whitespace" value="  #{localizedMessages.cockpitEditor}" ajax="false" url="cockpitEditor?projectName=#{project}" />
                                 <p:menuitem icon="ui-icon-cockpit" id="showAnalysis"  styleClass="element-with-whitespace" value="  #{localizedMessages.cockpit}" ajax="false" disabled="true" />
                                 <p:separator/>
                                 <p:menuitem id="copyButton" icon="ui-icon-copy"  styleClass="element-with-whitespace" value="  #{localizedProjectOverviewMessages.copyProject}" action="#{currentProjectOverviewBean.setProjectName(project)}" onclick="copyProjectDialog.show()"/>
-- 
GitLab