Android Open Source - SpunkyCharts Traditional Chart Fragment






From Project

Back to project page SpunkyCharts.

License

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.

Java Source Code

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;
                }                
            }
        }
}




Java Source Code List

com.jogden.spunkycharts.ApplicationPreferences.java
com.jogden.spunkycharts.BaseChartFragmentA.java
com.jogden.spunkycharts.ChartPanelSurfaceView.java
com.jogden.spunkycharts.DockingPanelActivity.java
com.jogden.spunkycharts.GlobalChartPreferences.java
com.jogden.spunkycharts.InitActivity.java
com.jogden.spunkycharts.MainApplication.java
com.jogden.spunkycharts.OpeningView.java
com.jogden.spunkycharts.animations.BaseAnimationA.java
com.jogden.spunkycharts.animations.BaseEntExAnimationA.java
com.jogden.spunkycharts.animations.BaseSelectAnimationA.java
com.jogden.spunkycharts.animations.HorizontalBulgeAnimation.java
com.jogden.spunkycharts.animations.HorizontalShakeAnimation.java
com.jogden.spunkycharts.animations.VerticalBulgeAnimation.java
com.jogden.spunkycharts.animations.VerticalShakeAnimation.java
com.jogden.spunkycharts.animations.WiggleAnimation.java
com.jogden.spunkycharts.data.DataClientLocalDebug.java
com.jogden.spunkycharts.data.DataContentService.java
com.jogden.spunkycharts.misc.BorderOverlay.java
com.jogden.spunkycharts.misc.ColorPaletteDialog.java
com.jogden.spunkycharts.misc.HideHorizontalLeftOverflowWrapper.java
com.jogden.spunkycharts.misc.OHLC.java
com.jogden.spunkycharts.misc.Pair.java
com.jogden.spunkycharts.misc.TextInput.java
com.jogden.spunkycharts.misc.Triple.java
com.jogden.spunkycharts.pricebyvolumechart.PriceByVolumeChartFragmentAdapter.java
com.jogden.spunkycharts.pricebyvolumechart.PriceByVolumeChartFragment.java
com.jogden.spunkycharts.pricebyvolumechart.PriceByVolumeChartPanel.java
com.jogden.spunkycharts.pricebyvolumechart.PriceByVolumeChartPreferences.java
com.jogden.spunkycharts.pricebyvolumechart.draw.DrawSemanticsA.java
com.jogden.spunkycharts.pricebyvolumechart.draw.DrawSemantics_SILO.java
com.jogden.spunkycharts.traditionalchart.InnerXAxis.java
com.jogden.spunkycharts.traditionalchart.TraditionalChartFragmentAdapter.java
com.jogden.spunkycharts.traditionalchart.TraditionalChartFragment.java
com.jogden.spunkycharts.traditionalchart.TraditionalChartPanel.java
com.jogden.spunkycharts.traditionalchart.TraditionalChartPreferences.java
com.jogden.spunkycharts.traditionalchart.XAxisTimeLabel.java
com.jogden.spunkycharts.traditionalchart.YAxisPriceLabel.java
com.jogden.spunkycharts.traditionalchart.draw.DrawSemanticsA_C.java
com.jogden.spunkycharts.traditionalchart.draw.DrawSemanticsA.java
com.jogden.spunkycharts.traditionalchart.draw.DrawSemantics_CANDLE.java
com.jogden.spunkycharts.traditionalchart.draw.DrawSemantics_LINE.java
com.jogden.spunkycharts.traditionalchart.draw.DrawSemantics_OC.java
com.jogden.spunkycharts.traditionalchart.draw.DrawSemantics_OHLC.java
com.jogden.spunkycharts.traditionalchart.draw.DrawSemantics_POINT.java
com.jogden.spunkycharts.traditionalchart.draw.DrawSemantics_SILO.java