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 }