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

« back to all changes in this revision

Viewing changes to src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ExtensibleTextEditor.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
// ExtendibleTextEditor.cs
 
2
//
 
3
// Author:
 
4
//   Mike Krüger <mkrueger@novell.com>
 
5
//
 
6
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
 
7
//
 
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
9
// of this software and associated documentation files (the "Software"), to deal
 
10
// in the Software without restriction, including without limitation the rights
 
11
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
12
// copies of the Software, and to permit persons to whom the Software is
 
13
// furnished to do so, subject to the following conditions:
 
14
//
 
15
// The above copyright notice and this permission notice shall be included in
 
16
// all copies or substantial portions of the Software.
 
17
//
 
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
23
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
24
// THE SOFTWARE.
 
25
 
 
26
using System;
 
27
using System.Collections.Generic;
 
28
using System.IO;
 
29
using System.Text;
 
30
using System.ComponentModel;
 
31
 
 
32
using Gtk;
 
33
 
 
34
using Mono.TextEditor;
 
35
using MonoDevelop.Core;
 
36
using MonoDevelop.Ide.Gui;
 
37
using MonoDevelop.Ide.Gui.Content;
 
38
using MonoDevelop.Projects.Dom;
 
39
using MonoDevelop.Projects.Dom.Parser;
 
40
using MonoDevelop.Projects.Gui.Completion;
 
41
using MonoDevelop.Components.Commands;
 
42
using Mono.TextEditor.Highlighting;
 
43
using MonoDevelop.Ide.CodeTemplates;
 
44
using Mono.Addins;
 
45
 
 
46
namespace MonoDevelop.SourceEditor
 
