diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 871ff0b..cc6305e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -130,7 +130,7 @@ android { dependencies { // Dzeio Charts - implementation(project(":charts")) + implementation("com.dzeio:charts:edd78e87e1") // Dzeio Crash Handler implementation("com.dzeio:crashhandler:1.0.1") @@ -139,7 +139,7 @@ dependencies { implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.appcompat:appcompat:1.7.0-alpha01") implementation("javax.inject:javax.inject:1") - implementation("com.google.android.material:material:1.8.0-beta01") + implementation("com.google.android.material:material:1.8.0-rc01") implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.5.1") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1") diff --git a/app/libs/samsung-health-data-1.5.0.aar b/app/libs/samsung-health-data-1.5.0.aar deleted file mode 100644 index e4f8cf6..0000000 Binary files a/app/libs/samsung-health-data-1.5.0.aar and /dev/null differ diff --git a/app/src/main/java/com/dzeio/openhealth/adapters/FoodAdapter.kt b/app/src/main/java/com/dzeio/openhealth/adapters/FoodAdapter.kt index 6452f47..1ae4b3c 100644 --- a/app/src/main/java/com/dzeio/openhealth/adapters/FoodAdapter.kt +++ b/app/src/main/java/com/dzeio/openhealth/adapters/FoodAdapter.kt @@ -8,6 +8,9 @@ import com.dzeio.openhealth.core.BaseViewHolder import com.dzeio.openhealth.data.food.Food import com.dzeio.openhealth.databinding.ItemFoodBinding import com.dzeio.openhealth.utils.DownloadImageTask +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import kotlin.math.roundToInt @@ -23,6 +26,11 @@ class FoodAdapter : BaseAdapter() { item: Food, position: Int ) { + + CoroutineScope(Dispatchers.IO).launch { + + } + // Download remote picture DownloadImageTask(holder.binding.productImage).execute(item.image) diff --git a/app/src/main/java/com/dzeio/openhealth/data/food/Food.kt b/app/src/main/java/com/dzeio/openhealth/data/food/Food.kt index 3c6c063..8a7b615 100644 --- a/app/src/main/java/com/dzeio/openhealth/data/food/Food.kt +++ b/app/src/main/java/com/dzeio/openhealth/data/food/Food.kt @@ -1,5 +1,6 @@ package com.dzeio.openhealth.data.food +import android.util.Log import androidx.room.Entity import androidx.room.PrimaryKey import com.dzeio.openhealth.data.openfoodfact.OFFProduct @@ -63,7 +64,11 @@ data class Food( /** * Transform an OpenFoodFact product to use for our Database */ - fun fromOpenFoodFact(food: OFFProduct, quantity: Float? = null): Food { + fun fromOpenFoodFact(food: OFFProduct, quantity: Float? = null): Food? { + // filter out foods that we can't use in the app + if (food.name == null || ((food.servingSize == null || food.servingSize == "") && (food.quantity == null || food.quantity == "") && food.servingQuantity == null && food.productQuantity == null)) { + return null + } // try to know how much was eaten by the user if not said var eaten = quantity ?: food.servingQuantity ?: food.productQuantity ?: 0f @@ -72,10 +77,13 @@ data class Food( eaten = food.servingQuantity!! } else if (food.productQuantity != null && food.productQuantity != 0f) { eaten = food.productQuantity!! + } else if (food.servingSize != null || food.quantity != null) { + Log.d("pouet", ".${food.servingSize ?: food.quantity}. .${(food.servingSize ?: food.quantity)!!.replace(Regex(" +\\w+$"), "")}. ${food}") + eaten = (food.servingSize ?: food.quantity)!!.trim().replace(Regex(" +\\w+$"), "").toInt().toFloat() } } return Food( - name = food.name, + name = food.name!!, // do some slight edit on the serving to remove strange entries like `100 g` serving = (food.servingSize ?: food.quantity ?: "unknown").replace(Regex(" +"), ""), quantity = eaten, diff --git a/app/src/main/java/com/dzeio/openhealth/data/openfoodfact/OFFProduct.kt b/app/src/main/java/com/dzeio/openhealth/data/openfoodfact/OFFProduct.kt index 1c44dfc..60a33a7 100644 --- a/app/src/main/java/com/dzeio/openhealth/data/openfoodfact/OFFProduct.kt +++ b/app/src/main/java/com/dzeio/openhealth/data/openfoodfact/OFFProduct.kt @@ -13,7 +13,7 @@ data class OFFProduct( * the product name */ @SerializedName("product_name") - var name: String, + var name: String?, /** * the size of a serving diff --git a/app/src/main/java/com/dzeio/openhealth/graphs/WeightChart.kt b/app/src/main/java/com/dzeio/openhealth/graphs/WeightChart.kt index 6f239fd..3a23150 100644 --- a/app/src/main/java/com/dzeio/openhealth/graphs/WeightChart.kt +++ b/app/src/main/java/com/dzeio/openhealth/graphs/WeightChart.kt @@ -4,7 +4,7 @@ import android.graphics.Color import android.view.View import com.dzeio.openhealth.data.weight.Weight import com.dzeio.openhealth.units.Units -import com.dzeio.openhealth.utils.GraphUtils +import com.dzeio.openhealth.utils.ChartUtils import com.github.mikephil.charting.charts.LineChart import com.github.mikephil.charting.components.LimitLine import com.github.mikephil.charting.components.YAxis @@ -29,7 +29,7 @@ object WeightChart { goal: Float?, limit: Boolean = true ) { - GraphUtils.lineChartSetup( + ChartUtils.lineChartSetup( chart, MaterialColors.getColor( view, @@ -84,7 +84,7 @@ object WeightChart { ) } - val rawData = GraphUtils.lineDataSet( + val rawData = ChartUtils.lineDataSet( LineDataSet( data.mapIndexed { _, weight -> return@mapIndexed Entry( @@ -98,7 +98,7 @@ object WeightChart { axisDependency = YAxis.AxisDependency.RIGHT } - val averageData = GraphUtils.lineDataSet(LineDataSet(averageYs, "Average")).apply { + val averageData = ChartUtils.lineDataSet(LineDataSet(averageYs, "Average")).apply { axisDependency = YAxis.AxisDependency.RIGHT color = Color.GREEN } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/food/SearchFoodDialogViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/food/SearchFoodDialogViewModel.kt index 0ccd279..f2179d7 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/food/SearchFoodDialogViewModel.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/food/SearchFoodDialogViewModel.kt @@ -8,6 +8,7 @@ import com.dzeio.openhealth.data.food.FoodRepository import com.dzeio.openhealth.data.openfoodfact.OpenFoodFactService import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch +import java.util.ArrayList import javax.inject.Inject @HiltViewModel @@ -23,9 +24,10 @@ class SearchFoodDialogViewModel @Inject internal constructor( val product = response.body() if (product != null) { - items.postValue(product.products - .filter { it.name != null } - .map { Food.fromOpenFoodFact(it) } + items.postValue( + product.products + .map { Food.fromOpenFoodFact(it) } + .filter { it != null } as List ) } } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt index 9199d7c..d0e9dda 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt @@ -17,7 +17,7 @@ import com.dzeio.openhealth.graphs.WeightChart import com.dzeio.openhealth.ui.weight.WeightDialog import com.dzeio.openhealth.units.Units import com.dzeio.openhealth.utils.DrawUtils -import com.dzeio.openhealth.utils.GraphUtils +import com.dzeio.openhealth.utils.ChartUtils import com.google.android.material.color.MaterialColors import dagger.hilt.android.AndroidEntryPoint import kotlin.math.max @@ -47,7 +47,6 @@ class HomeFragment : BaseFragment(HomeViewMo /** * Water Intake */ - binding.fragmentHomeWaterAdd.setOnClickListener { val water = viewModel.water.value if (water == null || !water.isToday()) { @@ -91,7 +90,7 @@ class HomeFragment : BaseFragment(HomeViewMo } // Make a line Chart using the graph library - GraphUtils.lineChartSetup( + ChartUtils.lineChartSetup( binding.weightGraph, MaterialColors.getColor( requireView(), diff --git a/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt index 17e8abd..1269e3e 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt @@ -11,7 +11,7 @@ import com.dzeio.openhealth.Application import com.dzeio.openhealth.adapters.StepsAdapter import com.dzeio.openhealth.core.BaseFragment import com.dzeio.openhealth.databinding.FragmentStepsHomeBinding -import com.google.android.material.color.MaterialColors +import com.dzeio.openhealth.utils.ChartUtils import dagger.hilt.android.AndroidEntryPoint import java.text.DateFormat import java.util.Calendar @@ -53,46 +53,16 @@ class StepsHomeFragment : val chart = binding.chart // setup serie - val serie = BarSerie(chart).apply { - barPaint.color = MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorPrimary - ) - textPaint.color = MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorOnPrimary - ) - } - - val errorColor = MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorError - ) + val serie = BarSerie(chart) chart.apply { - series = arrayListOf(serie) -// debug = true - + ChartUtils.materielTheme(chart, requireView()) yAxis.apply { - textLabel.color = MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorOnPrimaryContainer - ) - linePaint.color = MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorOnPrimaryContainer - ) - goalLinePaint.color = errorColor -// onValueFormat = { value -> "${value.toInt()}" } } xAxis.apply { dataWidth = 604800000.0 - textPaint.color = MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorOnPrimaryContainer - ) textPaint.textSize = 32f onValueFormat = onValueFormat@{ val formatter = DateFormat.getDateTimeInstance( @@ -107,8 +77,10 @@ class StepsHomeFragment : } viewModel.goal.observe(viewLifecycleOwner) { - chart.yAxis.setGoalLine(it?.toFloat()) - chart.refresh() + if (it != null) { + chart.yAxis.addLine(it.toFloat()) + chart.refresh() + } } viewModel.items.observe(viewLifecycleOwner) { list -> @@ -118,16 +90,8 @@ class StepsHomeFragment : return@observe } - - -// chart.animation.enabled = false -// chart.animation.refreshRate = 60 -// chart.animation.duration = 300 - // chart.scroller.zoomEnabled = false -// chart.xAxis.labels.size = 32f - val entries: HashMap = HashMap() list.forEach { @@ -138,7 +102,7 @@ class StepsHomeFragment : cal.set(Calendar.AM_PM, Calendar.AM) val ts = cal.timeInMillis if (!entries.containsKey(ts)) { - entries[ts] = Entry((ts).toDouble(), 0F, errorColor) + entries[ts] = Entry((ts).toDouble(), 0F, chart.yAxis.goalLinePaint.color) } entries[ts]!!.y += it.value.toFloat() diff --git a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeFragment.kt index f92bd92..c129b09 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeFragment.kt @@ -6,15 +6,16 @@ import android.view.View import android.view.ViewGroup import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager +import com.dzeio.charts.Entry +import com.dzeio.charts.series.BarSerie import com.dzeio.openhealth.adapters.WaterAdapter import com.dzeio.openhealth.core.BaseFragment import com.dzeio.openhealth.databinding.FragmentMainWaterHomeBinding -import com.dzeio.openhealth.utils.GraphUtils -import com.github.mikephil.charting.data.BarData -import com.github.mikephil.charting.data.BarDataSet -import com.github.mikephil.charting.data.BarEntry -import com.google.android.material.color.MaterialColors +import com.dzeio.openhealth.utils.ChartUtils import dagger.hilt.android.AndroidEntryPoint +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale @AndroidEntryPoint class WaterHomeFragment : @@ -45,39 +46,45 @@ class WaterHomeFragment : val chart = binding.chart - GraphUtils.barChartSetup( - chart, - MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorPrimary - ), - MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorOnBackground - ) - ) + val serie = BarSerie(chart) + + chart.apply { + ChartUtils.materielTheme(chart, requireView()) + + yAxis.apply { +// onValueFormat + } + + xAxis.apply { + dataWidth = 604800000.0 + textPaint.textSize = 32f + onValueFormat = onValueFormat@{ + return@onValueFormat SimpleDateFormat( + "yyyy-MM-dd", + Locale.getDefault() + ).format(Date(it.toLong())) + } + } + } binding.buttonEditDefaultIntake.setOnClickListener { findNavController().navigate(WaterHomeFragmentDirections.actionNavWaterHomeToNavWaterSizeDialog()) } - chart.xAxis.valueFormatter = GraphUtils.DateValueFormatter(1000 * 60 * 60 * 24) viewModel.items.observe(viewLifecycleOwner) { list -> adapter.set(list) - val dataset = BarDataSet( - list.map { - return@map BarEntry( - (it.timestamp / 1000 / 60 / 60 / 24).toFloat(), - it.value.toFloat() - ) - }, - "" - ) + val dataset = list.map { + return@map Entry( + it.timestamp.toDouble(), + it.value.toFloat() + ) + } - chart.data = BarData(dataset) - chart.invalidate() + serie.entries = dataset as ArrayList + chart.xAxis.x = dataset[0].x + chart.refresh() } } } diff --git a/app/src/main/java/com/dzeio/openhealth/utils/GraphUtils.kt b/app/src/main/java/com/dzeio/openhealth/utils/ChartUtils.kt similarity index 60% rename from app/src/main/java/com/dzeio/openhealth/utils/GraphUtils.kt rename to app/src/main/java/com/dzeio/openhealth/utils/ChartUtils.kt index 87112d0..8afb440 100644 --- a/app/src/main/java/com/dzeio/openhealth/utils/GraphUtils.kt +++ b/app/src/main/java/com/dzeio/openhealth/utils/ChartUtils.kt @@ -1,6 +1,9 @@ package com.dzeio.openhealth.utils -import com.github.mikephil.charting.charts.BarChart +import android.view.View +import com.dzeio.charts.ChartView +import com.dzeio.charts.series.BarSerie +import com.dzeio.charts.series.LineSerie import com.github.mikephil.charting.charts.BarLineChartBase import com.github.mikephil.charting.charts.LineChart import com.github.mikephil.charting.components.AxisBase @@ -11,6 +14,7 @@ import com.github.mikephil.charting.data.Entry import com.github.mikephil.charting.data.LineDataSet import com.github.mikephil.charting.formatter.ValueFormatter import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet +import com.google.android.material.color.MaterialColors import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -20,7 +24,7 @@ import java.util.Locale * * TODO: migrate to DzeioCharts once it is ready */ -object GraphUtils { +object ChartUtils { fun lineChartSetup(chart: LineChart, mainColor: Int, textColor: Int) { barLineChartSetup(chart, mainColor, textColor) @@ -35,10 +39,6 @@ object GraphUtils { } } - fun barChartSetup(chart: BarChart, mainColor: Int, textColor: Int) { - barLineChartSetup(chart, mainColor, textColor) - } - private fun >?> barLineChartSetup( chart: BarLineChartBase, mainColor: Int, @@ -101,4 +101,62 @@ object GraphUtils { // return super.getAxisLabel(value, axis) } } + + /** + * Apply Material theme to a DzeioChart [ChartView] + */ + fun materielTheme(chart: ChartView, view: View) { + + val errorColor = MaterialColors.getColor( + view, + com.google.android.material.R.attr.colorError + ) + + chart.apply { + yAxis.apply { + textLabel.color = MaterialColors.getColor( + view, + com.google.android.material.R.attr.colorOnPrimaryContainer + ) + linePaint.color = MaterialColors.getColor( + view, + com.google.android.material.R.attr.colorOnPrimaryContainer + ) + goalLinePaint.color = errorColor + } + + xAxis.apply { + textPaint.color = MaterialColors.getColor( + view, + com.google.android.material.R.attr.colorOnPrimaryContainer + ) + } + + for (serie in series) { + if (serie is BarSerie) { + serie.apply { + barPaint.color = MaterialColors.getColor( + view, + com.google.android.material.R.attr.colorPrimary + ) + textPaint.color = MaterialColors.getColor( + view, + com.google.android.material.R.attr.colorOnPrimary + ) + } + } else if (serie is LineSerie) { + serie.apply { + linePaint.color = MaterialColors.getColor( + view, + com.google.android.material.R.attr.colorPrimary + ) + textPaint.color = MaterialColors.getColor( + view, + com.google.android.material.R.attr.colorOnPrimary + ) + } + } + } + } + } } diff --git a/app/src/main/res/layout/fragment_main_water_home.xml b/app/src/main/res/layout/fragment_main_water_home.xml index d8e49b1..1f80e93 100644 --- a/app/src/main/res/layout/fragment_main_water_home.xml +++ b/app/src/main/res/layout/fragment_main_water_home.xml @@ -22,7 +22,7 @@ - - diff --git a/charts/src/main/java/com/dzeio/charts/Animation.kt b/charts/src/main/java/com/dzeio/charts/Animation.kt deleted file mode 100644 index 08c19b9..0000000 --- a/charts/src/main/java/com/dzeio/charts/Animation.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.dzeio.charts - -import kotlin.math.abs -import kotlin.math.max - -data class Animation( - /** - * Enable / Disable the Chart Animations - */ - var enabled: Boolean = true, - - /** - * Number of milliseconds the animation is running before it ends - */ - var duration: Int = 1000, - - /** - * Number of updates per seconds - */ - var refreshRate: Int = 50 -) { - /** - * Update the value depending on the maximum obtainable value - * - * @param maxValue the maximum value the item can obtain - * @param targetValue the value you want to obtain at the end of the animation - * @param currentValue the current value - * - * @return the new updated value - */ - fun updateValue( - maxValue: Float, - targetValue: Float, - currentValue: Float, - minValue: Float, - minStep: Float - ): Float { - if (!enabled) { - return targetValue - } - - if (currentValue < minValue) { - return minValue - } - - val moveValue = max(minStep, (maxValue - targetValue) / refreshRate) - - var result = targetValue - if (currentValue < targetValue) { - result = currentValue + moveValue - } else if (currentValue > targetValue) { - result = currentValue - moveValue - } - - if ( - abs(targetValue - currentValue) <= moveValue || - result < minValue || - result > maxValue - ) { - return targetValue - } - return result - } - - fun getDelay() = this.duration / this.refreshRate -} diff --git a/charts/src/main/java/com/dzeio/charts/ChartView.kt b/charts/src/main/java/com/dzeio/charts/ChartView.kt deleted file mode 100644 index d48b004..0000000 --- a/charts/src/main/java/com/dzeio/charts/ChartView.kt +++ /dev/null @@ -1,150 +0,0 @@ -package com.dzeio.charts - -import android.annotation.SuppressLint -import android.content.Context -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.RectF -import android.util.AttributeSet -import android.view.MotionEvent -import android.view.View -import com.dzeio.charts.axis.XAxis -import com.dzeio.charts.axis.YAxis -import com.dzeio.charts.components.ChartScroll -import com.dzeio.charts.series.SerieInterface - -class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) : - View(context, attrs), ChartViewInterface { - - private companion object { - const val TAG = "Charts/ChartView" - } - - override var debug: Boolean = false - - override val xAxis = XAxis(this) - - override val yAxis = YAxis(this) - - override var series: ArrayList = arrayListOf() - - override var padding: Float = 8f - - private val scroller = ChartScroll(this).apply { - var lastMovement = 0.0 - setOnChartMoved { movementX, _ -> - xAxis.x += (movementX - lastMovement) * xAxis.getDataWidth() / width - lastMovement = movementX.toDouble() - refresh() - } -// setOnZoomChanged { -// Log.d(TAG, "New Zoom: $it") -// zoom = (it * 1.2).toFloat() -// refresh() -// } - } - -// val animator: Runnable = object : Runnable { -// override fun run() { -// var needNewFrame = false -// for (serie in series) { -// val result = serie.onUpdate() -// if (result) { -// needNewFrame = true -// } -// } -// if (needNewFrame) { -// postDelayed(this, animation.getDelay().toLong()) -// } -// invalidate() -// } -// } - - // rect used for calculations - private val rect = RectF() - - // stroke used while in debug - private val debugStrokePaint = Paint().apply { - style = Paint.Style.STROKE - strokeWidth = 8f - color = Color.parseColor("#654321") - } - - override fun refresh() { - // run Axis logics - xAxis.refresh() - yAxis.refresh() - - // run series logic - for (serie in series) { - serie.refresh() - } - - // invalidate the view - invalidate() -// removeCallbacks(animator) -// post(animator) - } - - override fun onDraw(canvas: Canvas) { - - // don't draw anything if everything is empty - if (series.isEmpty() || series.maxOf { it.entries.size } == 0) { - super.onDraw(canvas) - return - } - - if (debug) { - // draw corners - canvas.drawRect(rect.apply { - set( - padding / 2, - padding / 2, - width.toFloat() - padding / 2, - height.toFloat() - padding / 2 - ) - }, debugStrokePaint) - } - - - val bottom = xAxis.onDraw(canvas, rect.apply { - set(padding, 0f, width.toFloat() - padding, height.toFloat() - padding) - }) - - // right distance from the yAxis - val rightDistance = yAxis.onDraw(canvas, rect.apply { - set(padding, padding, width.toFloat() - padding, height.toFloat() - bottom - padding) - }) - - // chart draw rectangle - rect.apply { - set( - padding, - padding, - width.toFloat() - padding - rightDistance, - height - bottom - padding - ) - } - - for (serie in series) { - serie.onDraw(canvas, rect) - } - super.onDraw(canvas) - } - - @SuppressLint("ClickableViewAccessibility") - override fun onTouchEvent(event: MotionEvent): Boolean { - performClick() - return scroller.onTouchEvent(event) - } - - override fun getDataset(): ArrayList { - val data: ArrayList = arrayListOf() - for (serie in series) { - data.addAll(serie.entries) - } - data.sortBy { it.x } - return data.filterIndexed { index, entry -> data.indexOf(entry) == index } as ArrayList - } -} diff --git a/charts/src/main/java/com/dzeio/charts/ChartViewInterface.kt b/charts/src/main/java/com/dzeio/charts/ChartViewInterface.kt deleted file mode 100644 index b566f21..0000000 --- a/charts/src/main/java/com/dzeio/charts/ChartViewInterface.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.dzeio.charts - -import com.dzeio.charts.axis.XAxisInterface -import com.dzeio.charts.axis.YAxisInterface -import com.dzeio.charts.series.SerieInterface - -interface ChartViewInterface { - - /** - * Make the whole view in debug mode - * - * add debug texts, logs, and more - */ - var debug: Boolean - - /** - * the padding inside the view - */ - var padding: Float - - /** - * Hold metadata about the X axis - */ - val xAxis: XAxisInterface - - /** - * Hold informations about the Y axis - */ - val yAxis: YAxisInterface - - /** - * handle the series - */ - var series: ArrayList - - /** - * refresh and run pre-display logic the chart - * - * this function should be run if you change parameters in the view - */ - fun refresh() - - /** - * @return the whole dataset (sorted and cleaned up of dupps) - */ - fun getDataset(): ArrayList -} \ No newline at end of file diff --git a/charts/src/main/java/com/dzeio/charts/Entry.kt b/charts/src/main/java/com/dzeio/charts/Entry.kt deleted file mode 100644 index 526fec8..0000000 --- a/charts/src/main/java/com/dzeio/charts/Entry.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.dzeio.charts - -/** - * A Base entry for any charts - */ -data class Entry( - var x: Double, - var y: Float, - var color: Int? = null -) diff --git a/charts/src/main/java/com/dzeio/charts/axis/XAxis.kt b/charts/src/main/java/com/dzeio/charts/axis/XAxis.kt deleted file mode 100644 index 458c6b6..0000000 --- a/charts/src/main/java/com/dzeio/charts/axis/XAxis.kt +++ /dev/null @@ -1,125 +0,0 @@ -package com.dzeio.charts.axis - -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.Rect -import android.graphics.RectF -import com.dzeio.charts.ChartViewInterface -import com.dzeio.charts.Entry - -class XAxis( - private val view: ChartViewInterface -) : XAxisInterface { - override var x: Double = 0.0 - set(value) { - val max = getXMax() - getDataWidth() - val min = getXMin() - if (value > max && min <= max) { - field = max - return - } - - if (value < min) { - field = min - return - } - - field = value - } - - override var enabled = true - - override var dataWidth: Double? = null - - override var labelCount: Int = 2 - - var spacing = 16.0 - - override val textPaint = Paint().apply { - isAntiAlias = true - color = Color.parseColor("#FC496D") - textSize = 30f - textAlign = Paint.Align.LEFT - } - - private val rect = Rect() - - override fun getPositionOnRect(entry: Entry, drawableSpace: RectF): Double { - return translatePositionToRect(entry.x, drawableSpace) - } - - fun translatePositionToRect(value: Double, drawableSpace: RectF): Double { - return drawableSpace.width() * (value - x) / getDataWidth() - } - - override fun getXMax(): Double { - return view.series.maxOf { serie -> - if (serie.entries.isEmpty()) { - return 0.0 - } - serie.entries.maxOf { entry -> entry.x } - } - } - - override fun getXMin(): Double { - return view.series.minOf { serie -> - if (serie.entries.isEmpty()) { - return 0.0 - } - serie.entries.minOf { entry -> entry.x } - } - } - - var onValueFormat: (value: Double) -> String = { it -> it.toString() } - - override fun onDraw(canvas: Canvas, space: RectF): Float { - if (!enabled) { - return 0f - } - - var maxHeight = 0f - - val graphIncrement = space.width() / (labelCount - 1) - val valueIncrement = (getDataWidth() / (labelCount - 1)).toDouble() - for (index in 0 until labelCount) { - val text = onValueFormat(x + valueIncrement * index) - textPaint.getTextBounds(text, 0, text.length, rect) - maxHeight = maxHeight.coerceAtLeast(rect.height().toFloat() + 1) - - var xPos = space.left + graphIncrement * index - - if (xPos + rect.width() > space.right) { - xPos = space.right - rect.width() - } - - canvas.drawText( - text, - xPos, - space.bottom, - textPaint - ) - } - return maxHeight + 32f - } - - override fun refresh() { -// TODO("Not yet implemented") - } - - override fun getEntryWidth(drawableSpace: RectF): Double { - var smallest = -1.0 - val dataset = view.getDataset() - for (idx in 0 until dataset.size - 1) { - val distance = dataset[idx + 1].x - dataset[idx].x - if (smallest == -1.0 || smallest > distance) { - smallest = distance - } - } - return drawableSpace.width() * smallest / getDataWidth() - spacing - } - - override fun getDataWidth(): Double { - return dataWidth ?: (getXMax() - getXMin()) - } -} diff --git a/charts/src/main/java/com/dzeio/charts/axis/XAxisInterface.kt b/charts/src/main/java/com/dzeio/charts/axis/XAxisInterface.kt deleted file mode 100644 index daa9f55..0000000 --- a/charts/src/main/java/com/dzeio/charts/axis/XAxisInterface.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.dzeio.charts.axis - -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.RectF -import com.dzeio.charts.Entry - -sealed interface XAxisInterface { - - /** - * enable/disable the display of the xAxis - */ - var enabled: Boolean - - /** - * set X position - */ - var x: Double - - /** - * the "width" of the graph - * - * if not set it will be `XMax - XMin` - * - * ex: to display a 7 days graph history with x values being timestamp in secs, use 7*24*60*60 - */ - var dataWidth: Double? - - /** - * text Paint - */ - val textPaint: Paint - - /** - * indicate the number of labels displayed - */ - var labelCount: Int - - /** - * run when manually refreshing the system - * - * this is where the pre-logic is handled to make [onDraw] quicker - */ - fun refresh() - - /** - * get the entry position on the rect - * - * @return the left side of the position of the entry - */ - fun getPositionOnRect(entry: Entry, drawableSpace: RectF): Double - - /** - * get the maximum the X can get to - */ - fun getXMax(): Double - - /** - * get the minimum the X can get to - */ - fun getXMin(): Double - - /** - * get the size of an entry in the graph - * - * @return the size in [drawableSpace] px - */ - fun getEntryWidth(drawableSpace: RectF): Double - - /** - * return the currently used dataWidth - */ - fun getDataWidth(): Double - - /** - * onDraw event that will draw the XAxis - * - * @param canvas the canvas to draw on - * @param space the space where it is allowed to draw - * - * @return the final height of the XAxis - */ - fun onDraw(canvas: Canvas, space: RectF): Float -} \ No newline at end of file diff --git a/charts/src/main/java/com/dzeio/charts/axis/YAxis.kt b/charts/src/main/java/com/dzeio/charts/axis/YAxis.kt deleted file mode 100644 index 314520b..0000000 --- a/charts/src/main/java/com/dzeio/charts/axis/YAxis.kt +++ /dev/null @@ -1,145 +0,0 @@ -package com.dzeio.charts.axis - -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.Rect -import android.graphics.RectF -import com.dzeio.charts.ChartViewInterface -import com.dzeio.charts.utils.drawDottedLine - -class YAxis( - private val view: ChartViewInterface -) : YAxisInterface { - - override var enabled = true - - override val textLabel = Paint().apply { - isAntiAlias = true - color = Color.parseColor("#FC496D") - textSize = 30f - textAlign = Paint.Align.LEFT - } - - override val linePaint = Paint().apply { - isAntiAlias = true - color = Color.BLUE - } - - override val goalLinePaint = Paint().apply { - isAntiAlias = true - color = Color.RED - strokeWidth = 4f - } - - var onValueFormat: (value: Float) -> String = { it -> it.toString() } - - override var labelCount = 5 - - private var min: Float? = 0f - private var max: Float? = null - - private val rect = Rect() - - override fun setYMin(yMin: Float?): YAxisInterface { - min = yMin - return this - } - - override fun setYMax(yMax: Float?): YAxisInterface { - max = yMax - return this - } - - override fun getYMax(): Float { - if (max != null) { - return max!! - } - if (view.series.isEmpty()) { - return (this.goalLine ?: 90f) + 10f - } - val seriesMax = view.series - .maxOf { serie -> - if (serie.getDisplayedEntries().isEmpty()) { - return@maxOf 0f - } - return@maxOf serie.getDisplayedEntries().maxOf { entry -> entry.y } - } - if (this.goalLine != null) { - return if (seriesMax > this.goalLine!!) seriesMax else this.goalLine!! + 1000f - } - return seriesMax - } - - override fun getYMin(): Float { - if (min != null) { - return min!! - } - if (view.series.isEmpty()) { - return this.goalLine ?: 0f - } - return view.series - .minOf { serie -> - if (serie.getDisplayedEntries().isEmpty()) { - return@minOf 0f - } - return@minOf serie.getDisplayedEntries().minOf { entry -> entry.y } - } - } - - override fun onDraw(canvas: Canvas, space: RectF): Float { - if (!enabled) { - return 0f - } - - val min = getYMin() - val max = getYMax() - min - val top = space.top - val bottom = space.bottom - var maxWidth = 0f - - val increment = (bottom - top) / labelCount - val valueIncrement = (max - min) / labelCount - for (index in 0 until labelCount) { - val text = onValueFormat((valueIncrement * (index + 1))) - textLabel.getTextBounds(text, 0, text.length, rect) - maxWidth = maxWidth.coerceAtLeast(rect.width().toFloat()) - - val posY = bottom - (index + 1) * increment - - canvas.drawText( - text, - space.width() - rect.width().toFloat(), - (posY + rect.height() / 2).coerceAtLeast(rect.height().toFloat()), - textLabel - ) -// canvas.drawDottedLine(0f, posY, canvas.width.toFloat(), posY, 40f, linePaint) - canvas.drawLine(space.left, posY, space.right - maxWidth - 32f, posY, linePaint) - - } - - if (this.goalLine != null) { - val pos = (1 - this.goalLine!! / max) * space.height() + space.top - canvas.drawDottedLine( - 0f, - pos, - space.right - maxWidth - 32f, - pos, - space.right / 20, - goalLinePaint - ) - } - - return maxWidth + 32f - } - - override fun refresh() { -// TODO("Not yet implemented") - } - - private var goalLine: Float? = null - - override fun setGoalLine(height: Float?) { - goalLine = height - } -} diff --git a/charts/src/main/java/com/dzeio/charts/axis/YAxisInterface.kt b/charts/src/main/java/com/dzeio/charts/axis/YAxisInterface.kt deleted file mode 100644 index b82afe2..0000000 --- a/charts/src/main/java/com/dzeio/charts/axis/YAxisInterface.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.dzeio.charts.axis - -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.RectF - -sealed interface YAxisInterface { - - /** - * whether or not this axis is displayed - */ - var enabled: Boolean - - /** - * get/set the number of label of this Y axis - * - * the first/last labels are at the bottom/top of the chart - */ - var labelCount: Int - - /** - * text label paint - */ - val textLabel: Paint - - /** - * paint for the lines - */ - val linePaint: Paint - - /** - * Goal line paint - */ - val goalLinePaint: Paint - - /** - * run when manually refreshing the system - * - * this is where the pre-logic is handled to make [onDraw] quicker - */ - fun refresh() - - /** - * override Y minimum - * - * @param yMin is set the min will ba at the value, if null it is calculated - */ - fun setYMin(yMin: Float?): YAxisInterface - - /** - * override Y maximum - * - * @param yMax is set the max will ba at the value, if null it is calculated - */ - fun setYMax(yMax: Float?): YAxisInterface - - /** - * get Y maximum - * - * @return the maximum value Y can get (for displayed values) - */ - fun getYMax(): Float - - /** - * get Y minimum - * - * @return the minimum value Y can get (for displayed values) - */ - fun getYMin(): Float - - /** - * function that draw our legend - * - * @param canvas the canvas to draw on - * @param space the space where it is allowed to draw on - * - * @return the width of the sidebar - */ - fun onDraw(canvas: Canvas, space: RectF): Float - - /** - * Add a Goal line - */ - fun setGoalLine(height: Float?) -} diff --git a/charts/src/main/java/com/dzeio/charts/axis/YAxisPosition.kt b/charts/src/main/java/com/dzeio/charts/axis/YAxisPosition.kt deleted file mode 100644 index d134c6d..0000000 --- a/charts/src/main/java/com/dzeio/charts/axis/YAxisPosition.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.dzeio.charts.axis - -/** - * CURRENTLY UNUSED - * - * declare where the YAxis for the graph will be - */ -enum class YAxisPosition { - LEFT, - RIGHT -} \ No newline at end of file diff --git a/charts/src/main/java/com/dzeio/charts/components/ChartScroll.kt b/charts/src/main/java/com/dzeio/charts/components/ChartScroll.kt deleted file mode 100644 index 38e1b9f..0000000 --- a/charts/src/main/java/com/dzeio/charts/components/ChartScroll.kt +++ /dev/null @@ -1,144 +0,0 @@ -package com.dzeio.charts.components - -import android.view.MotionEvent -import android.view.MotionEvent.INVALID_POINTER_ID -import android.view.ScaleGestureDetector -import android.view.View - -/** - * Class handling the scroll/zoom for the library - */ -class ChartScroll(view: View) { - - /** - * Enabled the zoom/unzoom of datas - */ - var zoomEnabled = true - - /** - * Enable the horizontal scroll feature - */ - var scrollEnabled = true - - // The ‘active pointer’ is the one currently moving our object. - private var activePointerId = INVALID_POINTER_ID - - private var lastTouchX: Float = 0f - private var lastTouchY: Float = 0f - - private var posX: Float = 0f - private var posY: Float = 0f - - private var lastZoom: Float = 100f - private var currentZoom: Float = 0f - - private var onChartMoved: ((movementX: Float, movementY: Float) -> Unit)? = null - fun setOnChartMoved(fn: (movementX: Float, movementY: Float) -> Unit) { - onChartMoved = fn - } - - private var onZoomChanged: ((scale: Float) -> Unit)? = null - - /** - * @param fn.scale Float starting from 100% - * - * 99-% zoom out, - * 101+% zoom in - */ - fun setOnZoomChanged(fn: (scale: Float) -> Unit) { - onZoomChanged = fn - } - - private val scaleGestureDetector = ScaleGestureDetector( - view.context, - object : ScaleGestureDetector.SimpleOnScaleGestureListener() { - override fun onScale(detector: ScaleGestureDetector): Boolean { - if (currentZoom != detector.scaleFactor) { - currentZoom = detector.scaleFactor - onZoomChanged?.invoke(lastZoom + -currentZoom + 1) - } - - return super.onScale(detector) - } - - override fun onScaleEnd(detector: ScaleGestureDetector) { - super.onScaleEnd(detector) - - lastZoom += -currentZoom + 1 - } - } - ) - - /** - * Code mostly stolen from https://developer.android.com/training/gestures/scale#drag - */ - fun onTouchEvent(ev: MotionEvent): Boolean { - - if (zoomEnabled) { - scaleGestureDetector.onTouchEvent(ev) - } - - when (ev.actionMasked) { - MotionEvent.ACTION_DOWN -> { - onToggleScroll?.invoke(false) - ev.actionIndex.also { pointerIndex -> - // Remember where we started (for dragging) - lastTouchX = ev.getX(pointerIndex) - lastTouchY = ev.getY(pointerIndex) - } - - // Save the ID of this pointer (for dragging) - activePointerId = ev.getPointerId(0) - } - - MotionEvent.ACTION_MOVE -> { - // Find the index of the active pointer and fetch its position - val (x: Float, y: Float) = - ev.findPointerIndex(activePointerId).let { pointerIndex -> - // Calculate the distance moved - ev.getX(pointerIndex) to ev.getY(pointerIndex) - } - - posX += x - lastTouchX - posY += y - lastTouchY - - if (scrollEnabled) { - onChartMoved?.invoke(-posX, posY) - } - - // Remember this touch position for the next move event - lastTouchX = x - lastTouchY = y - } - MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { - onToggleScroll?.invoke(true) - activePointerId = INVALID_POINTER_ID - } - MotionEvent.ACTION_POINTER_UP -> { - onToggleScroll?.invoke(true) - ev.actionIndex.also { pointerIndex -> - ev.getPointerId(pointerIndex) - .takeIf { it == activePointerId } - ?.run { - // This was our active pointer going up. Choose a new - // active pointer and adjust accordingly. - val newPointerIndex = if (pointerIndex == 0) 1 else 0 - lastTouchX = ev.getX(newPointerIndex) - lastTouchY = ev.getY(newPointerIndex) - activePointerId = ev.getPointerId(newPointerIndex) - } - } - } - } - return true - } - - private var onToggleScroll: ((Boolean) -> Unit)? = null - - /** - * @param ev if input is false disable scroll - */ - fun setOnToggleScroll(ev: (Boolean) -> Unit) { - onToggleScroll = ev - } -} diff --git a/charts/src/main/java/com/dzeio/charts/series/BarSerie.kt b/charts/src/main/java/com/dzeio/charts/series/BarSerie.kt deleted file mode 100644 index 50226fa..0000000 --- a/charts/src/main/java/com/dzeio/charts/series/BarSerie.kt +++ /dev/null @@ -1,125 +0,0 @@ -package com.dzeio.charts.series - -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.Rect -import android.graphics.RectF -import android.util.Log -import com.dzeio.charts.ChartView -import com.dzeio.charts.utils.drawRoundRect - -class BarSerie( - private val view: ChartView -) : BaseSerie(view) { - - private companion object { - const val TAG = "Charts/BarSerie" - } - - init { - view.series.add(this) - } - - val barPaint = Paint().apply { - isAntiAlias = true - color = Color.parseColor("#123456") - } - - val textPaint = Paint().apply { - isAntiAlias = true - color = Color.parseColor("#FC496D") - textSize = 30f - textAlign = Paint.Align.CENTER - } - - private val rect = Rect() - - override fun onDraw(canvas: Canvas, drawableSpace: RectF) { - val displayedEntries = getDisplayedEntries() - val barWidth = view.xAxis.getEntryWidth(drawableSpace).toFloat() - val max = view.yAxis.getYMax() - val min = view.yAxis.getYMin() - -// Log.d(TAG, "${space.left}, ${space.right}") - - for (entry in displayedEntries) { - // calculated height in percent from 0 to 100 - val top = (1 - entry.y / max) * drawableSpace.height() + drawableSpace.top - var posX = drawableSpace.left + view.xAxis.getPositionOnRect( - entry, - drawableSpace - ).toFloat() - - val right = (posX + barWidth).coerceAtMost(drawableSpace.right) - - if (posX > right) { - continue - } else if (posX < drawableSpace.left) { - posX = drawableSpace.left - } - - if (right < drawableSpace.left) { - continue - } - - // handle color recoloration - val paint = Paint(barPaint) - - if (entry.color != null) { - paint.color = entry.color!! - } - - canvas.drawRoundRect( - posX, - top, - right, - drawableSpace.bottom, -// 8f, 8f, - 32f, - 32f, - 0f, - 0f, - paint - ) - - // handle text display - val text = view.yAxis.onValueFormat(entry.y) - - textPaint.getTextBounds(text, 0, text.length, rect) - - val textLeft = (posX + barWidth / 2) - - if ( - // handle right side - textLeft + rect.width() / 2 > right || - // handle left sie - textLeft - rect.width() / 2 < drawableSpace.left - ) { - continue - } - - val doDisplayIn = - rect.height() + 40f < drawableSpace.bottom - top && - rect.width() < barWidth - - var textY = if (doDisplayIn) top + rect.height() + 20f else top - 20f - - if (textY < 0) { - textY = drawableSpace.top + rect.height() - } - - - canvas.drawText( - text, - textLeft, - textY, - textPaint - ) - } - } - - override fun refresh() { -// TODO("Not yet implemented") - } -} diff --git a/charts/src/main/java/com/dzeio/charts/series/BarSerie.kt.old b/charts/src/main/java/com/dzeio/charts/series/BarSerie.kt.old deleted file mode 100644 index b6205e0..0000000 --- a/charts/src/main/java/com/dzeio/charts/series/BarSerie.kt.old +++ /dev/null @@ -1,160 +0,0 @@ -package com.dzeio.charts.series - -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.Rect -import android.graphics.RectF -import android.util.Log -import kotlin.math.max - -class BarSerie : SerieAbstract() { - - companion object { - const val TAG = "DzeioCharts/BarSerie" - } - - var spacing: Float = 8f - - /** - * Values displayed on the grapd - */ - var displayedDatas = arrayListOf() - - /** - * Target values - */ - var targetDatas = arrayListOf() - - var targetPercentList = arrayListOf() - var percentList = arrayListOf() - - var previousRefresh = 0 - - private var fgPaint: Paint = Paint().apply { - isAntiAlias = true - } - - private val r = Rect() - - override fun onUpdate(): Boolean { - var needNewFrame = false - for (i in targetPercentList.indices) { - val value = view.animation.updateValue( - 1f, - targetPercentList[i], - percentList[i], - 0f, - 0.00f - ) - - if (value != percentList[i]) { - needNewFrame = true - percentList[i] = value - } - } - return needNewFrame - } - - override fun prepareData() { - val max: Float = if (view.yAxis.max != null) view.yAxis.max!! else { - getYMax(true) - } - - targetPercentList = arrayListOf() - -// Log.d(TAG, "offset: ${view.getXOffset()}, displayed: ${view.getDisplayedEntries()}") - for (item in getDisplayedEntries()) { -// // // Process bottom texts -// val text = view.xAxis.onValueFormat(item.x) -// bottomTexts.add(text) -// -// // get Text boundaries -// view.xAxis.labels.build().getTextBounds(text, 0, text.length, r) -// -// // get height of text -// if (bottomTextHeight < r.height()) { -// bottomTextHeight = r.height() -// } -// -// // get text descent -// val descent = abs(r.bottom) -// if (bottomTextDescent < descent) { -// bottomTextDescent = descent -// } - - // process values -// Log.d(TAG, item.y.toString()) - - // add to animations the values - targetPercentList.add(1 - item.y / max) - } - - // post list - val offset = view.getXOffset() - val movement = offset - previousRefresh - Log.d(TAG, "$offset - $previousRefresh = $movement") - if (movement != 0) { - previousRefresh = offset - } -// if (movement != 0) { -// Log.d(TAG, movement.toString()) -// } - if (movement >= 1) { - percentList = percentList.subList(1, percentList.size).toCollection(ArrayList()) - percentList.add(1f) - } else if (movement <= -1) { - percentList = percentList.subList(0, percentList.size - 1).toCollection(ArrayList()) - percentList.add(0, 1f) - } - - if (percentList.isEmpty() || percentList.size < targetPercentList.size) { - val temp = targetPercentList.size - percentList.size - for (i in 0 until temp) { - percentList.add(1f) - } - } else if (percentList.size > targetPercentList.size) { - val temp = percentList.size - targetPercentList.size - for (i in 0 until temp) { - percentList.removeAt(percentList.size - 1) - } - } - - fgPaint.color = view.yAxis.color - } - - override fun displayData(canvas: Canvas, rect: RectF) { - val barWidth = (rect.width() - view.padding * 2) / view.getDisplayedEntries() - spacing - - if (percentList.isNotEmpty()) { - // draw each rectangles - for (i in 1..percentList.size) { -// Log.d(TAG, percentList[i - 1].toString()) - val left = rect.left + spacing * i + barWidth * (i - 1).toFloat() + view.padding -// Log.d(TAG, "$spacing, $i, $barWidth = $left") - val right = rect.left + (spacing + barWidth) * i.toFloat() - val bottom = rect.top + rect.height() - view.padding - val top = (bottom - rect.top) * percentList[i - 1] + view.padding - - // create rounded rect - canvas.drawRoundRect(left, top, right, bottom, 8f, 8f, fgPaint) - // remove the bottom corners DUH - canvas.drawRect(left, max(top, bottom - 8f), right, bottom, fgPaint) - val targetTop = (bottom - rect.top) * targetPercentList[i - 1] - - val text = view.yAxis.onValueFormat(getYMax(true) - getYMax(true) * targetPercentList[i - 1], true) - view.xAxis.labels.build().getTextBounds(text, 0, text.length, r) - val doDisplayIn = - r.width() + 10f < barWidth && bottom - targetTop > r.height() + 40f - if (view.debug || !doDisplayIn || (doDisplayIn && bottom - top > r.height() + 40f)) { - val y = if (doDisplayIn) top + r.height() + 20f else top - r.height() - canvas.drawText( - text, - left + (right - left) / 2, - y, - view.xAxis.labels.build() - ) - } - } - } - } -} diff --git a/charts/src/main/java/com/dzeio/charts/series/BaseSerie.kt b/charts/src/main/java/com/dzeio/charts/series/BaseSerie.kt deleted file mode 100644 index dfce84b..0000000 --- a/charts/src/main/java/com/dzeio/charts/series/BaseSerie.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.dzeio.charts.series - -import android.graphics.Canvas -import android.graphics.RectF -import com.dzeio.charts.ChartViewInterface -import com.dzeio.charts.Entry -import com.dzeio.charts.axis.YAxisPosition - -sealed class BaseSerie( - private val view: ChartViewInterface -) : SerieInterface { - - private companion object { - const val TAG = "Charts/BaseSerie" - } - - override var yAxisPosition: YAxisPosition = YAxisPosition.RIGHT - - override var entries: ArrayList = arrayListOf() - - override fun getDisplayedEntries(): ArrayList { - val minX = view.xAxis.x - val maxX = minX + view.xAxis.getDataWidth() - - val result: ArrayList = arrayListOf() - - var lastIndex = -1 - for (i in 0 until entries.size) { - val it = entries[i] - if (it.x in minX..maxX) { - if (result.size === 0 && i > 0) { - result.add((entries[i - 1])) - } - lastIndex = i - result.add(it) - } - } - - if (lastIndex < entries.size - 1) { - result.add(entries [lastIndex + 1]) - } - - return result - } - - abstract override fun onDraw(canvas: Canvas, drawableSpace: RectF) -} diff --git a/charts/src/main/java/com/dzeio/charts/series/LineSerie.kt b/charts/src/main/java/com/dzeio/charts/series/LineSerie.kt deleted file mode 100644 index 289e8cc..0000000 --- a/charts/src/main/java/com/dzeio/charts/series/LineSerie.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.dzeio.charts.series - -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.RectF -import com.dzeio.charts.ChartView - -class LineSerie( - private val view: ChartView -) : BaseSerie(view) { - - private companion object { - const val TAG = "Charts/LineSerie" - } - - init { - view.series.add(this) - } - - val linePaint = Paint().apply { - isAntiAlias = true - color = Color.parseColor("#123456") - strokeWidth = 5f - } - - val textPaint = Paint().apply { - isAntiAlias = true - color = Color.parseColor("#FC496D") - textSize = 30f - textAlign = Paint.Align.CENTER - } - - override fun onDraw(canvas: Canvas, drawableSpace: RectF) { - val displayedEntries = getDisplayedEntries() - displayedEntries.sortBy { it.x } - val max = view.yAxis.getYMax() - - var previousPosX: Float? = null - var previousPosY: Float? = null - - for (entry in displayedEntries) { - // calculated height in percent from 0 to 100 - val top = (1 - entry.y / max) * drawableSpace.height() + drawableSpace.top - val posX = (drawableSpace.left + - view.xAxis.getPositionOnRect(entry, drawableSpace) + - view.xAxis.getEntryWidth(drawableSpace) / 2f).toFloat() - - // handle color recoloration - val paint = Paint(linePaint) - - if (entry.color != null) { - paint.color = entry.color!! - } - - // draw smol point - if (posX < drawableSpace.right) { - canvas.drawCircle(posX, top, paint.strokeWidth, paint) - } - - // draw line - if (previousPosX != null && previousPosY != null) { - canvas.drawLine(previousPosX, previousPosY, posX, top, paint) - - } - previousPosX = posX - previousPosY = top - } - } - - override fun refresh() { -// TODO("Not yet implemented") - } -} diff --git a/charts/src/main/java/com/dzeio/charts/series/SerieInterface.kt b/charts/src/main/java/com/dzeio/charts/series/SerieInterface.kt deleted file mode 100644 index e018dfe..0000000 --- a/charts/src/main/java/com/dzeio/charts/series/SerieInterface.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.dzeio.charts.series - -import android.graphics.Canvas -import android.graphics.RectF -import com.dzeio.charts.Entry -import com.dzeio.charts.axis.YAxisPosition - -sealed interface SerieInterface { - - /** - * location of the Y axis - */ - var yAxisPosition: YAxisPosition - - /** - * filter out out of display entries - * - * @return the list of entries displayed - */ - fun getDisplayedEntries(): ArrayList - - /** - * set the entries for the list - */ - var entries: ArrayList - - /** - * function that display the graph - * - * @param canvas the canvas to draw on - * @param drawableSpace the space you are allowed to draw on - */ - fun onDraw(canvas: Canvas, drawableSpace: RectF) - - /** - * run when manually refreshing the system - * - * this is where the pre-logic is handled to make [onDraw] quicker - */ - fun refresh() -} \ No newline at end of file diff --git a/charts/src/main/java/com/dzeio/charts/utils/CanvasUtils.kt b/charts/src/main/java/com/dzeio/charts/utils/CanvasUtils.kt deleted file mode 100644 index 781e76a..0000000 --- a/charts/src/main/java/com/dzeio/charts/utils/CanvasUtils.kt +++ /dev/null @@ -1,144 +0,0 @@ -package com.dzeio.charts.utils - -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.RectF -import kotlin.math.sqrt - -/** - * draw a dotted line - */ -fun Canvas.drawDottedLine( - startX: Float, - startY: Float, - endX: Float, - endY: Float, - spacing: Float, - paint: Paint -) { - //calculate line length - val length = if (endX - startX == 0f) { - // just length of Y - endY - startY - } else if (endY - startY == 0f) { - // just length of X - endX - startX - } else { - // calculate using the Pythagorean theorem - sqrt((startX + endX) * (startX + endX) + (startY + endY) * (startY + endY)) - } - - val lineCount = (length / spacing).toInt() - - val lenX = endX - startX - val lenY = endY - startY - -// Log.d("DrawDottedLine", "----------- Start -----------") -// Log.d("DrawDottedLine", "lenX: $lenX, lenY: $lenY") - for (line in 0 until lineCount) { - if (line % 2 == 0) { - continue - } - - val sx = lenX / lineCount * line + startX - val sy = lenY / lineCount * line + startY - val ex = lenX / lineCount * (line + 1) + startX - val ey = lenY / lineCount * (line + 1) + startY -// Log.d("DrawDottedLine", "$sx, $sy, $ex, $ey") - this.drawLine(sx, sy, ex, ey, paint) - // line - // total line startX, endX, startY, endY - // total line length - } -} - -/** - * A more customizable drawRoundRect function - */ -fun Canvas.drawRoundRect( - left: Float, - top: Float, - right: Float, - bottom: Float, - topLeft: Float, - topRight: Float, - bottomLeft: Float, - bottomRight: Float, - paint: Paint -) { - val maxRound = arrayOf(topLeft, topRight, bottomLeft, bottomRight).maxOf { it } - val width = right - left - val height = bottom - top - - // draw first/global rect - drawRoundRect(left, top, right, bottom, maxRound, maxRound, paint) - - // top left border - if (topLeft == 0f) { - drawRect(left, top, left + width / 2, top + height / 2, paint) - } else { - drawRoundRect(left, top, left + width / 2, top + height / 2, topLeft, topLeft, paint) - } - - // top right border - if (topRight == 0f) { - drawRect(right - width / 2, top, right, top + height / 2, paint) - } else { - drawRoundRect(right - width / 2, top, right, top + height / 2, topRight, topRight, paint) - } - - // bottom left border - if (bottomLeft == 0f) { - drawRect(left, bottom - height / 2, left + width / 2, bottom, paint) - } else { - drawRoundRect( - left, - bottom - height / 2, - left + width / 2, - bottom, - bottomLeft, - bottomLeft, - paint - ) - } - - // bottom right border - if (bottomRight == 0f) { - drawRect(right - width / 2, bottom - height / 2, right, bottom, paint) - } else { - drawRoundRect( - right - width / 2, - bottom - height / 2, - right, - bottom, - bottomRight, - bottomRight, - paint - ) - } - -} - -/** - * A more customizable drawRoundRect function - */ -fun Canvas.drawRoundRect( - rect: RectF, - topLeft: Float, - topRight: Float, - bottomLeft: Float, - bottomRight: Float, - paint: Paint -) { - drawRoundRect( - rect.left, - rect.top, - rect.right, - rect.bottom, - topLeft, - topRight, - bottomLeft, - bottomRight, - paint - ) -} diff --git a/charts/src/test/java/com/dzeio/charts/ExampleUnitTest.kt b/charts/src/test/java/com/dzeio/charts/ExampleUnitTest.kt deleted file mode 100644 index cf39879..0000000 --- a/charts/src/test/java/com/dzeio/charts/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.dzeio.charts - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/settings.gradle b/settings.gradle index 4db8ff9..2f2da57 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,4 +18,3 @@ dependencyResolutionManagement { rootProject.name = "OpenHealth" include ':app' -include ':charts'