changeset 4:fc2420d39e3c

Separate out Windows backend of FileDialog.
author Jordan Miner <jminer7@gmail.com>
date Sat, 20 Jun 2009 10:23:31 -0500
parents d806edad4300
children 4029d5af7542
files dynamin/gui/file_dialog.d dynamin/gui/windows_file_dialog.d dynamin/gui_backend.d
diffstat 3 files changed, 150 insertions(+), 107 deletions(-) [+]
line wrap: on
line diff
--- a/dynamin/gui/file_dialog.d	Mon Jun 15 22:19:30 2009 -0500
+++ b/dynamin/gui/file_dialog.d	Sat Jun 20 10:23:31 2009 -0500
@@ -25,11 +25,8 @@
 
 module dynamin.gui.file_dialog;
 
-import dynamin.c.windows;
 import dynamin.all_core;
-import dynamin.gui.window;
-import tango.io.Stdout;
-import Utf = tango.text.convert.Utf;
+import dynamin.gui_backend;
 
 // not used by programs
 struct FileDialogFilter {
@@ -50,6 +47,8 @@
  * $(IMAGE ../web/example_file_dialog.png)
  */
 abstract class FileDialog {
+private:
+	mixin FileDialogBackend;
 protected:
 	bool _multipleSelection;
 	string _initialFileName;
@@ -58,6 +57,14 @@
 	string[] _files;
 	FileDialogFilter[] _filters;
 	int _selectedFilter;
+
+	uint fileDialogType;
+	enum {
+		Open, Save
+	}
+	invariant() {
+		assert(fileDialogType == Open || fileDialogType == Save);
+	}
 public:
 	/**
 	 * Adds a filter that only shows files with the specified extensions.
@@ -143,107 +150,14 @@
 	string[] files() { return _files; }
 	/// Gets the first of the files selected by the user.
 	string file() { return _files[0]; }
-	protected int getXFileName(OPENFILENAME* ofn);
+
 	// TODO: parameters
-	// TODO: should ShowDialog take any parameters?
+	// TODO: should showDialog take any parameters?
 	//       what should happen if no owner is set?
 	//       Windows Forms sets the owner to the currently active window in the application
 	//       do the same? or have no owner (really annoying, as window can get below)?
 	DialogResult showDialog() {
-		OPENFILENAME ofn;
-		ofn.lStructSize = OPENFILENAME.sizeof;
-		//ofn.hwndOwner = ;
-
-		bool allFilesFilter = false;
-		foreach(filter; _filters)
-			if(filter.extensions.length == 0)
-				allFilesFilter = true;
-		if(!allFilesFilter) addFilter("All Files (*.*)");
-
-		string filterStr;
-		foreach(filter; _filters) {
-			if(filter.shouldShow)
-				continue;
-			string[] exts = filter.extensions.dup;
-			if(exts.length == 0)
-				exts = [cast(string)"*.*"];
-			else
-				for(int i = 0; i < exts.length; ++i)
-					exts[i] = "*." ~ exts[i];
-			filterStr ~= filter.name ~ "\0" ~ exts.join(";") ~ "\0";
-		}
-		filterStr ~= "\0";
-		ofn.lpstrFilter = filterStr.toWcharPtr();
-		ofn.nFilterIndex = _selectedFilter + 1;
-		wchar[] filesBufferW = Utf.toString16(_initialFileName~"\0");
-		filesBufferW.length = 4096;
-		scope(exit) delete filesBufferW;
-		ofn.lpstrFile = filesBufferW.ptr;
-		ofn.nMaxFile = filesBufferW.length;
-		ofn.lpstrInitialDir = _directory.toWcharPtr();
-		ofn.lpstrTitle = _text.toWcharPtr();
-		ofn.Flags = OFN_EXPLORER;
-		//if(canChooseLinks)
-		//	ofn.Flags |= OFN_NODEREFERENCELINKS;
-		ofn.Flags |= OFN_FILEMUSTEXIST;
-		ofn.Flags |= OFN_HIDEREADONLY;
-		ofn.Flags |= OFN_OVERWRITEPROMPT;
-		if(_multipleSelection)
-			ofn.Flags |= OFN_ALLOWMULTISELECT;
-
-		if(!getXFileName(&ofn)) {
-			if(CommDlgExtendedError() == FNERR_BUFFERTOOSMALL)
-				MessageBoxW(null, "Too many files picked.", "Error", 0);
-			return DialogResult.Cancel;
-		}
-
-		_selectedFilter = ofn.nFilterIndex - 1;
-		// must zero FFFF chars here because the
-		// parsing here assumes the unused part of the string is zeroed
-		foreach(i, c; filesBufferW)
-			if(c == 0xFFFF)
-				filesBufferW[i] = 0;
-		int index; // index of null char right after the last non-null char
-		for(index = filesBufferW.length; index > 0; --index)
-			if(filesBufferW[index-1] != 0)
-				break;
-		auto filesBuffer = Utf.toString(filesBufferW[0..index]);
-		scope(exit) delete filesBuffer;
-		if(filesBuffer.contains('\0')) { // multiple files
-			auto arr = filesBuffer.split("\0");
-			_directory = arr[0];
-			// make sure directory ends with a backslash
-			// "C:\" does but "C:\Program Files" does not
-			if(!_directory.endsWith("\\"))
-				_directory ~= "\\";
-			_files = new string[arr.length-1];
-			for(int i = 1; i < arr.length; ++i) {
-				if(arr[i].contains('\\')) // a dereferenced link--absolute
-					_files[i-1] = arr[i];
-				else
-					_files[i-1] = _directory ~ arr[i];
-			}
-		} else { //single file
-			assert(filesBuffer.contains('\\'));
-			_directory = filesBuffer[0..filesBuffer.findLast("\\")].dup;
-			_files = [filesBuffer.dup];
-		}
-
-		// if "All Files (*.*)" filter is not selected
-		if(_filters[selectedFilter].extensions.length > 0) {
-			// go over every chosen file and add the selected filter's
-			// extension if the file doesn't already have one from the selected filter
-			for(int i = 0; i < _files.length; ++i) {
-				bool validExt = false;
-				foreach(ext; _filters[selectedFilter].extensions)
-					if(_files[i].downcase().endsWith(ext.downcase()))
-						validExt = true;
-				if(!validExt)
-					_files[i] ~= "." ~ _filters[selectedFilter].extensions[0].downcase();
-			}
-		}
-
-		return DialogResult.OK;
+		return backend_showDialog();
 	}
 }
 
@@ -252,9 +166,7 @@
 	this() {
 		_multipleSelection = true;
 		// different settings
-	}
-	protected int getXFileName(OPENFILENAME* ofn) {
-		return GetOpenFileName(ofn);
+		fileDialogType = Open;
 	}
 }
 
@@ -263,8 +175,6 @@
 	this() {
 		_multipleSelection = false;
 		// different settings
-	}
-	protected int getXFileName(OPENFILENAME* ofn) {
-		return GetSaveFileName(ofn);
+		fileDialogType = Save;
 	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dynamin/gui/windows_file_dialog.d	Sat Jun 20 10:23:31 2009 -0500
@@ -0,0 +1,133 @@
+// Written in the D programming language
+// www.digitalmars.com/d/
+
+/*
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Dynamin library.
+ *
+ * The Initial Developer of the Original Code is Jordan Miner.
+ * Portions created by the Initial Developer are Copyright (C) 2006-2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jordan Miner <jminer7@gmail.com>
+ *
+ */
+
+module dynamin.gui.windows_file_dialog;
+
+public import dynamin.c.windows;
+public import Utf = tango.text.convert.Utf;
+
+template FileDialogBackend() {
+	DialogResult backend_showDialog() {
+		OPENFILENAME ofn;
+		ofn.lStructSize = OPENFILENAME.sizeof;
+		//ofn.hwndOwner = ;
+
+		bool allFilesFilter = false;
+		foreach(filter; _filters)
+			if(filter.extensions.length == 0)
+				allFilesFilter = true;
+		if(!allFilesFilter) addFilter("All Files (*.*)");
+
+		string filterStr;
+		foreach(filter; _filters) {
+			if(filter.shouldShow)
+				continue;
+			string[] exts = filter.extensions.dup;
+			if(exts.length == 0)
+				exts = [cast(string)"*.*"];
+			else
+				for(int i = 0; i < exts.length; ++i)
+					exts[i] = "*." ~ exts[i];
+			filterStr ~= filter.name ~ "\0" ~ exts.join(";") ~ "\0";
+		}
+		filterStr ~= "\0";
+		ofn.lpstrFilter = filterStr.toWcharPtr();
+		ofn.nFilterIndex = _selectedFilter + 1;
+		wchar[] filesBufferW = Utf.toString16(_initialFileName~"\0");
+		// TODO: should use a static buffer of 4096, passing to toString16
+		// avoid concat too
+		filesBufferW.length = 4096;
+		scope(exit) delete filesBufferW;
+		ofn.lpstrFile = filesBufferW.ptr;
+		ofn.nMaxFile = filesBufferW.length;
+		ofn.lpstrInitialDir = _directory.toWcharPtr();
+		ofn.lpstrTitle = _text.toWcharPtr();
+		ofn.Flags = OFN_EXPLORER;
+		//if(canChooseLinks)
+		//	ofn.Flags |= OFN_NODEREFERENCELINKS;
+		ofn.Flags |= OFN_FILEMUSTEXIST;
+		ofn.Flags |= OFN_HIDEREADONLY;
+		ofn.Flags |= OFN_OVERWRITEPROMPT;
+		if(_multipleSelection)
+			ofn.Flags |= OFN_ALLOWMULTISELECT;
+
+		auto GetFileName = fileDialogType == Open ?
+		                   &GetOpenFileName : &GetSaveFileName ;
+		if(!GetFileName(&ofn)) {
+			if(CommDlgExtendedError() == FNERR_BUFFERTOOSMALL)
+				MessageBoxW(null, "Too many files picked.", "Error", 0);
+			return DialogResult.Cancel;
+		}
+
+		_selectedFilter = ofn.nFilterIndex - 1;
+		// must zero FFFF chars here because the
+		// parsing here assumes the unused part of the string is zeroed
+		foreach(i, c; filesBufferW)
+			if(c == 0xFFFF)
+				filesBufferW[i] = 0;
+		int index; // index of null char right after the last non-null char
+		for(index = filesBufferW.length; index > 0; --index)
+			if(filesBufferW[index-1] != 0)
+				break;
+		auto filesBuffer = Utf.toString(filesBufferW[0..index]);
+		scope(exit) delete filesBuffer;
+		if(filesBuffer.contains('\0')) { // multiple files
+			auto arr = filesBuffer.split("\0");
+			_directory = arr[0];
+			// make sure directory ends with a backslash
+			// "C:\" does but "C:\Program Files" does not
+			if(!_directory.endsWith("\\"))
+				_directory ~= "\\";
+			_files = new string[arr.length-1];
+			for(int i = 1; i < arr.length; ++i) {
+				if(arr[i].contains('\\')) // a dereferenced link--absolute
+					_files[i-1] = arr[i];
+				else
+					_files[i-1] = _directory ~ arr[i];
+			}
+		} else { //single file
+			assert(filesBuffer.contains('\\'));
+			_directory = filesBuffer[0..filesBuffer.findLast("\\")].dup;
+			_files = [filesBuffer.dup];
+		}
+
+		// if "All Files (*.*)" filter is not selected
+		if(_filters[selectedFilter].extensions.length > 0) {
+			// go over every chosen file and add the selected filter's
+			// extension if the file doesn't already have one from the selected filter
+			for(int i = 0; i < _files.length; ++i) {
+				bool validExt = false;
+				foreach(ext; _filters[selectedFilter].extensions)
+					if(_files[i].downcase().endsWith(ext.downcase()))
+						validExt = true;
+				if(!validExt)
+					_files[i] ~= "." ~ _filters[selectedFilter].extensions[0].downcase();
+			}
+		}
+
+		return DialogResult.OK;
+	}
+}
+
--- a/dynamin/gui_backend.d	Mon Jun 15 22:19:30 2009 -0500
+++ b/dynamin/gui_backend.d	Sat Jun 20 10:23:31 2009 -0500
@@ -29,7 +29,7 @@
 	public import dynamin.gui.windows_clipboard;
 	public import dynamin.gui.windows_cursor;
 	//public import dynamin.gui.windows_directory_dialog;
-	//public import dynamin.gui.windows_file_dialog;
+	public import dynamin.gui.windows_file_dialog;
 	//public import dynamin.gui.windows_screen;
 	public import dynamin.gui.windows_window;
 } else {