DIRECTORY AtomButtons, AtomButtonsTypes, Buttons, CodeTimer, Feedback, FS, GraphicsButton, Imager, IO, Menus, PopUpSelection, Rope, SlackProcess, SV2d, SV3d, SVDraw, SVEditUser, SVEvent, SVFiles, SVInterfaceTypes, SVMenus, SVModelTypes, SVMouseEvent, SVSceneTypes, SVUserInput, SVWindow, VFonts, ViewerClasses, ViewerTools; SVMenusImpl: CEDAR PROGRAM IMPORTS AtomButtons, Buttons, CodeTimer, Feedback, FS, GraphicsButton, Imager, IO, PopUpSelection, Rope, SlackProcess, SVDraw, SVEditUser, SVEvent, SVFiles, SVMouseEvent, SVUserInput, SVWindow, VFonts, ViewerTools EXPORTS SVMenus = BEGIN Camera: TYPE = SVModelTypes.Camera; CoordSystem: TYPE = SVModelTypes.CoordSystem; EditToolData: TYPE = SVInterfaceTypes.EditToolData; FeedbackData: TYPE = AtomButtonsTypes.FeedbackData; FileCamera: TYPE = SVSceneTypes.FileCamera; MouseButton: TYPE = Menus.MouseButton; Plane: TYPE = SV3d.Plane; Point2d: TYPE = SV2d.Point2d; Scene: TYPE = SVSceneTypes.Scene; Viewer: TYPE = ViewerClasses.Viewer; SVData: TYPE = SVInterfaceTypes.SVData; entryHeight: CARDINAL = 15; -- height of a line of items entryVSpace: CARDINAL = 2; -- vertical leading between lines entryHSpace: CARDINAL = 2; -- horizontal space between items on a line column1: CARDINAL = 200; -- horizontal space between margin and column 1; column2: CARDINAL = 250; -- horizontal space between margin and column 2. column3: CARDINAL = 500; -- horizontal space between margin and column 3; fullColumn: CARDINAL = 600; -- the width of the standard large left column. boldFont: VFonts.Font; -- initialized in Init below; PopUpMenuEntry: TYPE = RECORD [ name: Rope.ROPE, input: LIST OF REF ANY ]; ExtractChoiceList: PROC [menu: LIST OF PopUpMenuEntry] RETURNS [choices: LIST OF Rope.ROPE] = { pos: LIST OF Rope.ROPE; newCell: LIST OF Rope.ROPE; IF menu = NIL THEN ERROR; choices _ CONS[menu.first.name, NIL]; pos _ choices; FOR l: LIST OF PopUpMenuEntry _ menu.rest, l.rest UNTIL l = NIL DO newCell _ CONS[l.first.name, NIL]; pos.rest _ newCell; pos _ newCell; ENDLOOP; }; QueuePopUpMenuAction: PROC [label: Rope.ROPE, menu: LIST OF PopUpMenuEntry, svData: SVData, onceOnly: BOOL _ TRUE] = { index: NAT; choices: LIST OF Rope.ROPE _ ExtractChoiceList[menu]; DO index _ PopUpSelection.Request[header: label, choice: choices]; IF index < 0 THEN ERROR; IF index = 0 THEN RETURN; FOR entries: LIST OF PopUpMenuEntry _ menu, entries.rest UNTIL entries = NIL DO IF index = 1 THEN { SVUserInput.EventNotify[svData, entries.first.input]; EXIT; }; index _ index - 1; REPEAT FINISHED => ERROR; ENDLOOP; IF onceOnly THEN RETURN; ENDLOOP; }; BuildControlPanel: PUBLIC PROC [svData: SVData, windowMenu: Menus.Menu, workingDirectory: Rope.ROPE] = { BuildFileMenuLine[svData]; BuildMasterMenuLine[svData]; BuildGravityLine[svData]; BuildSpecial3DLine[svData]; BuildFeedbackLine[svData]; }; BuildFileMenuLine: PROC [svData: SVData] = { nextX: INTEGER; interpressMenu: AtomButtons.ButtonLineEntry _ [popUpButton[ "Interpress", LIST[ [LIST[$ToIP], "ToIP", "Writes an interpress master to selected filename", boldFont], [LIST[$StorePoly], "StorePoly", "Stores a polygonal scene representation to selected filename"] ], -1, FALSE, boldFont ]]; svData.height _ svData.height + entryVSpace; nextX _ AtomButtons.BuildButtonLine [svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[ [button["Clear", LIST[LIST[$Clear]], -1, FALSE, NIL, ConfirmClear]], [button["Restore", LIST[LIST[$Restore]], -1, FALSE, NIL, ConfirmReset]], [button["Get", LIST[LIST[$Get]], -1, FALSE, NIL, ConfirmGet]], [button["Store", LIST[LIST[$Store]], -1, FALSE, NIL, ConfirmStore]], [button["Save", LIST[LIST[$Save]]]], [button["Split", LIST[LIST[$Split]]]], [button["Erase", LIST[LIST[$Erase]]]], interpressMenu ]]; nextX _ AtomButtons.BuildUnQueuedButtonLine [svData.outer, nextX, svData.height, svData, LIST[ ["Script", button, ScriptMenu, NIL, 0, -1, FALSE, NIL, boldFont], ["CastRays", button, CastRaysMenu, NIL, 0, -1, FALSE, NIL, boldFont], ["Revive!", button, ReviveButton] ]]; svData.height _ svData.height + entryVSpace + entryHeight; }; ReviveButton: Menus.ClickProc = { svData: SVData _ NARROW[clientData]; SVMouseEvent.ResetMouseMachinery[svData]; CodeTimer.ResetTable[CodeTimer.GetTable[$Solidviews]]; SlackProcess.Restart[svData.slackHandle]; svData.refresh.suppressRefresh _ FALSE; svData.aborted _ ALL[FALSE]; IF mouseButton#blue THEN SVWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, svData: svData, remake: triggerBag, backgndOK: FALSE, edited: FALSE, okToClearFeedback: TRUE] }; BuildMasterMenuLine: PROC [svData: SVData] = { nextX: INTEGER; nextX _ AtomButtons.BuildUnQueuedButtonLine [svData.outer, 0, svData.height, svData, LIST[ ["Debug", button, DebugMenu, NIL, 0, -1, FALSE, NIL, boldFont] ]]; nextX _ AtomButtons.BuildButtonLine [svData.outer, nextX, svData.height, svData, SVUserInput.EventNotify, LIST[ [button["Refresh!", LIST[LIST[$DrawSceneButton]]]], [button["DrawColor", LIST[LIST[$DrawColor]]]], [button["DrawB&W", LIST[LIST[$DrawBlackAndWhite]]]], [button["KillSelections", LIST[LIST[$KillSelectionsButton]]]], [button["DeleteJacks", LIST[LIST[$DeleteJacksButton]]]] ]]; svData.height _ svData.height + entryVSpace + entryHeight; }; -- end of BuildMasterMenuLine GravityExtentData: TYPE = REF GravityExtentDataObj; GravityExtentDataObj: TYPE = SVInterfaceTypes.GravityExtentDataObj; GravityExtentRepaint: PROC [dc: Imager.Context, clientData: REF ANY, buttonData: REF ANY, button: Viewer] = { caretPoint: Point2d; ged: GravityExtentData _ NARROW[buttonData]; extent: REAL _ ged.extent; Imager.TranslateT[dc, [button.ww, button.wh/2.0]]; caretPoint _ [-extent, 0.0]; SVDraw.DrawCaret[dc, caretPoint]; }; BuildGravityLine: PROC [svData: SVData] = { nextX: NAT _ 0; svData.hitTest.gravityTypeMenu _ AtomButtons.BuildEnumTypeSelection[viewer: svData.outer, x: 0, y: svData.height, maxWidth: 144, clientData: svData, handleProc: SVUserInput.EventNotify, title: "GravType:", default: "PreferPoints", borderOnButtons: TRUE, style: flipThru, allInOneRow: TRUE, buttonNames: LIST["StrictDistance", "PreferLines", "PreferPoints"], atom: $GravityChoiceChange]; svData.hitTest.gravityType _ pointsPreferred; nextX _ svData.hitTest.gravityTypeMenu.nextx; nextX _ AtomButtons.BuildButtonLine[ svData.outer, nextX + entryHSpace, svData.height, svData, SVUserInput.EventNotify, LIST[ [label["GravExtent:"]] ]]; nextX _ GraphicsButton.BuildGraphicsButton[ container: svData.outer, x: nextX + entryHSpace, y: svData.height, w: 60, -- changed from 72 to make more room in line h: entryHeight, clientData: svData, choices: LIST[ [LIST[$GravityExtentChange, $ValueUp]], [LIST[$GravityExtentChange, $InitialValue]], [LIST[$GravityExtentChange, $ValueDown]]], handleProc: SVUserInput.EventNotify, repaintProc: GravityExtentRepaint, buttonData: NEW[GravityExtentDataObj _ [extent: SVEditUser.GetDefaultGravityExtent[]]], updateProc: GravityExtentInSVData ]; [svData.hitTest.gravButton, nextX] _ AtomButtons.BuildTwoStateButton[viewer: svData.outer, x: nextX + 2*entryHSpace, y: svData.height, clientData: svData, handleProc: SVUserInput.EventNotify, name: "Gravity", action: LIST[$ToggleGravity], init: on]; [svData.hitTest.midpointButton, nextX] _ AtomButtons.BuildTwoStateButton[viewer: svData.outer, x: nextX + entryHSpace, y: svData.height, clientData: svData, handleProc: SVUserInput.EventNotify, name: "Midpoints", action: LIST[$ToggleMidpoints], init: off]; svData.height _ svData.height + entryHeight; }; BuildSpecial3DLine: PROC [svData: SVData] = { nextX: INTEGER; bigStringSize: NAT _ VFonts.StringWidth["///Users/Name.pa/Solidviews/PictureName.pic"]; smallStringSize: NAT _ VFonts.StringWidth["WireframeStyle"]; threeNumberSize: NAT _ VFonts.StringWidth["18, 18, 18"]; nextX _ AtomButtons.BuildButtonLine [svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[ [button["Style:", LIST[LIST[$StylePrompt]] ]], [label["Shaded", SceneStyleInSVData, smallStringSize]], [button["CoordsMode", LIST[LIST[$ShowCoordsMode]], -1, FALSE, NIL, NIL, ShowCoordsInSVData]], [button["x,y,z:", LIST[LIST[$XYZPrompt]]]], [text["0, 0, 0", XYZViewInSVData, threeNumberSize]], [button["Selected", LIST[LIST[$Selected]], -1, FALSE, NIL, NIL, SelectedInSVData]], [button["2Buffer", LIST[LIST[$DoubleBuffer]], -1, FALSE, NIL, NIL, DoubleBufferInSVData]] ]]; svData.height _ svData.height + entryVSpace + entryHeight; }; -- end of BuildSpecial3DLine BuildFeedbackLine: PROC [svData: SVData] = { nextX: NAT _ AtomButtons.BuildButtonLine[svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[ [label["Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Line", FeedbackLineInSVData, fullColumn]] ]]; svData.height _ svData.height + entryHeight; }; ConfirmClear: PUBLIC PROC [clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; scene: Scene _ svData.scene; rope: Rope.ROPE; dirty: BOOL; dirty _ svData.outer.newVersion; IF dirty THEN rope _ "Confirm discard of edits" ELSE rope _ "Confirm emptying of viewer"; Feedback.AppendHerald[svData.feedback, rope, oneLiner]; }; ConfirmReset: PUBLIC PROC [clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; scene: Scene _ svData.scene; dirty: BOOL; dirty _ svData.outer.newVersion; IF dirty THEN Feedback.PutFHerald[svData.feedback, oneLiner, "Confirm discard of edits"] ELSE Feedback.PutFHerald[svData.feedback, oneLiner, "Confirm reset of %g", [rope[scene.name]]]; }; -- end of ConfirmReset ConfirmSave: PUBLIC PROC [clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; scene: Scene _ svData.scene; exists: BOOL; rope: Rope.ROPE; exists _ SVFiles.FileExists[scene.name]; IF exists THEN rope _ IO.PutFR["Confirm Save to %g [Old File]", [rope[scene.name]]] ELSE { rope _ IO.PutFR["%g doesn't exist. Use Store", [rope[scene.name]]]; Feedback.Blink[svData.feedback] }; Feedback.Append[svData.feedback, rope, oneLiner]; }; ConfirmStore: PUBLIC PROC [clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; editToolData: EditToolData _ NARROW[svData.editToolData]; scene: Scene _ svData.scene; picName: Rope.ROPE _ ViewerTools.GetSelectionContents[]; fullName, wdir: Rope.ROPE; exists: BOOL; success: BOOL _ TRUE; rope: Rope.ROPE; IF Rope.Length[picName] = 0 THEN { Feedback.Append[svData.feedback, "Please select a file name.", oneLiner]; Feedback.Blink[svData.feedback]; RETURN; }; wdir _ editToolData.originalWorkingDirectory; [fullName,,] _ FS.ExpandName[picName, wdir ! FS.Error => IF error.group = user THEN { Feedback.Append[svData.feedback, Rope.Concat["Store: ", error.explanation], oneLiner]; success _ FALSE; CONTINUE; } ]; exists _ SVFiles.FileExists[fullName]; IF exists THEN rope _ IO.PutFR["Confirm Store of %g [Old File]", [rope[fullName]]] ELSE rope _ IO.PutFR["Confirm Store to %g [New File]", [rope[fullName]]]; Feedback.AppendHerald[svData.feedback, rope, oneLiner]; }; ConfirmGet: PUBLIC PROC [clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; editToolData: EditToolData _ NARROW[svData.editToolData]; scene: Scene _ svData.scene; picName: Rope.ROPE _ ViewerTools.GetSelectionContents[]; fullName, wdir: Rope.ROPE; success: BOOL _ TRUE; dirty: BOOL; IF Rope.Length[picName] = 0 THEN { Feedback.Append[svData.feedback, "Please select a file name.", oneLiner]; Feedback.Blink[svData.feedback]; RETURN; }; wdir _ editToolData.originalWorkingDirectory; [fullName,,] _ FS.ExpandName[picName, wdir ! FS.Error => IF error.group = user THEN { Feedback.Append[svData.feedback, Rope.Concat["Get: ", error.explanation], oneLiner]; success _ FALSE; CONTINUE; } ]; IF NOT success THEN RETURN; dirty _ svData.outer.newVersion; IF dirty THEN Feedback.PutF[svData.feedback, oneLiner, "Confirm discard of edits and load of %g", [rope[fullName]]] ELSE Feedback.PutF[svData.feedback, oneLiner, "Confirm load of %g", [rope[fullName]]]; }; -- end of ConfirmGet DebugMenu: Menus.ClickProc = { svData: SVData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry; menu _ LIST [ ["DrawBoundBoxes", LIST [$DrawBoundBoxes]], ["DrawBoundSpheres", LIST [$DrawBoundSpheres]], ["DrawCoordSystems", LIST [$DrawCoordSystems]], ["DrawPoint", LIST [$DrawPoint]], ["Draw Selection Box", LIST [$DrawSelectionBox]], ["CrossHairs", LIST [$CrossHairs]], ["TestGravity", LIST [$TestGravity]], ["Reset Statistics", LIST [$ResetStatistics]], ["Print Statistics", LIST [$PrintStatistics]] ]; QueuePopUpMenuAction["Debug", menu, svData, mouseButton#blue]; }; CastRaysMenu: Menus.ClickProc = { svData: SVData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry _ LIST [ ["RayCast", LIST [$RayCast]], ["StopRays", LIST [$StopRays]], ["ARay", LIST [$ARay]] ]; choices: LIST OF Rope.ROPE _ ExtractChoiceList[menu]; index: NAT _ PopUpSelection.Request[header: "SVCastRays", choice: choices]; SELECT index FROM =0 => RETURN; =1 => SVEvent.RayCast[LIST[$RayCast], svData]; =2 => SVEvent.StopRays[LIST[$StopRays], svData]; =3 => SVEvent.ARay[LIST[$ARay], svData]; ENDCASE => ERROR; }; ScriptMenu: Menus.ClickProc = { svData: SVData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry _ LIST [ ["OpenScript", LIST [$ScriptAction, $Open]], ["AppendToScript", LIST [$ScriptAction, $Append]], ["CloseScript", LIST [$ScriptAction, $Close]], ["PlaybackScript", LIST [$ScriptAction, $Playback]], ["FastPlayScript", LIST [$ScriptAction, $FastPlay]] ]; choices: LIST OF Rope.ROPE _ ExtractChoiceList[menu]; index: NAT _ PopUpSelection.Request[header: "Script", choice: choices]; SELECT index FROM =0 => RETURN; =1 => SVEvent.OpenScript[parent, clientData, mouseButton, shift, control]; =2 => SVEvent.AppendToScript[parent, clientData, mouseButton, shift, control]; =3 => SVEvent.CloseScript[parent, clientData, mouseButton, shift, control]; =4 => SVEvent.PlaybackScript[parent, clientData, mouseButton, shift, control]; =5 => SVEvent.FastPlayScript[parent, clientData, mouseButton, shift, control]; ENDCASE => ERROR; }; ConfirmRayCast: PUBLIC PROC [clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; exists: BOOL; aisFileRope: Rope.ROPE; redRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[aisFileRope], "-red.ais"]; greenRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[aisFileRope], "-green.ais"]; blueRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[aisFileRope], "-blue.ais"]; rope: Rope.ROPE; exists _ SVFiles.FileExists[aisFileRope]; rope _ IO.PutFR["Confirm raycast to %g.", [rope[aisFileRope]]]; IF exists THEN rope _ Rope.Concat[rope, " [Old File]"] ELSE rope _ Rope.Concat[rope, " [New File]"]; Feedback.AppendHerald[svData.feedback, rope, oneLiner]; }; GravityExtentInSVData: AtomButtonsTypes.UpdateGraphicsButtonProc = { svData: SVData _ NARROW[clientData]; svData.hitTest.gravityExtentButton _ stateInfo; }; FeedbackLineInSVData: AtomButtonsTypes.InitButtonProc = { svData: SVData _ NARROW[clientData]; feedback: FeedbackData _ Feedback.RegisterFeedback[button, $Solidviews]; svData.feedback _ feedback; }; ShowCoordsInSVData: AtomButtons.InitButtonProc = { svData: SVData _ NARROW[clientData]; svData.textSection.showCoords _ button; }; SceneStyleInSVData: AtomButtons.InitButtonProc = { svData: SVData _ NARROW[clientData]; svData.textSection.viewStyle _ button; }; SelectedInSVData: AtomButtons.InitButtonProc = { svData: SVData _ NARROW[clientData]; svData.textSection.selected _ button; }; XYZViewInSVData: AtomButtons.InitButtonProc = { svData: SVData _ NARROW[clientData]; svData.textSection.xyz _ button; }; DoubleBufferInSVData: AtomButtons.InitButtonProc = { svData: SVData _ NARROW[clientData]; svData.textSection.doubleBuffer _ button; Buttons.SetDisplayStyle[svData.textSection.doubleBuffer, $WhiteOnBlack]; }; Init: PROC = { boldFont _ VFonts.EstablishFont[family: "Helvetica", size: 10, bold: TRUE, italic: FALSE, defaultOnFailure: TRUE]; }; Init[]; END. ®SVMenusImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last edited by Bier on January 28, 1987 11:16:05 pm PST Contents: Routines for building the control panel on each solid viewer. Non-destructive (copies the menu names). Build All of the Control Panel Menus Clear, Restore, Get, Store, Save, Split, Erase, Interpress, Script, CastRays, Revive! Space down from the top of the viewer. This section implements a set of buttons, text windows, and options listers in this format: Draw: BBox BSphere Scene Coords Point Cross Color B&W Dither CoordsMode [svData.hitTest.heuristicsButton, nextX] _ AtomButtons.BuildTwoStateButton[viewer: svData.outer, x: nextX + entryHSpace, y: svData.height, clientData: svData, handleProc: SVUserInput.EventNotify, name: "Heuristics", action: LIST[$ToggleHeuristics], init: IF SVEditTool.GetDefaultHeuristics[] THEN on ELSE off]; This section implements a set of buttons, text windows, and options listers in this format: Text: Style: x,y,z: Selected 2Buffer AIS: Kill Selections DeleteJacks File Line Menus: Master Line Menus: QueuePopUpMenuAction["SVCastRays", menu, svData, mouseButton#blue]; InterpressMenu: Menus.ClickProc = { svData: SVData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry; menu _ LIST [ ["ToIP", LIST [$ToIP]], ["StorePoly", LIST [$StorePoly]] ]; QueuePopUpMenuAction["Interpress", menu, svData, mouseButton#blue]; }; IF mouseButton = blue THEN { -- black and white only } ELSE { exists _ SVFiles.FileExists[aisFileRope] OR SVFiles.FileExists[redRope] OR SVFiles.FileExists[greenRope] OR SVFiles.FileExists[blueRope]; rope _ IO.PutFR["Confirm raycast to %g [-red, -green, -blue, plain].ais", [rope[SVFiles.FilenameMinusExtension[aisFileRope]]]]; IF exists THEN rope _ Rope.Concat[rope, " [Old Files]"] ELSE rope _ Rope.Concat[rope, " [New Files]"]; }; Gravity Line Menus: Feedback Line Wiring Up Buttons to the Container: Ê;˜J˜Icodešœ™Kšœ Ïmœ1™Kš œžœžœžœžœ˜DKšœ$˜$Kšœžœžœ ˜&Kšœžœžœ ˜&K˜K˜—šœYžœ˜^Kšœžœ žœžœ ˜AKšœ#žœ žœžœ ˜EKšœ!˜!K˜K˜—Lšœ:˜:L˜L˜—šÐbn œ˜!Kšœžœ ˜$Kšœ)˜)Kšœ6˜6Kšœ)˜)Kšœ!žœ˜'Kšœžœžœ˜Kš žœžœtžœ žœžœ˜ºK˜K˜—šŸœžœ˜.Lšœ\™\LšŸœC™GKšœžœ˜šœUžœ˜ZKšœžœ žœžœ ˜>K˜—šœjžœ˜oKšœžœžœ˜3Kšœžœžœ˜.Kšœžœžœ˜4Kšœžœžœ˜>Kšœžœžœ˜7K˜K˜—Lšœ:˜:Lšœ ˜ L˜—Kšœžœžœ˜3Kšœžœ)˜Cš Ÿœžœ"žœžœžœžœ˜mK˜Kšœžœ ˜,Kšœžœ˜Kšœ2˜2Kšœ˜Kšœ!˜!K˜K˜—šŸœžœ˜+Kšœžœ˜Kšœ!˜!šœ_˜_Kšœ˜Kšœ$˜$Kšœ,˜,Kšœžœ žœ˜:Kšœ žœ2˜CKšœ˜—Kšœ-˜-K˜Kšœ-˜-šœ$˜$šœSžœ˜XKšœÏb œ˜—Kšœ˜K˜—šœ+˜+Kšœ˜Kšœ˜Kšœ˜Kšœ ,˜3Kšœ˜Kšœ˜šœ žœ˜Kšœžœ"˜'Kšœžœ'˜,Kšœžœ%˜*—Kšœ$˜$Kšœ"˜"Kšœ žœH˜WKšœ!˜!Kšœ˜K˜—Kšœ$˜$šœa˜aKšœ˜Kšœ$˜$Kšœ¢œ˜Kšœžœ˜Kšœ ˜ K˜—Kšœ(˜(šœ_˜_Kšœ˜Kšœ$˜$Kšœ¢ œ˜Kšœžœ˜Kšœ ˜ K˜—Kšœ*™*šœ_™_Kšœ™Kšœ$™$Kšœ¢ œ™Kšœžœ™ Kšœžœ#žœžœ™=K˜—Kšœ,˜,K˜K˜—šŸœžœ˜-Lšœ\™\LšœG™GLšžœ*™-L˜Kšœžœ˜KšœžœE˜WKšœžœ(˜˜>K˜—š¡ œ˜!Kšœžœ ˜$šœžœžœžœ˜%Kšœ žœ ˜Kšœ žœ˜Kšœ žœ ˜K˜—Kšœ žœžœžœ˜5KšœžœA˜Kšžœž˜Kšœžœ˜ Kšœžœ˜.Kšœžœ˜0Kšœžœ˜(Kšžœžœ˜—KšœC™CK˜—š¡ œ˜Kšœžœ ˜$šœžœžœžœ˜%Kšœžœ˜,Kšœžœ˜2Kšœžœ˜.Kšœžœ˜4Kšœžœ˜3K˜—Kšœ žœžœžœ˜5Kšœžœ=˜Gšžœž˜Kšœžœ˜ KšœJ˜JKšœN˜NKšœK˜KKšœN˜NKšœN˜NKšžœžœ˜—K˜—š¡œ™#Kšœžœ ™$Kšœžœžœ™šœžœ™ Kšœ žœ ™Kšœžœ™ K™—KšœC™CK™—š Ÿœžœžœžœžœ˜5Jšœžœ ˜$Jšœžœ˜ Jšœžœ˜JšœžœH˜ZJšœžœJ˜^JšœžœI˜\Jšœ žœ˜šžœžœ ™4Jšœ)˜)Jšœžœ6˜?Jšžœžœ(˜6Jšžœ)˜-Jšœ™—šžœ™Jšœ)žœžœžœ™‰Jšœžœv™Jšžœžœ)™7Jšžœ*™.Jšœ™—Jšœ7˜7Jšœ˜J˜—K™K™šŸœ/˜DKšœžœ ˜$Kšœ/˜/K˜K˜—K™ šŸœ%˜9Kšœžœ ˜$KšœH˜HKšœ˜K˜—K™K™#K˜šŸœ ˜2Kšœžœ ˜$Kšœ'˜'K˜K˜—šŸœ ˜2Kšœžœ ˜$Kšœ&˜&K˜K˜—šŸœ ˜0Kšœžœ ˜$Kšœ%˜%K˜K˜—šŸœ ˜/Kšœžœ ˜$Kšœ ˜ K˜K˜—šŸœ ˜4Kšœžœ ˜$Kšœ)˜)LšœH˜HK˜K˜—šŸœžœ˜KšœEžœ žœžœ˜rK˜K˜—Kšœ˜K˜Kšžœ˜K˜J˜—…—=îW×