<> <> <> DIRECTORY Convert USING [RopeFromInt], Graph USING [CaretIndex, ColorIndex, Entity, FontIndex, EntityList, EntityRec, NumberOfColors, NumberOfFonts, ROPE, Text, TextRec, Texts, UnitLineWidth, ValueList, Viewer, XY], GraphCarets USING [Move, TurnOff, TurnOn], GraphConvert USING [RopeOfSlope, ValueListFromRope], GraphCleanUp USING [CleanUpVL], GraphPrivate USING [AddEntityButton, AddTextButton, EntityHashSize, GraphAtomProc, GraphHandle, PaintAction, PaintAll, PaintEntity, PaintGrids, PaintTarget, PaintText, systemColor], GraphUtil USING [BlinkMsg, EntityFromId, GetIntField, GetRealField, InitSegAll, RaiseError, RealToScreenI, SetColor, TextFromId, UpdateSegAll, UpdateSegEnd], Imager USING [Error], ImagerFont USING [Find, Font, Scale], Rope USING [Cat, Concat], VFonts USING [EstablishFont], ViewerTools USING [GetContents, SetContents]; GraphUpdate: CEDAR PROGRAM IMPORTS Convert, GraphCarets, GraphCleanUp, GraphConvert, GraphPrivate, GraphUtil, Imager, ImagerFont, Rope, VFonts, ViewerTools EXPORTS GraphPrivate = { OPEN Graph, GraphPrivate, GraphUtil; Update: PUBLIC GraphAtomProc = { <> <> IF handle # NIL THEN IF handle.controller # NIL THEN { OPEN handle; msg: ROPE; i: INT; -- r: REAL; SELECT atom FROM $Divisions => UpdateDivisions[handle]; $Bounds => UpdateBounds[handle]; $Carets => UpdateCarets[handle]; $Targets => UpdateTargets[handle]; $Grids => UpdateGrids[handle]; $Color => { [msg, i] _ GetIntField[controller.colorIndex]; IF msg = NIL THEN IF i IN ColorIndex THEN UpdateColor[handle, i] ELSE BlinkMsg[Rope.Cat[ "Index must be in [0..", Convert.RopeFromInt[NumberOfColors], ")"]]; }; $Font => { [msg, i]_ GetIntField[controller.fontIndex]; IF msg = NIL THEN IF i IN FontIndex THEN UpdateFont[handle, i] ELSE BlinkMsg[Rope.Cat[ "Index must be in [0..", Convert.RopeFromInt[NumberOfFonts], ")"]]; }; $Text => { [msg, i] _ GetIntField[controller.textId]; IF msg = NIL THEN { text: Text _ TextFromId[handle.allTexts, i]; UpdateText[handle, text, i]; -- text = nil => add it. }; }; $XEntry => UpdateX[handle]; $Entity => { [msg, i] _ GetIntField[controller.entityId]; IF msg = NIL THEN { entity: Entity _ EntityFromId[entityHash, i]; UpdateEntity[handle, entity, i]; }; }; <<$CurveGroup => {>> <<[msg, i] _ GetIntField[controller.entityId];>> <> <> <> <<};>> <<};>> <<$Crosssection => {>> <<[msg, r] _ GetRealField[controller.entityId];>> <> <<};>> ENDCASE => RaiseError[$UnknownAtom, "in Update"]; }; }; -- Update UpdateDivisions: PROC[handle: GraphHandle] = { OPEN handle; graph.auto[divisions] _ controller.auto[divisions]; graph.division[x] _ UpdateFromIntField[controller.divX, graph.division[x]]; graph.division[y] _ UpdateFromIntField[controller.divY, graph.division[x]]; IF graph.division[x] < 1 OR graph.division[y] < 1 THEN BlinkMsg["x or y divisions < 1."] ELSE IF chart.viewer # NIL THEN PaintAll[handle, TRUE]; -- paint everything. }; -- SetDivisionFields UpdateBounds: PROC[handle: GraphHandle] = { OPEN handle; graph.auto[bounds] _ controller.auto[bounds]; graph.bounds _ [ xmin: UpdateFromRealField[controller.xmin, graph.bounds.xmin], ymin: UpdateFromRealField[controller.ymin, graph.bounds.ymin], xmax: UpdateFromRealField[controller.xmax, graph.bounds.xmax], ymax: UpdateFromRealField[controller.ymax, graph.bounds.ymax] ]; IF NOT graph.auto[bounds] AND (graph.bounds.xmin <= graph.bounds.xmax OR graph.bounds.ymin <= graph.bounds.ymax) THEN BlinkMsg["Illegal bounds. (xmin <= xmax or ymin <= ymax.)"] ELSE IF chart.viewer # NIL THEN PaintAll[handle, TRUE]; }; -- UpdateBounds UpdateCarets: PROC[handle: GraphHandle] = { OPEN handle; UpdateCaret: PROC[index: CaretIndex] = { vx: Viewer _ controller.caretPlace[index][x]; vy: Viewer _ controller.caretPlace[index][y]; rx: REAL _ UpdateFromRealField[vx, graph.caret[index].place.x]; ry: REAL _ UpdateFromRealField[vy, graph.caret[index].place.y]; sx: INTEGER _ RealToScreenI[handle, rx, x]; sy: INTEGER _ RealToScreenI[handle, ry, y]; graph.caret[index]^ _ [on: controller.caretOn[index], place: [rx, ry]]; IF chart.viewer # NIL THEN { GraphCarets.Move[handle, sx, sy, index]; IF graph.caret[index].on THEN GraphCarets.TurnOn[handle, index] ELSE GraphCarets.TurnOff[handle, index]; <> }; }; -- UpdateCaret FOR i: CaretIndex IN CaretIndex DO UpdateCaret[primary] ENDLOOP; ViewerTools.SetContents[controller.slope, IF (graph.showSlope _ controller.slopeOn) THEN GraphConvert.RopeOfSlope[graph.caret[primary].place, graph.caret[secondary].place] ELSE NIL]; }; -- UpdateCarets UpdateTargets: PROC[handle: GraphHandle] = { OPEN handle; UpdateTarget: PROC[xy: XY] = { IF chart.viewer # NIL AND graph.target[xy].on THEN PaintTarget[handle, erase, xy]; graph.target[xy].value _ UpdateFromRealField[ controller.targetValue[xy], graph.target[xy].value]; graph.target[xy].width _ UpdateFromRealField[ controller.targetWidth[xy], graph.target[xy].width]; graph.target[xy].colorIndex _ UpdateFromIntField[ controller.targetColor[xy], graph.target[xy].colorIndex]; IF graph.target[xy].colorIndex NOT IN ColorIndex THEN { graph.target[xy].colorIndex _ 13; BlinkMsg["Color index out of range. Default is used."]; }; IF (graph.target[xy].on _ controller.targetOn[xy]) THEN IF chart.viewer # NIL THEN PaintTarget[handle, paint, xy]; }; UpdateTarget[x]; UpdateTarget[y]; }; -- UpdateTargets UpdateGrids: PROC[handle: GraphHandle] = { OPEN handle; UpdateGrid: PROC[wasOn, isOn: BOOL, xy: XY] = { IF wasOn # isOn THEN { IF chart.viewer # NIL THEN { IF wasOn THEN PaintGrids[handle, erase, xy]; PaintGrids[handle, paint, xy]; -- paint grids or ticks. }; graph.grids[xy] _ isOn; }; }; UpdateGrid[graph.grids[x], controller.gridOn[x], x]; UpdateGrid[graph.grids[y], controller.gridOn[y], y]; }; -- UpdateGrids UpdateColor: PROC[handle: GraphHandle, index: ColorIndex] = { OPEN handle; GetRGB: PROC[v: Viewer, r: REAL] RETURNS [rgb: REAL] = { rgb _ UpdateFromRealField[v, r]; IF rgb > 1.0 OR rgb < 0.0 THEN { rgb _ MAX[0.0, MIN[1.0, rgb]]; BlinkMsg["color value limited by [0..1]."]; }; }; graph.color[index].R _ GetRGB[controller.red, graph.color[index].R]; graph.color[index].G _ GetRGB[controller.green, graph.color[index].G]; graph.color[index].B _ GetRGB[controller.blue, graph.color[index].B]; systemColor[index] _ SetColor[index, graph.color[index]]; }; -- UpdateColor UpdateFont: PROC[handle: GraphHandle, index: FontIndex] = { OPEN handle; PaintTextsOfThisFont: PROC [action: PaintAction] = { IF chart.viewer # NIL THEN FOR ts: Texts _ graph.texts, ts.rest UNTIL ts = NIL DO text: Text _ ts.first; IF text.fontIndex = index THEN PaintText[handle, action, text]; ENDLOOP; }; -- PaintTextsOfThisFont msg: ROPE; vFontSize: INT; pFontScale: REAL; vFont, pFont: ImagerFont.Font _ NIL; fontFamily: ROPE _ ViewerTools.GetContents[controller.fontFamily]; IF fontFamily = NIL THEN {BlinkMsg["Specify font family."]; RETURN}; [msg, vFontSize] _ GetIntField[controller.vFontSize]; IF msg # NIL THEN RETURN; [msg, pFontScale] _ GetRealField[controller.pFontScale]; IF msg # NIL THEN RETURN; vFont _ VFonts.EstablishFont[fontFamily, vFontSize, controller.boldOn, controller.italicOn, TRUE]; -- true means default on failure. pFont _ ImagerFont.Scale[ ImagerFont.Find[Rope.Cat[ "Xerox/PressFonts/", fontFamily, Rope.Concat[IF controller.boldOn THEN "-b" ELSE "-m", IF controller.italicOn THEN "ir" ELSE "rr"]]], pFontScale ! Imager.Error => {pFont _ NIL; CONTINUE}]; IF pFont = NIL THEN BlinkMsg["Can't find font."] ELSE { PaintTextsOfThisFont[erase]; graph.font[index] _ [fontFamily, controller.boldOn, controller.italicOn, vFontSize, pFontScale]; imagerFonts[screen][index] _ vFont; imagerFonts[interpress][index] _ pFont; PaintTextsOfThisFont[paint]; }; }; -- UpdateFont UpdateText: PROC[handle: GraphHandle, text: Text, id: INT] = { OPEN handle; rope: ROPE _ ViewerTools.GetContents[controller.textContent]; msg: ROPE _ NIL; add: BOOL _ text = NIL; int: INT; GetTextPlace: PROC [v: Viewer, original: REAL] RETURNS [r: REAL] = { r _ UpdateFromRealField[v, original]; IF r > 3.0 OR r < - 3.0 THEN { r _ MAX[-3.0, MIN[3.0, r]]; BlinkMsg["Text coordinates limited by [-3..3]"]; }; }; -- GetTextPlace IF rope = NIL THEN {BlinkMsg["name field is empty."]; RETURN}; IF add THEN text _ NEW[TextRec _ []] ELSE IF chart.viewer # NIL THEN PaintText[handle, erase, text]; int _ UpdateFromIntField[controller.textFont, text.fontIndex]; IF int NOT IN FontIndex THEN msg _ "Illegal font index." ELSE text.fontIndex _ int; int _ UpdateFromIntField[controller.textColor, text.colorIndex]; IF int NOT IN ColorIndex THEN msg _ msg.Cat[" Illegal color index."] ELSE text.colorIndex _ int; IF msg # NIL THEN {BlinkMsg[msg]; text _ NIL; RETURN}; text^ _ [ text: rope, place: [GetTextPlace[controller.textPlaceX, text.place.x], GetTextPlace[controller.textPlaceY, text.place.y]], fontIndex: text.fontIndex, colorIndex: text.colorIndex, justifX: controller.justifX, justifY: controller.justifY, id: id ]; IF chart.viewer # NIL THEN PaintText[handle, paint, text]; IF add THEN { handle.allTexts _ CONS[text, handle.allTexts]; graph.texts _ CONS[text, graph.texts]; [] _ AddTextButton[handle, text]; }; }; -- UpdateText UpdateX: PROC [handle: GraphHandle] = { OPEN handle; -- proc no use for now. length, pos: INT; vList: ValueList; [vList, length, pos] _ GraphConvert.ValueListFromRope[ ViewerTools.GetContents[controller.xValues]]; IF pos # 0 THEN RETURN; IF vList = NIL THEN {BlinkMsg["The values field is empty."]; RETURN}; IF length # entityGroupList.first.length THEN { BlinkMsg[Rope.Cat["There should be ", Convert.RopeFromInt[entityGroupList.first.length], "numbers in the values field."]]; RETURN}; UpdateSegEnd[entityGroupList.first.x, vList]; IF chart.viewer # NIL THEN PaintAll[handle]; }; -- UpdateX UpdateEntity: PROC [handle: GraphHandle, entity: Entity, id: INT] = { OPEN handle; msg: ROPE _ NIL; add: BOOL _ entity = NIL; vList: ValueList; length, pos, int: INT _ 0; painted: BOOL _ FALSE; <> <<[msg, groupId] _ GetIntField[controller.entityGroupId, "group id"];>> <> <> <> <> <> <<};>> [vList, length, pos] _ GraphConvert.ValueListFromRope[ ViewerTools.GetContents[controller.entityValues]]; IF pos # 0 THEN RETURN; IF vList = NIL THEN {BlinkMsg["Error in the values field."]; RETURN}; IF length # entityGroupList.first.length THEN { BlinkMsg[Rope.Cat["There should be ", Convert.RopeFromInt[entityGroupList.first.length], "numbers in the values field."]]; RETURN}; IF add THEN entity _ NEW[EntityRec _ []] ELSE { FOR el: EntityList _ graph.entityList, el.rest UNTIL el = NIL DO IF el.first = entity THEN painted _ TRUE; ENDLOOP; IF chart.viewer # NIL AND painted THEN PaintEntity[handle, erase, entity]; }; int _ UpdateFromIntField[controller.entityColor, entity.colorIndex]; IF int NOT IN ColorIndex THEN {BlinkMsg[" Illegal color index."]; RETURN}; entity^ _ [ name: ViewerTools.GetContents[controller.entityName], colorIndex: int, mark: controller.mark, width: UpdateFromRealField[controller.entityWidth, entity.width], oldValues: IF add THEN vList ELSE entity.oldValues, segments: entity.segments, group: IF entity.group = NIL THEN entityGroupList.first ELSE entity.group, -- for now. id: id ]; IF add THEN { -- add it on handle and on table. index: INT[0..EntityHashSize) _ id MOD EntityHashSize; entityHash[index] _ CONS[entity, entityHash[index]]; entity.group.ys.first.entityList _ CONS[entity, entity.group.ys.first.entityList]; -- for now. [] _ AddEntityButton[handle, entity]; -- for now. InitSegAll[entity]; } ELSE UpdateSegAll[entity, vList]; vList _ GraphCleanUp.CleanUpVL[vList]; IF add OR NOT painted THEN { -- add it on graph graph.entityList _ CONS[entity, graph.entityList]; }; IF chart.viewer # NIL THEN PaintEntity[handle, paint, entity]; }; -- UpdateEntity <> <<}; -- UpdateEntityGroup>> <> <> <> <> <> <> <> <> <> <<[ok, y] _ Crosssection[xEntity.newValues, el.first, x];>> <> <> <> <> <> <> <<}; -- UpdateCrosssection>> UpdateFromIntField: PROC[field: Viewer, origianl: INT _ 0, showMsg: BOOL _ TRUE] RETURNS [int: INT _ 0] = { <> msg: ROPE; [msg, int] _ GetIntField[field, showMsg]; IF msg # NIL THEN int _ origianl; }; -- UpdateFromIntField UpdateFromRealField: PROC[field: Viewer, origianl: REAL _ 0.0, showMsg: BOOL _ TRUE] RETURNS [real: REAL _ 0.0] = { <> msg: ROPE; [msg, real] _ GetRealField[field, showMsg]; IF msg # NIL THEN real _ origianl; }; -- UpdateFromRealField }. LOG. SChen, created at October 9, 1985 8:57:21 pm PDT.