@qooxdoo/framework
Version:
The JS Framework for Coders
456 lines (375 loc) • 12.5 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Sebastian Werner (wpbasti)
* Christian Hagendorn (chris_schmidt)
************************************************************************ */
/**
* This mixin links all methods to manage the multi selection from the
* internal selection manager to the widget.
*/
qx.Mixin.define("qx.ui.core.MMultiSelectionHandling",
{
/*
*****************************************************************************
CONSTRUCTOR
*****************************************************************************
*/
construct : function()
{
// Create selection manager
var clazz = this.SELECTION_MANAGER;
var manager = this.__manager = new clazz(this);
// Add widget event listeners
this.addListener("pointerdown", manager.handlePointerDown, manager);
this.addListener("tap", manager.handleTap, manager);
this.addListener("pointerover", manager.handlePointerOver, manager);
this.addListener("pointermove", manager.handlePointerMove, manager);
this.addListener("losecapture", manager.handleLoseCapture, manager);
this.addListener("keypress", manager.handleKeyPress, manager);
this.addListener("addItem", manager.handleAddItem, manager);
this.addListener("removeItem", manager.handleRemoveItem, manager);
// Add manager listeners
manager.addListener("changeSelection", this._onSelectionChange, this);
},
/*
*****************************************************************************
EVENTS
*****************************************************************************
*/
events :
{
/** Fires after the value was modified */
"changeValue" : "qx.event.type.Data",
/** Fires after the selection was modified */
"changeSelection" : "qx.event.type.Data"
},
/*
*****************************************************************************
PROPERTIES
*****************************************************************************
*/
properties :
{
/**
* The selection mode to use.
*
* For further details please have a look at:
* {@link qx.ui.core.selection.Abstract#mode}
*/
selectionMode :
{
check : [ "single", "multi", "additive", "one" ],
init : "single",
apply : "_applySelectionMode"
},
/**
* Enable drag selection (multi selection of items through
* dragging the pointer in pressed states).
*
* Only possible for the selection modes <code>multi</code> and <code>additive</code>
*/
dragSelection :
{
check : "Boolean",
init : false,
apply : "_applyDragSelection"
},
/**
* Enable quick selection mode, where no tap is needed to change the selection.
*
* Only possible for the modes <code>single</code> and <code>one</code>.
*/
quickSelection :
{
check : "Boolean",
init : false,
apply : "_applyQuickSelection"
}
},
/*
*****************************************************************************
MEMBERS
*****************************************************************************
*/
members :
{
/** @type {qx.ui.core.selection.Abstract} The selection manager */
__manager : null,
/** @type {Boolean} used to control recursion in onSelectionChange */
__inOnSelectionChange: false,
/*
---------------------------------------------------------------------------
USER API
---------------------------------------------------------------------------
*/
/**
* setValue implements part of the {@link qx.ui.form.IField} interface.
*
* @param items {null|qx.ui.core.Widget[]} Items to select.
* @returns {null|TypeError} The status of this operation.
*/
setValue : function(items) {
if (null === items) {
this.__manager.clearSelection();
return null;
}
if (qx.core.Environment.get("qx.debug")) {
for (var i=0, l=items.length; i<l; i++) {
if (!(items[i] instanceof qx.ui.core.Widget)) {
return new TypeError("Some items in provided argument are not widgets");
}
}
}
try {
this.setSelection(items);
return null;
} catch (e) {
return e;
}
},
/**
* getValue implements part of the {@link qx.ui.form.IField} interface.
*
* @returns {qx.ui.core.Widget[]} The selected widgets or null if there are none.
*/
getValue : function() {
return this.__manager.getSelection();
},
/**
* resetValue implements part of the {@link qx.ui.form.IField} interface.
*/
resetValue : function() {
this.__manager.clearSelection();
},
/**
* Selects all items of the managed object.
*/
selectAll : function() {
this.__manager.selectAll();
},
/**
* Detects whether the given item is currently selected.
*
* @param item {qx.ui.core.Widget} Any valid selectable item.
* @return {Boolean} Whether the item is selected.
* @throws {Error} if the item is not a child element.
*/
isSelected : function(item) {
if (!qx.ui.core.Widget.contains(this, item)) {
throw new Error("Could not test if " + item +
" is selected, because it is not a child element!");
}
return this.__manager.isItemSelected(item);
},
/**
* Adds the given item to the existing selection.
*
* Use {@link #setSelection} instead if you want to replace
* the current selection.
*
* @param item {qx.ui.core.Widget} Any valid item.
* @throws {Error} if the item is not a child element.
*/
addToSelection : function(item) {
if (!qx.ui.core.Widget.contains(this, item)) {
throw new Error("Could not add + " + item +
" to selection, because it is not a child element!");
}
this.__manager.addItem(item);
},
/**
* Removes the given item from the selection.
*
* Use {@link #resetSelection} when you want to clear
* the whole selection at once.
*
* @param item {qx.ui.core.Widget} Any valid item
* @throws {Error} if the item is not a child element.
*/
removeFromSelection : function(item) {
if (!qx.ui.core.Widget.contains(this, item)) {
throw new Error("Could not remove " + item +
" from selection, because it is not a child element!");
}
this.__manager.removeItem(item);
},
/**
* Selects an item range between two given items.
*
* @param begin {qx.ui.core.Widget} Item to start with
* @param end {qx.ui.core.Widget} Item to end at
*/
selectRange : function(begin, end) {
this.__manager.selectItemRange(begin, end);
},
/**
* Clears the whole selection at once. Also
* resets the lead and anchor items and their
* styles.
*/
resetSelection : function() {
this.__manager.clearSelection();
},
/**
* Replaces current selection with the given items.
*
* @param items {qx.ui.core.Widget[]} Items to select.
* @throws {Error} if one of the items is not a child element and if
* the mode is set to <code>single</code> or <code>one</code> and
* the items contains more than one item.
*/
setSelection : function(items) {
// Block recursion so that when selection changes modelSelection, the modelSelection
// cannot change selection again; this is important because modelSelection does not
// necessarily match selection, for example when the item's model properties are
// null.
if (this.__inOnSelectionChange) {
return;
}
for (var i = 0; i < items.length; i++) {
if (!qx.ui.core.Widget.contains(this, items[i])) {
throw new Error("Could not select " + items[i] +
", because it is not a child element!");
}
}
if (items.length === 0) {
this.resetSelection();
} else {
var currentSelection = this.getSelection();
if (!qx.lang.Array.equals(currentSelection, items)) {
this.__manager.replaceSelection(items);
}
}
},
/**
* Returns an array of currently selected items.
*
* Note: The result is only a set of selected items, so the order can
* differ from the sequence in which the items were added.
*
* @return {qx.ui.core.Widget[]} List of items.
*/
getSelection : function() {
return this.__manager.getSelection();
},
/**
* Returns an array of currently selected items sorted
* by their index in the container.
*
* @return {qx.ui.core.Widget[]} Sorted list of items
*/
getSortedSelection : function() {
return this.__manager.getSortedSelection();
},
/**
* Whether the selection is empty
*
* @return {Boolean} Whether the selection is empty
*/
isSelectionEmpty : function() {
return this.__manager.isSelectionEmpty();
},
/**
* Returns the last selection context.
*
* @return {String | null} One of <code>tap</code>, <code>quick</code>,
* <code>drag</code> or <code>key</code> or <code>null</code>.
*/
getSelectionContext : function() {
return this.__manager.getSelectionContext();
},
/**
* Returns the internal selection manager. Use this with
* caution!
*
* @return {qx.ui.core.selection.Abstract} The selection manager
*/
_getManager : function() {
return this.__manager;
},
/**
* Returns all elements which are selectable.
*
* @param all {Boolean} true for all selectables, false for the
* selectables the user can interactively select
* @return {qx.ui.core.Widget[]} The contained items.
*/
getSelectables: function(all) {
return this.__manager.getSelectables(all);
},
/**
* Invert the selection. Select the non selected and deselect the selected.
*/
invertSelection: function() {
this.__manager.invertSelection();
},
/**
* Returns the current lead item. Generally the item which was last modified
* by the user (tapped on etc.)
*
* @return {qx.ui.core.Widget} The lead item or <code>null</code>
*/
_getLeadItem : function() {
var mode = this.__manager.getMode();
if (mode === "single" || mode === "one") {
return this.__manager.getSelectedItem();
} else {
return this.__manager.getLeadItem();
}
},
/*
---------------------------------------------------------------------------
PROPERTY APPLY ROUTINES
---------------------------------------------------------------------------
*/
// property apply
_applySelectionMode : function(value, old) {
this.__manager.setMode(value);
},
// property apply
_applyDragSelection : function(value, old) {
this.__manager.setDrag(value);
},
// property apply
_applyQuickSelection : function(value, old) {
this.__manager.setQuick(value);
},
/*
---------------------------------------------------------------------------
EVENT HANDLER
---------------------------------------------------------------------------
*/
/**
* Event listener for <code>changeSelection</code> event on selection manager.
*
* @param e {qx.event.type.Data} Data event
*/
_onSelectionChange : function(e) {
if (this.__inOnSelectionChange) {
return;
}
this.__inOnSelectionChange = true;
try {
this.fireDataEvent("changeSelection", e.getData(), e.getOldData());
this.fireDataEvent("changeValue", e.getData(), e.getOldData());
} finally {
this.__inOnSelectionChange = false;
}
}
},
/*
*****************************************************************************
DESTRUCTOR
*****************************************************************************
*/
destruct : function() {
this._disposeObjects("__manager");
}
});