47
{
 
48
        public class ExtensibleTextEditor : Mono.TextEditor.TextEditor
 
49
        {
 
50
                ITextEditorExtension extension = null;
 
51
                SourceEditorView view;
 
52
                Dictionary<int, ErrorMarker> errors;
 
53
                
 
54
                Gdk.Point menuPopupLocation;
 
55
                
 
56
                public ITextEditorExtension Extension {
 
57
                        get {
 
58
                                return extension;
 
59
                        }
 
60
                        set {
 
61
                                extension = value;
 
62
                        }
 
63
                }
 
64
                
 
65
                public new ISourceEditorOptions Options {
 
66
                        get { return (ISourceEditorOptions)base.Options; }
 
67
                }
 
68
                
 
69
                public ExtensibleTextEditor (SourceEditorView view, ISourceEditorOptions options, Mono.TextEditor.Document doc) : base (doc, null)
 
70
                {
 
71
                        base.Options = options;
 
72
                        Initialize (view);
 
73
                }
 
74
                
 
75
                public ExtensibleTextEditor (SourceEditorView view)
 
76
                {
 
77
                        base.Options = new StyledSourceEditorOptions (view.Project);
 
78
                        Initialize (view);
 
79
                }
 
80
                
 
81
                internal SourceEditorView View {
 
82
                        get { return view; }
 
83
                }
 
84
 
 
85
                internal Dictionary<int, ErrorMarker> Errors {
 
86
                        get { return errors; }
 
87
                        set { errors = value; }
 
88
                }
 
89
                
 
90
                void Initialize (SourceEditorView view)
 
91
                {
 
92
                        this.view = view;
 
93
                        Caret.PositionChanged += delegate {
 
94
                                if (extension != null) {
 
95
                                        try {
 
96
                                                extension.CursorPositionChanged ();
 
97
                                        } catch (Exception ex) {
 
98
                                                ReportExtensionError (ex);
 
99
                                        }
 
100
                                }
 
101
                        };
 
102
                        Document.TextReplaced += delegate (object sender, ReplaceEventArgs args) {
 
103
                                if (extension != null) {
 
104
                                        try {
 
105
                                                extension.TextChanged (args.Offset, 
 
106
                                                    args.Offset + Math.Max (args.Count, args.Value != null ? args.Value.Length : 0));
 
107
                                        } catch (Exception ex) {
 
108
                                                ReportExtensionError (ex);
 
109
                                        }
 
110
                                }
 
111
                        };
 
112
                        
 
113
                        UpdateEditMode ();
 
114
                        
 
115
                        this.ButtonPressEvent += OnPopupMenu;
 
116
 
 
117
                        AddinManager.AddExtensionNodeHandler ("MonoDevelop/SourceEditor2/TooltipProviders", OnTooltipProviderChanged);
 
118
                }
 
119
                
 
120
                void UpdateEditMode ()
 
121
                {
 
122
                        if (Options.UseViModes) {
 
123
                                if (!(CurrentMode is IdeViMode))
 
124
                                        CurrentMode = new IdeViMode (this);
 
125
                        } else {
 
126
                //              if (!(CurrentMode is SimpleEditMode)){
 
127
                                        SimpleEditMode simpleMode = new SimpleEditMode ();
 
128
                                        simpleMode.KeyBindings [EditMode.GetKeyCode (Gdk.Key.Tab)] = new TabAction (this).Action;
 
129
                                        simpleMode.KeyBindings [EditMode.GetKeyCode (Gdk.Key.BackSpace)] = EditActions.AdvancedBackspace;
 
130
                                        CurrentMode = simpleMode;
 
131
                //              }
 
132
                        }
 
133
                }
 
134
 
 
135
                protected override void OnDestroyed ()
 
136
                {
 
137
                        extension = null;
 
138
                        view = null;
 
139
                        this.ButtonPressEvent -= OnPopupMenu;
 
140
                        AddinManager.RemoveExtensionNodeHandler  ("MonoDevelop/SourceEditor2/TooltipProviders", OnTooltipProviderChanged);
 
141
                        base.OnDestroyed ();
 
142
                }
 
143
                
 
144
                void OnTooltipProviderChanged (object s, ExtensionNodeEventArgs a)
 
145
                {
 
146
                        if (a.Change == ExtensionChange.Add) {
 
147
                                TooltipProviders.Add ((ITooltipProvider) a.ExtensionObject);
 
148
                        } else {
 
149
                                TooltipProviders.Remove ((ITooltipProvider) a.ExtensionObject);
 
150
                        }
 
151
                }
 
152
 
 
153
                void OnPopupMenu (object sender, Gtk.ButtonPressEventArgs args)
 
154
                {
 
155
                        if (args.Event.Button == 3) {
 
156
                                int textEditorXOffset = (int)args.Event.X - this.TextViewMargin.XOffset;
 
157
                                if (textEditorXOffset < 0)
 
158
                                        return;
 
159
                                this.menuPopupLocation = new Gdk.Point ((int)args.Event.X, (int)args.Event.Y);
 
160
                                DocumentLocation loc= this.TextViewMargin.VisualToDocumentLocation (textEditorXOffset, (int)args.Event.Y);
 
161
                                if (!this.IsSomethingSelected || !this.SelectionRange.Contains (Document.LocationToOffset (loc)))
 
162
                                        Caret.Location = loc;
 
163
                                
 
164
                                this.ShowPopup ();
 
165
                                base.ResetMouseState ();
 
166
                        }
 
167
                }
 
168
                
 
169
                public void FireOptionsChange ()
 
170
                {
 
171
                        this.OptionsChanged (null, null);
 
172
                }
 
173
                
 
174
                protected override void OptionsChanged (object sender, EventArgs args)
 
175
                {
 
176
                        if (view.Control != null) {
 
177
                                ((SourceEditorWidget)view.Control).ShowClassBrowser = Options.EnableQuickFinder;
 
178
                                if (!Options.ShowFoldMargin)
 
179
                                        this.Document.ClearFoldSegments ();
 
180
                        }
 
181
                        UpdateEditMode ();
 
182
                        base.OptionsChanged (sender, args);
 
183
                }
 
184
                
 
185
                protected override bool OnKeyPressEvent (Gdk.EventKey evnt)
 
186
                {
 
187
                        // Handle keyboard menu popup
 
188
                        if (evnt.Key == Gdk.Key.Menu || (evnt.Key == Gdk.Key.F10 && (evnt.State & Gdk.ModifierType.ShiftMask) == Gdk.ModifierType.ShiftMask)) {
 
189
                                this.menuPopupLocation = this.TextViewMargin.LocationToDisplayCoordinates (this.Caret.Location);
 
190
                                this.menuPopupLocation.Y += this.TextViewMargin.LineHeight;
 
191
                                this.ShowPopup ();
 
192
                                return true;
 
193
                        }
 
194
                        
 
195
                        // Handle keyboard toolip popup
 
196
/*                      if ((evnt.Key == Gdk.Key.F1 && (evnt.State & Gdk.ModifierType.ControlMask) == Gdk.ModifierType.ControlMask)) {
 
197
                                Gdk.Point p = this.TextViewMargin.LocationToDisplayCoordinates (this.Caret.Location);
 
198
                                this.mx = p.X;
 
199
                                this.my = p.Y;
 
200
                                this.ShowTooltip ();
 
201
                                return true;
 
202
                        }
 
203
*/                      
 
204
                        return base.OnKeyPressEvent (evnt);
 
205
                }
 
206
                
 
207
                bool ExtensionKeyPress (Gdk.Key key, char ch, Gdk.ModifierType state)
 
208
                {
 
209
                        try {
 
210
                                return extension.KeyPress (key, ch, state);
 
211
                        } catch (Exception ex) {
 
212
                                ReportExtensionError (ex);
 
213
                        }
 
214
                        return false;
 
215
                }
 
216
                
 
217
                void ReportExtensionError (Exception ex) 
 
218
                {
 
219
                        MonoDevelop.Core.LoggingService.LogError ("Error in text editor extension chain", ex);
 
220
                        MonoDevelop.Core.Gui.MessageService.ShowException (ex, "Error in text editor extension chain");
 
221
                }
 
222
                
 
223
                IEnumerable<char> TextWithoutCommentsAndStrings {
 
224
                        get {
 
225
                                bool isInString = false, isInChar = false;
 
226
                                bool isInLineComment  = false, isInBlockComment = false;
 
227
                                
 
228
                                for (int pos = 0; pos < Document.Length; pos++) {
 
229
                                        char ch = Document.GetCharAt (pos);
 
230
                                        switch (ch) {
 
231
                                                case '\r':
 
232
                                                case '\n':
 
233
                                                        isInLineComment = false;
 
234
                                                        break;
 
235
                                                case '/':
 
236
                                                        if (isInBlockComment) {
 
237
                                                                if (pos > 0 && Document.GetCharAt (pos - 1) == '*') 
 
238
                                                                        isInBlockComment = false;
 
239
                                                        } else  if (!isInString && !isInChar && pos + 1 < Document.Length) {
 
240
                                                                char nextChar = Document.GetCharAt (pos + 1);
 
241
                                                                if (nextChar == '/')
 
242
                                                                        isInLineComment = true;
 
243
                                                                if (!isInLineComment && nextChar == '*')
 
244
                                                                        isInBlockComment = true;
 
245
                                                        }
 
246
                                                        break;
 
247
                                                case '"':
 
248
                                                        if (!(isInChar || isInLineComment || isInBlockComment)) 
 
249
                                                                isInString = !isInString;
 
250
                                                        break;
 
251
                                                case '\'':
 
252
                                                        if (!(isInString || isInLineComment || isInBlockComment)) 
 
253
                                                                isInChar = !isInChar;
 
254
                                                        break;
 
255
                                                default :
 
256
                                                        if (!(isInString || isInChar || isInLineComment || isInBlockComment))
 
257
                                                                yield return ch;
 
258
                                                        break;
 
259
                                        }
 
260
                                }
 
261
                        }
 
262
                }
 
263
                        
 
264
                protected override bool OnIMProcessedKeyPressEvent (Gdk.EventKey evnt, char ch)
 
265
                {
 
266
                        bool result = true;
 
267
                        if (evnt.Key == Gdk.Key.Escape) {
 
268
                                bool b;
 
269
                                if (extension != null)
 
270
                                        b = ExtensionKeyPress (evnt.Key, ch, evnt.State);
 
271
                                else
 
272
                                        b = base.OnIMProcessedKeyPressEvent (evnt, ch);
 
273
                                if (b) {
 
274
                                        view.SourceEditorWidget.RemoveSearchWidget ();
 
275
                                        return true;
 
276
                                }
 
277
                                return false;
 
278
                        }
 
279
                        
 
280
                        
 
281
                        if (Document == null)
 
282
                                return true;
 
283
                        
 
284
                        bool inStringOrComment = false;
 
285
                        LineSegment line = Document.GetLine (Caret.Line);
 
286
                        if (line == null)
 
287
                                return true;
 
288
                        Stack<Span> stack = line.StartSpan != null ? new Stack<Span> (line.StartSpan) : new Stack<Span> ();
 
289
                        SyntaxModeService.ScanSpans (Document, Document.SyntaxMode, stack, line.Offset, Caret.Offset);
 
290
                        foreach (Span span in stack) {
 
291
                                if (span.Color == "comment" || span.Color == "literal") {
 
292
                                        inStringOrComment = true;
 
293
                                        break;
 
294
                                }
 
295
                        }
 
296
                        
 
297
                        Document.BeginAtomicUndo ();
 
298
                        
 
299
                        // insert template when space is typed (currently disabled - it's annoying).
 
300
                        bool templateInserted = false; //!inStringOrComment && (evnt.Key == Gdk.Key.space) && DoInsertTemplate ();
 
301
                        bool returnBetweenBraces =
 
302
                                evnt.Key == Gdk.Key.Return
 
303
                                && (evnt.State & (Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)) == Gdk.ModifierType.None
 
304
                                && Caret.Offset > 0
 
305
                                && Caret.Offset < Document.Length
 
306
                                && Document.GetCharAt (Caret.Offset - 1) == '{'
 
307
                                && Document.GetCharAt (Caret.Offset)     == '}'
 
308
                                && !inStringOrComment;
 
309
                        int initialOffset = Caret.Offset;
 
310
                        if (extension != null) {
 
311
                                if (ExtensionKeyPress (evnt.Key, ch, evnt.State)) 
 
312
                                        result = base.OnIMProcessedKeyPressEvent (evnt, ch);
 
313
                                if (returnBetweenBraces) {
 
314
                                        Caret.Offset = initialOffset;
 
315
                                        ExtensionKeyPress (Gdk.Key.Return, (char)0, Gdk.ModifierType.None);
 
316
                                }                       
 
317
                        } else {
 
318
                                result = base.OnIMProcessedKeyPressEvent (evnt, ch);
 
319
                                if (returnBetweenBraces) {
 
320
                                        Caret.Offset = initialOffset;
 
321
                                        base.SimulateKeyPress (Gdk.Key.Return, 0, Gdk.ModifierType.None);
 
322
                                }
 
323
                        }
 
324
/* auto insert templates IS annoying !!!
 
325
                        // auto insert templates
 
326
                        if (!templateInserted &&
 
327
                            Options.AutoInsertTemplates && 
 
328
                            ch != '\0' && // don't auto insert templates for control keys
 
329
                            IsTemplateKnown () // only insert templates when there is a 100% match (ex.: scw vs. scwl)
 
330
                            ) {
 
331
                                templateInserted = !inStringOrComment && DoInsertTemplate ();
 
332
                        }*/
 
333
                        if (templateInserted) {
 
334
                                Document.EndAtomicUndo ();
 
335
                                return true;
 
336
                        }
 
337
                                
 
338
                        if (Options.AutoInsertMatchingBracket && !inStringOrComment && MonoDevelop.Ide.Gui.TextEditor.IsOpenBrace (ch)) {
 
339
                                char closingBrace = MonoDevelop.Ide.Gui.TextEditor.GetMatchingBrace (ch);
 
340
                                int count = 0;
 
341
                                foreach (char curCh in TextWithoutCommentsAndStrings) {
 
342
                                        if (curCh == ch) {
 
343
                                                count++;
 
344
                                        } else if (curCh == closingBrace) {
 
345
                                                count--;
 
346
                                        }
 
347
                                }
 
348
                                if (count > 0) {
 
349
                                        string openBrackets = "{[('\"";
 
350
                                        if (openBrackets.Contains (ch.ToString()))
 
351
                                                Document.Insert (Caret.Offset, closingBrace.ToString());
 
352
                                }
 
353
                        }
 
354
                        Document.EndAtomicUndo ();
 
355
                        return result;
 
356
                }
 
357
                
 
358
                internal string GetErrorInformationAt (int offset)
 
359
                {
 
360
                        ErrorMarker error;
 
361
                        DocumentLocation location = Document.OffsetToLocation (offset);
 
362
                        if (errors.TryGetValue (location.Line, out error)) {
 
363
                                if (error.Info.ErrorType == ErrorType.Warning)
 
364
                                        return GettextCatalog.GetString ("<b>Parser Warning</b>: {0}",
 
365
                                                                         GLib.Markup.EscapeText (error.Info.Message));
 
366
                                else
 
367
                                        return GettextCatalog.GetString ("<b>Parser Error</b>: {0}",
 
368
                                                                         GLib.Markup.EscapeText (error.Info.Message));
 
369
                        }
 
370
                        else
 
371
                                return null;
 
372
                }
 
373
                
 
374
                public ProjectDom ProjectDom {
 
375
                        get {
 
376
                                ProjectDom result = null;
 
377
                                MonoDevelop.Ide.Gui.Document doc = IdeApp.Workbench.ActiveDocument;
 
378
                                if (doc != null || doc.Project == null) 
 
379
                                        result = ProjectDomService.GetProjectDom (doc.Project);
 
380
                                
 
381
                                if (result == null)
 
382
                                        result = ProjectDomService.GetFileDom (View.ContentName);
 
383
                                
 
384
                                return result;
 
385
                        }
 
386
                }
 
387
                
 
388
                int           oldOffset = -1;
 
389
                ResolveResult resolveResult = null;
 
390
                public ResolveResult GetLanguageItem (int offset)
 
391
                {
 
392
                        string txt = this.Document.Text;
 
393
                        string fileName = view.ContentName ?? view.UntitledName;
 
394
                        
 
395
                        // we'll cache old results.
 
396
                        if (offset == oldOffset)
 
397
                                return this.resolveResult;
 
398
                        oldOffset = offset;
 
399
                        
 
400
                        this.resolveResult = null;
 
401
                        MonoDevelop.Ide.Gui.Document doc = IdeApp.Workbench.ActiveDocument;
 
402
                        if (doc == null)
 
403
                                return null;
 
404
                        
 
405
                        IParser parser = ProjectDomService.GetParser (fileName, Document.MimeType);
 
406
                        if (parser == null)
 
407
                                return null;
 
408
 
 
409
                        ProjectDom        dom      = this.ProjectDom;
 
410
                        IResolver         resolver = parser.CreateResolver (dom, doc, fileName);
 
411
                        IExpressionFinder expressionFinder = parser.CreateExpressionFinder (dom);
 
412
                        if (resolver == null || expressionFinder == null) 
 
413
                                return null;
 
414
                        int wordEnd = offset;
 
415
                        while (wordEnd < txt.Length && (Char.IsLetterOrDigit (txt[wordEnd]) || txt[wordEnd] == '_'))
 
416
                                wordEnd++;
 
417
                        ExpressionResult expressionResult = expressionFinder.FindExpression (txt, wordEnd);
 
418
                        if (expressionResult == null)
 
419
                                return null;
 
420
                        DocumentLocation loc = Document.OffsetToLocation (offset);
 
421
                        this.resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line + 1, loc.Column + 1));
 
422
                        
 
423
                        if (this.resolveResult == null || this.resolveResult.ResolvedType == null || String.IsNullOrEmpty (this.resolveResult.ResolvedType.Name)) {
 
424
                                if (expressionResult.ExpressionContext == ExpressionContext.Attribute) {
 
425
                                        expressionResult.Expression += "Attribute";
 
426
                                        expressionResult.ExpressionContext = ExpressionContext.ObjectCreation;
 
427
                                        this.resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line + 1, loc.Column + 1));
 
428
                                } else {
 
429
                                        int j = Document.LocationToOffset (expressionResult.Region.End.Line - 1, expressionResult.Region.End.Column - 1);
 
430
                                        int bracket = 0;
 
431
                                        for (int i = j; i >= 0 && i < Document.Length; i++) {
 
432
                                                char ch = Document.GetCharAt (i);
 
433
                                                if (Char.IsWhiteSpace (ch))
 
434
                                                        continue;
 
435
                                                if (ch == '<') {
 
436
                                                        bracket++;
 
437
                                                } else if (ch == '>') {
 
438
                                                        bracket--;
 
439
                                                        if (bracket == 0) {
 
440
                                                                expressionResult.Expression += Document.GetTextBetween (j, i + 1);
 
441
                                                                expressionResult.ExpressionContext = ExpressionContext.ObjectCreation;
 
442
                                                                this.resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line + 1, loc.Column + 1));
 
443
                                                                break;
 
444
                                                        }
 
445
                                                } else {
 
446
                                                        if (bracket == 0)
 
447
                                                                break;
 
448
                                                }
 
