/// <summary> /// The stuff common to all the ways we mak an FSI. /// </summary> /// <param name="item"></param> protected void SetupFsi(FilterSortItem item) { MakeCombo(item); item.FilterChanged += new FilterChangeHandler(this.FilterChangedHandler); }
/// <summary> /// Create the common options for all FSI combos (except Integer). /// </summary> /// <param name="item"></param> protected void MakeCombo(FilterSortItem item) { FwComboBox combo = new FwComboBox(); combo.DropDownStyle = ComboBoxStyle.DropDownList; combo.BackColor = SystemColors.Window; combo.WritingSystemFactory = m_wsf; combo.StyleSheet = m_bv.StyleSheet; item.Combo = combo; combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksShowAll), null, item)); string blankPossible = XmlUtils.GetOptionalAttributeValue(item.Spec, "blankPossible", "true"); switch (blankPossible) { case "true": combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksBlanks), new BlankMatcher(), item)); combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksNonBlanks), new NonBlankMatcher(), item)); break; } // Enhance JohnT: figure whether the column has vernacular or analysis data... int ws = 0; if (item.Spec != null) { string wsParam = XmlViewsUtils.FindWsParam(item.Spec); if (wsParam.Length == 0) wsParam = XmlUtils.GetOptionalAttributeValue(item.Spec, "ws", ""); ws = XmlViewsUtils.GetWsFromString(wsParam, m_cache); } if (ws == 0) ws = m_cache.DefaultVernWs; // some sort of fall-back in case we can't determine a WS from the spec. string beSpec = XmlUtils.GetOptionalAttributeValue(item.Spec, "bulkEdit", ""); if (String.IsNullOrEmpty(beSpec)) beSpec = XmlUtils.GetOptionalAttributeValue(item.Spec, "chooserFilter", ""); string sortType = XmlUtils.GetOptionalAttributeValue(item.Spec, "sortType", null); switch (sortType) { case "integer": // For columns which are interger values we offer the user a couple preset filters // one is "0" and the other is "Greater than zero" combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksZero), new ExactMatcher(MatchExactPattern(XMLViewsStrings.ksZero)), item)); combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksGreaterThanZero), new RangeIntMatcher(1, Int32.MaxValue), item)); combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksGreaterThanOne), new RangeIntMatcher(2, Int32.MaxValue), item)); combo.Items.Add(new RestrictComboItem(MakeLabel(XMLViewsStrings.ksRestrict_), item, m_cache.DefaultUserWs, combo)); break; case "date": combo.Items.Add(new RestrictDateComboItem(MakeLabel(XMLViewsStrings.ksRestrict_), item, m_cache.DefaultUserWs, combo)); break; case "YesNo": // For columns which have only the values of "yes" or "no" we offer the user these preset // filters to choose. combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksYes), new ExactMatcher(MatchExactPattern(XMLViewsStrings.ksYes)), item)); combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksNo), new ExactMatcher(MatchExactPattern(XMLViewsStrings.ksNo)), item)); break; case "stringList": string[] labels = m_bv.BrowseView.GetStringList(item.Spec); if (labels == null) break; foreach (string aLabel in labels) { combo.Items.Add(new FilterComboItem(MakeLabel(aLabel), new ExactMatcher(MatchExactPattern(aLabel)), item)); } if (labels.Length > 2) { foreach (string aLabel in labels) { combo.Items.Add(new FilterComboItem(MakeLabel(string.Format(XMLViewsStrings.ksExcludeX, aLabel)), new InvertMatcher(new ExactMatcher(MatchExactPattern(aLabel))), item)); } } break; default: // If it isn't any of those, include the bad spelling item, provided we have a dictionary // for the relevant language, and provided it is NOT a list (for which we will make a chooser). if (!String.IsNullOrEmpty(beSpec)) break; Enchant.Dictionary dict = m_bv.BrowseView.EditingHelper.GetDictionary(ws); if (dict != null) { combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksSpellingErrors), new BadSpellingMatcher(ws, dict), item)); } break; } combo.Items.Add(new FindComboItem(MakeLabel(XMLViewsStrings.ksFilterFor_), item, ws, combo, m_bv)); if (!String.IsNullOrEmpty(beSpec)) { MakeListChoiceFilterItem(item, combo, beSpec, m_bv.Mediator); } // Todo: lots more interesting items. // - search the list for existing names // - "any of" and "none of" launch a dialog with check boxes for all existing values. // - maybe a control to check all items containing... // - "containing" launches dialog asking for string (may contain # at start or end). // - "matching pattern" launches dialog to obtain pattern. // - "custom" may launch dialog with "OR" options and "is, is not, is less than, is greater than, matches,..." // How can we get the current items? May not be available until later... // - May need to add 'ShowList' event to FwComboBox so we can populate the list when we show it. combo.SelectedIndex = 0; // Do this after selecting initial item, so we don't get a spurious notification. combo.SelectedIndexChanged += new EventHandler(Combo_SelectedIndexChanged); combo.AccessibleName = "FwComboBox"; this.Controls.Add(combo); }
// Make a FilterSortItem with a Finder that is an OwnMlPropFinder based on saSpec, // which is a stringalt element. /// ------------------------------------------------------------------------------------ /// <summary> /// Makes the string alt item. /// </summary> /// <param name="viewSpec">The view spec.</param> /// <param name="saSpec">The sa spec.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ protected FilterSortItem MakeStringAltItem(XmlNode viewSpec, XmlNode saSpec) { string className = GetStringAtt(saSpec, "class"); string attrName = GetStringAtt(saSpec, "field"); int ws = LangProject.GetWritingSystem(saSpec, m_cache, null, 0); if (className == null || attrName == null || ws == 0) return null; // Can't interpret an incomplete stringalt. string sWs = m_wsf.GetStrFromWs(ws); if (sWs == null || sWs == "") return null; // must have a valid writing system. int flid = (int)m_mdc.GetFieldId(className, attrName, true); FilterSortItem result = new FilterSortItem(); result.Spec = viewSpec; result.Finder = new OwnMlPropFinder(m_sda, flid, ws); SetupFsi(result); result.Sorter = new GenRecordSorter(new StringFinderCompare(result.Finder, new IcuComparer(sWs))); return result; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Make a FilterSortItem with a Finder that is an OwnIntPropFinder based on intSpec, /// which is an <int> element.. /// </summary> /// <param name="viewSpec">The view spec.</param> /// <param name="intSpec">The int spec.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ protected FilterSortItem MakeIntItem(XmlNode viewSpec, XmlNode intSpec) { string className = GetStringAtt(intSpec, "class"); string attrName = GetStringAtt(intSpec, "field"); if (className == null || attrName == null) return null; // Can't interpret an incomplete int. int flid = (int)m_mdc.GetFieldId(className, attrName, true); FilterSortItem result = new FilterSortItem(); result.Spec = viewSpec; result.Finder = new OwnIntPropFinder(m_sda, flid); MakeIntCombo(result); result.FilterChanged += new FilterChangeHandler(this.FilterChangedHandler); result.Sorter = new GenRecordSorter(new StringFinderCompare(result.Finder, new IntStringComparer())); return result; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Make a FilterSortItem with a finder that is a LayoutFinder with the specified layout name. /// </summary> /// <param name="colSpec">The col spec.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ protected FilterSortItem MakeLayoutItem(XmlNode colSpec) { FilterSortItem result = new FilterSortItem(); result.Spec = colSpec; // SetupFsi uses this to get the writing system to use for the combo. result.Finder = LayoutFinder.CreateFinder(m_cache, colSpec, m_bv.BrowseView.Vc); SetupFsi(result); int ws = LangProject.GetWritingSystem(colSpec, m_cache, null, 0); if (ws == 0) ws = m_cache.DefaultVernWs; string sWs = m_wsf.GetStrFromWs(ws); result.Sorter = new GenRecordSorter(new StringFinderCompare(result.Finder, new IcuComparer(sWs))); return result; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Make a FilterSortItem with a Finder that is MultiIndirectMlPropFinder, where /// the first sequence flid is flidSeq1, and the rest are derived from childSpec, /// the contents of the "frag" n</frag> /// </summary> /// <param name="viewSpec">The view spec.</param> /// <param name="flidSeq1">The flid seq1.</param> /// <param name="childSpec">The child spec.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ protected FilterSortItem MakeMultiIndirectItem(XmlNode viewSpec, int flidSeq1, XmlNode childSpec) { // currently we can only handle more levels of objseq. // enhance JohnT: could enhance MultiIndirectMlPropFinder so it takes information // about which props are sequences, then we could also handle <obj> elements. XmlNode subSpec = childSpec; List<int> flids = new List<int>(); flids.Add(flidSeq1); while(subSpec != null && subSpec.Name == "objseq") { string className = GetStringAtt(subSpec, "class"); string attrName = GetStringAtt(subSpec, "field"); if (className == null || attrName == null) return null; // Can't interpret an incomplete objseq. int flidSeq = (int)m_mdc.GetFieldId(className, attrName, true); flids.Add(flidSeq); subSpec = ExtractFromFlow(m_bv.BrowseView.Vc.GetSubFrag(subSpec)); } if (subSpec == null || subSpec.Name != "stringalt") return null; // leaf must be a stringalt. string classNameS = GetStringAtt(subSpec, "class"); string attrNameS = GetStringAtt(subSpec, "field"); int ws = LangProject.GetWritingSystem(subSpec, m_cache, null, 0); if (classNameS == null || attrNameS == null || ws == 0) return null; // Can't interpret an incomplete stringalt. int flid = (int)m_mdc.GetFieldId(classNameS, attrNameS, true); string sWs = m_wsf.GetStrFromWs(ws); if (sWs == null || sWs == "") return null; // must have a valid writing system. FilterSortItem result = new FilterSortItem(); result.Spec = viewSpec; result.Finder = new MultiIndirectMlPropFinder(m_sda, flids.ToArray(), flid, ws); SetupFsi(result); result.Sorter = new GenRecordSorter(new StringFinderCompare(result.Finder, new IcuComparer(sWs))); return result; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="T:RestrictComboItem"/> class. /// </summary> /// <param name="tssName">Name of the TSS.</param> /// <param name="fsi">The fsi.</param> /// <param name="ws">The ws.</param> /// <param name="combo">The combo.</param> /// ------------------------------------------------------------------------------------ public RestrictComboItem(ITsString tssName, FilterSortItem fsi, int ws, FwComboBox combo) : base(tssName, null, fsi) { m_combo = combo; m_ws = ws; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="T:FindComboItem"/> class. /// </summary> /// <param name="tssName">Name of the TSS.</param> /// <param name="fsi">The fsi.</param> /// <param name="ws">The ws.</param> /// <param name="combo">The combo.</param> /// <param name="bv">The bv.</param> /// ------------------------------------------------------------------------------------ public FindComboItem(ITsString tssName, FilterSortItem fsi, int ws, FwComboBox combo, BrowseViewer bv) : base(tssName, null, fsi) { m_ws = ws; m_combo = combo; m_bv = bv; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="T:ListChoiceComboItem"/> class. /// </summary> /// <param name="tssName">Name of the TSS.</param> /// <param name="fsi">The fsi.</param> /// <param name="cache">The cache.</param> /// <param name="mediator">The mediator.</param> /// <param name="combo">The combo.</param> /// <param name="fAtomic">if set to <c>true</c> [f atomic].</param> /// <param name="filterType">Type of the filter.</param> /// ------------------------------------------------------------------------------------ public ListChoiceComboItem(ITsString tssName, FilterSortItem fsi, FdoCache cache, XCore.Mediator mediator, FwComboBox combo, bool fAtomic, Type filterType) : base(tssName, null, fsi) { m_colSpec = fsi.Spec; if (filterType == null) { m_hvoList = BulkEditBar.GetNamedList(cache, fsi.Spec, "list"); // This basically duplicates the loading of treeBarHandler properties. Currently, we don't have access // to that information in XMLViews, and even if we did, the information may not be loaded until // the user actually switches to that RecordList. XmlNode windowConfiguration = (XmlNode)mediator.PropertyTable.GetValue("WindowConfiguration"); string owningClass; string property; BulkEditBar.GetListInfo(fsi.Spec, out owningClass, out property); XmlNode recordListNode = windowConfiguration.SelectSingleNode( String.Format("//recordList[@owner='{0}' and @property='{1}']", owningClass, property)); XmlNode treeBarHandlerNode = recordListNode.ParentNode.SelectSingleNode("treeBarHandler"); m_includeAbbr = XmlUtils.GetBooleanAttributeValue(treeBarHandlerNode, "includeAbbr"); m_bestWS = XmlUtils.GetOptionalAttributeValue(treeBarHandlerNode, "ws", null); } else { MethodInfo mi = filterType.GetMethod("List", BindingFlags.Public | BindingFlags.Static); m_hvoList = (int)mi.Invoke(null, new object[] { cache }); } m_cache = cache; m_mediator = mediator; m_combo = combo; m_fAtomic = fAtomic; m_filterType = filterType; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determine whether this combo item could have produced the specified filter. /// If so, return the string that should be displayed as the value of the combo box /// when this filter is active. Otherwise return null. /// By default, if the filter is exactly the same, just return your label. /// </summary> /// <param name="recordFilter">The record filter.</param> /// <param name="item">The item.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public override ITsString SetFromFilter(RecordFilter recordFilter, FilterSortItem item) { CheckDisposed(); ListChoiceFilter filter = recordFilter as ListChoiceFilter; if (filter == null) return null; if (!filter.CompatibleFilter(m_colSpec)) return null; return MakeLabel(filter); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determine whether this combo item could have produced the specified filter. /// If so, return the string that should be displayed as the value of the combo box /// when this filter is active. Otherwise return null. /// By default, if the filter is exactly the same, just return your label. /// </summary> /// <param name="recordFilter">The record filter.</param> /// <param name="item">The item.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public virtual ITsString SetFromFilter(RecordFilter recordFilter, FilterSortItem item) { CheckDisposed(); FilterBarCellFilter filter = recordFilter as FilterBarCellFilter; if (filter == null) return null; // combo items that don't produce FilterBarCellFilters should override. if (!filter.Finder.SameFinder(item.Finder)) return null; IMatcher matcher = filter.Matcher; ITsString result = SetFromMatcher(matcher); if (result != null) m_matcher = matcher; return result; }
/// <summary> /// Executes in two distinct scenarios. /// /// 1. If disposing is true, the method has been called directly /// or indirectly by a user's code via the Dispose method. /// Both managed and unmanaged resources can be disposed. /// /// 2. If disposing is false, the method has been called by the /// runtime from inside the finalizer and you should not reference (access) /// other managed objects, as they already have been garbage collected. /// Only unmanaged resources can be disposed. /// </summary> /// <param name="disposing"></param> /// <remarks> /// If any exceptions are thrown, that is fine. /// If the method is being done in a finalizer, it will be ignored. /// If it is thrown by client code calling Dispose, /// it needs to be handled by fixing the bug. /// /// If subclasses override this method, they should call the base implementation. /// </remarks> protected virtual void Dispose(bool disposing) { //Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************"); // Must not be run more than once. if (m_isDisposed) return; if (disposing) { // Dispose managed resources here. //if (m_matcher != null) //{ // if (m_matcher is IDisposable) // (m_matcher as IDisposable).Dispose(); //} } // Dispose unmanaged resources here, whether disposing is true or false. m_matcher = null; m_fsi = null; // Disposed elesewhere. if (m_tssName != null) { Marshal.ReleaseComObject(m_tssName); m_tssName = null; } m_isDisposed = true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="T:FilterComboItem"/> class. /// </summary> /// <param name="tssName">Name of the TSS.</param> /// <param name="matcher">The matcher.</param> /// <param name="fsi">The fsi.</param> /// ------------------------------------------------------------------------------------ public FilterComboItem(ITsString tssName, IMatcher matcher, FilterSortItem fsi) { m_tssName = tssName; m_matcher = matcher; m_fsi = fsi; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Makes the int combo. /// </summary> /// <param name="item">The item.</param> /// ------------------------------------------------------------------------------------ protected void MakeIntCombo(FilterSortItem item) { // This is just similar enough to MakeCombo to be annoying. FwComboBox combo = new FwComboBox(); combo.DropDownStyle = ComboBoxStyle.DropDownList; combo.WritingSystemFactory = m_wsf; item.Combo = combo; combo.Items.Add(new FilterComboItem(MakeLabel(XMLViewsStrings.ksShowAll), null, item)); combo.Items.Add(new RestrictComboItem(MakeLabel(XMLViewsStrings.ksRestrict_), item, m_cache.DefaultUserWs, combo)); combo.SelectedIndex = 0; // Do this after selecting initial item, so we don't get a spurious notification. combo.SelectedIndexChanged +=new EventHandler(Combo_SelectedIndexChanged); combo.AccessibleName = "FwComboBox"; this.Controls.Add(combo); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Make a combo menu item (and install it) for choosing from a list, based on the column /// spec at item.Spec. /// </summary> /// <param name="item">The item.</param> /// <param name="combo">The combo.</param> /// <param name="beSpec">The be spec.</param> /// <param name="mediator">The mediator.</param> /// ------------------------------------------------------------------------------------ private void MakeListChoiceFilterItem(FilterSortItem item, FwComboBox combo, string beSpec, XCore.Mediator mediator) { switch (beSpec) { case "complexListMultiple": combo.Items.Add(new ListChoiceComboItem(MakeLabel(XMLViewsStrings.ksChoose_), item, m_cache, mediator, combo, false, null)); break; case "external": Type beType = DynamicLoader.TypeForLoaderNode(item.Spec); Type filterType = null; if (typeof(ListChoiceFilter).IsAssignableFrom(beType)) { // typically it is a chooserFilter attribute, and gives the actual filter. filterType = beType; } else { // typically got a bulkEdit spec, and the editor class may know a compatible filter class. MethodInfo mi = beType.GetMethod("FilterType", BindingFlags.Static | BindingFlags.Public); if (mi != null) filterType = mi.Invoke(null, null) as Type; } if (filterType != null) { PropertyInfo pi = filterType.GetProperty("Atomic", BindingFlags.Public | BindingFlags.Static); bool fAtomic = false; if (pi != null) fAtomic = (bool)pi.GetValue(null, null); ListChoiceComboItem comboItem = new ListChoiceComboItem(MakeLabel(XMLViewsStrings.ksChoose_), item, m_cache, mediator, combo, fAtomic, filterType); combo.Items.Add(comboItem); PropertyInfo piLeaf = filterType.GetProperty("LeafFlid", BindingFlags.Public | BindingFlags.Static); if (piLeaf != null) comboItem.LeafFlid = (int)piLeaf.GetValue(null, null); } break; case "atomicFlatListItem": // Fall through case "morphTypeListItem": // Fall through case "variantConditionListItem": combo.Items.Add(new ListChoiceComboItem(MakeLabel(XMLViewsStrings.ksChoose_), item, m_cache, mediator, combo, true, null)); break; default: // if we didn't find it, try "chooserFilter", if we haven't already. string chooserFilter = XmlUtils.GetOptionalAttributeValue(item.Spec, "chooserFilter", ""); if (!String.IsNullOrEmpty(chooserFilter) && chooserFilter != beSpec) MakeListChoiceFilterItem(item, combo, chooserFilter, mediator); return; } }