CLIM mail archive
[Prev][Next][Index][Thread]
Spreadsheet style input method (or AVV)
Date: Tue, 25 Jan 1994 17:00 EST
From: Mike Harper <mlh@BBN.COM>
Has anyone built some type of spreadsheet like data input system in
CLIM (1 or 2)? Is this even a reasonable style of input to use CLIM for?
It's perfectly reasonable, but unless the spreadsheet-like thing is
fairly small, using ACCEPTING-VALUES is not the tool for the job. A
grid arrangement for input fields has strong constraints on what needs
to be redisplayed, but ACCEPTING-VALUES will always go ahead and just
try to redisplay everything it thinks might have changed. So a large
spreadsheet will be slow.
I believe I may have already posted a "grid" output record frob on which
spreadsheets can be built better. I will send it to you in another
message. It's for CLIM 2.0, by the way.
As lagniappe, here is a silly little spreadsheet dialog for CLIM 2.0.
Who knows, you may find it adequate.
-------- Cut here --------
;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Package: CLIM-USER; Base: 10; Lowercase: Yes -*-
(defparameter *default-cell-width* '(6 :character))
(defparameter *cell-text-field-width* '(10 :character))
(defparameter *cell-text-field-view* (make-instance 'text-field-view
:width *cell-text-field-width*))
;; A spreadsheet consists of a bunch of rows, a row consisting of
;; column sums, and a total.
(defclass spreadsheet ()
((rows :reader spreadsheet-rows)
(column-sums :reader spreadsheet-column-sums)
(total :accessor spreadsheet-total :initform 0.0)
(cell-width :reader spreadsheet-cell-width
:initarg :cell-width :initform *default-cell-width*)))
(defmethod initialize-instance :after ((spreadsheet spreadsheet)
&key nrows ncells &allow-other-keys)
(with-slots (rows column-sums) spreadsheet
(setf rows (make-array nrows))
(dotimes (i nrows)
(setf (aref rows i) (make-instance 'spreadsheet-row :ncells ncells)))
(setf column-sums (make-instance 'spreadsheet-row :ncells ncells))))
;; A row consists of a bunch of cells and a row sum.
(defclass spreadsheet-row ()
((cells :reader spreadsheet-row-cells)
(row-sum :accessor spreadsheet-row-sum :initform 0.0)))
(defmethod initialize-instance :after ((row spreadsheet-row)
&key ncells &allow-other-keys)
(with-slots (cells) row
(setq cells (make-array ncells :element-type 'float :initial-element 0.0))))
;; Formatting a spreadsheet row consists of getting as input a
;; value for each cell in the row, using as a default the value
;; that is there right now.
(defun format-spreadsheet-row (row stream cell-width &key use-text-fields)
(let ((cells (spreadsheet-row-cells row)))
(clim:formatting-row (stream)
(dotimes (i (length cells))
(clim:formatting-cell (stream :align-x :right
:min-width (and (not use-text-fields) cell-width))
(setf (aref cells i)
(clim:accept 'float
:default (aref cells i)
:prompt nil :prompt-mode :raw
:query-identifier (list cells i)
:stream stream
:view (if use-text-fields
*cell-text-field-view*
+textual-view+)))))
(present-sum (spreadsheet-row-sum row) stream cell-width))
(setf (spreadsheet-row-sum row) (reduce #'+ cells))))
(defun present-sum (sum stream cell-width)
(clim:formatting-cell (stream :align-x :right :min-width cell-width)
(clim:with-text-face (stream :bold)
(clim:present sum 'float :stream stream))))
(defun spreadsheet (nrows ncells
&key (cell-width *default-cell-width*) (stream *query-io*)
(use-text-fields t))
(let* ((spreadsheet (make-instance 'spreadsheet
:nrows nrows :ncells ncells
:cell-width cell-width))
(rows (spreadsheet-rows spreadsheet))
(column-totals (spreadsheet-row-cells (spreadsheet-column-sums spreadsheet))))
;; :RESYNCHRONIZE-EVERY-PASS T to get the totals recomputed
(clim:accepting-values (stream :own-window nil
:resynchronize-every-pass t)
(clim:formatting-table (stream :x-spacing '(2 :character)
:equalize-column-widths t)
(map nil #'(lambda (row)
(format-spreadsheet-row row stream cell-width
:use-text-fields use-text-fields))
rows)
(clim:formatting-row (stream)
(map nil #'(lambda (cell)
(present-sum cell stream cell-width)) column-totals)
(present-sum (spreadsheet-total spreadsheet) stream cell-width)))
(setf (spreadsheet-total spreadsheet) 0.0)
(dotimes (i ncells)
(setf (aref column-totals i) 0.0)
(dotimes (j nrows)
(incf (aref column-totals i) (aref (spreadsheet-row-cells (aref rows j)) i)))
(incf (spreadsheet-total spreadsheet) (aref column-totals i))))
spreadsheet))
References:
Main Index |
Thread Index