/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* 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 org.libreplan.web.templates;
import static org.libreplan.web.I18nHelper._;
import static org.libreplan.web.planner.tabs.MultipleTabsPlannerController.BREADCRUMBS_SEPARATOR;
import java.util.List;
import javax.annotation.Resource;
import org.libreplan.business.calendars.entities.BaseCalendar;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.templates.entities.OrderElementTemplate;
import org.libreplan.business.templates.entities.OrderTemplate;
import org.libreplan.web.common.ConstraintChecker;
import org.libreplan.web.common.IMessagesForUser;
import org.libreplan.web.common.Level;
import org.libreplan.web.common.MessagesForUser;
import org.libreplan.web.common.OnlyOneVisible;
import org.libreplan.web.common.Util;
import org.libreplan.web.common.entrypoints.EntryPointsHandler;
import org.libreplan.web.common.entrypoints.IURLHandlerRegistry;
import org.libreplan.web.planner.tabs.IGlobalViewEntryPoints;
import org.libreplan.web.templates.advances.AdvancesAssignmentComponent;
import org.libreplan.web.templates.criterionrequirements.CriterionRequirementTemplateComponent;
import org.libreplan.web.templates.historicalAssignment.OrderElementHistoricalAssignmentComponent;
import org.libreplan.web.templates.historicalStatistics.OrderElementHistoricalStatisticsComponent;
import org.libreplan.web.templates.labels.LabelsAssignmentToTemplateComponent;
import org.libreplan.web.templates.materials.MaterialAssignmentTemplateComponent;
import org.libreplan.web.templates.quality.QualityFormAssignerComponent;
import org.libreplan.web.tree.TreeComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.spring.SpringUtil;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Image;
import org.zkoss.zul.Label;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Tabpanel;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Window;
/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
@org.springframework.stereotype.Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class OrderTemplatesController extends GenericForwardComposer implements IOrderTemplatesControllerEntryPoints {
private IOrderTemplatesModel model;
private OnlyOneVisible cachedOnlyOneVisible;
private Window listWindow;
private Window editWindow;
private Textbox name;
private IMessagesForUser messagesForUser;
private Component messagesContainer;
private TreeComponent treeComponent;
private EditTemplateWindowController editTemplateController;
@Resource
private IGlobalViewEntryPoints globalView;
@Autowired
private IURLHandlerRegistry handlerRegistry;
public OrderTemplatesController() {
model = (IOrderTemplatesModel) SpringUtil.getBean("orderTemplatesModel");
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
messagesForUser = new MessagesForUser(messagesContainer);
getVisibility().showOnly(listWindow);
final EntryPointsHandler<IOrderTemplatesControllerEntryPoints> handler =
handlerRegistry.getRedirectorFor(IOrderTemplatesControllerEntryPoints.class);
handler.register(this, page);
setBreadcrumbs(comp);
}
public List<OrderElementTemplate> getTemplates() {
return model.getRootTemplates();
}
private OnlyOneVisible getVisibility() {
if (cachedOnlyOneVisible == null) {
cachedOnlyOneVisible = new OnlyOneVisible(listWindow, editWindow);
}
return cachedOnlyOneVisible;
}
public OrderElementTemplate getTemplate() {
return model.getTemplate();
}
@Override
public void goToCreateTemplateFrom(OrderElement orderElement) {
model.createTemplateFrom(orderElement);
showEditWindow();
}
public void goToEditForm(OrderElementTemplate template) {
model.initEdit(template);
showEditWindow();
}
private void showEditWindow() {
// openTemplateTree is not called if it's the first tab shown
bindTemplatesTreeWithModel();
bindAdvancesComponentWithCurrentTemplate();
bindMaterialsControllerWithCurrentTemplate();
bindCriterionRequirementControllerWithCurrentTemplate();
bindLabelsControllerWithCurrentTemplate();
bindQualityFormWithCurrentTemplate();
bindEditTemplateWindowWithController();
bindHistoricalArragenmentWithCurrentTemplate();
bindHistoricalStatisticsWithCurrentTemplate();
show(editWindow);
}
private <T extends Component> T findAtEditWindow(String id, Class<T> type) {
return type.cast(editWindow.getFellow(id));
}
private void bindAdvancesComponentWithCurrentTemplate() {
AdvancesAssignmentComponent c = findAtEditWindow("advancesAssignment", AdvancesAssignmentComponent.class);
c.useModel(model);
}
private void bindMaterialsControllerWithCurrentTemplate() {
MaterialAssignmentTemplateComponent c =
findAtEditWindow("listOrderElementMaterials", MaterialAssignmentTemplateComponent.class);
c.getController().openWindow(model.getTemplate());
}
private void bindCriterionRequirementControllerWithCurrentTemplate() {
CriterionRequirementTemplateComponent c =
findAtEditWindow("listOrderElementCriterionRequirements", CriterionRequirementTemplateComponent.class);
c.getController().openWindow(model);
}
private void bindLabelsControllerWithCurrentTemplate() {
LabelsAssignmentToTemplateComponent c =
findAtEditWindow("listOrderElementLabels", LabelsAssignmentToTemplateComponent.class);
c.getController().openWindow(model);
}
private void bindQualityFormWithCurrentTemplate() {
QualityFormAssignerComponent c = findAtEditWindow("assignedQualityForms", QualityFormAssignerComponent.class);
c.useModel(model);
}
private void bindEditTemplateWindowWithController() {
Window editTemplateWindow = (Window) editWindow.getFellow("editTemplateWindow");
editTemplateController = EditTemplateWindowController.bindTo(model, editTemplateWindow);
}
private void bindHistoricalArragenmentWithCurrentTemplate() {
OrderElementHistoricalAssignmentComponent c =
(OrderElementHistoricalAssignmentComponent) editWindow.getFellow("historicalAssignment");
c.useModel(model, globalView);
}
private void bindHistoricalStatisticsWithCurrentTemplate() {
OrderElementHistoricalStatisticsComponent c =
(OrderElementHistoricalStatisticsComponent) editWindow.getFellow("historicalStatistics");
c.useModel(model);
}
public boolean isTemplateTreeDisabled() {
return model.isTemplateTreeDisabled();
}
private void show(Component window) {
Util.reloadBindings(window);
getVisibility().showOnly(window);
}
public void showEditionFor(OrderElementTemplate template) {
editTemplateController.open(template);
}
public void saveAndExit() {
if (isAllValid()) {
try {
model.confirmSave();
messagesForUser.showMessage(Level.INFO, _("Template saved"));
show(listWindow);
} catch (ValidationException e) {
messagesForUser.showInvalidValues(e);
}
}
}
public void cancel() {
show(listWindow);
}
public void saveAndContinue() {
if (isAllValid()) {
try {
model.confirmSave();
model.initEdit(getTemplate());
bindTemplatesTreeWithModel();
messagesForUser.showMessage(Level.INFO, _("Template saved"));
} catch (ValidationException e) {
messagesForUser.showInvalidValues(e);
}
}
}
private boolean isAllValid() {
// Validate template name
ConstraintChecker.isValid(editWindow);
name = (Textbox) editWindow.getFellowIfAny("name");
if ((name != null) && (!name.isValid())) {
selectTab("tabGeneralData");
showInvalidWorkReportTypeName();
return false;
}
if (model.getTemplate().isOrderTemplate()) {
OrderTemplate orderTemplate = (OrderTemplate) model.getTemplate();
if (orderTemplate.getCalendar() == null) {
throw new WrongValueException(editWindow.getFellow("calendar"), _("calendar not specified"));
}
}
return true;
}
private void selectTab(String str) {
Tab tab = (Tab) editWindow.getFellowIfAny(str);
if (tab != null) {
tab.setSelected(true);
}
}
private void showInvalidWorkReportTypeName() {
try {
model.validateTemplateName(name.getValue());
} catch (IllegalArgumentException e) {
throw new WrongValueException(name, _(e.getMessage()));
}
}
private void setBreadcrumbs(Component comp) {
Component breadcrumbs = comp.getPage().getFellow("breadcrumbs");
if (breadcrumbs.getChildren() != null) {
breadcrumbs.getChildren().clear();
}
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
breadcrumbs.appendChild(new Label(_("Planning")));
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
breadcrumbs.appendChild(new Label(_("Templates")));
}
/**
* Ensures that the tree component is correctly initialized.
* It's called from templates.zul page when selecting the tab.
* <p>
* Please not that this method is not called if the first tab shown is the templates tree tab.
* </p>
*/
public void openTemplateTree() {
if (treeComponent == null) {
final TemplatesTreeController treeController = new TemplatesTreeController(model, this);
treeComponent = (TreeComponent) editWindow.getFellow("orderElementTree");
treeComponent.useController(treeController);
controlSelectionWithOnClick(getTreeFrom(treeComponent));
treeController.setReadOnly(false);
setTreeRenderer(treeComponent);
}
bindTemplatesTreeWithModel();
}
private void bindTemplatesTreeWithModel() {
if (treeComponent == null) {
// If the tree is not initialized yet no bind has to be done
return;
}
treeComponent.getController().bindModelIfNeeded();
}
private Tree getTreeFrom(TreeComponent treeComponent) {
return (Tree) treeComponent.getFellowIfAny("tree");
}
private void controlSelectionWithOnClick(final Tree tree) {
// Undo the work done by this event to be able to control it from the ON_CLICK event
tree.addEventListener(Events.ON_SELECT, event -> tree.clearSelection());
}
private void setTreeRenderer(TreeComponent orderElementsTree) {
final Tree tree = (Tree) orderElementsTree.getFellowIfAny("tree");
tree.setItemRenderer(orderElementsTree.getController().getRenderer());
}
public Constraint validateTemplateName() {
return (comp, value) -> {
try {
model.validateTemplateName((String) value);
} catch (IllegalArgumentException e) {
throw new WrongValueException(comp, _(e.getMessage()));
}
};
}
/**
* Pop up confirm remove dialog.
*
* @param template
*/
public void confirmDelete(OrderElementTemplate template) {
if (Messagebox.show(
_("Delete template. Are you sure?"), _("Confirm"),
Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION) == Messagebox.OK) {
if (this.model.hasNotApplications(template)) {
this.model.confirmDelete(template);
Grid gridOrderTemplates = (Grid) listWindow.getFellowIfAny("listing");
if (gridOrderTemplates != null) {
Util.reloadBindings(gridOrderTemplates);
}
} else {
messagesForUser.showMessage(Level.ERROR, _("Template cannot be removed because it has applications"));
}
}
}
public boolean isContainer() {
return model.getTemplate() != null && !model.getTemplate().isLeaf();
}
public void reloadBudget() {
Tabpanel tabPanel = (Tabpanel) editWindow.getFellow("tabPanelGeneralData");
Util.reloadBindings(tabPanel);
}
public String getMoneyFormat() {
return Util.getMoneyFormat();
}
public boolean isOrderTemplate() {
return model.getTemplate() != null && model.getTemplate().isOrderTemplate();
}
public BaseCalendar getCalendar() {
return isOrderTemplate() ? ((OrderTemplate) model.getTemplate()).getCalendar() : null;
}
public void setCalendar(BaseCalendar calendar) {
if (isOrderTemplate()) {
((OrderTemplate) model.getTemplate()).setCalendar(calendar);
}
}
}