[comp.windows.x] Deficiency in the translation mechanism

pc@ukc.ac.uk (R.P.A.Collinson) (01/22/89)

I have begun to write X applications programs recently and have come
across what I believe to be a deficiency in the way that event
translations are handled. It may be that I am missing something
and there is a solution to this, if so then please let me know.

Example problem:

	Create a text data entry area which acts in the exactly the
same way as the existing text widget but which only permits one line
of data to be entered. All actions which will cause a newline to be
entered - or which deal with line oriented functions (e.g.
scroll-one-line-down()) should cause the bell to ring on the console.

	This *should* interwork in the same applications program with
`normal' text area widgets.

Sample use: 

	a dialog box asking for a filename.

Current solution (1):

You supply a translation table which binds

	<Key>Return	to	Bell()

rather than

	<Key>Return:	newline()

This is not good enough to my thinking. It means that the application
writer has to second guess the bindings which the user may or may not
supply for all these actions. What is *really* needed is the ability
to alter the action of newline().

Registering an action table for newline() does not work because this
is not widget specific. It alters every newline() action in the
program.

Registering an action table for newline() and then calling the old
newline() code does not work because the old newline code is private.

Current solution (2):

Write a new widget which replicates most of the code in the text
widget.

Question:

	Why should all problems be solved by writing widgets? I do
intend to get involved with the full horror of this at some point in
the near future but at the moment it seems to a good idea to write
applications programs.  Eventually I guess we will enter the realm of
binary only X libraries and so this solution will not be available to
people.

	Anyway, all I want to do is to be able to selectively replace
the actions for a known widget with my own actions.  After all a
OneLineTextWidget will be forced to copy most of the source from a
normal TextWidget which seems a little wasteful.

Any help gratefully received.

Peter Collinson
pc@ukc.ac.uk

sundar@WHEATIES.AI.MIT.EDU (Sundar Narasimhan) (01/25/89)

   Current solution (2):

   Write a new widget which replicates most of the code in the text
   widget.

You are right. I decided after careful evaluation (and actually using
the text widgets provided in the Athena and Hp Widget sets) to do just
this. (But I don't think that it is the translation mechanism that is
at fault, but rather the poor interface or hooks provided by current
text widgets to the application writer).

The way I think it should have been done is to have before, during,
and after procedures that an application can alter or supply (these
could be just callbacks but you really want to have something more
like Lisp machine method combinations). The hp widget actually
provides you such a facility (it has Verify callbacks on modification,
for example).

With this capability writing a field editor that returns on carriage
return would be simple. I have, in fact a command and argument parser,
that for example dispatches on characters like ' ' to attempt
completing what the user typed, provide help etc. Notice that some of
these operations may involve modifying the text, the cursor position
etc.. operations which are very cumbersome to do in the current text
edit widgets at the application level. It will also provide you a
simple way to implement a tty window -- (a widget that just scrolls
error messages is actually hard to do with the present text widgets --
I know this facility can also be gotten by running xterm in slave mode but
then you'd have a whole extra process to contend with).

I think that such an interface to a text widget is more powerful than
the ones provided by the current widgets, and will make the widget
useable in more applications. (Mine is currently being used by
programs in a multiprocessor development environment, a plotter
program, and an experimenatal motion vision analysis package -- but it
runs only on Suns at this time).

-Sundar

kit@ATHENA.MIT.EDU (Chris D. Peterson) (01/27/89)

> You supply a translation table which binds

> 	<Key>Return	to	Bell()

> rather than

>	<Key>Return:	newline()

> This is not good enough to my thinking. It means that the application
> writer has to second guess the bindings which the user may or may not
> supply for all these actions.

There is no need to replace the entire translation table, just use 
XtOverrideTranslations() in your application to override only the
translation for Return.

This is what xman does for its "search" prompter, the code is publically
avaliable:

R3:		clients/xman/

Even better is to add a line it the AppDefaults file that overrides
the translations.

foo.bar.baz.text_widget:  #override \n\
	   		  <Key>Return:	newline()

						Chris D. Peterson     
						MIT X Consortium /
						Project Athena 

Net:	kit@athena.mit.edu		
Phone: (617) 253 - 1326			
USMail: MIT - Room E40-321
	77 Massachusetts Ave.		
	Cambridge, MA 02139		

alan@metasoft.UUCP (Alan Epstein) (01/27/89)

In article <8901261848.AA02930@DORA.MIT.EDU>, kit@ATHENA.MIT.EDU (Chris D. Peterson) writes:

> There is no need to replace the entire translation table, just use 
> XtOverrideTranslations() in your application to override only the
> translation for ....

In tweaking the asciiStringWidget, I wanted to remap the <Key> event
to do an additional step. Unfortunately, the placement of the <Key>
event in the default translation table with respect to other 'modified'
<Key> events, allowed it to do the right thing, whereas adding an
#override <Key> event caused the other modified <Key> events to be
ignored.

Does this mean that XtOverrideTranslations places the new bindings
at the start of the table?

-----------------------------
Alan Epstein
Meta Software Corp                   UUCP:  ...bbn!metasoft!alan
150 Cambridgepark Dr        Internet/ARPA:  alan%metasoft@bbn.com
Cambridge, MA 02140  USA
-----------------------------

pc@ukc.ac.UK (Peter Collinson) (01/28/89)

You miss the point.

Suppose the user has bound ^U to previous-line() because they believe
that ^U means `UP' rather than ^P being `PREVIOUS'.  The current
mechanism does not allow me as an application writer to trap that... I
will have trapped and replaced the binding

	^P -> previous-line()

