home *** CD-ROM | disk | FTP | other *** search
- package sub_arctic.input;
- import sub_arctic.lib.interactor;
- import sub_arctic.lib.manager;
- import sub_arctic.anim.timer;
- import sub_arctic.anim.timer_transition;
- import sub_arctic.anim.transition;
-
- /**
- * This is the agent that handles the pointable interface as well
- * as the display_help interface. It is an agent under the positional policy,
- * but must dispatch events in some cases in which there might be
- * no objects picked by the event. We use the dispatch_unused_event()
- * method on dispatch_agent to get that to work. Further, we use
- * the manager's "after_dispatch" list to get notified when other
- * agents dispatch events.
- *
- * @author Ian Smith
- */
- public class point_agent_class extends dispatch_agent implements timer {
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This is the transition that is currently pending to let us
- * know when the stable time has elapsed. It is null when
- * no transitions are pending.
- */
- protected transition trans = null;
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This variable becomes true if we have a help message displayed
- * right now.
- */
- protected boolean help_displayed = false;
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This holds the number of milliseconds the user must
- * be quiescent with the mouse to get a display help box. It defaults
- * to 1/2 second (500 millis).
- */
- protected long _stable_time = 500;
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Query the amount of time that the mouse must be stable
- * to get a display help box.
- * @return long the amount of stable time required to get a help display
- * (in milliseconds)
- */
- public long stable_time() { return _stable_time;}
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Set the length of time the user must be stable before a display help
- * display is generated.
- * @param long stable the length of time in milliseconds
- */
- public void set_stable_time(long stable) { _stable_time=stable;}
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This variable tells us if we are yet on the managers
- * list of interested agents for the "after_dispatch" notification.
- */
- protected boolean in_list=false;
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Highest event ID seen
- */
- protected int highest_event;
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This is where we keep the object we are currently pointing
- * at (or null to signify the that we aren't pointing at anything).
- */
- protected pointable _point_focus = null;
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Return the current point focus.
- * @return interactor the interactor we are currently pointing at (well,
- * pointing at <I>and</I> which implements the pointable
- * interface).
- */
- public pointable point_focus() { return _point_focus;}
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Set the point focus. Pass null to indicate that there is no
- * object currently in the focus.
- *
- * @param pointable i the new point focus
- * @param event evt the event that caused this change in focus
- */
- public void set_point_focus(pointable i, event evt){
- display_help help;
- event evt_copy;
-
- /* if we are not on the list in manager, we may need to be ...
- * also note that we CAN NOT do this in the constructor of this
- * class because this object is statically initialized in
- * the manager's initialization,
- * thus we would be making calls on the manager before it has
- * completed its own initialization ... also, this allows people
- * who aren't using this agent to not have any event dispatch
- * overhead */
-
- /* be aware that this code is NOT run if the point_focus is
- * not going to change (same object is pointed at)...
- * that will result in a call to mouse_event_same_object()*/
- if (i!=null) {
- /* are we in the list? */
- if ( !in_list) {
- in_list=true;
- manager.add_to_after_dispatch_list(this);
- }
- } else {
- /* check for the other case, as well... are we not in list? */
- if (in_list) {
- in_list=false;
- manager.remove_from_after_dispatch_list(this);
- }
-
- /* do we have any transitions pending?*/
- if (trans!=null) {
- manager.animation.remove_transition(trans);
- trans=null;
- }
- }
-
- /* some new focus ... was there a help message up?*/
- if (help_displayed) {
- help=(display_help)_point_focus;
- evt_copy = new event(evt);
- if (help instanceof interactor)
- evt_copy.global_to_local((interactor)help);
- else
- evt_copy.reset_to_global();
- help.help_close(evt_copy);
- help_displayed=false;
- }
-
- /* change the focus */
- _point_focus=i;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Construct a point_agent. User's should not have to do this,
- * it should be done by toolkit initialization.
- */
- public point_agent_class() {
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * We are only interested for normal dispatching purposes in
- * move events. We get a hold of the other types of mouse events
- * via the manager's "after_dispatch" list and that is how we
- * handle generating a mouse_exit() call.
- *
- * @param event evt the event to check to see if we care about it
- * @return boolean return true if its an event we care about
- */
- public boolean event_is_useful(event evt) {
- return (evt.id()==event.MOUSE_MOVE);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * We override dispatch_unused_event so we can tell the object
- * that the mouse left the area even if the mouse is now not
- * over any of our sub_arctic interactors.
- * @param event evt the event to dispatch
- * @return boolean return true if we dispatched the event
- */
- public boolean dispatch_unused_event(event evt) {
- event evt_copy;
-
- /* make copy of event */
- evt_copy = new event(evt);
-
- /* if we don't have a focus, no work to do */
- if (point_focus()==null) return false;
-
- /* put event in coordinates of object we are dispatching to */
- if (point_focus() instanceof interactor)
- evt_copy.global_to_local((interactor)point_focus());
- else
- evt_copy.reset_to_global();
-
- /* send the message */
- point_focus().mouse_exit(evt_copy);
-
- /* no focus now */
- set_point_focus(null,evt);
-
- /* we handled the event */
- return true;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This is the method that does most of the work for dispatching
- * these events. It determines if the object in question is
- * pointable and if it is sends it the right messages on in and out.
- *
- * @param event evt the event to dispatch
- * @param Object user_info policy defined user information
- * @param interactor to_obj the object to (possibly)send the event to
- * @param int seq_num the sequence number of this event
- */
- public boolean dispatch_event(
- event evt,
- Object user_info,
- interactor to_obj,
- int seq_num) {
-
- pointable p,pf=point_focus();
- event evt_copy = new event(evt);
-
- /* first determine if we care about this object */
- if (to_obj instanceof pointable){
-
- /* make sure we record that we saw this */
- if (seq_num>highest_event) {
- highest_event=seq_num;
- }
-
- /* its ours, is it the one we are already over? */
- p=(pointable)to_obj;
-
- /* is there already a point focus? */
- if (pf!=null) {
-
- /* is it already this object? */
- if (pf==p) {
-
- /* deal with this event */
- mouse_event_same_object(evt);
-
- /* we are done */
- return false;
-
- } else {
-
- /* need to tell them we are not on them anymore */
- if (pf instanceof interactor)
- evt_copy.global_to_local((interactor)pf);
- else
- evt_copy.reset_to_global();
- pf.mouse_exit(evt_copy);
- }
- }
-
- /* reset the focus */
- set_point_focus(p,evt);
-
- /* reschedule the transition for later */
- reschedule_transition();
-
- /* send the enter message */
- if (p instanceof interactor)
- evt_copy.global_to_local((interactor)p);
- else
- evt_copy.reset_to_global();
- p.mouse_enter(evt_copy,user_info);
-
- /* we handled it, so return true */
- return true;
- }
-
- /* if its not pointable we don't care*/
- return false;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This method is called by the manager after an event is
- * dispatched. This agent uses this to become informed of
- * events which were handled by other agents so it can
- * tell clients of its interface that the mouse may have
- * left their area.
-
- * @param event evt the event which was dispatched (or not)
- * @param boolean dispatched true if the event was handled by some agent
- *
- */
- public void after_dispatch_notify(event evt, boolean dispatched) {
- event evt_copy;
-
- /* there are several reasons we might not care about this
- * event: 1) we don't have a point _focus 2) its not an event
- * type we care about 3) its a sequence number we have
- * seen before (thus we've already dealt with it)
- */
- if ((point_focus()==null) ||
- (is_mouse_event(evt)==false) ||
- (highest_event==manager.event_seq_num())) {
- /* we don't care */
- return;
- }
-
- /* make a copy of the event */
- evt_copy = new event(evt);
-
- /* so this is the interesting case... some event got processed
- * and we have a point focus ... we need to tell them we
- * are done
- */
- if (point_focus() instanceof interactor)
- evt_copy.global_to_local((interactor)point_focus());
- else
- evt_copy.reset_to_global();
- point_focus().mouse_exit(evt_copy);
-
- /* reset */
- set_point_focus(null,evt);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This is a convenience method for checking if an event is
- * any of the mouse events.
- * @param event e the event to be tested
- * @return boolean true if the event is a mouse event
- */
- protected boolean is_mouse_event(event e) {
- return ((e.id()==event.MOUSE_MOVE) ||
- (e.id()==event.MOUSE_UP) ||
- (e.id()==event.MOUSE_DOWN) ||
- (e.id()==event.MOUSE_ENTER) ||
- (e.id()==event.MOUSE_EXIT));
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This is called to tell us that the timer we previous scheduled
- * has expired.
- * @param event e the event that caused this timer to expire
- * (currently ignored)
- */
- public void time_expired(event evt /* ignored */) {
- display_help help; /* cause I need somebody...not just anybody */
-
- /* is there a focus now?*/
- if ((point_focus()!=null) && (point_focus() instanceof display_help)){
-
- /* send the starting message */
- help=(display_help)point_focus();
- help.help_open();
- help_displayed=true;
-
- }
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This is called to get a new scheduled transition. The user has
- * moved or clicked, so we need to wait a few more seconds.
- */
- protected void reschedule_transition() {
- /* is there one */
- if (trans!=null) {
- manager.animation.remove_transition(trans);
- }
-
- /* make a new transition and schedule it */
- trans=new timer_transition(this,stable_time());
- manager.animation.schedule_transition(trans);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * This gets called when we get a mouse event, but it is over the
- * same object we were over before.
- * @param event evt the that caused this processing
- */
- public void mouse_event_same_object(event evt) {
- display_help help;
- event evt_copy;
-
- /* reset the transition */
- reschedule_transition();
-
- /* if there is a help message displayed, put it down */
- if (help_displayed) {
-
- help=(display_help)point_focus();
- evt_copy = new event(evt);
- if (help instanceof interactor)
- evt_copy.global_to_local((interactor)help);
- else
- evt_copy.reset_to_global();
- help.help_close(evt_copy);
- help_displayed=false;
-
- }
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- }
-
-
- /*=========================== COPYRIGHT NOTICE ===========================
-
- This file is part of the subArctic user interface toolkit.
-
- Copyright (c) 1996 Scott Hudson and Ian Smith
- All rights reserved.
-
- The subArctic system is freely available for most uses under the terms
- and conditions described in
- http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html
- and appearing in full in the lib/interactor.java source file.
-
- The current release and additional information about this software can be
- found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
-
- ========================================================================*/
-