DIRECTORY Buttons, MBQueue, ViewerClasses, Rope; MBWindows: CEDAR DEFINITIONS = BEGIN Viewer: TYPE = ViewerClasses.Viewer; EnumProc: TYPE = PROC[enum: REF ANY] RETURNS [label: Rope.ROPE, thing: REF ANY]; CountProc: TYPE = PROC[v: Viewer, enum: REF ANY] RETURNS [INT]; ThumbProc: TYPE = PROC[v: Viewer, enum: REF ANY, where: NAT] RETURNS [newEnum: REF ANY]; CreateMBWindow: PROC[ next, prev: EnumProc, -- to go forward and backward in the enumeration thumb: ThumbProc, -- to create an enumeration set to a particular position count: CountProc, -- to give total size of enumeration buttonProc: Buttons.ButtonProc, -- called with the thing associated with button info: ViewerClasses.ViewerRec_ [], -- allows client to fill in ViewerRec fields initialScroll: INT_ 0, -- what percentage of scroll to have for initial display q: MBQueue.Queue_ NIL] -- MBQueue under which to synchronize (doesn't yet work) RETURNS [viewer: Viewer]; END. An example of the use of MBWindows (from Squirrel, DomainNutImpl): To create the MBWindow: parent.scrollable_ FALSE; -- Scrollbar will be provided by MBWindow mbw_ MBWindows.CreateMBWindow[ count: GetThingCount, thumb: DomainThumb, next: DomainNextProc, prev: DomainPrevProc, buttonProc: ProcessEntitySelection, info: [parent: parent, wx: 0, wy: 0, ww: parent.ww, wh: 800, border: FALSE], q: NIL ]; Containers.ChildYBound[container: parent, child: mbw]; GetThingCount: MBWindows.CountProc = { parent: Viewer_ GetTopLevel[v]; dInfo: DomainInfo_ NARROW[ ViewerOps.FetchProp[parent, $DomainInfo] ]; RETURN[EntitySetSize[DomainSubset[dInfo.domain, "", "\177"], FALSE]]; }; DomainNextProc: MBWindows.EnumProc = TRUSTED BEGIN es: EntitySet_ LOOPHOLE[enum]; e: Entity_ NextEntity[es]; RETURN[IF e=NIL THEN NIL ELSE NameOf[e], e]; END; DomainPrevProc: MBWindows.EnumProc = TRUSTED BEGIN es: EntitySet_ LOOPHOLE[enum]; e: Entity_ PrevEntity[es]; RETURN[IF e=NIL THEN NIL ELSE NameOf[e], e]; END; DomainThumb: MBWindows.ThumbProc = TRUSTED BEGIN es: EntitySet_ LOOPHOLE[enum]; dInfo: DomainInfo = NARROW[ViewerOps.FetchProp[GetTopLevel[v], $DomainInfo]]; DB.ReleaseEntitySet[es]; IF where<10 THEN es_ DB.DomainSubset[dInfo.domain, "", "\177", First] ELSE IF where>90 THEN { es_ DB.DomainSubset[dInfo.domain, "", "\177", Last]; []_ PrevEntity[es]; []_ PrevEntity[es]; []_ PrevEntity[es]} ELSE { es_ DB.DomainSubset[dInfo.domain, "", "\177", First]; THROUGH [0..where*GetThingCount[v, es]/100) DO []_ NextEntity[es] ENDLOOP; }; RETURN[es] END; GetTopLevel: PROCEDURE [v: Viewer] RETURNS [ancestor: Viewer] = { FOR ancestor _ v, ancestor.parent UNTIL ancestor.parent=NIL DO ENDLOOP; }; üFile: MBWindows.mesa Contents: package implementing set of buttons in viewer when there are too many things to actually create buttons for all. Client passes procedures to go forward and backward through enumeration, and ScrollableButtonsImpl implements scrolling, calls client button proc on appropriate thing. Last Edited by: Cattell, October 5, 1983 9:19 am Returns next or previous element of the enumeration. Estimate size of enumeration. Used only for feedback so may be approximate. Use to set enumeration to particular position quickly; may return new enum. The where parameter is a percentage between 0 and 100. Client's buttonProc must be prepared to be called with an empty button (clientData and label NIL), as there will always be one screenheight of buttons even if they're not all occupied. It should do nothing in this case. Client's next proc should return [NIL, NIL] when there are no more items to enumerate. It may be called again after that, in which case it should continue to return [NIL, NIL]. Similarly for prev proc at beginning of list. Client's count procedure is used only for providing feedback in scroll bar, so it need not be exactly right. MBWindows will tolerate some inconsistency in the client's procedures, e.g. enumerating the same item twice when change from next to prev proc. Notice we do not need an initial REF ANY for the enumeration; it is created by calling the thumb procedure with where=initialScroll and enum=NIL. Note also that we allow the thumb procedure to create a new enumeration, while the next and prev procedures are expected to make any modification to the enum they are passed in place (they may modify it, because MBWindows has a REF to it). Note: if the MBWindow is nested inside another viewer, then the parent field should be set by passing a parent in the info field, and the client should call Containers.ChildYBound so that the MBWindow's size is set automatically with changes in the parent. See example below. Get there the hard way, though NextEntity calls Ê~˜J˜Jšœ™Jšœ£™£Jšœ0™0J˜JšÏk œ'˜0J˜Jšœ œ œ˜J˜Jš˜J˜Jšœœ˜$˜šœ œ˜Jšœœœœœ œœ˜?Jšœ4™4J˜——šœ œ˜Jš œœœœœ˜-JšœL™LJ˜—šœ œ˜Jšœœœ œœ œœ˜FJšœK™KJšœ7™7J˜—šÏnœœ˜JšœÏc0˜GJšœŸ8˜JJšœŸ$˜6Jšœ Ÿ/˜OJšœ#Ÿ,˜OJšœœŸ8˜OJšœœŸ8˜OJšœ˜J˜—Jšœ¼™¼J˜Jšœ‚™‚J˜Jšœ”™”J˜Jšœ˜J˜J˜J˜J˜BJ˜J˜˜JšœœŸ)˜C˜J˜J˜J˜J˜J˜#JšœEœ˜LJšœœ˜ —J˜6J˜—˜&J˜Jšœœ-˜FJšœ7œ˜EJ˜J˜—šœ%˜,Jšœœ˜$J˜Jš œœœœœœ˜,Jšœ˜J˜—šœ%˜,Jšœœ˜$J˜Jš œœœœœœ˜,Jšœ˜J˜—šœ#˜*Jšœœ˜$Jšœœ3˜MJšœ˜šœ œ˜Jšœœ.˜4—šœœ œ˜Jšœœ.˜4J˜;—šœ˜Jšœ/™/Jšœœ/˜5Jšœ%œœ˜JJ˜—Jšœ˜ Jšœ˜J˜—Jšž œ œ œ˜AJš œœœœœ˜GJ˜J˜J˜J˜—…— LÆ