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
008 package edu.wpi.first.wpilibj.buttons;
009
010 import edu.wpi.first.wpilibj.Sendable;
011 import edu.wpi.first.wpilibj.command.Command;
012 import edu.wpi.first.wpilibj.command.Scheduler;
013 import 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
019 * link 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
023 * a 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 functionality
025 * of the Trigger class.
026 *
027 * @author Joe Grinstead
028 */
029 public 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 use is pressed.
042 * @return whether get() return true or the internal table for SmartDashboard use is pressed
043 */
044 private boolean grab() {
045 return get() || (table != null /*&& table.isConnected()*/ && table.getBoolean("pressed", false));//FIXME make is connected work?
046 }
047
048 /**
049 * Starts the given command whenever the trigger just becomes active.
050 * @param command the command to start
051 */
052 public void whenActive(final Command command) {
053 new ButtonScheduler() {
054
055 boolean pressedLast = grab();
056
057 public void execute() {
058 if (grab()) {
059 if (!pressedLast) {
060 pressedLast = true;
061 command.start();
062 }
063 } else {
064 pressedLast = false;
065 }
066 }
067 }.start();
068 }
069
070 /**
071 * Constantly starts the given command while the button is held.
072 *
073 * {@link Command#start()} will be called repeatedly while the trigger is active,
074 * and will be canceled when the trigger becomes inactive.
075 *
076 * @param command the command to start
077 */
078 public void whileActive(final Command command) {
079 new ButtonScheduler() {
080
081 boolean pressedLast = grab();
082
083 public void execute() {
084 if (grab()) {
085 pressedLast = true;
086 command.start();
087 } else {
088 if (pressedLast) {
089 pressedLast = false;
090 command.cancel();
091 }
092 }
093 }
094 }.start();
095 }
096
097 /**
098 * Starts the command when the trigger becomes inactive
099 * @param command the command to start
100 */
101 public void whenInactive(final Command command) {
102 new ButtonScheduler() {
103
104 boolean pressedLast = grab();
105
106 public void execute() {
107 if (grab()) {
108 pressedLast = true;
109 } else {
110 if (pressedLast) {
111 pressedLast = false;
112 command.start();
113 }
114 }
115 }
116 }.start();
117 }
118
119 /**
120 * Toggles a command when the trigger becomes active
121 * @param command the command to toggle
122 */
123 public void toggleWhenActive(final Command command) {
124 new ButtonScheduler() {
125
126 boolean pressedLast = grab();
127
128 public void execute() {
129 if (grab()) {
130 if (!pressedLast) {
131 pressedLast = true;
132 if (command.isRunning()){
133 command.cancel();
134 } else{
135 command.start();
136 }
137 }
138 } else {
139 pressedLast = false;
140 }
141 }
142 }.start();
143 }
144
145 /**
146 * Cancels a command when the trigger becomes active
147 * @param command the command to cancel
148 */
149 public void cancelWhenActive(final Command command) {
150 new ButtonScheduler() {
151
152 boolean pressedLast = grab();
153
154 public void execute() {
155 if (grab()) {
156 if (!pressedLast) {
157 pressedLast = true;
158 command.cancel();
159 }
160 } else {
161 pressedLast = false;
162 }
163 }
164 }.start();
165 }
166
167 /**
168 * An internal class of {@link Trigger}. The user should ignore this, it is
169 * only public to interface between packages.
170 */
171 public abstract class ButtonScheduler {
172 public abstract void execute();
173
174 protected void start() {
175 Scheduler.getInstance().addButton(this);
176 }
177 }
178
179 /**
180 * These methods continue to return the "Button" SmartDashboard type until we decided
181 * to create a Trigger widget type for the dashboard.
182 */
183 public String getSmartDashboardType(){
184 return "Button";
185 }
186 private ITable table;
187 public void initTable(ITable table){
188 this.table = table;
189 if(table!=null){
190 table.putBoolean("pressed", get());
191 }
192 }
193
194 /**
195 * {@inheritDoc}
196 */
197 public ITable getTable(){
198 return table;
199 }
200 }