com.kotcrab.vis.ui.widget.VisWindow Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vis-ui Show documentation
Show all versions of vis-ui Show documentation
UI toolkit and flat design skin for scene2d.ui
/*
* Copyright 2014-2017 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.kotcrab.vis.ui.widget;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.scenes.scene2d.*;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Align;
import com.kotcrab.vis.ui.FocusManager;
import com.kotcrab.vis.ui.VisUI;
/**
* Extends functionality of standard scene2d.ui {@link Window}.
* @author Kotcrab
* @see Window
*/
public class VisWindow extends Window {
public static float FADE_TIME = 0.3f;
private boolean centerOnAdd;
private boolean keepWithinParent = false;
private boolean fadeOutActionRunning;
public VisWindow (String title) {
this(title, true);
getTitleLabel().setAlignment(VisUI.getDefaultTitleAlign());
}
public VisWindow (String title, boolean showWindowBorder) {
super(title, VisUI.getSkin(), showWindowBorder ? "default" : "noborder");
getTitleLabel().setAlignment(VisUI.getDefaultTitleAlign());
}
public VisWindow (String title, String styleName) {
super(title, VisUI.getSkin(), styleName);
getTitleLabel().setAlignment(VisUI.getDefaultTitleAlign());
}
public VisWindow (String title, WindowStyle style) {
super(title, style);
getTitleLabel().setAlignment(VisUI.getDefaultTitleAlign());
}
@Override
public void setPosition (float x, float y) {
super.setPosition((int) x, (int) y);
}
/**
* Centers this window, if it has parent it will be done instantly, if it does not have parent it will be centered when it will
* be added to stage
* @return true when window was centered, false when window will be centered when added to stage
*/
public boolean centerWindow () {
Group parent = getParent();
if (parent == null) {
centerOnAdd = true;
return false;
} else {
moveToCenter();
return true;
}
}
/**
* @param centerOnAdd if true window position will be centered on screen after adding to stage
* @see #centerWindow()
*/
public void setCenterOnAdd (boolean centerOnAdd) {
this.centerOnAdd = centerOnAdd;
}
@Override
protected void setStage (Stage stage) {
super.setStage(stage);
if (stage != null) {
stage.setKeyboardFocus(this); //issue #10, newly created window does not acquire keyboard focus
if (centerOnAdd) {
centerOnAdd = false;
moveToCenter();
}
}
}
private void moveToCenter () {
Stage parent = getStage();
if (parent != null) setPosition((parent.getWidth() - getWidth()) / 2, (parent.getHeight() - getHeight()) / 2);
}
/**
* Fade outs this window, when fade out animation is completed, window is removed from Stage. Calling this for the
* second time won't have any effect if previous animation is still running.
*/
public void fadeOut (float time) {
if (fadeOutActionRunning) return;
fadeOutActionRunning = true;
final Touchable previousTouchable = getTouchable();
setTouchable(Touchable.disabled);
Stage stage = getStage();
if (stage != null && stage.getKeyboardFocus() != null && stage.getKeyboardFocus().isDescendantOf(this)) {
FocusManager.resetFocus(stage);
}
addAction(Actions.sequence(Actions.fadeOut(time, Interpolation.fade), new Action() {
@Override
public boolean act (float delta) {
setTouchable(previousTouchable);
remove();
getColor().a = 1f;
fadeOutActionRunning = false;
return true;
}
}));
}
/** @return this window for the purpose of chaining methods eg. stage.addActor(new MyWindow(stage).fadeIn(0.3f)); */
public VisWindow fadeIn (float time) {
setColor(1, 1, 1, 0);
addAction(Actions.fadeIn(time, Interpolation.fade));
return this;
}
/** Fade outs this window, when fade out animation is completed, window is removed from Stage */
public void fadeOut () {
fadeOut(FADE_TIME);
}
/** @return this window for the purpose of chaining methods eg. stage.addActor(new MyWindow(stage).fadeIn()); */
public VisWindow fadeIn () {
return fadeIn(FADE_TIME);
}
/**
* Called by window when close button was pressed (added using {@link #addCloseButton()})
* or escape key was pressed (for close on escape {@link #closeOnEscape()} have to be called).
* Default close behaviour is to fade out window, this can be changed by overriding this function.
*/
protected void close () {
fadeOut();
}
/**
* Adds close button to window, next to window title. After pressing that button, {@link #close()} is called. If nothing
* else was added to title table, and current title alignment is center then the title will be automatically centered.
*/
public void addCloseButton () {
Label titleLabel = getTitleLabel();
Table titleTable = getTitleTable();
VisImageButton closeButton = new VisImageButton("close-window");
titleTable.add(closeButton).padRight(-getPadRight() + 0.7f);
closeButton.addListener(new ChangeListener() {
@Override
public void changed (ChangeEvent event, Actor actor) {
close();
}
});
closeButton.addListener(new ClickListener() {
@Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
event.cancel();
return true;
}
});
if (titleLabel.getLabelAlign() == Align.center && titleTable.getChildren().size == 2)
titleTable.getCell(titleLabel).padLeft(closeButton.getWidth() * 2);
}
/**
* Will make this window close when escape key or back key was pressed. After pressing escape or back, {@link #close()} is called.
* Back key is Android and iOS only
*/
public void closeOnEscape () {
addListener(new InputListener() {
@Override
public boolean keyDown (InputEvent event, int keycode) {
if (keycode == Keys.ESCAPE) {
close();
return true;
}
return false;
}
@Override
public boolean keyUp (InputEvent event, int keycode) {
if (keycode == Keys.BACK) {
close();
return true;
}
return false;
}
});
}
public boolean isKeepWithinParent () {
return keepWithinParent;
}
public void setKeepWithinParent (boolean keepWithinParent) {
this.keepWithinParent = keepWithinParent;
}
@Override
public void draw (Batch batch, float parentAlpha) {
if (keepWithinParent && getParent() != null) {
float parentWidth = getParent().getWidth();
float parentHeight = getParent().getHeight();
if (getX() < 0) setX(0);
if (getRight() > parentWidth) setX(parentWidth - getWidth());
if (getY() < 0) setY(0);
if (getTop() > parentHeight) setY(parentHeight - getHeight());
}
super.draw(batch, parentAlpha);
}
}