using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Interop;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Controls;
using System.Linq;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Threading;
namespace agree.Wpf.Util
{
public static class Util
{
public static Size DrawText(this DrawingContext dc, String s, double x, double y, Typeface f, double emSize, Brush b)
{
FormattedText ft = new FormattedText(s, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, f, emSize, b);
dc.DrawText(ft, new Point(x, y));
return new Size(ft.Width, ft.Height);
}
public static Size DrawText(this DrawingContext dc, String s, Point pt, Typeface f, double emSize, Brush b)
{
FormattedText ft = new FormattedText(s, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, f, emSize, b);
dc.DrawText(ft, pt);
return new Size(ft.Width, ft.Height);
}
public static void DrawText(this DrawingContext dc, FormattedText ft, double x, double y)
{
dc.DrawText(ft, new Point(x, y));
}
public static FormattedText FormattedText(this String s, Typeface f, double emSize, Brush b = null)
{
return new FormattedText(s, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, f, emSize, b ?? Brushes.Black);
}
static Size infinite_size = new Size(double.PositiveInfinity, double.PositiveInfinity);
public static void SaveToPng(FrameworkElement fe, System.IO.Stream stream)
{
using (var ps = new HwndSource(new HwndSourceParameters()))
{
ps.RootVisual = VisualTreeHelper.GetParent(fe) == null ? fe : null;
// Flush the dispatcher queue
//var disp = Dispatcher.CurrentDispatcher;
//if (disp == null)
// throw new Exception();
//disp.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));
fe.Measure(infinite_size);
Size sz = fe.DesiredSize;
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush br = new VisualBrush(fe);
br.AutoLayoutContent = true;
ctx.DrawRectangle(br, null, new Rect(0, 0, sz.Width, sz.Height));
}
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)sz.Width+2, (int)sz.Height+2, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(dv);
//disp.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream);
}
}
};
/// <summary>
/// http://thejoyofcode.com/Generating_images_using_WPF_on_the_Server.aspx
/// </summary>
public class BackgroundStaDispatcher
{
private Dispatcher _dispatcher;
static int id = 0;
public BackgroundStaDispatcher(Action<Exception> exception_handler)
{
AutoResetEvent are = new AutoResetEvent(false);
Thread thread = new Thread(() =>
{
_dispatcher = Dispatcher.CurrentDispatcher;
_dispatcher.UnhandledException += (o, e) =>
{
exception_handler(e.Exception);
if (!Debugger.IsAttached)
{
e.Handled = true;
}
};
are.Set();
Dispatcher.Run();
});
thread.Name = string.Format("BackgroundStaDispatcher({0})", (id++).ToString());
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
are.WaitOne();
}
public void Invoke(Action action)
{
_dispatcher.Invoke(action);
}
}
}
namespace agree.Wpf.Util
{
public class RoundedRectangle : Border, INotifyPropertyChanged
{
Rectangle r;
Border mask;
Grid g2;
public RoundedRectangle()
: this(default(UIElement))
{
}
public RoundedRectangle(String txt, TextWrapping wrap = TextWrapping.NoWrap)
: this(new TextBlock())
{
this.Text = txt;
}
public RoundedRectangle(UIElement el)
{
r = new Rectangle();
mask = new Border();
mask.Background = Brushes.White;
g2 = new Grid();
g2.OpacityMask = new VisualBrush(mask);
g2.Children.Add(r);
if (el != null)
g2.Children.Add(el);
Grid g1 = new Grid();
g1.Children.Add(mask);
g1.Children.Add(g2);
base.BorderThickness = new Thickness(1);
base.BorderBrush = Brushes.Black;
base.CornerRadius = new CornerRadius(6);
base.Child = g1;
}
public String Text
{
set
{
TextBlock tb = new TextBlock();
InnerChild = tb;
tb.Text = value;
tb.Foreground = Brushes.Black;
tb.Padding = new Thickness(1.5);
tb.TextWrapping = TextWrapping.NoWrap;
}
}
public UIElement InnerChild
{
get
{
return g2.Children.Count > 1 ? g2.Children[1] : null;
}
set
{
while (g2.Children.Count >= 2)
g2.Children.RemoveAt(1);
g2.Children.Add(value);
}
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == Border.CornerRadiusProperty)
mask.CornerRadius = this.CornerRadius;
else if (e.Property == Border.BackgroundProperty)
r.Fill = this.Background;
}
Point pt_top_center;
Point pt_bot_center;
public Point TopCenter { get { return pt_top_center; } }
public Point BottomCenter { get { return pt_bot_center; } }
public Double Top { get { return pt_top_center.Y; } }
public Double Bottom { get { return pt_bot_center.Y; } }
public Double Center { get { return pt_top_center.X; } }
public static readonly DependencyProperty ContainerParentProperty =
DependencyProperty.RegisterAttached("ContainerParent", typeof(Boolean), typeof(RoundedRectangle),
new FrameworkPropertyMetadata(
false,
0,
null,
null,
true));
public static Boolean GetTreeParent(FrameworkElement e)
{
return (Boolean)e.GetValue(ContainerParentProperty);
}
public static void SetTreeParent(FrameworkElement e, Boolean v)
{
e.SetValue(ContainerParentProperty, v);
}
FrameworkElement FindContainerParent()
{
FrameworkElement p = this;
while ((p = p.Parent as FrameworkElement) != null)
{
if ((Boolean)p.GetValue(ContainerParentProperty))
return p;
}
return null;
}
protected override Size ArrangeOverride(Size finalSize)
{
Size sz = base.ArrangeOverride(finalSize);
FrameworkElement p = FindContainerParent();
if (p != null)
{
Point pt;
pt = TranslatePoint(new Point(sz.Width / 2, 0), p);
if (!pt.Equals(pt_top_center))
{
pt_top_center = pt;
NotifyPropertyChanged("TopCenter");
NotifyPropertyChanged("Top");
NotifyPropertyChanged("Center");
}
pt = TranslatePoint(new Point(sz.Width / 2, sz.Height), p);
if (!pt.Equals(pt_bot_center))
{
pt_bot_center = pt;
NotifyPropertyChanged("BottomCenter");
NotifyPropertyChanged("Bottom");
}
}
return sz;
}
void NotifyPropertyChanged(String s_field)
{
var h = PropertyChanged;
if (h != null)
h(this, new PropertyChangedEventArgs(s_field));
}
public event PropertyChangedEventHandler PropertyChanged;
};
public class VizParseTree : StackPanel
{
IDerivation pce;
TreeLayoutPanel tlp;
public VizParseTree(ParseControl ctrl, IDerivation pce)
{
this.pce = pce;
this.Orientation = System.Windows.Controls.Orientation.Vertical;
tlp = new TreeLayoutPanel();
tlp.VerticalBuffer = 15;
tlp.HorizontalBuffer = 35;
tlp.HorizontalBufferSubtree = 35;
tlp.Margin = new Thickness(10);
tlp.Stroke = Brushes.Gray;
//tree_layout_panel.SetValue(TextBlock.FontSizeProperty, 18.0);
//tree_layout_panel.SetValue(TextBlock.FontFamilyProperty, new FontFamily("Arial"));
CreateTreeNode(ctrl.g.nl.GetParseTree(ctrl.chart, pce));
this.Children.Add(tlp);
var tb = new TextBlock(new Run(pce.UnpackedTfs.Name));
tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
this.Children.Add(tb);
}
public IDerivation ParseTree { get { return pce; } }
FrameworkElement CreateTreeNode(GrammarNodeLabeler.ParseTree pt)
{
FrameworkElement ltn = pt.Children.Length == 0 ? (FrameworkElement)
new TextBelowLabelTreeNode(pt) :
new LabelTreeNode(pt.Label);
tlp.Children.Add(ltn);
foreach (var fe in pt.Children.Select(c => CreateTreeNode(c)))
{
fe.SetValue(TreeLayoutPanel.TreeParentProperty, ltn);
}
return ltn;
}
class LabelTreeNode : RoundedRectangle
{
public LabelTreeNode(String text)
: base(text)
{
CornerRadius = new CornerRadius(1.5);
Background = Brushes.Honeydew;
HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
((TextBlock)InnerChild).Padding = new Thickness(5, 0, 5, 0);
}
};
class TextBelowLabelTreeNode : StackPanel
{
public TextBelowLabelTreeNode(GrammarNodeLabeler.ParseTree pt)
{
this.Orientation = System.Windows.Controls.Orientation.Vertical;
this.SnapsToDevicePixels = true;
var ltn = new LabelTreeNode(pt.Label);
ltn.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
this.Children.Add(ltn);
Run r = new Run(pt.SourceText);
r.FontFamily = new FontFamily("Tekton Pro");
r.FontSize = 21.0;
r.FontWeight = FontWeight.FromOpenTypeWeight(100);
var tb = new TextBlock();
tb.Margin = new Thickness(0, 4, 0, 0);
tb.Inlines.Add(r);
tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
this.Children.Add(tb);
}
};
};
}