Android Open Source - makler Graph View






From Project

Back to project page makler.

License

The source code is released under:

GNU General Public License

If you think the Android project makler 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 pl.net.newton.Makler.ui.graph;
// w w  w  .  j a  v  a2 s . com
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.Executors;

import org.achartengine.GraphicalView;
import org.achartengine.chart.BarChart;
import org.achartengine.chart.BarChart.Type;
import org.achartengine.chart.LineChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import pl.net.newton.Makler.R;
import pl.net.newton.Makler.db.quote.Quote;
import pl.net.newton.Makler.db.quote.QuoteField;
import pl.net.newton.Makler.db.symbol.Symbol;
import pl.net.newton.Makler.db.symbol.SymbolsDb;
import pl.net.newton.Makler.history.EntryListWithIndexes;
import pl.net.newton.Makler.history.HistoryFilter;
import pl.net.newton.Makler.history.service.HistoryService;
import pl.net.newton.Makler.ui.FullScreenGraph;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint.Align;
import android.os.Handler;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

@SuppressLint("ViewConstructor")
public class GraphView extends LinearLayout implements OnGestureListener, OnTouchListener {

  private static final String DD_MM = "dd.MM";

  private static final String MM_YYYY = "MM.yyyy";

  public static final class GraphRange {
    // One day
    static final int D1 = 0;

    // Five day
    static final int D5 = 1;

    // One Month
    static final int M1 = 2;

    // Three months
    static final int M3 = 3;

    // One year
    static final int Y1 = 4;

    // Two years
    static final int Y2 = 5;

    // All
    static final int ALL = 6;

    private GraphRange() {
    }
  }

  private int graphRange, newGraphRange;

  private int graphType = 0, newGraphType;

  private AlertDialog dialog;

  private Quote quote;

  private Handler mHandler;

  private HistoryService historyService;

  private SymbolsDb symbolsDb;

  private Context context;

  private Spinner rangeSpinner;

  /**
   * add gesture support for GraphView
   */
  private GestureDetector gestureDetector = null;

  private MaklerGraphicalView graphView = null;

  private boolean interActiveMode = false;

  private static final int GRAPH_SWIPE_MIN_DISTANCE = 60;

  private static final int GRAPH_SWIPE_THRESHOLD_VELOCITY = 200;

  private static final String TAG = "Makler";

  public GraphView(Context context, Quote quote, Handler mHandler, HistoryService historyService,
      SymbolsDb symbolsDb) {

    super(context);

    this.quote = quote;
    this.mHandler = mHandler;
    this.historyService = historyService;
    this.symbolsDb = symbolsDb;
    this.context = context;

    graphRange = GraphRange.D1;

    gestureDetector = new GestureDetector(context, this);

    setOnTouchListener(this);

    setFocusable(true);
    setFocusableInTouchMode(true);

    setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    setOrientation(LinearLayout.VERTICAL);
    prepareDialog();
  }

  public void setGraphRange(int newGraphRange) {
    int graphRangeToSet = newGraphRange;
    if (newGraphRange > GraphRange.ALL) {
      graphRangeToSet = GraphRange.D1;
    } else if (newGraphRange < GraphRange.D1) {
      graphRangeToSet = GraphRange.ALL;
    }
    this.graphRange = graphRangeToSet;
    mHandler.post(new Runnable() {
      public void run() {
        rangeSpinner.setSelection(GraphView.this.graphRange);
      }
    });
  }

  public void setGraphType(int graphType) {
    this.graphType = graphType;
  }

  public int getGraphRange() {
    return this.graphRange;
  }

  public int getGraphType() {
    return this.graphType;
  }

  public void refreshGraph(boolean force) {
    Symbol symbol = symbolsDb.getSymbolBySymbol(quote.get(QuoteField.SYMBOL));

    try {
      if (!historyService.isRangeExist(symbol, graphRange)) {
        showSpinner();
      }
      historyService.historyByInt(graphRange, symbol, force);
    } catch (NullPointerException e) {
      Log.e(TAG, "npe during refreshing graph", e);
    }
  }

