NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
numeredroptarget.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2017 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19
20#include "numeredroptarget.hpp"
21#include "NumeReWindow.h"
22#include "editor/editor.h"
23#include "terminal/terminal.hpp"
25#include "DirTraverser.hpp"
26#include "../common/vcsmanager.hpp"
27#include "../common/filerevisions.hpp"
28
29#define wxUSE_DRAG_AND_DROP 1
30
31#if wxUSE_DRAG_AND_DROP
32
33std::string replacePathSeparator(const std::string&);
34
43NumeReDropTarget::NumeReDropTarget(wxWindow* topwindow, wxWindow* owner, parentType type) : m_owner(owner), m_topWindow(topwindow), m_type(type)
44{
45 wxDataObjectComposite* dataobj = new wxDataObjectComposite();
46
47 if (type == EDITOR || type == CONSOLE)
48 {
49 dataobj->Add(new wxTextDataObject(), true);
50 dataobj->Add(new wxFileDataObject());
51 }
52 else // type == FILETREE
53 dataobj->Add(new wxFileDataObject(), true);
54
55 SetDataObject(dataobj);
56}
57
70wxDragResult NumeReDropTarget::OnDragOver(wxCoord x, wxCoord y, wxDragResult defaultDragResult)
71{
72 if (m_type == EDITOR)
73 {
74 NumeReEditor* edit = static_cast<NumeReEditor*>(m_owner);
75 defaultDragResult = edit->DoDragOver(x, y, defaultDragResult);
76 }
77 else if (m_type == FILETREE)
78 {
79 this->GetData();
80 wxDataObjectComposite* dataobj = static_cast<wxDataObjectComposite*>(GetDataObject());
81 wxDataFormat format = dataobj->GetReceivedFormat();
82
83 // The file tree won't accept pure text data
84 if (format.GetType() == wxDF_TEXT || format.GetType() == wxDF_UNICODETEXT)
85 return wxDragNone;
86
87 // Find the tree item currently below the cursor
88 FileTree* tree = static_cast<FileTree*>(m_owner);
89 wxTreeItemId currentId = tree->HitTest(wxPoint(x,y));
90
91 // Highlight the item below the cursor
92 if (currentId.IsOk())
93 tree->SetDnDHighlight(currentId);
94 }
95
96 return defaultDragResult;
97}
98
108wxDragResult NumeReDropTarget::OnData(wxCoord x, wxCoord y, wxDragResult defaultDragResult)
109{
110 this->GetData();
111 wxDataObjectComposite* dataobj = static_cast<wxDataObjectComposite*>(GetDataObject());
112 wxDataFormat format = dataobj->GetReceivedFormat();
113 wxDataObject* data = dataobj->GetObject(format);
114
115 // Switch for the dropped file type
116 switch (format.GetType())
117 {
118 case wxDF_FILENAME:
119 {
120 // a plain file
121 wxFileDataObject* filedata = static_cast<wxFileDataObject*>(data);
122 wxArrayString filenames = filedata->GetFilenames();
123
124 NumeReWindow* top = static_cast<NumeReWindow*>(m_topWindow);
125 std::vector<std::string> vPaths = top->getPathDefs();
126
127 // Select the current window type
128 if (m_type == EDITOR)
129 {
130 // Files are opened in the editor, if
131 // it supports this type of file.
132 // clear out the passed filenames
133 for (size_t i = 0; i < filenames.size(); i++)
134 {
135 while (filenames.size()
136 && (getFileType(filenames[i]) == NOTSUPPORTED
137 || getFileType(filenames[i]) == IMAGEFILE
138 || getFileType(filenames[i]) == BINARYFILE)
139 )
140 {
141 filenames.erase(filenames.begin()+i);
142 }
143 }
144
145 // return error, if nothing remained
146 if (!filenames.size())
147 return wxDragNone;
148
149 top->OpenSourceFile(filenames);
150 top->GetCurrentEditor()->SetFocus();
151 }
152 else if (m_type == CONSOLE)
153 {
154 // Files are either executed or loaded to
155 // memory, if dragged onto the console
156 std::string sExecutables;
157 std::string sLoadables;
158
159 // clear out the passed filenames
160 for (size_t i = 0; i < filenames.size(); i++)
161 {
162 while (filenames.size()
163 && (getFileType(filenames[i]) == IMAGEFILE
164 || getFileType(filenames[i]) == NOTSUPPORTED))
165 {
166 filenames.erase(filenames.begin()+i);
167 }
168
169 if (!filenames.size())
170 break;
171
172 // Is the current file a executable file (a script or
173 // a procedure)? Then we'll append it to the list of
174 // executables, which will be executed afterwards
175 if (getFileType(filenames[i]) == EXECUTABLE)
176 {
177 if (sExecutables.length())
178 sExecutables += ";";
179
180 // Is the current file a script or a procedure?
181 if (filenames[i].find(".nscr") != std::string::npos)
182 {
183 std::string sScriptName = replacePathSeparator(filenames[i].ToStdString());
184 sScriptName.erase(sScriptName.rfind(".nscr"));
185
186 if (sScriptName.substr(0, vPaths[SCRIPTPATH].length()) == vPaths[SCRIPTPATH])
187 sScriptName.erase(0, vPaths[SCRIPTPATH].length());
188
189 while (sScriptName.front() == '/')
190 sScriptName.erase(0,1);
191
192 if (sScriptName.find(' ') != std::string::npos)
193 sScriptName = "\"" + sScriptName + "\"";
194
195 sExecutables += "start " + sScriptName;
196 }
197 else
198 {
199 std::string sProcName = replacePathSeparator(filenames[i].ToStdString());
200 sProcName.erase(sProcName.rfind(".nprc"));
201
202 if (sProcName.substr(0, vPaths[PROCPATH].length()) == vPaths[PROCPATH])
203 {
204 sProcName.erase(0, vPaths[PROCPATH].length());
205
206 while (sProcName.front() == '/')
207 sProcName.erase(0,1);
208
209 while (sProcName.find('/') != std::string::npos)
210 sProcName[sProcName.find('/')] = '~';
211 }
212 else
213 sProcName = "'" + sProcName + "'";
214
215 sExecutables += "$" + sProcName + "()";
216 }
217 }
218 else
219 {
220 if (sLoadables.length())
221 sLoadables += ";";
222
223 // This is another file type. We'll add it to the list
224 // of loadable files and try to load it to memory afterwards
225 sLoadables += "load \"" + replacePathSeparator(filenames[i].ToStdString()) + "\" -app -ignore";
226 }
227 }
228
229 // return error, if nothing remained
230 if (!filenames.size())
231 return wxDragNone;
232
233 // Load the files here
234 if (sLoadables.length())
235 top->getTerminal()->pass_command(sLoadables, false);
236
237 // Execute the executable files here
238 if (sExecutables.length())
239 top->getTerminal()->pass_command(sExecutables, false);
240
241 top->getTerminal()->SetFocus();
242 }
243 else if (m_type == FILETREE)
244 {
245 // Files are added to the corresponding
246 // standard paths, if they are dragged
247 // onto the file tree
248 FileTree* tree = static_cast<FileTree*>(m_owner);
249 VersionControlSystemManager manager(top);
250 wxTreeItemId dragdropsource = top->getDragDropSourceItem();
251
252 // Internal drag-drop
253 if (dragdropsource.IsOk() && (static_cast<FileNameTreeData*>(tree->GetItemData(dragdropsource)))->filename == filenames[0])
254 {
255 wxTreeItemId dragdroptarget = tree->HitTest(wxPoint(x,y));
256 wxString pathname = top->getTreeFolderPath(dragdroptarget);
257
258 if (pathname.length())
259 {
260 wxString filename = pathname + "\\" + filenames[0].substr(filenames[0].rfind('\\')+1);
261
262 // Do not drag files on themselves
263 if (wxFileName(filename) == wxFileName(filenames[0]))
264 {
265 tree->SetDnDHighlight(wxTreeItemId());
266 return wxDragNone;
267 }
268
269 // If the current file already has revisions,
270 // add this file operation to the revision and
271 // mirror the operation for the revision file
272 if (manager.hasRevisions(filenames[0]))
273 {
274 std::unique_ptr<FileRevisions> revisions(manager.getRevisions(filenames[0]));
275
276 if (revisions.get())
277 {
278 revisions->moveFile(filenames[0], filename, manager.getRevisionPath(filename));
279 }
280 }
281
282 top->UpdateLocationIfOpen(filenames[0], filename);
283
284 if (wxCopyFile(filenames[0], filename, true))
285 wxRemoveFile(filenames[0]);
286
287 tree->SetDnDHighlight(wxTreeItemId());
288 return defaultDragResult;
289 }
290
291 tree->SetDnDHighlight(wxTreeItemId());
292 return wxDragNone;
293 }
294
295 // check, if file already exists in the location
296 for (size_t i = 0; i < filenames.size(); i++)
297 {
298 while (filenames.size()
299 && getFileType(filenames[i]) == NOTSUPPORTED)
300 {
301 filenames.erase(filenames.begin()+i);
302 }
303
304 if (!filenames.size())
305 return wxDragNone;
306
307 fileType type = getFileType(filenames[i]);
308 std::string sFileName = replacePathSeparator(filenames[i].ToStdString());
309
310 if (type == TEXTFILE || type == BINARYFILE)
311 {
312 // load or savepath
313 // already exists
314 if (sFileName.substr(vPaths[LOADPATH].length()) == vPaths[LOADPATH]
315 || sFileName.substr(vPaths[SAVEPATH].length()) == vPaths[SAVEPATH])
316 continue;
317
318 if (wxFileExists(vPaths[LOADPATH] + sFileName.substr(sFileName.rfind('/')))
319 || wxFileExists(vPaths[SAVEPATH] + sFileName.substr(sFileName.rfind('/'))))
320 continue;
321
322 wxCopyFile(sFileName, vPaths[LOADPATH] + sFileName.substr(sFileName.rfind('/')));
323 }
324 else if (type == EXECUTABLE)
325 {
326 // script or procpath
327 // already exists
328 if (sFileName.substr(vPaths[SCRIPTPATH].length()) == vPaths[SCRIPTPATH]
329 || sFileName.substr(vPaths[PROCPATH].length()) == vPaths[PROCPATH])
330 continue;
331
332 PathID pathID;
333
334 if (sFileName.find(".nscr") != std::string::npos)
335 pathID = SCRIPTPATH;
336 else
337 pathID = PROCPATH;
338
339 if (wxFileExists(vPaths[pathID] + sFileName.substr(sFileName.rfind('/'))))
340 continue;
341
342 wxCopyFile(sFileName, vPaths[pathID] + sFileName.substr(sFileName.rfind('/')));
343 }
344 else if (type == IMAGEFILE)
345 {
346 // script or procpath
347 // already exists
348 if (sFileName.substr(vPaths[PLOTPATH].length()) == vPaths[PLOTPATH])
349 continue;
350
351 PathID pathID = PLOTPATH;
352
353 if (wxFileExists(vPaths[pathID] + sFileName.substr(sFileName.rfind('/'))))
354 continue;
355
356 wxCopyFile(sFileName, vPaths[pathID] + sFileName.substr(sFileName.rfind('/')));
357 }
358 }
359
360 tree->SetDnDHighlight(wxTreeItemId());
361 // if no: copy the file to the fitting location
362 }
363
364 break;
365 }
366 case wxDF_TEXT:
367 case wxDF_UNICODETEXT:
368 {
369 // a selection of text
370 if (m_type == EDITOR)
371 {
372 // Text is copied in the editor at the
373 // selected position
374 wxTextDataObject* textdata = static_cast<wxTextDataObject*>(data);
375 NumeReEditor* edit = static_cast<NumeReEditor*>(m_owner);
376 edit->DoDropText(x, y, textdata->GetText());
377 edit->SetFocus();
378 }
379 else if (m_type == CONSOLE)
380 {
381 // Text is copied into the console at the
382 // current position (not the selected one)
383 wxTextDataObject* textdata = static_cast<wxTextDataObject*>(data);
384 std::string sText = textdata->GetText().ToStdString();
385
386 size_t nQuotes = 0;
387
388 // Replace line comments with block comments, where necessary
389 for (size_t i = 0; i < sText.length(); i++)
390 {
391 if (sText[i] == '"' && (!i || sText[i-1] != '\\'))
392 nQuotes++;
393
394 if (nQuotes % 2)
395 continue;
396
397 if (sText.substr(i, 2) == "##")
398 {
399 size_t p = sText.find('\n', i);
400
401 // The last one does not need any replacement
402 if (p == std::string::npos)
403 break;
404
405 sText[i+1] = '*';
406 sText.insert(p, "*#");
407 i = p+2;
408 }
409 }
410
411 size_t pos, pos2;
412
413 // Replace line continuation markers including their trailing
414 // line breaks with a single whitespace
415 while ((pos = sText.find("\\\\")) != std::string::npos
416 && (pos2 = sText.find_first_not_of(" \t", pos+2)) != std::string::npos
417 && sText[pos2] == '\n')
418 {
419 sText.replace(pos, pos2-pos+1, " ");
420 }
421
422 // Replace line break and tabulator characters,
423 // because they won't be parsed correctly
424 while ((pos = sText.find('\n')) != std::string::npos)
425 {
426 if (pos
427 && sText.find_last_not_of(" \t", pos-1) != std::string::npos
428 && sText[sText.find_last_not_of(" \t", pos-1)] != ';')
429 sText[pos] = ';';
430 else
431 sText[pos] = ' ';
432 }
433
434 while ((pos = sText.find('\t')) != std::string::npos)
435 sText[pos] = ' ';
436
437 NumeReWindow* top = static_cast<NumeReWindow*>(m_topWindow);
438 top->getTerminal()->ProcessInput(sText.length(), sText);
439 top->getTerminal()->SetFocus();
440 defaultDragResult = wxDragCopy;
441 }
442
443 break;
444 }
445 }
446
447 return defaultDragResult;
448}
449
458{
459 if (filename.find('.') == std::string::npos)
460 return NOEXTENSION;
461
462 // Declare the categories containing the
463 // corresponding file extensions
464 static wxString textExtensions = ";txt;dat;log;tex;csv;jdx;jcm;dx;nhlp;nlyt;ndb;nlng;def;ini;hlpidx;m;cpp;hpp;c;h;cxx;hxx;xml;diff;";
465 static wxString binaryExtensions = ";ndat;xls;xlsx;ods;labx;ibw;";
466 static wxString imageExtensions = ";png;gif;jpg;jpeg;bmp;eps;svg;";
467 static wxString execExtensions = ";nscr;nprc;";
468
469 wxString extension = ";"+filename.substr(filename.rfind('.')+1).Lower()+";";
470
471 // Identify the type of the file by its extensions
472 if (textExtensions.find(extension) != std::string::npos)
473 return TEXTFILE;
474
475 if (binaryExtensions.find(extension) != std::string::npos)
476 return BINARYFILE;
477
478 if (imageExtensions.find(extension) != std::string::npos)
479 return IMAGEFILE;
480
481 if (execExtensions.find(extension) != std::string::npos)
482 return EXECUTABLE;
483
484 return NOTSUPPORTED;
485}
486
487#endif //wxUSE_DRAG_AND_DROP
488
This class provides the needed functionalities for the file tree and the symbols tree.
Definition: treedata.hpp:42
void SetDnDHighlight(const wxTreeItemId &itemToHighLight)
Definition: filetree.cpp:37
NumeReDropTarget(wxWindow *topwindow, wxWindow *owner, parentType type)
Constructor. Initializes the data objects, which correspond to the assigned wxWindow.
wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult defaultDragResult)
This method handles the file operations after DragDrop.
fileType getFileType(const wxString &filename)
This method classifies the file type of the passed file type.
wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult defaultDragResult)
This method visualizes the DragDrop effect.
The class of the editor window.
Definition: editor.h:53
void pass_command(const std::string &command, bool isEvent)
Pass the external command to the kernel without printing it to the console.
Definition: terminal.cpp:925
virtual void ProcessInput(int len, const std::string &sData) override
Processes text received from the keybord or clipboard.
Definition: terminal.cpp:2118
This class is the actual NumeRe main frame. The application's logic is implemented here.
Definition: NumeReWindow.h:177
std::vector< std::string > getPathDefs()
This member function returns the standard path definitions as a vector.
void OpenSourceFile(wxArrayString fnames, unsigned int nLine=0, int nOpenFileFlag=OPENFILE_NOTHING)
Opens the given list of source files in the editor.
NumeReEditor * GetCurrentEditor()
Public access method for accessing the currently viewed editor. Does only return a pointer to the top...
wxTreeItemId getDragDropSourceItem()
This member function gets the drag-drop source item, if the source was the file tree.
NumeReTerminal * getTerminal()
Definition: NumeReWindow.h:228
wxString getTreeFolderPath(const wxTreeItemId &itemId)
This member function returns the paths connected to a specific directory in the file tree.
void UpdateLocationIfOpen(const wxFileName &fname, const wxFileName &newFName)
Updates the editor's and notebook's filename location, if it already opened and not modified.
bool hasRevisions(const wxString &currentFile)
This method detects, whether the selected file has revisions.
Definition: vcsmanager.cpp:90
wxString getRevisionPath(const wxString &currentFilePath)
This method returns the path, where the revisions are stored.
Definition: vcsmanager.cpp:39
FileRevisions * getRevisions(const wxString &currentFile)
This method returns the file revisions as pointer.
Definition: vcsmanager.cpp:68
PathID
@ SCRIPTPATH
@ LOADPATH
@ PLOTPATH
@ PROCPATH
@ SAVEPATH
auto format(const std::locale &loc, const CharT *fmt, const Streamable &tp) -> decltype(to_stream(std::declval< std::basic_ostream< CharT > & >(), fmt, tp), std::basic_string< CharT >{})
Definition: date.h:6249
std::string replacePathSeparator(const std::string &)
This function replaces the Windows style path sparators to UNIX style.