Presentation is loading. Please wait.

Presentation is loading. Please wait.

Model-Oriented Architectures and Frameworks for Swing-Based User Interfaces Dan Jacobs President and founder, ModelObjects Group.

Similar presentations

Presentation on theme: "Model-Oriented Architectures and Frameworks for Swing-Based User Interfaces Dan Jacobs President and founder, ModelObjects Group."— Presentation transcript:

1 Model-Oriented Architectures and Frameworks for Swing-Based User Interfaces Dan Jacobs President and founder, ModelObjects Group President and founder, JPlates Inc. Chairman, Boston ACM WebTech Group

2 GBCACM PDS April 30, 2005 Dan Jacobs 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

3 GBCACM PDS April 30, 2005 Dan Jacobs 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

4 GBCACM PDS April 30, 2005 Dan Jacobs 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

5 Overview of AWT and Swing

6 GBCACM PDS April 30, 2005 Dan Jacobs 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

7 GBCACM PDS April 30, 2005 Dan Jacobs 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

8 GBCACM PDS April 30, 2005 Dan Jacobs 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 System and Window System Application Code J2SE Many other standard extensions

9 GBCACM PDS April 30, 2005 Dan Jacobs 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.

10 GBCACM PDS April 30, 2005 Dan Jacobs 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

11 GBCACM PDS April 30, 2005 Dan Jacobs 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.

12 GBCACM PDS April 30, 2005 Dan Jacobs 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

13 GBCACM PDS April 30, 2005 Dan Jacobs 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

14 GBCACM PDS April 30, 2005 Dan Jacobs 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);

15 Object-Oriented Design Patterns and Frameworks

16 GBCACM PDS April 30, 2005 Dan Jacobs 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.

17 GBCACM PDS April 30, 2005 Dan Jacobs 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

18 GBCACM PDS April 30, 2005 Dan Jacobs 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.

19 GBCACM PDS April 30, 2005 Dan Jacobs 19 Object Adapter Design Pattern class OldHairDryer OldPlug getPlug(); boolean getBlowerOn(); setBlowerOn(boolean); … interface NewPlugProvider NewPlug getNewPlug(); … NewPlugAdapter implements NewPlugProvider NewPlug getNewPlug() { … } private OldSocket _oldSocket; … references implements class NewSocket plugIn( NewPlug ); … references

20 GBCACM PDS April 30, 2005 Dan Jacobs 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

21 GBCACM PDS April 30, 2005 Dan Jacobs 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-sourceimplements event

22 GBCACM PDS April 30, 2005 Dan Jacobs 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

23 GBCACM PDS April 30, 2005 Dan Jacobs 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);

24 GBCACM PDS April 30, 2005 Dan Jacobs 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.

25 Model View Controller Pattern Click Here A Frequently Misunderstood Pattern

26 GBCACM PDS April 30, 2005 Dan Jacobs 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.

27 GBCACM PDS April 30, 2005 Dan Jacobs 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 gesture events model state queries view control

28 GBCACM PDS April 30, 2005 Dan Jacobs 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.

29 GBCACM PDS April 30, 2005 Dan Jacobs 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.

30 GBCACM PDS April 30, 2005 Dan Jacobs 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.

31 GBCACM PDS April 30, 2005 Dan Jacobs 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()); … }

32 GBCACM PDS April 30, 2005 Dan Jacobs 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

33 Model-Oriented Architectures Model-Oriented Application = Model Objects + Coordinated Uses of Model Objects

34 GBCACM PDS April 30, 2005 Dan Jacobs 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

35 GBCACM PDS April 30, 2005 Dan Jacobs 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.

36 GBCACM PDS April 30, 2005 Dan Jacobs 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.

37 GBCACM PDS April 30, 2005 Dan Jacobs 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 Application Model Object Instance Application Model Object Class (or other metadata) n n 1 1 11 11 11 n 1 class level information instance level

38 GBCACM PDS April 30, 2005 Dan Jacobs 38 Inside ModelObjectAdapter public 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); }... }

39 GBCACM PDS April 30, 2005 Dan Jacobs 39 HashTable ModelAspectAdapter public 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) { … }

40 GBCACM PDS April 30, 2005 Dan Jacobs 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)

41 GBCACM PDS April 30, 2005 Dan Jacobs 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

42 Adapters for Edit Components

43 GBCACM PDS April 30, 2005 Dan Jacobs 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

44 GBCACM PDS April 30, 2005 Dan Jacobs 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.

45 GBCACM PDS April 30, 2005 Dan Jacobs 45 ViewAspectAdapter void setModelAspectValue(Object) Object getModelAspectValue() void setEditable(boolean) addChangeListener(ChangeListener) EditRuleModelAspectIdViewValueConverter AWT/Swing Component

46 GBCACM PDS April 30, 2005 Dan Jacobs 46 Inside JTextFieldAdapter public 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(); }

47 GBCACM PDS April 30, 2005 Dan Jacobs 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

48 GBCACM PDS April 30, 2005 Dan Jacobs 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(...);

49 Connecting Models to Views

50 GBCACM PDS April 30, 2005 Dan Jacobs 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.

51 GBCACM PDS April 30, 2005 Dan Jacobs 51 ModelEditMediator ModelObjectAdapter View Aspect Adapters Model Aspect Adapters Model Descriptor Model-Object Propagator Model-Object Validators Edit Rule View Value Converter User Interface Component ModelEditMediator apply, reset, undo, redo editModelObject(ModelObjectAdapter) editModelAsNewObject(ModelObjectAdapter) addModelEditListener(ModelEditListener) addModelEditFailureListener(…)

