DIRECTORY Buttons USING [Button, Create], ChoiceButtons USING [BuildTextPrompt, PromptDataRef], Containers USING [Container, Create, ChildXBound, ChildYBound], Environment USING [bytesPerWord], FileIO USING [Open], Graphics, GraphicsOps USING [DrawBitmap, BitmapRep], Icons, IconEditorDefs, IconEditorIO, IO, IconRegistry USING [IsRegistered], Menus USING [ClickProc, Menu, MenuProc], MessageWindow USING [Append, Blink, Confirm], Real USING [FixC], Rope USING [Cat, ROPE, Size], Rules USING [Create], Runtime USING [IsBound], TIPUser USING [TIPScreenCoords, InstantiateNewTIPTable], ViewerClasses USING [DestroyProc, NotifyProc, PaintProc, Viewer, ViewerClass, ViewerClassRec], ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass, SetNewVersion], ViewerTools USING [GetContents, SetContents]; IconEditorImplB: CEDAR PROGRAM IMPORTS Buttons, ChoiceButtons, Containers, Graphics, GraphicsOps, Icons, IconEditorDefs, IconEditorIO, IconRegistry, IO, MessageWindow, Real, Rope, Rules, Runtime, TIPUser, ViewerOps, ViewerTools, FileIO EXPORTS IconEditorDefs = { OPEN IconEditorDefs; foreground: Graphics.Color _ Graphics.black; background: Graphics.Color _ Graphics.white; deskTopGray: CARDINAL = 122645B; iconEditorIcon: Icons.IconFlavor = Icons.NewIconFromFile["IconEditor.icons", 0]; StartIconEditor: PROC RETURNS [tool: IconHandle] = { ENABLE UNWIND => NULL; iconFileInfo, iconNumberInfo: ChoiceButtons.PromptDataRef; iconFetchButton: Buttons.Button; iconViewerClass: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [ paint: IconPainter, notify: NotifyEvents, destroy: AboutToDestroy, coordSys: bottom, tipTable: TIPUser.InstantiateNewTIPTable["IconEditor.TIP"] ]]; tool _ NEW [IconHandleRec]; tool.iconFileName _ "Sample.icons"; tool.container _ Containers.Create[info: [name: "Icon Editor", scrollable: FALSE, iconic: TRUE, column: left, icon: iconEditorIcon]]; tool.container.menu _ CreateMenu[tool]; iconFileInfo _ ChoiceButtons.BuildTextPrompt[viewer: tool.container, x: 0, y: 0, title: "File: ", textViewerWidth: 250, clientdata: tool]; tool.iconFileWindow _ iconFileInfo.textViewer; ViewerTools.SetContents[tool.iconFileWindow, tool.iconFileName]; iconFileInfo _ ChoiceButtons.BuildTextPrompt[viewer: tool.container, x: iconFileInfo.newx, y: 0, title: " Icon Name: "]; tool.iconNameWindow _ iconFileInfo.textViewer; -- w.t. iconFetchButton _ Buttons.Create[info: [name: "FetchIcon: ", parent: tool.container, wx: 0, wy: 20, border: TRUE], proc: IconFetchProc, clientData: tool, fork: TRUE]; iconNumberInfo _ ChoiceButtons.BuildTextPrompt[viewer: tool.container, x: iconFetchButton.ww, y: 20, title: "Number[0-...]: ", textViewerWidth: 30]; tool.iconNumberWindow _ iconNumberInfo.textViewer; iconFileInfo _ ChoiceButtons.BuildTextPrompt[viewer: tool.container, x: iconNumberInfo.newx, y: 20, title: " from Icon file: "]; tool.iconFetchFileWindow _ iconFileInfo.textViewer; ViewerTools.SetContents[tool.iconFetchFileWindow, tool.iconFileName]; Containers.ChildXBound[tool.container, Rules.Create[info: [parent: tool.container, wx: 0, wy: 40, ww: 1, wh: 1]]]; ViewerOps.RegisterViewerClass[$IconViewer, iconViewerClass]; tool.viewer _ ViewerOps.CreateViewer[flavor: $IconViewer, info: [parent: tool.container, scrollable: FALSE, border: FALSE, wx: 0, wy: 40+distX, data: tool]]; Containers.ChildXBound[tool.container, tool.viewer]; Containers.ChildYBound[tool.container, tool.viewer]; [tool.numberReadIn, tool.iconFile] _ IconEditorDefs.LoadIcons[tool, tool.iconFileName ! IconEditorDefs.CouldntLoadIcons => GOTO BadFile]; tool.numberOfIcons _ tool.numberReadIn; EXITS BadFile => MessageWindow.Append[Rope.Cat["Icon file ",tool.iconFileName," could not be loaded"],TRUE]; }; IconFetchProc: Menus.ClickProc = { OPEN IconEditorDefs; handle: IconHandle _ NARROW[clientData]; badNews: BOOLEAN _ FALSE; iconInfo: iconInfoRef _ NEW[iconInfoRec _ [handle, icon, handle.currentIC]]; iconNumberRope: Rope.ROPE _ ViewerTools.GetContents[handle.iconNumberWindow]; iconNumber: INTEGER; iconFetchFileName: Rope.ROPE _ ViewerTools.GetContents[handle.iconFetchFileWindow]; h: IO.Handle _ IO.CreateInputStreamFromRope[iconNumberRope]; {ENABLE IO.Error => GOTO BadFile; badNews _ FALSE; iconNumber _ IO.GetInt[h ! IO.Error => { OPEN MessageWindow; Append["Type a valid number in the Number window first!", TRUE]; Blink[]; badNews _ TRUE; CONTINUE }]; IF badNews THEN RETURN; IF Rope.Size[iconNumberRope]=0 OR iconNumber<0 THEN { MessageWindow.Append[message: "Could not fetch icon due to invalid icon number . . .", clearFirst: TRUE]; RETURN}; TRUSTED {-- fetch the icon from the named file fetchFile: IO.Handle _ FileIO.Open[fileName: iconFetchFileName]; numIconsInFile: INTEGER _ fetchFile.GetLength[]/(Environment.bytesPerWord*SIZE[iconFileFormat]); IF iconNumber >= numIconsInFile THEN { MessageWindow.Append[message: "Could not fetch icon due to invalid icon number . . .", clearFirst: TRUE]; RETURN} ELSE { IO.SetIndex[fetchFile, iconNumber*(Environment.bytesPerWord*SIZE[iconFileFormat])]; [] _ IO.UnsafeGetBlock[fetchFile,[LOOPHOLE[handle.icons[LOOPHOLE[handle.currentIC]]], 0, SIZE[iconFileFormat]*2]]; IO.Close[fetchFile]; handle.currentIconRep _ handle.icons[LOOPHOLE[handle.currentIC]]; }; }; ViewerOps.SetNewVersion[handle.container]; ViewerOps.PaintViewer[viewer: handle.viewer, hint: all, whatChanged: iconInfo, clearClient: FALSE]; EXITS BadFile => MessageWindow.Append[message: Rope.Cat["Icon could not be fetched from ", iconFetchFileName], clearFirst: TRUE]; }}; BitMapToCurrentIcon: PUBLIC PROC [bitmap: REF ANY] = TRUSTED { iconInfo: iconInfoRef; handle: IconHandle _ NIL; handle.currentIC _ IconEditorDefs.GetNewFlavor[handle]; handle.currentIconRep _ handle.icons[LOOPHOLE[handle.currentIC]] _ NEW[IconEditorDefs.iconFileFormat]; iconInfo _ NEW[iconInfoRec _ [handle, newIcon, handle.currentIC]]; handle.numberOfIcons _ handle.numberOfIcons + 1; ViewerOps.SetNewVersion[handle.container]; handle.icons[LOOPHOLE[handle.currentIC]] _ LOOPHOLE[bitmap]; IF LOOPHOLE[handle.currentIC, CARDINAL] >= maxIconsOnDisplay THEN handle.startDisplay _ (handle.startDisplay + 1) MOD handle.numberOfIcons; ViewerOps.PaintViewer[viewer: handle.viewer, hint: client,whatChanged: iconInfo, clearClient: FALSE]; }; UndoProc: PUBLIC Menus.MenuProc = { OPEN IconEditorDefs; handle: IconHandle _ NARROW[clientData]; iconInfo: iconInfoRef _ NEW[iconInfoRec _ [handle, icon, handle.currentIC]]; ViewerOps.SetNewVersion[handle.container]; Undo[handle, handle.currentIC]; ViewerOps.PaintViewer[viewer: handle.viewer, hint: all, whatChanged: iconInfo, clearClient: FALSE]; }; DeleteIconProc: PUBLIC Menus.MenuProc = { handle: IconHandle _ NARROW[clientData]; iconInfo: iconInfoRef _ NEW[iconInfoRec _ [handle, screen, handle.currentIC]]; IF handle.numberOfIcons < 2 THEN { MessageWindow.Append[message: "Sorry, can't delete the last icon.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN }; IF ~MessageWindow.Confirm["Confirm deletion of current icon..."] THEN RETURN; DeleteIcon[handle]; ViewerOps.SetNewVersion[handle.container]; ViewerOps.PaintViewer[viewer: handle.viewer, hint: all, whatChanged: iconInfo, clearClient: FALSE]; }; CleanUp: PROCEDURE [handle: IconHandle, context: Graphics.Context] = { IF handle.functionNotApplied THEN IF handle.drewRectangle THEN {DrawRectangle[handle, context, handle.currentRectangle]; handle.drewRectangle _ FALSE}; IF handle.drewLine THEN {SketchLine[handle, context]; handle.drewLine _ FALSE}; }; IconPainter: PUBLIC ViewerClasses.PaintProc = { ENABLE UNWIND => NULL; iconInfo: iconInfoRef; iconContext: Graphics.Context _ context; bounds: Graphics.Box _ Graphics.GetBounds[iconContext]; MessageWindow.Append[clearFirst: TRUE, message: ""]; IF whatChanged=NIL THEN { handle: IconHandle _ NARROW[self.data]; LayoutBoard[handle, bounds ! ViewerNoGood => GOTO Done]; IF ~clear THEN ClearScreen[bounds, iconContext]; DrawIcons[handle, iconContext]; [] _ SetCurrentIcon[handle, XfromIC[handle, handle.currentIC]+10, YfromIC[handle, handle.currentIC]+10]; DrawBoard[handle, iconContext] } ELSE { iconInfo _ NARROW[whatChanged]; IconEditorDefs.LayoutBoard[iconInfo.handle, bounds ! ViewerNoGood => GOTO Done]; SELECT iconInfo.update FROM screen => { ClearScreen[bounds, iconContext]; iconInfo.handle.currentIC _ iconInfo.currentIcon; DrawIcons[iconInfo.handle, iconContext]; [] _ SetCurrentIcon[iconInfo.handle, XfromIC[iconInfo.handle, iconInfo.handle.currentIC]+10, YfromIC[iconInfo.handle, iconInfo.handle.currentIC]+10]; DrawBoard[iconInfo.handle, iconContext]; }; board => DrawBoard[iconInfo.handle, iconContext]; icon => { DrawIcon[iconInfo.handle, iconContext, LOOPHOLE[iconInfo.handle.currentIC _ iconInfo.currentIcon]]; DrawBoard[iconInfo.handle, iconContext] }; bit => { IF iconInfo.clearBit THEN RemoveBit[iconInfo.handle, iconContext, iconInfo.x, iconInfo.y] ELSE AddBit[iconInfo.handle, iconContext, iconInfo.x, iconInfo.y]; }; newIcon => { ClearScreen[bounds, iconContext]; DrawIcons[iconInfo.handle, iconContext]; DrawBoard[iconInfo.handle, iconContext]; DrawBorder[iconInfo.handle, iconContext]; }; mark => { IF iconInfo.handle.firstMark THEN { CleanUp[iconInfo.handle, iconContext]; iconInfo.handle.functionNotApplied _ TRUE; [iconInfo.handle.mark1.x, iconInfo.handle.mark1.y] _ BoardCoords[ iconInfo.handle, iconInfo.x, iconInfo.y]; iconInfo.handle.currentRectangle.x _ iconInfo.handle.mark1.x; iconInfo.handle.currentRectangle.y _ iconInfo.handle.mark1.y; iconInfo.handle.currentRectangle.w _ 0; iconInfo.handle.currentRectangle.h _ 0; } ELSE { DrawRectangle[iconInfo.handle, iconContext, iconInfo.handle.currentRectangle]; [iconInfo.handle.mark2.x, iconInfo.handle.mark2.y] _ BoardCoords[iconInfo.handle, iconInfo.x, iconInfo.y]; iconInfo.handle.currentRectangle _ IconEditorDefs.NormalizeRectangle[ iconInfo.handle.mark1, iconInfo.handle.mark2]; DrawRectangle[iconInfo.handle, iconContext, iconInfo.handle.currentRectangle]; } }; line => { IF iconInfo.handle.firstMark THEN { CleanUp[iconInfo.handle, iconContext]; iconInfo.handle.currentRectangle.x _ 0; iconInfo.handle.currentRectangle.y _ 0; iconInfo.handle.currentRectangle.w _ 0; iconInfo.handle.currentRectangle.h _ 0; iconInfo.handle.functionNotApplied _ TRUE; [iconInfo.handle.mark1.x, iconInfo.handle.mark1.y] _ BoardCoords[iconInfo.handle, iconInfo.x, iconInfo.y]; iconInfo.handle.mark2.x _ iconInfo.handle.mark1.x; iconInfo.handle.mark2.y _ iconInfo.handle.mark1.y;-- Initialize the line to be a point iconInfo.handle.currentLine _ IconEditorDefs.TransferEndPoints[iconInfo.handle.mark1, iconInfo.handle.mark2]; } ELSE { SketchLine[iconInfo.handle, iconContext]; [iconInfo.handle.mark2.x, iconInfo.handle.mark2.y] _ BoardCoords[iconInfo.handle, iconInfo.x, iconInfo.y]; iconInfo.handle.currentLine _ IconEditorDefs.TransferEndPoints[iconInfo.handle.mark1, iconInfo.handle.mark2]; SketchLine[iconInfo.handle, iconContext]; }; }; rect => { DrawRectangle[iconInfo.handle, iconContext, iconInfo.handle.labelRect]; }; ENDCASE; }; iconContext _ NIL; -- just to be safe EXITS Done => NULL; }; AboutToDestroy: PUBLIC ViewerClasses.DestroyProc = { ENABLE UNWIND => NULL; handle: IconHandle _ NARROW[self.data]; IO.Close[handle.iconFile]; }; XfromIC: PROC[handle: IconHandle, ic: IconEditorDefs.iconFlavor] RETURNS [CARDINAL] = { i: CARDINAL _ LOOPHOLE[ic]; realFlavor: CARDINAL _ (i - handle.startDisplay + handle.numberOfIcons) MOD handle.numberOfIcons; RETURN [handle.icX+(distX/2) + (realFlavor MOD handle.numIconsPerRow) * (IconEditorDefs.iconW+distX)]; }; YfromIC: PROC[handle: IconHandle, ic: IconEditorDefs.iconFlavor] RETURNS [CARDINAL] = { i: CARDINAL _ LOOPHOLE[ic]; realFlavor: CARDINAL _ (i - handle.startDisplay + handle.numberOfIcons) MOD handle.numberOfIcons; RETURN [handle.icY + (distY/2) + (handle.numIconsPerCol-1-realFlavor / handle.numIconsPerRow) * (IconEditorDefs.iconH+distY)]; }; ICfromXY: PROC[handle: IconHandle, x, y: REAL] RETURNS [ignore: BOOLEAN, ic: IconEditorDefs.iconFlavor] = { xC, yC: CARDINAL; possibleIC, theIC: CARDINAL; iconsOnDisplay: CARDINAL _ MIN[handle.numberOfIcons, maxIconsOnDisplay]; ignore _ FALSE; xC _ Real.FixC[x]; IF xC > handle.icX + (distX/2) THEN xC _ (xC-handle.icX-distX/2)/(IconEditorDefs.iconW+distX) ELSE { ignore _ TRUE; xC _ 0}; yC _ Real.FixC[y]; IF yC > handle.icY + (distY/2) THEN yC _ (yC-handle.icY-distY/2)/(IconEditorDefs.iconH+distY) ELSE { ignore _ TRUE; yC _ 0}; IF xC >= handle.numIconsPerRow THEN xC _ handle.numIconsPerRow-1; IF yC >= handle.numIconsPerCol THEN yC _ handle.numIconsPerCol-1; yC _ handle.numIconsPerCol-1-yC; possibleIC _ handle.numIconsPerRow*yC+xC; -- the icon we might have hit theIC _ (possibleIC + handle.startDisplay) MOD handle.numberOfIcons; ic _ LOOPHOLE[theIC, IconEditorDefs.iconFlavor]; }; BoardCoords: PROC [handle: IconHandle, x, y: REAL] RETURNS [i, j: CARDINAL] = { i _ IF x > handle.boardSize THEN IconEditorDefs.intHBound ELSE Real.FixC[x/handle.unit]; j _ LOOPHOLE[MAX[LOOPHOLE[IconEditorDefs.intHBound-Real.FixC[y/handle.unit],INTEGER], 0]]; }; DeleteIcon: PROCEDURE [handle: IconHandle] = { IF LOOPHOLE[handle.currentIC, CARDINAL] < handle.numberOfIcons - 1 THEN { FOR i: CARDINAL IN [LOOPHOLE[handle.currentIC, CARDINAL] .. handle.numberOfIcons-1) DO handle.icons[LOOPHOLE[i]] _ handle.icons[LOOPHOLE[i+1]]; ENDLOOP; } ELSE { handle.icons[LOOPHOLE[handle.currentIC]] _ NIL; handle.currentIC _ PRED[handle.currentIC]; }; handle.numberOfIcons _ handle.numberOfIcons - 1; handle.nextFlavor _ PRED[handle.nextFlavor]; handle.currentIconRep _ handle.icons[LOOPHOLE[handle.currentIC]]; }; Undo: PROC [handle: IconHandle, flavor: IconEditorDefs.iconFlavor] = { handle.icons[LOOPHOLE[flavor]].bits _ handle.savedBitMap; }; DrawIcons: PROC [handle: IconHandle, context: Graphics.Context] = { FOR i: CARDINAL IN [0..MIN[handle.numberOfIcons, maxIconsOnDisplay]) DO DrawIcon[handle, context, (handle.startDisplay + i) MOD handle.numberOfIcons]; ENDLOOP; }; DrawBit: PROC [handle: IconHandle, context: Graphics.Context, x, y: CARDINAL] = { OPEN IconEditorDefs; -- for intHBound and unit. lx: REAL _ x*handle.unit; by: REAL _ (intHBound-y)*handle.unit; [] _ Graphics.SetPaintMode[context, invert]; Graphics.DrawBox[context, [xmin: lx+1, ymin: by, xmax: lx+handle.unit, ymax: by+handle.unit-1]]; [] _ Graphics.SetPaintMode[context, opaque]; }; ClearScreen: PROC [bounds: Graphics.Box, context: Graphics.Context] = { p: Graphics.Path _ Graphics.NewPath[5]; Graphics.SetColor[context, background]; Graphics.Rectangle[p, 0.0, 0.0, bounds.xmax, bounds.ymax]; Graphics.DrawArea[context, p]; Graphics.SetColor[context, foreground]; }; DrawBox: PROCEDURE [context: Graphics.Context, x0, y0, x1, y1: INTEGER, thickness: REAL] = { p: Graphics.Path _ Graphics.NewPath[5]; [] _ Graphics.SetPaintMode[context, invert]; Graphics.MoveTo[p, x0, y0]; Graphics.LineTo[p, x0, y1]; Graphics.DrawStroke[context, p, normalThickness]; Graphics.FlushPath[p]; Graphics.MoveTo[p, x0 + 1, y1]; Graphics.LineTo[p, x1, y1]; Graphics.DrawStroke[context, p, normalThickness]; Graphics.FlushPath[p]; Graphics.MoveTo[p, x1, y1 - 1]; Graphics.LineTo[p, x1, y0]; Graphics.DrawStroke[context, p, normalThickness]; Graphics.FlushPath[p]; Graphics.MoveTo[p, x1 -1, y0]; Graphics.LineTo[p, x0, y0]; Graphics.DrawStroke[context, p, thickness]; [] _ Graphics.SetPaintMode[context, opaque]; }; DrawIcon: PROC [handle: IconHandle, context: Graphics.Context, index: CARDINAL] = { IF handle.icons[LOOPHOLE[index]] = NIL THEN RETURN -- Just to be safe ELSE { iconBitmap: REF GraphicsOps.BitmapRep _ NEW[GraphicsOps.BitmapRep _ [NIL, IconEditorDefs.iconW/bitsPerWord, IconEditorDefs.iconW, IconEditorDefs.iconH]]; iconBitmap.base _ handle.icons[LOOPHOLE[index]]; Graphics.SetCP[context, XfromIC[handle, LOOPHOLE[index]], YfromIC[handle, LOOPHOLE[index]] + IconEditorDefs.iconH]; GraphicsOps.DrawBitmap[context, iconBitmap, IconEditorDefs.iconW, IconEditorDefs.iconH]; }; }; DrawBoard: PROC [handle: IconHandle, context: Graphics.Context] = { OPEN IconEditorDefs; -- intHBound (to make code less cumbersome) x,y: REAL; [x,y] _ Graphics.GetCP[context]; Graphics.SetColor[context, background]; Graphics.DrawBox[context, [0.0, 0.0, handle.boardSize, handle.boardSize]]; Graphics.SetColor[context, foreground]; FOR i: CARDINAL IN [0..intHBound+1] DO temp: INT; Graphics.SetCP[context, temp _ i*handle.unit, 0.0]; Graphics.DrawTo[context, temp, handle.boardSize]; Graphics.SetCP[context, 0.0, temp _ i*handle.unit]; Graphics.DrawTo[context, handle.boardSize, temp]; ENDLOOP; Graphics.SetCP[context, x, y]; DrawCurrentIcon[handle, context]; handle.drewRectangle _ handle.drewLine _ FALSE; handle.functionNotApplied _ FALSE; }; DrawCurrentIcon: PROC [handle: IconHandle, context: Graphics.Context] = { [] _ Graphics.SetPaintMode[context, invert]; FOR i: CARDINAL IN IconEditorDefs.intH DO FOR j: CARDINAL IN IconEditorDefs.intW DO IF handle.currentIconRep.bits[i].b[j] THEN { lx: REAL _ j*handle.unit; by: REAL _ (IconEditorDefs.intHBound-i)*handle.unit; Graphics.DrawBox[context, [xmin: lx+1, ymin: by, xmax: lx+handle.unit, ymax: by+handle.unit-1]]; }; ENDLOOP; ENDLOOP; [] _ Graphics.SetPaintMode[context, opaque]; }; DrawRectangle: PROC [handle: IconHandle, context: Graphics.Context, rect: IconEditorDefs.rectangleRec] = { OPEN IconEditorDefs; -- for unit, intHBound rX0, rY0, rX1, rY1: INTEGER; rX0 _ rect.x*handle.unit - 1; -- top right corner rY0 _ (intHBound-rect.y + 1)*handle.unit + 1; rX1 _ (rect.x + rect.w)*handle.unit + 1; -- bottom left corner rY1 _ (intHBound-rect.y - rect.h + 1)*handle.unit - 1; DrawBox[context, rX0, rY0, rX1, rY1, normalThickness]; handle.drewRectangle _ TRUE; }; DrawBorder: PROC [handle: IconHandle, context: Graphics.Context] = { x0, y0, x1, y1: INTEGER; x0 _ XfromIC[handle, handle.currentIC]; y0 _ YfromIC[handle, handle.currentIC]+1; x1 _ x0 + IconEditorDefs.iconW - 1; y1 _ y0 + IconEditorDefs.iconH - 1; DrawBox[context, x0, y0, x1, y1, normalThickness]; }; SketchLine: PROC [handle: IconHandle, context: Graphics.Context] = { line: IconEditorDefs.lineRec _ IconEditorDefs.ComputeEndPoints[handle, handle.currentLine]; p: Graphics.Path _ Graphics.NewPath[]; [] _ Graphics. SetPaintMode[context, invert]; Graphics.MoveTo[p, line.x1, line.y1]; Graphics.LineTo[p, line.x2, line.y2]; Graphics.DrawStroke[context, p, normalThickness]; [] _ Graphics.SetPaintMode[context, opaque]; handle.drewLine _ TRUE; }; SetCurrentIcon: PROC [handle: IconHandle, x, y: REAL] RETURNS [ignored: BOOLEAN] = { ic: IconEditorDefs.iconFlavor; [ignored, ic] _ ICfromXY[handle, x, y]; IF ~ignored THEN { handle.currentIC _ ic; handle.currentIconRep _ handle.icons[LOOPHOLE[handle.currentIC]]; } }; BitSet: PROC [handle: IconHandle, x, y: REAL] RETURNS [BOOLEAN] = { xC, yC: CARDINAL; [xC, yC] _ BoardCoords[handle, x, y]; RETURN [handle.currentIconRep.bits[yC].b[xC]]; }; AddBit: PROC [handle: IconHandle, context: Graphics.Context, x, y: REAL] = { xC, yC: CARDINAL; [xC, yC] _ BoardCoords[handle, x, y]; handle.currentIconRep.bits[yC].b[xC] _ TRUE; DrawBit[handle, context, xC, yC]; DrawIcon[handle, context, LOOPHOLE[handle.currentIC]]; }; RemoveBit: PROC [handle: IconHandle, context: Graphics.Context, x, y: REAL] = { xC, yC: CARDINAL; [xC, yC] _ BoardCoords[handle, x, y]; handle.currentIconRep.bits[yC].b[xC] _ FALSE; DrawBit[handle, context, xC, yC]; DrawIcon[handle, context, LOOPHOLE[handle.currentIC]]; }; NotifyEvents: ViewerClasses.NotifyProc = { -- react on user input ENABLE UNWIND => NULL; -- release lock iMouse, jMouse: REAL; erase: BOOLEAN; handle: IconHandle _ NARROW[self.data]; InterpretAtom: PROC [atom: ATOM] = { SELECT atom FROM $Erase => erase _ TRUE; $Select => { IF iMouse > handle.boardSize OR jMouse > handle.boardSize THEN { ignored: BOOLEAN _ SetCurrentIcon[handle, iMouse, jMouse]; IF ~ignored THEN TRUSTED { iconInfo: iconInfoRef _ NEW[iconInfoRec _ [handle, icon, handle.currentIC]]; IF Runtime.IsBound[IconRegistry.IsRegistered] THEN ViewerTools.SetContents[handle.iconNameWindow, IconRegistry.IsRegistered[ fileName: ViewerTools.GetContents[handle.iconFileWindow], index: LOOPHOLE[handle.currentIC, CARDINAL]].name]; -- w.t. ViewerOps.PaintViewer[viewer: handle.viewer, hint: client, whatChanged: iconInfo, clearClient: FALSE]; }; }; }; $Draw => { -- SetBit / RemoveBit IF iMouse < handle.boardSize AND jMouse < handle.boardSize THEN { ViewerOps.SetNewVersion[handle.container]; IF erase = BitSet[handle, iMouse, jMouse] THEN { iconInfo: iconInfoRef _ NEW[iconInfoRec_[handle, bit, handle.currentIC, erase, iMouse, jMouse]]; ViewerOps.PaintViewer[viewer: handle.viewer, hint: client, whatChanged: iconInfo, clearClient: FALSE]; }; }; }; $Mark1 => { IF iMouse < handle.boardSize AND jMouse < handle.boardSize THEN { iconInfo: iconInfoRef _ NEW[iconInfoRec _ [handle, mark, handle.currentIC, erase, iMouse, jMouse]]; handle.firstMark _ TRUE; ViewerOps.SetNewVersion[handle.container]; ViewerOps.PaintViewer[viewer: handle.viewer, hint: client, whatChanged: iconInfo, clearClient: FALSE]; }; }; $Mark2 => { IF iMouse < handle.boardSize AND jMouse < handle.boardSize THEN { iconInfo: iconInfoRef _ NEW[iconInfoRec _ [handle, mark, handle.currentIC, erase, iMouse, jMouse]]; handle.firstMark _ FALSE; ViewerOps.SetNewVersion[handle.container]; ViewerOps.PaintViewer[viewer: handle.viewer, hint: client, whatChanged: iconInfo, clearClient: FALSE] }; }; $EndPoint1 => { IF iMouse < handle.boardSize AND jMouse < handle.boardSize THEN { iconInfo: iconInfoRef _ NEW[iconInfoRec _ [handle, line, handle.currentIC, erase, iMouse, jMouse]]; handle.firstMark _ TRUE; ViewerOps.SetNewVersion[handle.container]; ViewerOps.PaintViewer[viewer: handle.viewer, hint: client,whatChanged: iconInfo, clearClient: FALSE] }; }; $EndPoint2 => { IF iMouse < handle.boardSize AND jMouse < handle.boardSize THEN { iconInfo: iconInfoRef _ NEW[iconInfoRec _ [handle, line, handle.currentIC, erase, iMouse, jMouse]]; handle.firstMark _ FALSE; ViewerOps.SetNewVersion[handle.container]; ViewerOps.PaintViewer[viewer: handle.viewer, hint: client, whatChanged: iconInfo, clearClient: FALSE] }; }; ENDCASE; }; -- InterpretAtom FOR params: LIST OF REF ANY _ input, params.rest UNTIL params=NIL DO WITH params.first SELECT FROM x: TIPUser.TIPScreenCoords => { iMouse _ x.mouseX; jMouse _ x.mouseY; erase _ FALSE; }; x: ATOM => InterpretAtom[x]; ENDCASE; ENDLOOP; }; [] _ StartIconEditor[]; }. ”IconEditorImplB.mesa Written by Werner Winiger, 24-Aug-81 13:14:53 Converted to the Viewers world by Rick Beach, April 30, 1982 4:32 pm Last edit by Mike Spreitzer, November 13, 1982 3:33 pm Last Edited by: Teitelman, April 23, 1983 1:51 pm Last Edited by: Doug Wyatt, April 22, 1983 4:09 pm ************************** Declarations used for graphics ***************************** Set the file index to point at the icon we wish to fetch. Since each icon takes up Environment.bytesPerWord*SIZE[iconFileFormat] bytes, we index into the file by multiples of this. Now read in the block allows any bit map to be converted to icon format and allows the user to edit it make sure the new icon contains the bit map before we paint the screen, make sure new icon is visible make sure we have at least one icon left after we delete we better find out what viewer we want to be dealing with Erase the previous rectangle or line if necessary Erase the old rectangle Erase the previous line or rectangle if necessary Clear up the rectangle marking just in case Erase the old line Just to be safe, close the most recent icon file we were working with We must find some way of getting the handle from the viewer deletes the current icon and then compacts the array of icons. the icon we wish to delete is in the middle of the array of icons; Compact. we are deleting the last icon in the array. now let currentIC be the previous flavor. Since we always must have at least one icon in existance, we will always have a previous flavor Draws a box on the screen with bottom left corner (x0, y0) and top right corner (x1, y1) Draws a rectangle on the drawing board draws a thin border around newly created icons Draws a thin line from one endpoint to another Edited on April 11, 1983 4:13 pm, by Teitelman added code to create an icon name field for use in conjunction with register button, and to fill Name field when icon selected, changes to: DIRECTORY, IconEditorImpl, StartIconEditor, IconFetchProc, InterpretAtom (local of NotifyEvents), DIRECTORY, IconEditorImpl, StartIconEditor, IconFetchProc, InterpretAtom (local of NotifyEvents), } Edited on April 12, 1983 5:03 pm, by Teitelman changes to: InterpretAtom (local of NotifyEvents), DIRECTORY, IconEditorImpl Edited on April 23, 1983 1:51 pm, by Teitelman InterpretAtom was getting name of file from fetchIconFileWindow rather than fetchFileWIndow changes to: InterpretAtom (local of NotifyEvents) Ê®˜Jšœ™Jšœ-™-JšœD™DJšœ6™6Jšœ1™1Jšœ2™2J˜šÏk ˜ Jšœœ˜Jšœœ"˜5Jšœ œ/˜?Jšœ œ˜!Jšœœ˜J˜ Jšœ œ˜*J˜J˜J˜ Jšœ˜Jšœ œ˜"Jšœœ˜(Jšœœ˜-Jšœœ˜Jšœœœ˜Jšœœ ˜Jšœœ ˜Jšœœ+˜8šœœ:˜MJ˜—Jšœ œA˜PJšœ œ˜-—J˜šœœ˜JšœB˜IJšœ,œ5˜cJ˜Jšœ˜Jšœ˜—J˜JšœW™WJ˜J˜-J˜-Jšœ œ ˜ J˜J˜PJ˜šÏnœœœ˜4Jšœœœ˜J˜:J˜ J˜šœ-œ!˜QJ˜J˜J˜J˜J˜:J˜—J˜Jšœœ˜J˜#šœ>˜>Jšœ œ œ'˜F—J˜'J˜J˜aJ˜(J˜.J˜@J˜xJšœ0Ïc˜7J˜˜[Jšœœ0œ˜J—J˜”˜2J˜€—J˜3˜EJ˜r—J˜<˜XJšœ œ œ$˜D—J˜4J˜4˜WJšœ#œ ˜1—J˜'šœ ˜JšœUœ˜[—J˜—J˜šž œ˜"Jšœ˜Jšœœ ˜(Jšœ œœ˜Jšœœ1˜LJšœœ4˜MJšœ œ˜Jšœœ7˜SJšœœ œ+˜šœP™PJ˜—Jšœœ˜J˜7Jšœ%œœ ˜fJšœ œ4˜BJ˜0J˜*Jšœ+™+šœ œœ ˜˜BJ˜—˜ J˜!J˜(J˜(J˜)J˜—˜ šœœ˜#Jšœ1™1J˜&Jšœ%œ˜*˜AJ˜)—J˜=J˜=J˜'J˜'J˜—šœ˜Jšœ™J˜N˜4J˜5—˜EJ˜.—J˜NJ˜—J˜—˜ šœœ˜#Jšœ1™1J˜&Jšœ+™+J˜'J˜'J˜'J˜'Jšœ%œ˜*˜4J˜5—J˜2Jšœ2Ÿ$˜V˜J˜O—J˜—šœ˜Jšœ™J˜)˜4J˜5—˜J˜O—J˜)J˜—J˜—˜ J˜GJ˜—Jšœ˜J˜—JšœœŸ˜&Jšœ œ˜J˜—J˜šžœœ˜4Jšœœœ˜Jšœœ ˜'JšœE™EJ™;Jšœ˜J˜—J˜šžœœ4œœ˜WJšœœœ˜šœ œ4˜KJ˜—šœ%œ˜GJ˜—J˜—J˜šžœœ4œœ˜WJšœœœ˜šœ œ4˜KJ˜—šœ@˜FJ˜7—J˜—J˜šžœœœ˜.Jšœ œ$˜™>šœœœœ˜IJšœK™Kš œœœœœ˜VJšœ œœ˜8—Jšœ˜J˜—šœ˜Jšœ-™-Jšœ œœ˜/JšœQ™QJšœ8™8Jšœœ˜*J˜—J˜0Jšœœ˜,Jšœ%œ˜AJ˜—J˜šžœœ<˜FJšœ œ$˜9J˜—J˜šž œœ4˜Cš œœœœ+˜GJšœ4œ˜NJšœ˜—J˜—J˜šžœœ7œ˜QJšœŸ˜0Jšœœ˜Jšœœ˜%J˜,J˜`J˜,J˜—J˜šž œœ6˜GJ˜'J˜'J˜:J˜J˜'J˜—J˜šžœ œ-œ œ˜\JšœX™XJ˜'J˜,J˜J˜J˜1J˜J˜J˜J˜1J˜J˜J˜J˜1J˜J˜J˜J˜+J˜,J˜—J˜šžœœ8œ˜SJš œœ œœœŸ˜Ešœ˜šœ œœ˜CJšœœQ˜U—Jšœœ ˜0šœ(œ ˜9Jšœœ!˜9—˜BJ˜—J˜—J˜—J˜šž œœ4˜CJšœŸ-˜CJšœœ˜ J˜ J˜'J˜JJ˜'šœœœ˜&Jšœœ˜ J˜3J˜1J˜3J˜1Jšœ˜—J˜J˜!Jšœ)œ˜/Jšœœ˜"J˜—J˜šžœœ4˜IJ˜,šœœœ˜)šœœœ˜)šœ$œ˜,Jšœœ˜Jšœœ,˜4J˜`J˜—Jšœ˜—Jšœ˜—J˜,J˜—J˜šž œœ0˜CJ˜&Jšœ&™&JšœŸ˜,Jšœœ˜Jšœ$Ÿ˜7J˜-Jšœ,Ÿ˜AJ˜6J˜6Jšœœ˜J˜—J˜šž œœ4˜DJšœ.™.Jšœœ˜J˜'J˜)J˜#J˜#J˜2J˜—J˜šž œœ4˜DJšœ.™.J˜[J˜&J˜-J˜%J˜%J˜1J˜,Jšœœ˜J˜—J˜š žœœœœ œ˜TJ˜J˜'šœ œ˜J˜Jšœ%œ˜AJ˜—J˜—J˜š žœœœœœ˜CJšœœ˜J˜%Jšœ(˜.J˜—J˜šžœœ7œ˜LJšœœ˜J˜%Jšœ'œ˜,J˜!Jšœœ˜6J˜—J˜šž œœ7œ˜OJšœœ˜J˜%Jšœ'œ˜-J˜!Jšœœ˜6J˜—J˜šž œŸ˜AJšœœœŸ˜&Jšœœ˜Jšœœ˜Jšœœ ˜'šž œœœ˜$šœœ˜Jšœœ˜˜ šœœœ˜@Jšœ œ*˜:šœ œœ˜Jšœœ1˜Lšœ,˜2˜.˜Jšœ9˜9Jšœœœ Ÿ˜<———˜:Jšœ$œ˜+—J˜—J˜—J˜—šœ Ÿ˜ šœœœ˜AJ˜*šœ(œ˜0šœœ3˜NJ˜—˜GJšœœ˜—Jšœ˜—Jšœ˜—J˜—˜ šœœœ˜Ašœœ˜)Jšœ9˜9—Jšœœ˜J˜*˜QJšœ œ˜—Jšœ˜—J˜—˜ šœœœ˜Ašœœ˜)Jšœ9˜9—Jšœœ˜J˜*˜QJšœ œ˜—J˜—J˜—˜šœœœ˜Ašœœ˜)Jšœ9˜9—Jšœœ˜J˜*˜PJšœ œ˜—J˜—J˜—˜šœœœ˜Ašœœ6˜QJ˜—Jšœœ˜J˜*˜QJšœ œ˜—J˜—J˜—Jšœ˜—JšœŸ˜—J˜šœ œœœœœœ˜Dšœœ˜˜Jšœ.œ˜4J˜—Jšœœ˜Jšœ˜—Jšœ˜—J˜—J˜J˜J˜J˜J˜šœ.™.Jšœ€™€JšœÑ™Ñ—J™šœ.™.JšœL™L—™.JšÏr œN™[Jšœ   œ™1—J™—…—WVs˜