Esempio n. 1
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Redo the action(s) in this object. This is overridden to do nothing in
        /// non-undoable unit of work, but may be called even from there in one special case.
        /// </summary>
        /// <returns>
        /// Cumulative result of redoing all the actions. If we succeeded, then this will
        /// be kuresSuccess.
        /// </returns>
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Redo the action(s) in this object.
        /// </summary>
        internal virtual UndoResult Redo()
        {
            // Because of the complexities of our undo/redo system, we need to do the redo
            // in multiple passes:
            // 1) Restores any created objects.
            // 2) Redo any actions that are data change actions.
            // 3) Fire any PropChanges.
            // 4) Redo any actions that are not data change actions (e.g., selection change actions)

            m_uowService.SuppressSelections = true;
            UndoResult result = UndoResult.kuresSuccess;

            try
            {
                // Do the first pass (Restores any created objects)
                foreach (IUndoAction undoAction in m_changes)
                {
                    if (undoAction is IFirstPassRedo)
                    {
                        ((IFirstPassRedo)undoAction).FirstPassRedo();
                    }
                }

                // Do the second pass (Redo any actions that are data change actions)
                foreach (IUndoAction undoAction in m_changes)
                {
                    if (undoAction.IsDataChange && !undoAction.Redo())
                    {
                        // TODO: Undo any changes that have been redone
                        return(UndoResult.kuresFailed);
                    }
                }

                try
                {
                    // Do the third pass (Fire any PropChanges)
                    m_uowService.SendPropChangedNotifications(GetPropChangeInformation(false));
                }
                catch (Exception e)
                {
                    Logger.WriteEvent("Exception during PropChanges in Redo");
                    Logger.WriteError(e);
                    result = UndoResult.kuresRefresh;
                }
            }
            finally
            {
                m_uowService.SuppressSelections = false;
            }

            // Do the fourth pass (Redo any actions that are not data change actions)
            foreach (IUndoAction undoAction in m_changes)
            {
                if (!undoAction.IsDataChange && !undoAction.Redo())
                {
                    // TODO: Undo any changes that have been redone
                    return(UndoResult.kuresFailed);
                }
            }

            return(result);
        }
Esempio n. 2
0
        private void EndUndoTaskCommon(bool updateDateModified)
        {
            if (m_uowService.CurrentProcessingState != UnitOfWorkService.FdoBusinessTransactionState.ProcessingDataChanges)
            {
                throw new InvalidOperationException("Cannot end task that has not been started.");
            }

            if (updateDateModified)
            {
                // A generic side effect of all changes is to update DateModified.
                // Collect the objects we want to record the modify time on. Don't do each as found:
                // Updating them will add new dirtballs, which will mess up the DirtyObjects iterator.
                // Also, we don't need the overhead of updating an object repeatedly if it has several changes.
                var collector = new HashSet <ICmObjectInternal>();
                foreach (var item in m_currentBundle.DirtyObjects)
                {
                    item.CollectDateModifiedObject(collector);
                }
                // Don't update the modify time on new objects, it should be near enough, and Undo will fail
                // trying to restore the modify time on the deleted object.
                var newObjects = m_currentBundle.NewObjects;
                foreach (var dmObj in collector)
                {
                    if (!newObjects.Contains(dmObj.Id) && !m_currentBundle.IsDateModifiedExplicitly(dmObj))
                    {
                        dmObj.UpdateDateModified();
                    }
                }
                // Update the project DateModified, but only once every 2 minutes at most.
                if (m_currentBundle.DirtyObjects.Count() > 0)
                {
                    LangProject proj = m_currentBundle.DirtyObjects.ElementAt(0).Cache.LangProject as LangProject;
                    TimeSpan    span = new TimeSpan(DateTime.Now.Ticks - proj.DateModified.Ticks);
                    if (span.Minutes >= 2 || m_currentBundle.DirtyObjects.Contains(proj))
                    {
                        proj.UpdateDateModifiedInternal();
                    }
                }
            }

            m_uowService.m_lock.ExitWriteLock();

            m_uowService.CurrentProcessingState = UnitOfWorkService.FdoBusinessTransactionState.BroadcastingPropChanges;

            if (m_currentBundle.HasDataChange)
            {
                // Can't redo these now.
                // If m_currentBundle can't be finished well,
                // then it can all be rolled back
                ClearRedoStack();
                PushUowOnUndoStack(m_currentBundle);
                m_currentBundle.SetAfterXml();

                m_uowService.SuppressSelections = true;

                try
                {
                    // Handle Step 2.B (PropChanged calls) here.
                    // Do them here because we may not commit yet.
                    // 2.B can be moved after the optional save, but then rethink the states.
                    m_uowService.SendPropChangedNotifications(m_currentBundle.GetPropChangeInformation(false));
                }
                finally
                {
                    m_uowService.SuppressSelections = false;
                }
            }

            m_currentBundle = null;

            m_uowService.CurrentProcessingState = UnitOfWorkService.FdoBusinessTransactionState.ReadyForBeginTask;

            // Do this after we are back in a safe state to do a new UOW, if necessary.
            RaisePropChangedCompleted(false);
        }