//----------------------------------------------------------------------------- // Copyright (c) 2013 GarageGames, LLC // // 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 "console/console.h" #include "graphics/dgl.h" #include "gui/guiCanvas.h" #include "gui/buttons/guiCheckBoxCtrl.h" #include "console/consoleTypes.h" IMPLEMENT_CONOBJECT(GuiCheckBoxCtrl); //--------------------------------------------------------------------------- GuiCheckBoxCtrl::GuiCheckBoxCtrl() { mBounds.extent.set(140, 30); mStateOn = false; mIndent = 0; mButtonType = ButtonTypeCheck; mUseInactiveState = false; } //--------------------------------------------------------------------------- void GuiCheckBoxCtrl::initPersistFields() { Parent::initPersistFields(); addField("useInactiveState", TypeBool, Offset(mUseInactiveState, GuiCheckBoxCtrl)); } bool GuiCheckBoxCtrl::onWake() { if(!Parent::onWake()) return false; // make sure there is a bitmap array for this control type // if it is declared as such in the control mProfile->constructBitmapArray(); return true; } void GuiCheckBoxCtrl::onMouseDown(const GuiEvent& event) { if (!mUseInactiveState) return Parent::onMouseDown(event); if (mProfile->mCanKeyFocus) setFirstResponder(); if (mProfile->mSoundButtonDown) { AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown); alxPlay(handle); } //lock the mouse mouseLock(); mDepressed = true; //update setUpdate(); } void GuiCheckBoxCtrl::onMouseUp(const GuiEvent& event) { if (!mUseInactiveState) return Parent::onMouseUp(event); mouseUnlock(); setUpdate(); //if we released the mouse within this control, perform the action if (mDepressed) onAction(); mDepressed = false; } void GuiCheckBoxCtrl::onAction() { if (!mUseInactiveState) return Parent::onAction(); if(mButtonType == ButtonTypeCheck) { if (!mActive) { mActive = true; mStateOn = true; } else if (mStateOn) mStateOn = false; else if (!mStateOn) mActive = false; // Update the console variable: if ( mConsoleVariable[0] ) Con::setBoolVariable( mConsoleVariable, mStateOn ); // Execute the console command (if any) if( mConsoleCommand[0] ) Con::evaluate( mConsoleCommand, false ); } setUpdate(); // Provide and onClick script callback. if( isMethod("onClick") ) Con::executef( this, 2, "onClick" ); } //--------------------------------------------------------------------------- void GuiCheckBoxCtrl::onRender(Point2I offset, const RectI &updateRect) { ColorI backColor = mActive ? mProfile->mFillColor : mProfile->mFillColorNA; ColorI fontColor = mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor; ColorI insideBorderColor = isFirstResponder() ? mProfile->mBorderColorHL : mProfile->mBorderColor; // just draw the check box and the text: S32 xOffset = 0; dglClearBitmapModulation(); if(mProfile->mBitmapArrayRects.size() >= 4) { // if size >= 4 then the inactive state images should be present S32 index = mStateOn; if(!mActive) index = 4; // inactive state images are indexes 4 and 5. else if(mDepressed) index += 2; xOffset = mProfile->mBitmapArrayRects[0].extent.x + 2 + mIndent; S32 y = (mBounds.extent.y - mProfile->mBitmapArrayRects[0].extent.y) / 2; dglDrawBitmapSR(mProfile->mTextureHandle, offset + Point2I(mIndent, y), mProfile->mBitmapArrayRects[index]); } if(mButtonText[0] != '\0') { dglSetBitmapModulation( fontColor ); renderJustifiedText(Point2I(offset.x + xOffset, offset.y), Point2I(mBounds.extent.x - mBounds.extent.y, mBounds.extent.y), mButtonText); } //render the children renderChildControls(offset, updateRect); } ConsoleMethod(GuiCheckBoxCtrl, setStateOn, void, 3, 3, "(state) Sets the control as active and updates siblings of the same group." "@param state This argument may be a boolean value or an integer." "state < 0: Parent::setStateOn(false), obj::setActive(false)\n" "state == 0 (or false): Parent::setStateOn(false), obj::setActive(true)\n" "state > 0 (or true): Parent::setStateOn(true), obj::setActive(true)") { if (dStricmp(argv[2], "true") == 0) object->setStateOn(1); else if (dStricmp(argv[2], "false") == 0) object->setStateOn(0); else object->setStateOn(dAtoi(argv[2])); } void GuiCheckBoxCtrl::setStateOn(S32 state) { if (mUseInactiveState) { if (state < 0) { setActive(false); Parent::setStateOn(false); } else if (state == 0) { setActive(true); Parent::setStateOn(false); } else if (state > 0) { setActive(true); Parent::setStateOn(true); } } else Parent::setStateOn((bool)state); } const char* GuiCheckBoxCtrl::getScriptValue() { if (mUseInactiveState) { if (isActive()) if (mStateOn) return "1"; else return "0"; else return "-1"; } else return Parent::getScriptValue(); } //--------------------------------------------------------------------------- // EOF //