[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Weird bug -- seen before?

In article <1994Mar7.160951.26749@aisb.ed.ac.uk>, Kim Binsted wrote:

> Hi. I didn't find this in the FAQ. Has anyone had this problem before?
> I'm trying to put up windows containing text. The chunks of text may
> vary in size, so I was using default positioning. However, default
> positioning seems to work differently (and strangely) with *slightly*
> different bits of text. 

The problem seems to be in the way in which MCL calculates the default size
of a
dialog item.

If nil arguments are given for the size and position of a dialog item, 
then MCL calculates a default size and tries to find a vacant position in
the item's containing view for a subview of that size. If it can't find a
vacant position, then it sets the position to #@(0 0).

The problem arises in the calculation of the default size: 
(from the CD-ROM sources)

(defmethod view-default-size ((dialog-item dialog-item))
  (with-focused-dialog-item (dialog-item)
    (let* ((text (dialog-item-text dialog-item)))
      (make-point (with-pstrs ((sp text))
                    (+ (dialog-item-width-correction dialog-item)
                       (#_StringWidth sp)))
                  (multiple-value-bind (ascent descent widmax leading)    
                    (declare (ignore widmax))
                    (* (1+ (count #\return text))
																											(+ ascent descent leading)))))))

This calculates the height OK (by multiplying 1+ the number of returns by
the line height), but uses #_StringWidth to calculate the width, which does
not take into account that the text might be broken by returns; it's as if
the whole text were on one line.

So in Kim's example, the addition of the extra two letters did not increase
actual width of the return-broken block of text, but it did increase the
StringWidth of the dialog-item-text beyond that available in the dialog.
Hence the position of the dialog item reverted to #@(0 0), overwriting the
first item.

To fix this, you'd have to calculate the size yourself, or re-write
view-default-size using something like:

(Quick-and-dirty, probably neither robust not efficient)

(defun lines (string)
  (let ((break (position #\return string)))
    (if (not break)
      (list string)
      (cons (subseq string 0 break) (lines (subseq string (1+ break)))))))
(defun widest-line (string)
  (apply #'max (mapcar #'string-width (lines string))))

(defclass block-text-dialog-item (static-text-dialog-item) ())

(defmethod view-default-size ((dialog-item block-text-dialog-item))
  (with-focused-dialog-item (dialog-item)
    (let* ((text (dialog-item-text dialog-item)))
      (make-point (+ (dialog-item-width-correction dialog-item) 
                     (widest-line text))
                  (multiple-value-bind (ascent descent widmax leading) 
                    (declare (ignore widmax))
                    (* (1+ (count #\return text))
                       (+ ascent descent leading)))))))

=== John R. Gersh                John_Gersh@aplmail.jhuapl.edu           
=== The Johns Hopkins University Applied Physics Laboratory
=== Laurel, MD 20723                           +1(301)953-5503