/// <summary> /// Handle a change by adding a record to the database (only if the /// change does not arise directly out of processing a sync record from elsewhere). /// </summary> /// <param name="hvo"></param> /// <param name="tag"></param> /// <param name="ivMin"></param> /// <param name="cvIns"></param> /// <param name="cvDel"></param> public void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel) { CheckDisposed(); if (hvo == m_hvoIgnore && tag == m_flidIgnore) { return; } if (tag < 0) { return; // common for fake properties } // If it's a virtual property we don't want to make a sync record. IVwCacheDa cda = m_cache.MainCacheAccessor as IVwCacheDa; IVwVirtualHandler vh = cda.GetVirtualHandlerId(tag); if (vh != null) { return; } // (CLE-76) Topics List Editor needs to be sync'd with the database when // we make certain changes to possibility lists, especially structural ones // like adding/removing/moving/promoting possibilities. The simplest thing // to do for now, is to indicate a full refresh is needed when any of these // properties are being altered (even if it turns out to be minor). SyncMsg msg = SyncMsg.ksyncSimpleEdit; if (tag == (int)CmPossibility.CmPossibilityTags.kflidName || tag == (int)CmPossibility.CmPossibilityTags.kflidAbbreviation || tag == (int)CmPossibilityList.CmPossibilityListTags.kflidPossibilities || tag == (int)CmPossibility.CmPossibilityTags.kflidSubPossibilities) { // NOTE: assume that apps that watch for ksyncFullRefresh will only // refresh once, and not multiple times if multiple refreshes get posted. // This is how Topic List Editor currently behaves. msg = SyncMsg.ksyncFullRefresh; } m_cache.StoreSync(m_appGuid, new SyncInfo(msg, hvo, tag)); }
/// ------------------------------------------------------------------------------------ /// <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; }