001/*----------------------------------------------------------------------------*/ 002/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */ 003/* Open Source Software - may be modified and shared by FRC teams. The code */ 004/* must be accompanied by the FIRST BSD license file in the root directory of */ 005/* the project. */ 006/*----------------------------------------------------------------------------*/ 007 008package edu.wpi.first.wpilibj.buttons; 009 010import edu.wpi.first.wpilibj.Sendable; 011import edu.wpi.first.wpilibj.command.Command; 012import edu.wpi.first.wpilibj.command.Scheduler; 013import edu.wpi.first.wpilibj.tables.ITable; 014 015/** 016 * This class provides an easy way to link commands to inputs. 017 * 018 * It is very easy to link a button to a command. For instance, you could link 019 * the trigger button of a joystick to a "score" command. 020 * 021 * It is encouraged that teams write a subclass of Trigger if they want to have 022 * something unusual (for instance, if they want to react to the user holding a 023 * button while the robot is reading a certain sensor input). For this, they 024 * only have to write the {@link Trigger#get()} method to get the full 025 * functionality of the Trigger class. 026 * 027 * @author Joe Grinstead 028 */ 029public abstract class Trigger implements Sendable { 030 031 /** 032 * Returns whether or not the trigger is active 033 * 034 * This method will be called repeatedly a command is linked to the Trigger. 035 * 036 * @return whether or not the trigger condition is active. 037 */ 038 public abstract boolean get(); 039 040 /** 041 * Returns whether get() return true or the internal table for SmartDashboard 042 * use is pressed. 043 *$ 044 * @return whether get() return true or the internal table for SmartDashboard 045 * use is pressed 046 */ 047 private boolean grab() { 048 return get() 049 || (table != null /* && table.isConnected() */&& table.getBoolean("pressed", false));// FIXME 050 // make 051 // is 052 // connected 053 // work? 054 } 055 056 /** 057 * Starts the given command whenever the trigger just becomes active. 058 *$ 059 * @param command the command to start 060 */ 061 public void whenActive(final Command command) { 062 new ButtonScheduler() { 063 064 boolean pressedLast = grab(); 065 066 public void execute() { 067 if (grab()) { 068 if (!pressedLast) { 069 pressedLast = true; 070 command.start(); 071 } 072 } else { 073 pressedLast = false; 074 } 075 } 076 }.start(); 077 } 078 079 /** 080 * Constantly starts the given command while the button is held. 081 * 082 * {@link Command#start()} will be called repeatedly while the trigger is 083 * active, and will be canceled when the trigger becomes inactive. 084 * 085 * @param command the command to start 086 */ 087 public void whileActive(final Command command) { 088 new ButtonScheduler() { 089 090 boolean pressedLast = grab(); 091 092 public void execute() { 093 if (grab()) { 094 pressedLast = true; 095 command.start(); 096 } else { 097 if (pressedLast) { 098 pressedLast = false; 099 command.cancel(); 100 } 101 } 102 } 103 }.start(); 104 } 105 106 /** 107 * Starts the command when the trigger becomes inactive 108 *$ 109 * @param command the command to start 110 */ 111 public void whenInactive(final Command command) { 112 new ButtonScheduler() { 113 114 boolean pressedLast = grab(); 115 116 public void execute() { 117 if (grab()) { 118 pressedLast = true; 119 } else { 120 if (pressedLast) { 121 pressedLast = false; 122 command.start(); 123 } 124 } 125 } 126 }.start(); 127 } 128 129 /** 130 * Toggles a command when the trigger becomes active 131 *$ 132 * @param command the command to toggle 133 */ 134 public void toggleWhenActive(final Command command) { 135 new ButtonScheduler() { 136 137 boolean pressedLast = grab(); 138 139 public void execute() { 140 if (grab()) { 141 if (!pressedLast) { 142 pressedLast = true; 143 if (command.isRunning()) { 144 command.cancel(); 145 } else { 146 command.start(); 147 } 148 } 149 } else { 150 pressedLast = false; 151 } 152 } 153 }.start(); 154 } 155 156 /** 157 * Cancels a command when the trigger becomes active 158 *$ 159 * @param command the command to cancel 160 */ 161 public void cancelWhenActive(final Command command) { 162 new ButtonScheduler() { 163 164 boolean pressedLast = grab(); 165 166 public void execute() { 167 if (grab()) { 168 if (!pressedLast) { 169 pressedLast = true; 170 command.cancel(); 171 } 172 } else { 173 pressedLast = false; 174 } 175 } 176 }.start(); 177 } 178 179 /** 180 * An internal class of {@link Trigger}. The user should ignore this, it is 181 * only public to interface between packages. 182 */ 183 public abstract class ButtonScheduler { 184 public abstract void execute(); 185 186 protected void start() { 187 Scheduler.getInstance().addButton(this); 188 } 189 } 190 191 /** 192 * These methods continue to return the "Button" SmartDashboard type until we 193 * decided to create a Trigger widget type for the dashboard. 194 */ 195 public String getSmartDashboardType() { 196 return "Button"; 197 } 198 199 private ITable table; 200 201 public void initTable(ITable table) { 202 this.table = table; 203 if (table != null) { 204 table.putBoolean("pressed", get()); 205 } 206 } 207 208 /** 209 * {@inheritDoc} 210 */ 211 public ITable getTable() { 212 return table; 213 } 214}