~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to src/addins/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
Import upstream version 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
using System;
 
2
using System.IO;
 
3
using System.Collections.Generic;
 
4
using System.Text;
 
5
using System.Threading;
 
6
using MonoDevelop.Components.Extensions;
 
7
using System.Windows.Forms;
 
8
using MonoDevelop.Core;
 
9
using MonoDevelop.Ide;
 
10
 
 
11
namespace MonoDevelop.Platform
 
12
{
 
13
    class SelectFileDialogHandler : ISelectFileDialogHandler
 
14
    {
 
15
        volatile Form rootForm;
 
16
 
 
17
        public bool Run (SelectFileDialogData data)
 
18
        {
 
19
            var parentWindow = data.TransientFor ?? MessageService.RootWindow;
 
20
            parentWindow.FocusInEvent += OnParentFocusIn;
 
21
            
 
22
            bool result = RunWinUIMethod (RunDialog, data);
 
23
 
 
24
            parentWindow.FocusInEvent -= OnParentFocusIn;
 
25
            parentWindow.Present ();
 
26
 
 
27
            return result;
 
28
        }
 
29
 
 
30
        void OnParentFocusIn (object o, EventArgs args)
 
31
        {
 
32
            if (rootForm != null)
 
33
                rootForm.BeginInvoke (new Action (rootForm.Activate));
 
34
        }
 
35
 
 
36
        bool RunDialog (SelectFileDialogData data)
 
37
        {
 
38
                        Application.EnableVisualStyles ();
 
39
 
 
40
            CommonDialog dlg = null;
 
41
            if (data.Action == Gtk.FileChooserAction.Open)
 
42
                dlg = new OpenFileDialog();
 
43
            else if (data.Action == Gtk.FileChooserAction.Save)
 
44
                dlg = new SaveFileDialog();
 
45
                        else if (data.Action == Gtk.FileChooserAction.SelectFolder)
 
46
                                dlg = new FolderBrowserDialog ();
 
47
                        
 
48
                        if (dlg is FileDialog)
 
49
                                SetCommonFormProperties (data, (FileDialog)dlg);
 
50
                        else
 
51
                                SetFolderBrowserProperties (data, (FolderBrowserDialog)dlg);
 
52
                        
 
53
                        using (dlg) {
 
54
                rootForm = new WinFormsRoot ();
 
55
                if (dlg.ShowDialog (rootForm) == DialogResult.Cancel) {
 
56
                    return false;
 
57
                                }
 
58
                                
 
59
                                if (dlg is FileDialog) {
 
60
                                        var fileDlg = dlg as FileDialog;
 
61
                                        FilePath[] paths = new FilePath [fileDlg.FileNames.Length];
 
62
                                        for (int n=0; n < fileDlg.FileNames.Length; n++)
 
63
                                                paths [n] = fileDlg.FileNames [n];
 
64
                    data.SelectedFiles = paths;    
 
65
                                } else {
 
66
                                        var folderDlg = dlg as FolderBrowserDialog;
 
67
                                        data.SelectedFiles = new [] { new FilePath (folderDlg.SelectedPath) };
 
68
                                }
 
69
 
 
70
                                return true;
 
71
                        }
 
72
        }
 
73
 
 
74
        // Any native Winforms component needs to run on a thread marked as single-threaded apartment (STAThread).
 
75
        // Marking the MD's Main method with STAThread has historically shown to be a source of several problems,
 
76
        // thus we isolate the calls by creating a new thread for our calls.
 
77
        // More info here: http://blogs.msdn.com/b/jfoscoding/archive/2005/04/07/406341.aspx
 
78
        internal static bool RunWinUIMethod<T> (Func<T,bool> func, T data) where T : SelectFileDialogData
 
79
        {
 
80
            bool result = false;
 
81
            var t = new Thread (() => {
 
82
                try {
 
83
                    result = func (data);
 
84
                } catch (Exception ex) {
 
85
                    LoggingService.LogError ("Unhandled exception handling a native dialog", ex);
 
86
                }
 
87
            });
 
88
            t.Name = "Win32 Interop Thread";
 
89
            t.IsBackground = true;
 
90
            t.SetApartmentState (ApartmentState.STA);
 
91
 
 
92
            t.Start ();
 
93
            while (!t.Join (50))
 
94
                DispatchService.RunPendingEvents ();
 
95
 
 
96
            return result;
 
97
        }
 
98
                
 
99
                internal static void SetCommonFormProperties (SelectFileDialogData data, FileDialog dialog)
 
100
                {
 
101
                        if (!string.IsNullOrEmpty (data.Title))
 
102
                                dialog.Title = data.Title;
 
103
                        
 
104
                        dialog.AddExtension = true;
 
105
                        dialog.Filter = GetFilterFromData (data.Filters);
 
106
                        dialog.FilterIndex = data.DefaultFilter == null ? 1 : GetDefaultFilterIndex (data);
 
107
                        
 
108
                        dialog.InitialDirectory = data.CurrentFolder;
 
109
 
 
110
                        // FileDialog.FileName expects anything but a directory name.
 
111
                        if (!Directory.Exists (data.InitialFileName))
 
112
                                dialog.FileName = data.InitialFileName;
 
113
                        
 
114
                        OpenFileDialog openDialog = dialog as OpenFileDialog;
 
115
                        if (openDialog != null)
 
116
                                openDialog.Multiselect = data.SelectMultiple;
 
117
                }
 
118
 
 
119
                static int GetDefaultFilterIndex (SelectFileDialogData data)
 
120
                {
 
121
                        var defFilter = data.DefaultFilter;
 
122
                        int idx = data.Filters.IndexOf (defFilter) + 1;
 
123
 
 
124
                        // FileDialog doesn't show the file extension when saving a file,
 
125
                        // so we try to look fo the precise filter if none was specified.
 
126
                        if (data.Action == Gtk.FileChooserAction.Save && defFilter.Patterns.Contains ("*")) {
 
127
                                string ext = Path.GetExtension (data.InitialFileName);
 
128
 
 
129
                                if (!String.IsNullOrEmpty (ext))
 
130
                                        for (int i = 0; i < data.Filters.Count; i++) {
 
131
                                                var filter = data.Filters [i];
 
132
                                                foreach (string pattern in filter.Patterns)
 
133
                                                        if (pattern.EndsWith (ext))
 
134
                                                                return i + 1;
 
135
                                        }
 
136
                        }
 
137
 
 
138
                        return idx;
 
139
                }
 
140
                                
 
141
                static void SetFolderBrowserProperties (SelectFileDialogData data, FolderBrowserDialog dialog)
 
142
                {
 
143
                        if (!string.IsNullOrEmpty (data.Title))
 
144
                                dialog.Description = data.Title;
 
145
                        
 
146
                        dialog.SelectedPath = data.CurrentFolder;
 
147
                }
 
148
                
 
149
                static string GetFilterFromData (IList<SelectFileDialogFilter> filters)
 
150
                {
 
151
                        if (filters == null || filters.Count == 0)
 
152
                                return null;
 
153
                        
 
154
                        var sb = new StringBuilder ();
 
155
                        foreach (var f in filters) {
 
156
                                if (sb.Length > 0)
 
157
                                        sb.Append ('|');
 
158
                                
 
159
                                sb.Append (f.Name);
 
160
                                sb.Append ('|');
 
161
                                for (int i = 0; i < f.Patterns.Count; i++) {
 
162
                                        if (i > 0)
 
163
                                                sb.Append (';');
 
164
                                
 
165
                                        sb.Append (f.Patterns [i]);
 
166
                                }
 
167
                        }
 
168
                        
 
169
                        return sb.ToString ();
 
170
                }
 
171
    }
 
172
}