Browse Source

IMementoCapable support is back.

AvalonEdit: Fixed some focus issues; fixed crash when control is allowed to grow to infinite size.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3918 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
bc400c5dd9
  1. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs
  2. 22
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  3. 7
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindow.cs
  4. 0
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/ICompletionData.cs
  5. 7
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/Caret.cs
  6. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/Layer.cs
  7. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextArea.cs
  8. 17
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.cs
  9. 10
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.xaml
  10. 15
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextView.cs
  11. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  12. 16
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs
  13. 78
      src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs
  14. 2
      src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.xaml
  15. 8
      src/Main/Base/Project/Src/TextEditor/Gui/Editor/CodeCompletionBinding.cs
  16. 2
      src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs

@ -130,7 +130,7 @@ namespace CSharpBinding @@ -130,7 +130,7 @@ namespace CSharpBinding
ctrlSpaceProvider.ShowTemplates = true;
ctrlSpaceProvider.AllowCompleteExistingExpression = afterUnderscore;
ctrlSpaceProvider.ShowCompletion(editor);
return CodeCompletionKeyPressResult.Completed;
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
}
}
}

22
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -86,15 +86,25 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -86,15 +86,25 @@ namespace ICSharpCode.AvalonEdit.AddIn
void TextArea_TextInput(object sender, TextCompositionEventArgs e)
{
// don't start new code completion if there is still a completion window open
if (completionWindow != null)
return;
foreach (char c in e.Text) {
foreach (ICodeCompletionBinding cc in CodeCompletionBindings) {
CompletionWindow oldCompletionWindow = lastCompletionWindow;
CodeCompletionKeyPressResult result = cc.HandleKeyPress(textEditorAdapter, c);
if (result == CodeCompletionKeyPressResult.Completed) {
if (lastCompletionWindow != null && lastCompletionWindow != oldCompletionWindow) {
if (completionWindow != null) {
// a new CompletionWindow was shown, but does not eat the input
// tell it to expect the text insertion
lastCompletionWindow.ExpectInsertionBeforeStart = true;
completionWindow.ExpectInsertionBeforeStart = true;
}
return;
} else if (result == CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion) {
if (completionWindow != null) {
if (completionWindow.StartOffset == completionWindow.EndOffset) {
completionWindow.CloseWhenCaretAtBeginning = true;
}
}
return;
} else if (result == CodeCompletionKeyPressResult.EatKey) {
@ -105,12 +115,12 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -105,12 +115,12 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
CompletionWindow lastCompletionWindow;
CompletionWindow completionWindow;
internal void NotifyCompletionWindowOpened(CompletionWindow window)
{
lastCompletionWindow = window;
window.Closed += delegate { lastCompletionWindow = null; };
completionWindow = window;
window.Closed += delegate { completionWindow = null; };
}
}
}

7
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindow.cs

@ -16,6 +16,7 @@ using System.Windows.Media; @@ -16,6 +16,7 @@ using System.Windows.Media;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Gui;
using System.Windows.Threading;
namespace ICSharpCode.AvalonEdit.CodeCompletion
{
@ -39,6 +40,9 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -39,6 +40,9 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
this.SizeToContent = SizeToContent.Height;
this.Width = 200;
this.Content = completionList;
// prevent user from resizing window to 0x0
this.MinHeight = 15;
this.MinWidth = 30;
toolTip.PlacementTarget = this;
toolTip.Placement = PlacementMode.Right;
@ -161,7 +165,8 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -161,7 +165,8 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
public void Detach()
{
this.TextArea.DefaultInputHandler.Detach();
window.Close();
// close with dispatcher so we don't get reentrance problems in input handler Detach/Attach
window.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(window.Close));
}
}
#endregion

0
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/ICodeCompletionData.cs → src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/ICompletionData.cs

7
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/Caret.cs

@ -273,6 +273,7 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -273,6 +273,7 @@ namespace ICSharpCode.AvalonEdit.Gui
/// </summary>
public void Show()
{
Debug.WriteLine("Caret.Show()");
visible = true;
if (!showScheduled) {
showScheduled = true;
@ -285,6 +286,11 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -285,6 +286,11 @@ namespace ICSharpCode.AvalonEdit.Gui
void ShowInternal()
{
showScheduled = false;
// if show was scheduled but caret hidden in the meantime
if (!visible)
return;
if (caretAdorner != null && textView != null) {
VisualLine visualLine = textView.GetVisualLine(position.Line);
if (visualLine != null) {
@ -300,6 +306,7 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -300,6 +306,7 @@ namespace ICSharpCode.AvalonEdit.Gui
/// </summary>
public void Hide()
{
Debug.WriteLine("Caret.Hide()");
visible = false;
if (caretAdorner != null) {
caretAdorner.Hide();

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/Layer.cs

@ -25,6 +25,7 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -25,6 +25,7 @@ namespace ICSharpCode.AvalonEdit.Gui
Debug.Assert(textView != null);
this.textView = textView;
this.knownLayer = knownLayer;
this.Focusable = false;
}
protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters)

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextArea.cs

@ -41,8 +41,6 @@ namespace ICSharpCode.AvalonEdit @@ -41,8 +41,6 @@ namespace ICSharpCode.AvalonEdit
typeof(TextArea), new FrameworkPropertyMetadata(KeyboardNavigationMode.None));
FocusableProperty.OverrideMetadata(
typeof(TextArea), new FrameworkPropertyMetadata(Boxes.True));
FocusVisualStyleProperty.OverrideMetadata(
typeof(TextArea), new FrameworkPropertyMetadata(null));
}
/// <summary>
@ -581,7 +579,6 @@ namespace ICSharpCode.AvalonEdit @@ -581,7 +579,6 @@ namespace ICSharpCode.AvalonEdit
{
base.OnGotKeyboardFocus(e);
caret.Show();
e.Handled = true;
}
/// <inheritdoc/>
@ -589,7 +586,6 @@ namespace ICSharpCode.AvalonEdit @@ -589,7 +586,6 @@ namespace ICSharpCode.AvalonEdit
{
base.OnLostKeyboardFocus(e);
caret.Hide();
e.Handled = true;
}
#endregion

17
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.cs

@ -36,8 +36,8 @@ namespace ICSharpCode.AvalonEdit @@ -36,8 +36,8 @@ namespace ICSharpCode.AvalonEdit
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TextEditor),
new FrameworkPropertyMetadata(typeof(TextEditor)));
KeyboardNavigation.IsTabStopProperty.OverrideMetadata(
typeof(TextEditor), new FrameworkPropertyMetadata(Boxes.False));
FocusableProperty.OverrideMetadata(typeof(TextEditor),
new FrameworkPropertyMetadata(Boxes.True));
}
/// <summary>
@ -45,6 +45,17 @@ namespace ICSharpCode.AvalonEdit @@ -45,6 +45,17 @@ namespace ICSharpCode.AvalonEdit
/// </summary>
public TextEditor() : this(new TextArea()) {}
// Forward focus to TextArea.
/// <inheritdoc/>
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
base.OnGotKeyboardFocus(e);
if (!this.TextArea.IsKeyboardFocusWithin) {
Keyboard.Focus(this.TextArea);
e.Handled = true;
}
}
/// <summary>
/// Creates a new TextEditor instance.
/// </summary>
@ -103,7 +114,7 @@ namespace ICSharpCode.AvalonEdit @@ -103,7 +114,7 @@ namespace ICSharpCode.AvalonEdit
/// Options property.
/// </summary>
public static readonly DependencyProperty OptionsProperty
= TextEditor.OptionsProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(OnOptionsChanged));
= TextView.OptionsProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(OnOptionsChanged));
/// <summary>
/// Gets/Sets the options currently used by the text editor.

