/**
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.waveprotocol.wave.client.widget.button;
import com.google.gwt.user.client.Event;
/**
* Implements the logic for buttons that have two logical states and that toggle
* between those states when they are clicked.
*
*/
public class ToggleButton implements UniversalButton<ToggleButtonController> {
/**
* Is this button currently on? A {@link ToggleButton} is initially off, and
* toggles between on and off whenever it is clicked.
*/
protected boolean isOn = false;
/**
* Is the mouse currently over the button?
*/
protected boolean isMouseOver = false;
/**
* Is the mouse button currently down?
*/
protected boolean isMouseDown = false;
/**
* Is this button disabled?
*/
protected boolean isDisabled = false;
/**
* The visual representation of this button.
*/
protected ButtonDisplay display;
/**
* User-provided callback to be fired when the button is toggled.
*/
protected ToggleButtonListener toggleListener;
/**
* Contains actions to be performed when a toggle button is toggled.
*
*/
public interface ToggleButtonListener {
/**
* Called when the button is toggled to the 'on' state.
*/
void onOn();
/**
* Called when the button is toggled to the 'off' state.
*/
void onOff();
}
protected MouseListener mouseListener = new MouseListener() {
@Override
public void onClick() {
if (isDisabled) {
return;
}
isOn = !isOn;
if (isOn) {
toggleListener.onOn();
} else {
toggleListener.onOff();
}
updateState();
}
@Override
public void onMouseDown() {
Event.getCurrentEvent().stopPropagation();
Event.getCurrentEvent().preventDefault();
isMouseDown = true;
updateState();
}
@Override
public void onMouseEnter() {
isMouseOver = true;
updateState();
}
@Override
public void onMouseLeave() {
isMouseDown = false;
isMouseOver = false;
updateState();
}
@Override
public void onMouseUp() {
isMouseDown = false;
updateState();
}
};
@Override
public MouseListener getUiEventListener() {
return mouseListener;
}
/**
/**
* Sets whether or not this toggle button is on or off.
*
* @param isOn {@code true} to turn this button on, {@code false} to turn it
* off.
*/
public void setIsOn(boolean isOn) {
this.isOn = isOn;
updateState();
}
/**
* @return {@code true} if this button is on.
*/
public boolean isOn() {
return isOn;
}
/**
* @return {@code true} if this button is off.
*/
public boolean isOff() {
return !isOn;
}
/**
* Updates the visual state of the button to reflect the current logical
* state.
*/
protected void updateState() {
if (isDisabled) {
setState(ButtonDisplay.ButtonState.DISABLED);
return;
}
if (isOn) {
setState(ButtonDisplay.ButtonState.DOWN);
return;
}
if (isMouseOver) {
setState(isMouseDown ? ButtonDisplay.ButtonState.DOWN
: ButtonDisplay.ButtonState.HOVER);
} else {
setState(ButtonDisplay.ButtonState.NORMAL);
}
}
/**
* Sets a new state for this button and notifies the display.
*
* @param state The new state for this button.
*/
private void setState(ButtonDisplay.ButtonState state) {
// NOTE(patcoleman): Does not check here to see whether the new state is the same
// as the current state - possible optimisation can be added to return on NOOP? i.e.
// if(newState.equals(state)) return;
if (display != null) {
display.setState(state);
}
}
@Override
public void setButtonDisplay(ButtonDisplay display) {
this.display = display;
updateState();
}
/**
* @param toggleListener Listener for toggle events.
*/
public void setToggleButtonListener(ToggleButtonListener toggleListener) {
this.toggleListener = toggleListener;
}
/**
* The controller that external users can use to control this toggle button.
*/
protected final ToggleButtonController controller = new ToggleButtonController() {
@Override
public void setOn(boolean isOn) {
ToggleButton.this.isOn = isOn;
updateState();
}
@Override
public void setToggleListener(ToggleButtonListener listener) {
setToggleButtonListener(listener);
}
@Override
public void setDisabled(boolean isDisabled) {
if (ToggleButton.this.isDisabled != isDisabled) {
ToggleButton.this.isDisabled = isDisabled;
updateState();
}
}
};
@Override
public ToggleButtonController getController() {
return controller;
}
}