001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj2.command; 006 007import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; 008 009import edu.wpi.first.util.sendable.SendableBuilder; 010import java.util.function.Supplier; 011 012/** 013 * Schedules the given command when this command is initialized, and ends when it ends. Useful for 014 * forking off from CommandGroups. If this command is interrupted, it will cancel the command. 015 * 016 * <p>This class is provided by the NewCommands VendorDep 017 */ 018public class ProxyCommand extends CommandBase { 019 private final Supplier<Command> m_supplier; 020 private Command m_command; 021 022 /** 023 * Creates a new ProxyCommand that schedules the supplied command when initialized, and ends when 024 * it is no longer scheduled. Useful for lazily creating commands at runtime. 025 * 026 * @param supplier the command supplier 027 */ 028 public ProxyCommand(Supplier<Command> supplier) { 029 m_supplier = requireNonNullParam(supplier, "supplier", "ProxyCommand"); 030 } 031 032 /** 033 * Creates a new ProxyCommand that schedules the given command when initialized, and ends when it 034 * is no longer scheduled. 035 * 036 * @param command the command to run by proxy 037 */ 038 public ProxyCommand(Command command) { 039 this(() -> command); 040 setName("Proxy(" + command.getName() + ")"); 041 } 042 043 @Override 044 public void initialize() { 045 m_command = m_supplier.get(); 046 m_command.schedule(); 047 } 048 049 @Override 050 public void end(boolean interrupted) { 051 if (interrupted) { 052 m_command.cancel(); 053 } 054 m_command = null; 055 } 056 057 @Override 058 public void execute() {} 059 060 @Override 061 public boolean isFinished() { 062 // because we're between `initialize` and `end`, `m_command` is necessarily not null 063 // but if called otherwise and m_command is null, 064 // it's UB, so we can do whatever we want -- like return true. 065 return m_command == null || !m_command.isScheduled(); 066 } 067 068 /** 069 * Whether the given command should run when the robot is disabled. Override to return true if the 070 * command should run when disabled. 071 * 072 * @return true. Otherwise, this proxy would cancel commands that do run when disabled. 073 */ 074 @Override 075 public boolean runsWhenDisabled() { 076 return true; 077 } 078 079 @Override 080 public void initSendable(SendableBuilder builder) { 081 super.initSendable(builder); 082 builder.addStringProperty( 083 "proxied", () -> m_command == null ? "null" : m_command.getName(), null); 084 } 085}