Here's a top-level idea of how the current (Eclipse-based) Fluency codebase is organized. It's divided into 4 Eclipse plugins:
FluencySharedPlugin (acts like an MVC Model) (currently misnamed, should be 'FluencyRuntimePlugin';
for its overall design see the attachment titled "The Fluency User-Interface Builder".
- Fluency Widget (contains all the big actions, like widget create, delete, link, unlink, persist, and so on)
- fluency actions
- fluency events
- User Widget (controls user-event intercept, containment, hit detection, focus, and so on) (mostly still entirely Swing-specific and also not complete)
- screen widget
- mouse widget
- keyboard widget
- focusmanager
- Standard Widget Library (all the actual visual and non-visual widgets like Button, Timer, and so on)
- widget actions
- widget events
- various delegate interfaces for visual and non-visual widgets (see: http://en.wikipedia.org/wiki/Bridge_pattern)
- Swing
- Swing implementations of (visual) widget delegate interfaces
- Linkage Widget
- contains the map of all widget relationships
- that map is updated by Fluency Widget's actions
- Persistence
- persists each fluency session as an XML file
- is itself just another Fluency Widget action; see: http://fluency.knownspace.org/developer/codedoc/action-persistence.html])
- relies on the uuencode/uudecode XML parser
- Event Channel
- communication path between the fluency runtime and the fluency builder
- It's worth considering making it a widget
- But it's really just a special case pipe, and the same could be accomplished by making a composite of the Pipe widget.
- The builder emits request type events into the event channel and updates its views based on events the runtime emits to the event channel.
- The runtime emits events to the event channel when its state changes.
FluencyPlugin
- nothing to do with fluency, really
- its Eclipse-specific classes bring all other plugins together by talking to Eclipse to start the Eclipse fluency builder creation
FluencyLinkagePlugin
- org.knownspace.fluency.builder.linkage
- the core builder package
- contains the Eclipse editor for linkage as well as the plugin hooks classes
- org.knownspace.fluency.builder.linkage.model (the fluency builder's MVC Model)
- all GEF objects are backed by a model and have a corresponding view object (which is a figure, described above)
- models are what should be changed, and can have addition functionality that you can count on sticking around
- when you update a model, the figures should be updated accordingly by the GEF framework
- org.knownspace.fluency.builder.linkage.figures (the fluency builder's MVC View)
- figures are GEF objects
- they are created by the GEF framework and should not keep state that is counted on in the future, as the framework will throw away and recreate figures as it desires
- there are currently two figures in the linkage graph
- WidgetFigure: a rectangle that contains WidgetAnchorFigure children and a label for the widget
- the mouse listener code that controls the figure's collapse/expand behavior is in this class
- WidgetAnchorFigure: used to display an image which a pipe can anchor to (events, actions, and docks)
- WidgetFigure: a rectangle that contains WidgetAnchorFigure children and a label for the widget
- org.knownspace.fluency.builder.linkage.parts (the fluency builder's MVC Controller)
- EditParts are the controllers. They determine what models to use and how the models get populated for the various GEF pieces
- EditParts also determine EditPolicies (GEF layout managers). currently fluency uses an XYEditPolicy so that the author can move widget nodes as she pleases
- there should be more options in the future so that fluency can automatically arrange the graph in meaningful layouts for the author
- EditParts register with the EventChannel, listening for runtime events, which they can react to and have the model updated, which the user will then see in updated figures
- org.knownspace.fluency.builder.linkage.model.commands
- these are command objects, as in the command design pattern
- their execute() method dumps fluency events into the EventChannel
- Eclipse executes these commands when various events happen in the GEF interface, such as:
- PipeConnectCreateCommand: creates a pipe and triggers the creation of a real fluency pipe
- WidgetCreateCommand: creates a widget in the linkage graph editor.
- this currently is triggered when a visual widget is created in the layout editor and only creates a dummy non-visual widget. when a non-visual widget is created, this command should dump an event into the EventChannel so that the fluency runtime can create the corresponding widget, similar to how visual widgets are currently created when dropped onto the LayoutEditor (see below).
- org.knownspace.fluency.builder.linkage.events
- currently only contains one event, LinkageGraphRefreshEvent
- this event ensures that the linkage graph is refreshed correctly when it needs it (e.g. when a node is added to the graph, visually)
FluencyLayoutPlugin (acts like an MVC View and Controller mixed up; it talks to the EventChannel for most of the rest of the View)
- workbench (apparently presently almost dead, replaced by eclipse equivalents)
- visual widget palette
- frame (note: this is not the same as the (Swing) root Frame in the runtime as part of the SWL)
- plus other random GEF and Swing junk all mixed up to partly act as an MVC Model and partly as a Controller and partly as a View. this needs serious refactoring.
org.knownspace.fluency.builder.layout.LayoutEditor
- LayoutEditor is the starting point in FluencyLayoutPlugin. It creates,
configures, and wires together, everything in the fluency.builder.layout
subpackage. Eclipse's editors use the MVC design pattern - so, in our
case, the fluency runtime is the analog of the Model. LayoutEditor
contains the hook methods for persisting and restoring Fluency and
handles the graphical conversion from (the old Fluency builder's)
root (Swing) Frame into something that Eclipse can display using SWT.
LayoutEditor is a grabag of a class, containing, for example, the
property sheet, which probably shouldn't be there but may be an Eclipse
requirement. LayoutEditor is large and awkward, and needs a lot of
refactoring, especially in its interactions with the other participants
in GEF's MVC architecture (the View and Controller). A lot that stuff
should be separated out.
org.knownspace.fluency.builder.layout.model.LayoutModel
- LayoutModel is almost surely not being used properly in the Eclipse
MVC sense. It currently only contains a transient reference to the
PropertySheetPage (which holds each widget's properties) which it
refreshes when requested to do so. Nothing else. (see
http://fluency.knownspace.org/confluence/display/fdoc/Properties+Sheet).
Part of the problem may be because all of the real (Model) data is being
stored in the fluency runtime - Allen and Nate ran into some problems with
respect to how GEF internally manages the lifecycle of these objects.
org.knownspace.fluency.builder.layout.parts.LayoutEditPart
- LayoutEditPart is instantiated by the LayoutEditPartFactory,
which is instantiated by the LayoutEditor and is the Controller in
GEF's MVC. Currently it does two important things:
- # it listens to the fluency runtime's *EventChannel and asks the
LayoutModel to refresh the PropertySheetPage when some widget
property changes (so when we move around the widget in design mode
the property sheet will update the widget's (x,y) values, etc.),- it maintains an (Eclipse) EditPolicy which specifies commands
that GEF should execute when the user modifies the graphical editor
by dropping a widget from the palette onto the viewable area. When
this happens, a CreateRequest is sent to the LayoutEditPart's
EditPolicy (this happens internally within GEF). LayoutEditPart
then extracts information from this CreateRequest to generate
a org.knownspace.fluency.layout.command.WidgetCreateCommand. The
execution of that WidgetCreateCommand generates an AddWidgetRequest
that then gets pumped to the fluency runtime's EventChannel. After that,
everything is pretty much in the fluency runtime's court.
- it maintains an (Eclipse) EditPolicy which specifies commands
org.knownspace.fluency.builder.layout.LayoutEditorPaletteFactory
- LayoutEditorPaletteFactory defines the things you see in the
palette - the widgets you see, the different modes, etc. It stores
references to specific Fluency Widget classes (e.g., Button.class,
Listbox.class, etc.) in entries in the palette. When you drag'n'drop
something from the palette to the graphical editor area one of those
Class references is encoded into a CreateRequest that then gets sent
to the LayoutEditPart's EditPolicy so it knows which Fluency widget
to create.
Some useful urls:
james ellis's codebase overview document:
http://fluency.knownspace.org/developer/codedoc/structure.html
nathan deckard's builder document:
http://fluency.knownspace.org/developer/codedoc/builder.html
james ellis's and nathan deckard's design patterns in fluency document:
http://fluency.knownspace.org/developer/codedoc/patterns.html
nate johnson's eclipse builder document:
http://fluency.knownspace.org/fluency-rcp/
nate johnson and allen lee's eclipse fluency setup page:
http://fluency.knownspace.org/fluency-rcp/fluency-tools-intro.html
GEF tutorials and articles:
http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.gef.doc.isv/guide/guide.html
http://eclipsewiki.editme.com/GefDescription
http://www.eclipse.org/gef/reference/interactions.html
Also refer attached presentation.