public TextBufferTypingSession(RdTextBuffer buffer) { Assertion.Assert(!buffer.IsMaster, "Master version is not implemented"); myBuffer = buffer; myInitialBufferVersion = myBuffer.BufferVersion; myVersionBeforeOpening = myBuffer.Delegate.VersionBeforeTypingSession.Value; }
private void ReceiveChange(RdTextBufferChange rdTextBufferChange) { var newVersion = rdTextBufferChange.Version; var change = rdTextBufferChange.Change; var side = rdTextBufferChange.Origin; Assertion.Assert(side != myLocalOrigin, "side != mySide"); var masterVersionRemote = newVersion.Master; var slaveVersionRemote = newVersion.Slave; if (change.Kind == RdTextChangeKind.Reset) { ClearState(); } else if (change.Kind == RdTextChangeKind.PromoteVersion) { Assertion.Assert(!IsMaster, "!IsMaster"); BufferVersion = newVersion; return; } else { if (IsMaster) { Assertion.Assert(myChangesToConfirmOrRollback.Count == 0, "changesToConfirmOrRollback.IsEmpty()"); if (masterVersionRemote != BufferVersion.Master) { // reject the change. we've already sent overriding change. return; } } else { if (slaveVersionRemote != BufferVersion.Slave) { // rollback the changes and notify external subscribers // don't need to update history here - all reverted changes were already stored before on 'fire' stage foreach (var ch in Enumerable.Reverse(myChangesToConfirmOrRollback)) { if (ch.Version.Slave <= slaveVersionRemote) { break; } myTextChanged.SetValue(ch.Change.Reverse()); } myChangesToConfirmOrRollback.Clear(); } else { // confirm the changes queue. myChangesToConfirmOrRollback.Clear(); } } } BufferVersion = newVersion; myTextChanged.SetValue(change); }
private static int CompareVersions(TextBufferVersion first, TextBufferVersion second) { if (first.Master != second.Master) { return(first.Master - second.Master); } return(first.Slave - second.Slave); }
private void ReceiveOperation(OtOperation operation) { var remoteOrigin = operation.Origin; var transformedOp = operation; switch (operation.Kind) { case OtOperationKind.Normal: { var newDiff = new List <OtOperation>(); foreach (var localChange in myDiff) { var result = OtFramework.Transform(localChange, transformedOp); newDiff.Add(result.NewLocalDiff); transformedOp = result.LocalizedApplyToDocument; } myDiff = newDiff; break; } case OtOperationKind.Reset: { myDiff = new List <OtOperation>(); break; } default: throw new ArgumentOutOfRangeException(); } BufferVersion = remoteOrigin == RdChangeOrigin.Master ? BufferVersion.IncrementMaster() : BufferVersion.IncrementSlave(); var timestamp = operation.Timestamp; Assertion.Assert(remoteOrigin == RdChangeOrigin.Master ? BufferVersion.Master == timestamp : BufferVersion.Slave == timestamp, "operation.Timestamp == BufferVersion"); var changes = transformedOp.ToRdTextChanges(); for (var i = 0; i < changes.Count; i++) { using (new ComplexChangeCookie(this, i < changes.Count - 1)) { var change = changes[i]; myTextChanged.SetValue(change); } } if (operation.Kind == OtOperationKind.Normal) { SendAck(timestamp); } }
public RdTextBuffer(RdTextBufferState state) : base(state) { myTextChanged = new ViewableProperty <RdTextChange>(); myChangesToConfirmOrRollback = new List <RdTextBufferChange>(); BufferVersion = TextBufferVersion.InitVersion; myLocalOrigin = IsMaster ? RdChangeOrigin.Master : RdChangeOrigin.Slave; // disabling mastering, text buffer must resolve conflicts by itself ((RdProperty <RdTextBufferChange>)Delegate.Changes).IsMaster = false; }
public TextBufferTypingSession(RdTextBuffer buffer) { myBuffer = buffer; myInitialBufferVersion = myBuffer.BufferVersion; if (buffer.IsMaster) { myVersionBeforeOpening = myBuffer.BufferVersion; myBuffer.Delegate.VersionBeforeTypingSession.Value = myInitialBufferVersion; } else { myVersionBeforeOpening = buffer.Delegate.VersionBeforeTypingSession.Value; } }
public RdTextBufferChange(TextBufferVersion version, RdChangeOrigin origin, RdTextChange change) { Change = change; Version = version; Origin = origin; }