/// ------------------------------------------------------------------------------------ /// <summary> /// Called when [delete record]. /// </summary> /// <param name="commandObject">The command object.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public override bool OnDeleteRecord(object commandObject) { CheckDisposed(); if (m_rootb == null) MakeRoot(); IVwSelection vwsel = m_rootb.Selection; if (vwsel == null) return false; ISilDataAccess sda = m_bv.SpecialCache; List<XmlNode> columns = m_xbvvc.ColumnSpecs; if (columns == null || columns.Count == 0) return false; // Something is broken! TextSelInfo tsi = new TextSelInfo(m_rootb.Selection); if (tsi.ContainingObject(0) == XmlRDEBrowseViewVc.khvoNewItem) { ClearColumnStringsFromNewRow(); } else { // 1. Remove the domain from the sense shown in the second column. // 2. Delete the sense iff it is now empty except for the definition shown. // 3. Delete the entry iff the entry now has no senses. #if false // JohnT: don't understand the following code at all. In particular it makes no sense // to use ihvoRoot to index rgvsli; ihvoRoot is always zero in this view, it has only one root. // Possibly this was an unsuccessful attempt to adapt some generic code I wrote to this // particular application involving senses and entries? // I'm leaving it in existence for now in case the original author turns up and // can explain what he was getting at. int cLevels = vwsel.get_BoxDepth(true); int iLevel; int cBoxes = -1; int iBox = -1; VwBoxType[] rgvbt = new VwBoxType[cLevels]; VwBoxType vbt = VwBoxType.kvbtUnknown; for (iLevel = 0; iLevel < cLevels; ++iLevel) { vbt = vwsel.get_BoxType(false, iLevel); if (vbt == VwBoxType.kvbtTableCell) { cBoxes = vwsel.get_BoxCount(true, iLevel); iBox = vwsel.get_BoxIndex(true, iLevel); break; } } Debug.Assert(cBoxes == 2); Debug.Assert(iBox != -1); int hvoEntry; int hvoSense; if (iBox == 0) { hvoEntry = rgvsli[ihvoRoot].hvo; IVwSelection vwsel2 = m_rootb.MakeSelInBox(vwsel, false, iLevel, 1, true, false, false); SelLevInfo[] rgvsli2 = SelLevInfo.AllTextSelInfo(vwsel, vwsel2.CLevels(false) - 1, out ihvoRoot, out tag, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); hvoSense = rgvsli2[ihvoRoot].hvo; } else { hvoSense = rgvsli[ihvoRoot].hvo; IVwSelection vwsel2 = m_rootb.MakeSelInBox(vwsel, false, iLevel, 0, true, false, false); SelLevInfo[] rgvsli2 = SelLevInfo.AllTextSelInfo(vwsel, vwsel2.CLevels(false) - 1, out ihvoRoot, out tag, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); hvoEntry = rgvsli2[ihvoRoot].hvo; } #else int cvsli = tsi.Levels(false) - 1; int tag = tsi.ContainingObjectTag(cvsli - 1); Debug.Assert(cvsli >= 1); // there should be at least one level (each row is a sense) // The outermost thing in the VC is a display of all the senses of the root domain. // Therefore the last thing in rgvsli is always the information identifying the sense we // want to process. int hvoSense = tsi.ContainingObject(cvsli - 1); int hvoEntry = m_fdoCache.ServiceLocator.GetInstance<ICmObjectRepository>().GetObject(hvoSense).Owner.Hvo; #endif // If this was an editable object, it no longer is, because it's about to no longer exist. RDEVc.EditableObjectsRemove(hvoSense); var le = m_fdoCache.ServiceLocator.GetInstance<ILexEntryRepository>().GetObject(hvoEntry); var ls = m_fdoCache.ServiceLocator.GetInstance<ILexSenseRepository>().GetObject(hvoSense); string sUndo = XMLViewsStrings.ksUndoDeleteRecord; string sRedo = XMLViewsStrings.ksRedoDeleteRecord; UndoableUnitOfWorkHelper.Do(sUndo, sRedo, Cache.ActionHandlerAccessor, () => { ls.SemanticDomainsRC.Remove(Cache.ServiceLocator.GetInstance<ICmSemanticDomainRepository>().GetObject(m_hvoRoot)); if (ls.SemanticDomainsRC.Count == 0 && ls.AnthroCodesRC.Count == 0 && ls.AppendixesRC.Count == 0 && ls.DomainTypesRC.Count == 0 && ls.ThesaurusItemsRC.Count == 0 && ls.UsageTypesRC.Count == 0) { bool fKeep = false; ITsString tss = ls.Gloss.AnalysisDefaultWritingSystem; if (tss != null && tss.Length > 0) fKeep = true; if (!fKeep) { tss = ls.Gloss.UserDefaultWritingSystem; if (tss != null && tss.Length > 0) fKeep = true; } if (!fKeep) { tss = ls.Gloss.VernacularDefaultWritingSystem; if (tss != null && tss.Length > 0) fKeep = true; } if (!fKeep) { tss = ls.Definition.VernacularDefaultWritingSystem; if (tss != null && tss.Length > 0) fKeep = true; } if (!fKeep) { tss = ls.DiscourseNote.AnalysisDefaultWritingSystem; if (tss != null && tss.Length > 0) fKeep = true; } if (!fKeep) { tss = ls.DiscourseNote.UserDefaultWritingSystem; if (tss != null && tss.Length > 0) fKeep = true; } if (!fKeep) { tss = ls.DiscourseNote.VernacularDefaultWritingSystem; if (tss != null && tss.Length > 0) fKeep = true; } if (!fKeep) { tss = ls.ScientificName; if (tss != null && tss.Length > 0) fKeep = true; } if (!fKeep) { tss = ls.Source; if (tss != null && tss.Length > 0) fKeep = true; } if (!fKeep) { le.SensesOS.Remove(ls); ls = null; } } if (ls == null && le.SensesOS.Count == 0) { le.Delete(); le = null; } }); } return true; }
/// <summary> /// Create one from the specified end of the selection. If that end is not in a /// relevant property return null. Also return null if in the same StText as /// hvoOther. /// </summary> /// <param name="info"></param> /// <param name="fEndPoint"></param> static public TextStateInfo Create(TextSelInfo info, bool fEndPoint, FdoCache cache, int hvoOther) { int offset = 0; // in the SelInfoStack if (info.Tag(fEndPoint) == kflidContents) { if (info.Levels(fEndPoint) < 2) return null; } else { // One other case we need to handle is an embedded picture, because deleting it will modify the string. if (!info.IsPicture || info.Levels(false) < 3 || info.ContainingObjectTag(1) != kflidContents) return null; offset = 1; // one more level for the picture. } int hvoStText = info.ContainingObject(1 + offset, fEndPoint); if (hvoStText == hvoOther) return null; TextStateInfo result = new TextStateInfo(); result.m_stText = CmObject.CreateFromDBObject(cache, hvoStText) as StText;; result.m_hvoPara = info.ContainingObject(offset, fEndPoint); foreach (StTxtPara para in result.m_stText.ParagraphsOS) result.m_paras.Add(new ParaStateInfo(para)); result.m_tssAnchorText = cache.GetTsStringProperty(result.m_hvoPara, kflidContents); result.m_fCheckOtherParasOfText = true; return result; }
/// <summary> /// This override ensures that we always have whole objects selected. /// Enhance: it may cause flicker during drag, in which case, we may change to only do it on mouse up, /// or only IF the mouse is up. /// </summary> protected virtual void HandleSelectionChange(object sender, VwSelectionArgs args) { CheckDisposed(); if (m_InSelectionChanged || RootBox.Selection == null) return; var info = new TextSelInfo(RootBox); var end = Math.Max(info.ContainingObjectIndex(info.Levels(true) - 1, true), info.ContainingObjectIndex(info.Levels(false) - 1, false)); SelectUpTo(end); }
/// <summary> /// This override ensures that we always have whole objects selected. /// Enhance: it may cause flicker during drag, in which case, we may change to only do it on mouse up, /// or only IF the mouse is up. /// </summary> protected override void HandleSelectionChange(object sender, VwSelectionArgs args) { if (m_InSelectionChanged || RootBox.Selection == null) return; TextSelInfo info = new TextSelInfo(RootBox); int end = Math.Max(info.ContainingObjectIndex(info.Levels(true) - 1, true), info.ContainingObjectIndex(info.Levels(false) - 1, false)); int begin = Math.Min(info.ContainingObjectIndex(info.Levels(true) - 1, true), info.ContainingObjectIndex(info.Levels(false) - 1, false)); SelectRange(begin, end); }
/// <summary> /// This override ensures that we always have whole objects selected. /// Enhance: it may cause flicker during drag, in which case, we may change to only do it on mouse up, /// or only IF the mouse is up. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew"></param> public override void SelectionChanged(IVwRootBox prootb, IVwSelection vwselNew) { base.SelectionChanged(prootb, vwselNew); if (m_InSelectionChanged) return; if (RootBox.Selection == null) return; TextSelInfo info = new TextSelInfo(RootBox); int end = Math.Max(info.ContainingObjectIndex(info.Levels(true) - 1, true), info.ContainingObjectIndex(info.Levels(false) - 1, false)); int begin = Math.Min(info.ContainingObjectIndex(info.Levels(true) - 1, true), info.ContainingObjectIndex(info.Levels(false) - 1, false)); SelectRange(begin, end); }
/// <summary> /// This override ensures that we always have whole objects selected. /// Enhance: it may cause flicker during drag, in which case, we may change to only do it on mouse up, /// or only IF the mouse is up. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew"></param> public override void SelectionChanged(IVwRootBox prootb, IVwSelection vwselNew) { base.SelectionChanged(prootb, vwselNew); if (m_InSelectionChanged) return; if (RootBox.Selection == null) return; if (!(this is DialogInterlinRibbon)) // We want the selection in the dialog to behave differently. { TextSelInfo info = new TextSelInfo(RootBox); int end = Math.Max(info.ContainingObjectIndex(info.Levels(true) - 1, true), info.ContainingObjectIndex(info.Levels(false) - 1, false)); SelectUpTo(end); } }
private static int GetIndexOfTopLevelObject(TextSelInfo info, bool fEndPoint) { return info.ContainingObjectIndex(info.Levels(fEndPoint) - 1, fEndPoint); }
/// <summary> /// Get info about which cell the user clicked in. /// </summary> /// <param name="e"></param> /// <param name="clickedCell"></param> /// <param name="irow"></param> /// <returns>true if it is a template column, or false if some other column (Notes?)</returns> private bool GetCellInfo(MouseEventArgs e, out ChartLocation clickedCell, out int irow) { clickedCell = null; // in case of premature 'return' irow = -1; int icol = -1; if (m_hvoChart == 0 || m_AllColumns == null || e.Y > m_rootb.Height) return false; Point pt; Rectangle rcSrcRoot; Rectangle rcDstRoot; using (new HoldGraphics(this)) { pt = PixelToView(new Point(e.X, e.Y)); GetCoordRects(out rcSrcRoot, out rcDstRoot); IVwSelection sel = RootBox.MakeSelAt(pt.X, pt.Y, rcSrcRoot, rcDstRoot, false); if (sel == null) return false; TextSelInfo info = new TextSelInfo(sel); if (info.Levels(false) < 2) return false; irow = GetIndexOfTopLevelObject(info, false); IDsConstChart chart = DsConstChart.CreateFromDBObject(Cache, m_hvoChart); Debug.Assert(irow >= 0 && irow < chart.RowsRS.Count); icol = m_logic.GetColumnFromPosition(e.X, m_chart.ColumnPositions) - 1; clickedCell = new ChartLocation(icol, chart.RowsRS[irow]); // return true if we clicked on a valid template column (other than notes) // return false if we clicked on an 'other' column, like notes or row number? return icol > -1 && icol < m_AllColumns.Length; } }
/// <summary> /// Get info about which cell the user clicked in. /// </summary> /// <param name="e"></param> /// <param name="clickedCell">This needs to include the 'logical' column index.</param> /// <param name="irow"></param> /// <returns>true if it is a template column, or false if some other column (Notes?)</returns> private bool GetCellInfo(MouseEventArgs e, out ChartLocation clickedCell, out int irow) { clickedCell = null; // in case of premature 'return' irow = -1; if (m_hvoChart == 0 || AllColumns == null || e.Y > RootBox.Height || e.X > RootBox.Width) return false; Point pt; Rectangle rcSrcRoot; Rectangle rcDstRoot; using (new HoldGraphics(this)) { pt = PixelToView(new Point(e.X, e.Y)); GetCoordRects(out rcSrcRoot, out rcDstRoot); var sel = RootBox.MakeSelAt(pt.X, pt.Y, rcSrcRoot, rcDstRoot, false); if (sel == null) return false; var info = new TextSelInfo(sel); if (info.Levels(false) < 2) return false; irow = GetIndexOfTopLevelObject(info, false); var chart = Cache.ServiceLocator.GetInstance<IDsConstChartRepository>().GetObject(m_hvoChart); if (irow < 0 || chart.RowsOS.Count <= irow) return false; var icol = m_logic.GetColumnFromPosition(e.X, m_chart.ColumnPositions) - 1; if (-1 < icol && icol < AllColumns.Length && e.Clicks > 0) icol = LogicalFromDisplay(icol); // if this is just a mouse move, use 'display' column clickedCell = new ChartLocation(chart.RowsOS[irow], icol); // return true if we clicked on a valid template column (other than notes) // return false if we clicked on an 'other' column, like notes or row number? return -1 < icol && icol < AllColumns.Length; } }