Creating Resizeable Windows with AppGraphics

With the release of Simply Fortran version 2.23, AppGraphics now supports resizeable windows. This feature greatly improves the functionality of the library, but there is a bit of a learning curve in creating and managing such windows. We’ll walk through a simple example below that should illustrate how to go about creating an application that uses resizeable windows.

The first step is proceed as normal in creating our window. Of course, we still need to specify an initial size:

myscreen = initwindow(320, 240, closeflag=.TRUE.)

In the above declaration, one may notice that there is no mention of a resizing capability. Wee need to use another call to enable resizing:

call enableresize(handle_resize)

The subroutine above will enable resizing for the current window. The argument we’ve included, handle_resize, is actually the name of a subroutine to be called whenever the window changes size. Such a subroutine would be useful if, for example, we need to reposition window controls or redraw graphic contents of a window. We’ll try to do both in this example.

In our main program, we’ll first add a button to our window in the lower right corner:

integer::mybutton
logical::quit
....
mybutton = createbutton(270, 210, 40, 20, "Close", handle_button)
quit = .FALSE.

In the code above, we’ve added a “Close” button that will, when clicked, call a subroutine handle_button that will flip the value of quit to .TRUE. and exit idle mode. We’ll also need an event loop in our code:

do while(.NOT. quit)
    call draw_window()
    call loop()
end do

call closewindow(myscreen)

The event loop above basically draws our window and enters idle mode. If we ever idle mode, it first checks if the quit flag was triggered and, if not, redraws the window. The above structure means that we need only a simple subroutine for our resize callback handle_resize:

    subroutine handle_resize()
    use appgraphics
    implicit none
    
        call stopidle()
        
    end subroutine handle_resize

All the logic for laying out our window needs to reside in the draw_window subroutine. We’ll try to do two things in our drawing subroutine:

  1. Position mybutton in the lower right corner
  2. Output the window size, centered, in our window

For both of these tasks, we’ll need to know the current window size, which can easily be done with calls to getmaxx and getmaxy:

    integer::w,h
    ...
        w = getmaxx()
        h = getmaxy()

Based on the window size, we can actually reposition our button quite easily with a call to setbuttonposition:

        call setbuttonposition(mybutton, w-50, h-30, 40, 20)

The next task is to draw something in our window. We’ll simply write the window size near the top of the window, erasing any earlier text first:

        integer::tw
        character(100)::info
        ...
        write(info, '(A5,1X,I5,A1,I5)') "Size:", w, "x", h
    
        call setviewport(0, 0, w, 40, .FALSE.)
        call clearviewport()
        tw = textwidth(trim(info))
        call outtextxy( (w/2-tw/2), 5, trim(info))

The code above first writes the current window dimensions into the string info. Next, it defines and immediately clears a viewport where previous text would have existed. Finally, it outputs the text, centered in the window.

When you first run the program, you should see something like:

agr1

Unlike other AppGraphics windows, however, this one can be resize by dragging the borders.  Thanks to our design, things will continue to look nice at other sizes:

agr2

Working with a resizeable window is rather easy as long as you properly handle drawing the window when resize occurs.

If you’d like to try the code out for yourself, feel free to do so by clicking the link below:

It should work fine in Simply Fortran version 2.23 or higher.



Leave a comment