com.mcherm.zithiacharsheet.client.TweakableIntField.java Source code

Java tutorial

Introduction

Here is the source code for com.mcherm.zithiacharsheet.client.TweakableIntField.java

Source

/*
 * Copyright 2009 Michael Chermside
 *
 * 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.mcherm.zithiacharsheet.client;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.mcherm.zithiacharsheet.client.modeler.Disposable;
import com.mcherm.zithiacharsheet.client.modeler.Disposer;
import com.mcherm.zithiacharsheet.client.modeler.TweakableIntValue;
import com.mcherm.zithiacharsheet.client.modeler.Observable.Observer;

/**
 * A field that is tied to a value. If the value changes,
 * the field changes. You cannot edit the value (for now).
 */
public class TweakableIntField extends HorizontalPanel implements HasClickHandlers, Disposable {

    private final TweakableIntValue value;
    private final TextBox fieldValue;
    private final AsterixThing asterixThing;
    private final Disposer disposer = new Disposer();

    private class TweakPopup extends PopupPanel {
        final TweakableIntValue value;
        final RadioButton radioNormal;
        final RadioButton radioModifier;
        final RadioButton radioOverride;
        final TextBox modifierText;
        final TextBox overrideText;

        public TweakPopup(final TweakableIntValue value) {
            this.value = value;
            final Panel content = new VerticalPanel();
            content.add(new HTML("Tweak Calculation"));
            final Panel row1 = new HorizontalPanel();
            radioNormal = new RadioButton("tweak_type", "Calculate normally.");
            row1.add(radioNormal);
            content.add(row1);
            final Panel row2 = new HorizontalPanel();
            radioModifier = new RadioButton("tweak_type", "Calculate, then add ", true);
            row2.add(radioModifier);
            modifierText = new TextBox();
            modifierText.addStyleName("settableInt");
            row2.add(modifierText);
            content.add(row2);
            final Panel row3 = new HorizontalPanel();
            radioOverride = new RadioButton("tweak_type", "Just use ", true);
            row3.add(radioOverride);
            overrideText = new TextBox();
            overrideText.addStyleName("settableInt");
            row3.add(overrideText);
            content.add(row3);
            final Button exitButton = new Button("Done");
            content.add(exitButton);
            add(content);
            exitButton.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    TweakPopup.this.hide();
                }
            });
            addCloseHandler(new CloseHandler<PopupPanel>() {
                public void onClose(CloseEvent<PopupPanel> event) {
                    Integer override, modifier;
                    if (radioModifier.getValue()) {
                        override = null;
                        try {
                            modifier = new Integer(modifierText.getText());
                        } catch (NumberFormatException err) {
                            Window.alert("Invalid integer.");
                            modifier = null;
                        }
                    } else if (radioOverride.getValue()) {
                        modifier = null;
                        try {
                            override = new Integer(overrideText.getText());
                        } catch (NumberFormatException err) {
                            Window.alert("Invalid integer.");
                            override = null;
                        }
                    } else {
                        modifier = null;
                        override = null;
                    }
                    value.setAdjustments(override, modifier);
                }
            });
        }

        /**
         * Call this to launch the popup.
         */
        public void launch() {
            if (!value.isTweaked()) {
                radioNormal.setValue(true);
            } else if (value.getModifier() != null) {
                radioModifier.setValue(true);
            } else if (value.getOverride() != null) {
                radioOverride.setValue(true);
            } else {
                throw new RuntimeException("Unexpected state of value.");
            }
            modifierText.setValue(intToStr(value.getModifier()));
            overrideText.setValue(intToStr(value.getOverride()));
            center();
        }

        private String intToStr(Integer i) {
            return i == null ? "" : i.toString();
        }
    }

    private class AsterixThing extends SimplePanel implements HasClickHandlers {
        private String currentState;
        private TweakPopup tweakPopup;

        public AsterixThing() {
            currentState = ".";
            tweakPopup = new TweakPopup(value);
            this.add(new HTML(currentState));
            this.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    tweakPopup.launch();
                }
            });
        }

        public void setTweaked(boolean isTweaked) {
            if (isTweaked && currentState != "*") {
                currentState = "*";
                clear();
                this.add(new HTML(currentState));
            } else if (!isTweaked && currentState != ".") {
                currentState = ".";
                clear();
                this.add(new HTML(currentState));
            }
        }

        /**
         * HasClickHandlers - Code to add handlers to the panel
         */
        public HandlerRegistration addClickHandler(ClickHandler handler) {
            return addDomHandler(handler, ClickEvent.getType());
        }
    }

    /**
     * Constructor.
     * 
     * @param value the TweakableIntValue this is bound to.
     */
    public TweakableIntField(final TweakableIntValue value) {
        this.value = value;
        this.addStyleName("tweakableInt");
        fieldValue = new TextBox();
        fieldValue.setEnabled(false);
        asterixThing = new AsterixThing();
        add(fieldValue);
        add(asterixThing);
        updateDisplay();
        disposer.observe(value, new Observer() {
            public void onChange() {
                updateDisplay();
            }
        });
    }

    /**
     * Sets the displayed value to match the field value.
     */
    protected void updateDisplay() {
        String valueStr = Integer.toString(value.getValue());
        fieldValue.setValue(valueStr);
        asterixThing.setTweaked(value.isTweaked());
    }

    /**
     * HasClickHandlers - Code to add handlers to the panel
     */
    public HandlerRegistration addClickHandler(ClickHandler handler) {
        return addDomHandler(handler, ClickEvent.getType());
    }

    public void dispose() {
        disposer.dispose();
    }
}