449
                                        }
 
450
                                }
 
451
                        }
 
452
                        
 
453
                        return this.resolveResult;
 
454
                }
 
455
 
 
456
                public string GetExpression (int offset)
 
457
                {
 
458
                        string fileName = View.ContentName;
 
459
                        if (fileName == null)
 
460
                                fileName = View.UntitledName;
 
461
                        
 
462
                        IExpressionFinder expressionFinder = ProjectDomService.GetExpressionFinder (fileName);
 
463
                        string expression = expressionFinder == null ? GetExpressionBeforeOffset (offset) : expressionFinder.FindFullExpression (Document.Text, offset).Expression;
 
464
                        
 
465
                        if (expression == null)
 
466
                                return string.Empty;
 
467
                        else
 
468
                                return expression.Trim ();
 
469
                }
 
470
                
 
471
                string GetExpressionBeforeOffset (int offset)
 
472
                {
 
473
                        int start = offset;
 
474
                        while (start > 0 && IsIdChar (Document.GetCharAt (start)))
 
475
                                start--;
 
476
                        while (offset < Document.Length && IsIdChar (Document.GetCharAt (offset)))
 
477
                                offset++;
 
478
                        start++;
 
479
                        if (offset - start > 0 && start < Document.Length)
 
480
                                return Document.GetTextAt (start, offset - start);
 
481
                        else
 
482
                                return string.Empty;
 
483
                }
 
484
                
 
485
                bool IsIdChar (char c)
 
486
                {
 
487
                        return char.IsLetterOrDigit (c) || c == '_';
 
488
                }
 
489
                
 
490
                protected override bool OnFocusOutEvent (Gdk.EventFocus evnt)
 
491
                {
 
492
                        CompletionWindowManager.HideWindow ();
 
493
                        ParameterInformationWindowManager.HideWindow ();
 
494
                        return base.OnFocusOutEvent (evnt); 
 
495
                }
 
496
                
 
497
                protected override bool OnScrollEvent (Gdk.EventScroll evnt)
 
498
                {
 
499
                        CompletionWindowManager.HideWindow ();
 
500
                        ParameterInformationWindowManager.HideWindow ();
 
501
                        return base.OnScrollEvent (evnt);
 
502
                }
 
503
                
 
504
                void ShowPopup ()
 
505
                {
 
506
                        HideTooltip ();
 
507
                        CommandEntrySet cset = IdeApp.CommandService.CreateCommandEntrySet ("/MonoDevelop/SourceEditor2/ContextMenu/Editor");
 
508
                        Gtk.Menu menu = IdeApp.CommandService.CreateMenu (cset);
 
509
                        menu.Append (new SeparatorMenuItem ());
 
510
                        menu.Append (CreateInputMethodMenuItem (GettextCatalog.GetString ("_Input Methods")));
 
511
                        
 
512
                        menu.Destroyed += delegate {
 
513
                                this.QueueDraw ();
 
514
                        };
 
515
                        
 
516
                        menu.Popup (null, null, new Gtk.MenuPositionFunc (PositionPopupMenu), 0, Gtk.Global.CurrentEventTime);
 
517
                }
 
518
                
 
519
                void PositionPopupMenu (Menu menu, out int x, out int y, out bool pushIn) 
 
520
                {
 
521
                        this.GdkWindow.GetOrigin (out x, out y);
 
522
                        x += this.menuPopupLocation.X;
 
523
                        y += this.menuPopupLocation.Y;
 
524
                        pushIn = true;
 
525
                }
 
526
                
 
527
//              protected override void OnPopulatePopup (Menu menu)
 
528
//              {
 
529
//                      
 
530
//                      CommandEntrySet cset = IdeApp.CommandService.CreateCommandEntrySet ("");
 
531
//                      if (cset.Count > 0) {
 
532
//                              cset.AddItem (Command.Separator);
 
533
//                              IdeApp.CommandService.InsertOptions (menu, cset, 0);
 
534
//                      }
 
535
//                      base.OnPopulatePopup (menu);
 
536
//              }
 
537
//              
 
538
                
 
539
#region Templates
 
540
                int FindPrevWordStart (int offset)
 
541
                {
 
542
                        while (--offset >= 0 && !Char.IsWhiteSpace (Document.GetCharAt (offset))) 
 
543
                                ;
 
544
                        return ++offset;
 
545
                }
 
546
 
 
547
                public string GetWordBeforeCaret ()
 