  public void gotEntries(final EntryListWithIndexes entries) {
    Executors.newSingleThreadExecutor().execute(new Runnable() {
      public void run() {
        final LineChart xyChart = buildGraphView(entries);
        final BarChart volChart = buildVolGraphView(entries);

        mHandler.post(new Runnable() {
          public void run() {
            drawChart(entries, xyChart, volChart);
          }
        });
      }
    });
  }

  private BarChart buildVolGraphView(EntryListWithIndexes entries) {
    if (entries == null || entries.getLength() == 0) {
      return null;
    }

    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
    XYSeries series = new XYSeries("Wolumen");
    for (int i = 0; i < entries.getLength(); i++) {
      series.add(entries.getGraphIndex(i), entries.getVol(i));
    }

    dataset.addSeries(series);

    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
    renderer.setMargins(new int[] { 0, 0, 0, 0 });
    renderer.setAxesColor(Color.DKGRAY);
    renderer.setShowCustomTextGrid(false);
    renderer.setShowLabels(false);
    renderer.setShowGrid(false);
    renderer.setShowLegend(false);
    renderer.setShowAxes(true);
    renderer.setXLabels(0);
    renderer.setYLabels(6);

    if (graphRange == GraphRange.D1) {
      renderer.setXAxisMax(HistoryFilter.MINUTES_IN_DAY);
    }

    SimpleSeriesRenderer r = new SimpleSeriesRenderer();
    r.setColor(Color.rgb(0xCC, 0x33, 0x00));
    renderer.addSeriesRenderer(r);

    return new BarChart(dataset, renderer, Type.STACKED);
  }

