Skip to content

Commit fd1cdbd

Browse files
committed
Move 'view' demos to a subfolder.
1 parent e4c6ca1 commit fd1cdbd

24 files changed

+940
-1
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2023. JetBrains s.r.o.
3+
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4+
*/
5+
6+
plugins {
7+
kotlin("android")
8+
id("com.android.application")
9+
}
10+
11+
android {
12+
compileSdk = (findProperty("android.compileSdk") as String).toInt()
13+
namespace = "demo.plot.view"
14+
15+
defaultConfig {
16+
applicationId = "demo.plot.view"
17+
18+
minSdk = (findProperty("android.minSdk") as String).toInt()
19+
targetSdk = (findProperty("android.targetSdk") as String).toInt()
20+
21+
versionCode = 1
22+
versionName = "1.0"
23+
24+
}
25+
26+
buildTypes {
27+
debug {
28+
isDebuggable = true
29+
}
30+
}
31+
32+
compileOptions {
33+
sourceCompatibility = JavaVersion.VERSION_11
34+
targetCompatibility = JavaVersion.VERSION_11
35+
}
36+
37+
kotlin {
38+
jvmToolchain(11)
39+
}
40+
}
41+
42+
val letsPlotVersion = extra["letsPlot.version"] as String
43+
val letsPlotKotlinVersion = extra["letsPlotKotlin.version"] as String
44+
45+
dependencies {
46+
implementation(project(":platf-android"))
47+
implementation(project(":demo-plot-shared"))
48+
implementation("org.jetbrains.lets-plot:lets-plot-kotlin-kernel:${letsPlotKotlinVersion}")
49+
implementation("org.jetbrains.lets-plot:lets-plot-common:$letsPlotVersion")
50+
implementation("org.jetbrains.lets-plot:canvas:${letsPlotVersion}")
51+
implementation("org.jetbrains.lets-plot:plot-raster:$letsPlotVersion")
52+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools" >
4+
5+
<application
6+
android:allowBackup="true"
7+
android:debuggable="true"
8+
android:icon="@mipmap/ic_launcher"
9+
android:label="@string/app_name"
10+
android:roundIcon="@mipmap/ic_launcher_round"
11+
android:supportsRtl="true"
12+
tools:ignore="HardcodedDebugMode" >
13+
<activity
14+
android:name="demo.plot.view.PlotGirdDemoActivity"
15+
android:exported="true">
16+
<intent-filter>
17+
<action android:name="android.intent.action.MAIN" />
18+
19+
<category android:name="android.intent.category.LAUNCHER" />
20+
</intent-filter>
21+
</activity>
22+
23+
<activity
24+
android:name="demo.plot.view.LayoutDemoActivity"
25+
android:exported="true">
26+
<intent-filter>
27+
<action android:name="android.intent.action.MAIN" />
28+
29+
<category android:name="android.intent.category.LAUNCHER" />
30+
</intent-filter>
31+
</activity>
32+
33+
<activity
34+
android:name="demo.plot.view.ResizingWithFitContainerSizePolicyDemoActivity"
35+
android:exported="true">
36+
<intent-filter>
37+
<action android:name="android.intent.action.MAIN" />
38+
39+
<category android:name="android.intent.category.LAUNCHER" />
40+
</intent-filter>
41+
</activity>
42+
43+
<activity
44+
android:name="demo.plot.view.ResizingWithFixedPlotSizePolicyDemoActivity"
45+
android:exported="true">
46+
<intent-filter>
47+
<action android:name="android.intent.action.MAIN" />
48+
49+
<category android:name="android.intent.category.LAUNCHER" />
50+
</intent-filter>
51+
</activity>
52+
53+
54+
<!-- android:theme="@style/Theme.AppCompat.Light"> -->
55+
<!-- android:theme="@style/Theme.AppCompat.Light.NoActionBar"> -->
56+
<activity
57+
android:name="demo.plot.view.DensityPlotDemoActivity"
58+
android:exported="true" >
59+
<intent-filter>
60+
<action android:name="android.intent.action.MAIN" />
61+
62+
<category android:name="android.intent.category.LAUNCHER" />
63+
</intent-filter>
64+
</activity>
65+
66+
</application>
67+
68+
</manifest>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2025 JetBrains s.r.o.
3+
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4+
*/
5+
6+
package demo.plot.view
7+
8+
import android.app.Activity
9+
import android.graphics.Color
10+
import android.os.Bundle
11+
import org.jetbrains.letsPlot.android.canvas.CanvasView
12+
import org.jetbrains.letsPlot.core.util.sizing.SizingPolicy
13+
import org.jetbrains.letsPlot.intern.toSpec
14+
import org.jetbrains.letsPlot.raster.builder.MonolithicCanvas
15+
import plotSpec.DensitySpec
16+
17+
class DensityPlotDemoActivity : Activity() {
18+
override fun onCreate(savedInstanceState: Bundle?) {
19+
super.onCreate(savedInstanceState)
20+
21+
val plotFigure = DensitySpec().createFigure()
22+
23+
setContentView(
24+
CanvasView(this).apply {
25+
figure = MonolithicCanvas.buildPlotFigureFromRawSpec(
26+
rawSpec = plotFigure.toSpec(),
27+
sizingPolicy = SizingPolicy.fitContainerSize(false),
28+
computationMessagesHandler = {}
29+
)
30+
setBackgroundColor(Color.GREEN)
31+
}
32+
)
33+
}
34+
}
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package demo.plot.view
2+
3+
import android.app.Activity
4+
import android.graphics.Color
5+
import android.os.Bundle
6+
import android.view.ViewGroup
7+
import android.widget.*
8+
import org.jetbrains.letsPlot.android.canvas.CanvasView
9+
import org.jetbrains.letsPlot.core.util.sizing.SizingPolicy
10+
import org.jetbrains.letsPlot.intern.toSpec
11+
import org.jetbrains.letsPlot.raster.builder.MonolithicCanvas
12+
import org.jetbrains.letsPlot.raster.view.PlotCanvasFigure
13+
import org.jetbrains.letsPlot.themes.flavorDarcula
14+
import plotSpec.BarPlotSpec
15+
16+
class LayoutDemoActivity : Activity() {
17+
private companion object {
18+
private const val MAX_PLOT_WIDTH_DP = 390
19+
private const val MIN_PARENT_HEIGHT_DP = 50
20+
private const val MAX_PARENT_HEIGHT_DP = 390
21+
}
22+
23+
private lateinit var plotSizeLabel: TextView
24+
private lateinit var sizingPolicyOptions: RadioGroup
25+
private lateinit var preserveAspectRatio: CheckBox
26+
private lateinit var plotWidthSlider: SeekBar
27+
private lateinit var plotHeightSlider: SeekBar
28+
29+
private lateinit var containerOptionsGroup: ViewGroup
30+
private lateinit var fixedSizeOptionsGroup: ViewGroup
31+
32+
private lateinit var widthOptions: RadioGroup
33+
private lateinit var heightOptions: RadioGroup
34+
private lateinit var parentContainer: FrameLayout
35+
private lateinit var parentWidthSlider: SeekBar
36+
private lateinit var parentHeightSlider: SeekBar
37+
38+
39+
private lateinit var demoView: CanvasView
40+
private val plotFigure = PlotCanvasFigure()
41+
private val plotSpec = (BarPlotSpec().basic + flavorDarcula()).toSpec()
42+
43+
override fun onCreate(savedInstanceState: Bundle?) {
44+
super.onCreate(savedInstanceState)
45+
setContentView(R.layout.layout_demo_activity)
46+
47+
sizingPolicyOptions = findViewById(R.id.sizing_policy_options)
48+
preserveAspectRatio = findViewById(R.id.preserve_aspect_ratio)
49+
plotWidthSlider = findViewById(R.id.plot_width_slider)
50+
plotHeightSlider = findViewById(R.id.plot_height_slider)
51+
plotSizeLabel = findViewById(R.id.plot_size_label)
52+
containerOptionsGroup = findViewById(R.id.container_options_group)
53+
fixedSizeOptionsGroup = findViewById(R.id.fixed_size_options_group)
54+
55+
widthOptions = findViewById(R.id.width_options)
56+
heightOptions = findViewById(R.id.height_options)
57+
parentContainer = findViewById(R.id.parent_container)
58+
parentWidthSlider = findViewById(R.id.parent_width_slider)
59+
parentHeightSlider = findViewById(R.id.parent_height_slider)
60+
61+
demoView = CanvasView(this).apply {
62+
figure = plotFigure
63+
setBackgroundColor(Color.GREEN)
64+
}
65+
66+
parentContainer.addView(demoView)
67+
68+
setupControls()
69+
70+
findViewById<RadioButton>(R.id.width_match).isChecked = true
71+
findViewById<RadioButton>(R.id.height_match).isChecked = true
72+
findViewById<RadioButton>(R.id.sizing_policy_container).isChecked = true
73+
updateDemoViewLayoutParams()
74+
updateParentContainerSize()
75+
updatePlotOptions()
76+
updateUiEnabledState()
77+
}
78+
79+
private fun setupControls() {
80+
sizingPolicyOptions.setOnCheckedChangeListener { _, checkedId ->
81+
updateUiEnabledState()
82+
updatePlotOptions()
83+
}
84+
85+
preserveAspectRatio.setOnCheckedChangeListener { _, checkedId ->
86+
updatePlotOptions()
87+
}
88+
89+
val plotSizeUpdateListener = object : SeekBar.OnSeekBarChangeListener {
90+
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
91+
updatePlotOptions()
92+
}
93+
94+
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
95+
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
96+
}
97+
plotWidthSlider.setOnSeekBarChangeListener(plotSizeUpdateListener)
98+
plotHeightSlider.setOnSeekBarChangeListener(plotSizeUpdateListener)
99+
100+
101+
val layoutUpdateListener = RadioGroup.OnCheckedChangeListener { _, _ ->
102+
updateDemoViewLayoutParams()
103+
}
104+
widthOptions.setOnCheckedChangeListener(layoutUpdateListener)
105+
heightOptions.setOnCheckedChangeListener(layoutUpdateListener)
106+
107+
val parentSizeUpdateListener = object : SeekBar.OnSeekBarChangeListener {
108+
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
109+
updateParentContainerSize()
110+
}
111+
112+
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
113+
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
114+
}
115+
parentWidthSlider.setOnSeekBarChangeListener(parentSizeUpdateListener)
116+
parentHeightSlider.setOnSeekBarChangeListener(parentSizeUpdateListener)
117+
}
118+
119+
private fun updatePlotOptions() {
120+
val plotWidth = MAX_PLOT_WIDTH_DP * plotWidthSlider.progress / 100.0
121+
val plotHeight = MAX_PLOT_WIDTH_DP * plotHeightSlider.progress / 100.0
122+
123+
plotSizeLabel.text = "Plot size: $plotWidth x $plotHeight"
124+
125+
val sizingPolicy = when (sizingPolicyOptions.checkedRadioButtonId) {
126+
R.id.sizing_policy_fixed -> SizingPolicy.fixed(width = plotWidth, height = plotHeight)
127+
R.id.sizing_policy_container -> SizingPolicy.fitContainerSize(preserveAspectRatio.isChecked)
128+
else -> error("Unknown sizing policy option selected")
129+
}
130+
131+
MonolithicCanvas.updatePlotFigureFromRawSpec(plotFigure, plotSpec, sizingPolicy) { _ -> }
132+
}
133+
134+
private fun updateDemoViewLayoutParams() {
135+
val width = getSelectedLayoutParam(widthOptions.checkedRadioButtonId)
136+
val height = getSelectedLayoutParam(heightOptions.checkedRadioButtonId)
137+
138+
demoView.layoutParams = FrameLayout.LayoutParams(width, height)
139+
}
140+
141+
private fun updateParentContainerSize() {
142+
val density = resources.displayMetrics.density
143+
val lp = parentContainer.layoutParams
144+
145+
val parentOfContainer = parentContainer.parent as ViewGroup
146+
val parentMaxWidth = parentOfContainer.width - parentOfContainer.paddingStart - parentOfContainer.paddingEnd
147+
val progressWidth = parentWidthSlider.progress / 100f
148+
149+
if (parentMaxWidth > 0) {
150+
lp.width = (parentMaxWidth * progressWidth).coerceAtLeast(100f).toInt()
151+
}
152+
153+
val heightRangePx = (MAX_PARENT_HEIGHT_DP - MIN_PARENT_HEIGHT_DP) * density
154+
val minHeightPx = (MIN_PARENT_HEIGHT_DP * density)
155+
val progressHeight = parentHeightSlider.progress / 100f
156+
157+
lp.height = (minHeightPx + (heightRangePx * progressHeight)).toInt()
158+
159+
findViewById<TextView>(R.id.parent_container_size_label).text = "Parent size: ${lp.width} x ${lp.height}"
160+
161+
parentContainer.layoutParams = lp
162+
}
163+
164+
private fun getSelectedLayoutParam(checkedId: Int): Int {
165+
val density = resources.displayMetrics.density
166+
return when (checkedId) {
167+
R.id.width_match, R.id.height_match -> ViewGroup.LayoutParams.MATCH_PARENT
168+
R.id.width_wrap, R.id.height_wrap -> ViewGroup.LayoutParams.WRAP_CONTENT
169+
R.id.width_fixed, R.id.height_fixed -> (200 * density).toInt()
170+
else -> ViewGroup.LayoutParams.WRAP_CONTENT
171+
}
172+
}
173+
174+
private fun updateUiEnabledState() {
175+
when (sizingPolicyOptions.checkedRadioButtonId) {
176+
R.id.sizing_policy_container -> {
177+
// Enable the "fitContainerSize" options
178+
setGroupEnabled(containerOptionsGroup, true)
179+
// Disable the "fixed" size options
180+
setGroupEnabled(fixedSizeOptionsGroup, false)
181+
}
182+
R.id.sizing_policy_fixed -> {
183+
// Disable the "fitContainerSize" options
184+
setGroupEnabled(containerOptionsGroup, false)
185+
// Enable the "fixed" size options
186+
setGroupEnabled(fixedSizeOptionsGroup, true)
187+
}
188+
}
189+
}
190+
191+
private fun setGroupEnabled(viewGroup: ViewGroup, isEnabled: Boolean) {
192+
viewGroup.isEnabled = isEnabled
193+
// Loop through all the children of the ViewGroup
194+
for (i in 0 until viewGroup.childCount) {
195+
val child = viewGroup.getChildAt(i)
196+
child.isEnabled = isEnabled
197+
// Set alpha to provide a visual cue for being disabled
198+
child.alpha = if (isEnabled) 1.0f else 0.5f
199+
}
200+
}
201+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2025 JetBrains s.r.o.
3+
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4+
*/
5+
6+
package demo.plot.view
7+
8+
import android.app.Activity
9+
import android.graphics.Color
10+
import android.os.Bundle
11+
import org.jetbrains.letsPlot.android.canvas.CanvasView
12+
import org.jetbrains.letsPlot.core.util.sizing.SizingPolicy
13+
import org.jetbrains.letsPlot.intern.toSpec
14+
import org.jetbrains.letsPlot.raster.builder.MonolithicCanvas
15+
import plotSpec.PlotGridSpec
16+
17+
class PlotGirdDemoActivity : Activity() {
18+
override fun onCreate(savedInstanceState: Bundle?) {
19+
super.onCreate(savedInstanceState)
20+
21+
val plotFigure = PlotGridSpec().createFigure()
22+
23+
setContentView(
24+
CanvasView(this).apply {
25+
figure = MonolithicCanvas.buildPlotFigureFromRawSpec(
26+
rawSpec = plotFigure.toSpec(),
27+
sizingPolicy = SizingPolicy.fitContainerSize(false),
28+
computationMessagesHandler = {}
29+
)
30+
setBackgroundColor(Color.GREEN)
31+
}
32+
)
33+
}
34+
}

0 commit comments

Comments
 (0)