simple_window.anubis 8.24 KB

   
   
                             The Anubis/Paradize Project.
   
                              The simple window widget. 
   
                         Copyright (c) Alain Prouté 2004-2005. 

   
   Authors:   Alain Prouté
              Olivier Duvernois



read tools/basis.anubis
read widget.anubis


   This file defines  simple 'nude' windows. If you need  more sophisticated windows (with
   boundary and/or scrollbars) see 'widgets3/window.anubis'.
   
   A 'simple window'  is a rectangular area which  is able to show part  of another widget
   (its 'content') through itself:
   
   
        +...........................+
        :                content    :
        :                           :
        :                           :
        :                           :
        :    +-------------+        :
        :    |     window  |        :
        :    |             |        :
        :    |             |        :
        :    |             |        :
        :    |             |        :
        :    |             |        :
        :    +-------------+        :
        :                           :
        :                           :
        +...........................+
        
   
   The window has a position relative to its content. This position should not be confused
   with the position of  the window relative to its parent widget  or relative to the host
   window.  Also a window may change its size. 
   
   The size of a window must eventually be coordinated with the size of another window. It
   may be changed from outside the window, the position of the content may also be changed
   or read  from outside the window, for  example by scrollbars. For  these reasons, these
   dimensions are stored in variables which must be provided at the creation.

   A simple window widget is created by:
   
   
public define Widget
   create_simple_window
     (
       Var(Int32)    win_w,                // width of window
       Var(Int32)    win_h,                // height of window
       Var(Int32)    window_x_scroll,      // position of window relative to its content
       Var(Int32)    window_y_scroll,
       Widget        content, 
     ).

   
   
   --- That's all for the public part ! --------------------------------------------------
   
   
   
   
   
   If  (cont_w,cont_h) is  the size  of the  content, and  (win_w,win_h) the  size  of the
   window, we must always have:
   
        0 =< window_x_scroll =< sup(0,cont_w - win_w)
        0 =< window_y_scroll =< sup(0,cont_h - win_h)
   
   In other words, 'window_x_scroll' is 0 when the window is wider than its content. 
   
     
   The window widget handles events as follows. 
   
     - keyboard event: do nothing, 
     - mouse move event: 
         - if mouse captured: change values of 'window_x_scroll' and 'window_y_scroll'
         - otherwise: transmit to content, 
     - mouse click event:
         - left down: if content does not handle, capture the mouse
         - left up: if mouse captured, uncapture the mouse, otherwise transmit to content
         - other: transmit to content
   
   
   
   *** Managing window event
  
   
   The function 'do_when_moved'  is called at each mouse event when  the mouse is captured
   by the window.
   
define WidgetAnswer
   do_when_moved
     (
       KeyboardState                ks,
       WidgetMouseCapturedEvent     e,
       Widget                       content,
       Var(Int32)                     win_w, 
       Var(Int32)                     win_h,
       Var(Int32)                   window_x_scroll,
       Var(Int32)                   window_y_scroll,
       Var((Int32,Int32))           move_ref
     ) =
   if get_size(content)(unique) is (cont_w,cont_h) then 
   with xe = x(e), ye = y(e), 
   if *move_ref is (mrx,mry) then 
     window_x_scroll <- max(0,min(*window_x_scroll -xe+mrx,cont_w-*win_w));
     window_y_scroll <- max(0,min(*window_y_scroll -ye+mry,cont_h-*win_h));
     move_ref <- (xe,ye);
     handled([rect(0,0,*win_w,*win_h)]). 

   
   
   
   
   if e is 
    {
      moved(x,y)      then 
         if *move_ref is (mrx,mry) then 
           window_x_scroll <- max(0,min(*window_x_scroll -x+mrx,cont_w-win_w));
           window_y_scroll <- max(0,min(*window_y_scroll -y+mry,cont_h-win_h));
           move_ref <- (x,y);
           forget((WidgetPositionToolBox ptb) |-> 
                  set_position(content)(ptb,position(*window_x_scroll,*window_y_scroll)));
           handled([rect(0,0,*win_w,*win_h)]),
      liberated(x,y)  then 
         if *move_ref is (mrx,mry) then 
           window_x_scroll <- max(0,min(*window_x_scroll -x+mrx,cont_w-win_w));
           window_y_scroll <- max(0,min(*window_y_scroll -y+mry,cont_h-win_h));
           move_ref <- (x,y);
           forget((WidgetPositionToolBox ptb) |-> 
                  set_position(content)(ptb,position(*window_x_scroll,*window_y_scroll)));
           handled([rect(0,0,*win_w,*win_h)]),
    }.

   
