Skip to content

Latest commit

 

History

History
204 lines (164 loc) · 8.98 KB

File metadata and controls

204 lines (164 loc) · 8.98 KB

Spine Chords Core

Facilities and components for writing desktop applications with the Compose Multiplatform framework.

Default look and feel

Chords applications use a compact Material 3 desktop theme by default. It provides neutral work surfaces, semantic light and dark color schemes, restrained corner radii, regular-weight typography, and shared dimensions for common controls, navigation, tables, dialogs, and supporting panes. The dark scheme is selected from the operating system appearance observed at application startup. Changes to the system appearance while the application is running are not observed automatically; override ApplicationTheme when the application needs a live theme switch.

The standard Material values are available through MaterialTheme. Desktop values that Material does not define are available through ChordsTheme:

val rowHeight = ChordsTheme.dimensions.tableRowHeight
val hoverAlpha = ChordsTheme.interaction.hoveredStateAlpha

An application can replace the theme in one place by overriding Application.ApplicationTheme:

@Composable
override fun ApplicationTheme(content: @Composable () -> Unit) {
    ChordsTheme(
        colorScheme = myColorScheme,
        typography = myTypography,
        shapes = myShapes,
        dimensions = ChordsDimensions(
            controlHeight = 48.dp,
            tableRowHeight = 44.dp
        ),
        content = content
    )
}

Component properties take precedence over theme values. Class-based components can also be customized application-wide with sharedDefaults. The effective order is: instance properties, shared component defaults, Chords desktop tokens, and finally Material theme values.

Menus, dialogs, and tooltips use ChordsTheme.overlayColor and a visible outline to separate layers in dark themes. Custom popup panels can use PopupSurface; Material dropdown menus can apply Modifier.popupAppearance() from the same file. Filled actions use PrimaryButton; outlined actions use SecondaryButton. For actions represented by a single icon, use CircularIconButton. These buttons provide hover and keyboard focus feedback in the active window. EmptyState supplies the illustration, caption, and alignment for empty work areas. ScrollableColumn keeps long details reachable within a bounded pane. Each component's KDoc includes usage examples. Confirmation prompts share ChordsTheme.confirmationTextStyle.

Text inputs and selectors expose their text style, shape, modifier, and colors. Dropdowns expose popup shape, elevations, item height, padding, and selection colors. Tables expose content padding, container/header/row colors, and row heights. Dialogs, lightweight windows, and wizards expose their unique sizing, spacing, surface, shape, border, and elevation values.

Using Spine Chords Core in a Gradle project

Add a dependency to the library as follows:

dependencies {
    implementation("io.spine.chords:spine-chords-core:$chordsVersion")
}

Overview of library's facilities

Below is a high-level overview of what is included in the module for a quick start. You can also study the references for a more detailed documentation on respective topics.

Application's shell

Provides an API that simplifies creating Compose desktop applications that follow a multiview UI organization.

Although many components in Chords libraries do not depend on how the application is created on a high level, some components (particularly in the Spine Chords Client library) expect that the application is created using this Application Shell API.

See appshell/README.md for details.

A notion of class-based components

As an alternative to writing components as @Composable functions, as is typical in Compose, this library also adds a possibility to write components as classes. This adds certain possibilities for writing and using Compose components, while still maintaining an experience of using such components that is very similar to using regular function-based ones.

This approach doesn't replace the function-based components, but adds a possibility to write components using an object-oriented paradigm whenever that appears more appropriate, while using such components interchangeably with the usual function-based ones. The syntax of using such components is similar that of function-based ones.

See the documentation for the Component class for details.

Base classes for input components

InputComponent — a base class for all input components in Chords libraries

The library introduces its own notion of an input component that is represented by the InputComponent class. Having such a common basis for input components standardizes the API that is expected from all input components, and allows reusing it via class inheritance without having to repeat it for each implementation.

Such a standardized API is in particular useful for a polymorphic (uniform) usage of different input components in components like input forms, which have to be configured with arbitrary sets of input components.

See the InputComponent class, which includes such things as the property for edited value, validation support, etc.

InputField — a base class for text-based input components

This is a subclass of InputComponent, which simplifies creating input components for entering arbitrary value types in text form. It includes support for such aspects of entry as customizable parsing and formatting of respective value types, input text validation, etc.

See the InputField documentation for details.

DropdownSelector — for dropdown item selectors

DropdownSelector is a base class for creating another type of input components, where item selection should be performed using a drop-down list.

Facilities for addressing common app development needs

In addition to components, the library includes such facilities:

  • A simple API to declare and detect key combinations, like this:

    if (keyEvent matches 'x'.key.typed) { /*...*/ }

    or

    Modifier.on(Ctrl(Enter.key).up) { /*...*/ }

    See the Keystroke class.

  • Extension functions to address common tasks or current shortcomings in Compose, like ensuring the usual focus traversal with the Tab key for text fields (see Modifier.moveFocusOnTab()).

  • Some simple components that address common needs like CheckboxWithText, RadioButtonWithText, or WithTooltip.

  • A blocking progress overlay for content that is busy with an asynchronous process (ProgressOverlay). It wraps arbitrary content, and, while it is active, covers that content with a semitransparent layer that displays a progress indicator and prevents the covered content from being operated with a pointing device:

    ProgressOverlay(saving) {
        // The content that cannot be operated while it is being saved.
    }

    The overlay doesn't change the way that the covered content is measured. While it is inactive, no overlay or interaction-intercepting layer is composed, and the wrapped content is composed and behaves exactly as it does without the wrapper. Its background and indicator can be customized with the respective parameters.

  • More complex components like Wizard.

  • Automatic submission progress in Dialog and Wizard. Both apply ProgressOverlay to their content whenever their submitting property is true, which requires no changes at their usage sites. Such content additionally stops receiving key events, so it cannot be edited, navigated, or submitted again while the submission is in progress, while the dialog's Cancel button and the wizard's "Cancel" button keep working.