Panda3D
pgButton.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pgButton.cxx
10  * @author drose
11  * @date 2002-03-13
12  */
13 
14 #include "pgButton.h"
16 
17 #include "throw_event.h"
18 #include "mouseButton.h"
19 #include "mouseWatcherParameter.h"
20 #include "colorAttrib.h"
21 #include "transformState.h"
22 
23 TypeHandle PGButton::_type_handle;
24 
25 /**
26  *
27  */
28 PGButton::
29 PGButton(const std::string &name) : PGItem(name)
30 {
31  _button_down = false;
32  _click_buttons.insert(MouseButton::one());
33 
34  set_active(true);
35 }
36 
37 /**
38  *
39  */
40 PGButton::
41 ~PGButton() {
42 }
43 
44 /**
45  *
46  */
47 PGButton::
48 PGButton(const PGButton &copy) :
49  PGItem(copy),
50  _click_buttons(copy._click_buttons)
51 {
52  _button_down = false;
53 }
54 
55 /**
56  * Returns a newly-allocated Node that is a shallow copy of this one. It will
57  * be a different Node pointer, but its internal data may or may not be shared
58  * with that of the original Node.
59  */
61 make_copy() const {
62  LightReMutexHolder holder(_lock);
63  return new PGButton(*this);
64 }
65 
66 /**
67  * This is a callback hook function, called whenever the mouse enters the
68  * region.
69  */
71 enter_region(const MouseWatcherParameter &param) {
72  LightReMutexHolder holder(_lock);
73  if (get_active()) {
74  set_state(_button_down ? S_depressed : S_rollover);
75  }
76  PGItem::enter_region(param);
77 }
78 
79 /**
80  * This is a callback hook function, called whenever the mouse exits the
81  * region.
82  */
84 exit_region(const MouseWatcherParameter &param) {
85  LightReMutexHolder holder(_lock);
86  if (get_active()) {
87  set_state(S_ready);
88  }
89  PGItem::exit_region(param);
90 }
91 
92 /**
93  * This is a callback hook function, called whenever a mouse or keyboard
94  * button is depressed while the mouse is within the region.
95  */
97 press(const MouseWatcherParameter &param, bool background) {
98  LightReMutexHolder holder(_lock);
99  if (has_click_button(param.get_button())) {
100  if (get_active()) {
101  _button_down = true;
102  set_state(S_depressed);
103  }
104  }
105  PGItem::press(param, background);
106 }
107 
108 /**
109  * This is a callback hook function, called whenever a mouse or keyboard
110  * button previously depressed with press() is released.
111  */
113 release(const MouseWatcherParameter &param, bool background) {
114  LightReMutexHolder holder(_lock);
115  if (has_click_button(param.get_button())) {
116  _button_down = false;
117  if (get_active()) {
118  // Note that a "click" may come from a keyboard button press. In that
119  // case, instead of checking that the mouse cursor is still over the
120  // button, we check whether the item has keyboard focus.
121  if (param.is_outside() &&
123  set_state(S_ready);
124  } else {
125  set_state(S_rollover);
126  click(param);
127  }
128  }
129  }
130  PGItem::release(param, background);
131 }
132 
133 /**
134  * This is a callback hook function, called whenever the button is clicked
135  * down-and-up by the user normally.
136  */
138 click(const MouseWatcherParameter &param) {
139  LightReMutexHolder holder(_lock);
141  std::string event = get_click_event(param.get_button());
142  play_sound(event);
143  throw_event(event, EventParameter(ep));
144 
145  if (has_notify()) {
146  get_notify()->button_click(this, param);
147  }
148 }
149 
150 /**
151  * Sets up the button as a default text button using the indicated label
152  * string. The TextNode defined by PGItem::get_text_node() will be used to
153  * create the label geometry. This automatically sets up the frame according
154  * to the size of the text.
155  */
157 setup(const std::string &label, PN_stdfloat bevel) {
158  LightReMutexHolder holder(_lock);
159  clear_state_def(S_ready);
160  clear_state_def(S_depressed);
161  clear_state_def(S_rollover);
162  clear_state_def(S_inactive);
163 
164  TextNode *text_node = get_text_node();
165  text_node->set_text(label);
166  PT(PandaNode) geom = text_node->generate();
167 
168  LVecBase4 frame = text_node->get_card_actual();
169  set_frame(frame[0] - 0.4, frame[1] + 0.4, frame[2] - 0.15f, frame[3] + 0.15f);
170 
171  PT(PandaNode) ready = new PandaNode("ready");
172  PT(PandaNode) depressed = new PandaNode("depressed");
173  PT(PandaNode) rollover = new PandaNode("rollover");
174  PT(PandaNode) inactive = new PandaNode("inactive");
175 
176  PGFrameStyle style;
177  style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
178  style.set_width(bevel, bevel);
179 
180  style.set_type(PGFrameStyle::T_bevel_out);
181  set_frame_style(S_ready, style);
182 
183  style.set_color(0.9f, 0.9f, 0.9f, 1.0f);
184  set_frame_style(S_rollover, style);
185 
186  inactive->set_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.8f, 0.8f, 1.0f)));
187  style.set_color(0.6f, 0.6f, 0.6f, 1.0f);
188  set_frame_style(S_inactive, style);
189 
190  style.set_type(PGFrameStyle::T_bevel_in);
191  style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
192  set_frame_style(S_depressed, style);
193  depressed->set_transform(TransformState::make_pos(LVector3(0.05f, 0.0f, -0.05f)));
194 
195  get_state_def(S_ready).attach_new_node(ready, 1);
196  get_state_def(S_depressed).attach_new_node(depressed, 1);
197  get_state_def(S_rollover).attach_new_node(rollover, 1);
198  get_state_def(S_inactive).attach_new_node(inactive, 1);
199 
200  ready->add_child(geom);
201  depressed->add_child(geom);
202  rollover->add_child(geom);
203  inactive->add_child(geom);
204 }
205 
206 /**
207  * Sets up the button using the indicated NodePath as arbitrary geometry.
208  */
210 setup(const NodePath &ready, const NodePath &depressed,
211  const NodePath &rollover, const NodePath &inactive) {
212  LightReMutexHolder holder(_lock);
213  clear_state_def(S_ready);
214  clear_state_def(S_depressed);
215  clear_state_def(S_rollover);
216  clear_state_def(S_inactive);
217 
218  instance_to_state_def(S_ready, ready);
219  instance_to_state_def(S_depressed, depressed);
220  instance_to_state_def(S_rollover, rollover);
221  instance_to_state_def(S_inactive, inactive);
222 
223  // Set the button frame size.
224  LPoint3 min_point, max_point;
225  ready.calc_tight_bounds(min_point, max_point);
226  set_frame(min_point[0], max_point[0],
227  min_point[2], max_point[2]);
228 }
229 
230 /**
231  * Toggles the active/inactive state of the button. In the case of a
232  * PGButton, this also changes its visual appearance.
233  */
235 set_active(bool active) {
236  LightReMutexHolder holder(_lock);
237  if (active != get_active()) {
238  PGItem::set_active(active);
239  set_state(active ? S_ready : S_inactive);
240  }
241 }
242 
243 /**
244  * Adds the indicated button to the set of buttons that can effectively
245  * "click" the PGButton. Normally, this is just MouseButton::one(). Returns
246  * true if the button was added, or false if it was already there.
247  */
249 add_click_button(const ButtonHandle &button) {
250  LightReMutexHolder holder(_lock);
251  return _click_buttons.insert(button).second;
252 }
253 
254 /**
255  * Removes the indicated button from the set of buttons that can effectively
256  * "click" the PGButton. Normally, this is just MouseButton::one(). Returns
257  * true if the button was removed, or false if it was not in the set.
258  */
260 remove_click_button(const ButtonHandle &button) {
261  LightReMutexHolder holder(_lock);
262  return (_click_buttons.erase(button) != 0);
263 }
264 
265 /**
266  * Returns true if the indicated button is on the set of buttons that can
267  * effectively "click" the PGButton. Normally, this is just
268  * MouseButton::one().
269  */
271 has_click_button(const ButtonHandle &button) {
272  LightReMutexHolder holder(_lock);
273  return (_click_buttons.count(button) != 0);
274 }
PGItem::clear_state_def
void clear_state_def(int state)
Resets the NodePath assigned to the indicated state to its initial default, with only a frame represe...
Definition: pgItem.cxx:944
MouseButton::one
static ButtonHandle one()
Returns the ButtonHandle associated with the first mouse button.
Definition: mouseButton.cxx:43
PGItem::get_text_node
static TextNode * get_text_node()
Returns the TextNode object that will be used by all PGItems to generate default labels given a strin...
Definition: pgItem.cxx:1055
PGItem::set_frame
void set_frame(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top)
Sets the bounding rectangle of the item, in local coordinates.
Definition: pgItem.I:81
throw_event.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PGButton::click
virtual void click(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the button is clicked down-and-up by the user norma...
Definition: pgButton.cxx:138
TextNode::get_card_actual
LVecBase4 get_card_actual() const
Returns the actual dimensions of the card around the text.
Definition: textNode.I:503
PGItem::press
virtual void press(const MouseWatcherParameter &param, bool background)
This is a callback hook function, called whenever a mouse or keyboard button is depressed while the m...
Definition: pgItem.cxx:657
MouseWatcherParameter
This is sent along as a parameter to most events generated for a region to indicate the mouse and but...
Definition: mouseWatcherParameter.h:28
PGItem::get_focus
bool get_focus() const
Returns whether the PGItem currently has focus for keyboard events.
Definition: pgItem.I:170
PGItem
This is the base class for all the various kinds of gui widget objects.
Definition: pgItem.h:53
LightReMutexHolder
Similar to MutexHolder, but for a light reentrant mutex.
Definition: lightReMutexHolder.h:25
NodePath::calc_tight_bounds
bool calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, const NodePath &other=NodePath(), Thread *current_thread=Thread::get_current_thread()) const
Calculates the minimum and maximum vertices of all Geoms at this NodePath's bottom node and below.
Definition: nodePath.cxx:5467
mouseButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pgMouseWatcherParameter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ButtonHandle
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
Definition: buttonHandle.h:26
PGButton::set_active
virtual void set_active(bool active)
Toggles the active/inactive state of the button.
Definition: pgButton.cxx:235
colorAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PGButton::press
virtual void press(const MouseWatcherParameter &param, bool background)
This is a callback hook function, called whenever a mouse or keyboard button is depressed while the m...
Definition: pgButton.cxx:97
PGButton::setup
void setup(const std::string &label, PN_stdfloat bevel=0.1f)
Sets up the button as a default text button using the indicated label string.
Definition: pgButton.cxx:157
PandaNode::set_state
set_state
Sets the complete RenderState that will be applied to all nodes at this level and below.
Definition: pandaNode.h:173
TextNode
The primary interface to this module.
Definition: textNode.h:48
PGItem::get_state_def
get_state_def
Returns the Node that is the root of the subgraph that will be drawn when the PGItem is in the indica...
Definition: pgItem.h:135
PGButton::add_click_button
bool add_click_button(const ButtonHandle &button)
Adds the indicated button to the set of buttons that can effectively "click" the PGButton.
Definition: pgButton.cxx:249
PGMouseWatcherParameter
This specialization on MouseWatcherParameter allows us to tag on additional elements to events for th...
Definition: pgMouseWatcherParameter.h:27
PGItem::instance_to_state_def
NodePath instance_to_state_def(int state, const NodePath &path)
Parents an instance of the bottom node of the indicated NodePath to the indicated state index.
Definition: pgItem.cxx:962
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
transformState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PGFrameStyle::set_width
void set_width(PN_stdfloat x, PN_stdfloat y)
Sets the width parameter, which has meaning only for certain frame types.
Definition: pgFrameStyle.I:139
PGFrameStyle
Definition: pgFrameStyle.h:29
TextEncoder::set_text
set_text
Changes the text that is stored in the encoder.
Definition: textEncoder.h:124
MouseButton::is_mouse_button
static bool is_mouse_button(ButtonHandle button)
Returns true if the indicated ButtonHandle is a mouse button, false if it is some other kind of butto...
Definition: mouseButton.cxx:120
PGItem::get_active
bool get_active() const
Returns whether the PGItem is currently active for mouse events.
Definition: pgItem.I:160
PGFrameStyle::set_color
void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a)
Sets the dominant color of the frame.
Definition: pgFrameStyle.I:80
PGButton::remove_click_button
bool remove_click_button(const ButtonHandle &button)
Removes the indicated button from the set of buttons that can effectively "click" the PGButton.
Definition: pgButton.cxx:260
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
PGItem::set_frame_style
void set_frame_style(int state, const PGFrameStyle &style)
Changes the kind of frame that will be drawn behind the item when it is in the indicated state.
Definition: pgItem.cxx:992
EventParameter
An optional parameter associated with an event.
Definition: eventParameter.h:35
PGItem::exit_region
virtual void exit_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse exits the region.
Definition: pgItem.cxx:545
PGButton
This is a particular kind of PGItem that is specialized to behave like a normal button object.
Definition: pgButton.h:29
PGItem::release
virtual void release(const MouseWatcherParameter &param, bool background)
This is a callback hook function, called whenever a mouse or keyboard button previously depressed wit...
Definition: pgItem.cxx:686
PGButton::has_click_button
bool has_click_button(const ButtonHandle &button)
Returns true if the indicated button is on the set of buttons that can effectively "click" the PGButt...
Definition: pgButton.cxx:271
PGItem::set_active
virtual void set_active(bool active)
Sets whether the PGItem is active for mouse watching.
Definition: pgItem.cxx:828
PGButton::release
virtual void release(const MouseWatcherParameter &param, bool background)
This is a callback hook function, called whenever a mouse or keyboard button previously depressed wit...
Definition: pgButton.cxx:113
PGFrameStyle::set_type
void set_type(Type type)
Sets the basic type of frame.
Definition: pgFrameStyle.I:64
PGItem::enter_region
virtual void enter_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse enters the region.
Definition: pgItem.cxx:521
MouseWatcherParameter::get_button
ButtonHandle get_button() const
Returns the mouse or keyboard button associated with this event.
Definition: mouseWatcherParameter.I:148
MouseWatcherParameter::is_outside
bool is_outside() const
Returns true if the mouse was outside the region at the time the event was generated,...
Definition: mouseWatcherParameter.I:273
pgButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PGButton::exit_region
virtual void exit_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse exits the region.
Definition: pgButton.cxx:84
PGButton::enter_region
virtual void enter_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse enters the region.
Definition: pgButton.cxx:71
PGButton::get_notify
PGButtonNotify * get_notify() const
Returns the object which will be notified when the PGButton changes, if any.
Definition: pgButton.I:30
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
PGButton::make_copy
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
Definition: pgButton.cxx:61
PGItem::has_notify
bool has_notify() const
Returns true if there is an object configured to be notified when the PGItem changes,...
Definition: pgItem.I:59
mouseWatcherParameter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PGButton::get_click_event
std::string get_click_event(const ButtonHandle &button) const
Returns the event name that will be thrown when the button is clicked normally.
Definition: pgButton.I:74