Upload
sivan
View
47
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Model-Oriented Architectures and Frameworks for Swing-Based User Interfaces. Dan Jacobs [email protected] President and founder, ModelObjects Group http://www.modelobjects.com President and founder, JPlates Inc. http://www.jplates.com Chairman, Boston ACM WebTech Group - PowerPoint PPT Presentation
Citation preview
Model-Oriented Architectures and Frameworks for
Swing-Based User Interfaces
President and founder, ModelObjects Grouphttp://www.modelobjects.com
President and founder, JPlates Inc.http://www.jplates.com
Chairman, Boston ACM WebTech Grouphttp://www.acm.org/chapters/webtech
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
2
ModelObjects Group
Founded in December 1995 Object-Oriented Software Development Architecture, Design, Implementation Swing User-Interface Development Compilers and Language Tools Multithreaded Server Architectures Web & J2EE Applications IDE Integration and Plug-ins
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
3
Seminar Overview
Why build more traditional GUIs? Overview of AWT and Swing Important Design Patterns Levels of Model-View-Controller Model-Oriented UI Architectures Application-Level Controller Logic Effective Event-Handling Strategies Effective Swing Layout Management
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
4
Why Build Traditional GUIs?
Most interactive, most expressive Easier to develop (in some ways) Easier to debug, performance-tune, … Better at maintaining user confidence More flexible for managing complexity Integration with other applications Integration with other technologies Disadvantages too
Overview of AWT and Swing
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
6
Overview of AWT and Swing
Swing is built on core of AWT Common event-handling model Lightweight components Powerful graphics operations Fonts, colors, images, printing, etc. Layout managers, container composition
Rich component class library Pluggable Look and Feel Powerful and Extensible
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
7
Swing Development Challenges
Mostly single-threaded model Everything happens on event thread
Many large, complex frameworks Hard to know how & where to fit it
Unfamiliar layout and composition The right thing for cross-platform GUIs
API shows signs of age (from JDK1.1) Enormous API, not entirely consistent
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
8
AWT/Swing Software Layers
Swing (javax.swing and sub-packages)
J2SE Core Java Packages
JVM and native method libraries
AWT Lightweight Support / Graphics 2D
AWT Component & Container Framework
Platform Operating Systemand Window System
ApplicationCodeJ2SE
Many other standard extensions
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
9
Swing Components
Simple Components Button, text-field, check-box, scrollbar,
label, slider, combo-box, spinner, etc. Containers
Panel, scroll-pane, tab-pane, split-pane,dialog, window, popup, etc.
Complex Components Table, tree, menu, file-chooser, etc.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
10
Lightweight Component Model
Platform window system provides: Top-level windows and dialogs Underlying input events Underlying graphics operations
AWT/Swing does the rest: Mapping “flat” events to components Painting, clipping, etc. on window Platform doesn’t see lightweight comps
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
11
Inside Swing Components
Internal state management Event handling Painting / Rendering Support for event-listeners Component properties customization Internal composition and layout Built-in recursive support for child
components – events, painting, etc.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
12
Black-Box Component Behavior
Allocate and initialize Configure additional properties Add to parent container Add event listeners Add selection listeners Add property-change listeners Modify properties from listeners
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
13
White-Box Customization
Complex object-oriented frameworks Define subclass of component class Override methods as appropriate Call superclass methods as needed Stick to the rules (if you can find them) Requires much deeper knowledge of
AWT and Swing design and internals
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
14
Black-Box Component Use
JButton button1 = new JButton("Press Me");
button1.setEnabled(false);
buttonPanel.add(button1);
ActionListener bh = new ButtonHandler(this);
button1.addActionListener(bh);
Object-Oriented Design Patterns and Frameworks
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
16
Object-Oriented Design Patterns Recognizable patterns that appear over
and over again in good designs. General, reusable solutions to common
design problems. Encapsulate aspects of designs that are
likely to change. Allow independent parts of a design to
work together – maintain loose coupling. Reuse of intellectual effort & experience.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
17
Design Principle: Separation of Independent Concerns
Promote loose coupling and strong object encapsulation
Allow independent parts of application to evolve independently
Hide internal details from parts that should not depend on them
Don’t take it too far – some things are not independent of each other
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
18
Object-Adapter Design Pattern Problem: Use an existing class as if it
implemented a new interface, but without modifying the class or the interface.
Analogy: Plug an electric appliance into a different kind of outlet, without changing the appliance, the plug, or the outlet.
Object-Adapter prescribes the relationships between the existing class, the required interface, and a new adapter class.
Reusable concept and approach, but each new kind of adapter uses a new class.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
19
Object Adapter Design Pattern
class OldHairDryer
OldPlug getPlug();boolean getBlowerOn();setBlowerOn(boolean);
…
interface NewPlugProvider
NewPlug getNewPlug();…
NewPlugAdapterimplements NewPlugProvider
NewPlug getNewPlug() { … }private OldSocket _oldSocket;
…
references
implements
class NewSocket
plugIn(NewPlug);…
references
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
20
Event Listener Design Pattern
More flexible extension of Observer Support for multiple event listeners Event object exposes source, details Listeners implement common interface In Swing’s implementation:
Event sources follow naming conventions Listeners notified by synchronous calls Some event objects are modifiable
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
21
Event Listener Design Pattern
FooEventSource
addFooListener(FooListener)removeFooListener(FooListener)
fireFooEvent1()fireFooEvent2()
FooListener
handleFooEvent1(FooEvent)handleFooEvent2(FooEvent)
listeners
FooEvent
getSource()getEventType()
getEventDetails()
ConcreteFooListener
handleFooEvent1(FooEvent)handleFooEvent2(FooEvent)
event-source implements
event
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
22
PropertyChangeListener Pattern Special case of Event Listener pattern Central to Java Beans component model Events identify source, property, values Property normally identified by naming
conventions (e.g. getFoo(), setFoo(…)) Class must provide support for
managing PropertyChangeListeners Setter methods, after changing state,
fire PropertyChangeEvents
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
23
PropertyChangeListener Pattern
class ChangeHandler implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent event) { Object changeSource = event.getSource(); String propertyName = event.getPropertyName(); Object oldValue = event.getOldValue(); Object newValue = event.getNewValue(); ... }}
…ChangeHandler handler = new ChangeHandler();objectToWatch.addPropertyChangeListener(handler);…doSomethingTo(objectToWatch);
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
24
Object-Oriented Frameworks
Typically use many design patterns. Well defined roles to play, frequently
specified by interfaces. Core group of classes orchestrates
common behavior for other roles. Frameworks don’t have to be large or
complex – the fewer roles, the better. Can offer best kind of code reuse.
Model View Controller Pattern
<a href="dosomething?foo=3&bar=no">Click Here</a>
A Frequently Misunderstood Pattern
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
26
Model View Controller Pattern
One of best know (as MVC), least fully-understood design patterns.
Originated in Smalltalk-80 window system library – fully object-oriented.
Innumerable mutants, contortions, and distant cousin spin-off patterns.
Encapsulated object state is not the same thing as the model role.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
27
Model View Controller Pattern
Model• view-independent• object encapsulation• change-event source• first-class object
View• renders model info• change-event listener• gesture-event source• first-class object
Controller• gesture-event listener• updates models• selects alternative views• first-class object
model change events
model state changes
gestureevents
model state
queries
view control
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
28
MVC Variant Used in Swing
View and Controller combined into a single look-and-feel (L&F) object.
View-specific state in Component and L&F, view-independent state in Model.
Models are specified by interfaces, and default implementations provided.
Some components rarely expose the model, and support listeners directly.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
29
Swing MVC Example 1 - JButton View supports label, different colors
for disabled, armed, etc., icons for normal and disabled, etc.
Controller responds to mouse press and release, enter and exit, etc.
JButton state includes label, icons, colors, and button-model.
Model includes action-command, enabled, armed, pressed, rollover, selected (e.g. for checkbox), etc.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
30
Swing MVC Example 2 - JList List-model abstracts list of Objects and
change-events for contents of the list. Selection-model independent of model. View defined in terms of cell-renderers
that render individual model elements. Changes to model made by application
code, not by component interactions. Model changes handled by view, model
elements painted by cell-renderers.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
31
Direct Editing Example
class HtmlEmailCheckboxWatcher implements ItemListener { public void itemStateChanged(ItemEvent event) { boolean selected = (event.getStateChange() == ItemEvent.SELECTED); _recipient.setPrefersHtmlEmail(selected); } }
EmailRecipient _recipient;
JCheckBox prefersHtmlCheckbox = new JCheckBox("prefers HTML email"); prefersHtmlCheckBox.addItemListener(new HtmlEmailCheckboxWatcher());
public void editEmailRecipientPreferences(EmailRecipient recipient) { this._recipient = recipient; prefersHtmlCheckbox.setSelected(recipient.getPrefersHtmlEmail()); … }
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
32
A Closer Look at Direct Editing Initialize from Model property value. Use listener to change property value. Simple, but deceptively simplistic. Missing numerous important features:
enable/disable logic validation, propagation, transactions apply, reset, undo, redo notification of model changes to listeners
Direct use of model API by UI code
Model-Oriented Architectures
Model-Oriented Application = Model Objects + Coordinated Uses of Model Objects
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
34
Model-Oriented Frameworks
Abstract Class-Level Metadata Model-Oriented Form-Based Editing Application-Level MVC Frameworks for Tables and Trees Master-Detail Relationships Support for Model Class-Hierarchies More Object-Oriented Design Patterns
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
35
Abstract Class-Level Metadata Not all so-called models are Beans.
“tagged” hash-tables XML DOM sub-trees LDAP or JNDI entries URLs with query parameters database result-set wrappers
Frequently no built-in validation logic. Rarely any propagation logic. Rarely any change-listener support.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
36
Class-Level Metadata for the UI
May want additional (often extrinsic) properties just for the user interface.
Want controlled, secure exposure of business object internals.
May want higher levels of abstraction than back-end representations.
Want to localize dependencies on back-end representation details.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
37
Model Metadata Framework
ModelObjectAdapter
Object getAspectValue(ModelAspectId)void setAspectValue(ModelAspectId, Object)Object getModelObject()void validateModel() throws ModelValidationException
ModelDescriptor
ModelObjectAdapter makeModelObjectAdapter(Object)ModelAspectAdapter getModelAspectAdapter(ModelAspectId)void addModelObjectValidator(ModelObjectValidator)void validateModel(ModelObjectAdapter)
ModelAspectAdapter*
Object getAspectValue(ModelObjectAdapter)*void setAspectValue(ModelObjectAdapter, Object)*Class getModelAspectType()boolean isReadOnlyAspect()
ModelAspectId
String getName()
modelDescriptor
modelAspectAdapters
ApplicationModel ObjectInstance
ApplicationModel Object
Class(or other metadata)
n
n
1
1
1 1
1 1
11
n
1
class
level in
form
ati
on
inst
an
ce level
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
38
Inside ModelObjectAdapterpublic class ModelObjectAdapter { protected final Object _modelObject; protected final ModelDescriptor _modelDescriptor; ... public Object getAspectValue(ModelAspectId aspectId) throws NoSuchAspectException { ModelAspectAdapter modelAspectAdapter = _modelDescriptor.getModelAspectAdapter(aspectId); return modelAspectAdapter.getAspectValue(this, _modelObject); } public void setAspectValue(ModelAspectId aspectId, Object newValue) throws PropertyVetoException, NoSuchAspectException { ModelAspectAdapter modelAspectAdapter = _modelDescriptor.getModelAspectAdapter(aspectId); modelAspectAdapter.setAspectValue(this, _modelObject, newValue); } ...}
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
39
HashTable ModelAspectAdapterpublic class HashTableAspectAdapter extends ModelAspectAdapter{ private String _key; public HashTableAspectAdapter(String key) { super(ModelAspectId.forName(key), Object.class); this._key = key; } protected Object getAspectValue (Object modelObject, ModelObjectAdapter objectAdapter) { HashTable hashTable = (HashTable) modelObject; return hashTable.get(_key); } protected void setAspectValue (Object model, Object value, ModelObjectAdapter moa) { … }}
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
40
Levels of Validation Text input validation
keystroke at a time, or when losing focus based on logical type of data, not use
Field level validation checked on aspect-value assignment
Object level validation checked on apply, create, delete
Contextual validation consistency or uniqueness constraints may be performed externally (e.g. DBMS)
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
41
Validation Failure Feedback
Constrain input to avoid errors disable things that are not applicable offer constrained range or set of choices custom typed chooser components
Change color to indicate problems color of border, background, label, etc.
Use “what’s wrong” tool-tips normal tool-tips explain purpose of field
Alert dialog, status line, message log
Adapters for Edit Components
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
43
Abstract Aspect-Editors/Viewers Generalized “data-bound” controls. Allow any kind of UI component. Allow any kind of application model. Want a uniform abstract interface to:
associate with specific ModelAspectId initialize from model-aspect-value notify when edits have been made provide edited model-aspect-value provide unapplied view-aspect-value
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
44
ViewAspectAdapter Features
Conversion between model-aspect-values and view-aspect-values.
Conversion from component-specific events to uniform change-events.
Customizable enabled-for-edit rules. One adapter type for each component
type (sometimes more). Aspect identified by ModelAspectId.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
45
ViewAspectAdapter
ViewAspectAdapter
void setModelAspectValue(Object)Object getModelAspectValue()void setEditable(boolean)addChangeListener(ChangeListener)
EditRule ModelAspectIdViewValueConverter
AWT/Swing Component
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
46
Inside JTextFieldAdapterpublic class JTextFieldAdapter extends ViewAspectAdapter implements DocumentListener{ public JTextFieldAdapter(ModelAspectId modelAspectId, JTextField textField, EditRule editRule, ViewValueConverter valueConverter, ModelEditMediator editMediator) { super(modelAspectId, editRule, valueConverter, editMediator); this._textField = textField; textField.getDocument().addDocumentListener(this); } public void setEditable(boolean editable) { _textField.setEditable(editable); } public void setViewAspectValue(Object viewVal) { _textField.setText((viewVal == null) ? "" : viewVal.toString()); } public void insertUpdate(DocumentEvent event) { fireChangeEvent(); }
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
47
Prefer Renderers to Converters
Many Swing models support Objects Lists, Trees, Tables, Combo-Boxes, etc.
Can convert between application models and strings (for example) May require cumbersome lookup logic
Can render model aspects instead Swing model can hold the app model Custom renderer extracts selected info
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
48
Example Custom Cell Renderer
class EmailRecipientCellRenderer extends DefaultListCellRenderer{ public Component getListCellRendererComponent (JList list, Object val, int index, boolean select, boolean focus) { EmailRecipient recipient = (EmailRecipient) val; JLabel result = (JLabel) super. getListCellRendererComponent (list, recipient.getDisplayName(), index, select, focus); result.setIcon(getDisplayIcon(recipient)); return result; }}
JList recipientsList = new JList(allEmailRecipients); recipientsList.setCellRenderer(new EmailRecipientCellRenderer()); recipientsList.addListSelectionListener(...);
Connecting Models to Views
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
50
Connecting Models to Views Connect aspect-adapters on each side. Handle change notifications from view. Collect edited model-aspect values. Support apply and reset actions. Special treatment for new objects. Perform validation and report errors. Update the edited model-object. Notify listeners of changes, errors, etc.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
51
ModelEditMediator
ModelObjectAdapter
View AspectAdapters
Model AspectAdapters
ModelDescriptor
Model-ObjectPropagator
Model-ObjectValidators
Edit RuleView ValueConverter
User InterfaceComponent
ModelEditMediatorapply, reset, undo, redoeditModelObject(ModelObjectAdapter)editModelAsNewObject(ModelObjectAdapter)addModelEditListener(ModelEditListener)addModelEditFailureListener(…)
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
52
ModelEditMediator Apply Logic Apply-action enabled on “new” or change. Changed aspect-ids collected during edit. Collect model-aspect-values to assign.
all editable view-aspect-adapters for new model Assign values through ModelObjectAdapter. Run model-object validators & propagator. Undo changes (non-new only) on failure. Notify edit-listeners, failure-listeners, etc. On success, reset view and actions.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
53
Edit, Apply, and Validate Logic
Swing Components andSwing Models
ViewAspectAdaptersand ViewValueConverters
ModelEditMediator andcollected model-aspect values
PropertyChangeEvents andUndoableModelEditEvents
ModelObjectAdapterModelDescriptor andModelAspectAdapters
ModelObjectValidators andModelObjectPropagator
Application Model Object
ModelEditListeners andModelEditFailureListeners
ModelAspectValidators
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
54
Reset, Undo, and Redo Logic
Reset is same as starting over re-initialize all view-aspect-adapters clear all pending changes and actions
When new model-aspect values are assigned, undo information collected Aspect-id, old-value, new-value Swing undo framework helps a lot
Undo/Redo information recorded and managed on a per-object basis
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
55
Multi-Part Forms
Some models have a lot of aspects. Organize into logical groups of aspects. Tabbed-folder organization, wizards, … Complex view, still just one model. Creation “wizards” delay apply logic. Dependencies between values of fields. Want to use same logic for complex
and simple forms.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
56
Summary of Concepts So Far MVC: Model View Controller
event-listeners, view-independent model lower-level events to higher-level actions
Class-level metadata and model adapters uniform, flexible, extensible, powerful delegation to model-aspect-adapters
Adapters for UI components too manipulated with model-aspect-values
Edit-Mediator provides common behavior independent of both model and view “form-level” controller component
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
57
Application-Level MVC
Application Model• view-independent• model-change source• defines app behavior• high-level abstraction
Application View• render model aspects• model-change listener• fires initiator-events• organizes models
App Controller• initiator-event listener• update app models• use app-model API• select alternative views
model change events
model state changes andmethod calls
initiatorevents
model state
queries
view control
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
58
Application-Level MVC
Initiator-events from apply, reset, undo, redo, create, delete actions.
Application Models presented to UI with abstract metadata and adapters.
Almost everything done in Swing is part of the Application View.
ModelEditMediator provides sound foundation for Application Controllers.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
59
Type-Specific Model-Edit-Forms
ModelEditForm
getEditTypeKey()
Form Container &Edit Components
ModelEditMediatorModelDescriptor
getEditTypeKey()
ModelAspectAdaptersViewAspectAdapters
View Controller Model
Organizing Models in Views
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
61
Model-Oriented Tables & Trees
Organize for Select, Add, Delete Display view-oriented model aspects Adapt models to rows, sub-trees, etc. Import and export of model objects
Use internal representation in application Queries, filtering, sorting, etc. Refresh, caching, & performance issues Concurrent access to external data
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
62
Model-Oriented Tables ModelListTableModel
Subclass of AbstractTableModel Manages an ArrayList of model-objects Model-object per row, aspect per column Keeps track of sorting state
ModelTableColumnAdapter Façade and Factory for TableColumn getColumnValue(Object model, int row) Helps manage headers, sorting, widths,
custom cell-renderers, etc.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
63
Using Model-Oriented Tables
ModelTableColumnAdapter firstNameColumnAdapter = new ExprTableColumnAdapter("firstName", // property name "First Name", // column header label false, // editable String.class, // type for sorting, etc. 40, 120, 400); // min, normal, max widths...ModelTableColumnAdapter[] modelColumnAdapters = { firstNameColumnAdapter, lastNameColumnAdapter, ...};
ModelTable attendeesTable = new ModelTable(SeminarAttendee.class, modelColumnAdapters);attendeesTable.getSelectionModel().addListSelectionListener(...);
attendeesTable.getModelListTableModel().setContents(getAllAttendees());
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
64
Using Model-Oriented Tables
Create with custom column adapters. Customize rendering by column.
Register selection listener. Configure to support column sorting. Load with collection of model objects. Add new items to table-model. Delete items from table model. Load table from external data source.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
65
Model-Oriented Trees Each node responsible for computing
its own children, when asked. ModelTreeNode supports structural
hierarchy of application model objects. One-level-deep option for getting
expansion indicators right. Simple, powerful refresh logic based
on child-nodes computation. Basic tree-cell-renderer configuration:
getNodeIcon(…), getNodeString(…)
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
66
Using Model-Oriented Treesclass JavaClassTreeNode extends ModelTreeNode { public JavaClassTreeNode(Class javaClass) { this._javaClass = javaClass; } public List computeChildren() { ArrayList children = new ArrayList(); Method[] methods = _javaClass.getMethods(); for (int i = 0, n = methods.length; i < n; i++) children.add(new JavaMethodTreeNode(methods[i]); ... return(children); } public Icon getNodeIcon(boolean expanded, boolean selected, …) { if (_javaClass.isInterface()) return INTERFACE_ICON; ... } public String getNodeString(boolean expanded, boolean selected, …) { return _javaClass.getName(); }}
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
67
Coordinating Tables and Forms
TableFormMediator
selectionChanged(SelectionEvent)getDeleteRowAction()
getNewInstanceAction()
ModelTable
ModelEditFormManager
getEditTypeKey(Object model)editModelObject(Object model)
createAndEditNewInstance()
ModelEditForms ModelObjectFactory
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
68
Inside TableFormMediator
public void valueChanged(ListSelectionEvent listSelectionEvent) { // overrule selection change if changes would be lost if (_formManager.hasUnappliedChanges() && !handleUnappliedChanges()) { revertSelection(_editedRowModel); return; }
// clear model from current edit-form EditForm activeForm = _formManager.getActiveEditForm(); if (activeForm != null) _formManager.editModelObject(null, activeForm.getEditTypeKey());
// get selected model-object from selected row index int row = _table.getSelectedRow(); if ((row >= 0) && (row < _tableModel.getRowCount())) { // edit the model-object in the appropriate edit-form _editedRowModel = _tableModel.getRowModel(row); Object editTypeKey = _formManager.getEditTypeKey(_editedRowModel); _formManager.editModelObject(_editedRowModel, editTypeKey); }}
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
69
Application-MVC Controllers Specify initiator events and sources
Action events, model-edit events, etc. Specify responses to initiator events
Update application model state Call application model methods Import, export, and sync models
Specify what the UI should do next Translate handled initiator events into
application behavior
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
70
An Example Editor Application External XML
Internal Java XJX framework
Several tables Different Tabs Many subclasses Counts in Tabs
Consistent UI Same behavior Early feedback
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
71
Model-Oriented Data Flow
External Data(XML / DBMS)
Externalto JavaModel
Translation
TableFormMediator
EditFormManager
EditForm
ModelEditMediator
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
72
Application-Level MVC
Application Model• view-independent• model-change source• defines app behavior• high-level abstraction
Application View• edit model aspects• render model objects• organize model objects• fire initiator-events
App Controller• initiator-event listener• update app models• use app-model API• select alternative views
model change events
model state changes andmethod calls
initiatorevents
model state
queries
view control
Event-Handling Tips & Patterns
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
74
Event Handling Strategies
Configure UI Components with Actions Self-enabling Actions Relay-Actions & Action Wrappers ActionListeners without Inner Classes Failure Listeners / Exception Handlers Swing’s Single-Thread Restriction Long-Running Operations
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
75
Actions as Abstract Initiators Associate Actions with
Buttons, toolbar-buttons, menu-items, … When Action enabled, components too
Listeners register with Actions Same Action fired from different places
Actions can configure UI components Label, icon, mnemonic, accelerator, …
Extend AbstractAction for even more Component initialization, enable logic, …
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
76
Self-Enabling Actions Important to enable/disable Actions
appropriately. Can use a different tool-tip when
Action not enabled, to say why not. Views can use central action-manager
with self-enabling Actions. Encapsulate common enable logic:
Number and types of selections Selected object state – property values
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
77
RelayActions & Action Wrappers
In a Façade, want to relay events from within, with façade as source.
May want more control over when façade’s Actions are enabled.
Chain-of-Responsibility Pattern for configurable properties.
Chain-reaction of ActionListeners and ActionEvents.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
78
RelayActions & Action Wrapperspublic class RelayAction extends AbstractAction implements ActionListener, PropertyChangeListener{ public RelayAction(Action targetAction) { this._allowEnable = true; setTargetAction(targetAction); // register self as listener } public void propertyChange(PropertyChangeEvent event) { if ("enabled".equals(event.getPropertyName()) setEnabledInternal(); } public void setEnabled(boolean allowEnable) { this._allowEnable = allowEnable; setEnabledInternal(); } private void setEnabledInternal() { super.setEnabled(_allowEnable && _targetAction.isEnabled()); } ...
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
79
Action Listeners without Inner Classes
Use reflection to make a call to a method that takes an ActionEvent.
Encapsulate the Method call & other state in an ActionListener subclass.
Create instances of ActionListener subclass instead of many subclasses.
Listeners implemented in terms of methods in classes that uses them.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
80
MethodProxyActionListener/** * MethodProxyActionListener adapts any public instance method that * takes an ActionEvent parameter to the ActionListener interface. */public class MethodProxyActionListener implements ActionListener { public MethodProxyActionListener(Object instance, String methodName) throws NoSuchMethodException { _instance = instance; _method = this.findMethod(instance.getClass(), methodName); } public void actionPerformed(ActionEvent event) { try { _method.invoke(_instance, new Object[] { event }); } catch (Exception e) { // InvocationTargetException or IllegalAccessException rethrowAsRuntimeExceptionOrError(e); } } ...
someAction.addActionListener (new MethodProxyActionListener(handlerObj, "handleSomeAction"));
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
81
Failure-Event Listeners
Usually to report errors, not fix them. Multiple event-listeners possible. Failure-event has all the details. Event may be delivered long after
exception has been handled internally. Variation: attempt to fix problem
e.g. repair broken connection, try again listeners should mark the event for retry
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
82
Swing’s Single-Thread Design
Most Swing components and models are not thread-safe (by design).
Intended to be used and modified only on event-dispatch-thread.
To update components & models from another thread, use invokeLater(…).
invokeLater(Runnable) puts a special kind of event on the event-queue.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
83
Long Running Activities Use separate, cancelable threads.
Respond promptly to cancel requests. Disable appropriate parts of UI. Use events and listeners to notify:
Start and end of thread execution Use cancelable-thread-manager
Manage threads, coordinate cancel, etc. Relay events to general listeners
Use invokeLater to handle completion.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
84
Inside CancelableThread – 1public CancelableThread(Runnable innerRunnable) { this._innerRunnable = innerRunnable;}
public void run() { this.started = true; Throwable throwable = null; try { fireThreadStarted(_innerRunnable, this); _innerRunnable.run(); } catch (RuntimeException e) { throwable = e; } catch (ThreadDeath t) { throwable = t; } finally { this.completed = true; // notify about thread completion two different ways synchronized (this) { this.notify(); } fireThreadCompleted(_innerRunnable, this, throwable); }}
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
85
Inside CancelableThread – 2public void cancel() { _cancelled = true; // mark thread as cancelled this.interrupt(); // interrupt active wait calls}
public boolean terminate(int maxWaitMillis, boolean forceTermination) { if (!this.isAlive()) return true; this.cancel(); // request termination politely try { this.join(maxWaitMillis); // wait for termination or timeout } catch (InterruptedException e) { // safe to ignore here } if (!this.isAlive()) return true; if (forceTermination) this.stop(); // force hostile termination return false;}
Swing Layout Manager Tips
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
87
Swing Layout Manager Basics
Purpose and rationale Layout Manager Conceptual Model
Relative 2D constraints Constraints propagate bottom-up
Layout Roles & Responsibilities Important API Creating new Layout Managers
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
88
Layout Manager Rationale Best (maybe only) way to build cross-
platform user interfaces. Size and shape of components based
on configured properties. Labels, icons, borders, fonts, children, …
Containers should try to respect preferred sizes of child components.
Expressing multiple levels of constraints sounds harder than it is.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
89
Expressing Systems of Constraints in a 2-Dimensional Space
Layout Managers solve constraints. Flexible constraints usually relative. Easy to learn how to set the table:
Absolute relative positioning Absolute relative (preferred) sizes Absolute relative spacing Absolute relative orientation
Good layout managers add clarity.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
90
Users of Layout Managers Programmers
Code clarity and succinctness Choice of special-purpose alternatives Able to collaborate with other objects
Visual Layout Tools General-purpose visual metaphor Visual representation of constraints Often too complex to use by hand
Special-purpose layouts can wrap and delegate to general-purpose layouts.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
91
Setting the Table
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
92
LayoutManager Responsibilities Help compute Container’s preferred size
In terms of components’ preferred sizes In terms of insets, spacing, is-visible In terms of specified constraints (e.g. top)
Assign sizes and positions to components Using same constraints as above Don’t change container’s size or position
Components provide own preferred sizes Frequently using their own layout managers
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
93
Phases of Container Layout Compute Window’s preferred size
Compute child preferred sizes (recursive) Combine using window’s layout manager
Assign the Window’s size and position Layout each child component
Assign size and position to each child Ask the child to perform layout on itself
Layout each child component Assign size and position to each child Ask the child to perform layout on itself
…
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
94
Layout Roles and Methods
Component
Dimension getPreferredSize()Insets getInsets()
Container / JComponent
void doLayout()Component getComponent(int index)
void revalidate()
LayoutManager
Dimension preferredLayoutSize(Container)void layoutContainer(Container)
Concrete LayoutManager
extends implements
layout
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
95
Import Swing Layout API Important LayoutManager methods:
Dimension preferredLayoutSize(Container) void layoutContainer(Container) void addLayoutComponent(String*, Component) void removeLayoutComponent(Component)
Container methods (and others): void setLayout(LayoutManager) void setBounds(int x, int y, int w, int h) void doLayout() Dimension getPreferredSize() int getVisibleRowCount() (in JList) invalidate(), validate(), revalidate()
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
96
Containers and Layout Managerspublic class Container extends Component { public void setLayout(LayoutManager layout) { this._layout = layout; } public Dimension getPreferredSize() { return _layout.preferredLayoutSize(this); } public void doLayout() { _layout.layoutContainer(this); } …
public class AnyLayout implements LayoutManager { public Dimension preferredLayoutSize(Container container) { … container.getComponent(i).getPreferredSize() … } public void layoutContainer(Container container) { Dimension containerSize = container.getSize(); Insets containerInsets = container.getInsets(); … child.setBounds(childX, childY, childWidth, childHeight); …
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
97
Swing Layout Rules of Thumb Only LayoutManagers call setBounds()
(except for top-level windows). Almost never call setPreferredSize(). Implement Scrollable as appropriate. Break things down into simpler parts.
Use sub-containers with their own layouts Encapsulate common uses of complex
layout managers. revalidate() when composition changes.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
98
Custom Layout Managers Container-owned or sharable. Compute preferred-size abstractly.
Container’s current size doesn’t matter. Use preferred sizes of current children. Don’t forget the container’s insets.
Layout container concretely. Don’t change the container’s size, position, etc. Assign sizes and positions to all children. Don’t invalidate layout of anything else. Don’t forget the container’s insets.
How to handle excess/insufficient space. Stretch, align, squash, abbreviate, etc.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
99
Summary and Review User interfaces are for expressing
intentions and maintaining confidence. Check for and report success & problems.
Mature user interfaces exhibit two levels of Model-View-Controller. Application models and controllers should
be almost independent of user interface. Good frameworks maximize reuse and
minimize effort. Complex operations same for many apps. Roles the same for many apps.
GBCACM PDS April 30, 2005
Dan Jacobs http://www.modelobjects.com
100
Questions and Discussion