  private void drawChart(final EntryListWithIndexes entries, final LineChart xyChart,
      final BarChart volChart) {
    if (xyChart != null && volChart != null) {

      removeAllViews();

      graphView = new MaklerGraphicalView(context, xyChart, entries, quote, graphRange);
      GraphicalView graphViewVol = new GraphicalView(context, volChart);

      addView(graphView);
      addView(graphViewVol);

      LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) graphView.getLayoutParams();
      params.weight = 0.1f;
      graphView.setLayoutParams(params);

      params = (LinearLayout.LayoutParams) graphViewVol.getLayoutParams();
      params.weight = 0.9f;
      graphViewVol.setLayoutParams(params);
    } else {
      removeAllViews();
      TextView errorView = new TextView(context);
      errorView.setText(context.getString(R.string.graph_error_when_downloading));
      errorView.setGravity(Gravity.CENTER);
      errorView.setPadding(0, 20, 0, 0);

      addView(errorView);
    }
  }

  private LineChart buildGraphView(EntryListWithIndexes entries) {
    if (entries == null || entries.getLength() == 0) {
      return null;
    }

    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
    XYSeries series = new XYSeries(quote.get(QuoteField.SYMBOL));
    double min = Double.MAX_VALUE, max = -1;
    for (int i = 0; i < entries.getLength(); i++) {
      double value = ((double) entries.getClose(i)) / 100;
      series.add(entries.getGraphIndex(i), value);
      min = Math.min(value, min);
      max = Math.max(value, max);
    }
    dataset.addSeries(series);

    boolean kursOdn = false;
    if (displayReferenceQuote()) {
      double kursOdnDouble = quote.getAsDecimal(QuoteField.REFERENCE).doubleValue();
      series = new XYSeries("Kurs odn.");
      series.add(0, kursOdnDouble);
      series.add(HistoryFilter.MINUTES_IN_DAY, kursOdnDouble);
      dataset.addSeries(series);
      kursOdn = true;

      min = Math.min(kursOdnDouble, min);
      max = Math.max(kursOdnDouble, max);
    }

    XYMultipleSeriesRenderer renderer = getRenderer(entries, kursOdn, min, max);
    return new LineChart(dataset, renderer);
  }

  private void renderLabels(EntryListWithIndexes entries, XYMultipleSeriesRenderer renderer) {
    switch (graphRange) {
      case GraphRange.D1:
        addDailyLabels(renderer);
        renderer.setChartTitle(context.getString(R.string.d1));
        break;
      case GraphRange.D5:
        addLabels(5, entries, renderer, DD_MM);
        renderer.setChartTitle(context.getString(R.string.d5));
        break;
      case GraphRange.M1:
        addLabels(6, entries, renderer, DD_MM);
        renderer.setChartTitle(context.getString(R.string.m1));
        break;
      case GraphRange.M3:
        addLabels(7, entries, renderer, DD_MM);
        renderer.setChartTitle(context.getString(R.string.m3));
        break;
      case GraphRange.Y1:
        addLabels(6, entries, renderer, MM_YYYY);
        renderer.setChartTitle(context.getString(R.string.r1));
        break;
      case GraphRange.Y2:
        addLabels(6, entries, renderer, MM_YYYY);
        renderer.setChartTitle(context.getString(R.string.r2));
        break;
      case GraphRange.ALL:
        addLabels(6, entries, renderer, MM_YYYY);
        renderer.setChartTitle(context.getString(R.string.all));
        break;
      default:
        // do nothing
        break;
    }
  }

  private boolean displayReferenceQuote() {
    if (graphRange != GraphRange.D1) {
      return false;
    }
    if (quote == null || quote.get(QuoteField.REFERENCE) == null
        || quote.getAsDecimal(QuoteField.REFERENCE).compareTo(BigDecimal.ZERO) <= 0) {
      return false;
    }
    if (quote.get(QuoteField.UPDATED) == null
        || quote.getAsCalendar(QuoteField.UPDATED).get(Calendar.HOUR_OF_DAY) < 9) {
      return false;
    }
    return true;
  }

  private XYMultipleSeriesRenderer getRenderer(EntryListWithIndexes entries, boolean kursOdn, double min,
      double max) {
    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
    if (graphRange == GraphRange.D1) {
      renderer.setXAxisMax(HistoryFilter.MINUTES_IN_DAY);
    }

    renderer.setAxisTitleTextSize(16);
    renderer.setChartTitleTextSize(20);
    renderer.setLabelsTextSize(15);
    renderer.setMargins(new int[] { 0, 0, 0, 0 });
    renderer.setAxesColor(Color.DKGRAY);
    renderer.setLabelsColor(Color.LTGRAY);
    renderer.setShowLabels(true);
    renderer.setShowCustomTextGrid(true);
    renderer.setXLabels(0);
    renderer.setXLabelsAlign(Align.LEFT);
    renderer.setYLabels(10);
    renderer.setYLabelsAlign(Align.LEFT);
    renderer.setShowGrid(true);
    renderer.setShowLegend(false);

    XYSeriesRenderer r = new XYSeriesRenderer();
    r.setColor(Color.rgb(0x00, 0x99, 0xCC));
    r.setLineWidth(2);
    renderer.addSeriesRenderer(r);

    if (kursOdn) {
      r = new XYSeriesRenderer();
      r.setColor(Color.rgb(0xFF, 0xAA, 0x56));
      r.setLineWidth(1);
      renderer.addSeriesRenderer(r);
    }

    renderer.setZoomEnabled(false);
    renderer.setZoomEnabled(false, false);
    renderer.setPanEnabled(false);
    renderer.setPanEnabled(false, false);
    renderer.setClickEnabled(false);
    renderer.setYAxisMax(max);
    renderer.setYAxisMin(min);

    if (graphRange == GraphRange.D1) {
      renderer.setXAxisMax(HistoryFilter.MINUTES_IN_DAY);
    } else {
      renderer.setXAxisMax(entries.getGraphIndex(entries.getLength() - 1));
    }
    renderer.setXAxisMin(entries.getGraphIndex(0));
    renderLabels(entries, renderer);

    return renderer;
  }

  private void addDailyLabels(XYMultipleSeriesRenderer renderer) {
    for (int i = 0; i <= 8; i++) {
      renderer.addXTextLabel(i * 60, String.format("%02d", 9 + i));
    }
  }

  private void addLabels(int labels, EntryListWithIndexes entries, XYMultipleSeriesRenderer renderer,
      String format) {
    int lastDay = -1;
    List<Calendar> days = new ArrayList<Calendar>();
    List<Integer> daysIndexes = new ArrayList<Integer>();
    for (int i = 0; i < entries.getLength(); i++) {
      Calendar d = Calendar.getInstance();
      d.setTimeInMillis(entries.getDate(i));
      int value = entries.getGraphIndex(i);
      if (d.get(Calendar.DATE) != lastDay) {
        lastDay = d.get(Calendar.DATE);
        days.add(d);
        daysIndexes.add(value);
      }
    }

    int cappedLabels = labels;
    if (cappedLabels > days.size()) {
      cappedLabels = days.size();
    }
    if (cappedLabels == 0) {
      return;
    }

    DateFormat sdf = new SimpleDateFormat(format, Locale.US);
    int d = days.size() / cappedLabels;
    for (int i = 0; i < cappedLabels; i++) {
      int j = i * d;
      renderer.addXTextLabel(daysIndexes.get(j), sdf.format(days.get(j)));
    }
  }

  private void showSpinner() {
    mHandler.post(new Runnable() {
      public void run() {
        doShowSpinner();
      }
    });
  }

  private void doShowSpinner() {
    RelativeLayout layout = new RelativeLayout(context);

    removeAllViews();

    addView(layout);

    LayoutParams params = (LayoutParams) layout.getLayoutParams();
    params.width = LayoutParams.MATCH_PARENT;
    params.height = LayoutParams.MATCH_PARENT;
    layout.setLayoutParams(params);

    ProgressBar spinner = new ProgressBar(context);
    layout.addView(spinner);
    spinner.setIndeterminate(true);
    RelativeLayout.LayoutParams spinnerParams = (android.widget.RelativeLayout.LayoutParams) spinner
        .getLayoutParams();
    spinnerParams.width = LayoutParams.WRAP_CONTENT;
    spinnerParams.height = LayoutParams.WRAP_CONTENT;
    spinnerParams.addRule(RelativeLayout.CENTER_IN_PARENT, -1);
    spinner.setLayoutParams(spinnerParams);
  }

  /**
   * Prze??cz wykres na nast?pny zakres.
   */
  public void switchToNextRage() {
    setGraphRange(graphRange + 1);

    refreshGraph(false);
  }

  /**
   * Prze??cz wykres na poprzedni zakres.
   */
  public void switchToPreviousRage() {

    setGraphRange(graphRange - 1);

    refreshGraph(false);
  }

  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    boolean detected = false;

    if (Math.abs(velocityX) > GRAPH_SWIPE_THRESHOLD_VELOCITY) {
      if (e1.getX() - e2.getX() > GRAPH_SWIPE_MIN_DISTANCE) {
        switchToNextRage();
        detected = true;
      } else if (e2.getX() - e1.getX() > GRAPH_SWIPE_MIN_DISTANCE) {
        switchToPreviousRage();
        detected = true;
      }
    }

    return detected;
  }

  public void onLongPress(MotionEvent e) {
    if (!interActiveMode) {
      Toast.makeText(getContext(), context.getString(R.string.graph_interactive_mode_on),
          Toast.LENGTH_LONG).show();
    } else {
      Toast.makeText(getContext(), context.getString(R.string.graph_interactive_mode_off),
          Toast.LENGTH_LONG).show();
    }

    interActiveMode = !interActiveMode;
  }

  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    return false;
  }

  @Override
  public void onShowPress(MotionEvent e) {
    // do nothing
  }

  @Override
  public boolean onDown(MotionEvent e) {
    return true;
  }

  @Override
  public boolean onSingleTapUp(MotionEvent e) {
    // don't allow to start full screen graph in FullScreenGraph activity
    if (context instanceof FullScreenGraph) {
      return false;
    }

    Intent intent = new Intent(context, FullScreenGraph.class);
    intent.putExtra("symbol", quote.get(QuoteField.SYMBOL));
    intent.putExtra("graphRange", getGraphRange());
    intent.putExtra("graphType", getGraphType());
    context.startActivity(intent);

    return true;
  }

  public boolean onTouch(View v, MotionEvent event) {
    // If GraphView was already created then forward MontionEvents.
    if (graphView != null) {
      graphView.onTouchEvent(event);
    }

    return gestureDetector.onTouchEvent(event);
  }

  public void prepareDialog() {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View layout = inflater.inflate(R.layout.graph_dialog, null);

    rangeSpinner = (Spinner) layout.findViewById(R.id.graphRange);
    rangeSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
      public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        newGraphRange = arg2;
      }

      public void onNothingSelected(AdapterView<?> arg0) {
        newGraphRange = 0;
      }
    });

    dialog = new AlertDialog.Builder(context).setTitle("Wybierz zakres danych").setView(layout)
        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int whichButton) {
            if (newGraphRange != graphRange || graphType != newGraphType) {
              graphRange = newGraphRange;
              graphType = newGraphType;
              refreshGraph(false);
            }
          }
        }).create();
  }

  public void changeGraphRange() {
    mHandler.post(new Runnable() {
      public void run() {
        dialog.show();
      }
    });
  }
}




