All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.kotcrab.vis.ui.widget.VisWindow Maven / Gradle / Ivy

There is a newer version: 1.5.3
Show newest version
/*
 * 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);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy