PreviousUpNext

15.4.1484  src/lib/x-kit/widget/old/fancy/graphviz/get-mouse-selection.pkg

## get-mouse-selection.pkg

# Compiled by:
#     src/lib/x-kit/widget/xkit-widget.sublib

# Various geometric utility routines.
# This assumes a mechanism for allowing only
# one thread at a time to grab the server.


###              "Seek not the favor of the multitude;
###               it is seldom got by honest and lawful means.
###               But seek the testimony of few; and number not
###               voices, but weigh them."
###
###                               -- Immanuel Kant multitude


stipulate
    include package  threadkit;                                         # threadkit             is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
    #
    package g2d =  geometry2d;                                  # geometry2d            is from   src/lib/std/2d/geometry2d.pkg
    package xc  =  xclient;                                     # xclient               is from   src/lib/x-kit/xclient/xclient.pkg
    #
    package xtr =  xlogger;                                     # xlogger               is from   src/lib/x-kit/xclient/src/stuff/xlogger.pkg
herein


    package   get_mouse_selection
    :         Get_Mouse_Selection                               # Get_Mouse_Selection   is from   src/lib/x-kit/widget/old/fancy/graphviz/get-mouse-selection.api
    {
        fun pts_to_box ({ col=>x, row=>y }, { col=>x', row=>y' } )
            =
            {   fun minmax (a:  Int, b)
                    =
                    a <= b   ??   (a, b-a)
                             ::   (b, a-b);

                my (ox, sx) = minmax (x, x');
                my (oy, sy) = minmax (y, y');

                { col=>ox, row=>oy, wide=>sx, high=>sy };
            };

        fun wait_mouse mevt
            = 
            case (block_until_mailop_fires  mevt)
                #
                xc::MOUSE_FIRST_DOWN { mouse_button, window_point, ... } =>  (mouse_button, window_point);
                 _                                                       =>  wait_mouse  mevt;
            esac;


        fun wait_up (display, mevt, cursor)
            =
            loop ()
            where
                fun loop ()
                    =
                    case (block_until_mailop_fires  mevt)
                        #
                        xc::MOUSE_LAST_UP _ =>  ();
                        _                   =>  loop ();
                    esac;

                xc::change_active_grab_cursor  display  cursor;
            end;

        fun get_pt' waitup (window, m) (mbut, state)
            =
            {
                xsession =  xc::xsession_of_window  window;

                reply_slot = make_mailslot ();

                mevt =  if_then' (m, xc::get_contents_of_envelope);                     # "threadkit::if_then'"  is the plain name for   threadkit::(==>).


                fun is_set s
                    =
                    xc::mousebutton_is_set (s, mbut);


                fun do_pt ()
                    =
                    {
                        pt_cursor = xc::get_standard_xcursor
                                        xsession
                                        xc::cursors_old::tcross;

                        #  Need to block output to window subtree 

                        # Create overlay window and
                        # set its cursor:
                        #
                        my { size, ... }
                            =
                            xc::shape_of_window  window;

                        overwin
                            =
                            xc::make_input_only_window
                                window
                                (g2d::box::make (g2d::point::zero, size));

                        xc::set_cursor
                            overwin
                            (THE pt_cursor);

                        xc::show_window  overwin;

                        # Make sure button is up:
                        # 
                        xc::while_mouse_state  is_set  (state, mevt);

                        # Wait for mouse hit:
                        # 
                        my (bttn, pt)
                            =
                            wait_mouse  mevt;

                        if waitup
                            #
                            xc::while_mouse_state  xc::some_mousebutton_is_set (state, mevt);
                        fi;

                        xc::destroy_window overwin;

                        # Unblock output to window subtree:
                        #
                        if (bttn == mbut)   put_in_mailslot (reply_slot, THE pt);
                        else                put_in_mailslot (reply_slot, NULL  );
                        fi;
                    };


                xtr::make_thread  "get_mouse_selection get_pt"  do_pt;

                take_from_mailslot'  reply_slot;
            };

        get_pt       =  get_pt'  FALSE;
        get_click_pt =  get_pt'  TRUE;

        fun get_box (window, m) mbut
            =
            {   xtr::make_thread  "get_mouse_selection get_box"  do_box;
                #
                take_from_mailslot' reply_slot;
            }
            where
                xsession =  xc::xsession_of_window  window;

                black =  xc::black;

                pen = xc::make_pen [ xc::p::FUNCTION    xc::OP_XOR,
                                     xc::p::FOREGROUND  xc::rgb8_color1
                                   ];

                reply_slot = make_mailslot ();

                mevt =  if_then' (m, xc::get_contents_of_envelope);                             # "threadkit::if_then'" is the plain name for  threadkit::(==>).

                fun is_set s
                    =
                    xc::mousebutton_is_set (s, mbut);

                draw =  xc::draw_box
                            (xc::make_unbuffered_drawable  (xc::drawable_of_window  window))
                            pen;

                fun do_box' (pos, clip_g)
                    =
                    loop_box (initr, pos)
                    where
                        cursor = xc::get_standard_xcursor  xsession  xc::cursors_old::tcross;

                        xc::change_active_grab_cursor  xsession  cursor;

                        initr = pts_to_box (pos, pos);

                        draw initr;

                        fun loop_box (r, p)
                            =
                            case (block_until_mailop_fires  mevt)
                                #
                                xc::MOUSE_MOTION  { window_point,               ... } =>  update (r, p, clip_g window_point);
                                xc::MOUSE_UP      { window_point, mouse_button, ... } =>  update (r, p, clip_g window_point);
                                xc::MOUSE_DOWN    { window_point,               ... } =>  update (r, p, clip_g window_point);
                                xc::MOUSE_LAST_UP { window_point, mouse_button, ... } => { draw r;   r;  };
                                _                                                     =>  loop_box (r, p);
                            esac

                        also
                        fun update (oldr, oldp, newp)
                            =
                            if (newp == oldp)
                                #
                                loop_box (oldr, oldp);
                            else
                                newr = pts_to_box (pos, newp);

                                draw oldr;
                                draw newr;

                                loop_box (newr, newp);
                            fi;
                    end;

                fun do_box ()
                    =
                    {
                        box_cursor =  xc::get_standard_xcursor  xsession  xc::cursors_old::sizing;
                        x_cursor   =  xc::get_standard_xcursor  xsession  xc::cursors_old::x_cursor;

                        #  Need to block output to window subtree 

                        # Create overlay window and set its cursor:
                        #       
                        my { size=> size as { wide, high }, ... }
                            =
                            xc::shape_of_window  window;

                        overwin = xc::make_input_only_window
                                      window
                                      (g2d::box::make (g2d::point::zero, size));

                        xc::set_cursor  overwin  (THE box_cursor);
                        xc::show_window  overwin;


                        fun ext_box ({ col, row, wide, high } )
                            =
                            { col, row, wide=>wide+1, high=>high+1 };


                        fun clip ({ col, row } )
                            =
                            { col =>   col < 0   ??   0   ::   (col >= wide ?? (wide - 1) :: col),
                              row =>   row < 0   ??   0   ::   (row >= high ?? (high - 1) :: row)
                            };

                        # Wait for mouse hit:
                        #
                        my (bttn, p)
                            =
                            wait_mouse  mevt;


                        box = if (mbut == bttn)
                                   #
                                   do_box' (clip p, clip);
                               else
                                   wait_up (xsession, mevt, x_cursor);

                                   { col=>0, row=>0, wide=>0, high=>0 };
                               fi; 

                        xc::destroy_window  overwin;

                        #  Unblock output to window subtree 

                        if (mbut == bttn)   put_in_mailslot (reply_slot, THE (ext_box box));
                        else                put_in_mailslot (reply_slot, NULL);
                        fi;
                    };          # fun do_box

            end;                # fun get_box

        # move_box:
        # Move outline of given rectangle on screen.
        # First window argument specifies window making the grab
        # of resources.
        # Rectangle is in coordinates of second window;
        # return final rectangle in coordinates of second window.
        # We assume argument bttn is down; we wait until that
        # button is up to record final rectangle; we return
        # when all buttons are up.

      /*
        fun move_box (ownwin:  Pwin, window:  Pwin, bttn:  Button_State, r:  Box)
            =
            {
                winrect = inq_box window;
                winorigin = origin winrect;

                my (winox, winoy) = coords winorigin;
                my (wincx, wincy) = coords (winorigin + size winrect);

                rsize = size r;
                my (width, height) = coords rsize;
                bttnum = button_num bttn;

                # Make overlay:
                #
                overlay = make_odOverlay_win ownwin;

                # Change cursor:
                #
                set_pointer (overlay, THE move_cursor);

                # Get current mouse position
                #
                my (bttn0, pos0) = inq_pointer overlay;

                # Translate initial r to screen coordinates:
                #
                r0 = translate (r, winorigin)

                # do_box assumes bttn is down.
                # It loops until button is up:
                #
                fun do_box (p: Point, r:  Box)
                    =
                    {   my mouse (bttns, newp)
                            =
                            pw::read_mouse overlay;

                        if (is_up (bttnum, bttns))
                            #
                            # Erase rectangle:
                            draw_box (overlay, r, pn::xor_pen);;
                            r;
                        else
                            my (delx, dely) = coords (newp - p)           ;
                            my (ox, oy) = coords (origin r);

                            # Set new x values:
                            #
                            newox
                                =
                                if   (ox + delx < winox)            winox;
                                elif (ox + width + delx > wincx)    wincx - width;
                                else                                ox + delx;
                                fi;

                            # Set new y values:
                            #
                            newoy
                                =
                                if   (oy + dely < winoy)               winoy;
                                elif (oy + height + dely > wincy)      wincy - height;
                                else                                   oy + dely;
                                fi;

                            newr = g2d::box::make (mkPoint (newox, newoy), rsize);

                            # Redraw only if new rectangle:
                            #
                            if ((ox != newox) or (oy != newoy))
                                #
                                draw_box (overlay, r,    pn::xor_pen);
                                draw_box (overlay, newr, pn::xor_pen);
                            fi;

                            do_box (newp, newr);
                        fi
                      };

                finalr
                    = 
                    if (is_up (bttnum, bttn0))
                        #
                        r0;
                    else
                        # Draw original rectangle:
                        #
                        draw_box (overlay, r0, pn::xor_pen);
                        do_box (pos0, r0);
                    fi;

                # Reset cursor:
                #
                reset_pointer overlay;

                # Wait for buttons up:
                #
                bttns_up overlay;

                # Release overlay:
                #
                del_overlay_win overlay;

                THE (rtranslate (finalr, winorigin));
        };
      */

    };                          # package get 
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext