Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
f8f8280
Developer guide: a figure harness that renders themed app UI
shaiblah Sep 7, 2026
ff1eea3
Trigger the guide figure check on its native theme inputs
shaiblah Sep 7, 2026
0cb0f39
Developer guide: regenerate three Components figures from their own s…
shaiblah Sep 7, 2026
91f3fc9
Point the package javadoc images at where the guide actually publishe…
shaiblah Sep 7, 2026
58f338c
Baseline the three icon figures on CI output and record why they need…
shaiblah Sep 7, 2026
c556846
Developer guide: regenerate 64 more figures from their own samples
shaiblah Sep 8, 2026
1df709a
Drop the figures that photographed a launch form, and gate against it
shaiblah Sep 8, 2026
58458cf
Drop eight more figures that photographed the wrong thing
shaiblah Sep 8, 2026
6871f83
Pin locale and time zone, and drop the figures that cannot be determi…
shaiblah Sep 8, 2026
0bbf301
Trigger the figure check on the framework, and fix the javadoc image …
shaiblah Sep 8, 2026
a81507a
Crop from preferred content height, and drop six figures caught measu…
shaiblah Sep 8, 2026
094bb70
Crop correctly for painted and title-only figures, and drop autosize
shaiblah Sep 8, 2026
c79faf1
Baseline the figures on CI output, which is what the gate compares ag…
shaiblah Sep 8, 2026
6faa04a
Stop one figure's global state from landing on the next
shaiblah Sep 8, 2026
6fed8f1
Render ComponentGroup where grouping exists, and make the sidecars bind
shaiblah Sep 8, 2026
5c91497
Drop five more figures whose captions promise a state the render cann…
shaiblah Sep 8, 2026
b9d4cc9
Check the figure URLs embedded in Java sources instead of remembering…
shaiblah Sep 8, 2026
b5e0aab
Guarantee no simulator skin is active, rather than refusing only an i…
shaiblah Sep 8, 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
48 changes: 45 additions & 3 deletions .github/workflows/developer-guide-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,26 @@ on:
- 'maven/build-hint-catalog/**'
- 'maven/build-hint-tools/**'
- 'scripts/gen-build-hint-table.sh'
# The themed figures are rendered against the compiled native themes, so
# what those themes look like is an input to this guide exactly the way the
# build hint sources above are. build-native-themes.sh compiles
# native-themes/<name>/theme.css with maven/css-compiler, so a change to
# any of the three changes the pictures without touching docs/ at all --
# and the committed figures would then go stale silently until some later
# run failed against them.
- 'native-themes/**'
- 'maven/css-compiler/**'
- 'scripts/build-native-themes.sh'
Comment thread
shai-almog marked this conversation as resolved.
Resolved
# The figures are rendered by the framework itself, so a change to how a
# component paints, how a layout measures, or how the JavaSE port
# rasterizes changes every generated PNG without touching docs/ at all.
# The comparison is byte-exact, so without these the committed figures go
# stale silently and some later docs or release build is the one that
# fails.
- 'CodenameOne/**'
- 'Ports/JavaSE/**'
- 'maven/core/**'
- 'maven/javase/**'
release:
types: [published]
workflow_dispatch:
Expand Down Expand Up @@ -67,6 +87,18 @@ jobs:
- 'maven/build-hint-catalog/**'
- 'maven/build-hint-tools/**'
- 'scripts/gen-build-hint-table.sh'
# Same two-copies-of-one-list problem as the build hint inputs:
# triggering the workflow is not enough, because the figure
# comparison step is gated on this filter too.
- 'native-themes/**'
- 'maven/css-compiler/**'
- 'scripts/build-native-themes.sh'
# Same reason, and the same two-lists rule: the figure comparison
# step is gated on this filter as well as on the trigger.
- 'CodenameOne/**'
- 'Ports/JavaSE/**'
- 'maven/core/**'
- 'maven/javase/**'
workflow:
- '.github/workflows/developer-guide-docs.yml'

Expand All @@ -85,6 +117,17 @@ jobs:
- name: Render the build hint table
run: scripts/gen-build-hint-table.sh

