seanhalle@6: seanhalle@6:
seanhalle@6:seanhalle@6:
This file describes the first Visualizer project
seanhalle@6:==========
seanhalle@6:Steps in the project
seanhalle@6:It looks like a good way to go is to start with some simple examples, then seanhalle@6: work toward harder ones. This will be easier for you and at the same time let seanhalle@6: me develop the data structures over time, as the project proceeds.
seanhalle@6:A good way to organize the project is to do a number of smaller, mini-projects. seanhalle@6: The first is just visualizing a syntax graph for "A + B", and having it paint seanhalle@6: in the Display.
seanhalle@6:Please be aware that the syntax-graph data structures and the custom properties seanhalle@6: for EQNLang will change as more experience is gained in using them and it becomes seanhalle@6: clear that they have to be modified. This will cause the code you write to be seanhalle@6: modified, even after it is already working.
seanhalle@6:==========
seanhalle@6:Theory behind the syntax graph
seanhalle@6:The theory behind the way I want to do the syntax graph will probably seem seanhalle@6: a bit "strange" to you at first, especially if you have any experience with seanhalle@6: compilers. It's a bit abstract; the reason is to allow the same data structures seanhalle@6: to be re-used for any CTOS language that can be designed.
seanhalle@6:The best file to look at first is the "SyntacticElement.java" file, which has seanhalle@6: a very long comment that talks a bit about the thinking behind the data structures. seanhalle@6:
seanhalle@6:To summarize the idea behind the syntax data structures: Syntax is a pattern seanhalle@6: that correlates to the visual pattern that humans look at. Each element of the seanhalle@6: visual pattern has a corresponding element in the syntactic pattern.
seanhalle@6:So, that is the only thing that the data structures need to support: an element seanhalle@6: in the syntax for each visual cue. Visual cues are shapes and physical position. seanhalle@6: Physical position determines which visual pattern a given shape belongs to (more seanhalle@6: on this in the comment).
seanhalle@6:So, there are only three kinds of thing in the syntax graph:
seanhalle@6:Syntactic element
seanhalle@6:Syntactic link
seanhalle@6:Syntactic property
seanhalle@6:plus, a set of property-types, and a set of property values, for links and seanhalle@6: elements
seanhalle@6:To summarize the data structures.. I have only two main syntactic data types: seanhalle@6: elements and links. Each of these has a list of properties attached to it.
seanhalle@6:The element properties state what kind of element it is (for EQNLang), such seanhalle@6: as a root of a syntactic pattern, and/or a structural element, and/or a shape seanhalle@6: containing element.
seanhalle@6:The link properties state what kind of link it is (for EQNLang) such as a "back" seanhalle@6: link to the root of a syntactic pattern, or a link that indicates that data seanhalle@6: flows from one syntactic pattern to another..
seanhalle@6:===========
seanhalle@6:Property Names and Property Values
seanhalle@6:I have decided to make all property names and all property values be integers. seanhalle@6: I have included, in "EQNLangSyntaxSpecialization" a bunch of files that have seanhalle@6: static constants in them. These constants define the property names and property seanhalle@6: values. I also have a skeleton of how to use the properties in EQNLangSrcVisualizer.java seanhalle@6:
seanhalle@6:That file shows how to use the constants inside switch statements. The switch seanhalle@6: statements steer, to code that takes some action on the DisplayList. Each piece seanhalle@6: of code is only invoked if some set of things is true. For example, the method seanhalle@6: "foobar" is called when "Currently processing a SyntacticElement, and it is seanhalle@6: a command-type" is true, and only when that is true.
seanhalle@6:If you want to use a different code structure, write me an e-mail that makes seanhalle@6: a case for why you view the alternative structure as better.
seanhalle@6:You will find in EQNLangSrcHolder a test syntax graph that has been built in seanhalle@6: the code. This is the first syntax graph that you will visualize.
seanhalle@6:The next project after this one will add multiple syntactic patterns, positioning seanhalle@6: of them, and scaling of them. For now, just a single command with two variables.
seanhalle@6:============
seanhalle@6:What the Visualizer does
seanhalle@6:Each command in EQNLang has not only a shape but "ports". Each port is either seanhalle@6: an input or an output. They are placed visually around the shape.
seanhalle@6:The Visualizer must place an expression in the position of each port. If the seanhalle@6: input position in the syntax graph is empty, then the visualizer places an empty seanhalle@6: box in that input port's position. If the input position links to another command-rooted seanhalle@6: syntax pattern, then that entire syntax-pattern goes in the input-port's position. seanhalle@6:
seanhalle@6:The plus command in "A + B" has both input ports filled, and the command has seanhalle@6: no explicit output port. By "no explicit output port" I mean that, upon evaluation, seanhalle@6: the expression will be replaced by whatever it evaluates to. An expression's seanhalle@6: visual placement implies where it's output goes to. Syntax patterns with implied seanhalle@6: output ports are placed inside the input ports of other syntax patterns.
seanhalle@6:In the expression "A + B", the input ports of the "+" are filled by the "A" seanhalle@6: and "B". These are both "Name" patterns of memProcessor type. Name patterns seanhalle@6: have no visual input ports, and implied output ports.
seanhalle@6:What this all means is that information is needed about the position of input seanhalle@6: ports for each command. This additional information is what the Visualizer will seanhalle@6: use to place the syntax-patterns.
seanhalle@6:==========
seanhalle@6:Details of the Visualizer project
seanhalle@6:Here is what I would like (most of this is also in comments in the code):
seanhalle@6:-- The Visualizer will generate a DisplayList, which is a linked list of DisplayElements. seanhalle@6:
seanhalle@6:-- It first places a virtual shape for each syntactic element on a virtual seanhalle@6: grid, then generates a DisplayElement for each virtual shape.
seanhalle@6:-- The Visualizer doesn't know what the actual shapes are, it only knows the seanhalle@6: name of the shape and a bounding box for it. The Visualizer works with the bounding seanhalle@6: boxes.
seanhalle@6:-- The Visualizer places shapes onto a virtual grid. The grid is continuous, seanhalle@6: so each position is a float value.
seanhalle@6:-- the Display will create its own version of the virtual grid, and set "0,0" seanhalle@6: of its virtual grid to the lower left corner of its window (to start with.. seanhalle@6: the User can then pan and zoom).
seanhalle@6:-- Each syntactic element has associated layout information that is looked seanhalle@6: up via some mechanism.
seanhalle@6:-- The look-up info is loaded from disk during initialization of the Visualizer. seanhalle@6:
seanhalle@6:-- The layout information is a shape plus a list of ports.
seanhalle@6:-- The shape is a shape-name plus a bounding-box.
seanhalle@6:-- a bounding box consists of an origin x,y value and width plus height value.
seanhalle@6:-- The bounding box for a shape is the "minimum enclosing bounding box". The seanhalle@6: origin of the shape, when looked up, is always 0,0
seanhalle@6:-- a port has a bounding box too, but it has no shape.. instead, it's bounding seanhalle@6: box represents a constraint on how big the collection of shapes inside that seanhalle@6: port can grow.
seanhalle@6:-- The origin of a port bounding box is relative to the origin of the shape's seanhalle@6: BB (bounding box). It's as if the shape defined its own mini-grid, and the ports seanhalle@6: are placed on the shape's mini-grid. Thus, the origins of the ports are actually seanhalle@6: offsets from the origin of the shape.
seanhalle@6:-- The layout information for a "variable" in the syntax-graph comes from two seanhalle@6: sources: the type of variable is used to look up a font plus font-size, while seanhalle@6: the syntax-graph node has an attached text-string as a property-value.
seanhalle@6:-- Generate the shape's bounding box by calculating it. First look up the bounding seanhalle@6: box for each character in the string (from information about the font). Then seanhalle@6: calculate the smallest bounding box that encloses the entire string. Make the seanhalle@6: origin of the calculated enclosing bounding box be 0,0. A variable has no ports, seanhalle@6: so done.
seanhalle@6:-- do two passes when placing shapes. The first pass generates a tree of bounding seanhalle@6: boxes, the second pass scales and translates the bounding boxes, placing them seanhalle@6: onto the virtual grid.
seanhalle@6:seanhalle@6:
First pass:
seanhalle@6:-- walk the syntax-graph (in a spanning tree fashion) and build up a tree of seanhalle@6: BoundingBoxTreeNode.
seanhalle@6:-- start with a root BBChildLink. Set it to be the current BBChildLink.
seanhalle@6:-- set the root of the syntax-graph to be the current syntactic element.
seanhalle@6:-- Generate a BoundingBoxTreeNode for the current syntactic element.
seanhalle@6:-- Set the link in the current parent BBChildLink to the newly created BoundingBoxTreeNode. seanhalle@6:
seanhalle@6:-- look up the type of syntactic element to get its shape info and port list. seanhalle@6:
seanhalle@6:-- If the syntactic element has ports, then make a BBChildLink for each port seanhalle@6: on the port-list. Make the BBChildLink's BB be the bounding box information seanhalle@6: that was in the port-info. This is a constraint bounding box.
seanhalle@6:-- Each port corresponds to a child in the syntax graph, go to each child and seanhalle@6: make a BoundingBoxTreeNode, connect the corresponding BBChildLink to it, and seanhalle@6: repeat the above process.
seanhalle@6:-- There are two kinds of bounding box here. One kind is the minimum size box seanhalle@6: that completely encloses a shape. The other kind is a constraint. When the second seanhalle@6: pass is performed, the shapes will be scaled, such that the shape bounding box seanhalle@6: gets as big as possible while still completely enclosed by some constraining seanhalle@6: bounding box.
seanhalle@6:-- See the comments in the skeleton code for BoundingBoxTreeNode and BBChildLink. seanhalle@6:
seanhalle@6:-- Once all the syntactic elements have been added to the bounding-box tree, seanhalle@6: go to the second pass, which performs scaling and translation of bounding boxes, seanhalle@6: which places them onto the virtual grid.
seanhalle@6:seanhalle@6:
Second pass:
seanhalle@6:-- start with a default root bounding box that represents the entire graph. seanhalle@6: This is the "root" bounding box. It's origin is at 0,0 on the virtual grid. seanhalle@6:
seanhalle@6:-- this root BB is made the parent constraining BB
seanhalle@6:-- set the root node of the bounding-box tree as the current BoundingBoxTreeNode seanhalle@6: and begin:
seanhalle@6:-- <loop>
-- generate the minimum enclosing bounding box for the BoundingBoxTreeNode's seanhalle@6: shape together with all of its child nodes. Leave the BoundingBoxTreeNode's seanhalle@6: shape where it is, so the generated enclosing BB will have its origin placed seanhalle@6: relative to the shape's origin, but possibly shifted due to the ports around seanhalle@6: the shape.
seanhalle@6:-- calculate the scaling factor that will make the enclosing bounding box as seanhalle@6: large as possible while still being enclosed by the parent constraining bounding seanhalle@6: box.
seanhalle@6:-- apply the scaling factor (which moves the origins, as well as changes the seanhalle@6: sizes of the BBs)
seanhalle@6:-- calculate the translation to apply to the resized minimum enclosing BB to seanhalle@6: shift its origin to match the origin of the parent constraining BB
seanhalle@6:-- apply that translation to the shape's enclosing bounding box and each of seanhalle@6: its children's constraining bounding boxes. Those bounding boxes are now at seanhalle@6: their final placement on the virtual grid, at their final size.
seanhalle@6:-- generate the DisplayElement for the BoundingBoxTreeNode's shape, and add seanhalle@6: it to the DisplayList.
seanhalle@6:-- now, repeat the process for the contents of each child constraining BB:
seanhalle@6: In turn, set the child constraining BB to be the parent constraining BB.. and
seanhalle@6: set the BBChildLink's node as the current BoundingBoxTreeNode.. and go to the
seanhalle@6:
-- (Note, out of interest, that as one descends the bounding-box tree, the seanhalle@6: scaling factors multiply, and translations add..)
seanhalle@6:seanhalle@6:
-- When this process is complete for the entire syntax-graph, send the DisplayList seanhalle@6: to the Display.
seanhalle@6: seanhalle@6: