510 lines
14 KiB
Text
510 lines
14 KiB
Text
/**
|
|
* PANDA 3D SOFTWARE
|
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
*
|
|
* All use of this software is subject to the terms of the revised BSD
|
|
* license. You should have received a copy of this license along
|
|
* with this source code in a file named "LICENSE."
|
|
*
|
|
* @file pgItem.I
|
|
* @author drose
|
|
* @date 2002-03-13
|
|
*/
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE void PGItem::
|
|
set_name(const std::string &name) {
|
|
Namable::set_name(name);
|
|
_lock.set_name(name);
|
|
}
|
|
|
|
/**
|
|
* Returns the MouseWatcherRegion associated with this item. Every PGItem has
|
|
* a MouseWatcherRegion associated with it, that is created when the PGItem is
|
|
* created; it does not change during the lifetime of the PGItem. Even items
|
|
* that do not have a frame have an associated MouseWatcherRegion, although it
|
|
* will not be used in this case.
|
|
*/
|
|
INLINE PGMouseWatcherRegion *PGItem::
|
|
get_region() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return _region;
|
|
}
|
|
|
|
/**
|
|
* Sets the object which will be notified when the PGItem changes. Set this
|
|
* to NULL to disable this effect. The PGItem does not retain ownership of
|
|
* the pointer; it is your responsibility to ensure that the notify object
|
|
* does not destruct.
|
|
*/
|
|
INLINE void PGItem::
|
|
set_notify(PGItemNotify *notify) {
|
|
LightReMutexHolder holder(_lock);
|
|
if (_notify != nullptr) {
|
|
_notify->remove_item(this);
|
|
}
|
|
_notify = notify;
|
|
if (_notify != nullptr) {
|
|
_notify->add_item(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if there is an object configured to be notified when the
|
|
* PGItem changes, false otherwise.
|
|
*/
|
|
INLINE bool PGItem::
|
|
has_notify() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return (_notify != nullptr);
|
|
}
|
|
|
|
/**
|
|
* Returns the object which will be notified when the PGItem changes, if any.
|
|
* Returns NULL if there is no such object configured.
|
|
*/
|
|
INLINE PGItemNotify *PGItem::
|
|
get_notify() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return _notify;
|
|
}
|
|
|
|
/**
|
|
* Sets the bounding rectangle of the item, in local coordinates. This is the
|
|
* region on screen within which the mouse will be considered to be within the
|
|
* item. Normally, it should correspond to the bounding rectangle of the
|
|
* visible geometry of the item.
|
|
*/
|
|
INLINE void PGItem::
|
|
set_frame(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
|
|
set_frame(LVecBase4(left, right, bottom, top));
|
|
}
|
|
|
|
/**
|
|
* Sets the bounding rectangle of the item, in local coordinates. This is the
|
|
* region on screen within which the mouse will be considered to be within the
|
|
* item. Normally, it should correspond to the bounding rectangle of the
|
|
* visible geometry of the item.
|
|
*/
|
|
INLINE void PGItem::
|
|
set_frame(const LVecBase4 &frame) {
|
|
LightReMutexHolder holder(_lock);
|
|
if (!_has_frame || _frame != frame) {
|
|
_has_frame = true;
|
|
_frame = frame;
|
|
frame_changed();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the bounding rectangle of the item. See set_frame(). It is an
|
|
* error to call this if has_frame() returns false.
|
|
*/
|
|
INLINE const LVecBase4 &PGItem::
|
|
get_frame() const {
|
|
LightReMutexHolder holder(_lock);
|
|
nassertr(has_frame(), _frame);
|
|
return _frame;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the item has a bounding rectangle; see set_frame().
|
|
*/
|
|
INLINE bool PGItem::
|
|
has_frame() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return _has_frame;
|
|
}
|
|
|
|
/**
|
|
* Removes the bounding rectangle from the item. It will no longer be
|
|
* possible to position the mouse within the item; see set_frame().
|
|
*/
|
|
INLINE void PGItem::
|
|
clear_frame() {
|
|
LightReMutexHolder holder(_lock);
|
|
if (_has_frame) {
|
|
_has_frame = false;
|
|
frame_changed();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the "state" of this particular PGItem.
|
|
*
|
|
* The PGItem node will render as if it were the subgraph assigned to the
|
|
* corresponding index via set_state_def().
|
|
*/
|
|
INLINE void PGItem::
|
|
set_state(int state) {
|
|
LightReMutexHolder holder(_lock);
|
|
_state = state;
|
|
}
|
|
|
|
/**
|
|
* Returns the "state" of this particular PGItem. See set_state().
|
|
*/
|
|
INLINE int PGItem::
|
|
get_state() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return _state;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the PGItem is currently active for mouse events. See
|
|
* set_active().
|
|
*/
|
|
INLINE bool PGItem::
|
|
get_active() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return (_flags & F_active) != 0;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the PGItem currently has focus for keyboard events. See
|
|
* set_focus().
|
|
*/
|
|
INLINE bool PGItem::
|
|
get_focus() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return (_flags & F_focus) != 0;
|
|
}
|
|
|
|
/**
|
|
* Returns whether background_focus is currently enabled. See
|
|
* set_background_focus().
|
|
*/
|
|
INLINE bool PGItem::
|
|
get_background_focus() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return (_flags & F_background_focus) != 0;
|
|
}
|
|
|
|
/**
|
|
* This is just an interface to set the suppress flags on the underlying
|
|
* MouseWatcherRegion. See MouseWatcherRegion::set_suppress_flags().
|
|
*/
|
|
INLINE void PGItem::
|
|
set_suppress_flags(int suppress_flags) {
|
|
LightReMutexHolder holder(_lock);
|
|
_region->set_suppress_flags(suppress_flags);
|
|
}
|
|
|
|
/**
|
|
* This is just an interface to get the suppress flags on the underlying
|
|
* MouseWatcherRegion. See MouseWatcherRegion::get_suppress_flags().
|
|
*/
|
|
INLINE int PGItem::
|
|
get_suppress_flags() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return _region->get_suppress_flags();
|
|
}
|
|
|
|
/**
|
|
* Returns the Node that is the root of the subgraph that will be drawn when
|
|
* the PGItem is in the indicated state. The first time this is called for a
|
|
* particular state index, it may create the Node.
|
|
*/
|
|
INLINE NodePath &PGItem::
|
|
get_state_def(int state) {
|
|
nassertr(state >= 0 && state < 1000, get_state_def(0)); // Sanity check.
|
|
|
|
LightReMutexHolder holder(_lock);
|
|
return do_get_state_def(state);
|
|
}
|
|
|
|
/**
|
|
* Returns the unique ID assigned to this PGItem. This will be assigned to
|
|
* the region created with the MouseWatcher, and will thus be used to generate
|
|
* event names.
|
|
*/
|
|
INLINE const std::string &PGItem::
|
|
get_id() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return _region->get_name();
|
|
}
|
|
|
|
/**
|
|
* Set the unique ID assigned to this PGItem. It is the user's responsibility
|
|
* to ensure that this ID is unique.
|
|
*
|
|
* Normally, this should not need to be called, as the PGItem will assign
|
|
* itself an ID when it is created, but this function allows the user to
|
|
* decide to redefine the ID to be something possibly more meaningful.
|
|
*/
|
|
INLINE void PGItem::
|
|
set_id(const std::string &id) {
|
|
LightReMutexHolder holder(_lock);
|
|
_region->set_name(id);
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the enter event for all PGItems.
|
|
* The enter event is the concatenation of this string followed by get_id().
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_enter_prefix() {
|
|
return "enter-";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the exit event for all PGItems.
|
|
* The exit event is the concatenation of this string followed by get_id().
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_exit_prefix() {
|
|
return "exit-";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the within event for all PGItems.
|
|
* The within event is the concatenation of this string followed by get_id().
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_within_prefix() {
|
|
return "within-";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the without event for all
|
|
* PGItems. The without event is the concatenation of this string followed by
|
|
* get_id().
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_without_prefix() {
|
|
return "without-";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the focus_in event for all
|
|
* PGItems. The focus_in event is the concatenation of this string followed
|
|
* by get_id().
|
|
*
|
|
* Unlike most item events, this event is thrown with no parameters.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_focus_in_prefix() {
|
|
return "fin-";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the focus_out event for all
|
|
* PGItems. The focus_out event is the concatenation of this string followed
|
|
* by get_id().
|
|
*
|
|
* Unlike most item events, this event is thrown with no parameters.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_focus_out_prefix() {
|
|
return "fout-";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the press event for all PGItems.
|
|
* The press event is the concatenation of this string followed by a button
|
|
* name, followed by a hyphen and get_id().
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_press_prefix() {
|
|
return "press-";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the repeat event for all PGItems.
|
|
* The repeat event is the concatenation of this string followed by a button
|
|
* name, followed by a hyphen and get_id().
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_repeat_prefix() {
|
|
return "repeat-";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the release event for all
|
|
* PGItems. The release event is the concatenation of this string followed by
|
|
* a button name, followed by a hyphen and get_id().
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_release_prefix() {
|
|
return "release-";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix that is used to define the keystroke event for all
|
|
* PGItems. The keystroke event is the concatenation of this string followed
|
|
* by a hyphen and get_id().
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_keystroke_prefix() {
|
|
return "keystroke-";
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item is active and the
|
|
* mouse enters its frame, but not any nested frames.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_enter_event() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_enter_prefix() + get_id();
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item is active and the
|
|
* mouse exits its frame, or enters a nested frame.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_exit_event() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_exit_prefix() + get_id();
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item is active and the
|
|
* mouse moves within the boundaries of the frame. This is different from the
|
|
* enter_event in that the mouse is considered within the frame even if it is
|
|
* also within a nested frame.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_within_event() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_within_prefix() + get_id();
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item is active and the
|
|
* mouse moves completely outside the boundaries of the frame. This is
|
|
* different from the exit_event in that the mouse is considered within the
|
|
* frame even if it is also within a nested frame.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_without_event() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_without_prefix() + get_id();
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item gets the keyboard
|
|
* focus.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_focus_in_event() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_focus_in_prefix() + get_id();
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item loses the keyboard
|
|
* focus.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_focus_out_event() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_focus_out_prefix() + get_id();
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item is active and the
|
|
* indicated mouse or keyboard button is depressed while the mouse is within
|
|
* the frame.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_press_event(const ButtonHandle &button) const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_press_prefix() + button.get_name() + "-" + get_id();
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item is active and the
|
|
* indicated mouse or keyboard button is continuously held down while the
|
|
* mouse is within the frame.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_repeat_event(const ButtonHandle &button) const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_repeat_prefix() + button.get_name() + "-" + get_id();
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item is active and the
|
|
* indicated mouse or keyboard button, formerly clicked down is within the
|
|
* frame, is released.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_release_event(const ButtonHandle &button) const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_release_prefix() + button.get_name() + "-" + get_id();
|
|
}
|
|
|
|
/**
|
|
* Returns the event name that will be thrown when the item is active and any
|
|
* key is pressed by the user.
|
|
*/
|
|
INLINE std::string PGItem::
|
|
get_keystroke_event() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return get_keystroke_prefix() + get_id();
|
|
}
|
|
|
|
/**
|
|
* Changes the TextNode object that will be used by all PGItems to generate
|
|
* default labels given a string. This can be loaded with the default font,
|
|
* etc.
|
|
*/
|
|
INLINE void PGItem::
|
|
set_text_node(TextNode *node) {
|
|
_text_node = node;
|
|
}
|
|
|
|
/**
|
|
* Returns the one PGItem in the world that currently has keyboard focus, if
|
|
* any, or NULL if no item has keyboard focus. Use PGItem::set_focus() to
|
|
* activate or deactivate keyboard focus on a particular item.
|
|
*/
|
|
INLINE PGItem *PGItem::
|
|
get_focus_item() {
|
|
return _focus_item;
|
|
}
|
|
|
|
/**
|
|
* Returns the inverse of the frame transform matrix
|
|
*/
|
|
INLINE LMatrix4 PGItem::
|
|
get_frame_inv_xform() const {
|
|
LightReMutexHolder holder(_lock);
|
|
return _frame_inv_xform;
|
|
}
|
|
|
|
/**
|
|
* Computes the area of the indicated frame.
|
|
*/
|
|
INLINE PN_stdfloat PGItem::
|
|
compute_area(const LVecBase4 &frame) {
|
|
return (frame[1] - frame[0]) * (frame[3] - frame[2]);
|
|
}
|
|
|
|
/**
|
|
* Given that largest is the pointer to the largest frame so far, and
|
|
* largest_area is its area, compare that to the area of the new frame; if the
|
|
* new frame is larger, adjust largest and largest_area appropriately.
|
|
*/
|
|
INLINE void PGItem::
|
|
compare_largest(const LVecBase4 *&largest, PN_stdfloat &largest_area,
|
|
const LVecBase4 *new_frame) {
|
|
PN_stdfloat new_area = compute_area(*new_frame);
|
|
if (new_area > largest_area) {
|
|
largest = new_frame;
|
|
largest_area = new_area;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE PGItem::StateDef::
|
|
StateDef() :
|
|
_frame_stale(true)
|
|
{
|
|
}
|