Window Position with Initialize

I’m just dipping into Pan X with my Calendar program and can’t figure out how to have my .Initialize procedure open my windows in the positions I want. In Pan 6 there was the checkbox in the save dialog to open the file with no windows so I could specify them where I wanted them. I can’t find info on how to keep all the prior open windows from opening in the same spots and sizes even though my .Initialize procedure specifies which forms to open and put them where I want them to be.

Any help would be appreciated.

Thanks,
Scott

The only way I know to have the file open with all the windows you want opened, located and sized the way you want other than having them placed that way when the file was last saved is to use the makesecret statement in your .Initialize procedure. Here is an example where “MyFile” would be changed to the actual name of the file you are using and followed by the code you have to open the various windows:

makesecret
setactivedatabase "MyFile"
// Have your code here to open the forms in your position.

The problem of course is that all the saved windows will first briefly open and then immediately close before the new window order reopens everything according to your code.

Thanks, Gary. This sounds like the “flashing window” issue from the old Panorama years ago. I have multiple databases that are in professional use that need to start up in a specified format no matter how it was when quit. Is it possible to put this on the list as a feature request to somehow open the database with no open windows or a command to suppress that behavior?

I guess one solution is to revert to the desired arrangement upon quitting with the “.Quit” procedure so the windows will open that way the next time.

If I’m late to the party and this has already been discussed, my apologies.

Scott

There is no “.Quit” procedure which was actually “…CloseDatabase” in Panorama 6. This topic was discussed a long time back and was never really addressed as to its possible future implementation. So, it’s good you brought it up again. Here is a link to the previous discussion:

I have two custom statements that help with managing windows when you open a file. One is closeotherwindows, which closes all the data windows in a database except the active one. I use it in the procedure of the button used to close the database, followed by a save statement and then closewindow (if you close the last visible window, the database closes (I think)). When the database opens the next time, only that final window will open automatically. My closeotherwindows statement is not perfect; if there are any procedure windows or forms in Graphics mode in the same database, the procedure will stop.

My second custom statement is fixwindow, which hides the toolbar, and sizes the window to match its maximum dimensions, and scrolls back to the 0,0 position. I use that in the .Initialize statement so I get one window in the proper size. Then I usually add a zoomalign “top” statement to center the window at the top center. These reflect my preferences, and they have minimized the time adjusting windows when I open a database. If you want more than one window open, just add more openform statements to the .Initialize procedure. If you open more than one window, you can use Window statement to bring one to the front.

I would be happy to share my code if anyone wants either of these.

Your thinking is correct.

Hi Tom,

I would be interested in seeing what you did there. If you would send me the code for those two procedures, I would appreciate it. I’m gradually starting to move to Pan X after decades on the old system and some examples of code that solves these kind of problems would help me along.

I do use a button on the main screen triggering a “.Quit” routine to tidy up all the databases and put things in order as it quits, but sometimes somebody will just hit Command-Q and quit with all the windows in random positions. As I change to Pan X, I see that the old ways don’t all work the old way.

Scott

scott@stillpoint.us

My fixwindow statement code is:

setwindowoptions "Toolbar",false()
formxy 0,0
local theOptions,lvmaxheight
formblueprint "",info(“formname”),theOptions,"formoptions",true()
lvmaxheight=val(tagdata(theOptions,{"MAXIMUMHEIGHT",},",",1))+24
zoomwindow tagdata(theOptions,{"WINDOWTOPEDGE",},",",1), tagdata(theOptions,{"WINDOWLEFTEDGE",},",",1), lvmaxheight, tagdata(theOptions,{"MAXIMUMWIDTH",},",",1), "notoolbar noscroll"

Another statement where Gary Yonaites supplied some key code!
My closeotherwindows statement code is:

local lvdbname,lvcurrentwindow, lvopenwindows
lvdbname=info("databasename")
lvcurrentwindow=info("windowname")
lvopenwindows=info("windows")

/* filter the list of windows to be closed so other databases are unaffected and 
the calling window is unaffected. Strip the blank lines from the list */

lvopenwindows=arrayfilter(lvopenwindows,cr(),{?(import() contains lvdbname,import(),"")})
lvopenwindows=arrayfilter(lvopenwindows,cr(),{?(import() contains lvcurrentwindow,"",import())})
lvopenwindows=arraystrip(lvopenwindows,cr())

/* Loop through the list and close each window on the list. */

looparray lvopenwindows,cr(),lvformname

    openform array(lvformname,2,":")
    closewindow
    
endloop
rtn

Thanks for submitting this code Tom! I have some hopefully helpful suggestions on how it could be improved.

Panorama X’s blueprint feature is not a very efficient way to get option values. Much simpler and faster is to directly access the options. For example you get get the maximum height of the current form with this simple function:

getformoption("","","MAXIMUMHEIGHT")

(By the way, internally the formblueprint function is using this exact function to create the blueprint.)

