# ILayoutManager
> Pages authored in the Lectern UI editor: loading them, opening them, and running what their elements are bound to.
`gg.lode.lecternapi.api.manager.ILayoutManager`
---
## Signature
```java
public interface ILayoutManager
```
---
## Notes
This is the layer above `IHUDManager.playLayout`. That call plays a layout and stops, the
server owns every decision about when it appears and what it does. A page instead carries its own
rules, so dropping an exported file into `plugins/Lectern/layouts/` is enough to get a
command, an opening on join, and buttons that work, with no plugin written for it.
Pages are loaded from disk on startup and can be reloaded without a restart. A page opened for a
player is tracked, which is what lets a click be matched back to the page that was showing rather
than to whatever the client claims.
```java
ILayoutManager layouts = api.getLayoutManager();
layouts.open(player, "stats", Map.of("kills", "12"));
```
---
## Methods
### getPages
```java
Collection<LayoutPage> getPages()
```
Every page currently loaded, keyed by id.
---
### getPage
```java
LayoutPage getPage(String id)
```
The page with this id, or null if none is loaded.
| Parameter | Type |
|---|---|
| `id` | `String` |
---
### register
```java
void register(LayoutPage page)
```
Registers a page at runtime, replacing any already loaded under the same id.
For a plugin that ships its own pages rather than expecting a server owner to install files.
A page added this way is dropped on the next `reload()`, which only rereads the folder.
| Parameter | Type |
|---|---|
| `page` | `LayoutPage` |
---
### reload
```java
int reload()
```
Rereads `plugins/Lectern/layouts`, replacing what is loaded.
Commands are re-registered to match, and a page a player has open is left alone: reloading
mid-session changes what opens next, not what is already on screen.
**Returns:** how many pages were loaded
---
### open
```java
void open(Player player, String id)
void open(Player player, String id, Map<String, String> variables)
void open(Player player, LayoutPage page, Map<String, String> variables)
```
Opens a page for a player, applying its behaviour.
Opens a page for a player, filling `%tokens%` in its text from `variables`.
Opens an already-resolved page, which need not be one loaded from disk.
---
### close
```java
void close(Player player, String id)
```
Closes a page for a player. Does nothing if they do not have it open.
| Parameter | Type |
|---|---|
| `player` | `Player` |
| `id` | `String` |
---
### closeAll
```java
void closeAll(Player player)
```
Closes every page the player has open.
| Parameter | Type |
|---|---|
| `player` | `Player` |
---
### getOpenPages
```java
Collection<String> getOpenPages(Player player)
```
The ids of the pages this player currently has open.
| Parameter | Type |
|---|---|
| `player` | `Player` |
---
### isOpen
```java
boolean isOpen(Player player, String id)
```
Whether this player has this page open.
| Parameter | Type |
|---|---|
| `player` | `Player` |
| `id` | `String` |
---
### openPublished
```java
void openPublished(Player player, String publishedId, String scene)
void openPublished(Player player, String publishedId, String scene, LayoutTransition transition)
```
Plays a layout published on lode.gg, fetched by its shared id.
Unlike `open`, which draws on the pages in the server's own layouts folder, this
plays a document its author published from the editor, so a change made on the site reaches
the server without a file drop or a restart.
The document is cached after the first fetch and reused. The fetch itself runs off the main
thread and the playback hops back onto it, so a slow answer from lode.gg costs a frame of
lateness rather than a stalled tick. Call `clearPublishedCache()` to pick up an edit.
As above, deciding how the switch looks rather than leaving it to the document.
Worth using when the server knows something the author could not: a scene cut short by a
round ending wants to leave from wherever it got to, while a deliberate change of state may
want the cut. Pass `LayoutTransition.inherit()` to keep the scene's own setting, which
is what the three-argument form does.
---
### closePublished
```java
void closePublished(Player player, String publishedId)
```
Takes a published layout off screen, by the same id it was opened with.
| Parameter | Type |
|---|---|
| `player` | `Player` |
| `publishedId` | `String` |
---
### clearPublishedCache
```java
int clearPublishedCache()
```
Forgets every cached published document, so the next play fetches it again.
**Returns:** how many were being held
---
### fire
```java
int fire(Player player, String pageId, String elementRef, LayoutAction.Trigger trigger)
```
| Parameter | Type |
|---|---|
| `player` | `Player` |
| `pageId` | `String` |
| `elementRef` | `String` |
| `trigger` | `LayoutAction.Trigger` |
---
## Example
Open a page you exported from the UI editor, filling in its `%tokens%`:
```java
ILayoutManager layouts = LecternAPI.getApi().getLayoutManager();
layouts.open(player, "stats", Map.of(
"kills", String.valueOf(stats.kills()),
"rank", stats.rank()));
```
The page came from `plugins/Lectern/layouts/stats.json`, so nothing here had to describe what it
looks like. If you edit the file, `layouts.reload()` picks it up without a restart and returns how
many pages it read.
Closing is by id, and a player can have several pages open at once:
```java
if (layouts.isOpen(player, "stats")) {
layouts.close(player, "stats");
}
```
To run an element's bindings yourself, without the player clicking anything:
```java
layouts.fire(player, "stats", "close_button", LayoutAction.Trigger.CLICK);
```
---
## Related Pages
- [[LayoutPage]]. The page, its behaviour and its transitions
- [[LayoutOpenEvent]]. Gate a page before it opens
- [[LayoutInteractEvent]]. Gate what its elements do
- [[IHUDManager]]. Playing a layout straight from the server instead