internal static void HandleUpDownArrows(KeyEventArgs e, IVwRootBox rootBox, SelectionHelper curSel, List<IWritingSystem> wsList, int flid) { if (curSel == null || !curSel.IsValid) // LT-13805: sometimes selection was null return; var index = GetCurrentSelectionIndex(curSel, wsList); if (index < 0) return; var maxWsIndex = wsList.Count - 1; if (e.KeyCode == Keys.Up) { // Handle Up arrow if ((index - 1) < 0) return; index--; } else { // Handle Down arrow if ((index + 1) > maxWsIndex) return; index++; } // make new selection at index var newSelection = GetSelAtStartOfWs(rootBox, flid, index, wsList[index]); newSelection.Install(); e.Handled = true; }
/// <summary> /// The core of the Draw() method, where the rectangle actually gets painted. /// Vertical views use a rotated drawing routine. /// </summary> /// <param name="vdrb"></param> /// <param name="rootb"></param> /// <param name="hdc"></param> /// <param name="drawRect"></param> /// <param name="backColor"></param> /// <param name="drawSel"></param> /// <param name="clipRect"></param> public virtual void DrawTheRoot(IVwDrawRootBuffered vdrb, IVwRootBox rootb, IntPtr hdc, SIL.FieldWorks.Common.Utils.Rect drawRect, uint backColor, bool drawSel, Rectangle clipRect) { vdrb.DrawTheRoot(rootb, hdc, clipRect, backColor, drawSel, m_site); }
/// ------------------------------------------------------------------------------------ /// <summary> /// /// </summary> /// <param name="rootSite"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="rootb"></param> /// ------------------------------------------------------------------------------------ private void PrepareView(DummyBasicView rootSite, int width, int height, IVwRootBox rootb) { rootSite.Visible = false; rootSite.Width = width; rootSite.Height = height; rootSite.SetRootBox(rootb); }
internal static IVwSelection GetSelAtStartOfWs(IVwRootBox rootBox, int flid, int wsIndex, IWritingSystem ws) { try { return rootBox.MakeTextSelection(0, 0, null, flid, wsIndex, 0, 0, (ws == null) ? 0 : ws.Handle, false, -1, null, false); } catch (COMException) { return null; // can fail if we are hiding an empty WS. } }
/// ----------------------------------------------------------------------------------- /// <summary> /// Make one and hook it up to be called at the appropriate time. /// </summary> /// ----------------------------------------------------------------------------------- public RequestSelectionHelper(IActionHandlerExtensions hookup, IVwRootBox rootb, int ihvoRoot, SelLevInfo[] rgvsli, int tagTextProp, int cpropPrevious, int ich, int wsAlt, bool fAssocPrev, ITsTextProps selProps) { m_hookup = hookup; m_rootb = rootb; m_ihvoRoot = ihvoRoot; m_rgvsli = rgvsli; m_tagTextProp = tagTextProp; m_cpropPrevious = cpropPrevious; m_ich = ich; m_wsAlt = wsAlt; m_fAssocPrev = fAssocPrev; m_selProps = selProps; m_hookup.DoAtEndOfPropChanged(m_hookup_PropChangedCompleted); }
protected override void HandleSelectionChange(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); if (m_handlingSelectionChanged) return; m_handlingSelectionChanged = true; try { m_selectedSenseHvo = 0; if (vwselNew == null) return; base.HandleSelectionChange(rootb, vwselNew); // Get the Id of the selected snes, and store it. int cvsli = vwselNew.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. cvsli--; if (cvsli == 0) { // No objects in selection: don't allow a selection. m_rootb.DestroySelection(); // Enhance: invoke launcher's selection dialog. return; } ITsString tss; int ichAnchor; int ichEnd; bool fAssocPrev; int hvoObj; int hvoObjEnd; int tag; int ws; vwselNew.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); vwselNew.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); if (hvoObj != hvoObjEnd) return; m_selectedSenseHvo = hvoObj; } finally { m_handlingSelectionChanged = false; } }
/// <summary> /// Make one. /// </summary> public PromptSelectionRestorer(IVwRootBox rootbox) { m_rootbox = rootbox; if (rootbox == null) return; // Save information about the old selection. IVwSelection oldsel = rootbox.Selection; // Dummy variables int tagTextProp; int ichAnchor; int ichEnd; int ihvoEnd; bool fAssocPrev; if (oldsel != null && oldsel.CLevels(false) > 0) { cvsli = oldsel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. rgvsli = SelLevInfo.AllTextSelInfo(oldsel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); } }
/// <summary> /// print root sites are never used for editing, so this routine should never be called. /// </summary> public void RequestSelectionAtEndOfUow(IVwRootBox _rootb, int ihvoRoot, int cvlsi, SelLevInfo[] rgvsli, int tagTextProp, int cpropPrevious, int ich, int wsAlt, bool fAssocPrev, ITsTextProps selProps) { throw new NotImplementedException(); }
/// <summary> /// Get a transform for a given source point...shouldn't be needed but this is /// safe. /// </summary> /// <param name="root"></param> /// <param name="pt"></param> /// <param name="rcSrcRoot"></param> /// <param name="rcDstRoot"></param> public void GetTransformAtSrc(IVwRootBox root, Point pt, out Rect rcSrcRoot, out Rect rcDstRoot) { rcSrcRoot = m_rcSrc; rcDstRoot = m_rcDst; }
/// ------------------------------------------------------------------------------------ /// <summary> /// /// </summary> /// <param name="e"></param> /// ------------------------------------------------------------------------------------ private void Init(PrintPageEventArgs e) { #if false long x1 = System.DateTime.Now.Ticks; #endif // Set these now because the Graphics object will be locked below. m_rcDst = m_rcSrc = new Rect(0, 0, (int)e.Graphics.DpiX, (int)e.Graphics.DpiY); int dpix; if (MiscUtils.IsUnix) { dpix = 72; } else { dpix = (int)e.Graphics.DpiX; } m_dxpAvailWidth = PixelsFrom100ths(e.MarginBounds.Width, dpix); // Create and initialize a print context. m_vwPrintContext = VwPrintContextWin32Class.Create(); // TODO: When we provide a way for the user to specify the nFirstPageNo (i.e. the // first argument to SetPagePrintInfo), then change the arguments to // SetPagePrintInfo. m_vwPrintContext.SetPagePrintInfo(1, 1, 65535, 1, false); SetMargins(e); IVwGraphics vwGraphics = VwGraphicsWin32Class.Create(); IntPtr hdc = IntPtr.Zero; try { // Get the printer's hdc and use it to initialize other stuff. hdc = e.Graphics.GetHdc(); ((IVwGraphicsWin32)vwGraphics).Initialize(hdc); m_vwPrintContext.SetGraphics(vwGraphics); // Make a rootbox for printing and initialize it. m_rootb = VwRootBoxClass.Create(); m_rootb.RenderEngineFactory = SingletonsContainer.Get <RenderEngineFactory>(); m_rootb.TsStrFactory = TsStringUtils.TsStrFactory; m_rootb.SetSite(this); m_rootb.DataAccess = m_sda; m_rootb.SetRootObject(m_hvo, m_vc, m_frags, m_styleSheet); m_rootb.InitializePrinting(m_vwPrintContext); m_totalNumberOfPages = m_rootb.GetTotalPrintPages(m_vwPrintContext); m_psettings = e.PageSettings.PrinterSettings; SetPrintRange(); } catch (Exception ex) { m_rootb = null; throw new ContinuableErrorException("An error has occurred during the setup required for printing.", ex); } finally { if (hdc != IntPtr.Zero) { vwGraphics.ReleaseDC(); e.Graphics.ReleaseHdc(hdc); } } #if false long x2 = System.DateTime.Now.Ticks; Debug.WriteLine("PrintRootSite.Init() took " + DeltaTime(x1, x2) + " seconds."); #endif }
/// ----------------------------------------------------------------------------------- /// <summary> /// Cause the immediate update of the display of the root box. This should cause all pending /// paint operations to be done immediately, at least for the screen area occupied by the /// root box. It is typically called after processing key strokes, to ensure that the updated /// text is displayed before trying to process any subsequent keystrokes. /// </summary> /// <param name="prootb"></param> /// ----------------------------------------------------------------------------------- void IVwRootSite.DoUpdates(IVwRootBox prootb) { // Do nothing for printing }
/// <summary> see OnInsertDiffParas </summary> VwInsertDiffParaResponse IVwRootSite.OnInsertDiffPara(IVwRootBox prootb, ITsTextProps ttpDest, ITsTextProps ttpSrc, ITsString tssParas, ITsString tssTrailing) { throw new NotImplementedException(); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Handle insertion of paragraphs (i.e., from clipboard) with properties that don't /// match the properties of the paragraph where they are being inserted. This gives us /// the opportunity to create/modify the DB structure to recieve the paragraphs being /// inserted and to reject certain types of paste operations (such as attempting to /// paste a book). /// </summary> /// <param name="rootBox">the sender</param> /// <param name="ttpDest">properties of destination paragraph</param> /// <param name="cPara">number of paragraphs to be inserted</param> /// <param name="ttpSrcArray">Array of props of each para to be inserted</param> /// <param name="tssParas">Array of TsStrings for each para to be inserted</param> /// <param name="tssTrailing">Text of an incomplete paragraph to insert at end (with /// the properties of the destination paragraph.</param> /// <returns>One of the following: /// kidprDefault - causes the base implementation to insert the material as part of the /// current StText in the usual way; /// kidprFail - indicates that we have decided that this text should not be pasted at /// this location at all, causing entire operation to roll back; /// kidprDone - indicates that we have handled the paste ourselves, inserting the data /// wherever it ought to go and creating any necessary new structure.</returns> /// ------------------------------------------------------------------------------------ public override VwInsertDiffParaResponse OnInsertDiffParas(IVwRootBox rootBox, ITsTextProps ttpDest, int cPara, ITsTextProps[] ttpSrcArray, ITsString[] tssParas, ITsString tssTrailing) { CheckDisposed(); if (TeEditingHelper == null) return VwInsertDiffParaResponse.kidprFail; return TeEditingHelper.InsertDiffParas(rootBox, ttpDest, cPara, ttpSrcArray, tssParas, tssTrailing); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Return true if this kind of window uses semi-tagging. /// </summary> /// <param name="prootb"></param> /// ----------------------------------------------------------------------------------- bool IVwRootSite.get_SemiTagging(IVwRootBox prootb) { return(false); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Return true if this kind of window uses semi-tagging. /// </summary> /// <param name="prootb"></param> /// ----------------------------------------------------------------------------------- bool IVwRootSite.get_SemiTagging(IVwRootBox prootb) { return false; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Notifies the site that the size of the root box changed; scroll ranges and/or /// window size may need to be updated. The standard response is to update the scroll range. /// </summary> /// <remarks> /// Review JohnT: might this also be the place to make sure the selection is still visible? /// Should we try to preserve the scroll position (at least the top left corner, say) even /// if the selection is not visible? Which should take priority? /// </remarks> /// <param name="prootb"></param> /// ----------------------------------------------------------------------------------- void IVwRootSite.RootBoxSizeChanged(IVwRootBox prootb) { // Do nothing for printing }
/// ----------------------------------------------------------------------------------- /// <summary> /// When the state of the overlays changes, it propagates this to its site. /// </summary> /// <param name="prootb"></param> /// <param name="vo"></param> /// ----------------------------------------------------------------------------------- void IVwRootSite.OverlayChanged(IVwRootBox prootb, IVwOverlay vo) { // Do nothing for printing }
/// ----------------------------------------------------------------------------------- /// <summary> /// Notifies the site that something about the selection has changed. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew"></param> /// ----------------------------------------------------------------------------------- void IVwRootSite.SelectionChanged(IVwRootBox prootb, IVwSelection vwselNew) { // Do nothing for printing }
/// ----------------------------------------------------------------------------------- /// <summary> /// Inform the container when done with the graphics object. /// </summary> /// <param name="prootb"></param> /// <param name="pvg"></param> /// ----------------------------------------------------------------------------------- void IVwRootSite.ReleaseGraphics(IVwRootBox prootb, IVwGraphics pvg) { // Do nothing for printing }
/// <summary> /// Real drawing VG same as layout one for simple printing. /// </summary> /// <param name="_Root"></param> /// <returns></returns> public IVwGraphics get_ScreenGraphics(IVwRootBox _Root) { return(m_vwPrintContext.Graphics); }
/// ------------------------------------------------------------------------------------ /// <summary> /// /// </summary> /// <param name="prootb"></param> /// <param name="pt"></param> /// ------------------------------------------------------------------------------------ void IVwRootSite.ClientToScreen(IVwRootBox prootb, ref System.Drawing.Point pt) { // Do nothing for printing }
/// ----------------------------------------------------------------------------------- /// <summary>If there is a pending writing system that should be applied to typing, /// return it; also clear the state so that subsequent typing will not have a pending /// writing system until something sets it again. (This is mainly used so that /// keyboard-change commands can be applied while the selection is a range.)</summary> /// <param name="prootb"></param> /// <returns>Pending writing system</returns> /// ----------------------------------------------------------------------------------- int IVwRootSite.GetAndClearPendingWs(IVwRootBox prootb) { return(-1); }
/// ----------------------------------------------------------------------------------- /// <summary>If there is a pending writing system that should be applied to typing, /// return it; also clear the state so that subsequent typing will not have a pending /// writing system until something sets it again. (This is mainly used so that /// keyboard-change commands can be applied while the selection is a range.)</summary> /// <param name="prootb"></param> /// <returns>Pending writing system</returns> /// ----------------------------------------------------------------------------------- int IVwRootSite.GetAndClearPendingWs(IVwRootBox prootb) { return -1; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Answer whether boxes in the specified range of destination coordinates /// may usefully be converted to lazy boxes. Should at least answer false /// if any part of the range is visible. The default implementation avoids /// converting stuff within about a screen's height of the visible part(s). /// </summary> /// <param name="prootb"></param> /// <param name="ydBottom"></param> /// <param name="ydTop"></param> /// ----------------------------------------------------------------------------------- bool IVwRootSite.IsOkToMakeLazy(IVwRootBox prootb, int ydTop, int ydBottom) { return(false); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Notifies the site that something about the selection has changed. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew">Selection</param> /// <remarks>When overriding you should call the base class first.</remarks> /// ----------------------------------------------------------------------------------- protected override void HandleSelectionChange(IVwRootBox prootb, IVwSelection vwselNew) { if (m_fInSelectionChanged) return; // don't need to reprocess our own changes. m_fInSelectionChanged = true; try { base.HandleSelectionChange(prootb, vwselNew); IVwSelection sel = vwselNew; if (!sel.IsValid) sel = prootb.Selection; if (sel == null) return; SelectionHelper helper = SelectionHelper.Create(sel, prootb.Site); // Check whether the selection is on the proper line of a multilingual // annotation and, if not, fix it. See LT-9421. if (m_cpropPrevForInsert > 0 && !sel.IsRange && (helper.GetNumberOfPreviousProps(SelectionHelper.SelLimitType.Anchor) == 0 || helper.GetNumberOfPreviousProps(SelectionHelper.SelLimitType.End) == 0)) { try { helper.SetNumberOfPreviousProps(SelectionHelper.SelLimitType.Anchor, m_cpropPrevForInsert); helper.SetNumberOfPreviousProps(SelectionHelper.SelLimitType.End, m_cpropPrevForInsert); helper.MakeBest(true); m_cpropPrevForInsert = -1; // we've used this the one time it was needed. } catch (Exception exc) { if (exc != null) Debug.WriteLine(String.Format( "InterlinDocChild.SelectionChanged() trying to display prompt in proper line of annotation: {0}", exc.Message)); } } int flid = helper.GetTextPropId(SelectionHelper.SelLimitType.Anchor); //If the flid is -2 and it is an insertion point then we may have encountered a case where the selection has landed at the boundary between our (possibly empty) //translation field and a literal string containing our magic Bidi marker character that helps keep things in the right order. //Sometimes AssocPrev gets set so that we read the (non-existent) flid of the literal string and miss the fact that on the other side //of the insertion point is the field we're looking for. The following code will attempt to make a selection that associates in //the other direction to see if the flid we want is on the other side. [LT-10568] if (flid == -2 && !sel.IsRange && sel.SelType == VwSelType.kstText) { helper.AssocPrev = !helper.AssocPrev; try { var newSel = helper.MakeRangeSelection(this.RootBox, false); helper = SelectionHelper.Create(newSel, this); flid = helper.GetTextPropId(SelectionHelper.SelLimitType.Anchor); } catch (COMException) { // Ignore HResult E_Fail caused by Extended Keys (PgUp/PgDown) in non-editable text (LT-13500) } } //Fixes LT-9884 Crash when clicking on the blank space in Text & Words--->Print view area! if (helper.LevelInfo.Length == 0) return; int hvo = helper.LevelInfo[0].hvo; // If the selection is in a freeform or literal translation that is empty, display the prompt. if (SelIsInEmptyTranslation(helper, flid, hvo) && !m_rootb.IsCompositionInProgress) { var handlerExtensions = Cache.ActionHandlerAccessor as IActionHandlerExtensions; if (handlerExtensions != null && handlerExtensions.IsUndoTaskActive) { // Wait to make the changes until the task (typically typing backspace) completes. m_setupPromptHelper = helper; m_setupPromptFlid = flid; handlerExtensions.DoAtEndOfPropChanged(handlerExtensions_PropChangedCompleted); } else { // No undo task to tag on the end of, so do it now. SetupTranslationPrompt(helper, flid); } } else if (flid != kTagUserPrompt) { m_vc.SetActiveFreeform(0, 0, 0, 0); // clear any current prompt. } // do not extend the selection for a user prompt if the user is currently entering an IME composition, // since we are about to switch the prompt to a real comment field else if (helper.GetTextPropId(SelectionHelper.SelLimitType.End) == SimpleRootSite.kTagUserPrompt && !m_rootb.IsCompositionInProgress) { // If the selection is entirely in a user prompt then extend the selection to cover the // entire prompt. This covers changes within the prompt, like clicking within it or continuing // a drag while making it. sel.ExtendToStringBoundaries(); EditingHelper.SetKeyboardForSelection(sel); } } finally { m_fInSelectionChanged = false; } }
/// ----------------------------------------------------------------------------------- /// <summary> /// Invalidate rectangle /// </summary> /// <param name="root">The sender</param> /// <param name="xdLeft">Relative to top left of root box</param> /// <param name="ydTop"></param> /// <param name="xdWidth"></param> /// <param name="ydHeight"></param> /// ----------------------------------------------------------------------------------- void IVwRootSite.InvalidateRect(IVwRootBox root, int xdLeft, int ydTop, int xdWidth, int ydHeight) { // Do nothing for printing }
/// ----------------------------------------------------------------------------------- /// <summary> /// Handle a selection changed event. /// </summary> /// <param name="rootb">root box that has the selection change</param> /// <param name="vwselNew">Selection</param> /// ----------------------------------------------------------------------------------- protected override void HandleSelectionChange(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); base.HandleSelectionChange(rootb, vwselNew); // It's possible that the base either changed the selection or invalidated it in // calling commit and made this selection no longer useable. SelectionHelper helper = EditingHelper.CurrentSelection; if (helper == null || !helper.Selection.IsValid) return; // scroll the footnote pane to be in synch with the draft view // (TimS): Focused was taken out because it was causing selection changes that // happended from a menu item wouldn't scroll to the footnote. if (TheDraftViewWrapper != null && TheDraftViewWrapper.FootnoteViewShowing && Options.FootnoteSynchronousScrollingSetting) { // For performance on typing, don't try to scroll footnote pane on every update SelLevInfo paraInfo; if (helper.GetLevelInfoForTag(StTextTags.kflidParagraphs, out paraInfo)) { IStTxtPara para = m_fdoCache.ServiceLocator.GetInstance<IStTxtParaRepository>().GetObject(paraInfo.hvo); ITsString tss = para.Contents; if (helper.IchAnchor <= tss.Length) { int iRun = (helper.IchAnchor >= 0) ? tss.get_RunAt(helper.IchAnchor) : -1; if (iRun != -1 && (m_prevSelectedParagraph != paraInfo.hvo || iRun != m_prevAnchorPosition)) { SynchFootnoteView(helper); // Save selection information m_prevSelectedParagraph = paraInfo.hvo; m_prevAnchorPosition = iRun; } } } } // Debug code was taken out. It was put in to help with testing using TestLangProj. // Most of our tests are using the InMemoryCache so this information is almost useless. // If you need it, just change the "DEBUG_not_exist" to "DEBUG" and then compile. #region Debug code #if DEBUG_not_exist // This section of code will display selection information in the status bar when the // program is compiled in Debug mode. The information shown in the status bar is useful // when you want to make selections in tests. try { string text; SelLevInfo paraInfo = helper.GetLevelInfoForTag(StTextTags.kflidParagraphs); SelLevInfo secInfo = helper.GetLevelInfoForTag(ScrBookTags.kflidSections); SelLevInfo bookInfo = helper.GetLevelInfoForTag(BookFilter.Tag); bool inBookTitle = TeEditingHelper.InBookTitle; bool inSectionHead = TeEditingHelper.InSectionHead; text = "Book: " + bookInfo.ihvo + " Section: " + (inBookTitle ? "Book Title" : secInfo.ihvo.ToString()) + " Paragraph: " + paraInfo.ihvo + " Anchor: " + helper.IchAnchor + " End: " + helper.IchEnd + " AssocPrev: " + helper.AssocPrev; if (!inBookTitle && bookInfo.ihvo >= 0) { IStTxtPara para = m_fdoCache.ServiceLocator.GetInstance<IStTxtParaRepository>().GetObject(paraInfo.hvo); ITsString tss = para.Contents; if (helper.IchAnchor <= tss.Length) text += " Run No.: " + tss.get_RunAt(helper.IchAnchor); } if (TheMainWnd != null) TheMainWnd.StatusStrip.Items[0].Text = text; } catch { } #endif #endregion }
/// ----------------------------------------------------------------------------------- /// <summary> /// Get the width available for laying things out in the view. /// </summary> /// <param name="prootb"></param> /// <returns>Width available for layout</returns> /// ----------------------------------------------------------------------------------- int IVwRootSite.GetAvailWidth(IVwRootBox prootb) { return m_dxpAvailWidth; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Get the width available for laying things out in the view. /// </summary> /// <param name="prootb"></param> /// <returns>Width available for layout</returns> /// ----------------------------------------------------------------------------------- int IVwRootSite.GetAvailWidth(IVwRootBox prootb) { return(m_dxpAvailWidth); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Get a graphics object in an appropriate state for drawing and measuring in the view. /// The calling method should pass the IVwGraphics back to ReleaseGraphics() before /// it returns. In particular, problems will arise if OnPaint() gets called before the /// ReleaseGraphics() method. /// </summary> /// <param name="pRoot"></param> /// <param name="pvg"></param> /// <param name="rcSrcRoot"></param> /// <param name="rcDstRoot"></param> /// ----------------------------------------------------------------------------------- void IVwRootSite.GetGraphics(IVwRootBox pRoot, out IVwGraphics pvg, out Rect rcSrcRoot, out Rect rcDstRoot) { pvg = m_vwPrintContext.Graphics; rcSrcRoot = m_rcSrc; rcDstRoot = m_rcDst; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Adjust the scroll range when some lazy box got expanded. Needs to be done for both /// panes if we have more than one. /// </summary> /// <param name="prootb"></param> /// <param name="dxdSize"></param> /// <param name="dxdPosition"></param> /// <param name="dydSize"></param> /// <param name="dydPosition"></param> /// <returns></returns> /// ----------------------------------------------------------------------------------- bool IVwRootSite.AdjustScrollRange(IVwRootBox prootb, int dxdSize, int dxdPosition, int dydSize, int dydPosition) { return(false); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Get a graphics object in an appropriate state for drawing and measuring in the view. /// The calling method should pass the IVwGraphics back to ReleaseGraphics() before /// it returns. In particular, problems will arise if OnPaint() gets called before the /// ReleaseGraphics() method. /// </summary> /// <param name="pRoot"></param> /// <returns></returns> /// ----------------------------------------------------------------------------------- IVwGraphics IVwRootSite.get_LayoutGraphics(IVwRootBox pRoot) { return(m_vwPrintContext.Graphics); }
public override void SelectionChanged(IVwRootBox prootb, IVwSelection vwselNew) { CheckDisposed(); m_vc.TasVc.SelectionChanged(prootb, vwselNew); base.SelectionChanged(prootb, vwselNew); }
public ICollection <SpellCorrectMenuItem> GetSuggestions(Point mousePos, SimpleRootSite rootsite, out int hvoObj, out int tag, out int wsAlt, out int wsText, out string word, out ISpellEngine dict, out bool nonSpellingError) { hvoObj = tag = wsAlt = wsText = 0; // make compiler happy for early returns word = null; dict = null; nonSpellingError = true; IVwRootBox rootb = rootsite != null ? rootsite.RootBox : null; if (rootb == null) { return(null); } // Get a selection at the indicated point. IVwSelection sel = rootsite.GetSelectionAtPoint(mousePos, false); // Get the selected word and verify that it is a single run within a single // editable string. if (sel != null) { sel = sel.GrowToWord(); } if (sel == null || !sel.IsRange || sel.SelType != VwSelType.kstText || !SelectionHelper.IsEditable(sel)) { return(null); } ITsString tss; bool fAssocPrev; int ichAnchor; sel.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out wsAlt); int ichEnd, hvoObjE, tagE, wsE; sel.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjE, out tagE, out wsE); if (hvoObj != hvoObjE || tag != tagE || wsAlt != wsE) { return(null); } int ichMin = Math.Min(ichEnd, ichAnchor); int ichLim = Math.Max(ichEnd, ichAnchor); ILgWritingSystemFactory wsf = rootsite.RootBox.DataAccess.WritingSystemFactory; // May need to enlarge the word beyond what GrowToWord does, if there is adjacent wordforming material. int ichMinAdjust = AdjustWordBoundary(wsf, tss, ichMin, -1, 0) + 1; // further expanded start of word. int ichLimAdjust = AdjustWordBoundary(wsf, tss, ichLim - 1, 1, tss.Length); // further expanded lim of word. // From the ends we can strip stuff with different spell-checking properties. IVwStylesheet styles = rootsite.RootBox.Stylesheet; int spellProps = SpellCheckProps(tss, ichMin, styles); while (ichMinAdjust < ichMin && SpellCheckProps(tss, ichMinAdjust, styles) != spellProps) { ichMinAdjust++; } while (ichLimAdjust > ichLim && SpellCheckProps(tss, ichLimAdjust - 1, styles) != spellProps) { ichLimAdjust--; } ichMin = ichMinAdjust; ichLim = ichLimAdjust; ITsStrFactory tsf = TsStrFactoryClass.Create(); // Now we have the specific range we will check. Get the actual string. ITsStrBldr bldr = tss.GetBldr(); if (ichLim < bldr.Length) { bldr.ReplaceTsString(ichLim, bldr.Length, null); } if (ichMin > 0) { bldr.ReplaceTsString(0, ichMin, null); } ITsString tssWord = bldr.GetString(); // See whether we need the special blue underline, which is used mainly for adjacent words in different writing systems. List <int> wss = TsStringUtils.GetWritingSystems(tssWord); if (wss.Count > 1) { return(MakeWssSuggestions(tssWord, wss, rootb, hvoObj, tag, wsAlt, ichMin, ichLim)); } ITsString keepOrcs; // holds any ORCs we found in the original word that we need to keep rather than reporting. IList <SpellCorrectMenuItem> result = MakeEmbeddedNscSuggestion(ref tssWord, styles, rootb, hvoObj, tag, wsAlt, ichMin, ichLim, out keepOrcs); if (result.Count > 0) { return(result); } // Determine whether it is a spelling problem. wsText = TsStringUtils.GetWsOfRun(tssWord, 0); dict = SpellingHelper.GetSpellChecker(wsText, wsf); if (dict == null) { return(null); } word = tssWord.get_NormalizedForm(FwNormalizationMode.knmNFC).Text; if (word == null) { return(null); // don't think this can happen, but... } if (dict.Check(word)) { return(null); // not mis-spelled. } // Get suggestions. Make sure to return an empty collection rather than null, even if no suggestions, // to indicate an error. ICollection <string> suggestions = dict.Suggest(word); foreach (string suggest in suggestions) { ITsString replacement = tsf.MakeStringRgch(suggest, suggest.Length, wsText); if (keepOrcs != null) { ITsStrBldr bldrRep = keepOrcs.GetBldr(); bldrRep.ReplaceTsString(0, 0, replacement); replacement = bldrRep.GetString(); } result.Add(new SpellCorrectMenuItem(rootb, hvoObj, tag, wsAlt, ichMin, ichLim, suggest, replacement)); } nonSpellingError = false; // it IS a spelling problem. return(result); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Get a graphics object in an appropriate state for drawing and measuring in the view. /// The calling method should pass the IVwGraphics back to ReleaseGraphics() before /// it returns. In particular, problems will arise if OnPaint() gets called before the /// ReleaseGraphics() method. /// </summary> /// <param name="pRoot"></param> /// <returns></returns> /// ----------------------------------------------------------------------------------- IVwGraphics IVwRootSite.get_LayoutGraphics(IVwRootBox pRoot) { return m_vwPrintContext.Graphics; }
private IList <SpellCorrectMenuItem> MakeEmbeddedNscSuggestion(ref ITsString tssWord, IVwStylesheet styles, IVwRootBox rootb, int hvoObj, int tag, int wsAlt, int ichMin, int ichLim, out ITsString tssKeepOrcs) { List <SpellCorrectMenuItem> result = new List <SpellCorrectMenuItem>(); // Make an item with inserted spaces. ITsStrBldr bldr = tssWord.GetBldr(); int spCur = SpellCheckProps(tssWord, 0, styles); int offset = 0; bool foundDiff = false; bool fHasOrc = false; ITsStrBldr bldrWord = null; ITsStrBldr bldrKeepOrcs = null; int bldrWordOffset = 0; // Start at 0 even though we already got its props, because it just might be an ORC. for (int ich = 0; ich < tssWord.Length; ich++) { if (tssWord.GetChars(ich, ich + 1) == "\xfffc") { ITsTextProps ttp = tssWord.get_PropertiesAt(ich); string objData = ttp.GetStrPropValue((int)FwTextPropType.ktptObjData); if (objData.Length == 0 || objData[0] != Convert.ToChar((int)FwObjDataTypes.kodtGuidMoveableObjDisp)) { fHasOrc = true; int ichInsert = ich + offset; bldr.Replace(ichInsert, ichInsert, " ", null); spCur = -50 - ich; // Same trick as SpellCheckProps to ensure won't match anything following. offset++; foundDiff = true; } else { // An ORC we want to ignore, but not lose. We will strip it out of the word we will // actually spell-check if we don't find other ORC problems, but save it to be // inserted at the end of any correction word. We might still use // our own "insert missing spaces" option, too, if we find another ORC of a different type. // In that case, this ORC just stays as part of the string, without spaces inserted. if (bldrWord == null) { bldrWord = tssWord.GetBldr(); bldrKeepOrcs = TsStrBldrClass.Create(); } bldrWord.Replace(ich - bldrWordOffset, ich - bldrWordOffset + 1, "", null); bldrKeepOrcs.Replace(bldrKeepOrcs.Length, bldrKeepOrcs.Length, "\xfffc", ttp); bldrWordOffset++; } } else // not an orc, see if props changed. { int spNew = SpellCheckProps(tssWord, ich, styles); if (spNew != spCur) { int ichInsert = ich + offset; bldr.Replace(ichInsert, ichInsert, " ", null); spCur = spNew; offset++; foundDiff = true; } } } if (bldrWord != null) { tssWord = bldrWord.GetString(); tssKeepOrcs = bldrKeepOrcs.GetString(); } else { tssKeepOrcs = null; } if (!foundDiff) { return(result); } ITsString suggest = bldr.GetString(); // There might still be an ORC in the string, in the pathological case of a picture anchor and embedded verse number // in the same word(!). Leave it in the replacement, but not in the menu item. string menuItemText = suggest.Text.Replace("\xfffc", ""); if (fHasOrc) { menuItemText = RootSiteStrings.ksInsertMissingSpaces; } result.Add(new SpellCorrectMenuItem(rootb, hvoObj, tag, wsAlt, ichMin, ichLim, menuItemText, suggest)); return(result); }
/// <summary> /// Real drawing VG same as layout one for simple printing. /// </summary> /// <param name="_Root"></param> /// <returns></returns> public IVwGraphics get_ScreenGraphics(IVwRootBox _Root) { return m_vwPrintContext.Graphics; }
private ICollection <SpellCorrectMenuItem> MakeWssSuggestions(ITsString tssWord, List <int> wss, IVwRootBox rootb, int hvoObj, int tag, int wsAlt, int ichMin, int ichLim) { List <SpellCorrectMenuItem> result = new List <SpellCorrectMenuItem>(wss.Count + 1); // Make an item with inserted spaces. ITsStrBldr bldr = tssWord.GetBldr(); int wsFirst = TsStringUtils.GetWsOfRun(tssWord, 0); int offset = 0; for (int irun = 1; irun < tssWord.RunCount; irun++) { int wsNew = TsStringUtils.GetWsOfRun(tssWord, irun); if (wsNew != wsFirst) { int ichInsert = tssWord.get_MinOfRun(irun) + offset; bldr.Replace(ichInsert, ichInsert, " ", null); wsFirst = wsNew; offset++; } } ITsString suggest = bldr.GetString(); string menuItemText = suggest.Text; result.Add(new SpellCorrectMenuItem(rootb, hvoObj, tag, wsAlt, ichMin, ichLim, menuItemText, suggest)); // And items for each writing system. foreach (int ws in wss) { bldr = tssWord.GetBldr(); bldr.SetIntPropValues(0, bldr.Length, (int)FwTextPropType.ktptWs, (int)FwTextPropVar.ktpvDefault, ws); suggest = bldr.GetString(); ILgWritingSystemFactory wsf = rootb.DataAccess.WritingSystemFactory; ILgWritingSystem engine = wsf.get_EngineOrNull(ws); string wsName = engine.LanguageName; string itemText = string.Format(RootSiteStrings.ksMlStringIsMono, tssWord.Text, wsName); result.Add(new SpellCorrectMenuItem(rootb, hvoObj, tag, wsAlt, ichMin, ichLim, itemText, suggest)); } return(result); }
/// ----------------------------------------------------------------------------------- /// <summary> /// If the mousePos is part of a word that is not properly spelled, add to the menu /// options for correcting it. /// </summary> /// <param name="pt">The location on the screen of the word for which we want spelling /// suggestions (usually the mouse position)</param> /// <param name="rootsite">The focused rootsite</param> /// <param name="menu">to add items to.</param> /// <returns>the number of menu items added (not counting a possible separator line)</returns> /// ----------------------------------------------------------------------------------- public virtual int MakeSpellCheckMenuOptions(Point pt, SimpleRootSite rootsite, ContextMenuStrip menu) { int hvoObj, tag, wsAlt, wsText; string word; ISpellEngine dict; bool nonSpellingError; ICollection <SpellCorrectMenuItem> suggestions = GetSuggestions(pt, rootsite, out hvoObj, out tag, out wsAlt, out wsText, out word, out dict, out nonSpellingError); if (suggestions == null) { return(0); } // no detectable spelling problem. // Note that items are inserted in order starting at the beginning, rather than // added to the end. This is to support TE-6901. // If the menu isn't empty, add a separator. if (menu.Items.Count > 0) { menu.Items.Insert(0, new ToolStripSeparator()); } // Make the menu option. ToolStripMenuItem itemExtras = null; int cSuggestions = 0; int iMenuItem = 0; IVwRootBox rootb = rootsite.RootBox; foreach (SpellCorrectMenuItem subItem in suggestions) { subItem.Click += spellingMenuItemClick; if (cSuggestions++ < RootSiteEditingHelper.kMaxSpellingSuggestionsInRootMenu) { Font createdFont = null; try { Font font = subItem.Font; if (wsText != 0) { font = createdFont = EditingHelper.GetFontForNormalStyle(wsText, rootb.Stylesheet, rootb.DataAccess.WritingSystemFactory); //string familyName = rootb.DataAccess.WritingSystemFactory.get_EngineOrNull(wsText).DefaultBodyFont; //font = new Font(familyName, font.Size, FontStyle.Bold); } subItem.Font = new Font(font, FontStyle.Bold); menu.Items.Insert(iMenuItem++, subItem); } finally { if (createdFont != null) { createdFont.Dispose(); } } } else { if (itemExtras == null) { itemExtras = new ToolStripMenuItem(RootSiteStrings.ksAdditionalSuggestions); menu.Items.Insert(iMenuItem++, itemExtras); } itemExtras.DropDownItems.Add(subItem); } } if (suggestions.Count == 0) { ToolStripMenuItem noSuggestItems = new ToolStripMenuItem(RootSiteStrings.ksNoSuggestions); menu.Items.Insert(iMenuItem++, noSuggestItems); noSuggestItems.Enabled = false; } ToolStripMenuItem itemAdd = new AddToDictMenuItem(dict, word, rootb, hvoObj, tag, wsAlt, wsText, RootSiteStrings.ksAddToDictionary, m_cache); if (nonSpellingError) { itemAdd.Enabled = false; } menu.Items.Insert(iMenuItem++, itemAdd); itemAdd.Image = SIL.FieldWorks.Resources.ResourceHelper.SpellingIcon; itemAdd.Click += spellingMenuItemClick; return(iMenuItem); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Selections the changed. /// </summary> /// <param name="prootb">The prootb.</param> /// <param name="sel">The sel.</param> /// ------------------------------------------------------------------------------------ protected override void HandleSelectionChange(IVwRootBox prootb, IVwSelection sel) { CheckDisposed(); if (m_fInChangeSelectedObjects) { return; } m_fInChangeSelectedObjects = true; try { int cvsli = 0; // Out variables for AllTextSelInfo. int ihvoRoot = 0; int tagTextProp = 0; int cpropPrevious = 0; int ichAnchor = 0; int ichEnd = 0; int ws = 0; bool fAssocPrev = false; int ihvoEnd = 0; ITsTextProps ttpBogus = null; SelLevInfo[] rgvsli = new SelLevInfo[0]; List <int> newSelectedObjects = new List <int>(4); newSelectedObjects.Add(XmlVc.FocusHvo); if (sel != null) { cvsli = sel.CLevels(false) - 1; // Main array of information retrived from sel that made combo. rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); for (int i = 0; i < cvsli; i++) { newSelectedObjects.Add(rgvsli[i].hvo); } } var changed = new HashSet <int>(m_xmlVc.SelectedObjects); changed.SymmetricExceptWith(newSelectedObjects); if (changed.Count != 0) { m_xmlVc.SelectedObjects = newSelectedObjects; // Generate propChanged calls that force the relevant parts of the view to redraw // to indicate which command icons should be visible. foreach (int hvo in changed) { m_rootb.PropChanged(hvo, XmlVc.IsObjectSelectedTag, 0, 1, 1); } if (sel != null && !sel.IsValid) { // we wiped it out by regenerating parts of the display in our PropChanged calls! Restore it if we can. sel = m_rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttpBogus, true); } } } finally { m_fInChangeSelectedObjects = false; } base.HandleSelectionChange(prootb, sel); }
/// ------------------------------------------------------------------------------------ /// <summary> /// We override this method to make a selection in all of the views that are in a /// synced group. This fixes problems where the user changes the selection in one of /// the slaves, but the master is not updated. Thus the view is not scrolled as the /// groups scroll position only scrolls the master's selection into view. (TE-3380) /// </summary> /// <param name="rootb">The rootbox whose selection changed</param> /// <param name="vwselNew">The new selection</param> /// ------------------------------------------------------------------------------------ protected override void HandleSelectionChange(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); // Guard against recursive calls, typically caused by the MakeTextSelection call below. if (m_fInSelectionChanged) { return; } try { m_fInSelectionChanged = true; // Make sure we're not handling MouseDown since it // handles SelectionChanged and DoSelectionSideEffects. // No need to do it again. if (!ReadOnlySelect && !m_fHandlingMouseUp) { if (vwselNew == null) { return; } // The selection can apparently be invalid on rare occasions, and will lead // to a crash below trying to call CLevels. See LT-10301. Treat it the // same as a null selection. if (!vwselNew.IsValid) { return; } base.HandleSelectionChange(rootb, vwselNew); m_wantScrollIntoView = false; // It should already be visible here. // Collect all the information we can about the selection. int ihvoRoot = 0; int tagTextProp = 0; int cpropPrevious = 0; int ichAnchor = 0; int ichEnd = 0; int ws = 0; bool fAssocPrev = false; int ihvoEnd = 0; ITsTextProps ttpBogus = null; SelLevInfo[] rgvsli = new SelLevInfo[0]; int cvsli = vwselNew.CLevels(false) - 1; if (cvsli < 0) { return; // Nothing useful we can do. } // Main array of information retrived from sel that made combo. rgvsli = SelLevInfo.AllTextSelInfo(vwselNew, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); //for (int i = 0; i < cvsli; ++i) //{ // Debug.Write(String.Format("XmlBrowseView.SelectionChanged(): rgvsli[{0}].hvo={1}, ivho={2}, tag={3}, cpropPrevious={4}, ich={5}, ws={6}", // i, rgvsli[i].hvo, rgvsli[i].ihvo, rgvsli[i].tag, rgvsli[i].cpropPrevious, rgvsli[i].ich, rgvsli[i].ws)); // Debug.WriteLine(String.Format("; ihvoRoot={0}, ihvoEnd={1}, ichEnd={2}", // ihvoRoot, ihvoEnd, ichEnd)); //} // The call to the base implementation can invalidate the selection. It's rare, but quite // possible. (See the comment in EditingHelper.SelectionChanged() following // Commit().) This test fixes LT-4731. if (vwselNew.IsValid) { DoSelectionSideEffects(vwselNew); } else { // But if the selection is invalid, and we do nothing about it, then we can // type only one character at a time in a browse cell because we no longer // have a valid selection. See LT-6443. rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttpBogus, true); DoSelectionSideEffects(rootb.Selection); } m_wantScrollIntoView = true; } } finally { m_fInSelectionChanged = false; } }
/// ----------------------------------------------------------------------------------- /// <summary> /// Answer whether boxes in the specified range of destination coordinates /// may usefully be converted to lazy boxes. Should at least answer false /// if any part of the range is visible. The default implementation avoids /// converting stuff within about a screen's height of the visible part(s). /// </summary> /// <param name="prootb"></param> /// <param name="ydBottom"></param> /// <param name="ydTop"></param> /// ----------------------------------------------------------------------------------- bool IVwRootSite.IsOkToMakeLazy(IVwRootBox prootb, int ydTop, int ydBottom) { return false; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Replace the user prompt with the text the user typed. This method is called from /// the views code when the user prompt is edited. /// </summary> /// <param name="vwsel">Current selection in rootbox where this prop was updated</param> /// <param name="hvo">Hvo of the paragraph/string/segment whose contents are being /// changed</param> /// <param name="tag">Tag (must be SimpleRootSite.kTagUserPrompt)</param> /// <param name="frag">Owning flid of the text/object that owns the paragraph/string/ /// segment whose user prompt is being replaced with typed text</param> /// <param name="tssVal">Text the user just typed</param> /// <returns>possibly modified ITsString.</returns> /// <remarks>The return value is currently ignored in production code, but we use it /// in our tests.</remarks> /// ----------------------------------------------------------------------------------- public override ITsString UpdateProp(IVwSelection vwsel, int hvo, int tag, int frag, ITsString tssVal) { Debug.Assert(tag == SimpleRootSite.kTagUserPrompt, "Got an unexpected tag"); Debug.Assert(vwsel != null, "Got a null selection!"); Debug.Assert(vwsel.IsValid, "Got an invalid selection!"); IVwRootBox rootbox = vwsel.RootBox; // If a (typically Chinese) character composition is in progress, replacing the prompt will // destroy the selection and end the composition, causing weird typing problems (TE-8267). // Ending the composition does another Commit, which ensures that this will eventually be // called when there is NOT a composition in progress. if (rootbox.IsCompositionInProgress) { return(tssVal); } // Remove the UserPrompt pseudo-property from the text the user typed. // when appropriate also ensure the correct writing system. // The correct WS is m_wsDefault in the view constructor ITsStrBldr bldr = tssVal.GetBldr(); if (frag != SegmentTags.kflidFreeTranslation) { bldr.SetIntPropValues(0, bldr.Length, (int)FwTextPropType.ktptWs, (int)FwTextPropVar.ktpvDefault, m_wsDefault); } // Delete the user prompt property from the string (TE-3994) bldr.SetIntPropValues(0, bldr.Length, SimpleRootSite.ktptUserPrompt, -1, -1); tssVal = bldr.GetString(); // Get information about current selection int cvsli = vwsel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. int ihvoRoot; int tagTextProp_Ignore; int cpropPrevious; int ichAnchor; int ichEnd; int ihvoEnd; // Prior to the Commit in selection changed which causes this UpdateProp to be called, // earlier selection changed code has expanded the selection (because it is in a user prompt) // to the whole prompt. It is therefore a range selection, and the value of fAssocPrev we got // is useless. bool fAssocPrev_Ignore; int ws; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwsel, cvsli, out ihvoRoot, out tagTextProp_Ignore, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev_Ignore, out ihvoEnd, out ttp); int tagTextProp; ITsTextProps props = null; if (frag == SegmentTags.kflidFreeTranslation) { // If the length is zero...we need to suppress replacing the comment with a prompt. if (tssVal.Length == 0) { m_hvoOfSegmentWhoseBtPromptIsToBeSupressed = hvo; } ISegment seg = Cache.ServiceLocator.GetInstance <ISegmentRepository>().GetObject(hvo); if (seg.FreeTranslation.get_String(BackTranslationWS).Length == 0) { // Undo needs to unset suppressing the comment prompt. Cache.ActionHandlerAccessor.AddAction(new UndoSuppressBtPrompt(this, seg)); } ws = BackTranslationWS; tagTextProp = frag; seg.FreeTranslation.set_String(ws, tssVal); rootbox.PropChanged(seg.Paragraph.Owner.Hvo, StTextTags.kflidParagraphs, seg.Paragraph.IndexInOwner, 1, 1); } else { ReplacePromptUndoAction undoAction = new ReplacePromptUndoAction(hvo, rootbox, m_updatedPrompts); if (m_cache.ActionHandlerAccessor != null) { m_cache.ActionHandlerAccessor.AddAction(new UndoSelectionAction(rootbox.Site, true, vwsel)); m_cache.ActionHandlerAccessor.AddAction(undoAction); } // Mark the user prompt as having been updated - will not show prompt again. // Note: ReplacePromptUndoAction:Undo removes items from the Set. m_updatedPrompts.Add(hvo); // Replace the ITsString in the paragraph or translation props = StyleUtils.CharStyleTextProps(null, m_wsDefault); if (frag == CmTranslationTags.kflidTranslation) { ICmTranslation trans = Cache.ServiceLocator.GetInstance <ICmTranslationRepository>().GetObject(hvo); trans.Translation.set_String(m_wsDefault, tssVal); undoAction.ParaHvo = trans.Owner.Hvo; ws = BackTranslationWS; tagTextProp = frag; } else { IStTxtPara para = Cache.ServiceLocator.GetInstance <IStTxtParaRepository>().GetObject(hvo); para.Contents = tssVal; undoAction.ParaHvo = hvo; ws = 0; tagTextProp = StTxtParaTags.kflidContents; } // Do a fake propchange to update the prompt rootbox.PropChanged(undoAction.ParaHvo, StParaTags.kflidStyleRules, 0, 1, 1); } // Now request a selection at the end of the text that was just put in. rootbox.Site.RequestSelectionAtEndOfUow(rootbox, ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichEnd, ws, true, props); return(tssVal); }
public override void SelectionChanged(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); if (vwselNew == null) return; bool hasFoc = Focused; base.SelectionChanged(rootb, vwselNew); ITsString tss; int ichAnchor; bool fAssocPrev; int hvoObj; int tag; int ws; // NB: This will be 0 after each call, since the string does // not have alternatives. Ws would be the WS of an alternative, // if there were any. vwselNew.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); int ichEnd; int hvoObjEnd; vwselNew.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); if (hvoObjEnd != hvoObj) { CheckHeight(); return; } if (m_hvoOldSelection > 0 && hvoObj != m_hvoOldSelection) { // Try to validate previously selected string rep. if (m_silCache.get_StringProp(m_hvoOldSelection, kEnvStringRep).Length==0) { // Remove it from the dummy cache, since its length is 0. int limit = m_silCache.get_VecSize(m_rootObj.Hvo, kMainObjEnvironments); for (int i = 0; i < limit; ++i) { if (m_hvoOldSelection == m_silCache.get_VecItem(m_rootObj.Hvo, kMainObjEnvironments, i)) { RemoveFromDummyCache(i); break; } } } else // Validate previously selected string rep. { ValidateStringRep(m_hvoOldSelection); } } if (hvoObj != kDummyPhoneEnvID) { m_hvoOldSelection = hvoObj; CheckHeight(); return; } if (tss.Length == 0) { CheckHeight(); return; } // Create a new object, and recreate a new empty object. Make this part of the Undo // Task with the character we typed. m_silCache.GetActionHandler().ContinueUndoTask(); int count = m_silCache.get_VecSize(m_rootObj.Hvo, kMainObjEnvironments); int hvoNew = InsertNewEnv(count - 1); m_silCache.SetString(hvoNew, kEnvStringRep, tss); m_silCache.SetString(kDummyPhoneEnvID, kEnvStringRep, DummyString); m_silCache.EndUndoTask(); // Refresh m_silCache.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_rootObj.Hvo, kMainObjEnvironments, count - 1, 2, 1); // Reset selection. SelLevInfo[] rgvsli = new SelLevInfo[1]; rgvsli[0].cpropPrevious = 0; rgvsli[0].tag = kMainObjEnvironments; rgvsli[0].ihvo = count - 1; m_rootb.MakeTextSelection(0, rgvsli.Length, rgvsli, tag, 0, ichAnchor, ichEnd, ws, fAssocPrev, -1, null, true); m_hvoOldSelection = hvoNew; CheckHeight(); }
/// <summary> /// This is the real guts of type-ahead. It is called by the client whenever a key is pressed. /// It returns true if it handled the key press, which it does if the current selection /// is in a type-ahead name property. /// </summary> /// <param name="ehelp"></param> /// <param name="e"></param> /// <param name="modifiers"></param> /// <param name="vwGraphics"></param> /// <returns></returns> public virtual bool OnKeyPress(EditingHelper ehelp, KeyPressEventArgs e, Keys modifiers, IVwGraphics vwGraphics) { IVwRootBox rootb = ehelp.Callbacks.EditedRootBox; if (rootb == null) // If we don't have a root box, can't do anything interesting. { return(false); } IVwSelection sel = rootb.Selection; if (sel == null) // nothing interesting to do without a selection, either. { return(false); } ITsString tssA, tssE; int ichA, ichE, hvoObjA, hvoObjE, tagA, tagE, ws; bool fAssocPrev; // Enhance JohnT: what we're really trying to do here is confirm that the selection is // all in one string property. We could readily have a method in the selection interface to tell us that. sel.TextSelInfo(false, out tssA, out ichA, out fAssocPrev, out hvoObjA, out tagA, out ws); if (tagA != m_taTagName) { return(false); // selection not anchored in a type-ahead name property. } sel.TextSelInfo(true, out tssE, out ichE, out fAssocPrev, out hvoObjE, out tagE, out ws); int cch = tssA.Length; // To do our type-ahead trick, both ends of the seleciton must be in the same string property. // Also, we want the selection to extend to the end of the name. // Enhance JohnT: poupu list may not depend on selection extending to end. if (tagE != m_taTagName || hvoObjE != hvoObjA || cch != tssE.Length || Math.Max(ichA, ichE) != cch) { return(false); // not going to attempt type-ahead behavior } // if the key pressed is a backspace or del, prevent smart completion, // otherwise we are likely to put back what the user deleted. // Review JohnT: do arrow keys come through here? What do we do if so? int charT = Convert.ToInt32(e.KeyChar); if (charT == (int)Keys.Back || charT == (int)Keys.Delete) { return(false); // normal key handling will just delete selection. // Review: should backspace delete one more? } // OK, we're in a type-ahead situation. First step is to let normal editing take place. ehelp.OnKeyPress(e, modifiers); e.Handled = true; // Now see what we have. Note that our old selection is no longer valid. sel = rootb.Selection; if (sel == null) { return(true); // can't be smart, but we already did the keypress. } int cvsli = sel.CLevels(false); // CLevels includes the string prop itself, but AllTextSelInfo does not need it. cvsli--; // Get selection information to determine where the user is typing. int ihvoObj; int tagTextProp; int cpropPrevious, ichAnchor, ichEnd, ihvoEnd; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoObj, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); if (tagTextProp != m_taTagName || ichAnchor != ichEnd || ihvoEnd != -1 || cvsli < 1) { return(true); // something bizarre happened, but keypress is done. } int hvoLeaf = rgvsli[0].hvo; // Get the parent object we will modify. // (This would usually work, but not if the parent object is the root of the whole display, // as in a simple atomic ref type ahead slice. //int hvoParent = rgvsli[1].hvo; // object whose reference property we are setting.) int tagParent, cpropPreviousDummy, ihvo; IVwPropertyStore vps; int hvoParent; sel.PropInfo(false, 1, out hvoParent, out tagParent, out ihvo, out cpropPreviousDummy, out vps); if (hvoParent != m_hvoParent) { return(true); // another bizarre unexpected event. } // This is what the name looks like after the keypress. ITsString tssTyped = m_sda.get_StringProp(hvoLeaf, m_taTagName); // Get the substitute. This is where the actual type-ahead behavior happens. Sets hvoNewRef to 0 if no match. ICmObject objNewRef; ITsString tssLookup = Lookup(tssTyped, out objNewRef); int hvoNewRef = (objNewRef != null) ? objNewRef.Hvo : 0; IVwCacheDa cda = m_sda as IVwCacheDa; if (hvoNewRef == 0 && tssTyped.Length > 0) { // No match...underline string in red squiggle. ITsStrBldr bldr = tssLookup.GetBldr(); bldr.SetIntPropValues(0, tssLookup.Length, (int)FwTextPropType.ktptUnderline, (int)FwTextPropVar.ktpvEnum, (int)FwUnderlineType.kuntSquiggle); bldr.SetIntPropValues(0, tssLookup.Length, (int)FwTextPropType.ktptUnderColor, (int)FwTextPropVar.ktpvDefault, (int)ColorUtil.ConvertColorToBGR(Color.Red)); tssLookup = bldr.GetString(); } // Don't rely on sel from here on. if (hvoNewRef != hvoLeaf) { m_hvoTa = hvoNewRef; // Before we replace in the prop, so it gets displayed using special ta prop. switch (m_type) { case CellarPropertyType.ReferenceAtomic: if (m_hvoParent != 0) // I think it always is, except when loss of focus during debugging causes problems. { // If nothing matched, set the real property to null and the fake one to kbaseFakeObj. // Otherwise set both to the indicated object. m_sda.SetObjProp(m_hvoParent, m_tag, hvoNewRef); // Review: do we want to set the real thing yet? m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_tag, 0, 1, 1); if (hvoNewRef == 0) { hvoNewRef = m_hvoTa = kBaseFakeObj; // use in fake so we can display something. } cda.CacheObjProp(m_hvoParent, m_virtualTagObj, hvoNewRef); // Change the fake property m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_virtualTagObj, 0, 1, 1); } break; case CellarPropertyType.ReferenceSequence: case CellarPropertyType.ReferenceCollection: // Several cases, depending on whether we got a match and whether hvoLeaf is the dummy object // 1. match on dummy: insert appropriate real object, change dummy name to empty. // 2. match on non-dummy: replace old object with new // 3: non-match: do nothing. (Even if not looking at the fake object, we'll go on using the // actual object as a base for the fake name, since it's displayed only for the active position.) if (hvoNewRef == 0) { break; // case 3 } if (hvoLeaf == kBaseFakeObj) { // case 1 // The fake object goes back to being an empty name at the end of the list. ITsStrBldr bldr = tssLookup.GetBldr(); bldr.ReplaceTsString(0, bldr.Length, null); // makes an empty string in correct ws. cda.CacheStringProp(kBaseFakeObj, m_taTagName, bldr.GetString()); // Insert the new object before the fake one in fake prop and at end of real seq. // Include the fake object in the replace to get it redisplayed also. cda.CacheReplace(m_hvoParent, m_virtualTagObj, m_ihvoTa, m_ihvoTa + 1, new int[] { hvoNewRef, kBaseFakeObj }, 2); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_virtualTagObj, m_ihvoTa, 2, 1); m_sda.Replace(m_hvoParent, m_tag, m_ihvoTa, m_ihvoTa, new int[] { hvoNewRef }, 1); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_tag, m_ihvoTa, 1, 0); } else { // case 2 // Replace the object being edited with the indicated one in both props. cda.CacheReplace(m_hvoParent, m_virtualTagObj, m_ihvoTa, m_ihvoTa + 1, new int[] { hvoNewRef }, 1); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_virtualTagObj, m_ihvoTa, 1, 1); m_sda.Replace(m_hvoParent, m_tag, m_ihvoTa, m_ihvoTa + 1, new int[] { hvoNewRef }, 1); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_tag, m_ihvoTa, 1, 1); } break; default: throw new Exception("unsupported property type for type-ahead chooser"); } } cda.CacheStringProp(hvoNewRef, m_taTagName, tssLookup); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoNewRef, m_taTagName, 0, tssLookup.Length, tssTyped.Length); // Make a new selection, typically the range that is the bit added to the typed string. // no change is needed to rgvsli because it's the same object index in the same property of the same parent. sel = rootb.MakeTextSelection(ihvoObj, cvsli, rgvsli, m_taTagName, cpropPrevious, ichAnchor, tssLookup.Length, ws, true, -1, null, true); return(true); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Show the context menu for the specified root box at the location of /// its selection (typically an IP). /// </summary> /// <param name="rootb"></param> /// ------------------------------------------------------------------------------------ public override void ShowContextMenuAtIp(IVwRootBox rootb) { CheckDisposed(); ShowContextMenu(IPLocation); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Constructor. /// </summary> /// <param name="rootb">The rootb.</param> /// <param name="vwsel">The vwsel.</param> /// ------------------------------------------------------------------------------------ public VwSelectionArgs(IVwRootBox rootb, IVwSelection vwsel) { m_rootb = rootb; m_vwsel = vwsel; }
/// <summary> see OnInsertDiffParas </summary> public override VwInsertDiffParaResponse OnInsertDiffPara(IVwRootBox rootBox, ITsTextProps ttpDest, ITsTextProps ttpSrc, ITsString tssParas, ITsString tssTrailing) { CheckDisposed(); return OnInsertDiffParas(rootBox, ttpDest, 1, new ITsTextProps[] { ttpSrc }, new ITsString[] { tssParas } , tssTrailing); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the width available for laying things out in the view. /// Return the layout width for the window, depending on whether or not there is a /// scroll bar. If there is no scroll bar, we pretend that there is, so we don't have /// to keep adjusting the width back and forth based on the toggling on and off of /// vertical and horizontal scroll bars and their interaction. /// The return result is in pixels. /// The only common reason to override this is to answer instead a very large integer, /// which has the effect of turning off line wrap, as everything apparently fits on /// a line. /// </summary> /// <param name="prootb">The root box</param> /// <returns>Width available for layout</returns> /// ------------------------------------------------------------------------------------ public int GetAvailWidth(IVwRootBox prootb) { return(640); }
/// <summary> /// Handle a selection change by growing it to a word (unless the new selection IS /// the one we're growing to a word). /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew"></param> public override void SelectionChanged(IVwRootBox prootb, IVwSelection vwselNew) { CheckDisposed(); base.SelectionChanged (prootb, vwselNew); if (!m_fInSelChange) { m_fInSelChange = true; try { if (!vwselNew.IsRange) { vwselNew.GrowToWord().Install(); } } finally { m_fInSelChange = false; } } if (SelChanged != null) SelChanged(this, new EventArgs()); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the width available for laying things out in the view. /// Return the layout width for the window, depending on whether or not there is a /// scroll bar. If there is no scroll bar, we pretend that there is, so we don't have /// to keep adjusting the width back and forth based on the toggling on and off of /// vertical and horizontal scroll bars and their interaction. /// The return result is in pixels. /// The only common reason to override this is to answer instead a very large integer, /// which has the effect of turning off line wrap, as everything apparently fits on /// a line. /// </summary> /// <param name="prootb">The root box</param> /// <returns>Width available for layout</returns> /// ------------------------------------------------------------------------------------ public int GetAvailWidth(IVwRootBox prootb) { throw new Exception("The method or operation is not implemented."); }