You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
4.5 KiB
TypeScript

/**
* @packageDocumentation
* @module ui
*/
import { CustomToggleGroup } from "./CustomToggleGroup"
const { property, ccclass, requireComponent, executionOrder, menu } = cc._decorator
export enum ToggleSwitchType {
active,
animation
}
/**
* @en
* The toggle component is a CheckBox, when it used together with a ToggleGroup,
* it could be treated as a RadioButton.
*
* @zh
* Toggle CheckBox ToggleGroup 使 RadioButton
*/
@ccclass
@executionOrder(110)
@menu('UI/CustomToggle')
export class CustomToggle extends cc.Component {
/**
* @en
* When this value is true, the check mark component will be enabled,
* otherwise the check mark component will be disabled.
*
* @zh
* true check mark enabled disabled
*/
@property
get isChecked() {
return this._isChecked
}
set isChecked(value) {
this._set(value)
}
set _resizeToTarget(value: boolean) {
// if (value) {
// this._resizeNodeToTargetNode();
// }
}
get _toggleContainer() {
const parent = this.node.parent!
if (parent instanceof cc.Node) {
return parent.getComponent(CustomToggleGroup)
}
return null
}
/**
* @en
* If Toggle is clicked, it will trigger event's handler.
*
* @zh
* Toggle
*/
@property({ type: [cc.Component.EventHandler], tooltip: 'i18n:toggle.check_events' })
public checkEvents: cc.Component.EventHandler[] = []
@property(cc.Boolean)
protected _isChecked = true
@property([cc.Node])
protected onNodeList: cc.Node[] = []
@property([cc.Node])
protected offNodeList: cc.Node[] = []
@property({ type: cc.Enum(ToggleSwitchType) })
toggleSwitchType: ToggleSwitchType = ToggleSwitchType.active
//是否關閉點擊事件
@property(cc.Boolean)
isDoNotEmitToggle = false
private toggleEventMap: Map<ToggleSwitchType, Function> = new Map([
[ToggleSwitchType.active, this.switchByActive.bind(this)],
[ToggleSwitchType.animation, this.switchByAnimation.bind(this)]
])
protected _internalToggle() {
if (this.isDoNotEmitToggle) {
return
}
this.isChecked = !this.isChecked
}
protected _set(value: boolean, emitEvent = true) {
if (this._isChecked == value) return
this._isChecked = value
const group = this._toggleContainer
if (group && group.enabled && this.enabled) {
if (value || (!group.anyTogglesChecked() && !group.allowSwitchOff)) {
this._isChecked = true
group.notifyToggleCheck(this as any, emitEvent)
}
}
this.playEffect()
if (emitEvent) {
this._emitToggleEvents()
}
}
//
public playEffect() {
this.toggleEventMap.get(this.toggleSwitchType)()
}
switchByActive() {
this.onNodeList.forEach((node) => {
node.active = this._isChecked
})
this.offNodeList.forEach((node) => {
node.active = !this._isChecked
})
}
switchByAnimation() { }
/**
* @en
* Set isChecked without invoking checkEvents.
*
* @zh
* isChecked checkEvents
*
* @param value -
*/
public setIsCheckedWithoutNotify(value: boolean) {
this._set(value, false)
}
onEnable() {
this.playEffect()
if (!CC_EDITOR || CC_PREVIEW) {
this.node.on(cc.Node.EventType.TOUCH_END, this._internalToggle, this)
}
}
onDisable() {
if (!CC_EDITOR || CC_PREVIEW) {
this.node.off(cc.Node.EventType.TOUCH_END, this._internalToggle, this)
}
}
public OnDestroy() {
const group = this._toggleContainer
if (group) {
group.ensureValidState()
}
}
protected _emitToggleEvents() {
this.node.emit("toggle", this)
if (this.checkEvents) {
cc.Component.EventHandler.emitEvents(this.checkEvents, this)
}
}
}
/**
* @en
* Note: This event is emitted from the node to which the component belongs.
*
* @zh
* Node node.on
* @event toggle
* @param {Event.EventCustom} event
* @param {Toggle} toggle - The Toggle component.
*/