package org.sigmah.client.ui.view.project.logframe; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.util.ArrayList; import java.util.Date; import java.util.List; import org.sigmah.client.i18n.I18N; import org.sigmah.client.ui.notif.N10N; import org.sigmah.client.ui.presenter.project.logframe.ProjectLogFramePresenter; import org.sigmah.client.ui.presenter.project.logframe.menu.ActionsMenu; import org.sigmah.client.ui.presenter.project.logframe.menu.GroupActionMenu; import org.sigmah.client.ui.presenter.project.logframe.menu.RowActionsMenu; import org.sigmah.client.ui.view.project.logframe.FormWindow.FormSubmitListener; import org.sigmah.client.ui.view.project.logframe.grid.FlexTableView; import org.sigmah.client.ui.view.project.logframe.grid.FlexTableView.FlexTableViewListener; import org.sigmah.client.ui.view.project.logframe.grid.HTMLTableUtils; import org.sigmah.client.ui.view.project.logframe.grid.Row; import org.sigmah.client.ui.view.project.logframe.grid.RowsGroup; import org.sigmah.client.ui.widget.WorkInProgressWidget; import org.sigmah.shared.dto.logframe.ExpectedResultDTO; import org.sigmah.shared.dto.logframe.LogFrameActivityDTO; import org.sigmah.shared.dto.logframe.LogFrameDTO; import org.sigmah.shared.dto.logframe.LogFrameGroupDTO; import org.sigmah.shared.dto.logframe.LogFrameModelDTO; import org.sigmah.shared.dto.logframe.PrerequisiteDTO; import org.sigmah.shared.dto.logframe.SpecificObjectiveDTO; import org.sigmah.shared.dto.referential.LogFrameGroupType; import com.extjs.gxt.ui.client.event.BaseEvent; import com.extjs.gxt.ui.client.event.ButtonEvent; import com.extjs.gxt.ui.client.event.Events; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.MessageBoxEvent; import com.extjs.gxt.ui.client.widget.Dialog; import com.extjs.gxt.ui.client.widget.MessageBox; import com.extjs.gxt.ui.client.widget.Slider; import com.extjs.gxt.ui.client.widget.Window; import com.extjs.gxt.ui.client.widget.button.Button; import com.extjs.gxt.ui.client.widget.form.DateField; import com.extjs.gxt.ui.client.widget.form.FormPanel; import com.extjs.gxt.ui.client.widget.form.TextField; import com.extjs.gxt.ui.client.widget.layout.FitLayout; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.event.dom.client.MouseOverEvent; import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.Widget; import com.google.inject.Inject; import org.sigmah.client.event.EventBus; import org.sigmah.client.ui.view.project.logframe.grid.IndicatorListWidget; /** * Represents a log frame grid. * * @author Tom Miette (tmiette@ideia.fr) (v1.3) * @author Denis Colliot (dcolliot@ideia.fr) (v2.0) */ public class ProjectLogFrameGrid implements IsWidget { /** * Manages log frame events. * * @author Tom Miette (tmiette@ideia.fr) (v1.3) * @author Denis Colliot (dcolliot@ideia.fr) (v2.0) */ public static interface LogFrameGridListener { /** * Method called when the log frame has been edited. */ void logFrameEdited(); } /** * CSS style name for the entire grid. */ private static final String CSS_LOG_FRAME_GRID_STYLE_NAME = "logframe-grid"; /** * CSS style name for the action button which add elements. */ private static final String CSS_ADD_ACTION_STYLE_NAME = CSS_LOG_FRAME_GRID_STYLE_NAME + "-add-action"; /** * CSS style name for the action button which add groups. */ private static final String CSS_ADD_GROUP_ACTION_STYLE_NAME = CSS_LOG_FRAME_GRID_STYLE_NAME + "-add-group-action"; /** * CSS style name for the labels which display codes. */ private static final String CSS_CODE_LABEL_STYLE_NAME = CSS_LOG_FRAME_GRID_STYLE_NAME + "-code-label"; /** * CSS style name for the labels which display codes (active state). */ private static final String CSS_CODE_LABEL_ACTIVE_STYLE_NAME = CSS_CODE_LABEL_STYLE_NAME + "-active"; /** * CSS style name for the menus buttons. */ private static final String CSS_MENU_BUTTON_STYLE_NAME = CSS_LOG_FRAME_GRID_STYLE_NAME + "-menu-button"; /** * CSS style name for the menus buttons (active state). */ private static final String CSS_MENU_BUTTON_ACTIVE_STYLE_NAME = CSS_MENU_BUTTON_STYLE_NAME + "-active"; /** * CSS style name for the HTML textbox. */ private static final String CSS_HTML_TEXTBOX = "html-textbox"; /** * Listeners. */ private final ArrayList<LogFrameGridListener> listeners; /** * The current displayed log frame. */ private LogFrameDTO logFrame; /** * The current displayed log frame model. */ private LogFrameModelDTO logFrameModel; /** * If the log frame is read only or not. */ private boolean readOnly; /** * The grid used to manage the log frame. */ public final FlexTable table; /** * The number of the columns in the log frame grid. */ private int columnsCount = 0; /** * The form window for adding elements. */ private final FormWindow formWindow; /** * A view of the flex table in charge of the specific objectives. */ private FlexTableView specificObjectivesView; /** * A view of the flex table in charge of the expected results. */ private FlexTableView expectedResultsView; /** * A view of the flex table in charge of the activities. */ private FlexTableView activitiesView; /** * A view of the flex table in charge of the prerequisites. */ private FlexTableView prerequisitesView; @Inject private EventBus eventBus; private int databaseId; /** * Builds an empty grid. */ public ProjectLogFrameGrid() { listeners = new ArrayList<LogFrameGridListener>(); table = new FlexTable(); formWindow = new FormWindow(); } /** * Registers a listener. * * @param l * The new listener. */ public void addListener(LogFrameGridListener l) { this.listeners.add(l); } /** * Unregisters a listener. * * @param l * The old listener. */ public void removeListener(LogFrameGridListener l) { this.listeners.remove(l); } /** * Informs the view that the log frame has been edited. */ protected void fireLogFrameEdited() { for (final LogFrameGridListener l : listeners) { l.logFrameEdited(); } } /** * {@inheritDoc} */ @Override public Widget asWidget() { return table; } /** * Clears table content. */ protected void resetTable() { table.clear(true); table.removeAllRows(); } /** * Checks if a log frame is currently displayed in the grid. If not, an exception is thrown. */ protected void ensureLogFrame() { if (logFrame == null) { throw new IllegalStateException("No log frame currently displayed. Specify a log frame before adding an element."); } } /** * Initializes table content. */ protected void initTable() { resetTable(); // Table parameters. table.setCellPadding(0); table.setCellSpacing(0); // Columns sizes. table.getColumnFormatter().setWidth(0, "100px"); table.getColumnFormatter().setWidth(1, "50px"); table.getColumnFormatter().setWidth(2, "50px"); table.getColumnFormatter().setWidth(3, "22%"); table.getColumnFormatter().setWidth(4, "18%"); table.getColumnFormatter().setWidth(5, "18%"); table.getColumnFormatter().setWidth(6, "22%"); // Columns headers labels. final Label interventionLogicLabel = new Label(I18N.CONSTANTS.logFrameInterventionLogic()); final Label indicatorsLabel = new Label(I18N.CONSTANTS.indicators()); final Label meansOfVerificationLabel = new Label(I18N.CONSTANTS.logFrameMeansOfVerification()); final Label risksAndAssumptionsLabel = new Label(I18N.CONSTANTS.logFrameRisksAndAssumptions()); table.getFlexCellFormatter().setColSpan(0, 1, 2); table.setWidget(0, 2, interventionLogicLabel); table.setWidget(0, 3, indicatorsLabel); table.setWidget(0, 4, meansOfVerificationLabel); table.setWidget(0, 5, risksAndAssumptionsLabel); // Rows headers labels (and actions). // Specific objectives. final Label specificObjectivesLabel = new Label(I18N.CONSTANTS.logFrameSpecificObjectives() + " (" + I18N.CONSTANTS.logFrameSpecificObjectivesCode() + ")"); final Label specificObjectivesButton = new Label(I18N.CONSTANTS.logFrameAddRow()); specificObjectivesButton.addStyleName(CSS_ADD_ACTION_STYLE_NAME); specificObjectivesButton.setTitle(I18N.CONSTANTS.logFrameAddOS()); specificObjectivesButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent e) { addSpecificObjective(); } }); final Label specificObjectivesGroupsButton = new Label(I18N.CONSTANTS.logFrameAddGroup()); specificObjectivesGroupsButton.addStyleName(CSS_ADD_GROUP_ACTION_STYLE_NAME); specificObjectivesGroupsButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent e) { addSpecificObjectivesGroup(); } }); // Are groups enabled ? if (!logFrameModel.getEnableSpecificObjectivesGroups()) { specificObjectivesGroupsButton.setVisible(false); } final Grid specificObjectivesGrid = new Grid(3, 1); specificObjectivesGrid.setWidth("100%"); specificObjectivesGrid.setCellPadding(0); specificObjectivesGrid.setCellSpacing(0); specificObjectivesGrid.setWidget(0, 0, specificObjectivesLabel); if (!readOnly) { specificObjectivesGrid.setWidget(1, 0, specificObjectivesButton); specificObjectivesGrid.setWidget(2, 0, specificObjectivesGroupsButton); } // Expected results. final Label exceptedResultsLabel = new Label(I18N.CONSTANTS.logFrameExceptedResults() + " (" + I18N.CONSTANTS.logFrameExceptedResultsCode() + ")"); final Label expectedResultsButton = new Label(I18N.CONSTANTS.logFrameAddRow()); expectedResultsButton.addStyleName(CSS_ADD_ACTION_STYLE_NAME); expectedResultsButton.setTitle(I18N.CONSTANTS.logFrameAddER()); expectedResultsButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent e) { addExpectedResult(); } }); final Label expectedResultsGroupsButton = new Label(I18N.CONSTANTS.logFrameAddGroup()); expectedResultsGroupsButton.addStyleName(CSS_ADD_GROUP_ACTION_STYLE_NAME); expectedResultsGroupsButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent e) { addExpectedResultsGroup(); } }); // Are groups enabled ? if (!logFrameModel.getEnableExpectedResultsGroups()) { expectedResultsGroupsButton.setVisible(false); } final Grid exceptedResultsGrid = new Grid(3, 1); exceptedResultsGrid.setWidth("100%"); exceptedResultsGrid.setCellPadding(0); exceptedResultsGrid.setCellSpacing(0); exceptedResultsGrid.setWidget(0, 0, exceptedResultsLabel); if (!readOnly) { exceptedResultsGrid.setWidget(1, 0, expectedResultsButton); exceptedResultsGrid.setWidget(2, 0, expectedResultsGroupsButton); } // Activities. final Label activitiesLabel = new Label(I18N.CONSTANTS.logFrameActivities()); final Label activitiesButton = new Label(I18N.CONSTANTS.logFrameAddRow()); activitiesButton.addStyleName(CSS_ADD_ACTION_STYLE_NAME); activitiesButton.setTitle(I18N.CONSTANTS.logFrameAddA()); activitiesButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent e) { addActivity(); } }); final Label activitiesGroupsButton = new Label(I18N.CONSTANTS.logFrameAddGroup()); activitiesGroupsButton.addStyleName(CSS_ADD_GROUP_ACTION_STYLE_NAME); activitiesGroupsButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent e) { addActivitiesGroup(); } }); // Are groups enabled ? if (!logFrameModel.getEnableActivitiesGroups()) { activitiesGroupsButton.setVisible(false); } final Grid activitiesGrid = new Grid(3, 1); activitiesGrid.setWidth("100%"); activitiesGrid.setCellPadding(0); activitiesGrid.setCellSpacing(0); activitiesGrid.setWidget(0, 0, activitiesLabel); if (!readOnly) { activitiesGrid.setWidget(1, 0, activitiesButton); activitiesGrid.setWidget(2, 0, activitiesGroupsButton); } // Prerequisites. final Label prerequisitesLabel = new Label(I18N.CONSTANTS.logFramePrerequisites()); final Label prerequisitesButton = new Label(I18N.CONSTANTS.logFrameAddRow()); prerequisitesButton.addStyleName(CSS_ADD_ACTION_STYLE_NAME); prerequisitesButton.setTitle(I18N.CONSTANTS.logFrameAddP()); prerequisitesButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent e) { addPrerequisite(); } }); final Label prerequisitesGroupButton = new Label(I18N.CONSTANTS.logFrameAddGroup()); prerequisitesGroupButton.addStyleName(CSS_ADD_GROUP_ACTION_STYLE_NAME); prerequisitesGroupButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent e) { addPrerequisitesGroup(); } }); // Are groups enabled ? if (!logFrameModel.getEnablePrerequisitesGroups()) { prerequisitesGroupButton.setVisible(false); } final Grid prerequisitesGrid = new Grid(3, 1); prerequisitesGrid.setWidth("100%"); prerequisitesGrid.setCellPadding(0); prerequisitesGrid.setCellSpacing(0); prerequisitesGrid.setWidget(0, 0, prerequisitesLabel); if (!readOnly) { prerequisitesGrid.setWidget(1, 0, prerequisitesButton); prerequisitesGrid.setWidget(2, 0, prerequisitesGroupButton); } table.setWidget(1, 0, specificObjectivesGrid); table.setWidget(2, 0, exceptedResultsGrid); table.setWidget(3, 0, activitiesGrid); table.setWidget(4, 0, prerequisitesGrid); // Header styles. HTMLTableUtils.applyHeaderStyles(table, true); // Initializes grid views. columnsCount = 7; specificObjectivesView = new FlexTableView(table, columnsCount, 1); expectedResultsView = new FlexTableView(table, columnsCount, 2); activitiesView = new FlexTableView(table, columnsCount, 3); prerequisitesView = new FlexTableView(table, columnsCount, 4); specificObjectivesView.addDependency(expectedResultsView); specificObjectivesView.addDependency(activitiesView); specificObjectivesView.addDependency(prerequisitesView); expectedResultsView.addDependency(activitiesView); expectedResultsView.addDependency(prerequisitesView); activitiesView.addDependency(prerequisitesView); // Views listeners. specificObjectivesView.addFlexTableViewListener(new FlexTableViewListener() { @Override public void rowRemoved(RowsGroup<?> group, Row<?> row) { // Checks if the max number of elements is reached. final Integer max = logFrameModel.getSpecificObjectivesMax(); if (max != null && max > 0 && max > specificObjectivesView.getRowsCount()) { specificObjectivesButton.setVisible(true); } } @Override public void rowAdded(RowsGroup<?> group, Row<?> row) { // Checks if the max number of elements is reached. final Integer max = logFrameModel.getSpecificObjectivesMax(); if (max != null && max > 0 && max <= specificObjectivesView.getRowsCount()) { specificObjectivesButton.setVisible(false); } } @Override public void groupAdded(RowsGroup<?> group) { // Checks if the max number of groups is reached. final Integer max = logFrameModel.getSpecificObjectivesGroupsMax(); if (max != null && max > 1 && max <= specificObjectivesView.getGroupsCount()) { specificObjectivesGroupsButton.setVisible(false); } } }); expectedResultsView.addFlexTableViewListener(new FlexTableViewListener() { @Override public void rowRemoved(RowsGroup<?> group, Row<?> row) { // Checks if the max number of elements is reached. final Integer max = logFrameModel.getExpectedResultsMax(); if (max != null && max > 0 && max > expectedResultsView.getRowsCount()) { expectedResultsButton.setVisible(true); } } @Override public void rowAdded(RowsGroup<?> group, Row<?> row) { // Checks if the max number of elements is reached. final Integer max = logFrameModel.getExpectedResultsMax(); if (max != null && max > 0 && max <= expectedResultsView.getRowsCount()) { expectedResultsButton.setVisible(false); } } @Override public void groupAdded(RowsGroup<?> group) { // Checks if the max number of groups is reached. final Integer max = logFrameModel.getExpectedResultsGroupsMax(); if (max != null && max > 1 && max <= expectedResultsView.getGroupsCount()) { expectedResultsGroupsButton.setVisible(false); } } }); activitiesView.addFlexTableViewListener(new FlexTableViewListener() { @Override public void rowRemoved(RowsGroup<?> group, Row<?> row) { // Checks if the max number of elements is reached. final Integer max = logFrameModel.getActivitiesMax(); if (max != null && max > 0 && max > activitiesView.getRowsCount()) { activitiesButton.setVisible(true); } } @Override public void rowAdded(RowsGroup<?> group, Row<?> row) { // Checks if the max number of elements is reached. final Integer max = logFrameModel.getActivitiesMax(); if (max != null && max > 0 && max <= activitiesView.getRowsCount()) { activitiesButton.setVisible(false); } } @Override public void groupAdded(RowsGroup<?> group) { // Checks if the max number of groups is reached. final Integer max = logFrameModel.getActivitiesGroupsMax(); if (max != null && max > 1 && max <= activitiesView.getGroupsCount()) { activitiesGroupsButton.setVisible(false); } } }); prerequisitesView.addFlexTableViewListener(new FlexTableViewListener() { @Override public void rowRemoved(RowsGroup<?> group, Row<?> row) { // Checks if the max number of elements is reached. final Integer max = logFrameModel.getPrerequisitesMax(); if (max != null && max > 0 && max > prerequisitesView.getRowsCount()) { prerequisitesButton.setVisible(true); } } @Override public void rowAdded(RowsGroup<?> group, Row<?> row) { // Checks if the max number of elements is reached. final Integer max = logFrameModel.getPrerequisitesMax(); if (max != null && max > 0 && max <= prerequisitesView.getRowsCount()) { prerequisitesButton.setVisible(false); } } @Override public void groupAdded(RowsGroup<?> group) { // Checks if the max number of groups is reached. final Integer max = logFrameModel.getPrerequisitesGroupsMax(); if (max != null && max > 1 && max <= prerequisitesView.getGroupsCount()) { prerequisitesGroupButton.setVisible(false); } } }); } /** * Displays the log frame content in the log frame grid (specific objectives, expected results, prerequisites, * activities); * * @param databaseId * The database id. * @param logFrame * The log frame. */ public void displayLogFrame(int databaseId, LogFrameDTO logFrame) { displayLogFrame(databaseId, logFrame, true); } /** * Displays the log frame content in the log frame grid (specific objectives, expected results, prerequisites, * activities); * * @param databaseId * The database id. * @param logFrame * The log frame. * @param enabled * If the log frame is read only or not. */ public void displayLogFrame(int databaseId, LogFrameDTO logFrame, boolean enabled) { this.logFrame = logFrame; this.databaseId = databaseId; this.logFrameModel = logFrame.getLogFrameModel(); this.readOnly = !enabled; ensureLogFrame(); resetTable(); initTable(); // Displays all the groups (even the empty ones). for (final LogFrameGroupDTO group : logFrame.getGroups()) { switch (group.getType()) { case SPECIFIC_OBJECTIVE: if (logFrameModel.getEnableSpecificObjectivesGroups()) { addSpecificObjectivesGroup(group); } break; case EXPECTED_RESULT: if (logFrameModel.getEnableExpectedResultsGroups()) { addExpectedResultsGroup(group); } break; case PREREQUISITE: if (logFrameModel.getEnablePrerequisitesGroups()) { addPrerequisitesGroup(group); } break; case ACTIVITY: if (logFrameModel.getEnableActivitiesGroups()) { addActivitiesGroup(group); } break; } } // Displays the specific objectives (and recursively the expected // results and the activities). for (final SpecificObjectiveDTO objective : logFrame.getSpecificObjectives()) { addSpecificObjective(objective); } // Displays the prerequisietes. for (final PrerequisiteDTO prerequisite : logFrame.getPrerequisites()) { addPrerequisite(prerequisite); } } /** * Updates the log frame instance of the grid after an updating. * * @param logFrame * The updated log frame. */ public void updateLogFrame(LogFrameDTO logFrame) { // For the moment, each save action requires rebuilding the whole log // frame. Its needed to update the ids of the new entities in the local // maps. // TODO optimize this displayLogFrame(databaseId, logFrame); // this.logFrame = logFrame; // this.logFrameModel = logFrame.getLogFrameModelDTO(); } // ------------------------------------------------------------------------ // - SPECIFIC OBJECTIVES // ------------------------------------------------------------------------ // ------------------------ // -- GROUPS // ------------------------ /** * Creates a new display group for the specific objectives. */ protected void addSpecificObjectivesGroup() { ensureLogFrame(); // Checks if the model allows groups. if (!logFrameModel.getEnableSpecificObjectivesGroups()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameGroupsDisabledOS()); return; } // Checks if the max number of groups is reached. final Integer max = logFrameModel.getSpecificObjectivesGroupsMax(); if (max != null && max > 1 && max <= specificObjectivesView.getGroupsCount()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameGroupsMaxReachedOS()); return; } // Asks for the new group label. MessageBox.prompt(I18N.CONSTANTS.logFrameAddGroup(), I18N.CONSTANTS.logFrameAddGroupToOS(), false, new Listener<MessageBoxEvent>() { @Override public void handleEvent(MessageBoxEvent be) { // OK. if (Dialog.OK.equals(be.getButtonClicked().getItemId())) { String label = ProjectLogFramePresenter.DEFAULT_GROUP_LABEL; if (be.getValue() != null) { label = be.getValue(); } // Creates the new group. final LogFrameGroupDTO group = logFrame.addGroup(label, LogFrameGroupType.SPECIFIC_OBJECTIVE); // Displays it. addSpecificObjectivesGroup(group); } } }); } /** * Adds a new display group for the specific objectives. * * @param group * The specific objectives groups. * @return The just created group. */ private RowsGroup<LogFrameGroupDTO> addSpecificObjectivesGroup(final LogFrameGroupDTO group) { ensureLogFrame(); final RowsGroup<LogFrameGroupDTO> g = new RowsGroup<LogFrameGroupDTO>(group) { @Override public String getTitle(LogFrameGroupDTO userObject) { // Builds the title (prefix + label). final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFrameGroup()); sb.append(" ("); sb.append(I18N.CONSTANTS.logFrameSpecificObjectivesCode()); sb.append(") - "); sb.append(userObject.getLabel()); return sb.toString(); } @Override public int getId(LogFrameGroupDTO userObject) { return userObject.getClientSideId(); } @Override public int[] getMergedColumnIndexes(LogFrameGroupDTO userObject) { return new int[] { 1 }; } @Override public boolean isVisible(LogFrameGroupDTO userObject) { return logFrameModel.getEnableSpecificObjectivesGroups(); } @Override public Widget getWidget() { // Displays the group's label. final Label label = new Label(getTitle()); // Grid. final Grid grid = new Grid(1, 2); grid.setCellPadding(0); grid.setCellSpacing(0); grid.setWidget(0, 0, label); if (!readOnly) { grid.setWidget(0, 1, buildGroupMenu(specificObjectivesView, this, label)); } return grid; } }; // Adds a new group. specificObjectivesView.addGroup(g); fireLogFrameEdited(); return g; } // ------------------------ // -- ROWS // ------------------------ /** * Adds a new specific objective empty row. */ protected void addSpecificObjective() { ensureLogFrame(); // Checks if the max number of elements is reached. final Integer max = logFrameModel.getSpecificObjectivesMax(); if (max != null && max > 0 && max <= specificObjectivesView.getRowsCount()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameMaxReachedOS()); return; } // Must select a group. if (logFrameModel.getEnableSpecificObjectivesGroups()) { // Sets the form window. formWindow.clear(); formWindow.addChoicesList(I18N.CONSTANTS.logFrameGroup(), logFrame.getAllGroupsNotDeleted(LogFrameGroupType.SPECIFIC_OBJECTIVE), false, "label"); formWindow.addFormSubmitListener(new FormSubmitListener() { @Override public void formSubmitted(Object... elements) { // Checks that the values are correct. final Object element = elements[0]; if (!(element instanceof LogFrameGroupDTO)) { return; } // Retrieves the selected group. final LogFrameGroupDTO group = (LogFrameGroupDTO) element; // Creates and displays a new objective. final SpecificObjectiveDTO objective = logFrame.addSpecificObjective(); objective.setGroup(group); addSpecificObjective(objective); } }); formWindow.show(I18N.CONSTANTS.logFrameAddOS(), I18N.CONSTANTS.logFrameSelectGroupOS()); } // Groups are disabled, no need to select a group, the default one will // be selected. else { // Retrieves the default group. final LogFrameGroupDTO group = logFrame.getDefaultGroup(LogFrameGroupType.SPECIFIC_OBJECTIVE); // Creates and displays a new objective. final SpecificObjectiveDTO objective = logFrame.addSpecificObjective(); objective.setGroup(group); addSpecificObjective(objective); } } /** * Adds a specific objective row. * * @param specificObjective * The specific objective. Must not be <code>null</code>. */ private void addSpecificObjective(final SpecificObjectiveDTO specificObjective) { // Checks if the objective is correct. if (specificObjective == null) { throw new NullPointerException("specific objective must not be null"); } // Retrieves the group. final LogFrameGroupDTO logFrameGroup = specificObjective.getGroup(); // Retrieves the equivalent rows group. @SuppressWarnings("unchecked") RowsGroup<LogFrameGroupDTO> g = (RowsGroup<LogFrameGroupDTO>) specificObjectivesView.getGroup(logFrameGroup.getClientSideId()); // If the rows hasn't been created already, adds it. if (g == null) { g = addSpecificObjectivesGroup(logFrameGroup); } // Sets the display label. final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFrameSpecificObjectivesCode()); sb.append(" "); sb.append(specificObjective.getFormattedCode()); specificObjective.setLabel(sb.toString()); // Sets the position the last if it doesn't exist. if (specificObjective.getPosition() == null) { specificObjective.setPosition(g.getRowsCount() + 1); } // Adds the row. specificObjectivesView.insertRow(specificObjective.getPosition(), logFrameGroup.getClientSideId(), new Row<SpecificObjectiveDTO>(specificObjective) { @Override public boolean isSimilar(int column, SpecificObjectiveDTO userObject, SpecificObjectiveDTO other) { switch (column) { case 1: // Code. return userObject.getCode().equals(other.getCode()); } return false; } @Override public Widget getWidgetAt(int column, final SpecificObjectiveDTO userObject) { switch (column) { case 0: // Parent code. return null; case 1: // Code. final Label codeLabel = new Label(); codeLabel.addStyleName(CSS_CODE_LABEL_STYLE_NAME); if (userObject != null) { codeLabel.setText(userObject.getLabel()); } // Grid. final Grid grid = new Grid(1, 2); grid.setCellPadding(0); grid.setCellSpacing(0); grid.setWidget(0, 0, codeLabel); if (!readOnly) { grid.setWidget(0, 1, buildSpecificObjectiveMenu(this, codeLabel)); } return grid; case 2: // Intervention logic. final TextArea interventionLogicTextBox = new TextArea(); interventionLogicTextBox.setWidth("100%"); interventionLogicTextBox.setHeight("100%"); interventionLogicTextBox.setVisibleLines(3); interventionLogicTextBox.addStyleName(CSS_HTML_TEXTBOX); interventionLogicTextBox.setEnabled(!readOnly); if (userObject != null) { interventionLogicTextBox.setText(userObject.getInterventionLogic()); } interventionLogicTextBox.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent e) { userObject.setInterventionLogic(interventionLogicTextBox.getText()); fireLogFrameEdited(); } }); return interventionLogicTextBox; case 4: // Indicators. final IndicatorListWidget indicatorListWidget = new IndicatorListWidget(eventBus, databaseId, specificObjective); indicatorListWidget.addValueChangeHandler(new ValueChangeHandler<Void>() { @Override public void onValueChange(ValueChangeEvent<Void> event) { fireLogFrameEdited(); } }); return indicatorListWidget; case 5: // Risks and Assumptions. final TextArea risksAssumptionsTextBox = new TextArea(); risksAssumptionsTextBox.setWidth("100%"); risksAssumptionsTextBox.setHeight("100%"); risksAssumptionsTextBox.setVisibleLines(3); risksAssumptionsTextBox.addStyleName(CSS_HTML_TEXTBOX); risksAssumptionsTextBox.setEnabled(!readOnly); if (userObject != null) { risksAssumptionsTextBox.setText(userObject.getRisksAndAssumptions()); } risksAssumptionsTextBox.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent e) { userObject.setRisksAndAssumptions(risksAssumptionsTextBox.getText()); fireLogFrameEdited(); } }); return risksAssumptionsTextBox; default: return null; } } @Override public int getId(SpecificObjectiveDTO userObject) { return userObject.getClientSideId(); } }); fireLogFrameEdited(); // Adds sub expected results. for (final ExpectedResultDTO result : specificObjective.getExpectedResults()) { addExpectedResult(result); } } // ------------------------------------------------------------------------ // - EXPECTED RESULTS // ------------------------------------------------------------------------ // ------------------------ // -- GROUPS // ------------------------ /** * Creates a new display group for the expected results. */ protected void addExpectedResultsGroup() { ensureLogFrame(); // Checks if the model allows groups. if (!logFrameModel.getEnableExpectedResultsGroups()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameGroupsDisabledER()); return; } // Checks if the max number of groups is reached. final Integer max = logFrameModel.getExpectedResultsGroupsMax(); if (max != null && max > 1 && max <= expectedResultsView.getGroupsCount()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameGroupsMaxReachedER()); return; } // Asks for the new group label. MessageBox.prompt(I18N.CONSTANTS.logFrameAddGroup(), I18N.CONSTANTS.logFrameAddGroupToER(), false, new Listener<MessageBoxEvent>() { @Override public void handleEvent(MessageBoxEvent be) { // OK. if (Dialog.OK.equals(be.getButtonClicked().getItemId())) { String label = ProjectLogFramePresenter.DEFAULT_GROUP_LABEL; if (be.getValue() != null) { label = be.getValue(); } // Creates the new group. final LogFrameGroupDTO group = logFrame.addGroup(label, LogFrameGroupType.EXPECTED_RESULT); // Displays it. addExpectedResultsGroup(group); } } }); } /** * Adds a new display group for the expected results. * * @param group * The expected results groups. * @return The just created group. */ private RowsGroup<LogFrameGroupDTO> addExpectedResultsGroup(final LogFrameGroupDTO group) { ensureLogFrame(); final RowsGroup<LogFrameGroupDTO> g = new RowsGroup<LogFrameGroupDTO>(group) { @Override public String getTitle(LogFrameGroupDTO userObject) { // Builds the title (prefix + label). final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFrameGroup()); sb.append(" ("); sb.append(I18N.CONSTANTS.logFrameExceptedResultsCode()); sb.append(") - "); sb.append(userObject.getLabel()); return sb.toString(); } @Override public int getId(LogFrameGroupDTO userObject) { return userObject.getClientSideId(); } @Override public int[] getMergedColumnIndexes(LogFrameGroupDTO userObject) { return new int[] { 0 }; } @Override public boolean isVisible(LogFrameGroupDTO userObject) { return logFrameModel.getEnableExpectedResultsGroups(); } @Override public Widget getWidget() { // Displays the group's label. final Label label = new Label(getTitle()); // Grid. final Grid grid = new Grid(1, 2); grid.setCellPadding(0); grid.setCellSpacing(0); grid.setWidget(0, 0, label); if (!readOnly) { grid.setWidget(0, 1, buildGroupMenu(expectedResultsView, this, label)); } return grid; } }; // Adds a new group. expectedResultsView.addGroup(g); fireLogFrameEdited(); return g; } // ------------------------ // -- ROWS // ------------------------ /** * Adds a new expected result empty row. */ protected void addExpectedResult() { ensureLogFrame(); // Checks if the max number of elements is reached. final Integer max = logFrameModel.getExpectedResultsMax(); if (max != null && max > 0 && max <= expectedResultsView.getRowsCount()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameMaxReachedER()); return; } final List<SpecificObjectiveDTO> objectives = logFrame.getSpecificObjectives(); // Checks if there is at least one available specific objective. if (objectives.isEmpty()) { N10N.warn(I18N.CONSTANTS.logFrameNoSpecificObjective(), I18N.CONSTANTS.logFrameNoSpecificObjectiveDetails()); return; } // Must select a group. if (logFrameModel.getEnableExpectedResultsGroups()) { // Sets the form window. formWindow.clear(); formWindow.addChoicesList(I18N.CONSTANTS.logFrameSpecificObjective(), objectives, false, "label"); formWindow.addChoicesList(I18N.CONSTANTS.logFrameGroup(), logFrame.getAllGroupsNotDeleted(LogFrameGroupType.EXPECTED_RESULT), false, "label"); formWindow.addFormSubmitListener(new FormSubmitListener() { @Override public void formSubmitted(Object... elements) { // Checks that the values are correct. final Object element0 = elements[0]; if (!(element0 instanceof SpecificObjectiveDTO)) { return; } final Object element1 = elements[1]; if (!(element1 instanceof LogFrameGroupDTO)) { return; } // Retrieves the selected OS and group. final SpecificObjectiveDTO specificObjective = (SpecificObjectiveDTO) element0; final LogFrameGroupDTO group = (LogFrameGroupDTO) element1; // Creates and displays a new objective. final ExpectedResultDTO result = specificObjective.addExpectedResult(); result.setGroup(group); addExpectedResult(result); } }); formWindow.show(I18N.CONSTANTS.logFrameAddER(), I18N.CONSTANTS.logFrameSelectGroupER()); } // Groups are disabled, no need to select a group, the default one will // be selected. else { // Sets the form window. formWindow.clear(); formWindow.addChoicesList(I18N.CONSTANTS.logFrameSpecificObjective(), logFrame.getSpecificObjectives(), false, "label"); formWindow.addFormSubmitListener(new FormSubmitListener() { @Override public void formSubmitted(Object... elements) { // Checks that the values are correct. final Object element0 = elements[0]; if (!(element0 instanceof SpecificObjectiveDTO)) { return; } // Retrieves the selected OS. final SpecificObjectiveDTO specificObjective = (SpecificObjectiveDTO) element0; // Retrieves the default group. final LogFrameGroupDTO group = logFrame.getDefaultGroup(LogFrameGroupType.EXPECTED_RESULT); // Creates and displays a new objective. final ExpectedResultDTO result = specificObjective.addExpectedResult(); result.setGroup(group); addExpectedResult(result); } }); formWindow.show(I18N.CONSTANTS.logFrameAddER(), I18N.CONSTANTS.logFrameSelectGroup2ER()); } } /** * Adds an activity row. * * @param result * The expected result. Must not be <code>null</code>. */ private void addExpectedResult(final ExpectedResultDTO result) { // Checks if the result is correct. if (result == null) { throw new NullPointerException("result must not be null"); } // Retrieves the group. final LogFrameGroupDTO group = result.getGroup(); // Retrieves the equivalent rows group. @SuppressWarnings("unchecked") RowsGroup<LogFrameGroupDTO> g = (RowsGroup<LogFrameGroupDTO>) expectedResultsView.getGroup(group.getClientSideId()); // If the rows hasn't been created already, adds it. if (g == null) { g = addExpectedResultsGroup(group); } // Sets the display label. final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFrameExceptedResultsCode()); sb.append(" "); sb.append(result.getFormattedCode()); result.setLabel(sb.toString()); // Sets the position the last if it doesn't exist. if (result.getPosition() == null) { result.setPosition(g.getRowsCount() + 1); } // Adds the row. expectedResultsView.insertRow(result.getPosition(), group.getClientSideId(), new Row<ExpectedResultDTO>(result) { @Override public boolean isSimilar(int column, ExpectedResultDTO userObject, ExpectedResultDTO other) { switch (column) { case 0: // Parent code. return userObject.getParentSpecificObjective() != null && other.getParentSpecificObjective() != null && userObject.getParentSpecificObjective().getCode().equals(other.getParentSpecificObjective().getCode()); } return false; } @Override public Widget getWidgetAt(int column, final ExpectedResultDTO userObject) { switch (column) { case 0: // Parent code. final Label parentCodeLabel = new Label(); parentCodeLabel.addStyleName(CSS_CODE_LABEL_STYLE_NAME); final SpecificObjectiveDTO parent; if (userObject != null && (parent = userObject.getParentSpecificObjective()) != null) { final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFrameExceptedResultsCode()); sb.append(" ("); sb.append(I18N.CONSTANTS.logFrameSpecificObjectivesCode()); sb.append(" "); sb.append(parent.getFormattedCode()); sb.append(")"); parentCodeLabel.setText(sb.toString()); } return parentCodeLabel; case 1: // Code. final Label codeLabel = new Label(); codeLabel.addStyleName(CSS_CODE_LABEL_STYLE_NAME); if (userObject != null) { codeLabel.setText(userObject.getLabel()); } // Grid. final Grid grid = new Grid(1, 2); grid.setCellPadding(0); grid.setCellSpacing(0); grid.setWidget(0, 0, codeLabel); if (!readOnly) { grid.setWidget(0, 1, buildExpectedResultMenu(this, codeLabel)); } return grid; case 2: // Intervention logic. final TextArea interventionLogicTextBox = new TextArea(); interventionLogicTextBox.setWidth("100%"); interventionLogicTextBox.setHeight("100%"); interventionLogicTextBox.setVisibleLines(3); interventionLogicTextBox.addStyleName(CSS_HTML_TEXTBOX); interventionLogicTextBox.setEnabled(!readOnly); if (userObject != null) { interventionLogicTextBox.setText(userObject.getInterventionLogic()); } interventionLogicTextBox.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent e) { userObject.setInterventionLogic(interventionLogicTextBox.getText()); fireLogFrameEdited(); } }); return interventionLogicTextBox; case 4: // Indicators. final IndicatorListWidget indicatorListWidget = new IndicatorListWidget(eventBus, databaseId, result); indicatorListWidget.addValueChangeHandler(new ValueChangeHandler<Void>() { @Override public void onValueChange(ValueChangeEvent<Void> event) { fireLogFrameEdited(); } }); return indicatorListWidget; case 5: // Risks and Assumptions. final TextArea risksAssumptionsTextBox = new TextArea(); risksAssumptionsTextBox.setWidth("100%"); risksAssumptionsTextBox.setHeight("100%"); risksAssumptionsTextBox.setVisibleLines(3); risksAssumptionsTextBox.addStyleName(CSS_HTML_TEXTBOX); risksAssumptionsTextBox.setEnabled(!readOnly); if (userObject != null) { risksAssumptionsTextBox.setText(userObject.getRisksAndAssumptions()); } risksAssumptionsTextBox.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent e) { userObject.setRisksAndAssumptions(risksAssumptionsTextBox.getText()); fireLogFrameEdited(); } }); return risksAssumptionsTextBox; default: return null; } } @Override public int getId(ExpectedResultDTO userObject) { return userObject.getClientSideId(); } }); fireLogFrameEdited(); // Adds sub activities. for (final LogFrameActivityDTO activity : result.getActivities()) { addActivity(activity); } } // ------------------------------------------------------------------------ // - ACTIVITIES // ------------------------------------------------------------------------ // ------------------------ // -- GROUPS // ------------------------ /** * Creates a new display group for the activities. */ protected void addActivitiesGroup() { ensureLogFrame(); // Checks if the model allows groups. if (!logFrameModel.getEnableActivitiesGroups()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameGroupsDisabledA()); return; } // Checks if the max number of groups is reached. final Integer max = logFrameModel.getActivitiesGroupsMax(); if (max != null && max > 1 && max <= activitiesView.getGroupsCount()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameGroupsMaxReachedA()); return; } // Asks for the new group label. MessageBox.prompt(I18N.CONSTANTS.logFrameAddGroup(), I18N.CONSTANTS.logFrameAddGroupToA(), false, new Listener<MessageBoxEvent>() { @Override public void handleEvent(MessageBoxEvent be) { // OK. if (Dialog.OK.equals(be.getButtonClicked().getItemId())) { String label = ProjectLogFramePresenter.DEFAULT_GROUP_LABEL; if (be.getValue() != null) { label = be.getValue(); } // Creates the new group. final LogFrameGroupDTO group = logFrame.addGroup(label, LogFrameGroupType.ACTIVITY); // Displays it. addActivitiesGroup(group); } } }); } /** * Adds a new display group for the activities. * * @param group * The activities group. * @return The just created group. */ private RowsGroup<LogFrameGroupDTO> addActivitiesGroup(final LogFrameGroupDTO group) { ensureLogFrame(); final RowsGroup<LogFrameGroupDTO> g = new RowsGroup<LogFrameGroupDTO>(group) { @Override public String getTitle(LogFrameGroupDTO userObject) { // Builds the title (prefix + label). final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFrameGroup()); sb.append(" ("); sb.append(I18N.CONSTANTS.logFrameActivitiesCode()); sb.append(") - "); sb.append(userObject.getLabel()); return sb.toString(); } @Override public int getId(LogFrameGroupDTO userObject) { return userObject.getClientSideId(); } @Override public int[] getMergedColumnIndexes(LogFrameGroupDTO userObject) { return new int[] { 0 }; } @Override public boolean isVisible(LogFrameGroupDTO userObject) { return logFrameModel.getEnableActivitiesGroups(); } @Override public Widget getWidget() { // Displays the group's label. final Label label = new Label(getTitle()); // Grid. final Grid grid = new Grid(1, 2); grid.setCellPadding(0); grid.setCellSpacing(0); grid.setWidget(0, 0, label); if (!readOnly) { grid.setWidget(0, 1, buildGroupMenu(activitiesView, this, label)); } return grid; } }; // Adds a new group. activitiesView.addGroup(g); fireLogFrameEdited(); return g; } // ------------------------ // -- ROWS // ------------------------ /** * Adds a new activity empty row. */ protected void addActivity() { ensureLogFrame(); // Checks if the max number of elements is reached. final Integer max = logFrameModel.getActivitiesMax(); if (max != null && max > 0 && max <= activitiesView.getRowsCount()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameMaxReachedA()); return; } final List<ExpectedResultDTO> results = logFrame.getAllExpectedResultsDTO(); // Checks if there is at least one available result. if (results == null || results.isEmpty()) { N10N.warn(I18N.CONSTANTS.logFrameNoExceptedResults(), I18N.CONSTANTS.logFrameNoExceptedResultsDetails()); return; } // Must select a group. if (logFrameModel.getEnableActivitiesGroups()) { // Sets the form window. formWindow.clear(); formWindow.addChoicesList(I18N.CONSTANTS.logFrameExceptedResult(), results, false, "label"); formWindow.addChoicesList(I18N.CONSTANTS.logFrameGroup(), logFrame.getAllGroups(LogFrameGroupType.ACTIVITY), false, "label"); formWindow.addDateField(I18N.CONSTANTS.logFrameActivityStartDate(), true); formWindow.addDateField(I18N.CONSTANTS.logFrameActivityEndDate(), true); formWindow.addFormSubmitListener(new FormSubmitListener() { @Override public void formSubmitted(Object... elements) { // Checks that the values are correct. final Object element0 = elements[0]; if (!(element0 instanceof ExpectedResultDTO)) { return; } final Object element1 = elements[1]; if (!(element1 instanceof LogFrameGroupDTO)) { return; } final Object element2 = elements[2]; if (element2 != null && !(element2 instanceof Date)) { return; } final Object element3 = elements[3]; if (element3 != null && !(element3 instanceof Date)) { return; } // Retrieves the selected ER and group and activity params. final ExpectedResultDTO expectedResult = (ExpectedResultDTO) element0; final LogFrameGroupDTO group = (LogFrameGroupDTO) element1; final Date startDate = element2 != null ? (Date) element2 : null; final Date endDate = element3 != null ? (Date) element3 : null; // Creates and displays a new activity. final LogFrameActivityDTO activity = expectedResult.addActivity(); activity.setGroup(group); activity.setStartDate(startDate); activity.setEndDate(endDate); activity.setAdvancement(0); // advancement set to 0 at the // begin addActivity(activity); } }); formWindow.show(I18N.CONSTANTS.logFrameAddA(), I18N.CONSTANTS.logFrameSelectGroupA()); } // Groups are disabled, no need to select a group, the default one will // be selected. else { // Sets the form window. formWindow.clear(); formWindow.addChoicesList(I18N.CONSTANTS.logFrameExceptedResult(), results, false, "label"); formWindow.addDateField(I18N.CONSTANTS.logFrameActivityStartDate(), true); formWindow.addDateField(I18N.CONSTANTS.logFrameActivityEndDate(), true); formWindow.addFormSubmitListener(new FormSubmitListener() { @Override public void formSubmitted(Object... elements) { // Checks that the values are correct. final Object element0 = elements[0]; if (!(element0 instanceof ExpectedResultDTO)) { return; } final Object element1 = elements[1]; if (element1 != null && !(element1 instanceof Date)) { return; } final Object element2 = elements[2]; if (element2 != null && !(element2 instanceof Date)) { return; } // Retrieves the selected ER and group and activity params. final ExpectedResultDTO expectedResult = (ExpectedResultDTO) element0; final LogFrameGroupDTO group = logFrame.getDefaultGroup(LogFrameGroupType.ACTIVITY); final Date startDate = element1 != null ? (Date) element1 : null; final Date endDate = element2 != null ? (Date) element2 : null; // Creates and displays a new activity. final LogFrameActivityDTO activity = expectedResult.addActivity(); activity.setGroup(group); activity.setStartDate(startDate); activity.setEndDate(endDate); activity.setAdvancement(0); // advancement set to 0 at the // begin addActivity(activity); } }); formWindow.show(I18N.CONSTANTS.logFrameAddA(), I18N.CONSTANTS.logFrameSelectGroup2A()); } } /** * Adds an activity row. * * @param activity * The activity. Must not be <code>null</code>. */ private void addActivity(final LogFrameActivityDTO activity) { // Checks if the activity is correct. if (activity == null) { throw new NullPointerException("activity must not be null"); } // Retrieves the group. final LogFrameGroupDTO group = activity.getGroup(); // Retrieves the equivalent rows group. @SuppressWarnings("unchecked") RowsGroup<LogFrameGroupDTO> g = (RowsGroup<LogFrameGroupDTO>) activitiesView.getGroup(group.getClientSideId()); // If the rows hasn't been created already, adds it. if (g == null) { g = addActivitiesGroup(group); } // Sets the display label. final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFrameActivitiesCode()); sb.append(" "); sb.append(activity.getFormattedCode()); activity.setLabel(sb.toString()); // Sets the position the last if it doesn't exist. if (activity.getPosition() == null) { activity.setPosition(g.getRowsCount() + 1); } // Adds the row. activitiesView.insertRow(activity.getPosition(), group.getClientSideId(), new Row<LogFrameActivityDTO>(activity) { @Override public boolean isSimilar(int column, LogFrameActivityDTO userObject, LogFrameActivityDTO other) { switch (column) { case 0: // Parent code. return userObject.getParentExpectedResult() != null && other.getParentExpectedResult() != null && userObject.getParentExpectedResult().getCode().equals(other.getParentExpectedResult().getCode()); } return false; } @Override public Widget getWidgetAt(int column, final LogFrameActivityDTO userObject) { switch (column) { case 0: // Parent code. final Label parentCodeLabel = new Label(); parentCodeLabel.addStyleName(CSS_CODE_LABEL_STYLE_NAME); final ExpectedResultDTO parent; if (userObject != null && (parent = userObject.getParentExpectedResult()) != null) { final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFrameActivitiesCode()); sb.append(" ("); sb.append(I18N.CONSTANTS.logFrameExceptedResultsCode()); sb.append(" "); sb.append(parent.getFormattedCode()); sb.append(")"); parentCodeLabel.setText(sb.toString()); } return parentCodeLabel; case 1: // Code. final Label codeLabel = new Label(); codeLabel.addStyleName(CSS_CODE_LABEL_STYLE_NAME); if (userObject != null) { codeLabel.setText(userObject.getLabel()); } // Grid. final Grid grid = new Grid(1, 2); grid.setCellPadding(0); grid.setCellSpacing(0); grid.setWidget(0, 0, codeLabel); if (!readOnly) { grid.setWidget(0, 1, buildActivityMenu(this, codeLabel)); } return grid; case 2: // Activity content. final TextArea contentTextBox = new TextArea(); contentTextBox.setWidth("100%"); contentTextBox.setHeight("100%"); contentTextBox.setVisibleLines(2); contentTextBox.addStyleName(CSS_HTML_TEXTBOX); contentTextBox.setEnabled(!readOnly); if (userObject != null) { contentTextBox.setText(userObject.getTitle()); } contentTextBox.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent e) { userObject.setTitle(contentTextBox.getText()); fireLogFrameEdited(); } }); return contentTextBox; case 4: // Indicators. final IndicatorListWidget indicatorListWidget = new IndicatorListWidget(eventBus, databaseId, userObject); indicatorListWidget.addValueChangeHandler(new ValueChangeHandler<Void>() { @Override public void onValueChange(ValueChangeEvent<Void> event) { fireLogFrameEdited(); } }); return indicatorListWidget; case 5: return new Label(); default: return null; } } @Override public int getId(LogFrameActivityDTO userObject) { return userObject.getClientSideId(); } }); fireLogFrameEdited(); } // ------------------------------------------------------------------------ // - PREREQUISITES // ------------------------------------------------------------------------ // ------------------------ // -- GROUPS // ------------------------ /** * Creates a new display group for the prerequisites. */ protected void addPrerequisitesGroup() { ensureLogFrame(); // Checks if the model allows groups. if (!logFrameModel.getEnablePrerequisitesGroups()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameGroupsDisabledP()); return; } // Checks if the max number of groups is reached. final Integer max = logFrameModel.getPrerequisitesGroupsMax(); if (max != null && max > 1 && max <= prerequisitesView.getGroupsCount()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameGroupsMaxReachedP()); return; } // Asks for the new group label. MessageBox.prompt(I18N.CONSTANTS.logFrameAddGroup(), I18N.CONSTANTS.logFrameAddGroupToP(), false, new Listener<MessageBoxEvent>() { @Override public void handleEvent(MessageBoxEvent be) { // OK. if (Dialog.OK.equals(be.getButtonClicked().getItemId())) { String label = ProjectLogFramePresenter.DEFAULT_GROUP_LABEL; if (be.getValue() != null) { label = be.getValue(); } // Creates the new group. final LogFrameGroupDTO group = logFrame.addGroup(label, LogFrameGroupType.PREREQUISITE); // Displays it. addPrerequisitesGroup(group); } } }); } /** * Adds a new display group for the prerequisites. * * @param group * The prerequisites group. * @return The just created group. */ private RowsGroup<LogFrameGroupDTO> addPrerequisitesGroup(final LogFrameGroupDTO group) { ensureLogFrame(); final RowsGroup<LogFrameGroupDTO> g = new RowsGroup<LogFrameGroupDTO>(group) { @Override public String getTitle(LogFrameGroupDTO userObject) { // Builds the title (prefix + label). final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFrameGroup()); sb.append(" ("); sb.append(I18N.CONSTANTS.logFramePrerequisitesCode()); sb.append(") - "); sb.append(userObject.getLabel()); return sb.toString(); } @Override public int getId(LogFrameGroupDTO userObject) { return userObject.getClientSideId(); } @Override public int[] getMergedColumnIndexes(LogFrameGroupDTO userObject) { return new int[0]; } @Override public boolean isVisible(LogFrameGroupDTO userObject) { return logFrameModel.getEnablePrerequisitesGroups(); } @Override public Widget getWidget() { // Displays the group's label. final Label label = new Label(getTitle()); // Grid. final Grid grid = new Grid(1, 2); grid.setCellPadding(0); grid.setCellSpacing(0); grid.setWidget(0, 0, label); if (!readOnly) { grid.setWidget(0, 1, buildGroupMenu(prerequisitesView, this, label)); } return grid; } }; // Adds a new group. prerequisitesView.addGroup(g); fireLogFrameEdited(); return g; } // ------------------------ // -- ROWS // ------------------------ /** * Adds a new prerequisite empty row. */ protected void addPrerequisite() { ensureLogFrame(); // Checks if the max number of elements is reached. final Integer max = logFrameModel.getPrerequisitesMax(); if (max != null && max > 0 && max <= prerequisitesView.getRowsCount()) { N10N.warn(I18N.CONSTANTS.logFrameUnauthorizedAction(), I18N.CONSTANTS.logFrameMaxReachedP()); return; } // Must select a group. if (logFrameModel.getEnablePrerequisitesGroups()) { // Sets the form window. formWindow.clear(); formWindow.addChoicesList(I18N.CONSTANTS.logFrameGroup(), logFrame.getAllGroupsNotDeleted(LogFrameGroupType.PREREQUISITE), false, "label"); formWindow.addFormSubmitListener(new FormSubmitListener() { @Override public void formSubmitted(Object... elements) { // Checks that the values are correct. final Object element0 = elements[0]; if (!(element0 instanceof LogFrameGroupDTO)) { return; } // Retrieves the group. final LogFrameGroupDTO group = (LogFrameGroupDTO) element0; // Creates and displays a new prerequisite. final PrerequisiteDTO prerequisite = logFrame.addPrerequisite(); prerequisite.setGroup(group); addPrerequisite(prerequisite); } }); formWindow.show(I18N.CONSTANTS.logFrameAddP(), I18N.CONSTANTS.logFrameSelectGroupP()); } // Groups are disabled, no need to select a group, the default one will // be selected. else { // Retrieves the default group. final LogFrameGroupDTO group = logFrame.getDefaultGroup(LogFrameGroupType.PREREQUISITE); // Creates and displays a new prerequisite. final PrerequisiteDTO prerequisite = logFrame.addPrerequisite(); prerequisite.setGroup(group); addPrerequisite(prerequisite); } } /** * Adds an prerequisite row. * * @param prerequisite * The prerequisite. Must not be <code>null</code>. */ private void addPrerequisite(final PrerequisiteDTO prerequisite) { // Checks if the prerequisite is correct. if (prerequisite == null) { throw new NullPointerException("prerequisite must not be null"); } // Retrieves the group. final LogFrameGroupDTO group = prerequisite.getGroup(); // Retrieves the equivalent rows group. @SuppressWarnings("unchecked") RowsGroup<LogFrameGroupDTO> g = (RowsGroup<LogFrameGroupDTO>) prerequisitesView.getGroup(group.getClientSideId()); // If the rows hasn't been created already, adds it. if (g == null) { g = addPrerequisitesGroup(group); } // Sets the display label. final StringBuilder sb = new StringBuilder(); sb.append(I18N.CONSTANTS.logFramePrerequisitesCode()); sb.append(" "); sb.append(prerequisite.getFormattedCode()); prerequisite.setLabel(sb.toString()); // Sets the position the last if it doesn't exist. if (prerequisite.getPosition() == null) { prerequisite.setPosition(g.getRowsCount() + 1); } // Adds the row. prerequisitesView.insertRow(prerequisite.getPosition(), group.getClientSideId(), new Row<PrerequisiteDTO>(prerequisite) { @Override public boolean isSimilar(int column, PrerequisiteDTO userObject, PrerequisiteDTO other) { return false; } @Override public Widget getWidgetAt(int column, final PrerequisiteDTO userObject) { switch (column) { case 0: // Code. final Label codeLabel = new Label(); codeLabel.addStyleName(CSS_CODE_LABEL_STYLE_NAME); if (userObject != null) { codeLabel.setText(userObject.getLabel()); } // Grid. final Grid grid = new Grid(1, 2); grid.setCellPadding(0); grid.setCellSpacing(0); grid.setWidget(0, 0, codeLabel); if (!readOnly) { grid.setWidget(0, 1, buildPrerequisiteMenu(this, codeLabel)); } return grid; case 5: // Activity content. final TextArea contentTextBox = new TextArea(); contentTextBox.setWidth("100%"); contentTextBox.setHeight("100%"); contentTextBox.setVisibleLines(2); contentTextBox.addStyleName(CSS_HTML_TEXTBOX); contentTextBox.setEnabled(!readOnly); if (userObject != null) { contentTextBox.setText(userObject.getContent()); } contentTextBox.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent e) { userObject.setContent(contentTextBox.getText()); fireLogFrameEdited(); } }); return contentTextBox; default: return null; } } @Override public int getId(PrerequisiteDTO userObject) { return userObject.getClientSideId(); } }); fireLogFrameEdited(); } // ------------------------------------------------------------------------ // - MENUS // ------------------------------------------------------------------------ /** * Builds the widget of the menus. * * @param menu * The actions menu. * @param label * The label beside this menu. * @return The widget to display this menu. */ private Widget buildMenuWidget(final ActionsMenu menu, final Label label) { // Menu button. final Anchor anchor = new Anchor(); anchor.setHTML(" "); anchor.addStyleName(CSS_MENU_BUTTON_STYLE_NAME); final ClickHandler clickHandler = new ClickHandler() { @Override public void onClick(ClickEvent event) { menu.show(anchor); } }; final MouseOverHandler mouseOverHandler = new MouseOverHandler() { @Override public void onMouseOver(MouseOverEvent event) { anchor.addStyleName(CSS_MENU_BUTTON_ACTIVE_STYLE_NAME); if (label != null) { label.addStyleName(CSS_CODE_LABEL_ACTIVE_STYLE_NAME); } } }; final MouseOutHandler mouseOutHandler = new MouseOutHandler() { @Override public void onMouseOut(MouseOutEvent event) { anchor.removeStyleName(CSS_MENU_BUTTON_ACTIVE_STYLE_NAME); if (label != null) { label.removeStyleName(CSS_CODE_LABEL_ACTIVE_STYLE_NAME); } } }; anchor.addClickHandler(clickHandler); anchor.addMouseOverHandler(mouseOverHandler); anchor.addMouseOutHandler(mouseOutHandler); // Label. if (label != null) { label.addClickHandler(clickHandler); label.addMouseOverHandler(mouseOverHandler); label.addMouseOutHandler(mouseOutHandler); } return anchor; } /** * Builds an actions menu for a specific objective. * * @param row * The specific objective row. * @param label * The label beside this menu. * @return The menu. */ private Widget buildSpecificObjectiveMenu(final Row<SpecificObjectiveDTO> row, final Label label) { // Actions menu. return buildMenuWidget(new RowActionsMenu(specificObjectivesView, row, false) { @Override public boolean canBeRemoved() { return row.getUserObject().getExpectedResults().isEmpty(); } @Override public boolean beforeRemove() { final boolean removed = logFrame.removeSpecificObjective(row.getUserObject()); if (removed) { fireLogFrameEdited(); } return removed; } @Override public boolean canBeMovedUp() { // No functional restriction (the view // manages the row bounds itself). return true; } @Override public boolean beforeMoveUp() { // The view updates the position itself, nothing to do. fireLogFrameEdited(); return true; } @Override public boolean canBeMovedDown() { // No functional restriction (the view // manages the row bounds itself). return true; } @Override public boolean beforeMoveDown() { // The view updates the position itself, nothing to do. fireLogFrameEdited(); return true; } @Override public void buidModifyActionPopUp() { } }, label); } /** * Builds an actions menu for an expected result. * * @param row * The expected result row. * @param label * The label beside this menu. * @return The menu. */ private Widget buildExpectedResultMenu(final Row<ExpectedResultDTO> row, final Label label) { // Actions menu. return buildMenuWidget(new RowActionsMenu(expectedResultsView, row, false) { @Override public boolean canBeRemoved() { // Gets the sub activities list. return row.getUserObject().getActivities().isEmpty(); } @Override public boolean beforeRemove() { final boolean removed = row.getUserObject().getParentSpecificObjective().removeExpectedResult(row.getUserObject()); if (removed) { fireLogFrameEdited(); } return removed; } @Override public boolean canBeMovedUp() { // No functional restriction (the view // manages the row bounds itself). return true; } @Override public boolean beforeMoveUp() { // The view updates the position itself, nothing to do. fireLogFrameEdited(); return true; } @Override public boolean canBeMovedDown() { // No functional restriction (the view // manages the row bounds itself). return true; } @Override public boolean beforeMoveDown() { // The view updates the position itself, nothing to do. fireLogFrameEdited(); return true; } @Override public void buidModifyActionPopUp() { } }, label); } /** * Builds an actions menu for an activity. * * @param row * The activity row. * @param label * The label beside this menu. * @return The menu. */ private Widget buildActivityMenu(final Row<LogFrameActivityDTO> row, final Label label) { // Actions menu. return buildMenuWidget(new RowActionsMenu(activitiesView, row, true) { @Override public boolean canBeRemoved() { // No functional restriction. return true; } @Override public boolean beforeRemove() { final boolean removed = row.getUserObject().getParentExpectedResult().removeActivity(row.getUserObject()); if (removed) { fireLogFrameEdited(); } return removed; } @Override public boolean canBeMovedUp() { // No functional restriction (the view // manages the row bounds itself). return true; } @Override public boolean beforeMoveUp() { // The view updates the position itself, nothing to do. fireLogFrameEdited(); return true; } @Override public boolean canBeMovedDown() { // No functional restriction (the view // manages the row bounds itself). return true; } @Override public boolean beforeMoveDown() { // The view updates the position itself, nothing to do. fireLogFrameEdited(); return true; } @Override public void buidModifyActionPopUp() { final LogFrameActivityDTO activity = row.getUserObject(); final Window updateWindow = new Window(); updateWindow.setAutoHeight(true); updateWindow.setPlain(true); updateWindow.setModal(true); updateWindow.setBlinkModal(true); updateWindow.setHeadingText(I18N.CONSTANTS.logFrameModifyA()); updateWindow.setLayout(new FitLayout()); updateWindow.setWidth(380); updateWindow.setAutoHeight(true); final FormPanel updatePanel = new FormPanel(); updatePanel.setBodyBorder(false); updatePanel.setHeaderVisible(false); updatePanel.setPadding(5); updatePanel.setLabelWidth(100); updatePanel.setFieldWidth(250); updatePanel.setSize(380, 250); // titre if (activity.getTitle() != null && !activity.getTitle().trim().isEmpty()) { final TextField<String> titre = new TextField<String>(); titre.setFieldLabel(I18N.CONSTANTS.logFrameActivityTitle()); titre.setValue(activity.getTitle()); titre.setEnabled(false); updatePanel.add(titre); } // group final TextField<String> expectedResult = new TextField<String>(); expectedResult.setFieldLabel(I18N.CONSTANTS.logFrameExceptedResult()); expectedResult.setValue(activity.getParentExpectedResult().getLabel()); expectedResult.setEnabled(false); updatePanel.add(expectedResult); // advancement value final TextField<String> advancementValue = new TextField<String>(); advancementValue.setFieldLabel(I18N.CONSTANTS.logFrameActivityAdvancement()); advancementValue.setValue(String.valueOf(activity.getAdvancement() != null ? activity.getAdvancement() : 0) + " %"); advancementValue.setEnabled(false); updatePanel.add(advancementValue); // advancement slider final Slider sliderAdvancment = new Slider(); sliderAdvancment.setIncrement(1); sliderAdvancment.getAriaSupport().setLabelledBy("Avancement"); sliderAdvancment.setMessage("{0}%"); Integer activityAdvancement = activity.getAdvancement(); sliderAdvancment.setValue(activityAdvancement != null ? activityAdvancement : 0); sliderAdvancment.setMaxValue(100); sliderAdvancment.setMinValue(0); updatePanel.add(sliderAdvancment); // Updates dynamically the text field. sliderAdvancment.addListener(Events.Change, new Listener<BaseEvent>() { @Override public void handleEvent(BaseEvent be) { advancementValue.setValue(sliderAdvancment.getValue() + " %"); } }); // Start date final DateField startDate = new DateField(); startDate.setAllowBlank(true); startDate.setValue(activity.getStartDate()); startDate.setFieldLabel(I18N.CONSTANTS.logFrameActivityStartDate()); updatePanel.add(startDate); // End date final DateField endDate = new DateField(); endDate.setAllowBlank(true); endDate.setValue(activity.getEndDate()); endDate.setFieldLabel(I18N.CONSTANTS.logFrameActivityEndDate()); updatePanel.add(endDate); // save button final Button saveButton = new Button(I18N.CONSTANTS.ok()); saveButton.addListener(Events.OnClick, new Listener<ButtonEvent>() { @Override public void handleEvent(ButtonEvent be) { // get the new values for the selected activity activity.setStartDate(startDate.getValue()); activity.setEndDate(endDate.getValue()); activity.setAdvancement(sliderAdvancment.getValue()); updateWindow.hide(); fireLogFrameEdited(); } }); updatePanel.addButton(saveButton); updateWindow.add(updatePanel); updateWindow.show(); } }, label); } /** * Builds an actions menu for a prerequisite. * * @param row * The prerequisite row. * @param label * The label beside this menu. * @return The menu. */ private Widget buildPrerequisiteMenu(final Row<PrerequisiteDTO> row, final Label label) { // Actions menu. return buildMenuWidget(new RowActionsMenu(prerequisitesView, row, false) { @Override public boolean canBeRemoved() { // No functional restriction. return true; } @Override public boolean beforeRemove() { final boolean removed = logFrame.removePrerequisite(row.getUserObject()); if (removed) { fireLogFrameEdited(); } return removed; } @Override public boolean canBeMovedUp() { // No functional restriction (the view // manages the row bounds itself). return true; } @Override public boolean beforeMoveUp() { // The view updates the position itself, nothing to do. fireLogFrameEdited(); return true; } @Override public boolean canBeMovedDown() { // No functional restriction (the view // manages the row bounds itself). return true; } @Override public boolean beforeMoveDown() { // The view updates the position itself, nothing to do. fireLogFrameEdited(); return true; } @Override public void buidModifyActionPopUp() { } }, label); } /** * Builds an actions menu for a group. * * @param group * The group. * @param label * The label beside this menu. * @return The menu. */ private Widget buildGroupMenu(final FlexTableView view, final RowsGroup<LogFrameGroupDTO> group, final Label label) { // Actions menu. return buildMenuWidget(new GroupActionMenu(view, group) { @Override public void beforeRename(final AsyncCallback<String> callback) { // Asks for the group new label. MessageBox.prompt(I18N.CONSTANTS.logFrameActionRenameGroup(), I18N.CONSTANTS.logFrameActionRenameNewName(), false, new Listener<MessageBoxEvent>() { @Override public void handleEvent(MessageBoxEvent be) { // OK. if (Dialog.OK.equals(be.getButtonClicked().getItemId())) { String label = ProjectLogFramePresenter.DEFAULT_GROUP_LABEL; if (be.getValue() != null) { label = be.getValue(); } group.getUserObject().setLabel(label); fireLogFrameEdited(); callback.onSuccess(label); } } }); } @Override public boolean beforeRemove() { // Delete the group from LogFrameDTO boolean removed = logFrame.removeGroup(group.getUserObject()); if (removed) { // Notify that the logframe has been modified fireLogFrameEdited(); } return removed; } @Override public boolean canBeRemoved() { if (view.getGroupsCount() == 1) {// If this is the last group in // the view,can not be deleted return false; } if (group.getRowsCount() != 0) {// If this group is not // empty,can not be deleted return false; } return true; } @Override public boolean canBeRemaned() { // No restriction for renaming. return true; } }, label); } }