r46 - in trunk/tutti-ui-swing/src: main/java/fr/ifremer/tutti/ui/swing/content/catches/species main/java/fr/ifremer/tutti/ui/swing/content/operation main/java/fr/ifremer/tutti/ui/swing/content/operation/species main/java/fr/ifremer/tutti/ui/swing/util main/java/fr/ifremer/tutti/ui/swing/util/table test/java/fr/ifremer/tutti/ui/swing/content test/java/fr/ifremer/tutti/ui/swing/content/catches/species test/java/fr/ifremer/tutti/ui/swing/content/operation test/java/fr/ifremer/tutti/ui/swing/con
Author: tchemit Date: 2012-12-12 18:06:45 +0100 (Wed, 12 Dec 2012) New Revision: 46 Url: http://forge.codelutin.com/projects/tutti/repository/revisions/46 Log: - move frequency to their correct pakcage - being to implement the sampling logic for species batch Added: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyTableModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.css trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.jaxx trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIHandler.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/TuttiBeanMonitor.java trunk/tutti-ui-swing/src/test/java/fr/ifremer/tutti/ui/swing/content/operation/ trunk/tutti-ui-swing/src/test/java/fr/ifremer/tutti/ui/swing/content/operation/species/ trunk/tutti-ui-swing/src/test/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModelTest.java Removed: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/catches/species/frequency/ trunk/tutti-ui-swing/src/test/java/fr/ifremer/tutti/ui/swing/content/catches/species/frequency/ Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUI.css trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUI.jaxx trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUIHandler.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/FrequencyCellComponent.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchRowModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTableModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTreeModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTreeNode.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUI.css trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUI.jaxx trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUIHandler.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUIModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractTuttiTableUIHandler.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/TableRowModificationListener.java Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUI.css =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUI.css 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUI.css 2012-12-12 17:06:45 UTC (rev 46) @@ -33,7 +33,7 @@ actionIcon: "add"; } -#traitComboBox { +#fishingOperationComboBox { property: "selectedFishingOperation"; selectedItem: {model.getSelectedFishingOperation()}; } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUI.jaxx =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUI.jaxx 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUI.jaxx 2012-12-12 17:06:45 UTC (rev 46) @@ -62,7 +62,7 @@ <!-- FishingOperations fishingOperation --> <row> <cell anchor='west' weightx='1.0'> - <BeanComboBox id='traitComboBox' constructorParams='this' + <BeanComboBox id='fishingOperationComboBox' constructorParams='this' genericType='FishingOperation'/> </cell> <cell anchor='east'> Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUIHandler.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUIHandler.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/FishingOperationsUIHandler.java 2012-12-12 17:06:45 UTC (rev 46) @@ -25,8 +25,8 @@ */ import fr.ifremer.tutti.persistence.entities.TuttiEntities; +import fr.ifremer.tutti.persistence.entities.data.Cruise; import fr.ifremer.tutti.persistence.entities.data.FishingOperation; -import fr.ifremer.tutti.persistence.entities.data.Cruise; import fr.ifremer.tutti.service.PersistenceService; import fr.ifremer.tutti.ui.swing.AbstractTuttiUIHandler; import fr.ifremer.tutti.ui.swing.TuttiUIContext; @@ -48,13 +48,15 @@ public class FishingOperationsUIHandler extends AbstractTuttiUIHandler<FishingOperationsUIModel> { /** Logger. */ - private static final Log log = LogFactory.getLog(FishingOperationsUIHandler.class); + private static final Log log = + LogFactory.getLog(FishingOperationsUIHandler.class); private final FishingOperationsUI ui; private final PersistenceService persistenceService; - public FishingOperationsUIHandler(TuttiUIContext context, FishingOperationsUI ui) { + public FishingOperationsUIHandler(TuttiUIContext context, + FishingOperationsUI ui) { super(context); this.ui = ui; persistenceService = context.getService(PersistenceService.class); @@ -63,6 +65,9 @@ @Override public void beforeInitUI() { + if (log.isInfoEnabled()) { + log.info("for " + ui); + } FishingOperationsUIModel model = new FishingOperationsUIModel(); String cruiseId = context.getCruiseId(); @@ -71,11 +76,13 @@ Cruise cruise = persistenceService.getCruise(cruiseId); model.setCruise(cruise); - List<FishingOperation> fishingOperations = persistenceService.getAllFishingOperation(cruiseId); + List<FishingOperation> fishingOperations = + persistenceService.getAllFishingOperation(cruiseId); model.setFishingOperation(fishingOperations); if (log.isInfoEnabled()) { - log.info("Loaded " + fishingOperations.size() + " fishingOperation(s)."); + log.info("Loaded " + fishingOperations.size() + + " fishingOperation(s)."); } ui.setContextValue(model); @@ -90,7 +97,7 @@ List<FishingOperation> fishingOperations = model.getFishingOperation(); - initBeanComboBox(ui.getTraitComboBox(), + initBeanComboBox(ui.getFishingOperationComboBox(), fishingOperations, model.getSelectedFishingOperation()); @@ -104,8 +111,8 @@ model.addPropertyChangeListener(FishingOperationsUIModel.PROPERTY_FISHING_OPERATION, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - ui.getTraitComboBox().setData(null); - ui.getTraitComboBox().setData((List<FishingOperation>) evt.getNewValue()); + ui.getFishingOperationComboBox().setData(null); + ui.getFishingOperationComboBox().setData((List<FishingOperation>) evt.getNewValue()); } }); Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/FrequencyCellComponent.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/FrequencyCellComponent.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/FrequencyCellComponent.java 2012-12-12 17:06:45 UTC (rev 46) @@ -25,7 +25,6 @@ */ import com.google.common.base.Preconditions; -import fr.ifremer.tutti.ui.swing.content.catches.species.frequency.SpeciesFrequencyUI; import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil; import fr.ifremer.tutti.ui.swing.util.table.AbstractSelectTableAction; import fr.ifremer.tutti.ui.swing.util.table.ColumnIdentifier; Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchRowModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchRowModel.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchRowModel.java 2012-12-12 17:06:45 UTC (rev 46) @@ -32,7 +32,6 @@ import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.persistence.entities.referential.WeightCategory; import fr.ifremer.tutti.ui.swing.AbstractTuttiBeanUIModel; -import fr.ifremer.tutti.ui.swing.content.catches.species.frequency.SpeciesFrequencyRowModel; import org.apache.commons.collections.CollectionUtils; import org.nuiton.util.beans.Binder; import org.nuiton.util.beans.BinderFactory; Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTableModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTableModel.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTableModel.java 2012-12-12 17:06:45 UTC (rev 46) @@ -101,7 +101,7 @@ n_("tutti.table.species.batch.header.sampleWeight"), n_("tutti.table.species.batch.header.sampleWeight")); - public static final ColumnIdentifier<SpeciesBatchRowModel> ELEVATION_RATIO = ColumnIdentifier.newId( + public static final ColumnIdentifier<SpeciesBatchRowModel> SAMPLING_RATIO = ColumnIdentifier.newId( SpeciesBatchRowModel.PROPERTY_SAMPLING_RATIO, n_("tutti.table.species.batch.header.elevationRate"), n_("tutti.table.species.batch.header.elevationRate")); @@ -122,12 +122,9 @@ public SpeciesBatchTableModel(TableColumnModel columnModel) { super(columnModel); - // TODO This will be dynamic by the protocol... setNoneEditableCols( - AGE, - MATURITY, SAMPLE_WEIGHT, - ELEVATION_RATIO, + SAMPLING_RATIO, FILE ); noneEditableColIfNoSpecies = Sets.newHashSet(); @@ -177,6 +174,17 @@ } } + public void updateSamplingRatio(Set<SpeciesBatchRowModel> rows) { + for (SpeciesBatchRowModel row : rows) { + int rowIndex = getRows().indexOf(row); + fireTableCellUpdated(rowIndex, + SAMPLE_WEIGHT, + SAMPLING_RATIO); + } + + + } + @Override protected boolean isCellEditable(int rowIndex, int columnIndex, @@ -196,5 +204,4 @@ } return result; } - } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTreeModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTreeModel.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTreeModel.java 2012-12-12 17:06:45 UTC (rev 46) @@ -24,12 +24,14 @@ * #L% */ -import com.google.common.collect.Lists; -import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil; import java.io.Serializable; import java.util.List; +import java.util.Map; +import java.util.Set; /** * @author tchemit <chemit@codelutin.com> @@ -51,52 +53,180 @@ * * @since 0.2 */ - protected final String[] samplingOrder; + protected String[] samplingOrder; /** - * Samplings view as a linear list (to display in the table). + * Mapping from row to node. * * @since 0.2 */ - protected final List<SpeciesBatchTreeNode> lines; + protected final Map<SpeciesBatchRowModel, SpeciesBatchTreeNode> rowToNode; + /** + * Mapping from node to row. + * + * @since 0.2 + */ + protected final Map<SpeciesBatchTreeNode, SpeciesBatchRowModel> nodeToRow; + + public SpeciesBatchTreeModel(String... samplingOrder) { this.samplingOrder = samplingOrder; root = new SpeciesBatchTreeNode(); - lines = Lists.newArrayList(); + rowToNode = Maps.newHashMap(); + nodeToRow = Maps.newHashMap(); } - public SpeciesBatchTreeNode getNode(int rowIndex) { - return lines.get(rowIndex); + public void populate(List<SpeciesBatchRowModel> rows) { + + clear(); + + for (SpeciesBatchRowModel row : rows) { + + SpeciesBatchTreeNode node = getSamplingNode(row); + + nodeToRow.put(node, row); + } } - public int getSize() { - return lines.size(); + public String[] getSamplingOrder() { + return samplingOrder; } - public void populate(List<SpeciesBatch> data) { + public void setSamplingOrder(String... samplingOrder) { + this.samplingOrder = samplingOrder; + clear(); + } + protected void clear() { // clear tree representation root.removeAllChildren(); - // clear linear representation - lines.clear(); + // clear mappings + rowToNode.clear(); + nodeToRow.clear(); } - public Object[] getSamplingKey(SpeciesBatch bean) { - List<Object> result = Lists.newArrayList(); - for (String s : samplingOrder) { - Object property = TuttiUIUtil.getProperty(bean, s); - if (property == null) { - // stop findind sample key - break; + + public SpeciesBatchTreeNode removeNodeFromCache(SpeciesBatchRowModel row) { + SpeciesBatchTreeNode result = rowToNode.remove(row); + if (result != null) { + + nodeToRow.remove(result); + } + return result; + } + + public SpeciesBatchTreeNode getSamplingNode(SpeciesBatchRowModel row) { + + // search frist in cache + SpeciesBatchTreeNode result = rowToNode.get(row); + + if (result == null) { + + // not in cache must build the path + result = getSamplingNode(root, 0, row); + + // and add it in cache + rowToNode.put(row, result); + } + return result; + } + + protected SpeciesBatchTreeNode getSamplingNode(SpeciesBatchTreeNode node, + int samplingIndex, + SpeciesBatchRowModel row) { + + String samplingKey = samplingOrder[samplingIndex]; + + Serializable samplingValue = (Serializable) + TuttiUIUtil.getProperty(row, samplingKey); + + SpeciesBatchTreeNode result; + + if (samplingValue == null) { + + // was already on last sampling node + result = node; + } else { + + result = node.getChild(samplingValue); + + if (result == null) { + + // new node, creates it and add it as child of current node + result = new SpeciesBatchTreeNode(samplingKey, samplingValue); + node.add(result); } - result.add(property); + + if (samplingIndex < samplingOrder.length) { + + // can try to find yet another sampling level + result = getSamplingNode(result, samplingIndex + 1, row); + } } - return result.toArray(); + + return result; } - public String[] getSamplingDefinition(SpeciesBatch bean) { - return null; + public SamplingContext createSamplingContext(SpeciesBatchTreeNode rootNode) { + + Set<SpeciesBatchRowModel> childRows = Sets.newHashSet(); + + SpeciesBatchRowModel superSamplingRow = nodeToRow.get(rootNode); + float totalWeight = 0f; + for (int i = 0, nbChildren = rootNode.getChildCount(); i < nbChildren; i++) { + SpeciesBatchTreeNode node = rootNode.getChildAt(i); + SpeciesBatchRowModel row = nodeToRow.get(node); + if (row != null) { + childRows.add(row); + Float weight = row.getWeight(); + if (weight != null) { + totalWeight += weight; + } + } + } + SamplingContext result = new SamplingContext(rootNode, + superSamplingRow, + childRows, + totalWeight); + return result; } + + public static class SamplingContext { + + private final SpeciesBatchTreeNode rootNode; + + private final SpeciesBatchRowModel superSamplingRow; + + private final Set<SpeciesBatchRowModel> samplingRows; + + private final float totalWeight; + + public SamplingContext(SpeciesBatchTreeNode rootNode, + SpeciesBatchRowModel superSamplingRow, + Set<SpeciesBatchRowModel> samplingRows, + float totalWeight) { + this.rootNode = rootNode; + this.superSamplingRow = superSamplingRow; + this.samplingRows = samplingRows; + this.totalWeight = totalWeight; + } + + public SpeciesBatchTreeNode getRootNode() { + return rootNode; + } + + public SpeciesBatchRowModel getSuperSamplingRow() { + return superSamplingRow; + } + + public Set<SpeciesBatchRowModel> getSamplingRows() { + return samplingRows; + } + + public float getTotalWeight() { + return totalWeight; + } + } } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTreeNode.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTreeNode.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesBatchTreeNode.java 2012-12-12 17:06:45 UTC (rev 46) @@ -24,20 +24,18 @@ * #L% */ -import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; +import org.apache.commons.lang3.ObjectUtils; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeNode; import java.io.Serializable; /** - * Defines a node of a species catches. + * Defines a node of a species catches sampling. * <p/> - * UserObject is the {@link SpeciesBatch}. It can be null on two cases: - * <ul> - * <li>On root node</li> - * <li>For node on a path of sampling but with no filled data </li> - * </ul> + * A path in the tree gives a sampling path. + * <p/> + * UserObject is the {@code samplingValue}. It can be null only on root node. * * @author tchemit <chemit@codelutin.com> * @since 0.2 @@ -53,43 +51,55 @@ * * @since 0.2 */ - protected final String samplingPropertyKey; + protected final String samplingKey; - /** - * Property value defining the sampling. - * <p/> - * <strong>Note:</strong> can be null (only for root node). - * - * @since 0.2 - */ - protected final Serializable samplingPropertyValue; - public SpeciesBatchTreeNode() { - this(null, null, null); + this(null, null); } - public SpeciesBatchTreeNode(SpeciesBatch userObject, - String samplingPropertyKey, - Serializable samplingPropertyValue) { - this.samplingPropertyKey = samplingPropertyKey; - this.samplingPropertyValue = samplingPropertyValue; - setUserObject(userObject); + public SpeciesBatchTreeNode(String samplingKey, + Serializable samplingValue) { + this.samplingKey = samplingKey; + setUserObject(samplingValue); } public String getSamplingPropertyKey() { - return samplingPropertyKey; + return samplingKey; } - public Serializable getSamplingPropertyValue() { - return samplingPropertyValue; + public boolean matchSamplingValue(Serializable value) { + Serializable samplingValue = getUserObject(); + + boolean result = ObjectUtils.equals(value, samplingValue); + return result; } + public SpeciesBatchTreeNode getChild(Serializable samplingValue) { + SpeciesBatchTreeNode result = null; + + for (int i = 0, max = getChildCount(); i < max; i++) { + SpeciesBatchTreeNode child = getChildAt(i); + if (child.matchSamplingValue(samplingValue)) { + + // found matching child + result = child; + break; + } + } + return result; + } + @Override - public SpeciesBatch getUserObject() { - return (SpeciesBatch) super.getUserObject(); + public Serializable getUserObject() { + return (Serializable) super.getUserObject(); } @Override + public SpeciesBatchTreeNode getChildAt(int index) { + return (SpeciesBatchTreeNode) super.getChildAt(index); + } + + @Override public SpeciesBatchTreeNode getParent() { return (SpeciesBatchTreeNode) super.getParent(); } Copied: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModel.java (from rev 41, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/catches/species/frequency/SpeciesFrequencyRowModel.java) =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModel.java (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModel.java 2012-12-12 17:06:45 UTC (rev 46) @@ -0,0 +1,169 @@ +package fr.ifremer.tutti.ui.swing.content.operation.species; + +/* + * #%L + * Tutti :: UI + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 Ifremer + * %% + * 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 com.google.common.collect.Lists; +import com.google.common.collect.Ordering; +import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; +import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchFrequency; +import fr.ifremer.tutti.ui.swing.AbstractTuttiBeanUIModel; +import org.nuiton.util.beans.Binder; +import org.nuiton.util.beans.BinderFactory; + +import java.util.List; + +/** + * Represents a batch frequency row. + * + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class SpeciesFrequencyRowModel extends AbstractTuttiBeanUIModel<SpeciesBatchFrequency, SpeciesFrequencyRowModel> implements Comparable<SpeciesFrequencyRowModel> { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_LENGTH_STEP = "lengthStep"; + + public static final String PROPERTY_NUMBER = "number"; + + public static final String PROPERTY_WEIGHT = "weight"; + + public static final String PROPERTY_COMPUTED_WEIGHT = "computedWeight"; + + /** + * Length step. + * + * @since 0.2 + */ + protected Float lengthStep; + + /** + * Count of fishes for this lengthStep. + * + * @since 0.2 + */ + protected Integer number; + + /** + * Weight of fishes observed. + * + * @since 0.2 + */ + protected Float weight; + + /** + * Computed weight from number + relation taille-poids. + * + * @since 0.2 + */ + protected Float computedWeight; + + protected static final Binder<SpeciesBatchFrequency, SpeciesFrequencyRowModel> fromBeanBinder = + BinderFactory.newBinder(SpeciesBatchFrequency.class, + SpeciesFrequencyRowModel.class); + + protected static final Binder<SpeciesFrequencyRowModel, SpeciesBatchFrequency> toBeanBinder = + BinderFactory.newBinder(SpeciesFrequencyRowModel.class, + SpeciesBatchFrequency.class); + + private static final Ordering<Float> ordering = Ordering.natural().nullsFirst(); + + public static List<SpeciesFrequencyRowModel> fromBeans(List<SpeciesBatchFrequency> frequency) { + List<SpeciesFrequencyRowModel> result = Lists.newArrayList(); + for (SpeciesBatchFrequency b : frequency) { + SpeciesFrequencyRowModel model = new SpeciesFrequencyRowModel(); + fromBeanBinder.copy(b, model); + result.add(model); + } + return result; + } + + public static List<SpeciesBatchFrequency> toBeans(List<SpeciesFrequencyRowModel> frequency, SpeciesBatch batch) { + List<SpeciesBatchFrequency> result = Lists.newArrayList(); + for (SpeciesFrequencyRowModel b : frequency) { + SpeciesBatchFrequency model = new SpeciesBatchFrequency(); + toBeanBinder.copy(b, model); + model.setBatch(batch); + result.add(model); + } + return result; + } + + public SpeciesFrequencyRowModel() { + super(SpeciesBatchFrequency.class, fromBeanBinder, toBeanBinder); + } + + public Float getLengthStep() { + return lengthStep; + } + + public void setLengthStep(Float lengthStep) { + Object oldValue = getLengthStep(); + this.lengthStep = lengthStep; + firePropertyChange(PROPERTY_LENGTH_STEP, oldValue, lengthStep); + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + Object oldValue = getNumber(); + this.number = number; + firePropertyChange(PROPERTY_NUMBER, oldValue, number); + } + + public Float getWeight() { + return weight; + } + + public void setWeight(Float weight) { + Object oldValue = getWeight(); + this.weight = weight; + firePropertyChange(PROPERTY_WEIGHT, oldValue, weight); + } + + public Float getComputedWeight() { + return computedWeight; + } + + public void setComputedWeight(Float computedWeight) { + Object oldValue = getComputedWeight(); + this.computedWeight = computedWeight; + firePropertyChange(PROPERTY_COMPUTED_WEIGHT, oldValue, computedWeight); + } + + //TODO Use validator + @Override + public boolean isValid() { + return lengthStep != null && number != null; + } + + @Override + public int compareTo(SpeciesFrequencyRowModel o) { + int result = ordering.compare(lengthStep, o.lengthStep); + return result; + } +} Property changes on: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyTableModel.java (from rev 41, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/catches/species/frequency/SpeciesFrequencyTableModel.java) =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyTableModel.java (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyTableModel.java 2012-12-12 17:06:45 UTC (rev 46) @@ -0,0 +1,145 @@ +package fr.ifremer.tutti.ui.swing.content.operation.species; + +/* + * #%L + * Tutti :: UI + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 Ifremer + * %% + * 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 com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import fr.ifremer.tutti.ui.swing.util.table.AbstractTuttiTableModel; +import fr.ifremer.tutti.ui.swing.util.table.ColumnIdentifier; + +import javax.swing.table.TableColumnModel; +import java.util.List; +import java.util.Map; + +import static org.nuiton.i18n.I18n.n_; + +/** + * Model of the species frequency table. + * + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class SpeciesFrequencyTableModel extends AbstractTuttiTableModel<SpeciesFrequencyRowModel> { + + private static final long serialVersionUID = 1L; + + public static final ColumnIdentifier<SpeciesFrequencyRowModel> LENGTH_STEP = ColumnIdentifier.newId( + SpeciesFrequencyRowModel.PROPERTY_LENGTH_STEP, + n_("tutti.table.species.frequency.header.lengthStep"), + n_("tutti.table.species.frequency.header.lengthStep")); + + public static final ColumnIdentifier<SpeciesFrequencyRowModel> NUMBER = ColumnIdentifier.newId( + SpeciesFrequencyRowModel.PROPERTY_NUMBER, + n_("tutti.table.species.frequency.header.number"), + n_("tutti.table.species.frequency.header.number")); + + public static final ColumnIdentifier<SpeciesFrequencyRowModel> WEIGHT = ColumnIdentifier.newId( + SpeciesFrequencyRowModel.PROPERTY_WEIGHT, + n_("tutti.table.species.frequency.header.weight"), + n_("tutti.table.species.frequency.header.weight")); + + public static final ColumnIdentifier<SpeciesFrequencyRowModel> COMPUTED_WEIGHT = ColumnIdentifier.newId( + SpeciesFrequencyRowModel.PROPERTY_COMPUTED_WEIGHT, + n_("tutti.table.species.frequency.header.computedWeight"), + n_("tutti.table.species.frequency.header.computedWeight")); + + private final SpeciesFrequencyUIModel uiModel; + + private final Map<Float, SpeciesFrequencyRowModel> rowCache; + + public SpeciesFrequencyTableModel(TableColumnModel columnModel, + SpeciesFrequencyUIModel uiModel) { + super(columnModel); + this.uiModel = uiModel; + this.rowCache = Maps.newTreeMap(); + setNoneEditableCols(COMPUTED_WEIGHT); + } + + @Override + protected SpeciesFrequencyRowModel createNewRow() { + Float defaultStep = null; + + int rowCount = getRowCount(); + if (rowCount > 0) { + + SpeciesFrequencyRowModel rowModel = getEntry(rowCount - 1); + Float lengthStep = rowModel.getLengthStep(); + if (lengthStep != null) { + defaultStep = uiModel.getLengthStep( + lengthStep + uiModel.getStep()); + } + } + SpeciesFrequencyRowModel result = new SpeciesFrequencyRowModel(); + result.setLengthStep(defaultStep); + return result; + } + + @Override + public void setValueAt(Object aValue, + int rowIndex, + int columnIndex, + ColumnIdentifier<SpeciesFrequencyRowModel> propertyName, + SpeciesFrequencyRowModel entry) { + super.setValueAt(aValue, rowIndex, columnIndex, propertyName, entry); + // TODO Rebuild the computedWeight if possible... + } + + public Map<Float, SpeciesFrequencyRowModel> getRowCache() { + return rowCache; + } + + @Override + protected void onRowsChanged(List<SpeciesFrequencyRowModel> data) { + + // rebuild row cache + rowCache.clear(); + + for (SpeciesFrequencyRowModel row : data) { + Float lengthStep = row.getLengthStep(); + if (lengthStep != null) { + rowCache.put(lengthStep, row); + } + } + } + + @Override + protected void onRowAdded(int rowIndex, SpeciesFrequencyRowModel newValue) { + + Preconditions.checkNotNull(newValue, "can't add a null row"); + + // add new row to cache + Float lengthStep = newValue.getLengthStep(); + + Preconditions.checkNotNull(lengthStep, + "can't add a null lengthStep row"); + + float roundLenghtValue = uiModel.getLengthStep(lengthStep); + + if (!rowCache.containsKey(roundLenghtValue)) { + + rowCache.put(roundLenghtValue, newValue); + } + } +} \ No newline at end of file Property changes on: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyTableModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.css (from rev 41, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/catches/species/frequency/SpeciesFrequencyUI.css) =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.css (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.css 2012-12-12 17:06:45 UTC (rev 46) @@ -0,0 +1,141 @@ +/* + * #%L + * Tutti :: UI + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 Ifremer + * %% + * 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% + */ + +NumberEditor { + autoPopup: {handler.getConfig().isAutoPopupNumberEditor()}; + showPopupButton: {handler.getConfig().isShowNumberEditorButton()}; +} + +#stepLabel { + text: "tutti.label.frequencyConfiguration.step"; + labelFor: {stepField}; +} + +#stepField { + property: "step"; + model: {model.getStep()}; + useFloat: true; + numberPattern: {DECIMAL1_PATTERN}; + bean: {model}; +} + +#minStepLabel { + text: "tutti.label.frequencyConfiguration.minStep"; + labelFor: {minStepField}; +} + +#minStepField { + property: "minStep"; + model: {model.getMinStep()}; + useFloat: true; + showReset: true; + numberPattern: {DECIMAL1_PATTERN}; + bean: {model}; +} + +#maxStepLabel { + text: "tutti.label.frequencyConfiguration.maxStep"; + labelFor: {maxStepField}; +} + +#maxStepField { + property: "maxStep"; + model: {model.getMaxStep()}; + useFloat: true; + showReset: true; + numberPattern: {DECIMAL1_PATTERN}; + bean: {model}; +} + +#rafaleStepLabel { + text: "tutti.label.frequencyConfiguration.rafaleStep"; + labelFor: {rafaleStepField}; +} + +#rafaleStepField { + modelType: {Float.class}; + useFloat: true; + showReset: true; + numberPattern: {DECIMAL1_PATTERN}; +} + +#generateButton { + actionIcon: "generate"; + text: "tutti.action.generate"; + enabled: {model.isCanGenerate()}; +} + +#configurationPanel { + border: {new TitledBorder(null, _("tutti.legend.frequencyConfiguration"))}; +} + +#modeConfigurationLayout { + selected: {String.valueOf(mode.getSelectedValue())}; +} + +#modeConfigurationPanel { + layout: {modeConfigurationLayout}; +} + +#simpleModeButton { + text: "tutti.label.frequencyConfiguration.mode.simple"; + toolTipText: "tutti.label.frequencyConfiguration.mode.simple.tip"; + value: "simpleMode"; + selected: {model.isSimpleMode()}; + buttonGroup: "mode"; +} + +#simpleModeLabel { + text: "tutti.label.frequencyConfiguration.no.configuration"; + horizontalAlignment: {JLabel.CENTER}; + enabled: false; +} + +#autoGenModeButton { + text: "tutti.label.frequencyConfiguration.mode.autoGen"; + toolTipText: "tutti.label.frequencyConfiguration.mode.autoGen.tip"; + value: "autoGenMode"; + selected: {model.isAutoGenMode()}; + buttonGroup: "mode"; +} + +#rafaleModeButton { + text: "tutti.label.frequencyConfiguration.mode.rafale"; + toolTipText: "tutti.label.frequencyConfiguration.mode.rafale.tip"; + value: "rafaleMode"; + selected: {model.isRafaleMode()}; + buttonGroup: "mode"; +} + +#closeButton { + actionIcon: "close"; + text: "tutti.action.close"; +} + +#table { + selectionMode: {ListSelectionModel.SINGLE_SELECTION}; + selectionBackground: {null}; + selectionForeground: {Color.BLACK}; + sortable: false; +} \ No newline at end of file Property changes on: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.css ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.jaxx (from rev 41, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/catches/species/frequency/SpeciesFrequencyUI.jaxx) =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.jaxx (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.jaxx 2012-12-12 17:06:45 UTC (rev 46) @@ -0,0 +1,167 @@ +<!-- + #%L + Tutti :: UI + $Id$ + $HeadURL$ + %% + Copyright (C) 2012 Ifremer + %% + 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% + --> +<JPanel id='homePanel' layout='{new BorderLayout()}' + implements='fr.ifremer.tutti.ui.swing.TuttiUI<SpeciesFrequencyUIModel, SpeciesFrequencyUIHandler>'> + + <import> + fr.ifremer.tutti.ui.swing.TuttiUIContext + fr.ifremer.tutti.ui.swing.content.operation.species.SpeciesBatchRowModel + + jaxx.runtime.swing.CardLayout2Ext + jaxx.runtime.swing.editor.bean.BeanComboBox + jaxx.runtime.swing.editor.NumberEditor + + org.jdesktop.swingx.JXTable + + javax.swing.ListSelectionModel + javax.swing.SwingConstants + + java.awt.Color + java.awt.Dimension + + static org.nuiton.i18n.I18n._ + static jaxx.runtime.SwingUtil.getStringValue + </import> + + <script><![CDATA[ + + public SpeciesFrequencyUI(TuttiUIContext context) { + SpeciesFrequencyUIHandler handler = new SpeciesFrequencyUIHandler(context, this); + setContextValue(handler); + handler.beforeInitUI(); + } + + public void editBatch(SpeciesBatchRowModel row) { + handler.editBatch(row); + } + + protected void $afterCompleteSetup() { + handler.afterInitUI(); + } + ]]></script> + + <SpeciesFrequencyUIHandler id='handler' + initializer='getContextValue(SpeciesFrequencyUIHandler.class)'/> + + <SpeciesFrequencyUIModel id='model' + initializer='getContextValue(SpeciesFrequencyUIModel.class)'/> + + <CardLayout2Ext id='modeConfigurationLayout' + constructorParams='this, "modeConfigurationPanel"'/> + + <JPanel id='configurationPanel' layout='{new BorderLayout()}' constraints='BorderLayout.NORTH'> + + <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.CENTER'> + <VBox id='modePanel' constraints='BorderLayout.WEST' + verticalAlignment='{SwingConstants.CENTER}'> + <JRadioButton id='simpleModeButton' + onActionPerformed='model.setConfigurationMode(SpeciesFrequencyUIModel.ConfigurationMode.SIMPLE)'/> + <JRadioButton id='autoGenModeButton' + onActionPerformed='model.setConfigurationMode(SpeciesFrequencyUIModel.ConfigurationMode.AUTO_GEN)'/> + <JRadioButton id='rafaleModeButton' + onActionPerformed='model.setConfigurationMode(SpeciesFrequencyUIModel.ConfigurationMode.RAFALE)'/> + </VBox> + + <JPanel id='modeConfigurationPanel' constraints='BorderLayout.CENTER'> + <JPanel id='simpleModePanel' constraints='"simpleMode"' + layout='{new BorderLayout()}'> + <JLabel id='simpleModeLabel' constraints='BorderLayout.CENTER'/> + </JPanel> + <JPanel id='autoGenModePanel' constraints='"autoGenMode"'> + <Table fill='both' constraints='BorderLayout.SOUTH'> + <!-- Min step--> + <row> + <cell anchor='west'> + <JLabel id='minStepLabel'/> + </cell> + <cell weightx='1.0'> + <NumberEditor id='minStepField' constructorParams='this'/> + </cell> + </row> + <!-- Max step--> + <row> + <cell anchor='west'> + <JLabel id='maxStepLabel'/> + </cell> + <cell weightx='1.0'> + <NumberEditor id='maxStepField' constructorParams='this'/> + </cell> + </row> + <!-- Actions --> + <row> + <cell columns='2'> + <JPanel layout='{new GridLayout(1, 0)}'> + <JButton id='generateButton' + onActionPerformed='handler.generateLengthSteps()'/> + </JPanel> + </cell> + </row> + </Table> + </JPanel> + <JPanel id='rafaleModePanel' constraints='"rafaleMode"'> + <Table fill='both' constraints='BorderLayout.SOUTH'> + <!-- Rafale step--> + <row> + <cell weightx='1.0'> + <JLabel id='rafaleStepLabel'/> + </cell> + </row> + <row> + <cell weightx='1.0'> + <NumberEditor id='rafaleStepField' constructorParams='this'/> + </cell> + </row> + </Table> + </JPanel> + </JPanel> + </JPanel> + <Table fill='both' constraints='BorderLayout.SOUTH'> + <row> + <cell columns='2'> + <JSeparator/> + </cell> + </row> + <!-- Step --> + <row> + <cell anchor='west'> + <JLabel id='stepLabel'/> + </cell> + <cell weightx='1.0'> + <NumberEditor id='stepField' constructorParams='this'/> + </cell> + </row> + </Table> + </JPanel> + + <JScrollPane id='tableScrollPane' constraints='BorderLayout.CENTER'> + <JXTable id='table'/> + </JScrollPane> + + <!-- actions --> + <JPanel id='actionPanel' layout='{new GridLayout(1, 0)}' + constraints='BorderLayout.SOUTH'> + <JButton id='closeButton' onActionPerformed='handler.close()'/> + </JPanel> + +</JPanel> \ No newline at end of file Property changes on: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.jaxx ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIHandler.java (from rev 41, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/catches/species/frequency/SpeciesFrequencyUIHandler.java) =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIHandler.java (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIHandler.java 2012-12-12 17:06:45 UTC (rev 46) @@ -0,0 +1,350 @@ +package fr.ifremer.tutti.ui.swing.content.operation.species; + +/* + * #%L + * Tutti :: UI + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 Ifremer + * %% + * 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 com.google.common.collect.Lists; +import fr.ifremer.tutti.ui.swing.TuttiUI; +import fr.ifremer.tutti.ui.swing.TuttiUIContext; +import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil; +import fr.ifremer.tutti.ui.swing.util.table.AbstractTuttiTableUIHandler; +import jaxx.runtime.SwingUtil; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTable; +import org.jdesktop.swingx.decorator.HighlightPredicate; +import org.jdesktop.swingx.table.DefaultTableColumnModelExt; + +import javax.swing.JDialog; +import javax.swing.table.TableColumnModel; +import java.awt.Color; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class SpeciesFrequencyUIHandler extends AbstractTuttiTableUIHandler<SpeciesFrequencyRowModel, SpeciesFrequencyUIModel> { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(SpeciesFrequencyUIHandler.class); + + private final SpeciesFrequencyUI ui; + + public SpeciesFrequencyUIHandler(TuttiUIContext context, + SpeciesFrequencyUI ui) { + super(context, + SpeciesFrequencyRowModel.PROPERTY_LENGTH_STEP, + SpeciesFrequencyRowModel.PROPERTY_NUMBER, + SpeciesFrequencyRowModel.PROPERTY_WEIGHT, + SpeciesFrequencyRowModel.PROPERTY_COMPUTED_WEIGHT); + this.ui = ui; + } + + //------------------------------------------------------------------------// + //-- AbstractTuttiTableUIHandler methods --// + //------------------------------------------------------------------------// + + @Override + protected SpeciesFrequencyUIModel getModel() { + return ui.getModel(); + } + + @Override + protected SpeciesFrequencyTableModel getTableModel() { + return (SpeciesFrequencyTableModel) getTable().getModel(); + } + + @Override + protected JXTable getTable() { + return ui.getTable(); + } + + @Override + protected TableColumnModel createTableColumnModel() { + + DefaultTableColumnModelExt columnModel = new DefaultTableColumnModelExt(); + + { // LengthStep + + addFloatColumnToModel(columnModel, + SpeciesFrequencyTableModel.LENGTH_STEP, + TuttiUI.DECIMAL1_PATTERN); + } + + { // Number + + addIntegerColumnToModel(columnModel, + SpeciesFrequencyTableModel.NUMBER, + TuttiUI.INT_6_DIGITS_PATTERN); + } + + { // Weight + + addFloatColumnToModel(columnModel, + SpeciesFrequencyTableModel.WEIGHT, + TuttiUI.DECIMAL3_PATTERN); + } + + { // ComputedWeight + + addFloatColumnToModel(columnModel, + SpeciesFrequencyTableModel.COMPUTED_WEIGHT, + TuttiUI.DECIMAL3_PATTERN); + } + return columnModel; + } + + @Override + protected void onRowModified(SpeciesFrequencyRowModel row, + String propertyName, + Object oldValue, + Object newValue) { + if (SpeciesFrequencyRowModel.PROPERTY_NUMBER.equals(propertyName)) { + + // Need to recompute the computedWeight + computeComputedWeight(row); + } + } + + //------------------------------------------------------------------------// + //-- AbstractTuttiUIHandler methods --// + //------------------------------------------------------------------------// + + @Override + public void beforeInitUI() { + + SpeciesFrequencyUIModel model = new SpeciesFrequencyUIModel(); + + ui.setContextValue(model); + } + + @Override + public void afterInitUI() { + + initUI(ui); + + JXTable table = getTable(); + + // create table column model + TableColumnModel columnModel = createTableColumnModel(); + + SpeciesFrequencyUIModel model = getModel(); + + // create table model + SpeciesFrequencyTableModel tableModel = + new SpeciesFrequencyTableModel(columnModel, model); + + table.setModel(tableModel); + table.setColumnModel(columnModel); + + installTableKeyListener(columnModel, table); + + table.getTableHeader().setReorderingAllowed(false); + + table.addHighlighter(TuttiUIUtil.newBackgroundColorHighlighter( + HighlightPredicate.READ_ONLY, Color.LIGHT_GRAY)); + + // when model datas change let's propagate it table model + listenRowsFromModel(); + + //TODO Should it come from PROTOCOL or config ? + model.setStep(.5f); + + model.setMinStep(10f); + model.setMaxStep(20f); + + //TODO Configure this ? + model.setConfigurationMode(SpeciesFrequencyUIModel.ConfigurationMode.SIMPLE); + + // always scroll to selected row + SwingUtil.scrollToTableSelection(getTable()); + + ui.getRafaleStepField().getTextField().addKeyListener(new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + e.consume(); + Float step = (Float) ui.getRafaleStepField().getModel(); + + applyRafaleStep(step); + } + } + }); + } + + @Override + public void onCloseUI() { + } + + //------------------------------------------------------------------------// + //-- Public methods --// + //------------------------------------------------------------------------// + + public void generateLengthSteps() { + + SpeciesFrequencyUIModel model = getModel(); + + Map<Float, SpeciesFrequencyRowModel> rowsByStep = + getTableModel().getRowCache(); + + Float minStep = model.getLengthStep(model.getMinStep()); + Float maxStep = model.getLengthStep(model.getMaxStep()); + + for (float i = minStep, step = model.getStep(); i <= maxStep; i += step) { + if (!rowsByStep.containsKey(i)) { + + // add it + SpeciesFrequencyRowModel newRow = new SpeciesFrequencyRowModel(); + newRow.setLengthStep(i); + rowsByStep.put(i, newRow); + } + } + + List<SpeciesFrequencyRowModel> rows = + Lists.newArrayList(rowsByStep.values()); + + model.setRows(rows); + } + + public void applyRafaleStep(Float step) { + + if (log.isInfoEnabled()) { + log.info("Will apply rafale step: " + step); + } + SpeciesFrequencyUIModel model = getModel(); + SpeciesFrequencyTableModel tableModel = getTableModel(); + + Map<Float, SpeciesFrequencyRowModel> rowsByStep = tableModel.getRowCache(); + + float aroundLengthStep = model.getLengthStep(step); + + SpeciesFrequencyRowModel row = rowsByStep.get(aroundLengthStep); + + int rowIndex; + + if (row != null) { + + // increments current row + Integer number = row.getNumber(); + row.setNumber((number == null ? 0 : number) + 1); + rowIndex = tableModel.updateRow(row); + + } else { + + // create a new row + row = new SpeciesFrequencyRowModel(); + row.setLengthStep(aroundLengthStep); + row.setNumber(1); + + // get new index + List<Float> steps = Lists.newArrayList(rowsByStep.keySet()); + steps.add(aroundLengthStep); + + Collections.sort(steps); + + rowIndex = steps.indexOf(aroundLengthStep); + + tableModel.addNewRow(rowIndex, row); + } + + getTable().scrollRowToVisible(rowIndex); + } + + public void editBatch(SpeciesBatchRowModel row) { + + List<SpeciesFrequencyRowModel> frequency = null; + if (row != null) { + frequency = row.getFrequency(); + } + + List<SpeciesFrequencyRowModel> editFrequency; + if (CollectionUtils.isEmpty(frequency)) { + + // new list + editFrequency = Lists.newArrayList(); + } else { + + editFrequency = Lists.newArrayList(frequency); + } + + if (log.isInfoEnabled()) { + log.info("Will edit batch row: " + row + " with " + + editFrequency.size() + " frequency"); + } + getModel().setRows(editFrequency); + + // keep batch (will be used to push back editing entry) + getModel().setBatch(row); + } + + public void close() { + + if (log.isInfoEnabled()) { + log.info("Will close UI " + ui); + } + + // transfer rows to editor + + List<SpeciesFrequencyRowModel> frequency = Lists.newArrayList(); + for (SpeciesFrequencyRowModel row : getModel().getRows()) { + if (row.isValid()) { + + // can keep this row + frequency.add(row); + } + } + + if (log.isInfoEnabled()) { + log.info("Push back " + frequency.size() + + " frequency to batch " + getModel().getBatch()); + } + + // push back to batch + getModel().getBatch().setFrequency(frequency); + + ui.editBatch(null); + + SwingUtil.getParentContainer(ui, JDialog.class).setVisible(false); + } + + //------------------------------------------------------------------------// + //-- Internal methods --// + //------------------------------------------------------------------------// + + protected void computeComputedWeight(SpeciesFrequencyRowModel row) { + + if (log.isInfoEnabled()) { + log.info("Will recompute computed weight for frequency: " + row); + } + } + +} \ No newline at end of file Property changes on: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIModel.java (from rev 41, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/catches/species/frequency/SpeciesFrequencyUIModel.java) =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIModel.java (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIModel.java 2012-12-12 17:06:45 UTC (rev 46) @@ -0,0 +1,174 @@ +package fr.ifremer.tutti.ui.swing.content.operation.species; + +/* + * #%L + * Tutti :: UI + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 Ifremer + * %% + * 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.ifremer.tutti.ui.swing.util.table.AbstractTuttiTableUIModel; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class SpeciesFrequencyUIModel extends AbstractTuttiTableUIModel<SpeciesBatchRowModel, SpeciesFrequencyRowModel, SpeciesFrequencyUIModel> { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_CONFIGURATION_MODE = "configurationMode"; + + public static final String PROPERTY_STEP = "step"; + + private static final String PROPERTY_MIN_STEP = "minStep"; + + private static final String PROPERTY_MAX_STEP = "maxStep"; + + public static final String PROPERTY_CAN_GENERATE = "canGenerate"; + + public static final String PROPERTY_SIMPLE_MODE = "simpleMode"; + + public static final String PROPERTY_AUTO_GEN_MODE = "autoGenMode"; + + public static final String PROPERTY_RAFALE_MODE = "rafaleMode"; + + public static enum ConfigurationMode { + SIMPLE, + AUTO_GEN, + RAFALE + } + + /** + * Fill mode. + * + * @since 0.2 + */ + protected ConfigurationMode configurationMode; + + /** + * Batch that contains frequencies. + * + * @since 0.2 + */ + protected SpeciesBatchRowModel batch; + + /** + * Default step to increment length step. + * + * @since 0.2 + */ + protected float step; + + /** + * Min step to auto generate length steps. + * + * @since 0.2 + */ + protected Float minStep; + + /** + * Max step to auto generate length steps. + * + * @since 0.2 + */ + protected Float maxStep; + + public SpeciesFrequencyUIModel() { + super(SpeciesBatchRowModel.class, null, null); + } + + public ConfigurationMode getConfigurationMode() { + return configurationMode; + } + + public void setConfigurationMode(ConfigurationMode configurationMode) { + Object oldValue = getConfigurationMode(); + this.configurationMode = configurationMode; + firePropertyChange(PROPERTY_CONFIGURATION_MODE, oldValue, configurationMode); + firePropertyChange(PROPERTY_SIMPLE_MODE, null, isSimpleMode()); + firePropertyChange(PROPERTY_AUTO_GEN_MODE, null, isAutoGenMode()); + firePropertyChange(PROPERTY_RAFALE_MODE, null, isRafaleMode()); + } + + public float getStep() { + return step; + } + + public void setStep(float step) { + Object oldValue = getStep(); + this.step = step; + firePropertyChange(PROPERTY_STEP, oldValue, step); + } + + public Float getMinStep() { + return minStep; + } + + public void setMinStep(Float minStep) { + Object oldValue = getMinStep(); + this.minStep = minStep; + firePropertyChange(PROPERTY_MIN_STEP, oldValue, minStep); + firePropertyChange(PROPERTY_CAN_GENERATE, null, isCanGenerate()); + } + + public Float getMaxStep() { + return maxStep; + } + + public void setMaxStep(Float maxStep) { + Object oldValue = getMaxStep(); + this.maxStep = maxStep; + firePropertyChange(PROPERTY_MAX_STEP, oldValue, maxStep); + firePropertyChange(PROPERTY_CAN_GENERATE, null, isCanGenerate()); + } + + public boolean isSimpleMode() { + return ConfigurationMode.SIMPLE == configurationMode; + } + + public boolean isAutoGenMode() { + return ConfigurationMode.AUTO_GEN == configurationMode; + } + + public boolean isRafaleMode() { + return ConfigurationMode.RAFALE == configurationMode; + } + + public boolean isCanGenerate() { + return minStep != null && maxStep != null && maxStep > minStep; + } + + public SpeciesBatchRowModel getBatch() { + return batch; + } + + public void setBatch(SpeciesBatchRowModel batch) { + this.batch = batch; + } + + public float getLengthStep(float lengthStep) { + int intValue = (int) (lengthStep * 10); + int intStep = (int) (step * 10); + int correctIntStep = intValue - (intValue % intStep); + float result = correctIntStep / 10f; + return result; + } +} \ No newline at end of file Property changes on: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUIModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUI.css =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUI.css 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUI.css 2012-12-12 17:06:45 UTC (rev 46) @@ -71,10 +71,8 @@ } #totalHorsVracWeightField { - property: "totalHorsVracWeight"; - model: {model.getTotalHorsVracWeight()}; - useFloat: false; - numberPattern: {INT_6_DIGITS_PATTERN}; + text: {getStringValue(model.getTotalHorsVracWeight())}; + editable: false; } #table { Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUI.jaxx =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUI.jaxx 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUI.jaxx 2012-12-12 17:06:45 UTC (rev 46) @@ -29,7 +29,7 @@ fr.ifremer.tutti.ui.swing.TuttiUIContext fr.ifremer.tutti.ui.swing.content.operation.FishingOperationsUI - fr.ifremer.tutti.ui.swing.content.catches.species.frequency.SpeciesFrequencyUI + fr.ifremer.tutti.ui.swing.content.operation.species.SpeciesFrequencyUI org.jdesktop.swingx.JXTable @@ -43,6 +43,7 @@ java.awt.Color static org.nuiton.i18n.I18n._ + static jaxx.runtime.SwingUtil.getStringValue </import> <script><![CDATA[ @@ -106,7 +107,7 @@ <JLabel id='totalHorsVracWeightLabel'/> </cell> <cell> - <NumberEditor id='totalHorsVracWeightField' constructorParams='this'/> + <JTextField id='totalHorsVracWeightField'/> </cell> </row> </Table> Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUIHandler.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUIHandler.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUIHandler.java 2012-12-12 17:06:45 UTC (rev 46) @@ -24,7 +24,9 @@ * #L% */ +import com.google.common.base.Preconditions; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import fr.ifremer.tutti.persistence.entities.TuttiEntities; import fr.ifremer.tutti.persistence.entities.data.FishingOperation; import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; @@ -37,9 +39,10 @@ import fr.ifremer.tutti.service.PersistenceService; import fr.ifremer.tutti.ui.swing.TuttiUI; import fr.ifremer.tutti.ui.swing.content.operation.FishingOperationsUI; -import fr.ifremer.tutti.ui.swing.content.catches.species.frequency.SpeciesFrequencyRowModel; +import fr.ifremer.tutti.ui.swing.util.TuttiBeanMonitor; import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil; import fr.ifremer.tutti.ui.swing.util.table.AbstractTuttiTableUIHandler; +import fr.ifremer.tutti.ui.swing.util.table.TableRowModificationListener; import jaxx.runtime.SwingUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -49,9 +52,13 @@ import org.nuiton.util.beans.BeanMonitor; import org.nuiton.util.decorator.Decorator; +import javax.swing.event.ListSelectionListener; import javax.swing.table.TableColumnModel; import java.awt.Color; +import java.awt.Component; +import java.awt.event.FocusEvent; import java.util.List; +import java.util.Set; /** * @author tchemit <chemit@codelutin.com> @@ -62,18 +69,45 @@ /** Logger. */ private static final Log log = LogFactory.getLog(SpeciesTabUIHandler.class); + public static final Set<String> RECOMPUTE_TOTAL_WEIGHT = Sets.newHashSet( + SpeciesBatchRowModel.PROPERTY_VRAC_HORS_VRAC, + SpeciesBatchRowModel.PROPERTY_WEIGHT + ); + + public static final Set<String> SAMPLING_PROPERTIES = Sets.newHashSet( + SpeciesBatchRowModel.PROPERTY_SPECIES, + SpeciesBatchRowModel.PROPERTY_VRAC_HORS_VRAC, + SpeciesBatchRowModel.PROPERTY_WEIGHT_CATEGORY, + SpeciesBatchRowModel.PROPERTY_SEX, + SpeciesBatchRowModel.PROPERTY_MATURITY, + SpeciesBatchRowModel.PROPERTY_AGE + ); + + /** + * UI. + * + * @since 0.2 + */ private final SpeciesTabUI ui; - private final FishingOperationsUI parentUi; - + /** + * Persistence service. + * + * @since 0.2 + */ private final PersistenceService persistenceService; - private final BeanMonitor traitMonitor; + /** + * To monitor changes on the fishing operation. + * + * @since 0.2 + */ + private final BeanMonitor fishingOperationMonitor; public SpeciesTabUIHandler(FishingOperationsUI parentUi, SpeciesTabUI ui) { super(parentUi.getHandler().getContext(), + SpeciesBatchRowModel.PROPERTY_SPECIES_TO_CONFIRM, SpeciesBatchRowModel.PROPERTY_SPECIES, - SpeciesBatchRowModel.PROPERTY_SPECIES_TO_CONFIRM, SpeciesBatchRowModel.PROPERTY_VRAC_HORS_VRAC, SpeciesBatchRowModel.PROPERTY_WEIGHT_CATEGORY, SpeciesBatchRowModel.PROPERTY_SEX, @@ -85,9 +119,8 @@ SpeciesBatchRowModel.PROPERTY_COMMENT, SpeciesBatchRowModel.PROPERTY_FREQUENCY); this.ui = ui; - this.parentUi = parentUi; this.persistenceService = context.getService(PersistenceService.class); - traitMonitor = new BeanMonitor( + this.fishingOperationMonitor = new BeanMonitor( SpeciesTabUIModel.PROPERTY_SAMPLE_VRAC_WEIGHT, SpeciesTabUIModel.PROPERTY_TOTAL_HORS_VRAC_WEIGHT, SpeciesTabUIModel.PROPERTY_TOTAL_VRAC_WEIGHT, @@ -95,9 +128,13 @@ ); } + //------------------------------------------------------------------------// + //-- AbstractTuttiTableUIHandler methods --// + //------------------------------------------------------------------------// + @Override - protected JXTable getTable() { - return ui.getTable(); + protected SpeciesTabUIModel getModel() { + return ui.getModel(); } @Override @@ -106,24 +143,242 @@ } @Override - protected SpeciesTabUIModel getModel() { - return ui.getModel(); + protected JXTable getTable() { + return ui.getTable(); } @Override + protected void onModelRowsChanged(List<SpeciesBatchRowModel> rows) { + super.onModelRowsChanged(rows); + + // build the new sampling tree from the new rows to edit + getModel().getSamplingTreeModel().populate(rows); + } + + @Override + protected TableColumnModel createTableColumnModel() { + + List<String> samplingOrder = getModel().getSamplingOrder(); + + DefaultTableColumnModelExt columnModel = + new DefaultTableColumnModelExt(); + + { + // Species to confirm column + + addBooleanColumnToModel(columnModel, + SpeciesBatchTableModel.SPECIES_TO_CONFIRM, + getTable()); + } + + List<Species> allSpecies = persistenceService.getAllSpecies(); + + { + // Species (by code) column + + Decorator<Species> decorator = getDecorator( + Species.class, DecoratorService.SPECIES_BY_CODE); + + addComboDataColumnToModel(columnModel, + SpeciesBatchTableModel.SPECIES_BY_CODE, + decorator, allSpecies); + } + + { + // Species (by genusCode) column + + Decorator<Species> decorator = getDecorator( + Species.class, DecoratorService.SPECIES_BY_GENUS); + + addComboDataColumnToModel(columnModel, + SpeciesBatchTableModel.SPECIES_BY_GENUS_CODE, + decorator, allSpecies); + + } + + if (samplingOrder.contains(SpeciesBatchRowModel.PROPERTY_VRAC_HORS_VRAC)) { + + // Vrac / Hors vrac column + + addComboEnumColumnToModel(columnModel, + SpeciesBatchTableModel.VRAC_HORS_VRAC, + VracHorsVracEnum.values()); + } + + if (samplingOrder.contains(SpeciesBatchRowModel.PROPERTY_WEIGHT_CATEGORY)) { + + // WeightCategory column + + Decorator<WeightCategory> decorator = + getDecorator(WeightCategory.class, + DecoratorService.BY_NAME); + + List<WeightCategory> data = + persistenceService.getAllWeightCategory(); + + addComboDataColumnToModel(columnModel, + SpeciesBatchTableModel.WEIGHT_CATEGORY, + decorator, data); + } + + if (samplingOrder.contains(SpeciesBatchRowModel.PROPERTY_SEX)) { + + // Sex column + + Decorator<Sex> decorator = + getDecorator(Sex.class, DecoratorService.BY_NAME); + + List<Sex> data = persistenceService.getAllSex(); + + addComboDataColumnToModel(columnModel, + SpeciesBatchTableModel.SEX, + decorator, data); + } + + if (samplingOrder.contains(SpeciesBatchRowModel.PROPERTY_MATURITY)) { + + // Maturity column + + addFloatColumnToModel(columnModel, + SpeciesBatchTableModel.MATURITY, + TuttiUI.DECIMAL3_PATTERN); + } + + if (samplingOrder.contains(SpeciesBatchRowModel.PROPERTY_AGE)) { + + // Age column + + addFloatColumnToModel(columnModel, + SpeciesBatchTableModel.AGE, + TuttiUI.DECIMAL3_PATTERN); + } + + { // Weight column + + addFloatColumnToModel(columnModel, + SpeciesBatchTableModel.WEIGHT, + TuttiUI.DECIMAL3_PATTERN); + } + + { // Computed weight column (from frequencies) + + addColumnToModel(columnModel, + FrequencyCellComponent.newEditor(ui.getFrequencyUI()), + FrequencyCellComponent.newRender(), + SpeciesBatchTableModel.COMPUTED_WEIGHT); + } + + { // Computed number column (from frequencies) + + addColumnToModel(columnModel, + FrequencyCellComponent.newEditor(ui.getFrequencyUI()), + FrequencyCellComponent.newRender(), + SpeciesBatchTableModel.COMPUTED_NUMBER); + } + + { // Sample weight column + + addColumnToModel(columnModel, + SpeciesBatchTableModel.SAMPLE_WEIGHT); + } + + { // SamplingRatio column + + addColumnToModel(columnModel, + SpeciesBatchTableModel.SAMPLING_RATIO); + } + + { // Comment column + + addColumnToModel(columnModel, + SpeciesBatchTableModel.COMMENT); + } + + { // File column + + addColumnToModel(columnModel, + SpeciesBatchTableModel.FILE); + } + return columnModel; + } + + @Override + protected void onRowModified(SpeciesBatchRowModel row, + String propertyName, + Object oldValue, + Object newValue) { + + if (RECOMPUTE_TOTAL_WEIGHT.contains(propertyName)) { + + // Need to recompute totalHorsVracWeight + recomputeTotalHorsVrac(); + } + + SpeciesTabUIModel model = getModel(); + + SpeciesBatchTreeModel samplingTreeModel = model.getSamplingTreeModel(); + + if (SAMPLING_PROPERTIES.contains(propertyName)) { + + // Need to rebuilt this row sampling tree path (and then recompute + // old super - samplingRatio and new super - samplingRatio) + + // old node of the previous sampling def for this row + // and remove it from any cache + SpeciesBatchTreeNode oldNode = samplingTreeModel.removeNodeFromCache(row); + + // get new sampling node + SpeciesBatchTreeNode newNode = samplingTreeModel.getSamplingNode(row); + + moveSamplingNode(samplingTreeModel, row, oldNode, newNode); + } + + if (SpeciesBatchRowModel.PROPERTY_WEIGHT.equals(propertyName)) { + + // Need to recompute the super - samplingRatio + + SpeciesBatchTreeNode node = samplingTreeModel.getSamplingNode(row); + + recomputeSuperSamplingRatio(samplingTreeModel, row, node); + } + } + + //------------------------------------------------------------------------// + //-- AbstractTuttiUIHandler methods --// + //------------------------------------------------------------------------// + + @Override public void beforeInitUI() { + if (log.isInfoEnabled()) { + log.info("beforeInit: " + ui); + } + SpeciesTabUIModel model = new SpeciesTabUIModel(); ui.setContextValue(model); - traitMonitor.setBean(model); + fishingOperationMonitor.setBean(model); } @Override public void afterInitUI() { + if (log.isInfoEnabled()) { + log.info("afterInit: " + ui); + } + initUI(ui); + //TODO Will come from protocol + List<String> samplingOrder = Lists.newArrayList( + SpeciesBatchRowModel.PROPERTY_SPECIES, + SpeciesBatchRowModel.PROPERTY_VRAC_HORS_VRAC, + SpeciesBatchRowModel.PROPERTY_WEIGHT_CATEGORY, + SpeciesBatchRowModel.PROPERTY_SEX + ); + + getModel().setSamplingOrder(samplingOrder); + JXTable table = getTable(); // create table column model @@ -146,7 +401,14 @@ listenRowsFromModel(); // save when row chaged and was modified - listenRowModification(table); + ListSelectionListener listener = new TableRowModificationListener<SpeciesBatchRowModel>( + getTableModel(), getRowMonitor()) { + @Override + protected void saveSelectedRow() { + saveSelectedRowIfRequired(); + } + }; + table.getSelectionModel().addListSelectionListener(listener); // always scroll to selected row SwingUtil.scrollToTableSelection(getTable()); @@ -154,41 +416,33 @@ @Override public void onCloseUI() { + if (log.isInfoEnabled()) { + log.info("closing: " + ui); + } } - @Override - protected void saveRow(SpeciesBatchRowModel row) { - SpeciesBatch catchBean = row.toBean(); + //------------------------------------------------------------------------// + //-- Public methods --// + //------------------------------------------------------------------------// - FishingOperation fishingOperation = getModel().getTrait(); - catchBean.setFishingOperation(fishingOperation); - if (log.isInfoEnabled()) { - log.info("Selected fishingOperation: " + fishingOperation.getId()); - } + public void saveSelectedRowIfRequired(FocusEvent event) { - if (TuttiEntities.isNew(catchBean)) { + Component oppositeComponent = event.getOppositeComponent(); - catchBean = persistenceService.createSpeciesBatch(catchBean); - row.setId(catchBean.getId()); - } else { - persistenceService.saveSpeciesBatch(catchBean); - } + JXTable parentContainer = null; - List<SpeciesFrequencyRowModel> frequencyRows = row.getFrequency(); + if (oppositeComponent != null) { - List<SpeciesBatchFrequency> frequency = - SpeciesFrequencyRowModel.toBeans(frequencyRows, catchBean); - - if (log.isInfoEnabled()) { - log.info("Will save " + frequency.size() + " frequencies."); + // check out if still on table + parentContainer = SwingUtil.getParentContainer( + oppositeComponent, JXTable.class); } - frequency = persistenceService.saveSpeciesBatchFrequency( - catchBean.getId(), frequency); + if (parentContainer == null) { - // push it back to row model - frequencyRows = SpeciesFrequencyRowModel.fromBeans(frequency); - row.setFrequency(frequencyRows); + // out of the table can save + saveSelectedRowIfRequired(); + } } public void selectFishingOperation(FishingOperation bean) { @@ -201,11 +455,11 @@ table.editingCanceled(null); } - if (traitMonitor.wasModified()) { + if (fishingOperationMonitor.wasModified()) { // previous fishingOperation was modified, let's save it SpeciesTabUIModel traitMonitorBean = - (SpeciesTabUIModel) traitMonitor.getBean(); + (SpeciesTabUIModel) fishingOperationMonitor.getBean(); FishingOperation fishingOperation = traitMonitorBean.toBean(); @@ -229,7 +483,7 @@ if (empty) { rows = null; bean = new FishingOperation(); - model.setTrait(null); + model.setFishingOperation(null); } else { if (log.isInfoEnabled()) { @@ -248,146 +502,165 @@ rows.add(entry); } } - model.setTrait(bean); + model.setFishingOperation(bean); } model.fromBean(bean); model.setRows(rows); - listenModifcationOnFirstRow(); - - traitMonitor.clearModified(); + fishingOperationMonitor.clearModified(); } - @Override - protected TableColumnModel createTableColumnModel() { + //------------------------------------------------------------------------// + //-- Internal methods --// + //------------------------------------------------------------------------// - DefaultTableColumnModelExt columnModel = - new DefaultTableColumnModelExt(); + protected void moveSamplingNode(SpeciesBatchTreeModel samplingTreeModel, + SpeciesBatchRowModel row, + SpeciesBatchTreeNode oldNode, + SpeciesBatchTreeNode newNode) { - { // Species to confirm + if (oldNode != null) { - addBooleanColumnToModel(columnModel, - SpeciesBatchTableModel.SPECIES_TO_CONFIRM, - getTable()); + recomputeSuperSamplingRatio(samplingTreeModel, row, oldNode); + } - List<Species> allSpecies = persistenceService.getAllSpecies(); + recomputeSuperSamplingRatio(samplingTreeModel, row, newNode); - { // Species (by code) + } - Decorator<Species> decorator = getDecorator( - Species.class, DecoratorService.SPECIES_BY_CODE); + protected void recomputeSuperSamplingRatio(SpeciesBatchTreeModel samplingTreeModel, + SpeciesBatchRowModel row, + SpeciesBatchTreeNode node) { - addComboDataColumnToModel(columnModel, - SpeciesBatchTableModel.SPECIES_BY_CODE, - decorator, allSpecies); - } + SpeciesBatchTreeNode superSamplingNode = node.getParent(); - { // Species (by genusCode) + Preconditions.checkNotNull(superSamplingNode, + "Super sampling node can't be null"); - Decorator<Species> decorator = getDecorator( - Species.class, DecoratorService.SPECIES_BY_GENUS); + SpeciesBatchTreeModel.SamplingContext samplingContext = + samplingTreeModel.createSamplingContext(superSamplingNode); - addComboDataColumnToModel(columnModel, - SpeciesBatchTableModel.SPECIES_BY_GENUS_CODE, - decorator, allSpecies); + float samplingTotalWeight = samplingContext.getTotalWeight(); + Float superSamplingTotalWeight; + SpeciesBatchRowModel superSamplingRow = + samplingContext.getSuperSamplingRow(); + if (superSamplingRow == null) { + // Use directly the batch total weight (means no super-sampling) + + superSamplingTotalWeight = getModel().getTotalWeight(); + } else { + superSamplingTotalWeight = superSamplingRow.getWeight(); } - { // Vrac / Hors vrac + if (log.isInfoEnabled()) { + log.info("Super sampling total weight: " + + superSamplingTotalWeight); + } - addComboEnumColumnToModel(columnModel, - SpeciesBatchTableModel.VRAC_HORS_VRAC, - VracHorsVracEnum.values()); + Float samplingRatio = null; + if (superSamplingTotalWeight != null) { + samplingRatio = samplingTotalWeight / superSamplingTotalWeight; } - { // Catégorie de poids + if (log.isInfoEnabled()) { + log.info("Sampling ratio: " + samplingRatio); + } - Decorator<WeightCategory> decorator = - getDecorator(WeightCategory.class, - DecoratorService.BY_NAME); + getTableModel().updateSamplingRatio(samplingContext.getSamplingRows()); - List<WeightCategory> data = - persistenceService.getAllWeightCategory(); + } - addComboDataColumnToModel(columnModel, - SpeciesBatchTableModel.WEIGHT_CATEGORY, - decorator, data); - } - { // Sex + protected void recomputeTotalHorsVrac() { - Decorator<Sex> decorator = - getDecorator(Sex.class, DecoratorService.BY_NAME); + // recompute total hors vrac + Float totalHorsVrac = 0f; + Float totalVrac = 0f; - List<Sex> data = persistenceService.getAllSex(); + for (SpeciesBatchRowModel batch : getModel().getRows()) { + VracHorsVracEnum vracHorsVrac = batch.getVracHorsVrac(); + if (vracHorsVrac == null) { - addComboDataColumnToModel(columnModel, - SpeciesBatchTableModel.SEX, - decorator, data); + // can't sum anything + } else if (vracHorsVrac == VracHorsVracEnum.HORS_VRAC) { + Float weight = batch.getWeight(); + if (weight != null) { + totalHorsVrac += weight; + } + } else if (vracHorsVrac == VracHorsVracEnum.VRAC) { + Float weight = batch.getWeight(); + if (weight != null) { + totalVrac += weight; + } + } } + if (log.isInfoEnabled()) { + log.info("New total vrac / hors vrac: " + + totalVrac + " / " + totalHorsVrac); + } + getModel().setTotalHorsVracWeight(totalHorsVrac); + //TODO Should we also set the total vrac weight ? +// getModel().setTotalVracWeight(totalVrac); + } - { // Maturity + protected void saveSelectedRowIfRequired() { - addFloatColumnToModel(columnModel, - SpeciesBatchTableModel.MATURITY, - TuttiUI.DECIMAL3_PATTERN); - } + TuttiBeanMonitor<SpeciesBatchRowModel> rowMonitor = getRowMonitor(); - { // Age + SpeciesBatchRowModel bean = rowMonitor.getBean(); + if (bean != null && bean.isValid()) { - addFloatColumnToModel(columnModel, - SpeciesBatchTableModel.AGE, - TuttiUI.DECIMAL3_PATTERN); - } + // there is a valid bean attached to the monitor - { // Poids observé + if (rowMonitor.wasModified()) { - addFloatColumnToModel(columnModel, - SpeciesBatchTableModel.WEIGHT, - TuttiUI.DECIMAL3_PATTERN); - } + // monitored bean was modified, save it + if (log.isInfoEnabled()) { + log.info("Row " + bean + " was modified, will save it"); + } - { // Poids calculé + saveRow(bean); - addColumnToModel(columnModel, - FrequencyCellComponent.newEditor(ui.getFrequencyUI()), - FrequencyCellComponent.newRender(), - SpeciesBatchTableModel.COMPUTED_WEIGHT); + // clear modified flag on the monitor + rowMonitor.clearModified(); + } } + } - { // Nombre calculé + protected void saveRow(SpeciesBatchRowModel row) { - addColumnToModel(columnModel, - FrequencyCellComponent.newEditor(ui.getFrequencyUI()), - FrequencyCellComponent.newRender(), - SpeciesBatchTableModel.COMPUTED_NUMBER); + SpeciesBatch catchBean = row.toBean(); + + FishingOperation fishingOperation = getModel().getFishingOperation(); + catchBean.setFishingOperation(fishingOperation); + if (log.isInfoEnabled()) { + log.info("Selected fishingOperation: " + fishingOperation.getId()); } - { // Poids d'échantillon + if (TuttiEntities.isNew(catchBean)) { - addColumnToModel(columnModel, - SpeciesBatchTableModel.SAMPLE_WEIGHT); + catchBean = persistenceService.createSpeciesBatch(catchBean); + row.setId(catchBean.getId()); + } else { + persistenceService.saveSpeciesBatch(catchBean); } - { // Fraction d'élévation + List<SpeciesFrequencyRowModel> frequencyRows = row.getFrequency(); - addColumnToModel(columnModel, - SpeciesBatchTableModel.ELEVATION_RATIO); - } + List<SpeciesBatchFrequency> frequency = + SpeciesFrequencyRowModel.toBeans(frequencyRows, catchBean); - { // Commentaire - - addColumnToModel(columnModel, - SpeciesBatchTableModel.COMMENT); + if (log.isInfoEnabled()) { + log.info("Will save " + frequency.size() + " frequencies."); } + frequency = persistenceService.saveSpeciesBatchFrequency( + catchBean.getId(), frequency); - { // Pièces-jointes - - addColumnToModel(columnModel, - SpeciesBatchTableModel.FILE); - } - return columnModel; + // push it back to row model + frequencyRows = SpeciesFrequencyRowModel.fromBeans(frequency); + row.setFrequency(frequencyRows); } } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUIModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUIModel.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesTabUIModel.java 2012-12-12 17:06:45 UTC (rev 46) @@ -29,6 +29,8 @@ import org.nuiton.util.beans.Binder; import org.nuiton.util.beans.BinderModelBuilder; +import java.util.List; + /** * @author tchemit <chemit@codelutin.com> * @since 0.1 @@ -45,16 +47,55 @@ public static final String PROPERTY_TOTAL_HORS_VRAC_WEIGHT = "totalHorsVracWeight"; - protected FishingOperation trait; + /** + * Editing fishing operation. + * + * @since 0.2 + */ + protected FishingOperation fishingOperation; + /** + * Total Weight filled in screen. + * + * @since 0.2 + */ protected Float totalWeight; + /** + * Total vrac Weight filled in screen. + * + * @since 0.2 + */ protected Float totalVracWeight; + /** + * Total sample vrac Weight filled in screen. + * + * @since 0.2 + */ protected Float sampleVracWeight; + /** + * Total hors vrac Weight computed by hros vrac rows. + * + * @since 0.2 + */ protected Float totalHorsVracWeight; + /** + * Sampling order (sets by protocol). + * + * @since 0.2 + */ + protected List<String> samplingOrder; + + /** + * Tree of sampling for batch rows. + * + * @since 0.2 + */ + protected final SpeciesBatchTreeModel samplingTreeModel; + protected static final Binder<FishingOperation, SpeciesTabUIModel> fromBeanBinder = BinderModelBuilder.newEmptyBuilder(FishingOperation.class, SpeciesTabUIModel.class) .addProperty("speciesTotalWeight", PROPERTY_TOTAL_WEIGHT) .addProperty("speciesTotalHorsVracWeight", PROPERTY_TOTAL_HORS_VRAC_WEIGHT) @@ -72,16 +113,21 @@ public SpeciesTabUIModel() { super(FishingOperation.class, fromBeanBinder, toBeanBinder); + this.samplingTreeModel = new SpeciesBatchTreeModel(); } - public FishingOperation getTrait() { - return trait; + public FishingOperation getFishingOperation() { + return fishingOperation; } - public void setTrait(FishingOperation trait) { - this.trait = trait; + public void setFishingOperation(FishingOperation fishingOperation) { + this.fishingOperation = fishingOperation; } + public SpeciesBatchTreeModel getSamplingTreeModel() { + return samplingTreeModel; + } + public Float getTotalWeight() { return totalWeight; } @@ -122,9 +168,17 @@ firePropertyChange(PROPERTY_TOTAL_HORS_VRAC_WEIGHT, oldValue, totalHorsVracWeight); } + public List<String> getSamplingOrder() { + return samplingOrder; + } + + public void setSamplingOrder(List<String> samplingOrder) { + this.samplingOrder = samplingOrder; + samplingTreeModel.setSamplingOrder(samplingOrder.toArray(new String[samplingOrder.size()])); + } + @Override protected FishingOperation newEntity() { - return trait; + return fishingOperation; } - } Added: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/TuttiBeanMonitor.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/TuttiBeanMonitor.java (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/TuttiBeanMonitor.java 2012-12-12 17:06:45 UTC (rev 46) @@ -0,0 +1,82 @@ +package fr.ifremer.tutti.ui.swing.util; + +/* + * #%L + * Tutti :: UI + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 Ifremer + * %% + * 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 org.jdesktop.beans.AbstractBean; +import org.nuiton.util.beans.BeanMonitor; +import org.nuiton.util.beans.PropertyDiff; + +import java.util.Map; + +/** + * To monitor a bean and know when it changes. + * + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class TuttiBeanMonitor<B> extends AbstractBean { + + public static final String PROPERTY_BEAN = "bean"; + + BeanMonitor monitor; + + public TuttiBeanMonitor(String... properties) { + this.monitor = new BeanMonitor(properties); + } + + public B getBean() { + return (B) monitor.getBean(); + } + + public void setBean(B bean) { + Object oldValue = getBean(); + monitor.setBean(bean); + firePropertyChange(PROPERTY_BEAN, oldValue, bean); + } + + public BeanMonitor getMonitor() { + return monitor; + } + + public boolean wasModified() { + return monitor.wasModified(); + } + + public String[] getModifiedProperties() { + return monitor.getModifiedProperties(); + } + + public Map<String, Object> getOriginalValues() { + return monitor.getOriginalValues(); + } + + public PropertyDiff[] getPropertyDiffs() { + return monitor.getPropertyDiffs(); + } + + public void clearModified() { + monitor.clearModified(); + } +} Property changes on: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/TuttiBeanMonitor.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractTuttiTableUIHandler.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractTuttiTableUIHandler.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractTuttiTableUIHandler.java 2012-12-12 17:06:45 UTC (rev 46) @@ -28,33 +28,28 @@ import fr.ifremer.tutti.ui.swing.AbstractTuttiBeanUIModel; import fr.ifremer.tutti.ui.swing.AbstractTuttiUIHandler; import fr.ifremer.tutti.ui.swing.TuttiUIContext; +import fr.ifremer.tutti.ui.swing.util.TuttiBeanMonitor; import jaxx.runtime.SwingUtil; import jaxx.runtime.swing.JAXXWidgetUtil; import jaxx.runtime.swing.editor.EnumEditor; import jaxx.runtime.swing.editor.bean.BeanUIUtil; import jaxx.runtime.swing.editor.cell.NumberCellEditor; import jaxx.runtime.swing.renderer.DecoratorTableCellRenderer; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTable; import org.jdesktop.swingx.autocomplete.ComboBoxCellEditor; import org.jdesktop.swingx.autocomplete.ObjectToStringConverter; import org.jdesktop.swingx.table.TableColumnExt; -import org.nuiton.util.beans.BeanMonitor; import org.nuiton.util.decorator.Decorator; import javax.swing.JComboBox; import javax.swing.JTable; import javax.swing.border.LineBorder; -import javax.swing.event.ListSelectionListener; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import java.awt.Color; -import java.awt.Component; -import java.awt.event.FocusEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; @@ -82,12 +77,53 @@ * * @since 0.2 */ - private final BeanMonitor rowMonitor; + private final TuttiBeanMonitor<R> rowMonitor; + protected abstract JTable getTable(); + + protected abstract AbstractTuttiTableModel<R> getTableModel(); + + protected abstract TableColumnModel createTableColumnModel(); + + protected abstract void onRowModified(R row, + String propertyName, + Object oldValue, + Object newValue); + protected AbstractTuttiTableUIHandler(TuttiUIContext context, String... properties) { super(context); - rowMonitor = new BeanMonitor(properties); + rowMonitor = new TuttiBeanMonitor<R>(properties); + + // listen when bean is changed + rowMonitor.addPropertyChangeListener(TuttiBeanMonitor.PROPERTY_BEAN, new PropertyChangeListener() { + final PropertyChangeListener l = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + R row = (R) evt.getSource(); + onRowModified(row, + evt.getPropertyName(), + evt.getOldValue(), + evt.getNewValue()); + } + }; + + @Override + public void propertyChange(PropertyChangeEvent evt) { + R oldValue = (R) evt.getOldValue(); + R newValue = (R) evt.getNewValue(); + if (log.isInfoEnabled()) { + log.info("Monitor row changed from " + + oldValue + " to " + newValue); + } + if (oldValue != null) { + oldValue.removePropertyChangeListener(l); + } + if (newValue != null) { + newValue.addPropertyChangeListener(l); + } + } + }); } protected KeyListener installTableKeyListener(TableColumnModel columnModel, @@ -221,8 +257,7 @@ protected <B extends Enum<B>> void addComboEnumColumnToModel(TableColumnModel model, ColumnIdentifier<R> identifier, B[] data) { - EnumEditor<B> comboBox = - EnumEditor.newEditor(data); + EnumEditor<B> comboBox = EnumEditor.newEditor(data); BeanUIUtil.decorate(comboBox, ObjectToStringConverter.DEFAULT_IMPLEMENTATION); TableCellEditor editor = new ComboBoxCellEditor(comboBox); @@ -236,11 +271,15 @@ getModel().addPropertyChangeListener(AbstractTuttiTableUIModel.PROPERTY_ROWS, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - getTableModel().setRows((List<R>) evt.getNewValue()); + onModelRowsChanged((List<R>) evt.getNewValue()); } }); } + protected void onModelRowsChanged(List<R> rows) { + getTableModel().setRows(rows); + } + protected <O> TableCellRenderer newTableCellRender(Class<O> type) { return newTableCellRender(type, null); @@ -262,71 +301,8 @@ return result; } - protected void listenRowModification(JTable table) { - ListSelectionListener listener = new TableRowModificationListener( - getTableModel(), rowMonitor) { - @Override - protected void saveSelectedRow() { - saveSelectedRowIfRequired(); - } - }; - table.getSelectionModel().addListSelectionListener(listener); + protected TuttiBeanMonitor<R> getRowMonitor() { + return rowMonitor; } - public void saveSelectedRowIfRequired(FocusEvent event) { - - Component oppositeComponent = event.getOppositeComponent(); - - JXTable parentContainer = null; - - if (oppositeComponent != null) { - - // check out if still on table - parentContainer = SwingUtil.getParentContainer( - oppositeComponent, JXTable.class); - } - - if (parentContainer == null) { - - // out of the table can save - saveSelectedRowIfRequired(); - } - } - - public void saveSelectedRowIfRequired() { - - R bean = (R) rowMonitor.getBean(); - if (bean != null && bean.isValid()) { - - // there is a valid bean attached to the monitor - - if (rowMonitor.wasModified()) { - - // monitored bean was modified, save it - if (log.isInfoEnabled()) { - log.info("Row " + bean + " was modified, will save it"); - } - - saveRow(bean); - - // clear modified flag on the monitor - rowMonitor.clearModified(); - } - } - } - - protected abstract void saveRow(R row); - - protected abstract TableColumnModel createTableColumnModel(); - - protected abstract JTable getTable(); - - protected abstract AbstractTuttiTableModel<R> getTableModel(); - - protected void listenModifcationOnFirstRow() { - List<R> rows = getTableModel().getRows(); - if (CollectionUtils.isNotEmpty(rows)) { - rowMonitor.setBean(rows.get(0)); - } - } } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/TableRowModificationListener.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/TableRowModificationListener.java 2012-12-12 16:52:40 UTC (rev 45) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/TableRowModificationListener.java 2012-12-12 17:06:45 UTC (rev 46) @@ -24,32 +24,33 @@ * #L% */ +import fr.ifremer.tutti.ui.swing.util.TuttiBeanMonitor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.nuiton.util.beans.BeanMonitor; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; +import java.io.Serializable; /** * @author tchemit <chemit@codelutin.com> * @since 0.2 */ -public abstract class TableRowModificationListener implements ListSelectionListener { +public abstract class TableRowModificationListener<R extends Serializable> implements ListSelectionListener { /** Logger. */ private static final Log log = LogFactory.getLog(TableRowModificationListener.class); - private final AbstractTuttiTableModel tableModel; + private final AbstractTuttiTableModel<R> tableModel; - private final BeanMonitor beanMonitor; + private final TuttiBeanMonitor<R> beanMonitor; protected abstract void saveSelectedRow(); - public TableRowModificationListener(AbstractTuttiTableModel tableModel, - BeanMonitor beanMonitor) { + public TableRowModificationListener(AbstractTuttiTableModel<R> tableModel, + TuttiBeanMonitor<R> beanMonitor) { this.tableModel = tableModel; this.beanMonitor = beanMonitor; } @@ -67,7 +68,7 @@ log.info("New selected row: " + selectedRow); } - Object entry; + R entry; if (selectedRow == -1) { // no selection Copied: trunk/tutti-ui-swing/src/test/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModelTest.java (from rev 41, trunk/tutti-ui-swing/src/test/java/fr/ifremer/tutti/ui/swing/content/catches/species/frequency/SpeciesFrequencyRowModelTest.java) =================================================================== --- trunk/tutti-ui-swing/src/test/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModelTest.java (rev 0) +++ trunk/tutti-ui-swing/src/test/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModelTest.java 2012-12-12 17:06:45 UTC (rev 46) @@ -0,0 +1,66 @@ +package fr.ifremer.tutti.ui.swing.content.operation.species; + +/* + * #%L + * Tutti :: UI + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 Ifremer + * %% + * 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 org.junit.Assert; +import org.junit.Test; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class SpeciesFrequencyRowModelTest { + + @Test + public void compareTo() throws Exception { + + SpeciesFrequencyRowModel s0 = new SpeciesFrequencyRowModel(); + SpeciesFrequencyRowModel s1 = new SpeciesFrequencyRowModel(); + + // s0=null, s1=null + Assert.assertTrue(s0.compareTo(s1) == 0); + + // s0=1, s1=null + s0.setLengthStep(1f); + Assert.assertTrue(s0.compareTo(s1) > 0); + + // s0=null, s1=1 + s0.setLengthStep(null); + s1.setLengthStep(1f); + Assert.assertTrue(s0.compareTo(s1) < 0); + + // s0=2, s1=1 + s0.setLengthStep(2f); + Assert.assertTrue(s0.compareTo(s1) > 0); + + // s0=2, s1=2 + s1.setLengthStep(2f); + Assert.assertTrue(s0.compareTo(s1) == 0); + + // s0=2, s1=3 + s1.setLengthStep(3f); + Assert.assertTrue(s0.compareTo(s1) < 0); + } +} Property changes on: trunk/tutti-ui-swing/src/test/java/fr/ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyRowModelTest.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native
participants (1)
-
tchemit@users.forge.codelutin.com