All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.jaxx.application.swing.table.AbstractApplicationTableModel Maven / Gradle / Ivy

There is a newer version: 3.0-alpha-1
Show newest version
package org.nuiton.jaxx.application.swing.table;

/*
 * #%L
 * JAXX :: Application Swing
 * %%
 * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import jaxx.runtime.SwingUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdesktop.swingx.table.TableColumnModelExt;

import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import java.io.Serializable;
import java.util.List;
import java.util.Set;

/**
 * Abstract model of a table.
 *
 * @param  type of a row.
 * @author Tony Chemit - [email protected]
 * @since 2.8
 */
public abstract class AbstractApplicationTableModel extends AbstractTableModel {

    private static final long serialVersionUID = 1L;

    /** Logger. */
    private static final Log log =
            LogFactory.getLog(AbstractApplicationTableModel.class);

    /**
     * Data in the model.
     *
     * @since 0.2
     */
    protected List rows;

    /**
     * Set of non editable columns.
     *
     * @since 0.2
     */
    protected Set> noneEditableCols;

    /**
     * Creates a new row when moving to next editable cell / row ?
     *
     * @since 0.3
     */
    protected final boolean createNewRow;

    /**
     * Creates a first empty row when setting a null or empty list of rows ?
     *
     * @since 0.3
     */
    protected final boolean createEmptyRowIsEmpty;

    /**
     * Identifiers of columns (in initial order).
     *
     * @since 1.1
     */
    protected final List> identifiers;

    public abstract R createNewRow();

    protected AbstractApplicationTableModel(TableColumnModelExt columnModel,
                                            boolean createNewRow,
                                            boolean createEmptyRowIsEmpty) {
        this.identifiers = Lists.newArrayListWithCapacity(columnModel.getColumnCount());
        for (TableColumn tc : columnModel.getColumns(true)) {
            this.identifiers.add((ColumnIdentifier) tc.getIdentifier());
        }
        this.createNewRow = createNewRow;
        this.createEmptyRowIsEmpty = createEmptyRowIsEmpty;
    }

    public final List getRows() {
        return rows;
    }

    public final void setRows(List data) {

        // can't accept a empty data list
        Preconditions.checkNotNull(data, "Data list can not be null.");

        onBeforeRowsChanged(rows);

        this.rows = null;
        if (createEmptyRowIsEmpty && data.isEmpty()) {

            if (log.isDebugEnabled()) {
                log.debug("Creates a first empty row on tableModel " + this);
            }
            // add a first edit line
            data.add(createNewRow());
        }
        if (log.isDebugEnabled()) {
            log.debug("Set " + data.size() + " row(s) in table model " + this);
        }
        this.rows = data;
        onRowsChanged(data);
        fireTableDataChanged();
    }

    public boolean isCreateNewRow() {
        return createNewRow;
    }

    public boolean isCreateEmptyRowIsEmpty() {
        return createEmptyRowIsEmpty;
    }

    public final void addNewRow() {
        R newValue = createNewRow();
        addNewRow(newValue);
    }

    public final void addNewRow(R newValue) {

        addNewRow(getRowCount(), newValue);
    }

    public final void addNewRow(int rowIndex, R newValue) {

        Preconditions.checkNotNull(newValue, "Row can not be null.");

        List data = getRows();
        Preconditions.checkNotNull(data, "Data list can not be null.");

        data.add(rowIndex, newValue);

        onRowAdded(rowIndex, newValue);
        fireTableRowsInserted(rowIndex, rowIndex);
    }

    public final void fireTableRowsInserted(R newValue) {

        Preconditions.checkNotNull(newValue, "Row can not be null.");

        int rowIndex = getRowIndex(newValue);
        fireTableRowsInserted(rowIndex, rowIndex);
    }

    public final int updateRow(R row) {
        Preconditions.checkNotNull(row, "Row can not be null.");

        List data = getRows();
        Preconditions.checkNotNull(data, "Data list can not be null.");

        int rowIndex = data.indexOf(row);

        onRowUpdated(rowIndex, row);
        fireTableRowsUpdated(rowIndex, rowIndex);
        return rowIndex;
    }

    public final R removeRow(int rowIndex) {
        SwingUtil.ensureRowIndex(this, rowIndex);

        List data = getRows();

        R row = data.remove(rowIndex);

        onRowRemoved(rowIndex, row);
        fireTableRowsDeleted(rowIndex, rowIndex);
        return row;
    }

    protected void onRowsChanged(List newRows) {
        // by default do nothing
    }

    protected void onBeforeRowsChanged(List oldRows) {
        // by default do nothing
    }

    protected void onRowAdded(int rowIndex, R row) {
        // by default do nothing
    }

    protected void onRowUpdated(int rowIndex, R row) {
        // by default do nothing
    }

