# Observable - Disjoint UI updates for complex objects This library exists to combine together two objectives in updating UI objects: 1) Be able to 'remotely' notify UI objects about updates without having to iterate through the entire component tree. 2) Allow editting of a shared resource from multiple potential call sites without needing a controller object that holds references to every single interested view. This is a useful construct in the situation where you have a large number of fixed GUI components in a program (for example, rendering the various statistics of a Dungeons and Dragons (c) character), because the connections are made anonymously. ## Requirements - Java 7 - org.leumasjaffe.event - Google Guava ## Installation ### Steps 1. Download or clone this repository. 2. Open a console window in the directory. 3. Run `mvn install` 4. Add the below maven artifact to your pom.xml ### Maven Artifact ``` xml org.leumasjaffe observable ``` ## Example Code Snippets ### ObservableListener In the following hypothetical, imagine a spellbook that allows you to only cast N spells each day. We have a GUI setup that shows up the spells we can cast and the number of spells left, but the interface does not have the ability to edit things. An example would be a text-based interaction system like Zork, but with an active display for user ease. The player then types `cast Fireball` into the prompt, and automatically the spellbook window to the left decrements the spells remaining interface. ``` java class SpellBook extends Observable { int spellSlotsRemaining, maxSpellSlots; List> spellsAtLevel; } class SpellBookUI extends JPanel { ObservableListener listener; SpellBookUI(SpellBook model) { JTextField spellsRemaining = new JTextField(); add(spellsRemaining); // Set up a listener to anonymously update when model changes listener = new ObservableListener<>(spellsRemaining, (text, book) -> { text.setText(book.getSpellSlotsRemaining()); }); // Automatically invokes callback, setting the text field listener.setObserved(model); } } class CastSpellCommand { SpellBook book; void cast(Spell spell) { // ... --book.spellSlotsRemaining; // Will automatically invoke the code in the ObservableListener above ObserverDispatch.notifySubscribers(book); } } ```