MVC and Swing Models

Swing Data Binding Karsten Lentzsch www. JGoodies. com Presentation Goals Understand MVC and Swing models. Learn how to bind domain objects to Swing UI components. :: JGOODIES :: Java User Interface Design Speaker Qualifications ? ? ? ? ? ? Karsten builds elegant Swing apps works with Objects since 1990 helps others with UI and architectures provides libraries that complement Swing provides examples for Swing architectures writes about Java desktop issues :: JGOODIES :: Java User Interface Design Agenda ? ? ? ? ? ? Introduction MVC and Swing How to bind single values? How to bind lists A 3-tier Swing architecture How binding works in projects : JGOODIES :: Java User Interface Design Swing Building Blocks Application 1 Panels Utils Application 2 Help Printing Applications Helper Code/Libs Application Frame Basic Libraries Foundation Components, Application Management, etc. Appearance Layout Binding Validation JRE / Swing :: JGOODIES :: Java User Interface Design Swing Building Blocks Application 1 Panels Utils Application 2 Help Printing Applications Helper Code/Libs Application Frame Basic Libraries Foundation Components, Application Management, etc. Appearance Layout Binding Validation JRE / Swing :: JGOODIES :: Java User Interface Design Questions ? ? ? ? ? ? Where do I find MVC in Swing? How to structure a Swing application? What is part of the model? How do I choose models? How to build a view? What does a controller do? Do I need controllers? :: JGOODIES :: Java User Interface Design I – Basics MVC and Swing :: JGOODIES :: Java User Interface Design Before MVC Painting Code State Operations (Control Behavior) State How to live without MVC? :: JGOODIES :: Java User Interface Design Before MVC: 2 Layers Painting Code State Operations State Client Server :: JGOODIES :: Java User Interface Design Separate Domain from Views ? Domain logic contains no GUI code ?

Presentation handles all UI issues ? Advantages: – Each part is easier to understand – Each part is easier to change :: JGOODIES :: Java User Interface Design Domain and Presentation Painting Code Presentation Layer State Modifications State Domain Layer :: JGOODIES :: Java User Interface Design Loose Coupling ? The domain shall not reference the GUI ? Presentation refers to domain and can modify it ? Advantages: – Reduces complexity – Allows to build multiple presentations of a single domain object :: JGOODIES :: Java User Interface Design Loose Coupling Painting Code State Modifications reports changes State refers to/modifies : JGOODIES :: Java User Interface Design Separate View and Controller If you separate the painting code (View) from the state modifications (Controller), it’s easier to: ? combine views and controllers ? reuse views and controllers :: JGOODIES :: Java User Interface Design MVC refers to View Controller reports changes Model :: JGOODIES :: Java User Interface Design MVC refers to View Controller reports changes Model :: JGOODIES :: Java User Interface Design UI State vs. Data State We can categorize models into: ? domain related ? GUI related GUI state can make up its own layer. :: JGOODIES :: Java User Interface Design MVC plus Model Layer

View Controller Presentation Layer GUI Model (GUI) Model Layer Domain Model Domain Layer :: JGOODIES :: Java User Interface Design Candidates for a Model Layer ? TreeModel: converts a domain object tree into a form useable for JTree ? Models that do not belong to the domain: GUI state, e. g. mouse pressed, mouse over ? Password in a login dialog ? Search values ? :: JGOODIES :: Java User Interface Design Conbining MVC Triads A typical MVC UI combines MVC triads. ? Defines models as a graph of domain objects ? Composes larger views from small views ? Composes controllers from subcontrollers :: JGOODIES :: Java User Interface Design

MVC Triads with Model Layer V V M M Domain Object DO DO M V C C C Presentation Layer Model Layer Domain Layer :: JGOODIES :: Java User Interface Design Factoring out the Look Swing can change its appearance and behavior or in other words: look and feel. :: JGOODIES :: Java User Interface Design M-JComponent-VC View JComponent Controller Swing Model(s) :: JGOODIES :: Java User Interface Design Example: JCheckBox Painting JCheckBox Event Handling MetalCheckBoxUI ToggleButtonModel :: JGOODIES :: Java User Interface Design JCheckBox: Some Details JCheckBox ChangeListener Painting Event Handling MetalCheckBoxUI BasicButtonUI

