private void SocketClient_ReceivedMessage(object sender, EventArgs e)
        {
            using (var ms = new MemoryStream(SocketClient.ReceiveMessage()))
            {
                Dispatcher.Invoke(() =>
                {
                    var caretIndex = txtDocument.CaretIndex;

                    AppliedOperation appliedOperation = ProtoBuf.Serializer.Deserialize <AppliedOperation>(ms);
                    try
                    {
                        DocumentState.ApplyTransform(appliedOperation, ref caretIndex);
                    }
                    catch (Exception)
                    {
                        System.Diagnostics.Debugger.Break();
                        throw;
                    }

                    txtDocument.TextChanged -= Document_TextChanged;
                    txtDocument.Text         = DocumentState.CurrentState;
                    txtDocument.TextChanged += Document_TextChanged;
                    txtDocument.CaretIndex   = caretIndex;
                });
            }
        }
        private void ApplyAndSendChanges(TextBox sender, ICollection <TextChange> textChanges)
        {
            var caretIndex = txtDocument.CaretIndex;

            foreach (var change in textChanges)
            {
                AppliedOperation appliedOperation = null;

                if (change.AddedLength != 0)
                {
                    var addedString      = (sender).Text.Substring(change.Offset, change.AddedLength);
                    var changeCharOffset = change.Offset;
                    foreach (var c in addedString)
                    {
                        appliedOperation = new AppliedOperation(new InsertOperation(DocumentState, changeCharOffset++, c), DocumentState);
                        DocumentState.ApplyTransform(appliedOperation, ref caretIndex);
                        SendOperation(appliedOperation);
                    }
                }
                else
                {
                    var removedString = (sender).Text.Substring(change.Offset, change.RemovedLength);
                    foreach (var c in removedString)
                    {
                        appliedOperation = new AppliedOperation(new DeleteOperation(DocumentState, change.Offset), DocumentState);
                        DocumentState.ApplyTransform(appliedOperation, ref caretIndex);
                        SendOperation(appliedOperation);
                    }
                }
            }
            txtDocument.CaretIndex = caretIndex;
        }
Exemplo n.º 3
0
        public void DocumentState_ApplyTransform_Convergence_MultipleInsertsSameIndex()
        {
            var localDocumentState  = new DocumentState(1, "");
            var remoteDocumentState = new DocumentState(2, "");
            var localTransform      = new AppliedOperation(new InsertOperation(localDocumentState, 0, 'x'), localDocumentState);

            localDocumentState.ApplyTransform(localTransform);
            var localTransform2 = new AppliedOperation(new InsertOperation(localDocumentState, 1, 'x'), localDocumentState);

            localDocumentState.ApplyTransform(localTransform2);

            var remoteTransform = new AppliedOperation(new InsertOperation(remoteDocumentState, 0, 'Y'), remoteDocumentState);

            remoteDocumentState.ApplyTransform(remoteTransform);
            var remoteTransform2 = new AppliedOperation(new InsertOperation(remoteDocumentState, 1, 'Y'), remoteDocumentState);

            remoteDocumentState.ApplyTransform(remoteTransform2);

            localDocumentState.ApplyTransform(remoteTransform);
            localDocumentState.ApplyTransform(remoteTransform2);

            remoteDocumentState.ApplyTransform(localTransform);
            remoteDocumentState.ApplyTransform(localTransform2);

            Assert.AreEqual(localDocumentState.CurrentState, remoteDocumentState.CurrentState);
        }
        /// <summary>
        /// Applies an operation based on another site document (defined by a list of ids of operations that were applied prior to this one)
        /// and adjusts the supplied caret index as appropriate
        /// </summary>
        /// <param name="appliedOperation"></param>
        /// <param name="caretIndex"></param>
        public void ApplyTransform(AppliedOperation appliedOperation, ref int caretIndex)
        {
            var missingRemoteTransformIds = _AppliedOperationsOrder.Except(appliedOperation.PriorStateTransformIds);

            var operation = appliedOperation.Operation;

            foreach (var id in missingRemoteTransformIds.Reverse())
            {
                operation = OperationTransformer.Transform(operation, _AppliedOperations[id]);
            }

            TransformState(operation);

            if (operation.Position < caretIndex)
            {
                if (operation is InsertOperation)
                {
                    caretIndex += operation.Length;
                    caretIndex  = Math.Min(caretIndex, CurrentState.Length);
                }
                else if (operation is DeleteOperation)
                {
                    caretIndex -= operation.Length;
                    caretIndex  = Math.Max(caretIndex, 0);
                }
            }
        }
 private void SendOperation(AppliedOperation appliedOperation)
 {
     using (var ms = new MemoryStream())
     {
         ProtoBuf.Serializer.Serialize(ms, appliedOperation);
         Task.Delay(10000).ContinueWith(t => SocketClient.Send(ms.ToArray()));
     }
 }
        /// <summary>
        /// Undo the last transaction
        /// </summary>
        public AppliedOperation Undo(ref int caretIndex)
        {
            var lastOp = _AppliedOperationsOrder.Select(id => _AppliedOperations[id]).Last(ao => ao.UserId == UserId);

            AppliedOperation undoOperation = new AppliedOperation(lastOp.CreateInverse(this), this);

            ApplyTransform(undoOperation, ref caretIndex);
            return(undoOperation);
        }
