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
28 changes: 28 additions & 0 deletions .github/workflows/developer-guide-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- 'docs/developer-guide/**'
- 'docs/demos/**'
- '.github/workflows/developer-guide-docs.yml'
release:
types: [published]
Expand All @@ -22,6 +23,32 @@ jobs:
- name: Check out repository
uses: actions/checkout@v4

- name: Determine changed components
id: changes
if: github.event_name == 'pull_request'
uses: dorny/paths-filter@v3
with:
filters: |
demos:
- 'docs/demos/**'
docs:
- 'docs/developer-guide/**'

- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '11'

- name: Build Codename One demos
if: github.event_name != 'pull_request' || steps.changes.outputs.demos == '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 test

- name: Determine publication metadata
run: |
set -euo pipefail
Expand Down Expand Up @@ -87,6 +114,7 @@ jobs:
gem install --no-document asciidoctor asciidoctor-pdf

- name: Build Developer Guide HTML and PDF
if: github.event_name != 'pull_request' || steps.changes.outputs.docs == 'true' || steps.changes.outputs.demos == 'true'
run: |
set -euo pipefail
OUTPUT_ROOT="build/developer-guide"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.codenameone.developerguide;

import com.codename1.components.SpanLabel;
import com.codename1.ui.Button;
import com.codename1.ui.Form;
import com.codename1.ui.Slider;
import com.codename1.ui.layouts.BoxLayout;