# The javase jar carries iOSModernTheme.res and AndroidMaterialTheme.res,
# which the figure renderer installs. They are copied in from Themes/ by an
# antrun step with failonerror=false, so if they have not been compiled the
# copy fails open and the jar ships without them -- and the renderer then
# dies on a theme resource that is simply absent. Compiling them first is
# what run-javase-simulator-integration-tests.sh already does, for the same
# reason.
- name: Compile the native themes
if: github.event_name != 'pull_request' || steps.changes.outputs.docs == 'true' || steps.changes.outputs.demos == 'true' || steps.changes.outputs.workflow == 'true'
run: ./scripts/build-native-themes.sh
Comment thread
shai-almog marked this conversation as resolved.
Resolved

- 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: |
Expand Down Expand Up @@ -122,7 +165,7 @@ jobs:
install \
-DskipTests

- name: Verify pre-Advanced Theming screenshots are current
- name: Verify generated developer guide figures are current
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
Expand All @@ -142,8 +185,7 @@ jobs:
# difference if it carries a .tolerance sidecar saying why.
python3 scripts/developer-guide/compare-screenshots.py \
--generated "$GENERATED_DIR" \
--committed docs/developer-guide/img \
--expected-count 24
--committed docs/developer-guide/img/generated

# When the byte compare fails, the message names the file but not what it
# actually rendered, which leaves no way to tell a real regression from an
Expand Down
106 changes: 69 additions & 37 deletions CodenameOne/src/com/codename1/ui/package-info.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/