Exemplo n.º 7
0
        public AppliedOperation SaveOperation(AppliedOperation appliedOperation)
        {
            var account = GetAccountFromId(appliedOperation.Operation.AccountId);

            // TODO check account.CurrentBalance == appliedOperation.BalanceBeforeApply
            account.CurrentBalance = appliedOperation.BalanceAfterApply;
            account.OperationHistory.Add(appliedOperation);

            return(appliedOperation);
        }
Exemplo n.º 8
0
        public void DocumentState_ApplyTransform_Convergence()
        {
            var localDocumentState  = new DocumentState(1, "12345");
            var remoteDocumentState = new DocumentState(2, "12345");
            var localTransform      = new AppliedOperation(new InsertOperation(localDocumentState, 0, 'x'), localDocumentState);
            var remoteTransform     = new AppliedOperation(new InsertOperation(remoteDocumentState, 2, 'Y'), remoteDocumentState);

            localDocumentState.ApplyTransform(localTransform);
            localDocumentState.ApplyTransform(remoteTransform);

            remoteDocumentState.ApplyTransform(remoteTransform);
            remoteDocumentState.ApplyTransform(localTransform);

            Assert.AreEqual(localDocumentState.CurrentState, remoteDocumentState.CurrentState);
        }
Exemplo n.º 9
0
        public void DocumentState_ApplyTransform_IntentionPreservation()
        {
            var localDocumentState  = new DocumentState(1, "ABCDE");
            var remoteDocumentState = new DocumentState(2, "ABCDE");
            var localTransform      = new AppliedOperation(new InsertOperation(localDocumentState, 1, '1'), localDocumentState);
            var localTransform2     = new AppliedOperation(new InsertOperation(localDocumentState, 2, '2'), new[] { localTransform.Operation.Id });
            var remoteTransform     = new AppliedOperation(new DeleteOperation(remoteDocumentState, 2), remoteDocumentState);
            var remoteTransform2    = new AppliedOperation(new DeleteOperation(remoteDocumentState, 2), new[] { remoteTransform.Operation.Id });

            localDocumentState.ApplyTransform(localTransform);
            localDocumentState.ApplyTransform(localTransform2);
            localDocumentState.ApplyTransform(remoteTransform);
            localDocumentState.ApplyTransform(remoteTransform2);

            Assert.AreEqual("A12BE", localDocumentState.CurrentState);
        }
        /// <summary>
        /// Applies an operation based on another site document (defined by a list of ids of operations that were applied prior to this one)
        /// </summary>
        /// <param name="appliedOperation"></param>
        internal void ApplyTransform(AppliedOperation appliedOperation)
        {
            var caretIndex = 0;

            ApplyTransform(appliedOperation, ref caretIndex);
        }