Previous: Abstract Display Functions, Up: Abstract Display [Contents][Index]

#### 37.20.2 Abstract Display Example

Here is a simple example using functions of the ewoc package to implement a color components display, an area in a buffer that represents a vector of three integers (itself representing a 24-bit RGB value) in various ways.

    (setq colorcomp-ewoc nil
          colorcomp-data nil
          colorcomp-mode-map nil
          colorcomp-labels ["Red" "Green" "Blue"])

    (defun colorcomp-pp (data)
      (if data
          (let ((comp (aref colorcomp-data data)))
            (insert (aref colorcomp-labels data) "\t: #x"
                    (format "%02X" comp) " "
                    (make-string (ash comp -2) ?#) "\n"))
        (let ((cstr (format "#%02X%02X%02X"
                            (aref colorcomp-data 0)
                            (aref colorcomp-data 1)
                            (aref colorcomp-data 2)))
              (samp " (sample text) "))
          (insert "Color\t: "
                  (propertize samp 'face
                              `(foreground-color . ,cstr))
                  (propertize samp 'face
                              `(background-color . ,cstr))
                  "\n"))))

    (defun colorcomp (color)
      "Allow fiddling with COLOR in a new buffer.
    The buffer is in Color Components mode."
      (interactive "sColor (name or #RGB or #RRGGBB): ")
      (when (string= "" color)
        (setq color "green"))
      (unless (color-values color)
        (error "No such color: %S" color))
      (switch-to-buffer
       (generate-new-buffer (format "originally: %s" color)))
      (kill-all-local-variables)
      (setq major-mode 'colorcomp-mode
            mode-name "Color Components")
      (use-local-map colorcomp-mode-map)
      (erase-buffer)
      (buffer-disable-undo)
      (let ((data (apply 'vector (mapcar (lambda (n) (ash n -8))
                                         (color-values color))))
            (ewoc (ewoc-create 'colorcomp-pp
                               "\nColor Components\n\n"
                               (substitute-command-keys
                                "\n\\{colorcomp-mode-map}"))))
        (set (make-local-variable 'colorcomp-data) data)
        (set (make-local-variable 'colorcomp-ewoc) ewoc)
        (ewoc-enter-last ewoc 0)
        (ewoc-enter-last ewoc 1)
        (ewoc-enter-last ewoc 2)
        (ewoc-enter-last ewoc nil)))

This example can be extended to be a color selection widget (in other words, the “controller” part of the “model–view–controller” design paradigm) by defining commands to modify `colorcomp-data` and to finish the selection process, and a keymap to tie it all together conveniently.

    (defun colorcomp-mod (index limit delta)
      (let ((cur (aref colorcomp-data index)))
        (unless (= limit cur)
          (aset colorcomp-data index (+ cur delta)))
        (ewoc-invalidate
         colorcomp-ewoc
         (ewoc-nth colorcomp-ewoc index)
         (ewoc-nth colorcomp-ewoc -1))))

    (defun colorcomp-R-more () (interactive) (colorcomp-mod 0 255 1))
    (defun colorcomp-G-more () (interactive) (colorcomp-mod 1 255 1))
    (defun colorcomp-B-more () (interactive) (colorcomp-mod 2 255 1))
    (defun colorcomp-R-less () (interactive) (colorcomp-mod 0 0 -1))
    (defun colorcomp-G-less () (interactive) (colorcomp-mod 1 0 -1))
    (defun colorcomp-B-less () (interactive) (colorcomp-mod 2 0 -1))

    (defun colorcomp-copy-as-kill-and-exit ()
      "Copy the color components into the kill ring and kill the buffer.
    The string is formatted #RRGGBB (hash followed by six hex digits)."
      (interactive)
      (kill-new (format "#%02X%02X%02X"
                        (aref colorcomp-data 0)
                        (aref colorcomp-data 1)
                        (aref colorcomp-data 2)))
      (kill-buffer nil))

    (setq colorcomp-mode-map
          (let ((m (make-sparse-keymap)))
            (suppress-keymap m)
            (define-key m "i" 'colorcomp-R-less)
            (define-key m "o" 'colorcomp-R-more)
            (define-key m "k" 'colorcomp-G-less)
            (define-key m "l" 'colorcomp-G-more)
            (define-key m "," 'colorcomp-B-less)
            (define-key m "." 'colorcomp-B-more)
            (define-key m " " 'colorcomp-copy-as-kill-and-exit)
            m))

Note that we never modify the data in each node, which is fixed when the ewoc is created to be either `nil` or an index into the vector `colorcomp-data`, the actual color components.

Previous: Abstract Display Functions, Up: Abstract Display [Contents][Index]