Author: tchemit Date: 2013-09-25 09:22:58 +0200 (Wed, 25 Sep 2013) New Revision: 1221 Url: http://forge.codelutin.com/projects/tutti/repository/revisions/1221 Log: fixes #3315: [CAPTURE] pouvoir modifier la valeur de la cat?\195?\169gorisation d'un lot Modified: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/entities/data/SampleCategory.java trunk/tutti-ui-swing/src/main/filtered-resources/tutti-help-en.properties trunk/tutti-ui-swing/src/main/filtered-resources/tutti-help-fr.properties trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/SampleCategoryAble.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/SampleCategoryColumnIdentifier.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchRowModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchTableModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUI.css trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUI.jaxx trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUIHandler.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUIModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchRowModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchTableModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUI.css trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUI.jaxx trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUIHandler.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUIModel.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/AbstractTuttiUIHandler.java trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_en_GB.properties trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties Modified: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/entities/data/SampleCategory.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/entities/data/SampleCategory.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/entities/data/SampleCategory.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -40,6 +40,8 @@ public static final String PROPERTY_CATEGORY_WEIGHT = "categoryWeight"; + public static final String PROPERTY_CATEGORY_VALUE = "categoryValue"; + /** * Sample category definition. * Modified: trunk/tutti-ui-swing/src/main/filtered-resources/tutti-help-en.properties =================================================================== --- trunk/tutti-ui-swing/src/main/filtered-resources/tutti-help-en.properties 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/filtered-resources/tutti-help-en.properties 2013-09-25 07:22:58 UTC (rev 1221) @@ -1,5 +1,5 @@ #Generated by org.nuiton.jaxx.plugin.GenerateHelpIdsMojo -#Tue Sep 24 16:21:02 CEST 2013 +#Tue Sep 24 18:46:35 CEST 2013 tutti.config.help=config.html tutti.createAccidentalBatch.action.cancel.help=editFishingOperation.html\#captureCapturesAccidentellesActions tutti.createAccidentalBatch.action.saveAndClose.help=editFishingOperation.html\#captureCapturesAccidentellesActions @@ -26,8 +26,8 @@ tutti.createIndividualObservationBatch.action.addSpecies.help=editFishingOperation.html\#captureObservationsIndividuellesActions tutti.createIndividualObservationBatch.action.cancel.help=editFishingOperation.html\#captureObservationsIndividuellesActions tutti.createIndividualObservationBatch.action.save.help=editFishingOperation.html\#captureObservationsIndividuellesActions -tutti.createIndividualObservationBatch.action.saveAndClose.help= -tutti.createIndividualObservationBatch.action.saveAndContinue.help= +tutti.createIndividualObservationBatch.action.saveAndClose.help=editFishingOperation.html\#captureObservationsIndividuellesActions +tutti.createIndividualObservationBatch.action.saveAndContinue.help=editFishingOperation.html\#captureObservationsIndividuellesActions tutti.createIndividualObservationBatch.field.individualObservationLengthStepCaracteristic.help=editFishingOperation.html\#captureObservationsIndividuellesFields tutti.createIndividualObservationBatch.field.individualObservationSize.help=editFishingOperation.html\#captureObservationsIndividuellesFields tutti.createIndividualObservationBatch.field.individualObservationSpecies.help=editFishingOperation.html\#captureObservationsIndividuellesFields @@ -38,9 +38,9 @@ tutti.createMarineLitterBatch.action.saveAndContinue.help=editFishingOperation.html\#captureMacroDechetsActions tutti.createMarineLitterBatch.field.marineLitterCategory.help=editFishingOperation.html\#captureMacroDechetsFields tutti.createMarineLitterBatch.field.marineLitterSizeCategory.help=editFishingOperation.html\#captureMacroDechetsFields -tutti.createMarineLitterBatch.field.marineLitterWeight.help= +tutti.createMarineLitterBatch.field.marineLitterWeight.help=editFishingOperation.html\#captureMacroDechetsFields tutti.createMarineLitterBatch.field.number.help=editFishingOperation.html\#captureMacroDechetsFields -tutti.createMarineLitterBatch.field.weight.help= +tutti.createMarineLitterBatch.field.weight.help=editFishingOperation.html\#captureMacroDechetsFields tutti.createMarineLitterBatch.help=editFishingOperation.html\#captureMacroDechets tutti.createSpeciesBatch.action.addSpecies.help=editFishingOperation.html\#captureEspecesCreeLotActions tutti.createSpeciesBatch.action.cancel.help=editFishingOperation.html\#captureEspecesCreeLotActions @@ -68,6 +68,7 @@ tutti.editAccidentalBatch.action.importMultiPost.help=editFishingOperation.html\#captureCapturesAccidentellesActions tutti.editAccidentalBatch.action.removeBatch.help=editFishingOperation.html\#captureCapturesAccidentellesActions tutti.editAccidentalBatch.help=editFishingOperation.html\#captureCapturesAccidentelles +tutti.editBenthosBatch.action.changeSampleCategory.help=editFishingOperation.html\#captureBenthosActions tutti.editBenthosBatch.action.createBatch.help=editFishingOperation.html\#captureBenthosActions tutti.editBenthosBatch.action.createMelag.help=editFishingOperation.html\#captureBenthosActions tutti.editBenthosBatch.action.editFrequencies.help=editFishingOperation.html\#captureBenthosActions @@ -94,8 +95,8 @@ tutti.editBenthosFrequencies.action.cancel.help=editFishingOperation.html\#captureBenthosActions tutti.editBenthosFrequencies.action.generate.help=editFishingOperation.html\#captureBenthosActions tutti.editBenthosFrequencies.action.save.help=editFishingOperation.html\#captureBenthosActions -tutti.editBenthosFrequencies.action.saveAndClose.help= -tutti.editBenthosFrequencies.action.saveAndContinue.help= +tutti.editBenthosFrequencies.action.saveAndClose.help=editFishingOperation.html\#captureBenthosActions +tutti.editBenthosFrequencies.action.saveAndContinue.help=editFishingOperation.html\#captureBenthosActions tutti.editBenthosFrequencies.field.lengthStepCaracteristic.help=editFishingOperation.html\#captureBenthosFields tutti.editBenthosFrequencies.field.maxStep.help=editFishingOperation.html\#captureBenthosFields tutti.editBenthosFrequencies.field.minStep.help=editFishingOperation.html\#captureBenthosFields @@ -231,6 +232,7 @@ tutti.editSampleCategoryModel.action.removeEntry.help=editSampleCategory.html\#actions tutti.editSampleCategoryModel.action.save.help=editSampleCategory.html\#actions tutti.editSampleCategoryModel.help=editSampleCategory.html +tutti.editSpeciesBatch.action.changeSampleCategory.help=editFishingOperation.html\#captureEspecesActions tutti.editSpeciesBatch.action.createBatch.help=editFishingOperation.html\#captureEspecesActions tutti.editSpeciesBatch.action.createMelag.help=editFishingOperation.html\#captureEspecesActions tutti.editSpeciesBatch.action.editFrequencies.help=editFishingOperation.html\#captureEspecesActions @@ -251,10 +253,10 @@ tutti.editSpeciesBatch.help=editFishingOperation.html\#captureEspeces tutti.editSpeciesFrequencies.action.cancel.help=editFishingOperation.html\#captureEspecesMensurationActions tutti.editSpeciesFrequencies.action.generate.help=editFishingOperation.html\#captureEspecesMensurationActions -tutti.editSpeciesFrequencies.action.reset.help= +tutti.editSpeciesFrequencies.action.reset.help=editFishingOperation.html\#captureEspecesMensurationActions tutti.editSpeciesFrequencies.action.save.help=editFishingOperation.html\#captureEspecesMensurationActions -tutti.editSpeciesFrequencies.action.saveAndClose.help= -tutti.editSpeciesFrequencies.action.saveAndContinue.help= +tutti.editSpeciesFrequencies.action.saveAndClose.help=editFishingOperation.html\#captureEspecesMensurationActions +tutti.editSpeciesFrequencies.action.saveAndContinue.help=editFishingOperation.html\#captureEspecesMensurationActions tutti.editSpeciesFrequencies.field.lengthStepCaracteristic.help=editFishingOperation.html\#captureEspecesMensurationFields tutti.editSpeciesFrequencies.field.maxStep.help=editFishingOperation.html\#captureEspecesMensurationFields tutti.editSpeciesFrequencies.field.minStep.help=editFishingOperation.html\#captureEspecesMensurationFields Modified: trunk/tutti-ui-swing/src/main/filtered-resources/tutti-help-fr.properties =================================================================== --- trunk/tutti-ui-swing/src/main/filtered-resources/tutti-help-fr.properties 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/filtered-resources/tutti-help-fr.properties 2013-09-25 07:22:58 UTC (rev 1221) @@ -1,5 +1,5 @@ #Generated by org.nuiton.jaxx.plugin.GenerateHelpIdsMojo -#Tue Sep 24 16:21:02 CEST 2013 +#Tue Sep 24 18:46:35 CEST 2013 tutti.config.help=config.html tutti.createAccidentalBatch.action.cancel.help=editFishingOperation.html\#captureCapturesAccidentellesActions tutti.createAccidentalBatch.action.saveAndClose.help=editFishingOperation.html\#captureCapturesAccidentellesActions @@ -37,9 +37,9 @@ tutti.createMarineLitterBatch.action.saveAndContinue.help=editFishingOperation.html\#captureMacroDechetsActions tutti.createMarineLitterBatch.field.marineLitterCategory.help=editFishingOperation.html\#captureMacroDechetsFields tutti.createMarineLitterBatch.field.marineLitterSizeCategory.help=editFishingOperation.html\#captureMacroDechetsFields -tutti.createMarineLitterBatch.field.marineLitterWeight.help= +tutti.createMarineLitterBatch.field.marineLitterWeight.help=editFishingOperation.html\#captureMacroDechetsFields tutti.createMarineLitterBatch.field.number.help=editFishingOperation.html\#captureMacroDechetsFields -tutti.createMarineLitterBatch.field.weight.help= +tutti.createMarineLitterBatch.field.weight.help=editFishingOperation.html\#captureMacroDechetsFields tutti.createMarineLitterBatch.help=editFishingOperation.html\#captureMacroDechets tutti.createSpeciesBatch.action.addSpecies.help=editFishingOperation.html\#captureEspecesCreeLotActions tutti.createSpeciesBatch.action.cancel.help=editFishingOperation.html\#captureEspecesCreeLotActions @@ -67,6 +67,7 @@ tutti.editAccidentalBatch.action.importMultiPost.help=editFishingOperation.html\#captureCapturesAccidentellesActions tutti.editAccidentalBatch.action.removeBatch.help=editFishingOperation.html\#captureCapturesAccidentellesActions tutti.editAccidentalBatch.help=editFishingOperation.html\#captureCapturesAccidentelles +tutti.editBenthosBatch.action.changeSampleCategory.help=editFishingOperation.html\#captureBenthosActions tutti.editBenthosBatch.action.createBatch.help=editFishingOperation.html\#captureBenthosActions tutti.editBenthosBatch.action.createMelag.help=editFishingOperation.html\#captureBenthosActions tutti.editBenthosBatch.action.editFrequencies.help=editFishingOperation.html\#captureBenthosActions @@ -229,6 +230,7 @@ tutti.editSampleCategoryModel.action.removeEntry.help=editSampleCategory.html\#actions tutti.editSampleCategoryModel.action.save.help=editSampleCategory.html\#actions tutti.editSampleCategoryModel.help=editSampleCategory.html +tutti.editSpeciesBatch.action.changeSampleCategory.help=editFishingOperation.html\#captureEspecesActions tutti.editSpeciesBatch.action.createBatch.help=editFishingOperation.html\#captureEspecesActions tutti.editSpeciesBatch.action.createMelag.help=editFishingOperation.html\#captureEspecesActions tutti.editSpeciesBatch.action.editFrequencies.help=editFishingOperation.html\#captureEspecesActions @@ -249,7 +251,7 @@ tutti.editSpeciesBatch.help=editFishingOperation.html\#captureEspeces tutti.editSpeciesFrequencies.action.cancel.help=editFishingOperation.html\#captureEspecesMensurationActions tutti.editSpeciesFrequencies.action.generate.help=editFishingOperation.html\#captureEspecesMensurationActions -tutti.editSpeciesFrequencies.action.reset.help= +tutti.editSpeciesFrequencies.action.reset.help=editFishingOperation.html\#captureEspecesMensurationActions tutti.editSpeciesFrequencies.action.saveAndClose.help=editFishingOperation.html\#captureEspecesMensurationActions tutti.editSpeciesFrequencies.action.saveAndContinue.help=editFishingOperation.html\#captureEspecesMensurationActions tutti.editSpeciesFrequencies.field.lengthStepCaracteristic.help=editFishingOperation.html\#captureEspecesMensurationFields Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/SampleCategoryAble.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/SampleCategoryAble.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/SampleCategoryAble.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -26,6 +26,8 @@ import fr.ifremer.tutti.persistence.entities.data.SampleCategory; +import java.io.Serializable; + /** * Contract for model using {@link SampleCategory}. * @@ -44,6 +46,8 @@ SampleCategory getSampleCategoryById(Integer sampleCategoryId); + void setSampleCategoryValue(Integer sampleCategoryId, Serializable value); + void setSampleCategoryWeight(Integer sampleCategoryId, Object value); E getFirstAncestor(SampleCategory<?> entrySampleCategory); Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/SampleCategoryColumnIdentifier.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/SampleCategoryColumnIdentifier.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/SampleCategoryColumnIdentifier.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -27,6 +27,8 @@ import fr.ifremer.tutti.persistence.entities.data.SampleCategory; import fr.ifremer.tutti.ui.swing.util.table.ColumnIdentifier; +import java.io.Serializable; + /** * @author tchemit <chemit@codelutin.com> * @since 1.2 @@ -66,6 +68,11 @@ entry.setSampleCategoryWeight(getSampleCategoryId(), value); } + public void setCategoryValue(R entry, Serializable value) { + + entry.setSampleCategoryValue(getSampleCategoryId(), value); + } + public Integer getSampleCategoryId() { return sampleCategoryId; } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchRowModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchRowModel.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchRowModel.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -324,6 +324,15 @@ } @Override + public void setSampleCategoryValue(Integer sampleCategoryId, Serializable value) { + SampleCategory<?> sampleCategory = + getSampleCategoryById(sampleCategoryId); + TuttiUIUtil.setProperty(sampleCategory, + SampleCategory.PROPERTY_CATEGORY_VALUE, value); + firePropertyChange(PROPERTY_SAMPLE_CATEGORY_VALUE, null, sampleCategory); + } + + @Override public void setSampleCategoryWeight(Integer sampleCategoryId, Object value) { SampleCategory<?> sampleCategory = getSampleCategoryById(sampleCategoryId); Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchTableModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchTableModel.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchTableModel.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -37,6 +37,7 @@ import org.jdesktop.swingx.table.TableColumnModelExt; import javax.swing.table.TableColumn; +import java.io.Serializable; import java.util.Enumeration; import java.util.Set; @@ -171,19 +172,9 @@ log.debug("First ancestor row: " + firstRowIndex); } - // must save this row now + // save this row and his shell + updateShell(firstAncestor, columnIndex); - // get shell of the ancestor - Set<BenthosBatchRowModel> shell = Sets.newHashSet(); - firstAncestor.collectShell(shell); - - for (BenthosBatchRowModel batchRowModel : shell) { - int currentRowIndex = getRowIndex(batchRowModel); - if (log.isDebugEnabled()) { - log.debug("Update shell row: " + currentRowIndex); - } - fireTableCellUpdated(currentRowIndex, columnIndex); - } } else { super.setValueAt(aValue, rowIndex, columnIndex, propertyName, entry); } @@ -253,4 +244,65 @@ } return result; } + + /** + * Return the sample category id of a column or {@code null} if not on a + * sample category column. + * + * @param columnIndex index of the column to look at + * @return the sample category id of a column or {@code null} if not on a + * sample category column. + * @since 2.6 + */ + public Integer getSampleCategoryId(int columnIndex) { + Integer result = null; + ColumnIdentifier<BenthosBatchRowModel> identifier = getIdentifier(columnIndex); + if (sampleCols.contains(identifier)) { + SampleCategoryColumnIdentifier<BenthosBatchRowModel> sampleId = (SampleCategoryColumnIdentifier<BenthosBatchRowModel>) identifier; + result = sampleId.getSampleCategoryId(); + } + return result; + } + + /** + * Update the sample category value of all childs of the given {@code row}. + * + * @param row the row to walk through + * @param columnIndex index of the column where the sample category is + * @param newValue new sample category value to set + * @since 2.6 + */ + public void updateSampleCategorieValue(BenthosBatchRowModel row, + int sampleCategoryId, + int columnIndex, + Serializable newValue) { + + SampleCategoryColumnIdentifier<BenthosBatchRowModel> identifier = + (SampleCategoryColumnIdentifier<BenthosBatchRowModel>) getIdentifier(columnIndex); + + // get the first ancestor using the category to update + SampleCategory<?> sampleCategory = row.getSampleCategoryById(sampleCategoryId); + BenthosBatchRowModel firstAncestor = row.getFirstAncestor(sampleCategory); + + // set category value + identifier.setCategoryValue(firstAncestor, newValue); + + // update row shell + updateShell(firstAncestor, columnIndex); + } + + protected void updateShell(BenthosBatchRowModel entry, int columnIndex) { + + Set<BenthosBatchRowModel> shell = Sets.newHashSet(); + entry.collectShell(shell); + shell.add(entry); + + for (BenthosBatchRowModel batchRowModel : shell) { + int currentRowIndex = getRowIndex(batchRowModel); + if (log.isDebugEnabled()) { + log.debug("Update shell row: " + currentRowIndex); + } + fireTableCellUpdated(currentRowIndex, columnIndex); + } + } } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUI.css =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUI.css 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUI.css 2013-09-25 07:22:58 UTC (rev 1221) @@ -186,6 +186,15 @@ _help: {"tutti.editBenthosBatch.action.splitBatch.help"}; } +#changeSampleCategoryMenu { + actionIcon: batch-split; + text: "tutti.editBenthosBatch.action.changeSampleCategory"; + toolTipText: "tutti.editBenthosBatch.action.changeSampleCategory.tip"; + i18nMnemonic: "tutti.editBenthosBatch.action.changeSampleCategory.mnemonic"; + enabled: {model.isTableViewModeAll() && model.isChangeSampleCategoryEnabled()}; + _help: {"tutti.editBenthosBatch.action.changeSampleCategory.help"}; +} + #removeBenthosBatchMenu { actionIcon: batch-delete; text: "tutti.editBenthosBatch.action.removeBatch"; Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUI.jaxx =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUI.jaxx 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUI.jaxx 2013-09-25 07:22:58 UTC (rev 1221) @@ -77,6 +77,8 @@ <JPopupMenu id='tablePopup'> <JMenuItem id='splitBenthosBatchMenu' onActionPerformed='handler.splitBatch()'/> + <JMenuItem id='changeSampleCategoryMenu' + onActionPerformed='handler.changeBatchCategory()'/> <JMenuItem id='removeBenthosBatchMenu'/> <JMenuItem id='removeBenthosSubBatchMenu'/> <JMenuItem id='renameBenthosBatchMenu'/> Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUIHandler.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUIHandler.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUIHandler.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -26,6 +26,7 @@ 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.Attachment; import fr.ifremer.tutti.persistence.entities.data.BatchContainer; @@ -36,6 +37,7 @@ import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel; import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModelEntry; import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocols; +import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.service.DecoratorService; @@ -68,6 +70,8 @@ import fr.ifremer.tutti.ui.swing.util.table.AbstractSelectTableAction; import fr.ifremer.tutti.ui.swing.util.table.ColumnIdentifier; import jaxx.runtime.SwingUtil; +import jaxx.runtime.swing.editor.NumberEditor; +import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; import jaxx.runtime.validator.swing.SwingValidator; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; @@ -83,6 +87,7 @@ import org.nuiton.decorator.Decorator; import org.nuiton.validator.NuitonValidatorResult; +import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.RowFilter; @@ -241,7 +246,6 @@ } model.setRows(rows); - recomputeBatchActionEnable(); } //------------------------------------------------------------------------// @@ -320,9 +324,6 @@ } saveRow(firstAncestorRow); - // when row valid state has changed, recompute action enabled states - recomputeBatchActionEnable(); - cleanrRowMonitor(); return; @@ -333,9 +334,6 @@ } saveSelectedRowIfNeeded(); - - // when row valid state has changed, recompute action enabled states - recomputeBatchActionEnable(); } @Override @@ -380,28 +378,6 @@ } @Override - protected void onRowValidStateChanged(int rowIndex, - BenthosBatchRowModel row, - Boolean oldValue, - Boolean newValue) { - super.onRowValidStateChanged(rowIndex, row, oldValue, newValue); - - // when row valid state has changed, recompute action enabled states - recomputeBatchActionEnable(); - } - - @Override - protected void onAfterSelectedRowChanged(int oldRowIndex, - BenthosBatchRowModel oldRow, - int newRowIndex, - BenthosBatchRowModel newRow) { - super.onAfterSelectedRowChanged(oldRowIndex, oldRow, newRowIndex, newRow); - - // when selected row has changed, recompute action enabled states - recomputeBatchActionEnable(); - } - - @Override protected void addHighlighters(JXTable table) { super.addHighlighters(table); @@ -473,6 +449,163 @@ table.addHighlighter(attachmentHighlighter); } + @Override + protected void beforeOpenPopup(int rowIndex, int columnIndex) { + super.beforeOpenPopup(rowIndex, columnIndex); + + boolean enableAdd = true; + + boolean enableRename = false; + boolean enableSplit = false; + boolean enableChangeSampleCategory = false; + boolean enableRemove = false; + boolean enableRemoveSub = false; + boolean enableCreateMelag = false; + boolean enableEditFrequencies = false; + + if (rowIndex != -1) { + + // there is a selected row + + + //TODO If there is some sub-batch, can remove them + //TODO If there is no sub-batch, can split current batch + + BenthosBatchTableModel tableModel = getTableModel(); + BenthosBatchRowModel row = tableModel.getEntry(rowIndex); + int selectedRowCount = getTable().getSelectedRowCount(); + + // can edit frequencies on a single selected leaf row + + + enableSplit = true; + + // action with single selection + enableRemove = selectedRowCount == 1; + enableRemoveSub = selectedRowCount == 1; + enableRename = selectedRowCount == 1; + enableCreateMelag = selectedRowCount > 1; + enableEditFrequencies = selectedRowCount == 1; + enableChangeSampleCategory = selectedRowCount == 1 && tableModel.isCellEditable(rowIndex, columnIndex); + + if (enableSplit) { + + // can split if selected batch is a leaf + + Integer lastSamplingId = sampleCategoryModel.getLastCategoryId(); + + enableSplit = row.isBatchLeaf() + && selectedRowCount == 1 + && ObjectUtils.notEqual(lastSamplingId, row.getFinestCategory().getCategoryId()) + && row.getNumber() == null + && (row.getComputedNumber() == null + || row.getComputedNumber() == 0); + } + + if (enableChangeSampleCategory) { + + // can change category if there is still a brother category free + Integer sampleCategoryId = + tableModel.getSampleCategoryId(columnIndex); + + if (sampleCategoryId == null) { + + // not on a sample category column + enableChangeSampleCategory = false; + } else { + + // get category + SampleCategoryModelEntry category = + sampleCategoryModel.getCategoryById(sampleCategoryId); + + // get all used values for this category + Set<Serializable> used = getSampleUsedValues( + row, sampleCategoryId); + + if (category.getCaracteristic().isNumericType()) { + + // if number then can always change it + + } else { + + // get all possible values + + List<CaracteristicQualitativeValue> available = + Lists.newArrayList(category.getCaracteristic().getQualitativeValue()); + available.removeAll(used); + + // action possible only if there is still some available values + enableChangeSampleCategory = !available.isEmpty(); + } + } + + } + + if (enableEditFrequencies) { + + // can edit frequencies only on a leaf + enableEditFrequencies = row.isBatchLeaf(); + } + + if (enableRename) { + + // can rename if selected batch is a parent + enableRename = row.isBatchRoot(); + } + + if (enableRemove) { + + // can always remove the batch + // no more test + } + + if (enableRemoveSub) { + + // can remove sub batch if selected batch is not a leaf + enableRemoveSub = !row.isBatchLeaf(); + } + + if (enableCreateMelag) { + + JXTable table = getTable(); + + // can add species to a melag if several root are selected + int[] selectedRows = table.getSelectedRows(); + for (int selectedRowIndex : selectedRows) { + BenthosBatchRowModel selectedRow = + tableModel.getEntry(selectedRowIndex); + + if (!selectedRow.isBatchRoot()) { + enableCreateMelag = false; + break; + } + } + } + } + BenthosBatchUIModel model = getModel(); + model.setCreateBatchEnabled(enableAdd); + model.setSplitBatchEnabled(enableSplit); + model.setChangeSampleCategoryEnabled(enableChangeSampleCategory); + model.setRemoveBatchEnabled(enableRemove); + model.setRemoveSubBatchEnabled(enableRemoveSub); + model.setRenameBatchEnabled(enableRename); + model.setCreateMelagEnabled(enableCreateMelag); + model.setEditFrequenciesEnabled(enableEditFrequencies); + + if (log.isInfoEnabled()) { + StringBuilder builder = new StringBuilder("actions for (" + rowIndex + "," + columnIndex + "):"); + builder.append("\nenableAdd: ").append(enableAdd); + builder.append("\nenableSplit: ").append(enableSplit); + builder.append("\nenableChangeSampleCategory: ").append(enableChangeSampleCategory); + builder.append("\nenableRemove: ").append(enableRemove); + builder.append("\nenableRemoveSub: ").append(enableRemoveSub); + builder.append("\nenableRename: ").append(enableRename); + builder.append("\nenableCreateMelag: ").append(enableCreateMelag); + builder.append("\nenableEditFrequencies: ").append(enableEditFrequencies); + log.info(builder.toString()); + } + } + //------------------------------------------------------------------------// //-- AbstractTuttiUIHandler methods --// //------------------------------------------------------------------------// @@ -686,8 +819,6 @@ ); } } - - recomputeBatchActionEnable(); } public void editFrequencies() { @@ -754,6 +885,107 @@ } } + public void changeBatchCategory() { + + // get table model + BenthosBatchTableModel tableModel = getTableModel(); + + // get selected row + int rowIndex = getTable().getSelectedRow(); + + // get selected column + int columnIndex = getTable().getSelectedColumn(); + + // get selected row + BenthosBatchRowModel selectedRow = tableModel.getEntry(rowIndex); + + // get his sample category + Integer sampleCategoryId = tableModel.getSampleCategoryId(columnIndex); + SampleCategoryModelEntry sampleCategory = sampleCategoryModel.getCategoryById(sampleCategoryId); + Caracteristic caracteristic = sampleCategory.getCaracteristic(); + + // get used values + Set<Serializable> usedValues = getSampleUsedValues(selectedRow, + sampleCategoryId); + + // get the new selected value for this category + Serializable selectedItem; + + String categoryDecorated = decorate(caracteristic, DecoratorService.CARACTERISTIC_PARAMETER_ONLY); + String dialogTitle = _("tutti.editBenthosBatch.title.changeSampleCategoryValue", categoryDecorated); + + if (caracteristic.isNumericType()) { + + // open a simple number editor + NumberEditor editor = new NumberEditor(); + editor.setNumberPattern(TuttiUI.DECIMAL3_PATTERN); + editor.setUseSign(false); + editor.setUseFloat(true); + editor.setShowPopupButton(false); + editor.setShowReset(false); + + int response = JOptionPane.showConfirmDialog( + getUI(), + editor, + dialogTitle, + JOptionPane.OK_CANCEL_OPTION); + + if (response == JOptionPane.OK_OPTION) { + selectedItem = editor.getModel(); + } else { + // user cancel selection + selectedItem = null; + } + + if (usedValues.contains(selectedItem)) { + + // impossible de choisir cette valeur (déjà utilisée) + JOptionPane.showMessageDialog( + getTopestUI(), + _("tutti.editBenthosBatch.error.sampleCategoryValue.notAvailable", selectedItem, categoryDecorated)); + selectedItem = null; + } + + } else { + + // open a combobox to select new value + + List<CaracteristicQualitativeValue> availableValues = + Lists.newArrayList(caracteristic.getQualitativeValue()); + availableValues.removeAll(usedValues); + + JComboBox editor = new JComboBox(); + editor.setRenderer(new DecoratorListCellRenderer(getDecorator(CaracteristicQualitativeValue.class, null))); + SwingUtil.fillComboBox(editor, availableValues, availableValues.get(0)); + + int response = JOptionPane.showConfirmDialog( + getTopestUI(), + editor, + dialogTitle, + JOptionPane.OK_CANCEL_OPTION); + + if (response == JOptionPane.OK_OPTION) { + selectedItem = (CaracteristicQualitativeValue) editor.getSelectedItem(); + } else { + // user cancel selection + selectedItem = null; + } + } + + if (log.isInfoEnabled()) { + log.info("New selected category: " + selectedItem); + } + + if (selectedItem != null) { + + // update rows values + tableModel.updateSampleCategorieValue(selectedRow, + sampleCategoryId, + columnIndex, + selectedItem); + } + } + public void splitBatch(SampleCategoryModelEntry sampleCategoryDef, List<SplitBenthosBatchRowModel> rows, Float totalRowWeight) { @@ -805,8 +1037,6 @@ BenthosBatchUIModel model = getModel(); model.setLeafNumber(model.getLeafNumber() + newBatches.size() - 1); - - recomputeBatchActionEnable(); } public void updateTotalFromFrequencies(BenthosBatchRowModel row) { @@ -824,8 +1054,6 @@ } row.setComputedNumber(totalNumber); row.getFinestCategory().setOnlyOneFrequency(onlyOneFrequency); - - recomputeBatchActionEnable(); } public void saveRows(Iterable<BenthosBatchRowModel> rows) { @@ -835,190 +1063,10 @@ } } - protected void saveRow(BenthosBatchRowModel row) { - - FishingOperation fishingOperation = getModel().getFishingOperation(); - - Preconditions.checkNotNull(fishingOperation); - Preconditions.checkNotNull(row.getSpecies()); - Preconditions.checkNotNull(row.getFinestCategory()); - Preconditions.checkNotNull(row.getFinestCategory().getCategoryId()); - Preconditions.checkNotNull(row.getFinestCategory().getCategoryValue()); - -// SampleCategory<?> sampleCategory = row.getFinestCategory(); -// Preconditions.checkNotNull(sampleCategory); -// Preconditions.checkNotNull(sampleCategory.getCategoryId()); -// Preconditions.checkNotNull(sampleCategory.getCategoryValue()); - - BenthosBatch entityToSave = row.toEntity(); - - entityToSave.setFishingOperation(fishingOperation); - - BenthosBatchRowModel parent = row.getParentBatch(); - if (parent != null) { - //FIXME Check no need to convert parent weight ? :( - entityToSave.setParentBatch(parent.toBean()); - } - -// // apply sample category -// entityToSave.setSampleCategoryId(sampleCategory.getCategoryId()); -// entityToSave.setSampleCategoryValue(sampleCategory.getCategoryValue()); -// -// // convert sample category weight -// Float categoryWeight = sampleCategory.getCategoryWeight(); -// entityToSave.setSampleCategoryWeight(weightUnit.toEntity(categoryWeight)); - - if (TuttiEntities.isNew(entityToSave)) { - - BenthosBatchRowModel batchParent = row.getParentBatch(); - String parentBatchId = null; - - if (batchParent != null) { - parentBatchId = batchParent.getId(); - } - - if (log.isInfoEnabled()) { - log.info("Persist new species batch with parentId: " + - parentBatchId); - } - entityToSave = persistenceService.createBenthosBatch(entityToSave, - parentBatchId); - row.setId(entityToSave.getId()); - } else { - if (log.isInfoEnabled()) { - log.info("Persist existing species batch: " + entityToSave.getId() + " (parent : " + entityToSave.getParentBatch() + ")"); - } - persistenceService.saveBenthosBatch(entityToSave); - } - - List<BenthosFrequencyRowModel> frequencyRows = row.getFrequency(); - - List<BenthosBatchFrequency> frequency = - BenthosFrequencyRowModel.toEntity( - frequencyRows, - entityToSave); - - if (log.isInfoEnabled()) { - log.info("Will save " + frequency.size() + " frequencies."); - } - frequency = persistenceService.saveBenthosBatchFrequency( - entityToSave.getId(), frequency); - - // push it back to row model - frequencyRows = BenthosFrequencyRowModel.fromEntity(weightUnit, frequency); - row.setFrequency(frequencyRows); - - getModel().fireBatchUpdated(row); - } - public String getFilterBenthosBatchRootButtonText(int rootNumber) { return _("tutti.editBenthosBatch.filterBatch.mode.root", rootNumber); } - protected void recomputeBatchActionEnable() { - - int rowIndex = getTable().getSelectedRow(); - - //TODO Improve this test - boolean enableAdd = true; - - boolean enableRename = false; - boolean enableSplit = false; - boolean enableRemove = false; - boolean enableRemoveSub = false; - boolean enableCreateMelag = false; - boolean enableEditFrequencies = false; - - if (rowIndex != -1) { - - // there is a selected row - - - //TODO If there is some sub-batch, can remove them - //TODO If there is no sub-batch, can split current batch - - BenthosBatchTableModel tableModel = getTableModel(); - BenthosBatchRowModel row = tableModel.getEntry(rowIndex); - int selectedRowCount = getTable().getSelectedRowCount(); - - // can edit frequencies on a single selected leaf row - - - enableSplit = true; - - // action with single selection - enableRemove = selectedRowCount == 1; - enableRemoveSub = selectedRowCount == 1; - enableRename = selectedRowCount == 1; - enableCreateMelag = selectedRowCount > 1; - enableEditFrequencies = selectedRowCount == 1; - - if (enableSplit) { - - // can split if selected batch is a leaf - - Integer lastSamplingId = sampleCategoryModel.getLastCategoryId(); - - enableSplit = row.isBatchLeaf() - && selectedRowCount == 1 - && ObjectUtils.notEqual(lastSamplingId, row.getFinestCategory().getCategoryId()) - && row.getNumber() == null - && (row.getComputedNumber() == null - || row.getComputedNumber() == 0); - } - - if (enableEditFrequencies) { - - // can edit frequencies only on a leaf - enableEditFrequencies = row.isBatchLeaf(); - } - - if (enableRename) { - - // can rename if selected batch is a parent - enableRename = row.isBatchRoot(); - } - - if (enableRemove) { - - // can always remove the batch - // no more test - } - - if (enableRemoveSub) { - - // can remove sub batch if selected batch is not a leaf - enableRemoveSub = !row.isBatchLeaf(); - } - - if (enableCreateMelag) { - - JXTable table = getTable(); - - // can add species to a melag if several root are selected - int[] selectedRows = table.getSelectedRows(); - for (int selectedRowIndex : selectedRows) { - BenthosBatchRowModel selectedRow = - tableModel.getEntry(selectedRowIndex); - - if (!selectedRow.isBatchRoot()) { - enableCreateMelag = false; - break; - } - } - } - } - - BenthosBatchUIModel model = getModel(); - model.setCreateBatchEnabled(enableAdd); - model.setSplitBatchEnabled(enableSplit); - model.setRemoveBatchEnabled(enableRemove); - model.setRemoveSubBatchEnabled(enableRemoveSub); - model.setRenameBatchEnabled(enableRename); - model.setCreateMelagEnabled(enableCreateMelag); - model.setEditFrequenciesEnabled(enableEditFrequencies); - } - public void collectChildren(BenthosBatchRowModel row, Set<BenthosBatchRowModel> collectedRows) { @@ -1112,6 +1160,101 @@ return newRow; } + public void removeFromSpeciesUsed(BenthosBatchRowModel row) { + Preconditions.checkNotNull(row); + Preconditions.checkNotNull(row.getSpecies()); + SampleCategory<?> firstSampleCategory = row.getFirstSampleCategory(); + CaracteristicQualitativeValue categoryValue = (CaracteristicQualitativeValue) firstSampleCategory.getCategoryValue(); + Preconditions.checkNotNull(firstSampleCategory); + if (log.isInfoEnabled()) { + log.info("Remove from speciesUsed: " + decorate(categoryValue) + " - " + decorate(row.getSpecies())); + } + BenthosBatchUIModel model = getModel(); + model.getSpeciesUsed().remove(categoryValue, row.getSpecies()); + + if (row.isBatchRoot()) { + model.setRootNumber(model.getRootNumber() - 1); + } + } + + public Species openAddSpeciesDialog(String title, List<Species> species) { + SelectSpeciesUI dialogContent = new SelectSpeciesUI(ui); + SelectSpeciesUIModel model = dialogContent.getModel(); + model.setSelectedSpecies(null); + model.setSpecies(species); + + openDialog(dialogContent, title, new Dimension(400, 130)); + + return model.getSelectedSpecies(); + } + + //------------------------------------------------------------------------// + //-- Internal methods --// + //------------------------------------------------------------------------// + + protected void saveRow(BenthosBatchRowModel row) { + + FishingOperation fishingOperation = getModel().getFishingOperation(); + + Preconditions.checkNotNull(fishingOperation); + Preconditions.checkNotNull(row.getSpecies()); + Preconditions.checkNotNull(row.getFinestCategory()); + Preconditions.checkNotNull(row.getFinestCategory().getCategoryId()); + Preconditions.checkNotNull(row.getFinestCategory().getCategoryValue()); + + BenthosBatch entityToSave = row.toEntity(); + + entityToSave.setFishingOperation(fishingOperation); + + BenthosBatchRowModel parent = row.getParentBatch(); + if (parent != null) { + //FIXME Check no need to convert parent weight ? :( + entityToSave.setParentBatch(parent.toBean()); + } + + if (TuttiEntities.isNew(entityToSave)) { + + BenthosBatchRowModel batchParent = row.getParentBatch(); + String parentBatchId = null; + + if (batchParent != null) { + parentBatchId = batchParent.getId(); + } + + if (log.isInfoEnabled()) { + log.info("Persist new species batch with parentId: " + + parentBatchId); + } + entityToSave = persistenceService.createBenthosBatch(entityToSave, + parentBatchId); + row.setId(entityToSave.getId()); + } else { + if (log.isInfoEnabled()) { + log.info("Persist existing species batch: " + entityToSave.getId() + " (parent : " + entityToSave.getParentBatch() + ")"); + } + persistenceService.saveBenthosBatch(entityToSave); + } + + List<BenthosFrequencyRowModel> frequencyRows = row.getFrequency(); + + List<BenthosBatchFrequency> frequency = + BenthosFrequencyRowModel.toEntity( + frequencyRows, + entityToSave); + + if (log.isInfoEnabled()) { + log.info("Will save " + frequency.size() + " frequencies."); + } + frequency = persistenceService.saveBenthosBatchFrequency( + entityToSave.getId(), frequency); + + // push it back to row model + frequencyRows = BenthosFrequencyRowModel.fromEntity(weightUnit, frequency); + row.setFrequency(frequencyRows); + + getModel().fireBatchUpdated(row); + } + protected void loadBatchRow(BenthosBatchRowModel parentRow, BenthosBatchRowModel newRow, Integer sampleCategoryId, @@ -1164,23 +1307,6 @@ weightUnit); } - public void removeFromSpeciesUsed(BenthosBatchRowModel row) { - Preconditions.checkNotNull(row); - Preconditions.checkNotNull(row.getSpecies()); - SampleCategory<?> firstSampleCategory = row.getFirstSampleCategory(); - CaracteristicQualitativeValue categoryValue = (CaracteristicQualitativeValue) firstSampleCategory.getCategoryValue(); - Preconditions.checkNotNull(firstSampleCategory); - if (log.isInfoEnabled()) { - log.info("Remove from speciesUsed: " + decorate(categoryValue) + " - " + decorate(row.getSpecies())); - } - BenthosBatchUIModel model = getModel(); - model.getSpeciesUsed().remove(categoryValue, row.getSpecies()); - - if (row.isBatchRoot()) { - model.setRootNumber(model.getRootNumber() - 1); - } - } - protected void addToSpeciesUsed(BenthosBatchRowModel row) { Preconditions.checkNotNull(row); Preconditions.checkNotNull(row.getSpecies()); @@ -1198,17 +1324,6 @@ model.setRootNumber(model.getRootNumber() + 1); } - public Species openAddSpeciesDialog(String title, List<Species> species) { - SelectSpeciesUI dialogContent = new SelectSpeciesUI(ui); - SelectSpeciesUIModel model = dialogContent.getModel(); - model.setSelectedSpecies(null); - model.setSpecies(species); - - openDialog(dialogContent, title, new Dimension(400, 130)); - - return model.getSelectedSpecies(); - } - protected BenthosBatch convertRowToEntity(BenthosBatchRowModel row, boolean convertParent) { SampleCategory<?> sampleCategory = row.getFinestCategory(); Preconditions.checkNotNull(sampleCategory); @@ -1236,4 +1351,45 @@ return catchBean; } + + /** + * Return all the sample category values (of the given + * {@code sampleCategoryId}) for all brothers of the given {@code row}. + * + * @param row the row + * @param sampleCategoryId id of the sample category to seek in brothers of the given row + * @return all the sample category values (of the given + * {@code sampleCategoryId}) for all brothers of the given {@code row}. + */ + protected Set<Serializable> getSampleUsedValues(BenthosBatchRowModel row, + int sampleCategoryId) { + + // get the first ancestor for the sample category + SampleCategory<?> sampleCategory = row.getSampleCategoryById(sampleCategoryId); + BenthosBatchRowModel firstAncestor = row.getFirstAncestor(sampleCategory); + + Set<Serializable> usedValues = Sets.newHashSet(); + List<BenthosBatchRowModel> childs; + if (firstAncestor.isBatchRoot()) { + + // on a root must take all his brothers (but have no common ancestor...) + Species species = firstAncestor.getSpecies(); + childs = Lists.newArrayList(); + for (BenthosBatchRowModel rowToScan : getModel().getRows()) { + if (rowToScan.isBatchRoot() && species.equals(rowToScan.getSpecies())) { + childs.add(rowToScan); + } + } + } else { + // on a son, must take all the brother directly from his father + BenthosBatchRowModel parentBatch = firstAncestor.getParentBatch(); + childs = parentBatch.getChildBatch(); + } + + for (BenthosBatchRowModel child : childs) { + SampleCategory<?> category = child.getSampleCategoryById(sampleCategoryId); + usedValues.add(category.getCategoryValue()); + } + return usedValues; + } } \ No newline at end of file Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUIModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUIModel.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/benthos/BenthosBatchUIModel.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -51,6 +51,8 @@ public static final String PROPERTY_SPLIT_BATCH_ENABLED = "splitBatchEnabled"; + public static final String PROPERTY_CHANGE_SAMPLE_CATEGORY_ENABLED = "changeSampleCategoryEnabled"; + public static final String PROPERTY_REMOVE_SUB_BATCH_ENABLED = "removeSubBatchEnabled"; public static final String PROPERTY_RENAME_BATCH_ENABLED = "renameBatchEnabled"; @@ -86,6 +88,13 @@ protected boolean splitBatchEnabled; /** + * Can user change a sample category of the selected species batch ? + * + * @since 2.6 + */ + protected boolean changeSampleCategoryEnabled; + + /** * Can user remove a selected species batch? * * @since 0.3 @@ -313,6 +322,15 @@ firePropertyChange(PROPERTY_SPLIT_BATCH_ENABLED, null, splitBatchEnabled); } + public boolean isChangeSampleCategoryEnabled() { + return changeSampleCategoryEnabled; + } + + public void setChangeSampleCategoryEnabled(boolean changeSampleCategoryEnabled) { + this.changeSampleCategoryEnabled = changeSampleCategoryEnabled; + firePropertyChange(PROPERTY_CHANGE_SAMPLE_CATEGORY_ENABLED, null, changeSampleCategoryEnabled); + } + public boolean isRemoveBatchEnabled() { return removeBatchEnabled; } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchRowModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchRowModel.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchRowModel.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -475,6 +475,15 @@ } @Override + public void setSampleCategoryValue(Integer sampleCategoryId, Serializable value) { + SampleCategory<?> sampleCategory = + getSampleCategoryById(sampleCategoryId); + TuttiUIUtil.setProperty(sampleCategory, + SampleCategory.PROPERTY_CATEGORY_VALUE, value); + firePropertyChange(PROPERTY_SAMPLE_CATEGORY_VALUE, null, sampleCategory); + } + + @Override public void setSampleCategoryWeight(Integer sampleCategoryId, Object value) { SampleCategory<?> sampleCategory = getSampleCategoryById(sampleCategoryId); Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchTableModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchTableModel.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchTableModel.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -37,6 +37,7 @@ import org.jdesktop.swingx.table.TableColumnModelExt; import javax.swing.table.TableColumn; +import java.io.Serializable; import java.util.Enumeration; import java.util.Set; @@ -170,19 +171,9 @@ log.debug("First ancestor row: " + firstRowIndex); } - // must save this row now + // save this row and his shell + updateShell(firstAncestor, columnIndex); - // get shell of the ancestor - Set<SpeciesBatchRowModel> shell = Sets.newHashSet(); - firstAncestor.collectShell(shell); - - for (SpeciesBatchRowModel batchRowModel : shell) { - int currentRowIndex = getRowIndex(batchRowModel); - if (log.isDebugEnabled()) { - log.debug("Update shell row: " + currentRowIndex); - } - fireTableCellUpdated(currentRowIndex, columnIndex); - } } else { super.setValueAt(aValue, rowIndex, columnIndex, propertyName, entry); } @@ -252,4 +243,65 @@ } return result; } + + /** + * Return the sample category id of a column or {@code null} if not on a + * sample category column. + * + * @param columnIndex index of the column to look at + * @return the sample category id of a column or {@code null} if not on a + * sample category column. + * @since 2.6 + */ + public Integer getSampleCategoryId(int columnIndex) { + Integer result = null; + ColumnIdentifier<SpeciesBatchRowModel> identifier = getIdentifier(columnIndex); + if (sampleCols.contains(identifier)) { + SampleCategoryColumnIdentifier<SpeciesBatchRowModel> sampleId = (SampleCategoryColumnIdentifier<SpeciesBatchRowModel>) identifier; + result = sampleId.getSampleCategoryId(); + } + return result; + } + + /** + * Update the sample category value of all childs of the given {@code row}. + * + * @param row the row to walk through + * @param columnIndex index of the column where the sample category is + * @param newValue new sample category value to set + * @since 2.6 + */ + public void updateSampleCategorieValue(SpeciesBatchRowModel row, + int sampleCategoryId, + int columnIndex, + Serializable newValue) { + + SampleCategoryColumnIdentifier<SpeciesBatchRowModel> identifier = + (SampleCategoryColumnIdentifier<SpeciesBatchRowModel>) getIdentifier(columnIndex); + + // get the first ancestor using the category to update + SampleCategory<?> sampleCategory = row.getSampleCategoryById(sampleCategoryId); + SpeciesBatchRowModel firstAncestor = row.getFirstAncestor(sampleCategory); + + // set category value + identifier.setCategoryValue(firstAncestor, newValue); + + // update row shell + updateShell(firstAncestor, columnIndex); + } + + protected void updateShell(SpeciesBatchRowModel entry, int columnIndex) { + + Set<SpeciesBatchRowModel> shell = Sets.newHashSet(); + entry.collectShell(shell); + shell.add(entry); + + for (SpeciesBatchRowModel batchRowModel : shell) { + int currentRowIndex = getRowIndex(batchRowModel); + if (log.isDebugEnabled()) { + log.debug("Update shell row: " + currentRowIndex); + } + fireTableCellUpdated(currentRowIndex, columnIndex); + } + } } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUI.css =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUI.css 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUI.css 2013-09-25 07:22:58 UTC (rev 1221) @@ -162,6 +162,15 @@ _help: {"tutti.editSpeciesBatch.action.splitBatch.help"}; } +#changeSampleCategoryMenu { + actionIcon: batch-split; + text: "tutti.editSpeciesBatch.action.changeSampleCategory"; + toolTipText: "tutti.editSpeciesBatch.action.changeSampleCategory.tip"; + i18nMnemonic: "tutti.editSpeciesBatch.action.changeSampleCategory.mnemonic"; + enabled: {model.isTableViewModeAll() && model.isChangeSampleCategoryEnabled()}; + _help: {"tutti.editSpeciesBatch.action.changeSampleCategory.help"}; +} + #removeSpeciesBatchMenu { actionIcon: batch-delete; text: "tutti.editSpeciesBatch.action.removeBatch"; Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUI.jaxx =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUI.jaxx 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUI.jaxx 2013-09-25 07:22:58 UTC (rev 1221) @@ -78,6 +78,8 @@ <JPopupMenu id='tablePopup'> <JMenuItem id='splitSpeciesBatchMenu' onActionPerformed='handler.splitBatch()'/> + <JMenuItem id='changeSampleCategoryMenu' + onActionPerformed='handler.changeBatchCategory()'/> <JMenuItem id='removeSpeciesBatchMenu'/> <JMenuItem id='removeSpeciesSubBatchMenu'/> <JMenuItem id='renameSpeciesBatchMenu'/> Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUIHandler.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUIHandler.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUIHandler.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -26,6 +26,7 @@ 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.Attachment; import fr.ifremer.tutti.persistence.entities.data.BatchContainer; @@ -36,6 +37,7 @@ import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchFrequency; import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocols; +import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.service.DecoratorService; @@ -54,6 +56,7 @@ import fr.ifremer.tutti.ui.swing.content.operation.catches.species.split.SplitSpeciesBatchRowModel; import fr.ifremer.tutti.ui.swing.content.operation.catches.species.split.SplitSpeciesBatchUI; import fr.ifremer.tutti.ui.swing.util.TuttiBeanMonitor; +import fr.ifremer.tutti.ui.swing.util.TuttiUI; import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil; import fr.ifremer.tutti.ui.swing.util.WeightUnit; import fr.ifremer.tutti.ui.swing.util.attachment.AttachmentCellEditor; @@ -66,6 +69,8 @@ import fr.ifremer.tutti.ui.swing.util.table.AbstractSelectTableAction; import fr.ifremer.tutti.ui.swing.util.table.ColumnIdentifier; import jaxx.runtime.SwingUtil; +import jaxx.runtime.swing.editor.NumberEditor; +import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; import jaxx.runtime.validator.swing.SwingValidator; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; @@ -81,6 +86,7 @@ import org.nuiton.decorator.Decorator; import org.nuiton.validator.NuitonValidatorResult; +import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.RowFilter; @@ -247,7 +253,6 @@ } model.setRows(rows); - recomputeBatchActionEnable(); } //------------------------------------------------------------------------// @@ -321,9 +326,6 @@ } saveRow(firstAncestorRow); - // when row valid state has changed, recompute action enabled states - recomputeBatchActionEnable(); - cleanrRowMonitor(); return; @@ -334,9 +336,6 @@ } saveSelectedRowIfNeeded(); - - // when row valid state has changed, recompute action enabled states - recomputeBatchActionEnable(); } @Override @@ -381,28 +380,6 @@ } @Override - protected void onRowValidStateChanged(int rowIndex, - SpeciesBatchRowModel row, - Boolean oldValue, - Boolean newValue) { - super.onRowValidStateChanged(rowIndex, row, oldValue, newValue); - - // when row valid state has changed, recompute action enabled states - recomputeBatchActionEnable(); - } - - @Override - protected void onAfterSelectedRowChanged(int oldRowIndex, - SpeciesBatchRowModel oldRow, - int newRowIndex, - SpeciesBatchRowModel newRow) { - super.onAfterSelectedRowChanged(oldRowIndex, oldRow, newRowIndex, newRow); - - // when selected row has changed, recompute action enabled states - recomputeBatchActionEnable(); - } - - @Override protected void addHighlighters(JXTable table) { super.addHighlighters(table); @@ -475,6 +452,163 @@ table.addHighlighter(attachmentHighlighter); } + @Override + protected void beforeOpenPopup(int rowIndex, int columnIndex) { + super.beforeOpenPopup(rowIndex, columnIndex); + + boolean enableAdd = true; + + boolean enableRename = false; + boolean enableSplit = false; + boolean enableChangeSampleCategory = false; + boolean enableRemove = false; + boolean enableRemoveSub = false; + boolean enableCreateMelag = false; + boolean enableEditFrequencies = false; + + if (rowIndex != -1) { + + // there is a selected row + + + //TODO If there is some sub-batch, can remove them + //TODO If there is no sub-batch, can split current batch + + SpeciesBatchTableModel tableModel = getTableModel(); + SpeciesBatchRowModel row = tableModel.getEntry(rowIndex); + int selectedRowCount = getTable().getSelectedRowCount(); + + // can edit frequencies on a single selected leaf row + + + enableSplit = true; + + // action with single selection + enableRemove = selectedRowCount == 1; + enableRemoveSub = selectedRowCount == 1; + enableRename = selectedRowCount == 1; + enableCreateMelag = selectedRowCount > 1; + enableEditFrequencies = selectedRowCount == 1; + enableChangeSampleCategory = selectedRowCount == 1 && tableModel.isCellEditable(rowIndex, columnIndex); + + if (enableSplit) { + + // can split if selected batch is a leaf + + Integer lastSamplingId = sampleCategoryModel.getLastCategoryId(); + + enableSplit = row.isBatchLeaf() + && selectedRowCount == 1 + && ObjectUtils.notEqual(lastSamplingId, row.getFinestCategory().getCategoryId()) + && row.getNumber() == null + && (row.getComputedNumber() == null + || row.getComputedNumber() == 0); + } + + if (enableChangeSampleCategory) { + + // can change category if there is still a brother category free + Integer sampleCategoryId = + tableModel.getSampleCategoryId(columnIndex); + + if (sampleCategoryId == null) { + + // not on a sample category column + enableChangeSampleCategory = false; + } else { + + // get category + SampleCategoryModelEntry category = + sampleCategoryModel.getCategoryById(sampleCategoryId); + + // get all used values for this category + Set<Serializable> used = getSampleUsedValues( + row, sampleCategoryId); + + if (category.getCaracteristic().isNumericType()) { + + // if number then can always change it + + } else { + + // get all possible values + + List<CaracteristicQualitativeValue> available = + Lists.newArrayList(category.getCaracteristic().getQualitativeValue()); + available.removeAll(used); + + // action possible only if there is still some available values + enableChangeSampleCategory = !available.isEmpty(); + } + } + + } + + if (enableEditFrequencies) { + + // can edit frequencies only on a leaf + enableEditFrequencies = row.isBatchLeaf(); + } + + if (enableRename) { + + // can rename if selected batch is a parent + enableRename = row.isBatchRoot(); + } + + if (enableRemove) { + + // can always remove the batch + // no more test + } + + if (enableRemoveSub) { + + // can remove sub batch if selected batch is not a leaf + enableRemoveSub = !row.isBatchLeaf(); + } + + if (enableCreateMelag) { + + JXTable table = getTable(); + + // can add species to a melag if several root are selected + int[] selectedRows = table.getSelectedRows(); + for (int selectedRowIndex : selectedRows) { + SpeciesBatchRowModel selectedRow = + tableModel.getEntry(selectedRowIndex); + + if (!selectedRow.isBatchRoot()) { + enableCreateMelag = false; + break; + } + } + } + } + SpeciesBatchUIModel model = getModel(); + model.setCreateBatchEnabled(enableAdd); + model.setSplitBatchEnabled(enableSplit); + model.setChangeSampleCategoryEnabled(enableChangeSampleCategory); + model.setRemoveBatchEnabled(enableRemove); + model.setRemoveSubBatchEnabled(enableRemoveSub); + model.setRenameBatchEnabled(enableRename); + model.setCreateMelagEnabled(enableCreateMelag); + model.setEditFrequenciesEnabled(enableEditFrequencies); + + if (log.isInfoEnabled()) { + StringBuilder builder = new StringBuilder("actions for (" + rowIndex + "," + columnIndex + "):"); + builder.append("\nenableAdd: ").append(enableAdd); + builder.append("\nenableSplit: ").append(enableSplit); + builder.append("\nenableChangeSampleCategory: ").append(enableChangeSampleCategory); + builder.append("\nenableRemove: ").append(enableRemove); + builder.append("\nenableRemoveSub: ").append(enableRemoveSub); + builder.append("\nenableRename: ").append(enableRename); + builder.append("\nenableCreateMelag: ").append(enableCreateMelag); + builder.append("\nenableEditFrequencies: ").append(enableEditFrequencies); + log.info(builder.toString()); + } + } + //------------------------------------------------------------------------// //-- AbstractTuttiUIHandler methods --// //------------------------------------------------------------------------// @@ -625,8 +759,6 @@ getTable().setRowFilter(filter); } }); - - recomputeBatchActionEnable(); } @Override @@ -689,8 +821,6 @@ ); } } - - recomputeBatchActionEnable(); } public void editFrequencies() { @@ -757,6 +887,107 @@ } } + public void changeBatchCategory() { + + // get table model + SpeciesBatchTableModel tableModel = getTableModel(); + + // get selected row + int rowIndex = getTable().getSelectedRow(); + + // get selected column + int columnIndex = getTable().getSelectedColumn(); + + // get selected row + SpeciesBatchRowModel selectedRow = tableModel.getEntry(rowIndex); + + // get his sample category + Integer sampleCategoryId = tableModel.getSampleCategoryId(columnIndex); + SampleCategoryModelEntry sampleCategory = sampleCategoryModel.getCategoryById(sampleCategoryId); + Caracteristic caracteristic = sampleCategory.getCaracteristic(); + + // get used values + Set<Serializable> usedValues = getSampleUsedValues(selectedRow, + sampleCategoryId); + + // get the new selected value for this category + Serializable selectedItem; + + String categoryDecorated = decorate(caracteristic, DecoratorService.CARACTERISTIC_PARAMETER_ONLY); + String dialogTitle = _("tutti.editSpeciesBatch.title.changeSampleCategoryValue", categoryDecorated); + + if (caracteristic.isNumericType()) { + + // open a simple number editor + NumberEditor editor = new NumberEditor(); + editor.setNumberPattern(TuttiUI.DECIMAL3_PATTERN); + editor.setUseSign(false); + editor.setUseFloat(true); + editor.setShowPopupButton(false); + editor.setShowReset(false); + + int response = JOptionPane.showConfirmDialog( + getUI(), + editor, + dialogTitle, + JOptionPane.OK_CANCEL_OPTION); + + if (response == JOptionPane.OK_OPTION) { + selectedItem = editor.getModel(); + } else { + // user cancel selection + selectedItem = null; + } + + if (usedValues.contains(selectedItem)) { + + // impossible de choisir cette valeur (déjà utilisée) + JOptionPane.showMessageDialog( + getTopestUI(), + _("tutti.editSpeciesBatch.error.sampleCategoryValue.notAvailable", selectedItem, categoryDecorated)); + selectedItem = null; + } + + } else { + + // open a combobox to select new value + + List<CaracteristicQualitativeValue> availableValues = + Lists.newArrayList(caracteristic.getQualitativeValue()); + availableValues.removeAll(usedValues); + + JComboBox editor = new JComboBox(); + editor.setRenderer(new DecoratorListCellRenderer(getDecorator(CaracteristicQualitativeValue.class, null))); + SwingUtil.fillComboBox(editor, availableValues, availableValues.get(0)); + + int response = JOptionPane.showConfirmDialog( + getTopestUI(), + editor, + dialogTitle, + JOptionPane.OK_CANCEL_OPTION); + + if (response == JOptionPane.OK_OPTION) { + selectedItem = (CaracteristicQualitativeValue) editor.getSelectedItem(); + } else { + // user cancel selection + selectedItem = null; + } + } + + if (log.isInfoEnabled()) { + log.info("New selected category: " + selectedItem); + } + + if (selectedItem != null) { + + // update rows values + tableModel.updateSampleCategorieValue(selectedRow, + sampleCategoryId, + columnIndex, + selectedItem); + } + } + public void splitBatch(SampleCategoryModelEntry sampleCategoryDef, List<SplitSpeciesBatchRowModel> rows, Float totalRowWeight) { @@ -808,8 +1039,6 @@ SpeciesBatchUIModel model = getModel(); model.setLeafNumber(model.getLeafNumber() + newBatches.size() - 1); - - recomputeBatchActionEnable(); } public void updateTotalFromFrequencies(SpeciesBatchRowModel row) { @@ -827,8 +1056,6 @@ } row.setComputedNumber(totalNumber); row.getFinestCategory().setOnlyOneFrequency(onlyOneFrequency); - - recomputeBatchActionEnable(); } public void saveRows(Iterable<SpeciesBatchRowModel> rows) { @@ -838,188 +1065,10 @@ } } - protected void saveRow(SpeciesBatchRowModel row) { - - FishingOperation fishingOperation = getModel().getFishingOperation(); - Preconditions.checkNotNull(fishingOperation); - - Preconditions.checkNotNull(row.getSpecies()); - SampleCategory<?> sampleCategory = row.getFinestCategory(); - Preconditions.checkNotNull(sampleCategory); - Preconditions.checkNotNull(sampleCategory.getCategoryId()); - Preconditions.checkNotNull(sampleCategory.getCategoryValue()); - - SpeciesBatch catchBean = row.toBean(); - - // convert weight - Float weight = catchBean.getWeight(); - catchBean.setWeight(weightUnit.toEntity(weight)); - - catchBean.setFishingOperation(fishingOperation); - - SpeciesBatchRowModel parent = row.getParentBatch(); - if (parent != null) { - //FIXME Check no need to convert parent weight ? :( - catchBean.setParentBatch(parent.toBean()); - } - - // apply sample category - catchBean.setSampleCategoryId(sampleCategory.getCategoryId()); - catchBean.setSampleCategoryValue(sampleCategory.getCategoryValue()); - - // convert sample category weight - Float categoryWeight = sampleCategory.getCategoryWeight(); - catchBean.setSampleCategoryWeight(weightUnit.toEntity(categoryWeight)); - - if (TuttiEntities.isNew(catchBean)) { - - String parentBatchId = null; - if (parent != null) { - parentBatchId = parent.getId(); - } - - if (log.isInfoEnabled()) { - log.info("Persist new species batch with parentId: " + - parentBatchId); - } - catchBean = persistenceService.createSpeciesBatch(catchBean, - parentBatchId); - row.setId(catchBean.getId()); - } else { - if (log.isInfoEnabled()) { - log.info("Persist existing species batch: " + catchBean.getId() + " (parent : " + catchBean.getParentBatch() + ")"); - } - persistenceService.saveSpeciesBatch(catchBean); - } - - List<SpeciesFrequencyRowModel> frequencyRows = row.getFrequency(); - - List<SpeciesBatchFrequency> frequency = - SpeciesFrequencyRowModel.toEntity( - frequencyRows, - catchBean); - - if (log.isInfoEnabled()) { - log.info("Will save " + frequency.size() + " frequencies."); - } - frequency = persistenceService.saveSpeciesBatchFrequency( - catchBean.getId(), frequency); - - // push it back to row model - frequencyRows = SpeciesFrequencyRowModel.fromEntity(weightUnit, - frequency); - row.setFrequency(frequencyRows); - - getModel().fireBatchUpdated(row); - } - public String getFilterSpeciesBatchRootButtonText(int rootNumber) { return _("tutti.editSpeciesBatch.filterBatch.mode.root", rootNumber); } - protected void recomputeBatchActionEnable() { - - int rowIndex = getTable().getSelectedRow(); - - //TODO Improve this test - boolean enableAdd = true; - - boolean enableRename = false; - boolean enableSplit = false; - boolean enableRemove = false; - boolean enableRemoveSub = false; - boolean enableCreateMelag = false; - boolean enableEditFrequencies = false; - - if (rowIndex != -1) { - - // there is a selected row - - - //TODO If there is some sub-batch, can remove them - //TODO If there is no sub-batch, can split current batch - - SpeciesBatchTableModel tableModel = getTableModel(); - SpeciesBatchRowModel row = tableModel.getEntry(rowIndex); - int selectedRowCount = getTable().getSelectedRowCount(); - - // can edit frequencies on a single selected leaf row - - - enableSplit = true; - - // action with single selection - enableRemove = selectedRowCount == 1; - enableRemoveSub = selectedRowCount == 1; - enableRename = selectedRowCount == 1; - enableCreateMelag = selectedRowCount > 1; - enableEditFrequencies = selectedRowCount == 1; - - if (enableSplit) { - - // can split if selected batch is a leaf - Integer lastSamplingId = sampleCategoryModel.getLastCategoryId(); - - enableSplit = row.isBatchLeaf() - && selectedRowCount == 1 - && ObjectUtils.notEqual(lastSamplingId, row.getFinestCategory().getCategoryId()) - && row.getNumber() == null - && (row.getComputedNumber() == null - || row.getComputedNumber() == 0); - } - - if (enableEditFrequencies) { - - // can edit frequencies only on a leaf - enableEditFrequencies = row.isBatchLeaf(); - } - - if (enableRename) { - - // can rename if selected batch is a parent - enableRename = row.isBatchRoot(); - } - - if (enableRemove) { - - // can always remove the batch - // no more test - } - - if (enableRemoveSub) { - - // can remove sub batch if selected batch is not a leaf - enableRemoveSub = !row.isBatchLeaf(); - } - - if (enableCreateMelag) { - - JXTable table = getTable(); - - // can add species to a melag if several root are selected - int[] selectedRows = table.getSelectedRows(); - for (int selectedRowIndex : selectedRows) { - SpeciesBatchRowModel selectedRow = - tableModel.getEntry(selectedRowIndex); - - if (!selectedRow.isBatchRoot()) { - enableCreateMelag = false; - break; - } - } - } - } - - SpeciesBatchUIModel model = getModel(); - model.setCreateBatchEnabled(enableAdd); - model.setSplitBatchEnabled(enableSplit); - model.setRemoveBatchEnabled(enableRemove); - model.setRemoveSubBatchEnabled(enableRemoveSub); - model.setRenameBatchEnabled(enableRename); - model.setCreateMelagEnabled(enableCreateMelag); - model.setEditFrequenciesEnabled(enableEditFrequencies); - } - public void collectChildren(SpeciesBatchRowModel row, Set<SpeciesBatchRowModel> collectedRows) { @@ -1114,6 +1163,113 @@ return newRow; } + public void removeFromSpeciesUsed(SpeciesBatchRowModel row) { + Preconditions.checkNotNull(row); + Preconditions.checkNotNull(row.getSpecies()); + SampleCategory<?> firstSampleCategory = row.getFirstSampleCategory(); + CaracteristicQualitativeValue categoryValue = (CaracteristicQualitativeValue) firstSampleCategory.getCategoryValue(); + Preconditions.checkNotNull(firstSampleCategory); + if (log.isInfoEnabled()) { + log.info("Remove from speciesUsed: " + decorate(categoryValue) + " - " + decorate(row.getSpecies())); + } + SpeciesBatchUIModel model = getModel(); + model.getSpeciesUsed().remove(categoryValue, row.getSpecies()); + + if (row.isBatchRoot()) { + model.setRootNumber(model.getRootNumber() - 1); + } + } + + public Species openAddSpeciesDialog(String title, List<Species> species) { + SelectSpeciesUI dialogContent = new SelectSpeciesUI(ui); + SelectSpeciesUIModel model = dialogContent.getModel(); + model.setSelectedSpecies(null); + model.setSpecies(species); + + openDialog(dialogContent, title, new Dimension(400, 130)); + + return model.getSelectedSpecies(); + } + + //------------------------------------------------------------------------// + //-- Internal methods --// + //------------------------------------------------------------------------// + + protected void saveRow(SpeciesBatchRowModel row) { + + FishingOperation fishingOperation = getModel().getFishingOperation(); + Preconditions.checkNotNull(fishingOperation); + + Preconditions.checkNotNull(row.getSpecies()); + SampleCategory<?> sampleCategory = row.getFinestCategory(); + Preconditions.checkNotNull(sampleCategory); + Preconditions.checkNotNull(sampleCategory.getCategoryId()); + Preconditions.checkNotNull(sampleCategory.getCategoryValue()); + + SpeciesBatch catchBean = row.toBean(); + + // convert weight + Float weight = catchBean.getWeight(); + catchBean.setWeight(weightUnit.toEntity(weight)); + + catchBean.setFishingOperation(fishingOperation); + + SpeciesBatchRowModel parent = row.getParentBatch(); + if (parent != null) { + //FIXME Check no need to convert parent weight ? :( + catchBean.setParentBatch(parent.toBean()); + } + + // apply sample category + catchBean.setSampleCategoryId(sampleCategory.getCategoryId()); + catchBean.setSampleCategoryValue(sampleCategory.getCategoryValue()); + + // convert sample category weight + Float categoryWeight = sampleCategory.getCategoryWeight(); + catchBean.setSampleCategoryWeight(weightUnit.toEntity(categoryWeight)); + + if (TuttiEntities.isNew(catchBean)) { + + String parentBatchId = null; + if (parent != null) { + parentBatchId = parent.getId(); + } + + if (log.isInfoEnabled()) { + log.info("Persist new species batch with parentId: " + + parentBatchId); + } + catchBean = persistenceService.createSpeciesBatch(catchBean, + parentBatchId); + row.setId(catchBean.getId()); + } else { + if (log.isInfoEnabled()) { + log.info("Persist existing species batch: " + catchBean.getId() + " (parent : " + catchBean.getParentBatch() + ")"); + } + persistenceService.saveSpeciesBatch(catchBean); + } + + List<SpeciesFrequencyRowModel> frequencyRows = row.getFrequency(); + + List<SpeciesBatchFrequency> frequency = + SpeciesFrequencyRowModel.toEntity( + frequencyRows, + catchBean); + + if (log.isInfoEnabled()) { + log.info("Will save " + frequency.size() + " frequencies."); + } + frequency = persistenceService.saveSpeciesBatchFrequency( + catchBean.getId(), frequency); + + // push it back to row model + frequencyRows = SpeciesFrequencyRowModel.fromEntity(weightUnit, + frequency); + row.setFrequency(frequencyRows); + + getModel().fireBatchUpdated(row); + } + protected void loadBatchRow(SpeciesBatchRowModel parentRow, SpeciesBatchRowModel newRow, Integer sampleCategoryId, @@ -1161,29 +1317,11 @@ SampleCategoryComponent.newEditor(decorator, weightUnit), SampleCategoryComponent.newRender(defaultRenderer, decorator, - getConfig().getColorComputedWeights() - ), + getConfig().getColorComputedWeights()), columnIdentifier, weightUnit); } - public void removeFromSpeciesUsed(SpeciesBatchRowModel row) { - Preconditions.checkNotNull(row); - Preconditions.checkNotNull(row.getSpecies()); - SampleCategory<?> firstSampleCategory = row.getFirstSampleCategory(); - CaracteristicQualitativeValue categoryValue = (CaracteristicQualitativeValue) firstSampleCategory.getCategoryValue(); - Preconditions.checkNotNull(firstSampleCategory); - if (log.isInfoEnabled()) { - log.info("Remove from speciesUsed: " + decorate(categoryValue) + " - " + decorate(row.getSpecies())); - } - SpeciesBatchUIModel model = getModel(); - model.getSpeciesUsed().remove(categoryValue, row.getSpecies()); - - if (row.isBatchRoot()) { - model.setRootNumber(model.getRootNumber() - 1); - } - } - protected void addToSpeciesUsed(SpeciesBatchRowModel row) { Preconditions.checkNotNull(row); Preconditions.checkNotNull(row.getSpecies()); @@ -1201,38 +1339,14 @@ model.setRootNumber(model.getRootNumber() + 1); } - public Species openAddSpeciesDialog(String title, List<Species> species) { - SelectSpeciesUI dialogContent = new SelectSpeciesUI(ui); - SelectSpeciesUIModel model = dialogContent.getModel(); - model.setSelectedSpecies(null); - model.setSpecies(species); - - openDialog(dialogContent, title, new Dimension(400, 130)); - - return model.getSelectedSpecies(); - } - protected SpeciesBatch convertRowToEntity(SpeciesBatchRowModel row, boolean convertParent) { Preconditions.checkNotNull(row.getFinestCategory()); Preconditions.checkNotNull(row.getFinestCategory().getCategoryId()); Preconditions.checkNotNull(row.getFinestCategory().getCategoryValue()); -// SampleCategory<?> sampleCategory = row.getFinestCategory(); -// Preconditions.checkNotNull(sampleCategory); -// Preconditions.checkNotNull(sampleCategory.getCategoryId()); -// Preconditions.checkNotNull(sampleCategory.getCategoryValue()); - SpeciesBatch catchBean = row.toEntity(); -// // apply sample category -// catchBean.setSampleCategoryId(sampleCategory.getCategoryId()); -// catchBean.setSampleCategoryValue(sampleCategory.getCategoryValue()); -// -// // convert sample category weight -// Float categoryWeight = sampleCategory.getCategoryWeight(); -// catchBean.setSampleCategoryWeight(weightUnit.toEntity(categoryWeight)); - if (convertParent && row.getParentBatch() != null) { SpeciesBatch parent = convertRowToEntity(row.getParentBatch(), true); catchBean.setParentBatch(parent); @@ -1240,4 +1354,45 @@ return catchBean; } + + /** + * Return all the sample category values (of the given + * {@code sampleCategoryId}) for all brothers of the given {@code row}. + * + * @param row the row + * @param sampleCategoryId id of the sample category to seek in brothers of the given row + * @return all the sample category values (of the given + * {@code sampleCategoryId}) for all brothers of the given {@code row}. + */ + protected Set<Serializable> getSampleUsedValues(SpeciesBatchRowModel row, + int sampleCategoryId) { + + // get the first ancestor for the sample category + SampleCategory<?> sampleCategory = row.getSampleCategoryById(sampleCategoryId); + SpeciesBatchRowModel firstAncestor = row.getFirstAncestor(sampleCategory); + + Set<Serializable> usedValues = Sets.newHashSet(); + List<SpeciesBatchRowModel> childs; + if (firstAncestor.isBatchRoot()) { + + // on a root must take all his brothers (but have no common ancestor...) + Species species = firstAncestor.getSpecies(); + childs = Lists.newArrayList(); + for (SpeciesBatchRowModel rowToScan : getModel().getRows()) { + if (rowToScan.isBatchRoot() && species.equals(rowToScan.getSpecies())) { + childs.add(rowToScan); + } + } + } else { + // on a son, must take all the brother directly from his father + SpeciesBatchRowModel parentBatch = firstAncestor.getParentBatch(); + childs = parentBatch.getChildBatch(); + } + + for (SpeciesBatchRowModel child : childs) { + SampleCategory<?> category = child.getSampleCategoryById(sampleCategoryId); + usedValues.add(category.getCategoryValue()); + } + return usedValues; + } } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUIModel.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUIModel.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/SpeciesBatchUIModel.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -49,6 +49,8 @@ public static final String PROPERTY_SPLIT_BATCH_ENABLED = "splitBatchEnabled"; + public static final String PROPERTY_CHANGE_SAMPLE_CATEGORY_ENABLED = "changeSampleCategoryEnabled"; + public static final String PROPERTY_REMOVE_SUB_BATCH_ENABLED = "removeSubBatchEnabled"; public static final String PROPERTY_RENAME_BATCH_ENABLED = "renameBatchEnabled"; @@ -86,6 +88,13 @@ protected boolean splitBatchEnabled; /** + * Can user change a sample category of the selected species batch ? + * + * @since 2.6 + */ + protected boolean changeSampleCategoryEnabled; + + /** * Can user remove a selected species batch? * * @since 0.3 @@ -295,6 +304,15 @@ firePropertyChange(PROPERTY_SPLIT_BATCH_ENABLED, null, splitBatchEnabled); } + public boolean isChangeSampleCategoryEnabled() { + return changeSampleCategoryEnabled; + } + + public void setChangeSampleCategoryEnabled(boolean changeSampleCategoryEnabled) { + this.changeSampleCategoryEnabled = changeSampleCategoryEnabled; + firePropertyChange(PROPERTY_CHANGE_SAMPLE_CATEGORY_ENABLED, null, changeSampleCategoryEnabled); + } + public boolean isRemoveBatchEnabled() { return removeBatchEnabled; } Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/AbstractTuttiUIHandler.java =================================================================== --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/AbstractTuttiUIHandler.java 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/AbstractTuttiUIHandler.java 2013-09-25 07:22:58 UTC (rev 1221) @@ -1008,12 +1008,16 @@ JXTable source = (JXTable) e.getSource(); int[] selectedRows = source.getSelectedRows(); + int[] selectedColumns = source.getSelectedColumns(); // get the row index at this point int rowIndex = source.rowAtPoint(p); + // get the column index at this point + int columnIndex = source.columnAtPoint(p); + if (log.isDebugEnabled()) { - log.debug("At point [" + p + "] found Row " + rowIndex); + log.debug("At point [" + p + "] found Row " + rowIndex + ", Column " + columnIndex); } boolean canContinue = true; @@ -1039,8 +1043,17 @@ source.setRowSelectionInterval(rowIndex, rowIndex); } + // select column (could empty selection) + if (columnIndex == -1) { + source.clearSelection(); + } else if (!ArrayUtils.contains(selectedColumns, columnIndex)) { + source.setColumnSelectionInterval(columnIndex, columnIndex); + } + if (rightClick) { + beforeOpenPopup(rowIndex, columnIndex); + // on right click show popup popup.show(source, e.getX(), e.getY()); } @@ -1048,6 +1061,20 @@ } } + /** + * Hook to prepare popup just before showing it. + * <p/> + * The right place to update actions accessibility; a quite better design + * than trying to update each time something change in the table... + * + * @param rowIndex selected row index (or lowest selected one) + * @param columnIndex selected column index + * @since 2.6 + */ + protected void beforeOpenPopup(int rowIndex, int columnIndex) { + + } + public void openRowMenu(KeyEvent e, JPopupMenu popup) { if (e.getKeyCode() == KeyEvent.VK_CONTEXT_MENU) { @@ -1061,7 +1088,8 @@ lowestRow = Math.max(lowestRow, row); } // get the selected column - Rectangle r = source.getCellRect(lowestRow, source.getSelectedColumn(), true); + int selectedColumn = source.getSelectedColumn(); + Rectangle r = source.getCellRect(lowestRow, selectedColumn, true); // get the point in the middle lower of the cell Point p = new Point(r.x + r.width / 2, r.y + r.height); @@ -1085,6 +1113,9 @@ } if (canContinue) { + + beforeOpenPopup(lowestRow, selectedColumn); + popup.show(source, p.x, p.y); } } Modified: trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_en_GB.properties =================================================================== --- trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_en_GB.properties 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_en_GB.properties 2013-09-25 07:22:58 UTC (rev 1221) @@ -352,6 +352,9 @@ tutti.editAccidentalBatch.table.header.species.tip= tutti.editAccidentalBatch.table.header.weight= tutti.editAccidentalBatch.table.header.weight.tip= +tutti.editBenthosBatch.action.changeSampleCategory= +tutti.editBenthosBatch.action.changeSampleCategory.mnemonic= +tutti.editBenthosBatch.action.changeSampleCategory.tip= tutti.editBenthosBatch.action.createBatch= tutti.editBenthosBatch.action.createBatch.mnemonic= tutti.editBenthosBatch.action.createBatch.tip= @@ -389,6 +392,7 @@ tutti.editBenthosBatch.action.splitBatch= tutti.editBenthosBatch.action.splitBatch.mnemonic= tutti.editBenthosBatch.action.splitBatch.tip= +tutti.editBenthosBatch.error.sampleCategoryValue.notAvailable= tutti.editBenthosBatch.field.benthosTotalInertWeight= tutti.editBenthosBatch.field.benthosTotalInertWeight.tip= tutti.editBenthosBatch.field.benthosTotalLivingNotItemizedWeight= @@ -424,6 +428,7 @@ tutti.editBenthosBatch.table.header.toConfirm.tip= tutti.editBenthosBatch.table.header.weight= tutti.editBenthosBatch.table.header.weight.tip= +tutti.editBenthosBatch.title.changeSampleCategoryValue= tutti.editBenthosFrequencies.action.cancel= tutti.editBenthosFrequencies.action.cancel.mnemonic= tutti.editBenthosFrequencies.action.cancel.tip= @@ -868,6 +873,9 @@ tutti.editSampleCategoryModel.table.header.label= tutti.editSampleCategoryModel.table.header.label.tip= tutti.editSampleCategoryModel.title= +tutti.editSpeciesBatch.action.changeSampleCategory= +tutti.editSpeciesBatch.action.changeSampleCategory.mnemonic= +tutti.editSpeciesBatch.action.changeSampleCategory.tip= tutti.editSpeciesBatch.action.createBatch= tutti.editSpeciesBatch.action.createBatch.mnemonic= tutti.editSpeciesBatch.action.createBatch.tip= Modified: trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties =================================================================== --- trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties 2013-09-24 15:43:28 UTC (rev 1220) +++ trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties 2013-09-25 07:22:58 UTC (rev 1221) @@ -351,6 +351,9 @@ tutti.editAccidentalBatch.table.header.species.tip=Espèce tutti.editAccidentalBatch.table.header.weight=Poids observé tutti.editAccidentalBatch.table.header.weight.tip=Poids observé +tutti.editBenthosBatch.action.changeSampleCategory=Modifier la catégorie +tutti.editBenthosBatch.action.changeSampleCategory.mnemonic=M +tutti.editBenthosBatch.action.changeSampleCategory.tip=Modifier la catégorie de la cellule sélectionnée tutti.editBenthosBatch.action.createBatch=Créer un lot pour une espèce tutti.editBenthosBatch.action.createBatch.mnemonic=C tutti.editBenthosBatch.action.createBatch.tip=Créer un nouveau lot pour une espèce @@ -388,6 +391,8 @@ tutti.editBenthosBatch.action.splitBatch=Catégoriser le lot tutti.editBenthosBatch.action.splitBatch.mnemonic=C tutti.editBenthosBatch.action.splitBatch.tip=Catégoriser le lot courant (celui de la ligne sélectionné) +tutti.editBenthosBatch.error.sampleCategoryValue.notAvailable=La valeur %s de la catégorie %s est déjà utilisée +tutti.editSpeciesBatch.error.sampleCategoryValue.notAvailable=La valeur %s de la catégorie %s est déjà utilisée tutti.editBenthosBatch.field.benthosTotalInertWeight=Poids inerte trié tutti.editBenthosBatch.field.benthosTotalInertWeight.tip=Poids de la fraction inerte restante après le tri du benthos (cailloux, vase, débris coquilliers, etc.) tutti.editBenthosBatch.field.benthosTotalLivingNotItemizedWeight=Poids vivant non détaillé trié @@ -423,12 +428,16 @@ tutti.editBenthosBatch.table.header.toConfirm.tip=Case à cocher si il y a un doute sur l'identification de l'espèce tutti.editBenthosBatch.table.header.weight=Poids sous-échantillonné tutti.editBenthosBatch.table.header.weight.tip=Poids du lot mesuré ou dénombré +tutti.editBenthosBatch.title.changeSampleCategoryValue=Changer la valeur de la catégorie %s +tutti.editSpeciesBatch.title.changeSampleCategoryValue=Changer la valeur de la catégorie %s tutti.editBenthosFrequencies.action.cancel=Annuler tutti.editBenthosFrequencies.action.cancel.mnemonic=A tutti.editBenthosFrequencies.action.cancel.tip=Annuler l'édition des mensurations tutti.editBenthosFrequencies.action.generate=Générer tutti.editBenthosFrequencies.action.generate.mnemonic=G tutti.editBenthosFrequencies.action.generate.tip=Générer les mensurations +tutti.editBenthosFrequencies.action.reset=Réinitialiser +tutti.editBenthosFrequencies.action.reset.tip=Supprimer toutes les mensurations saisies tutti.editBenthosFrequencies.action.saveAndClose=Enregistrer et Fermer tutti.editBenthosFrequencies.action.saveAndClose.mnemonic=F tutti.editBenthosFrequencies.action.saveAndClose.tip=Enregistrer les mensurations @@ -867,6 +876,9 @@ tutti.editSampleCategoryModel.table.header.label=Label tutti.editSampleCategoryModel.table.header.label.tip=Label de la catéogire (sera utilisée dans les entêtes de tableau) tutti.editSampleCategoryModel.title=Configurer les catégorisations +tutti.editSpeciesBatch.action.changeSampleCategory=Modifier la catégorie +tutti.editSpeciesBatch.action.changeSampleCategory.mnemonic=M +tutti.editSpeciesBatch.action.changeSampleCategory.tip=Modifier la catégorie de la cellule sélectionnée tutti.editSpeciesBatch.action.createBatch=Créer un lot pour une espèce tutti.editSpeciesBatch.action.createBatch.mnemonic=C tutti.editSpeciesBatch.action.createBatch.tip=Créer un nouveau lot pour une espèce @@ -951,9 +963,6 @@ tutti.editSpeciesFrequencies.action.reset=Réinitialiser tutti.editSpeciesFrequencies.action.reset.mnemonic=R tutti.editSpeciesFrequencies.action.reset.tip=Supprimer toutes les mensurations saisies -tutti.editBenthosFrequencies.action.reset=Réinitialiser -tutti.editbenthosFrequencies.action.reset.mnemonic=R -tutti.editBenthosFrequencies.action.reset.tip=Supprimer toutes les mensurations saisies tutti.editSpeciesFrequencies.action.saveAndClose=Enregistrer et Fermer tutti.editSpeciesFrequencies.action.saveAndClose.mnemonic=F tutti.editSpeciesFrequencies.action.saveAndClose.tip=Enregistrer les mensurations @@ -992,6 +1001,7 @@ tutti.editSpeciesFrequencies.table.header.number=Nombre tutti.editSpeciesFrequencies.table.header.weight=Poids observé tutti.editSpeciesFrequencies.title=Mensuration +tutti.editbenthosFrequencies.action.reset.mnemonic=R tutti.error.about.could.not.reach.url=Récupération des versions de mises à jour impossible (l'url <strong>%s</strong> n'est pas joignable) tutti.error.delete.startActionFile=Impossible de supprimer le fichier %s tutti.error.errorpane.htmlmessage=<html><body><b>Une erreur s'est produite</b>\:<br/>%s</body></html>