Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Async/HeuristicLab.ExtLibs/HeuristicLab.AvalonEdit/5.0.1/AvalonEdit-5.0.1/CodeCompletion/CompletionWindow.cs @ 13401

Last change on this file since 13401 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 6.8 KB
Line 
1// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Diagnostics;
21using System.Windows;
22using System.Windows.Controls;
23using System.Windows.Controls.Primitives;
24using System.Windows.Data;
25using System.Windows.Input;
26using System.Windows.Threading;
27using ICSharpCode.AvalonEdit.Document;
28using ICSharpCode.AvalonEdit.Editing;
29
30namespace ICSharpCode.AvalonEdit.CodeCompletion
31{
32  /// <summary>
33  /// The code completion window.
34  /// </summary>
35  public class CompletionWindow : CompletionWindowBase
36  {
37    readonly CompletionList completionList = new CompletionList();
38    ToolTip toolTip = new ToolTip();
39   
40    /// <summary>
41    /// Gets the completion list used in this completion window.
42    /// </summary>
43    public CompletionList CompletionList {
44      get { return completionList; }
45    }
46   
47    /// <summary>
48    /// Creates a new code completion window.
49    /// </summary>
50    public CompletionWindow(TextArea textArea) : base(textArea)
51    {
52      // keep height automatic
53      this.CloseAutomatically = true;
54      this.SizeToContent = SizeToContent.Height;
55      this.MaxHeight = 300;
56      this.Width = 175;
57      this.Content = completionList;
58      // prevent user from resizing window to 0x0
59      this.MinHeight = 15;
60      this.MinWidth = 30;
61     
62      toolTip.PlacementTarget = this;
63      toolTip.Placement = PlacementMode.Right;
64      toolTip.Closed += toolTip_Closed;
65     
66      AttachEvents();
67    }
68   
69    #region ToolTip handling
70    void toolTip_Closed(object sender, RoutedEventArgs e)
71    {
72      // Clear content after tooltip is closed.
73      // We cannot clear is immediately when setting IsOpen=false
74      // because the tooltip uses an animation for closing.
75      if (toolTip != null)
76        toolTip.Content = null;
77    }
78   
79    void completionList_SelectionChanged(object sender, SelectionChangedEventArgs e)
80    {
81      var item = completionList.SelectedItem;
82      if (item == null)
83        return;
84      object description = item.Description;
85      if (description != null) {
86        string descriptionText = description as string;
87        if (descriptionText != null) {
88          toolTip.Content = new TextBlock  {
89            Text = descriptionText,
90            TextWrapping = TextWrapping.Wrap
91          };
92        } else {
93          toolTip.Content = description;
94        }
95        toolTip.IsOpen = true;
96      } else {
97        toolTip.IsOpen = false;
98      }
99    }
100    #endregion
101   
102    void completionList_InsertionRequested(object sender, EventArgs e)
103    {
104      Close();
105      // The window must close before Complete() is called.
106      // If the Complete callback pushes stacked input handlers, we don't want to pop those when the CC window closes.
107      var item = completionList.SelectedItem;
108      if (item != null)
109        item.Complete(this.TextArea, new AnchorSegment(this.TextArea.Document, this.StartOffset, this.EndOffset - this.StartOffset), e);
110    }
111   
112    void AttachEvents()
113    {
114      this.completionList.InsertionRequested += completionList_InsertionRequested;
115      this.completionList.SelectionChanged += completionList_SelectionChanged;
116      this.TextArea.Caret.PositionChanged += CaretPositionChanged;
117      this.TextArea.MouseWheel += textArea_MouseWheel;
118      this.TextArea.PreviewTextInput += textArea_PreviewTextInput;
119    }
120   
121    /// <inheritdoc/>
122    protected override void DetachEvents()
123    {
124      this.completionList.InsertionRequested -= completionList_InsertionRequested;
125      this.completionList.SelectionChanged -= completionList_SelectionChanged;
126      this.TextArea.Caret.PositionChanged -= CaretPositionChanged;
127      this.TextArea.MouseWheel -= textArea_MouseWheel;
128      this.TextArea.PreviewTextInput -= textArea_PreviewTextInput;
129      base.DetachEvents();
130    }
131   
132    /// <inheritdoc/>
133    protected override void OnClosed(EventArgs e)
134    {
135      base.OnClosed(e);
136      if (toolTip != null) {
137        toolTip.IsOpen = false;
138        toolTip = null;
139      }
140    }
141   
142    /// <inheritdoc/>
143    protected override void OnKeyDown(KeyEventArgs e)
144    {
145      base.OnKeyDown(e);
146      if (!e.Handled) {
147        completionList.HandleKey(e);
148      }
149    }
150   
151    void textArea_PreviewTextInput(object sender, TextCompositionEventArgs e)
152    {
153      e.Handled = RaiseEventPair(this, PreviewTextInputEvent, TextInputEvent,
154                                 new TextCompositionEventArgs(e.Device, e.TextComposition));
155    }
156   
157    void textArea_MouseWheel(object sender, MouseWheelEventArgs e)
158    {
159      e.Handled = RaiseEventPair(GetScrollEventTarget(),
160                                 PreviewMouseWheelEvent, MouseWheelEvent,
161                                 new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta));
162    }
163   
164    UIElement GetScrollEventTarget()
165    {
166      if (completionList == null)
167        return this;
168      return completionList.ScrollViewer ?? completionList.ListBox ?? (UIElement)completionList;
169    }
170   
171    /// <summary>
172    /// Gets/Sets whether the completion window should close automatically.
173    /// The default value is true.
174    /// </summary>
175    public bool CloseAutomatically { get; set; }
176   
177    /// <inheritdoc/>
178    protected override bool CloseOnFocusLost {
179      get { return this.CloseAutomatically; }
180    }
181   
182    /// <summary>
183    /// When this flag is set, code completion closes if the caret moves to the
184    /// beginning of the allowed range. This is useful in Ctrl+Space and "complete when typing",
185    /// but not in dot-completion.
186    /// Has no effect if CloseAutomatically is false.
187    /// </summary>
188    public bool CloseWhenCaretAtBeginning { get; set; }
189   
190    void CaretPositionChanged(object sender, EventArgs e)
191    {
192      int offset = this.TextArea.Caret.Offset;
193      if (offset == this.StartOffset) {
194        if (CloseAutomatically && CloseWhenCaretAtBeginning) {
195          Close();
196        } else {
197          completionList.SelectItem(string.Empty);
198        }
199        return;
200      }
201      if (offset < this.StartOffset || offset > this.EndOffset) {
202        if (CloseAutomatically) {
203          Close();
204        }
205      } else {
206        TextDocument document = this.TextArea.Document;
207        if (document != null) {
208          completionList.SelectItem(document.GetText(this.StartOffset, offset - this.StartOffset));
209        }
210      }
211    }
212  }
213}
Note: See TracBrowser for help on using the repository browser.