How to Guides - McCLIM/McCLIM GitHub Wiki

This page contains how-to guides, AKA recipes for CLIM. To understand what content and style is suitable for this page, consult the Diataxis Framework.

How to create a text editor pane

Add (make-pane 'text-editor-pane) to :pane, :panes or :layouts in your define-application-frame expression. For example -

(clim:define-application-frame test () ()
  (:layouts (default (clim:make-pane 'clim:text-editor-pane :height 200 :width 600))))

In :pane or :panes, just specifying :text-editor suffices -

(clim:define-application-frame test () ()
  (:pane :text-editor :height 200 :width 600))

How to modify running CLIM applications

  1. If you use a REPL, you probably don’t want it to be blocked when you start your CLIM application. This can be achieved in one of the following ways -
    (clim:find-application-frame 'my-frame)
    ;; or
    (bt:make-thread (lambda () (run-application-frame 'my-frame))
        

    TODO - link to reference entries for find-application-frame and run-application-frame

  2. To update the application menu bar after evaluating a new command definition, use one of -
    (setf (frame-command-table (find-application-frame 'my-frame)) (find-command-table 'my-table))
    ;; or (McCLIM-specific)
    (let ((frame *application-frame*))
      (climi::update-menu-bar (frame-menu-bar-pane frame)
                              frame
                              (frame-command-table frame))
        

How to make a maximized application frame

Use (graft-height (find-graft)) and (graft-width (find-graft)) as values for :height and :width, e.g. -

(in-package :clim-user)
(define-application-frame test () ()
  (:pane :application
         :height (graft-height (find-graft))
         :width (graft-width (find-graft))))
(run-frame-top-level (make-application-frame 'test))

You can read more about grafts in the CLIM User Guide or the CLIM 2 Specification.

How to relax the presentation type matching in accept

When accepting a type such as (integer 0 18), objects presented as integer are not sensitive even when the object falls in the mentioned range. This is because applicability is computed based on the presentation types first. To relax this constraint, we may use a translator. This has the benefit that it may be associated with a local command table, so it doesn’t affect other applications.

(defmacro define-multipass-translator
    (ptype &optional (command-table 'global-command-table))
  (let ((name (alexandria:symbolicate 'multipass- ptype)))
    `(define-presentation-translator ,name
         (,ptype nil ,command-table
                 :tester ((object context-type)
                          (presentation-typep object context-type)))
         (object context-type)
       (values object context-type))))

(define-multipass-translator integer my-command-table)

Now, within my-command-table, objects that are typep to (integer 0 18) will be selectable.

How to draw only the visible part of the application

Sometimes the drawing routine is complicated. In that case we don’t want to record all elements but rather redraw only the visible part of the screen, that is updated when scrolled. This snippet shows one possible way to do that.

(in-package #:clim-user)

(defclass my-fancy-record (climi::standard-displayed-output-record)
  ())

(defmethod replay-output-record ((record my-fancy-record) stream &optional region x y)
  (declare (ignore x y))
  (let ((ink (alexandria:random-elt (list +blue+ +red+ +yellow+ +green+ +cyan+ +grey+))))
    (with-bounding-rectangle* (x1 y1 x2 y2) (pane-viewport-region stream)
      (draw-rectangle* stream x1 y1 x2 y2 :ink +light-pink+)
      (draw-rectangle* stream (+ x1 10) (+ y1 10 ) (- x2 10) (- y2 10) :ink ink))))

(defun fancy-display (frame stream)
  (declare (ignore frame))
  (stream-add-output-record stream
                            (make-instance 'my-fancy-record
                                           :x1 0 :y1 0 :x2 800 :y2 600
                                           :ink +black+
                                           :clipping-region (make-rectangle* 0 0 800 600))))


(define-application-frame partialxr ()
  ()
  (:pane :application :display-function 'fancy-display :display-time t))

(find-application-frame 'partialxr)

How to perform an action by clicking on an object

  1. Print the object as a presentation, usually via with-output-as-presentation.
  2. Define a command for the action, usually via define-<frame>-command.
  3. Define a presentation-to-command-translator using define-presentation-to-command-translator.

If you wish to perform an action when the pointer is not on any object, supply blank-area as the from-type argument.

See also the description of presentation-to-command translators, and the address book, puzzle, checkers, and German towns examples.

⚠️ **GitHub.com Fallback** ⚠️