package io.github.lonamiwebs.klooni.actors; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.TimeUtils; import io.github.lonamiwebs.klooni.Klooni; import io.github.lonamiwebs.klooni.Theme; public class MoneyBuyBand extends Table { //region Members private final Label infoLabel; private final SoftButton confirmButton, cancelButton; private String infoText; private boolean showingTemp; // The theme card that is going to be bought next. We can't // only save the Theme because we need to tell the ThemeCard // that it was bought so it can reflect the new theme status. private ThemeCard toBuy; // Used to interpolate between strings private StringBuilder shownText; // When the next text update will take place private long nextTextUpdate; // When the temporary text should be reverted next private long nextTempRevertUpdate; // Milliseconds private final static long SHOW_ONE_CHARACTER_EVERY = 30; private final static long TEMP_TEXT_DELAY = 2 * 1000; //endregion //region Constructor public MoneyBuyBand(final Klooni game) { infoText = ""; shownText = new StringBuilder(); final Label.LabelStyle labelStyle = new Label.LabelStyle(); labelStyle.font = game.skin.getFont("font_small"); infoLabel = new Label(infoText, labelStyle); infoLabel.setAlignment(Align.left); add(infoLabel).expandX().left().padLeft(20); confirmButton = new SoftButton(0, "ok_texture"); confirmButton.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { if (toBuy != null) toBuy.performBuy(); showCurrentMoney(); hideBuyButtons(); } }); add(confirmButton).pad(8, 0, 8, 4); confirmButton.setVisible(false); cancelButton = new SoftButton(3, "cancel_texture"); cancelButton.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { showCurrentMoney(); hideBuyButtons(); } }); add(cancelButton).pad(8, 4, 8, 8); cancelButton.setVisible(false); setBackground(new TextureRegionDrawable(new TextureRegion(Theme.getBlankTexture()))); showCurrentMoney(); } //endregion //region Private methods private void showCurrentMoney() { setText("money: " + Klooni.getMoney()); } private void hideBuyButtons() { confirmButton.setVisible(false); cancelButton.setVisible(false); toBuy = null; } // Set the text to which the shown text will interpolate. // This will remove any temporary shown text or otherwise // it would mess up this new text. private void setText(String text) { infoText = text; showingTemp = false; nextTextUpdate = TimeUtils.millis() + SHOW_ONE_CHARACTER_EVERY; } // Temporary text will always reset to the shown money // because it would make no sense to go back to the buy "confirm?" private void setTempText(String text) { setText(text); showingTemp = true; nextTempRevertUpdate = TimeUtils.millis() + TEMP_TEXT_DELAY; } // Funky method to interpolate between the information // text and the currently being shown text private void interpolateText() { // If the currently shown text does not match the information text, // then that means that we need to interpolate between them. if (!shownText.toString().equals(infoText)) { // We need the pick the minimum text length limit // or charAt() will throw an IndexOutOfBoundsException int limit = Math.min(shownText.length(), infoText.length()); for (int i = 0; i < limit; ++i) { // As soon as we found a character which differs, we can interpolate // to the new string by updating that single character if (shownText.charAt(i) != infoText.charAt(i)) { shownText.setCharAt(i, infoText.charAt(i)); infoLabel.setText(shownText); return; } } // All the preceding characters matched, so now // what's left is to check for the string length if (shownText.length() > infoText.length()) { // The old text was longer than the new one, so shorten it shownText.setLength(shownText.length() - 1); } else { // It can't be equal length or we wouldn't be here, // so avoid checking shown.length() < info.length(). // We need to append the next character that we want to show shownText.append(infoText.charAt(shownText.length())); } infoLabel.setText(shownText); } } //endregion //region Public methods // Asks the user to buy the given theme, or shows // that they don't have enough money to buy it public void askBuy(final ThemeCard toBuy) { if (toBuy.theme.getPrice() > Klooni.getMoney()) { setTempText("cannot buy!"); confirmButton.setVisible(false); cancelButton.setVisible(false); } else { this.toBuy = toBuy; setText("confirm?"); confirmButton.setVisible(true); cancelButton.setVisible(true); } } @Override public void draw(Batch batch, float parentAlpha) { long now = TimeUtils.millis(); if (now > nextTextUpdate) { interpolateText(); nextTextUpdate = TimeUtils.millis() + SHOW_ONE_CHARACTER_EVERY; if (now > nextTempRevertUpdate && showingTemp) { // We won't be showing temp anymore if the current money is shown showCurrentMoney(); } } setColor(Klooni.theme.bandColor); infoLabel.setColor(Klooni.theme.textColor); super.draw(batch, parentAlpha); } //endregion }