548
                {
 
549
                        int offset = this.Caret.Offset;
 
550
                        int start  = FindPrevWordStart (offset);
 
551
                        return Document.GetTextAt (start, offset - start);
 
552
                }
 
553
                
 
554
                public bool IsTemplateKnown ()
 
555
                {
 
556
                        string word = GetWordBeforeCaret ();
 
557
                        
 
558
                        CodeTemplateGroup templateGroup = CodeTemplateService.GetTemplateGroupPerFilename (this.view.ContentName);
 
559
                        if (String.IsNullOrEmpty (word) || templateGroup == null) 
 
560
                                return false;
 
561
                        
 
562
                        bool result = false;
 
563
                        foreach (CodeTemplate template in templateGroup.Templates) {
 
564
                                if (template.Shortcut == word) {
 
565
                                        result = true;
 
566
                                } else if (template.Shortcut.StartsWith (word)) {
 
567
                                        result = false;
 
568
                                        break;
 
569
                                }
 
570
                        }
 
571
                        return result;
 
572
                }
 
573
                
 
574
                public bool DoInsertTemplate ()
 
575
                {
 
576
                        string word = GetWordBeforeCaret ();
 
577
                        CodeTemplateGroup templateGroup = CodeTemplateService.GetTemplateGroupPerFilename (this.view.ContentName);
 
578
                        if (String.IsNullOrEmpty (word) || templateGroup == null) 
 
579
                                return false;
 
580
                        
 
581
                        foreach (CodeTemplate template in templateGroup.Templates) {
 
582
                                if (template.Shortcut == word) {
 
583
                                        InsertTemplate (template);
 
584
                                        return true;
 
585
                                }
 
586
                        }
 
587
                        return false;
 
588
                }
 
