From d448f5c047e3e9ccdba6b768a3ee12341d54d7ef Mon Sep 17 00:00:00 2001 From: Nick Fellows Date: Fri, 4 Aug 2017 07:51:18 -0500 Subject: [PATCH 01/53] #55 Fixes PieRenderer.getContainingSegment for segments larger than 50% of the pie. (#57) --- .../java/com/androidplot/pie/PieRenderer.java | 38 ++++++++++------- .../com/androidplot/pie/PieRendererTest.java | 41 ++++++++++++++++++- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/androidplot-core/src/main/java/com/androidplot/pie/PieRenderer.java b/androidplot-core/src/main/java/com/androidplot/pie/PieRenderer.java index 8b663a82..dc83e620 100644 --- a/androidplot-core/src/main/java/com/androidplot/pie/PieRenderer.java +++ b/androidplot-core/src/main/java/com/androidplot/pie/PieRenderer.java @@ -30,11 +30,14 @@ */ public class PieRenderer extends SeriesRenderer { + private static final float FULL_PIE_DEGS = 360f; + private static final float HALF_PIE_DEGS = 180f; + // starting angle to use when drawing the first radial line of the first segment. private float startDegs = 0; // number of degrees to extend from startDegs; can be used to "shape" the pie chart. - private float extentDegs = 360; + private float extentDegs = FULL_PIE_DEGS; // TODO: express donut in units other than px. private float donutSize = 0.5f; @@ -240,7 +243,7 @@ protected PointF calculateLineEnd(float x, float y, float rad, float deg) { protected PointF calculateLineEnd(PointF origin, float rad, float deg) { - double radians = deg * Math.PI / 180F; + double radians = deg * Math.PI / HALF_PIE_DEGS; double x = rad * Math.cos(radians); double y = rad * Math.sin(radians); @@ -292,11 +295,10 @@ public Segment getContainingSegment(PointF point) { float dx = point.x - origin.x; float dy = point.y - origin.y; double theta = Math.atan2(dy, dx); - double angle = (theta * (180f / Math.PI)); + double angle = (theta * (HALF_PIE_DEGS / Math.PI)); if (angle < 0) { - // convert angle to 0-360 range with 0 being in the - // traditional "east" orientation: - angle += 360f; + // bring into 0-360 range + angle += FULL_PIE_DEGS; } // find the segment whose starting and ending angle (degs) contains @@ -310,10 +312,16 @@ public Segment getContainingSegment(PointF point) { float lastOffset = offset; float sweep = (float) (scale * (values[i]) * extentDegs); offset += sweep; - offset = offset % 360; + offset = offset % FULL_PIE_DEGS; final double dist = signedDistance(offset, angle); - if(dist > 0 && dist <= signedDistance(offset, lastOffset)) { + double endDist = signedDistance(offset, lastOffset); + if(endDist < 0) { + // segment accounts for more than 50% of the pie and wrapped around + // need to correct: + endDist = FULL_PIE_DEGS + endDist; + } + if(dist > 0 && dist <= endDist) { return sfPair.getSeries(); } i++; @@ -328,10 +336,10 @@ public Segment getContainingSegment(PointF point) { * @return */ protected static float degsToScreenDegs(float degs) { - degs = degs % 360; + degs = degs % FULL_PIE_DEGS; if (degs > 0) { - return 360 - degs; + return FULL_PIE_DEGS - degs; } else { return degs; } @@ -344,12 +352,12 @@ protected static float degsToScreenDegs(float degs) { * @return */ protected static double signedDistance(double angle1, double angle2) { - double d = Math.abs(angle1 - angle2) % 360; - double r = d > 180 ? 360 - d : d; + double d = Math.abs(angle1 - angle2) % FULL_PIE_DEGS; + double r = d > HALF_PIE_DEGS ? FULL_PIE_DEGS - d : d; //calculate sign - int sign = (angle1 - angle2 >= 0 && angle1 - angle2 <= 180) - || (angle1 - angle2 <= -180 && angle1 - angle2 >= -360) ? 1 : -1; + int sign = (angle1 - angle2 >= 0 && angle1 - angle2 <= HALF_PIE_DEGS) + || (angle1 - angle2 <= -HALF_PIE_DEGS && angle1 - angle2 >= -FULL_PIE_DEGS) ? 1 : -1; r *= sign; return r; } @@ -359,7 +367,7 @@ protected static double signedDistance(double angle1, double angle2) { * @param degs */ protected static void validateInputDegs(float degs) { - if(degs < 0 || degs > 360) { + if(degs < 0 || degs > FULL_PIE_DEGS) { throw new IllegalArgumentException("Degrees values must be between 0.0 and 360."); } } diff --git a/androidplot-core/src/test/java/com/androidplot/pie/PieRendererTest.java b/androidplot-core/src/test/java/com/androidplot/pie/PieRendererTest.java index dba4ce43..e504582a 100644 --- a/androidplot-core/src/test/java/com/androidplot/pie/PieRendererTest.java +++ b/androidplot-core/src/test/java/com/androidplot/pie/PieRendererTest.java @@ -110,7 +110,7 @@ public void testOnRender() throws Exception { } @Test - public void testGetContainingSegment() throws Exception { + public void getContainingSegment_returnsCorrectSegment() throws Exception { Segment segment1 = spy(new Segment("s1", 25)); Segment segment2 = spy(new Segment("s2", 25)); Segment segment3 = spy(new Segment("s3", 25)); @@ -150,6 +150,45 @@ public void testGetContainingSegment() throws Exception { assertEquals(segment1, renderer.getContainingSegment(new PointF(100, 0))); } + @Test + public void getContainingSegment_handlesSegmentsLargerThanHalfPie() throws Exception { + Segment segment1 = spy(new Segment("s1", 25)); + Segment segment2 = spy(new Segment("s2", 24)); + Segment segment3 = spy(new Segment("s3", 51)); + SegmentFormatter formatter = spy( + new SegmentFormatter(Color.GREEN, Color.GREEN, Color.GREEN, Color.GREEN)); + PieRenderer renderer = formatter.getRendererInstance(pieChart); + + pieChart.addSegment(segment1, formatter); + pieChart.addSegment(segment2, formatter); + pieChart.addSegment(segment3, formatter); + + // southeast + assertEquals(segment1, renderer.getContainingSegment(new PointF(100, 100))); + + // southwest + assertEquals(segment2, renderer.getContainingSegment(new PointF(0, 100))); + + // northwest + assertEquals(segment3, renderer.getContainingSegment(new PointF(0, 0))); + + // northeast + assertEquals(segment3, renderer.getContainingSegment(new PointF(100, 0))); + + renderer.setStartDegs(90); + // southeast + assertEquals(segment2, renderer.getContainingSegment(new PointF(100, 100))); + + // southwest + assertEquals(segment3, renderer.getContainingSegment(new PointF(0, 100))); + + // northwest + assertEquals(segment3, renderer.getContainingSegment(new PointF(0, 0))); + + // northeast + assertEquals(segment1, renderer.getContainingSegment(new PointF(100, 0))); + } + @Test public void testDegsToScreenDegs() throws Exception { assertEquals(0f, PieRenderer.degsToScreenDegs(0)); From 44c9b621cd6801b6fc368fea14932a2b50891162 Mon Sep 17 00:00:00 2001 From: Nick Fellows Date: Sat, 5 Aug 2017 09:29:03 -0500 Subject: [PATCH 02/53] Updates buildscript to CircleCI 2.0 --- .circleci/config.yml | 99 +++++++++++++++++++++++++++++++++++ .gitignore | 3 +- androidplot-core/build.gradle | 4 +- build.gradle | 2 +- circle.yml | 59 --------------------- demoapp-wearable/build.gradle | 2 +- 6 files changed, 104 insertions(+), 65 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 circle.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..43c50cfc --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,99 @@ +# Java Gradle CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-java/ for more details +# +version: 2 + +general: + branches: + only: + #- circleci +jobs: + build: + docker: + # specify the version you desire here + #- image: circleci/openjdk:8-jdk + + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + - image: circleci/android:api-25-alpha + + working_directory: ~/repo + + environment: + # Customize the JVM maximum heap limit + JVM_OPTS: -Xmx3200m + TERM: dumb +# KEYSTORE: ${CIRCLE_WORKING_DIRECTORY}/sigining.keystore +# PUBLISHER_ACCT_JSON_FILE: ${CIRCLE_WORKING_DIRECTORY}/publisher_profile.json + + steps: + - checkout + + - run: echo 'export KEYSTORE=${HOME}/repo/sigining.keystore' >> $BASH_ENV + - run: echo 'export PUBLISHER_ACCT_JSON_FILE=${HOME}/repo/publisher_profile.json' >> $BASH_ENV + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "build.gradle" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + # Get private keys etc + - run: ./misc/download_keystore.sh + - run: ./misc/inject_circle_build_number.sh + + - run: ./gradlew dependencies + + - save_cache: + paths: + - ~/.m2 + key: v1-dependencies-{{ checksum "build.gradle" }} + + # run tests & code coc! + - run: ./gradlew testDebug jacocoTestReportDebug + + # build release + - run: ./gradlew assembleRelease + + # javadoc + - run: ./gradlew javadoc + + # trigger codecod.io + - run: bash <(curl -s https://codecov.io/bash) + + - store_artifacts: + path: androidplot-core/build/outputs/aar/ + destination: aar + + - store_artifacts: + path: demoapp/build/outputs/apk/ + destination: apk + + - store_artifacts: + path: androidplot-core/build/reports/jacoco/debug/ + destination: coverage_report + + - store_artifacts: + path: androidplot-core/build/reports/tests/ + destination: test_results + + - store_test_results: + path: androidplot-core/build/test-results/ + + - deploy: + name: "Deploy to Bintray" + command: | + if [ "${CIRCLE_BRANCH}" == "master" ]; + then ./gradlew bintrayUpload; + fi + + - deploy: + name: "Deploy to Google Play" + command: | + if [ "${CIRCLE_BRANCH}" == "master" ]; + then + ./misc/download_google_publisher_json.sh; + ./gradlew publishApkRelease + fi \ No newline at end of file diff --git a/.gitignore b/.gitignore index 58204be4..694f2995 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,5 @@ DemoApp/.settings DemoApp/bin DemoApp/gen DemoApp/target -.idea/libraries -.idea/*.xml +.idea **/R.java diff --git a/androidplot-core/build.gradle b/androidplot-core/build.gradle index aff191ce..3e305c7d 100644 --- a/androidplot-core/build.gradle +++ b/androidplot-core/build.gradle @@ -74,7 +74,7 @@ android { lintOptions { abortOnError false } - buildToolsVersion '25.0.0' + buildToolsVersion theBuildToolsVersion } group = 'com.androidplot' @@ -86,7 +86,7 @@ def gitUrl = 'https://github.com/halfhp/androidplot.git' dependencies { compile 'com.halfhp.fig:figlib:1.0.3' - compile 'com.android.support:support-annotations:24.2.0' + compile 'com.android.support:support-annotations:25.3.1' testCompile "org.mockito:mockito-core:1.10.19" testCompile group: 'junit', name: 'junit', version: '4.12' testCompile "org.robolectric:robolectric:3.1" diff --git a/build.gradle b/build.gradle index d81cbf77..7b379558 100644 --- a/build.gradle +++ b/build.gradle @@ -38,7 +38,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.3.2' + classpath 'com.android.tools.build:gradle:2.3.3' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' classpath 'com.vanniktech:gradle-android-junit-jacoco-plugin:0.5.0' diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 494b4bc2..00000000 --- a/circle.yml +++ /dev/null @@ -1,59 +0,0 @@ - -machine: - environment: - KEYSTORE: ${HOME}/${CIRCLE_PROJECT_REPONAME}/sigining.keystore - PUBLISHER_ACCT_JSON_FILE: ${HOME}/${CIRCLE_PROJECT_REPONAME}/publisher_profile.json - -dependencies: - - pre: - - if [ ! -e /usr/local/android-sdk-linux/platforms/android-25 ]; then echo y | android update sdk --all --no-ui --filter "android-25"; fi; - - if [ ! -e /usr/local/android-sdk-linux/build-tools/25.0.2 ]; then echo y | android update sdk --all --no-ui --filter "build-tools-25.0.2"; fi; - - bash ./misc/download_keystore.sh - - bash ./misc/inject_circle_build_number.sh - -test: - - override: - - (./gradlew test assembleRelease javadoc): - timeout: 360 - - post: - - # core lib: - - cp -r ${HOME}/${CIRCLE_PROJECT_REPONAME}/androidplot-core/build/outputs/aar/ $CIRCLE_ARTIFACTS - - # demo app .apk: - - cp -r ${HOME}/${CIRCLE_PROJECT_REPONAME}/demoapp/build/outputs/apk/ $CIRCLE_ARTIFACTS - - # javadoc: - - cp -r ${HOME}/${CIRCLE_PROJECT_REPONAME}/androidplot-core/build/docs/javadoc/ $CIRCLE_ARTIFACTS - - - # junit xml report: - - mkdir -p $CIRCLE_TEST_REPORTS/junit-xml/ - - find . -type f -regex ".*/build/test-results/testReleaseUnitTest/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit-xml/ \; - - # junit html report: - # TODO: recursively copy subdirs etc - - mkdir -p $CIRCLE_TEST_REPORTS/junit-html/ - - cp -r ${HOME}/${CIRCLE_PROJECT_REPONAME}/androidplot-core/build/reports/tests/testReleaseUnitTest/* $CIRCLE_TEST_REPORTS/junit-html/ - - # lint report: - - mkdir -p $CIRCLE_TEST_REPORTS/lint/ - - find . -type f -regex ".*/build/outputs/.*html" -exec cp {} $CIRCLE_TEST_REPORTS/lint/ \; - - # code coverage: - - ./gradlew jacocoTestReportDebug - - mkdir -p $CIRCLE_TEST_REPORTS/jacoco/ - - cp -r ${HOME}/${CIRCLE_PROJECT_REPONAME}/androidplot-core/build/reports/jacoco/debug/. $CIRCLE_TEST_REPORTS/jacoco - - bash <(curl -s https://codecov.io/bash) - -deployment: - master: - branch: master - commands: - - (./gradlew bintrayUpload): - timeout: 360 - - bash ./misc/download_google_publisher_json.sh - - ./gradlew publishApkRelease diff --git a/demoapp-wearable/build.gradle b/demoapp-wearable/build.gradle index 37406aaa..8154801c 100644 --- a/demoapp-wearable/build.gradle +++ b/demoapp-wearable/build.gradle @@ -19,7 +19,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.2' + classpath 'com.android.tools.build:gradle:2.3.3' } } apply plugin: 'com.android.application' From a16a1df75adf417e4c18083e0f756eb746d6da36 Mon Sep 17 00:00:00 2001 From: Nick Fellows Date: Sat, 5 Aug 2017 09:58:01 -0500 Subject: [PATCH 03/53] #52 - Added NPE check to Plot.renderOnCanvas (#59) --- androidplot-core/src/main/java/com/androidplot/Plot.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/androidplot-core/src/main/java/com/androidplot/Plot.java b/androidplot-core/src/main/java/com/androidplot/Plot.java index f2eab84a..3ee10174 100644 --- a/androidplot-core/src/main/java/com/androidplot/Plot.java +++ b/androidplot-core/src/main/java/com/androidplot/Plot.java @@ -21,6 +21,7 @@ import android.graphics.*; import android.os.Build; import android.os.Looper; +import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.View; @@ -804,7 +805,10 @@ protected void onDraw(Canvas canvas) { * "heavy lifting". * @param canvas */ - protected synchronized void renderOnCanvas(Canvas canvas) { + protected synchronized void renderOnCanvas(@Nullable Canvas canvas) { + if(canvas == null) { + return; + } try { // any series interested in synchronizing with plot should // implement PlotListener.onBeforeDraw(...) and do a read lock from within its From 9088a7b1ae536fceb9b570ec07c2eb39fa0a13a0 Mon Sep 17 00:00:00 2001 From: Nick Fellows Date: Sat, 5 Aug 2017 09:59:50 -0500 Subject: [PATCH 04/53] updates quickstart lib version to 1.5.1 --- docs/quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/quickstart.md b/docs/quickstart.md index 76060cd9..cf238b57 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -14,7 +14,7 @@ To use the library in your gradle project add the following to your build.gradle ```groovy dependencies { - compile "com.androidplot:androidplot-core:1.5.0" + compile "com.androidplot:androidplot-core:1.5.1" } ``` From 0cb45aef633bc64fcaf4eca17c5b1ffd454f350f Mon Sep 17 00:00:00 2001 From: Nick Fellows Date: Sat, 5 Aug 2017 21:01:15 -0500 Subject: [PATCH 05/53] uprev to 1.5.2 for development --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7b379558..dad2f2f7 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ ext { theCompileSdkVersion = 25 theTargetSdkVersion = 25 theMinSdkVersion = 5 - theVersionName = '1.5.1' + theVersionName = '1.5.2' theVersionCode = 0 } From 4662832d5c73b7bceba53c9dd948f8e9ff1f9026 Mon Sep 17 00:00:00 2001 From: guycnicholas Date: Wed, 8 Nov 2017 09:40:24 -0800 Subject: [PATCH 06/53] For issue #61 updated screenToSeriesY to use the vertical bounds rather than horizontal (#62) --- .../com/androidplot/xy/XYGraphWidget.java | 2 +- .../com/androidplot/xy/XYGraphWidgetTest.java | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/androidplot-core/src/main/java/com/androidplot/xy/XYGraphWidget.java b/androidplot-core/src/main/java/com/androidplot/xy/XYGraphWidget.java index a6460799..d1ce96ec 100644 --- a/androidplot-core/src/main/java/com/androidplot/xy/XYGraphWidget.java +++ b/androidplot-core/src/main/java/com/androidplot/xy/XYGraphWidget.java @@ -489,7 +489,7 @@ protected float seriesToScreenX(Number x) { protected float seriesToScreenY(Number y) { return (float) plot.getBounds().getyRegion(). - transform(y.doubleValue(), gridRect.left, gridRect.right, true); + transform(y.doubleValue(), gridRect.bottom, gridRect.top, true); } @Override diff --git a/androidplot-core/src/test/java/com/androidplot/xy/XYGraphWidgetTest.java b/androidplot-core/src/test/java/com/androidplot/xy/XYGraphWidgetTest.java index 4b9f156a..0bfe4d9d 100644 --- a/androidplot-core/src/test/java/com/androidplot/xy/XYGraphWidgetTest.java +++ b/androidplot-core/src/test/java/com/androidplot/xy/XYGraphWidgetTest.java @@ -79,7 +79,7 @@ public void setUp() throws Exception { xyPlot.setRangeStep(StepMode.INCREMENT_BY_VAL, 1); graphWidget = spy(new XYGraphWidget(layoutManager, xyPlot, size)); - graphWidget.setGridRect(new RectF(0, 0, 100, 100)); + graphWidget.setGridRect(new RectF(0, 0, 10, 100)); graphWidget.setLabelRect(new RectF(0, 0, 100, 100)); } @@ -253,11 +253,11 @@ public void testScreenToSeries() throws Exception { assertEquals(-100, coords.x.intValue()); assertEquals(100, coords.y.intValue()); - coords = graphWidget.screenToSeries(new PointF(100, 100)); + coords = graphWidget.screenToSeries(new PointF(10, 100)); assertEquals(100, coords.x.intValue()); assertEquals(-100, coords.y.intValue()); - coords = graphWidget.screenToSeries(new PointF(50, 50)); + coords = graphWidget.screenToSeries(new PointF(5, 50)); assertEquals(0, coords.x.intValue()); assertEquals(0, coords.y.intValue()); } @@ -271,11 +271,11 @@ public void testSeriesToScreen() throws Exception { assertEquals(0f, point.y); point = graphWidget.seriesToScreen(new XYCoords(100, -100)); - assertEquals(100f, point.x); + assertEquals(10f, point.x); assertEquals(100f, point.y); point = graphWidget.seriesToScreen(new XYCoords(0, 0)); - assertEquals(50f, point.x); + assertEquals(5f, point.x); assertEquals(50f, point.y); } @@ -284,8 +284,8 @@ public void testScreenToSeriesX() throws Exception { when(xyPlot.getBounds()).thenReturn(new RectRegion(-100, 100, -100, 100)); assertEquals(-100, graphWidget.screenToSeriesX(new PointF(0, 0)).intValue()); - assertEquals(100, graphWidget.screenToSeriesX(new PointF(100, 100)).intValue()); - assertEquals(0, graphWidget.screenToSeriesX(new PointF(50, 50)).intValue()); + assertEquals(100, graphWidget.screenToSeriesX(new PointF(10, 100)).intValue()); + assertEquals(0, graphWidget.screenToSeriesX(new PointF(5, 50)).intValue()); } @Test @@ -302,16 +302,16 @@ public void testSeriesToScreenX() throws Exception { when(xyPlot.getBounds()).thenReturn(new RectRegion(-100, 100, -100, 100)); assertEquals(0f, graphWidget.seriesToScreenX(-100)); - assertEquals(100f, graphWidget.seriesToScreenX(100)); - assertEquals(50f, graphWidget.seriesToScreenX(0)); + assertEquals(10f, graphWidget.seriesToScreenX(100)); + assertEquals(5f, graphWidget.seriesToScreenX(0)); } @Test public void testSeriesToScreenY() throws Exception { when(xyPlot.getBounds()).thenReturn(new RectRegion(-100, 100, -100, 100)); - assertEquals(0f, graphWidget.seriesToScreenY(100)); - assertEquals(100f, graphWidget.seriesToScreenY(-100)); + assertEquals(100f, graphWidget.seriesToScreenY(100)); + assertEquals(0f, graphWidget.seriesToScreenY(-100)); assertEquals(50f, graphWidget.seriesToScreenY(0)); } } From 55fce04bff334e0988aa253b25eeb667456d5be8 Mon Sep 17 00:00:00 2001 From: Nick Fellows Date: Fri, 8 Dec 2017 08:43:17 -0600 Subject: [PATCH 07/53] Androidplot 1.5.2 (#65) * target Android SDK 26 * update fig dependency for gradle 3.x.x support * adds custom renderer documentation * remove obsolete class / unnecessary casts * adds sizing section to plot_composition.md * adds more sizing and positioning documentation --- .circleci/config.yml | 2 +- androidplot-core/build.gradle | 6 +- .../src/main/java/com/androidplot/Plot.java | 8 +- .../java/com/androidplot/ui/Formatter.java | 6 +- .../java/com/androidplot/ui/SizeMetric.java | 1 - .../ui/widget/LegendItemOrganizer.java | 9 -- .../java/com/androidplot/xy/BarRenderer.java | 2 +- .../com/androidplot/xy/XYRegionFormatter.java | 6 +- .../src/main/res/values/attrs.xml | 51 ++++++- build.gradle | 13 +- demoapp-wearable/build.gradle | 2 +- demoapp/build.gradle | 11 +- .../demos/SimpleXYPlotActivity.java | 6 +- .../demos/TouchZoomExampleActivity.java | 8 +- .../demos/XYRegionExampleActivity.java | 12 +- .../src/main/res/layout/bar_plot_example.xml | 54 ++++---- .../src/main/res/layout/demo_app_widget.xml | 17 ++- .../res/layout/dynamic_xyplot_example.xml | 22 +-- demoapp/src/main/res/layout/main.xml | 54 +++++--- demoapp/src/main/res/layout/pie_chart.xml | 3 +- .../main/res/layout/step_chart_example.xml | 25 ++-- .../main/res/layout/time_series_example.xml | 42 +++--- .../main/res/layout/touch_zoom_example.xml | 49 +++---- demoapp/src/main/res/values-hdpi/dimens.xml | 18 --- demoapp/src/main/res/values-ldpi/dimens.xml | 20 --- demoapp/src/main/res/values/dimens.xml | 18 --- demoapp/src/main/res/values/style.xml | 28 ---- docs/attrs.md | 50 ++++++- docs/custom_renderer.md | 101 ++++++++++++++ docs/grouprenderer.md | 8 +- docs/images/rounded_bar_renderer.png | Bin 0 -> 70585 bytes docs/images/sizing/abs100x-abs100y.png | Bin 0 -> 5852 bytes docs/images/sizing/abs100x-abs150y.png | Bin 0 -> 6725 bytes docs/images/sizing/abs100x-rel1y.png | Bin 0 -> 6049 bytes docs/images/sizing/fil50x-fil50y.png | Bin 0 -> 7882 bytes docs/images/sizing/rel075x-abs100y.png | Bin 0 -> 5907 bytes docs/index.md | 1 + docs/plot_composition.md | 131 +++++++++++++++++- docs/quickstart.md | 2 +- docs/release_notes.md | 12 ++ gradle/wrapper/gradle-wrapper.properties | 4 +- 41 files changed, 527 insertions(+), 275 deletions(-) delete mode 100644 androidplot-core/src/main/java/com/androidplot/ui/widget/LegendItemOrganizer.java delete mode 100644 demoapp/src/main/res/values-ldpi/dimens.xml delete mode 100644 demoapp/src/main/res/values/style.xml create mode 100644 docs/custom_renderer.md create mode 100644 docs/images/rounded_bar_renderer.png create mode 100644 docs/images/sizing/abs100x-abs100y.png create mode 100644 docs/images/sizing/abs100x-abs150y.png create mode 100644 docs/images/sizing/abs100x-rel1y.png create mode 100644 docs/images/sizing/fil50x-fil50y.png create mode 100644 docs/images/sizing/rel075x-abs100y.png diff --git a/.circleci/config.yml b/.circleci/config.yml index 43c50cfc..6a24c3f8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,7 +16,7 @@ jobs: # CircleCI maintains a library of pre-built images # documented at https://circleci.com/docs/2.0/circleci-images/ - - image: circleci/android:api-25-alpha + - image: circleci/android:api-26-alpha working_directory: ~/repo diff --git a/androidplot-core/build.gradle b/androidplot-core/build.gradle index 3e305c7d..a814a4c1 100644 --- a/androidplot-core/build.gradle +++ b/androidplot-core/build.gradle @@ -58,7 +58,6 @@ task generateAttrsMarkdown(type: AttrMarkdown) { android { compileSdkVersion theCompileSdkVersion - buildToolsVersion theBuildToolsVersion defaultConfig { versionCode theVersionCode @@ -74,7 +73,6 @@ android { lintOptions { abortOnError false } - buildToolsVersion theBuildToolsVersion } group = 'com.androidplot' @@ -85,8 +83,8 @@ def gitUrl = 'https://github.com/halfhp/androidplot.git' dependencies { - compile 'com.halfhp.fig:figlib:1.0.3' - compile 'com.android.support:support-annotations:25.3.1' + compile 'com.halfhp.fig:figlib:1.0.7' + compile 'com.android.support:support-annotations:27.0.2' testCompile "org.mockito:mockito-core:1.10.19" testCompile group: 'junit', name: 'junit', version: '4.12' testCompile "org.robolectric:robolectric:3.1" diff --git a/androidplot-core/src/main/java/com/androidplot/Plot.java b/androidplot-core/src/main/java/com/androidplot/Plot.java index 3ee10174..8b436199 100644 --- a/androidplot-core/src/main/java/com/androidplot/Plot.java +++ b/androidplot-core/src/main/java/com/androidplot/Plot.java @@ -520,7 +520,7 @@ private void loadAttrs(AttributeSet attrs, int defStyle) { // apply "configurator" attrs: (overrides any previously applied styleable attrs) // filter out androidplot prefixed attrs: - HashMap attrHash = new HashMap(); + HashMap attrHash = new HashMap<>(); for (int i = 0; i < attrs.getAttributeCount(); i++) { String attrName = attrs.getAttributeName(i); @@ -529,7 +529,11 @@ private void loadAttrs(AttributeSet attrs, int defStyle) { attrHash.put(attrName.substring(XML_ATTR_PREFIX.length() + 1), attrs.getAttributeValue(i)); } } - Fig.configure(getContext(), this, attrHash); + try { + Fig.configure(getContext(), this, attrHash); + } catch (FigException e) { + throw new RuntimeException(e); + } } } diff --git a/androidplot-core/src/main/java/com/androidplot/ui/Formatter.java b/androidplot-core/src/main/java/com/androidplot/ui/Formatter.java index 8f2a354b..d920ab36 100644 --- a/androidplot-core/src/main/java/com/androidplot/ui/Formatter.java +++ b/androidplot-core/src/main/java/com/androidplot/ui/Formatter.java @@ -48,7 +48,11 @@ public Formatter(Context ctx, int xmlCfgId) { } public void configure(Context ctx, int xmlCfgId) { - Fig.configure(ctx, this, xmlCfgId); + try { + Fig.configure(ctx, this, xmlCfgId); + } catch (FigException e) { + throw new RuntimeException(e); + } } /** diff --git a/androidplot-core/src/main/java/com/androidplot/ui/SizeMetric.java b/androidplot-core/src/main/java/com/androidplot/ui/SizeMetric.java index e3819acd..d7f3e58b 100644 --- a/androidplot-core/src/main/java/com/androidplot/ui/SizeMetric.java +++ b/androidplot-core/src/main/java/com/androidplot/ui/SizeMetric.java @@ -43,7 +43,6 @@ protected void validatePair(float value, SizeMode layoutType) { @Override public float getPixelValue(float size) { - //switch(layoutType) switch(getLayoutType()) { case ABSOLUTE: return getValue(); diff --git a/androidplot-core/src/main/java/com/androidplot/ui/widget/LegendItemOrganizer.java b/androidplot-core/src/main/java/com/androidplot/ui/widget/LegendItemOrganizer.java deleted file mode 100644 index 536ee9d8..00000000 --- a/androidplot-core/src/main/java/com/androidplot/ui/widget/LegendItemOrganizer.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.androidplot.ui.widget; - -import java.util.List; - - -public interface LegendItemOrganizer { - - void organize(List items); -} diff --git a/androidplot-core/src/main/java/com/androidplot/xy/BarRenderer.java b/androidplot-core/src/main/java/com/androidplot/xy/BarRenderer.java index c696bbf2..bb8c4c7f 100644 --- a/androidplot-core/src/main/java/com/androidplot/xy/BarRenderer.java +++ b/androidplot-core/src/main/java/com/androidplot/xy/BarRenderer.java @@ -238,7 +238,7 @@ protected RectF createBarRect(float w1, float h1, float w2, float h2, BarFormatt return result; } - protected void drawBar(Canvas canvas, Bar bar, RectF rect) { + protected void drawBar(Canvas canvas, Bar bar, RectF rect) { // null yVals are skipped: if(bar.getY() == null) { diff --git a/androidplot-core/src/main/java/com/androidplot/xy/XYRegionFormatter.java b/androidplot-core/src/main/java/com/androidplot/xy/XYRegionFormatter.java index b0a3186f..0492c6c2 100644 --- a/androidplot-core/src/main/java/com/androidplot/xy/XYRegionFormatter.java +++ b/androidplot-core/src/main/java/com/androidplot/xy/XYRegionFormatter.java @@ -43,7 +43,11 @@ public class XYRegionFormatter { public XYRegionFormatter(Context ctx, int xmlCfgId) { // prevent configuration of classes derived from this one: if (getClass().equals(XYRegionFormatter.class)) { - Fig.configure(ctx, this, xmlCfgId); + try { + Fig.configure(ctx, this, xmlCfgId); + } catch (FigException e) { + throw new RuntimeException(e); + } } } diff --git a/androidplot-core/src/main/res/values/attrs.xml b/androidplot-core/src/main/res/values/attrs.xml index e640706e..c9dc65a0 100644 --- a/androidplot-core/src/main/res/values/attrs.xml +++ b/androidplot-core/src/main/res/values/attrs.xml @@ -16,12 +16,17 @@ --> + @@ -442,6 +447,10 @@ __dimension|float|integer__ * relative_from_left * relative_from_right * relative_from_center + +`HorizontalPositioning` component of the `HorizontalPosition` of the `TextLabelWidget` +that displays the domain title. +See [Positioning Widgets](plot_composition.md#positioning-widgets) documentation. --> + xmlns:ap="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + ap:title="Growth" /> + android:layout_height="wrap_content" /> + android:layout_height="wrap_content" /> + android:layout_height="wrap_content" /> + android:progress="10" /> + android:progress="1" /> + android:checked="true" + android:text="Series 1" /> + android:checked="true" + android:text="Series 2" /> \ No newline at end of file diff --git a/demoapp/src/main/res/layout/demo_app_widget.xml b/demoapp/src/main/res/layout/demo_app_widget.xml index 85b5fe6b..81977453 100644 --- a/demoapp/src/main/res/layout/demo_app_widget.xml +++ b/demoapp/src/main/res/layout/demo_app_widget.xml @@ -17,14 +17,13 @@ --> + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> - - + \ No newline at end of file diff --git a/demoapp/src/main/res/layout/dynamic_xyplot_example.xml b/demoapp/src/main/res/layout/dynamic_xyplot_example.xml index ddfd0cba..5b0c5644 100644 --- a/demoapp/src/main/res/layout/dynamic_xyplot_example.xml +++ b/demoapp/src/main/res/layout/dynamic_xyplot_example.xml @@ -1,5 +1,4 @@ - - + xmlns:ap="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent"> + ap:legendTextSize="15sp" + ap:rangeTitle="Range" + ap:title="A Dynamic XY Plot" /> diff --git a/demoapp/src/main/res/layout/main.xml b/demoapp/src/main/res/layout/main.xml index 65a43ef9..590087de 100644 --- a/demoapp/src/main/res/layout/main.xml +++ b/demoapp/src/main/res/layout/main.xml @@ -32,99 +32,117 @@