OSDN Git Service

ドラッグしながらの選択ができなくなるので元に戻した
[fooeditengine/FooEditEngine.git] / WPF / FooEditEngine / FooTextBox.cs
index 145dcd2..30a3bb8 100644 (file)
@@ -28,13 +28,6 @@ using Microsoft.Win32;
 namespace FooEditEngine.WPF
 {
     /// <summary>
-    /// オートインデントを行うためのデリゲートを表す
-    /// </summary>
-    /// <param name="sender">イベント発生元のオブジェクト</param>
-    /// <param name="e">イベントデーター</param>
-    public delegate void AutoIndentHookerHandler(object sender,EventArgs e);
-
-    /// <summary>
     /// WPFでのFooTextBoxの実装
     /// </summary>
     public sealed class FooTextBox : Control, IDisposable
@@ -51,9 +44,13 @@ namespace FooEditEngine.WPF
         DispatcherTimer timer;
         bool disposed = false;
         FooTextBoxAutomationPeer peer;
-        bool nowCaretMove = false;
+        bool isNotifyChanged = false;
         Document _Document;
-        
+        Popup popup;
+
+        const int Interval = 96;
+        const int IntervalWhenLostFocuse = 160;
+
         static FooTextBox()
         {
             DefaultStyleKeyProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(typeof(FooTextBox)));
@@ -66,6 +63,8 @@ namespace FooEditEngine.WPF
         /// </summary>
         public FooTextBox()
         {
+            this.popup = new Popup();
+
             this.image = new Image();
             this.image.Stretch = Stretch.Fill;
             this.image.HorizontalAlignment = HorizontalAlignment.Left;
@@ -87,9 +86,6 @@ namespace FooEditEngine.WPF
             this.textStore.CompositionEnded += textStore_CompositionEnded;
 
             this.Render = new D2DRender(this, 200, 200,this.image);
-            this.Render.ShowFullSpace = this.ShowFullSpace;
-            this.Render.ShowHalfSpace = this.ShowHalfSpace;
-            this.Render.ShowTab = this.ShowTab;
 
             this.Document = new Document();
 
@@ -102,6 +98,9 @@ namespace FooEditEngine.WPF
             this.Document.HideRuler = !this.DrawRuler;
             this.Document.UrlMark = this.MarkURL;
             this.Document.TabStops = this.TabChars;
+            this.Document.ShowFullSpace = this.ShowFullSpace;
+            this.Document.ShowHalfSpace = this.ShowHalfSpace;
+            this.Document.ShowTab = this.ShowTab;
 
             this._Controller = new Controller(this.Document, this.View);
             this._Document.SelectionChanged += new EventHandler(Controller_SelectionChanged);
@@ -129,7 +128,7 @@ namespace FooEditEngine.WPF
             this.InputBindings.Add(new InputBinding(FooTextBoxCommands.ToggleCodePoint, new KeyGesture(Key.X, ModifierKeys.Alt)));
 
             this.timer = new DispatcherTimer();
-            this.timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
+            this.timer.Interval = new TimeSpan(0, 0, 0, 0, Interval);
             this.timer.Tick += new EventHandler(timer_Tick);
 
             this.Loaded += new RoutedEventHandler(FooTextBox_Loaded);
@@ -141,6 +140,8 @@ namespace FooEditEngine.WPF
             this.SystemEvents_UserPreferenceChanged(null, new UserPreferenceChangedEventArgs(UserPreferenceCategory.Keyboard));
 
             this.CaretMoved += (s, e) => { };
+
+            this.IsManipulationEnabled = true;
         }
 
         /// <summary>
@@ -155,6 +156,7 @@ namespace FooEditEngine.WPF
         /// <summary>
         /// オートインデントを行うためのイベント
         /// </summary>
+        [Obsolete]
         public AutoIndentHookerHandler AutoIndentHooker;
 
         /// <summary>
@@ -170,6 +172,12 @@ namespace FooEditEngine.WPF
                 Grid.SetRow(this.image, 0);
                 Grid.SetColumn(this.image, 0);
                 grid.Children.Add(this.image);
+
+                Grid.SetRow(this.popup, 0);
+                Grid.SetColumn(this.popup, 0);
+                grid.Children.Add(this.popup);
+                //this.popup.PlacementTarget = this;
+                this.popup.Placement = PlacementMode.Absolute;
             }
 
             this.horizontalScrollBar = this.GetTemplateChild("PART_HorizontalScrollBar") as ScrollBar;
