622
626
WorkspaceItem res = null;
624
FileSelector fdiag = new FileSelector (GettextCatalog.GetString ("Add to Workspace"));
626
fdiag.SetCurrentFolder (parentWorkspace.BaseDirectory);
627
fdiag.SelectMultiple = false;
628
if (MessageService.RunCustomDialog (fdiag) == (int) Gtk.ResponseType.Ok) {
630
res = AddWorkspaceItem (parentWorkspace, fdiag.Filename);
632
catch (Exception ex) {
633
MessageService.ShowException (ex, GettextCatalog.GetString ("The file '{0}' could not be loaded.", fdiag.Filename));
628
var dlg = new SelectFileDialog () {
629
Action = Gtk.FileChooserAction.Open,
630
CurrentFolder = parentWorkspace.BaseDirectory,
631
SelectMultiple = false,
634
dlg.AddAllFilesFilter ();
635
dlg.DefaultFilter = dlg.AddFilter (GettextCatalog.GetString ("Solution Files"), "*.mds", "*.sln");
639
res = AddWorkspaceItem (parentWorkspace, dlg.SelectedFile);
640
} catch (Exception ex) {
641
MessageService.ShowException (ex, GettextCatalog.GetString ("The file '{0}' could not be loaded.", dlg.SelectedFile));
655
660
public SolutionItem CreateProject (SolutionFolder parentFolder)
657
SolutionItem res = null;
658
662
string basePath = parentFolder != null ? parentFolder.BaseDirectory : null;
659
663
NewProjectDialog npdlg = new NewProjectDialog (parentFolder, false, basePath);
660
MessageService.ShowCustomDialog (npdlg);
664
if (MessageService.ShowCustomDialog (npdlg) == (int)Gtk.ResponseType.Ok)
665
return npdlg.NewItem as SolutionItem;
664
669
public SolutionItem AddSolutionItem (SolutionFolder parentFolder)
666
671
SolutionItem res = null;
668
FileSelector fdiag = new FileSelector (GettextCatalog.GetString ("Add to Solution"));
670
fdiag.SetCurrentFolder (parentFolder.BaseDirectory);
671
fdiag.SelectMultiple = false;
672
if (MessageService.RunCustomDialog (fdiag) == (int) Gtk.ResponseType.Ok) {
674
res = AddSolutionItem (parentFolder, fdiag.Filename);
676
catch (Exception ex) {
677
MessageService.ShowException (ex, GettextCatalog.GetString ("The file '{0}' could not be loaded.", fdiag.Filename));
673
var dlg = new SelectFileDialog () {
674
Action = Gtk.FileChooserAction.Open,
675
CurrentFolder = parentFolder.BaseDirectory,
676
SelectMultiple = false,
679
dlg.AddAllFilesFilter ();
680
dlg.DefaultFilter = dlg.AddFilter (GettextCatalog.GetString ("Project Files"), "*.*proj", "*.mdp");
684
res = AddSolutionItem (parentFolder, dlg.SelectedFile);
685
} catch (Exception ex) {
686
MessageService.ShowException (ex, GettextCatalog.GetString ("The file '{0}' could not be loaded.", dlg.SelectedFile));
1214
1246
return AddFilesToProject (project, files.ToFilePathArray (), targetDirectory);
1249
public IList<ProjectFile> AddFilesToProject (Project project, FilePath[] files, FilePath targetDirectory)
1251
return AddFilesToProject (project, files, targetDirectory, null);
1254
public IList<ProjectFile> AddFilesToProject (Project project, FilePath[] files, FilePath targetDirectory,
1257
Debug.Assert (targetDirectory.CanonicalPath == project.BaseDirectory.CanonicalPath
1258
|| targetDirectory.IsChildPathOf (project.BaseDirectory));
1260
var targetPaths = new FilePath[files.Length];
1261
for (int i = 0; i < files.Length; i++)
1262
targetPaths[i] = targetDirectory.Combine (files[i].FileName);
1264
return AddFilesToProject (project, files, targetPaths, buildAction);
1218
1268
/// Adds files to a project, potentially asking the user whether to move, copy or link the files.
1220
public IList<ProjectFile> AddFilesToProject (Project project, FilePath[] files, FilePath targetDirectory)
1270
public IList<ProjectFile> AddFilesToProject (Project project, FilePath[] files, FilePath[] targetPaths,
1273
Debug.Assert (project != null);
1274
Debug.Assert (files != null);
1275
Debug.Assert (targetPaths != null);
1276
Debug.Assert (files.Length == targetPaths.Length);
1278
AddAction action = AddAction.Copy;
1279
bool applyToAll = true;
1280
bool dialogShown = false;
1223
1282
IProgressMonitor monitor = null;
1225
1284
if (files.Length > 10) {
1230
1289
var newFileList = new List<ProjectFile> ();
1233
foreach (FilePath file in files) {
1291
//project.AddFile (string) does linear search for duplicate file, so instead we use this HashSet and
1292
//and add the ProjectFiles directly. With large project and many files, this should really help perf.
1293
//Also, this is a better check because we handle vpaths and links.
1294
//FIXME: it would be really nice if project.Files maintained these hashmaps
1295
var vpathsInProject = new HashSet<FilePath> (project.Files.Select (pf => pf.ProjectVirtualPath));
1296
var filesInProject = new Dictionary<FilePath,ProjectFile> ();
1297
foreach (var pf in project.Files)
1298
filesInProject [pf.FilePath] = pf;
1302
for (int i = 0; i < files.Length; i++) {
1303
FilePath file = files[i];
1234
1305
if (monitor != null) {
1235
1306
monitor.Log.WriteLine (file);
1236
1307
monitor.Step (1);
1245
//files in the project directory get added directly in their current location without moving/copying
1246
if (file.IsChildPathOf (project.BaseDirectory)) {
1247
newFileList.Add (project.AddFile (file));
1316
FilePath targetPath = targetPaths[i].CanonicalPath;
1317
Debug.Assert (targetPath.IsChildPathOf (project.BaseDirectory));
1319
var vpath = targetPath.ToRelative (project.BaseDirectory);
1320
if (vpathsInProject.Contains (vpath)) {
1321
MessageService.ShowWarning (GettextCatalog.GetString (
1322
"There is a already a file or link in the project with the name '{0}'", vpath));
1326
string fileBuildAction = buildAction;
1327
if (string.IsNullOrEmpty (buildAction))
1328
fileBuildAction = project.GetDefaultBuildAction (file);
1330
//files in the target directory get added directly in their current location without moving/copying
1331
if (file.CanonicalPath == targetPath) {
1332
AddFileToFolder (newFileList, vpathsInProject, filesInProject, file, fileBuildAction);
1251
1336
//for files outside the project directory, we ask the user whether to move, copy or link
1252
var md = new Gtk.MessageDialog (
1253
IdeApp.Workbench.RootWindow,
1254
Gtk.DialogFlags.Modal | Gtk.DialogFlags.DestroyWithParent,
1255
Gtk.MessageType.Question, Gtk.ButtonsType.None,
1256
GettextCatalog.GetString ("The file {0} is outside the project directory. What would you like to do?", file));
1259
Gtk.CheckButton remember = null;
1338
AddExternalFileDialog addExternalDialog = null;
1340
if (!dialogShown || !applyToAll) {
1341
addExternalDialog = new AddExternalFileDialog (file);
1260
1342
if (files.Length > 1) {
1261
remember = new Gtk.CheckButton (GettextCatalog.GetString ("Use the same action for all selected files."));
1262
md.VBox.PackStart (remember, false, false, 0);
1265
const int ACTION_LINK = 3;
1266
const int ACTION_COPY = 1;
1267
const int ACTION_MOVE = 2;
1269
md.AddButton (GettextCatalog.GetString ("_Link"), ACTION_LINK);
1270
md.AddButton (Gtk.Stock.Copy, ACTION_COPY);
1271
md.AddButton (GettextCatalog.GetString ("_Move"), ACTION_MOVE);
1272
md.AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel);
1277
ret = MessageService.RunCustomDialog (md);
1343
addExternalDialog.ApplyToAll = applyToAll;
1344
addExternalDialog.ShowApplyAll = true;
1346
if (file.IsChildPathOf (targetPath.ParentDirectory))
1347
addExternalDialog.ShowKeepOption (file.ParentDirectory.ToRelative (targetPath.ParentDirectory));
1349
if (action == AddAction.Keep)
1350
action = AddAction.Copy;
1351
addExternalDialog.SelectedAction = action;
1356
if (!dialogShown || !applyToAll) {
1357
if (MessageService.RunCustomDialog (addExternalDialog) == (int) Gtk.ResponseType.Cancel) {
1358
project.Files.AddRange (newFileList.Where (f => f != null));
1279
1359
return newFileList;
1280
if (remember != null && remember.Active) action = ret;
1285
var targetName = targetDirectory.Combine (file.FileName);
1287
if (ret == ACTION_LINK) {
1288
var pf = project.AddFile (file);
1289
pf.Link = project.GetRelativeChildPath (targetName);
1361
action = addExternalDialog.SelectedAction;
1362
applyToAll = addExternalDialog.ApplyToAll;
1366
if (action == AddAction.Keep) {
1367
AddFileToFolder (newFileList, vpathsInProject, filesInProject, file, fileBuildAction);
1371
if (action == AddAction.Link) {
1372
//FIXME: MD project system doesn't cope with duplicate includes - project save/load will remove the file
1374
if (filesInProject.TryGetValue (file, out pf)) {
1376
MessageService.ShowWarning (GettextCatalog.GetString (
1377
"The link '{0}' in the project already includes the file '{1}'", link, file));
1381
pf = new ProjectFile (file, fileBuildAction) {
1384
vpathsInProject.Add (pf.ProjectVirtualPath);
1385
filesInProject [pf.FilePath] = pf;
1290
1386
newFileList.Add (pf);
1295
if (MoveCopyFile (file, targetName, ret == ACTION_MOVE))
1296
newFileList.Add (project.AddFile (targetName));
1391
if (!Directory.Exists (targetPath.ParentDirectory))
1392
FileService.CreateDirectory (targetPath.ParentDirectory);
1394
if (MoveCopyFile (file, targetPath, action == AddAction.Move)) {
1395
var pf = new ProjectFile (targetPath, fileBuildAction);
1396
vpathsInProject.Add (pf.ProjectVirtualPath);
1397
filesInProject [pf.FilePath] = pf;
1398
newFileList.Add (pf);
1298
1401
newFileList.Add (null);
1300
1404
catch (Exception ex) {
1301
1405
MessageService.ShowException (ex, GettextCatalog.GetString (
1303
1407
newFileList.Add (null);
1410
if (addExternalDialog != null)
1411
addExternalDialog.Destroy ();
1415
project.Files.AddRange (newFileList.Where (f => f != null));
1310
1416
return newFileList;
1419
void AddFileToFolder (List<ProjectFile> newFileList, HashSet<FilePath> vpathsInProject, Dictionary<FilePath, ProjectFile> filesInProject, FilePath file, string fileBuildAction)
1421
//FIXME: MD project system doesn't cope with duplicate includes - project save/load will remove the file
1423
if (filesInProject.TryGetValue (file, out pf)) {
1425
MessageService.ShowWarning (GettextCatalog.GetString (
1426
"The link '{0}' in the project already includes the file '{1}'", link, file));
1429
pf = new ProjectFile (file, fileBuildAction);
1430
vpathsInProject.Add (pf.ProjectVirtualPath);
1431
filesInProject [pf.FilePath] = pf;
1432
newFileList.Add (pf);
1313
1435
bool MoveCopyFile (string filename, string targetFilename, bool move)
1315
1437
if (filename != targetFilename) {
1637
class OpenDocumentFileProvider: ITextFileProvider
1766
public class TextFileProvider : ITextFileProvider
1768
static TextFileProvider instance = new TextFileProvider ();
1769
public static TextFileProvider Instance {
1779
class ProviderProxy : ITextEditorDataProvider, IEditableTextFile
1781
TextEditorData data;
1782
public ProviderProxy (TextEditorData data)
1787
public TextEditorData GetTextEditorData ()
1792
#region IEditableTextFile implementation
1793
public FilePath Name { get { return data.Document.FileName; } }
1795
public int Length { get { return data.Length; } }
1797
public string GetText (int startPosition, int endPosition)
1799
return data.GetTextBetween (startPosition, endPosition);
1801
public char GetCharAt (int position)
1803
return data.GetCharAt (position);
1806
public int GetPositionFromLineColumn (int line, int column)
1808
return data.Document.LocationToOffset (line, column);
1811
public void GetLineColumnFromPosition (int position, out int line, out int column)
1813
var loc = data.Document.OffsetToLocation (position);
1815
column = loc.Column;
1818
public int InsertText (int position, string text)
1820
int result = data.Insert (position, text);
1821
File.WriteAllText (Name, Text);
1826
public void DeleteText (int position, int length)
1828
data.Remove (position, length);
1829
File.WriteAllText (Name, Text);
1832
public string Text {
1639
1844
public IEditableTextFile GetEditableTextFile (FilePath filePath)
1641
foreach (Document doc in IdeApp.Workbench.Documents) {
1846
foreach (var doc in IdeApp.Workbench.Documents) {
1642
1847
if (doc.FileName == filePath) {
1643
1848
IEditableTextFile ef = doc.GetContent<IEditableTextFile> ();
1644
1849
if (ef != null) return ef;
1853
TextEditorData data = new TextEditorData ();
1854
data.Document.FileName = filePath;
1855
data.Text = File.ReadAllText (filePath);
1856
return new ProviderProxy (data);
1859
public TextEditorData GetTextEditorData (FilePath filePath)
1862
return GetTextEditorData (filePath, out isOpen);
1865
public TextEditorData GetTextEditorData (FilePath filePath, out bool isOpen)
1867
foreach (var doc in IdeApp.Workbench.Documents) {
1868
if (doc.FileName == filePath) {
1874
TextEditorData data = new TextEditorData ();
1875
data.Document.FileName = filePath;
1876
data.Text = File.ReadAllText (filePath);