DIRECTORY Rope, Xl, XTkCollections, XTk, XTkFriends; XTkCollectionsImpl: CEDAR MONITOR IMPORTS Xl, XTk, XTkCollections, XTkFriends EXPORTS XTkCollections SHARES XTk = BEGIN OPEN XTk, XTkCollections; collectionClass: PUBLIC Class ¬ InitSuperClass[]; InitSuperClass: PROC [] RETURNS [csc: ImplementorClass] = { csc ¬ XTkFriends.CreateClass[[ key: $collectionSuper, classNameHint: $Collection, wDataNum: 1, cDataNum: 1, initInstPart: CollectionInitInstPart, removeChildLR: NIL, internalEnumerateChildren: InternalEnumerateChildren, pleaseResizeChild: XTkFriends.PropagateUpPleaseResizeChild ]]; csc.cClassData[csc.cDataIdx] ¬ NEW[CollectionClassPartRec ¬ [ addChildLR: AddChildInFirstPlaceLR, addChildrenLR: DefaultAddChildrenLR, enumerateChildren: BasicEnumerateChildren ]]; }; dymmyChildren: REF ChildrenData ~ NEW[ChildrenData[0]]; GetCollectionClassPart: PROC [collection: CollectionWidget] RETURNS [CollectionClassPart] = INLINE { RETURN [ NARROW[XTkFriends.ClassPart[collection, collectionClass]] ] }; CollectionInitInstPart: XTk.InitInstancePartProc = { ip: CollectionInstPart ~ NEW[CollectionInstPartRec ¬ [children: dymmyChildren]]; IF widget.s.geometry.borderWidth<0 THEN widget.s.geometry.borderWidth ¬ 0; XTkFriends.AssignInstPart[widget, collectionClass, ip]; }; Create: PUBLIC PROC [widgetSpec: XTk.WidgetSpec ¬ [], children: LIST OF Widget ¬ NIL, childCount: NAT ¬ 0] RETURNS [widget: CollectionWidget] = { widget ¬ XTk.CreateWidget[widgetSpec, collectionClass]; IF childCount>0 THEN AssertEmptySlotsLR[widget, childCount]; --creation IF children#NIL THEN AddChildrenLR[widget, children, FALSE]; --creation }; RemoveChild: PUBLIC PROC [collection: CollectionWidget, child: Widget, reConsiderNow: BOOL ¬ TRUE, preventDestruction: BOOL ¬ FALSE] = { rootTQ: Xl.TQ ~ collection.rootTQ; action: PROC = {RemoveChildLR[collection, child, reConsiderNow, preventDestruction]}; IF rootTQ=NIL THEN action[] --container is not yet stuck into shell... ELSE Xl.CallWithLock[rootTQ, action]; }; RemoveChildLR: PUBLIC PROC [collection: CollectionWidget, child: Widget, reConsiderNow: BOOL ¬ TRUE, preventDestruction: BOOL ¬ FALSE] = { done: BOOL; IF child.parent#collection THEN ERROR; child.s.mapping ¬ MAX[unconfigured, child.s.mapping]; done ¬ XTkFriends.RemoveChildLR[collection, child]; IF done THEN { IF child.state XTkFriends.AssignParentAndCheckScreenLR[newChild, collection]; ENDCASE => ERROR; IF newChild.s.mapping=dontUse THEN newChild.s.mapping ¬ mapped; classPart.addChildLR[collection, newChild, position, reConsiderNow]; }; AddChildren: PUBLIC PROC [collection: CollectionWidget, children: LIST OF Widget, reConsiderNow: BOOL ¬ TRUE] = { rootTQ: Xl.TQ ~ collection.rootTQ; action: PROC = {AddChildrenLR[collection, children, reConsiderNow]}; IF rootTQ=NIL THEN action[] --container is not yet stuck into shell... ELSE Xl.CallWithLock[rootTQ, action]; }; AddChildrenLR: PUBLIC PROC [collection: CollectionWidget, children: LIST OF Widget, reConsiderNow: BOOL ¬ TRUE] = { classPart: CollectionClassPart ~ GetCollectionClassPart[collection]; FOR l: LIST OF Widget ¬ children, l.rest WHILE l#NIL DO SELECT l.first.parent FROM NIL, collection => XTkFriends.AssignParentAndCheckScreenLR[l.first, collection]; ENDCASE => ERROR; IF l.first.s.mapping=dontUse THEN l.first.s.mapping ¬ mapped; ENDLOOP; classPart.addChildrenLR[collection, children, reConsiderNow]; }; EnumerateChildren: PUBLIC PROC [collection: CollectionWidget, eachChild: EachChildProc, data: REF ¬ NIL] = { classPart: CollectionClassPart ~ GetCollectionClassPart[collection]; classPart.enumerateChildren[collection, eachChild, data]; }; Find: PROC [ip: CollectionInstPart, child: Widget ¬ NIL, start: NAT ¬ 0] RETURNS [INT¬-1] = { FOR i: NAT IN [start..ip.slotsUsed) DO IF ip.children[i]=child THEN RETURN [i]; ENDLOOP; }; RemoveXWindowsLR: PROC [child: Widget] = { IF child#NIL THEN { p: Widget ¬ child.parent; IF p#NIL THEN XTkFriends.ForgetScreenLR[child]; }; }; RemoveAndSquezeLR: PROC [ip: CollectionInstPart, child: Widget] RETURNS [idx: INT] = { idx ¬ Find[ip, child]; IF idx>=0 THEN { ip.sizing ¬ NIL; FOR i: INT IN (idx..ip.slotsUsed) DO ip.children[i-1] ¬ ip.children[i]; ENDLOOP; ip.slotsUsed ¬ ip.slotsUsed-1; ip.children[ip.slotsUsed] ¬ [NIL]; }; }; AssertEmptySlotsLR: PUBLIC PROC [collection: CollectionWidget, num: NAT] = { ip: CollectionInstPart ~ GetCollectionInstPart[collection]; AssertEmptySlotsILR[ip, num]; }; AssertEmptySlotsILR: PROC [ip: CollectionInstPart, num: NAT] = { oldCount: NAT ¬ ip.children.count; IF num<1 THEN num ¬ 7; IF ip.slotsUsed+num<=oldCount THEN RETURN; IF ip.hasEmptySlots THEN { FOR i: INT IN [0..ip.slotsUsed) DO IF ip.children[i].child=NIL THEN {num ¬ num-1; IF num = 0 THEN RETURN}; ENDLOOP; }; IF ip.slotsUsed+num<=oldCount THEN RETURN; BEGIN newCount: NAT ¬ MAX[oldCount+5, oldCount+oldCount+1, ip.slotsUsed+num]; newCd: REF ChildrenData ~ NEW[ChildrenData[newCount]]; ip.sizing ¬ NIL; FOR i: INT IN [0..ip.slotsUsed) DO newCd.children[i] ¬ ip.children.children[i]; ENDLOOP; ip.children ¬ newCd; END; }; RemoveChildInPlaceLR: PUBLIC PROC [widget, child: Widget] RETURNS [done: BOOL ¬ FALSE] = { RemoveInPlaceLR: PROC [ip: CollectionInstPart, child: Widget] RETURNS [idx: INT] = { idx ¬ Find[ip, child]; IF idx>=0 THEN { ip.sizing ¬ NIL; ip.children[idx] ¬ [NIL]; IF idx+1=ip.slotsUsed THEN ip.slotsUsed ¬ ip.slotsUsed-1 ELSE ip.hasEmptySlots ¬ TRUE; }; }; ip: CollectionInstPart ~ GetCollectionInstPart[widget]; IF child=NIL THEN ERROR; IF RemoveInPlaceLR[ip, child]>=0 THEN { done ¬ TRUE; RemoveXWindowsLR[child]; XTk.NoteChildChange[widget]; }; }; RemoveChildAndSqueezeLR: PUBLIC PROC [widget, child: Widget] RETURNS [done: BOOL ¬ FALSE] = { SqueezeNRemoveLR: PROC [ip: CollectionInstPart, child: Widget] RETURNS [found: BOOL¬FALSE] = { nextToUse, nextToWatch: NAT ¬ 0; WHILE nextToWatch {ip.sizing ¬ NIL; LOOP}; c=child => {found ¬ TRUE; ip.sizing ¬ NIL; LOOP}; ENDCASE => { ip.children[nextToUse].child ¬ c; nextToUse ¬ nextToUse+1; }; ENDLOOP; FOR empty: NAT IN [nextToUse..ip.slotsUsed) DO ip.children[empty] ¬ [NIL] ENDLOOP; ip.slotsUsed ¬ nextToUse; ip.hasEmptySlots ¬ FALSE; }; ip: CollectionInstPart ~ GetCollectionInstPart[widget]; IF child=NIL THEN ERROR; IF SqueezeNRemoveLR[ip, child].found THEN { done ¬ TRUE; RemoveXWindowsLR[child]; XTk.NoteChildChange[widget]; }; }; AddChildInFirstPlaceLR: PUBLIC PROC [collection: CollectionWidget, newChild: Widget, position: REF, reConsiderNow: BOOL] = { IncludeHardLR: PROC [ip: CollectionInstPart, newChild: Widget] = { IncludeLR: PROC [ip: CollectionInstPart, w: Widget] RETURNS [INT¬-1] = { IF ip.hasEmptySlots THEN { idx: INT ~ Find[ip, NIL]; IF idx<0 THEN ERROR; --there was no empty slot ip.children[idx] ¬ [w]; IF Find[ip, NIL, idx+1]<0 THEN ip.hasEmptySlots ¬ FALSE; RETURN [idx] }; IF ip.slotsUsed=0 THEN ERROR; --tried to include multiple times IncludeHardLR[ip, newChild]; XTk.NoteChildChange[collection]; IF reConsiderNow THEN XTkFriends.ReconfigureChildrenLR[collection]; }; DefaultAddChildrenLR: PROC [collection: CollectionWidget, children: LIST OF Widget, reConsiderNow: BOOL] = { classPart: CollectionClassPart ~ GetCollectionClassPart[collection]; FOR l: LIST OF Widget ¬ children, l.rest WHILE l#NIL DO classPart.addChildLR[collection, l.first, NIL, (l.rest#NIL AND reConsiderNow)]; ENDLOOP; }; CountChildren: PROC [collection: CollectionWidget] RETURNS [n: INT ¬ 0] = { ip: CollectionInstPart ~ GetCollectionInstPart[collection]; FOR i: NAT IN [0..ip.slotsUsed) DO c: Widget ¬ ip.children[i]; IF c#NIL AND c.statežœžœžœžœ˜ˆK˜"KšœžœI˜Ušžœžœ˜Kšžœ Οc*˜8Kšžœ!˜%—K˜K˜—šŸ œžœžœ>žœžœžœžœ˜ŠKšœžœ˜ Kšžœžœžœ˜&Kšœžœ ˜5Kšœ3˜3šžœžœ˜šžœžœ˜Kšœ0žœ˜6—šžœ˜Kšžœ!˜%Kšžœ&˜*—K˜—Kšžœžœ-˜BK˜K˜—šŸœžœžœ<žœžœžœžœ˜{K˜"Kšœžœ?˜Kšžœžœ˜Kšžœ  *˜8Kšžœ!˜%—K˜K˜—šŸ œžœžœ<žœžœžœžœ˜}KšœD˜Dšžœž˜KšžœN˜QKšžœžœ˜—Kšžœžœ˜?KšœD˜DK˜K˜—šŸ œžœžœ*žœžœžœžœ˜qK˜"Kšœžœ8˜Dšžœžœ˜Kšžœ  *˜8Kšžœ!˜%—K˜K˜—šŸ œžœžœ*žœžœžœžœ˜sKšœD˜Dš žœžœžœžœžœž˜7šžœž˜KšžœM˜PKšžœžœ˜—Kšžœžœ˜=Kšžœ˜—Kšœ=˜=K˜K˜—š Ÿœžœžœ@žœžœ˜lKšœD˜DKšœ9˜9Kšœ˜—K˜š Ÿœžœ*žœ žœžœžœ˜]šžœžœžœž˜&Kšžœžœžœ˜(Kšžœ˜—K˜K˜—šŸœžœ˜*šžœžœžœ˜Kšœ˜Kšžœžœžœ"˜/K˜—K˜—K˜šŸœžœ)žœžœ˜VKšœ˜šžœžœ˜Kšœ ž˜šžœžœžœž˜$Kšœ"˜"Kšžœ˜—Kšœ˜Kšœžœ˜"K˜—K˜—K˜šŸœžœžœ%žœ˜LJš >™>Jš !™!Kšœ;˜;Kšœ˜K˜—K˜šŸœžœžœ˜@Kšœ žœ˜"Kšžœžœ ˜Kšžœžœžœ˜*šžœžœ˜šžœžœžœž˜"Kš žœžœžœžœ žœžœ˜GKšžœ˜—K˜—Kšžœžœžœ˜*šž˜Kšœ žœžœ4˜GKšœžœžœ˜6Kšœ žœ˜šžœžœžœž˜"Kšœ,˜,Kšžœ˜—Kšœ˜Kšžœ˜—K˜—K˜š Ÿœžœžœžœžœžœ˜ZšŸœžœ)žœžœ˜TKšœ˜šžœžœ˜Kšœ žœ˜Kšœžœ˜šžœ˜Kšžœ˜#Kšžœžœ˜—K˜—K˜—Kšœ7˜7Kšžœžœžœžœ˜šžœžœ˜'Kšœžœ˜ Kšœ˜Kšœ˜K˜—K˜K˜—š Ÿœžœžœžœžœžœ˜]š Ÿœžœ)žœ žœžœ˜^Kšœžœ˜ šžœž˜!KšœL˜Lšžœžœž˜Kš œžœžœžœžœ˜1Kšœžœžœžœ˜1šžœ˜ Kšœ:˜:K˜——Kšžœ˜—Kš žœžœžœžœžœžœ˜RKšœ˜Kšœžœ˜K˜—Kšœ7˜7Kšžœžœžœžœ˜šžœ#žœ˜+Kšœžœ˜ Kšœ˜Kšœ˜K˜—K˜K˜—š Ÿœžœžœ<žœžœ˜|šŸ œžœ/˜BšŸ œžœ%žœžœ˜Hšžœžœ˜Kšœžœ žœ˜Kšžœžœžœ ˜.Kšœ˜Kšžœ žœ žœžœ˜8Kšžœ˜ Kšœ˜—šžœ žœ˜(Kšœžœ˜Kšœ˜Kšœ˜Kšžœ˜ K˜—Jš ™K˜—Kšœžœ˜#šžœžœ˜Kšœ˜Kšœ˜K˜—K˜—Kšœ;˜;Kš žœ žœžœžœžœ˜9Kšžœžœžœ !˜FKšœ˜Kšœ ˜ Kšžœžœ.˜CK˜K˜—š Ÿœžœ*žœžœžœ˜lKšœD˜Dš žœžœžœžœžœž˜7Kšœ*žœ žœžœ˜OKšžœ˜—K˜K˜—šŸ œžœ žœžœ ˜KKšœ;˜;šžœžœžœž˜"Kšœ˜Kšžœžœžœžœ ˜'Kšžœ˜—K˜—K˜š Ÿœžœžœ@žœžœ˜qKšœ;˜;šžœžœžœž˜"Kšœ˜šžœžœžœžœ˜Kšžœ(žœžœ˜6—Kšžœ˜—K˜K˜—šŸœ'˜@Kšœ5˜5šžœžœžœž˜"Kšœ˜šžœžœžœžœ˜!Kšžœžœ žœžœ˜7K˜—Kšžœ˜—K˜—K˜šŸœžœžœžœ(˜qKšœ$žœ/˜YKšœžœ)˜;Kšœ:˜:K˜—K˜Kšžœ˜K˜K˜—…—&ž4F