@@ -185,7 +193,7 @@ namespace FooEditEngine.WPF
             {
                 this.verticalScrollBar.SmallChange = 1;
                 this.verticalScrollBar.LargeChange = 10;
-                this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;
+                this.verticalScrollBar.Maximum = this.Document.LayoutLines.Count - 1;
                 this.verticalScrollBar.Scroll += new ScrollEventHandler(verticalScrollBar_Scroll);
             }
         }
@@ -361,8 +369,7 @@ namespace FooEditEngine.WPF
         /// <returns>Taskオブジェクト</returns>
         public async Task LoadAsync(System.IO.TextReader tr, System.Threading.CancellationTokenSource token)
         {
-            WinFileReader fs = new WinFileReader(tr);
-            await this.LoadAsyncImpl(fs, token);
+            await this.Document.LoadAsync(tr, token);
         }
 
         /// <summary>
@@ -374,22 +381,27 @@ namespace FooEditEngine.WPF
         /// <returns>Taskオブジェクト</returns>
         public async Task LoadFileAsync(string filepath, Encoding enc,System.Threading.CancellationTokenSource token)
         {
-            WinFileReader fs = new WinFileReader(filepath, enc);
-            await this.LoadAsyncImpl(fs, token);
+            var fs = new System.IO.StreamReader(filepath, enc);
+            await this.Document.LoadAsync(fs, token);
             fs.Close();
         }
 
-        async Task LoadAsyncImpl(WinFileReader fs,System.Threading.CancellationTokenSource token)
+        private void Document_LoadProgress(object sender, ProgressEventArgs e)
         {
-            this.IsEnabled = false;
-            this.View.LayoutLines.IsFrozneDirtyFlag = true;
-            await this.Document.LoadAsync(fs, token);
-            this.View.LayoutLines.IsFrozneDirtyFlag = false;
-            TextStoreHelper.NotifyTextChanged(this.textStore, 0, 0, this.Document.Length);
-            if (this.verticalScrollBar != null)
-                this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;
-            this.View.CalculateLineCountOnScreen();
-            this.IsEnabled = true;
+            if (e.state == ProgressState.Start)
+            {
+                this.IsEnabled = false;
+            }
+            else if (e.state == ProgressState.Complete)
+            {
+                TextStoreHelper.NotifyTextChanged(this.textStore, 0, 0, this.Document.Length);
+                if (this.verticalScrollBar != null)
+                    this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;
+                this.View.CalculateWhloeViewPort();
+                this.View.CalculateLineCountOnScreen();
+                this.IsEnabled = true;
+                this.Refresh(this.View.PageBound);
+            }
         }
 
         /// <summary>
@@ -398,10 +410,11 @@ namespace FooEditEngine.WPF
         /// <param name="filepath">ファイルパス</param>
         /// <param name="newLine">改行コード</param>
         /// <param name="enc">エンコード</param>
+        /// <param name="token">キャンセル用トークン</param>
         /// <returns>Taskオブジェクト</returns>
         public async Task SaveFile(string filepath, Encoding enc,string newLine, System.Threading.CancellationTokenSource token)
         {
-            WinFileWriter fs = new WinFileWriter(filepath, enc);
+            var fs = new System.IO.StreamWriter(filepath, false , enc);
             fs.NewLine = newLine;
             await this.Document.SaveAsync(fs, token);
             fs.Close();
@@ -440,12 +453,8 @@ namespace FooEditEngine.WPF
             if (this.disposed || this.Visibility == Visibility.Collapsed)
                 return;
 
-            this.Render.BegineDraw();
-            if (this.IsEnabled)
-                this.View.Draw(updateRect);
-            else
-                this.Render.FillBackground(updateRect);
-            this.Render.EndDraw();
+            this.Render.DrawContent(this.View, this.IsEnabled, updateRect);
+            this.Document.IsRequestRedraw = false;
         }
 
         #region Commands
@@ -611,14 +620,20 @@ namespace FooEditEngine.WPF
             o_bottomRight = new POINT((int)pointBottomRight.X, (int)pointBottomRight.Y);
         }
 
