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

eu.webtoolkit.jwt.WBatchEditProxyModel Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2009 Emweb bvba, Leuven, Belgium.
 *
 * See the LICENSE file for terms of use.
 */
package eu.webtoolkit.jwt;

import java.util.*;
import java.util.regex.*;
import java.io.*;
import java.lang.ref.*;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.http.*;
import javax.servlet.*;
import eu.webtoolkit.jwt.*;
import eu.webtoolkit.jwt.chart.*;
import eu.webtoolkit.jwt.utils.*;
import eu.webtoolkit.jwt.servlet.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A proxy model for Wt's item models that provides batch editing.
 * 

* * This proxy model presents data from a source model, and caches any editing * operation without affecting the underlying source model, until * {@link WBatchEditProxyModel#commitAll() commitAll()} or * {@link WBatchEditProxyModel#revertAll() revertAll()} is called. In this way, * you can commit all the editing in batch to the underlying source model, only * when the user confirms the changes. *

* All editing operations are supported: *

    *
  • changing data ( * {@link WBatchEditProxyModel#setData(WModelIndex index, Object value, int role) * setData()})
  • *
  • inserting and removing rows ( * {@link WBatchEditProxyModel#insertRows(int row, int count, WModelIndex parent) * insertRows()} and * {@link WBatchEditProxyModel#removeRows(int row, int count, WModelIndex parent) * removeRows()})
  • *
  • inserting and removing columns ( * {@link WBatchEditProxyModel#insertColumns(int column, int count, WModelIndex parent) * insertColumns()} and * {@link WBatchEditProxyModel#removeColumns(int column, int count, WModelIndex parent) * removeColumns()})
  • *
*

* The model supports both simple tabular models, as well as hierarchical * (tree-like / treetable-like) models, with children under items in the first * column. *

* Default values for a newly inserted row can be set using * {@link WBatchEditProxyModel#setNewRowData(int column, Object data, int role) * setNewRowData()} and flags for its items using * {@link WBatchEditProxyModel#setNewRowFlags(int column, EnumSet flags) * setNewRowFlags()}. */ public class WBatchEditProxyModel extends WAbstractProxyModel { private static Logger logger = LoggerFactory .getLogger(WBatchEditProxyModel.class); /** * Constructor. */ public WBatchEditProxyModel(WObject parent) { super(parent); this.submitting_ = false; this.newRowData_ = new HashMap>(); this.newRowFlags_ = new HashMap>(); this.dirtyIndicationRole_ = -1; this.dirtyIndicationData_ = new Object(); this.modelConnections_ = new ArrayList(); this.mappedIndexes_ = new TreeMap(); } /** * Constructor. *

* Calls {@link #WBatchEditProxyModel(WObject parent) this((WObject)null)} */ public WBatchEditProxyModel() { this((WObject) null); } /** * Returns whether changes have not yet been committed. *

* Returns whether have been made to the proxy model, which could be * committed using {@link WBatchEditProxyModel#commitAll() commitAll()} or * reverted using {@link WBatchEditProxyModel#revertAll() revertAll()}. */ public boolean isDirty() { for (Iterator> i_it = this.mappedIndexes_ .entrySet().iterator(); i_it.hasNext();) { Map.Entry i = i_it .next(); WBatchEditProxyModel.Item item = ((i.getValue()) instanceof WBatchEditProxyModel.Item ? (WBatchEditProxyModel.Item) (i .getValue()) : null); if (!item.removedColumns_.isEmpty() || !item.insertedColumns_.isEmpty() || !item.removedRows_.isEmpty() || !item.insertedRows_.isEmpty() || !item.editedValues_.isEmpty()) { return true; } } return false; } /** * Commits changes. *

* This commits all changes to the source model. *

* * @see WBatchEditProxyModel#revertAll() */ public void commitAll() { this.submitting_ = true; for (Iterator> i_it = this.mappedIndexes_ .entrySet().iterator(); i_it.hasNext();) { Map.Entry i = i_it .next(); WBatchEditProxyModel.Item item = ((i.getValue()) instanceof WBatchEditProxyModel.Item ? (WBatchEditProxyModel.Item) (i .getValue()) : null); while (!item.removedColumns_.isEmpty()) { this.getSourceModel().removeColumn(item.removedColumns_.get(0), item.sourceIndex_); } while (!item.insertedColumns_.isEmpty()) { this.getSourceModel().insertColumn( item.insertedColumns_.get(0), item.sourceIndex_); } while (!item.removedRows_.isEmpty()) { this.getSourceModel().removeRow(item.removedRows_.get(0), item.sourceIndex_); } while (!item.insertedRows_.isEmpty()) { this.getSourceModel().insertRow(item.insertedRows_.get(0), item.sourceIndex_); } for (Iterator>> j_it = item.editedValues_ .entrySet().iterator(); j_it.hasNext();) { Map.Entry> j = j_it .next(); WModelIndex index = this.getSourceModel().getIndex( j.getKey().row, j.getKey().column, item.sourceIndex_); SortedMap data = j.getValue(); j_it.remove(); this.getSourceModel().setItemData(index, data); } } this.submitting_ = false; } /** * Reverts changes. *

* This reverts all changes. *

* * @see WBatchEditProxyModel#commitAll() */ public void revertAll() { for (Iterator> i_it = this.mappedIndexes_ .entrySet().iterator(); i_it.hasNext();) { Map.Entry i = i_it .next(); WBatchEditProxyModel.Item item = ((i.getValue()) instanceof WBatchEditProxyModel.Item ? (WBatchEditProxyModel.Item) (i .getValue()) : null); WModelIndex proxyIndex = this.mapFromSource(item.sourceIndex_); while (!item.insertedColumns_.isEmpty()) { this.removeColumn(item.insertedColumns_.get(0), proxyIndex); } while (!item.removedColumns_.isEmpty()) { int column = item.removedColumns_.get(0); this.beginInsertColumns(proxyIndex, column, 1); item.removedColumns_.remove(0); this.shiftColumns(item, column, 1); this.endInsertColumns(); } while (!item.insertedRows_.isEmpty()) { this.removeRow(item.insertedRows_.get(0), proxyIndex); } while (!item.removedRows_.isEmpty()) { int row = item.removedRows_.get(0); this.beginInsertRows(proxyIndex, row, 1); item.removedRows_.remove(0); this.shiftRows(item, row, 1); this.endInsertRows(); } for (Iterator>> j_it = item.editedValues_ .entrySet().iterator(); j_it.hasNext();) { Map.Entry> j = j_it .next(); WBatchEditProxyModel.Cell c = j.getKey(); j_it.remove(); WModelIndex child = this.getIndex(c.row, c.column, proxyIndex); this.dataChanged().trigger(child, child); } } } /** * Sets default data for a newly inserted row. *

* You can use this method to initialize data for a newly inserted row. */ public void setNewRowData(int column, Object data, int role) { this.newRowData_.get(column).put(role, data); } /** * Sets default data for a newly inserted row. *

* Calls {@link #setNewRowData(int column, Object data, int role) * setNewRowData(column, data, ItemDataRole.DisplayRole)} */ public final void setNewRowData(int column, Object data) { setNewRowData(column, data, ItemDataRole.DisplayRole); } /** * Sets the item flags for items in a newly inserted row. *

* By default, {@link WBatchEditProxyModel#getFlags(WModelIndex index) * getFlags()} will return ItemIsSelectable. */ public void setNewRowFlags(int column, EnumSet flags) { this.newRowFlags_.put(column, flags); } /** * Sets the item flags for items in a newly inserted row. *

* Calls {@link #setNewRowFlags(int column, EnumSet flags) * setNewRowFlags(column, EnumSet.of(flag, flags))} */ public final void setNewRowFlags(int column, ItemFlag flag, ItemFlag... flags) { setNewRowFlags(column, EnumSet.of(flag, flags)); } /** * Configures data used to indicate a modified item. *

* This sets data for item data role role to be * returned by * {@link WBatchEditProxyModel#getData(WModelIndex index, int role) * getData()} for an item that is dirty (e.g. because it belongs to a newly * inserted row/column, or because new data has been set for it. *

* When role is {@link ItemDataRole#StyleClassRole}, the style * class is appended to any style already returned by the source model or * set by * {@link WBatchEditProxyModel#setNewRowData(int column, Object data, int role) * setNewRowData()}. *

* By default there is no dirty indication. */ public void setDirtyIndication(int role, Object data) { this.dirtyIndicationRole_ = role; this.dirtyIndicationData_ = data; } public WModelIndex mapFromSource(WModelIndex sourceIndex) { if ((sourceIndex != null)) { if (this.isRemoved(sourceIndex.getParent())) { return null; } WModelIndex sourceParent = sourceIndex.getParent(); WBatchEditProxyModel.Item parentItem = this .itemFromSourceIndex(sourceParent); int row = this.adjustedProxyRow(parentItem, sourceIndex.getRow()); int column = this.adjustedProxyColumn(parentItem, sourceIndex .getColumn()); if (row >= 0 && column >= 0) { return this.createIndex(row, column, parentItem); } else { return null; } } else { return null; } } public WModelIndex mapToSource(WModelIndex proxyIndex) { if ((proxyIndex != null)) { WBatchEditProxyModel.Item parentItem = this .parentItemFromIndex(proxyIndex); int row = this.adjustedSourceRow(parentItem, proxyIndex.getRow()); int column = this.adjustedSourceColumn(parentItem, proxyIndex .getColumn()); if (row >= 0 && column >= 0) { return this.getSourceModel().getIndex(row, column, parentItem.sourceIndex_); } else { return null; } } else { return null; } } public void setSourceModel(WAbstractItemModel model) { if (this.getSourceModel() != null) { for (int i = 0; i < this.modelConnections_.size(); ++i) { this.modelConnections_.get(i).disconnect(); } this.modelConnections_.clear(); } super.setSourceModel(model); this.modelConnections_.add(this.getSourceModel() .columnsAboutToBeInserted().addListener(this, new Signal3.Listener() { public void trigger(WModelIndex e1, Integer e2, Integer e3) { WBatchEditProxyModel.this .sourceColumnsAboutToBeInserted(e1, e2, e3); } })); this.modelConnections_.add(this.getSourceModel().columnsInserted() .addListener(this, new Signal3.Listener() { public void trigger(WModelIndex e1, Integer e2, Integer e3) { WBatchEditProxyModel.this .sourceColumnsInserted(e1, e2, e3); } })); this.modelConnections_.add(this.getSourceModel() .columnsAboutToBeRemoved().addListener(this, new Signal3.Listener() { public void trigger(WModelIndex e1, Integer e2, Integer e3) { WBatchEditProxyModel.this .sourceColumnsAboutToBeRemoved(e1, e2, e3); } })); this.modelConnections_.add(this.getSourceModel().columnsRemoved() .addListener(this, new Signal3.Listener() { public void trigger(WModelIndex e1, Integer e2, Integer e3) { WBatchEditProxyModel.this.sourceColumnsRemoved( e1, e2, e3); } })); this.modelConnections_.add(this.getSourceModel() .rowsAboutToBeInserted().addListener(this, new Signal3.Listener() { public void trigger(WModelIndex e1, Integer e2, Integer e3) { WBatchEditProxyModel.this .sourceRowsAboutToBeInserted(e1, e2, e3); } })); this.modelConnections_.add(this.getSourceModel().rowsInserted() .addListener(this, new Signal3.Listener() { public void trigger(WModelIndex e1, Integer e2, Integer e3) { WBatchEditProxyModel.this.sourceRowsInserted( e1, e2, e3); } })); this.modelConnections_.add(this.getSourceModel().rowsAboutToBeRemoved() .addListener(this, new Signal3.Listener() { public void trigger(WModelIndex e1, Integer e2, Integer e3) { WBatchEditProxyModel.this .sourceRowsAboutToBeRemoved(e1, e2, e3); } })); this.modelConnections_.add(this.getSourceModel().rowsRemoved() .addListener(this, new Signal3.Listener() { public void trigger(WModelIndex e1, Integer e2, Integer e3) { WBatchEditProxyModel.this.sourceRowsRemoved(e1, e2, e3); } })); this.modelConnections_.add(this.getSourceModel().dataChanged() .addListener(this, new Signal2.Listener() { public void trigger(WModelIndex e1, WModelIndex e2) { WBatchEditProxyModel.this.sourceDataChanged(e1, e2); } })); this.modelConnections_.add(this.getSourceModel().headerDataChanged() .addListener(this, new Signal3.Listener() { public void trigger(Orientation e1, Integer e2, Integer e3) { WBatchEditProxyModel.this .sourceHeaderDataChanged(e1, e2, e3); } })); this.modelConnections_.add(this.getSourceModel() .layoutAboutToBeChanged().addListener(this, new Signal.Listener() { public void trigger() { WBatchEditProxyModel.this .sourceLayoutAboutToBeChanged(); } })); this.modelConnections_.add(this.getSourceModel().layoutChanged() .addListener(this, new Signal.Listener() { public void trigger() { WBatchEditProxyModel.this.sourceLayoutChanged(); } })); this.resetMappings(); } public int getColumnCount(WModelIndex parent) { WBatchEditProxyModel.Item item = this.itemFromIndex(parent, false); if (item != null) { if (item.insertedParent_ != null) { return item.insertedColumns_.size(); } else { return this.getSourceModel().getColumnCount(item.sourceIndex_) + item.insertedColumns_.size() - item.removedColumns_.size(); } } else { return this.getSourceModel().getColumnCount( this.mapToSource(parent)); } } public int getRowCount(WModelIndex parent) { WBatchEditProxyModel.Item item = this.itemFromIndex(parent, false); if (item != null) { if (item.insertedParent_ != null) { return item.insertedRows_.size(); } else { return this.getSourceModel().getRowCount(item.sourceIndex_) + item.insertedRows_.size() - item.removedRows_.size(); } } else { return this.getSourceModel().getRowCount(this.mapToSource(parent)); } } public WModelIndex getParent(WModelIndex index) { if ((index != null)) { WBatchEditProxyModel.Item parentItem = this .parentItemFromIndex(index); return this.mapFromSource(parentItem.sourceIndex_); } else { return null; } } public WModelIndex getIndex(int row, int column, WModelIndex parent) { WBatchEditProxyModel.Item item = this.itemFromIndex(parent); return this.createIndex(row, column, item); } public Object getData(WModelIndex index, int role) { WBatchEditProxyModel.Item item = this.itemFromIndex(index.getParent()); SortedMap i = item.editedValues_ .get(new WBatchEditProxyModel.Cell(index.getRow(), index .getColumn())); if (i != null) { Object j = i.get(role); if (j != null) { return this.indicateDirty(role, j); } else { return this.indicateDirty(role, null); } } WModelIndex sourceIndex = this.mapToSource(index); if ((sourceIndex != null)) { return this.getSourceModel().getData(sourceIndex, role); } else { return this.indicateDirty(role, null); } } /** * Sets item data. *

* The default implementation will copy {@link ItemDataRole#EditRole} data * to {@link ItemDataRole#DisplayRole}. You may want to specialize the model * to provide a more specialized editing behaviour. */ public boolean setData(WModelIndex index, Object value, int role) { WBatchEditProxyModel.Item item = this.itemFromIndex(index.getParent()); SortedMap i = item.editedValues_ .get(new WBatchEditProxyModel.Cell(index.getRow(), index .getColumn())); if (i == null) { WModelIndex sourceIndex = this.mapToSource(index); SortedMap dataMap = new TreeMap(); if ((sourceIndex != null)) { dataMap = this.getSourceModel().getItemData(sourceIndex); } dataMap.put(role, value); if (role == ItemDataRole.EditRole) { dataMap.put(ItemDataRole.DisplayRole, value); } item.editedValues_.put(new WBatchEditProxyModel.Cell( index.getRow(), index.getColumn()), dataMap); } else { i.put(role, value); if (role == ItemDataRole.EditRole) { i.put(ItemDataRole.DisplayRole, value); } } this.dataChanged().trigger(index, index); return true; } public EnumSet getFlags(WModelIndex index) { WModelIndex sourceIndex = this.mapToSource(index); if ((sourceIndex != null)) { return this.getSourceModel().getFlags(index); } else { EnumSet i = this.newRowFlags_.get(index.getColumn()); if (i != null) { return i; } else { return super.getFlags(index); } } } public Object getHeaderData(int section, Orientation orientation, int role) { if (orientation == Orientation.Vertical) { return null; } else { return this.getSourceModel().getHeaderData(section, orientation, role); } } public boolean insertRows(int row, int count, WModelIndex parent) { if (this.getColumnCount(parent) == 0) { this.insertColumns(0, 1, parent); } this.beginInsertRows(parent, row, row + count - 1); WBatchEditProxyModel.Item item = this.itemFromIndex(parent); this.shiftRows(item, row, count); this.insertIndexes(item, item.insertedRows_, item.insertedItems_, row, count); for (int i = 0; i < count; ++i) { for (int j = 0; j < this.getColumnCount(parent); ++j) { SortedMap data = new TreeMap(); SortedMap nri = this.newRowData_.get(j); if (nri != null) { data = nri; } item.editedValues_.put( new WBatchEditProxyModel.Cell(row + i, j), data); } } this.endInsertRows(); return true; } public boolean removeRows(int row, int count, WModelIndex parent) { this.beginRemoveRows(parent, row, row + count - 1); WBatchEditProxyModel.Item item = this.itemFromIndex(parent); this.removeIndexes(item, item.insertedRows_, item.removedRows_, item.insertedItems_, row, count); this.shiftRows(item.editedValues_, row, count); this.endRemoveRows(); return true; } public boolean insertColumns(int column, int count, WModelIndex parent) { this.beginInsertColumns(parent, column, column + count - 1); WBatchEditProxyModel.Item item = this.itemFromIndex(parent); this.shiftColumns(item, column, count); this.insertIndexes(item, item.insertedColumns_, (List) null, column, count); this.endInsertColumns(); return true; } public boolean removeColumns(int column, int count, WModelIndex parent) { this.beginRemoveColumns(parent, column, column + count - 1); WBatchEditProxyModel.Item item = this.itemFromIndex(parent); this.removeIndexes(item, item.insertedColumns_, item.removedColumns_, (List) null, column, count); this.shiftColumns(item.editedValues_, column, count); this.endRemoveColumns(); return true; } public void sort(int column, SortOrder order) { this.getSourceModel().sort(column, order); } static class Cell { private static Logger logger = LoggerFactory.getLogger(Cell.class); public int row; public int column; public Cell(int r, int c) { this.row = r; this.column = c; } } static class Item extends WAbstractProxyModel.BaseItem { private static Logger logger = LoggerFactory.getLogger(Item.class); public WBatchEditProxyModel.Item insertedParent_; public Map> editedValues_; public List removedRows_; public List insertedRows_; public List insertedItems_; public List removedColumns_; public List insertedColumns_; public Item(WModelIndex sourceIndex) { super(sourceIndex); this.insertedParent_ = null; this.editedValues_ = new HashMap>(); this.removedRows_ = new ArrayList(); this.insertedRows_ = new ArrayList(); this.insertedItems_ = new ArrayList(); this.removedColumns_ = new ArrayList(); this.insertedColumns_ = new ArrayList(); } public Item(WBatchEditProxyModel.Item insertedParent) { super(null); this.insertedParent_ = insertedParent; this.editedValues_ = new HashMap>(); this.removedRows_ = new ArrayList(); this.insertedRows_ = new ArrayList(); this.insertedItems_ = new ArrayList(); this.removedColumns_ = new ArrayList(); this.insertedColumns_ = new ArrayList(); } } private boolean submitting_; private Map> newRowData_; private Map> newRowFlags_; private int dirtyIndicationRole_; private Object dirtyIndicationData_; private List modelConnections_; private SortedMap mappedIndexes_; private void sourceColumnsAboutToBeInserted(WModelIndex parent, int start, int end) { if (this.isRemoved(parent)) { return; } this.beginInsertColumns(this.mapFromSource(parent), start, end); } private void sourceColumnsInserted(WModelIndex parent, int start, int end) { if (this.isRemoved(parent)) { return; } WModelIndex pparent = this.mapFromSource(parent); WBatchEditProxyModel.Item item = this.itemFromIndex(pparent); int count = end - start + 1; for (int i = 0; i < count; ++i) { int proxyColumn = this.adjustedProxyColumn(item, start + i); if (proxyColumn >= 0) { if (!this.submitting_) { this.beginInsertColumns(pparent, proxyColumn, proxyColumn); this.shiftColumns(item, proxyColumn, 1); this.endInsertColumns(); } else { int index = item.insertedColumns_.indexOf(proxyColumn); assert index != -1; item.insertedColumns_.remove(0 + index); } } else { assert !this.submitting_; int remi = -proxyColumn - 1; proxyColumn = item.removedColumns_.get(remi); this.beginInsertColumns(pparent, proxyColumn, proxyColumn); this.shiftColumns(item, proxyColumn, 1); this.endInsertColumns(); } } } private void sourceColumnsAboutToBeRemoved(WModelIndex parent, int start, int end) { if (this.isRemoved(parent)) { return; } WModelIndex pparent = this.mapFromSource(parent); WBatchEditProxyModel.Item item = this.itemFromIndex(pparent); int count = end - start + 1; for (int i = 0; i < count; ++i) { int proxyColumn = this.adjustedProxyColumn(item, start); if (proxyColumn >= 0) { this.beginRemoveColumns(pparent, proxyColumn, proxyColumn); this.shiftColumns(item, proxyColumn, -1); this.endRemoveColumns(); } else { int remi = -proxyColumn - 1; item.removedColumns_.remove(0 + remi); } } } private void sourceColumnsRemoved(WModelIndex parent, int start, int end) { if (this.isRemoved(parent)) { return; } this.endRemoveColumns(); } private void sourceRowsAboutToBeInserted(WModelIndex parent, int start, int end) { } private void sourceRowsInserted(WModelIndex parent, int start, int end) { if (this.isRemoved(parent)) { return; } WModelIndex pparent = this.mapFromSource(parent); WBatchEditProxyModel.Item item = this.itemFromIndex(pparent); int count = end - start + 1; for (int i = 0; i < count; ++i) { int proxyRow = this.adjustedProxyRow(item, start + i); if (proxyRow >= 0) { if (!this.submitting_) { this.beginInsertRows(pparent, proxyRow, proxyRow); this.shiftRows(item, proxyRow, 1); this.endInsertRows(); } else { int index = item.insertedRows_.indexOf(proxyRow); assert index != -1; WBatchEditProxyModel.Item child = item.insertedItems_ .get(index); if (child != null) { child.sourceIndex_ = this.getSourceModel().getIndex( start + i, 0, parent); child.insertedParent_ = null; this.mappedIndexes_.put(child.sourceIndex_, child); } item.insertedItems_.remove(0 + index); item.insertedRows_.remove(0 + index); } } else { assert !this.submitting_; int remi = -proxyRow - 1; proxyRow = item.removedRows_.get(remi); this.beginInsertRows(pparent, proxyRow, proxyRow); this.shiftRows(item, proxyRow, 1); this.endInsertRows(); } } this.shiftModelIndexes(parent, start, end - start + 1, this.mappedIndexes_); } private void sourceRowsAboutToBeRemoved(WModelIndex parent, int start, int end) { if (this.isRemoved(parent)) { return; } WModelIndex pparent = this.mapFromSource(parent); WBatchEditProxyModel.Item item = this.itemFromIndex(pparent); int count = end - start + 1; for (int i = 0; i < count; ++i) { int proxyRow = this.adjustedProxyRow(item, start); if (proxyRow >= 0) { this.beginRemoveRows(pparent, proxyRow, proxyRow); this.deleteItemsUnder(item, proxyRow); this.shiftRows(item, proxyRow, -1); this.endRemoveRows(); } else { int remi = -proxyRow - 1; item.removedRows_.remove(0 + remi); } } } private void sourceRowsRemoved(WModelIndex parent, int start, int end) { if (this.isRemoved(parent)) { return; } this.shiftModelIndexes(parent, start, -(end - start + 1), this.mappedIndexes_); } private void sourceDataChanged(WModelIndex topLeft, WModelIndex bottomRight) { if (this.isRemoved(topLeft.getParent())) { return; } WModelIndex parent = this.mapFromSource(topLeft.getParent()); for (int row = topLeft.getRow(); row <= bottomRight.getRow(); ++row) { for (int col = topLeft.getColumn(); col <= bottomRight.getColumn(); ++col) { WModelIndex l = this.getSourceModel().getIndex(row, col, topLeft.getParent()); if (!this.isRemoved(l)) { this.dataChanged().trigger(this.mapFromSource(l), this.mapFromSource(l)); } } } } private void sourceHeaderDataChanged(Orientation orientation, int start, int end) { if (orientation == Orientation.Vertical) { WBatchEditProxyModel.Item item = this.itemFromIndex(null); for (int row = start; row <= end; ++row) { int proxyRow = this.adjustedProxyRow(item, row); if (proxyRow != -1) { this.headerDataChanged().trigger(orientation, proxyRow, proxyRow); } } } else { this.headerDataChanged().trigger(orientation, start, end); } } private void sourceLayoutAboutToBeChanged() { this.layoutAboutToBeChanged().trigger(); this.resetMappings(); } private void sourceLayoutChanged() { this.layoutChanged().trigger(); } private WBatchEditProxyModel.Item itemFromSourceIndex( WModelIndex sourceParent, boolean autoCreate) { if (this.isRemoved(sourceParent)) { return null; } WAbstractProxyModel.BaseItem i = this.mappedIndexes_.get(sourceParent); if (i == null) { if (autoCreate) { WBatchEditProxyModel.Item result = new WBatchEditProxyModel.Item( sourceParent); this.mappedIndexes_.put(sourceParent, result); return result; } else { return null; } } else { return ((i) instanceof WBatchEditProxyModel.Item ? (WBatchEditProxyModel.Item) (i) : null); } } private final WBatchEditProxyModel.Item itemFromSourceIndex( WModelIndex sourceParent) { return itemFromSourceIndex(sourceParent, true); } private WBatchEditProxyModel.Item itemFromInsertedRow( WBatchEditProxyModel.Item parentItem, WModelIndex index, boolean autoCreate) { int i = parentItem.insertedRows_.indexOf(index.getRow()); if (!(parentItem.insertedItems_.get(i) != null) && autoCreate) { WBatchEditProxyModel.Item item = new WBatchEditProxyModel.Item( parentItem); parentItem.insertedItems_.set(i, item); } return parentItem.insertedItems_.get(i); } private final WBatchEditProxyModel.Item itemFromInsertedRow( WBatchEditProxyModel.Item parentItem, WModelIndex index) { return itemFromInsertedRow(parentItem, index, true); } private WBatchEditProxyModel.Item parentItemFromIndex(WModelIndex index) { return (WBatchEditProxyModel.Item) index.getInternalPointer(); } private WBatchEditProxyModel.Item itemFromIndex(WModelIndex index, boolean autoCreate) { if ((index != null)) { WBatchEditProxyModel.Item parentItem = this .parentItemFromIndex(index); int row = this.adjustedSourceRow(parentItem, index.getRow()); int column = this.adjustedSourceColumn(parentItem, index .getColumn()); if (row >= 0 && column >= 0) { WModelIndex sourceIndex = this.getSourceModel().getIndex(row, column, parentItem.sourceIndex_); return this.itemFromSourceIndex(sourceIndex, autoCreate); } else { if (index.getColumn() == 0) { return this.itemFromInsertedRow(parentItem, index, autoCreate); } else { if (autoCreate) { throw new WException( "WBatchEditProxyModel does not support children in column > 0"); } else { return null; } } } } else { return this.itemFromSourceIndex(null, autoCreate); } } private final WBatchEditProxyModel.Item itemFromIndex(WModelIndex index) { return itemFromIndex(index, true); } private boolean isRemoved(WModelIndex sourceIndex) { if (!(sourceIndex != null)) { return false; } WModelIndex sourceParent = sourceIndex.getParent(); if (this.isRemoved(sourceParent)) { return true; } else { WBatchEditProxyModel.Item parentItem = this .itemFromSourceIndex(sourceParent); int row = this.adjustedProxyRow(parentItem, sourceIndex.getRow()); if (row < 0) { return true; } int column = this.adjustedProxyColumn(parentItem, sourceIndex .getColumn()); return column < 0; } } private int adjustedProxyRow(WBatchEditProxyModel.Item item, int sourceRow) { return this.adjustedProxyIndex(sourceRow, item.insertedRows_, item.removedRows_); } private int adjustedSourceRow(WBatchEditProxyModel.Item item, int proxyRow) { return this.adjustedSourceIndex(proxyRow, item.insertedRows_, item.removedRows_); } private int adjustedProxyColumn(WBatchEditProxyModel.Item item, int sourceColumn) { return this.adjustedProxyIndex(sourceColumn, item.insertedColumns_, item.removedColumns_); } private int adjustedSourceColumn(WBatchEditProxyModel.Item item, int proxyColumn) { return this.adjustedSourceIndex(proxyColumn, item.insertedColumns_, item.removedColumns_); } private int adjustedProxyIndex(int sourceIndex, List ins, List rem) { if (ins.isEmpty() && rem.isEmpty()) { return sourceIndex; } int insi = 0; int remi = 0; int proxyIndex = -1; for (int si = 0; si <= sourceIndex; ++si) { ++proxyIndex; while (remi < (int) rem.size() && rem.get(remi) == proxyIndex) { if (si == sourceIndex) { return -1 - remi; } ++remi; ++si; } if (this.submitting_ && si == sourceIndex) { return proxyIndex; } while (insi < (int) ins.size() && ins.get(insi) == proxyIndex) { ++insi; ++proxyIndex; } } return proxyIndex; } private int adjustedSourceIndex(int proxyIndex, List ins, List rem) { int inserted = CollectionUtils.lowerBound(ins, proxyIndex); if (inserted < ins.size() && ins.get(inserted) == proxyIndex) { return -1; } int removed = CollectionUtils.upperBound(rem, proxyIndex); return proxyIndex + removed - inserted; } private void insertIndexes(WBatchEditProxyModel.Item item, List ins, List rowItems, int index, int count) { int insertIndex = CollectionUtils.lowerBound(ins, index); for (int i = 0; i < count; ++i) { ins.add(0 + insertIndex + i, index + i); if (rowItems != null) { rowItems.add(0 + insertIndex + i, (WBatchEditProxyModel.Item) null); } } } private void removeIndexes(WBatchEditProxyModel.Item item, List ins, List rem, List rowItems, int index, int count) { for (int i = 0; i < count; ++i) { int insi = CollectionUtils.lowerBound(ins, index); if (insi != ins.size() && ins.get(insi) == index) { ins.remove(0 + insi); if (rowItems != null) { ; rowItems.remove(0 + insi); } } else { if (rowItems != null) { this.deleteItemsUnder(item, index); } rem.add(0 + CollectionUtils.lowerBound(rem, index), index); } this.shift(ins, index, -1); this.shift(rem, index + 1, -1); } } private void deleteItemsUnder(WBatchEditProxyModel.Item item, int row) { WModelIndex sourceIndex = this.getSourceModel().getIndex(row, 0, item.sourceIndex_); for (Iterator> i_it = this.mappedIndexes_ .tailMap(sourceIndex).entrySet().iterator(); i_it.hasNext();) { Map.Entry i = i_it .next(); if (isAncestor(sourceIndex, i.getKey())) { ; i_it.remove(); } else { break; } } } private void shift(List v, int index, int count) { int first = CollectionUtils.lowerBound(v, index); for (int i = first; i < v.size(); ++i) { v.set(i, v.get(i) + count); } } private void shiftRows( Map> v, int row, int count) { for (Iterator>> i_it = v .entrySet().iterator(); i_it.hasNext();) { Map.Entry> i = i_it .next(); if (i.getKey().row >= row) { WBatchEditProxyModel.Cell c = i.getKey(); if (count < 0) { if (c.row >= row - count) { c.row += count; } else { i_it.remove(); } } else { c.row += count; } } else { break; } } } private void shiftRows(WBatchEditProxyModel.Item item, int row, int count) { this.shift(item.insertedRows_, row, count); this.shift(item.removedRows_, row, count); this.shiftRows(item.editedValues_, row, count); } private void shiftColumns( Map> v, int column, int count) { for (Iterator>> i_it = v .entrySet().iterator(); i_it.hasNext();) { Map.Entry> i = i_it .next(); if (i.getKey().column >= column) { WBatchEditProxyModel.Cell c = i.getKey(); if (count < 0) { if (c.column >= column - count) { c.column += count; } else { i_it.remove(); } } else { c.column += count; } } else { } } } private void shiftColumns(WBatchEditProxyModel.Item item, int column, int count) { this.shift(item.insertedColumns_, column, count); this.shift(item.removedColumns_, column, count); this.shiftColumns(item.editedValues_, column, count); } private void resetMappings() { for (Iterator> i_it = this.mappedIndexes_ .entrySet().iterator(); i_it.hasNext();) { Map.Entry i = i_it .next(); ; } this.mappedIndexes_.clear(); } private Object indicateDirty(int role, Object value) { if (role == this.dirtyIndicationRole_) { if (role == ItemDataRole.StyleClassRole) { WString s1 = StringUtils.asString(value); WString s2 = StringUtils.asString(this.dirtyIndicationData_); if (!(s1.length() == 0)) { s1.append(" "); } s1.append(s2); return s1; } else { return this.dirtyIndicationData_; } } else { return value; } } static boolean isAncestor(WModelIndex i1, WModelIndex i2) { if (!(i1 != null)) { return false; } for (WModelIndex p = i1; (p != null); p = p.getParent()) { if ((p == i2 || (p != null && p.equals(i2)))) { return true; } } return !(i2 != null); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy