X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?p=ede;a=blobdiff_plain;f=libede%2Fsrc%2FFileSystemBox.ec;h=fda27faa541d76d6d0726c5f05a2928586bdab0c;hp=cdd7aa2ddca7717bf37e11b58c2462e3fc1d08e4;hb=4943336814b7b33a190e420e7ed6014921522014;hpb=ce190f57ece361a88d3aa4827041b8136863a385 diff --git a/libede/src/FileSystemBox.ec b/libede/src/FileSystemBox.ec index cdd7aa2..fda27fa 100644 --- a/libede/src/FileSystemBox.ec +++ b/libede/src/FileSystemBox.ec @@ -8,7 +8,7 @@ static char * rootName = "File System"; #endif private: -define guiApp = ((GuiApplication)__thisModule); +define guiApp = (GuiApplication)((__thisModule).application); define selectionColor = guiApp.currentSkin.selectionColor; //Color { 10, 36, 106 }; static char * fileIconNames[] = @@ -137,25 +137,867 @@ public enum _FileType } }; -class ExplorerControl : Window +class FileSystemBoxBits { - bool previewPictures; + bool foldersOnly:1, filesOnly:1, details:1, pathColumn:1, treeBranches:1, previewPictures:1, navigateFolders:1, autoLoad:1; + bool preview:1; + //bool header:1, freeSelect:1, fullRowSelect:1, multiSelect:1, autoScroll:1, alwaysHL : 1, moveRows:1, resizable:1; + //bool moveFields:1, clearHeader:1, alwaysEdit:1, collapse:1, treeBranch:1, rootCollapse:1, heightSet:1; + //bool sortable:1, noDragging:1, fillLastField:1, expandOnAdd:1; +}; + +public class FileSystemBox : Window // should we not derive from ListBox instead? + // I say we should, but we can't right now... + // because ListBox (inside ecere library) is + // not exposing enough internal machinery... + // could we not have a different private and + // public mechanism when deriving a class than + // we do when simply instanciating a class? +/* + this stuff from the listbox would be nicely exposed... + fullRowSelect = false; + treeBranches = true; + collapseControl = true; + rootCollapseButton = true; + sortable = true; +*/ +{ + borderStyle = deep; + hasHorzScroll = false; + hasVertScroll = false; + + menu = Menu { }; + +public: + FileSystemNode root; + FileSystemBoxSelection selection { }; + + virtual bool Window::NotifyNodeSelect(FileSystemBox box, FileSystemBoxSelection selection); + //virtual bool Window::NotifyNodeNavigate(FileSystemBox box, FileSystemNode node); + virtual bool Window::NotifyNodeOpen(FileSystemBox box, FileSystemBoxSelection selection); + + property char * path + { + set + { + delete path; + if(value && value[0]) + path = CopyString(value); + if(locationBox) + locationBox.path = value; + if(created) + Load(); + } + + get { return path; } + //isset { return path && path[0]; } + } + + property bool foldersOnly { set { bits.foldersOnly = value; bits.filesOnly = !value; } get { return bits.foldersOnly; } }; + property bool filesOnly { set { bits.filesOnly = value; bits.foldersOnly = !value; } get { return bits.filesOnly; } }; + property bool previewPictures { set { bits.previewPictures = value; } get { return bits.previewPictures; } }; + property char * extensions { set { delete extensions; if(value && value[0]) extensions = CopyString(value); } get { return extensions; } } + property bool details { set { bits.details = value; ChangeViewType(); } get { return bits.details; } }; + property bool pathColumn { set { bits.pathColumn = value; ChangeViewType(); } get { return bits.pathColumn; } }; + property bool treeBranches + { + set + { + bits.treeBranches = value; + list.treeBranches = value; + list.collapseControl = value; + list.rootCollapseButton = value; + } + get { return bits.treeBranches; } + }; + property Color selectionColor { set { list.selectionColor = value; } get { return list.selectionColor; }/* isset { return selectionColor ? true : false; }*/ }; + property Color selectionText { set { list.selectionText = value; } get { return list.selectionText; }/* isset { return selectionText ? true : false; }*/ }; + property bool navigateFolders { set { bits.navigateFolders = value; bits.filesOnly = !value; } get { return bits.navigateFolders; } }; + property bool multiSelect { set { list.multiSelect = value; } get { return list.multiSelect; } }; + property bool autoLoad { set { bits.autoLoad = value; } get { return bits.autoLoad; } }; + property bool hasHeader { set { list.hasHeader = value; } get { return list.hasHeader; } }; + property bool preview + { + set + { + bits.preview = value; + split.leftPane = value ? list : null; + split.visible = value; + show.visible = value; + } + get { return bits.preview; } + }; + + property FileSystemNode node + { + get + { + if(!list) + return null; + if(!list.currentRow) + return null; + if(!list.currentRow.tag) + return null; + return (FileSystemNode)list.currentRow.tag; + } + } + + PathBox locationBox; + + void Select(FileSystemNode node) + { + if(node.row) + { + node.EnsureVisible(false); + list.SelectRow(node.row); + } + } + + void SelectMultipleByPath(Array paths) + { + DataRow row; + bool firstRow = false; + Map map { }; + for(path : paths) + map[path] = true; + for(row = list.firstRow; row; row = row.next) + { + FileSystemNode node = (FileSystemNode)row.tag; + if(map[node.path]) + { + if(!firstRow) + { + list.SelectRow(row); + firstRow = true; + } + else + row.selected = true; + } + else + row.selected = false; + } + delete map; + } + + FileSystemNode SelectLocation(char * location) + { + int c; + char * temp; + char step[MAX_LOCATION]; + + //StringArray steps { growingFactor = 4 }; + Array steps { }; + FileSystemNode result = null; + FileSystemNode node = null; + + temp = CopyString(location); + while(temp[0]) + { + GetLastDirectory(temp, step); + StripLastDirectory(temp, temp); + steps.Add(CopyString(step)); + } + + for(c = steps.count - 1; c >= 0; c--) + { + char * t = steps[c]; + node = Find(steps[c], node); + if(!node) + break; + //Select(node); + } + if(node) + { + result = node; + Select(result); + } + + steps.Free(); + delete temp; + delete steps; + + return result; + } + + FileSystemNode Find(const char * name, FileSystemNode parent) + { + FileSystemNode node = null; + FileSystemNode result = null; + if(!parent/* && !strcmp(name, "/")*/) + { + DataRow row; + for(row = list.firstRow; row; row = row.next) + { + node = (FileSystemNode)row.tag; + if(node.name && !fstrcmp(node.name, name)) + break; + } + if(node) + result = node; + //result = root; + } + else + { + FileSystemNode start = parent ? parent : root; + if(!start.bits.loaded || !start.bits.childrenLoaded) + LoadTreeNode(start); + for(node = start.children.first; node; node = node.next) + if(node.name && !fstrcmp(node.name, name)) + break; + if(node) + result = node; + } + return result; + } + + void Clear() + { + list.Clear(); + } + + void Refresh() + { + Load(); + } + +private: + FileSystemBoxBits bits; + + char * path; + char * extensions; + + BitmapResource fileIcons[_FileType]; + + Bitmap bitmap; + //BitmapArray bitmaps { growingFactor = 16 }; + + FileSystemBox() + { + char wd[MAX_LOCATION]; + GetWorkingDir(wd, sizeof(wd)); + property::path = wd; + + InitFileIcons(); + list.AddField(nameField); + bits.autoLoad = true; + } + + ~FileSystemBox() + { + delete extensions; + delete path; + } + + watch(background) + { + list.background = background; + }; + + void InitFileIcons() + { + _FileType c; + for(c = 0; c < _FileType::enumSize; c++) + { + fileIcons[c] = BitmapResource { fileIconNames[c], alphaBlend = true }; + AddResource(fileIcons[c]); + } + } + + DataField nameField { header = "Name", dataType = "FileSystemNode", width = 240, userData = this, freeData = false }; + DataField pathField { header = "Location", dataType = /*"String"*/ "char *", width = 300, freeData = false }; + DataField typeField { header = "Type", dataType = /*"String"*/ "char *", width = 40, freeData = false }; + DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right, freeData = false }; + DataField modifiedField { header = "Modified", dataType = "SecSince1970", width = 96, alignment = right, freeData = false }; + + bool OnPostCreate() + { + if(bits.autoLoad) + Load(); + return true; + } + + ListBox list + { + this; + + borderStyle = none; + hasHorzScroll = true; + hasVertScroll = true; + fullRowSelect = false; + sortable = true; + alwaysHighLight = true; + + anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; + + // WHY is this not working ? + /*void OnResize(int width, int height) + { + if(vertScroll.visible) + nameField.width = width - vertScroll.size.w; + else + nameField.width = width; + }*/ + + bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed) + { + if(row) + { + FileSystemNode node = (FileSystemNode)row.tag; + FileSystemNode child; + if(collapsed) + { + /* + for(child = node.children.last; child; child = node.children.last) + { + listBox.DeleteRow(child.row); + child.Free(); + delete child; + } + node.childrenLoaded = false; + */ + } + else + { + if(!node.bits.loaded || !node.bits.childrenLoaded) + { + LoadTreeNode(node); + //list.Sort(nameField, 1); + //node. + } + for(child = node.children.first; child && child.next; child = child.next); + if(child) + child.EnsureVisible(false); + } + } + return true; + } + + bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods) + { + DataRow row = listBox.currentRow; + if(row) + { + FileSystemNode node = (FileSystemNode)row.tag; + if(node) + { + char * text; + + PopupMenu popup; + Menu menu { }; + + text = PrintString("Open ", node.path); + + MenuItem { menu, text, o, NotifySelect = MenuOpen, disabled = false }; + MenuItem { menu, "Cut\tCtrl+X", t, NotifySelect = null, disabled = false }; + MenuItem { menu, "Copy\tCtrl+C", c, NotifySelect = null, disabled = false }; + MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /*!clipboard*/ }; + MenuItem { menu, "Delete\tDel", d, NotifySelect = null, disabled = false }; + //MenuDivider { menu }; + + popup = PopupMenu + { + master = this, menu = menu, + position = { + x + clientStart.x + absPosition.x - guiApp.desktop.position.x, + y + clientStart.y + absPosition.y - guiApp.desktop.position.y } + }; + popup.Create(); + } + } + return true; + } + + bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods) + { + OldList rows; + OldLink item; + + selection.nodes.Free(); + list.GetMultiSelection(rows); + for(item = rows.first; item; item = item.next) + { + DataRow row = item.data; + FileSystemNode node = (FileSystemNode)row.tag; + selection.nodes.Add(node); + incref node; + } + rows.Free(null); + if(row) + selection.node = (FileSystemNode)row.tag; + else + selection.node = null; + + if(selection.node && bits.preview) + { + //int pos; + FileSystemNode node = selection.node; + /*if(bitmap) + bitmap.Free();*/ + delete bitmap; + if(node && node.type == pictureFile) + { + bitmap = Bitmap { }; + bitmap.Load(node.path, null, displaySystem); + } + + /*bitmaps.Clear(); + bitmaps = BitmapArray { }; + for(pos = 0; pos < selectedItems.count; pos++) + { + Bitmap bitmap { }; + selItem = (ExplorerFileItem)selectedItems._[pos]; + bitmap.Load(selItem.path, null, displaySystem); + //bitmaps.Add(bitmap); + } + if(node && node.type == pictureFile) + { + bitmap = Bitmap { }; + bitmap.Load(node.path, null, displaySystem); + }*/ + + show.Update(null); + //NotifyItemSelect(master, view, item, selectedItems); + } + + NotifyNodeSelect(listBox.parent.master, this, selection); + return true; + } + + bool NotifyEditing(ListBox listBox, DataRow row) + { + if(row) + { + FileSystemNode node = (FileSystemNode)row.tag; + } + return true; + } + + bool NotifyEdited(ListBox listBox, DataRow row) + { + if(row) + { + FileSystemNode node = (FileSystemNode)row.tag; + } + return true; + } + + bool NotifyEditDone(ListBox listBox, DataRow row) + { + if(row) + { + FileSystemNode node = (FileSystemNode)row.tag; + } + return true; + } + + bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods) + { + bool result = !(selection.node && selection.node.type.isFolder && bits.navigateFolders); + OpenNode(); + return result; + } + + bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch) + { + bool result; + if((SmartKey)key == enter) + result = OpenNode(); + else + result = true; + return true; + } + }; + + PaneSplitter split + { + this; + //leftPane = list; + rightPane = show; + //split = 200; + scaleSplit = 0.5f; + tabCycle = true; + visible = false; + }; + + Window show + { + this; + visible = false; + borderStyle = none; + anchor = Anchor { top = 0, right = 0, bottom = 0 }; + + void OnRedraw(Surface surface) + { + FileSystemBox fsb = (FileSystemBox)parent; + if(fsb.bitmap) + { + int wBmp = fsb.bitmap.width; + int hBmp = fsb.bitmap.height; + int wWnd = fsb.show.clientSize.w; + int hWnd = fsb.show.clientSize.h; + + int wList = 0;//fsb.list.size.w + fsb.split.size.w; + + float scale = Min((float)(wWnd - 10) / wBmp, (float)(hWnd - 10) / hBmp); + + int wDraw = (int)(wBmp * scale); + int hDraw = (int)(hBmp * scale); + + #ifndef __linux__ + surface.Filter(fsb.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw, wBmp, hBmp); + #else + // Until Filter / Stretch works with X + surface.Blit(fsb.bitmap, (wWnd - wBmp) / 2, (hWnd - hBmp) / 2, 0, 0, wBmp, hBmp); + #endif + } + else + { + surface.SetForeground(white); + surface.Area(0, 0, fsb.clientSize.w - 1, fsb.clientSize.h - 1); + } + } + } + + bool MenuOpen(MenuItem selection, Modifiers mods) + { + OpenNode(); + } + + bool OpenNode() + { + bool result; + FileSystemBoxSelection selection = this.selection.Copy(); + FileSystemNode node = selection.node; + if(node && node.type.isFolder && bits.navigateFolders) + property::path = node.path; + result = NotifyNodeOpen(this.master, this, selection); + return result; + } + + // Edit Menu + Menu editMenu { menu, "Edit", e }; + MenuItem itemEditCut + { + editMenu, "Cut\tCtrl+X", t, disabled = true; + + bool NotifySelect(MenuItem selection, Modifiers mods) + { + //EditCut(); + return true; + } + }; + MenuItem itemEditCopy + { + editMenu, "Copy\tCtrl+C", c, disabled = true; + + bool NotifySelect(MenuItem selection, Modifiers mods) + { + //EditCopy(); + return true; + } + }; + MenuItem itemEditPaste + { + editMenu, "Paste\tCtrl+V", p; + + bool NotifySelect(MenuItem selection, Modifiers mods) + { + //EditPaste(); + return true; + } + }; + MenuItem itemEditDelete + { + editMenu, "Delete\tDel", d, disabled = true; + + bool NotifySelect(MenuItem selection, Modifiers mods) + { + //EditDelete(); + return true; + } + }; + + // WHY is this crashing ? + /*void OnResize(int width, int height) + { + if(this && nameField) + nameField.width = width - 80; + }*/ + + void ChangeViewType() + { + list.Clear(); + list.ClearFields(); + list.resizable = bits.details || bits.pathColumn; + list.moveFields = bits.details || bits.pathColumn; + list.hasHeader = bits.details || bits.pathColumn; + list.AddField(nameField); + if(bits.pathColumn) + list.AddField(pathField); + if(bits.details) + { + list.AddField(typeField); + list.AddField(sizeField); + list.AddField(modifiedField); + } + } + + void Load() + { + // TODO: fix this! + // this is crashing in for designer when details = true // can't save the file, always yields a crash + /*if(list && created) + { + list.ClearFields(); + list.AddField(nameField); + if(bits.details) + { + list.AddField(typeField); + list.AddField(sizeField); + } + }*/ + if(bits.treeBranches) + LoadTree(); + else + LoadList(); + } - BitmapResource fileIcons[_FileType]; + void LoadList() + { + FileListing listing { path, extensions = extensions }; - ExplorerControl() + list.Clear(); + while(listing.Find()) + { + if((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && listing.stats.attribs.isDirectory) || + (bits.filesOnly && listing.stats.attribs.isFile)) + { + FileSystemNode node = MakeFileSystemNode(listing.stats, listing.name, listing.path, false, bits.previewPictures, displaySystem); + AddNode(node); + } + } + list.Sort(nameField, 1); + } + + void LoadTree() { - _FileType c; - for(c = 0; c < _FileType::enumSize; c++) + bool isRoot = !strcmp(path, "/"); + char name[MAX_LOCATION]; + FileSystemNode parent; + FileSystemNode node; + FileListing listing { path, extensions = extensions }; + + if(!isRoot) + GetLastDirectory(path, name); + else + name[0] = '\0'; + + /*if(!path) + GetWorkingDir(startPath, sizeof(startPath)); + else + strcpy(path, startPath);*/ + + list.Clear(); + + delete root; + #ifdef __WIN32__ + if(isRoot) { - fileIcons[c] = BitmapResource { fileIconNames[c], alphaBlend = true }; - AddResource(fileIcons[c]); + root = FileSystemNode { bits.loaded = true, bits.childrenLoaded = true }; + AddTreeNode(root, true, false, null); + while(listing.Find()) + { + int len = strlen(listing.name); + char info[MAX_LOCATION]; + char name[MAX_LOCATION]; + if(listing.stats.attribs.isDrive && + len > 3 && !strncmp(&listing.name[1], ": [", 3)) + { + strncpy(name, listing.name, 2); + name[2] = 0; + strncpy(info, &listing.name[4], len - 5); + info[len - 5] = 0; + } + else + { + strcpy(name, listing.name); + info[0] = 0; + } + + parent = MakeFileSystemNode(listing.stats, name, listing.path, false, bits.previewPictures, displaySystem); + if(info[0]) + parent.info = info; //CopyString(info); + parent.bits.loaded = true; + AddTreeNode(parent, !listing.stats.attribs.isDirectory, listing.stats.attribs.isDirectory, root); + if(!listing.stats.attribs.isDirectory) + parent.bits.childrenLoaded = true; + } + + node = FileSystemNode { name = msNetwork, type = network }; + AddTreeNode(node, false, true, null); + node.row.collapsed = true; + } + else + #endif + { + root = MakeFileSystemNode(FileStats { attribs = FileExists(path)}, name, path, false, bits.previewPictures, displaySystem); + AddTreeNode(root, false, true, null); + LoadTreeNode(root); + } + + if(isRoot) + { + root.type = computer; + root.label = rootName; + } + + list.Sort(nameField, 1); + list.SelectRow(root.row); + } + + void LoadTreeNode(FileSystemNode node) + { + if(!node.bits.loaded) + { + char path[MAX_LOCATION]; + node.GetPath(path); + { + FileListing listing { path, extensions = extensions }; + if(node.children.count == 1) + DeleteNode(node.children.first); + + while(listing.Find()) + { + if(!listing.stats.attribs.isRemovable && ((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && listing.stats.attribs.isDirectory) || + (bits.filesOnly && listing.stats.attribs.isFile))) + { + FileSystemNode child = MakeFileSystemNode(listing.stats, listing.name, listing.path, false, bits.previewPictures, displaySystem); + AddTreeNode(child, true, false, node); + NodeChildLoad(child, node); + } + } + } + node.bits.childrenLoaded = true; + node.bits.loaded = true; + node.row.SortSubRows(false); + } + else if(!node.bits.childrenLoaded) + { + FileSystemNode child; + if(node.children.first) + { + for(child = node.children.first; child; child = child.next) + { + if(!child.bits.loaded) + LoadTreeNode(child); + else if(!child.bits.childrenLoaded) + NodeChildLoad(child, node); + } + node.bits.childrenLoaded = true; + node.row.SortSubRows(false); + } + } + } + + void NodeChildLoad(FileSystemNode parent, FileSystemNode node) + { + char path[MAX_LOCATION]; + parent.GetPath(path); + { + bool added = false; + FileListing listing { path, extensions = extensions }; + while(listing.Find()) + { + if((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && listing.stats.attribs.isDirectory) || + (bits.filesOnly && listing.stats.attribs.isFile)) + { + FileSystemNode child = MakeFileSystemNode(listing.stats, listing.name, listing.path, false, bits.previewPictures, displaySystem); + AddTreeNode(child, listing.stats.attribs.isFile, !listing.stats.attribs.isFile, parent); + added = true; + } + } + if(!added) + added = true; + } + parent.bits.childrenLoaded = true; + } + + void AddNode(FileSystemNode node) + { + DataRow row = list.AddRow(); + row.tag = (int)node; + node.row = row; + incref node; + row.SetData(nameField, node); + if(bits.pathColumn) + row.SetData(pathField, node.path); + if(bits.details) + { + if(node.type.isFile) + { + row.SetData(typeField, node.extension); + row.SetData(sizeField, /*(void *)*/node.stats.size); + } + row.SetData(modifiedField, node.stats.modified); + } + } + + void AddTreeNode(FileSystemNode node, bool loaded, bool addLoader, FileSystemNode addTo) + { + DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : list.AddRow(); + if(addTo) + { + node.parent = addTo; + node.indent = addTo.indent + 1; + addTo.children.Add(node); + } + row.tag = (int)node; + node.row = row; + row.SetData(null, node); + if(bits.pathColumn) + row.SetData(pathField, node.path); + if(bits.details) + { + if(node.type.isFile) + { + row.SetData(typeField, node.extension); + row.SetData(sizeField, /*(void *)*/node.stats.size); + } + row.SetData(modifiedField, node.stats.modified); + } + + node.bits.loaded = loaded; + if(addLoader) + //AddTreeNode(FileSystemNode { }, false, false, node); // why would this create a compile error? + AddTreeNode(FileSystemNode { type = none }, false, false, node); + + if(node.indent > 0) + row.collapsed = true; + else if(node.type == folder) + node.type = folderOpen; + } + + void DeleteNode(FileSystemNode node) + { + FileSystemNode child; + if(treeBranches) + { + for(; (child = node.children.first); ) + DeleteNode(child); } + list.DeleteRow(node.row); + node.Delete(); + //delete node; + //Update(null); } } +/* #if 0 -class ExplorerView : ExplorerControl +class ExplorerView : FileSystemBox { borderStyle = none; hasHorzScroll = false; @@ -286,7 +1128,7 @@ class ExplorerViewDetails : ExplorerView public: DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this }; - DataField typeField { header = "Type", dataType = /*"String"*/ "char *", width = 40 }; + DataField typeField { header = "Type", dataType = /-*"String"*-/ "char *", width = 40 }; DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right }; ExplorerViewDetails() @@ -589,7 +1431,7 @@ public: #endif #if 0 -class ExplorerTree : ExplorerControl +class ExplorerTree : FileSystemBox { hasHorzScroll = false; hasVertScroll = false; @@ -633,7 +1475,7 @@ public: FileSystemNode node; FileSystemNode start = parent ? parent : root; if(!start.loaded || !start.childrenLoaded) - NodeLoad(start, tree); + LoadTreeNode(start, tree); for(node = start.children.first; node; node = node.next) if(node.name && !strcmpi(node.name, name)) return node; @@ -655,13 +1497,13 @@ public: anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; // WHY is this not working ? - /*void OnResize(int width, int height) + /-*void OnResize(int width, int height) { if(vertScroll.visible) nameField.width = width - vertScroll.size.w; else nameField.width = width; - }*/ + }*-/ bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed) { @@ -671,7 +1513,7 @@ public: FileSystemNode child; if(collapsed) { - /* + /-* for(child = node.children.last; child; child = node.children.last) { listBox.DeleteRow(child.row); @@ -679,12 +1521,12 @@ public: delete child; } node.childrenLoaded = false; - */ + *-/ } else { if(!node.loaded || !node.childrenLoaded) - NodeLoad(node, tree); + LoadTreeNode(node, tree); for(child = node.children.first; child && child.next; child = child.next); if(child) child.EnsureVisible(false); @@ -706,7 +1548,7 @@ public: MenuItem { menu, "Cut\tCtrl+X", t, NotifySelect = null, disabled = false }; MenuItem { menu, "Copy\tCtrl+C", c, NotifySelect = null, disabled = false }; - MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /*!clipboard*/ }; + MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /-*!clipboard*-/ }; MenuItem { menu, "Delete\tDel", d, NotifySelect = null, disabled = false }; //MenuDivider { menu }; @@ -806,11 +1648,11 @@ public: }; // WHY is this crashing ? - /*void OnResize(int width, int height) + /-*void OnResize(int width, int height) { if(this && nameField) nameField.width = width - 80; - }*/ + }*-/ ExplorerTree() { @@ -831,7 +1673,7 @@ public: #else root.name = "/"; #endif - AddNode(root, true, false, null, tree); + AddTreeNode(root, true, false, null, tree); // How can this make sense for linux? #ifdef __WIN32__ @@ -854,24 +1696,24 @@ public: info[0] = 0; } - parent = MakeFileNode(listing.stats, name); + parent = MakeFileSystemNode(listing.stats, name); if(info[0]) parent.info = CopyString(info); parent.loaded = true; - AddNode(parent, !listing.stats.attribs.isDirectory, listing.stats.attribs.isDirectory, root, tree); + AddTreeNode(parent, !listing.stats.attribs.isDirectory, listing.stats.attribs.isDirectory, root, tree); if(!listing.stats.attribs.isDirectory) parent.childrenLoaded = true; } - + #endif node = FileSystemNode { name = msNetwork, type = network }; - AddNode(node, false, true, null, tree); + AddTreeNode(node, false, true, null, tree); node.row.collapsed = true; tree.Sort(nameField, 1); tree.SelectRow(root.row); - #endif } +} -/* +#if 0 public class ClipBoardFiles { @@ -924,6 +1766,7 @@ public: } } +/-* Private Type DROPFILES pFiles As Long pt As POINTAPI @@ -948,13 +1791,10 @@ If hGlobal Then 'if the globalalloc worked SetClipboardData CF_HDROP, hGlobal 'put files to the clipboard End If - +*-/ bool SaveFile(const char * filePath) { } -*/ - -} #endif #if 0 @@ -1014,7 +1854,7 @@ public class ExplorerFileItem : struct Bitmap bitmap; - void OnDisplay(Surface surface, int x, int y, int width, ExplorerControl control, Alignment alignment, DataDisplayFlags displayFlags) + void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox control, Alignment alignment, DataDisplayFlags displayFlags) { int indentSize = (displayFlags.dropBox) ? 0 : 10; int textOffset; @@ -1151,7 +1991,7 @@ ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, ExplorerFileItem item { }; - //if(attribs.isFile) // TODO fix this in ecere + //if(stats.attribs.isFile) // -- should work now if(attribs.isDirectory) { extension[0] = 0; @@ -1211,15 +2051,91 @@ ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, return item; } #endif +*/ -public class FileSystemNode : struct +public class FileSystemBoxSelection { - FileSystemNode prev, next; +public: + FileSystemNode node; + Array nodes { }; - bool loaded, childrenLoaded; - int indent; +private: + FileSystemBoxSelection Copy() + { + FileSystemBoxSelection copy { node = node }; + for(node : nodes) + { + copy.nodes.Add(node); + incref node; + } + return copy; + } + + ~FileSystemBoxSelection() + { + nodes.Free(); + } +} + +class FileSystemNodeBits +{ + bool loaded:1, childrenLoaded:1, displayPath:1; +}; + +public class FileSystemNode +{ + +private: + FileSystemNodeBits bits; + char * path; char * name; + char * extension; + char * label; char * info; + + ~FileSystemNode() + { + Free(); + } + +public: + /*//LinkElement link; + FileSystemNode parent; + + FileSystemNodeType type; + + char * name;*/ + + FileSystemNode prev, next; + + int indent; + + property char * path + { + set { delete path; if(value && value[0]) path = CopyString(value); } + get { return path; } isset { return path && path[0]; } + } + property char * name + { + set { delete name; if(value && value[0]) name = CopyString(value); } + get { return name; } isset { return name && name[0]; } + } + property char * extension + { + set { delete extension; if(value && value[0]) extension = CopyString(value); } + get { return extension; } isset { return extension && extension[0]; } + } + property char * label + { + set { delete label; if(value && value[0]) label = CopyString(value); } + get { return label; } isset { return label && label[0]; } + } + property char * info + { + set { delete info; if(value && value[0]) info = CopyString(value); } + get { return info; } isset { return info && info[0]; } + } + DataRow row; OldList children; _FileType type; @@ -1227,12 +2143,17 @@ public class FileSystemNode : struct FileStats stats; + Bitmap bitmap; + void GetPath(String outputPath) { - FileSystemNode up; - if(parent) + if(path) + strcpy(outputPath, path); + else if(parent) { - strcpy(outputPath, name); + FileSystemNode up; + if(name) + strcpy(outputPath, name); for(up = parent; up; up = up.parent) { char temp[MAX_LOCATION]; @@ -1240,14 +2161,17 @@ public class FileSystemNode : struct PathCat(temp, outputPath); strcpy(outputPath, temp); } + /*else + { + /-*#ifdef __WIN32__ + strcpy(outputPath, "/"); + #else*-/ + //strcpy(outputPath, name); + strcpy(outputPath, path); + PathCat(outputPath, name); + //#endif + }*/ } - else -#ifdef __WIN32__ - strcpy(outputPath, "/"); -#else - strcpy(outputPath, name); -#endif - } bool IsChildOf(FileSystemNode node) @@ -1259,7 +2183,7 @@ public class FileSystemNode : struct return false; } - void DuplicateChildren(bool recursive, bool forceExpanded, FileSystemNode addTo, ListBox tree) + void DuplicateChildren(bool recursive, bool forceExpanded, FileSystemNode addTo, FileSystemBox fsb) { if(children.first) { @@ -1268,13 +2192,13 @@ public class FileSystemNode : struct for(child = children.first; child; child = child.next) { FileSystemNode copy { }; - copy.name = CopyString(child.name); + copy.name = child.name; //CopyString(child.name); copy.type = child.type; - AddNode(copy, child.loaded, false, addTo, tree); + fsb.AddTreeNode(copy, child.bits.loaded, false, addTo); if(forceExpanded) copy.row.collapsed = false; if(recursive) - child.DuplicateChildren(recursive, forceExpanded, copy, tree); + child.DuplicateChildren(recursive, forceExpanded, copy, fsb); } } } @@ -1302,7 +2226,10 @@ public class FileSystemNode : struct children.Delete(child); } //if(name) + delete path; delete name; + delete extension; + delete label; delete info; } @@ -1313,7 +2240,7 @@ public class FileSystemNode : struct parent.children.Delete(this); } - void OnDisplay(Surface surface, int x, int y, int width, ExplorerControl control, Alignment alignment, DataDisplayFlags displayFlags) + void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox fsb, Alignment alignment, DataDisplayFlags displayFlags) { //int indentSize = (displayFlags.dropBox) ? 0 : 10; int indent = 16; @@ -1321,14 +2248,14 @@ public class FileSystemNode : struct int len; int w, h; //int textOffset; - char label[MAX_FILENAME]; + char string[MAX_FILENAME]; Bitmap icon; if(!this) return; - icon = control.fileIcons[type].bitmap; + icon = fsb.fileIcons[type].bitmap; //xStart = indent * indent + x + (icon ? (icon.width + 5) : 0); xStart = x + (icon ? (icon.width + 5) : 0); @@ -1336,10 +2263,10 @@ public class FileSystemNode : struct return; if(info) - sprintf(label, "%s [%s]", name, info); + sprintf(string, "%s [%s]", label ? label : name, info); else - strcpy(label, name); - len = strlen(label); + strcpy(string, label ? label : name); + len = strlen(string); if(!icon) { @@ -1350,8 +2277,9 @@ public class FileSystemNode : struct } //textOffset = indent * indentSize + (icon ? (icon.width + 4) : 0); + surface.SetForeground(displayFlags.selected ? fsb.selectionText : fsb.foreground); surface.TextOpacity(false); - surface.TextExtent(label, len, &w, &h); + surface.TextExtent(string, len, &w, &h); h = Max(h, 16); // Draw the current row stipple @@ -1361,7 +2289,7 @@ public class FileSystemNode : struct 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); + surface.WriteTextDots(alignment, xStart, y + 2, width, string, len); if(!guiApp.textMode) { @@ -1385,6 +2313,29 @@ public class FileSystemNode : struct if(icon) { + w = icon.width; + h = icon.height; + } + if(type == pictureFile && fsb.previewPictures && bitmap) + { + surface.SetForeground(white); + surface.blend = true; + //#ifndef __linux__ + //surface.Filter(bitmap, (clientSize.w - w) / 2,(clientSize.h - h) / 2, 0,0, w, h, bitmap.width, bitmap.height); + //surface.Filter(bitmap, x + indent/* * indentSize*/ + 2, y, 0, 0, w, h, bitmap.width, bitmap.height); + surface.Filter(bitmap, x,y,0,0, w, h, bitmap.width, bitmap.height); + //#else + // Until Filter / Stretch works with X + //surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2,(clientSize.h - bitmap.height) / 2, 0,0, bitmap.width, bitmap.height); + // surface.blend = true; + //surface.Blit(bitmap, x + indent/* * indentSize*/ + 2, y,0,0, w, h); + //surface.Blit(bitmap, x,y,0,0, bitmap.width, bitmap.height); + //#endif + //bitmap.Free(); + //delete bitmap; + } + else if(icon) + { //surface.blend = true; //surface.alphaWrite = blend; surface.SetForeground(white); @@ -1397,146 +2348,151 @@ public class FileSystemNode : struct int OnCompare(FileSystemNode b) { int result; - if(type == b.type || (type < folder && b.type < folder) || (type >= drive)) - result = strcmpi(name, b.name); + FileSystemNode a = this; + if(a.type == b.type || (a.type < folder && b.type < folder) || (a.type >= drive)) + result = strcmpi(a.name, b.name); else { - if(type == folder && b.type < folder) result = -1; - else if(type < folder && b.type == folder) result = 1; + if(a.type == folder && b.type < folder) result = -1; + else if(a.type < folder && b.type == folder) result = 1; + else result = 0; } return result; } + /*int OnCompare(FileSystemNode b) + { + int result; + FileSystemNode a = this; + if(a.parent < b.parent) result = -1; + else if(a.parent > b.parent) result = 1; + else + result = fstrcmp(a.name, b.name); + return result; + }*/ + char * OnGetString(char * tempString, FileSystemToolWindow fileSysToolWnd, bool * needClass) { return name ? name : ""; } -}; +} -FileSystemNode MakeFileNode(const FileStats stats, const char * name) +/*FileSystemNode MakeFileSystemNode(const FileStats stats, const char * name) { - FileSystemNode fileTreeNode { stats = stats }; - fileTreeNode.name = CopyString(name); - if(!fileTreeNode.name) - fileTreeNode.name = null; + FileSystemNode node { stats = stats }; + node.name = CopyString(name); + if(!node.name) + node.name = null; if(stats.attribs.isDirectory) { - fileTreeNode.type = (stats.attribs.isDrive) ? drive : folder; - if(stats.attribs.isServer) fileTreeNode.type = server; - if(stats.attribs.isShare) fileTreeNode.type = share; - if(stats.attribs.isCDROM) fileTreeNode.type = cdrom; - if(stats.attribs.isRemote) fileTreeNode.type = netDrive; + node.type = (stats.attribs.isDrive) ? drive : folder; + if(stats.attribs.isServer) node.type = server; + if(stats.attribs.isShare) node.type = share; + if(stats.attribs.isCDROM) node.type = cdrom; + if(stats.attribs.isRemote) node.type = netDrive; if(stats.attribs.isRemovable) { if(name[0] == 'A' || name[0] == 'B') - fileTreeNode.type = floppy; + node.type = floppy; else - fileTreeNode.type = removable; + node.type = removable; } } else { char extension[MAX_EXTENSION]; - GetExtension(fileTreeNode.name, extension); - fileTreeNode.type = _FileType::SelectByExtension(extension); - } - return fileTreeNode; -} - -void AddNode(FileSystemNode node, bool loaded, bool addLoader, FileSystemNode addTo, ListBox tree) + GetExtension(node.name, extension); + node.type = _FileType::SelectByExtension(extension); + } + return node; +}*/ + +FileSystemNode MakeFileSystemNode( + const FileStats stats, + const char * name, + const char * path, + const bool pathAddName, + const bool previewPicture, + const DisplaySystem displaySystem) { - DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : tree.AddRow(); - if(addTo) - { - node.parent = addTo; - node.indent = addTo.indent + 1; - addTo.children.Add(node); - } - row.tag = (int)node; - node.row = row; - row.SetData(null, node); - - node.loaded = loaded; - if(addLoader) - //AddNode(FileSystemNode { }, false, false, node, tree); // why would this create a compile error? - AddNode(FileSystemNode { type = none }, false, false, node, tree); - - if(node.indent > 0) - row.collapsed = true; - else if(node.type == folder) - node.type = folderOpen; -} + int len = strlen(name); + char info[MAX_LOCATION]; + char name2[MAX_LOCATION]; + char extension[MAX_EXTENSION]; + + FileSystemNode node { stats = stats }; -void NodeLoad(FileSystemNode node, ListBox tree) -{ - if(!node.loaded) + /*if(!pathAddName) { - char path[MAX_LOCATION]; - node.GetPath(path); - { - FileListing listing { path }; - if(node.children.count == 1) - DeleteNode(node.children.first, tree); + char o[MAX_LOCATION]; + //char r[MAX_LOCATION]; + //StripLastDirectory(path, o); + GetLastDirectory(path, o); + if(fstrcmp(name, o)) + //if(!FileExists(path)) + PrintLn("Stop!"); + }*/ + //if(stats.attribs.isFile) // TODO fix this in ecere -- WTH -- this has been fixed :/ + if(stats.attribs.isDirectory) + { + extension[0] = '\0'; - while(listing.Find()) - { - if(listing.stats.attribs.isDirectory) - { - FileSystemNode child = MakeFileNode(listing.stats, listing.name); - AddNode(child, true, false, node, tree); - NodeChildLoad(child, node, tree); - } - } + node.type = (stats.attribs.isDrive) ? drive : folder; + if(stats.attribs.isServer) node.type = server; + if(stats.attribs.isShare) node.type = share; + if(stats.attribs.isCDROM) node.type = cdrom; + if(stats.attribs.isRemote) node.type = netDrive; + if(stats.attribs.isRemovable) + { + if(name[0] == 'A' || name[0] == 'B') + node.type = floppy; + else + node.type = removable; } - node.childrenLoaded = true; - node.loaded = true; - node.row.SortSubRows(false); } - else if(!node.childrenLoaded) + else { - FileSystemNode child; - if(node.children.first) - { - for(child = node.children.first; child; child = child.next) - { - if(!child.loaded) - NodeLoad(child, tree); - else if(!child.childrenLoaded) - NodeChildLoad(child, node, tree); - } - node.childrenLoaded = true; - node.row.SortSubRows(false); - } + GetExtension(name, extension); + strlwr(extension); + + node.type = _FileType::SelectByExtension(extension); } -} -static void NodeChildLoad(FileSystemNode parent, FileSystemNode node, ListBox tree) -{ - char path[MAX_LOCATION]; - parent.GetPath(path); + if(stats.attribs.isDrive && + len > 3 && !strncmp(&name[1], ": [", 3)) { - bool added = false; - FileListing listing { path }; - while(listing.Find()) - { - if(listing.stats.attribs.isDirectory) - { - FileSystemNode child = MakeFileNode(listing.stats, listing.name); - AddNode(child, true, false, parent, tree); - added = true; - } - } - if(!added) - added = true; + strncpy(name2, name, 2); + name2[2] = 0; + strncpy(info, &name[4], len - 5); + info[len - 5] = 0; + } + else + { + strcpy(name2, name); + info[0] = 0; } - //parent.childrenLoaded = true; -} -void DeleteNode(FileSystemNode node, ListBox tree) -{ - FileSystemNode child; - for(; (child = node.children.first); ) - DeleteNode(child, tree); - tree.DeleteRow(node.row); - node.Delete(); + if(pathAddName) + { + bool isFile = stats.attribs.isFile; + bool isFolder = stats.attribs.isDirectory; + char full[MAX_LOCATION]; + strcpy(full, path); + PathCat(full, name); + node.path = full; //CopyString(full); + } + else + node.path = path; //CopyString(path); + node.name = name2; //CopyString(name2); + if(info[0]) + node.info = info; //CopyString(info); + node.extension = extension; //CopyString(extension); + + if(node.type == pictureFile && previewPicture) + { + node.bitmap = Bitmap { alphaBlend = true }; + node.bitmap.Load(path, null, displaySystem); + } + + return node; }