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 }
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
Definition: buttonHandle.h:26
An optional parameter associated with an event.
Similar to MutexHolder, but for a light reentrant mutex.
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...
static ButtonHandle one()
Returns the ButtonHandle associated with the first mouse button.
Definition: mouseButton.cxx:43
This is sent along as a parameter to most events generated for a region to indicate the mouse and but...
ButtonHandle get_button() const
Returns the mouse or keyboard button associated with this event.
bool is_outside() const
Returns true if the mouse was outside the region at the time the event was generated,...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
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:5511
This is a particular kind of PGItem that is specialized to behave like a normal button object.
Definition: pgButton.h:29
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
virtual void set_active(bool active)
Toggles the active/inactive state of the button.
Definition: pgButton.cxx:235
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
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
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
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
virtual void enter_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse enters the region.
Definition: pgButton.cxx:71
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
Definition: pgButton.cxx:61
virtual void exit_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse exits the region.
Definition: pgButton.cxx:84
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
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
PGButtonNotify * get_notify() const
Returns the object which will be notified when the PGButton changes, if any.
Definition: pgButton.I:30
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
void set_type(Type type)
Sets the basic type of frame.
Definition: pgFrameStyle.I:64
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
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
This is the base class for all the various kinds of gui widget objects.
Definition: pgItem.h:53
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:674
bool get_active() const
Returns whether the PGItem is currently active for mouse events.
Definition: pgItem.I:160
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:1007
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:953
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
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:1076
bool get_focus() const
Returns whether the PGItem currently has focus for keyboard events.
Definition: pgItem.I:170
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:703
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:977
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
virtual void exit_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse exits the region.
Definition: pgItem.cxx:562
bool has_notify() const
Returns true if there is an object configured to be notified when the PGItem changes,...
Definition: pgItem.I:59
virtual void enter_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse enters the region.
Definition: pgItem.cxx:538
virtual void set_active(bool active)
Sets whether the PGItem is active for mouse watching.
Definition: pgItem.cxx:837
This specialization on MouseWatcherParameter allows us to tag on additional elements to events for th...
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
set_state
Sets the complete RenderState that will be applied to all nodes at this level and below.
Definition: pandaNode.h:173
set_text
Changes the text that is stored in the encoder.
Definition: textEncoder.h:124
The primary interface to this module.
Definition: textNode.h:48
LVecBase4 get_card_actual() const
Returns the actual dimensions of the card around the text.
Definition: textNode.I:503
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.