/* * This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT). * * Copyright (c) JCThePants (www.jcwhatever.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.jcwhatever.nucleus.utils.text.dynamic; import com.jcwhatever.nucleus.utils.TimeScale; import com.jcwhatever.nucleus.utils.PreCon; import com.jcwhatever.nucleus.utils.text.ColoredCircularString; import com.jcwhatever.nucleus.utils.text.TextUtils; import com.jcwhatever.nucleus.utils.text.components.IChatMessage; /** * An {@link IDynamicText} implementation that displays marquee * text which can scroll text from left to right or right to left. */ public class MarqueeText implements IDynamicText { private final ColoredCircularString _marquee; private volatile int _charWidth; private volatile IDynamicText _text; private volatile MarqueeDirection _direction = MarqueeDirection.LEFT; private volatile int _refreshRate = 3; // 3 ticks private volatile long _nextUpdate; private volatile IChatMessage _currentText; private final Object _sync = new Object(); public enum MarqueeDirection { LEFT, RIGHT } /** * Constructor. * * @param charWidth The character width of the marquee. * @param text The text to display. */ public MarqueeText(int charWidth, String text) { PreCon.notNull(text); _text = new DynamicTextBuilder().append(text).build(); _marquee = new ColoredCircularString(); _charWidth = charWidth; } /** * Constructor. * * @param charWidth The character width of the marquee. * @param dynamicText The text to display. */ public MarqueeText(int charWidth, IDynamicText dynamicText) { PreCon.notNull(dynamicText); _marquee = new ColoredCircularString(); _charWidth = charWidth; _text = dynamicText; } /** * Get the marquee character width. */ public int getWidth() { return _charWidth; } /** * Set the marquee character width. * * @param width The width. Must be greater than zero. */ public void setWidth(int width) { PreCon.greaterThanZero(width); _charWidth = width; } /** * Get the text being displayed in the marquee. */ public IDynamicText getText() { return _text; } /** * Get the text currently being displayed by the marquee. */ public String getCurrentText() { return _currentText.toString(); } /** * Set the marquee text. * * @param text The text. */ public void setText(String text) { PreCon.notNull(text); _text = new DynamicTextBuilder().append(text).build(); } /** * Set the marquee text. * * @param text The text. */ public void setText(IDynamicText text) { PreCon.notNull(text); _text = text; } /** * Get the marquee's scroll direction. */ public MarqueeDirection getDirection() { return _direction; } /** * Set the marquee's scroll direction. * * @param direction The direction. */ public void setDirection(MarqueeDirection direction) { PreCon.notNull(direction); _direction = direction; } @Override public IChatMessage nextText() { // ensure refresh rate (and scroll rate) is maintained even if refreshed // at a faster rate than requested. if (_nextUpdate != 0 && _nextUpdate > System.currentTimeMillis()) { return _currentText; } synchronized (_sync) { String text = getMarqueeText(); _marquee.setString(text); if (_direction == MarqueeDirection.LEFT) { _marquee.rotateLeft(1); } else { _marquee.rotateRight(1); } _currentText = TextUtils.format(_marquee.subSequence(0, _charWidth).toString()); _nextUpdate = System.currentTimeMillis() + _refreshRate; return _currentText; } } @Override public int getRefreshRate() { return _refreshRate; } /** * Set the refresh rate. The refresh rate also represents * the scroll speed of the marquee. * * @param rate The rate. * @param timeScale The rate time scale. */ public void setRefreshRate(int rate, TimeScale timeScale) { _refreshRate = rate * timeScale.getTimeFactor() / 50; } // get the current text modified for the marquee private String getMarqueeText() { return _direction == MarqueeDirection.LEFT ? TextUtils.padLeft(_text.nextText().toString(), _charWidth) : TextUtils.padRight(_text.nextText().toString(), _charWidth); } }