OSDN Git Service

ナレーター周りをリファクタリングした&UWP版でナレーターがうまく動かないバグを修正した
[fooeditengine/FooEditEngine.git] / Core / Automaion / FooTextBoxAutomationPeer.cs
index 7ff5095..fe4403f 100644 (file)
@@ -32,6 +32,7 @@ using System.Windows.Automation;
 using System.Windows.Automation.Peers;
 using System.Windows.Automation.Provider;
 using System.Windows.Automation.Text;
+using FooEditEngine;
 using FooEditEngine.WPF;
 #endif
 
@@ -45,7 +46,11 @@ namespace FooEditEngine
     /// Text Pattern (ITextProvider) and Value Pattern (IValuePattern) interfaces.  So Touch keyboard shows 
     /// automatically when user taps on the control with Touch or Pen.
     /// </summary>
+#if METRO || WINDOWS_UWP
+    sealed class FooTextBoxAutomationPeer : FrameworkElementAutomationPeer, ITextProvider, ITextProvider2, IValueProvider
+#elif WPF
     sealed class FooTextBoxAutomationPeer : FrameworkElementAutomationPeer, ITextProvider, IValueProvider
+#endif
     {
         private FooTextBox fooTextBox;
         private string accClass = "FooTextBox";
@@ -87,10 +92,13 @@ namespace FooEditEngine
             {
                 return this;
             }
+            else if (patternInterface == PatternInterface.Text2)
+            {
+                return this;
+            }
             return base.GetPatternCore(patternInterface);
         }
-#endif
-#if WPF
+#elif WPF
         public override object GetPattern(PatternInterface patternInterface)
         {
             if (patternInterface == PatternInterface.Value)
@@ -138,24 +146,23 @@ namespace FooEditEngine
         protected override Windows.Foundation.Rect GetBoundingRectangleCore()
         {
             double scale = Util.GetScale();
-            return new Windows.Foundation.Rect(0, 0, this.fooTextBox.ActualWidth * scale, this.fooTextBox.ActualHeight * scale);
-        }
-#endif
-#if WPF
+            Point left = Util.GetPointInWindow(new Point(0, 0),this.fooTextBox).Scale(scale);
+            Point bottom = Util.GetPointInWindow(new Point(this.fooTextBox.ActualWidth, this.fooTextBox.ActualHeight),this.fooTextBox).Scale(scale);
+#elif WPF
         protected override System.Windows.Rect GetBoundingRectangleCore()
         {
-            System.Windows.Point left = this.fooTextBox.PointToScreen(new System.Windows.Point(0, 0));
-            System.Windows.Point bottom = this.fooTextBox.PointToScreen(new System.Windows.Point(this.fooTextBox.ActualWidth, this.fooTextBox.ActualHeight));
-            return new System.Windows.Rect(left, bottom);
-        }
+            Point left = Util.GetScreentPoint(new Point(0, 0), this.fooTextBox);
+            Point bottom = Util.GetScreentPoint(new Point(this.fooTextBox.ActualWidth, this.fooTextBox.ActualHeight), this.fooTextBox);
 #endif
+            return new Rectangle(left,bottom);
+        }
 
-    #region Implementation for ITextPattern interface
+        #region Implementation for ITextPattern and ITextPattern2 interface
         // Complete implementation of the ITextPattern is beyond the scope of this sample.  The implementation provided
         // is specific to this sample's custom control, so it is unlikely that they are directly transferable to other 
         // custom control.
 
-        ITextRangeProvider ITextProvider.DocumentRange
+        public ITextRangeProvider DocumentRange
         {
             // A real implementation of this method is beyond the scope of this sample.
             // If your custom control has complex text involving both readonly and non-readonly ranges, 
@@ -166,7 +173,7 @@ namespace FooEditEngine
             }
         }
 
-        ITextRangeProvider[] ITextProvider.GetSelection()
+        public ITextRangeProvider[] GetSelection()
         {
             ITextRangeProvider[] ret = new ITextRangeProvider[1];
             int selStart = this.fooTextBox.Selection.Index;
@@ -175,7 +182,7 @@ namespace FooEditEngine
             return ret;
         }
 
