Welcome, Guest! Log In | Create Account

Welcome to the Visualizer project

This page describes the first Visualizer project

Steps in the project

It looks like a good way to go is to start with some simple examples, then work toward harder ones. This will be easier for you and at the same time let me develop the data structures over time, as the project proceeds.
A good way to organize the project is to do a number of smaller, mini-projects. The first is just visualizing a syntax graph for "A + B", and having it paint in the Display.
Please be aware that the syntax-graph data structures and the custom properties for EQNLang will change as more experience is gained in using them and it becomes clear that they have to be modified. This will cause the code you write to be modified, even after it is already working.

Visit this page to learn about the syntax graph

What the Visualizer does

Some examples of source code being visualized appear in this figure. Each command in EQNLang has not only a shape but "ports". Each port is either an input or an output. They are placed visually around the shape.
The Visualizer must place an expression in the position of each port. If the input position in the syntax graph is empty, then the visualizer places an empty box in that input port's position. If the input position links to another command-rooted syntax pattern, then that entire syntax-pattern goes in the input-port's position.
The plus command in "A + B" has both input ports filled, and the command has no explicit output port. By "no explicit output port" I mean that, upon evaluation, the expression will be replaced by whatever it evaluates to. An expression's visual placement implies where it's output goes to. Syntax patterns with implied output ports are placed inside the input ports of other syntax patterns.
In the expression "A + B", the input ports of the "+" are filled by the "A" and "B". These are both "Name" patterns of memProcessor type. Name patterns have no visual input ports, and implied output ports.
What this all means is that information is needed about the position of input ports for each command. This additional information is what the Visualizer will use to place the syntax-patterns.

Details of the Visualizer project

Here is what I would like (most of this is also in comments in the code):
-- The Visualizer will generate a DisplayList, which is a linked list of DisplayElements.
-- It first places a virtual shape for each syntactic element on a virtual grid, then generates a DisplayElement for each virtual shape.
-- The Visualizer doesn't know what the actual shapes are, it only knows the name of the shape and a bounding box for it. The Visualizer works with the bounding boxes.
-- The Visualizer places shapes onto a virtual grid. The grid is continuous, so each position is a float value.
-- the Display will create its own version of the virtual grid, and set "0,0" of its virtual grid to the center of its window (to start with.. the User can then pan and zoom).
-- Each syntactic element has layout information. The layout information is retrieved from the SrcHolder by asking for it.
-- The layout info is loaded from disk during initialization of the SrcHolder.
-- The layout information is a shape plus a list of ports.
-- The shape is a shape-name plus a bounding-box.
-- a bounding box consists of an origin x,y value and width plus height value.
-- The bounding box for a shape is the "minimum enclosing bounding box". The origin of the shape, when looked up, is always 0,0
-- a port has a bounding box too, but it has no shape.. instead, it's bounding box represents a constraint on how big the collection of shapes inside that port can grow.
-- The origin of a port bounding box is relative to the origin of the shape's BB (bounding box). It's as if the shape defined its own mini-grid, and the ports are placed on the shape's mini-grid. Thus, the origins of the ports are actually offsets from the origin of the shape.
-- The layout information for a "variable" that appears in the syntax-graph comes from two sources: the type of variable is sent to the SrcHolder to ask for a font plus font-size, while one of the properties attached to the syntax-graph node is a "variable name" property. The property value is sent to the SrcHolder, which sends back a character string.
-- Generate the shape's bounding box by calculating it. First look up the bounding box for each character in the string (from information about the font). Then calculate the smallest bounding box that encloses the entire string. Make the origin of the calculated enclosing bounding box be 0,0. A variable has no ports, so done.
-- do two passes when placing shapes. The first pass generates a tree of bounding boxes, the second pass scales and translates the bounding boxes, placing them onto the virtual grid.

First pass:

-- walk the syntax-graph (in a spanning tree fashion) and build up a tree of BoundingBoxTreeNode.
-- start with a root BBChildLink. Set it to be the current BBChildLink.
-- set the root of the syntax-graph to be the current syntactic element.
-- Generate a BoundingBoxTreeNode for the current syntactic element.
-- Set the link in the current parent BBChildLink to the newly created BoundingBoxTreeNode.
-- look up the type of syntactic element to get its shape info and port list.
-- If the syntactic element has ports, then make a BBChildLink for each port on the port-list. Make the BBChildLink's BB be the bounding box information that was in the port-info. This is a constraint bounding box.
-- Each port corresponds to a child in the syntax graph, go to each child and make a BoundingBoxTreeNode, connect the corresponding BBChildLink to it, and repeat the above process.
-- There are two kinds of bounding box here. One kind is the minimum size box that completely encloses a shape. The other kind is a constraint. When the second pass is performed, the shapes will be scaled, such that the shape bounding box gets as big as possible while still completely enclosed by some constraining bounding box.
-- See the comments in the skeleton code for BoundingBoxTreeNode and BBChildLink.
-- Once all the syntactic elements have been added to the bounding-box tree, go to the second pass, which performs scaling and translation of bounding boxes, which places them onto the virtual grid.

Second pass:

-- start with a default root bounding box that represents the entire graph. This is the "root" bounding box. It's origin is at 0,0 on the virtual grid.
-- this root BB is made the parent constraining BB
-- set the root node of the bounding-box tree as the current BoundingBoxTreeNode and begin:
-- <loop>
-- generate the minimum enclosing bounding box for the BoundingBoxTreeNode's shape together with all of its child nodes. Leave the BoundingBoxTreeNode's shape where it is, so the generated enclosing BB will have its origin placed relative to the shape's origin, but possibly shifted due to the ports around the shape.
-- calculate the scaling factor that will make the enclosing bounding box as large as possible while still being enclosed by the parent constraining bounding box.
-- apply the scaling factor (which moves the origins, as well as changes the sizes of the BBs)
-- calculate the translation to apply to the resized minimum enclosing BB to shift its origin to match the origin of the parent constraining BB
-- apply that translation to the shape's enclosing bounding box and each of its children's constraining bounding boxes. Those bounding boxes are now at their final placement on the virtual grid, at their final size.
-- generate the DisplayElement for the BoundingBoxTreeNode's shape, and add it to the DisplayList.
-- now, repeat the process for the contents of each child constraining BB: In turn, set the child constraining BB to be the parent constraining BB.. and set the BBChildLink's node as the current BoundingBoxTreeNode.. and go to the
-- (Note, out of interest, that as one descends the bounding-box tree, the scaling factors multiply, and translations add..)

-- When this process is complete for the entire syntax-graph, send the DisplayList to the Display.

Questions from Talk with Sunita (and answers)

What are all the meanings for the word "box"

What are the steps to getting the visual information about a syntax node

What kinds of visual information are there

Given the visual information for a node, how is it turned into DisplayElements