MouseListener MouseMotionListener FocusListener PropertyChangeListener ChangeListener ToggleButtonModel :: JGOODIES :: Java User Interface Design JCheckBox: Types of State JCheckBox enabled text, … GUI Properties ToggleButtonModel armed pressed, … selected GUI State Data State :: JGOODIES :: Java User Interface Design JCheckBox: Binding Task JCheckBox GUI Component ToggleButtonModel selected Data Model anAlbum title=”Preludes” classical=true Domain object :: JGOODIES :: Java User Interface Design JCheckBox: Binding Task aJCheckBox GUI Component aToggleButtonModel selected=true Data Model connect, synchronize Domain Object : JGOODIES :: Java User Interface Design anAlbum title=”Preludes” classical=true Summary ? ? ? ? Swing doesn’t use the original MVC Swing uses an extended form of MVC Swing shares the motivation behind MVC Swing adds features to the original MVC Therefore, we will search and compare binding solutions for Swing, not MVC. :: JGOODIES :: Java User Interface Design II – Binding Values How to connect domain objects with UI components? :: JGOODIES :: Java User Interface Design Binding Tasks ? ? ? ? ? ? ? Read and write domain object properties Get and set GUI model state Report and handle changes in the domain Buffer values – delay until OK ressed Change management – commit required? Indirection as in an Master-Detail view Convert types, e. g. Date to String :: JGOODIES :: Java User Interface Design Copying Values to Views #setSelected 2. Write aToggleButtonModel selected=false aJCheckBox 1. Read #isClassical anAlbum title=”Preludes” classical=true :: JGOODIES :: Java User Interface Design Copying Values to Views aJCheckBox aToggleButtonModel 3. Value changed selected=true anAlbum title=”Preludes” classical=true :: JGOODIES :: Java User Interface Design Copying Values to the Domain aJCheckBox #isSelected 1. Read aToggleButtonModel selected=true nAlbum title=”Preludes” classical=false 2. Write #setClassical :: JGOODIES :: Java User Interface Design Copying Values to the Domain aJCheckBox aToggleButtonModel selected=true anAlbum title=”Preludes” classical=true 3. Value changed :: JGOODIES :: Java User Interface Design Code Example: Copy to View public void modelToView() { Album anAlbum = getEditedAlbum(); classicalBox. setSelected( anAlbum. isClassical()); titleField. setText( anAlbum. getTitle()); … } :: JGOODIES :: Java User Interface Design Code Example: Copy to Domain public void viewToModel() { Album anAlbum = getEditedAlbum(); anAlbum. setClassical( classicalBox. sSelected(); anAlbum. setTitle( titleField. getText(); … } :: JGOODIES :: Java User Interface Design Copying: Pros and Cons ? Easy to understand, easy to explain ? Works in almost all situations ? Easy to debug – explicit data operations ? Blows up the view code ? It’s difficult to synchronize views ? Handles domain changes poorly :: JGOODIES :: Java User Interface Design Alternative aJCheckBox aToggleButtonModel selected=false anAlbum title=”Preludes” classical=true Note: you can’t share the model :: JGOODIES :: Java User Interface Design Direct Adapter: TableModel aJTable implements myAlbumTableAdapter TableModel

Converts Album properties to TableModel aBook aBook title=”Swing” anAlbum title=”Swing” available=true title=”Preludes” available=true classical=true :: JGOODIES :: Java User Interface Design Direct Adapter: JCheckBox aJCheckBox implements anAlbumClassicalToggleButtonAdapter ToggleButtonModel Converts Album#classical to ToggleButtonModel anAlbum title=”Preludes” classical=true :: JGOODIES :: Java User Interface Design Problem with Direct Adapters Requires an individual adapter for each domain object property. Similar to incompatible electric connectors. Code is all the same except for the methods that read and write domain properties. : JGOODIES :: Java User Interface Design Concept ? Use a universal model (ValueModel) ? Convert domain properties to ValueModel ? Build converters from ValueModel to Swing models: ToggleButtonModel, etc. ? We end up with about 15 classes. :: JGOODIES :: Java User Interface Design ValueModel and Adapter aJCheckBox aToggleButtonAdapter aValueModel anAlbum title=”Preludes” classical=true :: JGOODIES :: Java User Interface Design ValueModel: Requirements ? We want to get its value ? We want to set its value ? We want to observe changes :: JGOODIES :: Java User Interface Design The ValueModel Interface ublic interface ValueModel { Object getValue(); void setValue(Object newValue); void addChangeListener(ChangeListener l); void removeChangeListener(ChangeListener l); } :: JGOODIES :: Java User Interface Design Which Event Type? ? ChangeEvent reports no new value; must be read from the model – if necessary ? PropertyChangeEvent provides the old and new value; both can be null :: JGOODIES :: Java User Interface Design ValueModel & PropertyAdapter aJCheckBox aToggleButtonAdapter implements ToggleButtonModel aPropertyAdapter propertyName=”classical” anAlbum title=”Preludes” classical=true mplements ValueModel :: JGOODIES :: Java User Interface Design Domain Object Requirements ? We want to get and set values ? We want to do so in a uniform way ? Changes shall be observable That’s what Java Beans provide. :: JGOODIES :: Java User Interface Design (Bound) Bean Properties ? Java Beans have properties, that we can get and set in a uniform way. ? Bean properties are bound, if we can observe property changes by means of PropertyChangeListeners. :: JGOODIES :: Java User Interface Design PropertyAdapter ? BeanAdapter and PropertyAdapter convert Bean properties to ValueModel ?

