Lisp HUG Maillist Archive

Nested drawn layouts

Hello dear LispWorks users,

I want to draw a diagram for a tree.  There are many ways to display
trees, and I have a special representation I want to implement.  As an
example I will provide a tree and how it should look like when
displalyed.

(root (foo (leaf-1))
      (leaf-2))

Eeach node is represented as a list whose FIRST element is the node
name and REST are its children.

Now, the drawing:

+-root-------------------+
|                        |
|  +-foo------+          |
|  |          |          |
|  |  leaf-1  |  leaf-2  |
|  |          |          |
|  +----------+          |
|                        |
+------------------------+


What we see above is:

 - Leaf nodes all appear vertically aligned.
 - For nodes with children the frames are being drawn.
 - The frame drawing must be customizeable (i.e., the color of the
   border and fill) and also interactable.

At the moment I use PINBOARD-LAYOUT with RECTANGLES as the frames, and
ITEM-PINBOARD-OBJECTs for the leaf nodes.  I do layouting manually --
when the diagram is being drawn, it first needs the PANE to draw onto
in order to have a way to determine string metrics.  The process then
recursively walks the tree and calculates the coordinates and
dimensions for all nodes in the tree.

But this approach does not work if the tree branches are of different
depth (in this case the rectangle for shallower branch will have
smaller height than the next rectangle for a branch with higher
depth).

All this mess could be easily solvable by using layouts.  The only
problem (for me) is that I don't know how to "draw the layouts".  Two
solutions that I could come up with are:

 1. Define a class that inherits from both a LAYOUT and a RECTANGLE.

   (defclass foo (capi:row-layout capi:rectangle) ())

   (capi:contain
    (make-instance
     'capi:pinboard-layout
     :description
     (list
      (make-instance
       'foo
       :description
       (list
        (make-instance 'capi:item-pinboard-object :text "foo")
        (make-instance 'capi:item-pinboard-object :text "bar"))))))

    This breaks when trying to CALCULATE-CONSTRAINTS for foo (the
    error is "Error: NIL is not of type ARRAY.").

 2. Use a SIMPLE-LAYOUT with the first level child being something
    that can draw itself (i.e. RECTANGLE), and then have that child
    have the next level layout as a child.  But this I don't know how
    to do...

What would be the right way to do this?  Note that the nodes will get
more complicated that that -- that's the reason why the layouts should
be used to do this.  For instance, leaf nodes could be COLUMN-LAYOUTS
with more than one thing in it.  But the nested-box nature of the
diagram will stay.

-- 
Janis Dzerins

  If million people say a stupid thing -- it's still a stupid thing.


Re: Nested drawn layouts

Janis Dzerins wrote:

> At the moment I use PINBOARD-LAYOUT with RECTANGLES as the frames, and
> ITEM-PINBOARD-OBJECTs for the leaf nodes.  I do layouting manually --
> when the diagram is being drawn, it first needs the PANE to draw onto
> in order to have a way to determine string metrics.  The process then
> recursively walks the tree and calculates the coordinates and
> dimensions for all nodes in the tree.
>
> But this approach does not work if the tree branches are of different
> depth (in this case the rectangle for shallower branch will have
> smaller height than the next rectangle for a branch with higher
> depth).

Sounds to me like you need to 'hook into the layout protocol' more fully
than you've done so far.  I think you'll need to define your own layout
class with DEFINE-LAYOUT and then write your own methods for
INTERPRET-DESCRIPTION, CALCULATE-CONSTRAINTS and CALCULATE-LAYOUT.

> All this mess could be easily solvable by using layouts.  The only
> problem (for me) is that I don't know how to "draw the layouts".

I wouldn't 'draw the layouts', but have the layout contain some panes
(or pinboard-objects) that can be drawn.

> Note that the nodes will get more complicated that that -- that's the
> reason why the layouts should be used to do this.  For instance, leaf
> nodes could be COLUMN-LAYOUTS with more than one thing in it.  But the
> nested-box nature of the diagram will stay.

Sounds like fun.  If you need more help with this, let me know.

Arthur Lemmens


Updated at: 2020-12-10 08:48 UTC