Skip to content

40. amade-commons at a Glance

The application chapters told the library's story in the order the programs needed it: start-up and languages with Pad, settings with Files, the keyring with Mail, the command runner with Imagescan. That is the right order to learn it in, and the wrong order to look something up in. Part IV is the manual: the same library, sorted by what it is for.

Each chapter of this part covers one area. Each section in it describes one part: what it is for, when to choose it and when something else fits better, how it works inside, and its methods. A line at the top of each section names the package, the chapter that introduced the part, and the source files on GitHub, so you can go from the manual to the story and to the code. The tests of amade-commons are its best examples; most sections show one.

Chapter Packages For
41. Start-up and Wiring app, swing Starting a program, its identity, what Guice binds for every program, the two threads
42. Look and Themes theme, swing The desktop's colour themes, custom themes, following Settings, the CDE look, the text size, colours of your own, the date dialog
43. Languages i18n The five languages, which one a program speaks, texts and their formats, menu letters, the language setting, the translation test
44. Settings and Files config Where files go, settings files that survive a crash, following a file the desktop writes
45. Desktop Integration desktop Opening links and files in other programs, the busy cursor, passwords in the keyring
46. Toolbars, Icons and Printing swing, print Icons drawn in code, toolbar buttons, a player's transport buttons, paper sizes, printing and PostScript
47. Programs, JSON and the Network process, json Running other programs, testing without them, reading and writing JSON, how the programs talk to web services

What amade-commons is, and is not

amade-commons is a library, not a framework. It calls your program exactly once, in AmadeApplication.launch, and from then on only when you hand it something to call: a styler, a listener, an action. There is no base class for windows and no application object to extend.

It holds only what at least two programs share. Everything in it came from a program that needed it first and moved in when a second program needed the same thing: PasswordStore from Mail, printing from Calendar and WritePad, Json from Mail and Audio. Pad's text decoding, Files' trash, Video's libmpv binding and Audio's sound engine stay in their programs, because no second program needs them yet. The rule is in chapter 10, and every chapter since ends with a table of what the program takes from the library and what stays.

The desktop's own tools (the Front Panel, Settings, Software) use amade-commons too. Part VI shows how to write one.

Ideas that run through the library

A few rules hold for nearly every class. Knowing them makes the rest of the manual shorter.

The desktop writes, the programs follow. The theme (theme.conf), the desktop language (locale.conf) and the icon theme are written by Settings into ~/.config/amadeos, and so is the text size. Programs only read these files, and a ConfigWatcher tells them when the files change. A program's own settings live in a directory of its own below (chapter 44).

Two threads. Swing components are touched only on the event dispatch thread (EDT); slow work runs on the virtual-thread executor that CommonsModule binds, and its result comes back through the @Ui executor. Listeners that amade-commons calls from a background thread say so in their javadoc, and AmadeUI.follow is the example of switching to the EDT (chapter 41).

Colours come from the theme, at the moment they are needed. No program stores a theme colour in a component, because the colour would stay after the user picks another theme. Standard components take their colours from Swing's table, which AmadeUI fills; anything else uses AmadeUI.style or asks AmadeUI.theme() while painting (chapter 42).

Texts are data. Every text a user reads comes from a .properties file in five languages, menu letters included. Formatting follows the language, apostrophes are plain, and a missing text shows as !key! instead of crashing. A test per program checks that every translation is complete (chapter 43).

Never write over the only copy. Every file amade-commons writes is written to a temporary file in the same directory and then renamed over the old one, so a crash leaves the old file or the new one, never half of one. Settings files are readable by their owner only (chapter 44).

Nothing waits forever. Programs started through CommandRunner and secret-tool have time limits that hold even when the program hangs without printing anything. Watching threads are daemon threads, so they never keep a closed program alive (chapter 47).

Tests need no desktop. Every class that reads the environment takes it as a parameter: XdgDirectories takes a map and a home directory, LocaleResolution the environment, ThemeStore a directory, CommandRunner is an interface a test answers with a lambda. The tests of the library and of the programs run anywhere, with xvfb-run for the few that draw.

Degrade quietly. Without xdg-open, DesktopLauncher uses AWT's Desktop. Without a keyring, passwords live for the session. Without X11, the busy cursor is skipped. Without a printer, PostScript can still be written. A program never fails to start because something around it is missing.

