updated .gitignore for .configs/
[ede] / explorer / src / FileTreeBranch.ec
1 public import "ecere"
2
3 import "ArrayFactoredGrowth"
4 import "ArrayBinarySorted"
5
6 import "ExplorerTree"
7
8 public class FileTreeBranchBSArray : ArrayBinarySorted
9 {
10    type = class(FileTreeBranch);
11 public:
12    FileTreeBranch * const _;
13    BSloc Add(FileTreeBranch item)
14    {
15       BSloc result = Find(item);
16       if(!result.valid)
17       {
18          Insert(result.pos, 1);
19          _[result.pos] = item;
20       }
21       return result;
22    }
23    BSloc Remove(FileTreeBranch item)
24    {
25       
26    }
27 }
28
29 public class FileTreeBranchArray : Array
30 {
31    type = class(FileTreeBranch);
32 public:
33    FileTreeBranch * const _;
34    FileTreeBranch * Add(FileTreeBranch item)
35    {
36       uint pos = _count;
37       Append(1);
38       _[pos] = item;
39       return &_[pos];
40    }
41    FileTreeBranch * AddBefore(uint position, FileTreeBranch item)
42    {
43       Insert(position, 1);
44       _[position] = item;
45       return &_[position];
46    }
47 }
48
49 public class FileTreeBranch : struct
50 {
51    FileTreeBranch prev, next;
52
53    bool loaded, childrenLoaded;
54    int indent;
55    char * name;
56    char * info;
57    DataRow row;
58    List children;
59    FileItemType type;
60    FileTreeBranch parent;
61
62    FileStats stats;
63
64    void GetPath(String outputPath)
65    {  
66       FileTreeBranch up;
67       strcpy(outputPath, name);
68       if(parent)
69       {
70          for(up = parent; up; up = up.parent)
71          {
72             char temp[MAX_LOCATION];
73             strcpy(temp, up.name);
74             PathCat(temp, outputPath);
75             strcpy(outputPath, temp);
76          }
77       }
78    }
79
80    bool IsChildOf(FileTreeBranch branch)
81    {
82       FileTreeBranch test;
83       for(test = parent; test; test = test.parent)
84          if(test == branch)
85             return true;
86       return false;
87    }
88
89    void DuplicateChildren(bool recursive, bool forceExpanded, FileTreeBranch addTo, ListBox tree)
90    {
91       if(children.first)
92       {
93          FileTreeBranch child;
94          
95          for(child = children.first; child; child = child.next)
96          {
97             FileTreeBranch copy { };
98             copy.name = CopyString(child.name);
99             copy.type = child.type;
100             AddBranch(copy, child.loaded, false, addTo, tree);
101             if(forceExpanded)
102                copy.row.collapsed = false;
103             if(recursive)
104                child.DuplicateChildren(recursive, forceExpanded, copy, tree);
105          }
106       }
107    }
108    
109    void EnsureVisible(bool expand)
110    {
111       if(parent)
112          parent.EnsureVisible(true);
113       if(expand)
114          row.collapsed = false;
115    }
116
117    void OnFree()
118    {
119    }
120
121    void Free()
122    {
123       FileTreeBranch child;
124       for(; (child = children.first); )
125       {
126          child.Free();
127          children.Delete(child);
128       }
129       //if(name)
130       delete name;
131       delete info;
132    }
133
134    void Delete()
135    {
136       Free();
137       if(parent)
138          parent.children.Delete(this);
139    }
140
141    void OnDisplay(Surface surface, int x, int y, int width, ExplorerListBox icons, Alignment alignment, DataDisplayFlags displayFlags)
142    {
143       //int indentSize = (displayFlags.dropBox) ? 0 : 10;
144       int indent = 16;
145       int xStart;
146       int len;
147       int w, h;
148       //int textOffset;
149       char label[MAX_FILENAME];
150
151       Bitmap icon;
152       if(!this)
153          return;
154       
155       /*Bitmap*/ 
156       icon = icons.icons[type].bitmap;
157       //xStart = indent * indent + x + (icon ? (icon.width + 5) : 0);
158       xStart = x + (icon ? (icon.width + 5) : 0);
159
160       if(!name)
161          return;
162
163       if(info)
164          sprintf(label, "%s [%s]", name, info);
165       else
166          strcpy(label, name);
167       len = strlen(label);
168       
169       if(!icon)
170       {
171          if(type == folder || type == folderOpen)
172             surface.SetForeground(yellow);
173          //indentSize = 8;
174          indent = 8;
175       }
176       //textOffset = indent * indentSize + (icon ? (icon.width + 4) : 0);
177       
178       surface.TextOpacity(false);
179       surface.TextExtent(label, len, &w, &h);
180       h = Max(h, 16);
181     
182       // Draw the current row stipple
183       if(displayFlags.selected)
184          //surface.Area(xStart - 1, y, xStart - 1, y + h - 1);
185          //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1);
186          surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1);
187       
188       //surface.WriteTextDots(alignment, x + textOffset, y + 2, width - textOffset, name, strlen(name));
189       surface.WriteTextDots(alignment, xStart, y + 2, width, label, len);
190
191       if(!guiApp.textMode)
192       {
193          if(displayFlags.current)
194          {
195             if(displayFlags.active)
196             {
197                surface.LineStipple(0x5555);
198                if(displayFlags.selected)
199                   surface.SetForeground(0xFFFFFF80);
200                else
201                   surface.SetForeground(black);
202             }
203             else
204             {
205                surface.SetForeground(selectionColor);
206             }
207             surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1);
208             surface.LineStipple(0);
209          }
210
211          if(icon)
212          {
213             //surface.blend = true;
214             //surface.alphaWrite = blend;
215             surface.SetForeground(white);
216             //surface.Blit(icon, x + indent * indentSize, y,0,0, icon.width, icon.height);
217             surface.Blit(icon, x,y,0,0, icon.width, icon.height);
218          }
219       }
220    }
221
222    int OnCompare(FileTreeBranch b)
223    {
224       int result;
225       if(type == b.type || (type < folder && b.type < folder) || (type >= drive))
226          result = strcmpi(name, b.name);
227       else
228       {
229          if(type == folder && b.type < folder) result = -1;
230          else if(type < folder && b.type == folder) result = 1;
231       }
232       return result;
233    }
234
235    char * OnGetString(char * tempString, FileSystemToolWindow fileSysToolWnd, bool * needClass)
236    {
237       return name ? name : "";
238    }
239 };
240
241 FileTreeBranch MakeFileTreeBranch(const FileStats stats, const char * name)
242 {
243    FileTreeBranch fileTreeBranch { stats = stats };
244    fileTreeBranch.name = CopyString(name);
245    if(!fileTreeBranch.name)
246       fileTreeBranch.name = null;
247    if(stats.attribs.isDirectory)
248    {
249       fileTreeBranch.type = (stats.attribs.isDrive) ? drive : folder;
250       if(stats.attribs.isServer) fileTreeBranch.type = server;
251       if(stats.attribs.isShare) fileTreeBranch.type = share;
252       if(stats.attribs.isCDROM) fileTreeBranch.type = cdrom;
253       if(stats.attribs.isRemote) fileTreeBranch.type = netDrive;
254       if(stats.attribs.isRemovable) 
255       {
256          if(name[0] == 'A' || name[0] == 'B')
257             fileTreeBranch.type = floppy;
258          else
259             fileTreeBranch.type = removable;
260       }
261    }
262    else
263    {
264       char extension[MAX_EXTENSION];
265       GetExtension(fileTreeBranch.name, extension);
266       fileTreeBranch.type = FileItemType::SelectByExtension(extension);
267    }
268    return fileTreeBranch;
269 }
270
271 void AddBranch(FileTreeBranch branch, bool loaded, bool addLoader, FileTreeBranch addTo, ListBox tree)
272 {
273    DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : tree.AddRow();
274    if(addTo)
275    {
276       branch.parent = addTo;
277       branch.indent = addTo.indent + 1;
278       addTo.children.Add(branch);
279    }
280    row.tag = (int)branch;
281    branch.row = row;
282    row.SetData(null, branch);
283
284    branch.loaded = loaded;
285    if(addLoader)
286       //AddBranch(FileTreeBranch { }, false, false, branch, tree); // why would this create a compile error?
287       AddBranch(FileTreeBranch { type = none }, false, false, branch, tree);
288
289    if(branch.indent > 0)
290       row.collapsed = true;
291    else if(branch.type == folder)
292       branch.type = folderOpen;
293 }
294
295 void BranchLoad(FileTreeBranch branch, ListBox tree)
296 {
297    if(!branch.loaded)
298    {
299       char path[MAX_LOCATION];
300       branch.GetPath(path);
301       {
302          FileListing listing { path };
303          if(branch.children.count == 1)
304          DeleteBranch(branch.children.first, tree);
305
306          while(listing.Find())
307          {
308             if(listing.stats.attribs.isDirectory)
309             {
310                FileTreeBranch child = MakeFileTreeBranch(listing.stats, listing.name);
311                AddBranch(child, true, false, branch, tree);
312                BranchChildLoad(child, branch, tree);
313             }
314          }
315       }
316       branch.childrenLoaded = true;
317       branch.loaded = true;
318    }
319    else if(!branch.childrenLoaded)
320    {
321       FileTreeBranch child;
322       if(branch.children.first)
323       {
324          for(child = branch.children.first; child; child = child.next)
325          {
326             if(!child.loaded)
327                BranchLoad(child, tree);
328             else if(!child.childrenLoaded)
329                BranchChildLoad(child, branch, tree);
330          }
331          branch.childrenLoaded = true;
332       }
333    }
334 }
335
336 static void BranchChildLoad(FileTreeBranch parent, FileTreeBranch branch, ListBox tree)
337 {
338    char path[MAX_LOCATION];
339    parent.GetPath(path);
340    {
341       bool added = false;
342       FileListing listing { path };
343       while(listing.Find())
344       {
345          if(listing.stats.attribs.isDirectory)
346          {
347             FileTreeBranch child = MakeFileTreeBranch(listing.stats, listing.name);
348             AddBranch(child, true, false, parent, tree);
349             added = true;
350          }
351       }
352       if(!added)
353          added = true;
354    }
355    //parent.childrenLoaded = true;
356 }
357
358 void DeleteBranch(FileTreeBranch branch, ListBox tree)
359 {
360    FileTreeBranch child;
361    for(; (child = branch.children.first); )
362       DeleteBranch(child, tree);
363    tree.DeleteRow(branch.row);
364    branch.Delete();
365 }