-        void _textStore_GetSelectionIndex(out int o_startIndex, out int o_endIndex)
+        void _textStore_GetSelectionIndex(int start_index, int max_count, out DotNetTextStore.TextSelection[] sels)
         {
-            TextStoreHelper.GetSelection(this._Controller, this.View.Selections, out o_startIndex, out o_endIndex);
+            TextRange selRange;
+            TextStoreHelper.GetSelection(this._Controller, this.View.Selections, out selRange);
+
+            sels = new DotNetTextStore.TextSelection[1];
+            sels[0] = new DotNetTextStore.TextSelection();
+            sels[0].start = selRange.Index;
+            sels[0].end = selRange.Index + selRange.Length;
         }
 
-        void _textStore_SetSelectionIndex(int i_startIndex, int i_endIndex)
+        void _textStore_SetSelectionIndex(DotNetTextStore.TextSelection[] sels)
         {
-            TextStoreHelper.SetSelectionIndex(this._Controller, this.View, i_startIndex, i_endIndex);
+            TextStoreHelper.SetSelectionIndex(this._Controller, this.View, sels[0].start, sels[0].end);
             this.Refresh();
         }
 
@@ -637,6 +652,7 @@ namespace FooEditEngine.WPF
             base.OnGotKeyboardFocus(e);
             this.textStore.SetFocus();
             this.View.IsFocused = true;
+            this.timer.Interval = new TimeSpan(0,0,0,0,Interval);
             this.Refresh();
         }
 
@@ -648,6 +664,7 @@ namespace FooEditEngine.WPF
         {
             base.OnLostKeyboardFocus(e);
             this.View.IsFocused = false;
+            this.timer.Interval = new TimeSpan(0, 0, 0, 0, IntervalWhenLostFocuse);
             this.Refresh();
         }
         #endregion
@@ -705,6 +722,15 @@ namespace FooEditEngine.WPF
                 return;
 
             ModifierKeys modiferKeys = e.KeyboardDevice.Modifiers;
