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 Command { 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 @SuppressWarnings("this-escape") 039 public ProxyCommand(Command command) { 040 this(() -> command); 041 setName("Proxy(" + command.getName() + ")"); 042 } 043 044 @Override 045 public void initialize() { 046 m_command = m_supplier.get(); 047 m_command.schedule(); 048 } 049 050 @Override 051 public void end(boolean interrupted) { 052 if (interrupted) { 053 m_command.cancel(); 054 } 055 m_command = null; 056 } 057 058 @Override 059 public void execute() {} 060 061 @Override 062 public boolean isFinished() { 063 // because we're between `initialize` and `end`, `m_command` is necessarily not null 064 // but if called otherwise and m_command is null, 065 // it's UB, so we can do whatever we want -- like return true. 066 return m_command == null || !m_command.isScheduled(); 067 } 068 069 /** 070 * Whether the given command should run when the robot is disabled. Override to return true if the 071 * command should run when disabled. 072 * 073 * @return true. Otherwise, this proxy would cancel commands that do run when disabled. 074 */ 075 @Override 076 public boolean runsWhenDisabled() { 077 return true; 078 } 079 080 @Override 081 public void initSendable(SendableBuilder builder) { 082 super.initSendable(builder); 083 builder.addStringProperty( 084 "proxied", () -> m_command == null ? "null" : m_command.getName(), null); 085 } 086}