// Filename: mouseWatcher.I
// Created by:  drose (13Jul00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::has_mouse
//       Access: Published
//  Description: Returns true if the mouse is anywhere within the
//               window, false otherwise.  Also see is_mouse_open().
////////////////////////////////////////////////////////////////////
INLINE bool MouseWatcher::
has_mouse() const {
  return _has_mouse;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::is_mouse_open
//       Access: Published
//  Description: Returns true if the mouse is within the window and
//               not over some particular MouseWatcherRegion that is
//               marked to suppress mouse events; that is, that the
//               mouse is in open space within the window.
////////////////////////////////////////////////////////////////////
INLINE bool MouseWatcher::
is_mouse_open() const {
  return _has_mouse && (_suppress_flags & MouseWatcherRegion::SF_mouse_position) == 0;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_mouse
//       Access: Published
//  Description: It is only valid to call this if has_mouse() returns
//               true.  If so, this returns the current position of
//               the mouse within the window.
////////////////////////////////////////////////////////////////////
INLINE const LPoint2f &MouseWatcher::
get_mouse() const {
#ifndef NDEBUG
  static LPoint2f bogus_mouse(0.0, 0.0);
  nassertr(_has_mouse, bogus_mouse);
#endif
  return _mouse;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_mouse_x
//       Access: Published
//  Description: It is only valid to call this if has_mouse() returns
//               true.  If so, this returns the current X position of
//               the mouse within the window.
////////////////////////////////////////////////////////////////////
INLINE float MouseWatcher::
get_mouse_x() const {
  nassertr(_has_mouse, 0.0);
  return _mouse[0];
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_mouse_y
//       Access: Published
//  Description: It is only valid to call this if has_mouse() returns
//               true.  If so, this returns the current Y position of
//               the mouse within the window.
////////////////////////////////////////////////////////////////////
INLINE float MouseWatcher::
get_mouse_y() const {
  nassertr(_has_mouse, 0.0);
  return _mouse[1];
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::is_over_region
//       Access: Published
//  Description: Returns true if the mouse is over any rectangular
//               region, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool MouseWatcher::
is_over_region() const {
  return get_over_region() != (MouseWatcherRegion *)NULL;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::is_over_region
//       Access: Published
//  Description: Returns true if the mouse is over any rectangular
//               region, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool MouseWatcher::
is_over_region(float x, float y) const {
  return get_over_region(x, y) != (MouseWatcherRegion *)NULL;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::is_over_region
//       Access: Published
//  Description: Returns true if the mouse is over any rectangular
//               region, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool MouseWatcher::
is_over_region(const LPoint2f &pos) const {
  return get_over_region(pos) != (MouseWatcherRegion *)NULL;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_over_region
//       Access: Published
//  Description: Returns the smallest region the mouse is currently
//               over, or NULL if it is over no region.
////////////////////////////////////////////////////////////////////
INLINE MouseWatcherRegion *MouseWatcher::
get_over_region() const {
  return _current_region;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_over_region
//       Access: Published
//  Description: Returns the smallest region the indicated point is
//               over, or NULL if it is over no region.
////////////////////////////////////////////////////////////////////
INLINE MouseWatcherRegion *MouseWatcher::
get_over_region(float x, float y) const {
  return get_over_region(LPoint2f(x, y));
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::set_button_down_pattern
//       Access: Published
//  Description: Sets the pattern string that indicates how the event
//               names are generated when a button is depressed.  This
//               is a string that may contain any of the following:
//
//                  %r  - the name of the region the mouse is over
//                  %b  - the name of the button pressed.
//
//               The event name will be based on the in_pattern
//               string specified here, with all occurrences of the
//               above strings replaced with the corresponding values.
////////////////////////////////////////////////////////////////////
INLINE void MouseWatcher::
set_button_down_pattern(const string &pattern) {
  _button_down_pattern = pattern;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_button_down_pattern
//       Access: Published
//  Description: Returns the string that indicates how event names are
//               generated when a button is depressed.  See
//               set_button_down_pattern().
////////////////////////////////////////////////////////////////////
INLINE const string &MouseWatcher::
get_button_down_pattern() const {
  return _button_down_pattern;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::set_button_up_pattern
//       Access: Published
//  Description: Sets the pattern string that indicates how the event
//               names are generated when a button is released.  See
//               set_button_down_pattern().
////////////////////////////////////////////////////////////////////
INLINE void MouseWatcher::
set_button_up_pattern(const string &pattern) {
  _button_up_pattern = pattern;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_button_up_pattern
//       Access: Published
//  Description: Returns the string that indicates how event names are
//               generated when a button is released.  See
//               set_button_down_pattern().
////////////////////////////////////////////////////////////////////
INLINE const string &MouseWatcher::
get_button_up_pattern() const {
  return _button_up_pattern;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::set_enter_pattern
//       Access: Published
//  Description: Sets the pattern string that indicates how the event
//               names are generated when the mouse wanders over a
//               region.  See set_button_down_pattern().
////////////////////////////////////////////////////////////////////
INLINE void MouseWatcher::
set_enter_pattern(const string &pattern) {
  _enter_pattern = pattern;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_enter_pattern
//       Access: Published
//  Description: Returns the string that indicates how event names are
//               generated when the mouse wanders over a region.  See
//               set_button_down_pattern().
////////////////////////////////////////////////////////////////////
INLINE const string &MouseWatcher::
get_enter_pattern() const {
  return _enter_pattern;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::set_leave_pattern
//       Access: Published
//  Description: Sets the pattern string that indicates how the event
//               names are generated when the mouse leaves a region.
//               See set_button_down_pattern().
////////////////////////////////////////////////////////////////////
INLINE void MouseWatcher::
set_leave_pattern(const string &pattern) {
  _leave_pattern = pattern;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_leave_pattern
//       Access: Published
//  Description: Returns the string that indicates how event names are
//               generated when the mouse leaves a region.  See
//               set_button_down_pattern().
////////////////////////////////////////////////////////////////////
INLINE const string &MouseWatcher::
get_leave_pattern() const {
  return _leave_pattern;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::set_geometry
//       Access: Published
//  Description: Sets the arc that will be transformed each frame by
//               the mouse's coordinates.  It will also be hidden when
//               the mouse goes outside the window.  This can be used
//               to implement a software mouse pointer for when a
//               hardware (or system) mouse pointer is unavailable.
////////////////////////////////////////////////////////////////////
INLINE void MouseWatcher::
set_geometry(NodeRelation *arc) {
  _geometry = arc;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::has_geometry
//       Access: Published
//  Description: Returns true if a software mouse pointer has been
//               setup via set_geometry(), or false otherwise.  See
//               set_geometry().
////////////////////////////////////////////////////////////////////
INLINE bool MouseWatcher::
has_geometry() const {
  return !_geometry.is_null();
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_geometry
//       Access: Published
//  Description: Returns the arc that has been set as the software
//               mouse pointer, or NULL if no arc has been set.  See
//               has_geometry() and set_geometry().
////////////////////////////////////////////////////////////////////
INLINE NodeRelation *MouseWatcher::
get_geometry() const {
  return _geometry;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::clear_geometry
//       Access: Published
//  Description: Stops the use of the software cursor set up via
//               set_geometry().
////////////////////////////////////////////////////////////////////
INLINE void MouseWatcher::
clear_geometry() {
  _geometry.clear();
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::set_extra_handler
//       Access: Published
//  Description: As an optimization for the C++ Gui, an extra handler
//               can be registered with a mouseWatcher so that events
//               can be dealt with much sooner.
////////////////////////////////////////////////////////////////////
INLINE void MouseWatcher::
set_extra_handler(EventHandler *eh) {
  _eh = eh;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_extra_handler
//       Access: Published
//  Description: As an optimization for the C++ Gui, an extra handler
//               can be registered with a mouseWatcher so that events
//               can be dealt with much sooner.
////////////////////////////////////////////////////////////////////
INLINE EventHandler *MouseWatcher::
get_extra_handler(void) const {
  return _eh;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::set_modifier_buttons
//       Access: Public
//  Description: Sets the buttons that should be monitored as modifier
//               buttons for generating events to the
//               MouseWatcherRegions.
////////////////////////////////////////////////////////////////////
INLINE void MouseWatcher::
set_modifier_buttons(const ModifierButtons &mods) {
  _mods = mods;
}

////////////////////////////////////////////////////////////////////
//     Function: MouseWatcher::get_modifier_buttons
//       Access: Published
//  Description: Returns the set of buttons that are being monitored
//               as modifier buttons, as well as their current state.
////////////////////////////////////////////////////////////////////
INLINE ModifierButtons MouseWatcher::
get_modifier_buttons() const {
  return _mods;
}
