Java tutorial
/******************************************************************************* * Copyright 2011 See AUTHORS file. * * 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 com.badlogic.gdx.scenes.scene2d.ui; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Touchable; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.Disableable; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Pools; /** A button is a {@link Table} with a checked state and additional {@link ButtonStyle style} fields for pressed, unpressed, and * checked. Each time a button is clicked, the checked state is toggled. Being a table, a button can contain any other actors.<br> * <br> * The button's padding is set to the background drawable's padding when the background changes, overwriting any padding set * manually. Padding can still be set on the button's table cells. * <p> * {@link ChangeEvent} is fired when the button is clicked. Cancelling the event will restore the checked button state to what is * was previously. * <p> * The preferred size of the button is determined by the background and the button contents. * @author Nathan Sweet */ public class Button extends Table implements Disableable { private ButtonStyle style; boolean isChecked, isDisabled; ButtonGroup buttonGroup; private ClickListener clickListener; public Button(Skin skin) { super(skin); initialize(); setStyle(skin.get(ButtonStyle.class)); setSize(getPrefWidth(), getPrefHeight()); } public Button(Skin skin, String styleName) { super(skin); initialize(); setStyle(skin.get(styleName, ButtonStyle.class)); setSize(getPrefWidth(), getPrefHeight()); } public Button(Actor child, Skin skin, String styleName) { this(child, skin.get(styleName, ButtonStyle.class)); } public Button(Actor child, ButtonStyle style) { initialize(); add(child); setStyle(style); setSize(getPrefWidth(), getPrefHeight()); } public Button(ButtonStyle style) { initialize(); setStyle(style); setSize(getPrefWidth(), getPrefHeight()); } /** Creates a button without setting the style or size. At least a style must be set before using this button. */ public Button() { initialize(); } private void initialize() { setTouchable(Touchable.enabled); addListener(clickListener = new ClickListener() { public void clicked(InputEvent event, float x, float y) { if (isDisabled()) return; setChecked(!isChecked); } }); } public Button(Drawable up) { this(new ButtonStyle(up, null, null)); } public Button(Drawable up, Drawable down) { this(new ButtonStyle(up, down, null)); } public Button(Drawable up, Drawable down, Drawable checked) { this(new ButtonStyle(up, down, checked)); } public Button(Actor child, Skin skin) { this(child, skin.get(ButtonStyle.class)); } public void setChecked(boolean isChecked) { if (this.isChecked == isChecked) return; if (buttonGroup != null && !buttonGroup.canCheck(this, isChecked)) return; this.isChecked = isChecked; ChangeEvent changeEvent = Pools.obtain(ChangeEvent.class); if (fire(changeEvent)) this.isChecked = !isChecked; Pools.free(changeEvent); } /** Toggles the checked state. This method changes the checked state, which fires a {@link ChangeEvent}, so can be used to * simulate a button click. */ public void toggle() { setChecked(!isChecked); } public boolean isChecked() { return isChecked; } public boolean isPressed() { return clickListener.isVisualPressed(); } public boolean isOver() { return clickListener.isOver(); } public ClickListener getClickListener() { return clickListener; } public boolean isDisabled() { return isDisabled; } /** When true, the button will not toggle {@link #isChecked()} when clicked and will not fire a {@link ChangeEvent}. */ public void setDisabled(boolean isDisabled) { this.isDisabled = isDisabled; } public void setStyle(ButtonStyle style) { if (style == null) throw new IllegalArgumentException("style cannot be null."); this.style = style; Drawable background = null; if (isPressed() && !isDisabled()) { background = style.down == null ? style.up : style.down; } else { if (isDisabled() && style.disabled != null) background = style.disabled; else if (isChecked && style.checked != null) background = (isOver() && style.checkedOver != null) ? style.checkedOver : style.checked; else if (isOver() && style.over != null) background = style.over; else background = style.up; } setBackground(background); } /** Returns the button's style. Modifying the returned style may not have an effect until {@link #setStyle(ButtonStyle)} is * called. */ public ButtonStyle getStyle() { return style; } public void draw(Batch batch, float parentAlpha) { validate(); boolean isPressed = isPressed(); boolean isDisabled = isDisabled(); Drawable background = null; if (isDisabled && style.disabled != null) background = style.disabled; else if (isPressed && style.down != null) background = style.down; else if (isChecked && style.checked != null) background = (style.checkedOver != null && isOver()) ? style.checkedOver : style.checked; else if (isOver() && style.over != null) background = style.over; else if (style.up != null) // background = style.up; setBackground(background); float offsetX = 0, offsetY = 0; if (isPressed && !isDisabled) { offsetX = style.pressedOffsetX; offsetY = style.pressedOffsetY; } else { offsetX = style.unpressedOffsetX; offsetY = style.unpressedOffsetY; } Array<Actor> children = getChildren(); for (int i = 0; i < children.size; i++) children.get(i).moveBy(offsetX, offsetY); super.draw(batch, parentAlpha); for (int i = 0; i < children.size; i++) children.get(i).moveBy(-offsetX, -offsetY); } public float getPrefWidth() { float width = super.getPrefWidth(); if (style.up != null) width = Math.max(width, style.up.getMinWidth()); if (style.down != null) width = Math.max(width, style.down.getMinWidth()); if (style.checked != null) width = Math.max(width, style.checked.getMinWidth()); return width; } public float getPrefHeight() { float height = super.getPrefHeight(); if (style.up != null) height = Math.max(height, style.up.getMinHeight()); if (style.down != null) height = Math.max(height, style.down.getMinHeight()); if (style.checked != null) height = Math.max(height, style.checked.getMinHeight()); return height; } public float getMinWidth() { return getPrefWidth(); } public float getMinHeight() { return getPrefHeight(); } /** The style for a button, see {@link Button}. * @author mzechner */ static public class ButtonStyle { /** Optional. */ public Drawable up, down, over, checked, checkedOver, disabled; /** Optional. */ public float pressedOffsetX, pressedOffsetY, unpressedOffsetX, unpressedOffsetY; public ButtonStyle() { } public ButtonStyle(Drawable up, Drawable down, Drawable checked) { this.up = up; this.down = down; this.checked = checked; } public ButtonStyle(ButtonStyle style) { this.up = style.up; this.down = style.down; this.over = style.over; this.checked = style.checked; this.checkedOver = style.checkedOver; this.disabled = style.disabled; this.pressedOffsetX = style.pressedOffsetX; this.pressedOffsetY = style.pressedOffsetY; this.unpressedOffsetX = style.unpressedOffsetX; this.unpressedOffsetY = style.unpressedOffsetY; } } }