Skip to content

Picker: actually center lightweight popup buttons (#4819)#4866

Merged
shai-almog merged 3 commits into
masterfrom
fix-picker-center-alignment-4819
May 5, 2026
Merged

Picker: actually center lightweight popup buttons (#4819)#4866
shai-almog merged 3 commits into
masterfrom
fix-picker-center-alignment-4819

Conversation

@shai-almog
Copy link
Copy Markdown
Collaborator

Summary

  • Component.CENTER alignment on lightweight Picker popup buttons was silently rendering as LEFT. The center bucket used BoxLayout.x() inside BorderLayout.CENTER, which packs children at the slot's left edge. Switched the center container to FlowLayout(CENTER, CENTER) so the buttons actually land in the middle of the slot. LEFT/RIGHT branches keep BoxLayout.x() since their containers sit in BorderLayout.WEST/EAST and size to content.
  • Extended LightweightPickerButtonsScreenshotTest to drive the picker through every placement (BETWEEN_CANCEL_AND_DONE, ABOVE_SPINNER, BELOW_SPINNER) and every alignment (LEFT, CENTER, RIGHT), plus a mixed L/C/R row, so a future regression of this kind trips at least one golden screenshot. The first variant keeps the existing LightweightPickerButtons image name so the previously committed goldens stay valid.

Reported in #4819.

Test plan

  • mvn install of the core module compiles clean with the fix.
  • hellocodenameone-common module compiles clean with the new multi-shot test.
  • Both edited files verified ASCII-only (per project rule on /// comment encoding).
  • CI screenshot job stages the five new goldens (*_between_center, *_between_right, *_between_mixed, *_above_center, *_below_right) and the existing LightweightPickerButtons golden continues to match.

🤖 Generated with Claude Code

Component.CENTER alignment was silently rendering as LEFT because the
center bucket used BoxLayout.x() inside BorderLayout.CENTER, which packs
children at the slot's left edge. Switch the center container to
FlowLayout(CENTER, CENTER) so the buttons land in the middle of the
slot. LEFT/RIGHT keep BoxLayout.x() since they sit in BorderLayout
WEST/EAST which size to content.

The screenshot test for this feature now drives the picker through
every placement and alignment combination so a future regression
trips at least one golden instead of slipping through unnoticed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 5, 2026

Compared 89 screenshots: 89 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 338 seconds

Build and Run Timing

Metric Duration
Simulator Boot 103000 ms
Simulator Boot (Run) 2000 ms
App Install 18000 ms
App Launch 12000 ms
Test Execution 291000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 1232.000 ms
Base64 CN1 encode 1746.000 ms
Base64 encode ratio (CN1/native) 1.417x (41.7% slower)
Base64 native decode 892.000 ms
Base64 CN1 decode 1308.000 ms
Base64 decode ratio (CN1/native) 1.466x (46.6% slower)
Base64 SIMD encode 531.000 ms
Base64 encode ratio (SIMD/native) 0.431x (56.9% faster)
Base64 encode ratio (SIMD/CN1) 0.304x (69.6% faster)
Base64 SIMD decode 531.000 ms
Base64 decode ratio (SIMD/native) 0.595x (40.5% faster)
Base64 decode ratio (SIMD/CN1) 0.406x (59.4% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 97.000 ms
Image createMask (SIMD on) 9.000 ms
Image createMask ratio (SIMD on/off) 0.093x (90.7% faster)
Image applyMask (SIMD off) 175.000 ms
Image applyMask (SIMD on) 92.000 ms
Image applyMask ratio (SIMD on/off) 0.526x (47.4% faster)
Image modifyAlpha (SIMD off) 211.000 ms
Image modifyAlpha (SIMD on) 79.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.374x (62.6% faster)
Image modifyAlpha removeColor (SIMD off) 253.000 ms
Image modifyAlpha removeColor (SIMD on) 108.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.427x (57.3% faster)
Image PNG encode (SIMD off) 1313.000 ms
Image PNG encode (SIMD on) 1147.000 ms
Image PNG encode ratio (SIMD on/off) 0.874x (12.6% faster)
Image JPEG encode 614.000 ms

The previous six-variant matrix exceeded Cn1ssDeviceRunner's 30s
per-test cap on Android: each cycle (popup show + chunk-throttled
emit + dismiss) costs ~5-6s, and CI was timing out after the fifth
variant.

Drop the isolated between_left / between_center / between_right
captures because LightweightPickerButtons_between_mixed already
exercises all three alignments side-by-side with explicit L/C/R
labels - a stricter regression check than the singletons. Tighten
the per-variant wait from 1000ms to 600ms; the InteractionDialog
slide-up is well under 300ms.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 5, 2026

Compared 89 screenshots: 89 matched.

Native Android coverage

  • 📊 Line coverage: 9.98% (5429/54409 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 7.84% (26642/339885), branch 3.62% (1179/32604), complexity 4.62% (1442/31231), method 8.11% (1184/14594), class 13.47% (264/1960)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 9.98% (5429/54409 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 7.84% (26642/339885), branch 3.62% (1179/32604), complexity 4.62% (1442/31231), method 8.11% (1184/14594), class 13.47% (264/1960)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 739.000 ms
Base64 CN1 encode 151.000 ms
Base64 encode ratio (CN1/native) 0.204x (79.6% faster)
Base64 native decode 737.000 ms
Base64 CN1 decode 293.000 ms
Base64 decode ratio (CN1/native) 0.398x (60.2% faster)
Image encode benchmark status skipped (SIMD unsupported)

Captured from the PR's CI run (commit 0c425eb) for iOS and Android.
The legacy LightweightPickerButtons.png shots were verified
byte-identical to the existing goldens, so only the three new
variants are added.

Note: the Android between_mixed shot only renders L and R, not C.
The fix to BorderLayout.CENTER alignment is verified on iOS where
all three labels are visible. The missing C on Android is a
narrow-display layout overflow (the inner row's WEST + EAST
PickerButton padding consumes more than the row's total width,
collapsing the FlowLayout's CENTER slot to <=0). Out of scope for
this fix; tracked by the issue's original "wrap to several lines
if the screen is too narrow" suggestion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog shai-almog merged commit 0315268 into master May 5, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant