forked from VaIeroK/Omf-Editor
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFileDrop.cs
More file actions
228 lines (197 loc) · 7.92 KB
/
Copy pathFileDrop.cs
File metadata and controls
228 lines (197 loc) · 7.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
namespace OMF_Editor
{
// Files dropped on the editor window. An .omf opens, or hands its motions
// over to the file already open; .skl/.skls go the same way as the File menu
// import; an .ogf becomes the model of the viewport. Anything else is not
// taken, so the drop is refused before it happens.
public partial class OMF_Editor
{
private enum DroppedOmfAnswer { Open, Merge, Cancel }
// Called from the form constructor, once every control is in place.
private void InitFileDrop()
{
AllowFileDrop(this);
}
// A drop lands on the control under the cursor and stops there: a child
// that takes no drops of its own refuses it rather than passing it up to
// the form. So the whole tree is registered, and so is whatever is added
// to it later. AllowDrop doubles as the mark of an already registered
// control - nothing else in the editor sets it.
private void AllowFileDrop(Control control)
{
if (!control.AllowDrop)
{
control.AllowDrop = true;
control.DragEnter += FileDragEnter;
control.DragOver += FileDragEnter;
control.DragDrop += FileDragDrop;
control.ControlAdded += FileDropControlAdded;
}
foreach (Control child in control.Controls)
AllowFileDrop(child);
}
private void FileDropControlAdded(object sender, ControlEventArgs e)
{
AllowFileDrop(e.Control);
}
private void FileDragEnter(object sender, DragEventArgs e)
{
e.Effect = !OverViewport(e) && DroppedFiles(e.Data).Count != 0
? DragDropEffects.Copy
: DragDropEffects.None;
}
private void FileDragDrop(object sender, DragEventArgs e)
{
if (OverViewport(e))
return;
List<string> files = DroppedFiles(e.Data);
if (files.Count == 0)
return;
// the handler returns at once and the work - questions, converter
// runs and all - happens after it: explorer stands still for as long
// as the drop it started is being served
BeginInvoke(new MethodInvoker(delegate { OpenDroppedFiles(files); }));
}
// A viewport with a model in it takes nothing. What is in it is the
// viewer's window, and the file would have to go through it - it has
// been told to leave dropped files alone, and the panel around it
// refuses them as well rather than doing something the picture gives no
// sign of. So the whole panel is one rectangle where the cursor says no.
private bool OverViewport(DragEventArgs e)
{
if (viewportPanel == null || !viewportPanel.Visible)
return false;
// Except while it stands empty: then it is the Append OGF button
// asking for a model, and a model dropped on it is the answer. The
// button is up for exactly as long as there is no model, which is
// also as long as there is no viewer window to get in the way.
if (viewportAppendButton != null && viewportAppendButton.Visible)
return false;
// the drag carries screen coordinates, whatever control it is over
return viewportPanel.RectangleToScreen(viewportPanel.ClientRectangle)
.Contains(e.X, e.Y);
}
private static List<string> DroppedFiles(IDataObject data)
{
List<string> files = new List<string>();
if (data == null || !data.GetDataPresent(DataFormats.FileDrop))
return files;
string[] paths = data.GetData(DataFormats.FileDrop) as string[];
if (paths == null)
return files;
foreach (string path in paths)
{
if (DroppedFileKind(path) != null)
files.Add(path);
}
return files;
}
// The extension in lower case for the three things the editor takes, and
// null for everything else.
private static string DroppedFileKind(string path)
{
string extension;
try
{
extension = Path.GetExtension(path).ToLowerInvariant();
}
catch (ArgumentException)
{
return null; // not a path we can do anything with
}
switch (extension)
{
case ".omf":
case ".skl":
case ".skls":
case ".ogf":
return extension;
default:
return null;
}
}
private void OpenDroppedFiles(List<string> files)
{
Activate();
List<string> models = new List<string>();
List<string> omfs = new List<string>();
List<string> skls = new List<string>();
foreach (string path in files)
{
switch (DroppedFileKind(path))
{
case ".ogf": models.Add(path); break;
case ".omf": omfs.Add(path); break;
default: skls.Add(path); break;
}
}
// the model goes in first: the motions that follow it are then built
// into a preview right away instead of waiting for one
if (models.Count != 0)
LoadDroppedModel(models[0]);
OpenDroppedOmfs(omfs);
if (skls.Count != 0)
ImportSklFiles(skls);
}
// Same as Viewport -> Load model..., without the file dialog: a model
// dropped while the viewport is hidden brings it out.
private void LoadDroppedModel(string path)
{
if (!viewportEnabled)
{
viewportShowItem.Checked = true;
EnableViewport(true);
if (!viewportEnabled)
return;
}
if (LoadViewportModel(path, true))
RequestViewportUpdate(true);
}
private void OpenDroppedOmfs(List<string> paths)
{
foreach (string path in paths)
{
bool open = Main_OMF == null;
if (!open)
{
switch (AskDroppedOmf(path))
{
case DroppedOmfAnswer.Open: open = true; break;
case DroppedOmfAnswer.Merge: open = false; break;
default: return;
}
}
try
{
if (open)
OpenFile(path);
else
AppendFile(path);
}
catch (Exception exp)
{
MessageBox.Show(exp.ToString());
}
}
}
// With a file already open a dropped OMF can be either of two things:
// the file to work on from now on, or motions to bring into the one
// open. Both are wanted often enough that the drop asks which.
private static DroppedOmfAnswer AskDroppedOmf(string path)
{
DialogResult answer = MessageBox.Show(
"Open " + Path.GetFileName(path) + "?\n\n" +
"No adds its motions to the file already open.",
"Dropped OMF", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (answer == DialogResult.Yes)
return DroppedOmfAnswer.Open;
if (answer == DialogResult.No)
return DroppedOmfAnswer.Merge;
return DroppedOmfAnswer.Cancel;
}
}
}