An open API service indexing awesome lists of open source software.

https://github.com/http-rpc/sierra

Declarative UI for Java
https://github.com/http-rpc/sierra

charts declarative-ui gui java swing xml

Last synced: 3 days ago
JSON representation

Declarative UI for Java

Awesome Lists containing this project

README

          

[![Releases](https://img.shields.io/github/release/HTTP-RPC/Sierra.svg)](https://github.com/HTTP-RPC/Sierra/releases)
[![Maven Central](https://img.shields.io/maven-central/v/org.httprpc/sierra.svg)](https://central.sonatype.com/artifact/org.httprpc/sierra/versions)
[![javadoc](https://javadoc.io/badge2/org.httprpc/sierra/javadoc.svg)](https://javadoc.io/doc/org.httprpc/sierra)

# Introduction
Sierra is an open-source framework for simplifying development of Java Swing applications. It is extremely lightweight and has minimal external dependencies. The project's name comes from the nautical _S_ or _Sierra_ flag, representing the first letter in "Swing":

![](sierra.png)

This guide introduces the Sierra framework and provides an overview of its key features.

# Getting Sierra
Sierra is distributed via Maven Central at [org.httprpc:sierra](https://central.sonatype.com/artifact/org.httprpc/sierra/versions). Java 21 or later is required. [FlatLaf](https://www.formdev.com/flatlaf/) is recommended.

A [DTD](sierra.dtd) is provided to assist with editing. It is not used for validation and is not required.

A custom DTD can be generated using the [DTD encoder](sierra-tools/dtd-encoder) tool. An interactive [previewer](sierra-tools/previewer) tool is also available. Both can be downloaded [here](https://github.com/HTTP-RPC/Sierra/releases).

# Sierra Classes
Sierra provides the `UILoader` class, which can be used in conjunction with the following types to declaratively establish a hierarchy of user interface elements:

* `RowPanel` - arranges sub-components in a horizontal line, optionally aligning to baseline
* `ColumnPanel` - arranges sub-components in a vertical line, optionally aligning nested elements to a grid
* `StackPanel` - sizes sub-components to fill the available space
* `Spacer` - provides fixed or flexible space between other components

These classes offer an alternative to the standard Java layout managers, which can often be limiting or difficult to use in practice.

Sierra also includes the `TextPane` and `ImagePane` components, which provide an alternative to `JLabel` for displaying basic text or image content, respectively. `TextPane` supports wrapping without requiring HTML, and `ImagePane` supports scaling without requiring an intermediate `BufferedImage`.

For example, the following markup declares a column panel containing a graphic and a simple greeting:

```xml


```

This markup could be deserialized and set as the content pane of a frame or dialog as follows:

```java
setContentPane(UILoader.load(this, "GreetingTest.xml"));
```

The same result could be achieved programmatically as shown below. However, the markup version is less verbose and more readable:

```java
var columnPanel = new ColumnPanel();

columnPanel.setBorder(new EmptyBorder(8, 8, 8, 8));

columnPanel.setOpaque(true);
columnPanel.setBackground(Color.WHITE);

var imagePane = new ImagePane();

try (var inputStream = getClass().getResourceAsStream("world.png")) {
imagePane.setImage(ImageIO.read(inputStream));
} catch (IOException exception) {
throw new RuntimeException(exception);
}

imagePane.setScaleMode(ImagePane.ScaleMode.FILL_WIDTH);

columnPanel.add(imagePane);

var textPane = new TextPane("Hello, World!");

textPane.setHorizontalAlignment(HorizontalAlignment.CENTER);

columnPanel.add(textPane);
```

The complete source code for this example can be found [here](sierra-test/src/main/java/org/httprpc/sierra/test/GreetingTest.java).

## Elements
XML elements represent component instances. Most Swing and all Sierra components are supported by default. Support for additional elements can be added via the `bind()` method of the `UILoader` class.

Elements can be nested to create a component hierarchy. For example:

```xml









```

## Attributes
XML attributes generally represent component properties. For example, this markup creates an instance of `TextPane` and sets its "text" property to "Hello, World!":

```xml

```

Numeric and boolean values are specified via their string representations. Supported constants and enum values are specified in [kebab case](https://en.wikipedia.org/wiki/Letter_case#Kebab_case).

### Color and Font Values
Color and font properties can be specified using the formats supported by `Color#decode()` and `Font#decode()`, respectively. For example, this markup creates an instance of `RowPanel` and sets its "background" property to white:

```xml

...

```

Colors and fonts can also be specified by name. The name can refer to either a value provided by Swing's UI defaults or a value defined by `UILoader`:

Sierra supports the complete set of [extended web colors](https://en.wikipedia.org/wiki/Web_colors#Extended_colors) by default. Additional named colors and fonts can be added via the `define()` methods of the `UILoader` class.

### Image and Icon Values
Image and icon properties can be specified via a path to an image document on the application's classpath. The path is relative to the document's "owner", the value passed as the first argument to `UILoader#load()`. For example:

```xml

```

Icon support is currently limited to SVG documents and requires the [FlatLaf Extras](https://github.com/JFormDesigner/FlatLaf/tree/main/flatlaf-extras) library:

```xml

```

Icons automatically adapt to the current theme:

Custom dimensions can be specified either as _path; size_ or _path; width, height_:

```xml
icon="icons/home_24dp.svg; 18"
```

### Border and Padding Values
The "border" and "padding" attributes can be used to create a solid border and reserve space around a component, respectively. For example, this markup creates a label with a light gray border and four pixels of padding on each side:

```xml

```

Border thickness can be specified as shown below:

```xml
border="#00ff00, 4"
```

Padding values for multiple sides can be specified in _top_, _left_, _bottom_, _right_ order:

```xml
padding="8, 8, 8, 8"
```

### Title Values
As an alternative to "border" and "padding", the "title" attribute can be used to establish a titled border around a component:

```xml



```

### Weight and Size Values
The "weight" attribute specifies the amount of excess space in a container that should be allocated to a component, relative to other weighted components in the container. When applied to a `Spacer` instance, it creates a "glue" component that automatically shrinks or stretches depending on the size of its container. However, weights are not limited to spacers and can be applied to any component type:

```xml



```

The "size" attribute specifies a fixed dimension for a component. It is typically used with `Spacer` instances to create "struts" between components, as an alternative to the "spacing" property provided by `RowPanel` and `ColumnPanel`:

```xml










...

```

Size values for multiple dimensions can be specified in _width_, _height_ order:

```xml
size="20, 20"
```

### FlatLaf Client Properties
FlatLaf style and [style class](https://www.formdev.com/flatlaf/typography/) values can be specified via the "style" and "styleClass" attributes, respectively. For example, this markup applies the "h4" style class to a `JLabel` instance used by a list cell renderer:

```xml




```

FlatLaf text styles are also accessible via the "font" property:

```xml

```

Several FlatLaf text field [properties](https://www.formdev.com/flatlaf/client-properties/#JTextField) are also supported. For example:

```xml



```

### Button Groups
The "group" attribute associates a button with a button group. For example, the following markup creates two radio buttons belonging to the "orientation" group:

```xml

```

### Tabbed Panes
When used in conjunction with `JTabbedPane`, the "tabTitle" and "tabIcon" attributes can be used to specify a component's tab title and icon, respectively:

```xml

```

### Element Names
The "name" attribute associates an identifier with a component. In addition to setting the component's "name" property, `UILoader` automatically injects the component itself into a field with the same name defined by the document's owner (called an "outlet").

For example, the following markup declares outlets named "greetingButton" and "greetingLabel":

```xml

```

When the `load()` method returns, the corresponding fields in the owner will be populated with the instances declared in the markup. Though not required, use of the `Outlet` annotation is recommended:

```java
public class ActionTest extends JFrame implements Runnable {
private @Outlet JButton greetingButton = null;
private @Outlet JLabel greetingLabel = null;

private static final ResourceBundle resourceBundle = ResourceBundle.getBundle(ActionTest.class.getName());

...

@Override
public void run() {
setContentPane(UILoader.load(this, "ActionTest.xml", resourceBundle));

greetingButton.addActionListener(event -> sayHello());

...
}

private void sayHello() {
greetingLabel.setText(resourceBundle.getString("greeting"));
}

...
}
```

### Resource Bundles
An optional resource bundle may be provided as the third argument to the `load()` method of `UILoader`. When specified, values of text properties are considered resource keys and are used to look up the associated strings in the bundle. For example:

```xml












...

```

```properties
title = Form Test

firstName = First Name
lastName = Last Name
streetAddress = Street Address

...
```

## Cell Alignment
When grid alignment is enabled in a `ColumnPanel`, the sub-components of every `RowPanel` in the column are vertically aligned in a grid, as in a spreadsheet or HTML table. The width of each sub-column is the maximum preferred width of the "cells" in that column (i.e. the components having the same index in each row).

Cell contents are aligned based on the component's _x_ and _y_ alignment values (returned by `getAlignmentX()` and `getAlignmentY()`, respectively). For most components, the default is 0.5, indicating that the component should fill the entire cell along both axes. Values between 0.0 and 0.5 will align the component to the cell's leading or top edge, and values between 0.5 and 1.0 will align the component to the cell's trailing or bottom edge. In both cases, a proportional amount of the excess space will be allocated to the component. A value of 0 or 1 will result in no excess space being given to the component (i.e. it will be aligned to the appropriate edge and will be given its preferred size along that axis).

For example, the following markup demonstrates x-alignment:

```xml













```

This markup demonstrates y-alignment:

```xml




















```

Row spacing and cell weights are ignored when grid alignment is enabled.

## Utility Components
In addition to the features outlined above, Sierra also includes some common user interface elements not provided by Swing.

### Validated Input
The `NumberField` and `ValidatedTextField` components can be used to validate user input. `NumberField` accepts only numeric content, and `ValidatedTextField` accepts only content that matches a provided regular expression. Similiar to `JFormattedTextField`, the `getValue()` method of these classes can be used to obtain the validated data:

`NumberField` is localized. See [ValidatedInputTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/ValidatedInputTest.java) for more information.

### Date and Time Selection
The `DatePicker` and `TimePicker` components allow a user to select a local date and time, respectively:


These classes are localized. See [DateTimePickerTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/DateTimePickerTest.java) for more information.

### Suggestion Pickers
The `SuggestionPicker` component allows a user to choose from a list of predefined values:

See [SuggestionPickerTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/SuggestionPickerTest.java) for more information.

### Menu Buttons
The `MenuButton` component displays a popup menu when pressed:

See [MenuButtonTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/MenuButtonTest.java) for more information.

### Activity Indicators
The `ActivityIndicator` component shows indeterminate progress:

See [ActivityIndicatorTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/ActivityIndicatorTest.java) for more information.

### Charts
The `ChartPane` component displays a [chart](charts-reference.md):

Charts automatically adapt to the current theme:


See [ChartsTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/ChartsTest.java) for more information.

## Focus Management
The `ScrollingKeyboardFocusManager` class ensures that components are automatically scrolled into view when focused (something that Swing oddly does not do by default). It can be installed at application startup as follows:

```java
KeyboardFocusManager.setCurrentKeyboardFocusManager(new ScrollingKeyboardFocusManager());
```

See [FormTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/FormTest.java) for more information.

## Task Execution
The `TaskExecutor` class performs a task in the background and and invokes a callback on the UI thread when the task is complete:

```java
public void execute(Callable task, BiConsumer handler) { ... }
```

For example:

```java
taskExecutor.execute(() -> {
// Perform long-running task that may throw
return result;
}, (result, exception) -> {
if (exception == null) {
// Handle success
} else {
// Handle failure
}
});
```

Internally, tasks are submitted to an executor service provided to the `TaskExecutor` constructor. See [TaskExecutorTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/TaskExecutorTest.java) for more information.

# Complete Example
The following is a complete example of an application built using Sierra. It uses the Tiingo [End-of-Day](https://www.tiingo.com/documentation/end-of-day) API to retrieve historical stock pricing information:


The application consists of the following source files:

* [TiingoTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/TiingoTest.java) - primary application logic
* [TiingoServiceProxy.java](sierra-test/src/main/java/org/httprpc/sierra/test/TiingoServiceProxy.java) - proxy interface used to submit API requests
* [Asset.java](sierra-test/src/main/java/org/httprpc/sierra/test/Asset.java) and [AssetPricing.java](sierra-test/src/main/java/org/httprpc/sierra/test/AssetPricing.java) - data types used by `TiingoServiceProxy`
* [TiingoTest.xml](sierra-test/src/main/resources/org/httprpc/sierra/test/TiingoTest.xml) - UI declaration
* [TiingoTest.properties](sierra-test/src/main/resources/org/httprpc/sierra/test/TiingoTest.properties) - localized string resources

An API token is required and must be specified as a system property at application startup:

```
-Dtoken=
```