Observe bound properties ? Use Bean Introspection that in turn uses Reflection to get and set bean properties :: JGOODIES :: Java User Interface Design ValueModel & PropertyAdapter aJCheckBox aToggleButtonAdapter aPropertyAdapter propertyName=”classical” ValueModel implements anAlbum (Bean) title=”Preludes” classical=true get/set :: JGOODIES :: Java User Interface Design Build a Chain of Adapters private void initComponents() { Album album = getEditedAlbum(); ValueModel aValueModel = new PropertyAdapter(album, “classical”); JCheckBox classicalBox = new JCheckBox(); classicalBox. etModel( new ToggleButtonAdapter(aValueModel)); } :: JGOODIES :: Java User Interface Design ComponentFactory private void initComponents() { Album album = getEditedAlbum(); JCheckBox classicalBox = ComponentFactory. createCheckBox( album, Album. PROPERTYNAME_CLASSICAL); } :: JGOODIES :: Java User Interface Design Buffering: Delaying Commits ? Selecting the JCheckBox changes the bound domain property immediately. ? Often we want to delay value commits until the user presses OK or Accept. ? We can buffer in the adapter chain or in the domain layer. :: JGOODIES :: Java User Interface Design

BufferedValueModel aJCheckBox Indicates Commit or Flush aToggleButtonAdapter aTriggerChannel aBufferedValueModel implements ValueModel aPropertyAdapter anAlbum classical=true implements :: JGOODIES :: Java User Interface Design Sharing a Buffer Trigger aJCheckBox aToggleButtonAdapter aBufferedValueModel aPropertyAdapter aJTextField aDocumentAdapter aBufferedValueModel aPropertyAdapter aTriggerChannel anAlbum title=”Preludes” classical=true :: JGOODIES :: Java User Interface Design Adapter vs. Connector aJTextField aJFormattedTextField aDocumentAdapter aPropertyConnector aPropertyAdapter for Album#title PropertyAdapter for Album#releaseDate anAlbum title=”Preludes” releaseDate=Dec-5-1967 :: JGOODIES :: Java User Interface Design Converter vs. Formatter aJTextField aDocumentAdapter aPropertyConnector DateToStringConverter aPropertyAdapter for Album#releaseDate aPropertyAdapter for Album#releaseDate uses Formatter aJFormattedTextField anAlbum releaseDate=Dec-5-1967 :: JGOODIES :: Java User Interface Design Indirection aJCheckBox aToggleButtonAdapter aPropertyAdapter propertyName=”classical” aJTextField aDocumentAdapter aPropertyAdapter propertyName=”title” Holds the edited album aBeanChannel nAlbum title=”Preludes” classical=true anAlbum title=”Etudes” classical=true :: JGOODIES :: Java User Interface Design Indirection aJCheckBox aToggleButtonAdapter aPropertyAdapter propertyName=”classical” aJTextField aDocumentAdapter aPropertyAdapter propertyName=”title” Holds the edited album aBeanChannel anAlbum title=”Preludes” classical=true anAlbum title=”Etudes” classical=true :: JGOODIES :: Java User Interface Design III – Binding Lists How to connect Lists of domain values with Swing components? :: JGOODIES :: Java User Interface Design List Binding Problems List views require fine grained change events.

