/**
* 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/>
*
* Created on 7/1/15 5:10 PM
*/
package odoo.controls;
import android.animation.LayoutTransition;
import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.odoo.R;
import com.odoo.base.addons.mail.widget.MailChatterView;
import com.odoo.core.orm.ODataRow;
import com.odoo.core.orm.OModel;
import com.odoo.core.orm.OValues;
import com.odoo.core.orm.fields.OColumn;
import com.odoo.core.utils.OResource;
import com.odoo.core.utils.logger.OLog;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class OForm extends LinearLayout {
public static final String TAG = OForm.class.getSimpleName();
private Boolean mEditable = false;
private String mModel;
private OModel model = null;
private HashMap<String, OField> mFormFieldControls = new HashMap<>();
private Context mContext = null;
private ODataRow mRecord = null;
private Boolean autoUIGenerate = true;
private int icon_tint_color = 0;
private Boolean mFirstModeChange = true;
private OValues extraValues = new OValues();
private MailChatterView chatterView = null;
private Boolean loadChatter = true;
public OForm(Context context) {
super(context);
init(context, null, 0, 0);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public OForm(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs, defStyleAttr, defStyleRes);
}
public OForm(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr, 0);
}
public OForm(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0, 0);
}
public void setEditable(Boolean editable) {
mEditable = editable;
if (mEditable) {
mFirstModeChange = true;
}
for (String key : mFormFieldControls.keySet()) {
OField control = mFormFieldControls.get(key);
control.setEditable(editable);
}
mFirstModeChange = false;
}
private void init(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
mFirstModeChange = true;
mContext = context;
if (attrs != null) {
TypedArray types = mContext.obtainStyledAttributes(attrs,
R.styleable.OForm);
mModel = types.getString(R.styleable.OForm_modelName);
mEditable = types.getBoolean(R.styleable.OForm_editableMode,
false);
autoUIGenerate = types.getBoolean(R.styleable.OForm_autoUIGenerate, true);
icon_tint_color = types.getColor(R.styleable.OForm_controlIconTint, -1);
types.recycle();
}
initForm();
LayoutTransition transition = new LayoutTransition();
setLayoutTransition(transition);
}
public boolean getEditable() {
return mEditable;
}
public void setModel(String model) {
mModel = model;
}
public String getModel() {
return mModel;
}
public void setData(ODataRow record) {
initForm(record);
}
public ODataRow getData() {
return mRecord;
}
public void initForm(ODataRow record) {
mRecord = new ODataRow();
mRecord = record;
initForm();
}
public void setIconTintColor(int color) {
icon_tint_color = color;
}
private void initForm() {
findAllFields(this);
OLog.log("Trying to get model " + mModel);
model = OModel.get(mContext, mModel, null);
if (model != null) {
setOrientation(VERTICAL);
for (String key : mFormFieldControls.keySet()) {
View v = mFormFieldControls.get(key);
if (v instanceof OField) {
OField c = (OField) v;
c.setEditable(mEditable);
c.useTemplate(autoUIGenerate);
c.setModel(model);
OColumn column = model.getColumn(c.getFieldName());
if (column != null) {
c.setColumn(column);
// Setting OnChange Event
if (column.hasOnChange()) {
setOnChangeForControl(column, c);
}
// Setting domain Filter for column
if (column.hasDomainFilterColumn()) {
setOnDomainFilterCallBack(column, c);
}
}
c.initControl();
Object val = c.getValue();
if (mRecord != null) {
if (mRecord.contains(c.getFieldName()))
val = mRecord.get(c.getFieldName());
}
if (val != null)
c.setValue(val);
if (icon_tint_color != -1) {
c.setIconTintColor(icon_tint_color);
}
}
}
// Adding chatter view if model requested
if (loadChatter) {
if (model != null && model.hasMailChatter()
&& mRecord != null && mRecord.contains("id")
&& mRecord.getInt("id") != 0) {
if (chatterView == null) {
chatterView = (MailChatterView) LayoutInflater.from(mContext)
.inflate(R.layout.base_mail_chatter, this, false);
chatterView.setModelName(model.getModelName());
chatterView.setRecordServerId(mRecord.getInt("id"));
chatterView.generateView();
addView(chatterView);
}
}
}
}
}
public void loadChatter(boolean loadChatter) {
this.loadChatter = loadChatter;
}
public void loadChatter(Boolean loadChatter) {
this.loadChatter = loadChatter;
}
private void findAllFields(ViewGroup view) {
int child = view.getChildCount();
for (int i = 0; i < child; i++) {
View v = view.getChildAt(i);
if (v instanceof LinearLayout || v instanceof RelativeLayout) {
if (v.getVisibility() == View.VISIBLE)
findAllFields((ViewGroup) v);
}
if (v instanceof OField) {
OField field = (OField) v;
if (field.getVisibility() == View.VISIBLE)
mFormFieldControls.put(field.getFieldName(), field);
}
}
}
public OValues getValues() {
OValues values = new OValues();
for (String key : mFormFieldControls.keySet()) {
OField control = mFormFieldControls.get(key);
Object val = control.getValue();
OColumn column = control.getColumn();
if (val == null || TextUtils.isEmpty(val.toString())
|| val.toString().equals("-1")) {
val = false;
}
if (column != null && column.isRequired()) {
if (val.toString().equals("false")) {
control.setError(column.getLabel() +
" " + OResource.string(mContext, R.string.label_required));
return null;
} else {
control.setError(null);
}
}
values.put(key, val);
}
values.addAll(extraValues.toDataRow().getAll());
return values;
}
// OnDomainFilterCallBack callbacks
private void setOnDomainFilterCallBack(final OColumn column, OField field) {
LinkedHashMap<String, OColumn.ColumnDomain> filterDomain = column
.getFilterDomains();
for (String key : filterDomain.keySet()) {
OColumn.ColumnDomain domain = filterDomain.get(key);
if (domain.getColumn() != null) {
OField fld = mFormFieldControls.get(domain.getColumn());
if (fld != null) {
setFilterDomainCallback(domain, fld, field, column);
}
}
}
}
private void setFilterDomainCallback(OColumn.ColumnDomain domain,
final OField field, final OField oField, final OColumn column) {
field.setOnFilterDomainCallBack(domain, new IOnDomainFilterCallbacks() {
@Override
public void onFieldValueChanged(OColumn.ColumnDomain dm) {
column.addDomain(dm.getColumn(), dm.getOperator(),
dm.getValue());
column.setHasDomainFilterColumn(false);
oField.setColumn(column);
oField.resetData();
}
});
}
// OnChange event for control column
private void setOnChangeForControl(final OColumn column, OField field) {
field.setOnChangeCallbackListener(new IOnChangeCallback() {
@Override
public void onValueChange(final ODataRow row) {
if (!mFirstModeChange) {
if (!column.isOnChangeBGProcess()) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Object value = model.getOnChangeMethodValue(column, row);
if (value instanceof ODataRow)
fillOnChangeData((ODataRow) value);
}
}, 300);
} else {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
OnChangeBackground bgProcess = new OnChangeBackground(
column);
bgProcess.execute(row);
}
}, 300);
}
}
if (mFirstModeChange) {
mFirstModeChange = false;
}
}
});
}
private void fillOnChangeData(ODataRow values) {
if (values != null) {
for (String key : values.keys()) {
if (mFormFieldControls.containsKey(key)) {
OField fld = mFormFieldControls.get(key);
fld.setValue(values.get(key));
} else {
extraValues.put(key, values.get(key));
}
}
}
}
private class OnChangeBackground extends
AsyncTask<ODataRow, Void, ODataRow> {
private ProgressDialog mDialog;
private OColumn mCol;
public OnChangeBackground(OColumn col) {
mCol = col;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
mDialog = new ProgressDialog(mContext);
mDialog.setTitle(mContext.getString(R.string.title_working));
mDialog.setMessage(mContext.getString(R.string.title_please_wait));
mDialog.setCancelable(false);
mDialog.show();
}
@Override
protected ODataRow doInBackground(ODataRow... params) {
try {
Thread.sleep(300);
return (ODataRow) model.getOnChangeMethodValue(mCol, params[0]);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(ODataRow result) {
super.onPostExecute(result);
if (result != null) {
fillOnChangeData(result);
}
mDialog.dismiss();
}
}
}