Browse Source
- improved attribute CC - added GridLengthEditor to EditGridColumnsAndRowsDialog - added XamlOutlineContentHost git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4554 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
19 changed files with 762 additions and 78 deletions
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
<UserControl x:Class="ICSharpCode.XamlBinding.PowerToys.Dialogs.GridLengthEditor" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
<StackPanel x:Name="panel" Orientation="Horizontal" Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center"> |
||||
<Button x:Name="btnType" Margin="3" Content=" * " Click="BtnTypeClick" /> |
||||
<TextBox x:Name="txtNumericValue" MaxLength="10" Width="50" Margin="3" TextChanged="TxtNumericValueTextChanged" /> |
||||
</StackPanel> |
||||
</UserControl> |
@ -0,0 +1,162 @@
@@ -0,0 +1,162 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Text; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Data; |
||||
using System.Windows.Documents; |
||||
using System.Windows.Input; |
||||
using System.Windows.Media; |
||||
|
||||
namespace ICSharpCode.XamlBinding.PowerToys.Dialogs |
||||
{ |
||||
/// <summary>
|
||||
/// Interaction logic for GridLengthEditor.xaml
|
||||
/// </summary>
|
||||
public partial class GridLengthEditor : UserControl |
||||
{ |
||||
GridUnitType type = GridUnitType.Star; |
||||
int cell; |
||||
|
||||
public GridLengthEditor(Orientation type, int cell, string value) |
||||
{ |
||||
InitializeComponent(); |
||||
|
||||
if (type == Orientation.Horizontal) |
||||
this.SetValue(Grid.ColumnProperty, cell); |
||||
else |
||||
this.SetValue(Grid.RowProperty, cell); |
||||
|
||||
SetValue(value.Trim()); |
||||
|
||||
this.cell = cell; |
||||
|
||||
this.panel.Orientation = type; |
||||
} |
||||
|
||||
void SetValue(string value) |
||||
{ |
||||
if (value.Equals("Auto", StringComparison.OrdinalIgnoreCase)) { |
||||
type = GridUnitType.Auto; |
||||
txtNumericValue.Text = ""; |
||||
} else { |
||||
if (value.EndsWith("px", StringComparison.OrdinalIgnoreCase)) { |
||||
type = GridUnitType.Pixel; |
||||
txtNumericValue.Text = value.Remove(value.Length - 2); |
||||
} else if (value.EndsWith("*", StringComparison.OrdinalIgnoreCase)) { |
||||
type = GridUnitType.Star; |
||||
txtNumericValue.Text = value.Remove(value.Length - 1); |
||||
} else if (string.IsNullOrEmpty(value)) { |
||||
type = GridUnitType.Star; |
||||
txtNumericValue.Text = ""; |
||||
} else { |
||||
type = GridUnitType.Pixel; |
||||
txtNumericValue.Text = value; |
||||
} |
||||
} |
||||
|
||||
switch (type) { |
||||
case GridUnitType.Star: |
||||
btnType.Content = " * "; |
||||
txtNumericValue.Visibility = Visibility.Visible; |
||||
break; |
||||
case GridUnitType.Pixel: |
||||
btnType.Content = "Pixel"; |
||||
txtNumericValue.Visibility = Visibility.Visible; |
||||
break; |
||||
case GridUnitType.Auto: |
||||
btnType.Content = "Auto"; |
||||
txtNumericValue.Visibility = Visibility.Collapsed; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void BtnTypeClick(object sender, RoutedEventArgs e) |
||||
{ |
||||
switch (type) { |
||||
case GridUnitType.Auto: |
||||
type = GridUnitType.Star; |
||||
btnType.Content = " * "; |
||||
txtNumericValue.Visibility = Visibility.Visible; |
||||
break; |
||||
case GridUnitType.Star: |
||||
type = GridUnitType.Pixel; |
||||
btnType.Content = "Pixel"; |
||||
txtNumericValue.Visibility = Visibility.Visible; |
||||
break; |
||||
case GridUnitType.Pixel: |
||||
type = GridUnitType.Auto; |
||||
btnType.Content = "Auto"; |
||||
txtNumericValue.Visibility = Visibility.Collapsed; |
||||
break; |
||||
} |
||||
OnSelectedValueChanged(new GridLengthSelectionChangedEventArgs(this.panel.Orientation, this.cell, SelectedValue)); |
||||
} |
||||
|
||||
public GridLength? SelectedValue { |
||||
get { |
||||
if (type == GridUnitType.Star || type == GridUnitType.Pixel) { |
||||
double value; |
||||
if (type == GridUnitType.Star && string.IsNullOrEmpty(txtNumericValue.Text)) { |
||||
return new GridLength(1, type); |
||||
} else { |
||||
if (double.TryParse(txtNumericValue.Text, out value)) |
||||
return new GridLength(value, type); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
return GridLength.Auto; |
||||
} |
||||
} |
||||
|
||||
public event EventHandler<GridLengthSelectionChangedEventArgs> SelectedValueChanged; |
||||
|
||||
protected virtual void OnSelectedValueChanged(GridLengthSelectionChangedEventArgs e) |
||||
{ |
||||
if (SelectedValueChanged != null) { |
||||
SelectedValueChanged(this, e); |
||||
} |
||||
} |
||||
|
||||
void TxtNumericValueTextChanged(object sender, TextChangedEventArgs e) |
||||
{ |
||||
if (type == GridUnitType.Star && string.IsNullOrEmpty(txtNumericValue.Text)) { |
||||
txtNumericValue.ClearValue(TextBox.BackgroundProperty); |
||||
txtNumericValue.ClearValue(TextBox.ForegroundProperty); |
||||
} else { |
||||
double x; |
||||
if (!double.TryParse(txtNumericValue.Text, out x)) { |
||||
txtNumericValue.Background = Brushes.Red; |
||||
txtNumericValue.Foreground = Brushes.White; |
||||
} else { |
||||
txtNumericValue.ClearValue(TextBox.BackgroundProperty); |
||||
txtNumericValue.ClearValue(TextBox.ForegroundProperty); |
||||
} |
||||
} |
||||
OnSelectedValueChanged(new GridLengthSelectionChangedEventArgs(this.panel.Orientation, cell, SelectedValue)); |
||||
} |
||||
} |
||||
|
||||
public class GridLengthSelectionChangedEventArgs : EventArgs |
||||
{ |
||||
public Orientation Type { get; private set; } |
||||
public int Cell { get; private set; } |
||||
public GridLength? Value { get; private set; } |
||||
|
||||
public GridLengthSelectionChangedEventArgs(Orientation type, int cell, GridLength? value) |
||||
{ |
||||
this.Type = type; |
||||
this.Cell = cell; |
||||
this.Value = value; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
<DockPanel x:Class="ICSharpCode.XamlBinding.XamlOutlineContentHost" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:treeview="http://icsharpcode.net/sharpdevelop/treeview" |
||||
> |
||||
<ToolBar DockPanel.Dock="Top"> |
||||
<Button>Test</Button> |
||||
</ToolBar> |
||||
<treeview:SharpTreeView |
||||
x:Name="treeView" |
||||
AllowDrop="True" |
||||
AllowDropOrder="True" |
||||
MouseDoubleClick="TreeViewMouseDoubleClick" /> |
||||
</DockPanel> |
@ -0,0 +1,355 @@
@@ -0,0 +1,355 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using ICSharpCode.Core; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Text; |
||||
using System.Threading.Tasks; |
||||
using System.Timers; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Data; |
||||
using System.Windows.Documents; |
||||
using System.Windows.Input; |
||||
using System.Windows.Media; |
||||
using System.Windows.Threading; |
||||
using System.Xml; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.TreeView; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
/// <summary>
|
||||
/// Interaction logic for XamlOutlineContentHost.xaml
|
||||
/// </summary>
|
||||
public partial class XamlOutlineContentHost : DockPanel, IOutlineContentHost |
||||
{ |
||||
ITextEditor editor; |
||||
Task updateTask; |
||||
DispatcherTimer timer; |
||||
|
||||
public XamlOutlineContentHost(ITextEditor editor) |
||||
{ |
||||
this.editor = editor; |
||||
|
||||
InitializeComponent(); |
||||
|
||||
this.timer = new DispatcherTimer(DispatcherPriority.Background, this.Dispatcher); |
||||
this.timer.Tick += new EventHandler(XamlOutlineContentHostTick); |
||||
|
||||
this.timer.Interval = new TimeSpan(0, 0, 2); |
||||
this.timer.Start(); |
||||
} |
||||
|
||||
void XamlOutlineContentHostTick(object sender, EventArgs e) |
||||
{ |
||||
if (updateTask != null && updateTask.Status == TaskStatus.Running) |
||||
updateTask.Wait(); |
||||
updateTask = new Task(UpdateTask); |
||||
updateTask.Start(); |
||||
} |
||||
|
||||
void UpdateTask() |
||||
{ |
||||
string content = WorkbenchSingleton.SafeThreadFunction(() => editor.Document.Text); |
||||
Stack<NodeWrapper> nodes = new Stack<NodeWrapper>(); |
||||
NodeWrapper root = null; |
||||
|
||||
using (XmlTextReader reader = new XmlTextReader(new StringReader(content))) { |
||||
try { |
||||
while (reader.Read()) { |
||||
switch (reader.NodeType) { |
||||
case XmlNodeType.Element: |
||||
NodeWrapper node = new NodeWrapper() { |
||||
ElementName = reader.LocalName, |
||||
Line = reader.LineNumber, |
||||
Column = reader.LinePosition, |
||||
EndColumn = -1, |
||||
EndLine = -1, |
||||
Children = new List<NodeWrapper>() |
||||
}; |
||||
if (reader.HasAttributes) { |
||||
string name = reader.GetAttribute("Name"); |
||||
if (name == null) |
||||
name = reader.GetAttribute("Name", CompletionDataHelper.XamlNamespace); |
||||
if (name != null) |
||||
node.Name = name; |
||||
} |
||||
if (root == null) { |
||||
root = node; |
||||
nodes.Push(root); |
||||
} else { |
||||
if (nodes.Count > 0) |
||||
nodes.Peek().Children.Add(node); |
||||
if (!reader.IsEmptyElement) |
||||
nodes.Push(node); |
||||
} |
||||
break; |
||||
case XmlNodeType.EndElement: |
||||
if (nodes.Count > 1) { |
||||
NodeWrapper n = nodes.Pop(); |
||||
n.EndLine = reader.LineNumber; |
||||
n.EndColumn = reader.LinePosition; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
} catch (XmlException) { |
||||
return; |
||||
} |
||||
|
||||
WorkbenchSingleton.SafeThreadCall(() => UpdateTree(root)); |
||||
} |
||||
} |
||||
|
||||
void UpdateTree(NodeWrapper root) |
||||
{ |
||||
if (this.treeView.Root == null) |
||||
this.treeView.Root = BuildNode(root); |
||||
else { |
||||
UpdateNode(this.treeView.Root as XamlOutlineNode, root); |
||||
} |
||||
} |
||||
|
||||
void UpdateNode(XamlOutlineNode node, NodeWrapper dataNode) |
||||
{ |
||||
if (dataNode != null && node != null) { |
||||
node.Name = dataNode.Name; |
||||
node.ElementName = dataNode.ElementName; |
||||
node.Marker = editor.Document.CreateAnchor(editor.Document.PositionToOffset(dataNode.Line, dataNode.Column)); |
||||
|
||||
ITextAnchor marker = null; |
||||
|
||||
if (dataNode.EndLine != -1 && dataNode.EndColumn != -1) { |
||||
marker = editor.Document.CreateAnchor(editor.Document.PositionToOffset(dataNode.EndLine, dataNode.EndColumn)); |
||||
} |
||||
|
||||
node.EndMarker = marker; |
||||
|
||||
int childrenCount = node.Children.Count; |
||||
int dataCount = dataNode.Children.Count; |
||||
|
||||
for (int i = 0; i < Math.Max(childrenCount, dataCount); i++) { |
||||
if (i >= childrenCount) { |
||||
node.Children.Add(BuildNode(dataNode.Children[i])); |
||||
} else if (i >= dataCount) { |
||||
while (node.Children.Count > dataCount) |
||||
node.Children.RemoveAt(dataCount); |
||||
} else { |
||||
UpdateNode(node.Children[i] as XamlOutlineNode, dataNode.Children[i]); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
XamlOutlineNode BuildNode(NodeWrapper item) |
||||
{ |
||||
ITextAnchor marker = null; |
||||
|
||||
if (item.EndLine != -1 && item.EndColumn != -1) { |
||||
marker = editor.Document.CreateAnchor(editor.Document.PositionToOffset(item.EndLine, item.EndColumn)); |
||||
} |
||||
|
||||
XamlOutlineNode node = new XamlOutlineNode() { |
||||
Name = item.Name, |
||||
ElementName = item.ElementName, |
||||
ShowIcon = false, |
||||
Marker = editor.Document.CreateAnchor(editor.Document.PositionToOffset(item.Line, item.Column)), |
||||
EndMarker = marker, |
||||
Editor = editor |
||||
}; |
||||
|
||||
foreach (var child in item.Children) |
||||
node.Children.Add(BuildNode(child)); |
||||
|
||||
return node; |
||||
} |
||||
|
||||
void TreeViewMouseDoubleClick(object sender, MouseButtonEventArgs e) |
||||
{ |
||||
XamlOutlineNode node = treeView.SelectedItem as XamlOutlineNode; |
||||
int offset = editor.Document.PositionToOffset(node.Marker.Line, node.Marker.Column); |
||||
int endOffset = node.GetEndOffset(); |
||||
editor.Select(offset - 1, endOffset - offset); |
||||
} |
||||
|
||||
public object OutlineContent { |
||||
get { |
||||
return this; |
||||
} |
||||
} |
||||
} |
||||
|
||||
class NodeWrapper { |
||||
public string ElementName { get; set; } |
||||
public string Name { get; set; } |
||||
|
||||
public int Line { get; set; } |
||||
public int Column { get; set; } |
||||
|
||||
public int EndLine { get; set; } |
||||
public int EndColumn { get; set; } |
||||
|
||||
public IList<NodeWrapper> Children { get; set; } |
||||
} |
||||
|
||||
class XamlOutlineNode : SharpTreeNode { |
||||
string elementName, name; |
||||
|
||||
public string ElementName { |
||||
get { return elementName; } |
||||
set { |
||||
this.elementName = value; |
||||
this.RaisePropertyChanged("Text"); |
||||
} |
||||
} |
||||
|
||||
public string Name { |
||||
get { return name; } |
||||
set { |
||||
this.name = value; |
||||
this.RaisePropertyChanged("Text"); |
||||
} |
||||
} |
||||
|
||||
public ITextAnchor Marker { get; set; } |
||||
public ITextAnchor EndMarker { get; set; } |
||||
public ITextEditor Editor { get; set; } |
||||
|
||||
public XamlOutlineNode Successor { |
||||
get { |
||||
if (this.Parent == null) |
||||
return null; |
||||
int index = this.Parent.Children.IndexOf(this); |
||||
if (index + 1 < this.Parent.Children.Count) |
||||
return this.Parent.Children[index + 1] as XamlOutlineNode; |
||||
else |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public override bool CanDrag(SharpTreeNode[] nodes) |
||||
{ |
||||
return nodes.All(node => node.Parent != null); |
||||
} |
||||
|
||||
public override DropEffect CanDrop(IDataObject data, DropEffect requestedEffect) |
||||
{ |
||||
return DropEffect.Move; |
||||
} |
||||
|
||||
public override bool CanCopy(SharpTreeNode[] nodes) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
public int GetEndOffset() |
||||
{ |
||||
if (EndMarker != null) { |
||||
return EndMarker.Offset + ElementName.Length + 2; |
||||
} else { |
||||
XamlOutlineNode successor = Successor; |
||||
if (successor != null) { |
||||
return successor.Marker.Offset; |
||||
} else { |
||||
XamlOutlineNode parent = Parent as XamlOutlineNode; |
||||
if (parent != null) |
||||
return parent.EndMarker.Offset - 1; |
||||
} |
||||
} |
||||
|
||||
return Editor.Document.TextLength + 1; |
||||
} |
||||
|
||||
public string GetMarkupText() |
||||
{ |
||||
int offset = Editor.Document.PositionToOffset(Marker.Line, Marker.Column); |
||||
|
||||
return Editor.Document.GetText(offset - 1, GetEndOffset() - offset); |
||||
} |
||||
|
||||
public override IDataObject Copy(SharpTreeNode[] nodes) |
||||
{ |
||||
string[] data = nodes |
||||
.OfType<XamlOutlineNode>() |
||||
.Select(item => item.GetMarkupText()) |
||||
.ToArray(); |
||||
var dataObject = new DataObject(); |
||||
dataObject.SetData(typeof(string[]), data); |
||||
|
||||
return dataObject; |
||||
} |
||||
|
||||
public override bool CanDelete(SharpTreeNode[] nodes) |
||||
{ |
||||
return nodes.All(node => node.Parent != null); |
||||
} |
||||
|
||||
public override void Drop(IDataObject data, int index, DropEffect finalEffect) |
||||
{ |
||||
try { |
||||
string insertText = (data.GetData(typeof(string[])) as string[]) |
||||
.Aggregate((text, part) => text += part); |
||||
ITextAnchor marker; |
||||
int length = 0; |
||||
if (index == this.Children.Count) { |
||||
if (index == 0) |
||||
marker = null; |
||||
else |
||||
marker = (this.Children[index - 1] as XamlOutlineNode).EndMarker; |
||||
if (marker == null) { |
||||
marker = this.EndMarker; |
||||
length = -1; // move backwards
|
||||
} else { |
||||
length = 2 + (this.Children[index - 1] as XamlOutlineNode).elementName.Length; |
||||
} |
||||
} else |
||||
marker = (this.Children[index] as XamlOutlineNode).Marker; |
||||
|
||||
int offset = marker.Offset + length; |
||||
Editor.Document.Insert(offset - 1, insertText); |
||||
} catch (Exception ex) { |
||||
throw ex; |
||||
} |
||||
} |
||||
|
||||
public override void Delete(SharpTreeNode[] nodes) |
||||
{ |
||||
DeleteCore(nodes); |
||||
} |
||||
|
||||
public override void DeleteCore(SharpTreeNode[] nodes) |
||||
{ |
||||
foreach (XamlOutlineNode node in nodes.OfType<XamlOutlineNode>()) { |
||||
node.Editor.Document.Remove(node.Marker.Offset - 1, node.GetEndOffset() - node.Marker.Offset); |
||||
} |
||||
} |
||||
|
||||
ContextMenu menu; |
||||
|
||||
public override ContextMenu GetContextMenu() |
||||
{ |
||||
if (menu == null) { |
||||
menu = new ContextMenu(); |
||||
menu.Items.Add(new MenuItem() { Command = ApplicationCommands.Cut }); |
||||
menu.Items.Add(new MenuItem() { Command = ApplicationCommands.Copy }); |
||||
menu.Items.Add(new MenuItem() { Command = ApplicationCommands.Paste }); |
||||
menu.Items.Add(new Separator()); |
||||
menu.Items.Add(new MenuItem() { Command = ApplicationCommands.Delete }); |
||||
} |
||||
return menu; |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return (!string.IsNullOrEmpty(Name) ? ElementName + " (" + Name + ")" : ElementName); } |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue