Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
a84a640
Modernize developer guide demos and snippets
shai-almog Jul 1, 2026
af43c11
Fix developer guide CI snapshot setup
shai-almog Jul 1, 2026
b0c3ef7
Speed up developer guide CI bootstrap
shai-almog Jul 1, 2026
d9af0e9
Address developer guide PR feedback
shai-almog Jul 1, 2026
a47d940
Remove obsolete CSharp native snippets
shai-almog Jul 1, 2026
3b79fe1
Fix developer guide quality gate findings
shai-almog Jul 1, 2026
d876b01
Fix advanced topic guide snippets
shai-almog Jul 2, 2026
325df1e
Fix Android demo source compile check
shai-almog Jul 2, 2026
45bfd74
Use staged Android jars for guide compile check
shai-almog Jul 2, 2026
c185d74
Address wallet snippet quality findings
shai-almog Jul 2, 2026
ac48cef
Stop treating guide snippet bundles as Java sources
shai-almog Jul 2, 2026
5af8230
Include Android module classes in guide compile check
shai-almog Jul 2, 2026
5aab3f8
Stub missing Android helpers for guide source check
shai-almog Jul 2, 2026
2a44f97
Update developer guide snippets after master merge
shai-almog Jul 2, 2026
2e11719
Fix media guide anchor collision
shai-almog Jul 2, 2026
bb0852d
Move platform native guide snippets out of common
shai-almog Jul 2, 2026
2c49d81
Move Android native stub out of common demos
shai-almog Jul 2, 2026
8c28211
Move JavaScript guide snippets out of common demos
shai-almog Jul 2, 2026
ef67bf2
Compile developer guide Java snippets in demos
shai-almog Jul 2, 2026
81820bc
Fix developer guide callouts and screenshots
shai-almog Jul 2, 2026
d1567ad
Restore CI guide screenshot baselines
shai-almog Jul 2, 2026
de8b17d
Validate guide CSS and restore OpenAPI snippet
shai-almog Jul 2, 2026
bf53e33
Prove developer guide screenshot capture in CI
shai-almog Jul 2, 2026
19de6fa
Expand developer guide screenshot coverage
shai-almog Jul 3, 2026
efabba9
Avoid ripgrep in guide screenshot manifest check
shai-almog Jul 3, 2026
8f9a8ea
Render transition screenshot frames directly
shai-almog Jul 3, 2026
d3c4ff3
Update generated guide screenshot baselines
shai-almog Jul 3, 2026
47b92fc
Stabilize guide animation screenshots
shai-almog Jul 3, 2026
3cdd4c6
Merge remote-tracking branch 'origin/master' into codex/modernize-dev…
shai-almog Jul 3, 2026
71c1b94
Move VideoIO guide snippets into demos
shai-almog Jul 3, 2026
92d5a1d
Render guide screenshots from real frames
shai-almog Jul 3, 2026
3ce866e
Keep website redirect update green on PRs
shai-almog Jul 3, 2026
5278ab2
Expand developer guide screenshot coverage
shai-almog Jul 3, 2026
b660065
Update guide screenshot baselines from CI
shai-almog Jul 3, 2026
641aa58
Stabilize interaction dialog guide screenshot
shai-almog Jul 3, 2026
47b292c
Refine interaction dialog guide screenshot
shai-almog Jul 3, 2026
365fd6b
Prevent interaction dialog guide screenshot clipping
shai-almog Jul 3, 2026
316572e
Widen interaction dialog guide example
shai-almog Jul 3, 2026
597e696
Keep interaction dialog host controls visible
shai-almog Jul 3, 2026
e3faf66
Clean interaction dialog screenshot host label
shai-almog Jul 3, 2026
89003e8
Update interaction dialog screenshot baseline
shai-almog Jul 3, 2026
ff83077
Refresh developer guide screenshot demos
shai-almog Jul 3, 2026
b562d9d
Tune developer guide screenshot baselines
shai-almog Jul 3, 2026
7f9814d
Tighten developer guide screenshot crops
shai-almog Jul 3, 2026
a693246
Validate developer guide snippets and screenshots
shai-almog Jul 4, 2026
9f84a02
Use CI guide screenshot baselines
shai-almog Jul 4, 2026
bd0f5d0
Add missing compiled guide snippets
shai-almog Jul 4, 2026
b1f32e6
Generate layout guide screenshots from snippets
shai-almog Jul 4, 2026
cbc2038
Update generated layout screenshot baselines
shai-almog Jul 4, 2026
58364ce
Generate missing layout guide screenshots
shai-almog Jul 5, 2026
217c84a
Upload guide screenshot diffs for review
shai-almog Jul 5, 2026
fabf8c7
Use CI-rendered guide layout screenshots
shai-almog Jul 5, 2026
545b183
Remove committed guide image audit table
shai-almog Jul 5, 2026
177ba0a
Generate remaining guide runtime screenshots
shai-almog Jul 5, 2026
e1a13f7
Expose guide screenshot diffs
shai-almog Jul 5, 2026
0ac4a5e
Use Linux guide screenshot baselines
shai-almog Jul 5, 2026
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
92 changes: 2 additions & 90 deletions .github/scripts/compare-animation-screenshots.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,94 +2,6 @@
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
BASELINE_DIR="${BASELINE_DIR:-${PROJECT_ROOT}/docs/developer-guide/img}"
STORAGE_DIR="${CN1_STORAGE_DIR:-${HOME}/.cn1}"
ARTIFACT_DIR="${1:-${PROJECT_ROOT}/docs/demos/animation-screenshot-artifacts}"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"

