Browse Source
Added support for "stacked" input handlers. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5065 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
21 changed files with 412 additions and 194 deletions
@ -0,0 +1,83 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Daniel Grunwald"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Linq; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Diagnostics; |
||||||
|
using System.Windows.Input; |
||||||
|
|
||||||
|
using ICSharpCode.AvalonEdit.Document; |
||||||
|
using ICSharpCode.AvalonEdit.Editing; |
||||||
|
|
||||||
|
namespace ICSharpCode.AvalonEdit.Snippets |
||||||
|
{ |
||||||
|
sealed class SnippetInputHandler : ITextAreaInputHandler |
||||||
|
{ |
||||||
|
readonly InsertionContext context; |
||||||
|
|
||||||
|
public SnippetInputHandler(InsertionContext context) |
||||||
|
{ |
||||||
|
this.context = context; |
||||||
|
} |
||||||
|
|
||||||
|
public TextArea TextArea { |
||||||
|
get { return context.TextArea; } |
||||||
|
} |
||||||
|
|
||||||
|
public void Attach() |
||||||
|
{ |
||||||
|
TextArea.PreviewKeyDown += TextArea_PreviewKeyDown; |
||||||
|
|
||||||
|
SelectElement(FindNextEditableElement(-1, false)); |
||||||
|
} |
||||||
|
|
||||||
|
void SelectElement(IActiveElement element) |
||||||
|
{ |
||||||
|
if (element != null) { |
||||||
|
TextArea.Selection = new SimpleSelection(element.Segment); |
||||||
|
TextArea.Caret.Offset = element.Segment.EndOffset; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void Detach() |
||||||
|
{ |
||||||
|
TextArea.PreviewKeyDown -= TextArea_PreviewKeyDown; |
||||||
|
context.Deactivate(EventArgs.Empty); |
||||||
|
} |
||||||
|
|
||||||
|
void TextArea_PreviewKeyDown(object sender, KeyEventArgs e) |
||||||
|
{ |
||||||
|
if (e.Key == Key.Escape || e.Key == Key.Return) { |
||||||
|
context.Deactivate(e); |
||||||
|
e.Handled = true; |
||||||
|
} else if (e.Key == Key.Tab) { |
||||||
|
bool backwards = e.KeyboardDevice.Modifiers == ModifierKeys.Shift; |
||||||
|
SelectElement(FindNextEditableElement(TextArea.Caret.Offset, backwards)); |
||||||
|
e.Handled = true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
IActiveElement FindNextEditableElement(int offset, bool backwards) |
||||||
|
{ |
||||||
|
IEnumerable<IActiveElement> elements = context.ActiveElements.Where(e => e.IsEditable && e.Segment != null); |
||||||
|
if (backwards) { |
||||||
|
elements = elements.Reverse(); |
||||||
|
foreach (IActiveElement element in elements) { |
||||||
|
if (offset > element.Segment.EndOffset) |
||||||
|
return element; |
||||||
|
} |
||||||
|
} else { |
||||||
|
foreach (IActiveElement element in elements) { |
||||||
|
if (offset < element.Segment.Offset) |
||||||
|
return element; |
||||||
|
} |
||||||
|
} |
||||||
|
return elements.FirstOrDefault(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -1,72 +0,0 @@ |
|||||||
// <file>
|
|
||||||
// <copyright see="prj:///doc/copyright.txt"/>
|
|
||||||
// <license see="prj:///doc/license.txt"/>
|
|
||||||
// <owner name="Daniel Grunwald"/>
|
|
||||||
// <version>$Revision$</version>
|
|
||||||
// </file>
|
|
||||||
|
|
||||||
using System; |
|
||||||
|
|
||||||
namespace ICSharpCode.AvalonEdit.Utils |
|
||||||
{ |
|
||||||
interface IFreezable |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe.
|
|
||||||
/// </summary>
|
|
||||||
bool IsFrozen { get; } |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Freezes this instance.
|
|
||||||
/// </summary>
|
|
||||||
void Freeze(); |
|
||||||
} |
|
||||||
|
|
||||||
[Serializable] |
|
||||||
sealed class FreezableNullSafeCollection<T> : NullSafeCollection<T>, IFreezable where T : class, IFreezable |
|
||||||
{ |
|
||||||
bool isFrozen; |
|
||||||
|
|
||||||
public bool IsFrozen { get { return isFrozen; } } |
|
||||||
|
|
||||||
public void Freeze() |
|
||||||
{ |
|
||||||
if (!isFrozen) { |
|
||||||
foreach (T item in this) { |
|
||||||
item.Freeze(); |
|
||||||
} |
|
||||||
isFrozen = true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void CheckBeforeMutation() |
|
||||||
{ |
|
||||||
if (isFrozen) |
|
||||||
throw new InvalidOperationException("Cannot mutate frozen " + GetType().Name); |
|
||||||
} |
|
||||||
|
|
||||||
protected override void ClearItems() |
|
||||||
{ |
|
||||||
this.CheckBeforeMutation(); |
|
||||||
base.ClearItems(); |
|
||||||
} |
|
||||||
|
|
||||||
protected override void InsertItem(int index, T item) |
|
||||||
{ |
|
||||||
this.CheckBeforeMutation(); |
|
||||||
base.InsertItem(index, item); |
|
||||||
} |
|
||||||
|
|
||||||
protected override void RemoveItem(int index) |
|
||||||
{ |
|
||||||
this.CheckBeforeMutation(); |
|
||||||
base.RemoveItem(index); |
|
||||||
} |
|
||||||
|
|
||||||
protected override void SetItem(int index, T item) |
|
||||||
{ |
|
||||||
this.CheckBeforeMutation(); |
|
||||||
base.SetItem(index, item); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue