2
// MonoDevelop XML Editor
4
// Copyright (C) 2004-2007 MonoDevelop Team
8
using System.Collections;
11
using MonoDevelop.Projects;
12
using MonoDevelop.Core;
13
using MonoDevelop.Ide.CodeCompletion;
15
namespace MonoDevelop.XmlEditor
17
public class XmlCompletionListWindow : XmlEditorListWindow, IListDataProvider
19
ICompletionWidget completionWidget;
20
ICodeCompletionContext completionContext;
21
ICompletionData[] completionData;
22
DeclarationViewWindow declarationviewwindow = new DeclarationViewWindow ();
23
ICompletionData currentData;
24
ICompletionDataProvider provider;
25
IMutableCompletionDataProvider mutableProvider;
26
Widget parsingMessage;
28
CompletionDelegate closedDelegate;
30
const int declarationWindowMargin = 3;
31
static DataComparer dataComparer = new DataComparer ();
33
public static event EventHandler WindowClosed;
35
class DataComparer: IComparer
37
public int Compare (object x, object y)
39
ICompletionData d1 = x as ICompletionData;
40
ICompletionData d2 = y as ICompletionData;
41
return String.Compare (d1.Text[0], d2.Text[0], true);
45
static XmlCompletionListWindow wnd;
47
static XmlCompletionListWindow ()
49
wnd = new XmlCompletionListWindow ();
52
internal XmlCompletionListWindow ()
54
SizeAllocated += new SizeAllocatedHandler (ListSizeChanged);
57
public static void ShowWindow (char firstChar, ICompletionDataProvider provider, ICompletionWidget completionWidget, ICodeCompletionContext completionContext, CompletionDelegate closedDelegate)
60
if (!wnd.ShowListWindow (firstChar, provider, completionWidget, completionContext, closedDelegate)) {
65
// makes control-space in midle of words to work
66
string text = wnd.completionWidget.GetCompletionText (completionContext);
67
if (text.Length == 0) {
68
text = provider.DefaultCompletionString;
69
if (text != null && text.Length > 0)
70
wnd.SelectEntry (text);
74
wnd.PartialWord = text;
75
//if there is only one matching result we take it by default
76
if (wnd.IsUniqueMatch && !wnd.IsChanging)
82
} catch (Exception ex) {
83
Console.WriteLine (ex);
87
bool ShowListWindow (char firstChar, ICompletionDataProvider provider, ICompletionWidget completionWidget, ICodeCompletionContext completionContext, CompletionDelegate closedDelegate)
89
if (mutableProvider != null) {
90
mutableProvider.CompletionDataChanging -= OnCompletionDataChanging;
91
mutableProvider.CompletionDataChanged -= OnCompletionDataChanged;
94
this.provider = provider;
95
this.completionContext = completionContext;
96
this.closedDelegate = closedDelegate;
97
mutableProvider = provider as IMutableCompletionDataProvider;
99
if (mutableProvider != null) {
100
mutableProvider.CompletionDataChanging += OnCompletionDataChanging;
101
mutableProvider.CompletionDataChanged += OnCompletionDataChanged;
103
if (mutableProvider.IsChanging)
104
OnCompletionDataChanging (null, null);
107
this.completionWidget = completionWidget;
108
this.firstChar = firstChar;
115
completionData = provider.GenerateCompletionData (completionWidget, firstChar);
116
if ((completionData == null || completionData.Length == 0) && !IsChanging)
119
this.Style = completionWidget.GtkStyle;
121
if (completionData == null)
122
completionData = new ICompletionData [0];
124
Array.Sort (completionData, dataComparer);
128
int x = completionContext.TriggerXCoord;
129
int y = completionContext.TriggerYCoord;
132
GetSize (out w, out h);
134
if ((x + w) > Screen.Width)
135
x = Screen.Width - w;
137
if ((y + h) > Screen.Height)
139
y = y - completionContext.TriggerTextHeight - h;
146
// HACK - make window bigger for namespace completion.
147
// This should probably be handled by the ListWidget/ListWindow
149
if (firstChar == '=') {
150
this.Resize(this.List.WidthRequest + 220, this.List.HeightRequest);
155
public static void HideWindow ()
161
/// Modified this method so that punctuation characters
162
/// will not close the completion window.
164
public static bool ProcessKeyEvent (Gdk.EventKey e)
166
if (!wnd.Visible) return false;
168
XmlEditorListWindow.KeyAction ka = wnd.ProcessKey (e);
170
if ((ka & XmlEditorListWindow.KeyAction.CloseWindow) != 0) {
171
if (e.Key == Gdk.Key.Escape || e.Key == Gdk.Key.BackSpace || !System.Char.IsPunctuation((char)e.KeyValue)) {
176
if ((ka & XmlEditorListWindow.KeyAction.Complete) != 0) {
180
case Gdk.Key.ISO_Enter:
181
case Gdk.Key.Key_3270_Enter:
182
case Gdk.Key.KP_Enter:
191
if ((ka & XmlEditorListWindow.KeyAction.Ignore) != 0)
194
if ((ka & XmlEditorListWindow.KeyAction.Process) != 0) {
195
if (e.Key == Gdk.Key.Left) {
196
if (wnd.declarationviewwindow.Multiple) {
197
wnd.declarationviewwindow.OverloadLeft ();
198
wnd.UpdateDeclarationView ();
201
} else if (e.Key == Gdk.Key.Right) {
202
if (wnd.declarationviewwindow.Multiple) {
203
wnd.declarationviewwindow.OverloadRight ();
204
wnd.UpdateDeclarationView ();
214
/// HACK - Insert the completion string not the text displayed in the
215
/// completion list and move the cursor between the attribute
216
/// quotes when an attribute is inserted.
217
/// This should really be done using methods in the
218
/// ICompletionWidget class. Here I am cheating and using
219
/// the XmlEditorView and XmlCompletionData directly (The
220
/// XmlCompletionData.InsertAction is not used in MonoDevelop).
222
// void UpdateWord ()
224
// XmlCompletionData data = (XmlCompletionData)completionData[List.Selection];
226
// string completeWord = data.CompletionString;
227
// completionWidget.SetCompletionText(completionContext, wnd.PartialWord, completeWord);
228
// if (data.XmlCompletionDataType == XmlCompletionData.DataType.XmlAttribute) {
229
// // Position cursor inside attribute value string.
230
// XmlEditorView view = (XmlEditorView)completionWidget;
231
// TextIter iter = view.Buffer.GetIterAtMark(view.Buffer.InsertMark);
233
// view.Buffer.PlaceCursor(iter);
235
// //completionWidget.SetCompletionText(wnd.PartialWord, wnd.CompleteWord);
240
string word = wnd.CompleteWord;
242
if (wnd.Selection != -1) {
243
IActionCompletionData ac = completionData [wnd.Selection] as IActionCompletionData;
245
ac.InsertAction (completionWidget, completionContext);
249
completionWidget.SetCompletionText (completionContext, wnd.PartialWord, word);
253
public new void Hide ()
256
declarationviewwindow.HideAll ();
257
if (provider != null) {
261
if (closedDelegate != null) {
263
closedDelegate = null;
267
protected override bool IsValidCompletionChar (char c)
269
return XmlParser.IsXmlNameChar(c);
272
void ListSizeChanged (object obj, SizeAllocatedArgs args)
274
UpdateDeclarationView ();
277
protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
279
bool ret = base.OnButtonPressEvent (evnt);
280
if (evnt.Button == 1 && evnt.Type == Gdk.EventType.TwoButtonPress) {
287
protected override void OnSelectionChanged ()
289
base.OnSelectionChanged ();
290
UpdateDeclarationView ();
293
void UpdateDeclarationView ()
295
if (completionData == null || List.Selection >= completionData.Length || List.Selection == -1)
298
if (List.GdkWindow == null) return;
299
Gdk.Rectangle rect = List.GetRowArea (List.Selection);
300
int listpos_x = 0, listpos_y = 0;
301
while (listpos_x == 0 || listpos_y == 0)
302
GetPosition (out listpos_x, out listpos_y);
303
int vert = listpos_y + rect.Y;
305
int lvWidth = 0, lvHeight = 0;
307
this.GdkWindow.GetSize (out lvWidth, out lvHeight);
308
if (vert >= listpos_y + lvHeight - 2) {
309
vert = listpos_y + lvHeight - rect.Height;
310
} else if (vert < listpos_y) {
314
ICompletionData data = completionData[List.Selection];
315
ICompletionDataWithMarkup datawMarkup = data as ICompletionDataWithMarkup;
316
XmlCompletionData ccdata = (XmlCompletionData) data;
318
string descMarkup = datawMarkup != null ? datawMarkup.DescriptionPango : data.Description;
320
declarationviewwindow.Hide ();
322
if (data != currentData) {
323
declarationviewwindow.Clear ();
324
declarationviewwindow.Realize ();
326
declarationviewwindow.AddOverload (descMarkup);
328
//foreach (CodeCompletionData odata in ccdata.GetOverloads ()) {
329
// ICompletionDataWithMarkup odatawMarkup = odata as ICompletionDataWithMarkup;
330
// declarationviewwindow.AddOverload (odatawMarkup == null ? odata.Description : odatawMarkup.DescriptionPango);
336
if (declarationviewwindow.DescriptionMarkup.Length == 0)
339
int dvwWidth, dvwHeight;
341
declarationviewwindow.Move (this.Screen.Width+1, vert);
343
declarationviewwindow.SetFixedWidth (-1);
344
declarationviewwindow.ReshowWithInitialSize ();
345
declarationviewwindow.ShowAll ();
346
//declarationviewwindow.Multiple = (ccdata.Overloads != 0);
348
declarationviewwindow.GdkWindow.GetSize (out dvwWidth, out dvwHeight);
350
int horiz = listpos_x + lvWidth + declarationWindowMargin;
351
if (this.Screen.Width - horiz >= lvWidth) {
352
if (this.Screen.Width - horiz < dvwWidth)
353
declarationviewwindow.SetFixedWidth (this.Screen.Width - horiz);
355
if (listpos_x - dvwWidth - declarationWindowMargin < 0) {
356
declarationviewwindow.SetFixedWidth (listpos_x - declarationWindowMargin);
357
dvwWidth = declarationviewwindow.SizeRequest ().Width;
359
horiz = listpos_x - dvwWidth - declarationWindowMargin;
362
declarationviewwindow.Move (horiz, vert);
367
get { return completionData.Length; }
370
public string GetText (int n)
372
return completionData[n].Text[0];
375
public string GetCompletionText (int n)
377
return completionData[n].CompletionString;
380
public Gdk.Pixbuf GetIcon (int n)
382
return RenderIcon (completionData[n].Image, Gtk.IconSize.Menu, "");
385
internal bool IsChanging {
386
get { return mutableProvider != null && mutableProvider.IsChanging; }
389
void OnCompletionDataChanging (object s, EventArgs args)
391
if (parsingMessage == null) {
392
VBox box = new VBox ();
393
box.PackStart (new Gtk.HSeparator (), false, false, 0);
394
HBox hbox = new HBox ();
395
hbox.BorderWidth = 3;
396
hbox.PackStart (new Gtk.Image ("md-parser", Gtk.IconSize.Menu), false, false, 0);
397
Gtk.Label lab = new Gtk.Label (GettextCatalog.GetString ("Gathering class information..."));
399
hbox.PackStart (lab, true, true, 3);
401
parsingMessage = hbox;
403
wnd.ShowFooter (parsingMessage);
406
void OnCompletionDataChanged (object s, EventArgs args)
416
public delegate void CompletionDelegate ();
b'\\ No newline at end of file'