use of com.jjoe64.graphview.series.Series in project GraphView by appsthatmatter.
the class GraphView method drawGraphElements.
/**
* draw all the stuff on canvas
*
* @param canvas
*/
protected void drawGraphElements(Canvas canvas) {
// must be in hardware accelerated mode
if (android.os.Build.VERSION.SDK_INT >= 11 && !canvas.isHardwareAccelerated()) {
// just warn about it, because it is ok when making a snapshot
Log.w("GraphView", "GraphView should be used in hardware accelerated mode." + "You can use android:hardwareAccelerated=\"true\" on your activity. Read this for more info:" + "https://developer.android.com/guide/topics/graphics/hardware-accel.html");
}
drawTitle(canvas);
mViewport.drawFirst(canvas);
mGridLabelRenderer.draw(canvas);
for (Series s : mSeries) {
s.draw(this, canvas, false);
}
if (mSecondScale != null) {
for (Series s : mSecondScale.getSeries()) {
s.draw(this, canvas, true);
}
}
if (mCursorMode != null) {
mCursorMode.draw(canvas);
}
mViewport.draw(canvas);
mLegendRenderer.draw(canvas);
}
use of com.jjoe64.graphview.series.Series in project GraphView by appsthatmatter.
the class LegendRenderer method draw.
/**
* draws the legend if it is visible
*
* @param canvas canvas
* @see #setVisible(boolean)
*/
public void draw(Canvas canvas) {
if (!mIsVisible)
return;
mPaint.setTextSize(mStyles.textSize);
int shapeSize = (int) (mStyles.textSize * 0.8d);
List<Series> allSeries = new ArrayList<Series>();
allSeries.addAll(mGraphView.getSeries());
if (mGraphView.mSecondScale != null) {
allSeries.addAll(mGraphView.getSecondScale().getSeries());
}
// width
int legendWidth = mStyles.width;
if (legendWidth == 0) {
// auto
legendWidth = cachedLegendWidth;
if (legendWidth == 0) {
Rect textBounds = new Rect();
for (Series s : allSeries) {
if (s.getTitle() != null) {
mPaint.getTextBounds(s.getTitle(), 0, s.getTitle().length(), textBounds);
legendWidth = Math.max(legendWidth, textBounds.width());
}
}
if (legendWidth == 0)
legendWidth = 1;
// add shape size
legendWidth += shapeSize + mStyles.padding * 2 + mStyles.spacing;
cachedLegendWidth = legendWidth;
}
}
// rect
float legendHeight = (mStyles.textSize + mStyles.spacing) * allSeries.size() - mStyles.spacing;
float lLeft;
float lTop;
if (mStyles.fixedPosition != null) {
// use fied position
lLeft = mGraphView.getGraphContentLeft() + mStyles.margin + mStyles.fixedPosition.x;
lTop = mGraphView.getGraphContentTop() + mStyles.margin + mStyles.fixedPosition.y;
} else {
lLeft = mGraphView.getGraphContentLeft() + mGraphView.getGraphContentWidth() - legendWidth - mStyles.margin;
switch(mStyles.align) {
case TOP:
lTop = mGraphView.getGraphContentTop() + mStyles.margin;
break;
case MIDDLE:
lTop = mGraphView.getHeight() / 2 - legendHeight / 2;
break;
default:
lTop = mGraphView.getGraphContentTop() + mGraphView.getGraphContentHeight() - mStyles.margin - legendHeight - 2 * mStyles.padding;
}
}
float lRight = lLeft + legendWidth;
float lBottom = lTop + legendHeight + 2 * mStyles.padding;
mPaint.setColor(mStyles.backgroundColor);
canvas.drawRoundRect(new RectF(lLeft, lTop, lRight, lBottom), 8, 8, mPaint);
int i = 0;
for (Series series : allSeries) {
mPaint.setColor(series.getColor());
canvas.drawRect(new RectF(lLeft + mStyles.padding, lTop + mStyles.padding + (i * (mStyles.textSize + mStyles.spacing)), lLeft + mStyles.padding + shapeSize, lTop + mStyles.padding + (i * (mStyles.textSize + mStyles.spacing)) + shapeSize), mPaint);
if (series.getTitle() != null) {
mPaint.setColor(mStyles.textColor);
canvas.drawText(series.getTitle(), lLeft + mStyles.padding + shapeSize + mStyles.spacing, lTop + mStyles.padding + mStyles.textSize + (i * (mStyles.textSize + mStyles.spacing)), mPaint);
}
i++;
}
}
use of com.jjoe64.graphview.series.Series in project GraphView by appsthatmatter.
the class Viewport method calcCompleteRange.
/**
* caches the complete range (minX, maxX, minY, maxY)
* by iterating all series and all datapoints and
* stores it into #mCompleteRange
*
* for the x-range it will respect the series on the
* second scale - not for y-values
*/
public void calcCompleteRange() {
List<Series> series = mGraphView.getSeries();
List<Series> seriesInclusiveSecondScale = new ArrayList<>(mGraphView.getSeries());
if (mGraphView.mSecondScale != null) {
seriesInclusiveSecondScale.addAll(mGraphView.mSecondScale.getSeries());
}
mCompleteRange.set(0d, 0d, 0d, 0d);
if (!seriesInclusiveSecondScale.isEmpty() && !seriesInclusiveSecondScale.get(0).isEmpty()) {
double d = seriesInclusiveSecondScale.get(0).getLowestValueX();
for (Series s : seriesInclusiveSecondScale) {
if (!s.isEmpty() && d > s.getLowestValueX()) {
d = s.getLowestValueX();
}
}
mCompleteRange.left = d;
d = seriesInclusiveSecondScale.get(0).getHighestValueX();
for (Series s : seriesInclusiveSecondScale) {
if (!s.isEmpty() && d < s.getHighestValueX()) {
d = s.getHighestValueX();
}
}
mCompleteRange.right = d;
if (!series.isEmpty() && !series.get(0).isEmpty()) {
d = series.get(0).getLowestValueY();
for (Series s : series) {
if (!s.isEmpty() && d > s.getLowestValueY()) {
d = s.getLowestValueY();
}
}
mCompleteRange.bottom = d;
d = series.get(0).getHighestValueY();
for (Series s : series) {
if (!s.isEmpty() && d < s.getHighestValueY()) {
d = s.getHighestValueY();
}
}
mCompleteRange.top = d;
}
}
// calc current viewport bounds
if (mYAxisBoundsStatus == AxisBoundsStatus.AUTO_ADJUSTED) {
mYAxisBoundsStatus = AxisBoundsStatus.INITIAL;
}
if (mYAxisBoundsStatus == AxisBoundsStatus.INITIAL) {
mCurrentViewport.top = mCompleteRange.top;
mCurrentViewport.bottom = mCompleteRange.bottom;
}
if (mXAxisBoundsStatus == AxisBoundsStatus.AUTO_ADJUSTED) {
mXAxisBoundsStatus = AxisBoundsStatus.INITIAL;
}
if (mXAxisBoundsStatus == AxisBoundsStatus.INITIAL) {
mCurrentViewport.left = mCompleteRange.left;
mCurrentViewport.right = mCompleteRange.right;
} else if (mXAxisBoundsManual && !mYAxisBoundsManual && mCompleteRange.width() != 0) {
// get highest/lowest of current viewport
// lowest
double d = Double.MAX_VALUE;
for (Series s : series) {
Iterator<DataPointInterface> values = s.getValues(mCurrentViewport.left, mCurrentViewport.right);
while (values.hasNext()) {
double v = values.next().getY();
if (d > v) {
d = v;
}
}
}
if (d != Double.MAX_VALUE) {
mCurrentViewport.bottom = d;
}
// highest
d = Double.MIN_VALUE;
for (Series s : series) {
Iterator<DataPointInterface> values = s.getValues(mCurrentViewport.left, mCurrentViewport.right);
while (values.hasNext()) {
double v = values.next().getY();
if (d < v) {
d = v;
}
}
}
if (d != Double.MIN_VALUE) {
mCurrentViewport.top = d;
}
}
// fixes blank screen when range is zero
if (mCurrentViewport.left == mCurrentViewport.right)
mCurrentViewport.right++;
if (mCurrentViewport.top == mCurrentViewport.bottom)
mCurrentViewport.top++;
}
use of com.jjoe64.graphview.series.Series in project GraphView by appsthatmatter.
the class BarGraphSeries method draw.
/**
* draws the bars on the canvas
*
* @param graphView corresponding graphview
* @param canvas canvas
* @param isSecondScale whether we are plotting the second scale or not
*/
@Override
public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) {
mPaint.setTextAlign(Paint.Align.CENTER);
if (mValuesOnTopSize == 0) {
mValuesOnTopSize = graphView.getGridLabelRenderer().getTextSize();
}
mPaint.setTextSize(mValuesOnTopSize);
resetDataPoints();
// get data
double maxX = graphView.getViewport().getMaxX(false);
double minX = graphView.getViewport().getMinX(false);
double maxY;
double minY;
if (isSecondScale) {
maxY = graphView.getSecondScale().getMaxY(false);
minY = graphView.getSecondScale().getMinY(false);
} else {
maxY = graphView.getViewport().getMaxY(false);
minY = graphView.getViewport().getMinY(false);
}
// Iterate through all bar graph series
// so we know how wide to make our bar,
// and in what position to put it in
int numBarSeries = 0;
int currentSeriesOrder = 0;
int numValues = 0;
boolean isCurrentSeries;
SortedSet<Double> xVals = new TreeSet<Double>();
for (Series inspectedSeries : graphView.getSeries()) {
if (inspectedSeries instanceof BarGraphSeries) {
isCurrentSeries = (inspectedSeries == this);
if (isCurrentSeries) {
currentSeriesOrder = numBarSeries;
}
numBarSeries++;
// calculate the number of slots for bars based on the minimum distance between
// x coordinates in the series. This is divided into the range to find
// the placement and width of bar slots
// (sections of the x axis for each bar or set of bars)
// TODO: Move this somewhere more general and cache it, so we don't recalculate it for each series
Iterator<E> curValues = inspectedSeries.getValues(minX, maxX);
if (curValues.hasNext()) {
xVals.add(curValues.next().getX());
if (isCurrentSeries) {
numValues++;
}
while (curValues.hasNext()) {
xVals.add(curValues.next().getX());
if (isCurrentSeries) {
numValues++;
}
}
}
}
}
if (numValues == 0) {
return;
}
double minGap = 0;
if (mDataWidth > 0.0) {
minGap = mDataWidth;
} else {
Double lastVal = null;
for (Double curVal : xVals) {
if (lastVal != null) {
double curGap = Math.abs(curVal - lastVal);
if (minGap == 0 || (curGap > 0 && curGap < minGap)) {
minGap = curGap;
}
}
lastVal = curVal;
}
}
int numBarSlots = (minGap == 0) ? 1 : (int) Math.round((maxX - minX) / minGap) + 1;
Iterator<E> values = getValues(minX, maxX);
// Calculate the overall bar slot width - this includes all bars across
// all series, and any spacing between sets of bars
int barSlotWidth = numBarSlots == 1 ? graphView.getGraphContentWidth() : graphView.getGraphContentWidth() / (numBarSlots - 1);
// Total spacing (both sides) between sets of bars
double spacing = Math.min(barSlotWidth * mSpacing / 100, barSlotWidth * 0.98f);
// Width of an individual bar
double barWidth = (barSlotWidth - spacing) / numBarSeries;
// Offset from the center of a given bar to start drawing
double offset = barSlotWidth / 2;
double diffY = maxY - minY;
double diffX = maxX - minX;
double contentHeight = graphView.getGraphContentHeight();
double contentWidth = graphView.getGraphContentWidth();
double contentLeft = graphView.getGraphContentLeft();
double contentTop = graphView.getGraphContentTop();
// draw data
int i = 0;
while (values.hasNext()) {
E value = values.next();
double valY = value.getY() - minY;
double ratY = valY / diffY;
double y = contentHeight * ratY;
double valY0 = 0 - minY;
double ratY0 = valY0 / diffY;
double y0 = contentHeight * ratY0;
double valueX = value.getX();
double valX = valueX - minX;
double ratX = valX / diffX;
double x = contentWidth * ratX;
// hook for value dependent color
if (getValueDependentColor() != null) {
mPaint.setColor(getValueDependentColor().get(value));
} else {
mPaint.setColor(getColor());
}
double left = x + contentLeft - offset + spacing / 2 + currentSeriesOrder * barWidth;
double top = (contentTop - y) + contentHeight;
double right = left + barWidth;
double bottom = (contentTop - y0) + contentHeight - (graphView.getGridLabelRenderer().isHighlightZeroLines() ? 4 : 1);
boolean reverse = top > bottom;
if (mAnimated) {
if ((Double.isNaN(mLastAnimatedValue) || mLastAnimatedValue < valueX)) {
long currentTime = System.currentTimeMillis();
if (mAnimationStart == 0) {
// start animation
mAnimationStart = currentTime;
mAnimationStartFrameNo = 0;
} else {
// anti-lag: wait a few frames
if (mAnimationStartFrameNo < 15) {
// second time
mAnimationStart = currentTime;
mAnimationStartFrameNo++;
}
}
float timeFactor = (float) (currentTime - mAnimationStart) / ANIMATION_DURATION;
float factor = mAnimationInterpolator.getInterpolation(timeFactor);
if (timeFactor <= 1.0) {
double barHeight = bottom - top;
barHeight = barHeight * factor;
top = bottom - barHeight;
ViewCompat.postInvalidateOnAnimation(graphView);
} else {
// animation finished
mLastAnimatedValue = valueX;
}
}
}
if (reverse) {
double tmp = top;
top = bottom + (graphView.getGridLabelRenderer().isHighlightZeroLines() ? 4 : 1);
bottom = tmp;
}
// overdraw
left = Math.max(left, contentLeft);
right = Math.min(right, contentLeft + contentWidth);
bottom = Math.min(bottom, contentTop + contentHeight);
top = Math.max(top, contentTop);
mDataPoints.put(new RectD(left, top, right, bottom), value);
Paint p;
if (mCustomPaint != null) {
p = mCustomPaint;
} else {
p = mPaint;
}
canvas.drawRect((float) left, (float) top, (float) right, (float) bottom, p);
// set values on top of graph
if (mDrawValuesOnTop) {
if (reverse) {
top = bottom + mValuesOnTopSize + 4;
if (top > contentTop + contentHeight)
top = contentTop + contentHeight;
} else {
top -= 4;
if (top <= contentTop)
top += contentTop + 4;
}
mPaint.setColor(mValuesOnTopColor);
canvas.drawText(graphView.getGridLabelRenderer().getLabelFormatter().formatLabel(value.getY(), false), (float) (left + right) / 2, (float) top, mPaint);
}
i++;
}
}
use of com.jjoe64.graphview.series.Series in project WordPress-Android by wordpress-mobile.
the class StatsVisitorsAndViewsFragment method updateUI.
protected void updateUI() {
if (!isAdded()) {
return;
}
if (mVisitsData == null) {
setupNoResultsUI(false);
return;
}
final VisitModel[] dataToShowOnGraph = getDataToShowOnGraph(mVisitsData);
if (dataToShowOnGraph == null || dataToShowOnGraph.length == 0) {
setupNoResultsUI(false);
return;
}
// Hide the "no-activity this period" message
mNoActivtyThisPeriodContainer.setVisibility(View.GONE);
// Read the selected Tab in the UI
OverviewLabel selectedStatsType = overviewItems[mSelectedOverviewItemIndex];
// Update the Legend and enable/disable the visitors checkboxes
mLegendContainer.setVisibility(View.VISIBLE);
mLegendLabel.setText(StringUtils.capitalize(selectedStatsType.getLabel().toLowerCase()));
switch(selectedStatsType) {
case VIEWS:
mVisitorsCheckboxContainer.setVisibility(View.VISIBLE);
mVisitorsCheckbox.setEnabled(true);
mVisitorsCheckbox.setChecked(mIsCheckboxChecked);
break;
default:
mVisitorsCheckboxContainer.setVisibility(View.GONE);
break;
}
// Setting Up labels and prepare variables that hold series
final String[] horLabels = new String[dataToShowOnGraph.length];
mStatsDate = new String[dataToShowOnGraph.length];
GraphView.GraphViewData[] mainSeriesItems = new GraphView.GraphViewData[dataToShowOnGraph.length];
GraphView.GraphViewData[] secondarySeriesItems = null;
if (mIsCheckboxChecked && selectedStatsType == OverviewLabel.VIEWS) {
secondarySeriesItems = new GraphView.GraphViewData[dataToShowOnGraph.length];
}
// index of days that should be XXX on the graph
final boolean[] weekendDays;
if (getTimeframe() == StatsTimeframe.DAY) {
weekendDays = new boolean[dataToShowOnGraph.length];
} else {
weekendDays = null;
}
// Check we have at least one result in the current section.
boolean atLeastOneResultIsAvailable = false;
// Fill series variables with data
for (int i = 0; i < dataToShowOnGraph.length; i++) {
int currentItemValue = 0;
switch(selectedStatsType) {
case VIEWS:
currentItemValue = dataToShowOnGraph[i].getViews();
break;
case VISITORS:
currentItemValue = dataToShowOnGraph[i].getVisitors();
break;
case LIKES:
currentItemValue = dataToShowOnGraph[i].getLikes();
break;
case COMMENTS:
currentItemValue = dataToShowOnGraph[i].getComments();
break;
}
mainSeriesItems[i] = new GraphView.GraphViewData(i, currentItemValue);
if (currentItemValue > 0) {
atLeastOneResultIsAvailable = true;
}
if (mIsCheckboxChecked && secondarySeriesItems != null) {
secondarySeriesItems[i] = new GraphView.GraphViewData(i, dataToShowOnGraph[i].getVisitors());
}
String currentItemStatsDate = dataToShowOnGraph[i].getPeriod();
horLabels[i] = getDateLabelForBarInGraph(currentItemStatsDate);
mStatsDate[i] = currentItemStatsDate;
if (weekendDays != null) {
SimpleDateFormat from = new SimpleDateFormat(StatsConstants.STATS_INPUT_DATE_FORMAT);
try {
Date date = from.parse(currentItemStatsDate);
Calendar c = Calendar.getInstance();
c.setFirstDayOfWeek(Calendar.MONDAY);
c.setTimeInMillis(date.getTime());
weekendDays[i] = c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY || c.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY;
} catch (ParseException e) {
weekendDays[i] = false;
AppLog.e(AppLog.T.STATS, e);
}
}
}
if (mGraphContainer.getChildCount() >= 1 && mGraphContainer.getChildAt(0) instanceof GraphView) {
mGraphView = (StatsBarGraph) mGraphContainer.getChildAt(0);
} else {
mGraphContainer.removeAllViews();
mGraphView = new StatsBarGraph(getActivity());
mGraphContainer.addView(mGraphView);
}
mGraphView.removeAllSeries();
GraphViewSeries mainSeriesOnScreen = new GraphViewSeries(mainSeriesItems);
mainSeriesOnScreen.getStyle().color = getResources().getColor(R.color.stats_bar_graph_main_series);
mainSeriesOnScreen.getStyle().outerColor = getResources().getColor(R.color.grey_lighten_30_translucent_50);
mainSeriesOnScreen.getStyle().highlightColor = getResources().getColor(R.color.stats_bar_graph_main_series_highlight);
mainSeriesOnScreen.getStyle().outerhighlightColor = getResources().getColor(R.color.stats_bar_graph_outer_highlight);
mainSeriesOnScreen.getStyle().padding = DisplayUtils.dpToPx(getActivity(), 5);
mGraphView.addSeries(mainSeriesOnScreen);
// Add the Visitors series if it's checked in the legend
if (mIsCheckboxChecked && secondarySeriesItems != null && selectedStatsType == OverviewLabel.VIEWS) {
GraphViewSeries secondarySeries = new GraphViewSeries(secondarySeriesItems);
secondarySeries.getStyle().padding = DisplayUtils.dpToPx(getActivity(), 10);
secondarySeries.getStyle().color = getResources().getColor(R.color.stats_bar_graph_secondary_series);
secondarySeries.getStyle().highlightColor = getResources().getColor(R.color.orange_fire);
mGraphView.addSeries(secondarySeries);
}
// the purpose of making these bars visually easily to compare.
switch(selectedStatsType) {
case VISITORS:
double maxYValue = getMaxYValueForVisitorsAndView(dataToShowOnGraph);
mGraphView.setManualYAxisBounds(maxYValue, 0d);
break;
default:
mGraphView.setManualYAxis(false);
break;
}
// Set the Graph Style
mGraphView.getGraphViewStyle().setNumHorizontalLabels(dataToShowOnGraph.length);
// Set the maximum size a column can get on the screen in PX
mGraphView.getGraphViewStyle().setMaxColumnWidth(DisplayUtils.dpToPx(getActivity(), StatsConstants.STATS_GRAPH_BAR_MAX_COLUMN_WIDTH_DP));
mGraphView.setHorizontalLabels(horLabels);
mGraphView.setGestureListener(this);
// If zero results in the current section disable clicks on the graph and show the dialog.
mNoActivtyThisPeriodContainer.setVisibility(atLeastOneResultIsAvailable ? View.GONE : View.VISIBLE);
mGraphView.setClickable(atLeastOneResultIsAvailable);
// Draw the background on weekend days
mGraphView.setWeekendDays(weekendDays);
// Only happens on 720DP tablets
if (mPrevNumberOfBarsGraph != -1 && mPrevNumberOfBarsGraph != dataToShowOnGraph.length) {
mSelectedBarGraphBarIndex = -1;
mPrevNumberOfBarsGraph = dataToShowOnGraph.length;
onBarTapped(dataToShowOnGraph.length - 1);
mGraphView.highlightBar(dataToShowOnGraph.length - 1);
return;
}
mPrevNumberOfBarsGraph = dataToShowOnGraph.length;
int barSelectedOnGraph;
if (mSelectedBarGraphBarIndex == -1) {
// No previous bar was highlighted, highlight the most recent one
barSelectedOnGraph = dataToShowOnGraph.length - 1;
} else if (mSelectedBarGraphBarIndex < dataToShowOnGraph.length) {
barSelectedOnGraph = mSelectedBarGraphBarIndex;
} else {
// A previous bar was highlighted, but it's out of the screen now. This should never happen atm.
barSelectedOnGraph = dataToShowOnGraph.length - 1;
mSelectedBarGraphBarIndex = barSelectedOnGraph;
}
updateUIBelowTheGraph(barSelectedOnGraph);
mGraphView.highlightBar(barSelectedOnGraph);
}
Aggregations