By Daniel Wood, 14 March 2011
In applications such as Mail, you may notice that window names can be dynamic, dependent upon the contents of a field. In the case of Mail, the subject dictates the window name. In this article I'll demonstrate a way this can be replicated for FileMaker, and more importantly, how these dynamic windows can easily be selected again once created.
This technique works great on Mac platform, but on Windows it may give some undesired results especially later on in the article where window selection is addressed, you may see a square box in the window name among other things. To put it bluntly, it's a mac only technique being illustrated.
By the phrase dynamic window name what I mean is a window whose name will be constantly changing, it's not set in stone. A classic example of this is the Mail application (and almost certainly other applications) when a new message is being composed:
As you can see the windows name is the same as the subject line. If I were to clear the subject line entirely, a default window name is used:
This would be a pretty cool thing to have in FileMaker - window names that change dynamically based on some value in a field. For example your window name could change to reflect the record you are viewing, whether you are in find mode or browse mode, or the subject of a note/task you are composing just to name a few.
This is a cool feature and would look very nice, but having this feature presents a new pitfall to think about. The next section will just demonstrate the method in which you can achieve live window naming, and it will then be followed by explaining what the situation is that arises and how you can go about resolving it.
You may have seen that one coming :) Script triggers are a great tool for introducing live and dynamic changes to a lot of different areas in FileMaker, and window names is just another of those.
As an example (please refer to the included example file) I have created a sample solution containing an E-Mail table. Each E-Mail is a draft that is pending to be sent in the database, and contains a recipient, subject, and message:
Here I have a list of the e-mails. Editing and sending of the e-mails is done in a special popup window. I wish to have just one of these popup windows open at any one time for editing emails.
In the image above you can see the windows name is exactly the same as the selected records subject. If I were to change the record, I would expect the window name to also change.
Here we see an e-mail with no subject. In this situation a default window name is assigned. So how is this done?
There are two triggers used here. The first is onRecordLoad, in which I am running a script whose purpose is to set the windows title. The onRecordLoad trigger is a useful one to use in this case because it handles various situations such as:
All of these operations cause a new record to load, and so the trigger will execute.
The second trigger used is on the field that is responsible for the windows name. In this case it is the e-mail subject:
Here we are using an onObjectModify trigger so that the windows name will be updated after the users keystroke is entered.
The script responsible for setting the window name is a very simple 1 line script which uses the Set Window Title script step. If the subject field is not empty, then the window name is set to that, otherwise the window name is set to a default value of "(No Subject)".
As with most things in FileMaker there is always a catch, or something that will cause an issue that you need to workaround, and this technique is no different.
With regular windows whose names do not change, the window name itself becomes a sort of identifier of that window, kind of like what a primary key is to a record. If the window needs to be selected at a later point in time, it can easily be selected because the window name will not be changing. The window name could thus be stored in a custom function, global variable, or global field as a way to obtain its name for selection.
In this situation however, we don't know what the windows name is because it is dynamic. When the window first opens it may have the name of "(No Subject)". Once the user enters a subject the window name has now changed to something entirely different, and similarly any change to the users current record will affect the window name also.
So the problem now becomes how can we identify what the window name is even when the name itself is changing?
The solution to this issue devised makes use of a little quirk in FileMaker window naming. A window name can actually be a return-delimited list of values, however only the first value in that list is visible to the user as the windows title.
What does this mean for us? It means if we can assign the window a name that is two values - the first being the visible window name, and the second being a constant identifier for the window, then this might just let us figure out the full windows name somehow.
Here is the code used for the set window title script step used:
Subject = Emails::Subject ;
List ( If ( IsEmpty ( Subject ) ; "(No Subject)" ; Subject ) ; window_Email )
You can see the use of the List function here in generating the windows name. The first value in the list is the visible window name, either the subject, or a default "(No Subject)" title. The second value however is a special custom function called window_Email. In this custom function I have placed a text string which I am confident has not been used as a window name elsewhere in the solution.
So, if we look back to the earlier picture of my popup windows window name, you will notice that the second value "- Email Compose" is not visible anywhere in the window title, yet it is still part of the overall windows name).
If we were to take a look at the WindowNames function what you end up seeing is something like:
As you can see, the window name spans two lines in this function as you would expect because of the fact the window name itself spans two lines.
This is something you may need to pay attention to especially if you use the WindowNames function to determine the number of open windows in a file, because in this case there is 2, but windowNames would suggest there were 3.
The original window name can be obtained with the help of some magic custom functions. To obtain the window name, we start with the fact that we know what the identifier is, we could then:
The example file has a custom function contained called window_OpenWindowName which accepts as a parameter the identifier, and will return the full window name if it is open, or blank if it is not.
There are a couple of other things you may need to keep in mind when using this technique.
The first is the selection of field/value to use as your visible window title. If you choose a field that may contain return characters, then you should probably substitute those for another character upon setting the window title, this will prevent any issues later on when trying to back-engineer the windows name. Substitute with a space or comma and that should be fine.
Secondly is the choice of identifier to use. This should be something that you know will not appear as a window name on another window. It is ok if the identifier appears as part of a windows name, so long as it is not the actual window name, the reason being that the custom functions employed to determine the original window name are looking for the identifier as its own value in the WindowNames list, not as part of a value.
Lastly is another little quirk that occurs with this method and creation of windows. Generally if you have a window whose name is 1-value, and you create a new window via Windows -> New Window, the new window name is appended with a number so that the new window name is different to the original. This is FileMakers way of trying to ensure you don't end up with two window names the same.
However you are not restricted in FileMaker to having unique window names. When this 2-value window name technique is used, the "- 2" appendage is not appended to either value of the window name, so you essentially create a new window whose name is exactly the same as the first.
For this reason, the technique still works, but it will always be the first window created that is considered to the be found window. subsequent windows will not be identified as the main window because of the way the custom functions work to obtain the windows name - they seek out the first occurrence of the identifier in WindowNames....
With all that said, we can now employ this technique to handle both creation of this special popup if it is not already open, or selection of the window if is already open. Looking at the example file as a guide, the script to open/select the window does the following (condensed):
Set Variable [ $Window ; window_OpenWindowName ( window_Email ) ]
If [ not isEmpty ( $Window ) ]
Select Window [ Name: $Window ; Current File ]
// Create the Window, onRecordLoad takes care of window title
// Correct record navigation is done afterwards, again onRecordLoad takes care of window title
The first thing is the potentially open window name is determined using the custom function. If it is found, that window is selected, if not, the window is created. After that the record the user wishes to view is selected via a find, GTRR or whatever other means, because we have the onRecordLoad trigger assigned to set the window title, we need not worry about setting it ourselves.
So far we have talked about the visible window title and the fact the first value is only shown there. However the other place window names are visible is in the Window menu itself. If you have this disabled via custom menu then this is not a problem, but if not read on:
In the Window menu, the name displayed is one of the following:
In our case, the end of the window name is the identifier, which actually works out quite well. We can choose an identifier that is about the required length, so that when the user views the Window names from the Window menu what they see is something like:
This is a great window name to see here because it lets you see the start of the visible window name for easy selection, but if the visible window title is not enough to tell what the actual window is, the identifier makes it very easy to see the purpose of the window. Imagine if you had 10 open windows, each with very arbitrary window names based on a field value, knowing which window is which in the Window menu would be a nightmare, but using the identifier you can very easily see what the windows are.
As a side note, the reason the identifier of " - Email Compose" was chosen as such, was for this purpose. In the case of a very short window name, this nicely formats the visible window name in the Window menu to:
"Short Name - Email Compose"
Which is much nicer to read.
Further to this, if the file is hosted on a server, then typically in the Window menu you will see the server name appear in brackets after the window name (if the window is hidden). In this situation the window name comprises of the last 25 some odd characters in the following:
So if you have a short server name, you can expect to see your identifier suffixed by it, ie:
Email Compose (FM Server)
Which again is quite nice.
This article is only really concerned with explaining the dynamic window technique and a way in which you can then reference these windows for selection or creation. The example chosen assumes that one popup window is required at any one time, and the user should not be allowed multiple email popup windows. But what if this is not the case, and we want the user to have as many popups as they want?
While I have not explored this area fully, I thought I would put my thoughts in on how you could achieve this. Fairly straightforward, it would just mean an adjustment to the way the identifier part of the window name is generated. The identifier would instead contain the primary key value of the record being viewed, as well as an textual component for ease of reading in the window menu, i.e.:
"(No Subject) - 58282 - Email Compose"
In this situation, the identifier is now:
" - 58282 - Email Compose"
Rather than the identifier being stored in a custom function, it would now be dynamically generated itself in the script responsible for window creation/selection, and in the script responsible for setting the windows title.
This technique was originally conceived because of the need to replicate a Mail composition type dialog in FileMaker, but it can be applied to all kinds of window types. I have found the combination of onRecordLoad and onObjectModify triggers to be pretty robust, though more testing may need to be done in the areas of find/preview mode usage.
The technique whereby a window name consists of a multi-line value is a great way to have a visible window name, and an invisible window name component for the purpose of window identification.
Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.