10
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.xaml

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
<Setter.Value>
<ControlTemplate TargetType="{x:Type AvalonEdit:TextEditor}">
<ScrollViewer
Focusable="False"
Name="PART_ScrollViewer"
CanContentScroll="True"
VerticalScrollBarVisibility="Visible"
@ -32,11 +33,13 @@ @@ -32,11 +33,13 @@
</Style>
<Style TargetType="{x:Type AvalonEdit:TextArea}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type AvalonEdit:TextArea}">
<DockPanel>
<DockPanel Focusable="False">
<ItemsControl DockPanel.Dock="Left"
Focusable="False"
ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LeftMargins}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
@ -44,7 +47,10 @@ @@ -44,7 +47,10 @@
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ContentPresenter Panel.ZIndex="-1" Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TextView}"/>
<ContentPresenter
Panel.ZIndex="-1"
Focusable="False"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TextView}"/>
</DockPanel>
</ControlTemplate>
</Setter.Value>

15
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextView.cs

@ -42,6 +42,7 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -42,6 +42,7 @@ namespace ICSharpCode.AvalonEdit.Gui
static TextView()
{
ClipToBoundsProperty.OverrideMetadata(typeof(TextView), new FrameworkPropertyMetadata(Boxes.True));
FocusableProperty.OverrideMetadata(typeof(TextView), new FrameworkPropertyMetadata(Boxes.False));
}
/// <summary>
@ -545,6 +546,10 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -545,6 +546,10 @@ namespace ICSharpCode.AvalonEdit.Gui
/// <inheritdoc/>
protected override Size MeasureOverride(Size availableSize)
{
// We don't support infinite available width, so we'll limit it to 32000 pixels.
if (availableSize.Width > 32000)
availableSize.Width = 32000;
if (!canHorizontallyScroll && !availableSize.Width.IsClose(lastAvailableSize.Width))
ClearVisualLines();
lastAvailableSize = availableSize;
@ -575,11 +580,11 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -575,11 +580,11 @@ namespace ICSharpCode.AvalonEdit.Gui
scrollOffset);
if (VisualLinesChanged != null)
VisualLinesChanged(this, EventArgs.Empty);
if (canHorizontallyScroll) {
return availableSize;
} else {
return new Size(maxWidth, availableSize.Height);
}
return new Size(
canHorizontallyScroll ? Math.Min(availableSize.Width, maxWidth) : maxWidth,
canVerticallyScroll ? Math.Min(availableSize.Height, heightTree.TotalHeight) : heightTree.TotalHeight
);
}
/// <summary>

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -79,7 +79,7 @@ @@ -79,7 +79,7 @@
<Compile Include="CodeCompletion\CompletionWindow.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="CodeCompletion\ICodeCompletionData.cs" />
<Compile Include="CodeCompletion\ICompletionData.cs" />
<Compile Include="Document\DocumentChangeOperation.cs">
<DependentUpon>UndoStack.cs</DependentUpon>
</Compile>

