<> <> <> <> <> DIRECTORY SB, Basics, BasicTime, Convert, Buttons, Commander, CommandTool, Containers, IO, FileNames, FS, Labels, Menus, MessageWindow, Rope, VFonts, ViewerClasses, ViewerOps, ViewerTools; SBTool: CEDAR PROGRAM IMPORTS BasicTime, Buttons, Commander, CommandTool, Convert, Containers, IO, FileNames, FS, Labels, Menus, MessageWindow, Rope, SB, VFonts, ViewerOps, ViewerTools = BEGIN SBToolHandle: TYPE = REF SBToolRec; -- For data of a particular instance SBToolRec: TYPE = RECORD [ outer: Containers.Container _ NIL, height: CARDINAL _ 0, -- measured from top league: SB.League _ NIL, file: Rope.ROPE _ NIL, lVwr: LeagueViewers, team: SB.Team _ 0, tVwr: TeamViewersSeq _ NIL, member: SB.Member _ NIL, iVwr: IndividualViewers ]; LeagueViewers: TYPE = RECORD [ read: Labels.Label _ NIL, write: Labels.Label _ NIL, file: ViewerClasses.Viewer _ NIL, year: ViewerClasses.Viewer _ NIL, time: ViewerClasses.Viewer _ NIL, players: ViewerClasses.Viewer _ NIL, keeps: ViewerClasses.Viewer _ NIL, males: ViewerClasses.Viewer _ NIL, females: ViewerClasses.Viewer _ NIL, paid: ViewerClasses.Viewer _ NIL, unpaid: ViewerClasses.Viewer _ NIL, dolIn: ViewerClasses.Viewer _ NIL, dolOut: ViewerClasses.Viewer _ NIL ]; TeamViewersSeq: TYPE = REF TeamViewersRec; TeamViewersRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF TeamViewers]; TeamViewers: TYPE = RECORD [ <> <> dIndex: ViewerClasses.Viewer _ NIL, players: ViewerClasses.Viewer _ NIL, keeps: ViewerClasses.Viewer _ NIL, males: ViewerClasses.Viewer _ NIL, females: ViewerClasses.Viewer _ NIL, points: ViewerClasses.Viewer _ NIL, prtctd: ViewerClasses.Viewer _ NIL ]; IndividualViewers: TYPE = RECORD [ edited: Labels.Label _ NIL, name: ViewerClasses.Viewer _ NIL, sse: ViewerClasses.Viewer _ NIL, type: ViewerClasses.Viewer _ NIL, rating: ViewerClasses.Viewer _ NIL, team: ViewerClasses.Viewer _ NIL, paid: ViewerClasses.Viewer _ NIL, group: ViewerClasses.Viewer _ NIL, shirt: ViewerClasses.Viewer _ NIL, sex: ViewerClasses.Viewer _ NIL, addr: ViewerClasses.Viewer _ NIL, tnum: ViewerClasses.Viewer _ NIL, pos: ViewerClasses.Viewer _ NIL, atten: ViewerClasses.Viewer _ NIL, comnt: ViewerClasses.Viewer _ NIL, dIndex: ViewerClasses.Viewer _ NIL ]; entryHeight: CARDINAL = 15; entryVSpace: CARDINAL = 2; entryLeftBias: CARDINAL _ 5; dataFont: VFonts.Font _ VFonts.EstablishFont["TimesRoman", 10, FALSE]; labelFont: VFonts.Font _ VFonts.EstablishFont["TimesRoman", 10, TRUE]; MakeSBTool: Commander.CommandProc = { tool: SBToolHandle _ NEW[SBToolRec]; comlist: LIST OF Rope.ROPE _ CommandTool.ParseToList[cmd].list; tool.file _ IF comlist#NIL THEN comlist.first ELSE NIL; tool.outer _ Containers.Create[[ name: "Softball Tool", iconic: FALSE, column: left, menu: Menus.CreateMenu[], scrollable: TRUE ]]; Menus.AppendMenuEntry[ menu: tool.outer.menu, entry: Menus.CreateEntry[ name: "Update", proc: RePaint, clientData: tool ] ]; tool.league _ NIL; tool.height _ entryHeight + entryVSpace; BVwr ["ReadFile", 0, 0, LeagueRead, tool]; tool.lVwr.write _ LVwr ["WriteFile", 0, 40, 60, 20, LeagueWrite, tool]; tool.lVwr.file _ TVwr ["File:", 1, 0, 10, 70, LeagueFile, tool]; tool.lVwr.year _ TVwr ["Year:", 2, 0, 10, 10, LeagueYear, tool]; tool.lVwr.time _ DVwr ["Time:", 2, 20, 30, 40, RePaint, tool]; tool.lVwr.players _ DVwr ["Players:", 3, 0, 10, 10, RePaint, tool]; tool.lVwr.keeps _ DVwr ["Keeps:", 4, 0, 10, 10, RePaint, tool]; tool.lVwr.males _ DVwr ["Males:", 3, 20, 30, 10, RePaint, tool]; tool.lVwr.females _ DVwr ["Females:", 4, 20, 30, 10, RePaint, tool]; tool.lVwr.paid _ DVwr ["Paid:", 3, 40, 50, 10, RePaint, tool]; tool.lVwr.unpaid _ DVwr ["Unpaid:", 4, 40, 50, 10, RePaint, tool]; tool.lVwr.dolIn _ DVwr ["$ paid:", 3, 60, 70, 10, RePaint, tool]; tool.lVwr.dolOut _ DVwr ["$ owed:", 4, 60, 70, 10, RePaint, tool]; tool.height _ tool.height + (5+2)*(entryHeight + entryVSpace); << BVwr ["Find", 0, 0, PlayerFindM, tool];>> << BVwr ["Team", 0, 8, PlayerNextT, tool];>> << BVwr ["Mate", 0, 16, PlayerNextMate, tool];>> BVwr ["Marry", 0, 0, PlayerMarry, tool]; BVwr ["Divorce", 0, 10, PlayerDivorce, tool]; BVwr ["Add", 0, 20, PlayerAddNew, tool]; BVwr ["Del", 0, 30, PlayerDelOld, tool]; IBVwr ["Draft", 0, 40, Draft, tool, 20]; BVwr ["Undo", 0, 50, PlayerUnDo, tool]; tool.iVwr.edited _ LVwr ["Mod", 0, 60, 65, 10, PlayerCngOld, tool]; tool.iVwr.name _ TVwr ["Name:", 1, 0, 10, 30, PlayerName, tool]; tool.iVwr.sse _ TVwr ["Mate:", 1, 40, 50, 30, PlayerSSE, tool]; tool.iVwr.team _ DVwr ["Team:", 2, 0, 10, 30, PlayerTeam, tool]; tool.iVwr.sex _ DVwr ["Sex:", 2, 40, 50, 10, PlayerSex, tool]; tool.iVwr.type _ DVwr ["Type:", 2, 60, 70, 20, PlayerType, tool]; tool.iVwr.rating _ DVwr ["Rating:", 3, 0, 10, 10, PlayerRating, tool]; tool.iVwr.shirt _ DVwr ["Shirt:", 3, 20, 30, 10, PlayerShirt, tool]; tool.iVwr.paid _ DVwr ["Paid:", 3, 40, 50, 10, PlayerPaid, tool]; tool.iVwr.group _ DVwr ["Group:", 3, 60, 70, 20, PlayerGroup, tool]; tool.iVwr.dIndex _ TVwr ["DIndex:", 4, 0, 10, 30, PlayerDIndex, tool]; tool.iVwr.pos _ TVwr ["Pos:", 4, 40, 50, 10, PlayerPos, tool]; tool.iVwr.atten _ TVwr ["Atten:", 4, 60, 70, 20, PlayerAtten, tool]; tool.iVwr.addr _ TVwr ["Addr:", 5, 0, 10, 30, PlayerAddr, tool]; tool.iVwr.tnum _ TVwr ["Tel:", 5, 40, 50, 30, PlayerTNum, tool]; tool.iVwr.comnt _ TVwr ["Cmnt:", 6, 0, 10, 60, PlayerComnt, tool]; <<>> tool.height _ tool.height + (7+1)*(entryHeight + entryVSpace); ViewerOps.SetOpenHeight[tool.outer, tool.height]; -- hint our desired height ViewerOps.PaintViewer[tool.outer, all]; -- reflect above change; IF tool.file=NIL THEN { year: [86..150] _ BasicTime.Unpack[BasicTime.Now[]].year-1900; tool.file _ IO.PutFR["SB%g.sum", IO.int[year]]}; tool.file _ FileNames.ConvertToSlashFormat[FS.ExpandName[tool.file].fullFName]; SetTVwr[tool.lVwr.file, tool.file] }; AVwr: PROC[row, tCol, tWid: CARDINAL, handle: SBToolHandle] RETURNS[textViewer: ViewerClasses.Viewer] = { textViewer _ ViewerTools.MakeNewTextViewer[ [ parent: handle.outer, wx: tCol*VFonts.CharWidth['0] + entryLeftBias, ww: tWid*VFonts.CharWidth['0], wy: row* (entryHeight + entryVSpace)+1 + handle.height, wh: entryHeight, scrollable: FALSE, border: FALSE]]; ViewerTools.InhibitUserEdits[textViewer]}; IHdlRec: TYPE = RECORD[team: SB.Team, handle: SBToolHandle]; IBVwr: PROC[name: Rope.ROPE, row, lCol: CARDINAL, proc: Buttons.ButtonProc, handle: SBToolHandle, team: SB.Team] = { button: Buttons.Button _ Buttons.Create[ info: [ name: name, parent: handle.outer, wx: lCol*VFonts.CharWidth['0] + entryLeftBias, wy: row* (entryHeight + entryVSpace) + handle.height, wh: entryHeight, border: FALSE ], proc: proc, guarded: FALSE, font: labelFont, clientData: NEW[IHdlRec_[team, handle]] ]; }; BVwr: PROC[name: Rope.ROPE, row, lCol: CARDINAL, proc: Buttons.ButtonProc, handle: SBToolHandle] = { button: Buttons.Button _ Buttons.Create[ info: [ name: name, parent: handle.outer, wx: lCol*VFonts.CharWidth['0] + entryLeftBias, wy: row* (entryHeight + entryVSpace) + handle.height, wh: entryHeight, border: FALSE ], proc: proc, guarded: FALSE, font: labelFont, clientData: handle]; }; DVwr: PROC [name: Rope.ROPE, row, bCol, tCol, tWid: CARDINAL, proc: Buttons.ButtonProc, handle: SBToolHandle] RETURNS[textViewer: ViewerClasses.Viewer] = {RETURN[TVwr[name, row, bCol, tCol, tWid, proc, handle, TRUE]]}; TVwr: PROC [name: Rope.ROPE, row, bCol, tCol, tWid: CARDINAL, proc: Buttons.ButtonProc, handle: SBToolHandle, noEdit: BOOL _ FALSE] RETURNS[textViewer: ViewerClasses.Viewer] = { button: Buttons.Button _ Buttons.Create[ info: [ name: name, parent: handle.outer, wx: bCol*VFonts.CharWidth['0] + entryLeftBias, wy: row* (entryHeight + entryVSpace) + handle.height, wh: entryHeight, border: FALSE ], guarded: FALSE, font: labelFont, proc: proc, clientData: handle]; textViewer _ ViewerTools.MakeNewTextViewer[ [ parent: handle.outer, wx: tCol*VFonts.CharWidth['0] + entryLeftBias, ww: tWid*VFonts.CharWidth['0], wy: row* (entryHeight + entryVSpace)+1 + handle.height, wh: entryHeight, scrollable: FALSE, border: FALSE]]; IF noEdit THEN ViewerTools.InhibitUserEdits[textViewer]}; LVwr: PROC [name: Rope.ROPE, row, bCol, tCol, tWid: CARDINAL, proc: Buttons.ButtonProc, handle: SBToolHandle] RETURNS[textViewer: ViewerClasses.Viewer] = { button: Buttons.Button _ Buttons.Create[ info: [ name: name, parent: handle.outer, wx: bCol*VFonts.CharWidth['0] + entryLeftBias, wy: row* (entryHeight + entryVSpace) + handle.height, wh: entryHeight, border: TRUE ], guarded: FALSE, font: labelFont, proc: proc, clientData: handle]; textViewer _ Labels.Create[ [ parent: handle.outer, wx: tCol*VFonts.CharWidth['0] + entryLeftBias, ww: tWid*VFonts.CharWidth['0], wy: row* (entryHeight + entryVSpace)+1 + handle.height, wh: entryHeight, border: FALSE]] }; <<>> <> <<[parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] ;>> <> <<>> SetTVwr: PROC[viewer: ViewerClasses.Viewer, contents: Rope.ROPE] = {ViewerTools.SetContents[viewer, contents]}; <<>> SetLVwr: PROC[label: Labels.Label, contents: Rope.ROPE] ={Labels.Set[label, contents]}; <<>> RePaint: Menus.MenuProc = { RePaintLeague [parent, clientData]; RePaintTeams [parent, clientData]; RePaintMember [parent, clientData]}; RePaintLeague: Menus.MenuProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; IF league=NIL THEN RETURN; <> SetTVwr[sbTool.lVwr.file, league.file]; SetTVwr[sbTool.lVwr.year, IO.PutFR["%3g",IO.card[league.year]]]; SetLVwr[sbTool.lVwr.time, IO.PutR[IO.time[league.time]]]; SetLVwr[sbTool.lVwr.players, IO.PutFR["%3g",IO.card[league.players]]]; SetLVwr[sbTool.lVwr.keeps, IO.PutFR["%3g",IO.card[league.keeps]]]; SetLVwr[sbTool.lVwr.males, IO.PutFR["%3g",IO.card[league.males]]]; SetLVwr[sbTool.lVwr.females, IO.PutFR["%3g",IO.card[league.females]]]; SetLVwr[sbTool.lVwr.paid, IO.PutFR["%3g",IO.card[league.paid]]]; SetLVwr[sbTool.lVwr.unpaid, IO.PutFR["%3g",IO.card[league.unpaid]]]; SetLVwr[sbTool.lVwr.dolIn, IO.PutFR["%4g",IO.card[league.dollarsIn]]]; SetLVwr[sbTool.lVwr.dolOut, IO.PutFR["%4g",IO.card[league.dollarsOut]]] }; RePaintTeams: Menus.MenuProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; team: SB.Team _ sbTool.team; IF league=NIL THEN RETURN; <> FOR t: CARDINAL IN [0..sbTool.tVwr.size) DO <> SetLVwr[sbTool.tVwr[t].players, IO.PutFR["%3g",IO.card[league.teamStats[t].players]]]; SetLVwr[sbTool.tVwr[t].keeps, IO.PutFR["%3g",IO.card[league.teamStats[t].keeps]]]; SetLVwr[sbTool.tVwr[t].males, IO.PutFR["%3g",IO.card[league.teamStats[t].males]]]; SetLVwr[sbTool.tVwr[t].females, IO.PutFR["%3g",IO.card[league.teamStats[t].females]]]; SetLVwr[sbTool.tVwr[t].points, IO.PutFR["%3g",IO.card[league.teamStats[t].points]]]; SetLVwr[sbTool.tVwr[t].prtctd, IO.PutFR["%3g",IO.card[league.teamStats[t].prtctd]]]; SetTVwr[sbTool.tVwr[t].dIndex, IO.PutFR["%3g%g", IO.card[league.teamStats[t].dIndex], IO.rope[IF t = league.nextDTeam THEN " <" ELSE ""] ]]; ENDLOOP}; NULLMember: SB.Member _ NEW[SB.MemberRec _ [ ] ]; RePaintMember: Menus.MenuProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; mem: SB.Member _ sbTool.member; IF league=NIL THEN RETURN; IF mem=NIL THEN mem _ NULLMember; <> SetTVwr[ sbTool.iVwr.name, mem.fname.Cat [" ", mem.lname]]; SetTVwr[ sbTool.iVwr.sse, (IF mem.sse#NIL THEN mem.sse.fname.Cat[" ", mem.sse.lname] ELSE NIL)]; SetTVwr[sbTool.iVwr.team, league.teamNms [LOOPHOLE[mem.team]]]; SetTVwr[sbTool.iVwr.sex, league.sexNms [LOOPHOLE[mem.sex]]]; SetTVwr[sbTool.iVwr.type, league.typeNms [LOOPHOLE[mem.type]]]; SetTVwr[sbTool.iVwr.rating, league.ratingNms [LOOPHOLE[mem.rating]]]; SetTVwr[sbTool.iVwr.shirt, league.shirtNms [LOOPHOLE[mem.shirt]]]; SetTVwr[sbTool.iVwr.group, league.groupNms [LOOPHOLE[mem.group]]]; SetTVwr[sbTool.iVwr.paid, league.paidNms [LOOPHOLE[mem.paid]]]; SetTVwr[sbTool.iVwr.dIndex, IO.PutFR["%3g",IO.card[mem.dIndex]]]; SetTVwr[sbTool.iVwr.pos, mem.pos]; SetTVwr[sbTool.iVwr.atten, mem.atten]; SetTVwr[sbTool.iVwr.addr, mem.addr]; SetTVwr[sbTool.iVwr.tnum, mem.tnum]; SetTVwr[sbTool.iVwr.comnt, mem.comnt] }; LeagueRead: Buttons.ButtonProc = { league: SB.League; sbTool: SBToolHandle _ NARROW[clientData]; sbTool.file _ ViewerTools.GetContents[sbTool.lVwr.file]; league _ SB.ReadLeagueFile[sbTool.file]; IF league=NIL THEN { MessageWindow.Append[message: "File not found.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; sbTool.league _ league; sbTool.team _ 0; sbTool.member _ sbTool.league.members.first; IF sbTool.tVwr=NIL OR (sbTool.tVwr#NIL AND sbTool.tVwr.size#league.teamNms.size) THEN { IF sbTool.tVwr=NIL THEN { BVwr ["Team", 0, 0, Dummy, sbTool]; BVwr ["Players", 0, 17, Dummy, sbTool]; BVwr ["Keeps", 0, 26, Dummy, sbTool]; BVwr ["Males", 0, 33, Dummy, sbTool]; BVwr ["Females", 0, 41, Dummy, sbTool]; BVwr ["Points", 0, 50, Dummy, sbTool]; BVwr ["Prtctd", 0, 57, Dummy, sbTool]; BVwr ["DIndex", 0, 65, Dummy, sbTool]; sbTool.height _ sbTool.height + 2*(entryHeight + entryVSpace) } ELSE { FOR t: CARDINAL IN [0..sbTool.tVwr.size) DO <> ViewerOps.DestroyViewer[sbTool.tVwr[t].players ]; ViewerOps.DestroyViewer[sbTool.tVwr[t].keeps ]; ViewerOps.DestroyViewer[sbTool.tVwr[t].males ]; ViewerOps.DestroyViewer[sbTool.tVwr[t].females ]; ViewerOps.DestroyViewer[sbTool.tVwr[t].points ]; ViewerOps.DestroyViewer[sbTool.tVwr[t].prtctd ]; ViewerOps.DestroyViewer[sbTool.tVwr[t].dIndex ]; ENDLOOP; sbTool.height _ sbTool.height - (sbTool.tVwr.size+2)*(entryHeight + entryVSpace) }; sbTool.tVwr _ NEW[TeamViewersRec[league.teamNms.size]]; FOR t: CARDINAL IN [0..sbTool.tVwr.size) DO IBVwr [league.teamNms[t], 0, 0, Draft, sbTool, t]; <> sbTool.tVwr[t].players _ AVwr [0, 20, 8, sbTool]; sbTool.tVwr[t].keeps _ AVwr [0, 28, 8, sbTool]; sbTool.tVwr[t].males _ AVwr [0, 36, 8, sbTool]; sbTool.tVwr[t].females _ AVwr [0, 44, 8, sbTool]; sbTool.tVwr[t].points _ AVwr [0, 52, 8, sbTool]; sbTool.tVwr[t].prtctd _ AVwr [0, 60, 8, sbTool]; sbTool.tVwr[t].dIndex _ AVwr [0, 68, 8, sbTool]; sbTool.height _ sbTool.height + (entryHeight + entryVSpace); ENDLOOP; sbTool.height _ sbTool.height + 2*(entryHeight + entryVSpace); ViewerOps.SetOpenHeight[sbTool.outer, sbTool.height] }; RePaint[parent, clientData]; SetLVwr[sbTool.lVwr.write, ""] }; LeagueWrite: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; sbTool.league.file _ ViewerTools.GetContents[sbTool.lVwr.file]; sbTool.league.year _ Convert.CardFromRope[ViewerTools.GetContents[sbTool.lVwr.year]]; SB.Update[sbTool.league]; SB.WriteLeagueFiles[sbTool.league]; SetLVwr[sbTool.lVwr.write, ""] }; LeagueFile: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; ViewerTools.SetSelection[sbTool.lVwr.file] }; LeagueYear: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; ViewerTools.SetSelection[sbTool.lVwr.year] }; Dummy: Buttons.ButtonProc = { }; <> <> <> <> <> <> <> <> <> <> <> <> < 1,>> < 0,>> < (IF current=0 THEN 0 ELSE -1));>> <> <> PlayerFindM: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; member: SB.Member _ NIL; IF league=NIL THEN RETURN; SELECT mouseButton FROM red => { m: LIST OF SB.Member; FOR m _ league.members, m.rest WHILE m.rest#NIL DO IF m.first#sbTool.member THEN LOOP; sbTool.member _ m.rest.first; EXIT REPEAT FINISHED => sbTool.member _ league.members.first ENDLOOP}; yellow => { rec: SB.MemberRec; [member, rec] _ ExtractIndividualViewerFields[sbTool]; IF member = NIL THEN member _ SB.FindMemberName[league, rec.lname]; IF member = NIL THEN member _ SB.FindMemberName[league, rec.fname]; IF member = NIL THEN { FOR lst: LIST OF SB.Member _ league.members, lst.rest WHILE lst#NIL DO subStr: Rope.ROPE _ Rope.Substr[lst.first.lname, 0, Rope.Length[rec.lname]]; IF ~Rope.Equal[subStr, rec.lname, FALSE] THEN LOOP; member _ lst.first; EXIT ENDLOOP}; IF member = NIL THEN { FOR lst: LIST OF SB.Member _ league.members, lst.rest WHILE lst#NIL DO aChar: CHAR _ lst.first.lname.Fetch[0]; bChar: CHAR _ rec.lname.Fetch[0]; IF aChar <= 'Z AND aChar >= 'A THEN aChar _ aChar + ('a-'A); IF bChar <= 'Z AND bChar >= 'A THEN bChar _ bChar + ('a-'A); IF aChar < bChar THEN LOOP; member _ lst.first; EXIT ENDLOOP; IF member = NIL THEN member _ league.members.first; MessageWindow.Append[message: "Not found.", clearFirst: TRUE]; MessageWindow.Blink[]}; IF member # NIL THEN sbTool.member _ member}; ENDCASE => { m: LIST OF SB.Member; FOR m _ league.members, m.rest WHILE m.rest#NIL DO IF m.rest.first#sbTool.member THEN LOOP; sbTool.member _ m.first; EXIT REPEAT FINISHED => sbTool.member _ m.first ENDLOOP}; RePaintMember[parent, clientData]; SetLVwr[sbTool.iVwr.edited, ""] }; PlayerNextMate: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; mem: SB.Member _ sbTool.member; IF league=NIL THEN RETURN; IF mem=NIL THEN RETURN; IF mem.sse=NIL THEN RETURN; sbTool.member _ mem.sse; RePaintMember[parent, clientData]; SetLVwr[sbTool.iVwr.edited, ""] }; ScanType: TYPE = {name, sse, team, sex, type, rating, shirt, paid, group, dIndex}; Scan: PROC[parent, clientData: REF, mouseButton: Menus.MouseButton, stype: ScanType] = { match: PROC[m: SB.Member] RETURNS[BOOL] = { RETURN[ SELECT stype FROM < rec.name = m.team,>> < rec.sse = m.team,>> team => rec.team = m.team, sex => rec.sex = m.sex, type => rec.type = m.type, rating => rec.rating = m.rating, shirt => rec.shirt = m.shirt, paid => rec.paid = m.paid, group => rec.group = m.group, < rec.dIndex = m.dIndex,>> ENDCASE => ERROR ]}; sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; m: LIST OF SB.Member; mem: SB.Member; first: SB.Member _ NIL; prev: SB.Member _ NIL; next: SB.Member _ NIL; last: SB.Member _ NIL; rec: SB.MemberRec; IF league=NIL THEN RETURN; IF stype = dIndex THEN {ScanDIndex [NARROW[parent], clientData, mouseButton]; RETURN}; IF stype = name THEN {PlayerFindM [NARROW[parent], clientData, mouseButton]; RETURN}; IF stype = sse THEN {PlayerNextMate [NARROW[parent], clientData, mouseButton]; RETURN}; [mem, rec] _ ExtractIndividualViewerFields[sbTool]; IF mem=NIL THEN mem _ league.members.first; FOR m _ league.members, m.rest WHILE m.first#mem DO IF ~match[m.first] THEN LOOP; IF first = NIL THEN first _ m.first; prev _ m.first ENDLOOP; FOR m _ m.rest, m.rest WHILE m#NIL DO IF ~match[m.first] THEN LOOP; IF next = NIL THEN next _ m.first; last _ m.first ENDLOOP; SELECT mouseButton FROM red => sbTool.member _ IF next#NIL THEN next ELSE first; yellow => { }; ENDCASE => sbTool.member _ IF prev#NIL THEN prev ELSE last; RePaintMember[NARROW[parent], clientData]; SetLVwr[sbTool.iVwr.edited, ""] }; ScanDIndex: PROC[parent, clientData: REF, mouseButton: Menus.MouseButton] = { match: PROC[m: SB.Member] RETURNS[BOOL] = { RETURN[ SELECT mouseButton FROM red => rec.dIndex+1 = m.dIndex, yellow => rec.dIndex = m.dIndex, ENDCASE => rec.dIndex = m.dIndex+1]}; sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; mem: SB.Member; rec: SB.MemberRec; IF league=NIL THEN RETURN; rec _ ExtractIndividualViewerFields[sbTool].rec; FOR m: LIST OF SB.Member _ league.members, m.rest WHILE m#NIL DO IF ~match[m.first] THEN LOOP; mem _ m.first; EXIT ENDLOOP; IF mem=NIL THEN { MessageWindow.Append[message: "Not found.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; sbTool.member _ mem; RePaintMember[NARROW[parent], clientData]; SetLVwr[sbTool.iVwr.edited, ""] }; ActionRec: TYPE = RECORD[action: Action, ref: REF]; Action: TYPE = {add, del, divorce, marry, draft}; Actions: TYPE = LIST OF ActionRec; actions: Actions _ NIL; PlayerMarry: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; member: SB.Member _ NIL; rec: SB.MemberRec; [member, rec] _ ExtractIndividualViewerFields[sbTool]; IF member=NIL THEN { MessageWindow.Append[message: "Member not found.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF rec.sse=NIL THEN { MessageWindow.Append[message: "Mate not found.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF member.sse#NIL AND member.sse#rec.sse THEN { MessageWindow.Append[message: "Member is already spoken for.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF rec.sse.sse#NIL AND rec.sse.sse#member THEN { MessageWindow.Append[message: "Mate is already spoken for.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; rec.sse.sse _ member; member.sse _ rec.sse; member.pair _ rec.sse.pair _ paired; MessageWindow.Append[message: "Sniff sniff.", clearFirst: TRUE]; sbTool.member _ member; SB.Update[league]; RePaint[parent, clientData]; SetLVwr[sbTool.lVwr.write, "edited"] }; PlayerDivorce: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; member: SB.Member _ NIL; rec: SB.MemberRec; [member, rec] _ ExtractIndividualViewerFields[sbTool]; IF member=NIL THEN { MessageWindow.Append[message: "Member not found.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF rec.sse=NIL THEN { MessageWindow.Append[message: "Mate not found.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF member.sse#rec.sse OR rec.sse.sse#member THEN { MessageWindow.Append[message: "They are not married.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; rec.sse.sse _ NIL; member.sse _ NIL; member.pair _ rec.sse.pair _ sgl; MessageWindow.Append[message: "Oh Lord! Free at last!", clearFirst: TRUE]; sbTool.member _ member; SB.Update[league]; RePaint[parent, clientData]; SetLVwr[sbTool.lVwr.write, "edited"] }; PlayerAddNew: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; member: SB.Member _ NIL; rec: SB.MemberRec; [member, rec] _ ExtractIndividualViewerFields[sbTool]; IF member#NIL THEN { MessageWindow.Append[message: "Old player. Not changed.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF rec.sse#NIL AND rec.sse.sse#NIL THEN { MessageWindow.Append[message: "Mate is already engaged. Not added.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; member _ NEW[SB.MemberRec _ rec]; SB.AddMember[league, member]; IF rec.sse#NIL THEN rec.sse.sse _ member; IF rec.sse#NIL THEN MessageWindow.Append[message: "Added 2 members", clearFirst: TRUE] ELSE MessageWindow.Append[message: "Added 1 member", clearFirst: TRUE]; sbTool.member _ member; SB.Update[league]; RePaint[parent, clientData]; SetLVwr[sbTool.lVwr.write, "edited"] }; PlayerDelOld: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; member: SB.Member _ NIL; first: SB.Member _ NIL; prev: SB.Member _ NIL; next: SB.Member _ NIL; last: SB.Member _ NIL; rec: SB.MemberRec; m: LIST OF SB.Member; [member, rec] _ ExtractIndividualViewerFields[sbTool]; IF member=NIL THEN { MessageWindow.Append[message: "Player not found.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF member.sse#NIL THEN {member.sse.pair _ sgl; member.sse.sse _ NIL}; FOR m _ league.members, m.rest WHILE m.first#member DO IF first = NIL THEN first _ m.first; prev _ m.first ENDLOOP; FOR m _ m.rest, m.rest WHILE m#NIL DO IF next = NIL THEN next _ m.first; last _ m.first ENDLOOP; SELECT mouseButton FROM red => sbTool.member _ IF next#NIL THEN next ELSE first; yellow => { }; ENDCASE => sbTool.member _ IF prev#NIL THEN prev ELSE last; actions _ CONS[[del, member], actions]; SB.DeleteMember[league, member]; MessageWindow.Append[message: "Deleted member", clearFirst: TRUE]; SB.Update[league]; RePaint[parent, clientData]; SetLVwr[sbTool.lVwr.write, "edited"] }; Draft: Buttons.ButtonProc = { data: REF IHdlRec _ NARROW[clientData]; sbTool: SBToolHandle _ data.handle; team: SB.Team _ data.team; league: SB.League _ sbTool.league; member: SB.Member _ NIL; rec: SB.MemberRec; [member, rec] _ ExtractIndividualViewerFields[sbTool]; IF team=20 THEN team _ league.nextDTeam; SELECT mouseButton FROM red, blue => { SetTVwr[sbTool.iVwr.team, league.teamNms [LOOPHOLE[team]]]; Scan[ parent, sbTool, mouseButton, team]; RETURN } ENDCASE; IF member=NIL THEN { MessageWindow.Append[message: "Member not found.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF team#0 THEN{ IF member.team#0 THEN { MessageWindow.Append[message: "Already drafted.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF member.sse#NIL AND member.sse.team#0 THEN { MessageWindow.Append[message: "Spouse already drafted.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; member.team _ team; member.dIndex _ league.nextDIndex; IF member.sse=NIL THEN MessageWindow.Append[message: "Drafted", clearFirst: TRUE] ELSE { member.sse.team _ team; member.sse.dIndex _ IF team#0 THEN league.nextDIndex+1 ELSE 0; MessageWindow.Append[message: "Pair Drafted", clearFirst: TRUE]} } ELSE { lastIndex: CARDINAL _ member.dIndex; IF member.team=0 THEN { MessageWindow.Append[message: "Already unassigned.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF member.sse#NIL AND member.sse.team=0 THEN { MessageWindow.Append[message: "Spouse already unassigned.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; member.team _ team; member.dIndex _ 0; IF member.sse=NIL THEN MessageWindow.Append[message: "Unassigned", clearFirst: TRUE] ELSE { lastIndex _ MIN[ member.dIndex, lastIndex]; lastIndex _ MAX[ 1, lastIndex]-1; member.sse.team _ team; member.sse.dIndex _ IF team#0 THEN league.nextDIndex+1 ELSE 0; MessageWindow.Append[message: "Pair Unassigned", clearFirst: TRUE]}}; <> <> sbTool.member _ member; SB.Update[league]; RePaint[parent, sbTool]; SetLVwr[sbTool.lVwr.write, "edited"] }; PlayerUnDo: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; IF league=NIL THEN RETURN; IF actions=NIL THEN { MessageWindow.Append[message: "No actions.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; SELECT actions.first.action FROM add => { sbTool.member _ NARROW[actions.first.ref]; actions _ actions.rest; RePaint[parent, clientData]; PlayerDelOld[parent, clientData, red, control]}; del => { sbTool.member _ NARROW[actions.first.ref]; actions _ actions.rest; MessageWindow.Append[message: "Un delete", clearFirst: TRUE]; IF sbTool.member.sse#NIL THEN IF sbTool.member.sse.sse#NIL AND sbTool.member.sse.sse#sbTool.member THEN {sbTool.member.pair _ sgl; sbTool.member.sse _ NIL} ELSE { sbTool.member.sse.pair _ paired; sbTool.member.sse.sse _ sbTool.member; MessageWindow.Append[message: " and remarry", clearFirst: FALSE] }; SB.AddMember[league, sbTool.member]}; ENDCASE => { MessageWindow.Append[message: "Action is not reversible.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; SB.Update[league]; RePaint[parent, clientData]; SetLVwr[sbTool.lVwr.write, "edited"] }; PlayerCngOld: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; league: SB.League _ sbTool.league; member: SB.Member _ NIL; rec: SB.MemberRec; [member, rec] _ ExtractIndividualViewerFields[sbTool]; IF member=NIL THEN { MessageWindow.Append[message: "Player not found.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; IF member.sse#rec.sse THEN { MessageWindow.Append[message: "Mating operations must be explicit", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN}; member^ _ rec; MessageWindow.Append[message: "Done", clearFirst: TRUE]; sbTool.member _ member; SB.Update[league]; RePaint[parent, clientData]; SetLVwr[sbTool.lVwr.write, "edited"] }; ExtractIndividualViewerFields: PROC[sbTool: SBToolHandle] RETURNS[mem: SB.Member, rec: SB.MemberRec] = { league: SB.League _ sbTool.league; sseFName: Rope.ROPE; sseLName: Rope.ROPE; [rec.fname, rec.lname] _ ParseName[ViewerTools.GetContents[sbTool.iVwr.name]]; mem _ SB.FindMember[league, rec.lname, rec.fname]; [sseFName, sseLName] _ ParseName[ViewerTools.GetContents[sbTool.iVwr.sse]]; rec.sse _ SB.FindMember[league, sseLName, sseFName]; IF rec.sse#NIL THEN rec.pair _ paired ELSE rec.pair _ sgl; rec.type _ LOOPHOLE[ SB.RopeSeqIndex[ViewerTools.GetContents[sbTool.iVwr.type], league.typeNms]]; rec.rating _ LOOPHOLE[ SB.RopeSeqIndex[ViewerTools.GetContents[sbTool.iVwr.rating], league.ratingNms]]; rec.team _ LOOPHOLE[ SB.RopeSeqIndex[ViewerTools.GetContents[sbTool.iVwr.team], league.teamNms]]; rec.paid _ LOOPHOLE[ SB.RopeSeqIndex[ViewerTools.GetContents[sbTool.iVwr.paid], league.paidNms]]; rec.group _ LOOPHOLE[ SB.RopeSeqIndex[ViewerTools.GetContents[sbTool.iVwr.group], league.groupNms]]; rec.shirt _ LOOPHOLE[ SB.RopeSeqIndex[ViewerTools.GetContents[sbTool.iVwr.shirt], league.shirtNms]]; rec.sex _ LOOPHOLE[ SB.RopeSeqIndex[ViewerTools.GetContents[sbTool.iVwr.sex], league.sexNms]]; rec.addr _ ViewerTools.GetContents[sbTool.iVwr.addr]; rec.tnum _ ViewerTools.GetContents[sbTool.iVwr.tnum]; rec.pos _ ViewerTools.GetContents[sbTool.iVwr.pos]; rec.atten _ ViewerTools.GetContents[sbTool.iVwr.atten]; rec.comnt _ ViewerTools.GetContents[sbTool.iVwr.comnt]; rec.dIndex _ Convert.CardFromRope[ViewerTools.GetContents[sbTool.iVwr.dIndex]] }; PlayerName: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, name] ELSE ViewerTools.SetSelection[sbTool.iVwr.name] }; PlayerSSE: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, sse] ELSE ViewerTools.SetSelection[sbTool.iVwr.sse] }; PlayerTeam: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, team] ELSE IncVwrSeq[mouseButton, sbTool.iVwr.team, sbTool.league.teamNms] }; PlayerSex: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, sex] ELSE IncVwrSeq[mouseButton, sbTool.iVwr.sex, sbTool.league.sexNms] }; PlayerType: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, type] ELSE IncVwrSeq[mouseButton, sbTool.iVwr.type, sbTool.league.typeNms] }; PlayerRating: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, rating] ELSE IncVwrSeq[mouseButton, sbTool.iVwr.rating, sbTool.league.ratingNms] }; PlayerShirt: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, shirt] ELSE IncVwrSeq[mouseButton, sbTool.iVwr.shirt, sbTool.league.shirtNms] }; PlayerPaid: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, paid] ELSE IncVwrSeq[mouseButton, sbTool.iVwr.paid, sbTool.league.paidNms] }; PlayerGroup: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, group] ELSE IncVwrSeq[mouseButton, sbTool.iVwr.group, sbTool.league.groupNms] }; PlayerDIndex: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; IF shift THEN Scan[ parent, clientData, mouseButton, dIndex] ELSE ViewerTools.SetSelection[sbTool.iVwr.dIndex] }; PlayerPos: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; ViewerTools.SetSelection[sbTool.iVwr.pos] }; PlayerAtten: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; ViewerTools.SetSelection[sbTool.iVwr.atten] }; PlayerAddr: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; ViewerTools.SetSelection[sbTool.iVwr.addr] }; PlayerTNum: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; ViewerTools.SetSelection[sbTool.iVwr.tnum] }; PlayerComnt: Buttons.ButtonProc = { sbTool: SBToolHandle _ NARROW[clientData]; ViewerTools.SetSelection[sbTool.iVwr.comnt] }; IncVwrSeq: PROC [mouse: Menus.MouseButton, viewer: ViewerClasses.Viewer, seq: SB.RopeSeq] = { index: CARDINAL _ SB.RopeSeqIndex[ViewerTools.GetContents[viewer], seq]; SetTVwr[viewer, seq[CardModMouse[mouse, index, seq.size]]] }; CardModMouse: PROC[mouseButton: Menus.MouseButton, val, mod: CARDINAL] RETURNS[result: CARDINAL] = { SELECT mouseButton FROM red => {result _ (val +1) MOD mod}; yellow => {result _ val}; ENDCASE => {result _ (val+mod-1) MOD mod} }; ParseName: PROC[rope: Rope.ROPE] RETURNS[first, last: Rope.ROPE] = { temp: Rope.ROPE; in: IO.STREAM _ IO.RIS[rope]; DO last _ first _ NIL; last _ IO.GetTokenRope[in ! IO.EndOfStream => {last _ NIL; EXIT}].token; first _ IO.GetTokenRope[in ! IO.EndOfStream => {first _ NIL; EXIT}].token; temp _ first; first _ last; last _ temp; EXIT; ENDLOOP }; Commander.Register[key: "SB", proc: MakeSBTool, doc: "Create a Softball tool" ]; END.