123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743 |
- /*
- * Copyright (c) 2012 cocos2d-x.org
- * http://www.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.
- *
- */
- #include "CCControlButton.h"
- #include "2d/CCLabel.h"
- #include "2d/CCAction.h"
- #include "2d/CCActionInterval.h"
- using namespace std;
- NS_CC_EXT_BEGIN
- enum
- {
- kZoomActionTag = 0xCCCB0001,
- };
- ControlButton::ControlButton()
- : _isPushed(false)
- , _parentInited(false)
- , _doesAdjustBackgroundImage(false)
- , _currentTitleColor(Color3B::WHITE)
- , _titleLabel(nullptr)
- , _backgroundSprite(nullptr)
- , _zoomOnTouchDown(false)
- , _marginV(ControlButtonMarginTB)
- , _marginH(ControlButtonMarginLR)
- {
- }
- ControlButton::~ControlButton()
- {
- CC_SAFE_RELEASE(_titleLabel);
- CC_SAFE_RELEASE(_backgroundSprite);
- }
- //initialisers
- bool ControlButton::init()
- {
- return this->initWithLabelAndBackgroundSprite(Label::createWithSystemFont("", "Helvetica", 12), cocos2d::ui::Scale9Sprite::create(),true);
- }
- bool ControlButton::initWithLabelAndBackgroundSprite(Node* node, ui::Scale9Sprite* backgroundSprite, bool adjustBackGroundSize)
- {
- if (Control::init())
- {
- CCASSERT(node != nullptr, "node must not be nil.");
- LabelProtocol* label = dynamic_cast<LabelProtocol*>(node);
- CCASSERT(backgroundSprite != nullptr, "Background sprite must not be nil.");
- CCASSERT(label != nullptr, "label must not be nil.");
-
- _parentInited = true;
- _isPushed = false;
- // Adjust the background image by adjustBackGroundSize
- setPreferredSize(Size::ZERO);
- setAdjustBackgroundImage(adjustBackGroundSize);
- // Zooming button by default
- _zoomOnTouchDown = true;
- _scaleRatio = 1.1f;
-
- // Set the default anchor point
- setIgnoreAnchorPointForPosition(false);
- setAnchorPoint(Vec2::ANCHOR_MIDDLE);
-
- // Set the nodes
- setTitleLabel(node);
- setBackgroundSprite(backgroundSprite);
- // Set the default color and opacity
- setColor(Color3B::WHITE);
- setOpacity(255.0f);
- setOpacityModifyRGB(true);
-
- // Initialize the dispatch table
-
- setTitleForState(label->getString(), Control::State::NORMAL);
- setTitleColorForState(node->getColor(), Control::State::NORMAL);
- setTitleLabelForState(node, Control::State::NORMAL);
- setBackgroundSpriteForState(backgroundSprite, Control::State::NORMAL);
-
- setLabelAnchorPoint(Vec2::ANCHOR_MIDDLE);
- // Layout update
- needsLayout();
- return true;
- }
- //couldn't init the Control
- else
- {
- return false;
- }
- }
- ControlButton* ControlButton::create(Node* label, cocos2d::ui::Scale9Sprite* backgroundSprite)
- {
- ControlButton *pRet = new (std::nothrow) ControlButton();
- pRet->initWithLabelAndBackgroundSprite(label, backgroundSprite, true);
- pRet->autorelease();
- return pRet;
- }
- ControlButton* ControlButton::create(Node* label, cocos2d::ui::Scale9Sprite* backgroundSprite, bool adjustBackGroundSize)
- {
- ControlButton *pRet = new (std::nothrow) ControlButton();
- pRet->initWithLabelAndBackgroundSprite(label, backgroundSprite, adjustBackGroundSize);
- pRet->autorelease();
- return pRet;
- }
- bool ControlButton::initWithTitleAndFontNameAndFontSize(const std::string& title, const std::string& fontName, float fontSize)
- {
- return initWithLabelAndBackgroundSprite(Label::createWithSystemFont(title, fontName, fontSize), cocos2d::ui::Scale9Sprite::create(),true);
- }
- ControlButton* ControlButton::create(const std::string& title, const std::string& fontName, float fontSize)
- {
- ControlButton *pRet = new (std::nothrow) ControlButton();
- pRet->initWithTitleAndFontNameAndFontSize(title, fontName, fontSize);
- pRet->autorelease();
- return pRet;
- }
- bool ControlButton::initWithBackgroundSprite(cocos2d::ui::Scale9Sprite* sprite)
- {
- Label *label = Label::createWithSystemFont("", "Arial", 30);//
- return initWithLabelAndBackgroundSprite(label, sprite,false);
- }
- ControlButton* ControlButton::create(cocos2d::ui::Scale9Sprite* sprite)
- {
- ControlButton *pRet = new (std::nothrow) ControlButton();
- pRet->initWithBackgroundSprite(sprite);
- pRet->autorelease();
- return pRet;
- }
- void ControlButton::setMargins(int marginH, int marginV)
- {
- _marginV = marginV;
- _marginH = marginH;
- needsLayout();
- }
- void ControlButton::setEnabled(bool enabled)
- {
- Control::setEnabled(enabled);
- needsLayout();
- }
- void ControlButton::setSelected(bool enabled)
- {
- Control::setSelected(enabled);
- needsLayout();
- }
- void ControlButton::setHighlighted(bool enabled)
- {
- if (enabled == true)
- {
- _state = Control::State::HIGH_LIGHTED;
- }
- else
- {
- _state = Control::State::NORMAL;
- }
-
- Control::setHighlighted(enabled);
- Action *action = getActionByTag(kZoomActionTag);
- if (action)
- {
- stopAction(action);
- }
- needsLayout();
- if( _zoomOnTouchDown )
- {
- float scaleValue = (isHighlighted() && isEnabled() && !isSelected()) ? _scaleRatio : 1.0f;
- Action *zoomAction = ScaleTo::create(0.05f, scaleValue);
- zoomAction->setTag(kZoomActionTag);
- runAction(zoomAction);
- }
- }
- void ControlButton::setZoomOnTouchDown(bool zoomOnTouchDown)
- {
- _zoomOnTouchDown = zoomOnTouchDown;
- }
- bool ControlButton::getZoomOnTouchDown() const
- {
- return _zoomOnTouchDown;
- }
- void ControlButton::setPreferredSize(const Size& size)
- {
- if(size.width == 0 && size.height == 0)
- {
- _doesAdjustBackgroundImage = true;
- }
- else
- {
- _doesAdjustBackgroundImage = false;
-
- for (auto iter = _backgroundSpriteDispatchTable.begin(); iter != _backgroundSpriteDispatchTable.end(); ++iter)
- {
- iter->second->setPreferredSize(size);
- }
- }
- _preferredSize = size;
- needsLayout();
- }
- const Size& ControlButton::getPreferredSize() const
- {
- return _preferredSize;
- }
- void ControlButton::setAdjustBackgroundImage(bool adjustBackgroundImage)
- {
- _doesAdjustBackgroundImage=adjustBackgroundImage;
- needsLayout();
- }
- bool ControlButton::doesAdjustBackgroundImage()
- {
- return _doesAdjustBackgroundImage;
- }
- const Vec2& ControlButton::getLabelAnchorPoint() const
- {
- return this->_labelAnchorPoint;
- }
- void ControlButton::setLabelAnchorPoint(const Vec2& labelAnchorPoint)
- {
- this->_labelAnchorPoint = labelAnchorPoint;
- if (_titleLabel != nullptr)
- {
- this->_titleLabel->setAnchorPoint(labelAnchorPoint);
- }
- }
- std::string ControlButton::getTitleForState(State state)
- {
- auto iter = _titleDispatchTable.find((int)state);
- if (iter != _titleDispatchTable.end())
- {
- return iter->second;
- }
-
- iter = _titleDispatchTable.find((int)Control::State::NORMAL);
-
- return iter != _titleDispatchTable.end() ? iter->second : "";
- }
- void ControlButton::setTitleForState(const std::string& title, State state)
- {
- _titleDispatchTable.erase((int)state);
- if (!title.empty())
- {
- _titleDispatchTable[(int)state] = title;
- }
-
- // If the current state if equal to the given state we update the layout
- if (getState() == state)
- {
- needsLayout();
- }
- }
- Color3B ControlButton::getTitleColorForState(State state) const
- {
- Color3B returnColor = Color3B::WHITE;
- auto iter = _titleColorDispatchTable.find((int)state);
- if (iter != _titleColorDispatchTable.end())
- {
- returnColor = iter->second;
- }
- else
- {
- iter = _titleColorDispatchTable.find((int)Control::State::NORMAL);
- if (iter != _titleColorDispatchTable.end())
- {
- returnColor = iter->second;
- }
- }
- return returnColor;
- }
- void ControlButton::setTitleColorForState(const Color3B& color, State state)
- {
- _titleColorDispatchTable.erase((int)state);
- _titleColorDispatchTable[(int)state] = color;
-
- // If the current state if equal to the given state we update the layout
- if (getState() == state)
- {
- needsLayout();
- }
- }
- Node* ControlButton::getTitleLabelForState(State state)
- {
- Node* titleLabel = _titleLabelDispatchTable.at((int)state);
- if (titleLabel)
- {
- return titleLabel;
- }
- return _titleLabelDispatchTable.at((int)Control::State::NORMAL);
- }
- void ControlButton::setTitleLabelForState(Node* titleLabel, State state)
- {
- Node* previousLabel = _titleLabelDispatchTable.at((int)state);
- if (previousLabel)
- {
- removeChild(previousLabel, true);
- _titleLabelDispatchTable.erase((int)state);
- }
- _titleLabelDispatchTable.insert((int)state, titleLabel);
- titleLabel->setVisible(false);
- titleLabel->setAnchorPoint(Vec2(0.5f, 0.5f));
- addChild(titleLabel, 1);
- // If the current state if equal to the given state we update the layout
- if (getState() == state)
- {
- needsLayout();
- }
- }
- void ControlButton::setTitleTTFForState(const std::string& fontName, State state)
- {
- this->setTitleLabelForState(Label::createWithSystemFont(getTitleForState(state), fontName, 12), state);
- }
- const std::string& ControlButton::getTitleTTFForState(State state)
- {
- LabelProtocol* label = dynamic_cast<LabelProtocol*>(this->getTitleLabelForState(state));
- Label* labelTTF = dynamic_cast<Label*>(label);
- if(labelTTF != 0)
- {
- return labelTTF->getSystemFontName();
- }
- static std::string ret("");
- return ret;
- }
- void ControlButton::setTitleTTFSizeForState(float size, State state)
- {
- LabelProtocol* label = dynamic_cast<LabelProtocol*>(this->getTitleLabelForState(state));
- if(label)
- {
- Label* labelTTF = dynamic_cast<Label*>(label);
- if(labelTTF != 0)
- {
- return labelTTF->setSystemFontSize(size);
- }
- }
- }
- float ControlButton::getTitleTTFSizeForState(State state)
- {
- LabelProtocol* label = dynamic_cast<LabelProtocol*>(this->getTitleLabelForState(state));
- Label* labelTTF = dynamic_cast<Label*>(label);
- if(labelTTF != 0)
- {
- return labelTTF->getSystemFontSize();
- }
- else
- {
- return 0;
- }
- }
- void ControlButton::setTitleBMFontForState(const std::string& fntFile, State state)
- {
- std::string title = this->getTitleForState(state);
- this->setTitleLabelForState(Label::createWithBMFont(fntFile, title), state);
- }
- const std::string& ControlButton::getTitleBMFontForState(State state)
- {
- LabelProtocol* label = dynamic_cast<LabelProtocol*>(this->getTitleLabelForState(state));
- auto labelBMFont = dynamic_cast<Label*>(label);
- if(labelBMFont != 0)
- {
- return labelBMFont->getBMFontFilePath();
- }
- static std::string ret("");
- return ret;
- }
- ui::Scale9Sprite* ControlButton::getBackgroundSpriteForState(State state)
- {
- auto backgroundSprite = _backgroundSpriteDispatchTable.at((int)state);
- if (backgroundSprite)
- {
- return backgroundSprite;
- }
- return _backgroundSpriteDispatchTable.at((int)Control::State::NORMAL);
- }
- void ControlButton::setBackgroundSpriteForState(ui::Scale9Sprite* sprite, State state)
- {
- Size oldPreferredSize = _preferredSize;
- auto previousBackgroundSprite = _backgroundSpriteDispatchTable.at((int)state);
- if (previousBackgroundSprite)
- {
- removeChild(previousBackgroundSprite, true);
- _backgroundSpriteDispatchTable.erase((int)state);
- }
- _backgroundSpriteDispatchTable.insert((int)state, sprite);
- sprite->setVisible(false);
- sprite->setAnchorPoint(Vec2(0.5f, 0.5f));
- addChild(sprite);
- if (this->_preferredSize.width != 0 || this->_preferredSize.height != 0)
- {
- if (oldPreferredSize.equals(_preferredSize))
- {
- // Force update of preferred size
- sprite->setPreferredSize(Size(oldPreferredSize.width+1, oldPreferredSize.height+1));
- }
-
- sprite->setPreferredSize(this->_preferredSize);
- }
- // If the current state if equal to the given state we update the layout
- if (getState() == state)
- {
- needsLayout();
- }
- }
- void ControlButton::setBackgroundSpriteFrameForState(SpriteFrame * spriteFrame, State state)
- {
- ui::Scale9Sprite * sprite = ui::Scale9Sprite::createWithSpriteFrame(spriteFrame);
- this->setBackgroundSpriteForState(sprite, state);
- }
- void ControlButton::needsLayout()
- {
- if (!_parentInited) {
- return;
- }
- // Hide the background and the label
- if (_titleLabel != nullptr) {
- _titleLabel->setVisible(false);
- }
- if (_backgroundSprite) {
- _backgroundSprite->setVisible(false);
- }
- // Update anchor of all labels
- this->setLabelAnchorPoint(this->_labelAnchorPoint);
-
- // Update the label to match with the current state
- _currentTitle = getTitleForState(_state);
- _currentTitleColor = getTitleColorForState(_state);
- this->setTitleLabel(getTitleLabelForState(_state));
- LabelProtocol* label = dynamic_cast<LabelProtocol*>(_titleLabel);
- if (label && !_currentTitle.empty())
- {
- label->setString(_currentTitle);
- }
- if (_titleLabel)
- {
- _titleLabel->setColor(_currentTitleColor);
- }
- if (_titleLabel != nullptr)
- {
- _titleLabel->setPosition(getContentSize().width / 2, getContentSize().height / 2);
- }
-
- // Update the background sprite
- this->setBackgroundSprite(this->getBackgroundSpriteForState(_state));
- if (_backgroundSprite != nullptr)
- {
- _backgroundSprite->setPosition(getContentSize().width / 2, getContentSize().height / 2);
- }
-
- // Get the title label size
- Size titleLabelSize;
- if (_titleLabel != nullptr)
- {
- titleLabelSize = _titleLabel->getBoundingBox().size;
- }
-
- // Adjust the background image if necessary
- if (_doesAdjustBackgroundImage)
- {
- // Add the margins
- if (_backgroundSprite != nullptr)
- {
- _backgroundSprite->setContentSize(Size(titleLabelSize.width + _marginH * 2, titleLabelSize.height + _marginV * 2));
- }
- }
- else
- {
- //TODO: should this also have margins if one of the preferred sizes is relaxed?
- if (_backgroundSprite != nullptr)
- {
- Size preferredSize = _backgroundSprite->getPreferredSize();
- if (preferredSize.width <= 0)
- {
- preferredSize.width = titleLabelSize.width;
- }
- if (preferredSize.height <= 0)
- {
- preferredSize.height = titleLabelSize.height;
- }
- _backgroundSprite->setContentSize(preferredSize);
- }
- }
-
- // Set the content size
- Rect rectTitle;
- if (_titleLabel != nullptr)
- {
- rectTitle = _titleLabel->getBoundingBox();
- }
- Rect rectBackground;
- if (_backgroundSprite != nullptr)
- {
- rectBackground = _backgroundSprite->getBoundingBox();
- }
- Rect maxRect = ControlUtils::RectUnion(rectTitle, rectBackground);
- setContentSize(Size(maxRect.size.width, maxRect.size.height));
-
- if (_titleLabel != nullptr)
- {
- _titleLabel->setPosition(getContentSize().width/2, getContentSize().height/2);
- // Make visible the background and the label
- _titleLabel->setVisible(true);
- }
-
- if (_backgroundSprite != nullptr)
- {
- _backgroundSprite->setPosition(getContentSize().width/2, getContentSize().height/2);
- _backgroundSprite->setVisible(true);
- }
- }
- bool ControlButton::onTouchBegan(Touch *pTouch, Event* /*pEvent*/)
- {
- if (!isTouchInside(pTouch) || !isEnabled() || !isVisible() || !hasVisibleParents() )
- {
- return false;
- }
-
- for (Node *c = this->_parent; c != nullptr; c = c->getParent())
- {
- if (c->isVisible() == false)
- {
- return false;
- }
- }
-
- _isPushed = true;
- this->setHighlighted(true);
- sendActionsForControlEvents(Control::EventType::TOUCH_DOWN);
- return true;
- }
- void ControlButton::onTouchMoved(Touch *pTouch, Event* /*pEvent*/)
- {
- if (!isEnabled() || !isPushed() || isSelected())
- {
- if (isHighlighted())
- {
- setHighlighted(false);
- }
- return;
- }
-
- bool isTouchMoveInside = isTouchInside(pTouch);
- if (isTouchMoveInside && !isHighlighted())
- {
- setHighlighted(true);
- sendActionsForControlEvents(Control::EventType::DRAG_ENTER);
- }
- else if (isTouchMoveInside && isHighlighted())
- {
- sendActionsForControlEvents(Control::EventType::DRAG_INSIDE);
- }
- else if (!isTouchMoveInside && isHighlighted())
- {
- setHighlighted(false);
-
- sendActionsForControlEvents(Control::EventType::DRAG_EXIT);
- }
- else if (!isTouchMoveInside && !isHighlighted())
- {
- sendActionsForControlEvents(Control::EventType::DRAG_OUTSIDE);
- }
- }
- void ControlButton::onTouchEnded(Touch *pTouch, Event* /*pEvent*/)
- {
- _isPushed = false;
- setHighlighted(false);
-
-
- if (isTouchInside(pTouch))
- {
- sendActionsForControlEvents(Control::EventType::TOUCH_UP_INSIDE);
- }
- else
- {
- sendActionsForControlEvents(Control::EventType::TOUCH_UP_OUTSIDE);
- }
- }
- void ControlButton::setOpacity(GLubyte opacity)
- {
- Control::setOpacity(opacity);
-
- for (auto iter = _backgroundSpriteDispatchTable.begin(); iter != _backgroundSpriteDispatchTable.end(); ++iter)
- {
- iter->second->setOpacity(opacity);
- }
- for (auto iter = _titleLabelDispatchTable.begin(); iter != _titleLabelDispatchTable.end(); ++iter)
- {
- iter->second->setOpacity(opacity);
- }
- }
- void ControlButton::updateDisplayedOpacity(GLubyte parentOpacity)
- {
- Control::updateDisplayedOpacity(parentOpacity);
- for (auto iter = _backgroundSpriteDispatchTable.begin(); iter != _backgroundSpriteDispatchTable.end(); ++iter)
- {
- iter->second->updateDisplayedOpacity(parentOpacity);
- }
- for (auto iter = _titleLabelDispatchTable.begin(); iter != _titleLabelDispatchTable.end(); ++iter)
- {
- iter->second->updateDisplayedOpacity(parentOpacity);
- }
- }
- void ControlButton::setColor(const Color3B & color)
- {
- Control::setColor(color);
-
- for (auto iter = _backgroundSpriteDispatchTable.begin(); iter != _backgroundSpriteDispatchTable.end(); ++iter)
- {
- iter->second->setColor(color);
- }
- for (auto iter = _titleLabelDispatchTable.begin(); iter != _titleLabelDispatchTable.end(); ++iter)
- {
- iter->second->setColor(color);
- }
- }
- void ControlButton::updateDisplayedColor(const Color3B& parentColor)
- {
- Control::updateDisplayedColor(parentColor);
- for (auto iter = _backgroundSpriteDispatchTable.begin(); iter != _backgroundSpriteDispatchTable.end(); ++iter)
- {
- iter->second->updateDisplayedColor(parentColor);
- }
- for (auto iter = _titleLabelDispatchTable.begin(); iter != _titleLabelDispatchTable.end(); ++iter)
- {
- iter->second->updateDisplayedColor(parentColor);
- }
- }
- void ControlButton::onTouchCancelled(Touch* /*pTouch*/, Event* /*pEvent*/)
- {
- _isPushed = false;
- setHighlighted(false);
- sendActionsForControlEvents(Control::EventType::TOUCH_CANCEL);
- }
- ControlButton* ControlButton::create()
- {
- ControlButton *pControlButton = new (std::nothrow) ControlButton();
- if (pControlButton && pControlButton->init())
- {
- pControlButton->autorelease();
- return pControlButton;
- }
- CC_SAFE_DELETE(pControlButton);
- return nullptr;
- }
- NS_CC_EXT_END
|