From 66f02db2f111511a0b265657d2092e223b67c4e4 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Wed, 7 Jan 2015 11:16:36 +0300 Subject: [PATCH] FileDialog - file type filter support, part 1 --- examples/example1/src/main.d | 4 +++ src/dlangui/core/files.d | 19 ++++++++++++- src/dlangui/dialogs/filedlg.d | 53 +++++++++++++++++++++++++++++++++-- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/examples/example1/src/main.d b/examples/example1/src/main.d index 67595064..89f45146 100644 --- a/examples/example1/src/main.d +++ b/examples/example1/src/main.d @@ -294,6 +294,10 @@ extern (C) int UIAppMain(string[] args) { UIString caption; caption = "Open Text File"d; FileDialog dlg = new FileDialog(caption, window, null); + dlg.addFilter(FileFilterEntry(UIString("FILTER_ALL_FILES", "All files (*.*)"d), "*.*")); + dlg.addFilter(FileFilterEntry(UIString("FILTER_TEXT_FILES", "Text files (*.txt)"d), "*.txt")); + dlg.addFilter(FileFilterEntry(UIString("FILTER_SOURCE_FILES", "Source files"d), "*.d;*.dd;*.c;*.cc;*.cpp;*.h;*.hpp")); + dlg.filterIndex = 2; dlg.onDialogResult = delegate(Dialog dlg, const Action result) { Log.d("FileDialog.onDialogResult: ", result, " param=", result.stringParam); window.showMessageBox(UIString("FileOpen result"d), UIString(toUTF32(result.stringParam))); diff --git a/src/dlangui/core/files.d b/src/dlangui/core/files.d index a3447a8f..aee21ce8 100644 --- a/src/dlangui/core/files.d +++ b/src/dlangui/core/files.d @@ -156,9 +156,26 @@ string parentDir(string path) { return buildNormalizedPath(path, ".."); } +/// check filename with pattern (currently only *.ext pattern is supported) +bool filterFilename(string filename, string pattern) { + if (pattern.equal("*.*")) + return true; // matches any + if (pattern.length < 3) + return false; + if (pattern[0] != '*' || pattern[1] != '.') + return false; + return filename.endsWith(pattern[1..$]); +} + /// Filters file name by pattern list bool filterFilename(string filename, string[] filters) { - return true; + if (filters.length == 0) + return true; // no filters - show all + foreach(pattern; filters) { + if (filterFilename(filename, pattern)) + return true; + } + return false; } /** List directory content diff --git a/src/dlangui/dialogs/filedlg.d b/src/dlangui/dialogs/filedlg.d index 35ddfb8b..08f30682 100644 --- a/src/dlangui/dialogs/filedlg.d +++ b/src/dlangui/dialogs/filedlg.d @@ -42,6 +42,7 @@ private import std.file; private import std.path; private import std.utf; private import std.conv : to; +private import std.array : split; /// flags for file dialog options @@ -56,6 +57,17 @@ enum FileDialogFlag : uint { Save = ConfirmOverwrite, } +/// filetype filter entry for FileDialog +struct FileFilterEntry { + UIString label; + string[] filter; + this(UIString displayLabel, string filterList) { + label = displayLabel; + if (filterList.length) + filter = split(filterList, ";"); + } +} + /// File open / save dialog class FileDialog : Dialog, CustomGridCellAdapter { protected FilePathPanel _edPath; @@ -66,6 +78,8 @@ class FileDialog : Dialog, CustomGridCellAdapter { protected Action _action; protected RootEntry[] _roots; + protected FileFilterEntry[] _filters; + protected int _filterIndex; protected string _path; protected string _filename; protected DirEntry[] _entries; @@ -85,6 +99,38 @@ class FileDialog : Dialog, CustomGridCellAdapter { _action = action; } + /// filter list for file type filter combo box + @property FileFilterEntry[] filters() { + return _filters; + } + + /// filter list for file type filter combo box + @property void filters(FileFilterEntry[] values) { + _filters = values; + } + + /// add new filter entry + void addFilter(FileFilterEntry value) { + _filters ~= value; + } + + /// filter index + @property int filterIndex() { + return _filterIndex; + } + + /// filter index + @property void filterIndex(int index) { + _filterIndex = index; + } + + /// return currently selected filter value - array of patterns like ["*.txt", "*.rtf"] + @property string[] selectedFilter() { + if (_filterIndex >= 0 && _filterIndex < _filters.length) + return _filters[_filterIndex].filter; + return null; + } + /// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout). override void layout(Rect rc) { super.layout(rc); @@ -96,12 +142,15 @@ class FileDialog : Dialog, CustomGridCellAdapter { return openDirectory(parentDir(_path), _path); } + protected bool reopenDirectory() { + return true; + } + protected bool openDirectory(string dir, string selectedItemPath) { dir = buildNormalizedPath(dir); Log.d("FileDialog.openDirectory(", dir, ")"); _fileList.rows = 0; - string[] filters; - if (!listDirectory(dir, true, true, false, filters, _entries)) + if (!listDirectory(dir, true, true, false, selectedFilter, _entries)) return false; _path = dir; _isRoot = isRoot(dir);