CLIM mail archive


Initializing application frames

    Date: Wed, 18 Dec 1991 01:24+0200

    I'm a bit confused about how to initialize my application frames.
    I'm displaying a static set of data in various panes which are
    scrollable.  I've defined an application frame and written an
    :after initialize-instance method to present the data in the 
    apropriate panes.  The scrollbars don't seem to get activated
    until I resize the frame and in fact, sometimes the menus are messed
    up as well.  The only alternative I can see is to defined a display
    function for each pane and let it do the presenting.  This seems
    wasteful (is there a clever way to do it?).

    Configuration:  MCL 2.0b1p3 w/ CLIM 1.0 from ILA on a MAC IIci.

    Seth Goldman
    (310) 317-5693

You should note that an :after initialize-instance method is 
in terms of CLIM a rather low level approach, because it
act directly on the CLOS object representing the new frame.

I suggest that you use CLIM facilities to solve your problem.
In case that your CLIM documentation doesn't say anything about that,
here's the appropriate chapter of Symbolics' CLIM Documentation.

Markus Fischer
Symbolics Systemhaus GmbH
Consulting Services
Frankfurt, Germany

Copyright for the part of the documenation:
(C) 1991 - 1981 Symbolics, Inc.
8 New England Executive Park, East
Burlington, MA 01803

       Initializing CLIM Application Frames

       There are several ways to initialize an application frame:

       1.   The value of an application frame's slot can be initialized using
           the1 0:initform slot option in the slot's specifier in the
           clim:define-application-frame form.1 0This technique is suit-
           able1 0if the slot's initial value does not depend on the values of
           other1 0slots, calculations based on the values of initialization ar-
           guments,1 0or other information which can not be determined until
           after the1 0application frame is created.1 0See the macro
           clos:defclass to learn about slot-specifiers.

       2.   For initializations which depend on information which may not be
           available until the application frame has been created, an :after
           method can be defined for clos:initialize-instance on the1 0ap-
           plication frame's class.1 0Note that the special variable
           clim:*application-frame* is not bound to the application since
           the application is not yet running.1 0The macro1 0clim:with-frame-
           state-variables cannot be used in this1 0context, either.1 0You
           may use clos:with-slots,1 0clos:with-accessors, or any slot
           readers or accessors which have1 0been defined.

       3.   A :before method for clim:run-frame-top-level on the1 0ap-
           plication's frame is probably the most versatile place to perform
           application frame initialization.1 0This method will not be executed
           until the application starts running.1 0clim:*application-frame*
           will be bound to the application frame, and you can use
           clim:with-frame-state-variables in this context.

       4.   If the application frame employs its own top-level function, then
           this function can perform initialization tasks at the beginning of
           its1 0body.1 0This top-level function may call1 0clim:default-frame-
           top-level to achieve the standard behavior1 0for application

       Of course, these are only suggestions.1 0There might be other tech-
       niques1 0which might be more appropriate for your application.1 0Of
       those listed, the1 0:before method on clim:run-frame-top-level is
       probably the best1 0for most circumstances.

       Although application frames are CLOS classes, do not use
       clos:make-instance to create them.1 0To instantiate an application
       frame, always use clim:make-application-frame.1 0This function
       provides important initialization arguments specific to application
       frames which clos:make-instance does not.1 0clim:make-
       application-frame passes any keyword value pairs1 0which it does
       not handle itself on to clos:make-instance.1 0Thus, it1 0will respect
       any initialization options which you give it, just as1 0clos:make-
       instance would.

       Here is an example of how an application frame's behavior might be
       modified by inheritance from a superclass.

       Suppose we wanted our application to record all of the commands
       which1 0were performed while it was executing.1 0This might be useful in
       the1 0context of a program for the financial industry where it is impor-
       tant to1 0keep audit trails for all transactions.1 0As this is a useful func-
       tionality1 0that might be added to any of a number of different appli-
       cations, we1 0will separate it out into a special class which implements
       the desired1 0behavior.1 0This class can then be used as a superclass for
       any1 0application which should keep a log of its actions.

       The class has an initialization option :pathname which specifies the
       name of the log file.1 0It has a slot named transaction-stream
       whose1 0value is a stream opened to the log file when the application
       is running.

            2(defclass transaction-recording-mixin ()
0                    2((transaction-pathname :type pathname
0                                    2       :initarg :pathname
0                                    2       :reader transaction-pathname)
0                    2 (transaction-stream :accessor transaction-stream)))
0       We use an :around method on clim:run-frame-top-level which
       opens1 0a stream to the log file, and stores it in the transaction-
       stream slot.1 0unwind-protect is used to clear the value of the slot
       when the stream1 0is closed.

            2(defmethod clim:run-frame-top-level :around
0                    2   ((frame transaction-recording-mixin))
0            2  (with-slots (transaction-pathname transaction-stream) frame
0            2    (with-open-file (stream transaction-pathname
0                                    2    :direction :output)
0            2      (unwind-protect
0                    2  (progn
0                    2    (setq transaction-stream stream)
0                    2    (call-next-method))
0                    2(setq transaction-stream nil)))))
0       This is where the actual logging takes place.1 0The command loop in
       clim:default-frame-top-level calls1 0clim:execute-frame-
       command to execute a command.1 0Here we1 0add a :before method
       which will log the command.

            2(defmethod clim:execute-frame-command :before
0                    2 ((frame transaction-recording-mixin) command)
0            2  (format (transaction-stream frame)
0                    2  "~&Command: ~a" command))
0       It is now an easy matter to alter the definition of an application to
       add1 0the command logging behavior.1 0Here is the definition of the puz-
       zle1 0application frame from the CLIM demos suite (from the file
       "SYS:CLIM;DEMO;PUZZLE.LISP").1 0Our modifications are shown in
       3italics0.1 0We use the superclasses argument to specify that the puzzle
       application frame should inherit from
       transaction-recording-mixin.1 0Because we are using the superclass
       argument, we must also explicitly1 0include clim:application-frame
       which was defaultly included when1 0the superclasses argument was

            2(define-application-frame puzzle 
0                                    2  (3transaction-recording-mixin application-fra
0            2    ((puzzle :initform (make-array '(4 4))
0                    2     :accessor puzzle-puzzle))
0            2  3(:default-initargs :pathname "puzzle-log.text")
0            2  (:panes ((title :title)
0                    2   (menu :command-menu)
0                    2   (display :application
0                            2    :default-text-style '(:fix :bold :very-large)
0                            2    :incremental-redisplay T
0                            2    :display-function draw-puzzle))))
0       Also note the use of 

            2(:default-initargs :pathname "puzzle-log.text")
0       to provide a default value for the log file name if the user doesn't
       specifty one.

       The user might run the application by executing

0            2 (clim:make-application-frame 'puzzle
0            2   :parent (clim:open-root-window :sheet)
0            2   :pathname "my-puzzle-log.text"))
0       Here the :pathname initialization argument was used to override the
       default name for the log file (as was specified by the :default-
       initargs1 0clause in the above application frame definition) and to use
       the name1 0"my-puzzle-log.text" instead.1 



Main Index | Thread Index