I need … : use …

I need Use Section
To start a program with the language, look and Guice set up AmadeApplication.launch, AppInfo 41
The background executor, the EDT executor, directories, the locale CommonsModule 41
To continue on the EDT after background work @Ui Executor, EdtExecutor 41
The colours of the current theme AmadeUI.theme(), DesktopTheme 42
A theme of my own on the desktop theme.properties in ~/.config/amadeos/themes/<id>/ 42
To follow the theme the user picks in Settings AmadeUI.follow (done by launch) 42
A component with colours beyond the standard ones AmadeUI.style 42
A sunken or raised bevel, a coloured dot AmadeUI.sunken(), raised(), colorDot 42
A dialog to pick a date DateChooser 42
Texts in five languages, formatted Messages, Texts.tr 43
Texts in a dialog or table model that gets nothing injected Texts.tr 43
Menu letters that each language chooses Mnemonics.apply 43
Which language the program speaks, and why LocaleResolution, LocaleSettings 43
A language field in my settings dialog LanguageChooser 43
A test that every translation is complete TranslationCheck 43
Where to put settings, caches and data AppDirectories, XdgDirectories 44
The user's pictures folder, in their language XdgDirectories.pictures() 44
To read and write a settings file safely PropertiesFile 44
To react when a file in a directory changes ConfigWatcher 44
To open a link in the browser or a file in its program DesktopLauncher 45
To know whether opening a file could run code DesktopLauncher.isRisky 45
To copy a picture to the clipboard ImageSelection 45
The busy cursor while another program starts LaunchFeedback.announce 45
A password kept in the desktop keyring PasswordStore 45
The user's contacts: names, addresses, birthdays ContactDirectory 45
Address completion in a To or Cc field AddressCompletion 45
A toolbar icon that follows the theme and scales ToolIcon, StandardGlyph 46
Toolbar buttons in the Motif style ToolButtons 46
Play, Pause, Stop and the rest TransportButtons, TransportGlyph 46
The usual paper where the user lives PaperSize.forLocale 46
To print pages with the system's dialog, or to a PostScript file PrintJobs 46
To run another program with a time limit CommandRunner.run, output 47
A clear message when a program is not installed ProgramMissingException 47
Tests that do not depend on installed programs FinishedProcess 47
To read a web service's answer or write a small JSON file Json 47
To call a web service java.net.http.HttpClient, as the programs do 47

Which chapter introduced what

Package Parts Introduced in
app AmadeApplication, AppInfo, CommonsModule 10. Pad
app @Ui 30. Fractals
theme DesktopTheme, ThemeRegistry, ThemeStore 10. Pad
swing AmadeUI, EdtExecutor 10. Pad
swing DateChooser 21. Calendar
swing ToolIcon, StandardGlyph, ToolButtons 30. Fractals
swing TransportGlyph, TransportButtons 33. Audio
i18n Language, LocaleResolution, LocaleSettings, LocaleStore, Messages, Mnemonics, TranslationCheck 10. Pad
i18n LanguageChooser 21. Calendar
i18n Texts 22. Mail
config XdgDirectories, ConfigWatcher 10. Pad
config AppDirectories, PropertiesFile 20. Files
config XdgDirectories.pictures() 34. Screenshot
desktop DesktopLauncher 11. Web
desktop LaunchFeedback 20. Files
desktop PasswordStore, SecretToolPasswordStore, SessionPasswordStore 22. Mail
desktop ImageSelection 34. Screenshot
contacts ContactDirectory, ContactCard, Recipient, AddressCompletion 25. Contacts
print PaperSize, PrintJobs 23. WritePad
process CommandRunner, ProgramResult, ProgramMissingException, FinishedProcess 31. Imagescan
json Json 33. Audio

Using it in a program

A program gets amade-commons from JitPack, pinned to a commit, and builds a checkout next to it instead when there is one, as chapter 0 shows. Pinning a commit instead of a version means a program never changes because the library did: it moves on when its author re-pins it, which is what the "re-pinning" sections of the application chapters do. When you change amade-commons and a program together, pin the program to the library commit that has the change, and merge the program's change no later than the library's.