|
|
|
@ -164,22 +164,25 @@ macro_rules! command_impl {
@@ -164,22 +164,25 @@ macro_rules! command_impl {
|
|
|
|
|
|
|
|
|
|
pub type CommandRef = Rc<RefCell<dyn Command>>; |
|
|
|
|
|
|
|
|
|
pub struct CommandGroup { |
|
|
|
|
commands: Vec<CommandRef>, |
|
|
|
|
command_data: CommandData, |
|
|
|
|
pub struct CommandGroupConfig { |
|
|
|
|
pub commands: Vec<CommandRef>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl CommandGroupConfig { |
|
|
|
|
pub fn new(commands: Vec<CommandRef>) -> Self { |
|
|
|
|
Self { commands } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub struct CommandGroupState { |
|
|
|
|
current_idx: Option<usize>, |
|
|
|
|
has_initialized: bool, |
|
|
|
|
has_cancelled: bool, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl CommandGroup { |
|
|
|
|
pub fn new<TCommands>(data: CommandData, commands: TCommands) -> Self |
|
|
|
|
where |
|
|
|
|
TCommands: IntoIterator<Item = CommandRef>, |
|
|
|
|
{ |
|
|
|
|
CommandGroup { |
|
|
|
|
commands: commands.into_iter().collect(), |
|
|
|
|
command_data: data, |
|
|
|
|
impl Default for CommandGroupState { |
|
|
|
|
fn default() -> Self { |
|
|
|
|
CommandGroupState { |
|
|
|
|
current_idx: None, |
|
|
|
|
has_initialized: false, |
|
|
|
|
has_cancelled: false, |
|
|
|
@ -187,51 +190,49 @@ impl CommandGroup {
@@ -187,51 +190,49 @@ impl CommandGroup {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl WithCommandData for CommandGroup { |
|
|
|
|
fn command_data(&self) -> &CommandData { |
|
|
|
|
&self.command_data |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
pub type CommandGroup = GenericCommand<CommandGroupConfig, CommandGroupState>; |
|
|
|
|
|
|
|
|
|
impl Command for CommandGroup { |
|
|
|
|
fn init(&mut self) { |
|
|
|
|
if self.current_idx.is_some() { |
|
|
|
|
if self.state.current_idx.is_some() { |
|
|
|
|
error!("CommandGroup init called twice"); |
|
|
|
|
} |
|
|
|
|
self.current_idx = Some(0); |
|
|
|
|
self.has_initialized = false; |
|
|
|
|
self.has_cancelled = false; |
|
|
|
|
self.state.current_idx = Some(0); |
|
|
|
|
self.state.has_initialized = false; |
|
|
|
|
self.state.has_cancelled = false; |
|
|
|
|
debug!("CommandGroup {} init", self.command_data().name()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn step(&mut self) -> CommandResult { |
|
|
|
|
use self::CommandResult::*; |
|
|
|
|
if self.has_cancelled { |
|
|
|
|
let state = &mut self.state; |
|
|
|
|
let commands = &self.config.commands; |
|
|
|
|
if state.has_cancelled { |
|
|
|
|
debug!("CommandGroup step called after cancelled"); |
|
|
|
|
return CommandResult::Cancel; |
|
|
|
|
} |
|
|
|
|
let mut current_idx = if let Some(c) = self.current_idx { |
|
|
|
|
let mut current_idx = if let Some(c) = state.current_idx { |
|
|
|
|
c |
|
|
|
|
} else { |
|
|
|
|
error!("CommandGroup step called before init"); |
|
|
|
|
self.has_cancelled = true; |
|
|
|
|
state.has_cancelled = true; |
|
|
|
|
return CommandResult::Cancel; |
|
|
|
|
}; |
|
|
|
|
let mut result: CommandResult; |
|
|
|
|
loop { |
|
|
|
|
if current_idx >= self.commands.len() { |
|
|
|
|
if current_idx >= commands.len() { |
|
|
|
|
debug!("CommandGroup out of commands"); |
|
|
|
|
return CommandResult::Done; |
|
|
|
|
} |
|
|
|
|
let mut command = self.commands[current_idx].borrow_mut(); |
|
|
|
|
if !self.has_initialized { |
|
|
|
|
let mut command = commands[current_idx].borrow_mut(); |
|
|
|
|
if !state.has_initialized { |
|
|
|
|
debug!( |
|
|
|
|
"CommandGroup init {0} ({1})", |
|
|
|
|
current_idx, |
|
|
|
|
command.command_data().name() |
|
|
|
|
); |
|
|
|
|
command.init(); |
|
|
|
|
self.has_initialized = true; |
|
|
|
|
state.has_initialized = true; |
|
|
|
|
} |
|
|
|
|
result = command.step(); |
|
|
|
|
if result != Continue { |
|
|
|
@ -246,29 +247,31 @@ impl Command for CommandGroup {
@@ -246,29 +247,31 @@ impl Command for CommandGroup {
|
|
|
|
|
match result { |
|
|
|
|
Done => { |
|
|
|
|
current_idx += 1; |
|
|
|
|
self.has_initialized = false; |
|
|
|
|
state.has_initialized = false; |
|
|
|
|
} |
|
|
|
|
Cancel => { |
|
|
|
|
self.has_cancelled = true; |
|
|
|
|
state.has_cancelled = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
_ => break, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
self.current_idx = Some(current_idx); |
|
|
|
|
state.current_idx = Some(current_idx); |
|
|
|
|
CommandResult::Continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn finish(&mut self, result: CommandResult) { |
|
|
|
|
let state = &mut self.state; |
|
|
|
|
let commands = &mut self.config.commands; |
|
|
|
|
if result == CommandResult::Cancel { |
|
|
|
|
if let Some(command) = self |
|
|
|
|
if let Some(command) = state |
|
|
|
|
.current_idx |
|
|
|
|
.and_then(|current_idx| self.commands.get(current_idx)) |
|
|
|
|
.and_then(|current_idx| commands.get(current_idx)) |
|
|
|
|
{ |
|
|
|
|
command.borrow_mut().finish(result); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
self.current_idx = None; |
|
|
|
|
state.current_idx = None; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|