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.