---
layout: ../Site.layout.js
---
# Just draw an ellipse! Screwlisp's Common Lisp Interface Manager McCLIM intro
- - «.intro»  (to "intro")
- - «.starting clim outside emacs»    (to "starting clim outside emacs")
- - «.lisp class w ellipses list»     (to "lisp class w ellipses list")
- - «.clim child of ellipses-mixin»   (to "clim child of ellipses-mixin")
- - «.display-function»       (to "display-function")
- - «.command random ellipse» (to "command random ellipse")
- - «.make ellipses frame»    (to "make ellipses frame")
- - «.add one ellipse manually»       (to "add one ellipse manually")
- - «.open the app»   (to "open the app")
- - «.now disconnect emacs from lisp» (to "now disconnect emacs from lisp")

<img src="../just-an-ellipse.png">

## Intro
- - «intro»  (to ".intro")

As I have said before, it is a bit of a misrepresentation of the common lisp interface manager spec to *just* draw an ellipse, though that is certainly very easy to do. Here is a very minimal application example though. We are of course using [JackDaniel](https://turtleware.eu)'s [McCLIM](https://codeberg.org/McCLIM/McCLIM/) implementation of the spec. In a gist, we are going to make a GUI application with a button that issues a command that adds a random ellipse, somewhat similar to my [cl-series-pure-lisp](/programming/cl-series-ellipse-sampling) one but using common lisp interface manager drawing equipment in a CLIM `application-frame` instead. Key features are the common lisp object system class integration and simply added interactive button, and threadsafe `execute-frame-command`.

As a quick note about historical context, while McCLIM hails originally from [Strandh](https://metamodular.com/) in 1996, the clim spec was and is the modern progeny of lisp's/lisp machines' dynamic-windows from the 80s.

## Start our clim lisp image outside of emacs
- - «starting clim outside emacs»  (to ".starting clim outside emacs")

Well, honestly inside emacs in this case, but it could have been outside of emacs. Starting lisp in a way emacs needs to explicitly separately connect to. I guess you [recognize this from over here](/momentary/eev-clim-kitten). And then `slime-connect`ing to the running common lisp image, that has McCLIM in it and started a swank server i.e. for emacs to connect to.

```
 (eepitch-shell)
ecl
(require "asdf")
(asdf:load-system :mcclim)
(asdf:system-source-directory :swank)
(merge-pathnames #p"*.*" *)
(directory *)
(merge-pathnames #p"start-swank.lisp" **)
(load *)
 (slime-connect "localhost" 4005)
 (setq eepitch-buffer-name "*slime-repl ECL*")
(in-package :clim-user)
(print '(I can see this is working))
```

## Common Lisp class with a list of ellipses
- - «lisp class w ellipses list»  (to ".lisp class w ellipses list")

```
(defclass ellipses-mixin () ((ellipses :initform '() :accessor ellipses)))
```

## CLIM `application-frame` child of that class
- - «clim child of ellipses-mixin»  (to ".clim child of ellipses-mixin")

```
(define-application-frame ellipses-frame
   (standard-application-frame ellipses-mixin) ()
 (:pane :application :display-function 'draw-ellipses))
```

## Display-function
- - «display-function»  (to ".display-function")

```
(defmethod draw-ellipses ((obj ellipses-frame) pane)
 (loop :for ellipse :in (ellipses obj) :do
   (apply 'draw-ellipse* pane ellipse)))
```

(The clim idiom is to `:incremental-redraw t .. updating-output` but that is its own kettle of fish. This is fine indicatively for now.)

## A command that adds a slightly random ellipse
- - «command random ellipse»  (to ".command random ellipse")

```
(define-ellipses-frame-command
   (com-add-random-ellipse :menu t :name t)
   ()
 (let ((frame *application-frame*)
       (ellipse (list (1+ (random #o200)) ; cx
                      (1+ (random #o200)) ; cy
                      (1+ (random #o200)) ; rdx1
                      (1+ (random #o200)) ; rdx2
                      (1+ (random #o200)) ; rdy1
                      (1+ (random #o200)) ; rdy2
                      )))
   (push ellipse (ellipses frame))))
```

## Make one of these frames
- - «make ellipses frame»  (to ".make ellipses frame")

```
(make-application-frame 'ellipses-frame)
(defparameter *ellipse-frame* *)
```

## Add one ellipse manually
- - «add one ellipse manually»  (to ".add one ellipse manually")

```
(execute-frame-command *ellipse-frame* '(com-add-random-ellipse))
```

There is no special reason to do this except to see `execute-frame-command`. Note that anything that goes through `execute-frame-command` is threadsafe by McCLIM - super handy.

## Finally, open that app!
- - «open the app»  (to ".open the app")

```
(run-frame-top-level *ellipse-frame*)
```

## Now quit lisp (`M-x sli-disc`) in emacs and go back to the image on its own
- - «now disconnect emacs from lisp»  (to ".now disconnect emacs from lisp")

And reopen the frame from the 'external' lisp image

```
 (eepitch-shell)
(in-package :clim-user)
(run-frame-top-level *ellipse-frame*)
```

Our ellipse and functionality introduced inside emacs is still there!

# Fin.

See you [on the Mastodon to talk about this example](https://gamerplus.org/@screwlisp/114594982268789432) too everyone. If you need a push to get started especially. NOT SALTY AT ALL ABOUT MY EXPERIENCE REPORT ON MIXINS AND CLIM PRESENTATIONS BEING BETTER-LUCK-NEXT-YEAR'D BY ONE REVIEWER AT ELS2025 (thank-you for your notes).