I want to replace the ACTION

	previous-line()

by something and not the bindings.

rlh2@ukc.ac.uk (Richard Hesketh) (01/31/89)

In article <8901261848.AA02930@DORA.MIT.EDU> kit@ATHENA.MIT.EDU (Chris D. Peterson) writes:
>
>> You supply a translation table which binds
>
>> 	<Key>Return	to	Bell()
>
>> rather than
>
>>	<Key>Return:	newline()
>
>> This is not good enough to my thinking. It means that the application
>> writer has to second guess the bindings which the user may or may not
>> supply for all these actions.
>
>There is no need to replace the entire translation table, just use 
>XtOverrideTranslations() in your application to override only the
>translation for Return.
>

I think the point Peter was trying to make is that although it is very easy
to override the event-to-action bindings by replacing the action called
when a particular event sequence is caught.  It is impossible to replace the
action side of the translations.  For example he wants to catch all calls
to the "newline()" action and therefore wishes to replace the "newline()"
action defined in the textWidgetClass with a "newline()" action defined
by the application.

The fact that the user can modify the translations from a defaults file
so that s/he could specify that the "newline()" action is called by,
say the <Meta><Shift><Key>[ sequence cannot be guessed by the application.
Just because a widgetclass defines actions does not mean that an application
wants them to be used.  The application may not want a particular action
to be ever called in a particular widget instance.  However the action
can still be called by the user specifying an event-to-action binding in a
defaults file and therefore upsets the designed interface!

Would any of the toolkit designers care to comment on the usefulness of
having a facility to override the action tables defined in widget classes
for particular widget instances?  Would the inclusion of an action resource
in the core part of the instance record be applicable or are we missing
something important which precludes this facility?

Richard Hesketh   :   rlh2@ukc.ac.uk    ..!mcvax!ukc!rlh2
---                                               
Computing Lab., University of Kent at Canterbury,
Canterbury, Kent, CT2 7NF, England.               

asente@decwrl.dec.com (Paul Asente) (02/02/89)

In article <31@harrier.ukc.ac.uk> rlh2@ukc.ac.uk (Richard Hesketh) writes:
>Would any of the toolkit designers care to comment on the usefulness of
>having a facility to override the action tables defined in widget classes
>for particular widget instances?  Would the inclusion of an action resource
>in the core part of the instance record be applicable or are we missing
>something important which precludes this facility?

I'm always happy to comment on anything whatsoever!

It would definitely be useful to be able to change action bindings.  For
example, you might have a text editing widget with an action for "visit
new file".  In a particular application, you might want this to call your
own version of the action procedure to make use of additional context (the
current directory, for example).  Modifying the translation table to do
this only works assuming that the user hasn't changed the default binding
for this action (e.g. the default binding might be escape-f for find file,
but the user might have rebound it to control-x control-v).

What is really needed here is a way to rebind an action name to a
different or an additional action procedure.  While this would be useful
on a per-widget rather than a per-class basis, that is unlikely to happen
since it would involve changing the core widget records, something we are
reluctant to do any more.  However, it could certainly be done on a
per-class basis, and the new class action procedure could do different
things depending upon the widget it's being passed.

You really need several new functions:
    XtAddActionName(widgetClass, actionName, newActionName)
to add a new name to an action procedure so you can still get to it after
you do an
    XtReplaceActionBinding(widgetClass, actionName, newActionProcedure)
to replace an action procedure with a new one.  You also need
    XtCallActionProc(widget, actionName, event, params, numParams)
to call the original action procedure from within your new action
procedure, if appropriate.  This last function is generally useful,
anyway; application should be able to call action procedures by name.

Anybody on the intrisics list think these are important enough to make
into a formal proposal?

	-paul asente
	    asente@decwrl.dec.com	decwrl!asente