This MasterStudio release implements all remaining features from the original function points list (#8o/#8p, #16, #18, #35, #46/11, #112b) and some features originally planned for later releases (-3, 13d, 15, 73, 87, 91). This is the biggest maintenance release so far, containing major new features as well as performance enhancements in numerous classes.
This is the first MasterStudio update that requires minor changes to your existing applications. Before using MasterStudio 1.0.6, please be prepared to print this page and to spend about 30 minutes going over the update instructions below. If you did not subclass any MasterStudio controllers or managers, then the amount of work required is minimal. Given the major improvements in a number of areas, you will find this a worthwhile time investment. As always, parameters and use of new methods and attributes were also documented in the source code.
More complete localization of demo application:
The demo application now uses localized strings for all windows and menus, including translated column and table names for German and Dutch. The Master-Detail demos now fully support live language switching between U.S. English, German, and Dutch. PlanBoard also supports Italian and U.K. English.
Drag & Drop of detail records: (function point #15)
It is now possible to copy one or more selected detail records to one or more master records by dragging them onto the master grid. This feature is automatically enabled after you set
$dragmode of the detail grid to
kDragData and set
$dropmode of the master grid to
kAcceptGrid. To copy detail records, users must hold the Control key (on Mac: Option) before dragging. This new feature is enabled in the demo application.
If no key is held down, the detail records, including any subdetail records they contain, are moved to the other master record.
MasterStudio will obey all delegate methods before copying: The copy is only allowed if the user can insert records into the detail list. A new delegate attribute
$mayCopyDetailToLine can be used to disallow copying and/or moving of detail records, even if the detail list is dragable.
Automatic deactivation of hidden entity list managers: (function point #35)
Detail entity controllers that are currently invisible (because they are hidden in a tab or because they were "collapsed" in a parent frameset) will no longer fetch records from the database. Objects on invisible panes also will no longer be redrawn until they are revealed again. This improvement considerably speeds up browsing and list redraws in complex windows.
Pessimistic record locking option: (function point #112b)
MasterStudio now offers a built-in way to enforce pessimistic record locking: This option ensures that while a record is being modified, it is locked for modifications by other users.
The new record locking option is activated by entering "
MoConstants.kMdLockingPessimistic" into the
<LOCK> element in the primary key of the schema class. Like "
MoConstants.kMdLockingRecordCounter", this uses a separate update counter column that must be present in the schema indicated by the
<LOCKFIELD> element. As soon as a user starts editing a record, its update counter is updated to its negative value. If a user starts editing a record while its update counter in the database is a negative number, an error message is displayed:
In the demo application, the "Employees" entity uses this new option so you can easily try it out. Note that the user may still update the record by clicking the "Override" button. This is implemented in new method
$mdAllowLockedRecordEdit of the entity table superclass. So if you do not like this option, you can easily override the message.
For performance reasons, the record lock check takes place after leaving the first field that is being edited. If a user starts editing a record that is no longer current (because someone else updated it after fetching it from the database), it is refetched automatically:
In this case, the field being edited keeps its new value. Of course, the user can still cancel the modification, either by right-clicking the master record and choosing "Restore Record" or by canceling all modifications.
It is possible to implement your own pessimistic record locking mechanism (perhaps using Oracle's "select for update" method) instead of using MasterStudio's
kMdLockingPessimistic method. In that case, you should override methods
$mdUnlockCurrentRecord of class
Standard "Refresh" context menu command:
A new "Refresh" command in Master-Detail context menus allows users to refresh (re-fetch) selected records from the database. This is useful in situations where other users have modified the records after they were originally fetched. When a Master record is refreshed, its details are refreshed as well. Note: The "Refresh" command is not available if one or more records are being edited. Users must save or cancel their current modifications before refreshing.
If you do not want the Refresh command to appear in the context menu of your entity, return
kFalse from the new
$showRefresh entity delegate template attribute.
Template methods for "start of edit" and "end of edit": (function points #8o and #8p)
Whenever a user starts editing a record, MasterStudio now calls the
$currentRecordEdited method of your entity delegate object. When the user cancels editing of that record, MasterStudio calls
$currentRecordCanceled. (Of course, when a record is saved, MasterStudio calls
$insert of the table instance.)
New schema integrity check:
During initialization of the root context, MasterStudio now checks all schema classes for invalid
<JOIN> elements, i.e. joins that point to a non-existing schema class. If an invalid schema class reference is found in a schema
<JOIN> tag, an error message will be displayed. Previous versions of MasterStudio did not verify
Automatic enforcement of delete constraints: (function point #18)
By default, MasterStudio will now enforce a "deny" constraint for users of OmnisSQL: When a user tries to delete a record that still has details linked to it, the following message will be displayed:
For Oracle, this constraint is off by default (allowing the constraint to be handled by the database). By overriding the new MasterStudio
$constrainMasterForDetail session attribute, you can change the default behavior. You can also define the constraint for each individual join by adding a "
CONSTRAIN=" attribute to the
<JOIN> tag of the foreign key.
Searching for empty strings: (function point #16)
By entering a "
!" into a field in search mode, a user can specify that MasterStudio must find records where that column is empty. The "
!" is the default value for constant
MdConstants.kMdFindEmptyString, and can thus be changed easily by subclassing the class factory or by overwriting the constant at application startup.
Enhanced frameset controls:
Double-clicking on a grid line in an expandable frameset will expand or collapse the frameset (unless the grid is used as a pick list, where double-clicking selects the record). In a non-enterable grid, the <Return> key can also be used to toggle the frame set. Whenever the <Return> key is assigned to other functions, you can still use Control-Alt-<Left/Right Arrow> to expand or collapse framesets (on Mac: Command-Option-<Left/Right Arrow>). To expand or collapse the container frameset from within a nested frameset, hold the Shift key as well.
Pane selector enhancements:
This release provides noticeably faster switching between pre-instantiated tab panes in the pane selector.
The pane selector now also automatically puts the cursor into the new tab when switching between tabs using the keyboard (Control-(Shift)-Tab on Windows, Command-Option-(Shift)-Tab on Mac OS).
Easier debugging of MasterStudio class instances: It is now much easier to debug MasterStudio sessions, database menus, statements, notification centers, controllers, and managers, because they now use unique and easily recognizable instance names. Each controller and context also returns this name from the new
The above screen shot shows the open instances of the list manager after opening the three Master-Detail windows of the demo application.
Faster fetching of tables containing many columns:
This release adds a new
MoConstants.kMoFetchCustom constant for schema columns that should only be fetched upon request. This is now the default for any columns that do not have a specific fetch level (
<FETCH> element), unless no column in the schema contains the
This new default makes it easy to create MasterStudio applications using schemas with many columns that should not be fetched immediately, or at all.
Icon picture cache:
By implementing an in-memory cache of record state icons used in MasterStudio entity grids, a considerable performance increase is achieved in all grid-based windows and subwindows. This performance increase is very noticeable when scrolling and browsing in lists and when moving between lines in enterable grids.
Performance enhancement by using tokenized constants:
MasterStudio framework speed was enhanced by tokenizing constants as class variables. In many cases, this means that constants (
kMd... variables) were replaced by class variables whose name starts with "
ck". All controllers, contexts, and managers now offer the following constant variables that you can use instead of "
It is important to recognize that these class variables are initialized explicitly (usually in the
$connectToSupercontroller of the first instance), rather than using the Omnis "initial value" field. Otherwise, the tokenized constant values will not be initialized automatically if they are first used by a method in a subclass.
By using the same method, and by using class variables instead of continuously redefined local variables, performance of the notification center (class
MoNotificationCenter) was also improved. This improvement is most noticeable when clicking, scrolling, and switching panes in complex windows.
Direct control over initial window/frameset coordinates: (function points #11 and #46)
If desired (and by default), MasterStudio automatically remembers the coordinates and sizes of windows and framesets by storing them in the local user preferences file. When a window is opened for the very first time (or after the user has deleted the preferences file), you can now specify the initial coordinates and sizes by adding the following lines to
$entityWillInitialize of your entity delegate:
;; For the window:
Do MoManagerWindows.$initializeCoordinates(MoContext.$objectPath, '0,0,720,480')
;; For the frameset:
Do MoManagerWindows.$initializeCoordinates(MoContext.$objectPath,'146,250,0', kFalse, iPaneControllerRef.$paneId)
(This example can also be found in the demo library, class
Faster inserts using the MasterStudio sequences table:
The MasterStudio sequences table (used to generate unique record sequence numbers) now uses its own cursor, allowing other cursors to be repeated with bind variables for improved performance when inserting many records.
MasterStudio license registration:
Like PlanBoard, MasterStudio now requires entry of a developer license key. The license key is entered into object class "
MoMasterStudioLicense" in your main library. After entering your license key, MasterStudio displays your developer license in its "About" box, instead of "UNREGISTERED". If you do not enter the license key, the folowing message appears at startup:
Fixed a potential cause for notation error #25216 that was raised when closing window contexts.
Removed a potential cause for notation error #25207 that was raised when closing an application context.
Fixed a bug where a master record was not redrawn after reverting (after pressing the Restore button).
Fixed a bug where a detail list was not refetched after saving (where the detail list showed -1 records).
Fixed a potential cause for an Omnis crash that occurred after browsing empty entity lists (caused by invalid bind variables after recalculating the entity list).
Fixed a bug where a context menu command was not displayed because the same command existed in a super-controller.
Fixed a bug where a new record that was deleted by the user was still calling the table's
$delete method, even though the record did not exist.
Solved a problem where MasterStudio would update record columns that had not originally been fetched from the database. Now, Master-Detail windows only update columns that have actually been fetched.
Fixed a bug that caused an entity to incorrectly enter or leave Find mode.
When closing the main library, the application no longer asks three times whether it should be closed. This was fixed by changing method
$canclose in the startup task of the demo library to:
If you would like this to work the same way in your own applications, change $canclose of the startup task in your main library.
Quit method pick($itasks.$findMoContextRootname('MoContextRoot'),kTrue,MoContextRoot.$close())
It is no longer required for all columns in a schema to have an
On Windows, the "Select" command button is now correctly placed at the very left of command bars, instead of between the "OK" and "Cancel" buttons.
Fixed a problem when using Omnis Studio 4 where MasterStudio subcontroller instances would not be destroyed, causing a potential memory leak and slowdown if window contexts were never closed.
Fixed a bug where the 3.2.4 PlanBoard demo application would crash on Omnis Studio 4 when repeatedly inserting or deleting records.
Fixed a bug in the PlanBoard demo application, where the simple "smartlist-based" windows for "Employees" and "Planning Slots" would not insert more than one record at once.
This MasterStudio release contains major enhancements and requires minor changes to your existing pre-1.0.6 applications. To update to MasterStudio 1.0.6, please follow the instructions below.
Make a backup of your application:
After updating to MasterStudio 1.0.6, your application's complex grid icons will no longer be displayed correctly in earlier versions of MasterStudio. To revert to the previous version of MasterStudio, you will also need to re-install the old versions of MoContextRoot and MoClassBroker.
Copy updated main library classes:
Copy the latest versions of
MoClassBroker from library
DemoLibrary into your main library, as well as the new license class
(Please note that in Omnis Studio 4.0 on Mac OS X, you must upgrade the libraries by opening them from the Omnis Studio browser. The No/Yes messages that Omnis displays during this process may not work if you dragged the demo library onto the Omnis icon or into the Omnis Studio browser.)
Verify Master-Detail dependencies in your complex windows:
Normally, a master entity does not need to know much about its detail entities: MasterStudio automatically handles their foreign key dependency. Usually, your own application code for the master entity does not contain references to detail entities. This is great, because it allows MasterStudio to initialize subcontrollers "as late as possible". For example, a detail entity controller in a tab pane is not initialized until the user opens that tab for the first time.
In MasterStudio 1.0.6, this concept is taken even further: If an entity controller (or one of its pane or grid controllers) is inactive (i.e., when the corresponding view is hidden by a tab in a pane selector or by an expanded frame in a frameset), then it will no longer fetch records from the database when the user browses through related master records. Such a "hidden" entity will automatically refetch its records when the user reveals the corresponding pane.
Obviously, this considerably speeds up browsing records in complex windows (containing many tabs or nested framesets), which is why this is now default behavior of Master-Detail windows in MasterStudio. In situations where this behavior is undesirable you must override the new
$shouldFetchInvisible attribute in the entity delegate object. By default,
kFalse for the fastest performance.
IMPORTANT NOTE: When
kFalse, your application code cannot rely on detail records to be present when the user browses through master records. If your code directly accesses detail records, you must override
$shouldFetchInvisible and return
kTrue, or you should add
.$activateCurrent() behind each
There are several ways in which you may have implemented a dependency on detail data in your applications:
You may have directly set a reference to a detail record by using attribute
$managerDetail of the list manager. (If you have a reference to the detail list manager, you can force it to activate by calling
.$activateCurrent. This forces the detail list to update itself before the next method is called. E.g.
You may have implemented some code in the detail's
$currentRecordChanged method. This code is no longer called for details whose frameset is invisible (e.g., because the entire detail is in a hidden tab, or because the frameset was collapsed hiding the detail entity).
You may have sent out a custom notification from the master record that causes the detail entity to react in some way.
A strong indication that you rely on the presence of detail lists, is if your application calls
$initializePane of a pane selector.
Use the new MasterStudio icon picture cache:
A major performance gain is achieved by MasterStudio's caching of often-used pictures, such as the record status icons displayed at the left of complex grids. The function manager now implements an in-memory picture cache. To take advantage of this cache, find all instances of "
OmnisIcn Library.$getpict(" in your own libraries. This should find the state icon picture fields in all your entity grids. After you verify that you have indeed found your grid classes, replace the old function call by "
MoManagerFunctions.$getpict(". Be sure to only do this in your own libraries, not in
If you use function "
OmnisIcn Library.$getpict" to repeatedly retrieve the same icon pictures in your libraries, you can replace the function by
MoManagerFunctions.$getpict to speed that up.
Use of schema definitions:
MasterStudio now caches schema definitions by reading schema classes (and the XML information in their descriptions) at startup. After reading all schemas, MasterStudio creates an internal list of schema dependencies, i.e. Master-Detail relationships. After this, schema and column information can be read from
MoSchemaColumn objects. Although MasterStudio tables automatically obtain their "schema object" upon instantiation (available through a list's
$moSchemaObject attribute), you can also obtain a schema definition by using
It is important to note that schema definitions are only available after the root context finishes initializing. This means that you can no longer use schema objects or MasterStudio tables during
$finishInitialization of the application context. If you need to access the database during startup of your application, use
MoContext.$notificationCenter().$notifyOnce to call your method after initialization of your application has finished.
Only relevant if you use your own custom language manager or a subclass of the MasterStudio language manager:
cMoMdLanguages, used in the Master-Detail window context, was replaced by an instance variable
iMdManagerLanguagesPath. If your application uses your own language manager subclass (stored in a class variable of type
Object), then you should change this class variable into an instance variable of type
The Master-Detail language manager now has an instance variable
MdPublic instead of task variable
MdPublic. If you use your own language manager subclass, please be aware that it no longer runs in your own application context, but rather in the root context. To check whether you have your own language manager subclass, use the inheritance tree on class
MoMdLanguages. Task variable "
MdPublic" is no longer available. Instead, you can use the new "
MdPublic" instance variable. If you have your own subclass of class
MoMdLanguages, it may be necessary to change its
$designtaskname attribute to
MoBaseClasses.MoContextSubSuperclass, and to replace "
$ctask.MdPublic" by "
Only relevant if you use your own custom pane controller:
You must call "
Do inherited" if you have overridden
$componentWillBeDeactivated in your own pane controller subclass. If you are unsure, search for the existence of these methods in your own libraries, or use the Inheritance Tree on class
MoControllerPaneSuperclass to find out if you have any of these subclasses.
Only relevant if you use PlanBoard or your own scratch libraries:
MoScratchLibrary now displays an error message if a scratch library file is unreadable or if it was updated to a newer version of Omnis Studio. If this happens, the old scratch library should be deleted from the MasterObjects preferences folder.
The following changes were made to the MasterStudio table superclass. Please search your own library for each of these variables, and replace them as follows:
iMoSchemaRef. --> iMoSchema.$classRef().
iMoPrimaryKeyRef (no longer available)
iMoSequenceName --> iMoSchema.$sequenceName
iMoSequenceUsesTableNY --> iMoSchema.$sequenceUsesTable
.$sequenceName --> .$moSchemaObject().$sequenceName
.$sequenceUsesTable --> .$moSchemaObject().$sequenceUsesTable
.$recordPrompt --> .$moSchemaObject().$promptSingular
.$recordsPrompt --> .$moSchemaObject().$promptPlural
Important if you call method "
.$addModelDefinition" from any of your classes: This method now expects a column object instead of a description. The column object can be created as follows:
Calculate xml as ... ;; the old string containing XML elements
Calculate column as MoClassFactory.$prototypeSchemaColumn
Check whether you have subclassed the list manager by using the Inheritance Tree on
MdManagerListGeneric. If you have your own custom subclass, please check the following:
iSchemaClassRef --> iMdEntityListRef.$moSchemaObject().$classRef
$analyzeSchemaColumns (no replacement)
.$recordPrompt --> iMdEntityListRef.$moSchemaObject().$promptSingular
.$recordsPrompt --> iMdEntityListRef.$moSchemaObject().$promptPlural
Check whether you have subclassed the record manager by using the Inheritance Tree on
MdManagerRecordsGeneric. If you have your own custom subclass, please note that most class variables starting with "
cDetail" and "
cMd" were renamed from
ckDetail... and from
New default for <FETCH> of database columns:
This release adds a new
MoConstants.kMoFetchCustom constant for schema columns that should only be fetched upon request. This is now the default for any columns that do not have a specific fetch level (<FETCH> element). To ensure that your application still fetches the columns you expect, please search all your schemas for the <FETCH> tag, and ensure that all columns that you want to fetch contain the element. If no column at all uses <FETCH>, then MasterStudio will still fetch all columns.
$dodelete in MasterStudio table superclass:
Although MasterStudio itself does not use Omnis' "smart lists", PlanBoard demo application windows, and possibly your own applications, do. The MasterStudio table superclass
MoDatabaseTableSuperclass was updated so that records cannot be deleted if they have a delete constraint. Also, a number of bugs were fixed by overriding
$dowork. If you use any of these methods, it is recommended that you search your own applications for subclasses of the MasterStudio table superclass, and make sure that they call
Do inherited where appropriate.
Other minor changes:
The following changes are very unlikely to impact your existing applications.
MoMdPublic: Text strings
MoMdT045 were replaced by
MoTxConstrain3. Several other string translations were improved.
If you are using Omnis Studio 4, please note that when closing the demo library from the Omnis Studio 4 Browser by clicking on the "Close Library" button, the "Are you sure you want to quit this application?" message will not work. This does not happen when you close the library using the context menu.
(Most of these new methods will be documented in the updated MasterStudio 1.0.6 Developer Manual)
New manager-related functions:
New methods in MoManagersSubcontexts:
New method in MoManagersRoot:
New task variables:
Class MoDatabaseSessionSuperclass has a new attribute
$constrainMasterForDetail(pMasterSchemaName, pDetailSchemaName, pDefaultConstraint) that you can override to control whether MasterStudio enforces a delete constraint when a user tries to delete a master record that still has details linked to it. By default, MasterStudio will "deny" such a deletion when OmnisSQL is used. For Oracle, MasterStudio does not enforce the constraint by default. The attribute function should return either
You should only override this function if you want to change the database default. Individual schema classes can override the database default by implementing the
CONSTRAIN= attribute in the
<JOIN> element, which defaults to
MoConstants.kMoConstrainByDatabase (meaning that the join constraint follows the the session attribute).
$controllerEnumeration now accepts a negative value for the controller enumeration type. If you pass in a negative value, then the list of subcontrollers is returned in reverse order.
Table template method
$mdDidRefetch is now called after one or more columns were refetched from the database. After each row refresh,
$mdDidRefetch is called with the fetch level as its second parameter.
(These new methods are documented in the second edition of the MasterStudio Developer Manual. See Book Errata & Addenda for a full listing of MasterStudio changes in versions 1.0.1 through 1.0.5)
MoManagersRoot now is a subclass of
MoControllerFramesetDelegateSuperclass now inherits from
$paneWillBeDeactivated are no longer expected to return true or false: Deactivation is unconditional. Also, deactivation of subcontrollers now takes place in reverse order: The "deepest" subcontrollers in the hierarchy are deactivated first.
MoManagerFunctions.$conciseText now accepts a second parameter, allowing specification of the maximum number of characters to be returned. By default, the string is shortened to 128 characters.
Back to General Release Notes