ccgui
Version:
351 lines (318 loc) • 16 kB
JavaScript
/**
*
* Copyright (c) 2010-2012 cocos2d-x.org
* Copyright 2011 Yannick Loriot.
* http://yannickloriot.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*
* converted to Javascript / cocos2d-x by Angus C
*/
/** Number of kinds of control event. */
cc.CONTROL_EVENT_TOTAL_NUMBER = 9;
/** Kinds of possible events for the control objects. */
cc.CONTROL_EVENT_TOUCH_DOWN = 1 << 0; // A touch-down event in the control.
cc.CONTROL_EVENT_TOUCH_DRAG_INSIDE = 1 << 1; // An event where a finger is dragged inside the bounds of the control.
cc.CONTROL_EVENT_TOUCH_DRAG_OUTSIDE = 1 << 2; // An event where a finger is dragged just outside the bounds of the control.
cc.CONTROL_EVENT_TOUCH_DRAG_ENTER = 1 << 3; // An event where a finger is dragged into the bounds of the control.
cc.CONTROL_EVENT_TOUCH_DRAG_EXIT = 1 << 4; // An event where a finger is dragged from within a control to outside its bounds.
cc.CONTROL_EVENT_TOUCH_UP_INSIDE = 1 << 5; // A touch-up event in the control where the finger is inside the bounds of the control.
cc.CONTROL_EVENT_TOUCH_UP_OUTSIDE = 1 << 6; // A touch-up event in the control where the finger is outside the bounds of the control.
cc.CONTROL_EVENT_TOUCH_CANCEL = 1 << 7; // A system event canceling the current touches for the control.
cc.CONTROL_EVENT_VALUECHANGED = 1 << 8; // A touch dragging or otherwise manipulating a control; causing it to emit a series of different values.
/** The possible state for a control. */
cc.CONTROL_STATE_NORMAL = 1 << 0; // The normal; or default state of a control梩hat is; enabled but neither selected nor highlighted.
cc.CONTROL_STATE_HIGHLIGHTED = 1 << 1; // Highlighted state of a control. A control enters this state when a touch down; drag inside or drag enter is performed. You can retrieve and set this value through the highlighted property.
cc.CONTROL_STATE_DISABLED = 1 << 2; // Disabled state of a control. This state indicates that the control is currently disabled. You can retrieve and set this value through the enabled property.
cc.CONTROL_STATE_SELECTED = 1 << 3; // Selected state of a control. This state indicates that the control is currently selected. You can retrieve and set this value through the selected property.
cc.CONTROL_STATE_INITIAL = 1 << 3;
/**
* CCControl is inspired by the UIControl API class from the UIKit library of
* CocoaTouch. It provides a base class for control CCSprites such as CCButton
* or CCSlider that convey user intent to the application.
* The goal of CCControl is to define an interface and base implementation for
* preparing action messages and initially dispatching them to their targets when
* certain events occur.
* To use the CCControl you have to subclass it.
* @class
* @extends cc.LayerRGBA
*/
cc.Control = cc.LayerRGBA.extend({
_isOpacityModifyRGB:false,
_hasVisibleParents:false,
isOpacityModifyRGB:function () {
return this._isOpacityModifyRGB;
},
setOpacityModifyRGB:function (opacityModifyRGB) {
this._isOpacityModifyRGB = opacityModifyRGB;
var children = this.getChildren();
for (var i = 0, len = children.length; i < len; i++) {
var selNode = children[i];
if (selNode && selNode.RGBAProtocol)
selNode.setOpacityModifyRGB(opacityModifyRGB);
}
},
/** The current control state constant. */
_state:cc.CONTROL_STATE_NORMAL,
getState:function () {
return this._state;
},
_enabled:false,
_selected:false,
_highlighted:false,
_dispatchTable:null,
/**
* Tells whether the control is enabled
* @param {Boolean} enabled
*/
setEnabled:function (enabled) {
this._enabled = enabled;
this._state = enabled ? cc.CONTROL_STATE_NORMAL:cc.CONTROL_STATE_DISABLED;
this.needsLayout();
},
isEnabled:function () {
return this._enabled;
},
/**
* A Boolean value that determines the control selected state.
* @param {Boolean} selected
*/
setSelected:function (selected) {
this._selected = selected;
this.needsLayout();
},
isSelected:function () {
return this._selected;
},
/**
* A Boolean value that determines whether the control is highlighted.
* @param {Boolean} highlighted
*/
setHighlighted:function (highlighted) {
this._highlighted = highlighted;
this.needsLayout();
},
isHighlighted:function () {
return this._highlighted;
},
hasVisibleParents:function () {
var parent = this.getParent();
for (var c = parent; c != null; c = c.getParent()) {
if (!c.isVisible())
return false;
}
return true;
},
ctor:function () {
cc.LayerRGBA.prototype.ctor.call(this);
this._dispatchTable = {};
this._color = cc.white();
},
init:function () {
if (cc.LayerRGBA.prototype.init.call(this)) {
//this.setTouchEnabled(true);
//m_bIsTouchEnabled=true;
// Initialise instance variables
this._state = cc.CONTROL_STATE_NORMAL;
this._enabled = true;
this._selected = false;
this._highlighted = false;
// Set the touch dispatcher priority by default to 1
this._defaultTouchPriority = 1;
this.setTouchPriority(1);
// Initialise the tables
//this._dispatchTable = {};
//dispatchTable.autorelease();
// dispatchTable_ = [[NSMutableDictionary alloc] initWithCapacity:1];
return true;
} else
return false;
},
registerWithTouchDispatcher:function () {
cc.registerTargetedDelegate(this.getTouchPriority(), true, this);
},
/**
* Sends action messages for the given control events.
* which action messages are sent. See "CCControlEvent" for bitmask constants.
* @param {Number} controlEvents A bitmask whose set flags specify the control events for
*/
sendActionsForControlEvents:function (controlEvents) {
// For each control events
for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) {
// If the given controlEvents bitmask contains the curent event
if ((controlEvents & (1 << i))) {
// Call invocations
// <CCInvocation*>
var invocationList = this._dispatchListforControlEvent(1 << i);
for (var j = 0, inLen = invocationList.length; j < inLen; j++) {
invocationList[j].invoke(this);
}
}
}
},
/**
* <p>
* Adds a target and action for a particular event (or events) to an internal <br/>
* dispatch table. <br/>
* The action message may optionally include the sender and the event as <br/>
* parameters, in that order. <br/>
* When you call this method, target is not retained.
* </p>
* @param {Object} target The target object that is, the object to which the action message is sent. It cannot be nil. The target is not retained.
* @param {function} action A selector identifying an action message. It cannot be NULL.
* @param {Number} controlEvents A bitmask specifying the control events for which the action message is sent. See "CCControlEvent" for bitmask constants.
*/
addTargetWithActionForControlEvents:function (target, action, controlEvents) {
// For each control events
for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) {
// If the given controlEvents bit mask contains the current event
if ((controlEvents & (1 << i)))
this._addTargetWithActionForControlEvent(target, action, 1 << i);
}
},
/**
* Removes a target and action for a particular event (or events) from an internal dispatch table.
*
* @param {Object} target The target object that is, the object to which the action message is sent. Pass nil to remove all targets paired with action and the specified control events.
* @param {function} action A selector identifying an action message. Pass NULL to remove all action messages paired with target.
* @param {Number} controlEvents A bitmask specifying the control events associated with target and action. See "CCControlEvent" for bitmask constants.
*/
removeTargetWithActionForControlEvents:function (target, action, controlEvents) {
// For each control events
for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) {
// If the given controlEvents bitmask contains the current event
if ((controlEvents & (1 << i)))
this._removeTargetWithActionForControlEvent(target, action, 1 << i);
}
},
/**
* Returns a point corresponding to the touh location converted into the
* control space coordinates.
* @param {cc.Touch} touch A CCTouch object that represents a touch.
*/
getTouchLocation:function (touch) {
var touchLocation = touch.getLocation(); // Get the touch position
return this.convertToNodeSpace(touchLocation); // Convert to the node space of this class
},
/**
* Returns a boolean value that indicates whether a touch is inside the bounds of the receiver. The given touch must be relative to the world.
*
* @param {cc.Touch} touch A cc.Touch object that represents a touch.
* @return {Boolean} YES whether a touch is inside the receiver's rect.
*/
isTouchInside:function (touch) {
var touchLocation = touch.getLocation(); // Get the touch position
touchLocation = this.getParent().convertToNodeSpace(touchLocation);
return cc.rectContainsPoint(this.getBoundingBox(), touchLocation);
},
/**
* <p>
* Returns an cc.Invocation object able to construct messages using a given <br/>
* target-action pair. (The invocation may optionally include the sender and <br/>
* the event as parameters, in that order)
* </p>
* @param {Object} target The target object.
* @param {function} action A selector identifying an action message.
* @param {Number} controlEvent A control events for which the action message is sent. See "CCControlEvent" for constants.
*
* @return {cc.Invocation} an CCInvocation object able to construct messages using a given target-action pair.
*/
_invocationWithTargetAndActionForControlEvent:function (target, action, controlEvent) {
return null;
},
/**
* Returns the cc.Invocation list for the given control event. If the list does not exist, it'll create an empty array before returning it.
*
* @param {Number} controlEvent A control events for which the action message is sent. See "CCControlEvent" for constants.
* @return {cc.Invocation} the cc.Invocation list for the given control event.
*/
_dispatchListforControlEvent:function (controlEvent) {
controlEvent = controlEvent.toString();
// If the invocation list does not exist for the dispatch table, we create it
if (!this._dispatchTable.hasOwnProperty(controlEvent))
this._dispatchTable[controlEvent] = [];
return this._dispatchTable[controlEvent];
},
/**
* Adds a target and action for a particular event to an internal dispatch
* table.
* The action message may optionally include the sender and the event as
* parameters, in that order.
* When you call this method, target is not retained.
*
* @param target The target object that is, the object to which the action
* message is sent. It cannot be nil. The target is not retained.
* @param action A selector identifying an action message. It cannot be NULL.
* @param controlEvent A control event for which the action message is sent.
* See "CCControlEvent" for constants.
*/
_addTargetWithActionForControlEvent:function (target, action, controlEvent) {
// Create the invocation object
var invocation = new cc.Invocation(target, action, controlEvent);
// Add the invocation into the dispatch list for the given control event
var eventInvocationList = this._dispatchListforControlEvent(controlEvent);
eventInvocationList.push(invocation);
},
/**
* Removes a target and action for a particular event from an internal dispatch table.
*
* @param {Object} target The target object that is, the object to which the action message is sent. Pass nil to remove all targets paired with action and the specified control events.
* @param {function} action A selector identifying an action message. Pass NULL to remove all action messages paired with target.
* @param {Number} controlEvent A control event for which the action message is sent. See "CCControlEvent" for constants.
*/
_removeTargetWithActionForControlEvent:function (target, action, controlEvent) {
// Retrieve all invocations for the given control event
//<CCInvocation*>
var eventInvocationList = this._dispatchListforControlEvent(controlEvent);
//remove all invocations if the target and action are null
//TODO: should the invocations be deleted, or just removed from the array? Won't that cause issues if you add a single invocation for multiple events?
var bDeleteObjects = true;
if (!target && !action) {
//remove objects
eventInvocationList.length = 0;
} else {
//normally we would use a predicate, but this won't work here. Have to do it manually
for (var i = 0; i < eventInvocationList.length; ) {
var invocation = eventInvocationList[i];
var shouldBeRemoved = true;
if (target)
shouldBeRemoved = (target == invocation.getTarget());
if (action)
shouldBeRemoved = (shouldBeRemoved && (action == invocation.getAction()));
// Remove the corresponding invocation object
if (shouldBeRemoved)
cc.ArrayRemoveObject(eventInvocationList, invocation);
else
i ++;
}
}
},
/**
* Updates the control layout using its current internal state.
*/
needsLayout:function () {
}
});
cc.Control.create = function () {
var retControl = new cc.Control();
if (retControl && retControl.init())
return retControl;
return null;
};