~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric-updates

« back to all changes in this revision

Viewing changes to src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor/XmlTextEditorExtension.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2009-02-18 08:40:51 UTC
  • mfrom: (1.2.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090218084051-gh8m6ukvokbwj7cf
Tags: 1.9.2+dfsg-1ubuntu1
* Merge from Debian Experimental (LP: #330519), remaining Ubuntu changes:
  + debian/control:
    - Update for Gnome# 2.24
    - Add libmono-cairo1.0-cil to build-deps to fool pkg-config check

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// 
 
2
// XmlTextEditorExtension.cs
 
3
// 
 
4
// Authors:
 
5
//   Matt Ward
 
6
//   Michael Hutchinson <mhutchinson@novell.com>
 
7
// 
 
8
// Copyright:
 
9
//   (C) 2007 Matt Ward
 
10
//   (C) 2008 Novell, Inc (http://www.novell.com)
 
11
// 
 
12
// License:
 
13
//   Derived from LGPL files (Matt Ward)
 
14
//   All code since then is MIT/X11
 
15
 
 
16
using System;
 
17
using System.Linq;
 
18
using System.Collections.Generic;
 
19
using System.Xml;
 
20
using System.Xml.Schema;
 
21
 
 
22
using MonoDevelop.Core;
 
23
using MonoDevelop.Components.Commands;
 
24
using MonoDevelop.Projects.Gui;
 
25
using MonoDevelop.Projects.Gui.Completion;
 
26
using MonoDevelop.Ide.Gui.Content;
 
27
using MonoDevelop.XmlEditor.Completion;
 
28
using MonoDevelop.Xml.StateEngine;
 
29
 
 
30
namespace MonoDevelop.XmlEditor
 
31
{
 
32
        
 
33
        
 
34
        public class XmlTextEditorExtension : MonoDevelop.XmlEditor.Gui.BaseXmlEditorExtension
 
35
        {
 
36
                const string TextXmlMimeType = "text/xml";
 
37
                const string ApplicationXmlMimeType = "application/xml";
 
38
                string stylesheetFileName;
 
39
                XmlSchemaCompletionData defaultSchemaCompletionData;
 
40
                string defaultNamespacePrefix;
 
41
                
 
42
                bool showSchemaAnnotation;
 
43
                
 
44
                public XmlTextEditorExtension() : base ()
 
45
                {
 
46
                }
 
47
                
 
48
                public override bool ExtendsEditor (MonoDevelop.Ide.Gui.Document doc, IEditableTextBuffer editor)
 
49
                {
 
50
                        if (doc == null)
 
51
                                return false;
 
52
                        return IsFileNameHandled (doc.Name);
 
53
                }
 
54
                
 
55
                protected override IEnumerable<string> SupportedExtensions {
 
56
                        get { throw new System.InvalidOperationException (); }
 
57
                }
 
58
 
 
59
                
 
60
                public override void Initialize ()
 
61
                {
 
62
                        base.Initialize ();
 
63
                        XmlEditorAddInOptions.PropertyChanged += XmlEditorPropertyChanged;
 
64
                        XmlSchemaManager.UserSchemaAdded += UserSchemaAdded;
 
65
                        XmlSchemaManager.UserSchemaRemoved += UserSchemaRemoved;
 
66
                        SetInitialValues();
 
67
                        
 
68
                        MonoDevelop.SourceEditor.SourceEditorView view = 
 
69
                                Document.GetContent<MonoDevelop.SourceEditor.SourceEditorView> ();
 
70
                        if (view != null && view.Document.SyntaxMode == null) {
 
71
                                Mono.TextEditor.Highlighting.SyntaxMode mode = 
 
72
                                        Mono.TextEditor.Highlighting.SyntaxModeService.GetSyntaxMode (ApplicationXmlMimeType);
 
73
                                if (mode != null)
 
74
                                        view.Document.SyntaxMode = mode;
 
75
                                else
 
76
                                        LoggingService.LogWarning ("XmlTextEditorExtension could not get SyntaxMode for mimetype '" 
 
77
                                            + ApplicationXmlMimeType + "'.");
 
78
                        }
 
79
                }
 
80
                
 
81
                bool disposed;
 
82
                public override void Dispose()
 
83
                {
 
84
                        if (!disposed) {
 
85
                                disposed = false;
 
86
                                XmlEditorAddInOptions.PropertyChanged -= XmlEditorPropertyChanged;
 
87
                                XmlSchemaManager.UserSchemaAdded -= UserSchemaAdded;
 
88
                                XmlSchemaManager.UserSchemaRemoved -= UserSchemaRemoved;
 
89
                                base.Dispose ();
 
90
                        }
 
91
                }
 
92
                
 
93
                #region Code completion
 
94
                
 
95
                IEditableTextBuffer GetBuffer ()
 
96
                {
 
97
                        IEditableTextBuffer buf = Document.GetContent<IEditableTextBuffer> ();
 
98
                        System.Diagnostics.Debug.Assert (buf != null);
 
99
                        return buf;
 
100
                }
 
101
                
 
102
                XmlElementPath GetCurrentPath ()
 
103
                {
 
104
                        return ConvertPath (Tracker.Engine.Nodes.OfType<XElement> ().Reverse ());
 
105
                }
 
106
                
 
107
                static XmlElementPath ConvertPath (IEnumerable<XElement> path)
 
108
                {
 
109
                        XmlElementPath elementPath = new XmlElementPath ();
 
110
                        var namespaces = new Dictionary<string, string> ();
 
111
                        string defaultNamespace = null;
 
112
                        foreach (XElement el in path) {
 
113
                                foreach (XAttribute att in el.Attributes) {
 
114
                                        if (att.Name.HasPrefix) {
 
115
                                                if (att.Name.Prefix == "xmlns")
 
116
                                                        namespaces [att.Name.Name] = att.Value;
 
117
                                        } else {
 
118
                                                if (att.Name.Name == "xmlns")
 
119
                                                        defaultNamespace = att.Value;
 
120
                                        }
 
121
                                }
 
122
                                string ns = null;
 
123
                                if (el.Name.HasPrefix)
 
124
                                        namespaces.TryGetValue (el.Name.Prefix, out ns);
 
125
                                else
 
126
                                        ns = defaultNamespace;
 
127
                                QualifiedName qn = new QualifiedName (el.Name.Name, ns, el.Name.Prefix ?? String.Empty);
 
128
                                elementPath.Elements.Add (qn);
 
129
                        }
 
130
                        return elementPath;
 
131
                }
 
132
                
 
133
                protected override void GetElementCompletions (CompletionDataList list)
 
134
                {       
 
135
                        XmlElementPath path = GetCurrentPath ();
 
136
                        if (path.Elements.Count > 0) {
 
137
                                XmlSchemaCompletionData schema = FindSchema (path);
 
138
                                if (schema != null) {
 
139
                                        ICompletionData[] completionData = schema.GetChildElementCompletionData (path);
 
140
                                        if (completionData != null)
 
141
                                                list.AddRange (completionData);
 
142
                                }
 
143
                        } else if (defaultSchemaCompletionData != null) {
 
144
                                list.AddRange (defaultSchemaCompletionData.GetElementCompletionData (defaultNamespacePrefix));
 
145
                        }
 
146
                }
 
147
                
 
148
                protected override void GetAttributeCompletions (CompletionDataList list, IAttributedXObject attributedOb, 
 
149
                                                                 Dictionary<string, string> existingAtts)
 
150
                {
 
151
                        XmlElementPath path = GetCurrentPath ();
 
152
                        if (path.Elements.Count > 0) {
 
153
                                XmlSchemaCompletionData schema = FindSchema (path);
 
154
                                if (schema != null) {
 
155
                                        ICompletionData[] completionData = schema.GetAttributeCompletionData (path);
 
156
                                        if (completionData != null)
 
157
                                                list.AddRange (completionData);
 
158
                                }
 
159
                        }
 
160
                }
 
161
                
 
162
                protected override void GetAttributeValueCompletions (CompletionDataList list, IAttributedXObject attributedOb,
 
163
                                                                      XAttribute att)
 
164
                {
 
165
                        XmlElementPath path = GetCurrentPath ();
 
166
                        if (path.Elements.Count > 0) {
 
167
                                XmlSchemaCompletionData schema = FindSchema (path);
 
168
                                if (schema != null) {
 
169
                                        ICompletionData[] completionData = schema.GetAttributeValueCompletionData (path, att.Name.FullName);
 
170
                                        if (completionData != null)
 
171
                                                list.AddRange (completionData);
 
172
                                }
 
173
                        }
 
174
                }
 
175
                
 
176
                #endregion
 
177
                
 
178
                #region From XmlCompletionDataProvider.cs
 
179
                
 
180
                public XmlSchemaCompletionData FindSchemaFromFileName (string fileName)
 
181
                {
 
182
                        return XmlSchemaManager.SchemaCompletionDataItems.GetSchemaFromFileName (fileName);
 
183
                }
 
184
                
 
185
                public XmlSchemaCompletionData FindSchema (string namespaceUri)
 
186
                {
 
187
                        return XmlSchemaManager.SchemaCompletionDataItems[namespaceUri];
 
188
                }
 
189
                
 
190
                public XmlSchemaCompletionData FindSchema (XmlElementPath path)
 
191
                {
 
192
                        return FindSchema (XmlSchemaManager.SchemaCompletionDataItems, path);
 
193
                }
 
194
                
 
195
                /// <summary>
 
196
                /// Finds the schema given the xml element path.
 
197
                /// </summary>
 
198
                public XmlSchemaCompletionData FindSchema (IXmlSchemaCompletionDataCollection schemaCompletionDataItems, XmlElementPath path)
 
199
                {
 
200
                        if (path.Elements.Count > 0) {
 
201
                                string namespaceUri = path.Elements[0].Namespace;
 
202
                                if (namespaceUri.Length > 0) {
 
203
                                        return schemaCompletionDataItems[namespaceUri];
 
204
                                } else if (defaultSchemaCompletionData != null) {
 
205
                                        
 
206
                                        // Use the default schema namespace if none
 
207
                                        // specified in a xml element path, otherwise
 
208
                                        // we will not find any attribute or element matches
 
209
                                        // later.
 
210
                                        foreach (QualifiedName name in path.Elements) {
 
211
                                                if (name.Namespace.Length == 0) {
 
212
                                                        name.Namespace = defaultSchemaCompletionData.NamespaceUri;
 
213
                                                }
 
214
                                        }
 
215
                                        return defaultSchemaCompletionData;
 
216
                                }
 
217
                        }
 
218
                        return null;
 
219
                }
 
220
                
 
221
                #endregion
 
222
                
 
223
                #region Schema resolution
 
224
                
 
225
                /// <summary>
 
226
                /// Gets the XmlSchemaObject that defines the currently selected xml element or attribute.
 
227
                /// </summary>
 
228
                /// <param name="currentSchemaCompletionData">This is the schema completion data for the schema currently being 
 
229
                /// displayed. This can be null if the document is not a schema.</param>
 
230
                public XmlSchemaObject GetSchemaObjectSelected (XmlSchemaCompletionData currentSchemaCompletionData)
 
231
                {
 
232
                        // Find element under cursor.
 
233
                        XmlElementPath path = GetCurrentPath ();
 
234
                        
 
235
                        //attribute name under cursor, if valid
 
236
                        string attributeName = null;
 
237
                        XAttribute xatt = Tracker.Engine.Nodes.Peek (0) as XAttribute;
 
238
                        if (xatt != null) {
 
239
                                XName xattName = xatt.Name;
 
240
                                if (Tracker.Engine.CurrentState is XmlNameState) {
 
241
                                        xattName = GetCompleteName ();
 
242
                                }
 
243
                                attributeName = xattName.FullName;
 
244
                        }
 
245
                        
 
246
                        // Find schema definition object.
 
247
                        XmlSchemaCompletionData schemaCompletionData = FindSchema (path);
 
248
                        XmlSchemaObject schemaObject = null;
 
249
                        if (schemaCompletionData != null) {
 
250
                                XmlSchemaElement element = schemaCompletionData.FindElement(path);
 
251
                                schemaObject = element;
 
252
                                if (element != null) {
 
253
                                        if (attributeName.Length > 0) {
 
254
                                                XmlSchemaAttribute attribute = schemaCompletionData.FindAttribute(element, attributeName);
 
255
                                                if (attribute != null) {
 
256
                                                        if (currentSchemaCompletionData != null) {
 
257
                                                                schemaObject = GetSchemaObjectReferenced (currentSchemaCompletionData, element, attribute);
 
258
                                                        } else {
 
259
                                                                schemaObject = attribute;
 
260
                                                        }
 
261
                                                }
 
262
                                        }
 
263
                                        return schemaObject;
 
264
                                }
 
265
                        }       
 
266
                        return null;
 
267
                }
 
268
                
 
269
                /// <summary>
 
270
                /// If the attribute value found references another item in the schema
 
271
                /// return this instead of the attribute schema object. For example, if the
 
272
                /// user can select the attribute value and the code will work out the schema object pointed to by the ref
 
273
                /// or type attribute:
 
274
                ///
 
275
                /// xs:element ref="ref-name"
 
276
                /// xs:attribute type="type-name"
 
277
                /// </summary>
 
278
                /// <returns>
 
279
                /// The <paramref name="attribute"/> if no schema object was referenced.
 
280
                /// </returns>
 
281
                XmlSchemaObject GetSchemaObjectReferenced (XmlSchemaCompletionData currentSchemaCompletionData, XmlSchemaElement element, XmlSchemaAttribute attribute)
 
282
                {
 
283
                        XmlSchemaObject schemaObject = null;
 
284
                        if (IsXmlSchemaNamespace(element)) {
 
285
                                // Find attribute value.
 
286
                                //fixme implement
 
287
                                string attributeValue = "";// XmlParser.GetAttributeValueAtIndex(xml, index);
 
288
                                if (attributeValue.Length == 0) {
 
289
                                        return attribute;
 
290
                                }
 
291
                
 
292
                                if (attribute.Name == "ref") {
 
293
                                        schemaObject = FindSchemaObjectReference(attributeValue, currentSchemaCompletionData, element.Name);
 
294
                                } else if (attribute.Name == "type") {
 
295
                                        schemaObject = FindSchemaObjectType(attributeValue, currentSchemaCompletionData, element.Name);
 
296
                                }
 
297
                        }
 
298
                        
 
299
                        if (schemaObject != null) {
 
300
                                return schemaObject;
 
301
                        }
 
302
                        return attribute;
 
303
                }
 
304
                
 
305
                /// <summary>
 
306
                /// Checks whether the element belongs to the XSD namespace.
 
307
                /// </summary>
 
308
                static bool IsXmlSchemaNamespace (XmlSchemaElement element)
 
309
                {
 
310
                        XmlQualifiedName qualifiedName = element.QualifiedName;
 
311
                        if (qualifiedName != null) {
 
312
                                return XmlSchemaManager.IsXmlSchemaNamespace (qualifiedName.Namespace);
 
313
                        }
 
314
                        return false;
 
315
                }
 
316
                
 
317
                /// <summary>
 
318
                /// Attempts to locate the reference name in the specified schema.
 
319
                /// </summary>
 
320
                /// <param name="name">The reference to look up.</param>
 
321
                /// <param name="schemaCompletionData">The schema completion data to use to
 
322
                /// find the reference.</param>
 
323
                /// <param name="elementName">The element to determine what sort of reference it is
 
324
                /// (e.g. group, attribute, element).</param>
 
325
                /// <returns><see langword="null"/> if no match can be found.</returns>
 
326
                XmlSchemaObject FindSchemaObjectReference(string name, XmlSchemaCompletionData schemaCompletionData, string elementName)
 
327
                {
 
328
                        QualifiedName qualifiedName = schemaCompletionData.CreateQualifiedName(name);
 
329
                        XmlSchemaCompletionData qualifiedNameSchema = FindSchema(qualifiedName.Namespace);
 
330
                        if (qualifiedNameSchema != null) {
 
331
                                schemaCompletionData = qualifiedNameSchema;
 
332
                        }
 
333
                        switch (elementName) {
 
334
                                case "element":
 
335
                                        return schemaCompletionData.FindElement(qualifiedName);
 
336
                                case "attribute":
 
337
                                        return schemaCompletionData.FindAttribute(qualifiedName.Name);
 
338
                                case "group":
 
339
                                        return schemaCompletionData.FindGroup(qualifiedName.Name);
 
340
                                case "attributeGroup":
 
341
                                        return schemaCompletionData.FindAttributeGroup(qualifiedName.Name);
 
342
                        }
 
343
                        return null;
 
344
                }
 
345
                
 
346
                /// <summary>
 
347
                /// Attempts to locate the type name in the specified schema.
 
348
                /// </summary>
 
349
                /// <param name="name">The type to look up.</param>
 
350
                /// <param name="schemaCompletionData">The schema completion data to use to
 
351
                /// find the type.</param>
 
352
                /// <param name="elementName">The element to determine what sort of type it is
 
353
                /// (e.g. group, attribute, element).</param>
 
354
                /// <returns><see langword="null"/> if no match can be found.</returns>
 
355
                XmlSchemaObject FindSchemaObjectType(string name, XmlSchemaCompletionData schemaCompletionData, string elementName)
 
356
                {
 
357
                        QualifiedName qualifiedName = schemaCompletionData.CreateQualifiedName(name);
 
358
                        XmlSchemaCompletionData qualifiedNameSchema = FindSchema(qualifiedName.Namespace);
 
359
                        if (qualifiedNameSchema != null) {
 
360
                                schemaCompletionData = qualifiedNameSchema;
 
361
                        }
 
362
                        switch (elementName) {
 
363
                                case "element":
 
364
                                        return schemaCompletionData.FindComplexType(qualifiedName);
 
365
                                case "attribute":
 
366
                                        return schemaCompletionData.FindSimpleType(qualifiedName.Name);
 
367
                        }
 
368
                        return null;
 
369
                }
 
370
                
 
371
                #endregion
 
372
                
 
373
                #region Settings handling
 
374
                
 
375
                void SetDefaultSchema (string fileName)
 
376
                {
 
377
                        if (fileName == null) {
 
378
                                return;
 
379
                        }
 
380
                        string extension = System.IO.Path.GetExtension (fileName).ToLower ();
 
381
                        defaultSchemaCompletionData = XmlSchemaManager.GetSchemaCompletionData (extension);
 
382
                        defaultNamespacePrefix = XmlSchemaManager.GetNamespacePrefix (extension);
 
383
                }
 
384
                
 
385
                /// Updates the default schema association since the schema may have been added.
 
386
                void UserSchemaAdded (object source, EventArgs e)
 
387
                {       
 
388
                        SetDefaultSchema (Document.Name);
 
389
                }
 
390
                
 
391
                // Updates the default schema association since the schema may have been removed.
 
392
                void UserSchemaRemoved (object source, EventArgs e)
 
393
                {
 
394
                        SetDefaultSchema (Document.Name);
 
395
                }
 
396
                
 
397
                void XmlEditorPropertyChanged (object sender, PropertyChangedEventArgs args)
 
398
                {
 
399
                        switch (args.Key) {
 
400
                        case "AutoCompleteElements":
 
401
                                AutoCompleteClosingTags = XmlEditorAddInOptions.AutoCompleteElements;
 
402
                                break;
 
403
                        case "ShowSchemaAnnotation":
 
404
                                showSchemaAnnotation = XmlEditorAddInOptions.ShowSchemaAnnotation;
 
405
                                break;
 
406
                        default:
 
407
                                string extension = System.IO.Path.GetExtension (Document.Name).ToLower ();
 
408
                                if (args.Key == extension) {
 
409
                                        SetDefaultSchema (Document.Name);
 
410
                                } else {
 
411
                                        LoggingService.LogError ("Unhandled property change in XmlTextEditorExtension: " + args.Key);
 
412
                                }
 
413
                                break;
 
414
                        }
 
415
                }
 
416
                
 
417
                void SetInitialValues()
 
418
                {
 
419
                        showSchemaAnnotation = XmlEditorAddInOptions.ShowSchemaAnnotation;
 
420
                        AutoCompleteClosingTags = XmlEditorAddInOptions.AutoCompleteElements;
 
421
                        SetDefaultSchema (Document.Name);
 
422
                }
 
423
                
 
424
                #endregion
 
425
                
 
426
                #region Stylesheet handling
 
427
                
 
428
                /// <summary>
 
429
                /// Gets or sets the stylesheet associated with this xml file.
 
430
                /// </summary>
 
431
                public string StylesheetFileName {
 
432
                        get { return stylesheetFileName; }
 
433
                        set { stylesheetFileName = value; }
 
434
                }
 
435
                                                
 
436
                #endregion
 
437
                
 
438
                #region Filetype/schema detection               
 
439
                
 
440
                public bool IsSchema {
 
441
                        get {
 
442
                                string extension = System.IO.Path.GetExtension (FileName);
 
443
                                if (extension != null)
 
444
                                        return String.Compare (extension, ".xsd", true) == 0;
 
445
                                return false;
 
446
                        }
 
447
                }
 
448
                
 
449
                /// <summary>
 
450
                /// Determines whether the file can be displayed by
 
451
                /// the xml editor.
 
452
                /// </summary>
 
453
                public static bool IsFileNameHandled (string fileName)
 
454
                {                       
 
455
                        if (fileName == null)
 
456
                                return false;
 
457
                        
 
458
                        if (System.IO.Path.IsPathRooted (fileName)) {
 
459
                                string vfsname = fileName.Replace ("%", "%25").Replace ("#", "%23").Replace ("?", "%3F");
 
460
                                string mimeType = MonoDevelop.Core.Gui.Services.PlatformService.GetMimeTypeForUri (vfsname);
 
461
                                if (IsMimeTypeHandled (mimeType))
 
462
                                        return true;
 
463
                        }
 
464
                        
 
465
                        return XmlFileExtensions.IsXmlFileExtension (System.IO.Path.GetExtension (fileName));
 
466
                }
 
467
                
 
468
                public static bool IsMimeTypeHandled (string mimeType)
 
469
                {
 
470
                        return (mimeType != null && (mimeType == TextXmlMimeType || mimeType == ApplicationXmlMimeType));
 
471
                }
 
472
                        
 
473
                #endregion
 
474
                
 
475
                #region Smart indent
 
476
                
 
477
                public override bool KeyPress (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
 
478
                {
 
479
                        bool result;
 
480
                        
 
481
                        if (TextEditorProperties.IndentStyle == IndentStyle.Smart && key == Gdk.Key.Return) {
 
482
                                result = base.KeyPress (key, keyChar, modifier);
 
483
                                SmartIndentLine (Editor.CursorLine);
 
484
                                return result;
 
485
                        }
 
486
                        return base.KeyPress (key, keyChar, modifier);
 
487
                }
 
488
                
 
489
                void SmartIndentLine (int line)
 
490
                {
 
491
                        //FIXME: implement this
 
492
                }
 
493
                
 
494
                string GetLineIndent (int line)
 
495
                {
 
496
                        string indent = string.Empty;
 
497
                        int start = Editor.GetPositionFromLineColumn (line, 1);
 
498
                        int i = start;
 
499
                        while (i < Editor.TextLength) {
 
500
                                char c = Editor.GetCharAt (i);
 
501
                                if (c == '\n' || c == '\r')
 
502
                                        break;
 
503
                                if (!char.IsWhiteSpace (c))
 
504
                                        break;
 
505
                                i++;
 
506
                        }
 
507
                        if (i > 0)
 
508
                                indent = Editor.GetText (start, i);
 
509
                        return indent;
 
510
                }
 
511
                
 
512
                //gets the indent of the line containing this position, up to the position index
 
513
                string GetPositionIndent (int position)
 
514
                {
 
515
                        int indentEnd = position;
 
516
                        int i = position - 1;
 
517
                        while (i > 0) {
 
518
                                char c = Editor.GetCharAt (i);
 
519
                                if (c == '\n' || c == '\r')
 
520
                                        return Editor.GetText (i + 1, indentEnd);
 
521
                                if (!char.IsWhiteSpace (c))
 
522
                                        indentEnd--;
 
523
                                i--;
 
524
                        }
 
525
                        return null;
 
526
                }
 
527
                
 
528
                #endregion
 
529
                
 
530
                #region Command handlers
 
531
                
 
532
                [CommandUpdateHandler (MonoDevelop.Ide.Commands.EditCommands.ToggleCodeComment)]
 
533
                protected void ToggleCodeCommentCommandUpdate (CommandInfo info)
 
534
                {
 
535
                        info.Enabled = false;
 
536
                }
 
537
                
 
538
                [CommandHandler (MonoDevelop.Ide.Commands.EditCommands.ToggleCodeComment)]
 
539
                public void ToggleCodeCommentCommand ()
 
540
                {
 
541
                        //FIXME: implement
 
542
                }
 
543
                
 
544
                [CommandHandler (Commands.Format)]
 
545
                public void FormatCommand ()
 
546
                {
 
547
                        MonoDevelop.Ide.Gui.IdeApp.Services.TaskService.ClearExceptCommentTasks ();
 
548
                        
 
549
                        using (IProgressMonitor monitor = XmlEditorService.GetMonitor ()) {
 
550
                                bool selection = (Editor.SelectionEndPosition - Editor.SelectionStartPosition) > 0;
 
551
                                string xml = selection? Editor.SelectedText : Editor.Text;
 
552
                                XmlDocument doc = XmlEditorService.ValidateWellFormedness (monitor, xml, FileName);
 
553
                                if (doc == null)
 
554
                                        return;
 
555
                                
 
556
                                //if there's a line indent at the current location, prepend that to all new lines
 
557
                                string extraIndent = null;
 
558
                                if (selection)
 
559
                                        extraIndent = GetPositionIndent (Editor.SelectionStartPosition);
 
560
                                
 
561
                                string formattedXml = XmlEditorService.IndentedFormat (xml);
 
562
                                
 
563
                                //convert newlines and prepend extra indents to each line if needed
 
564
                                bool nonNativeNewline = (Editor.NewLine != Environment.NewLine);
 
565
                                bool hasExtraIndent = !string.IsNullOrEmpty (extraIndent);
 
566
                                if (hasExtraIndent || nonNativeNewline) {
 
567
                                        System.Text.StringBuilder builder = new System.Text.StringBuilder (formattedXml);
 
568
                                        
 
569
                                        if (nonNativeNewline)
 
570
                                                builder.Replace (Environment.NewLine, Editor.NewLine);
 
571
                                        
 
572
                                        if (hasExtraIndent) {
 
573
                                                builder.Replace (Editor.NewLine, Editor.NewLine + extraIndent);
 
574
                                                if (formattedXml.EndsWith (Environment.NewLine))
 
575
                                                        builder.Remove (builder.Length - 1 - extraIndent.Length, extraIndent.Length);
 
576
                                        }
 
577
                                        formattedXml = builder.ToString ();
 
578
                                }
 
579
                                
 
580
                                Editor.BeginAtomicUndo ();
 
581
                                if (selection) {
 
582
                                        Editor.SelectedText = formattedXml;
 
583
                                } else {
 
584
                                        Editor.DeleteText (0, Editor.TextLength);
 
585
                                        Editor.InsertText (0, formattedXml);
 
586
                                }
 
587
                                Editor.EndAtomicUndo ();
 
588
                        }
 
589
                }
 
590
                
 
591
                [CommandHandler (Commands.CreateSchema)]
 
592
                public void CreateSchemaCommand ()
 
593
                {
 
594
                        try {
 
595
                                MonoDevelop.Ide.Gui.IdeApp.Services.TaskService.ClearExceptCommentTasks ();
 
596
                                string xml = Editor.Text;
 
597
                                using (IProgressMonitor monitor = XmlEditorService.GetMonitor ()) {
 
598
                                        XmlDocument doc = XmlEditorService.ValidateWellFormedness (monitor, xml, FileName);
 
599
                                        if (doc == null)
 
600
                                                return;
 
601
                                        monitor.BeginTask (GettextCatalog.GetString ("Creating schema..."), 0);
 
602
                                        try {
 
603
                                                string schema = XmlEditorService.CreateSchema (xml);
 
604
                                                string fileName = XmlEditorService.GenerateFileName (FileName, "{0}.xsd");
 
605
                                                MonoDevelop.Ide.Gui.IdeApp.Workbench.NewDocument (fileName, "application/xml", schema);
 
606
                                                monitor.ReportSuccess (GettextCatalog.GetString ("Schema created."));
 
607
                                        } catch (Exception ex) {
 
608
                                                string msg = GettextCatalog.GetString ("Error creating XML schema.");
 
609
                                                LoggingService.LogError (msg, ex);
 
610
                                                monitor.ReportError (msg, ex);
 
611
                                        }
 
612
                                }
 
613
                        } catch (Exception ex) {
 
614
                                MonoDevelop.Core.Gui.MessageService.ShowError(ex.Message);
 
615
                        }
 
616
                }
 
617
                
 
618
                [CommandHandler (Commands.OpenStylesheet)]
 
619
                public void OpenStylesheetCommand ()
 
620
                {
 
621
                        if (!string.IsNullOrEmpty (stylesheetFileName)) {
 
622
                                try {
 
623
                                        MonoDevelop.Ide.Gui.IdeApp.Workbench.OpenDocument (stylesheetFileName);
 
624
                                } catch (Exception ex) {
 
625
                                        MonoDevelop.Core.LoggingService.LogError ("Could not open document.", ex);
 
626
                                        MonoDevelop.Core.Gui.MessageService.ShowException (ex, "Could not open document.");
 
627
                                }
 
628
                        }
 
629
                }
 
630
                
 
631
                [CommandUpdateHandler (Commands.OpenStylesheet)]
 
632
                public void UpdateOpenStylesheetCommand (CommandInfo info)
 
633
                {
 
634
                        info.Enabled = !string.IsNullOrEmpty (stylesheetFileName);
 
635
                }
 
636
                
 
637
                [CommandHandler (Commands.GoToSchemaDefinition)]
 
638
                public void GoToSchemaDefinitionCommand ()
 
639
                {
 
640
                        try {
 
641
                                //try to resolve the schema
 
642
                                XmlSchemaCompletionData currentSchemaCompletionData = FindSchemaFromFileName (FileName);                                                
 
643
                                XmlSchemaObject schemaObject = GetSchemaObjectSelected (currentSchemaCompletionData);
 
644
                                
 
645
                                // Open schema if resolved
 
646
                                if (schemaObject != null && schemaObject.SourceUri != null && schemaObject.SourceUri.Length > 0) {
 
647
                                        string schemaFileName = schemaObject.SourceUri.Replace ("file:/", String.Empty);
 
648
                                        MonoDevelop.Ide.Gui.IdeApp.Workbench.OpenDocument (
 
649
                                            schemaFileName,
 
650
                                            Math.Max (1, schemaObject.LineNumber),
 
651
                                            Math.Max (1, schemaObject.LinePosition), true);
 
652
                                }
 
653
                        } catch (Exception ex) {
 
654
                                MonoDevelop.Core.LoggingService.LogError ("Could not open document.", ex);
 
655
                                MonoDevelop.Core.Gui.MessageService.ShowException (ex, "Could not open document.");
 
656
                        }
 
657
                }
 
658
                
 
659
                [CommandHandler (Commands.Validate)]
 
660
                public void ValidateCommand ()
 
661
                {
 
662
                        MonoDevelop.Ide.Gui.IdeApp.Services.TaskService.ClearExceptCommentTasks ();
 
663
                        using (IProgressMonitor monitor = XmlEditorService.GetMonitor()) {
 
664
                                if (IsSchema)
 
665
                                        XmlEditorService.ValidateSchema (monitor, Editor.Text, FileName);
 
666
                                else
 
667
                                        XmlEditorService.ValidateXml (monitor, Editor.Text, FileName);
 
668
                        }
 
669
                }
 
670
                
 
671
                [CommandHandler (Commands.AssignStylesheet)]
 
672
                public void AssignStylesheetCommand ()
 
673
                {
 
674
                        // Prompt user for filename.
 
675
                        string fileName = XmlEditorService.BrowseForStylesheetFile ();
 
676
                        if (!string.IsNullOrEmpty (stylesheetFileName))
 
677
                                stylesheetFileName = fileName;
 
678
                }
 
679
                
 
680
                [CommandHandler (Commands.RunXslTransform)]
 
681
                public void RunXslTransformCommand ()
 
682
                {
 
683
                        if (string.IsNullOrEmpty (stylesheetFileName)) {
 
684
                                stylesheetFileName = XmlEditorService.BrowseForStylesheetFile ();
 
685
                                if (string.IsNullOrEmpty (stylesheetFileName))
 
686
                                        return;
 
687
                        }
 
688
                        
 
689
                        using (IProgressMonitor monitor = XmlEditorService.GetMonitor()) {
 
690
                                try {
 
691
                                        string xsltContent;
 
692
                                        try {
 
693
                                                xsltContent = GetFileContent (stylesheetFileName);      
 
694
                                        } catch (System.IO.IOException) {
 
695
                                                monitor.ReportError (
 
696
                                                    GettextCatalog.GetString ("Error reading file '{0}'.", stylesheetFileName), null);
 
697
                                                return;
 
698
                                        }
 
699
                                        System.Xml.Xsl.XslTransform xslt = 
 
700
                                                XmlEditorService.ValidateStylesheet (monitor, xsltContent, stylesheetFileName);
 
701
                                        if (xslt == null)
 
702
                                                return;
 
703
                                        
 
704
                                        XmlDocument doc = XmlEditorService.ValidateXml (monitor, Editor.Text, FileName);
 
705
                                        if (doc == null)
 
706
                                                return;
 
707
                                        
 
708
                                        string newFileName = XmlEditorService.GenerateFileName (FileName, "-transformed{0}.xml");
 
709
                                        
 
710
                                        monitor.BeginTask (GettextCatalog.GetString ("Executing transform..."), 1);
 
711
                                        using (XmlTextWriter output = XmlEditorService.CreateXmlTextWriter()) {
 
712
                                                xslt.Transform (doc, null, output);
 
713
                                                MonoDevelop.Ide.Gui.IdeApp.Workbench.NewDocument (
 
714
                                                    newFileName, "application/xml", output.ToString ());
 
715
                                        }
 
716
                                        monitor.ReportSuccess (GettextCatalog.GetString ("Transform completed."));
 
717
                                        monitor.EndTask ();
 
718
                                } catch (Exception ex) {
 
719
                                        string msg = GettextCatalog.GetString ("Could not run transform.");
 
720
                                        monitor.ReportError (msg, ex);
 
721
                                        monitor.EndTask ();
 
722
                                }
 
723
                        }
 
724
                }
 
725
                
 
726
                string GetFileContent (string fileName)
 
727
                {
 
728
                        MonoDevelop.Projects.Text.IEditableTextFile tf =
 
729
                                MonoDevelop.DesignerSupport.OpenDocumentFileProvider.Instance.GetEditableTextFile (fileName);
 
730
                        if (tf != null)
 
731
                                return tf.Text;
 
732
                        System.IO.StreamReader reader = new System.IO.StreamReader (fileName, true);
 
733
                        return reader.ReadToEnd();
 
734
                }
 
735
                
 
736
                
 
737
                
 
738
                #endregion
 
739
                
 
740
        }
 
741
}