    protected void onRowRemoved(int rowIndex, R row) {
        // by default do nothing
    }

    public final int getRowIndex(R row) {
        return rows == null ? -1 : rows.indexOf(row);
    }

    public final R getEntry(int rowIndex) {
        SwingUtil.ensureRowIndex(this, rowIndex);
        List data = getRows();
        return data == null ? null : data.get(rowIndex);
    }

    public final void setNoneEditableCols(ColumnIdentifier... noneEditableCols) {
        this.noneEditableCols = Sets.newHashSet(noneEditableCols);
    }

    @Override
    public final int getRowCount() {
        return rows == null ? 0 : rows.size();
    }

    @Override
    public final int getColumnCount() {
        return identifiers.size();
    }

    @Override
    public final Object getValueAt(int rowIndex, int columnIndex) {
        R entry = getEntry(rowIndex);
        ColumnIdentifier identifier = getIdentifier(columnIndex);
        if (log.isDebugEnabled()) {
            log.debug("columnIndex: " + columnIndex + " :: " + identifier.getPropertyName());
        }
        return identifier.getValue(entry);
    }

    @Override
    public final void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        if (log.isDebugEnabled()) {
            log.debug("setValueAt " + aValue);
        }
        R entry = getEntry(rowIndex);
        ColumnIdentifier identifier = getIdentifier(columnIndex);
        setValueAt(aValue, rowIndex, columnIndex, identifier, entry);
    }

    @Override
    public final boolean isCellEditable(int rowIndex, int columnIndex) {
        ColumnIdentifier identifier = getIdentifier(columnIndex);
        return isCellEditable(rowIndex, columnIndex, identifier);
    }

    protected void setValueAt(Object aValue,
                              int rowIndex,
                              int columnIndex,
                              ColumnIdentifier propertyName,
                              R entry) {
        if (log.isDebugEnabled()) {
            log.debug("setValueAt " + aValue);
        }
        propertyName.setValue(entry, aValue);
    }

    protected boolean isCellEditable(int rowIndex,
                                     int columnIndex,
                                     ColumnIdentifier propertyName) {
        return !noneEditableCols.contains(propertyName);
    }

    public final void fireTableCellUpdated(int rowIndex,
                                           ColumnIdentifier... identifiers) {
        for (ColumnIdentifier identifier : identifiers) {
            int columnIndex = this.identifiers.indexOf(identifier);
            fireTableCellUpdated(rowIndex, columnIndex);
        }
    }

    public final void fireTableRowUpdatedShell(Set shell) {

        int minRowIndex1 = getColumnCount();
        int maxRowIndex1 = 0;

        for (R r : shell) {
            int rowIndex1 = getRowIndex(r);
            minRowIndex1 = Math.min(minRowIndex1, rowIndex1);
            maxRowIndex1 = Math.max(maxRowIndex1, rowIndex1);
        }
        fireTableRowsUpdated(minRowIndex1, maxRowIndex1);
    }

    protected void collectShell(R row, Set collectedRows) {

        // by default just add the incoming row
        collectedRows.add(row);
    }

    @Override
    public String getColumnName(int columnIndex) {
        return getIdentifier(columnIndex).getPropertyName();
    }

    protected ColumnIdentifier getIdentifier(int columnIndex) {
        return identifiers.get(columnIndex);
    }

    public int getColumnIndex(final String propertyName) {
        return Iterables.indexOf(identifiers, new Predicate>() {
            @Override
            public boolean apply(ColumnIdentifier input) {
                return ObjectUtils.equals(propertyName, input.getPropertyName());
            }
        });
    }

    public Pair getCell(R row, final String propertyName) {

        int rowIndex = getRowIndex(row);
        int columnIndex = getColumnIndex(propertyName);

        return Pair.of(rowIndex, columnIndex);
    }

    public void moveUp(R row) {

        int rowIndex = getRowIndex(row);

        if (log.isInfoEnabled()) {
            log.info("Will move up row of index: " + rowIndex);
        }
        rows.remove(rowIndex);
        rows.add(rowIndex - 1, row);
        fireTableRowsUpdated(rowIndex - 1, rowIndex);

    }

    public void moveDown(R row) {

        int rowIndex = getRowIndex(row);

        if (log.isInfoEnabled()) {
            log.info("Will move down row of index: " + rowIndex);
        }
        rows.remove(rowIndex);
        rows.add(rowIndex + 1, row);
        fireTableRowsUpdated(rowIndex, rowIndex + 1);

    }

    public boolean isFirstRow(R row) {

        int rowIndex = getRowIndex(row);
        return rowIndex == 0;

    }

    public boolean isLastRow(R row) {

        int rowIndex = getRowIndex(row);
        return rowIndex == getRowCount() - 1;

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy