Monday, December 18, 2006

shell extensions gotcha

Jeff Shrager posed this question back in September regarding his desire to create a Windows Explorer shell extension using Lisp (not specifically CL). I replied thusly and he later indicated that he'd had success.

It didn't occur to me at the time, but I've just now discovered that implementing shell extensions via certain implementations of Lisp, or any other single-instance runtime environment for that matter, might not be such a good idea. This thread has discussion of a similar idea, in this case involving the CLR. As a couple knowledgeable people point out in the ensuing discussion, the problem is that every application that does a mundane thing like invoking the common file dialog suddenly gets the runtime you used for your extension (Lisp or CLR or whatever) injected into it. Chaos could ensue for several reasons, for example if your runtime needs to reserve large chunks of virtual address space for itself that the host application isn't expecting and/or can't satisfy. Not to mention the potential inability of two such runtimes to co-exist in the same process, such as when you develop a GUI app that uses the same (or different!) version of said runtime.

There are easy-to-find examples and shareware floating around the Net for doing this. Nonetheless, I'd take Jesse Kaplan's and Raymond Chen's opinions at face value and think really hard about which Lisp I was using before venturing down such a path.

Saturday, December 16, 2006

AllegroCL 8.0 port

On the spur of the moment, I decided to try porting Graphic-Forms to AllegroCL 8.0. After a few hours work, I got all of the test programs running. It was fairly straightforward. These days, it seems that the main complication in porting Graphic-Forms is translating stdcall callback definitions into the vendor's particular FFI vocabulary. A CL whose dynamic FFI is a second-class citizen is likely to be a troublesome porting target, though.

Sunday, December 3, 2006

new job

Tomorrow, I'm starting a new job that is mostly Java programming but may also involve some C++ and C#. At least in the beginning, I'll be working on non-graphical library code. The problem domain is pretty interesting and (for me) brand new.

