/// ------------------------------------------------------------------------------------
        /// <summary>
        /// Return an FdoCollection representing all the records that need to be filtered.
        /// </summary>
        /// <param name="hvoPropOwner">ID of the object that owns the collection to be filtered
        /// </param>
        /// <returns>collection of all items (records) to be filtered</returns>
        /// ------------------------------------------------------------------------------------
        private FdoVector <ICmObject> GetCollectionOfRecordsToFilter(int hvoPropOwner)
        {
            int flid = m_flidProvider.GetFlidForPropOwner(hvoPropOwner);

            if (!m_changeWatchers.ContainsKey(flid))
            {
                m_changeWatchers.Add(flid, new VirtualPropChangeWatcher(flid, this));
            }

            // Return a collection of all items in the vector field
            switch (m_cache.GetFieldType(flid))
            {
            case FieldType.kcptReferenceCollection:
                return(new FdoReferenceCollection <ICmObject>(m_cache, hvoPropOwner, flid));

            case FieldType.kcptReferenceSequence:
                return(new FdoReferenceSequence <ICmObject>(m_cache, hvoPropOwner, flid));

            case FieldType.kcptOwningSequence:
                return(new FdoOwningSequence <ICmObject>(m_cache, hvoPropOwner, flid));

            default:
            case FieldType.kcptOwningCollection:
                return(new FdoOwningCollection <ICmObject>(m_cache, hvoPropOwner, flid));
            }
        }
Example #2
0
		/// <summary>
		/// Creates the appropriate string accessor to the given flid.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="hvoOwner"></param>
		/// <param name="flidOwning"></param>
		/// <param name="sView">Class_Field to load from database (obsolete?)</param>
		/// <returns></returns>
		static public MultiAccessor CreateMultiAccessor(FdoCache cache, int hvoOwner, int flidOwning, string sView)
		{
			FieldType flidType = cache.GetFieldType(flidOwning);
			switch (flidType)
			{
				case FieldType.kcptMultiUnicode:
				case FieldType.kcptMultiBigUnicode:
					return new MultiUnicodeAccessor(cache, hvoOwner, flidOwning, sView);
				case FieldType.kcptMultiString:
				case FieldType.kcptMultiBigString:
					return new MultiStringAccessor(cache, hvoOwner, flidOwning, sView);
				default:
					return null;
			}
		}
Example #3
0
		/// <summary>
		/// This is the ReferenceUi factory.
		/// We currently exclude ReferenceSequenceUi (see that class for reason).
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="rootObj"></param>
		/// <param name="referenceFlid"></param>
		/// <param name="targetHvo"></param>
		/// <returns></returns>
		static public ReferenceBaseUi MakeUi(FdoCache cache, ICmObject rootObj,
			int referenceFlid, int targetHvo)
		{
			FieldType iType = cache.GetFieldType(referenceFlid);
			if (iType == FieldType.kcptReferenceSequence || iType == FieldType.kcptReferenceCollection)
				return new VectorReferenceUi(cache, rootObj, referenceFlid, targetHvo);
			else if (iType == FieldType.kcptReferenceAtom)
				return new ReferenceBaseUi(cache, rootObj, referenceFlid, targetHvo);
			return null;
		}
Example #4
0
		public VectorReferenceUi(FdoCache cache, ICmObject rootObj, int referenceFlid, int targetHvo)
			: base(cache, rootObj, referenceFlid, targetHvo)
		{
			m_iType = cache.GetFieldType(m_flid);
			Debug.Assert(m_iType == FieldType.kcptReferenceSequence ||
					m_iType == FieldType.kcptReferenceCollection);
		}
