/* * This file is part of SpoutcraftPlugin. * * Copyright (c) 2011 SpoutcraftDev <http://spoutcraft.org//> * SpoutcraftPlugin is licensed under the GNU Lesser General Public License. * * SpoutcraftPlugin is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SpoutcraftPlugin is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.getspout.spoutapi.gui; import java.io.IOException; import java.util.UUID; import javax.xml.bind.TypeConstraintException; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.getspout.spoutapi.io.SpoutInputStream; import org.getspout.spoutapi.io.SpoutOutputStream; public abstract class GenericWidget implements Widget { /** * Set if this is Spoutcraft (client), cleared if it is Spout (server)... */ static final protected transient boolean isSpoutcraft = false; protected int X = 0; protected int Y = 0; protected int width = 50; protected int height = 50; protected boolean visible = true; protected transient boolean dirty = true; protected transient Screen screen = null; protected RenderPriority priority = RenderPriority.Normal; protected UUID id = UUID.randomUUID(); protected String tooltip = ""; protected String plugin = "Spoutcraft"; protected WidgetAnchor anchor = WidgetAnchor.SCALE; // Server side layout protected Container container = null; protected boolean fixed = false; protected int marginTop = 0, marginRight = 0, marginBottom = 0, marginLeft = 0; protected int minWidth = 0, maxWidth = 427, minHeight = 0, maxHeight = 240; protected int orig_x = 0, orig_y = 0; protected boolean autoDirty = true; protected transient boolean hasPosition = false; protected transient boolean hasSize = false; // Animation protected WidgetAnim animType = WidgetAnim.NONE; protected float animValue = 1f; protected short animCount = 0; protected short animTicks = 20; protected final byte ANIM_REPEAT = (1 << 0); protected final byte ANIM_RESET = (1 << 1); protected final byte ANIM_RUNNING = (1 << 2); protected final byte ANIM_STOPPING = (1 << 3); protected byte animFlags = 0; protected transient int animTick = 0; // Current tick protected transient int animFrame = 0; // Current frame public GenericWidget() { } @Override final public boolean isSpoutcraft() { return isSpoutcraft; } @Override public int getVersion() { return 6; } public GenericWidget(int X, int Y, int width, int height) { this.X = X; this.Y = Y; this.width = width; this.height = height; } @Override public Widget setAnchor(WidgetAnchor anchor) { if (anchor != null && !getAnchor().equals(anchor)) { this.anchor = anchor; autoDirty(); } return this; } @Override public WidgetAnchor getAnchor() { return anchor; } @Override public Plugin getPlugin() { return Bukkit.getServer().getPluginManager().getPlugin(plugin == null || plugin.equals("Spoutcraft") ? "Spout" : plugin); } @Override public Widget setPlugin(Plugin plugin) { if (plugin != null) { this.plugin = plugin.getDescription().getName(); } return this; } @Override public void readData(SpoutInputStream input) throws IOException { setX(input.readInt()); setY(input.readInt()); setWidth(input.readInt()); setHeight(input.readInt()); setAnchor(WidgetAnchor.getAnchorFromId(input.read())); setVisible(input.readBoolean()); setPriority(RenderPriority.getRenderPriorityFromId(input.readInt())); setTooltip(input.readString()); setPlugin(Bukkit.getServer().getPluginManager().getPlugin(input.readString())); animType = WidgetAnim.getAnimationFromId(input.read()); animFlags = (byte) input.read(); animValue = input.readFloat(); animTicks = input.readShort(); animCount = input.readShort(); } @Override public void writeData(SpoutOutputStream output) throws IOException { output.writeInt(getX()); output.writeInt(getY()); output.writeInt(getWidth()); output.writeInt(getHeight()); output.write(getAnchor().getId()); output.writeBoolean(isVisible()); output.writeInt(priority.getId()); output.writeString(getTooltip()); output.writeString(plugin != null ? plugin : "Spoutcraft"); output.write(animType.getId()); output.write(animFlags); output.writeFloat(animValue); output.writeShort(animTicks); output.writeShort(animCount); } @Override public void setDirty(boolean dirty) { this.dirty = dirty; } @Override public boolean isDirty() { return dirty; } @Override public UUID getId() { return id; } @Override public Screen getScreen() { return screen; } @Override @Deprecated public Widget setScreen(Screen screen) { return setScreen(null, screen); } @Override public Widget setScreen(Plugin plugin, Screen screen) { if (getScreen() != null && screen != null && !getScreen().equals(screen)) { getScreen().removeWidget(this); } this.screen = screen; if (plugin != null) { this.plugin = plugin.getDescription().getName(); } return this; } @Override public RenderPriority getPriority() { return priority; } @Override public Widget setPriority(RenderPriority priority) { if (priority != null && !getPriority().equals(priority)) { this.priority = priority; autoDirty(); } return this; } @Override public int getWidth() { return width; } @Override public Widget setWidth(int width) { hasSize = true; width = Math.max(getMinWidth(), Math.min(width, getMaxWidth())); if (getWidth() != width) { this.width = width; updateSize(); autoDirty(); } return this; } @Override public int getHeight() { return height; } @Override public Widget setHeight(int height) { hasSize = true; height = Math.max(getMinHeight(), Math.min(height, getMaxHeight())); if (getHeight() != height) { this.height = height; updateSize(); autoDirty(); } return this; } @Override public int getX() { return X; } @Override public int getY() { return Y; } @Override public Widget setX(int pos) { hasPosition = true; if (getX() != pos) { X = pos; autoDirty(); } return this; } @Override public Widget setY(int pos) { hasPosition = true; if (getY() != pos) { Y = pos; autoDirty(); } return this; } @Override public Widget shiftXPos(int modX) { setX(getX() + modX); return this; } @Override public Widget shiftYPos(int modY) { setY(getY() + modY); return this; } @Override public boolean isVisible() { return visible; } @Override public Widget setVisible(boolean enable) { if (isVisible() != enable) { visible = enable; updateSize(); if (hasContainer()) { getContainer().deferLayout(); } autoDirty(); } return this; } @Override public int hashCode() { return getId().hashCode(); } @Override public boolean equals(Object other) { return other instanceof Widget && other.hashCode() == hashCode(); } @Override public void onTick() { } @Override public Widget setTooltip(String t) { if (t != null && !getTooltip().equals(t)) { tooltip = t; autoDirty(); } return this; } @Override public String getTooltip() { return tooltip; } @Override public Container getContainer() { return container; } @Override public boolean hasContainer() { return container != null; } @Override public void setContainer(Container container) { if (hasContainer() && container != null && !getContainer().equals(container)) { getContainer().removeChild(this); } this.container = container; } @Override public Widget setFixed(boolean fixed) { if (isFixed() != fixed) { this.fixed = fixed; updateSize(); } return this; } @Override @Deprecated public boolean getFixed() { return isFixed(); } @Override public boolean isFixed() { return fixed; } @Override public Widget setMargin(int marginAll) { return setMargin(marginAll, marginAll, marginAll, marginAll); } @Override public Widget setMargin(int marginTopBottom, int marginLeftRight) { return setMargin(marginTopBottom, marginLeftRight, marginTopBottom, marginLeftRight); } @Override public Widget setMargin(int marginTop, int marginLeftRight, int marginBottom) { return setMargin(marginTop, marginLeftRight, marginBottom, marginLeftRight); } @Override public Widget setMargin(int marginTop, int marginRight, int marginBottom, int marginLeft) { if (getMarginTop() != marginTop || getMarginRight() != marginRight || getMarginBottom() != marginBottom || getMarginLeft() != marginLeft) { this.marginTop = marginTop; this.marginRight = marginRight; this.marginBottom = marginBottom; this.marginLeft = marginLeft; updateSize(); autoDirty(); } return this; } @Override public Widget setMarginTop(int marginTop) { if (getMarginTop() != marginTop) { this.marginTop = marginTop; updateSize(); autoDirty(); } return this; } @Override public Widget setMarginRight(int marginRight) { if (getMarginRight() != marginRight) { this.marginRight = marginRight; updateSize(); autoDirty(); } return this; } @Override public Widget setMarginBottom(int marginBottom) { if (getMarginBottom() != marginBottom) { this.marginBottom = marginBottom; updateSize(); autoDirty(); } return this; } @Override public Widget setMarginLeft(int marginLeft) { if (getMarginLeft() != marginLeft) { this.marginLeft = marginLeft; updateSize(); autoDirty(); } return this; } @Override public int getMarginTop() { return marginTop; } @Override public int getMarginRight() { return marginRight; } @Override public int getMarginBottom() { return marginBottom; } @Override public int getMarginLeft() { return marginLeft; } @Override public Widget setMinWidth(int min) { min = Math.max(min, 0); if (getMinWidth() != min) { minWidth = min; updateSize(); setWidth(width); // Enforce our new size if needed } return this; } @Override public int getMinWidth() { return minWidth; } @Override public Widget setMaxWidth(int max) { max = max <= 0 ? 427 : max; if (getMaxWidth() != max) { maxWidth = max; updateSize(); setWidth(width); // Enforce our new size if needed } return this; } @Override public int getMaxWidth() { return maxWidth; } @Override public Widget setMinHeight(int min) { min = Math.max(min, 0); if (getMinHeight() != min) { minHeight = min; updateSize(); setHeight(height); // Enforce our new size if needed } return this; } @Override public int getMinHeight() { return minHeight; } @Override public Widget setMaxHeight(int max) { max = max <= 0 ? 240 : max; if (getMaxHeight() != max) { maxHeight = max; updateSize(); setHeight(height); // Enforce our new size if needed } return this; } @Override public int getMaxHeight() { return maxHeight; } @Override public Widget savePos() { orig_x = getX(); orig_y = getY(); return this; } @Override public Widget restorePos() { setX(orig_x); setY(orig_y); return this; } @Override public Widget copy() { try { Widget copy = getType().getWidgetClass().newInstance(); copy.setX(getX()) // Easier reading .setY(getY()) .setWidth(getWidth()) .setHeight(getHeight()) .setVisible(isVisible()) .setPriority(getPriority()) .setTooltip(getTooltip()) .setAnchor(getAnchor()) .setMargin(getMarginTop(), getMarginRight(), getMarginBottom(), getMarginLeft()) // .setMinWidth(getMinWidth()) .setMaxWidth(getMaxWidth()) .setMinHeight(getMinHeight()) .setMaxHeight(getMaxHeight()) .setFixed(isFixed()) .setAutoDirty(isAutoDirty()) .animate(animType, animValue, animCount, animTicks, (animFlags & ANIM_REPEAT) != 0, (animFlags & ANIM_RESET) != 0); return copy; } catch (Exception e) { throw new IllegalStateException("Unable to create a copy of " + getClass() + ". Does it have a valid widget type?"); } } @Override public Widget updateSize() { if (hasContainer()) { container.updateSize(); } return this; } @Override public Widget setAutoDirty(boolean dirty) { return this; } @Override public boolean isAutoDirty() { return autoDirty; } @Override public void autoDirty() { if (isAutoDirty()) { setDirty(true); } } @Override public Widget animate(WidgetAnim type, float value, short count, short ticks) { animate(type, value, count, ticks, true, true); return this; } @Override public Widget animate(WidgetAnim type, float value, short count, short ticks, boolean repeat) { animate(type, value, count, ticks, repeat, true); return this; } @Override public Widget animate(WidgetAnim type, float value, short count, short ticks, boolean repeat, boolean reset) { if (!type.check(this)) { throw new TypeConstraintException("Cannot use Animation." + type.name() + " on " + getType().toString()); } animType = type; animValue = value; animCount = count; animTicks = ticks; animFlags = (byte) ((repeat ? ANIM_REPEAT : 0) | (reset ? ANIM_RESET : 0)); animTick = 0; animFrame = 0; autoDirty(); return this; } @Override public Widget animateStart() { if (animType != WidgetAnim.NONE) { animFlags |= ANIM_RUNNING; autoDirty(); } return this; } @Override public Widget animateStop(boolean finish) { if ((animFlags & ANIM_RUNNING) != 0 && finish) { animFlags |= ANIM_STOPPING; autoDirty(); } else { animFlags &= ~ANIM_RUNNING; autoDirty(); } return this; } @Override public void onAnimate() { if ((animFlags & ANIM_RUNNING) == 0 || animTicks == 0 || ++animTick % animTicks != 0) { return; } // We're running, and it's ready for our next frame... if (++animFrame == animCount) { animFrame = 0; if ((animFlags & ANIM_STOPPING) != 0 || (animFlags & ANIM_REPEAT) == 0) { animFlags &= ~ANIM_RUNNING; } } } @Override public void onAnimateStop() { } @Override public boolean hasPosition() { return hasPosition; } @Override public boolean hasSize() { return hasSize; } }