PlotGraph.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Barth, August 25, 1986 12:11:02 pm PDT
Christian LeCocq October 17, 1986 4:27:22 pm PDT
DIRECTORY
Imager, Vector2, ViewerClasses;
PlotGraph: CEDAR DEFINITIONS = BEGIN
Theory
This interface is used to display a collection of graphs on a collection of axis within one viewer. A graph is a set of point pairs relating x and y values. Color is used to differentiate multiple graphs on a single axis. Line styles can be used to simulate color on a black and white display. The axis are laid out within the viewer in a single vertical column. The plot coordinate system, which has [0.0, 0.0] in the lower left corner and [1.0, 1.0] in the upper right corner, is used to specify locations which are not relative to an axis.
This interface provides a procedural mechanism for enumerating the points of a graph so that client code can make appropriate space-time tradeoffs. Note that this burdens the client with enforcing synchronization constraints.
Types
ROPE: TYPE = Imager.ROPE;
VEC: TYPE = Imager.VEC; --maps into Vector2.VEC TYPE = RECORD [x, y: REAL]
Rectangle: TYPE = Imager.Rectangle; -- x, y, w, h
AxisList: TYPE ~ LIST OF Axis;
GraphList: TYPE ~ LIST OF Graph;
Viewer: TYPE ~ ViewerClasses.Viewer;
WorldRectangle: Rectangle = [0.0, 0.0, 0.0, 0.0];
Plot:
TYPE =
REF PlotRec;
PlotRec:
TYPE =
RECORD [
private: PlotGraphPrivate ← NIL,
name: REF READONLY ROPE ← NIL,
selection:
LIST
OF
REF
ANY ←
NIL,
Union[Axis, Graph, GraphPoint, PlotText]
axis: AxisList ← NIL, -- in order from bottom to top
texts: LIST OF PlotText ← NIL,
lowerBounds: VEC, -- Min all X, Min all Y,
upperBounds: VEC, -- Max all X, Max all Y over all graphs
eventProc: EventProc ← NIL, -- To interprete events unknown by the NotifyProc
data: REF ANY ← NIL -- Client data.
];
EventProc:
TYPE =
PROC [
plot: Plot, -- the clicked Plot
axis: Axis, -- the clicked Axis (could be # of the selected Axis)
pos: VEC, -- client coordinates of the mouse, if available.
event: ATOM -- Atom specified by the Tip table
];
PlotGraphPrivate: TYPE = REF PlotGraphPrivateRec;
PlotGraphPrivateRec:
TYPE =
RECORD [
viewer: Viewer, -- the Viewer used for the display
locked: BOOL ← FALSE, -- the Plot is protected through a CONDITION,
unlocked: CONDITION -- rather than through a monitor lock.
];
Axis:
TYPE =
REF AxisRec;
AxisRec:
TYPE =
RECORD[
graphs: GraphList ← NIL,
bounds: Rectangle,
name: ROPE ← NIL,
style: DrawingStyle ← analog,
maxChars: NAT ← 8, -- used to determine the heigth of the hexaV style row
axisData: ARRAY XY OF AxisData];
AxisData:
TYPE =
RECORD[
ticks: REAL ← 1.0,
visible: BOOL ← TRUE, -- draw axis itself
grid: BOOL ← FALSE];
DrawingStyle:
TYPE = {
analog, -- draws a segment between each point
hexaH, -- writes the rope provided or the hexadecimal value of y horizontally
hexaV -- writes the rope provided or the hexadecimal value of y vertically
};
GraphClass:
TYPE =
REF GraphClassRec;
GraphClassRec:
TYPE =
RECORD[
insert: GraphProc ← NIL,
delete: GraphProc ← NIL,
enumerate: GraphEnumerateProc ← NIL];
GraphProc:
TYPE =
PROC [graph: Graph, x, y:
REAL];
GraphEnumerateProc:
TYPE =
PROC [plot: Plot, graph: Graph, bounds: Rectangle, eachPoint: PointProc, data:
REF
ANY ←
NIL]
RETURNS [invalidEnumeration:
BOOL ←
FALSE];
The bounding rectangle is a hint to the enumeration indicating which points will really be used. eachPoint must be called for each of the points in the graph which bracket or are contained in the bounds. Points outside the bounds may also be passed to eachPoint. The implementation does a moveto for the first point and a drawto for the rest of them. If invalidEnumeration is TRUE this indicates that the data in the backing data structure has changed in such a way as to invalidate the points already enumerated. The axis will be erased and all of the graphs on the axis will be redrawn. data is a field wich is transmited to each eachPoint call.
PointProc:
TYPE =
PROC [x, y:
REAL, data:
REF
ANY ←
NIL, rope:
ROPE ←
NIL]
RETURNS [quit:
BOOL ←
FALSE];
x and y are, of course, relative to the axis upon which the graph is currently being drawn. If rope is specified then rope will be printed on the "hexa" style axis at location [x, 0.0]. If not, the value printed will be Convert.RopeFromInt[Real.Fix[y], 16, FALSE] i.e. the transcription of y in hexadecimal; rope is ignored on analog axis. If quit is true then the enumeration should be stopped.
Graph:
TYPE =
REF GraphRec;
GraphRec:
TYPE =
RECORD[
class: GraphClass ← NIL,
data: REF ANY ← NIL,
name: ROPE ← NIL,
mark: BOOL ← FALSE];
GraphPoint: TYPE = REF GraphPointRec;
GraphPointRec:
TYPE =
RECORD[
graph: Graph,
x, y: REAL];
PlotText:
TYPE =
REF PlotTextRec;
PlotTextRec:
TYPE =
RECORD[
contents: ROPE ← NIL,
wrt: Axis ← NIL, -- if nil then wrt entire plot
bounds: Rectangle, -- w or h = 0.0 mean use bounding box of ROPE
rotation: REAL ← 0.0, -- angle of rotation, ccw, in degrees
justifyX: JustifyX ← left,
justifyY: JustifyY ← bottom];
JustifyX: TYPE = {left, center, right};
JustifyY: TYPE = {top, center, bottom};
Operations
CreatePlot:
PROC [name:
ROPE ←
NIL]
RETURNS [plot: Plot];
Creates a new viewer. The name of the plot is immutable.
Client must lock a plot prior to changing the data structures so that interactive updates will be suspended.
LockPlot:
PROC [plot: Plot];
UnlockPlot:
PROC [plot: Plot];
RefreshPlot:
PROC [plot: Plot, axis: AxisList ←
NIL, graphs: GraphList ←
NIL, within: Rectangle ← WorldRectangle, eraseFirst:
BOOL ←
FALSE];
Call this to update the display. If either graphs or axis are not NIL then only the indicated graph and/or axis will be refreshed. within will be passed to the GraphProcs as the bounding rectangle and so should include the point to which a moveto must be done to setup for drawing. Generally eraseFirst should only be TRUE if previously enumerated points have been changed.
DeletePlot:
PROC [plot: Plot];
Makes the viewer disappear.
Interaction
General
DeleteSelection:
PROC [plot: Plot];
Delete the current selection.
Axis
SelectAxis:
PROC [plot: Plot, axis: Axis];
Deselect all current selections and then select the axis.
AddAxis:
PROC [plot: Plot, axis: Axis];
Add the axis to the selection.
GetSelectedAxis:
PROC [plot: Plot]
RETURNS [axis: Axis];
Returns last selected axis.
GetSelectedAxisList:
PROC [plot: Plot]
RETURNS [axisList:
LIST
OF Axis];
Returns currently selected axis.
InsertAxis: PROC [plot: Plot, axis, after: Axis];
DeleteAxis: PROC [plot: Plot, axis: Axis];
MoveAxis: PROC [plot: Plot, axis, after: Axis];
XChangeAxis: PROC [plot: Plot, axis1, axis2: Axis];
CopyAxis:
PROC [axis: Axis]
RETURNS [duplicate: Axis];
Various proc to edit a plot Axis List. DO NOT INSERT THE SAME AXIS TWICE (even in two plots).
Graph NYI !!!
SelectGraph:
PROC [plot: Plot, graph: Graph];
Deselect all current selections and then select the graph.
AddGraph:
PROC [plot: Plot, graph: Graph];
Add the graph to the selection.
GetSelectedGraph:
PROC [plot: Plot]
RETURNS [graph: Graph];
Returns currently selected graph. Complains on terminal if none or more than one selected.
GetSelectedGraphList:
PROC [plot: Plot]
RETURNS [graphList:
LIST
OF Graph];
Returns currently selected graphs. Complains on terminal if none selected or some selection is not a graph.
Graph Point NYI !!!
SelectPoint:
PROC [plot: Plot, point: GraphPoint];
Deselect all current selections and then select the given point on the graph.
AddPoint:
PROC [plot: Plot, point: GraphPoint];
Add the point to the selection.
GetSelectedPoint:
PROC [plot: Plot]
RETURNS [point: GraphPoint];
Returns currently selected point. Complains on terminal if none or more than one selected.
GetSelectedPointList:
PROC [plot: Plot]
RETURNS [pointList:
LIST
OF GraphPoint];
Returns currently selected points. Complains on terminal if none selected or some selection is not a point.
InsertPoint:
PROC [graph: Graph, x, y:
REAL]
RETURNS [ok:
BOOL ←
TRUE];
Adds the point to the graph. Not all classes support insertion and so ok may be false. An appropriate complaint will be sent to the terminal.
DeletePoint:
PROC [graph: Graph, x, y:
REAL]
RETURNS [ok:
BOOL ←
TRUE];
Deletes the point from the graph. Not all classes support deletion and so ok may be false. An appropriate complaint will be sent to the terminal.
Text NYI !!!
SelectText:
PROC [plot: Plot, text: PlotText];
Deselect all current selections and then select the text.
AddText:
PROC [plot: Plot, text: PlotText];
Add the text to the selection.
GetSelectedText:
PROC [plot: Plot]
RETURNS [text: PlotText];
Returns currently selected text. Complains on terminal if none or more than one selected.
GetSelectedTextList:
PROC [plot: Plot]
RETURNS [textList:
LIST
OF PlotText];
Returns currently selected texts. Complains on terminal if none selected or some selection is not a text.
MoveText:
PROC [plot: Plot, text: PlotText, position: Imager.
VEC];
Moves the text.
RotateText:
PROC [plot: Plot, text: PlotText, alpha:
REAL];
Rotates the text.
END.
Christian LeCocq August 11, 1986 5:37:16 pm PDT
Changed the Plot.name to be a REF READONLY ROPE to take care of the instability of life. I need to know the name at viewer creation.
changes to: Plot.name, CreatePlot[name]
added a field named "data" to the enumeration proc to ease the sharing of the "leaves" of the call tree beetween the screen procs and the interpress procs and avoid global variables.
changes to: GraphClass
Christian LeCocq October 17, 1986 3:26:07 pm PDT
Added the possibility to send back to the client the events notified to the viewer but not understood by its NotifyProc. Added the lock mechanism to Plot.private., InsertAxis, DeleteAxis, MoveAxis, XChangeAxis, CopyAxis