589
                
 
590
                public void InsertTemplate (CodeTemplate template)
 
591
                {
 
592
                        template.InsertTemplate (MonoDevelop.Ide.Gui.TextEditor.GetTextEditor (this.view));
 
593
                }               
 
594
#endregion
 
595
                
 
596
#region Key bindings
 
597
 
 
598
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.LineEnd)]
 
599
                internal void OnLineEnd ()
 
600
                {
 
601
                        RunAction (CaretMoveActions.LineEnd);
 
602
                }
 
603
                
 
604
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.LineStart)]
 
605
                internal void OnLineStart ()
 
606
                {
 
607
                        RunAction (CaretMoveActions.LineHome);
 
608
                }
 
609
                
 
610
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.DeleteLeftChar)]
 
611
                internal void OnDeleteLeftChar ()
 
612
                {
 
613
                        RunAction (DeleteActions.Backspace);
 
614
                }
 
615
                
 
616
                [CommandHandler (MonoDevelop.Ide.Commands.EditCommands.Delete)]
 
617
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.DeleteRightChar)]
 
618
                internal void OnDeleteRightChar ()
 
619
                {
 
620
                        RunAction (DeleteActions.Delete);
 
621
                }
 
622
                
 
623
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.CharLeft)]
 
624
                internal void OnCharLeft ()
 
625
                {
 
626
                        RunAction (CaretMoveActions.Left);
 
627
                }
 
628
                
 
629
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.CharRight)]
 
630
                internal void OnCharRight ()
 
631
                {
 
632
                        RunAction (CaretMoveActions.Right);
 
633
                }
 
634
                
 
635
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.LineUp)]
 
636
                internal void OnLineUp ()
 
637
                {
 
638
                        RunAction (CaretMoveActions.Up);
 
639
                }
 
640
                
 
641
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.LineDown)]
 
642
                internal void OnLineDown ()
 
643
                {
 
644
                        RunAction (CaretMoveActions.Down);
 
645
                }
 
646
                
 
647
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.DocumentStart)]
 
648
                internal void OnDocumentStart ()
 
649
                {
 
650
                        RunAction (CaretMoveActions.ToDocumentStart);
 
651
                }
 
652
                
 
653
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.DocumentEnd)]
 
654
                internal void OnDocumentEnd ()
 
655
                {
 
656
                        RunAction (CaretMoveActions.ToDocumentEnd);
 
657
                }
 
658
                
 
659
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.PageUp)]
 
660
                internal void OnPageUp ()
 
661
                {
 
662
                        RunAction (CaretMoveActions.PageUp);
 
663
                }
 
664
                
 
665
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.PageDown)]
 
666
                internal void OnPageDown ()
 
667
                {
 
668
                        RunAction (CaretMoveActions.PageDown);
 
669
                }
 
670
                
 
671
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.DeleteLine)]
 
672
                internal void OnDeleteLine ()
 
673
                {
 
674
                        RunAction (DeleteActions.CaretLine);
 
675
                }
 
676
                
 
677
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.DeleteToLineEnd)]
 
678
                internal void OnDeleteToLineEnd ()
 
679
                {
 
680
                        RunAction (DeleteActions.CaretLineToEnd);
 
681
                }
 
682
                
 
683
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.ScrollLineUp)]
 
684
                internal void OnScrollLineUp ()
 
685
                {
 
686
                        RunAction (ScrollActions.Up);
 
687
                }
 
688
                
 
689
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.ScrollLineDown)]
 
690
                internal void OnScrollLineDown ()
 
691
                {
 
692
                        RunAction (ScrollActions.Down);
 
693
                }
 
694
 
 
695
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.GotoMatchingBrace)]
 
696
                internal void OnGotoMatchingBrace ()
 
