/* *------------------------------------------------------------------------------ * Copyright (C) 2014 University of Dundee. All rights reserved. * * * 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 2 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, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.agents.measurement.view; //Java imports import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.table.AbstractTableModel; import omero.model.Length; import omero.model.enums.UnitsLength; import org.openmicroscopy.shoola.agents.measurement.util.model.MeasurementObject; import org.openmicroscopy.shoola.agents.measurement.util.ui.KeyDescription; import org.openmicroscopy.shoola.util.CommonsLangUtils; import org.openmicroscopy.shoola.util.roi.model.annotation.AnnotationKeys; import org.openmicroscopy.shoola.util.roi.model.util.MeasurementUnits; import org.openmicroscopy.shoola.util.ui.UIUtilities; /** * * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @since 5.0 */ public class MeasurementTableModel extends AbstractTableModel { private MeasurementUnits unitsType; /** The collection of column's names. */ private List<KeyDescription> columnNames; /** Collection of <code>Object</code>s hosted by this model. */ private List<MeasurementObject> values; /** Flag indicating to display the units.*/ private boolean showUnits; /** Keep track of the columns to show the units for.*/ private List<Boolean> unitsDisplay; /** * Creates a new instance. * * @param colNames The collection of column's names. * Mustn't be <code>null</code>. * @param units The units of measurement. */ MeasurementTableModel(List<KeyDescription> colNames, MeasurementUnits units) { if (colNames == null) throw new IllegalArgumentException("No column's names " + "specified."); this.columnNames = colNames; this.values = new ArrayList<MeasurementObject>(); this.unitsType = units; unitsDisplay = new ArrayList<Boolean>(); } /** * Sets the flag indicating to show the units. * * @param showUnits See above. */ void setShowUnits(boolean showUnits) { this.showUnits = showUnits; } public List<KeyDescription> getColumnNames() { return columnNames; } /** * Returns the units type. * * @return See above. */ public MeasurementUnits getUnitsType() { return unitsType; } /** * Adds a new row to the model. * * @param row The value to add. */ void addRow(MeasurementObject row) { values.add(row); fireTableStructureChanged(); } /** * Get a row from the model. * * @param index The row to return * * @return MeasurementObject the row. */ MeasurementObject getRow(int index) { if (index < values.size()) return values.get(index); return null; } /** * Returns the value of the specified cell. * @see AbstractTableModel#getValueAt(int, int) */ public Object getValueAt(int row, int col) { if (row < 0 || row > values.size()) return null; MeasurementObject rowData = values.get(row); Object value = rowData.getElement(col); if (value instanceof List && !showUnits) { List<Object> l = (List<Object>) value; if (l.size() == 1) return l.get(0); StringBuilder buffer = new StringBuilder(); Iterator<Object> i = l.iterator(); Object v; double total = 0; while (i.hasNext()) { v = i.next(); if (v instanceof Number) { double d = ((Number) v).doubleValue(); total += d; buffer.append(UIUtilities.formatToDecimal(d)); buffer.append(" "); } } if (total > 0) { buffer.append("= "+UIUtilities.formatToDecimal(total)); } return buffer.toString(); } if (showUnits) { if (value instanceof Length) { Length n = (Length) value; return convertLength(n, col); } else if (value instanceof List) { List l = (List) value; Iterator<Object> i = l.iterator(); Object v; StringBuilder buffer = new StringBuilder(); int size = l.size(); Object s; while (i.hasNext()) { v = i.next(); if (v instanceof Length) { Length n = (Length) v; s = convertLength(n, col); if (size == 1) return s; if (s != null) { buffer.append(s); buffer.append(" "); } } else if (v instanceof Number) { double d = ((Number) v).doubleValue(); if (size == 1) { return UIUtilities.twoDecimalPlacesAsNumber(d); } s = UIUtilities.twoDecimalPlaces(d); if (s != null) { buffer.append(s); buffer.append(" "); } } } return buffer.toString(); } else if (value instanceof Number) { double d = ((Number) value).doubleValue(); return UIUtilities.twoDecimalPlacesAsNumber(d); } } return value; } /** * Converts the length object either as a string or a numerical value. * * @param n The value to convert. * @param col The column hosting the value. * @return See above */ private Object convertLength(Length n, int col) { KeyDescription key = getColumnNames().get(col); MeasurementUnits units = getUnitsType(); String k = key.getKey(); String s = null; if (!units.getUnit().equals(UnitsLength.PIXEL)) { if (unitsDisplay.size() > col && unitsDisplay.get(col)) { s = UIUtilities.formatValue(n, AnnotationKeys.AREA.getKey().equals(k)); } else { return UIUtilities.formatValueNoUnitAsNumber(n, AnnotationKeys.AREA.getKey().equals(k)); } if (CommonsLangUtils.isNotBlank(s)) return s; } Number value = UIUtilities.twoDecimalPlacesAsNumber(n.getValue()); if (value.doubleValue() == 0) return null; return value; } /** * Sets the specified value. * @see AbstractTableModel#setValueAt(Object, int, int) */ public void setValueAt(Object value, int row, int col) {} /** * Overridden to return the name of the specified column. * @see AbstractTableModel#getColumnName(int) */ public String getColumnName(int col) { return columnNames.get(col).getDescription(); } /** * Overridden to return the number of columns. * @see AbstractTableModel#getColumnCount() */ public int getColumnCount() { return columnNames.size(); } /** * Overridden to return the number of rows. * @see AbstractTableModel#getRowCount() */ public int getRowCount() { return values.size(); } /** * Overridden so that the cell is not editable. * @see AbstractTableModel#isCellEditable(int, int) */ public boolean isCellEditable(int row, int col) { return false; } /** * Creates a copy of the model. * * @return See above. */ MeasurementTableModel copy() { //check column name KeyDescription key; List<KeyDescription> list = new ArrayList<KeyDescription>( this.columnNames.size()); Iterator<KeyDescription> kk = this.columnNames.iterator(); while (kk.hasNext()) { key = kk.next(); list.add(new KeyDescription(key.getKey(), key.getDescription())); } MeasurementTableModel model = new MeasurementTableModel( list, this.unitsType); model.values.addAll(this.values); //Add the units to the column names. for (int i = 0; i < model.getColumnCount(); i++) { List<String> symbols = new ArrayList<String>(); key = model.getColumnNames().get(i); String k = key.getKey(); for (int j = 0; j < getRowCount(); j++) { Object v = getValueAt(j, i); if (v instanceof Length) { Length l = (Length) v; if (AnnotationKeys.AREA.getKey().equals(k)) { l = UIUtilities.transformSquareSize(l); } else { l = UIUtilities.transformSize(l); } String s = l.getSymbol(); if (!symbols.contains(s) && !l.getUnit().equals(UnitsLength.PIXEL)) { symbols.add(s); } } else if (v instanceof Number) { if (k.equals(AnnotationKeys.ANGLE.getKey())) { String s = UIUtilities.DEGREE_SYMBOL; if (!symbols.contains(s)) { symbols.add(s); } } } } if (symbols.size() == 1) { String value = key.getDescription()+" ("+symbols.get(0); if (AnnotationKeys.AREA.getKey().equals(k)) { value += UIUtilities.SQUARED_SYMBOL; } value += ")"; key.setDescription(value); model.unitsDisplay.add(false); } else { model.unitsDisplay.add(true); } } return model; } }