16
src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs

@ -366,6 +366,11 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -366,6 +366,11 @@ namespace ICSharpCode.SharpDevelop.Gui
break;
}
}
if (!e.Cancel) {
foreach (IViewContent vc in this.viewContents) {
dockLayout.Workbench.StoreMemento(vc);
}
}
}
protected override void OnClosed()
@ -410,5 +415,16 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -410,5 +415,16 @@ namespace ICSharpCode.SharpDevelop.Gui
}
}
}
// Forward focus to the content.
/// <inheritdoc/>
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
base.OnGotKeyboardFocus(e);
UIElement content = this.Content as UIElement;
if (content != null && !content.IsKeyboardFocusWithin) {
Keyboard.Focus(content);
e.Handled = true;
}
}
}
}

78
src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs

@ -9,6 +9,8 @@ using System; @@ -9,6 +9,8 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
@ -98,7 +100,9 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -98,7 +100,9 @@ namespace ICSharpCode.SharpDevelop.Gui
if (e.Uri.Scheme == "mailto") {
try {
Process.Start(e.Uri.ToString());
} catch {}
} catch {
// catch exceptions - e.g. incorrectly installed mail client
}
} else {
FileService.OpenFile(e.Uri.ToString());
}
@ -273,6 +277,8 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -273,6 +277,8 @@ namespace ICSharpCode.SharpDevelop.Gui
throw new ArgumentNullException("content");
System.Diagnostics.Debug.Assert(WorkbenchLayout != null);
LoadViewContentMemento(content);
WorkbenchLayout.ShowView(content, switchToOpenedView);
if (switchToOpenedView) {
content.WorkbenchWindow.SelectWindow();
@ -323,6 +329,76 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -323,6 +329,76 @@ namespace ICSharpCode.SharpDevelop.Gui
}
}
#region ViewContent Memento Handling
string viewContentMementosFileName;
string ViewContentMementosFileName {
get {
if (viewContentMementosFileName == null) {
viewContentMementosFileName = Path.Combine(PropertyService.ConfigDirectory, "LastViewStates.xml");
}
return viewContentMementosFileName;
}
}
Properties LoadOrCreateViewContentMementos()
{
try {
return Properties.Load(this.ViewContentMementosFileName) ?? new Properties();
} catch (Exception ex) {
LoggingService.Warn("Error while loading the view content memento file. Discarding any saved view states.", ex);
return new Properties();
}
}
static string GetMementoKeyName(IViewContent viewContent)
{
return String.Concat(viewContent.GetType().FullName.GetHashCode().ToString("x", CultureInfo.InvariantCulture), ":", FileUtility.NormalizePath(viewContent.PrimaryFileName).ToUpperInvariant());
}
/// <summary>
/// Stores the memento for the view content.
/// Such mementos are automatically loaded in ShowView().
/// </summary>
public void StoreMemento(IViewContent viewContent)
{
IMementoCapable mementoCapable = viewContent as IMementoCapable;
if (mementoCapable != null && PropertyService.Get("SharpDevelop.LoadDocumentProperties", true)) {
if (viewContent.PrimaryFileName == null)
return;
string key = GetMementoKeyName(viewContent);
LoggingService.Debug("Saving memento of '" + viewContent.ToString() + "' to key '" + key + "'");
Properties memento = mementoCapable.CreateMemento();
Properties p = this.LoadOrCreateViewContentMementos();
p.Set(key, memento);
FileUtility.ObservedSave(new NamedFileOperationDelegate(p.Save), this.ViewContentMementosFileName, FileErrorPolicy.Inform);
}
}
void LoadViewContentMemento(IViewContent viewContent)
{
IMementoCapable mementoCapable = viewContent as IMementoCapable;
if (mementoCapable != null && PropertyService.Get("SharpDevelop.LoadDocumentProperties", true)) {
if (viewContent.PrimaryFileName == null)
return;
try {
string key = GetMementoKeyName(viewContent);
LoggingService.Debug("Trying to restore memento of '" + viewContent.ToString() + "' from key '" + key + "'");
Properties memento = this.LoadOrCreateViewContentMementos().Get<Properties>(key, null);
if (memento != null) {
mementoCapable.SetMemento(memento);
}
} catch (Exception e) {
MessageService.ShowError(e, "Can't get/set memento");
}
}
}
#endregion
public void RedrawAllComponents()
{
}

