@Override
		public boolean onTouch(View v, MotionEvent event) {
			switch(event.getAction()){
				case MotionEvent.ACTION_CANCEL:
					_downTime.set(0);
					break;
				case MotionEvent.ACTION_DOWN:
					_downTime.set(System.currentTimeMillis());
					_downX = event.getX();
					_downY = event.getY();
					if(_longClickTimer == null){	// if there is no pre-existing task, create a new one
						_longClickTimer = new AsyncTask<Void, Void, Boolean>(){
							@Override
							protected Boolean doInBackground(Void... params) {
								try{
									for(long i=0;i<Definitions.THRESHOLD_LONG_CLICK_MAX_DURATION;i+=INTERVAL_LONG_CLICK_CHECK){
										Thread.sleep(INTERVAL_LONG_CLICK_CHECK);
										long downTime = _downTime.get();
										if(downTime > 0 && System.currentTimeMillis()-downTime > Definitions.THRESHOLD_LONG_CLICK_MIN_DURATION){
											return true;
										}
									}
								}catch(InterruptedException ex){
									LogUtils.warn(CLASS_NAME, "doInBackground", ex.toString());
								}
								return false;
							}
							@Override
							protected void onPostExecute(Boolean result) {
								if(result){
									centerChart();
									_downTime.set(0);
								}
								_longClickTimer = null;
							}					
						};	// new asyncTask
						_longClickTimer.execute();
					}
					break;
				case MotionEvent.ACTION_MOVE:
					checkForMovement(event);
					break;
				case MotionEvent.ACTION_UP:
					long downTime = _downTime.getAndSet(0);
					if(downTime != 0 && (System.currentTimeMillis()-downTime) < Definitions.THRESHOLD_CLICK_MAX_DURATION && !checkForMovement(event)){
						SeriesSelection selection = _viewChart.getCurrentSeriesAndPoint();
						if(selection == null || selection.getSeriesIndex() != 0){	// if there was no selection or this is not the first series (point values)
							LogUtils.debug(CLASS_NAME, "onTouch", "No usable selection.");
						}else{
							List<GaugeValue> values = _currentGauge.getValues();
							int valueCount = values.size();
							int index = 0;
							//TODO: this will break if the chart shows something else than the last getMaxGraphPoints() of values
							if(valueCount - _settings.getMaxGraphPoints() > 0){
								index = valueCount - _settings.getMaxGraphPoints() + selection.getPointIndex();
							}else{
								index = selection.getPointIndex();
							}
							_currentValue = _currentGauge.getValues().get(index);
							(new GaugeValueDialog()).show(GraphActivity.this.getSupportFragmentManager(), GaugeValueDialog.TAG);
						}
					}
					break;
				default:
					break;	// ignore everything else
			}
			return false;	// always return false so that we do not interfere with the graph pan/zoom controls
		}
@Override
		public boolean onTouch(View v, MotionEvent event) {
			switch(event.getAction()){
				case MotionEvent.ACTION_CANCEL:
					_downTime.set(0);
					break;
				case MotionEvent.ACTION_DOWN:
					_downTime.set(System.currentTimeMillis());
					_downX = event.getX();
					_downY = event.getY();
					if(_longClickTimer == null){
						_longClickTimer = new AsyncTask<Void, Void, Boolean>(){
							@Override
							protected Boolean doInBackground(Void... params) {
								try{
									for(long i=0;i<Definitions.THRESHOLD_LONG_CLICK_MAX_DURATION;i+=INTERVAL_LONG_CLICK_CHECK){
										Thread.sleep(INTERVAL_LONG_CLICK_CHECK);
										long downTime = _downTime.get();
										if(downTime > 0 && System.currentTimeMillis()-downTime > Definitions.THRESHOLD_LONG_CLICK_MIN_DURATION){
											return true;
										}
									}
								}catch(InterruptedException ex){
									LogUtils.warn(CLASS_NAME, "doInBackground", ex.toString());
								}
								return false;
							}
							@Override
							protected void onPostExecute(Boolean result) {
								if(result){
									centerChart();
									_downTime.set(0);
								}
								_longClickTimer = null;
							}					
						};
						_longClickTimer.execute();
					}
					break;
				case MotionEvent.ACTION_MOVE:
					checkForMovement(event);
					break;
				case MotionEvent.ACTION_UP:
					long downTime = _downTime.getAndSet(0);
					if(downTime != 0 && (System.currentTimeMillis()-downTime) < Definitions.THRESHOLD_CLICK_MAX_DURATION && !checkForMovement(event)){
						SeriesSelection selection = _viewChart.getCurrentSeriesAndPoint();
						if(selection == null || selection.getSeriesIndex() != 0){
							LogUtils.debug(CLASS_NAME, "onTouch", "No usable selection.");
						}else{
							List<GaugeValue> values = _currentGauge.getValues();
							int valueCount = values.size();
							int index = 0;
						
							if(valueCount - _settings.getMaxGraphPoints() > 0){
								index = valueCount - _settings.getMaxGraphPoints() + selection.getPointIndex();
							}else{
								index = selection.getPointIndex();
							}
							_currentValue = _currentGauge.getValues().get(index);
							(new GaugeValueDialog()).show(GraphActivity.this.getSupportFragmentManager(), GaugeValueDialog.TAG);
						}
					}
					break;
				default:
					break;
			}
			return false;
		}
@override public boolean ontouch(view v, motionevent event) { switch(event.getaction()){ case motionevent.action_cancel: _downtime.set(0); break; case motionevent.action_down: _downtime.set(system.currenttimemillis()); _downx = event.getx(); _downy = event.gety(); if(_longclicktimer == null){ _longclicktimer = new asynctask<void, void, boolean>(){ @override protected boolean doinbackground(void... params) { try{ for(long i=0;i<definitions.threshold_long_click_max_duration;i+=interval_long_click_check){ thread.sleep(interval_long_click_check); long downtime = _downtime.get(); if(downtime > 0 && system.currenttimemillis()-downtime > definitions.threshold_long_click_min_duration){ return true; } } }catch(interruptedexception ex){ logutils.warn(class_name, "doinbackground", ex.tostring()); } return false; } @override protected void onpostexecute(boolean result) { if(result){ centerchart(); _downtime.set(0); } _longclicktimer = null; } }; _longclicktimer.execute(); } break; case motionevent.action_move: checkformovement(event); break; case motionevent.action_up: long downtime = _downtime.getandset(0); if(downtime != 0 && (system.currenttimemillis()-downtime) < definitions.threshold_click_max_duration && !checkformovement(event)){ seriesselection selection = _viewchart.getcurrentseriesandpoint(); if(selection == null || selection.getseriesindex() != 0){ logutils.debug(class_name, "ontouch", "no usable selection."); }else{ list<gaugevalue> values = _currentgauge.getvalues(); int valuecount = values.size(); int index = 0; if(valuecount - _settings.getmaxgraphpoints() > 0){ index = valuecount - _settings.getmaxgraphpoints() + selection.getpointindex(); }else{ index = selection.getpointindex(); } _currentvalue = _currentgauge.getvalues().get(index); (new gaugevaluedialog()).show(graphactivity.this.getsupportfragmentmanager(), gaugevaluedialog.tag); } } break; default: break; } return false; }