/*--------------------------------------------------------------------------
  Project:  Manual 2D Library - m2d
  File:     m2d_uiElement.cpp

  Copyright (C)2007-2009 Nintendo  All Rights Reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law. They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Revision: 1758 $
 *-------------------------------------------------------------------------*/

#include <nitro.h>
#include <nnsys/misc.h>
#include <ntmv/m2d/Rect.h>
#include <ntmv/m2d/uiElement.h>
#include <cstring>

namespace ntmv
{
namespace m2d
{

/*---------------------------------------------------------------------------*
  Name:         UIElement::UIElement

  Description:  Constructor

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
UIElement::UIElement()
{
    std::memset(&mFlags, 0, sizeof(mFlags));
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::UIElement

  Description:  Constructor

  Arguments:    position:  Display position (center).
                size:      Size.

  Returns:      None.
 *---------------------------------------------------------------------------*/
UIElement::UIElement(
    Point   position,
    Size    size
)
{
    std::memset(&mFlags, 0, sizeof(mFlags));

    mPosition  = position;
    mSize      = size;
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::Finalize

  Description:  Performs shutdown.

  Arguments:    objectConstructor:  A reference to an ObjectConstructor object.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
UIElement::Finalize(const ObjectConstructor& /*objectConstructor*/)
{}

/*---------------------------------------------------------------------------*
  Name:         UIElement::Draw

  Description:  Performs rendering.

  Arguments:    info:      A reference to an ObjG2dInfo object.
                parentPos: Parent position (global coordinates).

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
UIElement::Draw(
    const ObjG2dInfo&   /* info */,
    Point               parentPos
)
{
    if (! IsVisible())
    {
        return;
    }

    CalcGlbPosition(parentPos);
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::IsDrawn

  Description:  Determines whether this is drawn.

  Arguments:    parentPos:  Parent position (global coordinates).

  Returns:      Returns TRUE if it is drawn.
 *---------------------------------------------------------------------------*/
bool
UIElement::IsDrawn() const
{
    const Point ltGlbPos = GetLTGlbPosition();

    return ltGlbPos.x < GX_LCD_SIZE_X   && ltGlbPos.y < GX_LCD_SIZE_Y
        && ltGlbPos.x + mSize.width > 0 && ltGlbPos.y + mSize.height > 0;
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::DrawTest

  Description:  Determines whether this is drawn.
                When visible, global coordinates will be updated internally.

  Arguments:    parentPos:  Parent position (global coordinates).

  Returns:      Returns TRUE if it is drawn.
 *---------------------------------------------------------------------------*/
bool
UIElement::DrawTest(Point parentPos)
{
    if (! IsVisible())
    {
        return false;
    }

    CalcGlbPosition(parentPos);

    return IsDrawn();
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::Contains

  Description:  Determines whether this contains the specified position.

  Arguments:    point:  Position to check.

  Returns:      Returns TRUE when it is contained.
 *---------------------------------------------------------------------------*/
bool
UIElement::Contains(Point point) const
{
    if (! IsVisible())
    {
        return false;
    }

    const Rect buttonRect(GetLTGlbPosition(), mSize);
    return buttonRect.Contains(point);
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::SetPosition

  Description:  Sets the display position.

  Arguments:    value:  The position to set.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
UIElement::SetPosition(Point value)
{
    mPosition = value;
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::SetSize

  Description:  Sets the display size.

  Arguments:    value:  The size to set.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
UIElement::SetSize(Size value)
{
    mSize = value;
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::SetVisible

  Description:  Configures visibility.

  Arguments:    value:  TRUE to make it visible.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
UIElement::SetVisible(bool value)
{
    mFlags.invisible = ! value;
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::CheckHit

  Description:  Perform hit detection, and set the pressed state if hit.

  Arguments:    point:  Position to check.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
UIElement::CheckHit(Point point)
{
    if (IsVisible() && IsEnabled())
    {
        SetPointed(Contains(point));
    }
}

/*---------------------------------------------------------------------------*
  Name:         UIElement::GetLTGlbPosition

  Description:  Gets the upper-left position.

  Arguments:    None.

  Returns:      Returns the upper-left position.
 *---------------------------------------------------------------------------*/
Point
UIElement::GetLTGlbPosition() const
{
    // Offset to the upper-left position
    return Point(
        static_cast<s16>(mGlbPosition.x - mSize.width  / 2),
        static_cast<s16>(mGlbPosition.y - mSize.height / 2));
}

}   // namespace m2d
}   // namespace ntmv
