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)
26 OutOfBound = Class.new(Exception)
29 @history = [Item.new(state.dup, nil)]
31 @operations = OperationHistory.new
35 @history.each {|item| yield item.state, item.move }
38 def add_move(state, move, opts = { })
39 op = operation do |op|
40 op.truncate(@current + 1)
41 item = Item.new(state.dup, move)
42 item.text = opts[:text] if opts[:text]
45 op.execute :extra => opts
49 add_move(UnknownState.new, nil, :quiet => true)
53 raise OutOfBound if @current >= @history.size - 1
55 item = @history[@current]
58 [item.state, item.move]
62 raise OutOfBound if @current <= 0
63 move = @history[@current].move
67 [@history[@current].state, move]
75 [item.state, item.move]
88 @history[current].state
92 @history[current].state = value
97 @history[current].move = value
102 @history[current].text = value
106 def set_item(state, move)
107 @history[current] = Item.new(state, move)
112 @history[current].move
116 op = @operations.undo_operation
123 op = @operations.redo_operation
139 if index >= @history.size || index < 0
146 not @history[i].state.is_a?(UnknownState)
149 def path_defined?(from, to)
150 from, to = [from, to].sort
151 (from..to).all? { |i| valid_index?(i) }
156 def add_items(opts, *items)
158 old_current = @current
160 @current = @history.size - 1 if opts.fetch(:go_to_end, true)
162 :old_current => old_current,
163 :old_state => old_state,
169 def remove_items_at(index, opts = { })
171 fire :current_changed
173 items = @history[index..-1]
174 @history = @history[0...index]
175 @current = if @current >= index
180 fire :truncate => @current