52 GBCACM PDS April 30, 2005 Dan Jacobs 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.

53 GBCACM PDS April 30, 2005 Dan Jacobs 53 Edit, Apply, and Validate Logic Swing Components and Swing Models ViewAspectAdapters and ViewValueConverters ModelEditMediator and collected model-aspect values PropertyChangeEvents and UndoableModelEditEvents ModelObjectAdapter ModelDescriptor and ModelAspectAdapters ModelObjectValidators and ModelObjectPropagator Application Model Object ModelEditListeners and ModelEditFailureListeners ModelAspectValidators

54 GBCACM PDS April 30, 2005 Dan Jacobs 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

55 GBCACM PDS April 30, 2005 Dan Jacobs 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.

56 GBCACM PDS April 30, 2005 Dan Jacobs 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

57 GBCACM PDS April 30, 2005 Dan Jacobs 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 and method calls initiator events model state queries view control

58 GBCACM PDS April 30, 2005 Dan Jacobs 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.

59 GBCACM PDS April 30, 2005 Dan Jacobs 59 Type-Specific Model-Edit-Forms ModelEditForm getEditTypeKey() Form Container & Edit Components ModelEditMediator ModelDescriptor getEditTypeKey() ModelAspectAdaptersViewAspectAdapters ViewController Model

60 Organizing Models in Views

61 GBCACM PDS April 30, 2005 Dan Jacobs 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

62 GBCACM PDS April 30, 2005 Dan Jacobs 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.

63 GBCACM PDS April 30, 2005 Dan Jacobs 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());

64 GBCACM PDS April 30, 2005 Dan Jacobs 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.

65 GBCACM PDS April 30, 2005 Dan Jacobs 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(…)

66 GBCACM PDS April 30, 2005 Dan Jacobs 66 Using Model-Oriented Trees class 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(); }

67 GBCACM PDS April 30, 2005 Dan Jacobs 67 Coordinating Tables and Forms TableFormMediator selectionChanged(SelectionEvent) getDeleteRowAction() getNewInstanceAction() ModelTable ModelEditFormManager getEditTypeKey(Object model) editModelObject(Object model) createAndEditNewInstance() ModelEditFormsModelObjectFactory

68 GBCACM PDS April 30, 2005 Dan Jacobs 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); }

69 GBCACM PDS April 30, 2005 Dan Jacobs 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

70 GBCACM PDS April 30, 2005 Dan Jacobs 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

71 GBCACM PDS April 30, 2005 Dan Jacobs 71 Model-Oriented Data Flow External Data (XML / DBMS) External to Java Model Translation TableFormMediator EditFormManager EditForm ModelEditMediator

72 GBCACM PDS April 30, 2005 Dan Jacobs 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 and method calls initiator events model state queries view control

73 Event-Handling Tips & Patterns

74 GBCACM PDS April 30, 2005 Dan Jacobs 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

75 GBCACM PDS April 30, 2005 Dan Jacobs 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, …

76 GBCACM PDS April 30, 2005 Dan Jacobs 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

77 GBCACM PDS April 30, 2005 Dan Jacobs 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.

78 GBCACM PDS April 30, 2005 Dan Jacobs 78 RelayActions & Action Wrappers public 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()); }...

79 GBCACM PDS April 30, 2005 Dan Jacobs 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.

80 GBCACM PDS April 30, 2005 Dan Jacobs 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"));

81 GBCACM PDS April 30, 2005 Dan Jacobs 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

82 GBCACM PDS April 30, 2005 Dan Jacobs 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.

83 GBCACM PDS April 30, 2005 Dan Jacobs 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.

84 GBCACM PDS April 30, 2005 Dan Jacobs 84 Inside CancelableThread – 1 public CancelableThread(Runnable innerRunnable) { this._innerRunnable = innerRunnable; } public void run() { this.started = true; Throwable throwable = null; try { fireThreadStarted(_innerRunnable, this);; } 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); }

85 GBCACM PDS April 30, 2005 Dan Jacobs 85 Inside CancelableThread – 2 public 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; }

86 Swing Layout Manager Tips

87 GBCACM PDS April 30, 2005 Dan Jacobs 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

88 GBCACM PDS April 30, 2005 Dan Jacobs 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.

89 GBCACM PDS April 30, 2005 Dan Jacobs 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.

90 GBCACM PDS April 30, 2005 Dan Jacobs 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.

91 GBCACM PDS April 30, 2005 Dan Jacobs 91 Setting the Table

92 GBCACM PDS April 30, 2005 Dan Jacobs 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

93 GBCACM PDS April 30, 2005 Dan Jacobs 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  …

94 GBCACM PDS April 30, 2005 Dan Jacobs 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

95 GBCACM PDS April 30, 2005 Dan Jacobs 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()

96 GBCACM PDS April 30, 2005 Dan Jacobs 96 Containers and Layout Managers public 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); …

97 GBCACM PDS April 30, 2005 Dan Jacobs 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.

98 GBCACM PDS April 30, 2005 Dan Jacobs 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.

99 GBCACM PDS April 30, 2005 Dan Jacobs 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.

100 GBCACM PDS April 30, 2005 Dan Jacobs 100 Questions and Discussion

Download ppt "Model-Oriented Architectures and Frameworks for Swing-Based User Interfaces Dan Jacobs President and founder, ModelObjects Group."

Similar presentations

Ads by Google