This Old Window

One of the biggest challenges I’ve faced in programming over the years, is simply being able to put a Window up on the screen, and start interacting with it.  The sheer complexity of the act, kept we far away from programming in Windows, preferring NeXT, Taligent, and BeOS, just to avoid the dreaded event loops, key mappings, etc.

But, here it is, some 27 or so years since the first “Windows” hit the streets, and I’m back to it, but with new tools.  The basic Windows API hasn’t changed much in all that time.  Still the complex convoluted callbacks/windowproc message pump thing.  I’ve seen MFC, ATL, and myriad other frameworks from Microsoft and otherwise, come and go, and still, programming a simple window seems to be elusive.

I guess that’s one reason web browsers have become so popular as a programming platform.  Since the basic window, and attendant mouse and keyboard stuff is taken care of, the programmer is fairly free to simply focus on laying things out on a canvas.

Well, armed with my latest Lua libraries, the above “Hello World” style of window looks like this from the coding perspective:

require "GameWindow"
local appwin = GameWindow({Title = "Hello Window"})
appwin:Show()
appwin.GDIContext:Text("Hello, Lua World!", 50, 80)
appwin:Run()

That’s 5 lines of code.  And what do you get for your troubles?  You get a window up on the screen, you can draw into it, and you get an event loop which will safely shut things down when you click on the ‘close’ box of the window.  That’s about it, the bare minimum required to put a window up on the screen.

OK.  It’s deceptive.  You can argue that this style of application doesn’t really do anything, other than demonstrate you can create an dummy app with 5 lines of code.  So, how about something based on time?

require "GameWindow"
function ontick(win, tickCount)  
win.GDIContext:Text("Hello, Lua World!", 50, 80)
local stats = string.format("Frame: %d",tickCount)  
win.GDIContext:Text(stats)
end

local appwin = GameWindow({Title = "Hello Window", OnTickDelegate=ontick})
appwin:Run()

 

Here, I’ve made a couple of changes.  This time around, when I construct the GameWindow, I give a function ‘ontick’, which will be called for every frame.  By default the frame rate is 30 frames per second. Also, I’ve dispensed with the “Show()” function call, as that is done automatically by the “Run()” function.

Within the ontick function, I can do anything I want.  This is a typical “game loop” type of program.  So, if you’re used to programming games, you are familiar with this paradigm.  Everything from updating the scene, to rendering happens within this tick routine.  Of course, you’re free to spin up multiple threads, or coroutines, or whatever, to make your processing more efficient, but this is the basic event loop.

Now, keyboard command mapping, and mouse tracking are as cumbersome as ever, but Lua does make it somewhat easier. You can simply map a key combination to a function pointer, and be done with it. But, more than likely, these days you’ll have a keystroke fed to an input processor, which will asynchronously create and dispatch some form of command to be executed by some other part of the system.

A 5 line app isn’t going to do me much good, but the fact that getting started only takes 5 lines, or rather 3 lines really, makes experimentation that much easier to start and comprehend. Similarly, other parts of the library can be stitched together using bare minimums in terms of concepts, size of API surface area, and the like. So, finally, after 20 some odd years of programming, I’ve been able to create a UI system that even I can understand.

Advertisements


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s