Java Source Code List

pl.net.newton.Makler.common.Configuration.java
pl.net.newton.Makler.common.DateFormatUtils.java
pl.net.newton.Makler.common.GpwUtils.java
pl.net.newton.Makler.common.LocaleUtils.java
pl.net.newton.Makler.common.NumberFormatUtils.java
pl.net.newton.Makler.db.Constants.java
pl.net.newton.Makler.db.DbHelper.java
pl.net.newton.Makler.db.SqlConnection.java
pl.net.newton.Makler.db.alert.AlertBuilder.java
pl.net.newton.Makler.db.alert.AlertChecker.java
pl.net.newton.Makler.db.alert.AlertValue.java
pl.net.newton.Makler.db.alert.Alert.java
pl.net.newton.Makler.db.alert.AlertsDao.java
pl.net.newton.Makler.db.alert.Event.java
pl.net.newton.Makler.db.alert.Subject.java
pl.net.newton.Makler.db.quote.QuoteField.java
pl.net.newton.Makler.db.quote.Quote.java
pl.net.newton.Makler.db.quote.QuotesDao.java
pl.net.newton.Makler.db.service.SqlProvider.java
pl.net.newton.Makler.db.symbol.SymbolBuilder.java
pl.net.newton.Makler.db.symbol.Symbol.java
pl.net.newton.Makler.db.symbol.SymbolsDb.java
pl.net.newton.Makler.db.wallet.WalletDb.java
pl.net.newton.Makler.db.wallet.WalletItemBuilder.java
pl.net.newton.Makler.db.wallet.WalletItem.java
pl.net.newton.Makler.gpw.DefaultQuotesReceiver.java
pl.net.newton.Makler.gpw.QuotesReceiver.java
pl.net.newton.Makler.gpw.ex.GpwException.java
pl.net.newton.Makler.gpw.service.QuotesListener.java
pl.net.newton.Makler.gpw.service.QuotesService.java
pl.net.newton.Makler.gpw.service.UpdatingThread.java
pl.net.newton.Makler.history.BossaProvider.java
pl.net.newton.Makler.history.ByteArrayUtils.java
pl.net.newton.Makler.history.Cache.java
pl.net.newton.Makler.history.ChannelTools.java
pl.net.newton.Makler.history.EntryListWithIndexes.java
pl.net.newton.Makler.history.EntryList.java
pl.net.newton.Makler.history.HistoryFilter.java
pl.net.newton.Makler.history.HistoryProvider.java
pl.net.newton.Makler.history.service.HistoryListener.java
pl.net.newton.Makler.history.service.HistoryService.java
pl.net.newton.Makler.httpClient.Connector.java
pl.net.newton.Makler.receivers.QuotesAlarmReceiver.java
pl.net.newton.Makler.receivers.StartupReceiver.java
pl.net.newton.Makler.service.ServiceManager.java
pl.net.newton.Makler.ui.About.java
pl.net.newton.Makler.ui.AbstractActivity.java
pl.net.newton.Makler.ui.Alerts.java
pl.net.newton.Makler.ui.FullScreenGraph.java
pl.net.newton.Makler.ui.Preferences.java
pl.net.newton.Makler.ui.QuoteDetails.java
pl.net.newton.Makler.ui.Quotes.java
pl.net.newton.Makler.ui.Symbols.java
pl.net.newton.Makler.ui.WalletForm.java
pl.net.newton.Makler.ui.WalletItemCalculator.java
pl.net.newton.Makler.ui.Wallet.java
pl.net.newton.Makler.ui.adapter.AlertsAdapter.java
pl.net.newton.Makler.ui.adapter.QuotesAdapter.java
pl.net.newton.Makler.ui.adapter.SymbolsAdapter.java
pl.net.newton.Makler.ui.adapter.WalletAdapter.java
pl.net.newton.Makler.ui.graph.GraphView.java
pl.net.newton.Makler.ui.graph.MaklerGraphicalView.java