net.randomhacks.wave.voting.approval.client.ChoicesTable.java Source code

Java tutorial

Introduction

Here is the source code for net.randomhacks.wave.voting.approval.client.ChoicesTable.java

Source

// PickSeveral - Approval voting wave gadget
// Copyright 2009 Eric Kidd
//
// 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 net.randomhacks.wave.voting.approval.client;

import java.util.ArrayList;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.gadgets.client.DynamicHeightFeature;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.TextBox;

public class ChoicesTable extends FlexTable implements ChoicesModel.Listener {
    private TextBox inputBox = new TextBox();
    private Button addButton = new Button("Add");

    private ChoicesModel model;
    private ArrayList<String> knownChoices = new ArrayList<String>();
    private DynamicHeightFeature dynamicHeightFeature;

    ChoicesTable(ChoicesModel model) {
        super();
        this.model = model;

        getRowFormatter().addStyleName(0, "choicesHeader");
        // We'll call setHeaderText later.

        HorizontalPanel hbox = new HorizontalPanel();
        hbox.add(inputBox);
        hbox.add(addButton);
        setWidget(1, 0, hbox);

        addEventHandlers();
        model.addListener(this);
    }

    private void addEventHandlers() {
        addButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                addChoice();
            }
        });
        inputBox.addKeyPressHandler(new KeyPressHandler() {
            public void onKeyPress(KeyPressEvent event) {
                if (event.getCharCode() == KeyCodes.KEY_ENTER)
                    addChoice();
            }
        });
    }

    private void addChoice() {
        String input = inputBox.getText().trim();
        if (input.length() > 0) {
            inputBox.setText("");
            model.addChoice(input);
        }
    }

    public void notifyChoicesChanged(ArrayList<Choice> choicesModel, boolean isWritable) {
        updateChoicesTableHeader(choicesModel);
        updateChoicesTableBody(choicesModel, isWritable);
        updateChoicesTableFooter(isWritable);
        if (dynamicHeightFeature != null)
            dynamicHeightFeature.adjustHeight();
    }

    private void updateChoicesTableHeader(ArrayList<Choice> choicesModel) {
        if (choicesModel.size() < 2)
            setHeaderText("Add Choices");
        else
            setHeaderText("Pick Several");
    }

    private void setHeaderText(String headerText) {
        setText(0, 0, headerText);
    }

    private int rowForChoiceIndex(int i) {
        return i + 1;
    }

    private void updateChoicesTableBody(ArrayList<Choice> choicesModel, boolean isWritable) {
        // TODO - Move this code out into a presenter layer where we
        // can actually test and debug it properly.
        Log.debug("Known before: " + knownChoices.toString());
        Log.debug("Model: " + choicesModel.toString());
        int i = 0;
        for (Choice choice : choicesModel) {
            // While 'choice.key' is alphabetically greater than the current
            // key, then we need to remove the current row. Normally, this can
            // only happen when rewinding a wave in playback mode.
            while (i < knownChoices.size() && choice.key.compareTo(knownChoices.get(i)) > 0)
                removeChoiceRow(i);

            // If 'choice.key' is alphabetically less than the current
            // key, then we need to insert a new row.
            if (i >= knownChoices.size() || choice.key.compareTo(knownChoices.get(i)) < 0)
                insertChoiceRow(i, choice);

            // Make sure the current row matches the model.
            updateChoiceRow(i, choice, isWritable);
            ++i;
        }

        // If we have any trailing rows left over after we've taken care
        // of all the choices in our model, we'll need to remove them.
        while (i < knownChoices.size()) {
            Log.debug("Trailing choice: " + knownChoices.get(i));
            removeChoiceRow(i);
        }
        Log.debug("Known after: " + knownChoices.toString());
    }

    private void removeChoiceRow(int i) {
        Log.debug("Removing row " + Integer.toString(i) + ": " + knownChoices.get(i));
        knownChoices.remove(i);
        removeRow(rowForChoiceIndex(i));
    }

    private void insertChoiceRow(int i, final Choice choice) {
        Log.debug("Inserting row " + Integer.toString(i) + ": " + choice.key);
        knownChoices.add(i, choice.key);
        int row = rowForChoiceIndex(i);
        insertRow(row);
        final CheckBox checkBox = new CheckBox(choice.name);
        setWidget(row, 0, checkBox);
        checkBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
            public void onValueChange(ValueChangeEvent<Boolean> event) {
                model.setChosen(choice.name, event.getValue());
            }
        });
    }

    private void updateChoiceRow(int i, Choice choice, boolean isWritable) {
        Log.debug("Updating row " + Integer.toString(i) + ": " + choice.key);
        CheckBox checkBox = (CheckBox) getWidget(rowForChoiceIndex(i), 0);
        checkBox.setValue(choice.wasChosenByMe);
        String label = choice.name;
        if (choice.votes > 0)
            label += " (" + Integer.toString(choice.votes) + ")";
        checkBox.setText(label);
        if (choice.isWinner)
            checkBox.addStyleName("winningChoice");
        else
            checkBox.removeStyleName("winningChoice");
        checkBox.setEnabled(isWritable);
    }

    private void updateChoicesTableFooter(boolean isWritable) {
        inputBox.setEnabled(isWritable);
        addButton.setEnabled(isWritable);
    }

    public void setDynamicHeightFeature(DynamicHeightFeature feature) {
        dynamicHeightFeature = feature;
        dynamicHeightFeature.adjustHeight();
    }
}