2
src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.xaml

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "SharpDevelop (experimental WPF build)"
WindowStartupLocation = "Manual"
Background="{DynamicResource {x:Static SystemColors.MenuBarBrushKey}}"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
>
<DockPanel Name="dockPanel">
<Menu Name="mainMenu" DockPanel.Dock="Top"/>

8
src/Main/Base/Project/Src/TextEditor/Gui/Editor/CodeCompletionBinding.cs

@ -33,9 +33,17 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor @@ -33,9 +33,17 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
None,
/// <summary>
/// The binding handled code completion, the pressed key will be handled normally.
/// The pressed key will not be included in the completion expression, but will be
/// in front of it (this is usually used when the key is '.').
/// </summary>
Completed,
/// <summary>
/// The binding handled code completion, the pressed key will be handled normally.
/// The pressed key will be included in the completion expression.
/// This is used when starting to type any character starts code completion.
/// </summary>
CompletedIncludeKeyInCompletion,
/// <summary>
/// The binding handled code completion, and the key will not be handled by the text editor.
/// </summary>
EatKey

2
src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs

@ -331,6 +331,8 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor @@ -331,6 +331,8 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
CodeCompletionKeyPressResult result = ccBinding.HandleKeyPress(adapter, ch);
if (result == CodeCompletionKeyPressResult.Completed)
return false;
else if (result == CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion)
return false;
else if (result == CodeCompletionKeyPressResult.EatKey)
return true;
}

Loading…
Cancel
Save