X-Git-Url: http://ecere.com/cgi-bin/gitweb.cgi?p=ede;a=blobdiff_plain;f=libede%2Fsrc%2FFileSystemBox.ec;h=e184693e9848f0e13e5790a52f5ea0a2035ab1ce;hp=9527e2878d54a689c250b1c4eadfa40d9a9e5487;hb=47c68b7269adbb7d1b22fefb8b4cecbd3afb1c0c;hpb=c3c07aa52ae2c7d74ac9ffcbff9060dfae6404aa diff --git a/libede/src/FileSystemBox.ec b/libede/src/FileSystemBox.ec index 9527e28..e184693 100644 --- a/libede/src/FileSystemBox.ec +++ b/libede/src/FileSystemBox.ec @@ -1,5 +1,16 @@ public import "ecere" +#ifdef __WIN32__ +static char * rootName = "Entire Computer"; +static char * msNetwork = "Microsoft Windows Network"; +#else +static char * rootName = "File System"; +#endif + +private: +define guiApp = (GuiApplication)((__thisModule).application); +define selectionColor = guiApp.currentSkin.selectionColor; //Color { 10, 36, 106 }; + static char * fileIconNames[] = { "<:ecere>mimeTypes/file.png", /* none */ @@ -39,10 +50,7 @@ static char * fileIconNames[] = "" }; -//define guiApp = ((GuiApplication)__thisModule); -//define selectionColor = guiApp.currentSkin.selectionColor; //Color { 10, 36, 106 }; - -public enum __FileType +public enum _FileType { none, @@ -75,7 +83,7 @@ public enum __FileType get { return this >= normalFile && this <= opticalMediaImageFile; } } - __FileType ::SelectByExtension(char * extension) + _FileType ::SelectByExtension(char * extension) { if(!strcmpi(extension, "ews")) return ewsFile; @@ -129,1001 +137,2039 @@ public enum __FileType } }; -//public enum FileSystemNodeType { file, folder, system }; - -define guiApp = ((GuiApplication)__thisModule); // how to do this in a dll? -define selectionColor = guiApp.currentSkin.selectionColor; //Color { 10, 36, 106 }; +class FileSystemBoxBits +{ + bool foldersOnly:1, filesOnly:1, details:1, treeBranches:1, previewPictures:1, navigateFolders:1, autoLoad: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 FileSystemNode : struct // : struct +public class FileSystemBox : Window // should we not derive from ListBox instead? +/* + this stuff from the listbox would be nicely exposed... + fullRowSelect = false; + treeBranches = true; + collapseControl = true; + rootCollapseButton = true; + sortable = true; +*/ { -public: - /*//LinkElement link; - FileSystemNode parent; + borderStyle = deep; + hasHorzScroll = false; + hasVertScroll = false; - FileSystemNodeType type; + menu = Menu { }; - char * name;*/ +public: + FileSystemNode root; + FileSystemNode selection; - FileSystemNode prev, next; + virtual bool Window::NotifyNodeSelect(FileSystemBox box, FileSystemNode node); + virtual bool Window::NotifyNodeOpen(FileSystemBox box, FileSystemNode node); + + property char * path + { + set + { + delete path; + if(value && value[0]) + path = CopyString(value); + if(locationBox) + locationBox.path = value; + if(created) + Load(); + } - bool loaded, childrenLoaded; - int indent; - char * path; - char * name; - char * extension; - char * info; - DataRow row; - OldList children; - __FileType type; - FileSystemNode parent; + get { return path; } + //isset { return path && path[0]; } + } - FileStats stats; + 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; } get { return bits.details; } }; + property bool treeBranches + { + set + { + bits.treeBranches = value; + list.treeBranches = value; + list.collapseControl = value; + list.rootCollapseButton = value; + } + get { return bits.treeBranches; } + }; + 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 FileSystemNode node + { + get + { + if(!list) + return null; + if(!list.currentRow) + return null; + if(!list.currentRow.tag) + return null; + return (FileSystemNode)list.currentRow.tag; + } + } - Bitmap bitmap; + PathBox locationBox; - void GetPath(String outputPath) - { - FileSystemNode up; - if(parent) + void Select(FileSystemNode node) + { + if(node.row) { - strcpy(outputPath, name); - for(up = parent; up; up = up.parent) - { - char temp[MAX_LOCATION]; - strcpy(temp, up.name); - PathCat(temp, outputPath); - strcpy(outputPath, temp); - } + node.EnsureVisible(false); + list.SelectRow(node.row); } - else -#ifdef __WIN32__ - strcpy(outputPath, "/"); -#else - strcpy(outputPath, name); -#endif - } - bool IsChildOf(FileSystemNode node) + FileSystemNode SelectLocation(char * location) { - FileSystemNode test; - for(test = parent; test; test = test.parent) - if(test == node) - return true; - return false; + 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; } - void DuplicateChildren(bool recursive, bool forceExpanded, FileSystemNode addTo, FileSystemBox fsb) + FileSystemNode Find(const char * name, FileSystemNode parent) { - if(children.first) + FileSystemNode node = null; + FileSystemNode result = null; + if(!parent/* && !strcmp(name, "/")*/) { - FileSystemNode child; - - for(child = children.first; child; child = child.next) + DataRow row; + for(row = list.firstRow; row; row = row.next) { - FileSystemNode copy { }; - copy.name = CopyString(child.name); - copy.type = child.type; - fsb.AddTreeNode(copy, child.loaded, false, addTo); - if(forceExpanded) - copy.row.collapsed = false; - if(recursive) - child.DuplicateChildren(recursive, forceExpanded, copy, fsb); + 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.loaded || !start.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 EnsureVisible(bool expand) + + void Refresh() { - if(parent) - parent.EnsureVisible(true); - if(expand) - row.collapsed = false; - // TODO: row.EnsureVisible(); // making the row visible by scrolling + Load(); } - void OnFree() +private: + FileSystemBoxBits bits; + + char * path; + char * extensions; + + BitmapResource fileIcons[_FileType]; + + FileSystemBox() { - //delete name; + char wd[MAX_LOCATION]; + GetWorkingDir(wd, sizeof(wd)); + property::path = wd; + + InitFileIcons(); + list.AddField(nameField); + bits.autoLoad = true; } - - void Free() + ~FileSystemBox() { - FileSystemNode child; - for(; (child = children.first); ) + delete extensions; + delete path; + } + void InitFileIcons() + { + _FileType c; + for(c = 0; c < _FileType::enumSize; c++) { - child.Free(); - children.Delete(child); + fileIcons[c] = BitmapResource { fileIconNames[c], alphaBlend = true }; + AddResource(fileIcons[c]); } - //if(name) - delete name; - delete info; } - void Delete() + DataField nameField { dataType = "FileSystemNode", width = 240, userData = this, 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 }; + + bool OnPostCreate() { - Free(); - if(parent) - parent.children.Delete(this); + if(bits.autoLoad) + Load(); + return true; } - void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox fsb, Alignment alignment, DataDisplayFlags displayFlags) + ListBox list { - //int indentSize = (displayFlags.dropBox) ? 0 : 10; - int indent = 16; - int xStart; - int len; - int w, h; - //int textOffset; - char label[MAX_FILENAME]; + this; - Bitmap icon; + borderStyle = none; + hasHorzScroll = true; + hasVertScroll = true; + fullRowSelect = false; + sortable = true; - if(!this) - return; - - icon = fsb.fileIcons[type].bitmap; - /*if(type == normalFile) - PrintLn("dd");*/ - //xStart = indent * indent + x + (icon ? (icon.width + 5) : 0); - xStart = x + (icon ? (icon.width + 5) : 0); + anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; - if(!name) - return; + // WHY is this not working ? + /*void OnResize(int width, int height) + { + if(vertScroll.visible) + nameField.width = width - vertScroll.size.w; + else + nameField.width = width; + }*/ - if(info) - sprintf(label, "%s [%s]", name, info); - else - strcpy(label, name); - len = strlen(label); - - if(!icon) + bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed) { - 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) -- how to do this in a dll? - { - if(displayFlags.current) + if(row) { - if(displayFlags.active) + FileSystemNode node = (FileSystemNode)row.tag; + FileSystemNode child; + if(collapsed) { - surface.LineStipple(0x5555); - if(displayFlags.selected) - surface.SetForeground(0xFFFFFF80); - else - surface.SetForeground(black); + /* + for(child = node.children.last; child; child = node.children.last) + { + listBox.DeleteRow(child.row); + child.Free(); + delete child; + } + node.childrenLoaded = false; + */ } else { - surface.SetForeground(selectionColor); + if(!node.loaded || !node.childrenLoaded) + { + LoadTreeNode(node); + //list.Sort(nameField, 1); + //node. + } + for(child = node.children.first; child && child.next; child = child.next); + if(child) + child.EnsureVisible(false); } - surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1); - surface.LineStipple(0); } - - if(icon) + return true; + } + + bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods) + { + DataRow row = listBox.currentRow; + if(row) { - w = icon.width; - h = icon.height; + FileSystemNode node = (FileSystemNode)row.tag; + if(node) + { + PopupMenu popup; + Menu menu { }; + + 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(); + } } - if(type == pictureFile && fsb.previewPictures && bitmap) + return true; + } + + bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods) + { + if(row) { - 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; + FileSystemNode node = (FileSystemNode)row.tag; + NotifyNodeSelect(listBox.parent.master, this, node); + selection = node; } - else if(icon) + return true; + } + + bool NotifyEditing(ListBox listBox, DataRow row) + { + if(row) { - //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); + FileSystemNode node = (FileSystemNode)row.tag; } + return true; } - } - int OnCompare(FileSystemNode b) - { - int result; - FileSystemNode a = this; - if(a.type == b.type || (a.type < folder && b.type < folder) || (a.type >= drive)) - result = strcmpi(a.name, b.name); - else + bool NotifyEdited(ListBox listBox, DataRow row) { - if(a.type == folder && b.type < folder) result = -1; - else if(a.type < folder && b.type == folder) result = 1; - else result = 0; + if(row) + { + FileSystemNode node = (FileSystemNode)row.tag; + } + return true; } - 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; - }*/ + bool NotifyEditDone(ListBox listBox, DataRow row) + { + if(row) + { + FileSystemNode node = (FileSystemNode)row.tag; + } + return true; + } - char * OnGetString(char * tempString, FileSystemToolWindow fileSysToolWnd, bool * needClass) - { - return name ? name : ""; - } -} + bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods) + { + bool result = !(selection && selection.type.isFolder && bits.navigateFolders); + OpenNode(); + return result; + } -/*FileSystemNode MakeFileSystemNode(const FileStats stats, const char * name) -{ - FileSystemNode node { stats = stats }; - node.name = CopyString(name); - if(!node.name) - node.name = null; - if(stats.attribs.isDirectory) - { - 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) + bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch) { - if(name[0] == 'A' || name[0] == 'B') - node.type = floppy; + bool result; + if((SmartKey)key == enter) + result = OpenNode(); else - node.type = removable; + result = true; + return true; } - } - else + }; + + bool OpenNode() { - char extension[MAX_EXTENSION]; - GetExtension(node.name, extension); - node.type = __FileType::SelectByExtension(extension); + bool result; + if(selection && selection.type.isFolder && bits.navigateFolders) + property::path = selection.path; + result = NotifyNodeOpen(this.master, this, selection); + return result; } - return node; -}*/ -static FileSystemNode MakeFileSystemNode(const FileStats stats, - const char * fileName, const char * filePath, - const bool previewPicture, const DisplaySystem displaySystem) -{ - int len = strlen(fileName); - char info[MAX_LOCATION]; - char name[MAX_LOCATION]; - char extension[MAX_EXTENSION]; - - FileSystemNode node { stats = stats }; - //if(stats.attribs.isFile) // -- should work now - if(stats.attribs.isDirectory) + // Edit Menu + Menu editMenu { menu, "Edit", e }; + MenuItem itemEditCut { - extension[0] = '\0'; + editMenu, "Cut\tCtrl+X", t, disabled = true; - 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) + bool NotifySelect(MenuItem selection, Modifiers mods) { - if(fileName[0] == 'A' || fileName[0] == 'B') - node.type = floppy; - else - node.type = removable; + //EditCut(); + return true; } - } - else + }; + MenuItem itemEditCopy { - GetExtension(fileName, extension); - strlwr(extension); - - node.type = __FileType::SelectByExtension(extension); - } + editMenu, "Copy\tCtrl+C", c, disabled = true; - if(stats.attribs.isDrive && - len > 3 && !strncmp(&fileName[1], ": [", 3)) - { - strncpy(name, fileName, 2); - name[2] = 0; - strncpy(info, &fileName[4], len - 5); - info[len - 5] = 0; - } - else + bool NotifySelect(MenuItem selection, Modifiers mods) + { + //EditCopy(); + return true; + } + }; + MenuItem itemEditPaste { - strcpy(name, fileName); - info[0] = 0; - } - - node.path = CopyString(filePath); - node.name = CopyString(name); - if(info[0]) - node.info = CopyString(info); - node.extension = CopyString(extension); - - if(node.type == pictureFile && previewPicture) - { - node.bitmap = Bitmap { alphaBlend = true }; - node.bitmap.Load(filePath, null, displaySystem); - } - - return node; -} - -class FileSystemBoxBits -{ - bool foldersOnly:1, filesOnly:1, details:1, treeBranches:1, previewPictures:1, navigateFolders: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? -/* - 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; - FileSystemNode selection; - - virtual bool Window::NotifyNodeSelect(FileSystemBox box, FileSystemNode node); - virtual bool Window::NotifyNodeOpen(FileSystemBox box, FileSystemNode node); + editMenu, "Paste\tCtrl+V", p; - property char * path - { - set + bool NotifySelect(MenuItem selection, Modifiers mods) { - delete path; - if(value && value[0]) - path = CopyString(value); - if(locationBox) - locationBox.path = value; - if(created) - Load(); + //EditPaste(); + return true; } - - 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; } get { return bits.details; } }; - property bool treeBranches + }; + MenuItem itemEditDelete { - set + editMenu, "Delete\tDel", d, disabled = true; + + bool NotifySelect(MenuItem selection, Modifiers mods) { - bits.treeBranches = value; - list.treeBranches = value; - list.collapseControl = value; - list.rootCollapseButton = value; + //EditDelete(); + return true; } - get { return bits.treeBranches; } }; - property bool navigateFolders { set { bits.navigateFolders = value; bits.foldersOnly = !value; } get { return bits.navigateFolders; } }; - - property FileSystemNode node + + // WHY is this crashing ? + /*void OnResize(int width, int height) { - get + if(this && nameField) + nameField.width = width - 80; + }*/ + + 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) { - if(!list) - return null; - if(!list.currentRow) - return null; - if(!list.currentRow.tag) - return null; - return (FileSystemNode)list.currentRow.tag; - } + list.ClearFields(); + list.AddField(nameField); + if(bits.details) + { + list.AddField(typeField); + list.AddField(sizeField); + } + }*/ + if(bits.treeBranches) + LoadTree(); + else + LoadList(); } - PathBox locationBox; - - void Select(FileSystemNode node) + void LoadList() { - if(node.row) + FileListing listing { path, extensions = extensions }; + + list.Clear(); + while(listing.Find()) { - node.EnsureVisible(false); - list.SelectRow(node.row); + 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, bits.previewPictures, displaySystem); + DataRow row = list.AddRow(); + row.tag = (int)node; + row.SetData(nameField, node); + if(bits.details) + { + row.SetData(typeField, node.extension); + row.SetData(sizeField, (void *)node.stats.size); + } + } } + list.Sort(nameField, 1); } - FileSystemNode Find(const char * name, FileSystemNode parent) + void LoadTree() { + bool isRoot = !strcmp(path, "/"); + //char startPath[MAX_LOCATION]; + FileSystemNode parent; FileSystemNode node; - FileSystemNode start = parent ? parent : root; - if(!start.loaded || !start.childrenLoaded) - LoadTreeNode(start); - for(node = start.children.first; node; node = node.next) - if(node.name && !strcmpi(node.name, name)) - return node; - return null; - } - - void Refresh() - { - Load(); - } - -private: - FileSystemBoxBits bits; + FileListing listing { path, extensions = extensions }; + + /*if(!path) + GetWorkingDir(startPath, sizeof(startPath)); + else + strcpy(path, startPath);*/ + + list.Clear(); - char * path; - char * extensions; + delete root; + #ifdef __WIN32__ + if(isRoot) + { + root = FileSystemNode { loaded = true, 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; + } - BitmapResource fileIcons[__FileType]; + parent = MakeFileSystemNode(listing.stats, name, listing.path, bits.previewPictures, displaySystem); + if(info[0]) + parent.info = CopyString(info); + parent.loaded = true; + AddTreeNode(parent, !listing.stats.attribs.isDirectory, listing.stats.attribs.isDirectory, root); + if(!listing.stats.attribs.isDirectory) + parent.childrenLoaded = true; + } - FileSystemBox() - { - char wd[MAX_LOCATION]; - GetWorkingDir(wd, sizeof(wd)); - property::path = wd; - - InitFileIcons(); - list.AddField(nameField); - } - ~FileSystemBox() - { - delete extensions; - delete path; - } - void InitFileIcons() - { - __FileType c; - for(c = 0; c < __FileType::enumSize; c++) + node = FileSystemNode { name = msNetwork, type = network }; + AddTreeNode(node, false, true, null); + node.row.collapsed = true; + } + else + #endif { - fileIcons[c] = BitmapResource { fileIconNames[c], alphaBlend = true }; - AddResource(fileIcons[c]); + root = MakeFileSystemNode(FileStats { attribs = FileExists(path)}, path, path, bits.previewPictures, displaySystem); + AddTreeNode(root, false, true, null); + LoadTreeNode(root); } - } - DataField nameField { dataType = "FileSystemNode", width = 240, userData = this, 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 }; + if(isRoot) + { + root.type = computer; + root.label = rootName; + } - bool OnPostCreate() - { - Load(); - return true; + list.Sort(nameField, 1); + list.SelectRow(root.row); } - ListBox list + void LoadTreeNode(FileSystemNode node) { - this; - - borderStyle = none; - hasHorzScroll = true; - hasVertScroll = true; - fullRowSelect = false; - sortable = 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(!node.loaded) { - if(row) + char path[MAX_LOCATION]; + node.GetPath(path); { - FileSystemNode node = (FileSystemNode)row.tag; - FileSystemNode child; - if(collapsed) + FileListing listing { path, extensions = extensions }; + if(node.children.count == 1) + DeleteNode(node.children.first); + + while(listing.Find()) { - /* - for(child = node.children.last; child; child = node.children.last) + if(!listing.stats.attribs.isRemovable && ((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && listing.stats.attribs.isDirectory) || + (bits.filesOnly && listing.stats.attribs.isFile))) { - listBox.DeleteRow(child.row); - child.Free(); - delete child; - } - node.childrenLoaded = false; - */ - } - else - { - if(!node.loaded || !node.childrenLoaded) - { - LoadTreeNode(node); - //list.Sort(nameField, 1); - //node. + FileSystemNode child = MakeFileSystemNode(listing.stats, listing.name, listing.path, bits.previewPictures, displaySystem); + AddTreeNode(child, true, false, node); + NodeChildLoad(child, node); } - for(child = node.children.first; child && child.next; child = child.next); - if(child) - child.EnsureVisible(false); } } - return true; + node.childrenLoaded = true; + node.loaded = true; + node.row.SortSubRows(false); } - - bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods) + else if(!node.childrenLoaded) { - DataRow row = listBox.currentRow; - if(row) + FileSystemNode child; + if(node.children.first) { - FileSystemNode node = (FileSystemNode)row.tag; - if(node) + for(child = node.children.first; child; child = child.next) { - PopupMenu popup; - Menu menu { }; - - 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(); + if(!child.loaded) + LoadTreeNode(child); + else if(!child.childrenLoaded) + NodeChildLoad(child, node); } + node.childrenLoaded = true; + node.row.SortSubRows(false); } - return true; } + } - bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods) + void NodeChildLoad(FileSystemNode parent, FileSystemNode node) + { + char path[MAX_LOCATION]; + parent.GetPath(path); { - if(row) + bool added = false; + FileListing listing { path, extensions = extensions }; + while(listing.Find()) { - FileSystemNode node = (FileSystemNode)row.tag; - NotifyNodeSelect(listBox.parent.master, this, node); - selection = node; + 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, bits.previewPictures, displaySystem); + AddTreeNode(child, listing.stats.attribs.isFile, !listing.stats.attribs.isFile, parent); + added = true; + } } - return true; + if(!added) + added = true; } + parent.childrenLoaded = true; + } - bool NotifyEditing(ListBox listBox, DataRow row) + void AddTreeNode(FileSystemNode node, bool loaded, bool addLoader, FileSystemNode addTo) + { + DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : list.AddRow(); + if(addTo) { - if(row) - { - FileSystemNode node = (FileSystemNode)row.tag; - } - return true; + node.parent = addTo; + node.indent = addTo.indent + 1; + addTo.children.Add(node); } + row.tag = (int)node; + node.row = row; + row.SetData(null, node); - bool NotifyEdited(ListBox listBox, DataRow row) - { - if(row) - { - FileSystemNode node = (FileSystemNode)row.tag; - } - return true; - } + node.loaded = loaded; + if(addLoader) + //AddTreeNode(FileSystemNode { }, false, false, node); // why would this create a compile error? + AddTreeNode(FileSystemNode { type = none }, false, false, node); - bool NotifyEditDone(ListBox listBox, DataRow row) + if(node.indent > 0) + row.collapsed = true; + else if(node.type == folder) + node.type = folderOpen; + } + + void DeleteNode(FileSystemNode node) + { + FileSystemNode child; + for(; (child = node.children.first); ) + DeleteNode(child); + list.DeleteRow(node.row); + node.Delete(); + } +} + +/* +#if 0 +class ExplorerView : FileSystemBox +{ + borderStyle = none; + hasHorzScroll = false; + hasVertScroll = false; + + virtual void Load(FileSystemNode parent); + virtual void Refresh(); + + virtual void LaunchNotifyItemSelect(Window master, ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems) + { + view.NotifyItemSelect(master, view, item, selectedItems); + } + + virtual bool Window::NotifyItemSelect(ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems); + virtual bool Window::NotifyItemOpen(ExplorerView view, ExplorerFileItem item); + + ListBox list + { + master = master, parent = this; + //this, master; + borderStyle = none; + hasHorzScroll = true; + hasVertScroll = true; + resizable = true; + sortable = true; + fullRowSelect = false; + multiSelect = true; + + anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; + + bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods) { - if(row) + ExplorerView view = (ExplorerView)listBox.parent; + if(listBox.currentRow) { - FileSystemNode node = (FileSystemNode)row.tag; + DataRow listRow; + ExplorerFileItemArray selectedItems { growingFactor = 16 }; + for(listRow = listBox.firstRow; listRow; listRow = listRow.next) + if(listRow.selected) + selectedItems.Add((ExplorerFileItem)listRow.tag); + //view.NotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag); + view.LaunchNotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag, selectedItems); } return true; } bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods) { - return OpenNode(); + ExplorerView view = (ExplorerView)listBox.parent; + view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag); + return false; } bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch) { - bool result; if((SmartKey)key == enter) - result = OpenNode(); - else - result = true; + { + ExplorerView view = (ExplorerView)listBox.parent; + view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag); + } return true; } }; - bool OpenNode() + ExplorerView() { - bool result; - if(selection && selection.type.isFolder && bits.navigateFolders) - { - property::path = selection.path; - result = true; - } - else - result = NotifyNodeOpen(this.master, this, selection); - return result; } +} +#endif - // Edit Menu - Menu editMenu { menu, "Edit", e }; - MenuItem itemEditCut +#if 0 +class ExplorerViewList : ExplorerView +{ + + FileSystemNode location; + +public: + + DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this }; + + ExplorerViewDetails() { - editMenu, "Cut\tCtrl+X", t, disabled = true; + list.AddField(nameField); + } - bool NotifySelect(MenuItem selection, Modifiers mods) - { - //EditCut(); - return true; - } - }; - MenuItem itemEditCopy + void Refresh() { - editMenu, "Copy\tCtrl+C", c, disabled = true; + Load(location); + } - bool NotifySelect(MenuItem selection, Modifiers mods) - { - //EditCopy(); - return true; - } - }; - MenuItem itemEditPaste + void Load(FileSystemNode location) { - editMenu, "Paste\tCtrl+V", p; - - bool NotifySelect(MenuItem selection, Modifiers mods) + char path[MAX_LOCATION]; + this.location = location; + location.GetPath(path); { - //EditPaste(); - return true; - } - }; - MenuItem itemEditDelete - { - editMenu, "Delete\tDel", d, disabled = true; + FileListing listing { path }; + + ExplorerFileItem item; + DataRow row; - bool NotifySelect(MenuItem selection, Modifiers mods) - { - //EditDelete(); - return true; + list.Clear(); + + while(listing.Find()) + { + item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); + + row = list.AddRow(); + row.tag = (int)item; + row.SetData(nameField, item); + } + list.Sort(nameField, 1); } - }; + } +} +#endif - // WHY is this crashing ? - /*void OnResize(int width, int height) +#if 0 +class ExplorerViewDetails : ExplorerView +{ + list.hasHeader = true; + list.moveFields = true; + list.resizable = true; + list.sortable = true; + + FileSystemNode location; + +public: + + DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this }; + DataField typeField { header = "Type", dataType = /-*"String"*-/ "char *", width = 40 }; + DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right }; + + ExplorerViewDetails() { - if(this && nameField) - nameField.width = width - 80; - }*/ + list.AddField(nameField); + list.AddField(typeField); + list.AddField(sizeField); + } - void Load() + void Refresh() { - // 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(); + Load(location); } - void LoadList() + void Load(FileSystemNode location) { - FileListing listing { path, extensions = extensions }; + char path[MAX_LOCATION]; + this.location = location; + location.GetPath(path); + { + FileListing listing { path }; + + ExplorerFileItem item; + DataRow row; - list.Clear(); - while(listing.Find()) + list.Clear(); + + while(listing.Find()) + { + item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); + + row = list.AddRow(); + row.tag = (int)item; + row.SetData(nameField, item); + row.SetData(typeField, CopyString(item.extension)); + row.SetData(sizeField, (uint)listing.stats.size); + } + list.Sort(nameField, 1); + } + } +} +#endif + +#if 0 +class ExplorerViewIcons : ExplorerView +{ + + FileSystemNode location; + +public: + + DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this }; + + ExplorerViewDetails() + { + list.AddField(nameField); + } + + void Refresh() + { + Load(location); + } + + void Load(FileSystemNode location) + { + char path[MAX_LOCATION]; + this.location = location; + location.GetPath(path); { - if((!bits.foldersOnly && !bits.filesOnly) || - (bits.foldersOnly && listing.stats.attribs.isDirectory) || - (bits.filesOnly && listing.stats.attribs.isFile)) + FileListing listing { path }; + + ExplorerFileItem item; + DataRow row; + + list.Clear(); + + while(listing.Find()) { - FileSystemNode node = MakeFileSystemNode(listing.stats, listing.name, listing.path, bits.previewPictures, displaySystem); - DataRow row = list.AddRow(); - row.tag = (int)node; - row.SetData(nameField, node); - if(bits.details) - { - row.SetData(typeField, node.extension); - row.SetData(sizeField, (void *)node.stats.size); - } + item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); + + row = list.AddRow(); + row.tag = (int)item; + row.SetData(nameField, item); } + list.Sort(nameField, 1); } - list.Sort(nameField, 1); } +} +#endif - void LoadTree() +#if 0 +class ExplorerViewCards : ExplorerView +{ + + FileSystemNode location; + +public: + + DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this }; + + ExplorerViewDetails() { - //char startPath[MAX_LOCATION]; - FileSystemNode parent; - FileSystemNode node; - FileListing listing { path, extensions = extensions }; - - /*if(!path) - GetWorkingDir(startPath, sizeof(startPath)); - else - strcpy(path, startPath);*/ - - list.Clear(); + list.AddField(nameField); + } - delete root; - //root = FileSystemNode { type = computer, loaded = true, childrenLoaded = true }; - root = MakeFileSystemNode(FileStats { attribs = FileExists(path)}, path, path, bits.previewPictures, displaySystem); - #ifdef __WIN32__ - //root.name = rootName; - AddTreeNode(root, true, false, null);//, list); - #else - //root.name = "/"; - #endif - AddTreeNode(root, false, true, null); + void Refresh() + { + Load(location); + } - // How can this make sense for linux? - /*#ifdef __WIN32__ - while(listing.Find()) + void Load(FileSystemNode location) + { + char path[MAX_LOCATION]; + this.location = location; + location.GetPath(path); { - 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)) + FileListing listing { path }; + + ExplorerFileItem item; + DataRow row; + + list.Clear(); + + while(listing.Find()) { - strncpy(name, listing.name, 2); - name[2] = 0; - strncpy(info, &listing.name[4], len - 5); - info[len - 5] = 0; + item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); + + row = list.AddRow(); + row.tag = (int)item; + row.SetData(nameField, item); + } + list.Sort(nameField, 1); + } + } +} +#endif + +#if 0 +public class BitmapArray : RedjArray +{ + type = class(Bitmap); +public: + Bitmap * const _; + Bitmap * Add(Bitmap bitmap) + { + uint pos = _count; + Append(1); + _[pos] = bitmap; + return &_[pos]; + } + Bitmap * AddBefore(uint position, Bitmap bitmap) + { + Insert(position, 1); + _[position] = bitmap; + return &_[position]; + } + void Clear() + { + int c; + for(c = 0; c < _count; c++) + { + _[c].Free(); + delete _[c]; + } + count = 0; + size = 0; + } +} +#endif + +#if 0 +class ExplorerViewShowcase : ExplorerView +{ + list.anchor = Anchor { left = 0, top = 0, bottom = 0 }; + list.size = Size { w = 200 }; + + FileSystemNode location; + +public: + + DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 180, editable = true, userData = this }; + + Bitmap bitmap; + BitmapArray bitmaps { growingFactor = 16 }; + + Window show + { + this; + borderStyle = none; + anchor = Anchor { top = 0, right = 0, bottom = 0 }; + + void OnRedraw(Surface surface) + { + ExplorerViewShowcase view = (ExplorerViewShowcase)parent; + if(view.bitmap) + { + int wBmp = view.bitmap.width; + int hBmp = view.bitmap.height; + int wWnd = clientSize.w; + int hWnd = clientSize.h; + + int wList = view.list.size.w + view.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(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw, wBmp, hBmp); + #else + // Until Filter / Stretch works with X + surface.Blit(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw); + #endif } else { - strcpy(name, listing.name); - info[0] = 0; + surface.SetForeground(white); + surface.Area(0, 0, view.clientSize.w - 1, view.clientSize.h - 1); } + } + } - parent = MakeFileSystemNode(listing.stats, name); - if(info[0]) - parent.info = CopyString(info); - parent.loaded = true; - AddTreeNode(parent, !listing.stats.attribs.isDirectory, listing.stats.attribs.isDirectory, root, this); - if(!listing.stats.attribs.isDirectory) - parent.childrenLoaded = true; + SplitWindow split + { + this; + leftPane = list; + rightPane = show; + split = 200; + tabCycle = true; + }; + + ExplorerViewDetails() + { + list.AddField(nameField); + } + + void LaunchNotifyItemSelect(Window master, ExplorerViewShowcase view, ExplorerFileItem item, ExplorerFileItemArray selectedItems) + { + int pos; + ExplorerFileItem selItem; + if(view.bitmap) + view.bitmap.Free(); + delete view.bitmap; + if(item && item.type == pictureFile) + { + view.bitmap = Bitmap { }; + view.bitmap.Load(item.path, null, displaySystem); } - node = FileSystemNode { name = msNetwork, type = network }; - AddTreeNode(node, false, true, null, this); - node.row.collapsed = true; - Sort(nameField, 1); - SelectRow(root.row); - #endif*/ - LoadTreeNode(root); - list.Sort(nameField, 1); + view.bitmaps.Clear(); + view.bitmaps = BitmapArray { }; + for(pos = 0; pos < selectedItems.count; pos++) + { + Bitmap bitmap { }; + selItem = (ExplorerFileItem)selectedItems._[pos]; + bitmap.Load(selItem.path, null, displaySystem); + //view.bitmaps.Add(bitmap); + } + if(item && item.type == pictureFile) + { + view.bitmap = Bitmap { }; + view.bitmap.Load(item.path, null, displaySystem); + } + + view.show.Update(null); + view.NotifyItemSelect(master, view, item, selectedItems); } - void LoadTreeNode(FileSystemNode node) + void Refresh() { - if(!node.loaded) + Load(location); + } + + void Load(FileSystemNode location) + { + char path[MAX_LOCATION]; + this.location = location; + location.GetPath(path); { - char path[MAX_LOCATION]; - node.GetPath(path); + FileListing listing { path }; + + ExplorerFileItem item; + DataRow row; + + list.Clear(); + + while(listing.Find()) { - FileListing listing { path, extensions = extensions }; - if(node.children.count == 1) - DeleteNode(node.children.first); + item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); - while(listing.Find()) + row = list.AddRow(); + row.tag = (int)item; + row.SetData(nameField, item); + } + list.Sort(nameField, 1); + } + } +} +#endif + +#if 0 +class ExplorerTree : FileSystemBox +{ + hasHorzScroll = false; + hasVertScroll = false; + + menu = Menu { }; + +public: + + DataField nameField { dataType = "FileSystemNode", width = 240, userData = this }; + + FileSystemNode root; + FileSystemNode selection; + + virtual bool Window::NotifyNodeSelect(ExplorerTree tree, FileSystemNode node); + + property FileSystemNode node + { + get + { + if(!tree) + return null; + if(!tree.currentRow) + return null; + if(!tree.currentRow.tag) + return null; + return (FileSystemNode)tree.currentRow.tag; + } + } + + void Select(FileSystemNode node) + { + if(node.row) + { + node.EnsureVisible(false); + tree.SelectRow(node.row); + } + } + + FileSystemNode Find(const char * name, FileSystemNode parent) + { + FileSystemNode node; + FileSystemNode start = parent ? parent : root; + if(!start.loaded || !start.childrenLoaded) + LoadTreeNode(start, tree); + for(node = start.children.first; node; node = node.next) + if(node.name && !strcmpi(node.name, name)) + return node; + return null; + } + + ListBox tree + { + master = master, parent = this; + //this, master; + borderStyle = none; + hasHorzScroll = true; + hasVertScroll = true; + fullRowSelect = false; + treeNodees = true; + collapseControl = true; + rootCollapseButton = 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) { - if(!listing.stats.attribs.isRemovable && ((!bits.foldersOnly && !bits.filesOnly) || - (bits.foldersOnly && listing.stats.attribs.isDirectory) || - (bits.filesOnly && listing.stats.attribs.isFile))) + /-* + for(child = node.children.last; child; child = node.children.last) { - FileSystemNode child = MakeFileSystemNode(listing.stats, listing.name, listing.path, bits.previewPictures, displaySystem); - AddTreeNode(child, true, false, node); - NodeChildLoad(child, node); + listBox.DeleteRow(child.row); + child.Free(); + delete child; } + node.childrenLoaded = false; + *-/ } - } - node.childrenLoaded = true; - node.loaded = true; - node.row.SortSubRows(false); + else + { + if(!node.loaded || !node.childrenLoaded) + LoadTreeNode(node, tree); + 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) + { + PopupMenu popup; + Menu menu { }; + + 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) + { + if(row) + { + FileSystemNode node = (FileSystemNode)row.tag; + NotifyNodeSelect(listBox.parent.master, this, node); + selection = node; + } + 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; + } + }; + + // 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; + }*-/ + + ExplorerTree() + { + tree.AddField(nameField); + } + + void Load() + { + FileSystemNode parent; + FileSystemNode node; + FileListing listing { "/" }; + + tree.Clear(); + + root = FileSystemNode { type = computer, loaded = true, childrenLoaded = true }; + #ifdef __WIN32__ + root.name = rootName; + #else + root.name = "/"; + #endif + AddTreeNode(root, true, false, null, tree); + + // How can this make sense for linux? + #ifdef __WIN32__ + 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); + if(info[0]) + parent.info = CopyString(info); + parent.loaded = true; + 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 }; + AddTreeNode(node, false, true, null, tree); + node.row.collapsed = true; + tree.Sort(nameField, 1); + tree.SelectRow(root.row); + } +} + +#if 0 +public class ClipBoardFiles +{ + +public: + + property + +} + + // CLIPBOARD + void Copy() + { + if(this) + { + int size = SelSize(); + if(size) + { + // Try to allocate memory + ClipBoard clipBoard { }; + if(clipBoard.Allocate(size+1)) + { + GetSel(clipBoard.memory, true); + // Save clipboard + clipBoard.Save(); + } + delete clipBoard; + } + } + } + + void Paste() + { + if(this) + { + ClipBoard clipBoard { }; + if(clipBoard.Load()) + PutS(clipBoard.memory); + delete clipBoard; + } + } + + void Cut() + { + if(this) + { + Copy(); + DelSel(); + SetViewToCursor(true); + Modified(); + } + } + +/-* +Private Type DROPFILES + pFiles As Long + pt As POINTAPI + fNC As Long + fWide As Long +End Type +For iCounter = 0 To filelist.ListCount - 1 + If filelist.Selected(iCounter) = True Then + strFiles = strFiles & FixPath(filelist.Path) & filelist.List(iCounter) & vbNullChar + End If +Next +'all selected items are now put in strFiles + +hGlobal = GlobalAlloc(GHND, Len(DF) + Len(strFiles)) 'put all files to a exclusive number +If hGlobal Then 'if the globalalloc worked + lpGlobal = GlobalLock(hGlobal) 'lock the hGlobal + DF.pFiles = Len(DF) 'set the size of the files + + Call CopyMem(ByVal lpGlobal, DF, Len(DF)) 'copy df to the lpglobal + Call CopyMem(ByVal (lpGlobal + Len(DF)), ByVal strFiles, Len(strFiles)) 'copy strfiles to lpglobal + Call GlobalUnlock(hGlobal) 'unlock hglobal again + + SetClipboardData CF_HDROP, hGlobal 'put files to the clipboard +End If +*-/ + bool SaveFile(const char * filePath) + { + } +#endif + +#if 0 +public class FileTreeNodeBSArray : ArrayBinarySorted +{ + type = class(FileSystemNode); +public: + FileSystemNode * const _; + BSloc Add(FileSystemNode item) + { + BSloc result = Find(item); + if(!result.valid) + { + Insert(result.pos, 1); + _[result.pos] = item; + } + return result; + } + BSloc Remove(FileSystemNode item) + { + + } +} +#endif + +#if 0 +public class FileTreeNodeArray : RedjArray +{ + type = class(FileSystemNode); +public: + FileSystemNode * const _; + FileSystemNode * Add(FileSystemNode item) + { + uint pos = _count; + Append(1); + _[pos] = item; + return &_[pos]; + } + FileSystemNode * AddBefore(uint position, FileSystemNode item) + { + Insert(position, 1); + _[position] = item; + return &_[position]; + } +} +#endif + +#if 0 +public class ExplorerFileItem : struct +{ + char * path; + char * name; + char * info; + char * extension; + _FileType type; + int indent; + + Bitmap bitmap; + + void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox control, Alignment alignment, DataDisplayFlags displayFlags) + { + int indentSize = (displayFlags.dropBox) ? 0 : 10; + int textOffset; + int len; + char label[MAX_FILENAME]; + + //float scale = Min((float)clientSize.w / (float)bitmap.width, (float)clientSize.h / (float)bitmap.height); + int w = 16; //(int)(bitmap.width * scale); + int h = 16; //(int)(bitmap.height * scale); + + Bitmap icon; + + icon = control.fileIcons[type].bitmap; + if(!icon) + { + if(type == folder || type == folderOpen) + surface.SetForeground(red); //Color { 170, 170, 0 } // REDJ What is that color? + indentSize = 8; } - else if(!node.childrenLoaded) + textOffset = indent * indentSize + (icon ? (icon.width + 6) : 0); + + if(info) + sprintf(label, "%s [%s]", name, info); + else + strcpy(label, name); + len = strlen(label); + + surface.WriteTextDots + (alignment, x + textOffset, y + 2, width - textOffset, label, len); + if(type == pictureFile && control.previewPictures && bitmap) + { +#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); +#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); +#endif + //bitmap.Free(); + //delete bitmap; + } + else if(icon) + surface.Blit(icon, x + indent * indentSize + 2, y,0,0, icon.width, icon.height); + } + + int OnCompare(ExplorerFileItem 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; + } + + void OnCopy(ExplorerFileItem newData) + { + type = newData.type; + indent = newData.indent; + if(newData.name) + { + int len = strlen(newData.name) + 1; + name = new char[len]; + CopyBytes(name, newData.name, len); + } + } + + bool OnGetDataFromString(char * string) + { + int len = strlen(string) + 1; + name = new char[len]; + CopyBytes(name, string, len); + return true; + } + + void OnFree() + { + delete path; + delete name; + delete info; + delete extension; + if(bitmap) + bitmap.Free(); + } + + char * OnGetString(char * string, void * fieldData, bool * needClass) + { + return name; + } +}; + +public class ExplorerFileItemArray : RedjArray +{ + type = class(ExplorerFileItem); +public: + ExplorerFileItem * const _; + ExplorerFileItem * Add(ExplorerFileItem item) + { + uint pos = _count; + Append(1); + _[pos] = item; + return &_[pos]; + } + ExplorerFileItem * AddBefore(uint position, ExplorerFileItem item) + { + Insert(position, 1); + _[position] = item; + return &_[position]; + } + void Clear() + { + int c; + for(c = 0; c < _count; c++) + { + //_[c].Free() + delete _[c]; + } + count = 0; + size = 0; + } +} + +ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, const char * filePath, const bool previewPicture, const DisplaySystem displaySystem) +{ + int len = strlen(fileName); + char info[MAX_LOCATION]; + char name[MAX_LOCATION]; + char extension[MAX_EXTENSION]; + + ExplorerFileItem item { }; + + //if(stats.attribs.isFile) // -- should work now + if(attribs.isDirectory) + { + extension[0] = 0; + + item.type = (attribs.isDrive) ? drive : folder; + if(attribs.isServer) + item.type = server; + if(attribs.isShare) + item.type = share; + if(attribs.isCDROM) + item.type = cdrom; + if(attribs.isRemote) + item.type = netDrive; + if(attribs.isRemovable) + { + if(fileName[0] == 'A' || fileName[0] == 'B') + item.type = floppy; + else + item.type = removable; + } + } + else + { + GetExtension(fileName, extension); + //strupr(extension); + strlwr(extension); + + item.type = _FileType::SelectByExtension(extension); + } + + if(attribs.isDrive && + len > 3 && !strncmp(&fileName[1], ": [", 3)) + { + strncpy(name, fileName, 2); + name[2] = 0; + strncpy(info, &fileName[4], len - 5); + info[len - 5] = 0; + } + else + { + strcpy(name, fileName); + info[0] = 0; + } + + item.path = CopyString(filePath); + item.name = CopyString(name); + if(info[0]) + item.info = CopyString(info); + item.extension = CopyString(extension); + + if(item.type == pictureFile && previewPicture) + { + item.bitmap = Bitmap { }; + item.bitmap.Load(filePath, null, displaySystem); + } + + return item; +} +#endif +*/ + +public class FileSystemNode : struct +{ +public: + /*//LinkElement link; + FileSystemNode parent; + + FileSystemNodeType type; + + char * name;*/ + + FileSystemNode prev, next; + + bool loaded, childrenLoaded; + int indent; + char * path; + char * name; + char * label; + char * extension; + char * info; + DataRow row; + OldList children; + _FileType type; + FileSystemNode parent; + + FileStats stats; + + Bitmap bitmap; + + void GetPath(String outputPath) + { + FileSystemNode up; + if(parent) + { + if(name) + strcpy(outputPath, name); + for(up = parent; up; up = up.parent) + { + char temp[MAX_LOCATION]; + strcpy(temp, up.name); + PathCat(temp, outputPath); + strcpy(outputPath, temp); + } + } + else +/*#ifdef __WIN32__ + strcpy(outputPath, "/"); +#else*/ + strcpy(outputPath, name); +//#endif + + } + + bool IsChildOf(FileSystemNode node) + { + FileSystemNode test; + for(test = parent; test; test = test.parent) + if(test == node) + return true; + return false; + } + + void DuplicateChildren(bool recursive, bool forceExpanded, FileSystemNode addTo, FileSystemBox fsb) + { + if(children.first) + { + FileSystemNode child; + + for(child = children.first; child; child = child.next) + { + FileSystemNode copy { }; + copy.name = CopyString(child.name); + copy.type = child.type; + fsb.AddTreeNode(copy, child.loaded, false, addTo); + if(forceExpanded) + copy.row.collapsed = false; + if(recursive) + child.DuplicateChildren(recursive, forceExpanded, copy, fsb); + } + } + } + + void EnsureVisible(bool expand) + { + if(parent) + parent.EnsureVisible(true); + if(expand) + row.collapsed = false; + // TODO: row.EnsureVisible(); // making the row visible by scrolling + } + + void OnFree() + { + //delete name; + } + + void Free() + { + FileSystemNode child; + for(; (child = children.first); ) + { + child.Free(); + children.Delete(child); + } + //if(name) + delete name; + delete label; + delete info; + } + + void Delete() + { + Free(); + if(parent) + parent.children.Delete(this); + } + + 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; + int xStart; + int len; + int w, h; + //int textOffset; + char string[MAX_FILENAME]; + + Bitmap icon; + + if(!this) + return; + + icon = fsb.fileIcons[type].bitmap; + //xStart = indent * indent + x + (icon ? (icon.width + 5) : 0); + xStart = x + (icon ? (icon.width + 5) : 0); + + if(!name) + return; + + if(info) + sprintf(string, "%s [%s]", label ? label : name, info); + else + strcpy(string, label ? label : name); + len = strlen(string); + + 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(string, 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, string, len); + + if(!guiApp.textMode) { - FileSystemNode child; - if(node.children.first) + if(displayFlags.current) { - for(child = node.children.first; child; child = child.next) + if(displayFlags.active) { - if(!child.loaded) - LoadTreeNode(child); - else if(!child.childrenLoaded) - NodeChildLoad(child, node); + surface.LineStipple(0x5555); + if(displayFlags.selected) + surface.SetForeground(0xFFFFFF80); + else + surface.SetForeground(black); } - node.childrenLoaded = true; - node.row.SortSubRows(false); + else + { + surface.SetForeground(selectionColor); + } + surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1); + surface.LineStipple(0); } - } - } - 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(icon) { - 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, bits.previewPictures, displaySystem); - AddTreeNode(child, true, false, parent); - added = true; - } + 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); + //surface.Blit(icon, x + indent * indentSize, y,0,0, icon.width, icon.height); + surface.Blit(icon, x,y,0,0, icon.width, icon.height); } - if(!added) - added = true; } - //parent.childrenLoaded = true; } - void AddTreeNode(FileSystemNode node, bool loaded, bool addLoader, FileSystemNode addTo) + int OnCompare(FileSystemNode b) { - DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : list.AddRow(); - if(addTo) + int result; + FileSystemNode a = this; + if(a.type == b.type || (a.type < folder && b.type < folder) || (a.type >= drive)) + result = strcmpi(a.name, b.name); + else { - node.parent = addTo; - node.indent = addTo.indent + 1; - addTo.children.Add(node); + if(a.type == folder && b.type < folder) result = -1; + else if(a.type < folder && b.type == folder) result = 1; + else result = 0; } - row.tag = (int)node; - node.row = row; - row.SetData(null, node); - - node.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; + return result; } - void DeleteNode(FileSystemNode node) + /*int OnCompare(FileSystemNode b) { - FileSystemNode child; - for(; (child = node.children.first); ) - DeleteNode(child); - list.DeleteRow(node.row); - node.Delete(); - } -/* -public class ClipBoardFiles -{ - -public: - - property + 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 : ""; + } } - // CLIPBOARD - void Copy() +/*FileSystemNode MakeFileSystemNode(const FileStats stats, const char * name) +{ + FileSystemNode node { stats = stats }; + node.name = CopyString(name); + if(!node.name) + node.name = null; + if(stats.attribs.isDirectory) { - if(this) + 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) { - int size = SelSize(); - if(size) - { - // Try to allocate memory - ClipBoard clipBoard { }; - if(clipBoard.Allocate(size+1)) - { - GetSel(clipBoard.memory, true); - // Save clipboard - clipBoard.Save(); - } - delete clipBoard; - } + if(name[0] == 'A' || name[0] == 'B') + node.type = floppy; + else + node.type = removable; } } - - void Paste() + else { - if(this) - { - ClipBoard clipBoard { }; - if(clipBoard.Load()) - PutS(clipBoard.memory); - delete clipBoard; - } + char extension[MAX_EXTENSION]; + GetExtension(node.name, extension); + node.type = _FileType::SelectByExtension(extension); } + return node; +}*/ +static FileSystemNode MakeFileSystemNode(const FileStats stats, + const char * fileName, const char * filePath, + const bool previewPicture, const DisplaySystem displaySystem) +{ + int len = strlen(fileName); + char info[MAX_LOCATION]; + char name[MAX_LOCATION]; + char extension[MAX_EXTENSION]; + + FileSystemNode node { stats = stats }; - void Cut() + //if(stats.attribs.isFile) // TODO fix this in ecere + if(stats.attribs.isDirectory) { - if(this) + extension[0] = '\0'; + + 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) { - Copy(); - DelSel(); - SetViewToCursor(true); - Modified(); + if(fileName[0] == 'A' || fileName[0] == 'B') + node.type = floppy; + else + node.type = removable; } } + else + { + GetExtension(fileName, extension); + strlwr(extension); + + node.type = _FileType::SelectByExtension(extension); + } -Private Type DROPFILES - pFiles As Long - pt As POINTAPI - fNC As Long - fWide As Long -End Type -For iCounter = 0 To filelist.ListCount - 1 - If filelist.Selected(iCounter) = True Then - strFiles = strFiles & FixPath(filelist.Path) & filelist.List(iCounter) & vbNullChar - End If -Next -'all selected items are now put in strFiles + if(stats.attribs.isDrive && + len > 3 && !strncmp(&fileName[1], ": [", 3)) + { + strncpy(name, fileName, 2); + name[2] = 0; + strncpy(info, &fileName[4], len - 5); + info[len - 5] = 0; + } + else + { + strcpy(name, fileName); + info[0] = 0; + } -hGlobal = GlobalAlloc(GHND, Len(DF) + Len(strFiles)) 'put all files to a exclusive number -If hGlobal Then 'if the globalalloc worked - lpGlobal = GlobalLock(hGlobal) 'lock the hGlobal - DF.pFiles = Len(DF) 'set the size of the files - - Call CopyMem(ByVal lpGlobal, DF, Len(DF)) 'copy df to the lpglobal - Call CopyMem(ByVal (lpGlobal + Len(DF)), ByVal strFiles, Len(strFiles)) 'copy strfiles to lpglobal - Call GlobalUnlock(hGlobal) 'unlock hglobal again - - SetClipboardData CF_HDROP, hGlobal 'put files to the clipboard -End If + node.path = CopyString(filePath); + node.name = CopyString(name); + if(info[0]) + node.info = CopyString(info); + node.extension = CopyString(extension); - bool SaveFile(const char * filePath) + if(node.type == pictureFile && previewPicture) { + node.bitmap = Bitmap { alphaBlend = true }; + node.bitmap.Load(filePath, null, displaySystem); } -*/ + return node; }