Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

gest_int.C

Go to the documentation of this file.
00001 #include "geom/world.H"
00002 #include "gtex/buffer_ref_image.H"
00003 #include "std/config.H"
00004 
00005 #include "gest_int.H"
00006 
00007 using mlib::PIXEL;
00008 
00009 static bool debug = Config::get_var_bool("DEBUG_GEST_INT",false);
00010 
00011 GEST_INT::GEST_INT(
00012    CVIEWptr& view,
00013    CEvent &d, CEvent &m, CEvent &u,
00014    CEvent &d2, CEvent &u2) :
00015    Simple_int(d,m,u),
00016    _view(view),
00017    _obs(0),
00018    _stack(16),
00019    _drawer(new GestureDrawer()),
00020    _fsa(&_entry),
00021    _keep_history(false),
00022    _num_history(0)
00023 {
00024    // turn on indexing:
00025    _stack.begin_index();
00026 
00027    // for safety, no observers can get listed twice:
00028    _obs.set_unique();
00029 
00030    // If button 2 is pressed, jump to a useless state until button 2
00031    // is released. That way if button 1 gets pressed *while* button 2
00032    // is already pressed, no gesture is processed. This is useful,
00033    // because with the Wacom stylus, it's natural to press button 2
00034    // and also put the stylus to the tablet (which presses button 1).
00035 
00036    // This is a subclass of Simple_int, so the callback paramater to
00037    // Cb must be a CallMeth_t<Simple_int,Event>::_method), so we do a
00038    // cast:
00039    _entry +=
00040       Arc(d2, Cb((_callb::_method) &GEST_INT::null_cb, &_b2_pressed));
00041    _b2_pressed +=
00042       Arc(u2, Cb((_callb::_method) &GEST_INT::null_cb, (State *)-1));
00043 
00044    // Sign up for CAMobs callbacks:
00045    _view->cam()->data()->add_cb(this);
00046 }
00047 
00048 void 
00049 GEST_INT::rem_obs(GestObs* g) 
00050 {
00051    _obs -= g;
00052    if (_obs.empty())
00053       deactivate();
00054 }
00055 
00056 void 
00057 GEST_INT::add_obs(GestObs* g)
00058 {
00059    _obs += g;
00060    activate();
00061 }
00062 
00063 void
00064 GEST_INT::activate()
00065 {
00066    // get tick callbacks:
00067    _view->schedule(this);
00068 
00069    // get down/motion/up events:
00070    VIEWint_list::get(_view)->add_interactor(&_fsa);
00071 }
00072 
00073 void
00074 GEST_INT::deactivate()
00075 {
00076    // tick callbacks:
00077    _view->unschedule(this);
00078 
00079    // down/motion/up events:
00080    VIEWint_list::get(_view)->rem_interactor(&_fsa);
00081 }
00082 
00083 int
00084 GEST_INT::down(CEvent &e, State *&s)
00085 {
00086    // see if any of them observers want it:
00087    for (int k=0; k<_obs.num(); k++) {
00088       if (_obs[k]->handle_event(e,s))
00089          return 0;
00090    }
00091    
00092    // as usual, none did. but just check whether there are any
00093    // interactive widgets begging for it:
00094    DEVice_buttons *btns=(DEVice_buttons *)e._d;
00095    DEVice_2d      *ptr=btns->ptr2d();
00096    RAYhit r(ptr->cur());
00097 
00098    // here they go:
00099    if (e.view()->intersect(r).success() &&
00100        ray_geom(r,GEOM::null) &&
00101        ray_geom(r,GEOM::null)->interactive(e,s))
00102       return 0;
00103 
00104    // as usual, it's up to us to handle this gesture ourselves!
00105 
00106    // start a new one and make sure it's drawn
00107    _stack += new GESTURE(
00108       this, _stack.num(), ptr->cur(), ptr->pressure(), _drawer, e
00109       );
00110 
00111    BufferRefImage *buf = BufferRefImage::lookup(_view);
00112    if (buf && (buf->is_observing()))
00113       buf->add(_stack.last());
00114    else
00115       WORLD::display(_stack.last(), false);
00116 
00117 
00118    return 0;
00119 }
00120 
00121 int
00122 GEST_INT::move(CEvent &, State *&)
00123 {
00124    // mac version can get an up without a down, so this can be 0
00125    if (!DEVice_2d::last)
00126       return 0;
00127 
00128    DEVice_2d* ptr = DEVice_2d::last;
00129 
00130    double MIN_DIST = Config::get_var_dbl("GEST_ADD_MIN_DIST", 2.5, true);
00131    
00132    // XXX - If the camera is moving, then the GESTURE might
00133    // have started in a previous frame, and now be gone from
00134    // da stack.  Just punt this event if so...
00135 
00136    if ( !_stack.empty() ) {
00137       _stack.last()->add(
00138          PIXEL(ptr->cur()),        // location
00139          MIN_DIST,                 // threshold distance for accepting
00140          ptr->pressure()           // pressure
00141          );
00142    } else {
00143       err_adv(debug, "GEST_INT::move: tossing event for missing gesture.");
00144    }
00145    return 0;
00146 }
00147 
00148 int
00149 GEST_INT::up(CEvent &e, State *&)
00150 {
00151    // mac version can get an up without a down, so this can be 0
00152    if (!DEVice_2d::last)
00153       return 0;
00154 
00155    if (_stack.empty()) {
00156       // XXX - If the camera is moving, then the GESTURE might
00157       // have started in a previous frame, and now be gone from
00158       // da stack.  Just punt this event if so...
00159       err_adv(debug, "GEST_INT::move: tossing event for missing gesture.");
00160    } else {
00161       _stack.last()->complete(DEVice_2d::last->cur(), e);
00162 
00163       // Remove from BufferRefImage list if it's observing, else remove
00164       // from the WORLD's list...
00165         
00166       BufferRefImage *buf = BufferRefImage::lookup(_view);
00167       if (buf && buf->is_observing())
00168          buf->rem(_stack.last());
00169       else
00170          WORLD::undisplay(_stack.last(), false);
00171 
00172       for (int k=0; k<_obs.num(); k++)
00173          _obs[k]->notify_gesture(this, _stack.last());
00174    }
00175 
00176    return 0;
00177 }
00178 
00179 void
00180 GEST_INT::start_history()
00181 {
00182    // XXX - ???
00183    err_mesg(ERR_LEV_SPAM, "GEST_INT::start_history()");
00184 
00185    if(!_keep_history)
00186       return;
00187 
00188    assert(_num_history < _stack.num());
00189 
00190    // undisplay gestures in current history, if any
00191    for(int i=0; i<_num_history; i++)
00192    {
00193       err_mesg(ERR_LEV_SPAM, "GEST_INT::start_history() - Clearing history: %d", i);
00194    }
00195 
00196    _num_history = 0;
00197 }
00198 
00199 void
00200 GEST_INT::notify(CCAMdataptr&)
00201 {
00202    // CAMobs virtual method: notification that camera changed.
00203 
00204    // Undisplay any dangling GESTURE
00205 
00206    if (!(_stack.empty() || _stack.last()->complete())) 
00207    {
00208       err_adv(debug, "GEST_INT::move: undisplaying 'dangling' gesture.");
00209       BufferRefImage *buf = BufferRefImage::lookup(_view);
00210       if (buf && buf->is_observing())
00211          buf->rem(_stack.last());
00212       else
00213          WORLD::undisplay(_stack.last(), false);
00214    }
00215 
00216    // Forget previous gestures since they go with the old camera:
00217     _stack.clear();
00218 }
00219 
00220 int
00221 GEST_INT::tick()
00222 {
00223    // look for timeouts etc. here
00224 
00225    return 1;
00226 }
00227 
00228 /* end of file gest_int.C */

Generated on Mon Sep 18 11:39:30 2006 for jot by  doxygen 1.4.4