PreviousUpNext

15.3.718  src/lib/x-kit/widget/old/menu/popup-menu.api

## popup-menu.api
#
# See bottom-of-file comments
# for an extended overview.

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

# This api is implemented in:
#
#     src/lib/x-kit/widget/old/menu/popup-menu.pkg

stipulate
    include package   threadkit;                                # threadkit             is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
    #
    package xc =  xclient;                                      # xclient               is from   src/lib/x-kit/xclient/xclient.pkg
    #
    package g2d=  geometry2d;                                   # geometry2d            is from   src/lib/std/2d/geometry2d.pkg
    #
    package wg =  widget;                                       # widget                is from   src/lib/x-kit/widget/old/basic/widget.pkg
herein

    api Popup_Menu {

        Popup_Menu(X)
            =
            POPUP_MENU  List( Popup_Menu_Item(X) )

        also
        Popup_Menu_Item(X)
          #
          = POPUP_MENU_ITEM  (String, X)
          | POPUP_SUBMENU    (String, Popup_Menu(X))
          ;

        # Return values by which the user-supplied
        #
        #     attach_positioned_menu_to_widget
        #
        # callback function can communicate
        # its menu-placement choice:
        # 
        Popup_Menu_Position
          #
          = PUT_POPUP_MENU_UPPERLEFT_ON_SCREEN  g2d::Point              # Position the popup menu's upper-left corner at this screen coordinate.
          | PUT_POPUP_MENU_ITEM_BENEATH_MOUSE  Int                      # Position the popu menu with mouse cursor centered over given item (0 is first item).
          ;

        # Info from the MOUSE_FIRST_DOWN event
        # triggering the menu pop-up:
        # 
        Where_Info
            = 
            WHERE_INFO 
              { mouse_button:  xc::Mousebutton,
                window_point:  g2d::Point,
                screen_point:  g2d::Point,
                timestamp:     xc::xserver_timestamp::Xserver_Timestamp
              };

        # Create unlabeled menu:
        #
        attach_menu_to_widget
            :
            ( wg::Widget,                                               # Parent widget for the menu.
              List(xc::Mousebutton),                                    # Pop up menu if any of these buttons are pressed.
              Popup_Menu(X)                                             # Menu to pop up.
            )   
            ->
            ( wg::Widget,                                               # Resulting combined widget.
              Mailop(X)                                                 # 'do_one_mailop' on this to get user menu selections.
            );

        # Same as above, except menu is labelled:
        # 
        attach_labeled_menu_to_widget
            :
            ( wg::Widget,                                               # Parent widget for the menu.
              List(xc::Mousebutton),                                    # Pop up menu if any of these buttons are pressed.
              String,                                                   # Label for menu.
              Popup_Menu(X)                                             # Menu to pop up.
            )
            ->
            ( wg::Widget,                                               # Resulting combined widget.
              Mailop(X)                                                 # 'do_one_mailop' on this to get user menu selections.
            );

        # Same as attach_menu_to_widget except menu
        # placement is specified:
        #
        attach_positioned_menu_to_widget
            :
            ( wg::Widget,                                               # Parent widget for the menu.
              List(xc::Mousebutton),                                    # Pop up menu if any of these buttons are pressed.
              Popup_Menu(X),                                            # Menu to pop up.
              Where_Info -> Popup_Menu_Position                         # User function to position the menu at pop-up time.
            )
            ->
            ( wg::Widget,                                               # Resulting combined widget.
              Mailop(X)                                                 # 'do_one_mailop' on this to get user menu selections.
            );

        # A lower-level call allowing finer control:
        #
        make_lowlevel_popup_menu
            :
            ( wg::Root_Window,
              Popup_Menu(X),
              Null_Or(String)
            )
            ->
            ( xc::Mousebutton,
              Popup_Menu_Position,
              g2d::Point,
              Mailop( xc::Envelope(xc::Mouse_Mail))
            )
            ->
            Mailop( Null_Or(X) );

    };
end;

# OVERVIEW:
#
#      The x-kit widgets currently provide a simple form
#      of pop-up menu support in the popup_menu package. 
#
#      A MENU value specifies the structure of a menu
#      and the value associated with each entry.
#
#      The SUBMENU constructor is used for defining
#      hierarchical menus.  The menu remains displayed
#      and active as long as some mouse button is depressed.
#      The user's choice corresponds to the item under the
#      mouse cursor when the last mouse button is released.
#
#      One a menu has been defined, there are various ways
#      it can be used.
#
#      The simplest way is to attach it to a widget
#      using one of the two attach functions:
#
#          attach_menu_to_widget                # For menus without labels.
#          attach_labelled_menu                 # If a label is desired.
#
#      The result of attaching a menu to a widget is a
#      new widget and a mailop that provides the user's
#      menu choices.
#
#      When attaching a menu to a widget, the programmer
#      specifies the mouse button that is to pop up the menu.
#          When the user presses the specified mouse button
#      while the cursor is over the widget to which the
#      menu is attached, the menu pops up.
#          Any other mouse button press events, and all
#      other mouse events, are passed on to the underlying
#      widget.
#          If the user selects a menu item, then the
#      associated value is reported through the mailop.
#      If the user does not select an item, nothing is
#      reported.
#
#      attach_positioned_menu_to_widget
#          Same as attach_menu_to_widget, but provides control
#          over menu placement.  In particular, it can be
#          used to implement menu buttons.
#              When a  mouse button press triggers
#          the display of the menu, the user-supplied
#          callback function is invoked with a value
#          of type Where_Info, containing the information
#          supplied by the MOUSE_FIRST_DOWN event               # MOUSE_FIRST_DOWN      def in    src/lib/x-kit/xclient/src/window/widget-cable-old.pkg
#          corresponding to the button press.
#              The callback returns a Popup_Menu_Position
#          value specifying its choice of menu position,
#          which is honored so long as it allows the
#          complete popup menu to appear on-screen.
#
#     make_lowlevel_popup_menu:
#         At times the above high-level popup menu
#         interfaces do not provide enough control.
#
#         This function takes a Root_Window, a Popup_Menu,
#         and an optional string and returns a function
#         which pops up the given menu on the given display.
#
#         To use the popup fn a thread waits for some
#         mouseclick and then calls the popup fn with
#
#            ( clicked_button,                  # Mousebutton that activated the popup menu.
#              desired_popup_menu_position,     # Where onscreen to position the popup menu.
#              mouseclick_position,             # Position onscreen of clicked_button.
#              from_mouse'                      # Mailop yielding the mouse events.
#            )
#
#         The popup fn returns a popup_menu_result'
#         mailop which yields NULL if the user
#         made no selection, otherwise THE selection.
#
#         The calling thread should not read from
#         from_mouse' while the popup fn is running.
#
#         One package which uses this call:
#
#             src/lib/x-kit/widget/old/fancy/graphviz/graphviz-widget.pkg
#       
# Credit: The above comments are adapted from
# p36-37 of Gansner+Reppy's 1993 eXene widget manual,
# http://mythryl.org/pub/exene/1993-widgets.ps

## COPYRIGHT (c) 1991 by AT&T Bell Laboratories  See SMLNJ-COPYRIGHT file for details.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext