at.spardat.xma.mdl.tree.TreeWM Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
// @(#) $Id: TreeWM.java 10268 2013-01-11 10:34:57Z dschwarz $
package at.spardat.xma.mdl.tree;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import at.spardat.xma.mdl.ModelChangeEvent;
import at.spardat.xma.mdl.NewModelEvent;
import at.spardat.xma.mdl.NewModelEventFactory;
import at.spardat.xma.mdl.Notification;
import at.spardat.xma.mdl.WModel;
import at.spardat.xma.mdl.util.DNode;
import at.spardat.xma.mdl.util.Descriptive;
import at.spardat.xma.mdl.util.TransStringSet;
import at.spardat.xma.mdl.util.TransStringSet1;
import at.spardat.xma.mdl.util.TransStringSetN;
import at.spardat.xma.page.Page;
import at.spardat.xma.serializer.XmaInput;
import at.spardat.xma.serializer.XmaOutput;
import at.spardat.xma.test.TestUtil;
import at.spardat.xma.util.Assert;
/**
* A widget model that holds a tree and its selection status.
*
* @author YSD, 03.05.2003 19:56:56
*/
public class TreeWM extends WModel implements ITreeWM {
/**
* Constructor
*
* @param id id of the widget model within the page
* @param pm the page that this widget model is part of
* @param style bit or combination of style constants beginning with S_
* in this class or a superclass.
*/
public TreeWM (short id, Page pm, int style) {
super (id, pm);
if ((style & S_MULTI_SELECT) != 0) selection_ = new TransStringSetN();
else selection_ = new TransStringSet1();
page_ = pm;
}
/**
* @see at.spardat.xma.mdl.Transactional#changed()
*/
public boolean changed() {
return copy_ != null || selection_.changed();
}
/**
* @see at.spardat.xma.mdl.Transactional#rollback()
*/
public void rollback() {
if (copy_ != null) {
// restore from copy_
roots_ = copy_;
recalcStreamedSize();
recalcNodes();
copy_ = null;
}
// discard changes
changes_ = null;
streamedChangesSize_ = 0;
// rollback selection
selection_.rollback();
// notify listeners
handle (new TreeChangedEvent());
handle (new SelectionChangedEvent());
if (Assert.ON) debugInvariant();
}
/**
* @see at.spardat.xma.mdl.Transactional#commit()
*/
public void commit() {
copy_ = null;
// discard changes
changes_ = null;
streamedChangesSize_ = 0;
// commit selection
selection_.commit();
if (Assert.ON) debugInvariant();
}
/**
* @see at.spardat.xma.mdl.WModel#handle(at.spardat.xma.mdl.ModelChangeEvent)
*/
public boolean handle (ModelChangeEvent event) {
if (Assert.ON) debugInvariant();
if (event instanceof Notification) return true; // would not change this
if (!(event instanceof TreeChangeEvent)) {
// for events that do not modify the tree structurally, we do not need
// the change tracking stuff
boolean success = event.execute();
if (Assert.ON) debugInvariant();
return success;
}
// make a copy of data_ if not copied yet
boolean firstModification = false; // first modification since last syncpoint?
if (copy_ == null) {
ensureSaved();
firstModification = true;
}
// execute the event
boolean success = event.execute();
if (!success && firstModification) {
copy_ = null;
}
if (!success) return false;
// if this has been the first modification, decide if changes should be tracked
if (firstModification) {
if (streamedSize_ > 50) {
// start change tracking if there are at least 50 bytes in the tree (heuristics)
changes_ = new ArrayList();
streamedChangesSize_ = 0;
}
}
// if change tracking is on (changes_ != null), add the change to the list of changes
if (changes_ != null && event instanceof TreeChangeEvent) {
TreeChangeEvent tce = (TreeChangeEvent) event;
changes_.add(event);
streamedChangesSize_ += tce.streamedSize();
// decide if change tracking should be stopped because the cumulated size of
// the changes reaches some fraction of the cumulated size of the table.
if (streamedChangesSize_ > streamedSize_ * MAX_STREAMED_CHANGES_RATIO) {
// drop change list
changes_ = null;
streamedChangesSize_ = 0;
}
}
if (Assert.ON) debugInvariant();
return success;
}
/**
* @see at.spardat.xma.mdl.WModel#clear()
*/
public void clear() {
handle (new ClearEvent(false));
}
/**
* Returns the number of nodes in this tree.
*/
public int size () {
return nodes_.size();
}
/**
* @see at.spardat.xma.mdl.ISelectable#select(java.lang.String)
*/
public void select (String key) {
if (nodes_.containsKey(key)) {
boolean success = selection_.add (key);
handle (new SelectionChangedEvent ());
}
}
/**
* @see at.spardat.xma.mdl.tree.ITreeWM#selectAll()
*/
public void selectAll() {
if (!isMultiSelect()) throw new IllegalStateException();
Iterator iter = nodes_.keySet().iterator();
while (iter.hasNext()) {
String key = (String) iter.next();
selection_.add(key);
}
handle (new SelectionChangedEvent());
}
/**
* @see at.spardat.xma.mdl.ISelectable#deselect(java.lang.String)
*/
public void deselect (String key) {
selection_.remove (key);
handle (new SelectionChangedEvent ());
}
/**
* @see at.spardat.xma.mdl.ISelectable#deselectAll()
*/
public void deselectAll() {
selection_.clear();
handle (new SelectionChangedEvent ());
}
/**
* @see at.spardat.xma.mdl.ISelectable#isMultiSelect()
*/
public boolean isMultiSelect() {
return selection_ instanceof TransStringSetN;
}
/**
* @see at.spardat.xma.mdl.ISelectable#getSelected()
*/
public String getSelected() {
return selection_.getSome();
}
/**
* @see at.spardat.xma.mdl.ISelectable#getSelection()
*/
public String[] getSelection() {
return selection_.getAll();
}
/**
* @see at.spardat.xma.mdl.tree.ITreeWM#getSelectionOrdered()
*/
public String[] getSelectionOrdered() {
String[] result = new String[selection_.size()];
if(result.length==1) {
result[0]=selection_.getSome();
} else if(result.length>1) {
int i=0;
for(Iterator it=roots_.iterator();it.hasNext();) {
i=getSelectionOrdered((TreeNode) it.next(),result,i);
}
}
return result;
}
/**
* Adds all selected nodes of the given subtree to result beginning at index.
* @param node root of the subtree to check
* @param result to add the selected nodes
* @param index current index where to add the next seleted node
* @return the new index incremented by the count of found selected nodes
*/
private int getSelectionOrdered(TreeNode node,String[] result,int index) {
if(selection_.contains(node.key_)) {
result[index++]=node.key_;
}
if(node.childs_!=null) {
for(Iterator it=node.childs_.iterator();it.hasNext();) {
index = getSelectionOrdered((TreeNode)it.next(),result,index);
}
}
return index;
}
/**
* @see at.spardat.xma.mdl.ISelectable#getSelectionCount()
*/
public int getSelectionCount() {
return selection_.size();
}
/**
* @see at.spardat.xma.mdl.ISelectable#isSelected(java.lang.String)
*/
public boolean isSelected(String key) {
return selection_.contains(key);
}
/**
* @see at.spardat.xma.mdl.ISelectable#isStrict()
*/
public boolean isStrict() {
return true;
}
/**
* @see at.spardat.xma.mdl.WModel#randomlyChange()
*/
public void randomlyChange() {
if (Assert.ON) {
debugInvariant();
if (TestUtil.draw(0.05)) {
// clear the table with low probability
clear();
} else if (TestUtil.draw(0.05)) {
// remove a node
if (size() > 0) {
getNode (randomKey()).remove();
}
} else {
int change = TestUtil.randomInt(0, 8);
switch (change) {
case 0:
// select a random entry
if (size() > 0) {
if (!isMultiSelect() || TestUtil.draw(0.8)) select(randomKey());
else selectAll();
}
break;
case 1:
// deselect a random entry
if (size() > 0) deselect (randomKey());
break;
case 2:
// deselect all
deselectAll();
break;
case 3:
// select a key randomly choosen
select (TestUtil.randomString(TestUtil.randomInt(0, 3)));
break;
case 4:
case 5:
case 6:
// randomly add a node
Object parent = this;
if (size() > 0) {
if (TestUtil.draw(0.8)) parent = getNode (randomKey());
}
String key = TestUtil.randomString(3);
if (!containsKey(key)) {
if (TestUtil.draw(0.5)) {
new TreeNode (parent, getChildCount(parent), key, TestUtil.randomString(1, 10), (short)TestUtil.randomInt(0, 3));
} else {
new TreeNode (parent, key, TestUtil.randomString(1, 10), (short)TestUtil.randomInt(0, 3));
}
}
break;
case 7:
// update a node
if (size() > 0) {
TreeNode n = getNode (randomKey());
n.setText(TestUtil.randomString(1, 10));
}
break;
case 8:
// change node color
if (size() > 0) {
TreeNode n = getNode (randomKey());
if (TestUtil.draw(0.7))
n.setForegroundColor(new NodeColor(TestUtil.randomInt(0, 255), TestUtil.randomInt(0, 255), TestUtil.randomInt(0, 255)));
if (TestUtil.draw(0.7))
n.setBackgroundColor(new NodeColor(TestUtil.randomInt(0, 255), TestUtil.randomInt(0, 255), TestUtil.randomInt(0, 255)));
}
break;
}
}
debugInvariant();
}
}
/**
* Returns the number childs the parent has.
*
* @param parent the tree or a tree node
*/
private int getChildCount (Object parent) {
if (parent instanceof TreeNode) return ((TreeNode)parent).getChildCount();
else return roots_.size();
}
// returns a randomly choosen key from this or null, if the tree is empty
// just for testing, O(n)
private String randomKey () {
if (Assert.ON) {
if (nodes_.size() == 0) return null;
int index = TestUtil.randomInt(0, nodes_.size()-1);
Iterator iter = nodes_.keySet().iterator();
for (int i=0; io
private void externalizeTree (XmaOutput o) throws IOException {
// externalize parent nodes first
o.writeShort("numRoots", roots_.size());
for (int i=0, size=roots_.size(); iroots_ is empty.
* Does not update nodes_ or any other instance variable.
*/
private void internalizeTree (XmaInput in) throws IOException, ClassNotFoundException {
short rootCount = in.readShort();
for (int i=0; idead. It may no longer be accessed from outside.
* It also removes all subnodes from nodes_. Furthermore,
* it removes from selection_ any keys of the removed nodes
* if correctSelection is true.
*/
private void removeSubtree (TreeNode n, boolean correctSelection) {
// first, recusively descend
if (n.childs_ != null) {
for (int i=0, size=n.childs_.size(); icopy_,
* this method does a deep copy of the treenodes in roots_
* and stores it in copy_.
*/
private void ensureSaved () {
if (copy_ == null) {
copy_ = new ArrayList();
for (int i=0, size=roots_.size(); istreamedSize_.
*/
private void recalcStreamedSize () {
streamedSize_ = 0;
for (int i=0, size=roots_.size(); in including n itself.
*/
private int streamedSizeOfSubtree (TreeNode n) {
int result = n.streamedSize();
if (n.childs_ != null) {
for (int i=0, size=n.childs_.size(); inodes_, iterates over the tree and inserts
* all tree nodes into nodes_.
*/
private void recalcNodes () {
nodes_.clear();
for (int i=0, size=roots_.size(); in into nodes_.
*/
private void recalcNodesInSubtree (TreeNode n) {
if (n.childs_ != null) {
for (int i=0, size=n.childs_.size(); in
*/
private int nodeCountInSubtree (TreeNode n) {
int ret = 1;
if (n.childs_ != null) {
for (int i=0; iTreeNode objects, keys are Strings (the keys).
* This HashMap holds all nodes in the tree.
*/
HashMap nodes_ = new HashMap();
/**
* The cumulated hypothetical streamed size of all treenodes
*/
private int streamedSize_;
/**
* Contains a deep copy of roots_ in the case that this has been modified.
* This instance variable is null, if this has not been modified.
*/
private ArrayList copy_;
/**
* Keeps track of changes (TreeChangeEvents) applied to this since the last
* synchronization point (construction, commit, rollback). If there has
* been no change yet (copy_ == null), then changes_ also is null.
* If copy_ != null, changes_ may either be null or not. If changes_ == null,
* the change list has been dropped because is has grown to large
* in relation to the tree data. If changes_ != null, changes must be stored in this
* instance variable until the cumulated streamed size of the changes exceeds
* some fraction of the streamed size of the tree. Thereafter it may be dropped.
*/
private ArrayList changes_;
/**
* The cumulated streamed size of all changes in changes_.
*/
private int streamedChangesSize_;
/**
* When the cumulated streamed size of the changes exceeds the cumulated
* streamed size of the tree multiplied with this fraction, the
* change list is dropped because serializing the complete tree
* requires not much more space than serializing the deltas and it's of
* no use to further track deltas (which would consume memory).
*/
private static final double MAX_STREAMED_CHANGES_RATIO = 0.7;
/**
* The page this widget model belongs to
*/
private Page page_;
private static final byte T_CHANGENODE_EVT = 0;
private static final byte T_REMOVENODE_EVT = 1;
private static final byte T_ADDNODE_EVT = 2;
private static final byte T_CLEAR_EVT = 3;
/**
* Factory method for events used when internalizing events from a stream
*
* @param type one of the T_* codes defined above
* @return newly contructed TreeChangeEvent;
*/
private TreeChangeEvent createEvent (byte type) {
switch (type) {
case T_CHANGENODE_EVT: return new ChangeNodeEvent(false);
case T_REMOVENODE_EVT: return new RemoveNodeEvent(false);
case T_ADDNODE_EVT: return new AddNodeEvent(false);
case T_CLEAR_EVT: return new ClearEvent(false);
default: return null;
}
}
/**
* Common base class for all tree change events. When the events are executed,
* they must keep the instance variables nodes_, roots_
* and streamedSize_ up to date. The other instance variables
* of the tree are controlled outside.
*
* @author YSD, 03.05.2003 22:48:42
*/
abstract class TreeChangeEvent extends ModelChangeEvent implements Descriptive {
/**
* Constructor
*/
public TreeChangeEvent (boolean fromUI) {
super (TreeWM.this, fromUI);
}
/**
* Returns a type indicator used in serialization
*/
public abstract byte getType ();
/**
* Returns the number of bytes this event requires when streamed to a byte array
*/
public abstract int streamedSize ();
/**
* Reads the instance variables from an input stream
*/
public abstract void internalize (XmaInput in) throws IOException, ClassNotFoundException;
/**
* Writes the state to an output stream
*/
public abstract void externalize (XmaOutput out) throws IOException;
/**
* @see at.spardat.xma.mdl.util.Descriptive#describe(at.spardat.xma.mdl.util.DNode)
*/
public void describe (DNode n) {
n.appShortClass(this).app(": ");
n.app("streamedSize", streamedSize());
}
}
/**
* Carries the information of a node change and executes it
*
* @author YSD, 03.05.2003 22:30:12
*/
class ChangeNodeEvent extends TreeChangeEvent {
// Constructor used before internalize
public ChangeNodeEvent (boolean fromUI) {
super (fromUI);
}
/**
* Constructor
*/
public ChangeNodeEvent (String key, String text, short imageId, String props, boolean fromUI){
super (fromUI);
key_ = key;
text_ = text;
imageId_ = imageId;
props_ = props;
}
/**
* @see at.spardat.xma.mdl.ModelChangeEvent#execute()
*/
public boolean execute() {
TreeWM tree = TreeWM.this;
TreeNode n = tree.getNode (key_);
if (n == null) return false;
streamedSize_ -= n.streamedSize();
n.text_ = text_;
n.imageId_ = imageId_;
n.props_ = props_;
streamedSize_ += n.streamedSize();
return true;
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#getType()
*/
public byte getType() {
return T_CHANGENODE_EVT;
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#externalize(at.spardat.xma.mdl.XmaOutput)
*/
public void externalize (XmaOutput o) throws IOException {
o.writeString("key", key_);
o.writeString("txt", text_);
o.writeShort("image", imageId_);
o.writeBoolean("jnprops", props_ == null);
if (props_ != null) o.writeString ("props", props_);
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#internalize(at.spardat.xma.mdl.XmaInput, List)
*/
public void internalize (XmaInput i) throws IOException, ClassNotFoundException {
key_ = i.readString();
text_ = i.readString();
imageId_ = i.readShort();
boolean propsIsNull = i.readBoolean();
if (propsIsNull) props_ = null;
else props_ = i.readString();
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#streamedSize()
*/
public int streamedSize() {
return 1 + 4 + key_.length() + text_.length() + 2 + 1 + (props_ == null ? 0 : props_.length());
}
/**
* @see at.spardat.xma.mdl.util.Descriptive#describe(at.spardat.xma.mdl.util.DNode)
*/
public void describe (DNode n) {
super.describe(n); n.comma();
n.app("key", key_).comma();
n.app("text", text_).comma();
n.app("imageId", imageId_).comma();
n.app("props", props_);
}
/**
* Returns the key of the target node
*/
public String getKey () {
return key_;
}
// key, not null
private String key_;
// text, not null
private String text_;
private short imageId_;
// encoded properties; may be null
private String props_;
}
/**
* Carries the information of a node addition and is able to execute the event
*
* @author YSD, 03.05.2003 22:30:12
*/
class AddNodeEvent extends TreeChangeEvent {
// Constructor used before internalize
public AddNodeEvent (boolean fromUI) {
super (fromUI);
}
/**
* Constructor
*
* @param toFill a preconstructed TreeNode which is used and initialized; may be null,
* then a new TreeNode is created.
* @param parentKey is null if the new node is going to be a root
*/
public AddNodeEvent (TreeNode toFill, String key, String parentKey, int index, String text, short imageId, boolean fromUI){
super (fromUI);
key_ = key;
parentKey_ = parentKey;
index_ = index;
text_ = text;
imageId_ = imageId;
toFill_ = toFill;
}
/**
* @see at.spardat.xma.mdl.ModelChangeEvent#execute()
*/
public boolean execute() {
TreeWM tree = TreeWM.this;
TreeNode parentNode = null;
if (parentKey_ != null) parentNode = tree.getNode (parentKey_);
TreeNode newNode = toFill_;
if (newNode == null) newNode = new TreeNode();
newNode.key_ = key_;
newNode.text_ = text_;
newNode.imageId_ = imageId_;
newNode.tree_ = tree;
if (parentKey_ == null) {
// new root
roots_.add(index_, newNode);
newNode.parent_ = tree;
} else {
// new son of parentNode
if (parentNode.childs_ == null) parentNode.childs_ = new ArrayList();
parentNode.childs_.add(index_, newNode);
newNode.parent_ = parentNode;
}
streamedSize_ += newNode.streamedSize();
nodes_.put (newNode.key_, newNode);
return true;
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#getType()
*/
public byte getType() {
return T_ADDNODE_EVT;
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#externalize(at.spardat.xma.mdl.XmaOutput)
*/
public void externalize (XmaOutput o) throws IOException {
o.writeString("key", key_);
o.writeBoolean ("hasParent", parentKey_ == null);
if (parentKey_ != null) o.writeString ("parent", parentKey_);
o.writeInt("index", index_);
o.writeString("text", text_);
o.writeShort("image", imageId_);
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#internalize(at.spardat.xma.mdl.XmaInput, List)
*/
public void internalize (XmaInput i) throws IOException, ClassNotFoundException {
key_ = i.readString();
if (!i.readBoolean()) parentKey_ = i.readString();
index_ = i.readInt();
text_ = i.readString();
imageId_ = i.readShort();
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#streamedSize()
*/
public int streamedSize() {
return 1 + 2 + 1 + (parentKey_ == null ? 0 : parentKey_.length()) +
4 + 2 + text_.length() + 2;
}
/**
* @see at.spardat.xma.mdl.util.Descriptive#describe(at.spardat.xma.mdl.util.DNode)
*/
public void describe (DNode n) {
super.describe(n); n.comma();
n.app("key", key_).comma();
n.app("parentKey", parentKey_).comma();
n.app("index", index_).comma();
n.app("text", text_).comma();
n.app("imageId", imageId_);
}
/**
* Returns the key of the added node
*/
public String getKey () {
return key_;
}
/**
* Returns the index where the new node is inserted in the parents list of childs.
*/
public int getIndex () {
return index_;
}
// key, not null
private String key_;
// key of the parent node or null if new node is root
private String parentKey_;
// the index where to insert the node
private int index_;
// text, not null
private String text_;
private short imageId_;
private TreeNode toFill_;
}
/**
* Carries the information of a node deletion and has the capability to execute it.
* This event not just deletes a given node, it deletes the complete subtree
* that is rooted at the node. It also ajusts the selection.
*
* @author YSD, 03.05.2003 22:30:12
*/
class RemoveNodeEvent extends TreeChangeEvent {
// Constructor used before internalize
public RemoveNodeEvent (boolean fromUI) {
super (fromUI);
}
/**
* Constructor
*
* @param parentKey is null if the new node is going to be a root
*/
public RemoveNodeEvent (String key, boolean fromUI){
super (fromUI);
key_ = key;
}
/**
* @see at.spardat.xma.mdl.ModelChangeEvent#execute()
*/
public boolean execute() {
TreeWM tree = TreeWM.this;
TreeNode parentNode = null;
TreeNode toDelete = tree.getNode(key_);
streamedSize_ -= streamedSizeOfSubtree (toDelete);
if (toDelete.parent_ instanceof TreeNode) parentNode = (TreeNode) toDelete.parent_;
// parentNode is null if toDelete is a root
tree.removeSubtree (toDelete, true);
if (parentNode == null) {
// delete root
tree.roots_.remove(toDelete);
} else {
// delete some inner node
parentNode.childs_.remove(toDelete);
if (parentNode.childs_.size() == 0) parentNode.childs_ = null;
}
// correct selection
selection_.remove(key_);
return true;
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#getType()
*/
public byte getType() {
return T_REMOVENODE_EVT;
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#externalize(at.spardat.xma.mdl.XmaOutput)
*/
public void externalize (XmaOutput o) throws IOException {
o.writeString("key", key_);
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#internalize(at.spardat.xma.mdl.XmaInput, List)
*/
public void internalize (XmaInput i) throws IOException, ClassNotFoundException {
key_ = i.readString ();
}
/**
* @see at.spardat.xma.mdl.tree.TreeWM.TreeChangeEvent#streamedSize()
*/
public int streamedSize() {
return 1 + 2 + key_.length();
}
/**
* @see at.spardat.xma.mdl.util.Descriptive#describe(at.spardat.xma.mdl.util.DNode)
*/
public void describe (DNode n) {
super.describe(n); n.comma();
n.app("key", key_);
}
/**
* Returns the key of the target node
*/
public String getKey () {
return key_;
}
// key, not null
private String key_;
}
/**
* Carries the information of a deletion of the complete tree.
*
* @author YSD, 03.05.2003 22:30:12
*/
class ClearEvent extends TreeChangeEvent {
/**
* Constructor
*/
public ClearEvent (boolean fromUI){
super (fromUI);
}
/**
* @see at.spardat.xma.mdl.ModelChangeEvent#execute()
*/
public boolean execute() {
TreeWM tree = TreeWM.this;
for (int i=0; iS_
*/
public NewTreeWMEvent(int style) {
this.style=style;
}
// see at.spardat.xma.mdl.NewModelEvent.getType()
public byte getType() {
return NewModelEventFactory.TreeWM;
}
// see at.spardat.xma.mdl.NewModelEvent.createModel()
public WModel createModel(short id,Page page) {
return new TreeWM(id,page,style);
}
// see at.spardat.xma.mdl.NewModelEvent.serialize()
public void serialize(XmaOutput out) throws IOException {
super.serialize(out);
out.writeInt("style",style);
}
// see at.spardat.xma.mdl.NewModelEvent.deserialize()
public void deserialize(XmaInput in) throws IOException, ClassNotFoundException {
super.deserialize(in);
style=in.readInt();
}
}
// see at.sparda.xma.mdl.WModel.createNewModelEvent()
public NewModelEvent createNewModelEvent() {
int style = isMultiSelect()?S_MULTI_SELECT:S_NULL;
return new NewTreeWMEvent(style);
}
}