define WidgetAnswer
   manage_window_event
     (
      WidgetEventToolBox   etb, 
      WidgetNormalEvent    e,
       Widget              content,
       Var(Int32)          win_w, 
       Var(Int32)          win_h,
       Var(Int32)          window_x_scroll,
       Var(Int32)          window_y_scroll,
       Var((Int32,Int32))  move_ref
     ) =
   if e is 
    {
     mouse_gone                 then not_handled([]), 
     mouse_move(ks, x, y)       then not_handled([]),
     mouse_click(ks, mc, x, y)  then  
       if mc is 
        {
          left_down   then 
                (move_ref <- (x,y));
                forget(
                 capture_mouse
                    (etb,
                    (KeyboardState ks1, WidgetMouseCapturedEvent e1) |->
                        do_when_moved(ks1,e1,content,
                                      win_w,win_h,
                                      window_x_scroll,window_y_scroll,
                                      move_ref)));
                 resized,
          left_up      then not_handled([]),
          middle_down  then not_handled([]),
          middle_up    then not_handled([]),
          right_down   then not_handled([]),
          right_up     then not_handled([]),
        }
    }.

   
   
   *** Create Window
    
public define Widget
   create_simple_window
     (
       Var(Int32)    win_w,           // width of window
       Var(Int32)    win_h,           // height of window
       Var(Int32)    window_x_scroll, // position window relative to its content
       Var(Int32)    window_y_scroll,
       Widget        content, 
     ) = 
   with move_ref  = var(((Int32,Int32)) (0,0)),
          monitor = (WidgetMonitoringToolBox mtb, 
                     List(WidgetRectangle) -> One redraw) |->  
                       redraw([rect(0,0,*win_w,*win_h)]),
   create_widget
     (
       /* Set positions of childs */ 
       (WidgetPositionToolBox ptb) |-> 
             set_position(content)(ptb,position(-(*window_x_scroll),-(*window_y_scroll))),
   
       /* Get size */ 
       (One u) |-> (*win_w, *win_h), 
   
       /* Redraw the window */ 
       (WidgetDrawToolBox dtb) |-> 
          redraw(content)(dtb,rect(0,0,*win_w,*win_h)),
   
       /* Duplicate */
       (One u) |-> create_simple_window(win_w,win_h,window_x_scroll,window_y_scroll,
                     duplicate(content)(unique)), 
   
       /* Change size */
       (Int32 w, Int32 h) |-> 
          win_w <- max(10,w); 
          win_h <- max(10,h), 
   
       /* Handle normal events */ 
       (WidgetEventToolBox etb, WidgetNormalEvent e) |-> 
          if main_event_handler(content)(etb,e) is
           {
             not_handled(l)     then join(not_handled(l), manage_window_event
                                    (etb,
                                     e,
                                     content,
                                     win_w,win_h,
                                     window_x_scroll,window_y_scroll,
                                     move_ref)),
             handled(lwr)    then handled(lwr),
             resized         then handled([rect(0,0,*win_w,*win_h)])
           },
   
       /* Register variables to monitor */ 
       (List(WidgetRegistration)) 
         [
          register(win_w,monitor),
          register(win_h,monitor),
          register(window_x_scroll,monitor),
          register(window_y_scroll,monitor),
         ]
     ).