/// Main widget package containing the component/container "composite" similar
/// both in terminology and design to Swing/AWT.
///
Expand Down Expand Up @@ -37,39 +60,39 @@
///
/// ### AutoCompleteTextField
///
/// ![](https://www.codenameone.com/img/developer-guide/components-autocomplete.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-autocomplete.png)
/// `com.codename1.ui.AutoCompleteTextField` provides suggestions as you type into the text
/// field
///
///
/// ### BrowserComponent
///
/// ![](https://www.codenameone.com/img/developer-guide/components-browsercomponent.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-browsercomponent.png)
/// `com.codename1.ui.BrowserComponent` allows us to embed an OS native browser into the app and
/// connect to its JavaScript runtime!
///
///
/// ### Button
///
/// ![](https://www.codenameone.com/img/developer-guide/components-button.png)
/// ![](https://www.codenameone.com/developer-guide/img/generated/components-button-ios.png)
/// `com.codename1.ui.Button` allows us to bind events to a click
///
/// ### Link Button
///
/// ![](https://www.codenameone.com/img/developer-guide/components-link-button.png)
/// ![](https://www.codenameone.com/developer-guide/img/generated/components-link-button.png)
/// `com.codename1.ui.Button` can also be used as a hyperlink
///
/// ### Calendar
///
/// ![](https://www.codenameone.com/img/developer-guide/components-calendar.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-calendar.png)
/// `com.codename1.ui.Calendar` presents a visual date picker. Notice that we recommend using
/// the
/// `com.codename1.ui.spinner.Picker` class which is superior when running on the device for most use cases.
///
///
/// ### CheckBox
///
/// ![](https://www.codenameone.com/img/developer-guide/components-radiobutton-checkbox.png)
/// ![](https://www.codenameone.com/developer-guide/img/generated/components-radiobutton-checkbox.png)
/// `com.codename1.ui.CheckBox` provides a check flag to tick on/off.
/// `com.codename1.ui.RadioButton` provides an exclusive check marking that only applies to one radio within
/// the group.
Expand All @@ -78,47 +101,47 @@
///
/// ### ComboBox
///
/// ![](https://www.codenameone.com/img/developer-guide/components-combobox.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-combobox.png)
/// `com.codename1.ui.ComboBox` is a list with a single visible entry that can popup the full
/// list. Notice that we recommend using the
/// `com.codename1.ui.spinner.Picker` class which is superior when running on the device for most use cases
///
///
/// ### Command
///
/// ![](https://www.codenameone.com/img/developer-guide/components-toolbar.png)
/// ![](https://www.codenameone.com/developer-guide/img/generated/components-toolbar.png)
/// `com.codename1.ui.Command` & `com.codename1.ui.Toolbar` provide deep customization
/// of the title area and allow us to place elements in the side menu (hamburger), overflow menu etc.
///
///
/// ### ComponentGroup
///
/// ![](https://www.codenameone.com/img/developer-guide/components-componentgroup.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-componentgroup.png)
/// `com.codename1.ui.ComponentGroup` allows us to group components together in a a group and
/// manipulate
/// their UIID's.
///
///
/// ### Dialog
///
/// ![](https://www.codenameone.com/img/developer-guide/components-dialog-modal-south.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-dialog-modal-south.png)
/// `com.codename1.ui.Dialog` allows us to notify/ask the user in a modal/modless way.
///
/// ### InfiniteContainer
///
/// ![](https://www.codenameone.com/img/developer-guide/components-infinitescrolladapter.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-infinitescrolladapter.png)
/// `com.codename1.ui.InfiniteContainer` & `com.codename1.components.InfiniteScrollAdapter`
/// implement a `com.codename1.ui.Container` that can dynamically fetch more data
///
///
/// ### Label
///
/// ![](https://www.codenameone.com/img/developer-guide/components-label-text-position.png)
/// ![](https://www.codenameone.com/developer-guide/img/generated/components-label-text-position.png)
/// `com.codename1.ui.Label` displays text and/or icons to the user
///
/// ### List
///
/// ![](https://www.codenameone.com/img/developer-guide/components-generic-list-cell-renderer.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-generic-list-cell-renderer.png)
/// `com.codename1.ui.List` a list of items, this is a rather elaborate component to work with!
/// We often
/// recommend just using `com.codename1.ui.Container`, `com.codename1.ui.InfiniteContainer` or
Expand All @@ -127,41 +150,41 @@
///
/// ### MultiList
///
/// ![](https://www.codenameone.com/img/developer-guide/graphics-urlimage-multilist.png)
/// ![](https://www.codenameone.com/developer-guide/img/graphics-urlimage-multilist.png)
/// `com.codename1.ui.list.MultiList` a list that is a bit simpler to work with than List `com.codename1.ui.List` although
/// our recommendation to use something else still applies
///
///
/// ### Slider
///
/// ![](https://www.codenameone.com/img/developer-guide/components-slider.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-slider.png)
/// `com.codename1.ui.Slider` allows us to indicate progress or allows the user to drag a bar to
/// indicate
/// volume (as in quantity)
///
///
/// ### SwipeableContainer
///
/// ![](https://www.codenameone.com/img/developer-guide/components-swipablecontainer.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-swipablecontainer.png)
/// `com.codename1.ui.SwipeableContainer` enables side swipe gesture to expose additional
/// functionality
///
///
/// ### Tabs
///
/// ![](https://www.codenameone.com/img/developer-guide/components-tabs.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-tabs.png)
/// `com.codename1.ui.Tabs` places components/containers into tabbable entries, allows swiping
/// between choices thru touch
///
///
/// ### Carousel
///
/// ![](https://www.codenameone.com/img/developer-guide/components-tabs-swipe1.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-tabs-swipe1.png)
/// `com.codename1.ui.Tabs` can also be used as a swipe carousel
///
/// ### TextArea/Field
///
/// ![](https://www.codenameone.com/img/developer-guide/components-text-component.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-text-component.png)
/// `com.codename1.ui.TextArea` & `com.codename1.ui.TextField` allow for user input
/// via
/// the keyboard (virtual or otherwise)
Expand All @@ -176,34 +199,34 @@
///
/// ### Table
///
/// ![](https://www.codenameone.com/img/developer-guide/components-table-pinstripe.png)
/// ![](https://www.codenameone.com/developer-guide/img/generated/components-table-pinstripe.png)
/// `com.codename1.ui.table.Table` displays optionally editable tabular data to the user
///
/// ### Tree
///
/// ![](https://www.codenameone.com/img/developer-guide/components-tree-xml.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-tree-xml.png)
/// `com.codename1.ui.tree.Tree` displays data in a tree like hierarchy
///
/// ### ChartComponent
///
/// ![](https://www.codenameone.com/img/developer-guide/range_bar_chart.png)
/// ![](https://www.codenameone.com/developer-guide/img/range_bar_chart.png)
/// `com.codename1.charts.ChartComponent` can embed a wide range of visualization aids and
/// animations into your app
///
///
/// ### ImageViewer
///
/// ![](https://www.codenameone.com/img/developer-guide/components-imageviewer-dynamic.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-imageviewer-dynamic.png)
/// `com.codename1.components.ImageViewer` swipe, pinch to zoom and pan images
///
/// ### InfiniteProgress
///
/// ![](https://www.codenameone.com/img/developer-guide/infinite-progress.png)
/// ![](https://www.codenameone.com/developer-guide/img/infinite-progress.png)
/// `com.codename1.components.InfiniteProgress` provides a constantly spinning component
///
/// ### InteractionDialog
///
/// ![](https://www.codenameone.com/img/developer-guide/components-interaction-dialog.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-interaction-dialog.png)
/// `com.codename1.components.InteractionDialog` an "always on top" `com.codename1.ui.Dialog`
/// used for non-form modal UI patterns. You can make static `Dialog.show(...)` use
/// `InteractionDialog` by default with the theme constant `defaultInteractionDialogModeBool`
Expand All @@ -212,71 +235,71 @@
///
/// ### MediaPlayer
///
/// ![](https://www.codenameone.com/img/developer-guide/components-mediaplayer.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-mediaplayer.png)
/// `com.codename1.components.MediaPlayer` allows playing media including video coupled with the
/// `com.codename1.media.MediaManager`
///
///
/// ### MultiButton
///
/// ![](https://www.codenameone.com/img/developer-guide/components-multibutton.png)
/// ![](https://www.codenameone.com/developer-guide/img/generated/components-multibutton.png)
/// `com.codename1.components.MultiButton` is much more than a button
///
/// ### OnOffSwitch
///
/// ![](https://www.codenameone.com/img/developer-guide/components-onoffswitch.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-onoffswitch.png)
/// `com.codename1.components.OnOffSwitch` allows us to toggle a state similar to the `com.codename1.ui.CheckBox`
/// but with a more modern look
///
///
/// ### ShareButton
///
/// ![](https://www.codenameone.com/img/developer-guide/components-sharebutton-android.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-sharebutton-android.png)
/// `com.codename1.components.ShareButton` provides native "social share" functionality
///
/// ### SpanLabel
///
/// ![](https://www.codenameone.com/img/developer-guide/components-spanlabel.png)
/// ![](https://www.codenameone.com/developer-guide/img/generated/components-spanlabel.png)
/// `com.codename1.components.SpanLabel` a text label that "seamlessly" breaks lines
///
/// ### SpanButton
///
/// ![](https://www.codenameone.com/img/developer-guide/components-spanbutton.png)
/// ![](https://www.codenameone.com/developer-guide/img/generated/components-spanbutton.png)
/// `com.codename1.components.SpanButton` a button that "seamlessly" breaks lines
///
/// ### Picker (Date)
///
/// ![](https://www.codenameone.com/img/developer-guide/components-picker-date-android.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-picker-date-android.png)
/// `com.codename1.ui.spinner.Picker` allows us to show an OS native picker UI (Date Picker)
///
///
/// ### Picker (Time)
///
/// ![](https://www.codenameone.com/img/developer-guide/components-picker-time-android.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-picker-time-android.png)
/// `com.codename1.ui.spinner.Picker` allows us to show an OS native picker UI (Time Picker)
///
///
/// ### ToastBar
///
/// ![](https://www.codenameone.com/img/developer-guide/components-statusbar.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-statusbar.png)
/// `com.codename1.components.ToastBar` shows a non-obtrusive notice on the bottom of the `Form`
///
///
/// ### SignatureComponent
///
/// ![](https://www.codenameone.com/img/developer-guide/components-signature2.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-signature2.png)
/// `com.codename1.components.SignatureComponent` shows a dialog that allows the user to "sign"
/// using the touch screen
///
///
/// ### Accordion
///
/// ![](https://www.codenameone.com/img/developer-guide/components-accordion.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-accordion.png)
/// `com.codename1.components.Accordion` displays collapsible content panels
///
/// ### FloatingHint
///
/// ![](https://www.codenameone.com/img/developer-guide/components-floatinghint.png)
/// ![](https://www.codenameone.com/developer-guide/img/components-floatinghint.png)
/// `com.codename1.components.FloatingHint` animates the text field hint into a label on top of
/// the text field and visa versa
///
Expand All @@ -287,3 +310,12 @@
/// `com.codename1.components.FloatingActionButton` hovers over the UI presenting a default
/// action
package com.codename1.ui;

// The image URLs above are /developer-guide/img/..., which is where these files
// are actually published: scripts/website/build.sh rsyncs docs/developer-guide/
// to the site's static/developer-guide/, preserving subdirectories, so a figure
// under img/generated/ serves from /developer-guide/img/generated/. They used to
// be written the other way round, /img/developer-guide/..., a path nothing in
// this repository produces. Renaming or moving a file under docs/developer-guide/img
// therefore does change these URLs, and they have to move with it.

Loading
Loading