| 1 | Unit DirOutLn; | 
|---|
| 2 |  | 
|---|
| 3 | Interface | 
|---|
| 4 |  | 
|---|
| 5 | Uses | 
|---|
| 6 | SysUtils, Classes, Graphics, StdCtrls, Forms, Dialogs, | 
|---|
| 7 | Outline; | 
|---|
| 8 |  | 
|---|
| 9 | type | 
|---|
| 10 | TDirectoryOutline=Class(TOutline) | 
|---|
| 11 | Private | 
|---|
| 12 | FDirectory:String; | 
|---|
| 13 | FDrive:Char; | 
|---|
| 14 | FOnChange:TNotifyEvent; | 
|---|
| 15 | FlOpen,FlClose:TBitmap; | 
|---|
| 16 | Private | 
|---|
| 17 | Procedure SetDrive(NewDrive:Char); | 
|---|
| 18 | Procedure SetDirectory(Const NewDir:String); | 
|---|
| 19 | Procedure FillLevel(Node:TOutlineNode); | 
|---|
| 20 | Protected | 
|---|
| 21 | Procedure BuildTree;Virtual; | 
|---|
| 22 | Procedure WalkTree(Const Dir:String); | 
|---|
| 23 | Procedure SetupShow;Override; | 
|---|
| 24 | Procedure Expand(Index: Longint);Override; | 
|---|
| 25 | Procedure BuildOneLevel(ParentLevel:Longint);Virtual; | 
|---|
| 26 | Procedure Change;Virtual; | 
|---|
| 27 | Public | 
|---|
| 28 | Procedure SetupComponent;Override; | 
|---|
| 29 | Destructor Destroy;Override; | 
|---|
| 30 | Procedure Click;Override; | 
|---|
| 31 | Public | 
|---|
| 32 | Property Drive:Char read FDrive write SetDrive; | 
|---|
| 33 | Property Directory:String  read FDirectory write SetDirectory; | 
|---|
| 34 | Property Lines; | 
|---|
| 35 | Property OnChange:TNotifyEvent read FOnChange write FOnChange; | 
|---|
| 36 | End; | 
|---|
| 37 |  | 
|---|
| 38 | Implementation | 
|---|
| 39 |  | 
|---|
| 40 | {$R DirOutLn} | 
|---|
| 41 |  | 
|---|
| 42 | Procedure TDirectoryOutline.Change; | 
|---|
| 43 | Begin | 
|---|
| 44 | If FOnChange<>Nil Then FOnChange(Self); | 
|---|
| 45 | End; | 
|---|
| 46 |  | 
|---|
| 47 | Procedure TDirectoryOutline.FillLevel(Node:TOutlineNode); | 
|---|
| 48 | Var | 
|---|
| 49 | TempIndex:Longint; | 
|---|
| 50 | Root:ShortString; | 
|---|
| 51 | SearchRec: TSearchRec; | 
|---|
| 52 | Status:Integer; | 
|---|
| 53 | s,s1:String; | 
|---|
| 54 | Begin | 
|---|
| 55 | If Node.Data<>Nil Then exit; //already filled | 
|---|
| 56 | Root:=Node.FullPath; | 
|---|
| 57 | If Root[Length(Root)] In ['\','/'] Then dec(Root[0]); | 
|---|
| 58 |  | 
|---|
| 59 | Status:=FindFirst(Root+'\*.*',faDirectory,SearchRec); | 
|---|
| 60 | While Status=0 Do | 
|---|
| 61 | Begin | 
|---|
| 62 | If SearchRec.Attr And faDirectory = faDirectory Then | 
|---|
| 63 | Begin | 
|---|
| 64 | If ((SearchRec.Name<>'.')And(SearchRec.Name<>'..')) Then //no .. and . | 
|---|
| 65 | Begin | 
|---|
| 66 | If Node.HasItems Then //must sort | 
|---|
| 67 | Begin | 
|---|
| 68 | TempIndex:=Node.GetFirstChild; | 
|---|
| 69 | s:=SearchRec.Name; | 
|---|
| 70 | UpcaseStr(s); | 
|---|
| 71 | If TempIndex<>-1 Then | 
|---|
| 72 | Begin | 
|---|
| 73 | s1:=Items[TempIndex].Text; | 
|---|
| 74 | UpcaseStr(s1); | 
|---|
| 75 | End; | 
|---|
| 76 | While (TempIndex<>-1)And(s1<s) Do | 
|---|
| 77 | Begin | 
|---|
| 78 | TempIndex:=Node.GetNextChild(TempIndex); | 
|---|
| 79 | If TempIndex<>-1 Then | 
|---|
| 80 | Begin | 
|---|
| 81 | s1:=Items[TempIndex].Text; | 
|---|
| 82 | UpcaseStr(s1); | 
|---|
| 83 | End; | 
|---|
| 84 | End; | 
|---|
| 85 | If TempIndex<>-1 Then Insert(TempIndex, SearchRec.Name) | 
|---|
| 86 | Else Add(Node.GetLastChild, SearchRec.Name); | 
|---|
| 87 | End | 
|---|
| 88 | Else AddChild(Node.Index,SearchRec.Name); | 
|---|
| 89 | End; | 
|---|
| 90 | End; | 
|---|
| 91 | Status:=FindNext(SearchRec); | 
|---|
| 92 | End; | 
|---|
| 93 |  | 
|---|
| 94 | Node.Data:=Pointer(1); //mark item as processed | 
|---|
| 95 | end; | 
|---|
| 96 |  | 
|---|
| 97 |  | 
|---|
| 98 | Procedure TDirectoryOutline.BuildOneLevel(ParentLevel:Longint); | 
|---|
| 99 | Var Index:LongInt; | 
|---|
| 100 | RootNode:TOutlineNode; | 
|---|
| 101 | FList:TList; | 
|---|
| 102 | t:longint; | 
|---|
| 103 | Begin | 
|---|
| 104 | FillLevel(Items[ParentLevel]); | 
|---|
| 105 |  | 
|---|
| 106 | RootNode := Items[ParentLevel]; | 
|---|
| 107 | FList.Create; | 
|---|
| 108 | Index:=RootNode.GetFirstChild; | 
|---|
| 109 | While Index<>-1 Do | 
|---|
| 110 | Begin | 
|---|
| 111 | FList.Add(Items[Index]); | 
|---|
| 112 | Index:=RootNode.GetNextChild(Index); | 
|---|
| 113 | End; | 
|---|
| 114 |  | 
|---|
| 115 | For t:=0 To FList.Count-1 Do FillLevel(TOutlineNode(FList[t])); | 
|---|
| 116 | FList.Destroy; | 
|---|
| 117 | End; | 
|---|
| 118 |  | 
|---|
| 119 | Procedure TDirectoryOutline.SetupComponent; | 
|---|
| 120 | Begin | 
|---|
| 121 | Inherited SetupComponent; | 
|---|
| 122 | BorderStyle:=bsNone; | 
|---|
| 123 | FlOpen.Create; | 
|---|
| 124 | FlOpen.LoadFromResourceName('FolderOpen'); | 
|---|
| 125 | FlClose.Create; | 
|---|
| 126 | FlClose.LoadFromResourceName('FolderClose'); | 
|---|
| 127 | PictureOpen:=FlOpen; | 
|---|
| 128 | PictureClosed:=FlClose; | 
|---|
| 129 | PictureLeaf:=PictureClosed; | 
|---|
| 130 | PlusMinusSize.CX:=14; | 
|---|
| 131 | PlusMinusSize.CY:=14; | 
|---|
| 132 | ShowPlusMinus:=False; | 
|---|
| 133 | Name:='DirectoryOutline'; | 
|---|
| 134 | End; | 
|---|
| 135 |  | 
|---|
| 136 | Destructor TDirectoryOutline.Destroy; | 
|---|
| 137 | Begin | 
|---|
| 138 | Inherited Destroy; | 
|---|
| 139 |  | 
|---|
| 140 | FlOpen.Destroy; | 
|---|
| 141 | FlClose.Destroy; | 
|---|
| 142 | End; | 
|---|
| 143 |  | 
|---|
| 144 | Procedure TDirectoryOutline.Click; | 
|---|
| 145 | Begin | 
|---|
| 146 | inherited Click; | 
|---|
| 147 | Try | 
|---|
| 148 | If SelectedItem=-1 Then Beep(1200,400); | 
|---|
| 149 | Directory :=Items[SelectedItem].FullPath; | 
|---|
| 150 | Except | 
|---|
| 151 | End; | 
|---|
| 152 | End; | 
|---|
| 153 |  | 
|---|
| 154 | Procedure TDirectoryOutline.SetDrive(NewDrive:Char); | 
|---|
| 155 | Begin | 
|---|
| 156 | FDrive:=Upcase(NewDrive); | 
|---|
| 157 | ChDir(FDrive+':'); | 
|---|
| 158 | GetDir(0,FDirectory); | 
|---|
| 159 | If Not (csLoading In ComponentState) Then BuildTree; | 
|---|
| 160 | End; | 
|---|
| 161 |  | 
|---|
| 162 | Procedure TDirectoryOutline.SetDirectory(Const NewDir:String); | 
|---|
| 163 | Var | 
|---|
| 164 | TempPath: ShortString; | 
|---|
| 165 | Node:TOutlineNode; | 
|---|
| 166 | t:LongInt; | 
|---|
| 167 |  | 
|---|
| 168 | Function FindNode(Node:TOutlineNode):TOutlineNode; | 
|---|
| 169 | Var s:String; | 
|---|
| 170 | t:LongInt; | 
|---|
| 171 | Node1:TOutlineNode; | 
|---|
| 172 | Begin | 
|---|
| 173 | s:=Node.FullPath; | 
|---|
| 174 | UpcaseStr(s); | 
|---|
| 175 | If s=TempPath Then | 
|---|
| 176 | Begin | 
|---|
| 177 | result:=Node; | 
|---|
| 178 | exit; | 
|---|
| 179 | End; | 
|---|
| 180 |  | 
|---|
| 181 | For t:=0 To Node.ItemCount-1 Do | 
|---|
| 182 | Begin | 
|---|
| 183 | Node1:=Node.Items[t]; | 
|---|
| 184 | Node1:=FindNode(Node1); | 
|---|
| 185 | If Node1<>Nil Then | 
|---|
| 186 | Begin | 
|---|
| 187 | Result:=Node1; | 
|---|
| 188 | exit; | 
|---|
| 189 | End; | 
|---|
| 190 | End; | 
|---|
| 191 | Result:=Nil; | 
|---|
| 192 | End; | 
|---|
| 193 |  | 
|---|
| 194 | Begin | 
|---|
| 195 | If ((NewDir='')Or(NewDir=FDirectory)) Then exit; | 
|---|
| 196 |  | 
|---|
| 197 | TempPath := ExpandFileName(NewDir); | 
|---|
| 198 | If TempPath[Length(TempPath)] In ['\','/'] Then | 
|---|
| 199 | If Length(TempPath)>3 Then Dec(TempPath[0]); | 
|---|
| 200 |  | 
|---|
| 201 | ChDir(TempPath); | 
|---|
| 202 | FDirectory:=TempPath; | 
|---|
| 203 | If FDirectory[1]<>Drive Then Drive:=FDirectory[1] | 
|---|
| 204 | Else | 
|---|
| 205 | Begin | 
|---|
| 206 | WalkTree(TempPath); | 
|---|
| 207 | Change; | 
|---|
| 208 | End; | 
|---|
| 209 |  | 
|---|
| 210 | TempPath:=FDirectory; | 
|---|
| 211 | UpcaseStr(TempPath); | 
|---|
| 212 | For t:=0 To ItemCount-1 Do | 
|---|
| 213 | Begin | 
|---|
| 214 | Node:=Items[t]; | 
|---|
| 215 | Node:=FindNode(Node); | 
|---|
| 216 | If Node<>Nil Then Break; | 
|---|
| 217 | End; | 
|---|
| 218 | If Node<>Nil Then | 
|---|
| 219 | If SelectedNode<>Node Then SelectedNode:=Node; | 
|---|
| 220 | End; | 
|---|
| 221 |  | 
|---|
| 222 | Procedure TDirectoryOutline.SetupShow; | 
|---|
| 223 | Var CurDir:String; | 
|---|
| 224 | Begin | 
|---|
| 225 | Inherited SetupShow; | 
|---|
| 226 |  | 
|---|
| 227 | If FDrive=#0 Then  //test if unassigned | 
|---|
| 228 | Begin | 
|---|
| 229 | {$I-} | 
|---|
| 230 | GetDir(0, CurDir); | 
|---|
| 231 | {$I+} | 
|---|
| 232 | If IoResult<>0 Then exit; | 
|---|
| 233 | FDrive := Upcase(CurDir[1]); | 
|---|
| 234 | FDirectory := CurDir; | 
|---|
| 235 | End; | 
|---|
| 236 |  | 
|---|
| 237 | BuildTree; | 
|---|
| 238 | End; | 
|---|
| 239 |  | 
|---|
| 240 | Procedure TDirectoryOutline.BuildTree; | 
|---|
| 241 | Var | 
|---|
| 242 | RootIndex: Longint; | 
|---|
| 243 | Begin | 
|---|
| 244 | Clear; | 
|---|
| 245 | If FDrive=#0 Then exit; | 
|---|
| 246 | RootIndex:=AddChild(0,Drive+':'); | 
|---|
| 247 | WalkTree(FDirectory); | 
|---|
| 248 | Change; | 
|---|
| 249 | End; | 
|---|
| 250 |  | 
|---|
| 251 | Procedure TDirectoryOutline.WalkTree(Const Dir:String); | 
|---|
| 252 | Var | 
|---|
| 253 | b:LongInt; | 
|---|
| 254 | CurPath,NextDir,s:ShortString; | 
|---|
| 255 | TempItem,TempIndex: Longint; | 
|---|
| 256 | begin | 
|---|
| 257 | TempItem := 1; { start at root } | 
|---|
| 258 |  | 
|---|
| 259 | CurPath := Dir; | 
|---|
| 260 | b:=Pos(':',CurPath); | 
|---|
| 261 | If b>0 then CurPath:=Copy(CurPath,b+1,255); | 
|---|
| 262 | If CurPath<>'' Then | 
|---|
| 263 | If CurPath[1]='\' Then System.Delete(CurPath,1,1); | 
|---|
| 264 |  | 
|---|
| 265 | NextDir := CurPath; | 
|---|
| 266 | Repeat | 
|---|
| 267 | b:=Pos('\',CurPath); | 
|---|
| 268 | If b=0 Then b:=Pos('/',CurPath); | 
|---|
| 269 | If b > 0 then | 
|---|
| 270 | Begin | 
|---|
| 271 | NextDir:=Copy(CurPath,1,b-1); | 
|---|
| 272 | CurPath:=Copy(CurPath,b+1,255); | 
|---|
| 273 | End | 
|---|
| 274 | Else | 
|---|
| 275 | Begin | 
|---|
| 276 | NextDir:=CurPath; | 
|---|
| 277 | CurPath:=''; | 
|---|
| 278 | End; | 
|---|
| 279 |  | 
|---|
| 280 | Items[TempItem].Expanded:=True; | 
|---|
| 281 | TempIndex:=Items[TempItem].GetFirstChild; | 
|---|
| 282 | UpcaseStr(NextDir); | 
|---|
| 283 | If CurPath='' Then TempIndex:=-1 | 
|---|
| 284 | Else While TempIndex<>-1 Do | 
|---|
| 285 | Begin | 
|---|
| 286 | s:=Items[TempIndex].Text; | 
|---|
| 287 | UpcaseStr(s); | 
|---|
| 288 | If s=NextDir Then Break; | 
|---|
| 289 | TempIndex:=Items[TempItem].GetNextChild(TempIndex); | 
|---|
| 290 | End; | 
|---|
| 291 | If TempIndex<>-1 Then TempItem:=TempIndex | 
|---|
| 292 | Else CurPath:=''; //break | 
|---|
| 293 | Until CurPath=''; | 
|---|
| 294 | End; | 
|---|
| 295 |  | 
|---|
| 296 | Procedure TDirectoryOutline.Expand(Index:Longint); | 
|---|
| 297 | Begin | 
|---|
| 298 | BuildOneLevel(Index); | 
|---|
| 299 | Inherited Expand(Index); | 
|---|
| 300 | End; | 
|---|
| 301 |  | 
|---|
| 302 | initialization | 
|---|
| 303 | RegisterClasses([TDirectoryOutline]); | 
|---|
| 304 | end. | 
|---|