I'm using ltk to develop a GUI application for the Dijkstra algorithm in Common-Lisp. However, to place a node on a canvas, I need the label for it, and to do so, the execution must wait until the user enters a string (and press Return) to initiate an instance of a node, using this value. Without the listening process, the returning occurs right after the creation of the second toplevel screen.
Below is the code that executes when the user selects the "Add Node" option on a menu:
(defun node-add-mode (canvas)
(configure canvas :cursor "cross")
(bind canvas "<ButtonPress-1>"
(lambda (evt)
(let* ((pos-x (event-x evt))
(pos-y (event-y evt))
(data (read-node-data))
(node (make-instance 'node :pos (list pos-x pos-y) :data data)))
(populate-graph :node node)
(create-graph canvas *graph*)))))
The populate-graph
function just adds the created node to the actual graph, and the create-graph
function draws it on the canvas.
And this is the read-node-data
function I implemented so far:
(defun read-node-data ()
(let* ((m (make-instance 'toplevel))
(f (make-instance 'frame :master m))
(l (make-instance 'label
:master f
:text "Insert The Object Value"))
(v (make-instance 'entry
:master f
:width *entry-width*)))
(wm-title m "Entry")
(pack f)
(pack l)
(pack v)
(bind v "<Return>"
(lambda (evt)
(let ((text (text v)))
(destroy m)
text)))))
I want to return the entry text from this block of code only after the "<Return>"
event occured, to be able to pass this to the node instantiation.
Tcl has an vwait
mechanism for cases where the code needs to block on some variable's value. As far as I know, this is not available in LTK. You could use another system, like cl-async
, but maybe the simplest option is to turn your code inside-out so that it becomes event-based: build a node only when the name is known.
(defun read-node-data (continuation)
...
(bind v
"<Return>"
(lambda (evt &aux (text (text evt)))
(destroy m)
(funcall continuation text))))
And then:
(defun node-add-mode (canvas)
(configure canvas :cursor "cross")
(bind canvas "<ButtonPress-1>"
(lambda (evt)
(let ((pos-x (event-x evt))
(pos-y (event-y evt)))
(read-node-data
(lambda (data)
(let ((node (make-instance 'node
:pos (list pos-x pos-y)
:data data)))
(populate-graph :node node)
(create-graph canvas *graph*))))))))