Java tutorial
// -*- mode: java; c-basic-offset: 2; -*- // Copyright 2009-2011 Google, All Rights reserved // Copyright 2011-2012 MIT, All rights reserved // Released under the Apache License, Version 2.0 // http://www.apache.org/licenses/LICENSE-2.0 package com.google.appinventor.client.editor.youngandroid.properties; import static com.google.appinventor.client.Ode.MESSAGES; import com.google.appinventor.client.editor.simple.components.MockVisibleComponent; import com.google.appinventor.client.widgets.properties.AdditionalChoicePropertyEditor; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.RadioButton; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; /** * Property editor for length properties (i.e. width and height). * */ public class YoungAndroidLengthPropertyEditor extends AdditionalChoicePropertyEditor { public static final String CONST_AUTOMATIC = "" + MockVisibleComponent.LENGTH_PREFERRED; public static final String CONST_FILL_PARENT = "" + MockVisibleComponent.LENGTH_FILL_PARENT; private static int uniqueIdSeed = 0; private final RadioButton automaticRadioButton; private final RadioButton fillParentRadioButton; private final RadioButton customLengthRadioButton; private final RadioButton percentfillRadioButton; private final TextBox customLengthField; private final TextBox percentLengthField; public YoungAndroidLengthPropertyEditor() { this(true); } /** * Creates a new length property editor. * * @param includePercent whether to include percent of screen option */ public YoungAndroidLengthPropertyEditor(boolean includePercent) { // The radio button group cannot be shared across all instances, so we append a unique id. int uniqueId = ++uniqueIdSeed; String radioButtonGroup = "LengthType-" + uniqueId; automaticRadioButton = new RadioButton(radioButtonGroup, MESSAGES.automaticCaption()); fillParentRadioButton = new RadioButton(radioButtonGroup, MESSAGES.fillParentCaption()); percentfillRadioButton = new RadioButton(radioButtonGroup); customLengthRadioButton = new RadioButton(radioButtonGroup); customLengthField = new TextBox(); customLengthField.setVisibleLength(4); customLengthField.setMaxLength(4); percentLengthField = new TextBox(); percentLengthField.setVisibleLength(4); percentLengthField.setMaxLength(4); Panel customRow = new HorizontalPanel(); customRow.add(customLengthRadioButton); customRow.add(customLengthField); Label pixels = new Label(MESSAGES.pixelsCaption()); pixels.setStylePrimaryName("ode-PixelsLabel"); customRow.add(pixels); Panel percentRow = new HorizontalPanel(); percentRow.add(percentfillRadioButton); percentRow.add(percentLengthField); Label percent = new Label(MESSAGES.percentCaption()); percent.setStylePrimaryName("ode-PixelsLabel"); // recycle css definition percentRow.add(percent); Panel panel = new VerticalPanel(); panel.add(automaticRadioButton); panel.add(fillParentRadioButton); panel.add(customRow); if (includePercent) { panel.add(percentRow); } automaticRadioButton.addValueChangeHandler(new ValueChangeHandler() { @Override public void onValueChange(ValueChangeEvent event) { // Clear the custom and percent length fields. customLengthField.setText(""); percentLengthField.setText(""); } }); fillParentRadioButton.addValueChangeHandler(new ValueChangeHandler() { @Override public void onValueChange(ValueChangeEvent event) { // Clear the custom and percent length fields. customLengthField.setText(""); percentLengthField.setText(""); } }); customLengthField.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { // If the user clicks on the custom length field, but the radio button for a custom length // is not checked, check it. if (!customLengthRadioButton.isChecked()) { customLengthRadioButton.setChecked(true); percentLengthField.setText(""); } } }); percentLengthField.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { // If the user clicks on the percent length field, but the radio button for a custom length // is not checked, check it. if (!percentfillRadioButton.isChecked()) { percentfillRadioButton.setChecked(true); customLengthField.setText(""); } } }); initAdditionalChoicePanel(panel); } @Override protected void updateValue() { super.updateValue(); String propertyValue = property.getValue(); if (propertyValue.equals(CONST_AUTOMATIC)) { automaticRadioButton.setChecked(true); } else if (propertyValue.equals(CONST_FILL_PARENT)) { fillParentRadioButton.setChecked(true); } else { int v = Integer.parseInt(propertyValue); if (v <= MockVisibleComponent.LENGTH_PERCENT_TAG) { v = (-v) + MockVisibleComponent.LENGTH_PERCENT_TAG; percentfillRadioButton.setChecked(true); percentLengthField.setText("" + v); } else { customLengthRadioButton.setChecked(true); customLengthField.setText(propertyValue); } } } @Override protected String getPropertyValueSummary() { String lengthHint = property.getValue(); if (lengthHint.equals(CONST_AUTOMATIC)) { return MESSAGES.automaticCaption(); } else if (lengthHint.equals(CONST_FILL_PARENT)) { return MESSAGES.fillParentCaption(); } else { int v = Integer.parseInt(lengthHint); if (v <= MockVisibleComponent.LENGTH_PERCENT_TAG) { v = (-v) + MockVisibleComponent.LENGTH_PERCENT_TAG; return MESSAGES.percentSummary("" + v); } else { return MESSAGES.pixelsSummary(lengthHint); } } } @Override protected boolean okAction() { if (automaticRadioButton.isChecked()) { property.setValue(CONST_AUTOMATIC); } else if (fillParentRadioButton.isChecked()) { property.setValue(CONST_FILL_PARENT); } else if (customLengthRadioButton.isChecked()) { // Custom length String text = customLengthField.getText(); // Make sure it's a non-negative number. It is important // that this check stay within the custom length case because // CONST_AUTOMATIC and CONST_FILL_PARENT are deliberately negative. boolean success = false; try { if (Integer.parseInt(text) >= 0) { success = true; } } catch (NumberFormatException e) { // fall through with success == false } if (!success) { Window.alert(MESSAGES.nonnumericInputError()); return false; } property.setValue(text); } else { // Percent field! String text = percentLengthField.getText(); boolean success = false; try { int v = Integer.parseInt(text); if (v > 0 && v <= 100) { success = true; property.setValue("" + (-v + MockVisibleComponent.LENGTH_PERCENT_TAG)); } } catch (NumberFormatException e) { // fall through with success == false } if (!success) { Window.alert(MESSAGES.nonvalidPercentValue()); return false; } } return true; } }