We want to observe list content changes. Otherwise list views poorly handle the selection and scroll state. :: JGOODIES :: Java User Interface Design Requirements for a List Model ? Get list elements ? Provide the list size ? Report changes: – if elements change – if elements have been added – if elements have been removed The Swing class ListModel provides this. :: JGOODIES :: Java User Interface Design ListModel Implementations ? ArrayListModel extends ArrayList, implements ListModel ? LinkedListModel extends LinkedList, implements ListModel ? We can operate on List and can observe ListModel changes. : JGOODIES :: Java User Interface Design Binding Lists to JList aJList ListModel anArrayListModel implements List aBook aBook anAlbum :: JGOODIES :: Java User Interface Design Binding Lists to JTable aJTable anAlbumTableAdapter implements TableModel ListModel anArrayListModel implements List aBook aBook anAlbum :: JGOODIES :: Java User Interface Design Often: List with Single Selection ? We build a compound model that holds the ListModel and a selection in the list. ? This model reports changes of: – the selection – the selection index – the list contents – the list :: JGOODIES :: Java User Interface Design

SelectionInList aJList SelectionAdapter aSelectionInList ListModel SelectionHolder aBook aBook anAlbum :: JGOODIES :: Java User Interface Design Overview / Detail aJList SelectionAdapter aSelectionInList ListModel SelectionHolder aJTextField aDocumentAdapter aPropertyAdapter propertyName=”title” beanChannel aBook aBook anAlbum :: JGOODIES :: Java User Interface Design IV – Architecture A 3-tier Swing client architecture :: JGOODIES :: Java User Interface Design Design Goals ? Works with standard Swing components ? Works with custom Swing components ? Requires no special components ? Requires no special panels ?

Integrates well with validation ? Works with different validation styles :: JGOODIES :: Java User Interface Design 3-Tier Client Architecture JList JButton JTextField Presentation ListModel Action ValueModel Model Layer Domain Object Domain Layer DO DO :: JGOODIES :: Java User Interface Design Benefit of 3 Layers ? ? ? ? ? ? ? ? Views are easy to build Views are decoupled Domain layer is separated Developers know where to put what code Synchronization is easy Decreased complexity Model operations located in a single layer Poor code limited to the model layer :: JGOODIES :: Java User Interface Design Multiple Views

View 1 JTextField JButton JList View 2 JMenuItem JLabel Presentation ListModel Action ValueModel Model Layer :: JGOODIES :: Java User Interface Design Setting UI Properties: Actions JButton #enabled ButtonActionPropertyChangeListener Updates button property if the Action has changed ListModel Action #enabled ValueModel :: JGOODIES :: Java User Interface Design Setting UI Properties View JTextField ModelChangeHandler Updates textfield property if the model has changed JButton JList GUI Model ValueModel Can provide bound bean properties :: JGOODIES :: Java User Interface Design Adapting Multiple Properties

JTextField JTextField JCheckBox Presentation BeanAdapter Vends PropertyAdapters Album #title #artist #classical Domain Layer :: JGOODIES :: Java User Interface Design Example View Source Code 1) Variables for UI components 2) Constructors 3) Create, bind, configure UI components 4) Register GUI state handlers with the model 5) Build and return panel 6) Handlers that update GUI state :: JGOODIES :: Java User Interface Design Example View 1/7 public final class AlbumView { // Refers to the model provider private AlbumPresentationModel model; // UI components private JTextField private JCheckBox private JButton private JList … itleField; classicalBox; buyNowButton; referencesList; :: JGOODIES :: Java User Interface Design Example View 2/7 public AlbumView(AlbumPresentationModel m) { // Store a ref to the presentation model this. model = m; // Do some custom setup. … } :: JGOODIES :: Java User Interface Design Example View 3/7 private void initComponents() { titleField = ComponentFactory. createField( model. getTitleModel()); titleField. setEditable(false); buyNowButton = new JButton( model. getBuyNowAction()); referenceList = new JList( model. getReferenceListModel()); referenceList. setSelectionModel( model. etReferenceSelectionModel()); … :: JGOODIES :: Java User Interface Design Example View 4/7 private initEventHandling(){ // Observe the model to update GUI state model. addPropertyChangeListener( “composerEnabled”, new ComposerEnablementHandler()); } :: JGOODIES :: Java User Interface Design Example View 5/7 public JPanel buildPanel() { // Create, bind and configure components initComponents(); // Register handlers that change UI state initEventHandling(); FormLayout layout = new FormLayout( “right:pref, 3dlu, pref”, // 3 columns “p, 3dlu, p”); // 3 rows … :: JGOODIES :: Java User Interface Design