+
+            var autocomplete = this.Document.AutoComplete as AutoCompleteBox;
+            if (autocomplete != null &&
+                autocomplete.ProcessKeyDown(this,e, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control), this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift)))
+            {
+                e.Handled = true;
+                return;
+            }
+
             bool movedCaret = false;
             switch (e.Key)
             {
@@ -813,8 +839,11 @@ namespace FooEditEngine.WPF
 
             if (e.LeftButton == MouseButtonState.Pressed)
             {
+                if (p.X < this.Render.TextArea.X)
+                    this.Document.SelectLine((int)index);
+                else
+                    this.Document.SelectWord((int)index);
 
-                this.Document.SelectWord(index);
                 this.textStore.NotifySelectionChanged();
                 if(this.peer != null)
                     this.peer.OnNotifyCaretChanged();
@@ -832,6 +861,8 @@ namespace FooEditEngine.WPF
         /// </remarks>
         protected override void OnMouseDown(MouseButtonEventArgs e)
         {
+            this.CaptureMouse();
+
             var p = this.GetDipFromPoint(e.GetPosition(this));
             TextPoint tp = this.View.GetTextPointFromPostion(p);
             if (tp == TextPoint.Null)
@@ -868,11 +899,23 @@ namespace FooEditEngine.WPF
                     this.peer.OnNotifyCaretChanged();
                 this.View.IsFocused = true;
                 this.Focus();
+                this.Document.SelectGrippers.BottomLeft.Enabled = false;
+                this.Document.SelectGrippers.BottomRight.Enabled = false;
                 this.Refresh();
             }
         }
 
         /// <summary>
+        /// マウスのボタンが離されたときに呼ばれます
+        /// </summary>
+        /// <param name="e"></param>
+        protected override void OnMouseUp(MouseButtonEventArgs e)
+        {
+            this.ReleaseMouseCapture();
+            base.OnMouseUp(e);
+        }
+
+        /// <summary>
         /// マウスが移動したときに呼ばれます
         /// </summary>
         /// <param name="e">イベントパラメーター</param>
@@ -882,13 +925,35 @@ namespace FooEditEngine.WPF
         /// </remarks>
         protected override void  OnMouseMove(MouseEventArgs e)
         {
+            bool leftPressed = e.LeftButton == MouseButtonState.Pressed;
+
             var p = this.GetDipFromPoint(e.GetPosition(this));
-            TextPoint tp = this.View.GetTextPointFromPostion(p);
+
+            TextPointSearchRange searchRange;
+            if (this.View.HitTextArea(p.X, p.Y))
+            {
+                searchRange = TextPointSearchRange.TextAreaOnly;
+            }
+            else if (leftPressed)
+            {
+                searchRange = TextPointSearchRange.Full;
+            }
+            else
+            {
+                this.Cursor = Cursors.Arrow;
+                base.OnMouseMove(e);
+                return;
+            }
+
+            TextPoint tp = this.View.GetTextPointFromPostion(p, searchRange);
+
             if (tp == TextPoint.Null)
             {
+                this.Cursor = Cursors.Arrow;
                 base.OnMouseMove(e);
                 return;
             }
+
             int index = this.View.GetIndexFromLayoutLine(tp);
 
             FooMouseEventArgs newEventArgs = new FooMouseEventArgs(e.MouseDevice, e.Timestamp, e.StylusDevice, index);
@@ -898,25 +963,126 @@ namespace FooEditEngine.WPF
             if (newEventArgs.Handled)
                 return;
 
-            if (this.View.HitTextArea(p.X,p.Y))
+            //この状態のときはカーソルがテキストエリア内にある
+            if (searchRange == TextPointSearchRange.TextAreaOnly)
             {
                 if (this._Controller.IsMarker(tp, HilightType.Url))
                     this.Cursor = Cursors.Hand;
                 else
                     this.Cursor = Cursors.IBeam;
-
-                if (e.LeftButton == MouseButtonState.Pressed)
-                {
-                    this._Controller.MoveCaretAndSelect(tp);
-                    if (this.peer != null)
-                        this.peer.OnNotifyCaretChanged();
-                    this.Refresh();
-                }
             }
             else
             {
                 this.Cursor = Cursors.Arrow;
             }
+            if (leftPressed)
+            {
+                bool controlPressed = (Keyboard.GetKeyStates(Key.LeftCtrl) & KeyStates.Down) == KeyStates.Down;
+                this._Controller.MoveCaretAndSelect(tp, controlPressed);
+                if (this.peer != null)
+                    this.peer.OnNotifyCaretChanged();
+                this.Refresh();
+            }
+        }
+
+        Gripper hittedGripper;
+        bool touchScrolled = false;
+
+        /// <inheritdoc/>
+        protected override void OnTouchDown(TouchEventArgs e)
+        {
+            var p = this.GetDipFromPoint(e.GetTouchPoint(this).Position);
+            this.hittedGripper = this.View.HitGripperFromPoint(p);
+            this.CaptureTouch(e.TouchDevice);
+        }
+
+        /// <inheritdoc/>
+        protected override void OnTouchUp(TouchEventArgs e)
+        {
+            this.ReleaseTouchCapture(e.TouchDevice);
+            if(this.hittedGripper != null || this.touchScrolled)
+            {
+                this.hittedGripper = null;
+                this.touchScrolled = false;
+                return;
+            }
+
+            var p = this.GetDipFromPoint(e.GetTouchPoint(this).Position);
+            TextPoint tp = this.View.GetTextPointFromPostion(p);
+            if (tp == TextPoint.Null)
+                return;
+            int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);
+
+            FoldingItem foldingData = this.View.HitFoldingData(p.X, tp.row);
+            if (foldingData != null)
+            {
+                if (foldingData.Expand)
+                    this.View.LayoutLines.FoldingCollection.Collapse(foldingData);
+                else
+                    this.View.LayoutLines.FoldingCollection.Expand(foldingData);
+                this._Controller.JumpCaret(foldingData.Start, false);
+            }
+            else
+            {
+                this._Controller.JumpCaret(tp.row, tp.col, false);
+            }
+            if (this.peer != null)
+                this.peer.OnNotifyCaretChanged();
+            this.View.IsFocused = true;
+            this.Focus();
+            this.Document.SelectGrippers.BottomLeft.Enabled = false;
+            this.Document.SelectGrippers.BottomRight.Enabled = true;
+            this.Refresh();
+        }
+
+        /// <inheritdoc/>
+        protected override void OnTouchMove(TouchEventArgs e)
+        {
+            var p = this.GetDipFromPoint(e.GetTouchPoint(this).Position);
+            if (this.Controller.MoveCaretAndGripper(p, this.hittedGripper))
+            {
+                if (this.peer != null)
+                    this.peer.OnNotifyCaretChanged();
+                this.Refresh();
+            }
+        }
+
+        /// <inheritdoc/>
+        protected override void OnManipulationInertiaStarting(ManipulationInertiaStartingEventArgs e)
+        {
+        }
+
+        /// <inheritdoc/>
+        protected override void OnManipulationDelta(ManipulationDeltaEventArgs e)
+        {
+            if (this.hittedGripper != null)
+                return;
+
+            Point translation = new Point(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);
+
+            //Xの絶対値が大きければ横方向のスクロールで、そうでなければ縦方向らしい
+            if (Math.Abs(e.CumulativeManipulation.Translation.X) < Math.Abs(e.CumulativeManipulation.Translation.Y))
+            {
+                int deltay = (int)Math.Abs(Math.Ceiling(translation.Y));
+                if (translation.Y < 0)
+                    this._Controller.ScrollByPixel(ScrollDirection.Down, deltay, false, false);
+                else
+                    this._Controller.ScrollByPixel(ScrollDirection.Up, deltay, false, false);
+                this.touchScrolled = true;
+                this.Refresh();
+                return;
+            }
+
+            int deltax = (int)Math.Abs(Math.Ceiling(translation.X));
+            if (deltax != 0)
+            {
+                if (translation.X < 0)
+                    this._Controller.Scroll(ScrollDirection.Left, deltax, false, false);
+                else
+                    this._Controller.Scroll(ScrollDirection.Right, deltax, false, false);
+                this.touchScrolled = true;
+                this.Refresh();
+            }
         }
 
         private Point GetDipFromPoint(Point p)
