Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CodenameOne/src/com/codename1/ui/spinner/Picker.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.codename1.ui.events.ActionListener;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.ui.layouts.FlowLayout;
import com.codename1.ui.layouts.GridLayout;
import com.codename1.ui.list.DefaultListModel;
import com.codename1.ui.plaf.Border;
Expand Down Expand Up @@ -781,7 +782,11 @@ public void actionPerformed(ActionEvent evt) {
switch (entry.alignment) {
case Component.CENTER:
if (center == null) {
center = new Container(BoxLayout.x());
// FlowLayout(CENTER) so the buttons actually center inside
// the BorderLayout.CENTER slot below; BoxLayout.x() would
// pack them at the slot's left edge, which is the bug from
// https://github.com/codenameone/CodenameOne/issues/4819.
center = new Container(new FlowLayout(Component.CENTER, Component.CENTER));
$(center).selectAllStyles().setMargin(0).setPadding(0).setBorder(Border.createEmpty()).setBgTransparency(0);
}
center.add(button);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,54 +1,166 @@
package com.codenameone.examples.hellocodenameone.tests;

import com.codename1.ui.Component;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.ui.spinner.Picker;
import com.codename1.ui.spinner.Picker.LightweightPopupButtonPlacement;
import com.codename1.ui.util.UITimer;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;

/**
* Captures the lightweight Picker popup with custom buttons across the
* placement and alignment combinations that matter. Originally a single
* baseline shot ({@code LightweightPickerButtons}); extended after
* issue #4819 where {@code Component.CENTER} alignment silently
* left-aligned the buttons.
*
* The variant count is intentionally trimmed to four: each variant
* cycle (popup show, throttled chunk emission, popup dismiss) costs
* roughly 5-6s on Android, and {@code Cn1ssDeviceRunner}'s per-test
* deadline is 30s on native platforms. The {@code _between_mixed}
* shot subsumes isolated LEFT / CENTER / RIGHT BETWEEN_CANCEL_AND_DONE
* captures: it lays out all three alignments in the same row with
* explicit L / C / R labels, so a regression that re-broke any of
* them would visibly collapse one column toward another.
*/
public class LightweightPickerButtonsScreenshotTest extends BaseTest {
private Form form;
private Picker picker;
private Date fixedDate;
private Date fixedDatePlus7;
private Variant[] variants;

@Override
public boolean runTest() {
Form form = createForm("Picker Quick Buttons", BoxLayout.y(), "LightweightPickerButtons");
fixedDate = toDate(LocalDate.of(2026, 4, 11));
fixedDatePlus7 = toDate(LocalDate.of(2026, 4, 18));
variants = buildVariants();

form = new Form("Picker Quick Buttons", BoxLayout.y()) {
@Override
protected void onShowCompleted() {
runVariantsFrom(0);
}
};
picker = new Picker();
picker.setType(Display.PICKER_TYPE_DATE);
picker.setUseLightweightPopup(true);
picker.setDate(fixedDate);
form.add(picker);
form.show();
return true;
}

private Variant[] buildVariants() {
// Order matters for telemetry but not for correctness. The
// first entry's image name is "LightweightPickerButtons" to
// preserve the pre-existing golden (Today / +7 Days, both LEFT
// aligned) checked in under scripts/<port>/screenshots/.
return new Variant[] {
new Variant("LightweightPickerButtons", new Runnable() {
@Override
public void run() {
addToday(LightweightPopupButtonPlacement.BETWEEN_CANCEL_AND_DONE, Component.LEFT);
addPlus7(LightweightPopupButtonPlacement.BELOW_SPINNER, Component.LEFT);
}
}),
new Variant("LightweightPickerButtons_between_mixed", new Runnable() {
@Override
public void run() {
// Same placement, three alignments: covers the bug
// from #4819 (CENTER had been left-aligning) and
// the LEFT / RIGHT siblings in one shot.
picker.addLightweightPopupButton("L", null,
LightweightPopupButtonPlacement.BETWEEN_CANCEL_AND_DONE, Component.LEFT);
picker.addLightweightPopupButton("C", null,
LightweightPopupButtonPlacement.BETWEEN_CANCEL_AND_DONE, Component.CENTER);
picker.addLightweightPopupButton("R", null,
LightweightPopupButtonPlacement.BETWEEN_CANCEL_AND_DONE, Component.RIGHT);
}
}),
new Variant("LightweightPickerButtons_above_center", new Runnable() {
@Override
public void run() {
addToday(LightweightPopupButtonPlacement.ABOVE_SPINNER, Component.CENTER);
}
}),
new Variant("LightweightPickerButtons_below_right", new Runnable() {
@Override
public void run() {
addPlus7(LightweightPopupButtonPlacement.BELOW_SPINNER, Component.RIGHT);
}
}),
};
}

private void addToday(int placement, int alignment) {
picker.addLightweightPopupButton("Today", new Runnable() {
@Override
public void run() {
picker.setDate(fixedDate);
}
});
}, placement, alignment);
}

private void addPlus7(int placement, int alignment) {
picker.addLightweightPopupButton("+7 Days", new Runnable() {
@Override
public void run() {
picker.setDate(fixedDatePlus7);
}
}, Picker.LightweightPopupButtonPlacement.BELOW_SPINNER);
form.add(picker);
form.show();
return true;
}, placement, alignment);
}

@Override
protected void registerReadyCallback(Form parent, Runnable run) {
private void runVariantsFrom(final int index) {
if (index >= variants.length) {
done();
return;
}
final Variant variant = variants[index];
picker.clearLightweightPopupButtons();
picker.setDate(fixedDate);
variant.configure.run();
picker.startEditingAsync();
UITimer.timer(1000, false, parent, run);
// Wait for the popup to slide up before screenshotting. Each
// variant cycle (wait + chunk-throttled emit + popup dismiss)
// costs ~5s on Android, and the per-test deadline in
// Cn1ssDeviceRunner is 30s, so this budget can't be padded.
// 600ms is generous: the InteractionDialog transition is
// <300ms and setDate is applied synchronously above.
UITimer.timer(600, false, form, new Runnable() {
@Override
public void run() {
Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshot(variant.imageName, new Runnable() {
@Override
public void run() {
picker.stopEditing(new Runnable() {
@Override
public void run() {
runVariantsFrom(index + 1);
}
});
}
});
}
});
}

private static Date toDate(LocalDate date) {
return new Date(date.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli());
}

private static final class Variant {
final String imageName;
final Runnable configure;

Variant(String imageName, Runnable configure) {
this.imageName = imageName;
this.configure = configure;
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading