Menu and Keystroke Configurator
©1996-2009 Roedy Green, Canadian Mind Products
This essay does not describe an existing computer program, just
one that should exist. This essay is about a suggested
student
project in
Java programming. This essay gives a rough overview of how it
might work. I have
no source, object, specifications, file layouts or
anything else useful to implementing this project.
This project outline is not like the artificial tidy problems you are spoon-fed
in school, when all the facts you need are included, nothing extraneous is
mentioned, the answer is fully specified, along with hints to nudge you toward a
single expected canonical solution. This project is much more like the real
world of messy problems where it is up to you to fully the define the end point,
or a series of ever more difficult versions of this project, and research the
information yourself to solve them.
Everything I have to say to help you with this project is written below. I am not
prepared to help you implement it; or give you any additional materials. I have
too many other projects of my own.
Though I am a programmer, I don’t do people’s homework
for them. That just robs them of an education.
You have my full permission to implement this project in any way you please and
to keep all the profits from your endeavor.
Please do not email me about this project without reading the disclaimer above.
Introduction
The big advance of Windows over DOS was not the GUI or the mouse, but CUA, the
Common User Interface. To a very large extent, all Windows programs work the
same way. This makes learning easier, and switching from app to app easier.
However, in Windows, though the mouse actions were standardised, the keystrokes
were left in chaos. In Java and KDE there is even greater chaos.
I propose imposing a standard on them too, and implementing it first as part of
Java, or as part of Linux KDE to leapfrog past Windows in ease of use. The
beauty of my idea is it does not impose any particular menu or keystroke
assignment structure on anyone, not even the end user. I propose both greater
order and greater freedom to easily configure things just the way you
want, either globablly or on a per app basis using a standard set of tools.
I want menus globally configurable so the layout is almost the same in every
program, so that FIND is on the same position in every program, and accessible
with the same accelerator keystroke. I don’t want to have to configure
every program separately. I want to configure how I like my menus and
accelerators once and for all and be done with it.
Here is how it works.
- Function key to function mapping is global. In one place, the end user
can tell the system that F8 means SAVE, and instantly all conforming apps start
using F8 to mean save. I don’t have to configure each app individually,
using a zillion different configuring schemes. These configurations are saved on
a per-user basis so that different users of a machine can have different
assignments.
- There are perhaps a dozen registered standard ways that Search and Search/Replace
work. I can configure globally which scheme I prefer. I can plug in yet
another one from a third party if none of the standard ones are suitable.
- I can reconfigure the Ctrl-C, Ctrl-X, and Ctrl-V keys so that they will be
convenient for one-handed use on keyboard layouts other than the standard QWERTY.
- The menu structure and accelerator keys are fully user-configurable in a
completely standard way. You can reorder the menus, or remove items from them
you don’t want to use. This is handled by an intelligent merging of global
and app defaults.
- The application programmer does not hard code in particular keystrokes or menu
item positions. He specifies only standard function names. If he has some
special keystroke function key needs not covered by the standard set, he gives
them configurable names, and configured by the same utility.
- Standard functions would include those on the Sun keycaps:
Help
Stop
Props
Front
Open
Find
Again
Undo
Copy
Paste
Cut
plus others commonly found in apps such as:
Help
Open
save
Save All
Close
Close All
New
Print
Search
Search Back
Replace
Replace Back
Calculate
Exit
Undo
Cut
Copy
Paste
Go To
Bookmark
Font
Upper Case
Lower Case
Book Title Case
Validate
Configure
Tile
Tile Vertical
Tile Horizontal
Cascade
Horizontal Split
Vertical Split
I would expect this list to have hundreds of items by the time you were done.
- Normally menu items would be named in a standard way to match the function names.
- Each app does the analogous thing for that command, not necessarily the exact
same thing, e. g. VALIDATE might spell check in a word processor, and check HTML
syntax is a validator.
- There are perhaps a dozen different scrolling schemes registered. The end user,
can globally, in one place, configure which one he likes best and all conforming
apps instantly start using it. If he does not like any of them, he can buy a
plug-in replacement from some third party and configure that.
- The help file mechanism automatically displays the current function key
assignment, menu, and accelerators as well as the function name when discussing
various functions.
- The global configurator lets you print a compact cheat sheet for any app of the
function keys supported, or the fully expanded menu structure.
- Similarly, the generated menus have an automatically generated menu item under
help called "Keys" It displays a cheat sheet showing you all the
current keystroke accelerators (less the ones discribed directly on the menus.)
and their function and hover help.
Implementation
What sorts of file would you need to manage a global keystroke and menu
reconfiguring scheme? These are not necessarily flat files. The menu management
must be able to get at them easily. Perhaps they could be stored used the
Configuration api.
Global.PossibleFunctions
Global list of possible functions that may be supported in any program, either
by keystroke or menu. There is only one such file per user. It would have, at a
minimum, a list of all possible functions that can be globally configured for
all applications. The list need not be complete, e. g.
Help
Open
save
Save All
Close
Close All
New
Print
Search
Search Back
Replace
Replace Back
Calculate
Exit
Undo
Cut
Copy
Paste
Go To
Bookmark
Font
Upper Case
Lower Case
Book Title Case
Validate
Configure
Tile
Tile Vertical
Tile Horizontal
Cascade
Horizontal Split
Vertical Split
This list could come from three possible sources:
- The group that writes the automenu code and who define the official common
functions. This would include functions that no currently installed app is using.
You could still place these functions on your global menus in preparation for
installing apps that use them. This is the preferred source. This encourages
application developers to use common terminology for similar functionality. The
compilers of this list need both names and definitions of what are appropriate
uses for that function. You can make up fine distinctions between synonyms, e.g.
exec and launch.
- A list of all functions that two or more apps just happen to be using.
- A list of all functions in all apps currently installed.
App.PossibleFunctions
List of standard functions plus additional functions actually supported by a
given app. There would be one such file per app, e. g.
Open
Save
Quiet Toggle
Duplicate
Not every function need be listed, however, if it is not listed, it can be
reconfigured. Ideally you want every function to be configurable as to possition
and whether it even appears at all.
Global.KeystrokeAssociations
List of function key associations globally applicable unless overridden. There
is only one such file per user.
F1=Help
F2=Open
F3=Search,Whazmotron ; Whazmotron search technique
F7=Print
Ctrl-V=Paste
Ctrl-X=Cut
Ctrl-C=Copy
App.KeystrokeAssociations
List of function key associations for a particular application. They override
the global defaults if a keystroke appears in both lists. There is only one such
file per application.
F9=Validate
Alt-F9=Go To
Ctrl-Q=Quiet Toggle
Global.MenuAssociations
Your globally specified preferred default menu structure, describes menu
structure, Alt-style keystroke accelerators, and tooltip (bubble/hover) help.
There is only one such file per user.
File/&Open=Open a file
File/&Save=Save the current file
File/app
File/Print=Print
app/
&Help/About
&Help/Register
app is a magic keyword that tells where you want the
app specific menu commands to squeeze in. Similarly app/
shows where you want the app specific stuff to squeeze in on the menu bar.
This will be merged with the list of supported app functions and the
MenuAssociation overrides for the apps to create the actual menu. It is thus not
an error to specify function that the app does not support.
The symbols =, & and / are permitted in the tooltip help. & has
reserved meaning in the menu to specify the accelerator key.
The app itself still has the ability to hide and reveal menu items, using only
their function names. It would not usually dynamically build a menu.
App.MenuDefaults
Provided by the writer of the application. This is the default menu layout he
suggests. If you provide no global or specific overrides, this is what you will
get. Items appearing in the global menu will be moved to new places. Non-standard
columns will fit in the /app section of the menu. The suggested default may use
menu headers from the global pattern such as File and Help.
App.MenuAssociations
Your overrides for a specific app to describe the menu structure, Alt-style
keystroke accelerators, and tooltip (bubble/hover) help. It is merged with
information from the global .MenuAssociations and the
apps .PossibleFunctions file to create the actual menu
structure. It is thus not an error to specify function that the app does not
support. Further, you don’t have to put every function the app supports on
the menu. However, if you don’t specify a given supported function, that
function won’t be accessible, e. g.
Document/&Tabs=tab settings
Document/Margin=margins around the document
Internationalisation
This scheme I have described does not handle languages other than English. You
want the application programmer to have to deal only with English (or her native
language), with the ability to add arbitrary languages simply by manipulating
these configuration files.
Let us assume we want to support French, as well. The .MenuAssociations
file and .KeystrokeAssociations files would be written
entirely in French. The .PossibleFunctions files would
be extended like this:
Help=Aider
Open=Ouvrer
Save=Sauver
Tools
The actual files would be case sensitive, though the tools to manipulate them
might be case insensitive.
The tools to manipulate these files would be fully generic. The end user thus
has only one configuring tool to learn, not one per app. You could also
manipulate them with a text editor very easily.
The tools to modify the .PossibleFunctions files would
not normally be employed by end users.
Tools would have a way of restoring you to a default factory default.
Because the file formats are so simple, it would a trivial matter to write a set
of tools, with any degree of whiz-bang you wanted.
The tools warn you of conflicts between global and local settings and help you
resolve them. They also detect accelerator conflicts. They would remove ordering
errors, collecting together duplicate entries for the same menu column. They
would warn you when you had inaccessible functions, or a keystroke or menu item
associated with more than one function.
Note that the scheme can also specify 3 or even 4 level menus. These may be
implemented as multiple toolbars for very large menus. The run-time engine
itself would be quite robust. It would carry on no matter what a mess the
configuration files were in.
Using the Scheme From Java
Here is how you might use the global keystroke and menu configuration files in a
Java application or Applet:
This is considerably simpler than building the menus item by item
programmatically, and of course much more flexible.
Security Issues
You would want this scheme to work with Applets as well. You would want users to
be able to configure Applets, just like Applications. This means somehow getting
the default definition files onto the local hard disk, ideally without a signed
Applet. They would be like cookies, an exception to the no-write rule.
There are a ton of little files to manage, one set for each user for each app.
You want to be able to borrow configuration files with read-only access from
other users. I have not tackled the issue of how you would name all these files
to track them. You also need master factory default files and master default
files for various languages. A user might even want to maintain some alternates
for a given app, e.g. a stripped down version where it is easier to find stuff,
and a full version.
Loose Ends
The accelerator keystrokes must be filtered out so that the KeyListeners never
see them. They must be app wide, no matter which Component currently has focus.
This requires hooking into the AWT.
It may be difficult to remap keys like Ctrl-C, Ctrl-V and Ctrl-X which may be
handled specially.
I have not described how pluggable search/replace algorithms could work that
would be sufficiently general to work in a spreadsheet, database or word
processing program. It would not directly touch data. It would be more of a
state machine that did its work via methods of a delegate object passed to it.
I have not described how you would configure the pluggable scrolling algorithm,
or define the various mouse and keystroke options to control it. This might be a
class with a few replacement components for some of the scrollable AWT/Swing
components, such as TextArea.
An app may regenerate the menu from scratch during its lifetime. This would
allow it to have more than one menu structure, e.g. for different phases of the
app. It would also allow the app to manipulate the configuring text files
directly, usually to select from one of a set of canned configurations, e.g.
Brief vs Epsilon vs CUA emulation.
Should there be so many separate files, or should they be combined into fewer?
The advantage of separate files are:
- Simpler tools (which might encourage an earlier implementation).
- Fine control of read/write access using the file system.
- More robust if people start manually editing it since the format is simpler, and
damage to a file is confined to one file.
- It is easier to add new languages, just add new files. There is no need to merge
the data.
- RAM usage is slightly more efficient since you never load data, for other
languages, you don’t currently use.
The advantages of combined files are:
- greater speed
- fewer files to manage manually.
- Less confusion trying to guess which files are the ones you manually want to
configure or view.
The decision which way to go should probably go to the first implementor. Tools
should optionally remove entries from the app configs that duplicate the global
settings. That way changes to the global settings will be automatically
reflected in the apps.
How should it come pre-configured out the box? I would hope there would develop
some named schools of thought on that, and you could try the entire
configuration suite with a single tool menu change to get a reasonably pleasing
starting point before you did your fine tuning.
I find I cannot type without visual feedback. Secret passwords you type blind
drive me nuts. As soon as the feedback disappears I go numb and just cannot type
worth a bean. So, I would like the hiddenness of passwords to be configurable. I
want them visible when I type. The CIA has no interest in me. I have heard there
are ways of doing them so that snoops have great difficultly picking up the
monitor radiation, but they are still visible.
Key bindings really needs to happen globally, including non-Java apps, so
perhaps it makes no sense to try for a Java-only implementation, other than as a
proof of concept. The application programmer’s interface should allow for
the possibility this scheme will later be implemented at the OS rather than the
Java level. It should work through methods, rather than playing with
configuration files directly.
There also needs to be mechanisms for particular applications to request that
they get no translation of keystrokes (or a particular one) and to query what
those translations currently are.
Whatever mechanism is used, it must live in the privileged sphere, requiring
user ok. Remapping the spacebar to Undo would drive many people round the bend!
What Is Important?
Don’t take any of the implementation details too seriously. You will soon
know far more about this project than I when you get into implementing it. The
four things I consider most important are:
- The user should have an easy way to move a menu item to a consistent place on
every app.
- The user should have an easy way to change the accelerators in all programs so
they are consistent.
- The user should have a way to override my general menu/accelerator scheme for a
particular app, including the menu items that occur only in it and nowhere else.
- Apps should work whether the user configures all the menu items or not. The user
should just have to configure the menu items he finds irksome, not the whole
thing. Individual Apps should provide a default menu structure. There should be
default general menu structure.
Summary
I have been bitching about this issue since DOS days. I have a history of
building what I think are better mousetraps then finding that almost no one is
willing to even investigate them.
I think acceptance would be much greater if this if implementing this were more
of a team effort.
Happily, Sun (Hans.Muller@Eng.Sun.COM and Scott.Violet@Eng.Sun.COM) has already
started some
in this direction. After an ice age, evolution can
again progress.
David Alex Lamb of Queen’s
Univerity in Kingston Ontario Canada has been doing some work on the problem. he
suggests a scheme of search path of files and resources to find the menu and
keystroke accelerator configuration information…
The KDE people are working on an implementation for Linux. Perhaps other OSes
will follow their pattern, and eventually Java will have a platform-independent
hook for this in-future-common OS feature.