Dynamic View Services > Specifying Dynamic View Types > Collectors > Editing a Collector
 
Editing a Collector
Two types of editing operations can be performed on a collector:
*Adding or removing an existing representation object to or from a collector
*Creating a new representation object attached to a collector
Adding or Removing a Representation Object
Adding or removing a representation object from a collector means
calling one of the functions IlsRpObject::onAddToCollection or IlsRpObject::onRmFromCollection.
These functions apply to the representation object to be added or removed and take the owner and the identifier of the collector attribute as parameters.
Suppose that you want to transfer an employee from department1 to department2, and that dragging and dropping a row from one table to another triggers the callback function TableR::onRowDragDrop on the destination table with the moved row as the argument.
This callback could be implemented as follows:
void TableR::onRowDragDrop(RowR& movedRow)
{
movedRow.addToCollection(*this,getAttributeId("rows"));
}
On the server side, this implies adding the employee represented by movedRow to the employees relation of the destination department. Because this relation is an ownership relation, the employee is first cut from its previous owner. This is why it is not necessary to call the function onRmFromCollection in the function onRowDragDrop.
Note that the row should not be dragged and dropped to the new table directly by the component. It is the server’s task to:
*acknowledge the modification induced on its objects,
*notify the deletion of the employee row in the table department1,
*add a new row associated with the moved employee to the table department2.
Creating a New Representation Object
Collectors are also used to have new representation objects created directly by a component. If, for instance, you want to add a new employee to a department, the component directly constructs a new row in the table.This row constructor must call a specific constructor of the class IlsRpObject, as follows:
RowR::RowR(TableR& table)
: IlsRpObject(table,table.getAttributeId("rows"))
{}
On the server side, a new employee is created through a call to the default constructor of the class Employee and this object is added to the relation employees of the department represented by the table object. The new department is empty. Once it is created, the value of the attributes that are editable in the row representation object should be notified to the server. The code sample below shows how the callback function TableR::onNewRow, which should be called when a new row is created in the matrix gadget, can be implemented:
void TableR::onNewRow(int newRowIndex)
{
RowR* row=new RowR(*this);
 
   row->onUpdate(r->getAttributeId("column",1),
 _gadget->getCellString(newRowIndex,0));
   row->onUpdate(r->getAttributeId("column",2),
_gadget->getCellInt(newRowIndex,1));
}
By default, this operation is carried out via three separate requests sent by the component to the server. These three requests trigger three transactions in the server.
To build the full object in the same transaction on the server side, you must first modify the RowR constructor as follows:
RowR::RowR(TableR& table)
: IlsRpObject(table,table.getAttributeId("rows"),0,IlsFalse)
{}
The value IlsFalse passed as the last argument of the constructor of IlsRpObject indicates that some updates are going to be performed on the new object. It prevents an immediate notification of the object creation to the server. Then, you must indicate at which moment the updates on the object are completed. This is done by adding a call to the function IlsRpObject::endC2SUpdate to the function onNewRow after all the relevant attributes have been assigned a value, as shown on the next page:
void TableR::onNewRow(int newRowIndex)
{
RowR* row;
IlsRepresentation* repres=getRepresentation();
assert(repres);
row=new RowR(*this);
row->onUpdate(row->getAttributeId("column",1),
_gadget->getCellString(newRowIndex,0));
row->onUpdate(row->getAttributeId("column",2),
_gadget->getCellInt(newRowIndex,1));
row->endC2SUpdate();
}
Note that the implementation of the function onNewRow strongly relies on the fact that there are two editable columns —the first one of type string, the second one of type integer— in the specification of the row representation associated with Employee.
A more common implementation, independent of the representation specification, is:
void TableR::onNewRow(int newRowIndex)
{
RowR* row;
IlsRepresentation* repres=getRepresentation();
IlsRpAttributeId attrId;
int i=1;
 
row=new RowR(*this);
while (attrId=row->getAttributeId("column",i) >= 0){
if (row->isEditable(attrId)){
        IlsMvDataType::Kind attrKind;
 
        attrKind=row->getAttributeType(attrId).getKind();
        switch (attrKind){
        case IlsMvDataType::MV_LONG:
         row->onUpdate(attrId,
                        _gadget->getCellInt(newRowIndex,i-1));
          break;
        case IlsMvDataType::MV_STRING:
         row->onUpdate(attrId,
                        _ gadget->getCellString(newRowIndex,i-1));
          break;
        }
     }
}
row->endC2SUpdate();
}

Version 6.1
Copyright © 2016, Rogue Wave Software, Inc. All Rights Reserved.