Example #5
0
		/// <summary>
		/// Returns an array of string values (keys) for the objects under this layout node.
		/// </summary>
		/// <param name="fdoCache"></param>
		/// <param name="layout"></param>
		/// <param name="hvo"></param>
		/// <param name="layoutCache"></param>
		/// <param name="caller">where layout is a component of a 'part' element, caller
		/// is the 'part ref' that invoked it.</param>
		/// <param name="stringTbl"></param>
		/// <param name="wsForce">if non-zero, "string" elements are forced to use that writing system for multistrings.</param>
		/// <returns></returns>
		static public string[] StringsFor(FdoCache fdoCache, XmlNode layout, int hvo,
			LayoutCache layoutCache, XmlNode caller, StringTable stringTbl, int wsForce)
		{
			// Some nodes are known to be uninteresting.
			if (XmlVc.CanSkipNode(layout))
				return new string[0]; // don't know how to sort, treat as empty key.

			switch (layout.Name)
			{
				case "string":
					{
						int hvoTarget = hvo;
						XmlVc.GetActualTarget(layout, ref hvoTarget, fdoCache); // modify the hvo if needed
						if (hvo != hvoTarget)
						{
							return AddStringFromOtherObj(layout, hvoTarget, fdoCache);
						}
						int flid = GetFlid(fdoCache, layout, hvo);
						if (wsForce != 0)
						{
							// If we are forcing a writing system, and it's a multistring, get the forced alternative.
							int itype = fdoCache.MetaDataCacheAccessor.GetFieldType((uint)flid);
							itype = itype & 0x1f; // strip virtual bit
							switch (itype)
							{
								case (int) FieldType.kcptMultiUnicode:
								case (int) FieldType.kcptMultiString:
								case (int) FieldType.kcptMultiBigUnicode:
								case (int) FieldType.kcptMultiBigString:
									return new string[]
											   {fdoCache.MainCacheAccessor.get_MultiStringAlt(hvo, flid, wsForce).Text};
							}
						}
						bool fFoundType;
						string strValue = fdoCache.GetText(hvo, flid, layout, out fFoundType);
						if (fFoundType)
						{
							return new string[] {strValue};
						}
						else
						{
							throw new Exception("Bad property type (" + strValue + " for hvo " + hvo +
												" found for string property "
												+ flid + " in " + layout.OuterXml);
						}
					}
				case "configureMlString":
				{
					int flid = GetFlid(fdoCache, layout, hvo);
					// The Ws info specified in the part ref node
					Set<int> wsIds = LangProject.GetAllWritingSystems(caller, fdoCache, null, hvo, flid);
					if (wsIds.Count == 1)
					{
						string strValue = fdoCache.MainCacheAccessor.get_MultiStringAlt(hvo, flid, wsIds.ToArray()[0]).Text;
						return new string[] {strValue};
					}
					else
						return new string[] {AddMultipleAlternatives(fdoCache, wsIds, hvo, flid, caller)};
				}
				case "multiling":
					return ProcessMultiLingualChildren(fdoCache, layout, hvo, layoutCache, caller, stringTbl, wsForce);
				case "layout":
					// "layout" can occur when GetNodeToUseForColumn returns a phony 'layout'
					// formed by unifying a layout with child nodes. Assemble its children.
					// (arguably, we should treat that like div if current flow is a pile.
					// but we can't tell that and it rarely makes a difference.)
				case "para":
				case "span":
				{
					return AssembleChildKeys(fdoCache, layout, hvo, layoutCache, caller, stringTbl, wsForce);
				}
				case "column":
					// top-level node for whole column; concatenate children as for "para"
					// if multipara is false, otherwise as for "div"
					if (XmlUtils.GetOptionalBooleanAttributeValue(layout, "multipara", false))
						return ChildKeys(fdoCache, layout, hvo, layoutCache, caller, stringTbl, wsForce);
					else
						return AssembleChildKeys(fdoCache, layout, hvo, layoutCache, caller, stringTbl, wsForce);

				case "part":
				{
					string partref = XmlUtils.GetOptionalAttributeValue(layout, "ref");
					if (partref == null)
						return ChildKeys(fdoCache, layout, hvo, layoutCache, caller, stringTbl, wsForce); // an actual part, made up of its pieces
					XmlNode part = XmlVc.GetNodeForPart(hvo, partref, false, fdoCache.MainCacheAccessor, layoutCache);
					// This is the critical place where we introduce a caller. The 'layout' is really a 'part ref' which is the
					// 'caller' for all embedded nodes in the called part.
					return StringsFor(fdoCache, part, hvo, layoutCache, layout, stringTbl, wsForce);
				}
				case "div":
				case "innerpile":
				{
					// Concatenate keys for child nodes (as distinct strings)
					return ChildKeys(fdoCache, layout, hvo, layoutCache, caller, stringTbl, wsForce);
				}
				case "obj":
				{
					// Follow the property, get the object, look up the layout to use,
					// invoke recursively.
					int flid = GetFlid(fdoCache, layout, hvo);
					int hvoTarget = fdoCache.MainCacheAccessor.get_ObjectProp(hvo, flid);
					if (hvoTarget == 0)
						break; // return empty key
					string targetLayoutName = XmlUtils.GetOptionalAttributeValue(layout, "layout"); // uses 'default' if missing.
					XmlNode layoutTarget = GetLayoutNodeForChild(fdoCache, hvoTarget, flid, targetLayoutName, layout, layoutCache);
					if (layoutTarget == null)
						break;
					return ChildKeys(fdoCache, layoutTarget, hvoTarget, layoutCache, caller, stringTbl, wsForce);
				}
				case "seq":
				{
					// Follow the property. For each object, look up the layout to use,
					// invoke recursively, concatenate
					int flid = GetFlid(fdoCache, layout, hvo);
					int ctarget = fdoCache.MainCacheAccessor.get_VecSize(hvo, flid);
					string[] result = null;
					string targetLayoutName = XmlVc.GetLayoutName(layout, caller); // also allows for finding "param" attr in caller, if not null
					//string targetLayoutName = XmlUtils.GetOptionalAttributeValue(layout, "layout");
					for(int i = 0; i < ctarget; i++)
					{
						int hvoTarget = fdoCache.MainCacheAccessor.get_VecItem(hvo, flid, i);
						int prevResultLength = GetArrayLength(result);
						XmlNode layoutTarget = GetLayoutNodeForChild(fdoCache, hvoTarget, flid, targetLayoutName, layout, layoutCache);
						if (layoutTarget == null)
							continue; // should not happen, but best recovery we can make
						result = Concatenate(result, ChildKeys(fdoCache, layoutTarget, hvoTarget, layoutCache, caller, stringTbl, wsForce));
						// add a separator between the new childkey group and the previous childkey group
						if (i > 0 && prevResultLength != GetArrayLength(result) && prevResultLength > 0)
						{
							int ichIns = 0;
							if (result[prevResultLength - 1] != null)
								ichIns = result[prevResultLength - 1].Length;
							AddSeparator(ref result[prevResultLength - 1],  ichIns, layout);
						}
					}
					return result;
				}
				case "choice":
				{
					foreach(XmlNode whereNode in layout.ChildNodes)
					{
						if (whereNode.Name != "where")
						{
							if (whereNode.Name == "otherwise")
								return StringsFor(fdoCache, XmlUtils.GetFirstNonCommentChild(whereNode), hvo, layoutCache, caller, stringTbl, wsForce);
							continue; // ignore any other nodes,typically comments
						}
						// OK, it's a where node.
						if (XmlVc.ConditionPasses(whereNode, hvo, fdoCache, caller))
							return StringsFor(fdoCache, XmlUtils.GetFirstNonCommentChild(whereNode), hvo, layoutCache, caller, stringTbl, wsForce);
					}
					break; // if no condition passes and no otherwise, return null.
				}
				case "if":
				{
					if (XmlVc.ConditionPasses(layout, hvo, fdoCache, caller))
						return StringsFor(fdoCache, XmlUtils.GetFirstNonCommentChild(layout), hvo, layoutCache, caller, stringTbl, wsForce);
					break;
				}
				case "ifnot":
				{
					if (!XmlVc.ConditionPasses(layout, hvo, fdoCache, caller))
						return StringsFor(fdoCache, XmlUtils.GetFirstNonCommentChild(layout), hvo, layoutCache, caller, stringTbl, wsForce);
					break;
				}
				case "lit":
				{
					string literal = layout.InnerText;
					if (stringTbl != null)
					{
						string sTranslate = XmlUtils.GetOptionalAttributeValue(layout, "translate", "");
						if (sTranslate.Trim().ToLower() != "do not translate")
							literal = stringTbl.LocalizeLiteralValue(literal);
					}
					return new string[] { literal };
				}
				case "int":
				{
					int flid = GetFlid(fdoCache, layout, hvo);
					int val = fdoCache.MainCacheAccessor.get_IntProp(hvo, flid);
					return new string[] {XmlViewsUtils.AlphaCompNumberString(val)};
				}
				case "datetime":
				{
					int flid = GetFlid(fdoCache, layout, hvo);
					FieldType itype = fdoCache.GetFieldType(flid);
					if (itype == FieldType.kcptTime)
					{
						DateTime dt = fdoCache.GetTimeProperty(hvo, flid);
						return new string[] {XmlViewsUtils.DateTimeCompString(dt)};
					}
					else
					{
						string stFieldName = XmlUtils.GetManditoryAttributeValue(layout, "field");
						throw new Exception("Bad field type (" + stFieldName + " for hvo " + hvo + " found for " +
							layout.Name + "  property "	+ flid + " in " + layout.OuterXml);
					}
				}
				case "picture":
					// Treat a picture as a non-empty string for purposes of deciding whether something is empty.
					// This string seems as good as anything for other purposes.
					return new string[] {"a picture"};
				default: // unknown or comment node, adds nothing
					Debug.Assert(false, "unrecognized XML node.");
					break;
			}
			return new string[0]; // don't know how to sort, treat as empty key.
		}
