7-2-2001 by Christopher J. Demers
Presenter Generator Tool for Dolphin Smalltalk (Version 4.0).
Disclaimer:
This is Alpha code. I have been using it myself for the past few months, but it is defiantly not well tested. If I waited until I was done to post this code it might never get posted. ;) Make sure you have working backups and use this code carefully. At this point I would suggest that only experienced Dolphin users that understand what the code does should use it. After this code gets more testing and I get more feedback from people I think this code might be helpful for people who are new to MVP. Neither I nor any entity with which I may be associated will be responsible for the use or misuse of this code. Use it at your own risk.
Background:
I have been using Smalltalk (VAST and VSE) for many years. A little over a year ago I moved to using Dolphin Smalltalk as my primary environment. I think it has one of the best Smalltalk user interfaces out there. However I think there is some room for improvement in regard to its UI development tools. It took me a while to come up to speed on MVP. Even now I still find myself needing to improvise a bit more than I might like in order to get what I want out of MVP.
I like to program, I don't like to type. ;) It seemed to me that there was a great deal of skeleton code that needed to be added to a presenter just to make it work. This kind of thing makes it harder on someone who is new to this area as they have to remember all the method names, variable names, view names, and when to make super calls, etc... If you get any of that wrong it will not work. If you make a typo in a view name it can be hard to spot as there will be no error message. This just seems like a lot of work to me. So I decided to write some code to create a simple presenter skeleton based on a view and some default mapping.
Description:
My Presenter Generator will add presenter instance variables to existing presenter classes as well as a createComponents method to initialize the sub presenters based on the named sub views in the specified view. The code works if you add new named views, it will only append the new instance variables and initialization code. This means it can be used incrementally as you are developing your view. It will also work for cases where you have super classes handling some sub presenters, it will not create conflicting instance variables or code. Because it appends to the createComponents method rather than replacing it you can make manual changes as needed and they will be preserved.
Example:
This is very simple example of what the Presenter Generator does.
Suppose we have a simple address window. First you create the presenter class (PGEXAddressWindow) for your view. Then we add the view to the presenter class and save it. Our example view looks like this:

We name all the sub views that we want to have corresponding sub presenters in our presenter. Unnamed sub views are ignored (so are certain view classes (as defined in the viewClassesToIgnore method) such as PushButton). The generator will create an instance variable for each presenter (if it does not already exist). The naming convention is [view name] + "Presenter".
We would run the Presenter Generator like this:
CJDPresenterGenTool generateClass: PGEXAddressWindow viewName: nil
It will prompt us for the view to use, and then add the instance variables and a createComponents method to our presenter.
This is the resulting class definition:
| Shell
subclass:
#PGEXAddressWindow instanceVariableNames: 'lastNamePresenter firstNamePresenter statePresenter streetAddressLine1Presenter streetAddressLine2Presenter townPresenter zipCodePresenter streetAddressLine3Presenter' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: '' |
This is the resulting createComponents definition:
|
createComponents super createComponents."(AutoGenerated on 7:21:10 PM, Monday, July 02, 2001)" firstNamePresenter := self add: TextPresenter new name: 'firstName'. lastNamePresenter := self add: TextPresenter new name: 'lastName'. townPresenter := self add: TextPresenter new name: 'town'. statePresenter := self add: TextPresenter new name: 'state'. streetAddressLine1Presenter := self add: TextPresenter new name: 'streetAddressLine1'. streetAddressLine2Presenter := self add: TextPresenter new name: 'streetAddressLine2'. "(AutoGenerated on 7:22:11 PM, Monday, July 02, 2001)" streetAddressLine3Presenter := self add: TextPresenter new name: 'streetAddressLine3'. zipCodePresenter := self add: TextPresenter new name: 'zipCode'. |
The code above was actually generated by running the Presenter Generator twice as indicated by the comment appended above the additions. The first time I ran it the view did not have a zip code or a 3rd address line. I simply added the new views and reran the generator. This code can now be edited manually and will retain changes even if you run the generator again.
Notes:
1. While the class definition changes, it may not be marked as changed in some source tracking applications. I need to investigate this further. I am using a slightly different approach, and I am not sure if this is still an issue, but it may be.
Future Improvements:
There are quite a few features I would like to add in the future. I would like to add a pick list type interface to assist in the coding of the model: and createSchematicWiring methods. It is also possible that I could add a user interface to better choose view to presenter class mapping. Let me know if these would be welcome enhancements, or if you have additional suggestions.
The Package:
The PresenterGenerator can be downloaded from the links bellow. The package contains two classes:
| CJDPresenterGenTool | This is the primary class. See class and method comments for more information. |
| CJDMenuManager | This is NOT used by default, however it is used to support the optional adding of a context menu item for the Presenter Generator. This has to be initiated manually via: CJDPresenterGenTool addContextMenu. It can also remove the context menu item via CJDPresenterGenTool removeContextMenu. This code will open a view and programmatically add the menu and then save the new view. It will make a backup view. This is an experimental concept, and is even more alpha than the rest of the code. My intent here was to provide an easy way to add or remove menu commands in system view with out replacing the view, and with out replacing system methods. For now it only supports context menus, but I intend to eventually add support for menu bars as well. Please give me feedback regarding this approach. |
Please give me feedback ( Christopher J. Demers ) about this code. If I see that it is useful to people I will try to improve the documentation and add new features. It is a lot of work to maintain public code, so I don't want to spend the time unless it is of value to others.
License:
This code is freeware, not public domain, I retain the copyright. The code may be freely used and freely modified, but please don't redistributed modified versions. I may make exceptions (ask me), and I may make this more lenient in the future. For now I want to keep things simple.
Download:
By downloading the code bellow you are signifying your acceptance of my license (above) and disclaimer (at top).