Conditional Commands (And Sheets) Extension for McCLIM
Last edited on November 24, 2005
Finally my first entry about Lisp! I have been intending to write about my CLIM demonstration Town Example, the File Selector (also embedded into the Lisp Listener and used as the Find File command for Climacs), and the Tab Layout Pane, which is already used by Beirc, but I was too lazy. Now is the time! Be wowed by the shear beauty this impressive screenshot:
Okay, this entry will not be too much work as I've already written the documentation and can therefore just quote the README file:
----------------------------------------------------------- Title: Conditional Commands (And Sheets) Extension Created: 2005/11/22 Author: Max-Gerd Retzlaff
, http://bl0rg.net/~mgr ------------------------------------------------------------ (c) copyright 2005 by Max-Gerd Retzlaff
This extensions tries to add simple and elegant methods to specify dependencies among commands and between commands and sheets of a (Mc)CLIM application.
Imagine an audio player: The play commands should only be enabled if a audio file is loaded; the same is true for the push-buttons that trigger these commands and probably for a slider that might represent the current position in the audio file.
It may also be nice if only the possible commands and gadgets (in general: sheets) will be enabled if you restart the GUI of such a programme (restart only the GUI not the whole programme).
The extensions uses the term conditional command for commands that enable or disable commands and/or sheets, and the term conditional application frame for an application frame in whose context conditional commands are invoked.
It is stored which commands and sheets got disabled during a run of a conditional application frame; when you exit the application frame and run the top level of a newly created instance of the application frame the previous state will be re-established. This implies that only one instance of a conditional application frame can be running at given time!
ENTITY-ENABLEDNESS-CHANGE has to be a list that matches the parameter list:
(application-frame &key enable-commands disable-commands enable-sheets disable-sheets evaluate-this)
(define-conditional-command (com-bar :name t :menu t :command-table cruft-command-table) (conditional-commands-example :enable-commands (com-baz) :disable-commands (com-bar) :enable-sheets (thud) :disable-sheets (grunt)) () (format t "~%bar called"))
Note that the elements of the arguments to :ENABLE-COMMANDS and :DISABLE-COMMANDS can not only be names of commands but also names of command-tables; in the latter case all comamnds of the command table will be enabled (or disabled).
With EVALUATE-THIS you can specify a form that will be evaluated when the "entity enabledness change" happens, for conditional commands this is immediately after the body of the command has been executed.
In this case ENTITY-ENABLEDNESS-CHANGE has to be a list that matches the parameter list:
(&key enable-commands disable-commands enable-sheets disable-sheets evaluate-this)
(define-conditional-application-frame conditional-commands-example () (:disable-commands (com-bar com-baz) :disable-sheets (thud grunt) :evaluate-this (incf incarnation-number)) () (:command-table ...) (:panes ...) ...)
This "entity enabledness change" happens in a :BEFORE method of CLIM:RUN-FRAME-TOP-LEVEL that dispatches on the just defined conditional application frame.
It might be less confusing to define all "entity enabledness changes" in one place, therefore it is also possible to define an "entity enabledness change" separately, for example:
(add-entity-enabledness-change 'com-baz 'conditional-commands-example :enable-commands '(com-bar) :disable-commands '(com-baz) :enable-sheets '(grunt) :disable-sheets '(thud))
The argument to ADD-ENTITY-ENABLEDNESS-CHANGE has to be a list that matches the parameter list:
(command application-frame &key enable-commands disable-commands enable-sheets disable-sheets evaluate-this)