/*
* This file is part of Domodroid.
*
* Domodroid is Copyright (C) 2011 Pierre LAINE, Maxime CHOFARDET
*
* Domodroid is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* Domodroid 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Domodroid. If not, see <http://www.gnu.org/licenses/>.
*/
package widgets;
import android.app.Activity;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import org.domogik.domodroid13.R;
import org.json.JSONException;
import org.json.JSONObject;
import Abstract.translate;
import Entity.Entity_Feature;
import Entity.Entity_Map;
import Entity.Entity_client;
import database.WidgetUpdate;
import misc.tracerengine;
import rinor.send_command;
public class Graphical_Range extends Basic_Graphical_widget implements SeekBar.OnSeekBarChangeListener {
private TextView state;
private SeekBar seekBarVaria;
private String address;
private int state_progress;
private int scale;
private int valueMin = 0;
private int valueMax = 100;
private int CustomMax;
private String type;
private static int stateThread;
private final boolean activate = false;
private Animation animation;
private boolean touching;
private int updating = 0;
public static FrameLayout container = null;
private static final FrameLayout myself = null;
private static String mytag;
private Message msg;
private Boolean realtime = false;
private String stateS = "";
private String test_unite;
private String command_id = null;
private String command_type = null;
private final Entity_Feature feature;
private final int session_type;
private final SharedPreferences params;
private JSONObject jparam;
public Graphical_Range(tracerengine Trac,
final Activity activity, int widgetSize, int session_type, int place_id, String place_type, SharedPreferences params,
final Entity_Feature feature, Handler handler) {
super(params, activity, Trac, feature.getId(), feature.getDescription(), feature.getState_key(), feature.getIcon_name(), widgetSize, place_id, place_type, mytag, container, handler);
this.feature = feature;
this.params = params;
this.session_type = session_type;
onCreate();
}
public Graphical_Range(tracerengine Trac,
final Activity activity, int widgetSize, int session_type, int place_id, String place_type, SharedPreferences params,
final Entity_Map feature_map, Handler handler) {
super(params, activity, Trac, feature_map.getId(), feature_map.getDescription(), feature_map.getState_key(), feature_map.getIcon_name(), widgetSize, place_id, place_type, mytag, container, handler);
this.feature = feature_map;
this.session_type = session_type;
this.params = params;
onCreate();
}
private void onCreate() {
String state_key = feature.getState_key();
int dev_id = feature.getDevId();
String parameters = feature.getParameters();
this.address = feature.getAddress();
mytag = "Graphical_Range(" + dev_id + ")";
stateThread = 1;
try {
this.stateS = getResources().getString(translate.do_translate(getContext(), Tracer, state_key));
} catch (Exception e) {
this.stateS = state_key;
}
//get parameters
try {
jparam = new JSONObject(parameters.replaceAll(""", "\""));
} catch (JSONException e) {
Tracer.i(mytag, "No parameters");
seekBarVaria.setEnabled(false);
}
if (api_version >= 0.7f) {
try {
int number_of_command_parameters = jparam.getInt("number_of_command_parameters");
if (number_of_command_parameters == 1) {
command_id = jparam.getString("command_id");
command_type = jparam.getString("command_type1");
}
} catch (JSONException e) {
Tracer.i(mytag, "No parameters for command");
seekBarVaria.setEnabled(false);
}
} else {
try {
String command = jparam.getString("command");
valueMin = jparam.getInt("valueMin");
valueMax = jparam.getInt("valueMax");
} catch (JSONException e) {
Tracer.i(mytag, "No parameters for command");
seekBarVaria.setEnabled(false);
}
int range = valueMax - valueMin;
scale = 100 / range;
}
try {
test_unite = jparam.getString("unit");
} catch (JSONException e) {
test_unite = "%";
}
if (test_unite == null || test_unite.length() == 0) {
test_unite = "%";
}
String[] model = feature.getDevice_type_id().split("\\.");
type = model[0];
//linearlayout horizontal body
LinearLayout bodyPanHorizontal = new LinearLayout(activity);
bodyPanHorizontal.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, Gravity.CENTER_VERTICAL));
bodyPanHorizontal.setOrientation(LinearLayout.HORIZONTAL);
//right panel with different info and seekbars
FrameLayout rightPan = new FrameLayout(activity);
rightPan.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
rightPan.setPadding(0, 0, 10, 0);
// panel
LinearLayout leftPan = new LinearLayout(activity);
leftPan.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, Gravity.BOTTOM));
leftPan.setOrientation(LinearLayout.VERTICAL);
leftPan.setGravity(Gravity.CENTER_VERTICAL);
leftPan.setPadding(4, 5, 0, 0);
state = new TextView(activity);
state.setTextColor(Color.BLACK);
state.setPadding(20, 0, 0, 0);
state.setText(stateS);
animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(1000);
//first seekbar variator
seekBarVaria = new SeekBar(activity);
seekBarVaria.setProgress(0);
if (api_version < 0.7f)
seekBarVaria.setMax(valueMax - valueMin);
seekBarVaria.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
seekBarVaria.setProgressDrawable(getResources().getDrawable(R.drawable.bgseekbarvaria));
seekBarVaria.setThumb(getResources().getDrawable(R.drawable.buttonseekbar));
seekBarVaria.setThumbOffset(-3);
seekBarVaria.setOnSeekBarChangeListener(this);
seekBarVaria.setPadding(0, 0, 15, 7);
leftPan.addView(state);
leftPan.addView(seekBarVaria);
rightPan.addView(leftPan);
bodyPanHorizontal.addView(rightPan);
super.LL_topPan.removeView(super.LL_featurePan);
super.LL_infoPan.addView(bodyPanHorizontal);
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
/// Deprecated method to die /////////////////////////////////////////
if (activate) {
Tracer.d(mytag, "Handler receives a request to die ");
//That seems to be a zombie
removeView(LL_background);
myself.setVisibility(GONE);
if (container != null) {
container.removeView(myself);
container.recomputeViewAttributes(myself);
}
try {
finalize();
} catch (Throwable t) {
t.printStackTrace();
} //kill the handler thread itself
///////////////////////////////////////////////////////////////////
} else {
int new_val = 0;
if (msg.what == 9999) {
//state_engine send us a signal to notify value changed
if (session == null)
return;
try {
Tracer.d(mytag, "Handler receives a new value from cache_engine <" + session.getValue() + ">");
new_val = Integer.parseInt(session.getValue());
} catch (Exception e) {
new_val = 0;
}
String Timestamp = session.getTimestamp();
Tracer.d(mytag, "Handler receives a new value <" + new_val + "> at " + Timestamp);
//#1649
//Value min and max should be the limit of the widget
if (new_val <= valueMin) {
state.setText(stateS + " : " + valueMin + " " + test_unite);
} else if (new_val > valueMin && new_val < valueMax) {
state.setText(stateS + " : " + new_val + " " + test_unite);
} else if (new_val >= valueMax) {
state.setText(stateS + " : " + valueMax + " " + test_unite);
}
state.setAnimation(animation);
new SBAnim(seekBarVaria.getProgress(), new_val - valueMin).execute();
} else if (msg.what == 9998) {
// state_engine send us a signal to notify it'll die !
Tracer.d(mytag, "state engine disappeared ===> Harakiri !");
session = null;
realtime = false;
removeView(LL_background);
myself.setVisibility(GONE);
if (container != null) {
container.removeView(myself);
container.recomputeViewAttributes(myself);
}
try {
finalize();
} catch (Throwable t) {
t.printStackTrace();
} //kill the handler thread itself
}
}
}
};
//================================================================================
/*
* New mechanism to be notified by widgetupdate engine when our value is changed
*
*/
WidgetUpdate cache_engine = WidgetUpdate.getInstance();
if (cache_engine != null) {
if (api_version <= 0.6f) {
session = new Entity_client(dev_id, state_key, mytag, handler, session_type);
} else if (api_version >= 0.7f) {
session = new Entity_client(feature.getId(), "", mytag, handler, session_type);
}
try {
if (Tracer.get_engine().subscribe(session)) {
realtime = true; //we're connected to engine
//each time our value change, the engine will call handler
handler.sendEmptyMessage(9999); //Force to consider current value in session
}
} catch (Exception e) {
e.printStackTrace();
}
}
//================================================================================
//updateTimer(); //Don't use anymore cyclic refresh....
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
//#1649
//Value min and max should be the limit of the widget
int realprogress = (progress + valueMin);
if (realprogress <= valueMin) {
state.setText(stateS + " : " + valueMin + " " + test_unite);
change_this_icon(0);
} else if (realprogress > valueMin && realprogress < valueMax) {
state.setText(stateS + " : " + realprogress + " " + test_unite);
change_this_icon(1);
} else if (realprogress >= valueMax) {
state.setText(stateS + " : " + valueMax + " " + test_unite);
change_this_icon(2);
}
}
public void onStartTrackingTouch(SeekBar arg0) {
touching = true;
updating = 3;
}
public void onStopTrackingTouch(SeekBar arg0) {
//send the correct value by replacing it with a converted one.
state_progress = arg0.getProgress() + valueMin;
send_command.send_it(activity, Tracer, command_id, command_type, String.valueOf(state_progress), api_version);
touching = false;
}
public class SBAnim extends AsyncTask<Void, Integer, Void> {
private final int begin;
private final int end;
public SBAnim(int begin, int end) {
this.begin = begin;
this.end = end;
}
@Override
protected Void doInBackground(Void... params) {
final int steps = java.lang.Math.abs(end - begin);
new Thread(new Runnable() {
public synchronized void run() {
for (int i = 0; i <= steps; i++) {
try {
this.wait(7 * scale);
if (!touching) {
if (end - begin > 0) seekBarVaria.setProgress(begin + i);
else seekBarVaria.setProgress(begin - i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
return null;
}
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
if (visibility == View.VISIBLE) {
//activate=true;
}
}
}