/* Copyright (C) 2023 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */
 
#include <gdkmm/graphene_point.h>
#include <gdkmm/graphene_size.h>

_CONFIGINCLUDE(gdkmmconfig.h)
_DEFS(gdkmm,gdk)

#ifndef DOXYGEN_SHOULD_SKIP_THIS
extern "C"
{
struct _graphene_rect_t;
using graphene_rect_t = _graphene_rect_t;
}
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

namespace Gdk
{
/** Types for graphic libraries.
 *
 * Namespace %Gdk::Graphene contains C++ bindings of part of the
 * [Graphene](https://github.com/ebassi/graphene) library.
 * It contains classes and class members that are useful in Gtkmm.
 * It does not aim at being a complete C++ binding of %Graphene.
 */
namespace Graphene
{
//TODO: When we can break ABI, _CLASS_OPAQUE_COPYABLE -> _CLASS_GENERIC.
// graphene_rect_t gobject_; //Not a pointer.
// https://gitlab.gnome.org/GNOME/gtkmm/-/issues/155

/** The location and size of a rectangle region.
 *
 * The width and height of a %Gdk::Graphene::Rect can be negative; for instance,
 * a %Gdk::Graphene::Rect with an origin of [ 0, 0 ] and a size of [ 10, 10 ] is
 * equivalent to a %Gdk::Graphene::Rect with an origin of [ 10, 10 ] and a size
 * of [ -10, -10 ].
 *
 * Application code can normalize rectangles using normalize();
 * this function will ensure that the width and height of a rectangle are
 * positive values. All functions taking a %Gdk::Graphene::Rect as an argument
 * will internally operate on a normalized copy; all functions returning a
 * %Gdk::Graphene::Rect will always return a normalized rectangle.
 *
 * @newin{4,12}
 */
class GDKMM_API Rect
{
  _CLASS_OPAQUE_COPYABLE(Rect, graphene_rect_t, NONE, gdkmm_graphene_rect_copy, graphene_rect_free, GDKMM_API)
  _IGNORE(graphene_rect_init, graphene_rect_init_from_rect, graphene_rect_free)
public:
  Rect(float x, float y, float width, float height);

  /** Checks if this instance is valid.
   * It is valid if and only if it contains a value.
   * For instance,
   * @code
   * if (rect)
   *   do_something()
   * @endcode
   */
  explicit operator bool() const;

#m4 _CONVERSION(`graphene_point_t',`Point',`$2(const_cast<$1*>(&($3)), true)')
#m4 _CONVERSION(`graphene_size_t',`Size',`$2(const_cast<$1*>(&($3)), true)')
#m4 _CONVERSION(`Point',`graphene_point_t',`*($3).gobj()')
#m4 _CONVERSION(`Size',`graphene_size_t',`*($3).gobj()')
  _MEMBER_GET(origin, origin, Point, graphene_point_t)
  _MEMBER_SET(origin, origin, Point, graphene_point_t)
  _MEMBER_GET(size, size, Size, graphene_size_t)
  _MEMBER_SET(size, size, Size, graphene_size_t)

  /** Retrieves the coordinates of the center of the given rectangle.
   */
  Point get_center() const;
  _IGNORE(graphene_rect_get_center)

  /** Retrieves the coordinates of the top-left corner of the given rectangle.
   */
  Point get_top_left() const;
  _IGNORE(graphene_rect_get_top_left)

  /** Retrieves the coordinates of the top-right corner of the given rectangle.
   */
  Point get_top_right() const;
  _IGNORE(graphene_rect_get_top_right)

  /** Retrieves the coordinates of the bottom-right corner of the given rectangle.
   */
  Point get_bottom_right() const;
  _IGNORE(graphene_rect_get_bottom_right)

  /** Retrieves the coordinates of the bottom-left corner of the given rectangle.
   */
  Point get_bottom_left() const;
  _IGNORE(graphene_rect_get_bottom_left)

  _WRAP_METHOD(bool equal(const Rect& b) const, graphene_rect_equal, newin "4,12")
  _WRAP_METHOD(void normalize(), graphene_rect_normalize, newin "4,12")
  _WRAP_METHOD(float get_x() const, graphene_rect_get_x, newin "4,12")
  _WRAP_METHOD(float get_y() const, graphene_rect_get_y, newin "4,12")
  _WRAP_METHOD(float get_width() const, graphene_rect_get_width, newin "4,12")
  _WRAP_METHOD(float get_height() const, graphene_rect_get_height, newin "4,12")
  _WRAP_METHOD(float get_area() const, graphene_rect_get_area, newin "4,12")
  _WRAP_METHOD(bool contains_point(const Point& p) const, graphene_rect_contains_point, newin "4,12")
  _WRAP_METHOD(bool contains_rect(const Rect& b) const, graphene_rect_contains_rect, newin "4,12")
};
} // namespace Graphene
} // namespace Gdk
