...
Code Block |
---|
Settings INIClass ! Global non-volatile storage manager CODE Settings.Init('.\ClarionTest.INI', NVD_INI) ! Configure INIManager to use INI file Main() Settings.Kill ! Destroy INI manager |
The I didn't call my instance INIMgr, which is what the ABC templates use. I called it Settings because that's what the object does - it manages settings. I may be storing those settings in an INI file, but that isn't the defining aspect.
Complaints: the second parameter to Init is unnecessarily cryptic. I can deduce the _INI part, but what does NVD stand for? And why the need for an explicit call to Kill? Here's the method code:
...
Code Block |
---|
open(window) Window{PROP:MinWidth} = 600 Window{PROP:MinHeight} = 300 ACCEPT case event() of EVENT:OpenWindow settings.Fetch(ProcedureName,window) of EVENT:CloseWindow settings.Update(ProcedureName,window) END case accepted() of ?Close post(event:closewindow) END ! Restrict the minimum window width Window{PROP:MinHeight} = 300 END close(window) |
My app remembers its last window position and size but I need to be able to resize the list box that contains the tests and results.
Again, I resorted to an ABC class: WindowResizeClass. I might want to replace this at some point, but like INIClass it's fairly innocuous. That 'Class' suffix on the name is superfluous - I don't know that I've ever seen a class library where every class has that word in its name. For that matter, ABC is inconsistent - there are a number of class names that do not end on 'Class'. None of them should.
I had to play around a little with the resizer to get it to do what I wanted.Here's my first cut of the window:
I have some flat buttons in the toolbar, and four controls in the window area: a prompt, an entry field, a lookup button and a list box. The prompt needs to stay fixed, and the entry field should only extend to the right. The lookup button needs to stay fixed to the right side of the entry field. The list box needs to resize to fill the window.
I ended up with this override of the Init method:
Code Block |
---|
Resizer.Init PROCEDURE(BYTE AppStrategy=AppStrategy:Resize,BYTE SetWindowMinSize=False,BYTE SetWindowMaxSize=False) CODE PARENT.Init(AppStrategy,SetWindowMinSize,SetWindowMaxSize) SELF.SetParentDefaults() ! Restrict the minimum window height Resizer.Init(AppStrategy:Spread) ! Controls will spread out as the! windowCalculate getsdefault bigger ACCEPT case event() of EVENT:OpenWindow settings.Fetch(ProcedureName,window) of EVENT:CloseWindow settings.Update(ProcedureName,window) of EVENT:Sized Resizer.Resize() END case accepted() of ?Close post(event:closewindow) END END close(window) |
WindowResizeClass. I might want to replace this at some point, but I find it a relatively
...
control parent-child relationships based upon their positions on the window
SELF.SetStrategy(?TestList, Resize:FixLeft+Resize:FixTop, Resize:Resize) ! Override strategy for ?LIST1
self.SetStrategy(?TestDll:Prompt,Resize:FixLeft+Resize:FixTop,Resize:LockSize)
self.SetStrategy(?TestDll,Resize:FixLeft+Resize:FixTop,Resize:LockHeight+resize:resize)
self.SetParentControl(?LookupTestDll,?TestDll) |
Note the use of SetParentControl to lock the lookup button to the entry field.
I still have a couple of problems with resizing. I wanted the Close button in the toolbar to stay to the right edge of the toolbar, but the resizer throws an assert if I attempt to use it with a control inside a toolbar. I can see that being a useful restriction for height changes, but in fact you can change the position of controls inside a toolbar so I chafe at this restriction. I got around it with a line of code inside the Resized event handling.
Another problem is that my entry field isn't resized as fully as I'd like. As I make the window wider the entry field stretches but at a slower rate, so that its right edge gets further from the right side of the window instead of keeping a constant distance.
I wouldn't be the first person to write my own resizer class, but again I can live with these limitations for now.
Down the wrong rabbit hole
I had bit of a detour early on. In reviewing the original code I saw that there was a call to read the list of test DLLs from the directory. First there was a queue declaration:
Code Block |
---|
AllFiles QUEUE(File:queue),PRE(FIL) ! END ! |
Then and then some code to load up the queue:.
Code Block |
---|
Free(AllFiles) DIRECTORY(AllFiles,CLIP(Set:FolderToMonitor) & '\*.DLL',ff_:DIRECTORY) |
...
So that was a lot of work just to replace a few lines of code, but it's all part of getting more ClarionMag code into DCL, so it's worth the effort.
Except that I didn't really need it after all, at least at this stage of the rewrite. The purpose of the directory listing was to show all of the test DLLs. I don't generally work with more than one test DLL at a time so there's no real need to display that information on screen.
Moral: Don't spend time on code that isn't needed! Although as noted it was probably time those classes made their way into DCL.
Loading up a test DLL