/* * ダブルクリックで単語を選択します。 * 単語の文字はIsLetterOrDigitか'_'とします。 */ public void SelectByDoubleClick(int start_pos) { Debug.WriteLine("ダブルクリック"); // マウス位置にテキストがある場合 // 単語の始まりを探します。 int phrase_start = start_pos; for (; 0 <= phrase_start && (Char.IsLetterOrDigit(Chars[phrase_start].Chr) || Chars[phrase_start].Chr == '_'); phrase_start--) { ; } phrase_start++; // 単語の終わりを探します。 int phrase_end = start_pos; for (; phrase_end < Chars.Count && (Char.IsLetterOrDigit(Chars[phrase_end].Chr) || Chars[phrase_end].Chr == '_'); phrase_end++) { ; } // 単語の始まりと終わりを選択します SelOrigin = phrase_start; SelCurrent = phrase_end; // テキストの選択位置の変更をIMEに伝えます。 MyNotifySelectionChanged(); // 再描画します。 Win2DCanvas.Invalidate(); }
/* * ScrollViewerがスクロールした。 */ private void EditScroll_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e) { Debug.WriteLine("<<--- ViewChanged"); // 再描画します。 Win2DCanvas.Invalidate(); }
/* * かな漢字変換の途中で表示するテキストの書式を指定してきた。 */ private void EditContext_FormatUpdating(CoreTextEditContext sender, CoreTextFormatUpdatingEventArgs ev) { Debug.WriteLine("<<--- FormatUpdating: BG:{0} cancel:{1} range:({2},{3}) reason:{4} result:{5} color:{6} under-line:({7},{8})", (ev.BackgroundColor == null ? "null" : ev.BackgroundColor.Value.ToString()), ev.IsCanceled, ev.Range.StartCaretPosition, ev.Range.EndCaretPosition, ev.Reason, ev.Result, (ev.TextColor == null ? "null" : ev.TextColor.Value.ToString()), (ev.UnderlineColor == null ? "null" : ev.UnderlineColor.Value.ToString()), (ev.UnderlineType == null ? "null" : ev.UnderlineType.Value.ToString()) ); if (ev.UnderlineType != null) { // 下線がnullでない場合 // 選択範囲の文字の下線を指定します。 for (int i = ev.Range.StartCaretPosition; i < ev.Range.EndCaretPosition; i++) { // TCharはstructなので Chars[i]=ev.UnderlineType.Value; と書くとエラーになります。 TChar ch = Chars[i]; ch.Underline = ev.UnderlineType.Value; Chars[i] = ch; } } // 再描画します。 Win2DCanvas.Invalidate(); }
/* * ボタンがフォーカスを取得した。 * TextBlockはフォーカスの取得/喪失の管理ができないので、TextBlockの上に透明のRadioButtonをかぶせてフォーカスの管理をしています。 */ private async void OverlappedButton_GotFocus(object sender, RoutedEventArgs e) { Debug.WriteLine("<<--- Button GotFocus"); if (DesignMode.DesignModeEnabled) { // ビューデザイナーの中で動作している場合は何もしない。 return; } if (textServiceManager == null) { // 初めての場合 // 少し待たないと「漢字」キーが効かない。 await Task.Delay(500); // CoreTextServicesManagerを作ります。 Debug.WriteLine("--->> GetForCurrentView"); textServiceManager = CoreTextServicesManager.GetForCurrentView(); // IMEの切り替えのイベントハンドラを登録します。 Debug.WriteLine("--->> Subscribe InputLanguageChanged"); textServiceManager.InputLanguageChanged += TextServiceManager_InputLanguageChanged; } // editContextを作り直します。 UpdateEditContext(); // 再描画します。 Win2DCanvas.Invalidate(); }
/* * テキストの内容の変化を通知してきた。 */ private void EditContext_TextUpdating(CoreTextEditContext sender, CoreTextTextUpdatingEventArgs ev) { Debug.WriteLine("<<--- TextUpdating:({0},{1})->({2},{3}) [{4}] {5} {6}", ev.Range.StartCaretPosition, ev.Range.EndCaretPosition, ev.NewSelection.StartCaretPosition, ev.NewSelection.EndCaretPosition, ev.Text, ev.Result, MeasureText(ev.Text, TextFormat) ); // テキストを変更して、変更情報をアンドゥ/リドゥのスタックにプッシュします。 PushUndoRedoStack(ev.Range.StartCaretPosition, ev.Range.EndCaretPosition, ev.Text, UndoStack); // 再描画します。 Win2DCanvas.Invalidate(); }
/* * アンドゥとリドゥ */ void UndoRedo(bool is_undo) { Stack <TDiff> src_stack; Stack <TDiff> dst_stack; // アンドゥとリドゥは操作対象のスタックが違うだけです。 if (is_undo) { // アンドゥの場合 // アンドゥのスタックからポップして、リドゥのスタックにプッシュします。 src_stack = UndoStack; dst_stack = RedoStack; } else { // リドゥの場合 // リドゥのスタックからポップして、アンドゥのスタックにプッシュします。 src_stack = RedoStack; dst_stack = UndoStack; } if (src_stack.Count == 0) { // ポップするスタックが空の場合 return; } // 変更情報をポップします。 TDiff src_diff = src_stack.Pop(); // 削除された文字列 string removed_string = new string((from x in src_diff.RemovedChars select x.Chr).ToArray()); // テキストを変更して、変更情報をアンドゥ/リドゥのスタックにプッシュします。 PushUndoRedoStack(src_diff.DiffPos, src_diff.DiffPos + src_diff.InsertedCount, removed_string, dst_stack); // テキストの変更をIMEに伝えます。 MyNotifyTextChanged(src_diff.DiffPos, src_diff.DiffPos + src_diff.InsertedCount, src_diff.RemovedChars.Length); // 再描画します。 Win2DCanvas.Invalidate(); }
/* * ボタンがフォーカスを喪失した。 */ private void OverlappedButton_LostFocus(object sender, RoutedEventArgs e) { Debug.WriteLine("<<--- Button LostFocus"); if (DesignMode.DesignModeEnabled) { // ビューデザイナーの中で動作している場合は何もしない。 return; } if (editContext != null) { // IMEにフォーカスの喪失を知らせます。 Debug.WriteLine("--->> NotifyFocusLeave"); editContext.NotifyFocusLeave(); } // 再描画します。 Win2DCanvas.Invalidate(); }
/* * ドラッグしてテキストを選択します。 */ public IEnumerator SelectByDrag(int start_pos) { Debug.WriteLine("ドラッグの選択の始め {0}", start_pos); // 再描画します。 Win2DCanvas.Invalidate(); yield return(0); while (true) { switch (PointerEventType) { case EEvent.PointerMoved: // ドラッグの場合 // ポインターの座標からテキストの位置を得ます。 int pos = TextPositionFromPointer(CurrentPointerEvent.CurrentPoint); if (pos != -1) { // ポインターの下にテキストがある場合 SelCurrent = pos; Debug.WriteLine("ドラッグして選択 {0}", pos); // 再描画します。 Win2DCanvas.Invalidate(); } break; case EEvent.PointerReleased: // リリースの場合 // テキストの選択位置の変更をIMEに伝えます。 MyNotifySelectionChanged(); yield break; } yield return(0); } }
/* * 現在の選択位置をセットします。 * シフトキーが押されてない場合は選択を始めた位置を現在の選択位置にします。 */ void SetSelection(int pos) { if (pos != -1 && pos != SelCurrent) { // 選択位置が変わった場合 SelCurrent = pos; if ((Window.Current.CoreWindow.GetKeyState(VirtualKey.Shift) & CoreVirtualKeyStates.Down) == 0) { // シフトキーが押されてない場合 SelOrigin = SelCurrent; } // テキストの選択位置の変更をIMEに伝えます。 MyNotifySelectionChanged(); // 再描画します。 Win2DCanvas.Invalidate(); } }
protected void PaintWords() { if (m_Words == null) { return; } if (m_Layout == null) { return; } IEnumerable <LayoutItem> wordsToRedraw = m_Layout.GetWordsInArea(new Rect(0, 0, this.ActualWidth, this.ActualHeight)); using (CanvasDrawingSession ds = _DrawingCanvas.CreateDrawingSession()) { ds.Clear(m_BackColor); using (IGraphicEngine graphicEngine = new GdiGraphicEngine(ds, FontStyle, FontFamily, m_Palette, MinFontSize, MaxFontSize, m_MinWordWeight, m_MaxWordWeight)) { foreach (LayoutItem currentItem in wordsToRedraw) { String hummaa = currentItem.Word.Text; if (m_ItemUderMouse == currentItem) { graphicEngine.DrawEmphasized(currentItem); } else { graphicEngine.Draw(currentItem); } } } } Win2DCanvas.Invalidate(); }
/* * 選択した範囲のテキストを別のテキストに置換します。 */ void ReplaceText(int sel_start, int sel_end, string new_text) { // リドゥのスタックはクリアします。 RedoStack.Clear(); // テキストを変更して、変更情報をアンドゥ/リドゥのスタックにプッシュします。 PushUndoRedoStack(sel_start, sel_end, new_text, UndoStack); // テキストの変更をIMEに伝えます。 MyNotifyTextChanged(sel_start, sel_end, new_text.Length); if (!double.IsNaN(LineHeight)) { double document_height = LineCount * LineHeight; if (EditCanvas.Height != document_height) { EditCanvas.Height = document_height; } } // 再描画します。 Win2DCanvas.Invalidate(); }
/* * 選択部分のテキストをドラッグ&ドロップします。 */ public IEnumerator DragDropHandler(PointerEventArgs e) { // マウスカーソルを矢印に変えます。 CoreApplication.GetCurrentView().CoreWindow.PointerCursor = ArrowCoreCursor; while (true) { switch (PointerEventType) { case EEvent.PointerMoved: // ドラッグの場合 // ポインターの座標からテキストの位置を得ます。 int drag_pos = TextPositionFromPointer(CurrentPointerEvent.CurrentPoint); if (drag_pos != -1 && !(SelStart <= drag_pos && drag_pos < SelEnd)) { // ポインターの下に選択部分以外のテキストがある場合 // ドロップ位置をセットします。ドロップ先に挿入カーソルを描画するのに使われます。 DropPos = drag_pos; Debug.WriteLine("ドロップ中 {0}", DropPos); } else { DropPos = -1; } // 再描画します。 Win2DCanvas.Invalidate(); yield return(0); break; case EEvent.PointerReleased: // リリースの場合 if (DropPos != -1) { // 選択部分の文字列 string sel_str = new string((from c in Chars.Skip(SelStart) select c.Chr).Take(SelEnd - SelStart).ToArray()); if ((Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) & CoreVirtualKeyStates.Down) == 0) { // Ctrlキーが押されてない場合 // 選択位置の後ろにドロップ位置があるならtrue bool drop_after_selection = (SelStart < DropPos); // 選択されたテキストを削除します。 ReplaceText(SelStart, SelEnd, ""); if (drop_after_selection) { // 選択位置の後ろにドロップ位置があるの場合 // ドロップ位置を選択テキストの長さだけ引きます。 DropPos -= sel_str.Length; } } // ドロップ位置に選択テキストを挿入します。 ReplaceText(DropPos, DropPos, sel_str); DropPos = -1; } // マウスカーソルをIカーソルに戻します。 CoreApplication.GetCurrentView().CoreWindow.PointerCursor = IBeamCoreCursor; // 再描画します。 Win2DCanvas.Invalidate(); yield break; default: yield return(0); break; } } }