|
@@ -0,0 +1,685 @@
|
|
|
+unit outline;
|
|
|
+
|
|
|
+{$CODEPAGE cp437}
|
|
|
+
|
|
|
+{***************************************************************************}
|
|
|
+ interface
|
|
|
+{***************************************************************************}
|
|
|
+
|
|
|
+uses drivers,objects,views;
|
|
|
+
|
|
|
+type Pnode=^Tnode;
|
|
|
+ Tnode=record
|
|
|
+ next:Pnode;
|
|
|
+ text:Pstring;
|
|
|
+ childlist:Pnode;
|
|
|
+ expanded:boolean;
|
|
|
+ end;
|
|
|
+
|
|
|
+ Poutlineviewer=^Toutlineviewer;
|
|
|
+ Toutlineviewer=object(Tscroller)
|
|
|
+ foc:sw_integer;
|
|
|
+ constructor init(var bounds:Trect;
|
|
|
+ AHscrollbar,AVscrollbar:Pscrollbar);
|
|
|
+ procedure adjust(node:pointer;expand:boolean);virtual;
|
|
|
+ function creategraph(level:integer;lines:longint;
|
|
|
+ flags:word;levwidth,endwidth:integer;
|
|
|
+ const chars:string):string;
|
|
|
+ procedure draw;virtual;
|
|
|
+ procedure expandall(node:pointer);
|
|
|
+ function firstthat(test:pointer):pointer;
|
|
|
+ procedure focused(i:sw_integer);virtual;
|
|
|
+ procedure foreach(action:pointer);
|
|
|
+ function getchild(node:pointer;i:sw_integer):pointer;virtual;
|
|
|
+ function getgraph(level:integer;lines:longint;flags:word):string;
|
|
|
+ function getnode(i:sw_integer):pointer;virtual;
|
|
|
+ function getnumchildren(node:pointer):sw_integer;virtual;
|
|
|
+ function getpalette:Ppalette;virtual;
|
|
|
+ function getroot:pointer;virtual;
|
|
|
+ function gettext(node:pointer):string;virtual;
|
|
|
+ procedure handleevent(var event:Tevent);virtual;
|
|
|
+ function haschildren(node:pointer):boolean;virtual;
|
|
|
+ function isexpanded(node:pointer):boolean;virtual;
|
|
|
+ function isselected(i:sw_integer):boolean;virtual;
|
|
|
+ procedure selected(i:sw_integer);virtual;
|
|
|
+ procedure setstate(Astate:word;enable:boolean);virtual;
|
|
|
+ procedure update;
|
|
|
+ private
|
|
|
+ procedure set_focus(Afocus:sw_integer);
|
|
|
+ function do_recurse(action,callerframe:pointer;
|
|
|
+ stop_if_found:boolean):pointer;
|
|
|
+ end;
|
|
|
+
|
|
|
+ Poutline=^Toutline;
|
|
|
+ Toutline=object(Toutlineviewer)
|
|
|
+ root:Pnode;
|
|
|
+ constructor init(var bounds:Trect;
|
|
|
+ AHscrollbar,AVscrollbar:Pscrollbar;
|
|
|
+ Aroot:Pnode);
|
|
|
+ procedure adjust(node:pointer;expand:boolean);virtual;
|
|
|
+ function getchild(node:pointer;i:sw_integer):pointer;virtual;
|
|
|
+ function getnumchildren(node:pointer):sw_integer;virtual;
|
|
|
+ function getroot:pointer;virtual;
|
|
|
+ function gettext(node:pointer):string;virtual;
|
|
|
+ function haschildren(node:pointer):boolean;virtual;
|
|
|
+ function isexpanded(node:pointer):boolean;virtual;
|
|
|
+ destructor done;virtual;
|
|
|
+ end;
|
|
|
+
|
|
|
+const ovExpanded = $1;
|
|
|
+ ovChildren = $2;
|
|
|
+ ovLast = $4;
|
|
|
+
|
|
|
+ Coutlineviewer=Cscroller+#8#8;
|
|
|
+
|
|
|
+function newnode(const Atext:string;Achildren,Anext:Pnode):Pnode;
|
|
|
+procedure disposenode(node:Pnode);
|
|
|
+
|
|
|
+
|
|
|
+{***************************************************************************}
|
|
|
+ implementation
|
|
|
+{***************************************************************************}
|
|
|
+
|
|
|
+type TMyFunc = function(_EBP: Pointer; Cur: Pointer;
|
|
|
+ Level, Position: sw_integer; Lines: LongInt;
|
|
|
+ Flags: Word): Boolean;
|
|
|
+
|
|
|
+
|
|
|
+function newnode(const Atext:string;Achildren,Anext:Pnode):Pnode;
|
|
|
+
|
|
|
+begin
|
|
|
+ newnode:=new(Pnode);
|
|
|
+ with newnode^ do
|
|
|
+ begin
|
|
|
+ next:=Anext;
|
|
|
+ text:=newstr(Atext);
|
|
|
+ childlist:=Achildren;
|
|
|
+ expanded:=true;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure disposenode(node:Pnode);
|
|
|
+
|
|
|
+var next:Pnode;
|
|
|
+
|
|
|
+begin
|
|
|
+ while node<>nil do
|
|
|
+ begin
|
|
|
+ disposenode(node^.childlist);
|
|
|
+ disposestr(node^.text);
|
|
|
+ next:=node^.next;
|
|
|
+ dispose(node);
|
|
|
+ node:=next;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
+{ Toutlineviewer object methods }
|
|
|
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
+
|
|
|
+constructor Toutlineviewer.init(var bounds:Trect;
|
|
|
+ AHscrollbar,AVscrollbar:Pscrollbar);
|
|
|
+
|
|
|
+begin
|
|
|
+ inherited init(bounds,AHscrollbar,AVscrollbar);
|
|
|
+ foc:=0;
|
|
|
+ growmode:=gfGrowHiX+gfGrowHiY;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.adjust(node:pointer;expand:boolean);
|
|
|
+
|
|
|
+begin
|
|
|
+ abstract;
|
|
|
+end;
|
|
|
+
|
|
|
+function TOutlineViewer.CreateGraph(Level: Integer; Lines: LongInt;
|
|
|
+ Flags: Word; LevWidth, EndWidth: Integer;
|
|
|
+ const Chars: String): String;
|
|
|
+const
|
|
|
+ FillerOrBar = 0;
|
|
|
+ YorL = 2;
|
|
|
+ StraightOrTee= 4;
|
|
|
+ Retracted = 6;
|
|
|
+var
|
|
|
+ Last, Children, Expanded: Boolean;
|
|
|
+ I , J : Byte;
|
|
|
+ Graph : String;
|
|
|
+
|
|
|
+begin
|
|
|
+ { Load registers }
|
|
|
+ graph:=space(Level*LevWidth+EndWidth+1);
|
|
|
+
|
|
|
+ { Write bar characters }
|
|
|
+ J := 1;
|
|
|
+ while (Level > 0) do
|
|
|
+ begin
|
|
|
+ Inc(J);
|
|
|
+ if (Lines and 1) <> 0 then
|
|
|
+ Graph[J] := Chars[FillerOrBar+2]
|
|
|
+ else
|
|
|
+ Graph[J] := Chars[FillerOrBar+1];
|
|
|
+ for I := 1 to LevWidth - 1 do
|
|
|
+ Graph[I]:= Chars[FillerOrBar+1];
|
|
|
+ J := J + LevWidth - 1;
|
|
|
+ Dec(Level);
|
|
|
+ Lines := Lines shr 1;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { Write end characters }
|
|
|
+ Dec(EndWidth);
|
|
|
+ if EndWidth > 0 then
|
|
|
+ begin
|
|
|
+ Inc(J);
|
|
|
+ if Flags and ovLast <> 0 then
|
|
|
+ Graph[J] := Chars[YorL+2]
|
|
|
+ else
|
|
|
+ Graph[J] := Chars[YorL+1];
|
|
|
+ Dec(EndWidth);
|
|
|
+ if EndWidth > 0 then
|
|
|
+ begin
|
|
|
+ Dec(EndWidth);
|
|
|
+ for I := 1 to EndWidth do
|
|
|
+ Graph[I]:= Chars[StraightOrTee+1];
|
|
|
+ J := J + EndWidth;
|
|
|
+ Inc(J);
|
|
|
+ if (Flags and ovChildren) <> 0 then
|
|
|
+ Graph[J] := Chars[StraightOrTee+2]
|
|
|
+ else
|
|
|
+ Graph[J] := Chars[StraightOrTee+1];
|
|
|
+ end;
|
|
|
+ Inc(J);
|
|
|
+ if Flags and ovExpanded <> 0 then
|
|
|
+ Graph[J] := Chars[Retracted+2]
|
|
|
+ else
|
|
|
+ Graph[J] := Chars[Retracted+1];
|
|
|
+ end;
|
|
|
+ Graph[0] := Char(J);
|
|
|
+
|
|
|
+ CreateGraph := Graph;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.do_recurse(action,callerframe:pointer;
|
|
|
+ stop_if_found:boolean):pointer;
|
|
|
+
|
|
|
+var position:sw_integer;
|
|
|
+ r:pointer;
|
|
|
+
|
|
|
+ function recurse(cur:pointer;level:integer;lines:longint;lastchild:boolean):pointer;
|
|
|
+
|
|
|
+ var i,childcount:sw_integer;
|
|
|
+ child:pointer;
|
|
|
+ flags:word;
|
|
|
+ children,expanded,found:boolean;
|
|
|
+
|
|
|
+ begin
|
|
|
+ inc(position);
|
|
|
+ recurse:=nil;
|
|
|
+
|
|
|
+ children:=haschildren(cur);
|
|
|
+ expanded:=isexpanded(cur);
|
|
|
+
|
|
|
+ {Determine flags.}
|
|
|
+ flags:=0;
|
|
|
+ if not children or expanded then
|
|
|
+ inc(flags,ovExpanded);
|
|
|
+ if children and expanded then
|
|
|
+ inc(flags,ovChildren);
|
|
|
+ if lastchild then
|
|
|
+ inc(flags,ovLast);
|
|
|
+
|
|
|
+ {Call the function.}
|
|
|
+ found:=TMyFunc(action)(callerframe,cur,level,position,lines,flags);
|
|
|
+
|
|
|
+ if stop_if_found and found then
|
|
|
+ recurse:=cur
|
|
|
+ else if children and expanded then {Recurse children?}
|
|
|
+ begin
|
|
|
+ if not lastchild then
|
|
|
+ lines:=lines or (1 shl level);
|
|
|
+ {Iterate all childs.}
|
|
|
+ childcount:=getnumchildren(cur);
|
|
|
+ for i:=0 to childcount-1 do
|
|
|
+ begin
|
|
|
+ child:=getchild(cur,i);
|
|
|
+ if (child<>nil) and (level<31) then
|
|
|
+ recurse:=recurse(child,level+1,lines,i=childcount-1);
|
|
|
+ {Did we find a node?}
|
|
|
+ if recurse<>nil then
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+begin
|
|
|
+ position:=-1;
|
|
|
+ r:=getroot;
|
|
|
+ if r<>nil then
|
|
|
+ do_recurse:=recurse(r,0,0,true)
|
|
|
+ else
|
|
|
+ do_recurse:=nil;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.draw;
|
|
|
+
|
|
|
+var c_normal,c_normal_x,c_select,c_focus:byte;
|
|
|
+ maxpos:sw_integer;
|
|
|
+ b:Tdrawbuffer;
|
|
|
+
|
|
|
+ function draw_item(cur:pointer;level,position:sw_integer;
|
|
|
+ lines:longint;flags:word):boolean;
|
|
|
+
|
|
|
+ var c,i:byte;
|
|
|
+ s,t:string;
|
|
|
+
|
|
|
+ begin
|
|
|
+ draw_item:=position>=delta.y+size.y;
|
|
|
+ if (position<delta.y) or draw_item then
|
|
|
+ exit;
|
|
|
+
|
|
|
+ maxpos:=position;
|
|
|
+ s:=getgraph(level,lines,flags);
|
|
|
+ t:=gettext(cur);
|
|
|
+
|
|
|
+ {Determine text colour.}
|
|
|
+ if (foc=position) and (state and sffocused<>0) then
|
|
|
+ c:=c_focus
|
|
|
+ else if isselected(position) then
|
|
|
+ c:=c_select
|
|
|
+ else if flags and ovexpanded<>0 then
|
|
|
+ c:=c_normal_x
|
|
|
+ else
|
|
|
+ c:=c_normal;
|
|
|
+
|
|
|
+ {Fill drawbuffer with graph and text to draw.}
|
|
|
+ for i:=0 to size.x-1 do
|
|
|
+ begin
|
|
|
+ wordrec(b[i]).hi:=c;
|
|
|
+ if i+delta.x<length(s) then
|
|
|
+ wordrec(b[i]).lo:=byte(s[1+i+delta.x])
|
|
|
+ else if 1+i+delta.x-length(s)<=length(t) then
|
|
|
+ wordrec(b[i]).lo:=byte(t[1+i+delta.x-length(s)])
|
|
|
+ else
|
|
|
+ wordrec(b[i]).lo:=byte(' ');
|
|
|
+ end;
|
|
|
+
|
|
|
+ {Draw!}
|
|
|
+ writeline(0,position-delta.y,size.x,1,b);
|
|
|
+ end;
|
|
|
+
|
|
|
+begin
|
|
|
+ c_normal:=getcolor(4);
|
|
|
+ c_normal_x:=getcolor(1);
|
|
|
+ c_focus:=getcolor(2);
|
|
|
+ c_select:=getcolor(3);
|
|
|
+ maxpos:=-1;
|
|
|
+ foreach(@draw_item);
|
|
|
+ movechar(b,' ',c_normal,size.x);
|
|
|
+ writeline(0,maxpos+1,size.x,size.y-(maxpos-delta.y),b);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.expandall(node:pointer);
|
|
|
+
|
|
|
+var i:sw_integer;
|
|
|
+
|
|
|
+begin
|
|
|
+ if haschildren(node) then
|
|
|
+ begin
|
|
|
+ for i:=0 to getnumchildren(node)-1 do
|
|
|
+ expandall(getchild(node,i));
|
|
|
+ adjust(node,true);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.firstthat(test:pointer):pointer;
|
|
|
+
|
|
|
+begin
|
|
|
+ firstthat:=do_recurse(test,get_caller_frame(get_frame),true);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.focused(i:sw_integer);
|
|
|
+
|
|
|
+begin
|
|
|
+ foc:=i;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.foreach(action:pointer);
|
|
|
+
|
|
|
+begin
|
|
|
+ do_recurse(action,get_caller_frame(get_frame),false);
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.getchild(node:pointer;i:sw_integer):pointer;
|
|
|
+
|
|
|
+begin
|
|
|
+ abstract;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.getgraph(level:integer;lines:longint;
|
|
|
+ flags:word):string;
|
|
|
+
|
|
|
+begin
|
|
|
+ getgraph:=creategraph(level,lines,flags,3,3,' ³ÃÀÄÄ+Ä');
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.getnode(i:sw_integer):pointer;
|
|
|
+
|
|
|
+ function test_position(node:pointer;level,position:sw_integer;lines:longInt;
|
|
|
+ flags:word):boolean;
|
|
|
+
|
|
|
+ begin
|
|
|
+ test_position:=position=i;
|
|
|
+ end;
|
|
|
+
|
|
|
+begin
|
|
|
+ getnode:=firstthat(@test_position);
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.getnumchildren(node:pointer):sw_integer;
|
|
|
+
|
|
|
+begin
|
|
|
+ abstract;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.getpalette:Ppalette;
|
|
|
+
|
|
|
+const p:string[length(Coutlineviewer)]=Coutlineviewer;
|
|
|
+
|
|
|
+begin
|
|
|
+ getpalette:=@p;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.getroot:pointer;
|
|
|
+
|
|
|
+begin
|
|
|
+ abstract;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.gettext(node:pointer):string;
|
|
|
+
|
|
|
+begin
|
|
|
+ abstract;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.handleevent(var event:Tevent);
|
|
|
+
|
|
|
+var mouse:Tpoint;
|
|
|
+ cur:pointer;
|
|
|
+ new_focus:sw_integer;
|
|
|
+ count:byte;
|
|
|
+ handled,m,mouse_drag:boolean;
|
|
|
+ graph:string;
|
|
|
+
|
|
|
+ function graph_of_focus(var graph:string):pointer;
|
|
|
+
|
|
|
+ var _level:sw_integer;
|
|
|
+ _lines:longInt;
|
|
|
+ _flags:word;
|
|
|
+
|
|
|
+ function find_focused(cur:pointer;level,position:sw_integer;
|
|
|
+ lines:longint;flags:word):boolean;
|
|
|
+
|
|
|
+ begin
|
|
|
+ find_focused:=position=foc;
|
|
|
+ if find_focused then
|
|
|
+ begin
|
|
|
+ _level:=level;
|
|
|
+ _lines:=lines;
|
|
|
+ _flags:=flags;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ begin
|
|
|
+ graph_of_focus:=firstthat(@find_focused);
|
|
|
+ graph:=getgraph(_level,_lines,_flags);
|
|
|
+ end;
|
|
|
+
|
|
|
+const skip_mouse_events=3;
|
|
|
+
|
|
|
+begin
|
|
|
+ inherited handleevent(event);
|
|
|
+ case event.what of
|
|
|
+ evKeyboard:
|
|
|
+ begin
|
|
|
+ new_focus:=foc;
|
|
|
+ handled:=true;
|
|
|
+ case ctrltoarrow(event.keycode) of
|
|
|
+ kbUp,kbLeft:
|
|
|
+ dec(new_focus);
|
|
|
+ kbDown,kbRight:
|
|
|
+ inc(new_focus);
|
|
|
+ kbPgDn:
|
|
|
+ inc(new_focus,size.y-1);
|
|
|
+ kbPgUp:
|
|
|
+ dec(new_focus,size.y-1);
|
|
|
+ kbCtrlPgUp:
|
|
|
+ new_focus:=0;
|
|
|
+ kbCtrlPgDn:
|
|
|
+ new_focus:=limit.y-1;
|
|
|
+ kbHome:
|
|
|
+ new_focus:=delta.y;
|
|
|
+ kbEnd:
|
|
|
+ new_focus:=delta.y+size.y-1;
|
|
|
+ kbCtrlEnter,kbEnter:
|
|
|
+ selected(new_focus);
|
|
|
+ else
|
|
|
+ case event.charcode of
|
|
|
+ '-','+':
|
|
|
+ begin
|
|
|
+ adjust(getnode(new_focus),event.charcode='+');
|
|
|
+ update;
|
|
|
+ end;
|
|
|
+ '*':
|
|
|
+ begin
|
|
|
+ expandall(getnode(new_focus));
|
|
|
+ update;
|
|
|
+ end;
|
|
|
+ else
|
|
|
+ handled:=false;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ if new_focus<0 then
|
|
|
+ new_focus:=0;
|
|
|
+ if new_focus>=limit.y then
|
|
|
+ new_focus:=limit.y-1;
|
|
|
+ if foc<>new_focus then
|
|
|
+ set_focus(new_focus);
|
|
|
+ if handled then
|
|
|
+ clearevent(event);
|
|
|
+ end;
|
|
|
+ evMouseDown:
|
|
|
+ begin
|
|
|
+ count:=1;
|
|
|
+ mouse_drag:=false;
|
|
|
+ repeat
|
|
|
+ makelocal(event.where,mouse);
|
|
|
+ if mouseinview(event.where) then
|
|
|
+ new_focus:=delta.y+mouse.y
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ inc(count,byte(event.what=evMouseAuto));
|
|
|
+ if count and skip_mouse_events=0 then
|
|
|
+ begin
|
|
|
+ if mouse.y<0 then
|
|
|
+ dec(new_focus);
|
|
|
+ if mouse.y>=size.y then
|
|
|
+ inc(new_focus);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ if new_focus<0 then
|
|
|
+ new_focus:=0;
|
|
|
+ if new_focus>=limit.y then
|
|
|
+ new_focus:=limit.y-1;
|
|
|
+ if foc<>new_focus then
|
|
|
+ set_focus(new_focus);
|
|
|
+ m:=mouseevent(event,evMouseMove+evMouseAuto);
|
|
|
+ if m then
|
|
|
+ mouse_drag:=true;
|
|
|
+ until not m;
|
|
|
+ if event.double then
|
|
|
+ selected(foc)
|
|
|
+ else if not mouse_drag then
|
|
|
+ begin
|
|
|
+ cur:=graph_of_focus(graph);
|
|
|
+ if mouse.x<length(graph) then
|
|
|
+ begin
|
|
|
+ adjust(cur,not isexpanded(cur));
|
|
|
+ update;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function Toutlineviewer.haschildren(node:pointer):boolean;
|
|
|
+
|
|
|
+begin
|
|
|
+ abstract;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.isexpanded(node:pointer):boolean;
|
|
|
+
|
|
|
+begin
|
|
|
+ abstract;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutlineviewer.isselected(i:sw_integer):boolean;
|
|
|
+
|
|
|
+begin
|
|
|
+ isselected:=foc=i;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.selected(i:sw_integer);
|
|
|
+
|
|
|
+begin
|
|
|
+ {Does nothing by default.}
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.set_focus(Afocus:sw_integer);
|
|
|
+
|
|
|
+begin
|
|
|
+ assert((Afocus>=0) and (Afocus<limit.y));
|
|
|
+ focused(Afocus);
|
|
|
+ if Afocus<delta.y then
|
|
|
+ scrollto(delta.x,Afocus)
|
|
|
+ else if Afocus-size.y>=delta.y then
|
|
|
+ scrollto(delta.x,Afocus-size.y+1);
|
|
|
+ drawview;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.setstate(Astate:word;enable:boolean);
|
|
|
+
|
|
|
+begin
|
|
|
+ if Astate and sffocused<>0 then
|
|
|
+ drawview;
|
|
|
+ inherited setstate(Astate,enable);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutlineviewer.update;
|
|
|
+
|
|
|
+var count:sw_integer;
|
|
|
+ maxwidth:byte;
|
|
|
+
|
|
|
+ procedure check_item(cur:pointer;level,position:sw_integer;
|
|
|
+ lines:longint;flags:word);
|
|
|
+
|
|
|
+ var width:word;
|
|
|
+
|
|
|
+ begin
|
|
|
+ inc(count);
|
|
|
+ width:=length(gettext(cur))+length(getgraph(level,lines,flags));
|
|
|
+ if width>maxwidth then
|
|
|
+ maxwidth:=width;
|
|
|
+ end;
|
|
|
+
|
|
|
+begin
|
|
|
+ count:=0;
|
|
|
+ maxwidth:=0;
|
|
|
+ foreach(@check_item);
|
|
|
+ setlimit(maxwidth,count);
|
|
|
+ set_focus(foc);
|
|
|
+end;
|
|
|
+
|
|
|
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
+{ Toutline object methods }
|
|
|
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
+
|
|
|
+constructor Toutline.init(var bounds:Trect;
|
|
|
+ AHscrollbar,AVscrollbar:Pscrollbar;
|
|
|
+ Aroot:Pnode);
|
|
|
+
|
|
|
+begin
|
|
|
+ inherited init(bounds,AHscrollbar,AVscrollbar);
|
|
|
+ root:=Aroot;
|
|
|
+ update;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Toutline.adjust(node:pointer;expand:boolean);
|
|
|
+
|
|
|
+begin
|
|
|
+ assert(node<>nil);
|
|
|
+ Pnode(node)^.expanded:=expand;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutline.getnumchildren(node:pointer):sw_integer;
|
|
|
+
|
|
|
+var p:Pnode;
|
|
|
+
|
|
|
+begin
|
|
|
+ assert(node<>nil);
|
|
|
+ p:=Pnode(node)^.childlist;
|
|
|
+ getnumchildren:=0;
|
|
|
+ while p<>nil do
|
|
|
+ begin
|
|
|
+ inc(getnumchildren);
|
|
|
+ p:=p^.next;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutline.getchild(node:pointer;i:sw_integer):pointer;
|
|
|
+
|
|
|
+begin
|
|
|
+ assert(node<>nil);
|
|
|
+ getchild:=Pnode(node)^.childlist;
|
|
|
+ while i<>0 do
|
|
|
+ begin
|
|
|
+ dec(i);
|
|
|
+ getchild:=Pnode(getchild)^.next;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutline.getroot:pointer;
|
|
|
+
|
|
|
+begin
|
|
|
+ getroot:=root;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutline.gettext(node:pointer):string;
|
|
|
+
|
|
|
+begin
|
|
|
+ assert(node<>nil);
|
|
|
+ gettext:=Pnode(node)^.text^;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutline.haschildren(node:pointer):boolean;
|
|
|
+
|
|
|
+begin
|
|
|
+ assert(node<>nil);
|
|
|
+ haschildren:=Pnode(node)^.childlist<>nil;
|
|
|
+end;
|
|
|
+
|
|
|
+function Toutline.isexpanded(node:pointer):boolean;
|
|
|
+
|
|
|
+begin
|
|
|
+ assert(node<>nil);
|
|
|
+ isexpanded:=Pnode(node)^.expanded;
|
|
|
+end;
|
|
|
+
|
|
|
+destructor Toutline.done;
|
|
|
+
|
|
|
+begin
|
|
|
+ disposenode(root);
|
|
|
+ inherited done;
|
|
|
+end;
|
|
|
+
|
|
|
+end.
|