@@ -985,14 +1151,14 @@ namespace FooEditEngine.WPF
                 return;
             if (this.Resize(this.image.ActualWidth, this.image.ActualHeight))
             {
-                this.Refresh();
+                this.Refresh(this.View.PageBound);
                 return;
             }
 
-            bool updateAll = this.View.LayoutLines.HilightAll() || this.View.LayoutLines.GenerateFolding();
+            bool updateAll = this.View.LayoutLines.HilightAll() || this.View.LayoutLines.GenerateFolding() || this.Document.IsRequestRedraw;
 
             if (updateAll)
-                this.Refresh();
+                this.Refresh(this.View.PageBound);
             else
                 this.Refresh(this.View.GetCurrentCaretRect());
         }
@@ -1006,7 +1172,7 @@ namespace FooEditEngine.WPF
                 toX = this.horizontalScrollBar.Value;
             else
                 toX = -this.horizontalScrollBar.Value;
-            this._Controller.Scroll(toX, this.View.Src.Row, false, false);
+            this.Controller.ScrollByPixel(ScrollDirection.Left, (int)toX, false, false);
             this.Refresh();
         }
 
@@ -1014,10 +1180,7 @@ namespace FooEditEngine.WPF
         {
             if (this.verticalScrollBar == null)
                 return;
-            int newRow = (int)this.verticalScrollBar.Value;
-            if (newRow >= this.View.LayoutLines.Count)
-                return;
-            this._Controller.Scroll(this.View.Src.X,newRow, false, false);
+            this.Controller.Scroll(this.Document.Src.X, (int)this.verticalScrollBar.Value, false, false);
             this.Refresh();
         }
 
@@ -1026,8 +1189,8 @@ namespace FooEditEngine.WPF
             if (this.horizontalScrollBar == null || this.verticalScrollBar == null)
                 return;
             EditView view = this.View;
-            if (view.Src.Row > this.verticalScrollBar.Maximum)
-                this.verticalScrollBar.Maximum = view.Src.Row + view.LineCountOnScreen + 1;
+            if (view.Src.Row > this.Document.LayoutLines.Count)
+                this.verticalScrollBar.Maximum = this.Document.LayoutLines.Count - 1;
             double absoulteX = Math.Abs(view.Src.X);
             if(absoulteX > this.horizontalScrollBar.Maximum)
                 this.horizontalScrollBar.Maximum = absoulteX + view.PageBound.Width + 1;
