{"id":23413687,"url":"https://github.com/http-rpc/sierra","last_synced_at":"2026-04-06T18:00:59.345Z","repository":{"id":46264352,"uuid":"515268257","full_name":"HTTP-RPC/Sierra","owner":"HTTP-RPC","description":"Declarative UI for Java","archived":false,"fork":false,"pushed_at":"2026-03-19T19:05:53.000Z","size":40624,"stargazers_count":139,"open_issues_count":0,"forks_count":11,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-03-20T10:30:21.032Z","etag":null,"topics":["charts","declarative-ui","gui","java","swing","xml"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HTTP-RPC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-07-18T16:51:23.000Z","updated_at":"2026-03-19T19:05:58.000Z","dependencies_parsed_at":"2024-04-19T22:22:44.878Z","dependency_job_id":"79adcc79-c201-436d-b119-7484baf640fa","html_url":"https://github.com/HTTP-RPC/Sierra","commit_stats":{"total_commits":229,"total_committers":1,"mean_commits":229.0,"dds":0.0,"last_synced_commit":"6be8b591c98e2529083ee61fe91ce4bef2c07141"},"previous_names":[],"tags_count":107,"template":false,"template_full_name":null,"purl":"pkg:github/HTTP-RPC/Sierra","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HTTP-RPC%2FSierra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HTTP-RPC%2FSierra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HTTP-RPC%2FSierra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HTTP-RPC%2FSierra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HTTP-RPC","download_url":"https://codeload.github.com/HTTP-RPC/Sierra/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HTTP-RPC%2FSierra/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31483380,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T17:22:55.647Z","status":"ssl_error","status_checked_at":"2026-04-06T17:22:54.741Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["charts","declarative-ui","gui","java","swing","xml"],"created_at":"2024-12-22T19:54:07.337Z","updated_at":"2026-04-06T18:00:59.298Z","avatar_url":"https://github.com/HTTP-RPC.png","language":"Java","readme":"[![Releases](https://img.shields.io/github/release/HTTP-RPC/Sierra.svg)](https://github.com/HTTP-RPC/Sierra/releases)\n[![Maven Central](https://img.shields.io/maven-central/v/org.httprpc/sierra.svg)](https://central.sonatype.com/artifact/org.httprpc/sierra/versions)\n[![javadoc](https://javadoc.io/badge2/org.httprpc/sierra/javadoc.svg)](https://javadoc.io/doc/org.httprpc/sierra)\n\n# Introduction\nSierra 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\":\n\n![](sierra.png)\n\nThis guide introduces the Sierra framework and provides an overview of its key features.\n\n# Getting Sierra\nSierra 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.\n\nA [DTD](sierra.dtd) is provided to assist with editing. It is not used for validation and is not required. \n\nA 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).\n\n# Sierra Classes\nSierra provides the `UILoader` class, which can be used in conjunction with the following types to declaratively establish a hierarchy of user interface elements:\n\n* `RowPanel` - arranges sub-components in a horizontal line, optionally aligning to baseline\n* `ColumnPanel` - arranges sub-components in a vertical line, optionally aligning nested elements to a grid\n* `StackPanel` - sizes sub-components to fill the available space\n* `Spacer` - provides fixed or flexible space between other components\n\nThese classes offer an alternative to the standard Java layout managers, which can often be limiting or difficult to use in practice.\n\nSierra 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`.\n\nFor example, the following markup declares a column panel containing a graphic and a simple greeting:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\n\u003c!DOCTYPE column-panel SYSTEM \"sierra.dtd\"\u003e\n\n\u003ccolumn-panel padding=\"8\" opaque=\"true\" background=\"white\"\u003e\n    \u003cimage-pane image=\"world.png\" scaleMode=\"fill-width\"/\u003e\n    \u003ctext-pane text=\"Hello, World!\" horizontalAlignment=\"center\"/\u003e\n\u003c/column-panel\u003e\n```\n\nThis markup could be deserialized and set as the content pane of a frame or dialog as follows:\n\n```java\nsetContentPane(UILoader.load(this, \"GreetingTest.xml\"));\n```\n\n\u003cimg src=\"README/greeting.png\" width=\"432px\"/\u003e\n\nThe same result could be achieved programmatically as shown below. However, the markup version is less verbose and more readable:\n\n```java\nvar columnPanel = new ColumnPanel();\n\ncolumnPanel.setBorder(new EmptyBorder(8, 8, 8, 8));\n\ncolumnPanel.setOpaque(true);\ncolumnPanel.setBackground(Color.WHITE);\n\nvar imagePane = new ImagePane();\n\ntry (var inputStream = getClass().getResourceAsStream(\"world.png\")) {\n    imagePane.setImage(ImageIO.read(inputStream));\n} catch (IOException exception) {\n    throw new RuntimeException(exception);\n}\n\nimagePane.setScaleMode(ImagePane.ScaleMode.FILL_WIDTH);\n\ncolumnPanel.add(imagePane);\n\nvar textPane = new TextPane(\"Hello, World!\");\n\ntextPane.setHorizontalAlignment(HorizontalAlignment.CENTER);\n\ncolumnPanel.add(textPane);\n```\n\nThe complete source code for this example can be found [here](sierra-test/src/main/java/org/httprpc/sierra/test/GreetingTest.java).\n\n## Elements\nXML 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.\n\nElements can be nested to create a component hierarchy. For example:\n\n```xml\n\u003ccolumn-panel spacing=\"8\" padding=\"8\" opaque=\"true\"\u003e\n    \u003ccolumn-panel\u003e\n        \u003ccheck-box text=\"checkBox1\"/\u003e\n        \u003ccheck-box text=\"checkBox2\"/\u003e\n    \u003c/column-panel\u003e\n\n    \u003crow-panel spacing=\"8\"\u003e\n        \u003cbutton name=\"button\" text=\"executeTask\"/\u003e\n        \u003clabel name=\"label\" foreground=\"gray\"/\u003e\n        \u003cspacer weight=\"1\"/\u003e\n        \u003cactivity-indicator name=\"activityIndicator\" indicatorSize=\"18\"/\u003e\n    \u003c/row-panel\u003e\n\u003c/column-panel\u003e\n```\n\n\u003cimg src=\"README/task-executor.png\" width=\"432px\"/\u003e\n\n## Attributes\nXML attributes generally represent component properties. For example, this markup creates an instance of `TextPane` and sets its \"text\" property to \"Hello, World!\":\n\n```xml\n\u003ctext-pane text=\"Hello, World!\" horizontalAlignment=\"center\"/\u003e\n```\n\nNumeric 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).\n\n### Color and Font Values\nColor 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:\n\n```xml\n\u003crow-panel spacing=\"8\" padding=\"16\" opaque=\"true\" background=\"#ffffff\"\u003e\n    ...\n\u003c/row-panel\u003e\n```\n\nColors 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`:\n\n\u003cimg src=\"README/color-chooser.png\" width=\"1136px\"/\u003e\n\nSierra 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.\n\n### Image and Icon Values\nImage 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:\n\n```xml\n\u003cimage-pane image=\"world.png\" scaleMode=\"fill-width\"/\u003e\n```\n\nIcon support is currently limited to SVG documents and requires the [FlatLaf Extras](https://github.com/JFormDesigner/FlatLaf/tree/main/flatlaf-extras) library:\n\n```xml\n\u003ctoggle-button name=\"alignLeftButton\"\n    icon=\"icons/format_align_left_24dp.svg\"\n    style=\"buttonType: toolBarButton\"\n    group=\"alignment\"/\u003e\n```\n\n\u003cimg src=\"README/button-group.png\" width=\"432px\"/\u003e\n\nIcons automatically adapt to the current theme:\n\n\u003cimg src=\"README/button-group-dark.png\" width=\"432px\"/\u003e\n\nCustom dimensions can be specified either as _path; size_ or _path; width, height_:\n\n```xml\nicon=\"icons/home_24dp.svg; 18\"\n```\n\n### Border and Padding Values\nThe \"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:\n\n```xml\n\u003clabel text=\"pageStart\" horizontalAlignment=\"center\" border=\"silver\" padding=\"4\"/\u003e\n```\n\nBorder thickness can be specified as shown below:\n\n```xml\nborder=\"#00ff00, 4\"\n```\n\nPadding values for multiple sides can be specified in _top_, _left_, _bottom_, _right_ order:\n\n```xml\npadding=\"8, 8, 8, 8\"\n```\n\n### Title Values\nAs an alternative to \"border\" and \"padding\", the \"title\" attribute can be used to establish a titled border around a component:\n\n```xml\n\u003ccolumn-panel title=\"Options\"\u003e\n    \u003cradio-button text=\"One\" group=\"options\" selected=\"true\"/\u003e\n    \u003cradio-button text=\"Two\" group=\"options\"/\u003e\n    \u003cradio-button text=\"Three\" group=\"options\"/\u003e\n\u003c/column-panel\u003e\n```\n\n\u003cimg src=\"README/title.png\" width=\"352px\"/\u003e\n\n### Weight and Size Values\nThe \"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:\n\n```xml\n\u003crow-panel spacing=\"4\" weight=\"1\"\u003e\n    \u003clabel text=\"lineStart\" font=\"h2\" horizontalAlignment=\"center\" border=\"silver\" padding=\"4\"/\u003e\n    \u003clabel text=\"center\" font=\"h1\" horizontalAlignment=\"center\" border=\"silver\" padding=\"4\" weight=\"1\"/\u003e\n    \u003clabel text=\"lineEnd\" font=\"h2\" horizontalAlignment=\"center\" border=\"silver\" padding=\"4\"/\u003e\n\u003c/row-panel\u003e\n```\n\n\u003cimg src=\"README/border.png\" width=\"592px\"/\u003e\n\nThe \"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`:\n\n```xml\n\u003ccolumn-panel spacing=\"4\" padding=\"8\" opaque=\"true\"\u003e\n    \u003crow-panel\u003e\n        \u003cbutton text=\"1a\"/\u003e\n        \u003cspacer size=\"4\"/\u003e\n        \u003cbutton text=\"1b\"/\u003e\n        \u003cspacer size=\"4\"/\u003e\n        \u003cbutton text=\"1c\"/\u003e\n        \u003cspacer weight=\"1\"/\u003e\n    \u003c/row-panel\u003e\n    \n    ...\n\u003c/column-panel\u003e\n```\n\n\u003cimg src=\"README/box.png\" width=\"559px\"/\u003e\n\nSize values for multiple dimensions can be specified in _width_, _height_ order:\n\n```xml\nsize=\"20, 20\"\n```\n\n### FlatLaf Client Properties\nFlatLaf 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:\n\n```xml\n\u003crow-panel spacing=\"4\" padding=\"4\" opaque=\"true\"\u003e\n    \u003cimage-pane name=\"imagePane\" size=\"30, 30\" scaleMode=\"fill-width\"/\u003e\n\n    \u003ccolumn-panel\u003e\n        \u003clabel name=\"nameLabel\" styleClass=\"h4\"/\u003e\n        \u003clabel name=\"descriptionLabel\"/\u003e\n    \u003c/column-panel\u003e\n\u003c/row-panel\u003e\n```\n\n\u003cimg src=\"README/cell-renderer.png\" width=\"532px\"/\u003e\n\nFlatLaf text styles are also accessible via the \"font\" property:\n\n```xml\n\u003ctext-pane text=\"Heading 1\" font=\"h1.font\" wrapText=\"true\"/\u003e\n```\n\n\u003cimg src=\"README/block-layout.png\" width=\"472px\"/\u003e\n\nSeveral FlatLaf text field [properties](https://www.formdev.com/flatlaf/client-properties/#JTextField) are also supported. For example: \n\n```xml\n\u003ccolumn-panel spacing=\"4\" padding=\"8\" opaque=\"true\"\u003e\n    \u003ctext-field columns=\"16\"\n        placeholderText=\"firstName\"\n        showClearButton=\"true\"/\u003e\n    \n    \u003ctext-field columns=\"16\"\n        placeholderText=\"lastName\"\n        showClearButton=\"true\"/\u003e\n\n    \u003cspacer size=\"8\"/\u003e\n\n    \u003ctext-field columns=\"16\"\n        leadingIcon=\"icons/search_24dp.svg; 18\"\n        trailingIcon=\"icons/people_24dp.svg; 18\"/\u003e\n\u003c/column-panel\u003e\n```\n\n\u003cimg src=\"README/text-fields.png\" width=\"318px\"/\u003e\n\n### Button Groups\nThe \"group\" attribute associates a button with a button group. For example, the following markup creates two radio buttons belonging to the \"orientation\" group:\n\n```xml\n\u003cradio-button name=\"leftToRightButton\" group=\"orientation\" text=\"leftToRight\"/\u003e\n\u003cradio-button name=\"rightToLeftButton\" group=\"orientation\" text=\"rightToLeft\"/\u003e\n```\n\n\u003cimg src=\"README/orientation.png\" width=\"454px\"/\u003e\n\n### Tabbed Panes\nWhen used in conjunction with `JTabbedPane`, the \"tabTitle\" and \"tabIcon\" attributes can be used to specify a component's tab title and icon, respectively:\n\n```xml\n\u003ctabbed-pane name=\"tabbedPane\" tabPlacement=\"top\" tabLayoutPolicy=\"scroll-tab-layout\"\u003e\n    \u003clabel tabTitle=\"Tab 1\" tabIcon=\"icons/home_24dp.svg; 18\"\n        text=\"This is the first tab.\"\n        horizontalAlignment=\"center\"\n        verticalAlignment=\"center\"/\u003e\n\u003c/tabbed-pane\u003e\n```\n\n\u003cimg src=\"README/root-pane.png\" width=\"592px\"/\u003e\n\n### Element Names\nThe \"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\").\n\nFor example, the following markup declares outlets named \"greetingButton\" and \"greetingLabel\": \n\n```xml\n\u003cbutton name=\"greetingButton\" text=\"prompt\"/\u003e\n\u003clabel name=\"greetingLabel\" horizontalAlignment=\"center\"/\u003e\n```\n\nWhen 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:\n\n```java\npublic class ActionTest extends JFrame implements Runnable {\n    private @Outlet JButton greetingButton = null;\n    private @Outlet JLabel greetingLabel = null;\n\n    private static final ResourceBundle resourceBundle = ResourceBundle.getBundle(ActionTest.class.getName());\n\n    ...\n\n    @Override\n    public void run() {\n        setContentPane(UILoader.load(this, \"ActionTest.xml\", resourceBundle));\n\n        greetingButton.addActionListener(event -\u003e sayHello());\n\n        ...\n    }\n\n    private void sayHello() {\n        greetingLabel.setText(resourceBundle.getString(\"greeting\"));\n    }\n\n    ...\n}\n```\n\n\u003cimg src=\"README/action.png\" width=\"352px\"/\u003e\n\n### Resource Bundles\nAn 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:\n\n```xml\n\u003ccolumn-panel spacing=\"4\" padding=\"8\" alignToGrid=\"true\" scrollableTracksViewportWidth=\"true\"\u003e\n    \u003crow-panel alignToBaseline=\"true\"\u003e\n        \u003clabel text=\"firstName\" alignmentX=\"1.0\"/\u003e\n        \u003ctext-field columns=\"12\" alignmentX=\"0.0\"/\u003e\n    \u003c/row-panel\u003e\n\n    \u003crow-panel alignToBaseline=\"true\"\u003e\n        \u003clabel text=\"lastName\" alignmentX=\"1.0\"/\u003e\n        \u003ctext-field columns=\"12\" alignmentX=\"0.0\"/\u003e\n    \u003c/row-panel\u003e\n\n    \u003crow-panel alignToBaseline=\"true\"\u003e\n        \u003clabel text=\"streetAddress\" alignmentX=\"1.0\"/\u003e\n        \u003ctext-field columns=\"24\" alignmentX=\"0.0\"/\u003e\n    \u003c/row-panel\u003e\n    \n    ...\n\u003c/column-panel\u003e\n```\n\n```properties\ntitle = Form Test\n\nfirstName = First Name\nlastName = Last Name\nstreetAddress = Street Address\n\n...\n```\n\n\u003cimg src=\"README/form.png\" width=\"592px\"/\u003e\n\n## Cell Alignment\nWhen 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).\n\nCell 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).\n\nFor example, the following markup demonstrates x-alignment:\n\n```xml\n\u003ccolumn-panel spacing=\"4\" padding=\"8\" alignToGrid=\"true\" opaque=\"true\"\u003e\n    \u003crow-panel\u003e\n        \u003ctext-pane text=\"0.0\" alignmentX=\"0.0\" border=\"silver\"/\u003e\n        \u003ctext-pane text=\"0.25\" horizontalAlignment=\"center\" alignmentX=\"0.25\" border=\"silver\"/\u003e\n        \u003ctext-pane text=\"0.5\" horizontalAlignment=\"center\" alignmentX=\"0.5\" border=\"silver\"/\u003e\n        \u003ctext-pane text=\"0.75\" horizontalAlignment=\"center\" alignmentX=\"0.75\" border=\"silver\"/\u003e\n        \u003ctext-pane text=\"1.0\" alignmentX=\"1.0\" border=\"silver\"/\u003e\n    \u003c/row-panel\u003e\n\n    \u003crow-panel\u003e\n        \u003cspacer size=\"120, 40\" border=\"silver\"/\u003e\n        \u003cspacer size=\"120, 40\" border=\"silver\"/\u003e\n        \u003cspacer size=\"120, 40\" border=\"silver\"/\u003e\n        \u003cspacer size=\"120, 40\" border=\"silver\"/\u003e\n        \u003cspacer size=\"120, 40\" border=\"silver\"/\u003e\n    \u003c/row-panel\u003e\n\u003c/column-panel\u003e\n```\n\n\u003cimg src=\"README/alignment-x.png\" width=\"744px\"/\u003e\n\nThis markup demonstrates y-alignment:\n\n```xml\n\u003ccolumn-panel spacing=\"4\" padding=\"8\" alignToGrid=\"true\" opaque=\"true\"\u003e\n    \u003crow-panel\u003e\n        \u003ctext-pane text=\"0.0\" alignmentY=\"0.0\" border=\"silver\"/\u003e\n        \u003cspacer size=\"160, 80\" border=\"silver\"/\u003e\n    \u003c/row-panel\u003e\n    \u003crow-panel\u003e\n        \u003ctext-pane text=\"0.25\" verticalAlignment=\"center\" alignmentY=\"0.25\" border=\"silver\"/\u003e\n        \u003cspacer size=\"160, 80\" border=\"silver\"/\u003e\n    \u003c/row-panel\u003e\n    \u003crow-panel\u003e\n        \u003ctext-pane text=\"0.5\" verticalAlignment=\"center\" alignmentY=\"0.5\" border=\"silver\"/\u003e\n        \u003cspacer size=\"160, 80\" border=\"silver\"/\u003e\n    \u003c/row-panel\u003e\n    \u003crow-panel\u003e\n        \u003ctext-pane text=\"0.75\" verticalAlignment=\"center\" alignmentY=\"0.75\" border=\"silver\"/\u003e\n        \u003cspacer size=\"160, 80\" border=\"silver\"/\u003e\n    \u003c/row-panel\u003e\n    \u003crow-panel\u003e\n        \u003ctext-pane text=\"1.0\" alignmentY=\"1.0\" border=\"silver\"/\u003e\n        \u003cspacer size=\"160, 80\" border=\"silver\"/\u003e\n    \u003c/row-panel\u003e\n\u003c/column-panel\u003e\n```\n\n\u003cimg src=\"README/alignment-y.png\" width=\"319px\"/\u003e\n\nRow spacing and cell weights are ignored when grid alignment is enabled.\n\n## Utility Components\nIn addition to the features outlined above, Sierra also includes some common user interface elements not provided by Swing.\n\n### Validated Input\nThe `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:\n\n\u003cimg src=\"README/validated-input.png\" width=\"325px\"/\u003e\n\n`NumberField` is localized. See [ValidatedInputTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/ValidatedInputTest.java) for more information.\n\n### Date and Time Selection\nThe `DatePicker` and `TimePicker` components allow a user to select a local date and time, respectively:\n\n\u003cimg src=\"README/date-time-picker-1.png\" width=\"460px\"/\u003e\n\u003cimg src=\"README/date-time-picker-2.png\" width=\"460px\"/\u003e\n\nThese classes are localized. See [DateTimePickerTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/DateTimePickerTest.java) for more information.\n\n### Suggestion Pickers\nThe `SuggestionPicker` component allows a user to choose from a list of predefined values: \n\n\u003cimg src=\"README/suggestion-picker.png\" width=\"300px\"/\u003e\n\nSee [SuggestionPickerTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/SuggestionPickerTest.java) for more information.\n\n### Menu Buttons\nThe `MenuButton` component displays a popup menu when pressed:\n\n\u003cimg src=\"README/menu-button.png\" width=\"210px\"/\u003e\n\nSee [MenuButtonTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/MenuButtonTest.java) for more information.\n\n### Activity Indicators\nThe `ActivityIndicator` component shows indeterminate progress:\n\n\u003cimg src=\"README/activity-indicator.png\" width=\"157px\"/\u003e\n\nSee [ActivityIndicatorTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/ActivityIndicatorTest.java) for more information.\n\n### Charts\nThe `ChartPane` component displays a [chart](charts-reference.md):\n\n\u003cimg src=\"README/charts.png\" width=\"630px\"/\u003e\n\nCharts automatically adapt to the current theme:\n\n\u003cimg src=\"README/charts-dark-1.png\" width=\"630px\"/\u003e\n\u003cimg src=\"README/charts-dark-2.png\" width=\"630px\"/\u003e\n\nSee [ChartsTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/ChartsTest.java) for more information.\n\n## Focus Management\nThe `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:\n\n```java\nKeyboardFocusManager.setCurrentKeyboardFocusManager(new ScrollingKeyboardFocusManager());\n```\n\nSee [FormTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/FormTest.java) for more information.\n\n## Task Execution\nThe `TaskExecutor` class performs a task in the background and and invokes a callback on the UI thread when the task is complete:\n\n```java\npublic \u003cT\u003e void execute(Callable\u003cT\u003e task, BiConsumer\u003cT, Exception\u003e handler) { ... }\n```\n\nFor example:\n\n```java\ntaskExecutor.execute(() -\u003e {    \n    // Perform long-running task that may throw\n    return result;\n}, (result, exception) -\u003e {\n    if (exception == null) {\n        // Handle success\n    } else {\n        // Handle failure\n    }\n});\n```\n\nInternally, 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.\n\n# Complete Example\nThe 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:\n\n\u003cimg src=\"README/tiingo.png\" width=\"1072px\"/\u003e\n\u003cimg src=\"README/tiingo-dark.png\" width=\"1072px\"/\u003e\n\nThe application consists of the following source files:\n\n* [TiingoTest.java](sierra-test/src/main/java/org/httprpc/sierra/test/TiingoTest.java) - primary application logic\n* [TiingoServiceProxy.java](sierra-test/src/main/java/org/httprpc/sierra/test/TiingoServiceProxy.java) - proxy interface used to submit API requests\n* [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`\n* [TiingoTest.xml](sierra-test/src/main/resources/org/httprpc/sierra/test/TiingoTest.xml) - UI declaration\n* [TiingoTest.properties](sierra-test/src/main/resources/org/httprpc/sierra/test/TiingoTest.properties) - localized string resources\n\nAn API token is required and must be specified as a system property at application startup:\n\n```\n-Dtoken=\u003cTiingo API Token\u003e\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttp-rpc%2Fsierra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhttp-rpc%2Fsierra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttp-rpc%2Fsierra/lists"}