/* * Copyright (c) 2012 cocos2d-x.org * https://axmolengine.github.io/ * * Copyright 2012 Yannick Loriot. All rights reserved. * http://yannickloriot.com * * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. * * 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 falseT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND falseNINFRINGEMENT. IN false 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. * */ #include "CCControlStepper.h" NS_AX_EXT_BEGIN #define ControlStepperLabelColorEnabled Color3B(55, 55, 55) #define ControlStepperLabelColorDisabled Color3B(147, 147, 147) #define ControlStepperLabelFont "CourierNewPSMT" #define kAutorepeatDeltaTime 0.15f #define kAutorepeatIncreaseTimeIncrement 12 ControlStepper::ControlStepper() : _value(0.0) , _continuous(false) , _autorepeat(false) , _wraps(false) , _minimumValue(0.0) , _maximumValue(0.0) , _stepValue(0.0) , _touchInsideFlag(false) , _touchedPart(Part::NONE) , _autorepeatCount(0) , _minusSprite(nullptr) , _plusSprite(nullptr) , _minusLabel(nullptr) , _plusLabel(nullptr) {} ControlStepper::~ControlStepper() { unscheduleAllCallbacks(); AX_SAFE_RELEASE(_minusSprite); AX_SAFE_RELEASE(_plusSprite); AX_SAFE_RELEASE(_minusLabel); AX_SAFE_RELEASE(_plusLabel); } bool ControlStepper::initWithMinusSpriteAndPlusSprite(Sprite* minusSprite, Sprite* plusSprite) { if (Control::init()) { AXASSERT(minusSprite, "Minus sprite must be not nil"); AXASSERT(plusSprite, "Plus sprite must be not nil"); // Set the default values _autorepeat = true; _continuous = true; _minimumValue = 0; _maximumValue = 100; _value = 0; _stepValue = 1; _wraps = false; this->setIgnoreAnchorPointForPosition(false); // Add the minus components this->setMinusSprite(minusSprite); _minusSprite->setPosition(minusSprite->getContentSize().width / 2, minusSprite->getContentSize().height / 2); this->addChild(_minusSprite); this->setMinusLabel(Label::createWithSystemFont("-", ControlStepperLabelFont, 40)); _minusLabel->setColor(ControlStepperLabelColorDisabled); _minusLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE); _minusLabel->setPosition(_minusSprite->getContentSize().width / 2, _minusSprite->getContentSize().height / 2); _minusSprite->addChild(_minusLabel); // Add the plus components this->setPlusSprite(plusSprite); _plusSprite->setPosition(minusSprite->getContentSize().width + plusSprite->getContentSize().width / 2, minusSprite->getContentSize().height / 2); this->addChild(_plusSprite); this->setPlusLabel(Label::createWithSystemFont("+", ControlStepperLabelFont, 40)); _plusLabel->setColor(ControlStepperLabelColorEnabled); _plusLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE); _plusLabel->setPosition(_plusSprite->getContentSize().width / 2, _plusSprite->getContentSize().height / 2); _plusSprite->addChild(_plusLabel); // Defines the content size Rect maxRect = ControlUtils::RectUnion(_minusSprite->getBoundingBox(), _plusSprite->getBoundingBox()); this->setContentSize( Size(_minusSprite->getContentSize().width + _plusSprite->getContentSize().height, maxRect.size.height)); return true; } return false; } ControlStepper* ControlStepper::create(Sprite* minusSprite, Sprite* plusSprite) { ControlStepper* pRet = new ControlStepper(); if (pRet->initWithMinusSpriteAndPlusSprite(minusSprite, plusSprite)) { pRet->autorelease(); } else { AX_SAFE_DELETE(pRet); } return pRet; } //// Properties void ControlStepper::setWraps(bool wraps) { _wraps = wraps; if (_wraps) { _minusLabel->setColor(ControlStepperLabelColorEnabled); _plusLabel->setColor(ControlStepperLabelColorEnabled); } this->setValue(_value); } void ControlStepper::setMinimumValue(double minimumValue) { if (minimumValue >= _maximumValue) { AXASSERT(0, "Must be numerically less than maximumValue."); } _minimumValue = minimumValue; this->setValue(_value); } void ControlStepper::setMaximumValue(double maximumValue) { if (maximumValue <= _minimumValue) { AXASSERT(0, "Must be numerically greater than minimumValue."); } _maximumValue = maximumValue; this->setValue(_value); } void ControlStepper::setValue(double value) { this->setValueWithSendingEvent(value, true); } double ControlStepper::getValue() const { return _value; } void ControlStepper::setStepValue(double stepValue) { if (stepValue <= 0) { AXASSERT(0, "Must be numerically greater than 0."); } _stepValue = stepValue; } bool ControlStepper::isContinuous() const { return _continuous; } // //// ControlStepper Public Methods void ControlStepper::setValueWithSendingEvent(double value, bool send) { if (value < _minimumValue) { value = _wraps ? _maximumValue : _minimumValue; } else if (value > _maximumValue) { value = _wraps ? _minimumValue : _maximumValue; } _value = value; if (!_wraps) { _minusLabel->setColor((value == _minimumValue) ? ControlStepperLabelColorDisabled : ControlStepperLabelColorEnabled); _plusLabel->setColor((value == _maximumValue) ? ControlStepperLabelColorDisabled : ControlStepperLabelColorEnabled); } if (send) { this->sendActionsForControlEvents(Control::EventType::VALUE_CHANGED); } } void ControlStepper::startAutorepeat() { _autorepeatCount = -1; this->schedule(AX_SCHEDULE_SELECTOR(ControlStepper::update), kAutorepeatDeltaTime, AX_REPEAT_FOREVER, kAutorepeatDeltaTime * 3); } /** Stop the autorepeat. */ void ControlStepper::stopAutorepeat() { this->unschedule(AX_SCHEDULE_SELECTOR(ControlStepper::update)); } void ControlStepper::update(float /*dt*/) { _autorepeatCount++; if ((_autorepeatCount < kAutorepeatIncreaseTimeIncrement) && (_autorepeatCount % 3) != 0) return; if (_touchedPart == Part::MINUS) { this->setValueWithSendingEvent(_value - _stepValue, _continuous); } else if (_touchedPart == Part::PLUS) { this->setValueWithSendingEvent(_value + _stepValue, _continuous); } } //// ControlStepper Private Methods void ControlStepper::updateLayoutUsingTouchLocation(Vec2 location) { if (location.x < _minusSprite->getContentSize().width && _value > _minimumValue) { _touchedPart = Part::MINUS; _minusSprite->setColor(Color3B::GRAY); _plusSprite->setColor(Color3B::WHITE); } else if (location.x >= _minusSprite->getContentSize().width && _value < _maximumValue) { _touchedPart = Part::PLUS; _minusSprite->setColor(Color3B::WHITE); _plusSprite->setColor(Color3B::GRAY); } else { _touchedPart = Part::NONE; _minusSprite->setColor(Color3B::WHITE); _plusSprite->setColor(Color3B::WHITE); } } bool ControlStepper::onTouchBegan(Touch* pTouch, Event* /*pEvent*/) { if (!isTouchInside(pTouch) || !isEnabled() || !isVisible()) { return false; } Vec2 location = this->getTouchLocation(pTouch); this->updateLayoutUsingTouchLocation(location); _touchInsideFlag = true; if (_autorepeat) { this->startAutorepeat(); } return true; } void ControlStepper::onTouchMoved(Touch* pTouch, Event* /*pEvent*/) { if (this->isTouchInside(pTouch)) { Vec2 location = this->getTouchLocation(pTouch); this->updateLayoutUsingTouchLocation(location); if (!_touchInsideFlag) { _touchInsideFlag = true; if (_autorepeat) { this->startAutorepeat(); } } } else { _touchInsideFlag = false; _touchedPart = Part::NONE; _minusSprite->setColor(Color3B::WHITE); _plusSprite->setColor(Color3B::WHITE); if (_autorepeat) { this->stopAutorepeat(); } } } void ControlStepper::onTouchEnded(Touch* pTouch, Event* /*pEvent*/) { _minusSprite->setColor(Color3B::WHITE); _plusSprite->setColor(Color3B::WHITE); if (_autorepeat) { this->stopAutorepeat(); } if (this->isTouchInside(pTouch)) { Vec2 location = this->getTouchLocation(pTouch); this->setValue(_value + ((location.x < _minusSprite->getContentSize().width) ? (0.0 - _stepValue) : _stepValue)); } } NS_AX_EXT_END