[jsword-devel] Design/Architecture of BibleDesktop

DM Smith dmsmith555 at yahoo.com
Sat Jan 26 11:00:37 MST 2008


I've been asked to supplement the documentation of the Design and 
Architecture of JSword (former thread at: 
http://www.crosswire.org/pipermail/jsword-devel/2006-April/001954.html) 
with that of BibleDesktop. Ideally, both of these should be put on the 
website and not buried in a post.

BibleDesktop is best described top-down.

First, the relationship between Common, Common-Swing, JSword, and 
BibleDesktop.
Common defines general purpose routines that can be used by any program. 
They are directly used by the three other parts.
Common-swing defines general purpose "Java swing" code that can be used 
by any program.
Neither Common or Common-swing are frameworks.
JSword is a framework that defines how to work with books. It is a 
pluggable model and at this time, it supports Sword modules. It could 
also support any other kind of module (e.g. STEP, eSword), if plugins 
were written for these.

The program starts with org.crosswire.bibledesktop.desktop.Desktop (aka 
o.c.b.desktop.Desktop or o.c.b.d.Desktop) which initializes the program. 
The steps in initialization reflect the overall design and architecture 
of the program, so they will be discussed in order.

BibleDesktop is governed by o.c.jsword.util.Project, which determines 
the "home" directories of JSword. These directories are:
1) The default location of Sword resources, e.g. where modules should be 
downloaded.
2) The location of JSword resources, i.e. various pieces of saved state.
3) All the possible locations of Sword modules. (This can get in your 
way if you are developing modules and JSword sees
The location of these directories are platform dependent and vary across 
Unix, Windows and Mac.
These directories are critical in the resource model that looks up 
resources. For a description of the resource model, see the thread: 
http://www.crosswire.org/pipermail/jsword-devel/2006-August/001997.html.

The next thing that BibleDesktop does is establish the Locale for the 
program. Java by default will set the Locale to what it thinks is best 
for the user. This may not be appropriate. BibleDesktop allows a user to 
change this to any of the supported translations of BibleDesktop. The 
setting of the locale has to be done before any other resources are 
looked up.

At this point we know which splash screen to use and it is put up using 
o.c.b.d.Splash. This is done at the earliest possible time so that the 
user can know that the program is starting up and that it is making 
progress toward it's goal of showing the main screen. The splash screen 
is timed on the assumption that the application will show within that 
time. The splash is dismissed on timeout, on user click and upon the 
desktop being shown.

Once the proper locale is obtained, the user's preferences are read in. 
This can be improved as at this time, we read in the catalog of 
installed books to determine which should be put into the drop-downs in 
the options dialog.

While it can be done earlier the rest of error management is set up. 
Error management is done by reporting errors with o.c.c.u.Reporter. This 
will report o.c.c.u.ReporterEvents to o.c.c.u.ReporterListerers. One 
such listener is o.c.c.swing.ExceptionPane, used by BibleDesktop to show 
exceptions.

On the topic of error management, BibleDesktop and JSword use a logging 
mechanism, o.c.c.u.Logger to do all logging. We could use Java's logging 
or another logging facility directly, but this lets us swap out 
implementations fairly easily. Though it could be even easier with a 
plug-in model.

We avoid writing to standard out and standard error as much as possible. 
If these are found in the code, they are generally debug statements 
which should be migrated to Logger.

With regard to this we try to have every message that goes through these 
two mechanisms use strings defined in property files.  We do this 
through a class called o.c.c.u.MsgBase, from which we derive a Msg class 
in nearly every package. We also use the Msg class for labels that are 
shown in the GUI. This is a problem for translators, because it does not 
separate what must be translated (i.e. the GUI) from what can probably 
be skipped. It also does not distinguish between errors that the user 
can cause (e.g. entering a badly formed Bible reference) and ones that 
are programming errors (e.g. "Stupid programmer's error. Should never 
get here!") This should be improved.

After that, a o.c.common.progress.Job is started to communicate to the 
user what is going on. Jobs are background, threaded processes that 
communicate with o.c.c.p.WorkListener of which Splash is one. There are 
two types of Jobs, determinate and indeterminate. Determinate knows the 
size of the job that need to be done and can measure progress toward the 
goal. Indeterminate, which is most often used in BibleDesktop, guesses 
at the progress the first time and then uses the length of time for the 
last run to predict the next. One place that indeterminate is used that 
is inappropriate is the downloading of modules. It should be based upon 
the size of the module, which can vary widely.

Jobs are the mechanism in BibleDesktop to do things in the background so 
that the user interface can keep refreshed and allow the user to do 
other things. One place where it is not used but could be is in the 
reading of a Dictionary's entries. Loading Webster's Dictionary makes 
the program seem like it is hanging. Jobs don't need to be tied to a 
o.c.c.swing.progress.JobsProgressBar, but it is preferable to let the 
user know what is going on.

After setting up the job, o.c.b.d.DesktopActions is instantiated. 
DesktopActions is the heart of user interaction in BibleDesktop. Nearly 
every thing that can be done in the main screen goes through here. 
DesktopActions used to be part of Desktop, but was broken out merely to 
minimize file size and to have setup of BD in Desktop and the actual 
work in DesktopActions. One of the strengths of Java is it's Action 
model, where an action can be tied to one or more widgets. When a widget 
is tickled, it activates ActionListeners tied to the Action. We define 
o.c.c.u.CWActions within o.c.b.d.Desktop.properties, with each behavior 
having multiple entries. This file has a complete definition of each of 
the entries that define an action. We have extended this a bit further 
with a bit of Java's reflection via o.c.c.u.ActionFactory, such that if 
there is a File action defined in the properties file, then there must 
be a corresponding doFile(...) and reflection ties the two together.

Generally, each screen in BibleDesktop follows this pattern.

This simplifies adding new behavior. One merely adds a behavior to an 
*Action.properties and then adds a doNewBehavior(...) to the implementor 
of ActionFactory.

One shortcoming of this is that a button cannot be used for two 
different purposes. For example, if *Action.properties defines an OK 
CWAction, then all instances of it are tied. It would be very nice to be 
able to share some definitions, but not tie them together. (Peter and 
other translators would love this! and perhaps it ought to be entered 
into our issues db at www.crosswire.org/bugs under Common)

Desktop next sets up the GUI. This is split between generateComponents() 
and init(), though there is little value in having these as two separate 
methods, if any.

On the bottom of the screen is a o.c.b.d.StatusBar, which contains a 
message area, a progress area which can show the progress of all the 
jobs executing at the same time, and in the far right an area that shows 
the version number of BD. BibleDesktop allows the user to hide the 
status area. One needed improvement is that when it is hidden then any 
jobs that are in progress should probably pop up a dialog box showing 
the progress of all jobs.

On the top of the Desktop screen is a JMenuBar (except on Mac where it 
shows on the top of the monitor). This always shows.

Below the menu bar (or at the top of the Desktop screen on the Mac), a 
o.c.c.swing.ToolBar is shown. This extends JToolBar with a few 
behaviors. This tool bar can be hidden by the user. The content of the 
toolbar is hard coded in BD. It would be nice to allow the user to put 
any button of their choice on it.

On the right side of the screen is o.c.b.book.MultiBookPane, which is a 
vertical presentation of all non-Bible books. At the top is a selector 
of books. In the middle is a picker appropriate for the type of the book 
and at the bottom is a display of what has been picked.

On the left side of the screen, is the o.c.c.swing.desktop.ViewManager. 
The ViewManager allows the flipping between a tabbed set of 
o.c.b.b.BibleViewPanes and a multi-windowed view. I think the 
multi-windowed view is needed a lot less now that BibleDesktop allows 
parallel viewing of Bible passages.

The BibleViewPane consists of a o.c.b.passage.KeySidebar, which is 
hidden by default. The KeySidebar show the list of passages currently 
being shown in the BibleViewPane and allows one to add 1 or 5 verses to 
both sides of each passage, or to delete a passage from view. This is 
especially handy after a search to prune hits that do not match one's 
goal for the search and to expand the context of particular passages to 
see the full contextual meaning of a verse.

At the top of the BibleViewPane is o.c.b.book.DisplaySelectPane, which 
allows a user
* to choose one or more Bibles with o.c.b.b.ParallelBookPicker
* to quickly pick a book and chapter using o.c.b.b.BibleComboBoxModelSet
* to enter a range of passages to lookup (JTextField)
* to search a Lucene index. This displays either a button to create an 
index or enter a search.

To the right of the lookup is a button that will bring up a 
o.c.b.b.PassageSelectPane, a tree view of Book, Chapter and Verse that 
allows one to quickly create a passage selection without typing.

And right of search is a button that will bring up 
o.c.b.b.AdvancedSearchPane, which is the only way to do a ranked search, 
but is otherwise used to learn how to write searches using the advanced 
search capabilities of JSword.

At the bottom of the BibleViewPane is a 
o.c.b.display.basic.TabbedBookDataDisplay. The TabbedBookDataDisplay is 
a bottom tabbed display of Bible verses. When ever there are more than a 
user configurable number of verses to display, a "More..." tab is show 
to the right of the current tab. Clicking on the More... tab will fetch 
the next x verses and if there are more remaining, a new More... tab is 
shown. The splitting up of verses needs to be improved. It sometimes 
will break at the most unfortunate places. The purpose of the tabs is to 
manage performance.

The actual display of Book content is handled by 
o.c.b.display.basic.TextPaneBookDataDisplay. This is set up as a HTML 
viewer. Java's ability to display HTML is very poor. We would like to 
replace this with an OS dependent Web Browser (i.e. FireFox, IE, Safari, 
...). This is the major reason that we are looking at rewriting 
BibleDesktop with Eclipse's SWT/JFace/RCP. There is a prototype of the 
start of this.

When JSword is requested for the contents of a set of passages it will 
return an OSIS document regardless of the actual module's 
representation. BibleDesktop then uses o.c.b.d.XSLTProperties to 
remember the user's preferences on showing the passage and to pass it as 
properties to the process that transforms the OSIS to HTML. The HTML is 
then passed to the display. All this is contained in 
TextPaneBookDataDisplay.refresh().

Well that's about it. Digging into the code should fill in the gaps. If 
there is something missing that should be added please point it out.

In His Service,
    DM Smith

















More information about the jsword-devel mailing list