697
                {
 
698
                        RunAction (MiscActions.GotoMatchingBracket);
 
699
                }
 
700
 
 
701
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMoveLeft)]
 
702
                internal void OnSelectionMoveLeft ()
 
703
                {
 
704
                        RunAction (SelectionActions.MoveLeft);
 
705
                }
 
706
 
 
707
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMoveRight)]
 
708
                internal void OnSelectionMoveRight ()
 
709
                {
 
710
                        RunAction (SelectionActions.MoveRight);
 
711
                }
 
712
 
 
713
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.MovePrevWord)]
 
714
                internal void OnMovePrevWord ()
 
715
                {
 
716
                        RunAction (CaretMoveActions.PreviousWord);
 
717
                }
 
718
 
 
719
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.MoveNextWord)]
 
720
                internal void OnMoveNextWord ()
 
721
                {
 
722
                        RunAction (CaretMoveActions.NextWord);
 
723
                }
 
724
 
 
725
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMovePrevWord)]
 
726
                internal void OnSelectionMovePrevWord ()
 
727
                {
 
728
                        RunAction (SelectionActions.MovePreviousWord);
 
729
                }
 
730
 
 
731
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMoveNextWord)]
 
732
                internal void OnSelectionMoveNextWord ()
 
733
                {
 
734
                        RunAction (SelectionActions.MoveNextWord);
 
735
                }
 
736
 
 
737
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMoveUp)]
 
738
                internal void OnSelectionMoveUp ()
 
739
                {
 
740
                        RunAction (SelectionActions.MoveUp);
 
741
                }
 
742
 
 
743
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMoveDown)]
 
744
                internal void OnSelectionMoveDown ()
 
745
                {
 
746
                        RunAction (SelectionActions.MoveDown);
 
747
                }
 
748
 
 
749
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMoveHome)]
 
750
                internal void OnSelectionMoveHome ()
 
751
                {
 
752
                        RunAction (SelectionActions.MoveLineHome);
 
753
                }
 
754
 
 
755
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMoveEnd)]
 
756
                internal void OnSelectionMoveEnd ()
 
757
                {
 
758
                        RunAction (SelectionActions.MoveLineEnd);
 
759
                }
 
760
 
 
761
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMoveToDocumentStart)]
 
762
                internal void OnSelectionMoveToDocumentStart ()
 
763
                {
 
764
                        RunAction (SelectionActions.MoveToDocumentStart);
 
765
                }
 
766
 
 
767
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionMoveToDocumentEnd)]
 
768
                internal void OnSelectionMoveToDocumentEnd ()
 
769
                {
 
770
                        RunAction (SelectionActions.MoveToDocumentEnd);
 
771
                }
 
772
 
 
773
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SwitchCaretMode)]
 
774
                internal void OnSwitchCaretMode ()
 
775
                {
 
776
                        RunAction (MiscActions.SwitchCaretMode);
 
777
                }
 
778
 
 
779
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.InsertTab)]
 
780
                internal void OnInsertTab ()
 
781
                {
 
782
                        RunAction (MiscActions.InsertTab);
 
783
                }
 
784
 
 
785
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.RemoveTab)]
 
786
                internal void OnRemoveTab ()
 
787
                {
 
788
                        RunAction (MiscActions.RemoveTab);
 
789
                }
 
790
 
 
791
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.InsertNewLine)]
 
792
                internal void OnInsertNewLine ()
 
793
                {
 
794
                        RunAction (MiscActions.InsertNewLine);
 
795
                }
 
796
 
 
797
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.DeletePrevWord)]
 
798
                internal void OnDeletePrevWord ()
 
799
                {
 
800
                        RunAction (DeleteActions.PreviousWord);
 
801
                }
 
802
 
 
803
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.DeleteNextWord)]
 
804
                internal void OnDeleteNextWord ()
 
805
                {
 
806
                        RunAction (DeleteActions.NextWord);
 
807
                }
 
808
 
 
809
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionPageDownAction)]
 
810
                internal void OnSelectionPageDownAction ()
 
811
                {
 
812
                        RunAction (SelectionActions.MovePageDown);
 
813
                }
 
814
 
 
815
                [CommandHandler (MonoDevelop.Ide.Commands.TextEditorCommands.SelectionPageUpAction)]
 
816
                internal void OnSelectionPageUpAction ()
 
817
                {
 
818
                        RunAction (SelectionActions.MovePageUp);
 
819
                }
 
820
                
 
821
#endregion
 
822
                
 
823
        }
 
824
}