/**
* Simple interactive demo that lets the user update a counter using buttons and a slider.
*/
public class CounterDemo implements Demo {
@Override
public String getTitle() {
return "Counter";
}

@Override
public String getDescription() {
return "Interactive counter with increment/decrement controls and a slider.";
}

@Override
public void show(Form parent) {
Form form = new Form("Counter", BoxLayout.y());
form.setName("counterForm");
form.getToolbar().setBackCommand("Back", e -> parent.showBack());

SpanLabel valueLabel = new SpanLabel("Current value: 0");
valueLabel.setName("counterValueLabel");

Slider slider = new Slider();
slider.setName("counterSlider");
slider.setEditable(true);
slider.setMinValue(0);
slider.setMaxValue(20);
slider.setProgress(0);

Button increment = new Button("Increment");
increment.setName("incrementButton");
Button decrement = new Button("Decrement");
decrement.setName("decrementButton");

increment.addActionListener(e -> adjustValue(slider, valueLabel, Math.min(slider.getProgress() + 1, slider.getMaxValue())));
decrement.addActionListener(e -> adjustValue(slider, valueLabel, Math.max(slider.getProgress() - 1, slider.getMinValue())));
slider.addDataChangedListener((type, index) -> updateLabel(valueLabel, slider.getProgress()));

form.addAll(valueLabel, slider, increment, decrement);
form.show();
}

private void adjustValue(Slider slider, SpanLabel valueLabel, int newValue) {
slider.setProgress(newValue);
updateLabel(valueLabel, newValue);
}

private void updateLabel(SpanLabel valueLabel, int value) {
valueLabel.setText("Current value: " + value);
valueLabel.repaint();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.codenameone.developerguide;

import com.codename1.ui.Form;

/**
* Represents a standalone demo that can be launched from the demo browser.
*/
public interface Demo {
/**
* @return The title used to identify this demo to the user.
*/
String getTitle();

/**
* @return A short description that is displayed in the demo browser.
*/
String getDescription();

/**
* Launches the demo, optionally using the supplied parent form to return
* to when the demo is closed.
*
* @param parent The form that launched this demo.
*/
void show(Form parent);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.codenameone.developerguide;

import com.codename1.components.MultiButton;
import com.codename1.ui.Container;
import com.codename1.ui.Form;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.BoxLayout;

/**
* Parent form that lists all demos and allows launching them.
*/
public class DemoBrowserForm extends Form {

public DemoBrowserForm() {
super("Developer Guide Demos", new BorderLayout());
getToolbar().setTitleCentered(false);
Container listContainer = new Container(BoxLayout.y());
listContainer.setName("demoList");
listContainer.setScrollableY(true);

int index = 0;
for (Demo demo : DemoRegistry.getDemos()) {
MultiButton demoButton = new MultiButton(demo.getTitle());
demoButton.setTextLine2(demo.getDescription());
demoButton.setName("demoButton-" + index++);
demoButton.addActionListener(e -> demo.show(DemoBrowserForm.this));
listContainer.add(demoButton);
}

add(BorderLayout.CENTER, listContainer);
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,13 @@
package com.codenameone.developerguide;

import static com.codename1.ui.CN.*;
import com.codename1.system.Lifecycle;
import com.codename1.ui.*;
import com.codename1.ui.layouts.*;
import com.codename1.io.*;
import com.codename1.ui.plaf.*;
import com.codename1.ui.util.Resources;

/**
* This file was generated by <a href="https://www.codenameone.com/">Codename One</a> for the purpose
* of building native mobile applications using Java.
* Application entry point that launches the demo browser.
*/
public class DemoCode extends Lifecycle {
@Override
public void runApp() {
Form hi = new Form("Hi World", BoxLayout.y());
Button helloButton = new Button("Hello World");
hi.add(helloButton);
helloButton.addActionListener(e -> hello());
hi.getToolbar().addMaterialCommandToSideMenu("Hello Command",
FontImage.MATERIAL_CHECK, 4, e -> hello());
hi.show();
new DemoBrowserForm().show();
}

private void hello() {
Dialog.show("Hello Codename One", "Welcome to Codename One", "OK", null);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.codenameone.developerguide;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
* Registry of available demos so that the browser can enumerate them.
*/
public final class DemoRegistry {
private static final List<Demo> DEMOS = Collections.unmodifiableList(
Arrays.asList(
new HelloWorldDemo(),
new CounterDemo()
)
);

private DemoRegistry() {
// utility class
}

public static List<Demo> getDemos() {
return DEMOS;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.codenameone.developerguide;

import com.codename1.ui.Button;
import com.codename1.ui.Dialog;
import com.codename1.ui.Form;
import com.codename1.ui.layouts.BoxLayout;

/**
* Simple hello world demo showing a dialog.
*/
public class HelloWorldDemo implements Demo {

@Override
public String getTitle() {
return "Hello World";
}

@Override
public String getDescription() {
return "Shows a button that pops up a welcome dialog.";
}

@Override
public void show(Form parent) {
Form form = new Form("Hello World", BoxLayout.y());
form.setName("helloWorldForm");
form.getToolbar().setBackCommand("Back", e -> parent.showBack());
Button helloButton = new Button("Say Hello");
helloButton.setName("helloButton");
helloButton.addActionListener(e -> Dialog.show("Hello Codename One", "Welcome to Codename One", "OK", null));
form.add(helloButton);
form.show();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.codenameone.developerguide;

import com.codename1.components.SpanLabel;
import com.codename1.testing.AbstractTest;
import com.codename1.testing.TestUtils;
import com.codename1.ui.Button;
import com.codename1.ui.Command;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Slider;
import com.codename1.ui.events.ActionEvent;

/**
* Validates the Counter demo's interactions update the UI consistently.
*/
public class CounterDemoTest extends AbstractTest {

@Override
public boolean runTest() throws Exception {
Form parent = new Form("Parent");
parent.show();
TestUtils.waitForFormTitle("Parent", 5000);

Demo demo = new CounterDemo();
demo.show(parent);
TestUtils.waitForFormTitle("Counter", 5000);

Form current = Display.getInstance().getCurrent();
assertEqual("Counter", current.getTitle());
assertEqual("counterForm", current.getName());

SpanLabel valueLabel = (SpanLabel) TestUtils.findByName("counterValueLabel");
assertNotNull(valueLabel, "Counter value label should exist.");
assertEqual("Current value: 0", valueLabel.getText());

Slider slider = (Slider) TestUtils.findByName("counterSlider");
assertNotNull(slider, "Counter slider should exist.");
assertEqual(0, slider.getProgress());

Button increment = (Button) TestUtils.findByName("incrementButton");
Button decrement = (Button) TestUtils.findByName("decrementButton");
assertNotNull(increment);
assertNotNull(decrement);

increment.pressed();
increment.released();
TestUtils.waitFor(200);
assertEqual(1, slider.getProgress());
assertEqual("Current value: 1", valueLabel.getText());

slider.setProgress(slider.getMaxValue());
TestUtils.waitFor(200);
assertEqual("Current value: " + slider.getMaxValue(), valueLabel.getText());

increment.pressed();
increment.released();
TestUtils.waitFor(200);
assertEqual(slider.getMaxValue(), slider.getProgress());
assertEqual("Current value: " + slider.getMaxValue(), valueLabel.getText());

decrement.pressed();
decrement.released();
TestUtils.waitFor(200);
assertEqual(slider.getMaxValue() - 1, slider.getProgress());
assertEqual("Current value: " + (slider.getMaxValue() - 1), valueLabel.getText());

slider.setProgress(slider.getMinValue());
TestUtils.waitFor(200);
decrement.pressed();
decrement.released();
TestUtils.waitFor(200);
assertEqual(slider.getMinValue(), slider.getProgress());
assertEqual("Current value: " + slider.getMinValue(), valueLabel.getText());

Command back = current.getBackCommand();
assertNotNull(back, "Back command should be available.");
back.actionPerformed(new ActionEvent(back));
TestUtils.waitForFormTitle("Parent", 5000);
assertEqual(parent, Display.getInstance().getCurrent());

return true;
}

@Override
public boolean shouldExecuteOnEDT() {
return true;
}
}
Loading