Back to project page SpunkyCharts.
The source code is released under:
GNU General Public License
If you think the Android project SpunkyCharts listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.jogden.spunkycharts.traditionalchart; /* /*from w w w .ja v a2 s. co m*/ Copyright (C) 2014 Jonathon Ogden < jeog.dev@gmail.com > This program 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. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses. */ import java.util.Stack; import android.app.Activity; import android.app.Dialog; import android.content.CursorLoader; import android.content.Loader; import android.database.Cursor; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.os.Handler; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.TextView; import com.jogden.spunkycharts.ApplicationPreferences; import com.jogden.spunkycharts.BaseChartFragmentA; import com.jogden.spunkycharts.GlobalChartPreferences; import com.jogden.spunkycharts.MainApplication; import com.jogden.spunkycharts.R; import com.jogden.spunkycharts.data.DataContentService; /** A derived class used to implement an actual chart type. * In this case a number of the traditional charts you have * probably seen before( e.g bar, candle, line charts). * </p> * Use this class a template for how to design a chart of your * own. Notice how this object handles inflating the views, * handling life-cycle, initiating data connections, and dealing * with local preferences via the TraditionalChartPreferences * object. * </p> * With that sad most of the granular operations: calculations, * displays, redraws, internal adjusts, and low(er) level data * handling, should be done by a custom Adapter object. * Currently there is no Abstract Base for an adapter but use * TraditionalChartFragmentAdapter as a template. */ public class TraditionalChartFragment extends BaseChartFragmentA { static private final float TTL_PNL_WGHT = 10f; /* our important inner views */ private LinearLayout _yAxis; private LinearLayout _xAxis; private LinearLayout _volAxis; private LinearLayout _rightPanel; private TraditionalChartPanel _mainPanel; private TraditionalChartPanel _volumePanel; /* all the internal logical and view management*/ private TraditionalChartFragmentAdapter _chartAdapter; private TraditionalChartFragment _this = this; private ViewGroup _myViewGroup = null; private String _symbol; private float _pricePnlWght = 0; private OnLayoutChangeListener _pAxisLayoutChngLstnr = null; private ZoomAndSlideOverlay _zoomAndSlideOverlay = null; /* private settings */ private int _xSegWidth = ApplicationPreferences.getSegmentWidth(); private TraditionalChartPreferences.Type _type = TraditionalChartPreferences.getDefaultType(); private TraditionalChartPreferences.Frequency _frequency = TraditionalChartPreferences.getDefaultFrequency(); private float _segThickness = TraditionalChartPreferences.getDefaultSegThickness(); private int _foreColor = TraditionalChartPreferences.getDefaultForegroundColor(); private int _backColor = TraditionalChartPreferences.getDefaultBackgroundColor(); private int _lineColor = TraditionalChartPreferences.getDefaultLineColor(); /* cache these to avoid myriad getter calls */ static boolean majorMarkFlag = ApplicationPreferences.getShowMajorMark(); static boolean minorMarkFlag = ApplicationPreferences.getShowMinorMark(); /* used to draw ALL axis marks of this chart type */ public static final Paint axisMarkBrush = new Paint(Paint.ANTI_ALIAS_FLAG); static{ axisMarkBrush.setStrokeWidth( ApplicationPreferences.getAxisMarkThickness() ); axisMarkBrush.setColor( ApplicationPreferences.getAxisMarkColor() ); } /*|---------> begin PUBLIC interface <--------|*/ /* getter/setters for universal preferences*/ static public void setAxisMarkColor(int colorId) { axisMarkBrush.setColor(colorId); } static public int getAxisMarktColor() { return axisMarkBrush.getColor(); } static public void setAxisMarkThickness(int pixSize) { axisMarkBrush.setStrokeWidth(pixSize); } static public float getAxisMarkThickness() { return axisMarkBrush.getStrokeWidth(); } static public void setShowMinorMark(boolean show) { minorMarkFlag = show; } static public boolean getShowMinorMark() { return minorMarkFlag; } static public void setShowMajorMark(boolean show) { majorMarkFlag = show; } static public boolean getShowMajorMark() { return majorMarkFlag; } @Override public void setAxisFontSize(int sp) { if( _chartAdapter != null) _chartAdapter.setAxisFontSize(sp); } @Override public void setAxisFontColor(int colorId) { if( _chartAdapter != null) _chartAdapter.setAxisFontColor(colorId); } @Override public void setXAxisPaddingSize(int pixSize) { if(_chartAdapter != null) _chartAdapter.setXAxisPaddingSize(pixSize); } @Override public void setAxisTimeout(int value) { if(_chartAdapter != null) _chartAdapter.setAxisTimeout(value); } @Override public void setTimeoutIncrement(int value) { if(_chartAdapter != null) _chartAdapter.setTimeoutIncrement(value); } /*these should be optimized, called often to tidy up */ @Override public void refresh() { if(!_chartAdapter.isFullOfSegments()) if(MainApplication.readyForData) DataContentService.load(_symbol, _chartAdapter); _chartAdapter.axisRefresh(); _mainPanel.forceDraw(); _volumePanel.forceDraw(); } /* this needs to be overridden public so DockingPanelActivity * can call it. need to call down to the super class * method AND mergeLocalPreferencesDialog() */ @Override public Dialog getLocalPreferencesDialog() { /* be sure to call down first and collect the dialog */ final Dialog dialog = super.getLocalPreferencesDialog(); /* than call mergeDialogLayout to add our layout */ final Dialog perfDialog = mergeLocalPreferencesDialog( dialog,R.layout.chart_settings_traditional ); Bundle bndl = new Bundle(); bndl.putString( TraditionalChartPreferences.TRADITIONAL_CHART_TYPE, this.getChartType().toString() ); bndl.putString( TraditionalChartPreferences.TRADITIONAL_CHART_FREQ, this.getChartFrequency().toString() ); bndl.putFloat( TraditionalChartPreferences.TRADITIONAL_SEG_THICKNESS, this.getSegmentThickness() ); bndl.putInt( TraditionalChartPreferences.TRADITIONAL_FORE_COLOR, this.getForegroundColor() ); bndl.putInt( TraditionalChartPreferences.TRADITIONAL_BACK_COLOR, this.getBackgroundColor() ); bndl.putInt( TraditionalChartPreferences.TRADITIONAL_LINE_COLOR, this.getLineColor() ); TraditionalChartPreferences tPref = new TraditionalChartPreferences(); MainApplication.ViewFindable finder = new MainApplication.ViewFindable(){ public View findViewById(int id){ return perfDialog.findViewById(id); } }; if( tPref.findViews(finder) ) tPref.setup( bndl, new ApplicationPreferences.ChartPreferencesSetup.Callback(){ @Override public <T> void callback(String pref, T val) { if( pref.equals( TraditionalChartPreferences.TRADITIONAL_CHART_TYPE )) _this.setChartType( TraditionalChartPreferences.Type.valueOf((String)val) ); else if( pref.equals( TraditionalChartPreferences.TRADITIONAL_CHART_FREQ )) _this.setChartFrequency( TraditionalChartPreferences.Frequency.valueOf( (String)val ) ); else if( pref.equals( TraditionalChartPreferences.TRADITIONAL_SEG_THICKNESS )) _this.setSegmentThickness( (Float)val ); else if( pref.equals( TraditionalChartPreferences.TRADITIONAL_FORE_COLOR )) _this.setForegroundColor((Integer)val); else if( pref.equals( TraditionalChartPreferences.TRADITIONAL_BACK_COLOR )) _this.setBackgroundColor((Integer)val); else if( pref.equals( TraditionalChartPreferences.TRADITIONAL_LINE_COLOR )) _this.setLineColor((Integer)val); } }, this.getActivity() ); return perfDialog; } @Override public void hide() { super.hide(); _mainPanel.forceStop(); _volumePanel.forceStop(); } @Override public void show() { super.show(); _mainPanel.forceStart(); _volumePanel.forceStart(); } /*|---------> end PUBLIC interface <--------|*/ /*|---------> begin PROTECTED interface <--------|*/ protected void setLineColor( int colorId ) { _mainPanel.setLineColor(colorId); _mainPanel.forceDraw(); _volumePanel.setLineColor(colorId); _volumePanel.forceDraw(); _lineColor = colorId; } protected int getLineColor() { return _lineColor; } protected void setForegroundColor( int colorId ) { _foreColor = colorId; _rightPanel.setBackgroundColor(colorId); ((HorizontalScrollView)_xAxis.getParent()).setBackgroundColor( colorId ); super.setColor(colorId); } protected int getForegroundColor() { return _foreColor; } protected void setBackgroundColor( int colorId ) { _backColor = colorId; _myViewGroup.setBackgroundColor(colorId); } protected int getBackgroundColor() { return _backColor; } protected void setChartType( TraditionalChartPreferences.Type type ) { _chartAdapter.setChartType(type); DataContentService.load(_symbol, _chartAdapter); _type = type; } protected TraditionalChartPreferences.Type getChartType() { return _type; } protected void setChartFrequency( TraditionalChartPreferences.Frequency frequency ){ _chartAdapter.setChartFrequency(frequency); DataContentService.load(_symbol, _chartAdapter); _frequency = frequency; } protected TraditionalChartPreferences.Frequency getChartFrequency() { return _frequency; } protected void setSegmentThickness( float thickness) { _mainPanel.setSegmentThickness(thickness); _mainPanel.forceDraw(); _volumePanel.setSegmentThickness(thickness); _volumePanel.forceDraw(); _segThickness = thickness; } protected float getSegmentThickness() { return _segThickness; } @Override protected void setLineThickness( GlobalChartPreferences.LineThickness thickness ){ _mainPanel.setLineThickness(thickness); _mainPanel.forceDraw(); _volumePanel.setLineThickness(thickness); _volumePanel.forceDraw(); super.setLineThickness(thickness); } @Override protected void setRefreshRate( int refreshRate) { super.setRefreshRate(refreshRate); } @Override /* should be a mirror of onSavedState handler */ protected void extractState(Bundle savedState) { if(savedState == null) return; if( _symbol == null) _symbol = savedState.getString("symbol"); if( _symbol == null) throw new IllegalStateException( "ChartFragment does not have valid symbol string" ); _type = TraditionalChartPreferences.Type.valueOf( savedState.getString( TraditionalChartPreferences.TRADITIONAL_CHART_TYPE ) ); _frequency = TraditionalChartPreferences.Frequency .valueOf( savedState.getString( TraditionalChartPreferences.TRADITIONAL_CHART_FREQ ) ); _segThickness = savedState.getFloat( TraditionalChartPreferences.TRADITIONAL_SEG_THICKNESS ); _foreColor = savedState.getInt( TraditionalChartPreferences.TRADITIONAL_FORE_COLOR ); _backColor = savedState.getInt( TraditionalChartPreferences.TRADITIONAL_BACK_COLOR ); _lineColor = savedState.getInt( TraditionalChartPreferences.TRADITIONAL_LINE_COLOR ); super.extractState(savedState); } /* how to handle a held/long touch of the frag view */ @Override protected void onHoldDown() { if(_zoomAndSlideOverlay != null){ _zoomAndSlideOverlay.close(); _zoomAndSlideOverlay = null; } else { _zoomAndSlideOverlay = new ZoomAndSlideOverlay(); } _myViewGroup.invalidate(); } /* remember oldTop == this */ @Override protected void onStacked( BaseChartFragmentA base, BaseChartFragmentA oldTop, BaseChartFragmentA newTop ){ TraditionalChartFragment tcfOldTop = (TraditionalChartFragment)oldTop; float mWeight = tcfOldTop._getPricePanelWeight(); int segW = tcfOldTop._chartAdapter.getSegmentWidth(); TraditionalChartFragment tmp = (TraditionalChartFragment)newTop.getTopOfStack(); do{ /*assimilate the views, find the old base ... */ tmp._setRelativePanelWeights(mWeight,10-mWeight); tmp._chartAdapter.setSegmentWidth(segW); tmp.setBackgroundColor(Color.TRANSPARENT); }while( tmp.getLastLinkOfStack() != oldTop && (tmp = (TraditionalChartFragment)tmp.getLastLinkOfStack() ).TRUE ); /*note: the intentional side-effect */ /* ... to remove its listener, ...*/ if(tmp._hasPriceAxisOnLayoutChangeListener()) tmp._removePriceAxisOnLayoutChangeListener(); /* ... find its panel of axises, ... */ ViewGroup vgFrom = (ViewGroup)tmp.getView().findViewById( R.id.chart_right_panel_holder ); ViewGroup vgTo = (ViewGroup)base.getView().findViewById( R.id.chart_right_panel_holder ); int sz = vgFrom.getChildCount(); /* ... move those axises to the new base, ... */ while(sz-- > 1){ /* account for the spacer */ View v = vgFrom.getChildAt(1); vgFrom.removeView( v ); vgTo.addView( v ); } TraditionalChartFragment tcfBase = (TraditionalChartFragment)base; /*... and add a new listenter to the new base. */ if(!tcfBase._hasPriceAxisOnLayoutChangeListener()) tcfBase._setPriceAxisOnLayoutChangeListener(); try{ vgTo.invalidate(); vgFrom.invalidate(); }catch(Exception e){ vgTo.postInvalidate(); vgFrom.postInvalidate(); } } /* currently not reseting prefs changed in onStacked */ @Override protected void onDeStacked( BaseChartFragmentA base, BaseChartFragmentA oldTop, BaseChartFragmentA newTop ){ ViewGroup vgFrom = (ViewGroup)base.getView().findViewById( R.id.chart_right_panel_holder ); ViewGroup vgTo = (ViewGroup)oldTop.getView().findViewById( R.id.chart_right_panel_holder ); View v = vgFrom.getChildAt( vgFrom.getChildCount() - 1); vgFrom.removeView(v); vgTo.addView(v); View vv = oldTop.getView().findViewById( R.id.chart_right_panel_spacer ); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)vv.getLayoutParams(); lp.width = LinearLayout.LayoutParams.WRAP_CONTENT; vv.setLayoutParams(lp); TraditionalChartFragment tcfBase = (TraditionalChartFragment)base; if(base == newTop && tcfBase._hasPriceAxisOnLayoutChangeListener()) tcfBase._removePriceAxisOnLayoutChangeListener(); try{ vgTo.invalidate(); vgFrom.invalidate(); }catch(Exception e){ vgTo.postInvalidate(); vgFrom.postInvalidate(); } } /*|---------> end PROTECTED interface <--------|*/ /*|---------> begin PRIVATE methods <--------|*/ private float _getPricePanelWeight() { return _pricePnlWght; } private boolean _hasPriceAxisOnLayoutChangeListener() { return _pAxisLayoutChngLstnr != null; } private void _removePriceAxisOnLayoutChangeListener() { ((LinearLayout)(_myViewGroup.findViewById( R.id.chart_right_panel_holder))).removeOnLayoutChangeListener( _pAxisLayoutChngLstnr ); _pAxisLayoutChngLstnr = null; } private void _setPriceAxisOnLayoutChangeListener() { _pAxisLayoutChngLstnr = new OnLayoutChangeListener(){ @Override public void onLayoutChange( View v, int left, int top,int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom){ for( BaseChartFragmentA tmp = getTopOfStack() ; tmp != getBaseOfStack(); tmp = tmp.getLastLinkOfStack() ){ tmp.getView().findViewById( R.id.chart_right_panel_spacer ).setLayoutParams( new LinearLayout.LayoutParams( right-left, LinearLayout.LayoutParams.MATCH_PARENT ) ); } } }; ((LinearLayout)(_myViewGroup.findViewById( R.id.chart_right_panel_holder))).addOnLayoutChangeListener( _pAxisLayoutChngLstnr ); } private void _syncPanels() { final TextView tv = (TextView)_rightPanel.findViewById(R.id.xAxis_mirror); final int innerHeight = getResources().getDimensionPixelSize( R.dimen.chart_frag_trad_inner_axis_height ); /* synch X-Axis heights */ _xAxis.addOnLayoutChangeListener( new OnLayoutChangeListener(){ @Override public void onLayoutChange( View v, int left, int top,int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom){ tv.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, (int)((bottom-top)+ innerHeight) ) ); _rightPanel.invalidate(); } } ); } private void _setRelativePanelWeights(float a, float b) { (( LinearLayout.LayoutParams) _mainPanel.getLayoutParams()).weight = (( LinearLayout.LayoutParams) _yAxis.getLayoutParams()).weight = a; (( LinearLayout.LayoutParams) _volumePanel.getLayoutParams()).weight = (( LinearLayout.LayoutParams) _volAxis.getLayoutParams()).weight = b; ourViewGroup.postInvalidate(); _pricePnlWght = a; refresh(); } /*|---------> end PRIVATE methods <--------|*/ /*|---------> begin LIFE-CYCLE handlers <--------|*/ @Override public void onAttach(Activity activity) { super.onAttach(activity); _symbol = this.getArguments().getString("symbol"); } @Override public void onCreate(Bundle savedState) { super.onCreate(savedState); } @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedState ){ /* create the surrounding view first */ super.onCreateView(inflater, container, savedState); _myViewGroup = (ViewGroup)inflater.inflate( R.layout.chart_fragment_traditional, ourViewGroup, true ).findViewById(R.id.trad_chart_main); _yAxis = (LinearLayout)_myViewGroup.findViewById( R.id.label_yAxis ); _xAxis = (LinearLayout)_myViewGroup.findViewById( R.id.label_xAxis ); _volAxis = (LinearLayout)_myViewGroup.findViewById( R.id.label_yAxis_vol ); _rightPanel = (LinearLayout)_myViewGroup.findViewById( R.id.chart_right_panel ); _mainPanel = (TraditionalChartPanel)_myViewGroup.findViewById( R.id.main_lay ); _volumePanel = (TraditionalChartPanel)_myViewGroup.findViewById( R.id.volume_lay ); _pricePnlWght = ((LinearLayout.LayoutParams)( _mainPanel.getLayoutParams() )).weight; _syncPanels(); _mainPanel.init(); _volumePanel.init(); setBackgroundColor( _backColor ); setForegroundColor( _foreColor ); return ourViewGroup; } @Override public void onActivityCreated(Bundle savedState){ super.onActivityCreated(savedState); _chartAdapter = /* Setup adapter for data */ new TraditionalChartFragmentAdapter( parentActivity, new Handler(), MainApplication.getLocalBroadcastManager(), _mainPanel, _xAxis, _yAxis, _volumePanel, _volAxis, _myViewGroup, _xSegWidth, _type, _frequency, null, _symbol ); DataContentService.addChannel(_symbol,_chartAdapter); } @Override public void onStart() { super.onStart(); if(MainApplication.readyForData) DataContentService.load(_symbol, _chartAdapter); } @Override public void onResume() { super.onResume(); } @Override public void onPause() { super.onPause(); } @Override public void onStop() { super.onStop(); _chartAdapter.cleanUpAndUpdate(); } @Override public void onSaveInstanceState(Bundle savedState) { savedState.putString("symbol", _symbol); savedState.putString( TraditionalChartPreferences.TRADITIONAL_CHART_TYPE, _type.toString() ); savedState.putString( TraditionalChartPreferences.TRADITIONAL_CHART_FREQ, _frequency.toString() ); savedState.putFloat( TraditionalChartPreferences.TRADITIONAL_SEG_THICKNESS, _segThickness ); savedState.putInt( TraditionalChartPreferences.TRADITIONAL_FORE_COLOR, _foreColor ); savedState.putInt( TraditionalChartPreferences.TRADITIONAL_BACK_COLOR, _backColor ); savedState.putInt( TraditionalChartPreferences.TRADITIONAL_LINE_COLOR, _lineColor ); super.onSaveInstanceState(savedState); } @Override public void onDestroyView() { super.onDestroyView(); } @Override public void onDestroy() { DataContentService.removeChannel(_symbol,_chartAdapter); super.onDestroy(); } @Override public void onDetach() { super.onDetach(); } /*|---------> end LIFE-CYCLE handlers <--------|*/ /*|---------> begin NESTED OBJECT DEFS <--------|*/ /*handles the creation and touch events of a view * that allows for adjusting the horizontal and vertical zoom * of the main price panel and the relative size of it * and the volume(,potentially other,) panel(s) */ private class ZoomAndSlideOverlay { private final View lower; private final View upper; private final View div; private final LinearLayout mainOverlay; private int savedBackColor; public ZoomAndSlideOverlay() { mainOverlay = (LinearLayout)parentActivity.getLayoutInflater().inflate( R.layout.chart_fragment_traditional_adj, _myViewGroup ).findViewById(R.id.trad_chart_main_adj); div = mainOverlay.findViewById(R.id.label_xAxis_adj); upper = mainOverlay.findViewById(R.id.main_lay_adj); lower = mainOverlay.findViewById(R.id.volume_lay_adj); div.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, (int) (_xAxis.getMeasuredHeight() + getResources().getDimension( R.dimen.chart_frag_trad_inner_axis_height) ) ) ); upper.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, 0, _pricePnlWght ) ); lower.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, 0, TTL_PNL_WGHT - _pricePnlWght ) ); div.setBackgroundColor(Color.BLACK); ((TextView)div).setTextColor(Color.WHITE); upper.setBackgroundColor(Color.DKGRAY); upper.setAlpha(.60f); savedBackColor = getBackgroundColor(); setBackgroundColor(Color.TRANSPARENT); upper.setOnTouchListener( new OverlayUpperTouchListener() ); div.setOnTouchListener( new OverlayDividerTouchListener() ); } public void close() { View v = _myViewGroup.findViewById(R.id.trad_chart_main_adj); if( v != null) _myViewGroup.removeView(v); setBackgroundColor(savedBackColor); } /* deal with zoom in/out */ private class OverlayUpperTouchListener implements OnTouchListener { private float startX = 0; private float startY = 0; private boolean hasMoved = false; @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch(action) { case(MotionEvent.ACTION_DOWN): startX = event.getX(); startY = event.getY(); break; case(MotionEvent.ACTION_MOVE): float moveX = event.getX(); float moveY = event.getY(); if( Math.abs(moveX-startX) > MainApplication.TMOVE_THRSHLD || Math.abs(moveY-startY) > MainApplication.TMOVE_THRSHLD ){ hasMoved = true; } break; case(MotionEvent.ACTION_CANCEL): case(MotionEvent.ACTION_UP): if( hasMoved ){ float x = event.getX(); float y = event.getY(); int width = upper.getMeasuredWidth(); int height = upper.getMeasuredHeight(); float relMoveX = (x - startX)/ width; float relMoveY = (y-startY)/height; float absRelMoveX = Math.abs(relMoveX); float absRelMoveY = Math.abs(relMoveY); for( TraditionalChartFragment tmp = (TraditionalChartFragment)getTopOfStack() ; tmp != null; tmp = (TraditionalChartFragment)tmp.getLastLinkOfStack() ){ /* treat as X axis zoom */ if((absRelMoveX+=1) > (absRelMoveY+=1)) { if(relMoveX > 0) tmp._chartAdapter.setSegmentWidth( (int)( _chartAdapter.getSegmentWidth() / absRelMoveX ) ); else tmp._chartAdapter.setSegmentWidth( (int)( _chartAdapter.getSegmentWidth() * absRelMoveX ) ); } else { /* treat as Y axis zoom */ if(relMoveY > 0) tmp._chartAdapter.setHighLowDisplayMultiple( absRelMoveY ); else tmp._chartAdapter.setHighLowDisplayMultiple( 1 / absRelMoveY ); } } mainOverlay.invalidate(); }else if((event.getEventTime() - event.getDownTime()) > ApplicationPreferences.getChartHoldThreshold() ){ onHoldDown(); } hasMoved = false; } return true; } } /* deal with relative segment size */ private class OverlayDividerTouchListener implements OnTouchListener { private float startX = 0; private float startY = 0; boolean hasMoved = false; @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch(action) { case(MotionEvent.ACTION_DOWN): startX = event.getX(); startY = event.getY(); break; case(MotionEvent.ACTION_MOVE): float moveX = event.getX(); float moveY = event.getY(); if( Math.abs(moveX-startX) > MainApplication.TMOVE_THRSHLD || Math.abs(moveY-startY) > MainApplication.TMOVE_THRSHLD ){ hasMoved = true; } break; case(MotionEvent.ACTION_CANCEL): case(MotionEvent.ACTION_UP): if( hasMoved ){ float y = event.getY(); float newYPos = y + (int) (_mainPanel.getMeasuredHeight() + getResources().getDimension( R.dimen.chart_frag_trad_inner_axis_height) ); float relYPos = newYPos / _rightPanel.getMeasuredHeight(); if(relYPos < .50f) relYPos = .50f; if(relYPos > 1.0f) relYPos = 1.0f; for( TraditionalChartFragment tmp = (TraditionalChartFragment)getTopOfStack() ; tmp != null; tmp = (TraditionalChartFragment)tmp.getLastLinkOfStack() ){ _setRelativePanelWeights( relYPos * 10, (1-relYPos)*10 ); } div.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, (int) (_xAxis.getMeasuredHeight() + getResources().getDimension( R.dimen.chart_frag_trad_inner_axis_height) ) ) ); upper.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, 0, _pricePnlWght ) ); lower.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, 0, TTL_PNL_WGHT - _pricePnlWght ) ); mainOverlay.invalidate(); } hasMoved = false; } return true; } } } }