Ask Reuben

TopMost Normal Window

What is the Topmost Normal Window? 

Why can I only see one window? 

Why can I only see two windows?

The phrase “Topmost Normal Window” is one that will be familiar to Genero developers who used the various incarnations of the Genero Web Client from around 2008 or so.  For those Genero developers who have stuck solely with the Genero Desktop Client, this maybe a new concept as they move to 4.00 and Universal Rendering.

The concept is that instead of displaying every window and allowing the user to move/resize these windows independently,  at most only two windows will be rendered.  They are …

  • the topmost normal window
  • the topmost modal window (if it is was opened after the topmost normal window)

For most ISV’s who have moved to the web as being their preferred front-end , this is seen as something in keeping with a typical web interface, and they have transformed their Genero applications to work within this framework.

Before I explain further I will first explain what a modal window is.  The Wikipedia description is quite good

A modal window creates a mode that disables user interaction with the main window but keeps it visible, with the modal window as a child window in front of it. Users must interact with the modal window before they can return to the parent window. This avoids interrupting the workflow on the main window.

In Genero speak, a modal window opens with a dialog, typically a MENU, but can be any other dialog such  DISPLAY ARRAY, INPUT, and the user completes that dialog before returning to the dialog that there were in before the modal window was opened.

In Genero, a modal window is determined by Presentation Styles and in particular the windowType Style Attribute.  In FGLDIR/lib/default.4st, you will some entries…

StyleAttribute name="windowType" value="modal"

… and this is used in Styles such as…

Style name="Window.dialog"

…  If you have OPEN WINDOW … STYLE=”dialog”, this is the signal to open a window as a modal window.  Due to this entry in the Stylesheet then where you see STYLE=”dialog” in your code, this is a modal window.

You should also note that effectively MENU … STYLE=”dialog” is opening a modal window, as is PROMPT , and utility functions such as FGL_WINMESSAGE, FGL_WINQUESTION etc.

A normal window is the base for the users workflow.  It is where the value for windowType Style Attribute is “normal”.  This is also the default value so does not normally need to be explicitly stated.

To see the differences between Desktop rendering and Universal Rendering with its Topmost Normal Window concept,  run the example code at the end of this article.  This program allows you to open multiple windows and to choose wether each window is opened as normal or as modal (STYLE=dialog).

For the screenshots below, I pressed normal, normal, dialog, dialog to open 4 windows.

In the 3.21 GDC, after some resizing and dragging, I can see all 4 windows, the two normal windows W1, W2, and two modal windows W3, W4 …

With 4.00 and Universal Rendering I can only see W2, the topmost normal window, and W4 the topmost modal window.

To see window W1, I have to click on the Window List icon in the top left corner and that will allow me to select and view the other normal windows.

Ideally there is only ever one modal window in the stack of windows, however there is nothing stopping you opening multiple modal windows, if you do you will only ever see the topmost modal window.  There is also nothing stopping you opening a normal window from a modal window, if you do that you will see the new topmost normal window only.

As there is only ever one normal window (the top most normal window) displayed in the window container, this window is full size within the container and has no ability to be resized other than what you can do with the window container (the GDC window, the browser tab, the mobile device).  The topmost modal window is sized based on its content, rendered as a window and can be dragged and resized.

As I said at the beginning of the article, most ISV’s who have been using Web Client for a number of years now will be familiar with this Topmost Normal Window concept.  They have adapted their application to fit and as a result their application looks like any other web application.  Instead of layer upon layer of independent window, they have one window at the base of their rendering where the user does most of their workflow, and when a user selects certain actions, a modal window maybe displayed above this normal window, and then when the user finishes in this modal window they are returned to the normal window and their workflow within this window.

#! askreuben187.4gl
MAIN
    DEFINE depth INTEGER
    DEFINE choice STRING

    LET depth = 0
    WHILE TRUE
        IF depth < 0 THEN
            EXIT WHILE
        END IF

        LET choice = get_choice(depth)
        IF choice ="normal" OR choice="dialog" THEN
            LET depth = depth + 1
            CASE depth
                WHEN 1
                    OPEN WINDOW w1 WITH FORM "askreuben187" ATTRIBUTES(STYLE = choice)
                WHEN 2
                    OPEN WINDOW w2 WITH FORM "askreuben187" ATTRIBUTES(STYLE = choice)
                WHEN 3
                    OPEN WINDOW w3 WITH FORM "askreuben187" ATTRIBUTES(STYLE = choice)
                WHEN 4
                    OPEN WINDOW w4 WITH FORM "askreuben187" ATTRIBUTES(STYLE = choice)
                WHEN 5
                    OPEN WINDOW w5 WITH FORM "askreuben187" ATTRIBUTES(STYLE = choice)
                WHEN 6
                    OPEN WINDOW w6 WITH FORM "askreuben187" ATTRIBUTES(STYLE = choice)
            END CASE
            DISPLAY depth TO depth
            DISPLAY choice TO style
            CONTINUE WHILE
        END IF
        IF choice = "close_window" THEN
            CASE depth
                WHEN 1
                    CLOSE WINDOW w1
                WHEN 2
                    CLOSE WINDOW w2
                WHEN 3
                    CLOSE WINDOW w3
                WHEN 4
                    CLOSE WINDOW w4
                WHEN 5
                    CLOSE WINDOW w5
                WHEN 6
                    CLOSE WINDOW w6
            END CASE
            LET depth = depth - 1
            CONTINUE WHILE
        END IF
    END WHILE
END MAIN

FUNCTION get_choice(depth INTEGER)
    MENU ""
        BEFORE MENU
            CALL DIALOG.setActionActive("normal", depth < 6)
            CALL DIALOG.setActionActive("dialog", depth < 6)
        ON ACTION normal
            RETURN "normal"
        ON ACTION dialog
            RETURN "dialog"
        ON ACTION close_window
            RETURN "close_window"
    END MENU
    RETURN "close_window"
END FUNCTION
#! askreuben187.per
LAYOUT
GRID
{
Depth   [f01       ]
Style   [f02       ]
}
END
END
ATTRIBUTES
f01 = formonly.depth;
f02 = formonly.style;