Panda3D
 All Classes Functions Variables Enumerations
pgButton.cxx
1 // Filename: pgButton.cxx
2 // Created by: drose (13Mar02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "pgButton.h"
16 #include "pgMouseWatcherParameter.h"
17 
18 #include "throw_event.h"
19 #include "mouseButton.h"
20 #include "mouseWatcherParameter.h"
21 #include "colorAttrib.h"
22 #include "transformState.h"
23 
24 TypeHandle PGButton::_type_handle;
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: PGButton::Constructor
28 // Access: Published
29 // Description:
30 ////////////////////////////////////////////////////////////////////
31 PGButton::
32 PGButton(const string &name) : PGItem(name)
33 {
34  _button_down = false;
35  _click_buttons.insert(MouseButton::one());
36 
37  set_active(true);
38 }
39 
40 ////////////////////////////////////////////////////////////////////
41 // Function: PGButton::Destructor
42 // Access: Public, Virtual
43 // Description:
44 ////////////////////////////////////////////////////////////////////
45 PGButton::
46 ~PGButton() {
47 }
48 
49 ////////////////////////////////////////////////////////////////////
50 // Function: PGButton::Copy Constructor
51 // Access: Public
52 // Description:
53 ////////////////////////////////////////////////////////////////////
54 PGButton::
55 PGButton(const PGButton &copy) :
56  PGItem(copy),
57  _click_buttons(copy._click_buttons)
58 {
59  _button_down = false;
60 }
61 
62 ////////////////////////////////////////////////////////////////////
63 // Function: PGButton::make_copy
64 // Access: Public, Virtual
65 // Description: Returns a newly-allocated Node that is a shallow copy
66 // of this one. It will be a different Node pointer,
67 // but its internal data may or may not be shared with
68 // that of the original Node.
69 ////////////////////////////////////////////////////////////////////
71 make_copy() const {
72  LightReMutexHolder holder(_lock);
73  return new PGButton(*this);
74 }
75 
76 ////////////////////////////////////////////////////////////////////
77 // Function: PGButton::enter_region
78 // Access: Public, Virtual
79 // Description: This is a callback hook function, called whenever the
80 // mouse enters the region.
81 ////////////////////////////////////////////////////////////////////
82 void PGButton::
84  LightReMutexHolder holder(_lock);
85  if (get_active()) {
86  set_state(_button_down ? S_depressed : S_rollover);
87  }
88  PGItem::enter_region(param);
89 }
90 
91 ////////////////////////////////////////////////////////////////////
92 // Function: PGButton::exit_region
93 // Access: Public, Virtual
94 // Description: This is a callback hook function, called whenever the
95 // mouse exits the region.
96 ////////////////////////////////////////////////////////////////////
97 void PGButton::
99  LightReMutexHolder holder(_lock);
100  if (get_active()) {
101  set_state(S_ready);
102  }
103  PGItem::exit_region(param);
104 }
105 
106 ////////////////////////////////////////////////////////////////////
107 // Function: PGButton::press
108 // Access: Public, Virtual
109 // Description: This is a callback hook function, called whenever a
110 // mouse or keyboard button is depressed while the mouse
111 // is within the region.
112 ////////////////////////////////////////////////////////////////////
113 void PGButton::
114 press(const MouseWatcherParameter &param, bool background) {
115  LightReMutexHolder holder(_lock);
116  if (has_click_button(param.get_button())) {
117  if (get_active()) {
118  _button_down = true;
119  set_state(S_depressed);
120  }
121  }
122  PGItem::press(param, background);
123 }
124 
125 ////////////////////////////////////////////////////////////////////
126 // Function: PGButton::release
127 // Access: Public, Virtual
128 // Description: This is a callback hook function, called whenever a
129 // mouse or keyboard button previously depressed with
130 // press() is released.
131 ////////////////////////////////////////////////////////////////////
132 void PGButton::
133 release(const MouseWatcherParameter &param, bool background) {
134  LightReMutexHolder holder(_lock);
135  if (has_click_button(param.get_button())) {
136  _button_down = false;
137  if (get_active()) {
138  if (param.is_outside()) {
139  set_state(S_ready);
140  } else {
141  set_state(S_rollover);
142  click(param);
143  }
144  }
145  }
146  PGItem::release(param, background);
147 }
148 
149 ////////////////////////////////////////////////////////////////////
150 // Function: PGButton::click
151 // Access: Public, Virtual
152 // Description: This is a callback hook function, called whenever the
153 // button is clicked down-and-up by the user normally.
154 ////////////////////////////////////////////////////////////////////
155 void PGButton::
157  LightReMutexHolder holder(_lock);
159  string event = get_click_event(param.get_button());
160  play_sound(event);
161  throw_event(event, EventParameter(ep));
162 
163  if (has_notify()) {
164  get_notify()->button_click(this, param);
165  }
166 }
167 
168 ////////////////////////////////////////////////////////////////////
169 // Function: PGButton::setup
170 // Access: Published
171 // Description: Sets up the button as a default text button using the
172 // indicated label string. The TextNode defined by
173 // PGItem::get_text_node() will be used to create the
174 // label geometry. This automatically sets up the frame
175 // according to the size of the text.
176 ////////////////////////////////////////////////////////////////////
177 void PGButton::
178 setup(const string &label, PN_stdfloat bevel) {
179  LightReMutexHolder holder(_lock);
180  clear_state_def(S_ready);
181  clear_state_def(S_depressed);
182  clear_state_def(S_rollover);
183  clear_state_def(S_inactive);
184 
185  TextNode *text_node = get_text_node();
186  text_node->set_text(label);
187  PT(PandaNode) geom = text_node->generate();
188 
189  LVecBase4 frame = text_node->get_card_actual();
190  set_frame(frame[0] - 0.4, frame[1] + 0.4, frame[2] - 0.15f, frame[3] + 0.15f);
191 
192  PT(PandaNode) ready = new PandaNode("ready");
193  PT(PandaNode) depressed = new PandaNode("depressed");
194  PT(PandaNode) rollover = new PandaNode("rollover");
195  PT(PandaNode) inactive = new PandaNode("inactive");
196 
197  PGFrameStyle style;
198  style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
199  style.set_width(bevel, bevel);
200 
201  style.set_type(PGFrameStyle::T_bevel_out);
202  set_frame_style(S_ready, style);
203 
204  style.set_color(0.9f, 0.9f, 0.9f, 1.0f);
205  set_frame_style(S_rollover, style);
206 
207  inactive->set_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.8f, 0.8f, 1.0f)));
208  style.set_color(0.6f, 0.6f, 0.6f, 1.0f);
209  set_frame_style(S_inactive, style);
210 
211  style.set_type(PGFrameStyle::T_bevel_in);
212  style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
213  set_frame_style(S_depressed, style);
214  depressed->set_transform(TransformState::make_pos(LVector3(0.05f, 0.0f, -0.05f)));
215 
216  get_state_def(S_ready).attach_new_node(ready, 1);
217  get_state_def(S_depressed).attach_new_node(depressed, 1);
218  get_state_def(S_rollover).attach_new_node(rollover, 1);
219  get_state_def(S_inactive).attach_new_node(inactive, 1);
220 
221  ready->add_child(geom);
222  depressed->add_child(geom);
223  rollover->add_child(geom);
224  inactive->add_child(geom);
225 }
226 
227 ////////////////////////////////////////////////////////////////////
228 // Function: PGButton::setup
229 // Access: Published
230 // Description: Sets up the button using the indicated NodePath as
231 // arbitrary geometry.
232 ////////////////////////////////////////////////////////////////////
233 void PGButton::
234 setup(const NodePath &ready, const NodePath &depressed,
235  const NodePath &rollover, const NodePath &inactive) {
236  LightReMutexHolder holder(_lock);
237  clear_state_def(S_ready);
238  clear_state_def(S_depressed);
239  clear_state_def(S_rollover);
240  clear_state_def(S_inactive);
241 
242  instance_to_state_def(S_ready, ready);
243  instance_to_state_def(S_depressed, depressed);
244  instance_to_state_def(S_rollover, rollover);
245  instance_to_state_def(S_inactive, inactive);
246 
247  // Set the button frame size.
248  LPoint3 min_point, max_point;
249  ready.calc_tight_bounds(min_point, max_point);
250  set_frame(min_point[0], max_point[0],
251  min_point[2], max_point[2]);
252 }
253 
254 ////////////////////////////////////////////////////////////////////
255 // Function: PGButton::set_active
256 // Access: Published, Virtual
257 // Description: Toggles the active/inactive state of the button. In
258 // the case of a PGButton, this also changes its visual
259 // appearance.
260 ////////////////////////////////////////////////////////////////////
261 void PGButton::
262 set_active(bool active) {
263  LightReMutexHolder holder(_lock);
264  if (active != get_active()) {
265  PGItem::set_active(active);
266  set_state(active ? S_ready : S_inactive);
267  }
268 }
269 
270 ////////////////////////////////////////////////////////////////////
271 // Function: PGButton::add_click_button
272 // Access: Published
273 // Description: Adds the indicated button to the set of buttons that
274 // can effectively "click" the PGButton. Normally, this
275 // is just MouseButton::one(). Returns true if the
276 // button was added, or false if it was already there.
277 ////////////////////////////////////////////////////////////////////
278 bool PGButton::
280  LightReMutexHolder holder(_lock);
281  return _click_buttons.insert(button).second;
282 }
283 
284 ////////////////////////////////////////////////////////////////////
285 // Function: PGButton::remove_click_button
286 // Access: Published
287 // Description: Removes the indicated button from the set of buttons
288 // that can effectively "click" the PGButton. Normally,
289 // this is just MouseButton::one(). Returns true if the
290 // button was removed, or false if it was not in the
291 // set.
292 ////////////////////////////////////////////////////////////////////
293 bool PGButton::
295  LightReMutexHolder holder(_lock);
296  return (_click_buttons.erase(button) != 0);
297 }
298 
299 ////////////////////////////////////////////////////////////////////
300 // Function: PGButton::has_click_button
301 // Access: Published
302 // Description: Returns true if the indicated button is on the set of
303 // buttons that can effectively "click" the PGButton.
304 // Normally, this is just MouseButton::one().
305 ////////////////////////////////////////////////////////////////////
306 bool PGButton::
308  LightReMutexHolder holder(_lock);
309  return (_click_buttons.count(button) != 0);
310 }
311 
ButtonHandle get_button() const
Returns the mouse or keyboard button associated with this event.
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
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:114
This specialization on MouseWatcherParameter allows us to tag on additional elements to events for th...
void set_width(PN_stdfloat x, PN_stdfloat y)
Sets the width parameter, which has meaning only for certain frame types.
Definition: pgFrameStyle.I:172
This is the base class for all the various kinds of gui widget objects.
Definition: pgItem.h:58
virtual void enter_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse enters the region.
Definition: pgButton.cxx:83
An optional parameter associated with an event.
NodePath & get_state_def(int state)
Returns the Node that is the root of the subgraph that will be drawn when the PGItem is in the indica...
Definition: pgItem.cxx:1043
void set_text(const string &text)
Changes the text that is displayed under the TextNode.
Definition: textNode.I:1171
This is a particular kind of PGItem that is specialized to behave like a normal button object...
Definition: pgButton.h:32
void set_type(Type type)
Sets the basic type of frame.
Definition: pgFrameStyle.I:76
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:100
static ButtonHandle one()
Returns the ButtonHandle associated with the first mouse button.
Definition: mouseButton.cxx:50
virtual void enter_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse enters the region.
Definition: pgItem.cxx:541
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:100
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
bool calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, 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:6198
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
Definition: buttonHandle.h:28
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:95
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:133
LVecBase4 get_card_actual() const
Returns the actual dimensions of the card around the text.
Definition: textNode.I:578
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:1102
virtual void exit_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse exits the region.
Definition: pgButton.cxx:98
virtual void set_active(bool active)
Toggles the active/inactive state of the button.
Definition: pgButton.cxx:262
bool has_notify() const
Returns true if there is an object configured to be notified when the PGItem changes, false otherwise.
Definition: pgItem.I:72
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:1068
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:726
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:96
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:307
bool get_active() const
Returns whether the PGItem is currently active for mouse events.
Definition: pgItem.I:199
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:1177
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
Definition: pgButton.cxx:71
Similar to MutexHolder, but for a light reentrant mutex.
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
void set_state(int state)
Sets the "state" of this particular PGItem.
Definition: pgItem.I:175
The primary interface to this module.
Definition: textNode.h:52
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:1021
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
This is sent along as a parameter to most events generated for a region to indicate the mouse and but...
virtual void exit_region(const MouseWatcherParameter &param)
This is a callback hook function, called whenever the mouse exits the region.
Definition: pgItem.cxx:568
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:156
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165
virtual void set_active(bool active)
Sets whether the PGItem is active for mouse watching.
Definition: pgItem.cxx:890
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
Definition: nodePath.cxx:723
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:279
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:294
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:694
PGButtonNotify * get_notify() const
Returns the object which will be notified when the PGButton changes, if any.
Definition: pgButton.I:38
bool is_outside() const
Returns true if the mouse was outside the region at the time the event was generated, false otherwise.
void setup(const string &label, PN_stdfloat bevel=0.1f)
Sets up the button as a default text button using the indicated label string.
Definition: pgButton.cxx:178