Menu and Keystroke Configurator
©1996-2017 Roedy Green of Canadian Mind Products
Disclaimer
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. Everything I have prepared to help you is right here.
This project outline is not like the artificial, tidy little 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 by profession, 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 endeavour.
Please do not email me about this project without reading the disclaimer above.
Introduction
The big advance of Windows over DOS (Disk Operating System)
was not the GUI (Graphic User Interface) or the mouse, but CUA (Common User Access),
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 (K Desktop Environment)
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 (Hypertext Markup Language) 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 (Advanced Windowing Toolkit).
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 (Random Access Memory) 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 (Central Intelligence Agency) 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 (Operating System) 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
Learning More
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 OS
es will follow their pattern and eventually Java will have a platform-independent hook
for this in-future-common OS
feature.