1 # Copyright (c) 2009 Paolo Capriotti <p.capriotti@gmail.com>
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 require 'observer_utils.rb'
9 require 'interaction/operation'
10 require 'interaction/operation_history'
15 include OperationInterface
18 attr_reader :operations
20 class Item < Struct.new(:state, :move)
23 OutOfBound = Class.new(Exception)
26 @history = [Item.new(state.dup, nil)]
28 @operations = OperationHistory.new
32 @history.each {|item| yield item.state, item.move }
35 def add_move(state, move, opts = { })
36 op = operation do |op|
37 op.truncate(@current + 1)
38 item = Item.new(state.dup, move)
39 item.text = opts[:text] if opts[:text]
42 op.execute :extra => opts
46 raise OutOfBound if @current >= @history.size - 1
48 item = @history[@current]
51 [item.state, item.move]
55 raise OutOfBound if @current <= 0
56 move = @history[@current].move
60 [@history[@current].state, move]
68 [item.state, item.move]
81 @history[current].state
85 @history[current].state = value
89 def set_item(state, move)
90 @history[current] = Item.new(state, move)
95 @history[current].move
99 op = @operations.undo_operation
106 op = @operations.redo_operation
117 if index >= @history.size || index < 0
125 def add_items(opts, *items)
127 old_current = @current
129 @current = @history.size - 1 if opts.fetch(:go_to_end, true)
131 :old_current => old_current,
132 :old_state => old_state,
138 def remove_items_at(index)
139 @current = index.pred
140 fire :current_changed
142 items = @history[index..-1]
143 @history = @history[0...index]
144 @current = if @current >= index
149 fire :truncate => @current