Backup of current development stage

This commit is contained in:
Andreas Stöckel 2011-02-24 16:10:11 +00:00
parent 398185f525
commit e416c61890
2 changed files with 407 additions and 5 deletions

View File

@ -332,6 +332,22 @@ egwActionLink.prototype.set_actionId = function(_value)
/** egwActionObject Object **/ /** egwActionObject Object **/
//State bitmask (only use powers of two for new states!)
const EGW_AO_STATE_NORMAL = 0x00;
const EGW_AO_STATE_SELECTED = 0x01;
const EGW_AO_STATE_FOCUSED = 0x02;
const EGW_AO_EVENT_DRAG_OVER_ENTER = 0x00;
const EGW_AO_EVENT_DRAG_OVER_LEAVE = 0x01;
const EGW_AO_SHIFT_STATE_NONE = 0x00;
const EGW_AO_SHIFT_STATE_MULTI = 0x01;
const EGW_AO_SHIFT_STATE_LIST = 0x02;
// If this flag is set, this object will not be returned as "focused". If this
// flag is not applied to container objects, it may lead to some strange behaviour.
const EGW_AO_FLAG_IS_CONTAINER = 0x01;
/** /**
* The egwActionObject represents an abstract object to which actions may be * The egwActionObject represents an abstract object to which actions may be
* applied. Communication with the DOM tree is established by using the * applied. Communication with the DOM tree is established by using the
@ -341,17 +357,280 @@ egwActionLink.prototype.set_actionId = function(_value)
* @param string _id is the identifier of the object which * @param string _id is the identifier of the object which
* @param object _parent is the parent object in the hirachy. This may be set to NULL * @param object _parent is the parent object in the hirachy. This may be set to NULL
* @param object _manager is the action manager this object is connected to * @param object _manager is the action manager this object is connected to
* @param object _interaction is the egwActionObjectInterface which connects * @param object _iface is the egwActionObjectInterface which connects
* this object to the DOM tree. * this object to the DOM tree.
* @param boolean _flags a set of additional flags being applied to the object
*/ */
function egwActionObject(_id, _parent, _manager, _interaction) function egwActionObject(_id, _parent, _manager, _iface, _flagss)
{ {
this.id = _id; this.id = _id;
this.parent = _parent; this.parent = _parent;
this.interaction = _interaction;
this.children = []; this.children = [];
this.actionLinks = []; this.actionLinks = [];
this.manager = _manager; this.manager = _manager;
this.selectBehaviour = _selectBehaviour;
this.iface = _iface;
this.iface.setStateChangeCallback(this._ifaceCallback, this)
}
/**
* Searches for the root object in the action object tree and returns it.
*/
egwActionObject.prototype.getRootObject = function()
{
if (this.parent === null)
{
return this;
}
else
{
return this.parent.getRootObject();
}
}
/**
* Returns a list with all parents of this object.
*/
egwActionObject.prototype.getParentList = function()
{
if (this.parent === null)
{
return [];
}
else
{
var list = this.parent.getParentList();
list.unshift(this.parent);
return list;
}
}
/**
* Returns the first parent which has the container flag
*/
egwActionObject.prototype.getContainerRoot = function()
{
if (egwBitIsSet(this.flags, EGW_AO_FLAG_IS_CONTAINER) || this.parent === null)
{
return this;
}
else
{
return this.parent.getContainerRoot();
}
}
/**
* Creates a list which contains all items of the element tree.
*
* @param object _obj is used internally to pass references to the array inside
* the object.
*/
egwActionObject.prototype.flatList = function(_obj)
{
if (typeof(_obj) == "undefined")
{
_obj = {
"elements": [];
}
}
_obj.elements.push(this);
for (var i = 0; i < this.children.length; i++)
{
this.children[i].flatList(_obj);
}
return _obj.elements;
}
/**
* Returns a traversal list with all objects which are in between the given object
* and this one. The operation returns an empty list, if a container object is
* found on the way.
*/
egwActionObject.prototype.traversePath = function(_to)
{
var contRoot = this.getContainerRoot();
if (contRoot)
{
// Get a flat list of all the hncp elements and search for this object
// and the object supplied in the _to parameter.
var flatList = contRoot.flatList();
var thisId = contRoot.indexOf(this);
var toId = contRoot.indexOf(_to);
// Check whether both elements have been found in this part of the tree,
// return the slice of that list.
if (thisId !== -1 && toId !== -1)
{
var from = Math.min(thisId, toId);
var to = Math.max(thisId, toId);
return this.slice(from, to + 1);
}
}
return [];
}
/**
* Returns the index of this object in the children list of the parent object.
*/
egwActionObject.prototype.getIndex = function()
{
if (this.parent === null)
{
return 0;
}
else
{
return this.parent.children.indexOf(this);
}
}
/**
* Returns the deepest object which is currently focused. Objects with the
* "container"-flag will not be returned.
*/
egwActionObject.prototype.getFocusedObject = function()
{
//Search for the focused object in the children
for (var i = 0; i < this.children.length; i++)
{
var obj = this.children[i].getFocused()
if (obj)
{
return obj;
}
}
//One of the child objects hasn't been focused, probably this object is
if (!egwBitIsSet(this.flags, EGW_AO_FLAG_IS_CONTAINER) && this.getFocused())
{
return this;
}
return null;
}
egwActionObject.prototype._ifaceCallback = function(_newState, _shiftState)
{
// Remove the focus from all children on the same level
if (this.parent)
{
var selected = egwBitIsSet(_newState, EGW_AO_STATE_SELECTED);
if (selected)
{
// Search the index of this object
var id = this.parent.children.indexOf(this);
var objs = [];
// Deselect all other objects inside this container, if the "MULTI" shift-
// state is not set
if (!egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_MULTI))
{
var lst = this.getContainerRoot().flatList();
for (var i = 0; i < lst.length; i++)
{
if (lst[i] != this)
{
lst[i].setSelected(false);
}
}
}
// If the LIST state is active, get all objects inbetween this one and the focused one
// and set their select state.
if (egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_LIST))
{
var focused = this.getRootObject().getFocusedObject();
if (focused)
{
objs = this.traversePath(focused);
for (var i = 0; i < objs.length; i++)
{
objs[i].setSelected(true);
}
}
}
// If the focused element didn't belong to this container, or the "list"
// shift-state isn't active, set the focus to this element.
if (objs.length == 0 || !egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_LIST))
{
this.getRootObject().setFocused(false);
this.setFocused(true);
}
}
}
}
egwActionObject.prototype.getSelected = function()
{
return egwBitIsSet(this.getState(), EGW_AO_STATE_SELECTED);
}
egwActionObject.prototype.getFocused = function()
{
}
egwActionObject.prototype.getState = function()
{
}
egwActionObject.prototype.setSelected = function(_selected, _applyToSelf,
_applyToChildren, _applyToParent)
{
if (typeof _applyToSelf == "undefined")
_applyToSelf = true;
if (typeof _applyToChildren == "undefined")
_applyToChildren = true;
if (typeof _applyToParent == "undefined")
_applyToParent = false;
if (_applyToSelf)
{
var state = this.iface.getState();
if (_selected)
{
state &= ~EGW_AO_STATE_SELECTED;
}
else
{
state |= EGW_AO_STATE_SELECTED;
}
this.iface.setState(state, true);
}
if (_applyToChildren)
{
for (var i = 0; i < this.children.length; i++)
{
this.children[i].setFocused(true, true, false);
}
}
if (_applyToParent)
{
for (var i = 0; i < this.children.length; i++)
{
this.children[i].setFocused(true, false, true);
}
}
}
egwActionObject.prototype.setFocused = function(_focused, _applyToSelf,
_applyToChildren, _applyToParent)
{
} }
/** /**
@ -462,8 +741,8 @@ egwActionObject.prototype.getActionImplementationGroups = function(_test, _group
} }
} }
// Recursively add the actions of the children to the result (as _groups is) // Recursively add the actions of the children to the result (as _groups is
// a object, only the reference is passed. // an object, only the reference is passed).
for (var i = 0; i < this.children.length; i++) for (var i = 0; i < this.children.length; i++)
{ {
this.children[i].getActionImplementationGroups(_test, _groups); this.children[i].getActionImplementationGroups(_test, _groups);
@ -472,3 +751,102 @@ egwActionObject.prototype.getActionImplementationGroups = function(_test, _group
return _groups; return _groups;
} }
/** egwActionObjectInterface Interface **/
/**
* The egwActionObjectInterface has to be implemented for each actual object in
* the browser. E.g. for the object "DataGridRow", there has to be an
* egwActionObjectInterface which is responsible for returning the outer DOMNode
* of the object to which JS-Events may be attached by the egwActionImplementation
* object, and to do object specific stuff like highlighting the object in the
* correct way and to route state changes (like: "object has been selected")
* to the egwActionObject object the interface is associated to.
*/
function egwActionObjectInterface()
{
//Preset the interface functions
this.doGetDOMNode = function() {return null};
// _outerCall may be used to determine, whether the state change has been
// evoked from the outside and the stateChangeCallback has to be called
// or not.
this.doSetState = function(_state, _outerCall) {};
this.doTriggerEvent = function(_event) {};
this._state = EGW_AO_STATE_NORMAL;
}
/**
* Sets the callback function which will be called when a user interaction changes
* state of the object.
*/
egwActionObjectInterface.prototype.setStateChangeCallback(_callback, _context)
{
this.stateChangeCallback = _callback;
this.stateChangeContext = _context;
}
/**
* Internal function which should be used whenever the select status of the object
* has been changed by the user. This will automatically calculate the new state of
* the object and call the stateChangeCallback (if it has been set)
*
* @param boolean _selected Whether the object is selected or not.
*/
egwActionObjectInterface.prototype._selectChange(_selected)
{
// Check whether the selected bit has actually changed - the callback may
// perform expensive operations, and we don't want those to happen without
// a reason.
if (egwBitIsSet(this._state, EGW_AO_STATE_SELECTED) != _selected)
{
//Set the EGW_AO_STATE_SELECTED bit accordingly and call the callback
this._state = egwBitSet(this._state, EGW_AO_STATE_SELECTED, _selected);
if (this.stateChangeCallback)
{
this.stateChangeCallback.call(this.stateChangeContext, this._state);
}
}
}
/**
* Returns the DOM-Node the ActionObject is actually a representation of.
* Calls the internal "doGetDOMNode" function, which has to be overwritten
* by implementations of this class.
*/
egwActionObjectInterface.prototype.getDOMNode = function()
{
return this.doGetDOMNode();
}
/**
* Sets the state of the object.
* Calls the internal "doSetState" function, which has to be overwritten
* by implementations of this class. The state-change callback must not be evoked!
*
* @param _state is the state of the object.
*/
egwActionObjectInterface.prototype.setState = function(_state)
{
//Call the doSetState function with the new state (if it has changed at all)
if (_state != this._state)
{
this._state = _state;
this.doSetState(_state, true);
}
}
/**
* Returns the current state of the object. The state is maintained by the
* egwActionObjectInterface and implementations do not have to overwrite this
* function as long as they call the _selectChange function.
*/
egwActionObjectInterface.prototype.getState = function()
{
return this._state;
}

View File

@ -37,3 +37,27 @@ function egwActionStoreJSON(_data, _obj, _setterOnly)
} }
} }
/**
* Switches the given bit in the set on or off.
*
* @param int _set is the current set
* @param int _bit is the position of the bit which should be switched on/off
* @param boolean _state is whether the bit should be switched on or off
* @returns the new set
*/
function egwSetBit(_set, _bit, _state)
{
if (_state)
return _set |= _bit;
else
return _set &= ~_bit;
}
/**
* Returns whether the given bit is set in the set.
*/
function egwBitIsSet(_set, _bit)
{
return (_set & _bit) > 0;
}