@@ -1042,11 +1205,12 @@ namespace FooEditEngine.WPF
             this.View.CaretBlink = this.View.CaretBlink;
             this.CaretMoved(this, null);
             //こうしないと選択できなくなってしまう
-            this.nowCaretMove = true;
+            this.isNotifyChanged = true;
+            SetValue(SelectedTextProperty, this._Controller.SelectedText);
             SetValue(SelectionProperty, new TextRange(this._Controller.SelectionStart, this._Controller.SelectionLength));
             SetValue(CaretPostionProperty, this.Document.CaretPostion);
-            this.nowCaretMove = false;            
-            if(this.textStore.IsLocked() == false)
+            this.isNotifyChanged = false;
+            if (this.textStore.IsLocked() == false)
                 this.textStore.NotifySelectionChanged();
         }
 
@@ -1082,6 +1246,78 @@ namespace FooEditEngine.WPF
             return false;
         }
 
+        private void SetDocument(Document value)
+        {
+            if (value == null)
+                return;
+
+            Document old_doc = this._Document;
+            int oldLength = 0;
+            if (this._Document != null)
+            {
+                old_doc.Update -= new DocumentUpdateEventHandler(Document_Update);
+                old_doc.LoadProgress -= Document_LoadProgress;
+                old_doc.SelectionChanged -= new EventHandler(Controller_SelectionChanged);
+                old_doc.AutoCompleteChanged -= _Document_AutoCompleteChanged;
+                oldLength = old_doc.Length;
+                if (this._Document.AutoComplete != null)
+                {
+                    ((AutoCompleteBox)this._Document.AutoComplete).TargetPopup = null;
+                    this._Document.AutoComplete.GetPostion = null;
+                    this._Document.AutoComplete = null;
+                }
+            }
+
+            this._Document = value;
+            this._Document.LayoutLines.Render = this.Render;
+            this._Document.Update += new DocumentUpdateEventHandler(Document_Update);
+            this._Document.LoadProgress += Document_LoadProgress;
+            this._Document.AutoCompleteChanged += _Document_AutoCompleteChanged;
+            if (this._Document.AutoComplete != null && this.Document.AutoComplete.GetPostion == null)
+                this._Document_AutoCompleteChanged(this.Document, null);
+            //初期化が終わっていればすべて存在する
+            if (this.Controller != null && this.View != null && this.textStore != null)
+            {
+                this._Document.SelectionChanged += new EventHandler(Controller_SelectionChanged);
+
+                this.Controller.Document = value;
+                this.View.Document = value;
+                this.Controller.AdjustCaret();
+                this.textStore.NotifyTextChanged(oldLength, value.Length);
+
+                //依存プロパティとドキュメント内容が食い違っているので再設定する
+                this.ShowFullSpace = value.ShowFullSpace;
+                this.ShowHalfSpace = value.ShowHalfSpace;
+                this.ShowLineBreak = value.ShowLineBreak;
+                this.ShowTab = value.ShowTab;
+                this.FlowDirection = value.RightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
+                this.IndentMode = value.IndentMode;
+                this.DrawCaretLine = !value.HideLineMarker;
+                this.InsertMode = value.InsertMode;
+                this.DrawRuler = !value.HideRuler;
+                this.DrawLineNumber = value.DrawLineNumber;
+                this.MarkURL = value.UrlMark;
+                this.LineBreakMethod = value.LineBreak;
+                this.LineBreakCharCount = value.LineBreakCharCount;
+                this.TabChars = value.TabStops;
+
+                this.Refresh();
+            }
+        }
+
+        private void _Document_AutoCompleteChanged(object sender, EventArgs e)
+        {
+            Document doc = (Document)sender;
+            ((AutoCompleteBox)this._Document.AutoComplete).TargetPopup = this.popup;
+            this._Document.AutoComplete.GetPostion = (tp, edoc) =>
+            {
+                var p = this.View.GetPostionFromTextPoint(tp);
+                int height = (int)this.Render.emSize.Height;
+                p.Y += height;
+                return PointToScreen(this.TranslatePoint(p.Scale(Util.GetScale()), this));
+            };
+        }
+
         /// <summary>
         /// プロパティーが変更されたときに呼ばれます
         /// </summary>
