280 строки
7.5 KiB
C#
Executable File
280 строки
7.5 KiB
C#
Executable File
//
|
|
// RichTextViewBackend.cs
|
|
//
|
|
// Author:
|
|
// Alan McGovern <alan@xamarin.com>
|
|
//
|
|
// Copyright (c) 2012 Xamarin, Inc.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Xml;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Markup;
|
|
using Xwt.Backends;
|
|
|
|
using Xwt.WPFBackend.Utilities;
|
|
using System.Windows.Data;
|
|
using System.Windows.Navigation;
|
|
|
|
namespace Xwt.WPFBackend
|
|
{
|
|
class RichTextViewBackend
|
|
: WidgetBackend, IRichTextViewBackend
|
|
{
|
|
public new IRichTextViewEventSink EventSink {
|
|
get { return (IRichTextViewEventSink) base.EventSink; }
|
|
}
|
|
|
|
public new ExRichTextBox Widget
|
|
{
|
|
get { return (ExRichTextBox) base.Widget; }
|
|
set { base.Widget = value; }
|
|
}
|
|
|
|
public RichTextViewBackend ()
|
|
{
|
|
Widget = new ExRichTextBox ();
|
|
Widget.BorderThickness = new System.Windows.Thickness (0);
|
|
}
|
|
|
|
public override void EnableEvent (object eventId)
|
|
{
|
|
base.EnableEvent (eventId);
|
|
if (eventId is RichTextViewEvent) {
|
|
switch ((RichTextViewEvent) eventId) {
|
|
case RichTextViewEvent.NavigateToUrl:
|
|
Widget.AddHandler (Hyperlink.RequestNavigateEvent, new RequestNavigateEventHandler (HyperlinkNavigated), true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void DisableEvent (object eventId)
|
|
{
|
|
base.DisableEvent (eventId);
|
|
if (eventId is RichTextViewEvent) {
|
|
switch ((RichTextViewEvent) eventId) {
|
|
case RichTextViewEvent.NavigateToUrl:
|
|
Widget.RemoveHandler (Hyperlink.RequestNavigateEvent, new RequestNavigateEventHandler (HyperlinkNavigated));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void HyperlinkNavigated (object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
|
|
{
|
|
Context.InvokeUserCode (() => {
|
|
EventSink.OnNavigateToUrl (e.Uri);
|
|
e.Handled = true;
|
|
});
|
|
}
|
|
|
|
public IRichTextBuffer CreateBuffer ()
|
|
{
|
|
return new RichTextBuffer ();
|
|
}
|
|
|
|
public void SetBuffer (IRichTextBuffer buffer)
|
|
{
|
|
var buf = buffer as RichTextBuffer;
|
|
if (buf == null)
|
|
throw new ArgumentException ("Passed buffer is of incorrect type", "buffer");
|
|
|
|
if (Widget.Document != null)
|
|
Widget.Document.ClearValue (FlowDocument.PageWidthProperty);
|
|
Widget.Document = buf.ToFlowDocument ();
|
|
Widget.Document.SetBinding (FlowDocument.PageWidthProperty, new Binding ("ActualWidth") { Source = Widget });
|
|
Widget.IsDocumentEnabled = true;
|
|
Widget.Document.IsEnabled = true;
|
|
Widget.IsReadOnly = true;
|
|
}
|
|
|
|
class RichTextBuffer : IRichTextBuffer
|
|
{
|
|
const int FontSize = 16;
|
|
const int HeaderIncrement = 8;
|
|
|
|
StringBuilder builder;
|
|
XmlWriter writer;
|
|
FlowDocument doc;
|
|
|
|
public RichTextBuffer ()
|
|
{
|
|
builder = new StringBuilder ();
|
|
writer = XmlWriter.Create (builder, new XmlWriterSettings () { OmitXmlDeclaration = true, NewLineOnAttributes = true, Indent = true, IndentChars = "\t" });
|
|
writer.WriteStartElement ("FlowDocument", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
|
|
}
|
|
|
|
public void EmitText (string text)
|
|
{
|
|
if (string.IsNullOrEmpty(text))
|
|
return;
|
|
|
|
var lines = text.Split (new[] { Environment.NewLine }, StringSplitOptions.None);
|
|
var first = true;
|
|
foreach (var line in lines) {
|
|
if (!first) {
|
|
writer.WriteStartElement ("LineBreak");
|
|
writer.WriteEndElement ();
|
|
}
|
|
writer.WriteElementString ("Run", line);
|
|
first = false;
|
|
}
|
|
}
|
|
|
|
public void EmitStartHeader (int level)
|
|
{
|
|
EmitStartParagraph (0);
|
|
writer.WriteStartElement ("Span");
|
|
writer.WriteAttributeString ("FontSize", (FontSize + HeaderIncrement * level).ToString ());
|
|
}
|
|
|
|
public void EmitEndHeader()
|
|
{
|
|
writer.WriteEndElement();
|
|
EmitEndParagraph();
|
|
}
|
|
|
|
public void EmitOpenList ()
|
|
{
|
|
writer.WriteStartElement ("List");
|
|
}
|
|
|
|
public void EmitOpenBullet ()
|
|
{
|
|
writer.WriteStartElement ("ListItem");
|
|
EmitStartParagraph (0);
|
|
}
|
|
|
|
public void EmitCloseBullet ()
|
|
{
|
|
writer.WriteEndElement ();
|
|
writer.WriteEndElement ();
|
|
}
|
|
|
|
public void EmitCloseList ()
|
|
{
|
|
// Close the list
|
|
writer.WriteEndElement ();
|
|
}
|
|
|
|
public void EmitStartLink (string href, string title)
|
|
{
|
|
writer.WriteStartElement ("Hyperlink");
|
|
writer.WriteAttributeString ("NavigateUri", href);
|
|
if (!string.IsNullOrEmpty (title))
|
|
writer.WriteAttributeString ("ToolTip", title);
|
|
}
|
|
|
|
public void EmitEndLink()
|
|
{
|
|
writer.WriteEndElement();
|
|
}
|
|
|
|
int rtbCounter;
|
|
public void EmitCodeBlock (string code)
|
|
{
|
|
writer.WriteStartElement ("BlockUIContainer");
|
|
writer.WriteAttributeString ("Margin", "15");
|
|
|
|
string name = "rtb" + (rtbCounter++);
|
|
|
|
writer.WriteStartElement ("RichTextBox");
|
|
writer.WriteAttributeString ("Name", name);
|
|
writer.WriteAttributeString ("HorizontalScrollBarVisibility", "Hidden");
|
|
|
|
writer.WriteStartElement ("FlowDocument");
|
|
//writer.WriteAttributeString ("PageWidth", "1000");
|
|
writer.WriteAttributeString ("PageWidth", "{Binding ElementName=" + name + ",Path=ActualWidth}");
|
|
writer.WriteStartElement ("Paragraph");
|
|
|
|
writer.WriteAttributeString ("xml", "space", null, "preserve");
|
|
writer.WriteAttributeString ("FontFamily", "Global Monospace");
|
|
writer.WriteString (code);
|
|
|
|
writer.WriteEndElement ();
|
|
writer.WriteEndElement ();
|
|
writer.WriteEndElement ();
|
|
writer.WriteEndElement ();
|
|
}
|
|
|
|
public void EmitText (string text, RichTextInlineStyle style)
|
|
{
|
|
switch (style) {
|
|
case RichTextInlineStyle.Bold:
|
|
case RichTextInlineStyle.Italic:
|
|
writer.WriteStartElement (style.ToString ());
|
|
EmitText (text);
|
|
break;
|
|
|
|
case RichTextInlineStyle.Monospace:
|
|
writer.WriteStartElement ("Run");
|
|
writer.WriteAttributeString ("FontFamily", "Global Monospace");
|
|
writer.WriteString (text);
|
|
break;
|
|
|
|
default:
|
|
EmitText (text);
|
|
return;
|
|
}
|
|
writer.WriteEndElement ();
|
|
}
|
|
|
|
public void EmitStartParagraph (int indentLevel)
|
|
{
|
|
//FIXME: indentLevel
|
|
writer.WriteStartElement ("Paragraph");
|
|
}
|
|
|
|
public void EmitEndParagraph ()
|
|
{
|
|
writer.WriteEndElement ();
|
|
}
|
|
|
|
public void EmitHorizontalRuler ()
|
|
{
|
|
writer.WriteStartElement("BlockUIContainer");
|
|
writer.WriteAttributeString ("Margin", "0,0,0,0");
|
|
writer.WriteElementString("Separator", "");
|
|
writer.WriteEndElement();
|
|
}
|
|
|
|
public FlowDocument ToFlowDocument ()
|
|
{
|
|
if (doc == null) {
|
|
writer.WriteEndElement ();
|
|
writer.Flush ();
|
|
doc = (FlowDocument) XamlReader.Parse (builder.ToString ());
|
|
builder = null;
|
|
writer = null;
|
|
}
|
|
return doc;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|