Tony CHEMIT pushed to branch develop-7.x at ultreiaio / ird-observe Commits: ef780559 by Tony CHEMIT at 2018-07-12T16:20:27Z Improve FOB Form - Closes #948 - - - - - 9 changed files: - client/src/main/java/fr/ird/observe/client/ui/ObserveKeyStrokes.java - client/src/main/java/fr/ird/observe/client/ui/content/data/seine/FloatingObjectUI.jaxx - client/src/main/java/fr/ird/observe/client/ui/content/data/seine/FloatingObjectUI.jcss - client/src/main/java/fr/ird/observe/client/ui/content/data/seine/FloatingObjectUIHandler.java - client/src/main/java/fr/ird/observe/client/ui/content/data/seine/FloatingObjectUIModel.java - client/src/main/java/fr/ird/observe/client/ui/content/data/seine/dcp/FloatingObjectPartsTreeNode.java - + client/src/main/java/fr/ird/observe/client/ui/content/data/seine/dcp/FloatingObjectPartsTreeTable.java - client/src/main/java/fr/ird/observe/client/ui/content/data/seine/dcp/FloatingObjectPartsTreeTableModel.java - dto/src/main/java/fr/ird/observe/dto/data/seine/ObjectMaterialHierarchyDto.java Changes: ===================================== client/src/main/java/fr/ird/observe/client/ui/ObserveKeyStrokes.java ===================================== @@ -111,6 +111,8 @@ public abstract class ObserveKeyStrokes { public static final KeyStroke KEY_STROKE_QUIT = KeyStroke.getKeyStroke("ctrl pressed Q"); public static final KeyStroke KEY_STROKE_DELETE = KeyStroke.getKeyStroke("ctrl pressed U"); + public static final KeyStroke KEY_STROKE_EXPAND_TREE_TABLE_NODE = KeyStroke.getKeyStroke("ctrl released RIGHT"); + public static final KeyStroke KEY_STROKE_COLLAPSE_TREE_TABLE_NODE = KeyStroke.getKeyStroke("ctrl released LEFT"); private static final ImmutableList<KeyStroke> KEY_STROKE_GO_TABS = ImmutableList.of( KEY_STROKE_GO_TAB_1, ===================================== client/src/main/java/fr/ird/observe/client/ui/content/data/seine/FloatingObjectUI.jaxx ===================================== @@ -39,6 +39,7 @@ fr.ird.observe.client.ui.actions.main.global.DeleteDataGlobalUIAction fr.ird.observe.client.ui.actions.main.global.ResetDataGlobalUIAction fr.ird.observe.client.ui.actions.main.global.SaveDataGlobalUIAction + fr.ird.observe.client.ui.content.data.seine.dcp.FloatingObjectPartsTreeTable fr.ird.observe.client.ui.content.data.seine.dcp.FloatingObjectPartsTreeTableModel fr.ird.observe.client.ui.content.data.seine.dcp.FloatingObjectPartLegendTreeCellRenderer fr.ird.observe.client.ui.util.JComment @@ -175,7 +176,7 @@ <row> <cell anchor="north" weightx="1" weighty="1"> <JScrollPane id='tableScroll'> - <JXTreeTable id='table'/> + <FloatingObjectPartsTreeTable id='table' constructorParams="new FloatingObjectPartsTreeTableModel(getModel())"/> </JScrollPane> </cell> </row> ===================================== client/src/main/java/fr/ird/observe/client/ui/content/data/seine/FloatingObjectUI.jcss ===================================== @@ -140,9 +140,3 @@ BeanComboBox { focusable:false; } -#table { - treeTableModel:{new FloatingObjectPartsTreeTableModel(getModel())}; - treeCellRenderer:{new FloatingObjectPartLegendTreeCellRenderer()}; - selectionMode:{ListSelectionModel.SINGLE_SELECTION}; - rootVisible:false; -} ===================================== client/src/main/java/fr/ird/observe/client/ui/content/data/seine/FloatingObjectUIHandler.java ===================================== @@ -29,9 +29,6 @@ import fr.ird.observe.client.db.constants.DataContextType; import fr.ird.observe.client.ui.content.ContentMode; import fr.ird.observe.client.ui.content.ContentUIHandler; import fr.ird.observe.client.ui.content.ContentUIModel; -import fr.ird.observe.client.ui.content.data.seine.dcp.FloatingObjectPartsTableCellEditor; -import fr.ird.observe.client.ui.content.data.seine.dcp.FloatingObjectPartsTableCellRenderer; -import fr.ird.observe.client.ui.content.data.seine.dcp.FloatingObjectPartsTreeNode; import fr.ird.observe.client.ui.content.data.seine.dcp.FloatingObjectPartsTreeTableModel; import fr.ird.observe.client.ui.tree.navigation.NavigationTree; import fr.ird.observe.client.ui.tree.navigation.nodes.NavigationTreeNodeSupport; @@ -53,12 +50,6 @@ import fr.ird.observe.services.service.actions.consolidate.dcp.ConsolidateFloati import fr.ird.observe.spi.DtoModelHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.log4j.lf5.viewer.categoryexplorer.TreeModelAdapter; -import org.jdesktop.swingx.JXTable; -import org.jdesktop.swingx.JXTreeTable; -import org.jdesktop.swingx.decorator.ColorHighlighter; -import org.jdesktop.swingx.table.ColumnFactory; -import org.jdesktop.swingx.table.TableColumnExt; import org.nuiton.jaxx.runtime.spi.UIHandler; import org.nuiton.jaxx.runtime.swing.SwingUtil; import org.nuiton.jaxx.validator.swing.SwingValidatorMessage; @@ -68,8 +59,6 @@ import org.nuiton.validator.NuitonValidatorScope; import javax.swing.Icon; import javax.swing.SwingUtilities; import javax.swing.event.TableModelListener; -import javax.swing.event.TreeModelEvent; -import java.awt.Color; import java.util.HashSet; import java.util.Map; import java.util.Objects; @@ -182,17 +171,18 @@ public class FloatingObjectUIHandler extends ContentUIHandler<FloatingObjectDto, } loadReferentialReferenceSetsInModel(form); - getModel().setForm(form); + FloatingObjectUIModel model = getModel(); + model.setForm(form); FloatingObjectHelper.copyFloatingObjectDto(form.getObject(), bean); - getModel().reset(); + model.reset(); - openTable(partsSet, getUi().getTable(), bean.isPersisted()); + getUi().getTable().openTable(model, partsSet, bean.isPersisted()); setContentMode(mode); // do this after setting mode (since only update mode use this...) - getModel().setReference(floatingObjectReference.orElse(null)); + model.setReference(floatingObjectReference.orElse(null)); if (mode != ContentMode.READ) { getUi().startEdit(null); @@ -203,31 +193,15 @@ public class FloatingObjectUIHandler extends ContentUIHandler<FloatingObjectDto, @Override protected void openedUI() { - SwingUtilities.invokeLater(this::forceGrabFocusOnForm); } - private void openTable(Set<FloatingObjectPartReference> partsSet, JXTreeTable table, boolean persisted) { - - FloatingObjectUIModel model = getModel(); - for (FloatingObjectPartReference p : partsSet) { - String objectMaterialId = p.getObjectMaterialId(); - String whenArriving = p.getWhenArriving(); - String whenLeaving = p.getWhenLeaving(); - if (whenArriving != null && !Objects.equals("false", whenArriving)) { - model.setWhenArriving(objectMaterialId, whenArriving); - } - if (whenLeaving != null && !Objects.equals("false", whenLeaving)) { - model.setWhenLeaving(objectMaterialId, whenLeaving); - } - } - - FloatingObjectPartsTreeTableModel treeTableModel = (FloatingObjectPartsTreeTableModel) table.getTreeTableModel(); - treeTableModel.reset(); - - if (persisted) { - table.expandAll(); + @Override + public void stopEditUI() { + if (ui.getMainTabbedPane().getSelectedIndex() == 1) { + ui.getTable().editingCanceled(null); } + super.stopEditUI(); } @Override @@ -334,7 +308,7 @@ public class FloatingObjectUIHandler extends ContentUIHandler<FloatingObjectDto, FloatingObjectUIModel model = getModel(); model.setReferentialMap(allMap); - initTable(detailedForm, ui.getTable()); + ui.getTable().initTable(model, () -> getUi().getPreferredSize().width - 200, detailedForm); model.addPropertyChangeListener(FloatingObjectUIModel.PROPERTY_REFERENCE, e -> { if (!model.isUpdatingMode()) { @@ -386,60 +360,10 @@ public class FloatingObjectUIHandler extends ContentUIHandler<FloatingObjectDto, getModel().setArriving(operation.isWhenArriving()); getModel().setLeaving(operation.isWhenLeaving()); } - FloatingObjectPartsTreeTableModel treeModel = (FloatingObjectPartsTreeTableModel) getUi().getTable().getTreeTableModel(); + FloatingObjectPartsTreeTableModel treeModel = getUi().getTable().getTreeTableModel(); treeModel.reset(); } - private void initTable(ObjectMaterialHierarchyDto materials, JXTreeTable table) { - - FloatingObjectPartsTreeTableModel treeModel = (FloatingObjectPartsTreeTableModel) table.getTreeTableModel(); - treeModel.rebuildRootNode(materials); - - table.setColumnFactory(new ColumnFactory() { - - @Override - public void configureColumnWidths(JXTable table, TableColumnExt columnExt) { - if (table.getColumn(0).equals(columnExt)) { - columnExt.setPreferredWidth(getUi().getPreferredSize().width - 200); - columnExt.setMinWidth(columnExt.getPreferredWidth()); - return; - } - super.configureColumnWidths(table, columnExt); - columnExt.setMinWidth(columnExt.getPreferredWidth()); - } - }); - treeModel.addTreeModelListener(new TreeModelAdapter() { - @Override - public void treeNodesChanged(TreeModelEvent e) { - if (treeModel.isAdjusting()) { - return; - } - getModel().setModified(true); - getModel().setPartsModified(); - } - - }); - - table.setDefaultRenderer(Object.class, new FloatingObjectPartsTableCellRenderer(table)); - table.setDefaultEditor(Object.class, new FloatingObjectPartsTableCellEditor(table)); - table.addHighlighter(new ColorHighlighter((renderer, adapter) -> { - JXTreeTable component = (JXTreeTable) adapter.getComponent(); - int row = adapter.convertRowIndexToModel(adapter.row); - FloatingObjectPartsTreeNode node = (FloatingObjectPartsTreeNode) component.getPathForRow(row).getLastPathComponent(); - boolean valid1 = node.isValid(1); - boolean valid2 = node.isValid(2); - switch (adapter.convertRowIndexToModel(adapter.column)) { - case 0: - return false; - case 1: - return !valid1; - case 2: - return !valid2; - } - return true; - }, ObserveSwingApplicationContext.get().getConfig().getFloatingObjectMaterialErrorColor(), Color.WHITE)); - } - protected void computeTabValidState(SwingValidatorMessageTableModel errorTableModel) { Set<String> errorProperties = new HashSet<>(); ===================================== client/src/main/java/fr/ird/observe/client/ui/content/data/seine/FloatingObjectUIModel.java ===================================== @@ -127,7 +127,7 @@ public class FloatingObjectUIModel extends ContentUIModel<FloatingObjectDto> { return result.build(); } - void setPartsModified() { + public void setPartsModified() { firePropertyChange(PROPERTY_PARTS_MODIFIED, true); } ===================================== client/src/main/java/fr/ird/observe/client/ui/content/data/seine/dcp/FloatingObjectPartsTreeNode.java ===================================== @@ -23,9 +23,10 @@ package fr.ird.observe.client.ui.content.data.seine.dcp; */ import com.google.common.collect.ImmutableSet; +import fr.ird.observe.client.ObserveSwingApplicationContext; import fr.ird.observe.client.ui.content.data.seine.FloatingObjectUIModel; import fr.ird.observe.dto.data.seine.ObjectMaterialHierarchyDto; -import fr.ird.observe.dto.referential.FormulaHelper; +import fr.ird.observe.dto.referential.ReferentialLocale; import fr.ird.observe.dto.referential.seine.ObjectMaterialTypeReference; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -60,13 +61,13 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im static FloatingObjectPartsTreeNode createRoot(FloatingObjectUIModel model, ObjectMaterialHierarchyDto dto) { FloatingObjectPartsTreeNode root; FloatingObjectPartsTreeNodeContext rootModel = new FloatingObjectPartsTreeNodeContext(model); - if (dto != null) { + if (dto == null) { + root = new FloatingObjectPartsTreeNode(rootModel); + } else { FloatingObjectPartsTreeNodeContext childModel = new FloatingObjectPartsTreeNodeContext(dto, rootModel); root = new FloatingObjectPartsTreeNode(childModel); root.computeCompanions(null); root.setCompanions(null); - } else { - root = new FloatingObjectPartsTreeNode(rootModel); } return root; } @@ -164,6 +165,8 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im getUserObject().text = null; getUserObject().validWhenArriving = true; getUserObject().validWhenLeaving = true; + getUserObject().needOneSelectionOnArriving = false; + getUserObject().needOneSelectionOnLeaving = false; } @Override @@ -171,83 +174,88 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im return (FloatingObjectPartsTreeNode) super.getParent(); } - void fillNodeSets(ImmutableSet.Builder<FloatingObjectPartsTreeNode> allNodesBuilder, - ImmutableSet.Builder<FloatingObjectPartsTreeNode> needOneSelectionNodesBuilder, - ImmutableSet.Builder<FloatingObjectPartsTreeNode> mandatoryNodesBuilder) { + ImmutableSet<FloatingObjectPartsTreeNode> getShell() { - allNodesBuilder.add(this); - if (getUserObject().needOneSelection) { - needOneSelectionNodesBuilder.add(this); - } - if (getUserObject().mandatory) { - mandatoryNodesBuilder.add(this); - } + ImmutableSet.Builder<FloatingObjectPartsTreeNode> allNodesBuilder = ImmutableSet.builder(); + getShell(allNodesBuilder); + return allNodesBuilder.build(); + } + private void getShell(ImmutableSet.Builder<FloatingObjectPartsTreeNode> allNodesBuilder) { + allNodesBuilder.add(this); for (FloatingObjectPartsTreeNode child : this) { - child.fillNodeSets(allNodesBuilder, needOneSelectionNodesBuilder, mandatoryNodesBuilder); + child.getShell(allNodesBuilder); } + } + boolean withMandatoryConstraintsOnChildren() { + ObjectMaterialHierarchyDto userObject = getUserObject().dto; + return userObject == null || userObject.isChildSelectionMandatory(); } void computeNeedAtLeastOnSelectValidState(boolean whenArriving, boolean whenLeaving) { - + boolean needSelect = isEditable(); + FloatingObjectPartsTreeNodeContext userObject = getUserObject(); if (whenArriving) { - getUserObject().validWhenArriving = isAtLeastOneSelected(1); + userObject.needOneSelectionOnArriving = (!needSelect || withValue(1)) && isAtLeastOneSelected(1); } if (whenLeaving) { - getUserObject().validWhenLeaving = isAtLeastOneSelected(2); + userObject.needOneSelectionOnLeaving = (!needSelect || withValue(2)) && isAtLeastOneSelected(2); + } + if (userObject.needOneSelectionOnArriving || userObject.needOneSelectionOnLeaving) { + log.info("Validate node " + this); } - - log.info("Validate node " + this); } - void computeMandatoryValidState(boolean whenArriving, boolean whenLeaving) { - if (whenArriving) { - getUserObject().validWhenArriving = getParent().getUserObject().validWhenArriving; - } - if (whenLeaving) { - getUserObject().validWhenLeaving = getParent().getUserObject().validWhenLeaving; + private FloatingObjectPartsTreeNode getFirstAncestorNeedOneSelection(int column) { + if (withMandatoryConstraintsOnChildren()) { + if (parent == null) { + return this; + } + if (withValue(column)) { + return this; + } } - - log.info("Validate node " + this); + return getParent().getFirstAncestorNeedOneSelection(column); } - void computeFormulaValidState(boolean whenArriving, boolean whenLeaving) { - if (getUserObject().dto == null || getUserObject().dto.isBoolean()) { - return; - } - String validation = getUserObject().dto.getValidation(); - if (whenArriving && getUserObject().validWhenArriving) { - Object value = getUserObject().getValueAt(1); - if (value != null) { - if (getUserObject().dto.isText()) { - getUserObject().validWhenArriving = FormulaHelper.validateObjectMaterialValidation(validation, value); - } else if (getUserObject().dto.isInteger()) { - getUserObject().validWhenArriving = FormulaHelper.validateObjectMaterialValidation(validation, Integer.valueOf(value.toString())); - } else if (getUserObject().dto.isFloat()) { - getUserObject().validWhenArriving = FormulaHelper.validateObjectMaterialValidation(validation, Float.valueOf(value.toString())); - } + void computeMandatoryValidState(boolean whenArriving, boolean whenLeaving) { + FloatingObjectPartsTreeNodeContext userObject = getUserObject(); + FloatingObjectPartsTreeNode parent = getParent(); + if (whenArriving) { + if (parent != null && !parent.getUserObject().validWhenArriving) { + userObject.validWhenArriving = false; + } else { + userObject.validWhenArriving = getFirstAncestorNeedOneSelection(1).getUserObject().needOneSelectionOnArriving; } } - if (whenLeaving && getUserObject().validWhenLeaving) { - Object value = getUserObject().getValueAt(2); - if (value != null) { - if (getUserObject().dto.isText()) { - getUserObject().validWhenLeaving = FormulaHelper.validateObjectMaterialValidation(validation, value); - } else if (getUserObject().dto.isInteger()) { - getUserObject().validWhenLeaving = FormulaHelper.validateObjectMaterialValidation(validation, Integer.valueOf(value.toString())); - } else if (getUserObject().dto.isFloat()) { - getUserObject().validWhenLeaving = FormulaHelper.validateObjectMaterialValidation(validation, Float.valueOf(value.toString())); - } + if (whenLeaving) { + if (parent != null && !parent.getUserObject().validWhenLeaving) { + userObject.validWhenLeaving = false; + } else { + userObject.validWhenLeaving = getFirstAncestorNeedOneSelection(2).getUserObject().needOneSelectionOnLeaving; } } + if (userObject.getValueAt(1) != null || userObject.getValueAt(2) != null) { + log.info("Validate node " + this); + } } - boolean withValidation() { - return getUserObject().dto != null && getUserObject().dto.withValidation(); - } +// void computeFormulaValidState(boolean whenArriving, boolean whenLeaving) { +// FloatingObjectPartsTreeNodeContext userObject = getUserObject(); +// ObjectMaterialHierarchyDto dto = Objects.requireNonNull(userObject.dto); +// if (whenArriving && userObject.validWhenArriving) { +// Object value = userObject.getValueAt(1); +// userObject.validWhenArriving = dto.isValid(value); +// } +// if (whenLeaving && userObject.validWhenLeaving) { +// Object value = userObject.getValueAt(2); +// userObject.validWhenLeaving = dto.isValid(value); +// } +// +// } private void setCompanions(ImmutableSet.Builder<FloatingObjectPartsTreeNode> companionsBuilder) { if (companionsBuilder != null) { @@ -258,12 +266,21 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im } } + private boolean withValue(int column) { + return getValueAt(column) != null; + } + + private boolean withValidValue(int column) { + return withValue(column) && (column == 1 ? getUserObject().valueValidOnArriving : getUserObject().valueValidOnLeaving); + } + private boolean isAtLeastOneSelected(int column) { - if (getValueAt(column) != null) { - return true; - } for (FloatingObjectPartsTreeNode child : this) { - if (child.isAtLeastOneSelected(column)) { + if (child.withValidValue(column)) { + return true; + } + boolean result = child.isAtLeastOneSelected(column); + if (result) { return true; } } @@ -288,6 +305,7 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im return dto != null && !dto.isChildrenMultiSelectable() && !isLeaf(); } + //TODO Improve the design, we should not store anything in uiModel and separate leaving and arriving data private static class FloatingObjectPartsTreeNodeContext { // main model to get and store values @@ -298,15 +316,22 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im private final boolean enabled; // Is this node editable ? private final boolean editable; - // Is this node need at least one child selected ? - private final boolean needOneSelection; - // Is this node in the path of at least one mandatory child ancestor ? - private final boolean mandatory; // Is the node is exclusive (means only one value possible for him and his brothers) ? private final boolean exclusive; - // Is the node valid for whenArriving column ? + // Is the node use validation on his value ? + private final boolean useValidation; + private final ReferentialLocale referentialLocale; + // Is this node (on arriving) need at least one child selected ? (if editable then node must be selected) + private boolean needOneSelectionOnLeaving; + // Is this node (on leaving) need at least one child selected ? (if editable then node must be selected) + private boolean needOneSelectionOnArriving; + // for a validation node (on arriving), is value valid (if no value then it is valid) + private boolean valueValidOnLeaving = true; + // for a validation node (on leaving), is value valid (if no value then it is valid) + private boolean valueValidOnArriving = true; + // Is the node valid (on arriving) column ? private boolean validWhenArriving = true; - // Is the node valid for whenLeaving column ? + // Is the node valid (on leeaving) column ? private boolean validWhenLeaving = true; // Set of brothers of this node that is in a exclusive group of node (only one value among all of them) private ImmutableSet<FloatingObjectPartsTreeNode> companions; @@ -314,33 +339,33 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im private String text; FloatingObjectPartsTreeNodeContext(FloatingObjectUIModel uiModel) { - Objects.requireNonNull(uiModel); - this.uiModel = uiModel; + this.uiModel = Objects.requireNonNull(uiModel); this.dto = null; this.enabled = true; this.editable = false; - this.mandatory = false; this.exclusive = false; - this.needOneSelection = false; + this.useValidation = false; + this.valueValidOnArriving = true; + this.valueValidOnLeaving = true; + this.referentialLocale = ObserveSwingApplicationContext.get().getDecoratorService().getReferentialLocale(); } FloatingObjectPartsTreeNodeContext(ObjectMaterialHierarchyDto dto, FloatingObjectPartsTreeNodeContext parent) { - Objects.requireNonNull(dto); - Objects.requireNonNull(parent); - this.uiModel = parent.uiModel; - this.dto = dto; + this.uiModel = Objects.requireNonNull(parent).uiModel; + this.dto = Objects.requireNonNull(dto); // enabled if parent is enabled and dto is enabled this.enabled = parent.enabled && dto.isEnabled(); - // need one selection if is enabled and dto requires it - this.needOneSelection = enabled && dto.isChildSelectionMandatory(); // editable if dto is selectable (we also make sure that the object material type is here too) this.editable = dto.isSelectable() && dto.getObjectMaterialType() != null; - - // mandatory if enabled parent is so or parent makes this child to be - this.mandatory = parent.mandatory || parent.needOneSelection; + this.useValidation = enabled && editable && dto.withValidation(); + if (!useValidation) { + valueValidOnArriving = true; + valueValidOnLeaving = true; + } // exclusive if his parent requires it this.exclusive = parent.dto != null && !parent.dto.isChildrenMultiSelectable(); - log.info(String.format("New node: %s - mandatory %s - needOneSelection %s - exclusive %s", dto.getLabel2(), mandatory, needOneSelection, exclusive)); + this.referentialLocale = ObserveSwingApplicationContext.get().getDecoratorService().getReferentialLocale(); + log.info(String.format("New node: %s %s - needOneSelection %b-%b - exclusive %s", dto.getCode(), dto.getLabel(referentialLocale), needOneSelectionOnArriving, needOneSelectionOnLeaving, exclusive)); } Object getValueAt(int column) { @@ -356,12 +381,19 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im } void setValueAt(Object aValue, int column) { + text = null; switch (column) { case 1: // when arriving uiModel.setWhenArriving(dto.getId(), aValue == null ? null : String.valueOf(aValue)); + if (useValidation) { + valueValidOnArriving = dto.isValid(aValue); + } return; case 2: // when leaving uiModel.setWhenLeaving(dto.getId(), aValue == null ? null : String.valueOf(aValue)); + if (useValidation) { + valueValidOnLeaving = dto.isValid(aValue); + } return; } throw new IllegalStateException(); @@ -393,7 +425,7 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im public String getText() { if (text == null && dto != null) { - text = String.format("%s [value: %s-%s] [valid: %s-%s]", dto.getLabel2(), getValueAt(1), getValueAt(2), isValid(1), isValid(2)); + text = String.format("%s [value: %s-%s] [valid: %s-%s]", dto.getLabel(referentialLocale), getValueAt(1), getValueAt(2), isValid(1), isValid(2)); } return text; } ===================================== client/src/main/java/fr/ird/observe/client/ui/content/data/seine/dcp/FloatingObjectPartsTreeTable.java ===================================== @@ -0,0 +1,188 @@ +package fr.ird.observe.client.ui.content.data.seine.dcp; + +/*- + * #%L + * ObServe :: Client + * %% + * Copyright (C) 2008 - 2018 IRD, Code Lutin, Ultreia.io + * %% + * 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 fr.ird.observe.client.ObserveSwingApplicationContext; +import fr.ird.observe.client.ui.ObserveKeyStrokes; +import fr.ird.observe.client.ui.content.data.seine.FloatingObjectUIModel; +import fr.ird.observe.dto.data.seine.FloatingObjectPartReference; +import fr.ird.observe.dto.data.seine.ObjectMaterialHierarchyDto; +import org.apache.log4j.lf5.viewer.categoryexplorer.TreeModelAdapter; +import org.jdesktop.swingx.JXTable; +import org.jdesktop.swingx.JXTreeTable; +import org.jdesktop.swingx.decorator.ColorHighlighter; +import org.jdesktop.swingx.table.ColumnFactory; +import org.jdesktop.swingx.table.TableColumnExt; +import org.jdesktop.swingx.treetable.MutableTreeTableNode; + +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeModelEvent; +import javax.swing.tree.TreePath; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.util.Enumeration; +import java.util.Objects; +import java.util.Set; +import java.util.function.Supplier; + +/** + * Created by tchemit on 11/07/2018. + * + * @author Tony Chemit - dev@tchemit.fr + */ +public class FloatingObjectPartsTreeTable extends JXTreeTable { + + public FloatingObjectPartsTreeTable(FloatingObjectPartsTreeTableModel treeModel) { + super(treeModel); + setTreeCellRenderer(new FloatingObjectPartLegendTreeCellRenderer()); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + setRootVisible(false); + } + + @Override + public FloatingObjectPartsTreeTableModel getTreeTableModel() { + return (FloatingObjectPartsTreeTableModel) super.getTreeTableModel(); + } + + public void openTable(FloatingObjectUIModel model, Set<FloatingObjectPartReference> partsSet, boolean persisted) { + + for (FloatingObjectPartReference p : partsSet) { + String objectMaterialId = p.getObjectMaterialId(); + String whenArriving = p.getWhenArriving(); + String whenLeaving = p.getWhenLeaving(); + if (whenArriving != null && !Objects.equals("false", whenArriving)) { + model.setWhenArriving(objectMaterialId, whenArriving); + } + if (whenLeaving != null && !Objects.equals("false", whenLeaving)) { + model.setWhenLeaving(objectMaterialId, whenLeaving); + } + } + + FloatingObjectPartsTreeTableModel treeTableModel = getTreeTableModel(); + treeTableModel.reset(); + + if (persisted) { + expandAll(); + } else { + // expand first level nodes (except if they are disabled) + FloatingObjectPartsTreeNode root = treeTableModel.getRoot(); + Enumeration<? extends MutableTreeTableNode> children = root.children(); + while (children.hasMoreElements()) { + FloatingObjectPartsTreeNode mutableTreeTableNode = (FloatingObjectPartsTreeNode) children.nextElement(); + if (mutableTreeTableNode.isEnabled()) { + SwingUtilities.invokeLater(() -> expandPath(new TreePath(new Object[]{root, mutableTreeTableNode}))); + } + } + } + // auto expand nodes when selected + addTreeSelectionListener(e -> { + int selectedRow = getSelectedRow(); + if (selectedRow != -1) { + if (!isExpanded(selectedRow)) { + SwingUtilities.invokeLater(() -> expandRow(selectedRow)); + } + } + }); + } + + public void initTable(FloatingObjectUIModel model, Supplier<Integer> width, ObjectMaterialHierarchyDto materials) { + + FloatingObjectPartsTreeTableModel treeModel = getTreeTableModel(); + treeModel.rebuildRootNode(materials); + + setColumnFactory(new ColumnFactory() { + + @Override + public void configureColumnWidths(JXTable table, TableColumnExt columnExt) { + if (table.getColumn(0).equals(columnExt)) { + columnExt.setPreferredWidth(width.get()); + columnExt.setMinWidth(columnExt.getPreferredWidth()); + return; + } + super.configureColumnWidths(table, columnExt); + columnExt.setMinWidth(columnExt.getPreferredWidth()); + } + }); + treeModel.addTreeModelListener(new TreeModelAdapter() { + @Override + public void treeNodesChanged(TreeModelEvent e) { + if (treeModel.isAdjusting()) { + return; + } + model.setModified(true); + model.setPartsModified(); + } + + }); + + setDefaultRenderer(Object.class, new FloatingObjectPartsTableCellRenderer(this)); + setDefaultEditor(Object.class, new FloatingObjectPartsTableCellEditor(this)); + addHighlighter(new ColorHighlighter((renderer, adapter) -> { + JXTreeTable component = (JXTreeTable) adapter.getComponent(); + int row = adapter.convertRowIndexToModel(adapter.row); + FloatingObjectPartsTreeNode node = (FloatingObjectPartsTreeNode) component.getPathForRow(row).getLastPathComponent(); + boolean valid1 = node.isValid(1); + boolean valid2 = node.isValid(2); + switch (adapter.convertRowIndexToModel(adapter.column)) { + case 0: + return false; + case 1: + return !valid1; + case 2: + return !valid2; + } + return true; + }, ObserveSwingApplicationContext.get().getConfig().getFloatingObjectMaterialErrorColor(), Color.WHITE)); + + InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); + ActionMap actionMap = getActionMap(); + inputMap.put(ObserveKeyStrokes.KEY_STROKE_EXPAND_TREE_TABLE_NODE,"expandNode"); + actionMap.put("expandNode", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + int selectedRow = getSelectedRow(); + if (selectedRow != -1) { + if (!isExpanded(selectedRow)) { + SwingUtilities.invokeLater(() -> expandRow(selectedRow)); + } + } + } + }); + inputMap.put(ObserveKeyStrokes.KEY_STROKE_COLLAPSE_TREE_TABLE_NODE,"collapseNode"); + actionMap.put("collapseNode", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + int selectedRow = getSelectedRow(); + if (selectedRow != -1) { + if (!isCollapsed(selectedRow)) { + SwingUtilities.invokeLater(() -> collapseRow(selectedRow)); + } + } + } + }); + } +} ===================================== client/src/main/java/fr/ird/observe/client/ui/content/data/seine/dcp/FloatingObjectPartsTreeTableModel.java ===================================== @@ -33,7 +33,6 @@ import org.nuiton.i18n.I18n; import java.util.Arrays; import java.util.Optional; -import java.util.stream.Collectors; /** * Created by tchemit on 05/08/17. @@ -51,7 +50,6 @@ public class FloatingObjectPartsTreeTableModel extends DefaultTreeTableModel { private ImmutableSet<FloatingObjectPartsTreeNode> allNodes; private ImmutableSet<FloatingObjectPartsTreeNode> needOneSelectionNodes; private ImmutableSet<FloatingObjectPartsTreeNode> mandatoryNodes; - private ImmutableSet<FloatingObjectPartsTreeNode> withValidationNodes; private boolean adjusting; public FloatingObjectPartsTreeTableModel(FloatingObjectUIModel uiModel) { @@ -71,18 +69,22 @@ public class FloatingObjectPartsTreeTableModel extends DefaultTreeTableModel { public void setRoot(TreeTableNode root) { super.setRoot(root); - FloatingObjectPartsTreeNode myRoot = (FloatingObjectPartsTreeNode) root; + allNodes = ((FloatingObjectPartsTreeNode) root).getShell(); - ImmutableSet.Builder<FloatingObjectPartsTreeNode> allNodesBuilder = ImmutableSet.builder(); ImmutableSet.Builder<FloatingObjectPartsTreeNode> needOneSelectionNodesBuilder = ImmutableSet.builder(); ImmutableSet.Builder<FloatingObjectPartsTreeNode> mandatoryNodesBuilder = ImmutableSet.builder(); - myRoot.fillNodeSets(allNodesBuilder, needOneSelectionNodesBuilder, mandatoryNodesBuilder); - - allNodes = allNodesBuilder.build(); + for (FloatingObjectPartsTreeNode node : allNodes) { + if (!node.isEnabled()) { + continue; + } + mandatoryNodesBuilder.add(node); + if (node.withMandatoryConstraintsOnChildren()) { + needOneSelectionNodesBuilder.add(node); + } + } needOneSelectionNodes = needOneSelectionNodesBuilder.build(); mandatoryNodes = mandatoryNodesBuilder.build(); - withValidationNodes = ImmutableSet.copyOf(allNodes.stream().filter(FloatingObjectPartsTreeNode::withValidation).collect(Collectors.toSet())); } public void rebuildRootNode(ObjectMaterialHierarchyDto materials) { @@ -129,7 +131,6 @@ public class FloatingObjectPartsTreeTableModel extends DefaultTreeTableModel { needOneSelectionNodes.forEach(n -> n.computeNeedAtLeastOnSelectValidState(whenArriving, whenLeaving)); mandatoryNodes.forEach(n -> n.computeMandatoryValidState(whenArriving, whenLeaving)); - withValidationNodes.forEach(n -> n.computeFormulaValidState(whenArriving, whenLeaving)); boolean notValid = allNodes.stream().anyMatch(FloatingObjectPartsTreeNode::isNotValid); uiModel.getBean().setMaterialsValid(!notValid); ===================================== dto/src/main/java/fr/ird/observe/dto/data/seine/ObjectMaterialHierarchyDto.java ===================================== @@ -22,6 +22,7 @@ package fr.ird.observe.dto.data.seine; * #L% */ +import fr.ird.observe.dto.referential.FormulaHelper; import fr.ird.observe.dto.referential.seine.ObjectMaterialDto; import org.nuiton.util.beans.Binder; import org.nuiton.util.beans.BinderFactory; @@ -60,6 +61,20 @@ public class ObjectMaterialHierarchyDto extends ObjectMaterialDto { return result; } + public boolean isValid(Object value) { + if (value==null) { + return true; + } + if (isText()) { + return FormulaHelper.validateObjectMaterialValidation(validation, value); + } else if (isInteger()) { + return FormulaHelper.validateObjectMaterialValidation(validation, Integer.valueOf(value.toString())); + } else if (isFloat()) { + return FormulaHelper.validateObjectMaterialValidation(validation, Float.valueOf(value.toString())); + } + throw new IllegalStateException("Can't validate this dto... "+this); + } + private void getAllDtos(ObjectMaterialHierarchyDto hierarchyDto, Set<ObjectMaterialHierarchyDto> result) { result.add(hierarchyDto); hierarchyDto.getChildren().forEach(c -> getAllDtos(c, result)); View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/commit/ef7805596cb94ee1e1347451ae24... -- View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/commit/ef7805596cb94ee1e1347451ae24... You're receiving this email because of your account on gitlab.com.
participants (1)
-
Tony CHEMIT