New features in ModelMaker 8.10
ModelMaker C# Edition
ModelMaker 8 comes in two editions: MM Pascal Edition and MM C# Edition. Each offering native language support. In each edition Dialogs and modeling constraints are dedicated to and optimized for the supported language.
Each edition should only be used for models for the specific language. The model file extension for MM C# models is ".mmcs", for MM Pascal models it's ".mpb" (as previously). Delegates in models saved with C# edition build 2399 and higher, cannot be loaded in the pascal edition. Opening such a C# model in the Pascal edition shows a delegate version incompatibility error message and resets the model delegates to just TNotifyEvent.
Although models created in one edition can be opened in the other edition, this should only be done to convert a model to the other language. MMC# will warn when opening a pascal model, as does MM Pascal when opening a C# model.
A basic Pascal to C# model converter will optionally run upon opening a pascal model in the C# Edition. This converter applies C# model constraints:
- convert parameter lists for methods and array properties - escaping reserved words,
- assure that properties use get and set methods to access state fields,
- rename constructors and destructors,
- clear state fields for events,
- reset invalid modifiers and options for C#,
- it does not convert module (unit) code, nor MMWIN: class tags in units. It's best to entirely remove units from the model and recreate C# modules.
- it does not convert method implementation code.
The IDE integration experts connect to the correct edition based on source file extension or Project Personality. Delphi 8 and 2005 allow interacting with both editions.
Different in MM C# Edition
A few things in MMC# are done (slighty) different from the Pascal edition.
Module code generationMMC# tags start with #MM: instead of MMWIN: . For example:
#MM:>>STARTREMOVE
#MM:ENDEXPAND;
Where possible user-owned code is inserted instead of non-user code. Particularly property access code is inserted using customizable code snippets. Basically only design patterns insert non-user owned code.
During code generation non-user code is optionally (default enabled) surrounded with a region.
#region MM:read-only section::base-call
base.SomeMethod();
#endregion
}
public string Documentation {
get {
#region MM:read-only section::getter-code
return documentation;
#endregion
}
}
Project Code Generation Options allows suppressing emitting the regions. This results in cleaner Code. However, when re-importing this code, the importer won't be able to match non-user owned code and reduces non-user owned code to user owned code.
Method Implementation EditorMethod code is edited as a single piece of text. Non-user code are surrounded with regions, identical to generated code. Deleting the region resets the corresponding option (where-ever possible)
IDE integrationMMC# (optionally) integrates with Microsoft Visual Studio 2003 and 2005 beta 2. The free MM VS IDE Integration pack can be downloaded from the web site download page. The Environment Options | IDE integration tab allows setting the preferred IDE Family to a VS IDE. This this also adjusts the MM GUI to VS: captions, default Build Solution shortcut etc.
General Changes
- Interfaces may have an unspecified (empty) ancestor. Project options Code Import and Coding Style tabs allow defining the default ancestor for interfaces when creating new interfaces and importing interfaces.
- Member Type sorting order and Visibility sorting may be redefined using the Project Options | Sorting Order tab. This allows you to define how "sort on type" and "sort on visibility" are actually evaluated in all places where you are able to define sorting on "type" and "visibility". For example: code generation, members view, class symbols on diagrams.
- Source files dropped on the main window or modules (units) view are imported.
- Option "Public Classes Only" in Import Source Dialog allows skipping non-public classes during import. Pascal: if enabled only classes from the interface section are imported. C#: if enabled only classes with public visibility modifier are imported.
- Messages may be sorted by "Reverse priority". This places priority 1 on top followed by 2..5 and undefined. This is particularly useful to make ToDo item sorting identical with the Delphi IDE Todo list.
Refactoring
- The Convert to Resourcestring / Const refactorings allow selecting the scope for the extracted identifier:
- Module: defines the identifier globally in the current module - identical to the previous behavior.
- Local: defines the identifier as a local resourcestring / const in the current method.
- The Convert to Const refactoring allows the same scopes: Module or Local.
- Method (and Pascal Procedure) dialogs have an Integrated Parameter wizard:
- A button to the left of the Parameters edit shows / hides the integrated wizard. (shortcut Ctrl+Shift P)
- While the wizard is enabled, the parameters edit is disabled.
- Parameters renamed with the integrated wizard are (optionally) propagated in method code.
- Renaming parameters is globally controlled by option "Rename Method Parameter propagates in method's code" on the Refactoring | Options | IntelliReplace tab.
- Method and Procedure Dialogs have collapsible Type selector and Directives and Options. Persistent between sessions.
- Add Parameter refactoring invokes the Parameter wizard and allows adding / rearranging multiple parameters. The token at editor cursor is used as default parameter name.
- Rename Parameter refactoring invokes the Parameter wizard and allows renaming multiple parameters at once. Renamed Parameters are optionally propagated in method code.
- Local Var, Field and Parameter Wizard use Hungarian type look up when clicking the "other.." type in the type selector.
- Try.. finally wizard and Default block wizards: check Implementation / Module Code View
Customizable Property Access Code
Property access code as inserted with C# Edit Property dialogs is customizable (and not controlled with check boxes read code / write code) The Pascal Property dialog allows adding custom code snippets as read/write access code. Unlike the access code controlled with the read / write code options, snippet code is not auto-maintained. Using the property dialog, snippets can only be inserted, not updated or removed. Standard refactorings like renaming the property state field within the access methods work as expected. Snippets are selected with combo boxes that also allow adding new code snippets. Macros makes snippets flexible.
Here are a few examples for new pascal accessor code snippets:
if (<!FieldName!> <> <!WriteParam!>) then
begin
<!FieldName!> := <!WriteParam!>;
Changed;
end;
... and for reading an enumerated value from a combo box:
Result := <!PropertyType!>(<!PropertyName!>Combo.ItemIndex);
The code snippets are maintained on the Environment Options | Code Snippets tabs. These allow adding new snippets and changing predefined snippets. Note that the Pascal access code inserted with the read/write code options still inserts the internal (hard coded) code and does not use the predefined snippets.
Diagrams
- Sequence diagram messages are created horizontal unless the Ctrl key is pressed when releasing the mouse.
- Properties can be marked as "Normal", "Derived" or "Transient" (property dialog, ToolsAPI). Derived and Transient properties are (optionally) displayed with a different color in class symbol compartments. Additionally Derived properties are prefixed with a "/" in class symbols.
- The display of class association names for associations linked to an association class is controlled with a visual style option named "show association class names" as an extension to the already existing "show association names".
- Printing multiple diagrams in a single operation now creates a single printer document as long as diagram page orientations are identical. Printing a diagrams with a different orientation creates new printer documents where appropriate. Particularly useful for creating pdf documents with a printer device. Also, the total number of pages now spans the total of all diagrams printed. Printing 2 diagrams on 4 pages each results in pages 1 of 8 through 8 of 8.
Implementation / Module Code View
- Sort Selection performs case insensitive sort of entire lines. Available in pop up menus (Advanced) and as customizable toolbar button.
- Customizable toolbar buttons added for Increase Line Indent / Decrease Line Indent.
- Try.. finally wizard: acts like a smart surround template, looks at the preceding code to determine the code for the finally block. Customizable using a look-up list in file TryFinallyWizard.txt in the shared directory, for example "C:\Program Files\ModelMakerTools\Shared". Check this article for details. Default shortcut is Ctrl+Alt+J (similar to Delphi's Ctrl+J to invoke a template).
- Surround with Default Block Wizard: acts like a smart surround template to enclose the selection in a begin end or { } block. Indention is smart and derived from the code preceding the selection. Shortcut is Ctrl+Shift+B.
Multiple Inheritance for interfaces
- In C# and Delphi.NET interfaces can have multiple ancestors. In ModelMaker an interface has a primary ancestor and (optional) "additional ancestors". The additional ancestors are used for code generation and code visualization. Additional Ancestors do not need to exist in the model and can be plain text.
- To display interface hierarchy (in tree views), only the primary ancestors are used.
- Additional ancestors are (automatically) visualized when an interface is visualized on a diagram.
- Changing inheritance with the diagram editor changes the primary ancestor - not the additional ancestors. Only when using the "Destroy linked entity" tool, the additional ancestor is removed.
Documentation
- The importer clears the model documentation if the source entity contains an empty documentation comment - that is: a comment with the documentation signature, but without any other text. If the source entity contains no documentation comment at all, the documentation for the model entity remains unchanged - and is not cleared. Similar for importing one-liners from source.
- Documentation is optionally un-word-wrapped during import. All lines are trimmed and concatenated using a space. Empty lines
are interpreted as line breaks. For example, when importing this documentation from source:
///this is the resulting un-word-wrapped documentation:
/// Hello
/// World
///
/// More
/// text
///
///
/// Last line.
///
Hello World
More text
Last line.
- "Insert Predefined Macro" on documentation editor toolbar lets you insert a predefined documentation macro in the text.
Patterns
- Patterns as available from the patterns view can now be applied as wizard instead of active agent. When applied as wizard, user owned code is inserted instead of pattern owned code. Also, the pattern does not reflect changes after applying and the pattern does not appear in the patterns view list. The default value is set in the Environment Options | General tab. The pattern dialogs contain a check box to modify the default value.
- The Lock and Observer patterns are no longer supported. Loading a model containing an unsupported pattern converts the pattern to user owned entities and code - you'll get a warning.
- The Observer Pattern Wizard is now available from the Patterns palette. (Pascal only)
.NET Assembly import / extraction
Class and interface definitions from .NET framework 1.1 and 2.0 assemblies can be imported or converted to source.
Import .NET assembly extracts class and member definitions from an assembly and imports the classes into the model. This is commonly used to import placeholder classes from the .NET Framework. Command is available from main toolbar, main File menu and Modules view pop up menu. Read Article...
A dialog similar to the Import Source File dialog allows selecting assembly file and selecting the framework version plus setting member and class filters. Currently only class, interface and delegate types are imported - records / structs are skipped. .NET Attributes and documentation are skipped. Nested types are currently also skipped. You'll get warnings when applicable.
The "Extract Class definitions from Assembly to source" tool behaves similar, except that this generates a source file for the class definitions rather than importing them in the model. Command is available form the Tools menu.
IDE Integration
To customize Delphi and Visual Studio IDE integration, the tab Environment Options | IDE Integration allows selecting a "Preferred IDE". MM first tries to connect to the Preferred IDE. If that's not available, you can define what should be done next: nothing, or look for another IDE in the same IDE family (Delphi / Visual Studio) or look for any available IDE in any IDE family. The Main ModelMaker window menu and toolbar are updated according to the selected IDE family (Delphi or Visual Studio).
MM ToolsAPI
- IMMModuleImportHook added. This hook is called after a module is imported and allows for example to custom change (clean-up) module code after import, for new modules and Refresh Import modules. Only gets invoked if a Module entity is created when importing a module.
Solved problems
- Compartmented symbols would not allow collapsing / expanding compartments with the [+] [-] icons. Solved.
- Pascal Method Implementation view: When selecting an abstract method the code editor would still show the previous edited text. Solved
- In some cases the Pascal importer would rename overload methods on importing. Solved
- In some cases Copying a class or members could focus to Messages View. Solved
- Importing pure assembly method would cause an AV or Invalid Pointer Op. Solved: you'll get a warning that pure assembly methods are unsupported. The imported method should not be regenerated. Code generation is locked to avoid unwanted overwriting of the pure assembly method.
- Refreshing all design critics would not clear messages from disabled critics. Solved.


Code generation basics