Example #6
0
		internal static string[] AddStringFromOtherObj(XmlNode frag, int hvoTarget, FdoCache cache)
		{
			int flid = XmlVc.GetFlid(frag, hvoTarget, cache);
			ITsStrFactory tsf = TsStrFactoryClass.Create();
			FieldType itype = cache.GetFieldType(flid);
			if ((itype == FieldType.kcptUnicode) ||
				(itype == FieldType.kcptBigUnicode))
			{
				return new string[] {cache.GetUnicodeProperty(hvoTarget, flid)};
			}
			else if ((itype == FieldType.kcptString) ||
				(itype == FieldType.kcptBigString))
			{
				return new string[] { cache.GetTsStringProperty(hvoTarget, flid).Text };
			}
			else // multistring of some type
			{
				int wsid = 0;
				string sep = "";
				if (s_cwsMulti > 1)
				{
					string sLabelWs = XmlUtils.GetOptionalAttributeValue(frag, "ws");
					if (sLabelWs != null && sLabelWs == "current")
					{
						sep = DisplayMultiSep(frag, cache)
							+ DisplayWsLabel(s_qwsCurrent, cache);
						wsid = s_qwsCurrent.WritingSystem;
					}
				}
				if (wsid == 0)
					wsid = LangProject.GetWritingSystem(frag, cache, null, LangProject.kwsAnal);
				if ((itype == FieldType.kcptMultiUnicode) ||
					(itype == FieldType.kcptMultiBigUnicode))
				{
					return new string[] {sep, cache.GetMultiUnicodeAlt(hvoTarget, flid, wsid, null) };
				}
				else
				{
					return new string[] {sep, cache.GetMultiStringAlt(hvoTarget, flid, wsid).Text };
				}
			}
		}
