[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnu-arch-users] Re: [OT] fixing emacs

From: Tom Lord
Subject: [Gnu-arch-users] Re: [OT] fixing emacs
Date: Mon, 1 Sep 2003 11:01:28 -0700 (PDT)

    > From: "Stephen J. Turnbull" <address@hidden>

    >     Tom>    Rather, I want certain buffers that, when I have a window
    >     Tom> on those buffers, the emacs text redisplay isn't involved at
    >     Tom> all.  Instead, there's a widget-tree in that window -- whose
    >     Tom> structure is (dynamically) determined by the contents of the
    >     Tom> text buffer.

    > You're right, this is not what we're doing.  What we have is a widget
    > tree whose structure and content is determined dynamically by Lisp
    > code.  [....] I don't see the advantage in using (presumably)
    > unstructured text over Lisp code, especially in this context where a
    > lot of what we're doing looks like TeX's "a vbox containing a list of
    > hboxes containing a list of vboxnes containing ... a list of primitive
    > functional widgets".

    > Show me (examples of) the proposed buffer contents and explain the
    > desired semantics.  I don't see how this can work to advantage.  

In widget trees, roughly speaking, the internal nodes are doing
layout, and the leaf nodes are doing the actual interaction.

Let's start by identifying a set of leaf-widget types for which we can
also make a reasonable text implementation.   For example, we might

        choose one item from a short list       -- a radio-button set

           in text:

                itemA [ ]       itemC [ ]
                itemB [X]       itemD [ ]

        choose one item from a long list        -- a scrollable list

           in text:

                itemM           itemP           itemS
                itemN           *itemQ*         itemT
                itemO           itemR           *itemU*

           (with hidden text between "--prev--" and "itemM" and between
            "*itemU*" and "--next--")

        choose n items from a short list        -- a checkbox set

        choose n items from a long list         -- a scrollable list

        fill in a short text string             -- a text entry widget
             special cases for 
               (existing?) filename
               (existing?) dirname
               (existing?) buffer

        choose a scalar value                   -- slider + label


(Note that the mapping from what I'm calling "leaf widgets" to the
primitive widget types of the toolkit doesn't have to be exact.  A
button or a "slider + label" may be a composite in the toolkit but we
can still think of it as a leaf widget for our purposes here.)

Each of those widget types has a natural text+properties
representation.  For example, "choose a scalar value" may be painted
in text as:

        Red [0..255]: ______

with text properties giving hints to the text major mode where the
point should be moved to, and where self-insert-command does
something, and what kinds of input validation are required

Meanwhile, if rendered as a slider widget, the label for the widget
and the range of values can be parsed from the text, layout hints
(e.g., horizontal or vertical, where does the label go, etc.) can be
snarfed from text properties (i.e., they don't have to make the text
buffer ugly).

When this buffer is displayed as a widget, the text in the "____"
(plus some other state, such as its previous valid value and whether
the major mode has put the text widget in "edit mode") get fed into
the widget.  E.g., if a program inserts (in the usual way) 123 in that
space, then at the next redisplay cycle, you set the widget (slider
position, in this case) to 123; if a program says "This field is in
edit mode" and then (presumbably interactively) the user types 
"__1-!-___" (where -!- is the point) then you wait to update the
widget until the field is no longer in edit mode.   If a program
changes the label ("Red" -> "red") you can propogate that, too.