Does this mean the end of my Lisp hacking days? Not at all. Throughout my career, I've consistently worked on projects in my free time -- I tell people that if programming wasn't my job, it would be my hobby. And I know there are lots of people who feel the same way. Lisp multiplies the fun by 10x (or whatever factor you want to plug in, it's large). I am and will continue to be an enthusiastic member of the Lisp community.

I am returning to the so-called commercial software development world armed with a broader view of how to solve problems. I also have a pragmatic view of Java programming as a technology, and Java/C++ programmers as highly capable and intellectually stimulating folks with whom to work. It will be nice to collaborate with folks on a face-to-face basis.

Meanwhile, I continue to work on Graphic-Forms and look forward to making the next release available (I'm thinking January is likely). My McCLIM backend project continues as well. I salute the SBCL developers for getting to the 1.0 stage and hope to find ways of contributing to the Win32 port. I continue to be one of the binary package maintainers for CLISP. And there are some other projects that I have cooking.

If only there were more hours in each day!

Friday, December 1, 2006

Graphic-Forms version 0.7.0

Release 0.7.0 of Graphic-Forms, a Common Lisp library for Windows GUI programming, is now available. This is an alpha release, meaning that the feature set and API have not yet stabilized.

Here is what's new in this release:

. Implemented cursor support. Applications can choose from the system-defined cursors or load them from external files. Also provided are convenience macros GFW:WITH-CURSOR and GFW:WITH-WAIT-CURSOR.

. Implemented a new layout manager called GFW:BORDER-LAYOUT which allows applications to assign children to regions around the perimeter of a window or the center.

. Implemented GFS:OBTAIN-SYSTEM-METRICS as a higher-level interface to the Win32 GetSystemMetrics() API. It returns a hash table containing slightly post-processed system metrics values.

. Implemented the function GFW:PROCESS-EVENTS to help applications flush the event queue of pending events.

. GFW:APPEND-ITEM now accepts an optional classname argument so that applications can use custom item classes.

. Implemented a new macro GFW:WITH-ROOT-WINDOW which manages the lifetime of an instance of GFW:ROOT-WINDOW for use within the macro body.

. Fixed ASDF loading problems.

The README.txt file in the release zip file also has additional important information about this release.

Download the release zip file here:
http://prdownloads.sourceforge.net/graphic-forms/graphic-forms-0.7.0.zip?download

The project website is:
http://common-lisp.net/project/graphic-forms/

Sunday, November 19, 2006

my McCLIM restart

After realizing I had tried to absorb too much too fast in terms of McCLIM and backend implementation, and after taking a break from it, this weekend I pressed the Reset button. Not that I've thrown any code away, but rather, I'm going to spend some time working with McCLIM in its natural habitat -- that is to say, via SBCL on Linux and the CLX backend (maybe I'll experiment with gtkairo too, we'll see). I'll get some practical experience with it in an environment where it works, then return to my Win32 backend implementation.

[Update: well, my Gentoo install is old enough that GTK+ 2.8.19 fails to build. So it's back to CLX on Win32 after all. I really should upgrade my Linux, though.]

Friday, November 17, 2006

releases rant follow-up

I can't seem to add a reply to either of Greg's blog entries concerning my "releases" rant (or else there will be duplicate comments showing up, oops!) so I'll respond here and hope that he sees it.

As Dave mentioned in his comment on your blog, and after considering your more recent ideas, I suspect you're still tackling a different problem (and that's OK, I acknowledge that you may have a different perspective). I think you're assuming a certain state of mind that translates into critical thinking about what exactly a release tag corresponds to, whereas my concern is with developers who have been explicit about their decision not to spend mental energy on that. The result is that I can't justify adding their code as a dependency for my users.

Wednesday, November 15, 2006

"we don't do releases"

I have encountered several CL libraries whose dev teams are either indifferent about doing official releases or have an explicit statement on their project website(s) notifying the world that they don't plan to spend time on such activities. One project in particular observes that formal releases are a lot of work and they can be troublesome, and hey installation is as easy as typing `darcs get blah...'

What these developers fail to recognize (or maybe don't care about) is that this attitude puts the next developer down the foodchain in a difficult position. Here's my perspective -- every dependency of my project is automatically a dependency for my users. When the current source control version doesn't work or whose API/behavior is changing dramatically from day to day, this becomes my problem. I am in a much better position to debug such an issue or look for a substitute, so I don't think it's fair to ask my users to do it. Obviously, I prefer to have some control over the situation, such as being able to say "the version of foobar I have tested for use with my project is 0.x.y patchlevel z". But when a project's release procedure consists of telling people to check out the latest from source control, I have little or no control over which version my users actually get.

So when I see a library that looks useful but doesn't do official releases, I have to decide amongst three choices: a) move on in the hopes of finding an equal or better alternative, b) bundle a snapshot of the library inside my own project, or c) nag the developers to make snapshots available that others can depend on being available (for some useful amount of time). None of those are good choices, frankly.

One last comment...I'm not complaining about brand new projects whose websites are barely a week old. In cases like that, one generally either sees a statement like 'this stuff is brand new and we haven't done any release yet' or it's just easy to tell. Every project has to start somewhere. My beef is with projects that have been around and whose developers really ought to know better -- this is basic configuration management.

Sunday, November 12, 2006

12 Nov 2006

The last two weeks have been a disaster as far as productivity goes. I've had some distractions (of the good kind) and I guess have been feeling somewhat burned out. But forward progress has not completely ground to a halt, and so here is what I've been up to lately.

I haven't made much progress on a McCLIM backend work since those first few days after I announced the start of that project. This is not due to lack of interest! I think I was pushing a little too hard in my efforts to simultaneously understand the CLIM spec, and the existing codebase, and write backend code at the same time. This resulted in signficant burnout, so I decided to put this aside for a bit.

I was embarrassed to discover basic problems with loading the Graphic-Forms system, which I briefly mentioned in my previous blog entry. Who knows how many folks downloaded recent releases and gave up because of this. Well, at least there are fixes available (posted to the mailing list and checked in). Serves me right for not actually using the documented procedure myself. That too has been fixed.

My research into broader layout management functionality has continued. I have spent significant time investigating MiG Layout, which is a monster all-encompassing layout engine in Java. I don't intend to clone that thing, I'll just use it as a rich source of ideas to go along with the many other layout managers that are out there (in different languages). In a related vein, I've always recognized the importance of constraint-based layouts, so I've been on the lookout for constraint engines. A new project called computed-class has caught my eye. The project page advertises simplicity relative to some of the competition.

As for actual coding, I've been working on something called border-layout, which organizes a container window into 5 regions, each of which may be assigned a child component. I anticipate finishing coding and testing of this new layout class within the next several days.

Wednesday, November 1, 2006

note to self: when releasing software, test the build process

Please see the following posting to graphic-forms-devel concerning fixes for loading Graphic-Forms:

http://common-lisp.net/pipermail/graphic-forms-devel/2006-November/000022.html

Saturday, October 28, 2006

delving into McCLIM

I've taken the plunge and started working on a new backend for McCLIM using Graphic-Forms as the substrate. Thus, the result will be a native Win32 backend. Realistically, some time will have to pass before I've got enough functionality working that at least the standard demos can run. It's OK to make quick-and-dirty hacks just to see something pop up on the screen, but if I'm going to propose adding this backend to McCLIM for real at some point, then it needs to play by the rules.

There are plenty of good reasons to take this project on, but for me the most compelling argument is that CLIM represents a much higher-level way of thinking about GUI building. Since I think of myself as somewhat of a specialist in GUI development, this is very important. After I've climbed the somewhat steep learning curve, digesting new concepts along the way (like what the heck `flipping ink' is all about), I'll be that much stronger in my GUI-fu. I can take some of these concepts back to my design of Graphic-Forms -- not necessarily with the intention of directly incorporating CLIM concepts like presentation types, but as a way to take a fresh look at the services that GF provides. After all, GF is itself an abstraction layer over the Win32 User/GDI APIs and does some translation of raw Win32 concepts to Lisp-y abstractions.

A secondary benefit of this will be more code that uses Graphic-Forms, and maybe more users (albeit indirectly).

By the way -- hooray for open-source and Lisp and learning new things and having the ability to spend as much time as I want on this stuff!

Sunday, October 22, 2006

Graphic-Forms version 0.6.0

Release 0.6.0 of Graphic-Forms, a Common Lisp library for Windows GUI programming, is now available. This is an alpha release, meaning that the feature set and API have not yet stabilized.

Here is what's new in this release:

. CFFI snapshot 060925 or later is now required if you are running CLISP 2.40 or later (due to a change in the argument list of CLISP's FFI:FOREIGN-LIBRARY-FUNCTION).

. Completely revamped the Programming Reference. DocBook/XSL is now used for help authoring, and the manual is delivered in HTML Help format.

. Implemented scrolling protocol and related helper objects and functions to facilitate scrolling functionality in applications:

* window styles :horizontal-scrollbar and :vertical-scrollbar

* functions to retrieve window scrollbars

* GFW:EVENT-SCROLL function for handling low-level scrolling events

* GFW:SCROLLING-HELPER for automatic management of a scrollable child panel and window scrollbars (works in combination with GFW:HEAP-LAYOUT)

* integral scrolling and resizing for step sizes greater than 1

. Initial list box control functionality implemented:

* three selection modes (none / multiple / extend)

* list item data comprised by arbitrary application-defined data

* application defined sorting predicates

* querying and programmatic control of item selection states

* customizability of vertical scrollbar mode and keyboard input

Additional list box features are planned for a future release.

. Implemented stand-alone scrollbar and slider control types.

. Renamed functions that query the standard color, file, and font dialogs to make their naming scheme more consistent.

. Implemented GFW:EVENT-PRE-RESIZE function so that applications can customize the behavior of a window's size drag rectangle.

. Implemented GFW:EVENT-PRE-MOVE function so that applications can customize the behavior of a window's move drag rectangle.

. Improved GFW:HEAP-LAYOUT such that it obeys the top child's minimum and maximum sizes, if any such sizes are set.

. Added GFG:FONT method for querying the current font selected for a window.

. Did some housecleaning of the item-manager protocol and heavily refactored the implementation of item-manager base functionality.

. Implemented GFW:ENABLE-REDRAW to enable applications to temporarily disable (and later re-enable) drawing of widget content.

. Fixed a bug in GFW:CHECKED-P (and GFW:SELECTED-P) for checkbox and radio button -style buttons.

. Fixed a bug in the initialization of the paint rectangle in the WM_PAINT message handling method; the correct rectangle is now passed to
GFW:EVENT-PAINT

. Fixed a bug in the SETF functions for GFW:MAXIMUM-SIZE and GFW:MINIMUM-SIZE for windows whereby the size value was not being set in the appropriate slot if there were no layout set for the window.

The README.txt file in the release zip file also has additional important information about this release.

Download the release zip file here:
http://prdownloads.sourceforge.net/graphic-forms/graphic-forms-0.6.0.zip?download

The project website is:
http://common-lisp.net/project/graphic-forms/

Jack Unrue
jdunrue (at) gmail (dot) com
22 October 2006

Sunday, October 1, 2006

new FAQ page

I posted a new FAQ page for Graphic-Forms here. As much as this is intended to advocate my project, hopefully it also helps advocate in favor of GUI programming in Common Lisp on Windows. Comments and suggestions are welcome.

Friday, September 8, 2006

DEFSETF misadventure

While working through some new unit-tests for Graphic-Forms, I happened to discover an assertion failure in an existing test occurring when I run the test more than once. Strangely, it happens on LispWorks and SBCL, but not CLISP. -- Drat! -- The failing assertion validates an attribute value set on a test layout manager (which is created anew every time the test runs), then a bit further on the test sets this attribute to a different value and checks it again. The failure scenario is on the second run. Right now, it looks like the 2nd value from the first run has persisted and that's why the assertion fails.

The culprit appears to be a `short form' DEFSETF defined in Graphic-Forms so application code can SETF attributes on layout managers. Or perhaps the culprit is an attribute setter function upon which the DEFSETF is implemented?

These layout manager attributes are stored in per-object lists; there is no global state in my code where these attributes are concerned. Perhaps there is some memoization being done behind the scenes? It's very puzzling.

Sunday, September 3, 2006

my copy of AMOP arrived

A few days ago, I received a used copy of AMOP ordered through Amazon. This was getting to be a long-overdue stage in my development as a Lisper, because while I have written some MOP-using code (portably, thanks to Pascal Costanza's excellent Closer to MOP library), I had not yet actually studied the MOP from end to end.

One little suggestion for my fellow used-book shoppers: when a seller describes a used-copy's condition as "acceptable -- light underlining and notes in blue pen throughout," I heartily recommend moving on to the next seller. Because even though this copy arrived exactly as described, I had no idea how completely annoying it is to try to read text on the page when the previous owner has underlined nearly every single line, even in the code samples, and added little squiggles and extra notes because apparently the underlining wasn't enough! And in blue pen, which nicely stands out! Aargghh.

Anyway. Obviously, this book demystifies what the MOP is all about. Reading it gets one to thinking "hey, I could do that." Sort of the same feeling one gets while taking an operating system class in college -- getting into the nuts and bolts, one realizes that a lot of what makes up a kernel is just record-keeping (yes yes yes, there are nasty details, too). Implementing a layered architecture with good performance while preserving extensibility is a neat trick, though. This book gives me much to think about.

Wednesday, August 30, 2006

Mr. Interesting-Problems-To-Solve

I had to laugh a while back when I read through one of the now semi-recent threads on comp.lang.lisp, wherein a certain old-timer boasted about how many of us ought to send him our resumes. Although he had his hands full with interesting problems to solve, he allowed as to there being possibly a month or two of boring code to be dealt with afterwards; and we knuckle-draggers who spend most of our time slogging through the muck might be able to handle that (pending credentials review, of course). OK, he didn't write anything about "knuckle-draggers," that part was my invention.

Getting the boring code done -- the stuff about to drive you bonkers because it's so boring -- is a thankless job, but you'll hear about it when you actually get users and they find out you've skimped on certain details. The boring code stops some people from getting their projects past a certain, how shall I say it, critical juncture. Everybody prefers the interesting problems (the 20%), but some folks can't grind out the rest of the project (the 80%), and they move on to greener pastures. I don't think Mr. Interesting-Problems-To-Solve is one of those folks; I'll bet his work is good and thorough. But I laughed because I've seen that attitude for real.

Now where was I? Ah yes, list box notification messages. Oh goody.

Tuesday, August 22, 2006

Graphic-Forms version 0.5.0 released

Release 0.5.0 of Graphic-Forms, a Common Lisp library for Windows GUI
programming, is now available. This is an alpha release, meaning that
the feature set and API have not yet stabilized.

Here is what's new in this release:

. SBCL is now supported (specifically version 0.9.15). Graphic-Forms
includes a small patch provided to the SBCL community by
Alastair Bridgewater to enable the stdcall calling convention for
alien callbacks. Please see src/external-libraries/sbcl-callback-patch

. Implemented a plugin mechanism for integrating graphics libraries. This
means that ImageMagick is now optional -- if your application can get
by with just BMP and ICO formats, then the default plugin (which has no
external dependencies) may be used. This feature also allows applications
to integrate other graphics libraries of their choice.

. In addition to ImageMagick now being optional, external library
dependencies have been further simplified. Several small libraries
are now directly bundled with the Graphic-Forms. Cells is no longer
used in the library proper nor in the demos (but may return at a
later point).

. Implemented a class called icon-bundle which may be populated with
multiple images and then used to set icon data for window frames.
This includes the concept of there being 'large' and 'small' icon
sizes.

. Simplified the argument lists for the event-*** generic functions.
Provided gfw:obtain-event-time as a substitute for passing a time
argument to every function (for which the vast majority of methods
had no use).

. Defined the following new generic functions:

* event-session GF so applications can participate in the
WM_QUERYENDSESSION / WM_ENDSESSION protocol.

* event-activate and event-deactivate GFs so applications can respond
to window activation state changes.

* GFs for querying undo and redo state. Implemented corresponding
methods for edit controls.

* GFs for configuring auto-scrolling and scrollbar visibility. Implemented
corresponding methods for edit controls.

* GFs representing text clipboard data convenience functionality.
Implemented corresponding methods for edit controls.

. Made other miscellaneous improvements to flesh out edit control
support.

. Implemented the standard color chooser dialog and associated
convenience macro 'with-color-dialog'.

. Added the macro 'with-graphics-context' as a convenience for code that
needs to instantiate a context outside of event-paint.

. Heavily revised internal layout manager code in preparation for
supporting more sophisticated layouts. A new class called layout-managed
has been created to serve as a mix-in when defining objects (not
necessarily only windows) that have children to be sized and positioned.

. Implemented a new demo program called textedit which is essentially
a Notepad clone. Its purpose is to show off the multi-line edit
control and the standard Find/Replace dialog.

. Upgraded to the latest lisp-unit and changed test loading code so that
unit-tests are no longer compiled.

. Wrote more documentation and reorganized existing content a bit.
Added discussion of certain naming convention choices.

. Made a variety of bug fixes.

The README.txt file in the release zip file also has additional important
information about this release.

Download the release zip file here:
http://prdownloads.sourceforge.net/graphic-forms/graphic-forms-0.5.0.zip?download

The project website is:
http://common-lisp.net/project/graphic-forms/

Saturday, August 19, 2006

porting code is good!

A long time ago, I used to work at a company called XVT Software, whose main product during that time was a C-language-based user interface portability toolkit. (Yes, we had other products, but the C toolkits were the bread-and-butter). For those of us on the development team, the mantra was 'port early, port often.' We had to deal with lots and lots of environments, and as anyone in the biz back then knows, even within (or especially within!) the Unix-like family tree, the differences between vendor implementations were huge. So you saved yourself a lot of trouble by following our mantra.

Even though as a complete Lisp newbie I knew there were differences between CL implementations, I have only recently started to understand at a deep level how much our old mantra from XVT applies to the CL world. I now have code running well on LispWorks, CLISP, and SBCL. And what I've discovered is that code porting, rather than being a negative, is actually very healthy. In my experience, it has been a process of fine-tuning and improvement, as each new compiler points out bad habits, opportunities for cleanup, etc. In fact, I would go so far as to recommend folks with single-vendor codebases to make some effort at porting to at least one other implementation -- no matter how good your current compiler is (or how good you *think* it is), there will almost always be new/useful tidbits that another compiler will point out. If you try it, I think you'll be glad that you did.

Friday, August 18, 2006

Just testing Writely integration with my blog. Move along, nothing to see here.

Sunday, August 13, 2006

graphics library plugin mechanism

I've recently implemented a neat abstraction in Graphic-Forms. For quite a while now, it has been possible to load image files from disk so that they may be displayed. Until recently, I required the use of ImageMagick to handle the file loading task. It's a very nice library, and I have a small binding implemented for the MagickCore API which is the low-level C-based API. But it's also heavyweight -- your process ends up loading quite a large number of DLLs due to interdependencies in their code, and what's possibly worse is that you pretty much have to do a 'real' install because their code expects certain registry entries and directory structures to exist.

What I've done is to create a simple plugin mechanism, the key aspect of which is implementation of a bit of code in each plugin to translate from library-specific representation of image formats to the Graphic-Forms IMAGE-DATA class. The latter is then what the main library code consumes for image creation and attribute querying. When an image file is to be loaded, each registered plugin is given a chance and the first to succeed wins.

Based on that mechanism, I've now implemented an ImageMagick plugin that you can use if you need to handle more formats besides BMP and ICO. Or if those two formats are all you need, you can load the 'default' plugin which has Lisp code that understands those two formats directly. You can implement additional plugins in application code if you want to use some other graphics library; I plan to document how to do this in the next release.

By the way, another benefit of this strategy is that you can write pixel processing code in terms of IMAGE-DATA or in terms of the external library of your choice, and then create IMAGE instances using IMAGE-DATA as input to display the result.

Thursday, August 10, 2006

SBCL port

Just a quick update. Among the various things I'm working on for the next release, I've now got a significant part of Graphic-Forms up and running on SBCL/Win32. Woot!

Monday, July 10, 2006

input requested: adding a Lisp listener

I'm thinking about adding a Lisp listener to Graphic-Forms, and was
hoping to get some input. Do you think it is:

a) a "must have" feature if GF is to be taken seriously

b) a "nice-to-have" feature that you could live without
(note -- thinking of the availability of SLIME or
commercial IDEs as I write this)

c) more important to make sure apps built with GF have
the right building blocks for a listener, rather than
bundling one directly with the library proper

d) a complete waste of time

???

a lesson in CLOS-based interface fine-tuning

I recently made a fine-tuning pass through the argument lists for event-handling functions in Graphic-Forms and had an interesting experience.

First a bit of background. In Graphic-Forms, applications handle each event type by implementing the associated generic function. E.g., one implements EVENT-SELECT to handle a button press or menu item click. Prior to this past weekend, every event function included a time argument, which was a system-generated timestamp for the event. Other UI libraries have included that information (such as SWT's TypedEvent, which has a time instance variable) so I had figured it would be a good idea to include it in my library. Going ahead with this design choice without thinking harder was my first mistake: events in SWT are objects that are passed to interface methods, thus they can carry any amount of ancillary information with little added cost (from the standpoint of an application implementing those interface methods).

Instead of realizing the design error, I made the narrower observation that an event timestamp is needed in only a few special circumstances -- and in all of the test code I have written so far, I was writing a (declare (ignore time)) form everywhere. That gave me some empirical evidence to justify changing the API. I wanted to alleviate the need for application code to worry about that argument, yet still have access to it in the rare cases where it is needed.

So, my first inclination was to make the time argument &optional. oops! In CLOS, optional arguments in methods have to be congruent in their number just like required arguments, so event method implementors are not saved any work this way.

Then I considered making time a keyword argument, so method implementors could specify &allow-other-keys when they don't need the timestamp. But that adds more clutter than it saves; in other words, a symptom of this being the wrong reason to use keyword arguments.

Finally, the light bulb above my head flickered on, and I decided to remove the time argument completely. As a substitute, I decided to provide a separate access function. Problem solved.

I took away a couple conclusions from this. First, CLOS not only has powerful features, but there are easy-to-see signs that you're misusing them if you just pay attention. And more importantly, it's a mistake to copy a feature without thinking hard.

Monday, July 3, 2006

Graphic-Forms version 0.4.0 released

Release 0.4.0 of Graphic-Forms, a Common Lisp library for Windows GUI
programming, is now available. This is an alpha release, meaning that
the feature set and API have not yet stabilized.

Here is what's new in this release:

. CFFI snapshot 060606 or later is required in order to benefit from a
bugfix for a problem when running on LispWorks where foreign structure
contents could be corrupted; the most obvious symptom of this was a
Win32 error encountered when attempting to create a window.

. A new layout manager called `heap-layout' has been implemented. Its
purpose is to align all the children of a container in a single
Z-orderwise stack and allow the application to select which of the
children are top-most at any given time. This is useful when
implemnenting windows with panels containing related functionality,
where only one such panel should be visible at a time (e.g., property
sheets or wizard dialogs).

. This release provides access to the standard font dialog, and
integrates with the previously-defined font and font-data classes.

. Application-defined modal and modeless dialogs are now fully
supported, including keyboard navigation (tab traversal, default
button invocation via the ENTER key, and cancel button invocation via
the ESC key).

. In this release, the flow-layout manager gets a new style called
:normalize which instructs the manager to size children equally using
the maximum dimension of the children's preferred sizes opposite to
the dimension in which the layout is oriented.

. Applications may set minimum size and/or maximum size constraints
for top-level windows. Setting both constraints to the same size
implicitly disables resizing by the user.

. It is also possible to explicitly disable resizabilty, which not
only results in a fixed window size but also causes window decorations
to be updated appropriately (no maximize box and no resize handles in
the window frame).

. The button class has been expanded to support checkboxes, radio
buttons, toggle buttons, and tri-state button controls.

. There is now basic support for instantiating single-line and
multi-line edit controls. Edit controls participate in the focus gain
/ focus loss protocol; they also provide notification when contents
change via the event-modify generic function.

. Implemented event-focus-gain and event-focus-loss to allow applications
to response to changes in focus.

. It is now possible to customize the background color, foreground
color, and font of label controls. Infrastructure to support similar
customizations for other controls is in place.

. Functions capture-mouse and release-mouse are available to implement
mouse capturing behavior.

. Added a function to programmatically append separators to menus;
this was already possible via DEFMENU but not yet supported for
dynamic menu management.

. Rewrote timer event processing such that the library no longer uses
the TimerProc callback technique, but instead each call to the Win32
SetTimer function is made with the handle to a hidden utility window
managed by the library code.

. Changed the rectangle type to be a structure; it was a class before.

. Started work on infrastructure required to support a new layout
manager called `group-layout' which will appear in a subsequent
release. The infrastructure developed this time includes definition of
a text-baseline method that widgets implement to help layout managers
align text appropriately.

. Also started work on infrastructure needed to enable WinXP-themed
controls.

. Continued work on the UnBlocked demo game.

The above list is in addition to documentation enhancements and
bug fixes. The README.txt file in the release zip file also has
additional important information about this release.

Download the release zip file here:
http://prdownloads.sourceforge.net/graphic-forms/graphic-forms-0.4.0.zip?download

The project website is:
http://common-lisp.net/project/graphic-forms/

Tuesday, June 27, 2006

WGA WTF???

I have been somewhat tolerant of Microsoft's flaws and missteps, especially compared to many in the Lisp community. It seemed to me in the last couple of years that MS dialed down their aggressive/monopolistic tendencies somewhat and revisited their attitudes/strategies towards open-source, standards organizations, communication with the outside world, etc. For instance, the reality of Windows Activation for XP turned out to be pretty reasonable -- certainly a lot less draconian than some thought back when XP was approaching its ship date.

Lately, Microsoft has been getting some bad press about Windows Genuine Advantage, e.g., here and here. Not a very good track record so far! I myself have not encountered any severe problems, so I was willing to believe that this stuff would eventually get sorted out and all would be well.

But I just read this, which is speculation that in the future MS may require legally-licensed Windows users to install WGA or risk having their system disabled. The reply Ed Bott received from MS when he asked for official confirmation is a red flag. It would be very hard for me to rationalize continuing onward as a Windows developer if this speculation becomes reality. WGA is more intrusive than Activation was, it has a poor track record, and I'm not as inclined to give MS the benefit of the doubt as I might have been in the past. So as I continue work on Graphic-Forms, I'm keeping an eye on this situation, as should all Windows users.

Sunday, June 25, 2006

Common Lisp and Windows Vista

The other day, I installed Windows Vista Beta 2 from DVD into a dedicated partition on my PC (the other partition is WinXP SP2). Beta 2 is the first Vista pre-release available to anybody and everybody, as opposed to the technical Betas available to MSDN subscribers and other similarly-connected folks. The only install hiccup that I encountered was that there is currently no driver for my sound system available though Microsoft Update. No biggy. By now, there are probably a dozen reviews of Vista Beta 2 out there, and this blog entry will not be another one. Just in case it helps somebody, here are a few review links:

Naturally, I'm looking at Vista from the perspective of a Common Lisp programmer. So in addition to wanting to poke around the new system and see for myself what it's like, my intention is to get started working with CL implementations on this new version of Windows. In particular, I want to test Graphic-Forms and think about where GF should go, taking into consideration the ways in which the GUI subsystems are changing for Vista and beyond (e.g. some info about that here).

Friday, June 9, 2006

away from the REPL for a week

Next week, I'll be in Maine on vacation and then attending my brother's wedding, so Graphic-Forms work will be interrupted briefly.

There are yet loose ends needing to be tied up before I can make the next release. I might spend some more time on preparations (which are already underway) for implementing the equivalent of GroupLayout that is going to be part of the next JDK/NetBeans release. There are some folks implementing this for SWT as well. And so I want something like it in Graphic-Forms, too. I want to revamp my existing layout-tester program to look and feel more like a GUI layout tool, as a more scalable and robust way of testing the layout managers I've written. Maybe layout-tester ought to evolve into such a tool for real instead of just being happy as a test program. Continuing down my todo list, there are some remaining issues with keyboard navigation in dialogs. I'd also like to implement at least one more common dialog and some controls (especially the edit control). And I'd like to change the graphics package to depend on ImageMagick only if the app developer explicitly chooses to.

The 0.2.0 and 0.3.0 releases saw a decent number of downloads, certainly more than I expected, which is really cool. Unfortunately for me as the lead developer, there has been practically no feedback on the dev mailing list. I'm not working very hard at building `community' around this code, for one thing. I suspect not many folks are getting past the `open the tarball and look at the code' stage. And maybe there aren't that many folks interested in a Windows-only UI library for Common Lisp.

Another possibility is that people are reluctant to invest time and effort in a brand new API that has no appreciable mindshare. I can sympathize with that and every day I think about what the best solution is. Forget about Graphic-Forms for a second, and consider my personal requirements for a UI library: must support Windows as a first-class target, must leverage platform-specific features wherever possible as opposed to compromising in the name of platform portability, must not have too many intermediate layers (especially not some toolkit in another language), and must (eventually, if not already) support multiple Lisp implementations. Right now, I'm not aware of any other UI library for CL that meets those requirements, aside from what I can build myself.

I just hope somebody gets some value out of the code besides me.

Saturday, May 27, 2006

a slight detour

My wife is a professional trombonist who also teaches private lessons in a variety of brass instruments. Her beginner students are especially in need of repeated drills on fingering / positions on their instruments. There are several training programs out there, and while each has useful features, my wife wasn't completely happy with any of them. Since she is married to a programmer :-) she figured she could acquire a program that had exactly the features she has been looking for.

So I've been working on this, and doing it in Common Lisp. I've been spending the majority of my time on it especially recently as a final push to get the first version out. While this has taken time away from direct work on Graphic-Forms, it has given me the chance to use GF as an application developer. That's a perspective that every library developer should take periodically; I believe "dogfooding" is a popular phrase these days :-) And this fingering training program has served as a good testcase.

So, this has been a slight detour in my work, but it's a worthy cause and a lot of fun, too.

Sunday, May 14, 2006

pre-0.4.0 status report

For those who are following progress on Graphic-Forms, here's another status report.

One of the major themes for 0.4.0 will be support for custom dialogs, and that is where most of my effort have been devoted since 0.3.0. One of the reasons why this feature has taken so long to appear in GF is that I put a lot of thought into whether to reuse the built-in dialog manager and dialog template mechanisms that Win32 provides.

A discussion of the tradeoffs could occupy a whole separate blog entry, which I think I will indeed write up and post sometime. I'll cut to chase for now and state that I'm using low-functionality to implement proper dialog behavior.

Some other miscellaneous development:

• implemented a layout manager called `heap-layout' whose behavior is to align all the children of a container in a single Z-order-wise column and allow the application to select which of the children are top-most at any given time. This kind of layout is useful when implementing windows with panels containing related functionality, where only one such panel should be visible at a time (think property sheets or wizard dialogs). The user can then flip between panels based on some gesture such as clicking on a tab control.

• implemented event-focus-gain/event-focus-loss for reacting to changes in focus

• fixed some bugs in key event processing that prevented repeated events for untranslateable keys (e.g., function keys F1-F12) from being delivered

• implemented background/foreground color and font customization for labels, with infrastructure put into place for other controls

• added a method to programmatically append separators to menus; this was already possible via DEFMENU but not yet supported for dynamic menu management

• rewrote timer event processing such that GF no longer uses the TimerProc callback technique, but instead each call to the Win32 SetTimer function is made with the handle to a non-visible utility window that the library creates

• fixed some problems with timer initial delays

That's it for now. Happy coding!

Wednesday, April 26, 2006

Graphic-Forms 0.3.0 released

The next release of Graphic-Forms (version 0.3.0), a CL library for Windows GUI programming, is now available. This is definitely pre-alpha code, so be prepared for missing features, bugs, and API changes in subsequent releases.

Download a release tarball from here:

http://prdownloads.sourceforge.net/graphic-forms/graphic-forms-0.3.0.tar.gz?download

The primary changes in this release are as follows:

  • implemented graphics-context methods for the typical drawing operations and pen attributes; see the new test program invoked by (gft::run-drawing-tester)

  • implemented a representation of fonts and font data, including an API for looking up fonts based on font data

  • implemented font metrics and text metrics querying

  • expanded image drawing operations to support double-buffering

  • expanded the classes representing different window types: top-level represents primary application windows, panel represents child-windows, and the root-window class represents the desktop

  • formalized the window parent and owner concepts with documentation and functions

  • implemented the display class to represent the monitor attached to the system

  • implemented new window style attributes to help applications choose whether the system should automatically repaint the background

  • provided maximum-size and minimum-size functions to allow applications to constrain window sizes

  • revised label controls to support either text or images

  • implemented the file-dialog class which encapsulates the standard open/save dialog

  • made other bug fixes and resource usage cleanup

Please consult README.txt for other details about this release.

The main project website is:

http://common-lisp.net/project/graphic-forms/

Friday, April 7, 2006

Graphic-Forms progress report

I’m making progress towards the next Graphic-Forms release. Here is a brief status update:

  • implemented graphics-context methods for the common drawing operations and pen attributes; there is a new test program invoked via (gft:run-drawing-tester) that exercises these operations

  • implemented a representation of fonts as well as font data and fleshed out the API for creating fonts from font data as well as obtaining font metrics; the aforementioned drawing tester program does exercise fonts

  • expanded the representation of windows, such that there are now classes representing top-level windows and child windows (the latter are called ‘panels’ in GF), as well as a root-window class representing the desktop and a display class representing the system’s monitor

  • also added new window style attributes to help applications choose whether the system should automatically repaint the background or not

  • did some testing and tracked down some embarrassing GDI handle leaks

  • currently developing a simple blocks game as a more complete demo and as a test bed for me to learn how Cells works

  • filed a bug with CLISP concerning stdcall callbacks, which impacts a couple of important functional areas in GF (the test case I submitted might be further reducible and I will work on that)

I’d like to get some more basic infrastructure done before the 0.3.0 release, such as:

  • in particular, complete my research of Cells and decide how/where to integrate that (in particular, I consider this a prerequisite for any further work on layout managers)

  • also more controls

  • at least a couple of the common dialogs

  • and of course more testing

Also, a short while after 0.2.0 went out, I entered ~70 bugs into the tracker at SourceForge. At this early stage, I view most of those as ToDo entries because they are missing features rather than unanticipated problems. Just today, Erik Enge announced that common-lisp.net now has Trac available, and I will certainly investigate further and perhaps decide to migrate issue tracking away from SourceForge.

Wednesday, March 29, 2006

Ideas for a Lisp FFI wiki

A person named “Sacha” recently made the following comment on c.l.l in a thread entitled “CLISP and win32 clipboard access”:

> I've been recently working a lot with .NET, and found
> http://www.pinvoke.net/ to be very usefull.
> This web site is providing the .NET world equivalent to FFI for win32 calls.
> Wouldn't it be very nice to have such a wiki for FFIs ?

Yeah, I think there are several features of pinvoke.net that could/should be replicated in a Lisp FFI wiki:

  • entries for

  • data structures and immediate types

  • function signatures

  • consistent structure across each entry

  • summary

  • complete FFI definition that you can copy&paste

  • perhaps for just CFFI?

  • usage notes or gotchas

  • example code

  • alternatives, if any, for the current entry

  • pointer to relevant doc in the native library (e.g., ImageMagick manual, Gtk+ manual, MSDN, etc)

  • FAQ

  • pros and cons of the various FFIs

  • address SWIG, Verrazano, and other automation tools

  • search

  • a search engine that has a decent syntax and the ability to constrain the search to specific areas (e.g., Google's group: modifier)
In other words, not a jumble of info thrown together, but an organized format that has had some thought put into it. To be useful, this wiki would have to be fairly extensive.

One other crazy thought I had about this is if the wiki was organized via tags a la del.icio.us rather than (or in addition to) a hierarchy. I’d bet that would be especially handy for folks implementing portability layers. E.g., you could search on the combination of “window” and “creation” tags to see FFI definitions for window creation functions in the various UI libraries.

Tuesday, March 21, 2006

Graphic-Forms 0.2.0 released

The first release of Graphic-Forms (version 0.2.0), a CL library for Windows GUI programming, is now available. This is definitely pre-alpha code, so be prepared for missing features, bugs, and API changes in subsequent releases.

Download a release tarball from here:
http://prdownloads.sourceforge.net/graphic-forms/graphic-forms-0.2.0.tar.gz?download

Please consult README.txt for specific details about this release.

The main project website is:
http://common-lisp.net/project/graphic-forms/

Sunday, March 19, 2006

Screenshots

In preparation for releasing version 0.2.0 of Graphic-Forms, I’ve uploaded screenshots:

http://sourceforge.net/project/screenshots.php?group_id=163034

Saturday, March 18, 2006

A couple more items

Following up on the prior entry, here are a couple more motivations for library implementers:
printing
menu accelerator key tables

Motivation for GUI Library development

One of the jobs of a GUI library is to enhance programmer productivity. Any such library having pretensions of being useful for real-world applications necessarily has to provide abstractions over system-level APIs. The system provides building blocks that the library organizes.

With that in mind, I think a GUI library for the MS Windows environment (Win32) has to tackle issues including but not limited to:
  • graphics:

    • bitmap transparency

    • manipulation of non-native image formats

    • scrolling

  • facilitation of multi-threaded applications

    • providing mechanisms for worker threads to safely communicate with event threads

  • construction and inspection of complex structures (e.g., child window hierarchies, menus, and table and tree controls)

    • structure definition

    • efficient modification (especially minimizing redrawing/flashing)

    • tab traversal in non-dialog windows

    • layout management

  • internationalization

    • resource externalization (e.g., strings and data formatting)

    • layout management comes into play here as well

  • smoothing over inconsistencies, bugs, or misfeatures

    • in particular, exposing functionality in a way that makes for the target programming language
Obviously, all of the above can be accomplished by writing directly to the Win32 APIs (since that is how such a library is implemented). But the above features are not directly enabled by Win32, so the application programmer without any GUI library has to implement them or go without.

I would claim that if you’re serious about GUI development, then the above is a subset of the functionality with which you need to be concerned.

Tuesday, February 21, 2006

UI Layout Management, redux

I got a little ahead of myself with the previous entry. Having gotten my first (simple) layout manager working the traditional way, at this point, I think that geometry management in a UI toolkit might be too narrow an application for a generalized constraint solving framework. One of the ideas I might salvage from that last entry is the notion of providing an extended set of layout management primitives with a abstraction over it. That might happen after I’ve done some refactoring. As it stands now, I’ve got a workable interface between layout managers, the containers that rely on layout, and widgets organized via the layouts.

Tuesday, February 14, 2006

UI Layout Management

I’m planning a series of blog entries that discuss the design and implementation of Graphic-Forms layout managers via a constraint-solving engine. In a nutshell, GUI layout management is an abstraction for UI composition whose purpose is to handle the messy details of organizing screen display based on attributes of UI elements plus policies selected by the application programmer. On top of the library usability aspect, layout management is a key enabler for I18n. It seems to me that constraint solving is a powerful but also natural foundation on which to build a layout engine. Check out this tutorial for some background reading on geometric constraint solving.

While I am not claiming that this combination is a novel idea, I do feel confident that it makes sense, given the kind of job that a layout manager needs to accomplish. And as an algorithmic solution, it leverages one of the fundamental strengths of Lisp-based languages.

It’s important to keep the target audience in mind when designing features. The core layout manager can be built with as much generality as desired, such that it understands a broad range of possible layout strategies, and that is definitely a goal. But for usability’s sake, Graphic-Forms should provide pre-defined layout schemes that are each focused on a particular behavior that the developer needs to accomplish. So while the underlying engine may provide enough flexibility to define arbitrary layout schemes, the canned schemes are built on top of the general mechanism and these are what the average developer deals with. But there is an added benefit – advanced developers can use the same mechanism to extend the toolkit’s layout functionality without needing to reinvent the core primitives.

One other preliminary comment: this is an area of the toolkit that is sensitive to performance issues, because

  • real-world application windows and dialogs are often stuffed to the gills with components (usability be damned)

  • the end user will definitely notice repainting performance problems

In an ideal world, the creation/resizing/reorganization of windows and dialogs is near instantaneous as far as the end user can perceive. The reality of course is that overhead is an inescapable factor. Everyone has seen at least one GUI application which exhibited jerkiness or obnoxious flashing in painting as windows are moved and resized. Visual artifacts like that leave a bad impression. Therefore, one of Graphic-Forms’ goals is to strike a balance between power/generality in implementation vs. snappy responsiveness on the screen. I anticipate having to make some hard choices.

For next time, I’m planning an overview of design issues and maybe some discussion of layout manager features available in other UI libraries.

Sunday, February 5, 2006

Graphic-Forms, a new UI toolkit

I’ve been making progress on a Windows-only toolkit for CL, called Graphic-Forms, which I had intended to use for my own projects. But this weekend, I decide to take the plunge and get a project set up at common-lisp.net (still waiting on the reply to my project creation request, though). I hope this code ends up being useful for other people besides me.