@@ -1090,15 +1326,31 @@ namespace FooEditEngine.WPF
         {
             switch (e.Property.Name)
             {
+                case "Document":
+                    this.SetDocument(this.Document);
+                    break;
+                case "Hilighter":
+                    this.View.Hilighter = this.Hilighter;
+                    break;
+                case "TextAntialiasMode":
+                    this.Render.TextAntialiasMode = this.TextAntialiasMode;
+                    break;
+                case "FoldingStrategy":
+                    this.View.LayoutLines.FoldingStrategy = this.FoldingStrategy;
+                    break;
+                case "SelectedText":
+                    if (!this.isNotifyChanged)
+                        this._Controller.SelectedText = this.SelectedText;
+                    break;
                 case "IndentMode":
                     this._Controller.IndentMode = this.IndentMode;
                     break;
                 case "Selection":
-                    if(!this.nowCaretMove)
+                    if(!this.isNotifyChanged)
                         this.Select(this.Selection.Index, this.Selection.Length);
                     break;
                 case "CaretPostion":
-                    if (!this.nowCaretMove)
+                    if (!this.isNotifyChanged)
                         this.JumpCaret(this.CaretPostion.row, this.CaretPostion.col);
                     break;
                 case "LineBreakMethod":
@@ -1140,6 +1392,9 @@ namespace FooEditEngine.WPF
                 case "Foreground":
                     this.Render.Foreground = D2DRender.ToColor4(this.Foreground);
                     break;
+                case "HilightForeground":
+                    this.Render.HilightForeground = D2DRender.ToColor4(this.HilightForeground);
+                    break;
                 case "Background":
                     this.Render.Background = D2DRender.ToColor4(this.Background);
                     break;
@@ -1224,50 +1479,48 @@ namespace FooEditEngine.WPF
         /// </summary>
         public TextAntialiasMode TextAntialiasMode
         {
-            get
-            {
-                return this.Render.TextAntialiasMode;
-            }
-            set
-            {
-                this.Render.TextAntialiasMode = value;
-            }
+            get { return (TextAntialiasMode)GetValue(TextAntialiasModeProperty); }
+            set { SetValue(TextAntialiasModeProperty, value); }
         }
 
         /// <summary>
+        /// TextAntialiasModeの依存プロパティを表す
+        /// </summary>
+        public static readonly DependencyProperty TextAntialiasModeProperty =
+            DependencyProperty.Register("TextAntialiasMode", typeof(TextAntialiasMode), typeof(FooTextBox), new PropertyMetadata(TextAntialiasMode.Default));
+
+        /// <summary>
         /// シンタックスハイライターを表す
         /// </summary>
         public IHilighter Hilighter
         {
-            get
-            {
-                return this.View.Hilighter;
-            }
-            set
-            {
-                this.View.Hilighter = value;
-                this.View.LayoutLines.ClearLayoutCache();
-            }
+            get { return (IHilighter)GetValue(HilighterProperty); }
+            set { SetValue(HilighterProperty, value); }
         }
 
         /// <summary>
+        /// Hilighterの依存プロパティを表す
+        /// </summary>
+        public static readonly DependencyProperty HilighterProperty =
+            DependencyProperty.Register("Hilighter", typeof(IHilighter), typeof(FooTextBox), new PropertyMetadata(null));
+
+        /// <summary>
         /// フォールティングを作成するインターフェイスを表す
         /// </summary>
         public IFoldingStrategy FoldingStrategy
         {
-            get
-            {
-                return this.View.LayoutLines.FoldingStrategy;
-            }
-            set
-            {
-                this.View.LayoutLines.FoldingStrategy = value;
-                if (value == null)
-                    this.View.LayoutLines.FoldingCollection.Clear();
-            }
+            get { return (IFoldingStrategy)GetValue(FoldingStrategyProperty); }
+            set { SetValue(FoldingStrategyProperty, value); }
         }
 
         /// <summary>
+        /// FoldingStrategyの依存プロパティ
+        /// </summary>
+        public static readonly DependencyProperty FoldingStrategyProperty =
+            DependencyProperty.Register("FoldingStrategy", typeof(IFoldingStrategy), typeof(FooTextBox), new PropertyMetadata(null));
+
+
+        /// <summary>
         /// マーカーパターンセット
         /// </summary>
         public MarkerPatternSet MarkerPatternSet
@@ -1279,55 +1532,20 @@ namespace FooEditEngine.WPF
         }
 
         /// <summary>
-        /// ドキュメント表す
+        /// ドキュメント表す
         /// </summary>
         public Document Document
         {
-            get
-            {
-                return this._Document;
-            }
-            set
-            {
-                Document old_doc = this._Document;
-                int oldLength = 0;
-                if(this._Document != null)
-                {
-                    old_doc.Update -= new DocumentUpdateEventHandler(Document_Update);
-                    oldLength = old_doc.Length;
-                }
+            get { return (Document)GetValue(DocumentProperty); }
+            set { SetValue(DocumentProperty, value); }
+        }
 
-                this._Document = value;
-                this._Document.LayoutLines.Render = this.Render;
-                this._Document.Update += new DocumentUpdateEventHandler(Document_Update);
-                //初期化が終わっていればすべて存在する
-                if(this.Controller != null && this.View != null && this.textStore != null)
-                {
-                    this.Controller.Document = value;
-                    this.View.Document = value;
-                    this.Controller.AdjustCaret();
-                    this.textStore.NotifyTextChanged(oldLength, value.Length);
-
-                    //依存プロパティとドキュメント内容が食い違っているので再設定する
-                    this.ShowFullSpace = value.ShowFullSpace;
-                    this.ShowHalfSpace = value.ShowHalfSpace;
-                    this.ShowLineBreak = value.ShowLineBreak;
-                    this.ShowTab = value.ShowTab;
-                    this.FlowDirection = value.RightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
-                    this.IndentMode = value.IndentMode;
-                    this.DrawCaretLine = !value.HideLineMarker;
-                    this.InsertMode = value.InsertMode;
-                    this.DrawRuler = !value.HideRuler;
-                    this.DrawLineNumber = value.DrawLineNumber;
-                    this.MarkURL = value.UrlMark;
-                    this.LineBreakMethod = value.LineBreak;
-                    this.LineBreakCharCount = value.LineBreakCharCount;
-                    this.TabChars = value.TabStops;
+        /// <summary>
+        /// ドキュメント添付プロパティ
+        /// </summary>
+        public static readonly DependencyProperty DocumentProperty =
+            DependencyProperty.Register("Document", typeof(Document), typeof(FooTextBox), new PropertyMetadata(null));
 
-                    this.Refresh();
-                }
-            }
-        }
 
         /// <summary>
         /// レイアウト行を表す