What about input from the widget?  Behind the scenes, Emacs is getting
callbacks from the widget and you probably have a choice between lower
and higher level callbacks (e.g., mouse events on the slider
vs. pre-wired higher level events like "user chose a new value for
this scalar").  I think that as a rule of thumb you'll want to use the
lower-level callbacks, and probably to map them to new event types.
So, for example, a mouse event on the slider might generate an event
of type:

        [slider mouse-down-1]

with the event itself containing hints about _which_ slider.  The
mouse-motion-with-button-down events would normally be read by a
command that inserts the updated value in the text (not putting the
text widget into edit mode -- taking it out of edit mode if it is
already in edit mode) and then calls `(sit-for 0)'.

You can go through a similar exercise for each leaf-widget type.

So what about layout?  In general, attractive text layout and
attractive widget-tree layout will be distinct -- only very
subjectively related.  So, I would do it this way:

Divide the text buffer into distinct "screens" -- each of which
defines a single, window-filling widget tree.   Each screen will
contain a number of leaf widgets.

Each leaf widget should have a text property set that spans exactly
the text region of that leaf widget.  Each screen-region should have a
text property that spans the entire screen, and whose value is the
layout specification.  The layout specification can be whatever you
currently use: a cons-pair tree of HBOX and VBOX lists is fine.

The leaf nodes of the layout specification tree should be markers --
each marker pointing to the textual location of the appropriate leaf

For extra fanciness, I guess you could (optionally) display a buffer
containing multiple screens as a tabbed widget that switches betwen
them.    When displayed as text, perhaps this would correspond to
narrowing to the region of one screen at a time, with some navigation
commands between screens.

Here's a slight subtlety that illustrates the potential benefits of
this approach.  Widget toolkits generally have some notion of
"keyboard focus" -- so the keyboard is "talking to" to a particular
widget at one time.  I don't think you want to expose keyboard focus
directly to Emacs Lisp or require that it works _precisely_ the same
way in Emacs as it does in other applications using the same toolkit
[*!].  Instead, you want an automatic mapping between the keyboard
focus of the widget and the position of the point in the text buffer.

Why does that work out nicely?  Let's suppose that I have a widget
tree with several text entry fields, with the indicated point position
(i.e., in the text buffer):

        source archive: -!-__________
        source revision: __________
        dest archive: __________
        dest revision: __________
        project tree: __________

        [do it]         [cancel]        [preview]

In the corresponding widget view, I have those text entry widgets and
three buttons.  There's a blinking cursor in the "source archive" text

One immediate benefit is that since events are routed through the text
buffer interpretation, I have the full range of Emacs commands
available for editting the text entry widget, regardless of the
capabilities of the underlying toolkit.  (E.g., I might C-x r g A (aka
M-x insert-register A RET) -- or type "l o r TAB" to invoke M-x

And then slickness like this:

Using the widget display, I decide that I want to push the preview
button.    Sure, I could reach for the mouse -- but I could also:

        C-s p r e RET RET

(Incremental search, start to spell "preview", see that the preview
button has gained keyboard focus, hit RET to leave incremental search,
hit RET to push the button.  Notice how the nice
lightweight-modalities of the Emacs interact loop are preserved and
extended to the widget interface (i.e., the brief excursion into the
isearch keymaps).  Notice how the unified, mostly-flat representation
(the text buffer) nicely fixes the UI glitches that GUI applications
typically have because the tree-structure of the widgets is
over-exposed in input processing.)

And note that that behavior isn't specially programmed -- it falls out
of the low-level implementation:

        1) widget keyboard focus and (point) are related

        2) the visible text in the widgets is part of the text buffer
           including both "field values" and "widget labels"

        3) widget callbacks are translated into Emacs events that 
           make sense from the perspective of the text buffer

Another nice side effect is that I can save these text buffers with
properties and (with appropriate modes):

        1) Display both the text buffer and widget tree
           simultaneously, hot connected, in separate windows

        2) Edit the leaf widgets directly in the text buffer, with
           instant feedback in the widget tree

Add a text mode for editting layout properties and you've got a
really nice application builder, nearly "for free".

[*!] (About widget keyboard focus being handled by Emacs instead of
      the toolkit.)

     Yes, it is important to make sure that the accessability features
     lost by doing that are replaced by comparable features on the
     Emacs side.  (But won't it be nice to have applications in which
     those features can be extended and customized by Emacs lisp

    >     Tom> c) How far are you, really, from being able to mutually merge
    >     Tom> with GNU emacs.  Two forks is cool -- one-way forks is lame.

    > There will be no merger.  It's not our choice, it's GNU's.  The offer
    > on the table is "abandon existing XEmacs code and reimplement it from
    > scratch in GNU Emacs."[1]  Oh, and "forget about abstract data types
    > and orthogonal APIs; they don't fit our programming style."  Not to
    > mention, "of course we'll look at all contributions, but the GNU
    > maintainer will make the final decisions on the basis of GNU's needs."
    > The same setup that was offered to Lucid---nothing has changed in 12
    > years, I think nothing will in the next 12.

If the functionality sketched above can be implemented, I'd ideally
like to see it available for both Emacs (whether or not or regardless
of when it became part of GNU).   I'd ideally like to see it
implemented in a way that doesn't create _new_ legal problems for
merging into GNU.   I'd ideally like to see it implemented in a way
that programs using the feature are portable between the Emacsen.
That's all.



    > >>>>> "Tom" == Tom Lord <address@hidden> writes:

    >     Tom> A couple of things:

    >     Tom> a) I can't even freekin' build out of the box on my box.

    > What system and what is the error message?  What version of XEmacs?
    > Did you get it from or from a ports distribution?

checking for buggy gcc versions... yes
configure: warning: Don't use -O2 with gcc 2.7.2 under Intel/XXX without also 
configure: warning: -fno-caller-saves.
configure: error: Aborting due to known problem

    >     Tom>    Well, fine -- then don't use those options and compile.

    > I assume you've unset CFLAGS in the environment, and didn't use
    > --cflags?  


reply via email to

[Prev in Thread] Current Thread [Next in Thread]