All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.tidalwave.ui.android.view.AndroidBindings Maven / Gradle / Ivy

There is a newer version: 1.0.13
Show newest version
/***********************************************************************************************************************
 *
 * 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