Panda3D
 All Classes Functions Variables Enumerations
pgButton.cxx
00001 // Filename: pgButton.cxx
00002 // Created by:  drose (13Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pgButton.h"
00016 #include "pgMouseWatcherParameter.h"
00017 
00018 #include "throw_event.h"
00019 #include "mouseButton.h"
00020 #include "mouseWatcherParameter.h"
00021 #include "colorAttrib.h"
00022 #include "transformState.h"
00023 
00024 TypeHandle PGButton::_type_handle;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: PGButton::Constructor
00028 //       Access: Published
00029 //  Description: 
00030 ////////////////////////////////////////////////////////////////////
00031 PGButton::
00032 PGButton(const string &name) : PGItem(name)
00033 {
00034   _button_down = false;
00035   _click_buttons.insert(MouseButton::one());
00036 
00037   set_active(true);
00038 }
00039 
00040 ////////////////////////////////////////////////////////////////////
00041 //     Function: PGButton::Destructor
00042 //       Access: Public, Virtual
00043 //  Description: 
00044 ////////////////////////////////////////////////////////////////////
00045 PGButton::
00046 ~PGButton() {
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: PGButton::Copy Constructor
00051 //       Access: Public
00052 //  Description: 
00053 ////////////////////////////////////////////////////////////////////
00054 PGButton::
00055 PGButton(const PGButton &copy) :
00056   PGItem(copy),
00057   _click_buttons(copy._click_buttons)
00058 {
00059   _button_down = false;
00060 }
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: PGButton::make_copy
00064 //       Access: Public, Virtual
00065 //  Description: Returns a newly-allocated Node that is a shallow copy
00066 //               of this one.  It will be a different Node pointer,
00067 //               but its internal data may or may not be shared with
00068 //               that of the original Node.
00069 ////////////////////////////////////////////////////////////////////
00070 PandaNode *PGButton::
00071 make_copy() const {
00072   LightReMutexHolder holder(_lock);
00073   return new PGButton(*this);
00074 }
00075 
00076 ////////////////////////////////////////////////////////////////////
00077 //     Function: PGButton::enter_region
00078 //       Access: Public, Virtual
00079 //  Description: This is a callback hook function, called whenever the
00080 //               mouse enters the region.
00081 ////////////////////////////////////////////////////////////////////
00082 void PGButton::
00083 enter_region(const MouseWatcherParameter &param) {
00084   LightReMutexHolder holder(_lock);
00085   if (get_active()) {
00086     set_state(_button_down ? S_depressed : S_rollover);
00087   }
00088   PGItem::enter_region(param);
00089 }
00090 
00091 ////////////////////////////////////////////////////////////////////
00092 //     Function: PGButton::exit_region
00093 //       Access: Public, Virtual
00094 //  Description: This is a callback hook function, called whenever the
00095 //               mouse exits the region.
00096 ////////////////////////////////////////////////////////////////////
00097 void PGButton::
00098 exit_region(const MouseWatcherParameter &param) {
00099   LightReMutexHolder holder(_lock);
00100   if (get_active()) {
00101     set_state(S_ready);
00102   }
00103   PGItem::exit_region(param);
00104 }
00105 
00106 ////////////////////////////////////////////////////////////////////
00107 //     Function: PGButton::press
00108 //       Access: Public, Virtual
00109 //  Description: This is a callback hook function, called whenever a
00110 //               mouse or keyboard button is depressed while the mouse
00111 //               is within the region.
00112 ////////////////////////////////////////////////////////////////////
00113 void PGButton::
00114 press(const MouseWatcherParameter &param, bool background) {
00115   LightReMutexHolder holder(_lock);
00116   if (has_click_button(param.get_button())) {
00117     if (get_active()) {
00118       _button_down = true;
00119       set_state(S_depressed);
00120     }
00121   }
00122   PGItem::press(param, background);
00123 }
00124 
00125 ////////////////////////////////////////////////////////////////////
00126 //     Function: PGButton::release
00127 //       Access: Public, Virtual
00128 //  Description: This is a callback hook function, called whenever a
00129 //               mouse or keyboard button previously depressed with
00130 //               press() is released.
00131 ////////////////////////////////////////////////////////////////////
00132 void PGButton::
00133 release(const MouseWatcherParameter &param, bool background) {
00134   LightReMutexHolder holder(_lock);
00135   if (has_click_button(param.get_button())) {
00136     _button_down = false;
00137     if (get_active()) {
00138       if (param.is_outside()) {
00139         set_state(S_ready);
00140       } else {
00141         set_state(S_rollover);
00142         click(param);
00143       }
00144     }
00145   }
00146   PGItem::release(param, background);
00147 }
00148 
00149 ////////////////////////////////////////////////////////////////////
00150 //     Function: PGButton::click
00151 //       Access: Public, Virtual
00152 //  Description: This is a callback hook function, called whenever the
00153 //               button is clicked down-and-up by the user normally.
00154 ////////////////////////////////////////////////////////////////////
00155 void PGButton::
00156 click(const MouseWatcherParameter &param) {
00157   LightReMutexHolder holder(_lock);
00158   PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
00159   string event = get_click_event(param.get_button());
00160   play_sound(event);
00161   throw_event(event, EventParameter(ep));
00162 
00163   if (has_notify()) {
00164     get_notify()->button_click(this, param);
00165   }
00166 }
00167 
00168 ////////////////////////////////////////////////////////////////////
00169 //     Function: PGButton::setup
00170 //       Access: Published
00171 //  Description: Sets up the button as a default text button using the
00172 //               indicated label string.  The TextNode defined by
00173 //               PGItem::get_text_node() will be used to create the
00174 //               label geometry.  This automatically sets up the frame
00175 //               according to the size of the text.
00176 ////////////////////////////////////////////////////////////////////
00177 void PGButton::
00178 setup(const string &label, PN_stdfloat bevel) {
00179   LightReMutexHolder holder(_lock);
00180   clear_state_def(S_ready);
00181   clear_state_def(S_depressed);
00182   clear_state_def(S_rollover);
00183   clear_state_def(S_inactive);
00184 
00185   TextNode *text_node = get_text_node();
00186   text_node->set_text(label);
00187   PT(PandaNode) geom = text_node->generate();
00188 
00189   LVecBase4 frame = text_node->get_card_actual();
00190   set_frame(frame[0] - 0.4, frame[1] + 0.4, frame[2] - 0.15f, frame[3] + 0.15f);
00191 
00192   PT(PandaNode) ready = new PandaNode("ready");
00193   PT(PandaNode) depressed = new PandaNode("depressed");
00194   PT(PandaNode) rollover = new PandaNode("rollover");
00195   PT(PandaNode) inactive = new PandaNode("inactive");
00196 
00197   PGFrameStyle style;
00198   style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
00199   style.set_width(bevel, bevel);
00200 
00201   style.set_type(PGFrameStyle::T_bevel_out);
00202   set_frame_style(S_ready, style);
00203 
00204   style.set_color(0.9f, 0.9f, 0.9f, 1.0f);
00205   set_frame_style(S_rollover, style);
00206 
00207   inactive->set_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.8f, 0.8f, 1.0f)));
00208   style.set_color(0.6f, 0.6f, 0.6f, 1.0f);
00209   set_frame_style(S_inactive, style);
00210 
00211   style.set_type(PGFrameStyle::T_bevel_in);
00212   style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
00213   set_frame_style(S_depressed, style);
00214   depressed->set_transform(TransformState::make_pos(LVector3(0.05f, 0.0f, -0.05f)));
00215 
00216   get_state_def(S_ready).attach_new_node(ready, 1);
00217   get_state_def(S_depressed).attach_new_node(depressed, 1);
00218   get_state_def(S_rollover).attach_new_node(rollover, 1);
00219   get_state_def(S_inactive).attach_new_node(inactive, 1);
00220 
00221   ready->add_child(geom);
00222   depressed->add_child(geom);
00223   rollover->add_child(geom);
00224   inactive->add_child(geom);
00225 }
00226 
00227 ////////////////////////////////////////////////////////////////////
00228 //     Function: PGButton::setup
00229 //       Access: Published
00230 //  Description: Sets up the button using the indicated NodePath as
00231 //               arbitrary geometry.
00232 ////////////////////////////////////////////////////////////////////
00233 void PGButton::
00234 setup(const NodePath &ready, const NodePath &depressed, 
00235       const NodePath &rollover, const NodePath &inactive) {
00236   LightReMutexHolder holder(_lock);
00237   clear_state_def(S_ready);
00238   clear_state_def(S_depressed);
00239   clear_state_def(S_rollover);
00240   clear_state_def(S_inactive);
00241 
00242   instance_to_state_def(S_ready, ready);
00243   instance_to_state_def(S_depressed, depressed);
00244   instance_to_state_def(S_rollover, rollover);
00245   instance_to_state_def(S_inactive, inactive);
00246 
00247   // Set the button frame size.
00248   LPoint3 min_point, max_point;
00249   ready.calc_tight_bounds(min_point, max_point);
00250   set_frame(min_point[0], max_point[0],
00251             min_point[2], max_point[2]);
00252 }
00253 
00254 ////////////////////////////////////////////////////////////////////
00255 //     Function: PGButton::set_active
00256 //       Access: Published, Virtual
00257 //  Description: Toggles the active/inactive state of the button.  In
00258 //               the case of a PGButton, this also changes its visual
00259 //               appearance.
00260 ////////////////////////////////////////////////////////////////////
00261 void PGButton:: 
00262 set_active(bool active) {
00263   LightReMutexHolder holder(_lock);
00264   if (active != get_active()) {
00265     PGItem::set_active(active);
00266     set_state(active ? S_ready : S_inactive);
00267   }
00268 }
00269 
00270 ////////////////////////////////////////////////////////////////////
00271 //     Function: PGButton::add_click_button
00272 //       Access: Published
00273 //  Description: Adds the indicated button to the set of buttons that
00274 //               can effectively "click" the PGButton.  Normally, this
00275 //               is just MouseButton::one().  Returns true if the
00276 //               button was added, or false if it was already there.
00277 ////////////////////////////////////////////////////////////////////
00278 bool PGButton::
00279 add_click_button(const ButtonHandle &button) {
00280   LightReMutexHolder holder(_lock);
00281   return _click_buttons.insert(button).second;
00282 }
00283 
00284 ////////////////////////////////////////////////////////////////////
00285 //     Function: PGButton::remove_click_button
00286 //       Access: Published
00287 //  Description: Removes the indicated button from the set of buttons
00288 //               that can effectively "click" the PGButton.  Normally,
00289 //               this is just MouseButton::one().  Returns true if the
00290 //               button was removed, or false if it was not in the
00291 //               set.
00292 ////////////////////////////////////////////////////////////////////
00293 bool PGButton::
00294 remove_click_button(const ButtonHandle &button) {
00295   LightReMutexHolder holder(_lock);
00296   return (_click_buttons.erase(button) != 0);
00297 }
00298 
00299 ////////////////////////////////////////////////////////////////////
00300 //     Function: PGButton::has_click_button
00301 //       Access: Published
00302 //  Description: Returns true if the indicated button is on the set of
00303 //               buttons that can effectively "click" the PGButton.
00304 //               Normally, this is just MouseButton::one().
00305 ////////////////////////////////////////////////////////////////////
00306 bool PGButton::
00307 has_click_button(const ButtonHandle &button) {
00308   LightReMutexHolder holder(_lock);
00309   return (_click_buttons.count(button) != 0);
00310 }
00311 
 All Classes Functions Variables Enumerations