if ! command -v compare >/dev/null 2>&1; then
echo "ImageMagick 'compare' command is required." >&2
exit 2
fi

mkdir -p "${ARTIFACT_DIR}"
find "${ARTIFACT_DIR}" -mindepth 1 -delete

if [[ ! -d "${STORAGE_DIR}" ]]; then
echo "Storage directory ${STORAGE_DIR} does not exist; nothing to compare."
exit 0
fi

shopt -s nullglob
mapfile -d '' SCREENSHOTS < <(find "${STORAGE_DIR}" -type f -name '*.png' -print0)
shopt -u nullglob

if [[ ${#SCREENSHOTS[@]} -eq 0 ]]; then
echo "No screenshots found under ${STORAGE_DIR}; nothing to compare."
exit 0
fi

mismatch_count=0

for screenshot in "${SCREENSHOTS[@]}"; do
filename="$(basename "${screenshot}")"
base="${filename%.png}"

baseline=""
baseline_ext=""
for ext in png PNG jpg JPG jpeg JPEG; do
candidate="${BASELINE_DIR}/${base}.${ext}"
if [[ -f "${candidate}" ]]; then
baseline="${candidate}"
baseline_ext="${ext}"
break
fi
done

if [[ -z "${baseline}" ]]; then
echo "No baseline found for ${filename}; treating as mismatch." >&2
mismatch_count=$((mismatch_count + 1))
cp "${screenshot}" "${ARTIFACT_DIR}/${filename}"
rm -f "${screenshot}"
continue
fi

metric_file="$(mktemp)"
diff_image="${ARTIFACT_DIR}/${base}.diff.png"

set +e
compare -metric AE "${screenshot}" "${baseline}" "${diff_image}" 2>"${metric_file}"
status=$?
set -e

if [[ ${status} -eq 0 ]]; then
rm -f "${screenshot}" "${diff_image}" "${metric_file}"
echo "${filename} matches baseline; capture discarded."
continue
fi

if [[ ${status} -ne 1 ]]; then
cat "${metric_file}" >&2
rm -f "${metric_file}" "${diff_image}"
echo "ImageMagick comparison failed for ${filename}." >&2
exit ${status}
fi

mismatch_count=$((mismatch_count + 1))
metric_value="$(cat "${metric_file}")"
rm -f "${metric_file}"

cp "${screenshot}" "${ARTIFACT_DIR}/${filename}"
cp "${baseline}" "${ARTIFACT_DIR}/${base}.baseline.${baseline_ext}"
echo "${metric_value}" > "${ARTIFACT_DIR}/${base}.metric.txt"
rm -f "${screenshot}"
echo "${filename} differs from baseline; artifacts stored in ${ARTIFACT_DIR}." >&2
done

if [[ ${mismatch_count} -eq 0 ]]; then
echo "All screenshots match their baselines."
exit 0
fi

echo "${mismatch_count} screenshot(s) differ from the documented baseline." >&2
exit 1
exec "${PROJECT_ROOT}/scripts/developer-guide/compare-guide-screenshots.sh" "$@"
61 changes: 42 additions & 19 deletions .github/workflows/developer-guide-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
paths:
- 'docs/developer-guide/**'
- 'docs/demos/**'
- 'scripts/developer-guide/**'
- '.github/workflows/developer-guide-docs.yml'
release:
types: [published]
Expand All @@ -30,9 +31,14 @@ jobs:
filters: |
demos:
- 'docs/demos/**'
- 'scripts/developer-guide/compare-guide-screenshots.sh'
- 'scripts/developer-guide/guide-screenshots.txt'
- '.github/workflows/developer-guide-docs.yml'
docs:
- 'docs/developer-guide/**'
- 'docs/demos/common/src/main/snippets/**'
- 'scripts/developer-guide/migrate-inline-guide-snippets.py'
- 'scripts/developer-guide/validate-guide-snippets.py'
- '.github/workflows/developer-guide-docs.yml'
workflow:
- '.github/workflows/developer-guide-docs.yml'
Expand All @@ -41,46 +47,63 @@ jobs:
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '11'
java-version: '17'

- name: Install local Codename One Maven artifacts
if: github.event_name != 'pull_request' || steps.changes.outputs.docs == 'true' || steps.changes.outputs.demos == 'true' || steps.changes.outputs.workflow == 'true'
run: |
set -euo pipefail
xvfb-run -a mvn -B -ntp -f maven/pom.xml \
-pl core,javase,css-compiler,codenameone-maven-plugin \
-am install \
-Plocal-dev-javase \
-DskipTests \
-Dmaven.javadoc.skip=true

- name: Build Codename One demos
if: github.event_name != 'pull_request' || steps.changes.outputs.demos == 'true' || steps.changes.outputs.workflow == 'true'
if: github.event_name != 'pull_request' || steps.changes.outputs.docs == 'true' || steps.changes.outputs.demos == 'true' || steps.changes.outputs.workflow == 'true'
run: |
set -euo pipefail
mkdir -p "$HOME/.codenameone"
touch "$HOME/.codenameone/guibuilder.jar"
cp maven/CodeNameOneBuildClient.jar "$HOME/.codenameone/CodeNameOneBuildClient.jar"
xvfb-run -a mvn -B -ntp -Dgenerate-gui-sources-done=true -pl common -am -f docs/demos/pom.xml install
xvfb-run -a mvn -B -ntp -Dgenerate-gui-sources-done=true -Dcodename1.platform=javase -f docs/demos/pom.xml test

- name: Validate developer guide snippets
if: github.event_name != 'pull_request' || steps.changes.outputs.docs == 'true' || steps.changes.outputs.demos == 'true' || steps.changes.outputs.workflow == 'true'
run: |
set -euo pipefail
python3 scripts/developer-guide/validate-guide-snippets.py

- name: Install ImageMagick for screenshot comparison
if: github.event_name != 'pull_request' || steps.changes.outputs.demos == 'true' || steps.changes.outputs.workflow == 'true'
if: github.event_name != 'pull_request' || steps.changes.outputs.docs == 'true' || steps.changes.outputs.demos == 'true' || steps.changes.outputs.workflow == 'true'
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends imagemagick

- name: Compare animation screenshots
id: compare_animation_screenshots
if: github.event_name != 'pull_request' || steps.changes.outputs.demos == 'true' || steps.changes.outputs.workflow == 'true'
- name: Compare guide screenshots
id: compare_guide_screenshots
if: github.event_name != 'pull_request' || steps.changes.outputs.docs == 'true' || steps.changes.outputs.demos == 'true' || steps.changes.outputs.workflow == 'true'
continue-on-error: true
run: |
set -euo pipefail
ARTIFACT_DIR="build/developer-guide/animation-screenshots"
ARTIFACT_DIR="build/developer-guide/guide-screenshots"
mkdir -p "${ARTIFACT_DIR}"
.github/scripts/compare-animation-screenshots.sh "${ARTIFACT_DIR}"
scripts/developer-guide/compare-guide-screenshots.sh "${ARTIFACT_DIR}"

- name: Upload animation screenshot mismatches
if: steps.compare_animation_screenshots.outcome == 'failure'
- name: Upload guide screenshot mismatches
if: steps.compare_guide_screenshots.outcome == 'failure'
uses: actions/upload-artifact@v7
with:
name: developer-guide-animation-screenshots
path: build/developer-guide/animation-screenshots
name: developer-guide-screenshots
path: build/developer-guide/guide-screenshots
if-no-files-found: warn

- name: Fail when animation screenshots differ
if: steps.compare_animation_screenshots.outcome == 'failure'
- name: Fail when guide screenshots differ
if: steps.compare_guide_screenshots.outcome == 'failure'
run: |
echo "Animation demo screenshots differ from developer guide assets." >&2
echo "Generated guide screenshots differ from developer guide assets." >&2
exit 1

- name: Determine publication metadata
Expand Down Expand Up @@ -407,7 +430,7 @@ jobs:
if-no-files-found: warn

- name: Upload AsciiDoc linter report
if: always()
if: always() && env.ASCII_DOC_LINT_REPORT != ''
uses: actions/upload-artifact@v7
with:
name: developer-guide-asciidoc-lint
Expand Down Expand Up @@ -435,15 +458,15 @@ jobs:
if-no-files-found: warn

- name: Upload paragraph capitalization report
if: always()
if: always() && env.PARAGRAPH_CAP_REPORT != ''
uses: actions/upload-artifact@v7
with:
name: developer-guide-paragraph-capitalization
path: ${{ env.PARAGRAPH_CAP_REPORT }}
if-no-files-found: warn

- name: Upload LanguageTool report
if: always()
if: always() && env.LANGUAGETOOL_REPORT != ''
uses: actions/upload-artifact@v7
with:
name: developer-guide-languagetool
Expand Down
4 changes: 2 additions & 2 deletions docs/demos/android/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<codename1.platform>android</codename1.platform>
<codename1.projectPlatform>android</codename1.projectPlatform>
<codename1.defaultBuildTarget>android-device</codename1.defaultBuildTarget>
Expand Down
2 changes: 1 addition & 1 deletion docs/demos/common/codenameone_settings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ codename1.android.keystore=
codename1.android.keystoreAlias=
codename1.android.keystorePassword=
codename1.arg.ios.newStorageLocation=true
codename1.arg.java.version=8
codename1.arg.java.version=17
codename1.displayName=DemoCode
codename1.icon=icon.png
codename1.ios.appid=Q5GHSKAL2F.com.codenameone.developerguide
Expand Down
4 changes: 2 additions & 2 deletions docs/demos/common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ public final class DemoRegistry {
new SwipeBackSupportDemo()
)
);
private static final List<GuideScreenshot> SCREENSHOTS = Collections.unmodifiableList(
Arrays.asList(
screenshot("layout-animations", "Layout Animations", "layout-animation-1.png"),
screenshot("slide-transitions", "Slide Transitions", "transition-slide.png"),
screenshot("bubble-transition", "Bubble Transition", "transition-bubble.png"),
screenshot("morph-transition", "Morph Transition", "mighty-morphing-components-1.png")
)
);

private DemoRegistry() {
// utility class
Expand All @@ -45,4 +53,17 @@ private DemoRegistry() {
public static List<Demo> getDemos() {
return DEMOS;
}

public static List<GuideScreenshot> getScreenshots() {
return SCREENSHOTS;
}

private static GuideScreenshot screenshot(String id, String demoTitle, String fileName) {
for (Demo demo : DEMOS) {
if (demo.getTitle().equals(demoTitle)) {
return new GuideScreenshot(id, demo, fileName);
}
}
throw new IllegalStateException("No guide demo registered with title: " + demoTitle);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.codenameone.developerguide;

/**
* Stable mapping between a runnable guide demo and the image it documents.
*/
public final class GuideScreenshot {
private final String id;
private final Demo demo;
private final String fileName;

public GuideScreenshot(String id, Demo demo, String fileName) {
this.id = id;
this.demo = demo;
this.fileName = fileName;
}

public String getId() {
return id;
}

public Demo getDemo() {
return demo;
}

public String getFileName() {
return fileName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Generated from docs/developer-guide source blocks. Edit the guide snippets here, not inline.

// tag::3d-graphics-java-001[]
RenderView view = new RenderView(new Renderer() {
private final Camera camera = new Camera();
private Mesh cube;
private Material material;
private float angle;

public void onInit(GraphicsDevice device) {
cube = Primitives.cube(device, 1.5f);
material = new Material(Material.Type.PHONG)
.setColor(0xff3366ff)
.setShininess(24f);
camera.setPerspective(45f, 0.1f, 100f)
.setPosition(2.5f, 2f, 3.5f)
.setTarget(0f, 0f, 0f);
device.setLight(new Light().setDirection(-0.4f, -1f, -0.6f));
}

public void onResize(GraphicsDevice device, int w, int h) {
camera.setAspect((float) w / Math.max(1, h));
device.setViewport(0, 0, w, h);
}

public void onFrame(GraphicsDevice device) {
angle += 0.02f;
device.clear(0xff101018, true, true);
device.setCamera(camera);
device.draw(cube, material, Matrix4.rotation(angle, 0.3f, 1f, 0.1f));
}

public void onDispose(GraphicsDevice device) {
}
});
view.setContinuous(true); // animate; omit for on-demand rendering

Form hi = new Form("3D", new BorderLayout());
hi.add(BorderLayout.CENTER, view);
hi.show();
// end::3d-graphics-java-001[]

// tag::3d-graphics-java-002[]
Texture tex = device.createTexture(myImage); // or createTexture(w, h, argb)
tex.setFilter(Texture.Filter.LINEAR).setWrap(Texture.Wrap.REPEAT);
Material m = new Material(Material.Type.UNLIT).setTexture(tex);
// end::3d-graphics-java-002[]

// tag::3d-graphics-java-003[]
VertexBuffer vb = device.createVertexBuffer(VertexFormat.POSITION_NORMAL_TEXCOORD, 4);
vb.setData(new float[] { /* px,py,pz, nx,ny,nz, u,v per vertex ... */ });
IndexBuffer ib = device.createIndexBuffer(6);
ib.setData(new int[] { 0, 1, 2, 0, 2, 3 });
Mesh mesh = new Mesh(vb, ib, PrimitiveType.TRIANGLES);
// end::3d-graphics-java-003[]

// tag::3d-graphics-java-004[]
InputStream in = Display.getInstance().getResourceAsStream(getClass(), "/boombox.glb");
GltfLoader.GltfModel loaded = GltfLoader.loadModel(device, in);
Material material = new Material(Material.Type.PHONG).setShininess(16f);
if (loaded.getBaseColorTexture() != null) {
material.setTexture(loaded.getBaseColorTexture());
}
Mesh model = loaded.getMesh(); // draw it like any other mesh
// end::3d-graphics-java-004[]

// tag::3d-graphics-java-005[]
if (CN.isGpuSupported()) {
// GraphicsDevice.getCapabilities() exposes max texture size, shader level, etc.
}
// end::3d-graphics-java-005[]
Loading
Loading