use super::Operation;
use buffer::Buffer;
pub struct OperationGroup {
operations: Vec<Box<Operation>>,
}
impl Operation for OperationGroup {
fn run(&mut self, buffer: &mut Buffer) {
for operation in &mut self.operations {
operation.run(buffer);
}
}
fn reverse(&mut self, buffer: &mut Buffer) {
for operation in &mut self.operations.iter_mut().rev() {
operation.reverse(buffer);
}
}
fn clone_operation(&self) -> Box<Operation> {
Box::new(OperationGroup{
operations: self.operations.iter().map(|o| (*o).clone_operation()).collect()
})
}
}
impl OperationGroup {
pub fn new() -> OperationGroup {
OperationGroup{ operations: Vec::new() }
}
pub fn add(&mut self, operation: Box<Operation>) {
self.operations.push(operation);
}
pub fn is_empty(&self) -> bool {
self.operations.is_empty()
}
}
impl Buffer {
pub fn start_operation_group(&mut self) {
match self.operation_group {
Some(_) => (),
None => {
self.operation_group = Some(OperationGroup::new());
}
}
}
pub fn end_operation_group(&mut self) {
match self.operation_group.take() {
Some(group) => {
if !group.is_empty() {
self.history.add(Box::new(group))
}
},
None => (),
}
}
}
#[cfg(test)]
mod tests {
use super::OperationGroup;
use buffer::operations::Insert;
use buffer::{Buffer, Position};
use buffer::operation::Operation;
#[test]
fn run_and_reverse_call_themselves_on_all_operations() {
let mut group = OperationGroup::new();
let mut buffer = Buffer::new();
let first = Box::new(Insert::new("something".to_string(), Position{ line: 0, offset: 0 }));
let second = Box::new(Insert::new(" else".to_string(), Position{ line: 0, offset: 9 }));
group.add(first);
group.add(second);
group.run(&mut buffer);
assert_eq!(buffer.data(), "something else");
group.reverse(&mut buffer);
assert_eq!(buffer.data(), "");
}
#[test]
fn end_operation_group_drops_group_if_empty() {
let mut buffer = Buffer::new();
buffer.insert("amp");
buffer.start_operation_group();
buffer.end_operation_group();
buffer.undo();
assert_eq!(buffer.data(), "");
}
}