Added new 'Overall progress' chart

Rearrange code for creating and organizing tabs ('Load', 'Earned
value')

FEA: ItEr63OTS07ReporteAvancesCadeaCritica
This commit is contained in:
Diego Pino Garcia 2010-11-11 11:52:08 +01:00
parent d5c18c245e
commit 660a9ff088
3 changed files with 329 additions and 90 deletions

View file

@ -47,6 +47,7 @@ import org.joda.time.LocalDate;
import org.navalplanner.business.common.IAdHocTransactionService;
import org.navalplanner.business.common.IOnTransaction;
import org.navalplanner.business.common.daos.IConfigurationDAO;
import org.navalplanner.business.common.entities.ProgressType;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.orders.daos.IOrderDAO;
import org.navalplanner.business.orders.entities.HoursGroup;
@ -136,6 +137,7 @@ import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Constraint;
@ -143,6 +145,7 @@ import org.zkoss.zul.Datebox;
import org.zkoss.zul.Div;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.Progressmeter;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Tabbox;
import org.zkoss.zul.Tabpanel;
@ -271,6 +274,8 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel {
@Autowired
private ITaskSourceDAO taskSourceDAO;
private OverAllProgressContent overallProgressContent;
private final class ReturningNewAssignments implements
IAssignmentsOnResourceCalculator {
@ -369,34 +374,183 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel {
configureModificators(orderReloaded, configuration);
planner.setConfiguration(configuration);
Timeplot chartLoadTimeplot = createEmptyTimeplot();
Timeplot chartEarnedValueTimeplot = createEmptyTimeplot();
OrderEarnedValueChartFiller earnedValueChartFiller = new OrderEarnedValueChartFiller(
orderReloaded);
earnedValueChartFiller.calculateValues(planner.getTimeTracker()
.getRealInterval());
appendTabpanels(chartComponent, chartLoadTimeplot,
chartEarnedValueTimeplot, earnedValueChartFiller);
// Prepare tabpanels
Tabpanels chartTabpanels = new Tabpanels();
// Create 'Load' tab
Timeplot chartLoadTimeplot = createEmptyTimeplot();
chartTabpanels.appendChild(createLoadTimeplotTab(chartLoadTimeplot));
// Create 'Earned value' tab
Timeplot chartEarnedValueTimeplot = createEmptyTimeplot();
OrderEarnedValueChartFiller earnedValueChartFiller = createOrderEarnedValueChartFiller(planner.getTimeTracker());
chartTabpanels.appendChild(createEarnedValueTab(chartEarnedValueTimeplot, earnedValueChartFiller));
// Create 'Overall progress' tab
Hbox chartOverallProgressTimeplot = new Hbox();
chartTabpanels.appendChild(createOverallProgressTab(chartOverallProgressTimeplot));
// Append tab panels
chartComponent.appendChild(chartTabpanels);
setupLoadChart(chartLoadTimeplot, planner, configuration, saveCommand);
setupEarnedValueChart(chartEarnedValueTimeplot, earnedValueChartFiller, planner, configuration, saveCommand);
ProgressType progressType = configurationDAO.getConfiguration().getProgressType();
setupOverallProgress(chartComponent, progressType, planner, configuration, saveCommand);
Chart loadChart = setupChart(orderReloaded, new OrderLoadChartFiller(
orderReloaded), chartLoadTimeplot, planner);
refillLoadChartWhenNeeded(configuration, planner, saveCommand,
loadChart);
Chart earnedValueChart = setupChart(orderReloaded,
earnedValueChartFiller,
chartEarnedValueTimeplot, planner);
refillLoadChartWhenNeeded(configuration, planner, saveCommand,
earnedValueChart);
setEventListenerConfigurationCheckboxes(earnedValueChart);
planner.addGraphChangeListenersFromConfiguration(configuration);
}
private Tabpanel createOverallProgressTab(
Hbox chartOverallProgressTimeplot) {
Tabpanel result = new Tabpanel();
org.zkoss.zk.ui.Component component = Executions.createComponents(
"/planner/_tabPanelOverallProgress.zul", result, null);
component.setParent(result);
return result;
}
private Timeplot createEmptyTimeplot() {
Timeplot timeplot = new Timeplot();
timeplot.appendChild(new Plotinfo());
return timeplot;
}
private Tabpanel createLoadTimeplotTab(
Timeplot loadChart) {
Tabpanel result = new Tabpanel();
appendLoadChartAndLegend(result, loadChart);
return result;
}
private void appendLoadChartAndLegend(Tabpanel loadChartPannel,
Timeplot loadChart) {
Hbox hbox = new Hbox();
hbox.appendChild(getLoadChartLegend());
hbox.setSclass("load-chart");
Div div = new Div();
div.appendChild(loadChart);
div.setSclass("plannergraph");
hbox.appendChild(div);
loadChartPannel.appendChild(hbox);
}
private OrderEarnedValueChartFiller createOrderEarnedValueChartFiller(TimeTracker timeTracker) {
OrderEarnedValueChartFiller result = new OrderEarnedValueChartFiller(orderReloaded);
result.calculateValues(timeTracker.getRealInterval());
return result;
}
private Tabpanel createEarnedValueTab(
Timeplot chartEarnedValueTimeplot,
OrderEarnedValueChartFiller earnedValueChartFiller) {
Tabpanel result = new Tabpanel();
appendEarnedValueChartAndLegend(result, chartEarnedValueTimeplot,
earnedValueChartFiller);
return result;
}
private void appendEarnedValueChartAndLegend(
Tabpanel earnedValueChartPannel, Timeplot chartEarnedValueTimeplot,
final OrderEarnedValueChartFiller earnedValueChartFiller) {
Vbox vbox = new Vbox();
vbox.setClass("legend-container");
vbox.setAlign("center");
vbox.setPack("center");
Hbox dateHbox = new Hbox();
dateHbox.appendChild(new Label(_("Select date:")));
LocalDate initialDateForIndicatorValues = earnedValueChartFiller.initialDateForIndicatorValues();
Datebox datebox = new Datebox(initialDateForIndicatorValues
.toDateTimeAtStartOfDay().toDate());
datebox.setConstraint(dateMustBeInsideVisualizationArea(earnedValueChartFiller));
dateHbox.appendChild(datebox);
appendEventListenerToDateboxIndicators(earnedValueChartFiller, vbox,
datebox);
vbox.appendChild(dateHbox);
vbox.appendChild(getEarnedValueChartConfigurableLegend(
earnedValueChartFiller, initialDateForIndicatorValues));
Hbox hbox = new Hbox();
hbox.setSclass("earned-value-chart");
hbox.appendChild(vbox);
Div div = new Div();
div.appendChild(chartEarnedValueTimeplot);
div.setSclass("plannergraph");
hbox.appendChild(div);
earnedValueChartPannel.appendChild(hbox);
}
private void setupLoadChart(Timeplot chartLoadTimeplot, Planner planner,
PlannerConfiguration<TaskElement> configuration,
ISaveCommand saveCommand) {
Chart loadChart = setupChart(orderReloaded, new OrderLoadChartFiller(
orderReloaded), chartLoadTimeplot, planner);
refillLoadChartWhenNeeded(configuration, planner, saveCommand,
loadChart);
}
private void setupEarnedValueChart(Timeplot chartEarnedValueTimeplot,
OrderEarnedValueChartFiller earnedValueChartFiller,
Planner planner, PlannerConfiguration<TaskElement> configuration,
ISaveCommand saveCommand) {
Chart earnedValueChart = setupChart(orderReloaded,
earnedValueChartFiller, chartEarnedValueTimeplot, planner);
refillLoadChartWhenNeeded(configuration, planner, saveCommand,
earnedValueChart);
setEventListenerConfigurationCheckboxes(earnedValueChart);
}
private void setupOverallProgress(Tabbox chartComponent,
final ProgressType progressType, Planner planner, PlannerConfiguration<TaskElement> configuration,
ISaveCommand saveCommand) {
chartComponent.addEventListener(Events.ON_SELECT, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
Tab selectedTab = getSelectedTab((SelectEvent) event);
if (isOverAllProgressSelected(selectedTab)) {
if (overallProgressContent == null) {
final Tabpanel tabpanel = getSelectedPanel(selectedTab);
overallProgressContent = new OverAllProgressContent(tabpanel, progressType);
}
overallProgressContent.update();
}
}
private boolean isOverAllProgressSelected(Tab selectedTab) {
return selectedTab != null
&& selectedTab.getLabel().equals(_("Overall progress"));
}
private Tabpanel getSelectedPanel(Tab selectedTab) {
Tabbox tabbox = (Tabbox) selectedTab.getParent().getParent();
return tabbox.getSelectedPanel();
}
private Tab getSelectedTab(SelectEvent event) {
Set<Tab> tabs = event.getSelectedItems();
if (tabs != null) {
return tabs.iterator().next();
}
return null;
}
});
}
private void addPrintSupport(
PlannerConfiguration<TaskElement> configuration, final Order order) {
configuration.setPrintAction(new IPrintAction() {
@ -451,9 +605,6 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel {
return deadlineMarker;
}
public static IDetailItemModificator createBankHolidayMarker() {
return new BankHolidaysMarker();
}
@ -462,42 +613,12 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel {
Tabs chartTabs = new Tabs();
chartTabs.appendChild(new Tab(_("Load")));
chartTabs.appendChild(new Tab(_("Earned value")));
chartTabs.appendChild(new Tab(_("Overall progress")));
chartComponent.appendChild(chartTabs);
chartTabs.setSclass("charts-tabbox");
}
private void appendTabpanels(Tabbox chartComponent, Timeplot loadChart,
Timeplot chartEarnedValueTimeplot,
OrderEarnedValueChartFiller earnedValueChartFiller) {
Tabpanels chartTabpanels = new Tabpanels();
Tabpanel loadChartPannel = new Tabpanel();
appendLoadChartAndLegend(loadChartPannel, loadChart);
chartTabpanels.appendChild(loadChartPannel);
Tabpanel earnedValueChartPannel = new Tabpanel();
appendEarnedValueChartAndLegend(earnedValueChartPannel,
chartEarnedValueTimeplot, earnedValueChartFiller);
chartTabpanels.appendChild(earnedValueChartPannel);
chartComponent.appendChild(chartTabpanels);
}
private void appendLoadChartAndLegend(Tabpanel loadChartPannel,
Timeplot loadChart) {
Hbox hbox = new Hbox();
hbox.appendChild(getLoadChartLegend());
hbox.setSclass("load-chart");
Div div = new Div();
div.appendChild(loadChart);
div.setSclass("plannergraph");
hbox.appendChild(div);
loadChartPannel.appendChild(hbox);
}
private org.zkoss.zk.ui.Component getLoadChartLegend() {
Hbox hbox = new Hbox();
hbox.setClass("legend-container");
@ -508,44 +629,6 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel {
return hbox;
}
private void appendEarnedValueChartAndLegend(
Tabpanel earnedValueChartPannel, Timeplot chartEarnedValueTimeplot,
final OrderEarnedValueChartFiller earnedValueChartFiller) {
Vbox vbox = new Vbox();
vbox.setClass("legend-container");
vbox.setAlign("center");
vbox.setPack("center");
Hbox dateHbox = new Hbox();
dateHbox.appendChild(new Label(_("Select date:")));
LocalDate initialDateForIndicatorValues = earnedValueChartFiller.initialDateForIndicatorValues();
Datebox datebox = new Datebox(initialDateForIndicatorValues
.toDateTimeAtStartOfDay().toDate());
datebox.setConstraint(dateMustBeInsideVisualizationArea(earnedValueChartFiller));
dateHbox.appendChild(datebox);
appendEventListenerToDateboxIndicators(earnedValueChartFiller, vbox,
datebox);
vbox.appendChild(dateHbox);
vbox.appendChild(getEarnedValueChartConfigurableLegend(
earnedValueChartFiller, initialDateForIndicatorValues));
Hbox hbox = new Hbox();
hbox.setSclass("earned-value-chart");
hbox.appendChild(vbox);
Div div = new Div();
div.appendChild(chartEarnedValueTimeplot);
div.setSclass("plannergraph");
hbox.appendChild(div);
earnedValueChartPannel.appendChild(hbox);
}
private Constraint dateMustBeInsideVisualizationArea(
final OrderEarnedValueChartFiller earnedValueChartFiller) {
return new Constraint() {
@ -1448,4 +1531,72 @@ public abstract class OrderPlanningModel implements IOrderPlanningModel {
}
}
/**
*
* @author Diego Pino García<dpino@igalia.com>
*
* Helper class to show the content of a OverallProgress panel
*
*/
private class OverAllProgressContent {
private Progressmeter progressCriticalPathByDuration;
private Label lbCriticalPathByDuration;
private Progressmeter progressCriticalPathByNumHours;
private Label lbCriticalPathByNumHours;
private Progressmeter progressAdvancePercentage;
private Label lbAdvancePercentage;
public OverAllProgressContent(Tabpanel tabpanel, ProgressType progressType) {
progressCriticalPathByDuration = (Progressmeter) tabpanel.getFellowIfAny("progressCriticalPathByDuration");
lbCriticalPathByDuration = (Label) tabpanel.getFellowIfAny("lbCriticalPathByDuration");
progressCriticalPathByNumHours = (Progressmeter) tabpanel.getFellowIfAny("progressCriticalPathByNumHours");
lbCriticalPathByNumHours = (Label) tabpanel.getFellowIfAny("lbCriticalPathByNumHours");
progressAdvancePercentage = (Progressmeter) tabpanel.getFellowIfAny("progressAdvancePercentage");
lbAdvancePercentage = (Label) tabpanel.getFellowIfAny("lbAdvancePercentage");
}
public void update() {
TaskGroup rootTask = planningState.getRootTask();
setAdvancePercentage(rootTask.getAdvancePercentage());
setCriticalPathByDuration(rootTask.getCriticalPathProgressByDuration());
setCriticalPathByNumHours(rootTask.getCriticalPathProgressByNumHours());
}
private void setAdvancePercentage(BigDecimal value) {
if (value != null) {
value = value.multiply(BigDecimal.valueOf(100));
value = value.setScale(2, BigDecimal.ROUND_HALF_EVEN);
lbAdvancePercentage.setValue(value.toString() + " %");
progressAdvancePercentage.setValue(value.intValue());
}
}
public void setCriticalPathByDuration(BigDecimal value) {
if (value != null) {
value = value.multiply(BigDecimal.valueOf(100));
value = value.setScale(2, BigDecimal.ROUND_HALF_EVEN);
lbCriticalPathByDuration.setValue(value.toString() + " %");
progressCriticalPathByDuration.setValue(value.intValue());
}
}
public void setCriticalPathByNumHours(BigDecimal value) {
if (value != null) {
value = value.multiply(BigDecimal.valueOf(100));
value = value.setScale(2, BigDecimal.ROUND_HALF_EVEN);
lbCriticalPathByNumHours.setValue(value.toString() + " %");
progressCriticalPathByNumHours.setValue(value.intValue());
}
}
}
}

View file

@ -0,0 +1,59 @@
<!--
This file is part of NavalPlan
Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
Desenvolvemento Tecnolóxico de Galicia
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/>.
-->
<?taglib uri="/WEB-INF/tld/i18n.tld" prefix="i18n" ?>
<div sclass="plannergraph">
<vbox style="margin-left: 25px" >
<separator />
<!-- Advance percentage -->
<label style="font-weight: bold; font-size: 14px" value="${i18n:_('Spread progress')}" />
<hbox style="margin-top: 5px">
<progressmeter id="progressAdvancePercentage" style="margin-right: 5px" width="400px" />
<label id="lbAdvancePercentage" style="font-weight: bold; font-size: 14px" />
</hbox>
<separator />
<!-- Critical path by duration -->
<label style="font-weight: bold; font-size: 14px" value="${i18n:_('Critical path by duration')}" />
<hbox style="margin-top: 5px">
<progressmeter id="progressCriticalPathByDuration" style="margin-right: 5px" width="400px" />
<label id="lbCriticalPathByDuration" style="font-weight: bold; font-size: 14px" />
</hbox>
<separator />
<!-- Critical path by number of hours -->
<label style="font-weight: bold; font-size: 14px" value="${i18n:_('Critical path by number of hours')}" />
<hbox style="margin-top: 5px">
<progressmeter id="progressCriticalPathByNumHours" style="margin-right: 5px" width="400px" />
<label id="lbCriticalPathByNumHours" style="font-weight: bold; font-size: 14px" />
</hbox>
</vbox>
</div>

View file

@ -0,0 +1,29 @@
<!--
This file is part of NavalPlan
Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
Desenvolvemento Tecnolóxico de Galicia
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/>.
-->
<?taglib uri="/WEB-INF/tld/i18n.tld" prefix="i18n" ?>
<?component name="overallProgressContent"
macroURI="_contentOverallProgress.zul"
inline="true" ?>
<hbox sclass="load-chart">
<overallProgressContent id="overallProgressContent" />
</hbox>