@@ -1342,18 +1560,17 @@ namespace FooEditEngine.WPF
         /// </summary>
         public string SelectedText
         {
-            get
-            {
-                return this._Controller.SelectedText;
-            }
-            set
-            {
-                int oldLength = this.Document.Length;
-                this._Controller.SelectedText = value;
-            }
+            get { return (string)GetValue(SelectedTextProperty); }
+            set { SetValue(SelectedTextProperty, value); }
         }
 
         /// <summary>
+        /// SelectedTextの依存プロパティを表す
+        /// </summary>
+        public static readonly DependencyProperty SelectedTextProperty =
+            DependencyProperty.Register("SelectedText", typeof(string), typeof(FooTextBox), new PropertyMetadata(null));
+
+        /// <summary>
         /// インデントの方法を表す
         /// </summary>
         public IndentMode IndentMode
@@ -1460,7 +1677,22 @@ namespace FooEditEngine.WPF
         /// </summary>
         public new static readonly DependencyProperty BackgroundProperty =
             DependencyProperty.Register("Background", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowColor));
-        
+
+        /// <summary>
+        /// 選択時の文字色を表す。これは依存プロパティです
+        /// </summary>
+        public System.Windows.Media.Color HilightForeground
+        {
+            get { return (System.Windows.Media.Color)GetValue(HilightForegroundProperty); }
+            set { SetValue(HilightForegroundProperty, value); }
+        }
+
+        /// <summary>
+        /// ControlCharの依存プロパティを表す
+        /// </summary>
+        public static readonly DependencyProperty HilightForegroundProperty =
+            DependencyProperty.Register("HilightForeground", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.White));
+
         /// <summary>
         /// コントロールコードの文字色を表す。これは依存プロパティです
         /// </summary>