Example View 6/7 PanelBuilder builder = new PanelBuilder(layout); CellConstraints cc = new CellConstraints(); builder. addLabel(“Title”, builder. add(titleField, builder. add(availableBox, builder. add(buyNowButton, builder. add(referenceList, return builder. getPanel(); } :: JGOODIES :: Java User Interface Design cc. xy(1, cc. xy(3, cc. xy(3, cc. xy(3, cc. xy(3, 1)); 1)); 3)); 5)); 7)); Example View 7/7 /* Listens to #composerEnabled, changes #enabled of the composerField. private class ComposerEnablementHandler implements PropertyChangeListener { public void propertyChange( PropertyChangeEvent evt) { composerField. etEnabled( model. isComposerEnabled()); } } :: JGOODIES :: Java User Interface Design */ Simpler Event Handling private initEventHandling(){ // Synchronize model with GUI state PropertyConnector. connect( model, “composerEnabled”, composerField, “enabled”); } :: JGOODIES :: Java User Interface Design V – Field Report How does Adapter Binding work? :: JGOODIES :: Java User Interface Design Costs ? Adapter Binding: – increases learning costs – decreases production costs a little – can significantly reduce change costs :: JGOODIES :: Java User Interface Design

Use a ComponentFactory! ? Encapsulate the creation of adapters from ValueModel to Swing components. ? Some components have no appropriate model, e. g. JFormattedTextField ? Vends components for ValueModels :: JGOODIES :: Java User Interface Design Buffering ? Use BufferedValueModel judicously – prevents validation on domain models – makes it harder to use domain logic ? The client domain layer can buffer if: – domain objects are copies – domain objects temporarily accept invalid data :: JGOODIES :: Java User Interface Design Performance ? Adapter chains fire many change events ?

That seems to be no performance problem ? ListModel can improve the performance compared to copying list contents :: JGOODIES :: Java User Interface Design Debugging ? Copying approach is easy to debug; you can see when where what happens. ? Adapter chains “move“ values implicitly; it’s harder to understand updates. ? Reflection and Introspection hide who reads and writes values. ? Favor named over anonymous listeners. :: JGOODIES :: Java User Interface Design Renaming Methods ? Reflection and Introspection make it more difficult to rename bean properties and their getter and setters. Use constants for bean property names! ? Obfuscators fail to detect the call graph. :: JGOODIES :: Java User Interface Design When is Binding Useful? ? I guess that adapter binding can be applied to about 80% of all Swing projects. ? However, you need at least one expert who masters the binding classes. :: JGOODIES :: Java User Interface Design Benefits of Adapter Binding ? ? ? ? Adapter binding can save a lot of code. Code is easier to read. Helps you separate code into layers. Can significantly reduce the complexity. :: JGOODIES :: Java User Interface Design

Where does Binding stand? ? ? ? ? ? Approach is 10 years old and stable. Architecture of the Java port is stable. Tests cover 90% of the classes. Little documentation. Tutorial is quite small. :: JGOODIES :: Java User Interface Design End Summary and References :: JGOODIES :: Java User Interface Design Summary ? ? ? ? ? ? We’ve learned about MVC and Swing We’ve identified Binding tasks We’ve motivated the ValueModel interface We’ve learned how to bind single values We’ve learned how to bind lists We’ve seen a 3-tier architecture :: JGOODIES :: Java User Interface Design

JGoodies Swing Suite Example 1 Example 2 Convenience Sources User Interface Framework (UIF) Looks Forms Binding Validation Example n Applications Helper Code Framework Basic Libraries Foundation JRE / Swing :: JGOODIES :: Java User Interface Design References I ? Fowler’s Enterprise Patterns martinfowler. com/eaaDev/ ? JGoodies Binding binding. dev. java. net ? JGoodies Articles www. JGoodies. com/articles/ ? JGoodies Demos www. JGoodies. com/freeware/ :: JGOODIES :: Java User Interface Design References II ? Sun’s JDNC jdnc. dev. java. net ?

Understanding and Using ValueModels c2. com/ppr/vmodels. html ? Oracle’s JClient and ADF otn. oracle. com/, search for ‘JClient’ ? Spring Rich Client Project www. springframework. org/spring-rcp. html :: JGOODIES :: Java User Interface Design Demo/Tutorial: JGoodies Binding Tutorial Binding Problems and Solutions (in progress) Ships with the JGoodies Binding library. :: JGOODIES :: Java User Interface Design Questions and Answers :: JGOODIES :: Java User Interface Design End Good Luck! Karsten Lentzsch :: JGOODIES :: Java User Interface Design