So here is a simplified version of Tom’s fixwindow code:

setwindowoptions "Toolbar",false()
formxy 0,0
zoomwindow
    getformoption("","","WINDOWTOPEDGE"),
    getformoption("","","WINDOWLEFTEDGE"),
    getformoption("","","MAXIMUMHEIGHT"),
    getformoption("","","MAXIMUMWIDTH"), "notoolbar noscroll"

I’m not sure if the setwindowoptions statement is needed, since the toolbar is being turned off by the zoom that may be extraneous.

Tom’s closeotherwindows code above won’t work if any of the window names have been changed with the windowname statement. Here is a version that uses the windowinfo( function so that it will work even if some windows have been renamed, and also works with data sheet and procedures in addition to forms.

// current window is always listed first by info("windows"), so skip it
let otherwindows = arrayrange(info("windows"),2,-1,cr())
looparray otherwindows,cr(),otherwindow
    // is this window in the same database as original window?
    if windowinfo(otherwindow,"database")=info("databasename")
        // figure out what kind of window it is, bring it forward, then close it
        let windowtype = windowinfo(otherwindow,"type")
        if windowtype = "Form"
            openform windowinfo(otherwindow,"form")
        elseif windowtype = "Procedure"
            openprocedure windowinfo(otherwindow,"procedure")
        else
            opensheet
        endif
        closewindow
    endif
endloop

This code could still get mixed up if two or more windows have the exact same name. I don’t think there is any way to fix that. Actually, since the window names have to be unique anyway, I think the code can be simplified to this:

let otherwindows = arrayrange(info("windows"),2,-1,cr())
looparray otherwindows,cr(),otherwindow
    // is this window in the same database as original window?
    if windowinfo(otherwindow,"database")=info("databasename")
        // bring window forward, then close it
        window otherwindow
        closewindow
    endif
endloop

CAVEAT: I have not tested any of these programs, or even checked the syntax.

Thanks Jim. Can I submit all of my code for review?

These work (both versions of closeotherwindows) except in closeotherwindows the last endif should be an endloop.

Seeing your improvements illustrates a problem for someone like me: there are so many statements and procedures in PanX that it is difficult to find the best solution for a problem. I was not familiar with arrayrange, windowinfo, or getformoption. Next time, I can use those.

Might I suggest that you do not shoot for perfect code but rather working code?

Your recognition that you are unaware of functions and statements will always be a fact. Even those that ‘live with Panorama’ forget about some of these. Over time, you will continue to find ‘new’ (old) functions and statements that you were unaware of and you will incorporate those into your working code and improve the efficiency of your code but fortunately for all of us, with Panorama’s speed, the differences in speed are typically minimal. Better to be more productive than more perfect.

I would like both productive and perfect.

:slight_smile:

Whoops. I have gone back and edited the post for future readers.

Arrayrange( has actually been around for over 20 years. It’s a key go-to function for me that I use all the time. In fact I find it so useful that in writing Panorama X I built a version of arrayrange( in Objective-C for internal use. I would definitely suggest mastering that one. The Panorama X version of the function does have the nice improvement of allowing negative indexes, which are counted from the end of the array rather than the beginning. I used that feature in the code above.

The windowinfo( and getformoption( functions are new to Panorama X, so I figured they might not be familiar to you or most Panorama users, in fact that’s why I decided to write this detailed post. The won’t be used often, but are there when you need them.

I would suggest that if you find yourself needing to get information about any internal component of Panorama X, there is almost certainly a function to get the information, so look around for it. In Panorama 6 there was lots of information that was hidden away and couldn’t be reached except from a graphical interface, but Panorama X was intentionally designed to be completely transparent. This was primarily done for my own benefit, as much of Panorama’s user interface is actually implemented using the Panorama programming language and standard forms. For example the Panorama preferences window is actually a standard Panorama form, so obviously all of the options that can be controlled by that dialog can also be accessed and controlled directly by a Panorama program. In fact, each option is implemented by first making it programmable, and only then added to the user interface. So to restate the first sentence of this paragraph, think to yourself “would Jim ever need to access or control this option?” – of course the answer is yes, so you can do so also!

Looks like most those functions deal with the coordinates of a window. And these days, it’s probably enough. But seems to me, for maximum robustness, you’d want a little handle on the screen size you are dealing with too. “Back-in-the-day”, when people were migrating from 4:3 to 16:9, this was a big deal - especially since Panorama ran on both PC’s and Macs. Now that PanoramaX is Mac only, and Screen size has settle down a bit, it’s not so critical. But still, if your database was moved from your big desktop monitor to a smaller laptop (I understand that they might have the same aspect ratio), you might want to make an adjustment on window sizes. Can’t assume the database will always be running on the same monitor. Just Say’n.

There are nice functions in Panorama X exactly dealing with available screen estate e.g. info(“availablescreenrectangle”).