private void OnCommitText(string text, bool checkIfFocused) { var selHelper = SetupForTypingEventHandler(checkIfFocused, true); if (selHelper == null) { return; } try { var selectionProps = GetSelectionProps(selHelper); var countBackspace = TrimBeginningBackspaces(ref text); var bottom = selHelper.GetIch(SelectionHelper.SelLimitType.Bottom); selHelper.IchAnchor = Math.Max(0, selHelper.GetIch(SelectionHelper.SelLimitType.Top) - countBackspace); selHelper.IchEnd = bottom; selHelper.SetSelection(true); UpdateSelectionForReplacingPreeditText(selHelper, countBackspace); // Insert 'text' ITsString str = CreateTsStringUsingSelectionProps(text, selectionProps, false); selHelper.Selection.ReplaceWithTsString(str); } finally { m_InitialSelection = null; m_EndOfPreedit = null; if (m_ActionHandler != null) { m_ActionHandler.EndUndoTask(); m_ActionHandler = null; } OnPreeditClosed(); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// End the undoable UOW and Undo everything. /// </summary> /// ------------------------------------------------------------------------------------ protected void UndoAll() { IActionHandler actionHandler = Cache.ActionHandlerAccessor; // This ends a UOW, but with no Commit. if (actionHandler.CurrentDepth > 0) { actionHandler.EndUndoTask(); } // Undo the UOW (or more than one of them, if the test made new ones). while (actionHandler.CanUndo()) { actionHandler.Undo(); } // Need to 'Commit' to clear out redo stack, // since nothing is really saved. actionHandler.Commit(); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Sets the current book, particularly picking the right set of annotations /// to add new ones to. Also (and more conspicuously) ends the current Undo task /// and makes a new one for importing the new book. Should therefore be called /// BEFORE setting up the Undo action for the creation of the book. /// </summary> /// <param name="nCanonicalBookNumber">The canonical book number.</param> /// <param name="fVernacular">if set to <c>true</c> currently importing the vernacular. /// </param> /// <returns>The existing book in the current imported version, if any; otherwise /// <c>null</c></returns> /// <remarks>If importing annotations and/or BTs without importing the vernacular, the /// importer is responsible for calling this directly.</remarks> /// ------------------------------------------------------------------------------------ private IScrBook SetCurrentBook(int nCanonicalBookNumber, bool fVernacular) { if (nCanonicalBookNumber <= 0 || nCanonicalBookNumber > BCVRef.LastBook) { throw new ArgumentOutOfRangeException("nCanonicalBookNumber", nCanonicalBookNumber, "Expected a canonical book number."); } IActionHandler actionHandler = m_cache.DomainDataByFlid.GetActionHandler(); // We want a new undo task for each new book, except the first one if (m_importedBooks.Count > 0) { actionHandler.EndUndoTask(); } if (actionHandler.CurrentDepth == 0) { // No need to use localizable string from resources because the user will never // see these labels because we collapse to a single undo task when the import // completes. actionHandler.BeginUndoTask("Undo Import Book " + nCanonicalBookNumber, "Redo Import Book " + nCanonicalBookNumber); } if (m_importedBooks.ContainsKey(nCanonicalBookNumber)) { m_lastBookAddedToImportedBooks = 0; } else { m_lastBookAddedToImportedBooks = nCanonicalBookNumber; m_importedBooks[nCanonicalBookNumber] = fVernacular; } m_annotations = m_scr.BookAnnotationsOS[nCanonicalBookNumber - 1]; return((m_importedVersion == null) ? null : m_importedVersion.FindBook(nCanonicalBookNumber)); }
/// <summary> /// Handle the CommitText event. Transfer to GUI thread if neccessary. /// </summary> private void CommitTextEventHandler(string text) { if (AssociatedSimpleRootSite.InvokeRequired) { AssociatedSimpleRootSite.SafeBeginInvoke( new CommitDelegate(CommitTextEventHandler), new object[] { text }); return; } IActionHandler actionHandler = AssociatedSimpleRootSite.DataAccess.GetActionHandler(); try { if (actionHandler != null) { actionHandler.BeginUndoTask(Resources.ksUndoTyping, Resources.ksRedoTyping); } // Save existing Preedit Selection and existing left-over preedit string. var preeditSelection = SavePreeditSelection(); ITsString preedit; preeditSelection.Selection.GetSelectionString(out preedit, String.Empty); // Change selection to a insertion point (unless we moved the selection before, // which happens when we come here as part of processing a mouse click) // And insert commit text. var selHelper = new SelectionHelper( m_savedPreeditSelection ?? AssociatedSimpleRootSite.EditingHelper.CurrentSelection); if (m_savedPreeditSelection == null) { selHelper.ReduceToIp(SelectionHelper.SelLimitType.Anchor); } selHelper.SetSelection(true); AssociatedSimpleRootSite.EditingHelper.OnCharAux(text, VwShiftStatus.kfssNone, Keys.None); int deletedChars = TrimBeginningBackspaces(ref text); // Update the saved preedit selection to take account of the inserted text // text is in NFC, but the view uses it in NFD, so we have to convert it. // We don't do this if we moved the selection prior to this method. int textLenNFD = m_savedPreeditSelection != null ? 0 : Icu.Normalize(text, Icu.UNormalizationMode.UNORM_NFD).Length; int anchor = preeditSelection.IchAnchor + textLenNFD - deletedChars; // select the text we just inserted // TODO: underline the text so that it is more obvious that this is just preedit text preeditSelection.SetIch(SelectionHelper.SelLimitType.Anchor, anchor); preeditSelection.SetIch(SelectionHelper.SelLimitType.End, preeditSelection.IchEnd + textLenNFD - deletedChars); // reshow the preedit selection RestorePreeditSelection(preeditSelection); preeditSelection.Selection.ReplaceWithTsString(preedit); preeditSelection.SetSelection(true); } finally { m_savedPreeditSelection = null; if (actionHandler != null) { actionHandler.EndUndoTask(); } } }
/// <summary> /// This method must be called by the GUI thread only. /// It shows the current Preedit as a selection. /// </summary> private void ShowPreedit(string text, bool visible) { // Don't allow modifying the preedit if an undo or redo is in progress. if (m_dataChanging) { return; } if (AssociatedSimpleRootSite.InvokeRequired) { throw new ApplicationException( "Programming Error: ShowPreedit should only be called on GUI thread"); } if (AssociatedSimpleRootSite.RootBox == null) { return; } if (AssociatedSimpleRootSite.RootBox.Selection == null) { return; } // Some IME send a initial empty preedit, which can clear an existing selection // TODO: we could also check the selection is a range if this is neccessary if (string.IsNullOrEmpty(text) && m_ignoreInitialPreedit) { return; } m_ignoreInitialPreedit = false; IActionHandler actionHandler = AssociatedSimpleRootSite.DataAccess.GetActionHandler(); try { if (actionHandler != null) { actionHandler.BeginUndoTask(Resources.ksUndoTyping, Resources.ksRedoTyping); } AssociatedSimpleRootSite.EditingHelper.DeleteRangeIfComplex( AssociatedSimpleRootSite.RootBox); // update the current preedit selection with new preedit text. var selHelper = new SelectionHelper( AssociatedSimpleRootSite.EditingHelper.CurrentSelection); ITsString str = CreateTsStringUsingSelectionProps(text, selHelper); selHelper.Selection.ReplaceWithTsString(str); // make the selection fit the new text selHelper.SetIch(SelectionHelper.SelLimitType.Anchor, selHelper.GetIch(SelectionHelper.SelLimitType.Top)); selHelper.SetIch(SelectionHelper.SelLimitType.End, selHelper.IchAnchor + str.Length); // make the selection visible selHelper.SetSelection(true); } finally { if (actionHandler != null) { actionHandler.EndUndoTask(); } } // Update the position where a preedit window will appear SetImeCursorLocation(); }