PreviousUpNext

15.4.1282  src/lib/tk/src/event-loop.pkg

# event-loop.pkg
#   (C) 1996-99, Bremen Institute for Safe Systems, Universitaet Bremen
#   Author: bu/stefan (Last modification $Author: 2cxl $)

# Compiled by:
#     src/lib/tk/src/tk.sublib

#############################################################################
#
#   tk event handler.
#
#   This module implements the tk event handling mechanism -- i.e. 
#   the bit which listens to something coming from Tcl, figures out which
#   naming this corresponds to, and calls the corresponding SML function.
#
#   Further, there are the two functions, start_tcl and start_tcl_and_trap_tcl_exceptions, which
#   launch the application loop and the GUI.
#
#   $Date: 2001/03/30 13:39:10 $
#   $Revision: 3.0 $
#############################################################################



###           "A day will come when beings,
###                now latent in our thoughts
###                    and hidden in our loins,
###            shall stand upon Earth
###                as a footstool and laugh,
###            and reach out their hands
###                amidst the stars." 
###
###                     --  H.G. Wells, 1902



package   event_loop
: (weak)  Event_Loop                    # Event_Loop    is from   src/lib/tk/src/event-loop.api
{
    include package   basic_utilities;
    include package   basic_tk_types;
    include package   gui_state;

    #############################################################################
    #
    # tk's main event handler.
    #
    # This is the 'raw' event handler. Below, we wrap the interrupt handler
    # around this, so diverging event handling functions can be interrupted
    #############################################################################

    fun do_interpret_event s
        =
        {   my kind . window . path . ss
                =
                string_util::words s;
        
            case kind
                
                 "Command"
                     =>
                     widget_tree::select_command_path (window, path) (); 

                 "MCommand"
                     =>
                     {   mitpath = config::read_casc_path (hd ss);
                         widget_tree::select_mcommand_mpath (window, path) mitpath (); 
                     };

                 "SCommand"
                     =>
                     {   newval = the (float::from_string (hd (ss)));
                               
                         widget_tree::select_scommand_path (window, path) newval;
                     };

                 "Destroy"
                     =>
                     {   key  = path; #  no path in Window Namings 
                         ev_v = hd (ss);
                         tkev = tk_event::unparse ev_v;
                         wind = (THE (gui_state::get_window_gui window))
                                    except WINDOWS t => NULL; end ;

                         case wind
                           
                              THE wind => (window::select_bind_key_path window key)tkev;
                              NULL     => ();
                         esac;

                         if   (gui_state::is_init_window  window)
                             
                              com::exit_tcl ();
                              window::delete_all_gui;
                         else
                              window::delete_gui window;
                         fi;
                      }
                      except
                          WINDOWS t = ();

                 "WinNaming"
                     =>
                     {   key  = path; #  no path in Window Namings 
                         ev_v = hd (ss);
                         tkev = tk_event::unparse ev_v;

                         wind = (THE (gui_state::get_window_gui window))
                                except
                                    WINDOWS t = NULL;

                         case wind
                           
                              THE wind =>  (window::select_bind_key_path window key) tkev;
                              NULL     =>  debug::print 1 "got NONEX-WNaming\n";
                         esac;
                      }
                      except
                          WINDOWS t = debug::warning ("Exception WINDOWS: " + t);

                 "WNaming"
                     =>
                     {   my key . ev_v . _  = ss;
                         tkev = tk_event::unparse ev_v;

                         wid  = (THE (widget_tree::get_widget_guipath (window, path)))
                                except
                                    WINDOWS t => NULL;
                                    WIDGET t  => NULL;
                                end ;

                         case wid
                           
                              THE wid =>  (widget_tree::select_bind_key_path (window, path) key) tkev;
                              NULL    =>  debug::print 1 "got NONEX-WNaming\n";
                         esac;
                     }
                     except
                         WIDGET                   t =>  debug::warning ("Exception WIDGET: " + t);
                         canvas_item::CANVAS_ITEM t =>  debug::warning ("Exception CANVAS_ITEM: " + t);
                     end;

                 "CNaming"
                     =>
                     {   my cid . key . ev_v . _  = ss;
                         tkev = tk_event::unparse ev_v;

                         wid  = (THE (widget_tree::get_widget_guipath (window, path)))
                                except
                                    WINDOWS t => NULL;
                                    WIDGET t  => NULL;
                                end ;
                         case wid
                           
                              THE wid =>  (canvas_item::get_naming_by_name wid cid key) tkev;
                              NULL    =>  debug::print 1 ("got NONEX-CNaming\n");
                         esac;
                       }
                       except
                           canvas_item::CANVAS_ITEM t =>  debug::warning("Exception CANVAS_ITEM: " + t);
                           WIDGET                   t =>  debug::warning("Exception WIDGET: " + t);
                       end;

                 "TNaming"
                     =>
                     {    my tn . key . ev_v . _   = ss;
                          tkev = tk_event::unparse ev_v;

                          wid  = (THE (widget_tree::get_widget_guipath (window, path)))
                                 except
                                     WINDOWS t => NULL;
                                     WIDGET t  => NULL;
                                 end;

                          case wid
                             
                               THE wid => (text_item::get_naming_by_name wid tn key) tkev;
                               NULL     => debug::print 1 ("got NONEX-TNaming\n");
                          esac;
                     }
                     except
                         canvas_item::CANVAS_ITEM t =>  debug::warning("Exception CANVAS_ITEM: " + t);
                         WIDGET                   t =>  debug::warning("Exception WIDGET: " + t);
                     end;

                 "VValue"
                     =>
                     debug::print 1 ("event_loop::interpret_event: someone missed VValue");

                 "ERROR"
                     =>
                     {   debug::print 1 ("event_loop::interpret_event: got Tcl Error: \"" +
                                              (string::join " " (window . path . ss)) + "\"");

                         raise exception TCL_ERROR ("event_loop::interpret_event: got Tcl Error: \"" +
                                                (string::join " " (window . path . ss)) + "\"");
                     };

                 _   =>
                     debug::warning ("Tcl junk sent to tk: " + s);
             esac; 
        };

      # except e => debug::warning ("Event::interpret_event: exception " + (exception_name e) +
      #                            " raised (and ignored) with event: " + s) 


      # **********************************************************************
      #
      # Interrupt Handling 
      #
      # I refer the honourable gentleman to the answer I gave earlier.
      #

       lcnt = REF 0;

        Intr_Listener = MAKE_IL  Int;

       listeners = REF [(0, \\()= file::print "[tk] Interrupt.\n")];

       /* Register an interrupt listener, i.e. a function f: Void-> Void to be
        * called when an interrupt occurs. Use sparingly if ever. */
       fun register_signal_callback h
           = 
           { id= inc lcnt; 
             (make_il id) then (listeners := *listeners @ [ (id, h) ]);
           };

       # Deregister this listener -- don't call us, we'll call you:
       #
       fun deregister_signal_callback (make_il id)
           = 
           listeners := list::filter (\\ (lid, _)=> not (lid == id); end ) *listeners;

       # Call all the interrupt listeners:
       #
       fun get_listeners s
           = 
           list::fold_forward (o) (\\ x= x) (map #2 *listeners) s;

       # The 'real' event handler is this one:
       #        
       fun interpret_event s
           =
           sys_dep::interruptable do_interpret_event get_listeners s;

    ########################################################################
    # The main application loop
    # 
    # For the wish, we sometimes need to read Tcl values (e.g. 
    # readCoords, get_val) and while we do so, other Tcl namings may fire. 
    # In this case, these Tcl answers are stored in the COM_state, and 
    # are processed separately by readAnswerFromTcl below.
    ########################################################################

    fun app_loop _
        = 
        while (com_state::wish_active()) {

            com::read_answer_from_tcl interpret_event; 
            interpret_event (com::get_line());
        };

    /***********************************************************************
     *
     * Launching the application loop.
     *
     */


    fun start_tcl ws
        =
        {   com::init_tcl();
            apply window::open_w ws;
            app_loop();
        };

    fun start_tcl_and_trap_tcl_exceptions ws
        = 
        {   start_tcl ws;
            "";
        } 
        except WIDGET                    t =>  "WIDGET: "       + t;
              canvas_item::CANVAS_ITEM   t =>  "CANVAS_ITEM: "  + t;
              WINDOWS                    t =>  "WINDOWS: "      + t;
              CONFIG                     t =>  "CONFIG: "       + t;
              basic_tk_types::TCL_ERROR  t =>  "TCL_ERROR: "    + t;
              text_item::TEXT_ITEM       t =>  "TEXT_ITEM: "    + t;
        end ;

};




Comments and suggestions to: bugs@mythryl.org

PreviousUpNext