Thanks for the reply!
James Clarks wrote:
The key part of any application implementing the Model-View-Controller design pattern in the Model application.
The goal of the pattern is to eliminate "technical" dependencies on the View application. You should be able to
have a single Model application and multiple Views via View/Controller pairs. Cell phone, PDA, command-line, HTML browser should all be able to easily communicate with a Model application. What this means is there is no business logic in the View or the Controller.
That is clear to me.
On a side note: The controller in the Sun example (see link in first post) keeps a
list of registered models.
When does it make sense to register multiple models with a constroller?
But back to my problem...
The View only contains logic for displaying a GUI and displaying data returned from Model. Note, the Model returns data when an action is initiated from the View. Model doesn't start this process. The "human" that is using the GUI starts the process.
That's how I implemented my classes.
View manages swing components and registers ActionListeners / MouseListeners and so on.
Model holds all data and provides methods to get/set and work with the data.
In your classes, you don't have any business methods in the Model class and you don't have any GUI controls in your View class. I suggest that you start over, first defining some business method(s) and then creating a GUI, and then create the Controller to enable the View to execute a business method and display some data returned from the Model.
The code samples I provided are extremely simplified versions of my real classes.
I tried to reduce them to the parts I am unsure about.
My actual View extends JPanel and displays a guitar fretboard.
It contains JComboBoxes to set the tuning of each
string (guitar string not
Java string
) and a custom component (extends JComponent) that draws the fretboard.
The user can click on the fretboard and select or deselect fret/string positions. The fretboard draws markers at all selected frets and displays the corresponding notes.
The component that actually draws the fretboard holds information about the number of strings and frets, the tuning of each string, fret selection and some other stuff.
My model among others contains information about the number of strings and frets (int variables), tuning of each string (Note array) and the selected fret/string positions (ArrayList<Point>).
[
Note: I guess keeping two (or more if there's more than one view) copies of the properties in memory is unavoidable? E.g. the model saves the number of strings in an int, but the swing component also saves it's own string number int that is used in the draw method.]
It provides getter/setter methods for all properties, methods to add/remove fret selections and to find the list of notes that are defined by the fret selection.
So at least the last method that calculates the note list is pure business logic, isn't it?
Now lets say I click on the fretboard component. A MouseEvent is send to the components MouseListener which calls the
controller method toggleFretSelection(<Point> fret). This controller method does nothing but call the
model method toggleFretSelection(<Point> fret).
[
Note: Basically all my controller methods call model methods with the exact same signature. Feels kind of wierd, is this how it's supposed to be done?]
If the provided fret position is already selected the model will remove the selection, otherwise it will add the position to the ArrayList.
Then it calls firePropertyChange("fretSelection", newValue, oldValue), where newValue is null if a list item has been removed (oldValue is the removed value) or
oldValue is null if an item (newValue) has been added.
The controller passes this PropertyChangeEvent to the view, which checks wether an add or remove occured.
The view calls the (de)selectFretPosition(Point fret) method of the component that draws the fretboard, which updates it's internal ArrayList accordingly and calls repaint().
My original question was wether or not this way of firing a PropertyChangeEvent and handling it in a view method is good practice.
I have seen MVC examples where the model only notifies the view of a change, which then directly calls one of the model's get methods to obtain the new value.
In other examples the model sends a notification AND the new value to the view, so the view can use the passed value and doesn't have to keep a reference to the model.
My view doesn't know about the model, except for the reference that is provided via PropertyChangeEvent.getSource().
So, should I use this reference? Theoretically I could even use it to directly change model data by calling getSource().setXXX() from the view and bypass the controller, but I assume that wouldn't be in the spirit of MVC?