it.tidalwave.ui.android.view.AndroidBindings Maven / Gradle / Ivy
/***********************************************************************************************************************
*
* blueBill Mobile - Android - open source birding
* Copyright (C) 2009-2011 by Tidalwave s.a.s. (http://www.tidalwave.it)
*
***********************************************************************************************************************
*
* 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.
*
***********************************************************************************************************************
*
* WWW: http://bluebill.tidalwave.it/mobile
* SCM: https://java.net/hg/bluebill-mobile~android-src
*
**********************************************************************************************************************/
package it.tidalwave.ui.android.view;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Action;
import java.util.Arrays;
import java.util.List;
import it.tidalwave.util.thread.annotation.ThreadConfined;
import it.tidalwave.util.ui.FormProperty;
import it.tidalwave.netbeans.util.Locator;
import android.content.Context;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.Spinner;
import it.tidalwave.ui.android.widget.DisplayableArrayAdapter;
import it.tidalwave.ui.android.widget.PresentationModelAdapter;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import static it.tidalwave.util.thread.ThreadType.*;
import static it.tidalwave.util.ui.FormProperty.*;
/***********************************************************************************************************************
*
* @author Fabrizio Giudici
* @version $Id$
*
**********************************************************************************************************************/
@NoArgsConstructor(access=AccessLevel.PRIVATE)
public final class AndroidBindings
{
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@ThreadConfined(type=UI)
public static void bind (final @Nonnull Button button, final @Nonnull Action action)
{
button.setOnClickListener(new ViewOnClickListenerAdapter(action));
button.setEnabled(action.isEnabled());
button.setText((String)action.getValue(Action.NAME));
// FIXME: use a weak listener!
action.addPropertyChangeListener(new PropertyChangeListener()
{
@ThreadConfined(type=ANY)
public void propertyChange (final @Nonnull PropertyChangeEvent event)
{
if ("enabled".equals(event.getPropertyName()))
{
button.post(new Runnable()
{
public void run()
{
button.setEnabled(action.isEnabled());
}
});
}
}
});
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@ThreadConfined(type=UI)
public static void bind (final @Nonnull ListView listView,
final @Nonnull PresentationModelAdapter listAdapter)
{
listView.setAdapter(listAdapter);
listView.setOnItemClickListener(listAdapter.getOnItemClickListener());
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@ThreadConfined(type=UI)
public static void bind (final @Nonnull EditText editText, final @Nonnull FormProperty> prop)
{
final FormProperty property = (FormProperty)prop;
editText.setText(property.getValue());
editText.setEnabled(property.isEnabled());
editText.setOnKeyListener(new View.OnKeyListener()
{
public boolean onKey (final @Nonnull View view, final int keyCode, final @Nonnull KeyEvent event)
{
property.setValue(editText.getText().toString());
return false; // not consumed
}
});
property.addPropertyChangeListener(new PropertyChangeListener() // FIXME: weak!
{
public void propertyChange (final @Nonnull PropertyChangeEvent event)
{
final String propertyName = event.getPropertyName();
if (PROP_VALUE.equals(propertyName))
{
final String value = property.getValue();
if (!editText.getText().toString().equals(value)) // avoid loops
{
editText.setText(value);
}
}
else if (PROP_ENABLED.equals(propertyName))
{
editText.setEnabled(property.isEnabled());
}
if (PROP_VALID.equals(propertyName))
{
// editText.setText(property.getValue());
}
}
});
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@ThreadConfined(type=UI)
public static void bind (final @Nonnull CheckBox checkBox, final @Nonnull FormProperty> prop)
{
final FormProperty property = (FormProperty)prop;
checkBox.setChecked(property.getValue());
checkBox.setEnabled(property.isEnabled());
checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged (final @Nonnull CompoundButton buttonView, final boolean isChecked)
{
property.setValue(isChecked);
}
});
property.addPropertyChangeListener(new PropertyChangeListener() // FIXME: weak!
{
public void propertyChange (final @Nonnull PropertyChangeEvent event)
{
final String propertyName = event.getPropertyName();
if (PROP_VALUE.equals(propertyName))
{
checkBox.setChecked(property.getValue());
}
else if (PROP_ENABLED.equals(propertyName))
{
checkBox.setEnabled(property.isEnabled());
}
// no PROP_VALID, a Checkbox is always valid
}
});
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@ThreadConfined(type=UI)
public static void bind (final @Nonnull Spinner spinner, final @Nonnull FormProperty> prop)
{
if (!prop.getType().isEnum())
{
throw new IllegalArgumentException("Only FormProperty can be bound to a spinner; instead was " + prop.getType());
}
final Enum>[] values = (Enum>[])prop.getType().getEnumConstants(); // FIXME: move to property.getValues()
final FormProperty> property = (FormProperty>)prop;
select(values, property.getValue(), spinner);
spinner.setEnabled(property.isEnabled());
final Context context = Locator.find(Context.class); // is it ok or need Activity as Context?
final ArrayAdapter adapter = new DisplayableArrayAdapter(context, android.R.layout.simple_spinner_item, values);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new OnItemSelectedListener()
{
public void onItemSelected (final @Nonnull AdapterView> parent,
final @Nonnull View view,
final @Nonnegative int position,
final long id)
{
property.setValue(values[position]);
}
public void onNothingSelected (final @Nonnull AdapterView> parent)
{
property.setValue(null);
}
});
property.addPropertyChangeListener(new PropertyChangeListener() // FIXME: weak!
{
public void propertyChange (final @Nonnull PropertyChangeEvent event)
{
final String propertyName = event.getPropertyName();
if (PROP_VALUE.equals(propertyName))
{
select(values, property.getValue(), spinner);
}
else if (PROP_ENABLED.equals(propertyName))
{
spinner.setEnabled(property.isEnabled());
}
// no PROP_VALID, a Spinner is always valid
}
});
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@ThreadConfined(type=UI)
public static void bind (final @Nonnull List radiobuttons, final @Nonnull FormProperty> prop)
{
if (!prop.getType().isEnum())
{
throw new IllegalArgumentException("Only FormProperty can be bound to a spinner; instead was " + prop.getType());
}
final Enum>[] values = (Enum>[])prop.getType().getEnumConstants(); // FIXME: move to property.getValues()
final FormProperty> property = (FormProperty>)prop;
select(values, property.getValue(), radiobuttons);
for (final RadioButton radioButton : radiobuttons)
{
radioButton.setEnabled(property.isEnabled());
}
final OnCheckedChangeListener checkedChangeListener = new OnCheckedChangeListener()
{
public void onCheckedChanged (final @Nonnull CompoundButton buttonView, final boolean isChecked)
{
if (isChecked)
{
property.setValue(values[radiobuttons.indexOf(buttonView)]);
}
}
};
for (final RadioButton radioButton : radiobuttons)
{
radioButton.setOnCheckedChangeListener(checkedChangeListener);
}
property.addPropertyChangeListener(new PropertyChangeListener() // FIXME: weak!
{
public void propertyChange (final @Nonnull PropertyChangeEvent event)
{
final String propertyName = event.getPropertyName();
if (PROP_VALUE.equals(propertyName))
{
select(values, property.getValue(), radiobuttons);
}
else if (PROP_ENABLED.equals(propertyName))
{
for (final RadioButton radioButton : radiobuttons)
{
radioButton.setEnabled(property.isEnabled());
}
}
// no PROP_VALID, RadioButtons are always valid
}
});
}
/*******************************************************************************************************************
*
* Selects the proper value in a {@link Spinner}.
*
* @param values the possible values
* @param selectedValue the selected value
* @param spinner the {@code Spinner}
*
******************************************************************************************************************/
private static void select (final @Nonnull Enum>[] values,
final @Nonnull Object selectedValue,
final @Nonnull Spinner spinner)
{
final int index = Arrays.binarySearch(values,selectedValue);
if (index < 0)
{
spinner.setSelected(false);
}
else
{
spinner.setSelected(true);
spinner.setSelection(index);
}
}
/*******************************************************************************************************************
*
* Selects the proper {@link RadioButton} in a group.
*
* @param values the possible values
* @param selectedValue the selected value
* @param radioButtonGroup the group of {@code RadioButton}s
*
******************************************************************************************************************/
private static void select (final @Nonnull Enum>[] values,
final @Nonnull Object selectedValue,
final @Nonnull List radioButtonGroup)
{
for (int i = 0; i < values.length; i++)
{
radioButtonGroup.get(i).setChecked(values[i] == selectedValue);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy