/*
* Odoo, Open Source Management Solution
* Copyright (C) 2012-today Odoo SA (<http:www.odoo.com>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http:www.gnu.org/licenses/>
*
*/
package odoo.controls;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import odoo.controls.OField.TextStyle;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.LinearLayout;
import android.widget.Spinner;
import com.odoo.orm.OColumn;
import com.odoo.orm.OColumn.ColumnDomain;
import com.odoo.orm.ODataRow;
import com.odoo.orm.OModel;
import com.odoo.support.listview.OListAdapter;
import com.odoo.R;
/**
* The Class OManyToOneWidget.
*/
public class OManyToOneWidget extends LinearLayout implements
OnItemSelectedListener {
/** The Constant KEY_MODEL_NAME. */
public static final String KEY_MODEL_NAME = "model_name";
/** The Constant KEY_COLUMN_NAME. */
public static final String KEY_COLUMN_NAME = "column_name";
/** The context. */
private Context mContext = null;
/** The typed array. */
private TypedArray mTypedArray = null;
/** The attrs. */
private OControlAttributes mAttrs = new OControlAttributes();
/** The model. */
private OModel mModel = null;
/** The column. */
private OColumn mColumn = null;
/** The spinner. */
private Spinner mSpinner = null;
/** The params. */
private LayoutParams mParams = null;
/** The spinner adapter. */
private OListAdapter mSpinnerAdapter = null;
/** The spinner objects. */
private List<Object> mSpinnerObjects = new ArrayList<Object>();
/** The selected position. */
private Integer mSelectedPosition = -1;
/** The current id. */
private Integer mCurrentId = -1;
/** The many to one item change listener. */
private ManyToOneItemChangeListener mManyToOneItemChangeListener = null;
/** The custom_layout. */
private Integer custom_layout = null;
/**
* Instantiates a new many to one widget.
*
* @param context
* the context
*/
public OManyToOneWidget(Context context) {
super(context);
init(context, null, 0);
}
/**
* Instantiates a new many to one widget.
*
* @param context
* the context
* @param attrs
* the attrs
*/
public OManyToOneWidget(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
/**
* Instantiates a new many to one widget.
*
* @param context
* the context
* @param attrs
* the attrs
* @param defStyle
* the def style
*/
public OManyToOneWidget(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
/**
* Inits the control.
*
* @param context
* the context
* @param attrs
* the attrs
* @param defStyle
* the def style
*/
private void init(Context context, AttributeSet attrs, int defStyle) {
mContext = context;
if (attrs != null) {
mTypedArray = mContext.obtainStyledAttributes(attrs,
R.styleable.OManyToOneWidget);
mAttrs.put(KEY_MODEL_NAME, mTypedArray
.getString(R.styleable.OManyToOneWidget_model_name));
mAttrs.put(KEY_COLUMN_NAME, mTypedArray
.getString(R.styleable.OManyToOneWidget_column_name));
mModel = OModel.get(mContext,
mAttrs.getString(KEY_MODEL_NAME, null));
mColumn = mModel.getColumn(mAttrs.getString(KEY_COLUMN_NAME, null));
mTypedArray.recycle();
}
initControls();
}
/**
* Re init the control.
*/
public void reInit() {
initControls();
}
/**
* Sets the custom layout.
*
* @param layout
* the new custom layout
*/
public void setCustomLayout(Integer layout) {
custom_layout = layout;
}
/**
* Inits the controls.
*/
private void initControls() {
removeAllViews();
mSpinner = new Spinner(mContext);
mParams = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
mSpinner.setLayoutParams(mParams);
if (mModel != null) {
mSpinner.setTag("many_to_one_" + mModel.getTableName());
addView(mSpinner);
setAdapter();
}
}
/**
* Sets the model.
*
* @param model
* the model
* @param column
* the column
* @return the o many to one widget
*/
public OManyToOneWidget setModel(OModel model, String column) {
return setModel(model, column,
new LinkedHashMap<String, OColumn.ColumnDomain>());
}
public OManyToOneWidget setModel(OModel model, String column,
LinkedHashMap<String, ColumnDomain> domains) {
mModel = model;
mColumn = mModel.getColumn(column);
mColumn.cloneDomain(domains);
return this;
}
/**
* Sets the record id.
*
* @param id
* the new record id
*/
public void setRecordId(Integer id) {
mCurrentId = id;
}
/**
* Sets the adapter.
*/
private void setAdapter() {
mSpinnerAdapter = new OListAdapter(mContext, 0, mSpinnerObjects) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ODataRow row = (ODataRow) mSpinnerObjects.get(position);
return getRowForm(row);
}
@Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
ODataRow row = (ODataRow) mSpinnerObjects.get(position);
return getRowForm(row);
}
};
mSpinner.setAdapter(mSpinnerAdapter);
fillRecords();
}
/**
* Fill records.
*/
private void fillRecords() {
mSpinnerObjects.clear();
ODataRow select_row = new ODataRow();
select_row.put("id", 0);
select_row.put(mColumn.getName(), "Select " + mColumn.getLabel());
mSpinnerObjects.add(select_row);
StringBuffer whr = new StringBuffer();
List<Object> args_list = new ArrayList<Object>();
for (String key : mColumn.getDomains().keySet()) {
ColumnDomain domain = mColumn.getDomains().get(key);
if (domain.getConditionalOperator() != null) {
whr.append(domain.getConditionalOperator());
} else {
whr.append(" ");
whr.append(domain.getColumn());
whr.append(" ");
whr.append(domain.getOperator());
whr.append(" ? ");
args_list.add(domain.getValue());
}
}
String where = null;
Object[] args = null;
if (args_list.size() > 0) {
where = whr.toString();
args = args_list.toArray(new Object[args_list.size()]);
}
for (ODataRow row : mModel.select(where, args)) {
mSpinnerObjects.add(row);
if (mCurrentId > 0 && mCurrentId == row.getInt(OColumn.ROW_ID)) {
mSelectedPosition = mSpinnerObjects.indexOf(row);
}
}
mSpinnerAdapter.notifiyDataChange(mSpinnerObjects);
mSpinner.setSelection(mSelectedPosition);
}
/**
* Gets the row form.
*
* @param row
* the row
* @return the row form
*/
private OForm getRowForm(ODataRow row) {
AbsListView.LayoutParams mParams = new AbsListView.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
OForm form = null;
if (custom_layout != null) {
form = (OForm) LayoutInflater.from(mContext).inflate(custom_layout,
null);
} else {
form = new OForm(mContext);
form.setLayoutParams(mParams);
form.setOrientation(LinearLayout.VERTICAL);
}
form.setModel(mModel);
if (custom_layout == null) {
this.mParams = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
// Creating name field
OField field = new OField(mContext);
field.setFieldName(mColumn.getName());
field.showLabel(false);
field.setLayoutParams(this.mParams);
field.setPadding(8, 8, 8, 8);
field.reInit();
field.setTextAppearance(android.R.style.TextAppearance_Medium);
field.setTextStyle(TextStyle.NORMAL);
form.addView(field);
}
form.initForm(row);
return form;
}
/**
* Sets the on many to one item change listener.
*
* @param listener
* the new on many to one item change listener
*/
public void setOnManyToOneItemChangeListener(
ManyToOneItemChangeListener listener) {
Log.v("", "setOnManyToOneItemChangeListener()");
mManyToOneItemChangeListener = listener;
mSpinner.setOnItemSelectedListener(this);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
ODataRow row = (ODataRow) mSpinnerObjects.get(position);
mManyToOneItemChangeListener
.onManyToOneItemChangeListener(mColumn, row);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
/**
* The listener interface for receiving manyToOneItemChange events. The
* class that is interested in processing a manyToOneItemChange event
* implements this interface, and the object created with that class is
* registered with a component using the component's
* <code>addManyToOneItemChangeListener<code> method. When
* the manyToOneItemChange event occurs, that object's appropriate
* method is invoked.
*
* @see ManyToOneItemChangeEvent
*/
public interface ManyToOneItemChangeListener {
/**
* On many to one item change listener.
*
* @param column
* the column
* @param row
* the row
*/
public void onManyToOneItemChangeListener(OColumn column, ODataRow row);
}
}