public import "ecere" import "ArrayFactoredGrowth" import "ArrayBinarySorted" import "ExplorerTree" public class FileTreeBranchBSArray : ArrayBinarySorted { type = class(FileTreeBranch); public: FileTreeBranch * const _; BSloc Add(FileTreeBranch item) { BSloc result = Find(item); if(!result.valid) { Insert(result.pos, 1); _[result.pos] = item; } return result; } BSloc Remove(FileTreeBranch item) { } } public class FileTreeBranchArray : Array { type = class(FileTreeBranch); public: FileTreeBranch * const _; FileTreeBranch * Add(FileTreeBranch item) { uint pos = _count; Append(1); _[pos] = item; return &_[pos]; } FileTreeBranch * AddBefore(uint position, FileTreeBranch item) { Insert(position, 1); _[position] = item; return &_[position]; } } public class FileTreeBranch : struct { FileTreeBranch prev, next; bool loaded, childrenLoaded; int indent; char * name; char * info; DataRow row; List children; FileItemType type; FileTreeBranch parent; FileStats stats; void GetPath(String outputPath) { FileTreeBranch up; strcpy(outputPath, name); if(parent) { for(up = parent; up; up = up.parent) { char temp[MAX_LOCATION]; strcpy(temp, up.name); PathCat(temp, outputPath); strcpy(outputPath, temp); } } } bool IsChildOf(FileTreeBranch branch) { FileTreeBranch test; for(test = parent; test; test = test.parent) if(test == branch) return true; return false; } void DuplicateChildren(bool recursive, bool forceExpanded, FileTreeBranch addTo, ListBox tree) { if(children.first) { FileTreeBranch child; for(child = children.first; child; child = child.next) { FileTreeBranch copy { }; copy.name = CopyString(child.name); copy.type = child.type; AddBranch(copy, child.loaded, false, addTo, tree); if(forceExpanded) copy.row.collapsed = false; if(recursive) child.DuplicateChildren(recursive, forceExpanded, copy, tree); } } } void EnsureVisible(bool expand) { if(parent) parent.EnsureVisible(true); if(expand) row.collapsed = false; } void OnFree() { } void Free() { FileTreeBranch child; for(; (child = children.first); ) { child.Free(); children.Delete(child); } //if(name) delete name; delete info; } void Delete() { Free(); if(parent) parent.children.Delete(this); } void OnDisplay(Surface surface, int x, int y, int width, ExplorerListBox icons, Alignment alignment, DataDisplayFlags displayFlags) { //int indentSize = (displayFlags.dropBox) ? 0 : 10; int indent = 16; int xStart; int len; int w, h; //int textOffset; char label[MAX_FILENAME]; Bitmap icon; if(!this) return; /*Bitmap*/ icon = icons.icons[type].bitmap; //xStart = indent * indent + x + (icon ? (icon.width + 5) : 0); xStart = x + (icon ? (icon.width + 5) : 0); if(!name) return; if(info) sprintf(label, "%s [%s]", name, info); else strcpy(label, name); len = strlen(label); if(!icon) { if(type == folder || type == folderOpen) surface.SetForeground(yellow); //indentSize = 8; indent = 8; } //textOffset = indent * indentSize + (icon ? (icon.width + 4) : 0); surface.TextOpacity(false); surface.TextExtent(label, len, &w, &h); h = Max(h, 16); // Draw the current row stipple if(displayFlags.selected) //surface.Area(xStart - 1, y, xStart - 1, y + h - 1); //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1); surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1); //surface.WriteTextDots(alignment, x + textOffset, y + 2, width - textOffset, name, strlen(name)); surface.WriteTextDots(alignment, xStart, y + 2, width, label, len); if(!guiApp.textMode) { if(displayFlags.current) { if(displayFlags.active) { surface.LineStipple(0x5555); if(displayFlags.selected) surface.SetForeground(0xFFFFFF80); else surface.SetForeground(black); } else { surface.SetForeground(selectionColor); } surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1); surface.LineStipple(0); } if(icon) { //surface.blend = true; //surface.alphaWrite = blend; surface.SetForeground(white); //surface.Blit(icon, x + indent * indentSize, y,0,0, icon.width, icon.height); surface.Blit(icon, x,y,0,0, icon.width, icon.height); } } } int OnCompare(FileTreeBranch b) { int result; if(type == b.type || (type < folder && b.type < folder) || (type >= drive)) result = strcmpi(name, b.name); else { if(type == folder && b.type < folder) result = -1; else if(type < folder && b.type == folder) result = 1; } return result; } char * OnGetString(char * tempString, FileSystemToolWindow fileSysToolWnd, bool * needClass) { return name ? name : ""; } }; FileTreeBranch MakeFileTreeBranch(const FileStats stats, const char * name) { FileTreeBranch fileTreeBranch { stats = stats }; fileTreeBranch.name = CopyString(name); if(!fileTreeBranch.name) fileTreeBranch.name = null; if(stats.attribs.isDirectory) { fileTreeBranch.type = (stats.attribs.isDrive) ? drive : folder; if(stats.attribs.isServer) fileTreeBranch.type = server; if(stats.attribs.isShare) fileTreeBranch.type = share; if(stats.attribs.isCDROM) fileTreeBranch.type = cdrom; if(stats.attribs.isRemote) fileTreeBranch.type = netDrive; if(stats.attribs.isRemovable) { if(name[0] == 'A' || name[0] == 'B') fileTreeBranch.type = floppy; else fileTreeBranch.type = removable; } } else { char extension[MAX_EXTENSION]; GetExtension(fileTreeBranch.name, extension); fileTreeBranch.type = FileItemType::SelectByExtension(extension); } return fileTreeBranch; } void AddBranch(FileTreeBranch branch, bool loaded, bool addLoader, FileTreeBranch addTo, ListBox tree) { DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : tree.AddRow(); if(addTo) { branch.parent = addTo; branch.indent = addTo.indent + 1; addTo.children.Add(branch); } row.tag = (int)branch; branch.row = row; row.SetData(null, branch); branch.loaded = loaded; if(addLoader) //AddBranch(FileTreeBranch { }, false, false, branch, tree); // why would this create a compile error? AddBranch(FileTreeBranch { type = none }, false, false, branch, tree); if(branch.indent > 0) row.collapsed = true; else if(branch.type == folder) branch.type = folderOpen; } void BranchLoad(FileTreeBranch branch, ListBox tree) { if(!branch.loaded) { char path[MAX_LOCATION]; branch.GetPath(path); { FileListing listing { path }; if(branch.children.count == 1) DeleteBranch(branch.children.first, tree); while(listing.Find()) { if(listing.stats.attribs.isDirectory) { FileTreeBranch child = MakeFileTreeBranch(listing.stats, listing.name); AddBranch(child, true, false, branch, tree); BranchChildLoad(child, branch, tree); } } } branch.childrenLoaded = true; branch.loaded = true; } else if(!branch.childrenLoaded) { FileTreeBranch child; if(branch.children.first) { for(child = branch.children.first; child; child = child.next) { if(!child.loaded) BranchLoad(child, tree); else if(!child.childrenLoaded) BranchChildLoad(child, branch, tree); } branch.childrenLoaded = true; } } } static void BranchChildLoad(FileTreeBranch parent, FileTreeBranch branch, ListBox tree) { char path[MAX_LOCATION]; parent.GetPath(path); { bool added = false; FileListing listing { path }; while(listing.Find()) { if(listing.stats.attribs.isDirectory) { FileTreeBranch child = MakeFileTreeBranch(listing.stats, listing.name); AddBranch(child, true, false, parent, tree); added = true; } } if(!added) added = true; } //parent.childrenLoaded = true; } void DeleteBranch(FileTreeBranch branch, ListBox tree) { FileTreeBranch child; for(; (child = branch.children.first); ) DeleteBranch(child, tree); tree.DeleteRow(branch.row); branch.Delete(); }