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

Re: Hypertext in MCL?



In article <1994May16.201458.16399@midway.uchicago.edu>,
fensterm@cs.uchicago.edu (Kurt D. Fenstermacher) wrote:

> I'd like to implement a "hypertext" system in MCL.  The program I'm
> working on involves retrieving recipes from a database, given a user
> request in English (e.g. "I'm looking for a recipe for a Thai peanut
> salad dressing, which is spicy, but also a little sour.")  After I've
> recalled the appropriate recipes, I'd like the user to be able to click
> on keywords (e.g. what in the recipe made the program conclude that it
> was sour?) in the recipe text, and get an explanation of the program's
> "chain of thought.".
> 
> At the moment the parse code which processes the recipes produces
> embedded codes in the text to indicate these keywords.  Currently, I
> can display the plain text using a static text dialog item.  But how
> can I turn a plain text item (i.e. a word) into a button, indicated by
> a different foreground/background color?
> 
> One solution seems to be to calculate (based on window size, font size,
> etc.) the position of the word in the dialog item, and then draw a
> button with the word/phrase as the button's text, in the appropriate
> location, right over the existing word.  But this calucation would be
> complicated by such things as proportional fonts, resized windows, etc.
>  Are there higher-level functions to do implement hypertext more
> cleanly?

There's a method called fred-point-position, which returns the position in
a fred-item's buffer nearest to a point.  For example if you click on a
character, and that character is the 5th in the fred-buffer,
fred-point-position of the point of that click would return 5.  Of course,
fred-point-position probably is undefined for static-text-dialog-items (try
it and see!).  I'd suggest specializing a fred-something
(fred-dialog-item?) for your purposes.

It seems like you could surround this with a function to return the word
that the click was in (parse for whitespace), returning (buffer-substring
...) and interface that to your database of word-meanings or uses.  This
behavior could all be implemented in the view-click-event-handler for your
class.  If you make your class' view-key-event-handler nil, and the
view-click-event-handler nil except for this hypertexting thing and use
view-cursor to make the cursor appropriate, it should act just like a
static-text-dialog-item.

Does this sound like a solution to your problem?  If you're confused by the
CLOS-ish object-oriented stuff, check out a friend's copy of Sonya E.
Keene's Object-Oriented Programming in Common Lisp.  Certainly if you have
any questions, feel free to ask me -- and, of course, definitely let me
know whether this was helpful to you.  It doesn't seem hard to implement at
all, lots easier that the button stuff...

Try something like this...

(defclass hyper-fred (fred-dialog-item)        ;; inherits fredness...
	())

(defmethod view-key-event-handler ((self hyper-fred) char)
	())                                      ;; deaf and dumb to keystrokes

(defmethod view-click-event-handler ((self hyper-fred) where)
 (when (and *hyperactive* (double-click-p)
        (not (> *multi-click-count* 2)))  ;; guard against additional
clicking
    (act-on (current-word self (fred-point-position self where)))))

(defun current-word (hyper-fred position)      ;; returns string-- nearest
word
   (let* ((hyper-fred-buffer (fred-buffer hyper-fred))
           (begin-word
            (1+ (or (buffer-string-pos hyper-fred-buffer " " 
                       :start 0 :end position :from-end t) -1)))
           (end-word
             (or (buffer-string-pos hyper-fred-buffer " " :start position)
                 (buffer-size (fred-buffer hyper-fred)))))
      (set-selection-range hyper-fred begin-word end-word)
      (buffer-substring (fred-buffer hyper-fred) begin-word  end-word)))

(defun act-on (string)
   (format t "~%You clicked on ~s" string))

(defvar win (make-instance 'window :view-size #@(400 15)))
(defvar piper                  ;; the hyperfred!
   (make-instance 'hyper-fred
       :view-size #@(400 15)
       :dialog-item-text "This is a very fine day to be living on the south
side of chicago."))
(add-subviews win piper)
(defvar *hyperactive* t)
(set-selection-range piper 0 0)

> Thanks for your help.
> 
> Kurt D. Fenstermacher
> Artificial Intelligence Laboratory
> University of Chicago

welcome.

chris

-- 
Chris Crone
Northwestern University, School of Education and Social Policy
chrispi@merle.acns.nwu.edu