As I mentioned on my show, while clim2 feels like there could be a
more explanatory tutorial, attempts to create one pretty much converge
to the superapp example.

Anyway, in my one I focus on separating my class/es from the McCLIM
clim2 implementation classes. I'll reproduce what I did in the post,
though canonically it's at

git@codeberg.org:j9000/lispusers -> tfw/high/stringlist.lisp

Define this package: ``` (uiop:define-package
:lispusers/tfw/high/stringlist (:mix :clim :clim-lisp :cl) (:export
#:app-main))

(in-package :lispusers/tfw/high/stringlist) ```

Then I wanted to try the default redisplay - which redraws the entire
application but only when a new command has been run ( :command-loop )
with both a string and a list data structure, so I deffed these
similar classes:

``` (defclass textholder () ((my-string :initform "foo" :type 'string
:accessor my-string)))

(defclass textsholder () ((my-strings :initform '("foo") :type 'list
 :accessor my-strings))) ```

Now, I found if clim's #'define-application-frame gets told a
superclass, it doesn't attempt to provide the clim classes, so there
needs to be an ancestral default clim application frame.

``` (define-application-frame app () ()) ```

Hence I can combine my data-carrying class definition/s with the
ancestral app clim default application. Since this definition defines
the displayed app, all the app panes and layout stuff has to be
together here.

``` (define-application-frame textap (app textsholder) ()
(:pointer-documentation t) (:panes (app :application :height 128
:width 300 :display-function 'display-app) (int :interactor :height
128 :width 300)) (:layouts (default (vertically () app int)))) ```
Now, the superapp example uses something like this function I removed:
``` (defun display-app (frame pane) (let ((strings (my-strings
frame))) (format pane "~@{~a~%~}~%" string))) ``` Instead, since I
wanted to change between my pure clos data classes ``` (defmethod
display-app ((frame textholder) (pane stream)) (let ((string
(my-string frame))) (format pane "~@{~a~%~}~%" string)))

(defmethod display-app ((frame textsholder) (pane stream)) (let
 ((strings (my-strings frame))) (format pane "~{~a~%~}~%" strings)))
 ``` Now, the running and operated upon application is bound to the
 special scope *application-frame*, at least from the command's
 perspective. So quitting is ``` (define-textap-command (com-quit
 :name t) () (frame-exit "application-frame")) ``` But since
 *application-frame* isn't an arguement, I had to use typecase here:
 ``` (define-textap-command (com-addtext :name t) ((string 'string))
 (typecase *application-frame* (textsholder (push string (my-strings
 *application-frame*))) (textholder (setf (my-string
 *application-frame*) string)))) ``` and a utility function for
 running one of this: ``` (defun app-main () (run-frame-top-level
 (make-application-frame 'textap))) ``` See the screenshot phosted
 next to this.

Hope it helps someone, phosted responses and corrections welCOMed.