Example #7
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Cycle through the applications main windows and synchronize them with database
		/// changes.
		/// </summary>
		/// <param name="sync">synchronization information record</param>
		/// <param name="cache">database cache</param>
		/// <returns>false if a refreshall was performed or presync failed; this suppresses
		/// subsequent sync messages. True to continue processing.</returns>
		/// ------------------------------------------------------------------------------------
		public virtual bool Synchronize(SyncInfo sync, FdoCache cache)
		{
			CheckDisposed();

			if (m_suppressedCaches.ContainsKey(cache))
			{
				Queue<SyncInfo> messages = m_suppressedCaches[cache].Queue;
				if (!messages.Contains(sync))
					messages.Enqueue(sync);
				return true;
			}

			cache.StoreSync(SyncGuid, sync);

			if (sync.msg == SyncMsg.ksyncFullRefresh || sync.msg == SyncMsg.ksyncCustomField)
			{
				RefreshAllViews(cache);
				return false;
			}

			foreach (IFwMainWnd wnd in MainWindows)
			{
				if (wnd.Cache == cache && !wnd.PreSynchronize(sync))
					return false;
			}

			if (sync.msg == SyncMsg.ksyncWs)
			{
				// REVIEW TeTeam: AfLpInfo::Synchronize calls AfLpInfo::FullRefresh, which
				// clears the cache, loads the styles, loads ws and updates wsf, load project
				// basics, updates external link root, load overlays and refreshes possibility
				// lists. I don't think we need to do any of these here.
				RefreshAllViews(cache);
				return false;
			}
			else if (sync.msg == SyncMsg.ksyncPromoteEntry)
			{
				// Review: Write code here to deal with this case. Look at
				// AfLpInfo::Syncronize to see what's necessary.
				// This would be relevant to an application that uses subentries (like Data Notebook--
				// if it used FwApp).
			}
			else if (sync.msg == SyncMsg.ksyncSimpleEdit)
			{
				// Use the UpdatePropIfCached method to update anything that changed that we care about.
				// Todo: need to get Synchronize called for each new syncinfo in DB on window activate.
				IVwOleDbDa odd = cache.VwOleDbDaAccessor;
				int hvo = sync.hvo;
				int flid = sync.flid;
				FieldType iType = cache.GetFieldType(flid);

				switch(iType)
				{
					case FieldType.kcptMultiString:
					case FieldType.kcptMultiUnicode:
					case FieldType.kcptMultiBigString:
					case FieldType.kcptMultiBigUnicode:
						// Try all active WS to see if cached. (Pathologically, if some wss are used for both,
						// they will be updated twice.)
						foreach (int ws in cache.LangProject.VernWssRC.HvoArray)
							odd.UpdatePropIfCached(hvo, flid, (int)iType, ws);
						foreach (int ws in cache.LangProject.AnalysisWssRC.HvoArray)
							odd.UpdatePropIfCached(hvo, flid, (int)iType, ws);
						// This will usually prevent a double-update; pathologically, one might still happen
						// if the user ws is in the analysis or vernacular lists but is not the first analysis one.
						if (cache.DefaultUserWs != cache.DefaultAnalWs)
							odd.UpdatePropIfCached(hvo, flid, (int)iType, cache.DefaultUserWs);
						break;
					case 0:
						// This is very rare but possible.  Do nothing since kcptNull is not a real data
						// type, hence cannot have any data.
						break;
					default:
						odd.UpdatePropIfCached(hvo, flid, (int)iType, 0);
						break;
				}
				return true;
			}

			foreach (IFwMainWnd wnd in MainWindows)
			{
				if (wnd.Cache == cache && !wnd.Synchronize(sync))
				{
					// The window itself was not able to process the message successfully;
					// play safe and refresh everything
					RefreshAllViews(cache);
					return false;
				}
			}

			return true;
		}