Class: VER::Undo::Tree

Inherits:
Struct
  • Object
show all
Defined in:
lib/ver/undo.rb

Overview

The Tree keeps track of the current Record and creates new records.

It maintains a pointer to the widget and the current record in the tree. The current record is the record that was last applied.

When a record is undone: If there is a parent, it becomes the new current record. If there is no parent, it stays the current record, only flagged as unapplied. it’s parent (if there is one), becomes the new current record.

When a record is redone, it’s current child (if there is one), becomes the new current record.

The Tree doesn’t have a maximum depth at the moment, but this will be added, when old records are pruned, only the record at depth+1 that is current stays.

Eventually we have to separate records and undo/redo stepping. Some operations involve more than one record, but should be undone/redone together. It would also be handy if these operations could be identified automagically (like multiple operations within one record block).

Constant Summary

Constants inherited from Struct

Struct::CACHE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Struct

new

Constructor Details

#initialize(widget) ⇒ Tree

Returns a new instance of Tree.



28
29
30
31
# File 'lib/ver/undo.rb', line 28

def initialize(widget)
  self.widget = widget
  self.stack = []
end

Instance Attribute Details

#appliedObject

Returns the value of attribute applied

Returns:

  • (Object)

    the current value of applied



27
28
29
# File 'lib/ver/undo.rb', line 27

def applied
  @applied
end

#pendingObject

Returns the value of attribute pending

Returns:

  • (Object)

    the current value of pending



27
28
29
# File 'lib/ver/undo.rb', line 27

def pending
  @pending
end

#recordingObject

Returns the value of attribute recording

Returns:

  • (Object)

    the current value of recording



27
28
29
# File 'lib/ver/undo.rb', line 27

def recording
  @recording
end

#stackObject

Returns the value of attribute stack

Returns:

  • (Object)

    the current value of stack



27
28
29
# File 'lib/ver/undo.rb', line 27

def stack
  @stack
end

#widgetObject

Returns the value of attribute widget

Returns:

  • (Object)

    the current value of widget



27
28
29
# File 'lib/ver/undo.rb', line 27

def widget
  @widget
end

Instance Method Details

#compact!Object

Join previous applied changes that have only one child and that modify data consecutive. This rewrites already applied history only.



94
95
96
97
98
# File 'lib/ver/undo.rb', line 94

def compact!
  return unless applied
  applied.compact!
  self.pending = applied.next
end

#recordObject



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/ver/undo.rb', line 41

def record
  if recording
    stack << Proc.new
  else
    self.recording = true
    current = Record.new(self, widget, applied)

    yield current

    applied.next = current if applied = self.applied

    self.applied = current
    self.applied = current
    self.pending = nil

    compact!
    self.recording = false

    if pending = stack.shift
      record(&pending)
    end
  end
end

#record_multiObject



33
34
35
36
37
38
39
# File 'lib/ver/undo.rb', line 33

def record_multi
  AutoSeparator.new self do |auto_separator|
    yield auto_separator
  end

  compact!
end

#redoObject

Redo pending change so it becomes the new applied change. If the pending change has a next child, it becomes the new pending one.



80
81
82
83
84
85
86
87
88
89
# File 'lib/ver/undo.rb', line 80

def redo
  while pending = self.pending
    pending.redo

    self.applied = pending
    self.pending = pending.next

    break if pending && pending.separator
  end
end

#separate!Object



100
101
102
# File 'lib/ver/undo.rb', line 100

def separate!
  applied.separator = true if applied
end

#undoObject

Undo last applied change so it becomes the next pending change. Parent of the applied change becomes the next applied change.



67
68
69
70
71
72
73
74
75
76
# File 'lib/ver/undo.rb', line 67

def undo
  while applied = self.applied
    applied.undo

    self.pending = applied
    self.applied = applied = applied.parent

    break if applied && applied.separator
  end
end