DIRECTORY Buttons USING [Button, ButtonProc, Create], DefaultRemoteNames USING [DefaultNames, Get], DFToolInternal USING [ Choice, DFTool, OpDefiner, Operation, OpTable, OptionSelector, Parameters, ToolParameters, UserClass], FS USING [ComponentPositions, Error, ExpandName], IO USING [Close, EndOfStream, GetTokenRope, IDProc, RIS, STREAM], Labels USING [Create, --Destroy, --Label], Rope USING [Cat, Concat, Equal, Index, ROPE, Substr], UserCredentials USING [Get], UserProfile USING [Boolean, ListOfTokens, Number, ProfileChangedProc, Token], VFonts USING [EstablishFont, Font, FontHeight, StringWidth], ViewerClasses USING [Viewer], ViewerOps USING [DestroyViewer], -- should be Labels.Destroy ViewerSpecs USING [openLeftWidth, openRightWidth], ViewerTools USING [GetContents, SetContents]; DFToolUtilitiesImpl: CEDAR MONITOR IMPORTS Buttons, DefaultRemoteNames, FS, IO, Labels, Rope, UserCredentials, UserProfile, VFonts, ViewerOps, ViewerSpecs, ViewerTools EXPORTS DFToolInternal = BEGIN OPEN Tool: DFToolInternal; ROPE: TYPE = Rope.ROPE; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- userClasses: PUBLIC ARRAY Tool.UserClass OF ROPE _ ["Individual", "ReleaseParticipant", "ReleaseMaster"]; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- parameters: Tool.Parameters; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- maxOps: NAT = 10; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- AddOpToTable: PUBLIC PROC [definer: REF Tool.OpDefiner] = { definer.opAlias _ GetOpAlias[definer.opName]; parameters.opTable.ops[parameters.opTable.nOps] _ definer; parameters.opTable.nOps _ parameters.opTable.nOps.SUCC; }; ViewerToRopeList: PUBLIC PROC [viewer: ViewerClasses.Viewer] RETURNS [list: LIST OF ROPE _ NIL] = { tail: LIST OF ROPE _ NIL; s: IO.STREAM = IO.RIS[ViewerTools.GetContents[viewer]]; DO r: ROPE _ s.GetTokenRope[IO.IDProc ! IO.EndOfStream => EXIT].token; rL: LIST OF ROPE; rL _ CONS[r, NIL]; IF list = NIL THEN list _ rL ELSE tail.rest _ rL; tail _ rL; ENDLOOP; s.Close[]; }; EnsureDFName: PUBLIC PROC [r: ROPE] RETURNS [ROPE] = { cp: FS.ComponentPositions; fullFName: ROPE _ NIL; [fullFName, cp] _ FS.ExpandName[r ! FS.Error => CONTINUE]; IF fullFName ~= NIL AND cp.ver.length = 0 AND cp.ext.length = 0 THEN r _ r.Concat[".df"]; RETURN[r] }; LabelWidthForChoices: PUBLIC PROC [tool: Tool.DFTool, list: LIST OF Tool.Choice] RETURNS [max: INT _ 0] = { maxRope: ROPE _ NIL; temp: Labels.Label; IF list = NIL THEN RETURN; FOR l: LIST OF Tool.Choice _ list, l.rest UNTIL l = NIL DO w: INT = VFonts.StringWidth[l.first.name]; IF w > max THEN {maxRope _ l.first.name; max _ w}; ENDLOOP; temp _ Labels.Create[ info: [name: maxRope, wx: 0, wy: 0, parent: tool.outer, border: FALSE], paint: FALSE ]; max _ temp.cw; ViewerOps.DestroyViewer[viewer: temp, paint: FALSE]; -- Labels.Destroy[temp] repaints }; MakeCenteredLabel: PUBLIC PROC [op: Tool.Operation, name: ROPE] = { tool: Tool.DFTool = op.tool; IF tool.parameters.compactLayout THEN RETURN; [] _ Labels.Create[ info: [name: name, wx: (OuterContainerWidth[tool] - VFonts.StringWidth[name])/2, wy: op.height, wh: tool.parameters.entryHeight, parent: op.optionsContainer, border: FALSE ], font: tool.parameters.boldFont ]; op.height _ op.height + tool.parameters.entryHeight + tool.parameters.entryVSpace; }; OuterContainerWidth: PUBLIC PROC [tool: Tool.DFTool] RETURNS [INT] = { RETURN[ IF tool.outer.column = left THEN ViewerSpecs.openLeftWidth ELSE ViewerSpecs.openRightWidth ] }; CreateSelector: PUBLIC PROC [ name: ROPE, proc: Buttons.ButtonProc, clientData: REF ANY, choices: LIST OF Tool.Choice, op: Tool.Operation, x: INTEGER _ -1] RETURNS [selector: REF Tool.OptionSelector, initialChoice: Tool.Choice, newX: INTEGER] = { tool: Tool.DFTool = op.tool; button: Buttons.Button; defaultOption: ROPE _ UserProfile.Token[Rope.Cat["DFTool.", op.definer.opAlias, ".", name]]; IF defaultOption = NIL THEN defaultOption _ UserProfile.Token[Rope.Cat["DFTool.", op.definer.opName, ".", name]]; IF x < 0 THEN x _ tool.parameters.entryHSpace; button _ Buttons.Create[ info: [name: name.Concat[":"], wx: x, wy: op.height, wh: tool.parameters.entryHeight, parent: op.optionsContainer, border: FALSE ], proc: proc, fork: FALSE, clientData: clientData, font: tool.parameters.font ]; selector _ NEW[Tool.OptionSelector _ [ name: name, choices: choices, default: (initialChoice _ choices.first).name ]]; IF defaultOption ~= NIL THEN FOR l: LIST OF Tool.Choice _ choices, l.rest UNTIL l = NIL DO IF defaultOption.Equal[l.first.name, FALSE] THEN { selector.default _ (initialChoice _ l.first).name; EXIT }; ENDLOOP; selector.displayer _ Labels.Create[ info: [ name: selector.default, wx: button.wx + button.ww + tool.parameters.entryHSpace, wy: op.height, wh: tool.parameters.entryHeight, ww: LabelWidthForChoices[op.tool, choices], parent: op.optionsContainer, border: FALSE ], font: tool.parameters.font ]; newX _ selector.displayer.wx + selector.displayer.ww; }; SelectOption: PUBLIC PROC [selector: REF Tool.OptionSelector] RETURNS [choice: Tool.Choice] = { NextChoice: PROC [this: ROPE, list: LIST OF Tool.Choice] RETURNS [next: Tool.Choice _ [NIL, NIL]] = { IF list = NIL THEN RETURN; FOR l: LIST OF Tool.Choice _ list, l.rest UNTIL l = NIL DO IF this.Equal[l.first.name, FALSE] THEN RETURN[IF l.rest = NIL THEN list.first ELSE l.rest.first] ENDLOOP; RETURN[list.first] }; choice _ NextChoice[ViewerTools.GetContents[selector.displayer], selector.choices]; ViewerTools.SetContents[selector.displayer, choice.name]; }; ResetOption: PUBLIC PROC [selector: REF Tool.OptionSelector] = { ViewerTools.SetContents[selector.displayer, selector.default]; }; GetToolParameters: PUBLIC ENTRY PROC RETURNS [Tool.Parameters] = {RETURN[parameters]}; ReactToProfile: PUBLIC ENTRY UserProfile.ProfileChangedProc = { ENABLE UNWIND => NULL; params: Tool.Parameters _ NEW[Tool.ToolParameters]; fontFamily: ROPE = UserProfile.Token["DFTool.FontFamily", "Tioga"]; fontSize: NAT = UserProfile.Number["DFTool.FontSize", 10]; class: ROPE = UserProfile.Token[key: "DFTool.UserClass", default: userClasses[$individual]]; userName: ROPE _ UserCredentials.Get[].name; defaultNames: DefaultRemoteNames.DefaultNames _ DefaultRemoteNames.Get[]; IF reason = firstTime THEN RETURN; -- handled by initialization code, below. userName _ userName.Substr[len: userName.Index[s2: "."]]; params.dfNamePrefixes _ UserProfile.ListOfTokens[ key: "DFTool.DFNamePrefixes", default: LIST[ Rope.Concat[defaultNames.current, "Top>"], Rope.Cat[defaultNames.userHost, "<", userName, ">"], Rope.Concat[defaultNames.previous, "Top>"] ] ]; params.userClass _ $individual; FOR userClass: Tool.UserClass IN Tool.UserClass DO IF class.Equal[userClasses[userClass], FALSE] THEN {params.userClass _ userClass; EXIT}; ENDLOOP; params.opTable _ NEW[Tool.OpTable[maxOps]]; IF parameters = NIL THEN params.opTable.nOps _ 0 -- called from this module's initialization; opTable filled in later ELSE { params.opTable.nOps _ parameters.opTable.nOps; FOR op: NAT IN [0..parameters.opTable.nOps) DO old: REF Tool.OpDefiner = parameters.opTable[op]; params.opTable.ops[op] _ NEW[Tool.OpDefiner _ [ opName: old.opName, opID: old.opID, userClass: old.userClass, proc: old.proc, opAlias: GetOpAlias[old.opName] ]]; ENDLOOP; }; params.compactLayout _ UserProfile.Boolean["DFTool.CompactLayout", FALSE]; params.font _ VFonts.EstablishFont[fontFamily, fontSize]; params.boldFont _ VFonts.EstablishFont[family: fontFamily, size: fontSize, bold: TRUE]; params.entryHeight _ VFonts.FontHeight[params.font] + 2; params.entryVSpace _ VFonts.FontHeight[params.font]*1/3; IF params.compactLayout THEN params.entryVSpace _ 1; params.entryHSpace _ 10; parameters _ params; }; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- GetOpAlias: PROC [opName: ROPE] RETURNS [alias: ROPE] = { RETURN[UserProfile.Token[Rope.Concat["DFTool.NameFor", opName], opName]] }; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ReactToProfile[edit]; END. ÌDFToolUtilitiesImpl.mesa Levin on December 16, 1983 2:27 pm Russ Atkinson on February 13, 1984 10:02:19 pm PST Global "Variables" (constant after init) Global Variables (protected by monitor) Configuration Parameters (private) Utilities (exports to DFToolInternal for individual ops) assumed to be called only before 'ReactToProfile' is enabled. It is important that the entire `parameters' data structure be copied, since there is unsynchronized access to its contents elsewhere in the tool. Since this will happen rarely, the cost is acceptable. User profile fields: DFTool.DFNamePrefixes: DFTool.UserClass: {Individual, ReleaseParticipant, ReleaseMaster} DFTool.NameFor: synonym (where is "BringOver", "SModel", etc.) DFTool.FontFamily DFTool.FontSize DFTool..: (use "..." if embedded spaces) DFTool.CompactLayout: TRUE | FALSE Internal Procedures Initialization Ê *˜šœ™Jšœ"™"Jšœ2™2—J˜šÏk ˜ Jšœœ˜+Jšœœ˜-šœœ˜Jšœf˜f—Jšœœ)˜1Jšœœ,œœ˜AJšœœ Ïc œ˜*Jšœœœ ˜5Jšœœ˜Jšœ œ<˜MJšœœ0˜˜>J˜J˜—Jš Ÿœœœœœœ˜VJ˜šœœœ#˜?JšœÊ™ÊJšœœœ˜šœ™Jšœ5™5JšœA™AJšœS™SJ™J™J™VJ™"—Jšœœ˜3Jšœ œ3˜CJšœ œ-˜:JšœœQ˜\Jšœ œ˜,JšœI˜IJšœœœž)˜MJšœ9˜9šœ1˜1J˜šœ œ˜Jšœ*˜*Jšœ4˜4Jšœ*˜*J˜—J˜—Jšœ˜šœœ˜2Jšœ%œœ œ˜XJšœ˜—Jšœœ˜+šœœ˜JšœžD˜]—šœ˜Jšœ.˜.šœœœ˜.Jšœœ)˜1šœœ˜/Jšœ˜J˜Jšœ˜Jšœ˜Jšœ˜J˜—Jšœ˜—J˜—JšœCœ˜JJšœ9˜9JšœQœ˜WJšœ8˜8Jšœ8˜8Jšœœ˜4Jšœ˜Jšœ˜J˜—J˜Jšžœžœžœžœžœžœžœž˜'J™Jšžœžœžœžœžœžœžœž˜'J˜š Ÿ œœ œœ œ˜9JšœB˜HJ˜—J˜Jšžœžœžœžœžœžœžœž˜'J™Jšžœžœžœžœžœžœžœž˜'J˜J˜Jšœ˜J˜Jšœ˜J˜J˜J™J˜—…—Â.¸