Skip to content
Snippets Groups Projects
Commit 8cd0a325 authored by Nils Christian Ehmke's avatar Nils Christian Ehmke
Browse files

Further development of the cockpit editor.

parent 44ffb306
No related branches found
No related tags found
No related merge requests found
......@@ -16,18 +16,28 @@
package kieker.webgui.web.beans.view;
import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.AjaxBehaviorEvent;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import kieker.analysis.model.analysisMetaModel.MIAnalysisMetaModelFactory;
import kieker.analysis.model.analysisMetaModel.MIDisplay;
......@@ -52,15 +62,20 @@ import kieker.webgui.web.beans.application.GlobalPropertiesBean;
import kieker.webgui.web.beans.application.ProjectsBean;
import kieker.webgui.web.beans.session.UserBean;
import org.primefaces.component.behavior.ajax.AjaxBehavior;
import org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl;
import org.primefaces.component.dashboard.Dashboard;
import org.primefaces.component.panel.Panel;
import org.primefaces.context.RequestContext;
import org.primefaces.event.DashboardReorderEvent;
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;
import org.eclipse.emf.common.util.EList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
......@@ -79,7 +94,7 @@ public class CurrentCockpitEditorBean {
private static final int NUMBER_COLUMNS = 2;
private static final Log LOG = LogFactory.getLog(CurrentCockpitEditorBean.class);
private final MIAnalysisMetaModelFactory factory = new MAnalysisMetaModelFactory();
private final MIAnalysisMetaModelFactory factory = MAnalysisMetaModelFactory.eINSTANCE;
@Autowired
private IProjectService projectService;
......@@ -157,38 +172,50 @@ public class CurrentCockpitEditorBean {
final Application application = fc.getApplication();
// Add a panel for every display connector we have
final List<MIDisplayConnector> displayConnectors = this.activeView.getDisplayConnectors();
this.currId = 0;
for (final MIDisplayConnector connector : displayConnectors) {
final Panel panel = (Panel) application.createComponent(fc, "org.primefaces.component.Panel", "org.primefaces.component.PanelRenderer");
panel.setId("displayConnector_" + Integer.toString(this.connectors.get(connector)));
panel.setHeader(connector.getName());
panel.setClosable(true);
panel.setToggleable(false);
this.getDashboard().getChildren().add(panel);
final DashboardColumn column = this.dashboard.getModel().getColumn(0);
column.addWidget(panel.getId());
final HtmlOutputText text = new HtmlOutputText();
text.setValue(connector.getDisplay().getName());
panel.getChildren().add(text);
this.currId++;
for (int col = 0; col < 2; col++) {
final Collection<MIDisplayConnector> displayConnectors = this.getSortedDisplayConnectors(this.activeView.getDisplayConnectors(), col);
final DashboardColumn column = this.dashboard.getModel().getColumn(col);
for (final MIDisplayConnector connector : displayConnectors) {
final Panel panel = (Panel) application.createComponent(fc, "org.primefaces.component.Panel", "org.primefaces.component.PanelRenderer");
panel.setId("displayConnector_" + Integer.toString(this.connectors.get(connector)));
panel.setHeader(connector.getName());
panel.setClosable(true);
panel.setToggleable(false);
final AjaxBehavior behaviour = new AjaxBehavior();
behaviour.setProcess("@this");
behaviour.addAjaxBehaviorListener(new AjaxBehaviorListenerImpl() {
@Override
public void processAjaxBehavior(final AjaxBehaviorEvent event) throws AbortProcessingException {
System.out.println(((Panel) event.getSource()).getId());
}
});
panel.addClientBehavior("close", behaviour);
this.getDashboard().getChildren().add(panel);
column.addWidget(panel.getId());
final HtmlOutputText text = new HtmlOutputText();
text.setValue(connector.getDisplay().getName());
panel.getChildren().add(text);
this.currId++;
}
}
}
}
/**
* Clears the dashboard and removes all children within it.
*/
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();
private Collection<MIDisplayConnector> getSortedDisplayConnectors(final EList<MIDisplayConnector> eList, final int col) {
final List<MIDisplayConnector> l = new ArrayList<MIDisplayConnector>(Collections2.filter(eList, new ColumnPredicate(col)));
Collections.sort(l, new PosComparator());
return l;
}
/**
......@@ -206,6 +233,9 @@ public class CurrentCockpitEditorBean {
// Remember the current time! This is important for the later comparison of the time stamps.
this.resetTimeStamp();
this.reloadComponents();
this.stringToLayout(this.projectService.getCockpitLayout(this.projectName));
// Update the class loader and the specific classes used within various methods in this bean
this.fillDashboard();
}
......@@ -221,18 +251,10 @@ public class CurrentCockpitEditorBean {
}
}
/**
* Reloads the available components within this bean.
*/
private void reloadComponents() {
this.availableComponents = this.projectService.getAvailableComponents(this.projectName);
}
/**
* This method delivers the project stored in this bean.
*
* @return The project for this user.
*/
public MIProject getProject() {
return this.project;
}
......@@ -246,21 +268,10 @@ public class CurrentCockpitEditorBean {
return Collections.nCopies(3, null);
}
/**
* This method sets the project stored within this bean and returns the new page for the navigation.
*
* @param newName
* The name of the project.
*/
public void setProjectName(final String newName) {
this.projectName = newName;
}
/**
* This method delivers the project name stored in this bean.
*
* @return The project name for this user.
*/
public String getProjectName() {
return this.projectName;
}
......@@ -310,7 +321,7 @@ public class CurrentCockpitEditorBean {
public void saveProject(final boolean overwriteNewerProject) {
try {
this.projectService.saveProject(this.projectName, this.project, this.timeStamp, overwriteNewerProject, this.userBean.getUsername(), null,
this.projectService.getCockpitLayout(this.projectName));
this.layoutToString());
GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_INFO, this.globalPropertiesBean.getMsgProjectSaved());
// Update the time stamp!
this.resetTimeStamp();
......@@ -420,7 +431,7 @@ public class CurrentCockpitEditorBean {
final Application application = fc.getApplication();
final Panel panel = (Panel) application.createComponent(fc, "org.primefaces.component.Panel", "org.primefaces.component.PanelRenderer");
panel.setId("displayConnector_" + Integer.toString(this.connectors.get(connector)));
panel.setId(this.displayConnectorToID(connector));
panel.setHeader(connector.getName());
panel.setClosable(true);
panel.setToggleable(false);
......@@ -435,6 +446,33 @@ public class CurrentCockpitEditorBean {
this.currId++;
this.setModificationsFlag();
this.saveLayoutOfCurrentView();
}
}
private static final String ID_PREFIX = "displayConnector_";
final Map<MIView, Map<MIDisplayConnector, Point>> connectorPositions = new HashMap<MIView, Map<MIDisplayConnector, Point>>();
public void handleReorder(final DashboardReorderEvent event) {
this.saveLayoutOfCurrentView();
}
/**
* This method is used as a validator for new display connector names.
*
* @param context
* The context of the validation.
* @param toValidate
* The components which has be validated.
* @param value
* The new value.
*/
public void validateDisplayConnectorName(final FacesContext context, final UIComponent toValidate, final Object value) {
if ((value instanceof String) && (toValidate instanceof UIInput)) {
final boolean nameExists = this.existsDisplayConnectorName((String) value);
((UIInput) toValidate).setValid(!nameExists);
}
}
......@@ -465,6 +503,26 @@ public class CurrentCockpitEditorBean {
}
}
/**
* Getter for the property {@link CurrentCockpitEditorBean#dashboard}.
*
* @return The current value of the property.
*/
public Dashboard getDashboard() {
return this.dashboard;
}
/**
* Setter for the property {@link CurrentCockpitEditorBean#dashboard}.
*
* @param dashboard
* The new value for the property.
*/
public void setDashboard(final Dashboard dashboard) {
this.dashboard = dashboard;
this.dashboard.setModel(this.dashboardModel);
}
/**
* This method checks whether a display connector with the given name exists already.
*
......@@ -491,50 +549,108 @@ public class CurrentCockpitEditorBean {
return result;
}
/**
* This method is used as a validator for new display connector names.
*
* @param context
* The context of the validation.
* @param toValidate
* The components which has be validated.
* @param value
* The new value.
*/
public void validateDisplayConnectorName(final FacesContext context, final UIComponent toValidate, final Object value) {
if ((value instanceof String) && (toValidate instanceof UIInput)) {
final boolean nameExists = this.existsDisplayConnectorName((String) value);
((UIInput) toValidate).setValid(!nameExists);
private void clearDashboard() {
// Run through all columns of the dashboard model and remove the items
final List<DashboardColumn> columns = this.dashboard.getModel().getColumns();
for (final DashboardColumn column : columns) {
column.getWidgets().clear();
}
// Now remove the items from the dashboard
this.dashboard.getChildren().clear();
}
/**
* Getter for the property {@link CurrentCockpitEditorBean#dashboard}.
*
* @return The current value of the property.
*/
public Dashboard getDashboard() {
return this.dashboard;
private void saveLayoutOfCurrentView() {
if (this.activeView != null) {
final Map<MIDisplayConnector, Point> layout = new HashMap<MIDisplayConnector, Point>();
// Run through all columns and put the position of every widget into the map
int col = 0;
for (final DashboardColumn column : this.dashboardModel.getColumns()) {
int row = 0;
for (final String widgetID : column.getWidgets()) {
layout.put(this.idToDisplayConnector(widgetID), new Point(col, row));
row++;
}
col++;
}
// Store the map for the whole view
this.connectorPositions.put(this.activeView, layout);
}
}
/**
* Setter for the property {@link CurrentCockpitEditorBean#dashboard}.
*
* @param dashboard
* The new value for the property.
*/
public void setDashboard(final Dashboard dashboard) {
this.dashboard = dashboard;
this.dashboard.setModel(this.dashboardModel);
private void stringToLayout(final String layout) {
final String[] elements = layout.split(" ");
int i = 0;
for (final MIView view : this.project.getViews()) {
final Map<MIDisplayConnector, Point> positions = new HashMap<MIDisplayConnector, Point>();
this.connectorPositions.put(view, positions);
for (final MIDisplayConnector connector : view.getDisplayConnectors()) {
final Point pos = new Point(Integer.valueOf(elements[i]), Integer.valueOf(elements[i + 1]));
positions.put(connector, pos);
i += 2;
}
}
}
/**
* Delivers the available components.
*
* @return A list with the available components.
*/
public ComponentListContainer getAvailableComponents() {
return this.availableComponents;
private String layoutToString() {
final StringBuilder builder = new StringBuilder();
for (final MIView view : this.project.getViews()) {
final Map<MIDisplayConnector, Point> positions = this.connectorPositions.get(view);
for (final MIDisplayConnector connector : view.getDisplayConnectors()) {
final Point pos = positions.get(connector);
builder.append(pos.x);
builder.append(' ');
builder.append(pos.y);
builder.append(' ');
}
}
return builder.toString();
}
private String displayConnectorToID(final MIDisplayConnector displayConnector) {
return ID_PREFIX + this.connectors.get(displayConnector);
}
private MIDisplayConnector idToDisplayConnector(final String id) {
final String shortID = id.substring(ID_PREFIX.length());
final int intID = Integer.valueOf(shortID);
return this.connectors.get(intID);
}
private class PosComparator implements Comparator<MIDisplayConnector> {
@Override
public int compare(final MIDisplayConnector o1, final MIDisplayConnector o2) {
final int pos1 = CurrentCockpitEditorBean.this.connectorPositions.get(CurrentCockpitEditorBean.this.activeView).get(o1).y;
final int pos2 = CurrentCockpitEditorBean.this.connectorPositions.get(CurrentCockpitEditorBean.this.activeView).get(o2).y;
return pos1 - pos2;
}
}
private class ColumnPredicate implements Predicate<MIDisplayConnector> {
private final int col;
public ColumnPredicate(final int col) {
this.col = col;
}
@Override
public boolean apply(@Nullable final MIDisplayConnector key) {
return CurrentCockpitEditorBean.this.connectorPositions.get(CurrentCockpitEditorBean.this.activeView).get(key).x == this.col;
}
}
}
......@@ -36,7 +36,7 @@
<p:remoteCommand autoRun="false" name="nodeSelected" action="#{currentCockpitEditorBean.nodeSelected()}" update=":propertiesForm" />
</h:form>
</ui:define>
<ui:define name="js">
<!-- This javascript code will be executed in the onload-part of the body and shows a localized message via the growl-component. -->
<script>
......@@ -73,7 +73,9 @@
nodeSelected([{name : 'id', value : event.currentTarget.id}]);
});
</script>
<p:dashboard id="dynamicDashboard" binding="#{currentCockpitEditorBean.dashboard}"/>
<p:dashboard id="dynamicDashboard" binding="#{currentCockpitEditorBean.dashboard}">
<p:ajax event="reorder" listener="#{currentCockpitEditorBean.handleReorder}"/>
</p:dashboard>
</ui:fragment>
</h:form>
</ui:define>
......@@ -143,13 +145,13 @@
</ui:define>
<ui:define name="furtherDialogIncludes">
<p:confirmDialog id="confirmDialog" message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="closeConfirmation" >
<p:confirmDialog id="confirmDialog" message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="closeConfirmation" >
<h:form>
<p:commandButton id="confirm" value="#{localizedMessages.yes}" ajax="false" oncomplete="closeConfirmation.hide()" action="ProjectOverviewPage.xhtml?faces-redirect=true" />
<p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="closeConfirmation.hide()" type="button" />
</h:form>
</p:confirmDialog>
<!-- Include the dialogs for the views. -->
<ui:include src="../dialogs/CockpitEditorPageDialogs.xhtml" />
</ui:define>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment