1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
|
Here's the readme I provided when I published the sources online: of
course, to be accurate it needs to be accompanied by a license.txt file
containing the GPL.
JDasher Source Code
===================
Find further information at www.smowton.net/chris
Contents:
I. Licensing
II. Package outline
III. Class outline of dasher package
IV. Contacting the author
I. Licensing
------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
The complete license can be found in COPYING in the parent directory.
II. Package outline
-------------------
dasher.*
========
This contains the core Dasher source code. It corresponds to the
DasherCore package in the original C version of Dasher. By themselves
the classes in this package cannot form a completely working Dasher. To
produce a working system, one must:
a) Implement the CDasherScreen interface (see section III for details)
b) Subclass CDasherInput at least once to provide co-ordinates (eg. from
a mouse) on demand (again, see details below)
c) Subclass CDasherInterfaceBase, specifying the abstract methods of
that class. Most of these can be stubbed and still produce a working
system, though it may lack the ability to learn from training text, or
load XML files.
d) Optionally, subclass CSettingsStore to provide the ability to store
persistent settings. If this isn't done and the base CSettingsStore is
used, the defaults will be loaded every time Dasher is run.
dasher.applet.*
===============
This package contains the classes to complete an implementation of
Dasher as a Swing applet, by more or less the means described above. It
also provides some extra, optional functionality, such as listening for
text events and showing the currently entered text in a text box.
Key components:
* JDasher, which is a subclass of CDasherInterfaceBase and provides
methods to retrieve data files from a JAR
* JDasherApplet, which sets up a Swing GUI and generates Dasher events
to provide control.
* JMouseInput, a subclass of CDasherInput which provides mouse
co-ordinates on demand.
* JDasherScreen, which implements CDasherScreen and converts graphics
primitive instructions to Java AWT drawing commands.
* JSettings, which subclasses CSettingsStore to use the Java Preferences
class to store persistent settings. The Preferences class in turn defers
to the JVM, meaning it will try to use the Registry on Windows, a
.javasettings file in Linux, and so forth.
dasher.net.*
============
This is an implementation of Dasher which provides a network interface
based upon XML transactions. The 'screen' (NetDasherScreen) implements
CDasherScreen but doesn't really act as a screen; rather it gathers
relevant data and sends this to a client, such as the JavaScript client
found at www.smowton.f2s.com/jsdasher.html. Similarly, NetInput provides
input by interpreting XML documents fed by the client.
The net package provides a multithreaded server to host several such
Dashers at once. Loosely, the structure is that NetDasherListener is
started as the main thread, and this spawns a
NetDasherCommandInterpreterThread for every incoming connection it
receives. These threads interpret the XML document sent by the client
and respond in a variety of ways, usually creating or invoking methods
of a NetDasherConnectionHandler (which creates an instance of Dasher,
NetScreen and NetInput and acts to pass messages back and forth between
Dasher and the network server).
These ConnectionHandler objects as well as their associated Dashers are
persistent between connections, and so act to provide a continuous session.
Typically JavaScript clients will not speak directly to the Dasher
server, but will pass requests to a webserver first, since security
restrictions typically require that JavaScript does not invoke URLs
which are not on the same server as the JavaScript itself.
III. Dasher core in detail
--------------------------
CAlphabet: Represents the alphabet we're currently working with. It it
responsible for holding information about how each symbol in the
alphabet should be typed, how it should be displayed on screen, and some
aspects of how the symbols should be coloured.
CAlphabetManager: Carries out certain functions which manipulate the
general Dasher state, but depend upon Alphabet data. Example include
outputting the appropriate text when the user enters a node, and
populating child nodes when required to do so by the Model.
CAlphabetManagerFactory: Factory class for the above.
CAlphabetMap: Wrapper around a HashMap from a UTF-8 representation of a
symbol to its unique integer identifer. This used to be much more
complicated, but could probably now be reduced to just a HashMap which
would probably be a member of CAlphabet.
CAlphIO: Given a list of XML files, parses them for descriptions of
alphabets, and uses this to report a list of available alphabets.
CAutoSpeedControl: Uses a variety of diagnostic signs to establish
whether the user would like to go slower or faster, and controls the
Dasher maximum speed appropriately.
CCannaConversionHelper: In the C version, provides for conversion from
Hiragana to Kanji in Japanese. At the time of writing this was an
unstable development feature, and this class is a stub at present in
JDasher.
CCircleStartHandler: Provides the possibility of a circular target which
can be used to start Dasher.
CClickFilter (extends CInputFilter): An input filter which causes Dasher
to zoom when the user clicks. It does this by calculating a set of
points forming a line between the current position and that which was
clicked and adds these to m_deGotoQueue, a list of "pending points"
which the Model consults as a potential source of movement instructions.
CColourIO: As CAlphIO, but reads colour scheme XML files.
CContextBase: Base class of all language models' classes representing
some context for predicting input. This is typically used outside the
language model so that the rest of the program does not depend upon a
particular language model. It exposes no methods, and so contexts cannot
be modified outside the language model.
CCustomColours: Wraps around a colour scheme object read by CColourIO;
used by the View classes to determine how the nodes should look.
CDasherComponent: This is a base class for a large number of Dasher
components, and provides several basic functionalities, including the
handling and creation of events, and the ability to consult and modify
the settings store. It provides a default EventHandler which ignores all
events, which is designed to be overridden by subclasses. Only
subclasses of CDasherComponent can register themselves to listen for events.
CDasherInput: This is a base class for some form of co-ordinate input
which provides either 1 or 2 co-ordinates. This class is abstract and
must be extended if you wish to provide any input to Dasher.
CDasherInterfaceBase: This is the central class of the Dasher core. It
provides centralised functions which have widespread consequences
including Start(), ChangeAlphabet() and so forth. It also provides
NewFrame(long) which is the standard way to cause Dasher to update the
model and draw a frame. It does not perform much of the functionality
itself however; it defers the maintenance of the model to CDasherModel
and the drawing of it to CDasherView and its children.
It includes a number of abstract methods which are
implementation-dependent. These must be implemented to produce a working
Dasher, but most can be stubbed safely. The only issue which is
genuinely important is to ensure that a CSettingsStore (or subclass) is
produced before any CDasherComponents are created (which would depend
upon it).
CDasherModel: This maintains a tree of CDasherNodes, each of which
represents a box with a letter in it. It is responsible for deciding
when to create new nodes (although it defers the actual act to the
AlphabetManager) as well as when to delete old nodes, in collaboration
with the View (which informs the Model of situations such as a node
being too small to draw, and so a candidate for deletion). It also plays
a major role in making Dasher "move" by altering the crosshair position
in response to newFrame calls made to CDasherInterfaceBase.
CDasherNode: This represents a box with a symbol in it, and is the unit
component of the Dasher tree maintained by the CDasherModel. It also
posesses a Context object (child of CContextBase) which describes the
prediction context for this node (ie. the data the language model should
use in deciding its likely successors). Nodes are also aware of their
size in terms of Dasher co-ordinates, though not their on-screen size.
CDasherScreen: This defines an interface for drawing (or otherwise
outputting) graphics primitives. Some class must implement this to get
any visual output from Dasher, and an instance of this class must be
registered with the Interface by means of its ChangeScreen method.
CDasherView/Square: The base and one implementation for a 'view' which
is to say a class for visualising the Dasher tree. Whereas the model
knows only the nodes' relative probabilities, the View converts these
into some visual representation; in the case of ViewSquare, into a set
of square boxes. It responds to a Draw() request by translating the
Model's data into primitive drawing commands executed by some
implementation of CDasherScreen.
CDefaultFilter: Default input filter, which simply causes Dasher to zoom
towards wherever the user is currently hovering the mouse.
CDelayedDraw: Helper class for drawing boxes with a symbol in them
without the risk of overwriting symbols by mistake. All text to be drawn
is placed on a stack, and at the end of the drawing cycle, and after all
other primitives have been drawn, the stack is emptied and its contents
drawn.
CEventHandler: The event handler permits CDasherComponents to register
themselves as event listeners. All components register themselves as
part of the Component's constructor, though of course this can be
overridden. When an event is raised, the HandleEvent method of each is
called in turn with the Event as a parameter.
The EventHandler does not involve any threading whatsoever, unlike
Java's built-in event subsystem. When a Dasher event is raised, the
raising method will not continue until all listeners have had their
HandleEvent routines called.
For the eventuality that a reponse to an event causes another event to
be raised, the event handler keeps track of how many events are
currently unfinished. If a listener tries to add itself whilst this
number is not zero, it goes in a queue. As soon as the last event
finishes processing, the Components in the queue are made listeners proper.
CInputFilter: Base class of all input filters. These play a pivotal role
in the update-model-and-draw frame cycle. They respond to both key
presses and mouse clicks by their keyDown methods being invoked, and the
drawing of a frame without cue through their Timer method, whose
argument specifies the time since the last frame.
Typically, the start of a new frame consists of the Timer method being
called, which is then responsible for calling the Model's functions with
parameters indicating what changes need making.
The inputfilter will also be invoked at the very end of the new frame
cycle in order to apply any view decorations it wishes to on top of the
standard appearance rendered by DasherView. A typical example is drawing
a line to the current mouse position.
CLanguageModel: This is responsible for Dasher's prediction of what the
user is most likely to enter next. It is fed data by having its
EnterSymbol and LearnSymbol methods called on Context objects (children
of CContextBase), and will have getProbs called to determine the
relative sizes of CDasherNodes whenver the tree is expanded by the
AlphabetManager.
Details of how the modelling is done is dependent on the language model
used. The only subclass included here is CPPMLanguageModel, but a few
other possibilities were explored in the original C version and can be
found in its source.
IV. Contacting the Author
=========================
I can be reached on chris@smowton.net, cs448@cam.ac.uk, or
chris.smowton@cl.cam.ac.uk.
|