-        ITextRangeProvider[] ITextProvider.GetVisibleRanges()
+        public ITextRangeProvider[] GetVisibleRanges()
         {
             ITextRangeProvider[] ret = new ITextRangeProvider[1];
             if (this.fooTextBox.LayoutLineCollection.Count == 0)
@@ -184,59 +191,63 @@ namespace FooEditEngine
             }
             else
             {
-#if METRO || WINDOWS_UWP
-                int startIndex = this.fooTextBox.GetIndexFromPostion(new Windows.Foundation.Point(0,0));
-                int endIndex = this.fooTextBox.GetIndexFromPostion(new Windows.Foundation.Point(this.fooTextBox.ActualWidth, this.fooTextBox.ActualHeight));
-#endif
-#if WPF
-                int startIndex = this.fooTextBox.GetIndexFromPostion(new System.Windows.Point(0, 0));
-                int endIndex = this.fooTextBox.GetIndexFromPostion(new System.Windows.Point(this.fooTextBox.ActualWidth, this.fooTextBox.ActualHeight));
-#endif
+                EditView view = this.fooTextBox.View;
+                
+                int startIndex = view.GetIndexFromLayoutLine(new TextPoint(view.Src.Row,0));
+                int endIndex = view.GetIndexFromLayoutLine(new TextPoint(view.Src.Row + view.LineCountOnScreen, 0));
                 ret[0] = new FooTextBoxRangeProvider(this.fooTextBox, startIndex, endIndex - startIndex, this);
             }
             return ret;
         }
 
-        ITextRangeProvider ITextProvider.RangeFromChild(IRawElementProviderSimple childElement)
+        public ITextRangeProvider RangeFromChild(IRawElementProviderSimple childElement)
         {
             return new FooTextBoxRangeProvider(this.fooTextBox,0,0, this);
         }
 
 #if METRO || WINDOWS_UWP
-        ITextRangeProvider ITextProvider.RangeFromPoint(Windows.Foundation.Point screenLocation)
+        public ITextRangeProvider RangeFromPoint(Windows.Foundation.Point screenLocation)
+#elif WPF
+        public ITextRangeProvider RangeFromPoint(System.Windows.Point screenLocation)
+#endif
         {
-            Point pt = Util.GetClientPoint(screenLocation, this.fooTextBox);
+            Point pt = Util.GetClientPoint(screenLocation, fooTextBox);
+            EditView view = this.fooTextBox.View;
 
-            int index = this.fooTextBox.GetIndexFromPostion(pt);
+            int index = view.GetIndexFromLayoutLine(view.GetTextPointFromPostion(pt));
             int length = 1;
             if (index == this.fooTextBox.Document.Length)
                 length = 0;
-            
+
             return new FooTextBoxRangeProvider(this.fooTextBox, index, length, this);
         }
-#endif
-#if WPF
-        ITextRangeProvider ITextProvider.RangeFromPoint(System.Windows.Point screenLocation)
+
+        public SupportedTextSelection SupportedTextSelection
+        {
+            get { return SupportedTextSelection.Single; }
+        }
+
+        public ITextRangeProvider RangeFromAnnotation(IRawElementProviderSimple annotationElement)
         {
-            System.Windows.Point pt = this.fooTextBox.PointFromScreen(screenLocation);
+            throw new NotImplementedException();
+        }
 
-            int index = this.fooTextBox.GetIndexFromPostion(pt);
+        public ITextRangeProvider GetCaretRange(out bool isActive)
+        {
+
+            EditView view = this.fooTextBox.View;
+            Document doc = this.fooTextBox.Document;
+            isActive = true;
+            int index = view.GetIndexFromLayoutLine(doc.CaretPostion);
             int length = 1;
             if (index == this.fooTextBox.Document.Length)
                 length = 0;
 
             return new FooTextBoxRangeProvider(this.fooTextBox, index, length, this);
         }
-#endif
-
-        SupportedTextSelection ITextProvider.SupportedTextSelection
-        {
-            get { return SupportedTextSelection.Single; }
-        }
-
-    #endregion
+        #endregion
 
-    #region Implementation for IValueProvider interface
+        #region Implementation for IValueProvider interface
         // Complete implementation of the IValueProvider is beyond the scope of this sample.  The implementation provided
         // is specific to this sample's custom control, so it is unlikely that they are directly transferable to other 
         // custom control.
