text: //-----------------------------------------------------------------------------
  // 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 //
  
  
  