@@ -245,19 +256,19 @@ namespace FooEditEngine
         /// The value needs to be false for the Touch keyboard to be launched automatically because Touch keyboard
         /// does not appear when the input focus is in a readonly UI control.
         /// </summary>
-        bool IValueProvider.IsReadOnly
+        public bool IsReadOnly
         {
             get { return false; }
         }
 
-        void IValueProvider.SetValue(string value)
+        public void SetValue(string value)
         {
             string oldText = this.fooTextBox.Document.ToString(0);
             this.fooTextBox.Document.Replace(0,this.fooTextBox.Document.Length,value);
             this.RaisePropertyChangedEvent(ValuePatternIdentifiers.ValueProperty, oldText, this.fooTextBox.Document.ToString(0));
         }
 
-        string IValueProvider.Value
+        public string Value
         {
             get
             {
@@ -271,339 +282,8 @@ namespace FooEditEngine
         {
             return ProviderFromPeer(this);
         }
-    }
-
-    /// <summary>
-    /// A minimal implementation of ITextRangeProvider, used by CustomControl2AutomationPeer
-    /// A real implementation is beyond the scope of this sample
-    /// </summary>
-    sealed class FooTextBoxRangeProvider : ITextRangeProvider
-    {
-        private FooTextBox textbox;
-        private FooTextBoxAutomationPeer _peer;
-        private int start, end;
-
-        public FooTextBoxRangeProvider(FooTextBox textbox, FooTextBoxAutomationPeer peer)
-            : this(textbox,0,textbox.Document.Length,peer)
-        {
-        }
-        public FooTextBoxRangeProvider(FooTextBox textbox, int start, int length, FooTextBoxAutomationPeer peer)
-        {
-            this.textbox = textbox;
-            this.start = start;
-            this.end = start + length;
-            _peer = peer;
-        }
-
-        public void AddToSelection()
-        {
-            throw new InvalidOperationException();
-        }
-
-        public ITextRangeProvider Clone()
-        {
-            return new FooTextBoxRangeProvider(this.textbox,this.start,this.end - this.start, _peer);
-        }
-
-        public bool Compare(ITextRangeProvider o)
-        {
-            FooTextBoxRangeProvider other = o as FooTextBoxRangeProvider;
-            if (other == null)
-                throw new ArgumentNullException("null以外の値を指定してください");
-            if (this.start == other.start && this.end == other.end)
-                return true;
-            else
-                return false;
-        }
-
-        public int CompareEndpoints(TextPatternRangeEndpoint endpoint, ITextRangeProvider targetRange, TextPatternRangeEndpoint targetEndpoint)
-        {
-            FooTextBoxRangeProvider other = targetRange as FooTextBoxRangeProvider;
-            
-            if (other == null)
-                throw new ArgumentException("");
-
-            if (endpoint == TextPatternRangeEndpoint.Start)
-            {
-                if (targetEndpoint == TextPatternRangeEndpoint.Start)
-                    return this.Compare(this.start,other.start);
-                if(targetEndpoint == TextPatternRangeEndpoint.End)
-                    return this.Compare(this.start,other.end);
-            }
-            if (endpoint == TextPatternRangeEndpoint.End)
-            {
-                if (targetEndpoint == TextPatternRangeEndpoint.Start)
-                    return this.Compare(this.start, other.end);
-                if (targetEndpoint == TextPatternRangeEndpoint.End)
-                    return this.Compare(this.end, other.end);
-            }
-            throw new ArgumentException("endpointに未知の値が指定されました");
-        }
-
-        int Compare(int self, int other)
-        {
-            if (self < other)
-                return -1;
-            else if (self > other)
-                return 1;
-            else
-                return 0;
-        }
-
-        public void ExpandToEnclosingUnit(TextUnit unit)
-        {
-            Controller ctrl = this.textbox.Controller;
-            Document doc = this.textbox.Document;
-            if (unit == TextUnit.Character)
-            {
-                return;
-            }
-            if (unit == TextUnit.Format || unit == TextUnit.Word)
-            {
-                var t = doc.GetSepartor(this.start, (c) => Util.IsWordSeparator(c));
-                if (t == null)
-                    this.start = this.end = 0;
-                else
-                {
-                    this.start = t.Item1;
-                    this.end = t.Item2;
-                }
-                return;
-            }
-            if (unit == TextUnit.Line || unit == TextUnit.Paragraph)
-            {
-                var t = doc.GetSepartor(this.start, (c) => c == Document.NewLine);
-                if (t == null)
-                    this.start = this.end = 0;
-                else
-                {
-                    this.start = t.Item1;
-                    this.end = t.Item2;
-                }
-                return;
-            }
-            if (unit == TextUnit.Page || unit == TextUnit.Document)
-            {
-                this.start = 0;
-                this.end = this.textbox.Document.Length;
-                return;
-            }
-            throw new NotImplementedException();
-        }
 
-        public ITextRangeProvider FindAttribute(int attribute, Object value, bool backward)
-        {
-            return null;
-        }
-
-        public ITextRangeProvider FindText(String text, bool backward, bool ignoreCase)
-        {
-            if (backward)
-                throw new NotImplementedException();
-            textbox.Document.SetFindParam(text, false, ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None);
-            IEnumerator<SearchResult> it = textbox.Document.Find();
-            if (it.MoveNext())
-            {
-                SearchResult sr = it.Current;
-                return new FooTextBoxRangeProvider(this.textbox, sr.Start, sr.End - sr.Start + 1, _peer);
-            }
-            return null;
-        }
-
-        public Object GetAttributeValue(int attribute)
-        {
-            return null;
-        }
-
-#if METRO || WINDOWS_UWP
-        public void GetBoundingRectangles(out double[] rectangles)
-#endif
-#if WPF
-        public double[] GetBoundingRectangles()
-#endif
-        {
-            LineToIndexTable layoutLineCollection = this.textbox.LayoutLineCollection;
-            TextPoint topLeft = layoutLineCollection.GetTextPointFromIndex(this.start);
-            TextPoint bottomRight = this.textbox.LayoutLineCollection.GetTextPointFromIndex(IsNewLine(this.end) ? this.end - 1 : this.end);
-
-
-#if METRO || WINDOWS_UWP
-            float dpi;
-            Util.GetDpi(out dpi,out dpi);
-            double scale = dpi / 96;
-            Point topLeftPos = this.textbox.GetPostionFromTextPoint(topLeft);
-            Point bottomRightPos = this.textbox.GetPostionFromTextPoint(bottomRight);
-            topLeftPos = Util.GetPointInWindow(topLeftPos.Scale(scale),textbox);
-            bottomRightPos = Util.GetPointInWindow(bottomRightPos.Scale(scale),textbox);
-#endif
-#if WPF
-            Point topLeftPos = this.textbox.GetPostionFromTextPoint(topLeft);
-            Point bottomRightPos = this.textbox.GetPostionFromTextPoint(bottomRight);
-            topLeftPos = this.textbox.PointToScreen(topLeftPos);
-            bottomRightPos = this.textbox.PointToScreen(bottomRightPos);
-#endif
-
-            double width = bottomRightPos.X - topLeftPos.X;
-            if (width == 0)
-                width = 1;
-            Rectangle rect = new Rectangle(topLeftPos.X, topLeftPos.Y,
-                 width,
-                 bottomRightPos.Y - topLeftPos.Y + layoutLineCollection.GetLineHeight(bottomRight));
-
-#if METRO || WINDOWS_UWP
-            rectangles = new double[4]{
-                rect.X,
-                rect.Y,
-                rect.Width,
-                rect.Height
-            };
-#endif
-#if WPF
-            return new double[4]{
-                rect.X,
-                rect.Y,
-                rect.Width,
-                rect.Height
-            };
-#endif
-        }
-
-        bool IsNewLine(int index)
-        {
-            if (this.textbox.Document.Length > 0)
-                return this.textbox.Document[index == 0 ? 0 : index - 1] == Document.NewLine;
-            else
-                return false;
-        }
-
-        public IRawElementProviderSimple[] GetChildren()
-        {
-            return new IRawElementProviderSimple[0];
-        }
-
-        public IRawElementProviderSimple GetEnclosingElement()
-        {
-            return _peer.GetRawElementProviderSimple();
-        }
-
-        public String GetText(int maxLength)
-        {
-            if (this.textbox.Document.Length == 0)
-                return "";
-            int length = this.end - this.start;
-            if (maxLength < 0)
-                return this.textbox.Document.ToString(this.start, length);
-            else
-                return this.textbox.Document.ToString(this.start, (int)Math.Min(length, maxLength));
-        }
-
-        public int Move(TextUnit unit, int count)
-        {
-            if (count == 0)
-                return 0;
-            Controller ctrl = textbox.Controller;
-            LineToIndexTable layoutLine = textbox.LayoutLineCollection;
-            int moved = this.MoveEndpointByUnit(TextPatternRangeEndpoint.Start, unit, count);
-            this.ExpandToEnclosingUnit(unit);
-            return moved;
-        }
-
-        public void MoveEndpointByRange(TextPatternRangeEndpoint endpoint, ITextRangeProvider targetRange, TextPatternRangeEndpoint targetEndpoint)
-        {
-            FooTextBoxRangeProvider other = targetRange as FooTextBoxRangeProvider;
-
-            if (other == null)
-                throw new ArgumentException("");
-
-            if (endpoint == TextPatternRangeEndpoint.Start)
-            {
-                if (targetEndpoint == TextPatternRangeEndpoint.Start)
-                    this.start = other.start;
-                if (targetEndpoint == TextPatternRangeEndpoint.End)
-                    this.start = other.end;
-                if (this.start > this.end)
-                    this.end = this.start;
-                return;
-            }
-            if (endpoint == TextPatternRangeEndpoint.End)
-            {
-                if (targetEndpoint == TextPatternRangeEndpoint.Start)
-                    this.end = other.start;
-                if (targetEndpoint == TextPatternRangeEndpoint.End)
-                    this.end = other.end;
-                return;
-            }
-            throw new ArgumentException("endpointに未知の値が指定されました");
-        }
-
-        public int MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, TextUnit unit, int count)
-        {
-            if (count == 0)
-                return 0;
-
-            int moved = 0;
-            TextPoint caret = TextPoint.Null,newCaret = TextPoint.Null;
-            Controller ctrl = textbox.Controller;
-            LineToIndexTable layoutLine = textbox.LayoutLineCollection;
-
-            if (endpoint == TextPatternRangeEndpoint.Start)
-                caret = layoutLine.GetTextPointFromIndex(this.start);
-            else if (endpoint == TextPatternRangeEndpoint.End)
-                caret = layoutLine.GetTextPointFromIndex(this.end);
-
-            switch(unit)
-            {
-                case TextUnit.Character:
-                    newCaret = ctrl.GetNextCaret(caret, count, MoveFlow.Character, out moved);
-                    break;
-                case TextUnit.Format:
-                case TextUnit.Word:
-                    newCaret = ctrl.GetNextCaret(caret, count, MoveFlow.Word, out moved);
-                    break;
-                case TextUnit.Line:
-                    newCaret = ctrl.GetNextCaret(caret, count, MoveFlow.Line, out moved);
-                    break;
-                case TextUnit.Paragraph:
-                    newCaret = ctrl.GetNextCaret(caret, count, MoveFlow.Paragraph, out moved);
-                    break;
-                case TextUnit.Page:
-                case TextUnit.Document:
-                    this.start = 0;
-                    this.end = this.textbox.Document.Length - 1;
-                    moved = 1;
-                    break;
-            }
-
-            if (endpoint == TextPatternRangeEndpoint.Start)
-            {
-                this.start = layoutLine.GetIndexFromTextPoint(newCaret);
-                if (this.start > this.end)
-                    this.end = this.start;
-            }
-            else if (endpoint == TextPatternRangeEndpoint.End)
-            {
-                this.end = layoutLine.GetIndexFromTextPoint(newCaret);
-                if (this.end < this.start)
-                    this.start = this.end;
-            }
-            return moved;
-        }
-
-        public void RemoveFromSelection()
-        {
-            throw new InvalidOperationException();
-        }
-
-        public void ScrollIntoView(bool alignToTop)
-        {
-            int row = this.textbox.LayoutLineCollection.GetLineNumberFromIndex(alignToTop ? this.start : this.end);
-            this.textbox.ScrollIntoView(row, alignToTop);
-        }
-
-        public void Select()
-        {
-            this.textbox.Select(this.start, this.end - this.start + 1);
-        }
     }
+
 #endif
 }