Windows
Overview
The Layouts API is accessible via the io.layouts
object.
Configuration
It's possible to configure the Layouts API by using the layouts
property of the optional Config
object passed during the initialization of the io.Connect JavaScript library. The Layouts API supports several modes of initialization. It can also be configured whether to auto save the context of individual windows and for which Layout types (Global, App Default, Workspace) to save it.
Below is an example of configuring the Layouts API:
const config = {
layouts: {
mode: "full",
// Individual window context will be saved only when saving the specified types of Layouts.
autoSaveWindowContext: ["Global", "Workspace"]
}
};
const io = await IODesktop(config);
The different modes of the Layouts API restrict or enable certain functionalities. In "slim"
mode, Layouts can't be manipulated (created, removed, renamed) and Layout events aren't available, but custom context data can still be saved. In "full"
mode, all functionalities are available.
The layouts
object has the following properties:
Property | Type | Description |
---|---|---|
mode |
"full" | "slim" | "fullWaitSnapshot" |
In "full" mode, all Layout functionalities are available. In "slim" mode, Layout events aren't tracked and Layouts can't be manipulated. The "fullWaitSnapshot" mode is the same as the "full" mode, except that the Layouts API will notify that it's ready a little later - when a snapshot of the available Layouts has been received. |
autoSaveWindowContext |
boolean | LayoutType[] |
If true , window context will be saved for all Layout types. If an array of Layout types is passed instead, window context will be saved only for the specified Layout types. Possible Layout types are "Global" , "ApplicationDefault" and "Workspace" . |
Layout Operations
Current Global Layout
To get the currently restored Global Layout, use the getCurrentLayout()
method:
const currentLayout = await io.layouts.getCurrentLayout();
Listing All Layouts
To get a collection of all currently available Layout
objects, use the list()
method:
const layouts = io.layouts.list();
⚠️ Note that the
list()
method isn't available in"slim"
mode. Useexport()
instead.
All Layouts by Type
To get all Layouts by type, use the getAll()
method and specify the Layout type. It resolves with a collection of LayoutSummary
objects, which don't contain the extensive objects describing the actual Layout
components:
const allGlobalLayouts = await io.layouts.getAll("Global");
Specific Layout
To get a specific Layout, use the get()
method and provide the name of the Layout and the Layout type as arguments. It resolves with the requested Layout
object or undefined
if a Layout with the specified name and type doesn't exist:
const name = "My Layout";
const type = "Global";
const myLayout = await io.layouts.get(name, type);
Save & Restore
To save a Layout, use the save()
method and pass a NewLayoutOptions
object with a required name
property. If a Layout with that name already exists, it will be replaced. The method resolves with the saved Layout
object:
const options = {
name: "My Layout"
};
const savedLayout = await io.layouts.save(options);
To restore a Layout, use the restore()
method and pass a RestoreOptions
object specifying the name of the Layout (required) and other restore options:
const restoreOptions = {
name: "My Layout",
// Specify whether to close all running apps before restoring the Layout.
// The default is `true` for Global Layouts.
closeRunningInstance: false
};
const result = await io.layouts.restore(restoreOptions);
⚠️ Note that saving, and especially restoring, a Global Layout may be a taxing operation depending mainly on how many apps there are in the Layout, how heavy they are, and how much context is attached to the Layout. If you need a quicker way to switch between Global Layouts, see the Hibernate & Resume section.
Available since io.Connect Desktop 9.1
When saving a Layout, you can specify whether to set it as the currently active Global Layout by using the setAsCurrent
property of the NewLayoutOptions
object:
const options = {
name: "My Layout",
setAsCurrent: true
};
const myLayout = await io.layouts.save(options);
Restored Layouts Info
Available since io.Connect Desktop 9.4
To retrieve information about the currently active Global Layout (ID, type, name, participating app instances), as well as about any previously active Global Layouts that may still have running instances of their participating apps, use the getRestoredLayoutsInfo()
method.
By default, when a Global Layout is restored, any remaining app instances of the previously active Global Layout are closed and the getRestoredLayoutsInfo()
method will return information only about the currently active Global Layout. However, if the closeRunningInstance
property of the RestoreOptions
object is set to false
when restoring a Global Layout, all running app instances of the previously active Global Layout will remain intact and in this case the getRestoredLayoutsInfo()
method will return information about that Global Layout as well.
⚠️ Note that the
getRestoredLayoutsInfo()
method won't return any information about a currently or previously active Global Layout if any of its components is a Workspace, as Workspace Layouts aren't supported for this operation. Also keep in mind that the information about the restored Global Layouts is updated dynamically, so if all app instances participating in a Global Layout are closed, thegetRestoredLayoutsInfo()
method won't return any information about it.
The getRestoredLayoutsInfo()
method resolves with a GetRestoredLayoutsInfoResult
object with a layoutInfo
property holding a list of RestoredLayoutDetails
objects. Each RestoredLayoutDetails
object describes the currently active or any previously active Global Layouts that may still have running instances of their participating apps.
This method may be useful if you want to get the IDs of all Global Layouts that the user has restored (and that still have running instances of their participating apps) in order to use them in operations like resetting a Global Layout.
The following example demonstrates retrieving information about all restored Global Layouts and finding the currently active one in order to use its ID:
// Retrieve information about all restored Global Layouts.
const allRestoredLayoutsInfo = (await io.layouts.getRestoredLayoutsInfo()).layoutInfo;
// Get the current Global Layout in order to compare the Layout names.
const currentLayout = await io.layouts.getCurrentLayout();
// Find the details about the current Global Layout.
const myLayoutInfo = allRestoredLayoutsInfo.find(layoutInfo => layoutInfo.name === currentLayout.name);
// Use the Layout ID.
console.log(myLayoutInfo.id);
Hibernate & Resume
Hibernating and resuming provides a quicker way to save and restore Global Layouts. The hibernation operation saves the Layout (therefore the original Global Layout will be overwritten) and enables you to resume (restore) the Layout more quickly by preserving the participating app instances and hiding them from the user. If you have heavy apps in a Layout and they take a lot of time to load, you may choose to hibernate the Layout when the user switches to another Layout. Resuming the Layout later will save the time usually needed for loading the heavy apps, but at the expense of higher memory consumption on the user machine. You should carefully consider the advantages and disadvantages of using hibernation when deciding on a strategy for saving and restoring Global Layouts.
⚠️ Note that in order for the hibernation operation to be most beneficial, you should prevent your app instances from closing when being hibernated. You can specify settings for closing or preserving hibernated app instances globally and per app which provides you with flexibility when designing your hibernation strategy. For more details, see the Developers > Configuration > System > App Settings > Hibernation and Developers > Configuration > Application > Hibernation sections.
To hibernate a Layout, use the hibernate()
method and provide the name of the Layout to hibernate as a required first argument. As a second optional argument, you can pass a HibernationOptions
object:
const name = "My Layout";
const options = {
context: { io: 42 },
metadata: { layout: "MyHibernatedLayout"}
};
const result = await io.layouts.hibernate(name, options);
console.log(`Layout hibernated ${result.status === "Success" ? "successfully" : "unsuccessfully"}.`);
To resume a hibernated Layout, use the resume()
method and provide the name of the Layout to resume as a required first argument. As optional second and third arguments you can provide context for the resumed Layout and a ResumeOptions
object:
const name = "My Layout";
const context = { io: 42 };
const options = {
// Will close any already running app instances before resuming the Layout.
cleanUp: true
};
const result = await io.layouts.resume(name, context, options);
console.log(`Layout resumed ${result.status === "Success" ? "successfully" : "unsuccessfully"}.`);
Rename
To rename a Layout, use the rename()
method. You must pass the Layout
object to rename as a first argument and the new name for the Layout as a second argument:
await io.layouts.rename(myLayout, "My New Layout");
Remove
To remove a Layout, use the remove()
method. You must pass the Layout type and the name of the Layout as arguments:
await io.layouts.remove("Global", "My Layout");
Export & Import
You can export all currently available Layout
objects with the export()
method. Exported Layouts can be stored to a database and then be used as restore points, or can be sent to another user and imported on their machine:
const layouts = await io.layouts.export();
The export()
method (as opposed to list()
) is available in all modes if you need to get a collection of all Layouts.
To import exported Layouts, use the import()
method. Pass the collection of Layout
objects to import and specify an ImportMode
:
const mode = "merge";
await io.layouts.import(layouts, mode);
The ImportMode
controls the import behavior. If set to "replace"
(default), all existing Layouts will be removed and will be replaced by the imported ones. If set to "merge"
, the imported Layouts will be added to the existing ones, replacing any Layouts with conflicting names.
Update Metadata
To persist any changes made to the metadata of a Layout
object, use the updateMetadata()
method and provide the Layout as an argument:
// Changing the metadata of a Layout.
myLayout.metadata = { io: 42 };
// Updating the metadata of a Layout so that it will be persisted.
await io.layouts.updateMetadata(myLayout);
Reset
Available since io.Connect Desktop 9.4
Resetting a Layout programmatically enables you to quickly revert a Global Layout to its default state, without the user having to manually start missing app instances or move and resize windows. Already running instances that are part of the Layout will be reused. You can specify whether the missing app instances should be recreated and whether apps that may have been hidden programmatically should be reset. It's also possible to specify whether to revert the participating app instances to their default state in regard to their window context and selected Channel.
⚠️ Note that Workspaces Apps aren't included in the reset Layout operation.
To reset a Layout, use the reset()
method and pass a ResetLayoutOptions
object as a required argument. The only required property in the ResetLayoutOptions
object is layoutId
where you must provide the ID of the Layout to reset:
// Retrieve details about the currently restored Layout that you want to reset.
const myLayout = (await io.layouts.getRestoredLayoutsInfo()).layoutInfo.find(l => l.name === "My Layout");
const options = {
// Provide the ID of the Layout to reset.
layoutId: myLayout.id,
// Will exclude hidden apps from the reset operation.
visibleOnly: true,
// Will create missing app instances.
createMissing: true,
// Will preserve the current state of the app instances (window context and selected Channel).
resetState: false
};
const result = await io.layouts.reset(options);
To retrieve the ID of the Layout in which your are interested, you can use the getRestoredLayoutsInfo()
method, or the RestoreResumeResult
object returned both by the restore()
method for restoring a saved Layout and by the resume()
method for resuming a hibernated Layout.
Refresh
To force a refresh of the Layout list available to the user when using a REST service or io.Manager as a Layout store, use the forceRefresh()
method:
await io.layouts.forceRefresh();
Events
The Layouts API provides methods for reacting to various Layout events. Use the returned unsubscribe function to stop receiving notifications about the respective event.
Added
To get notified when a Layout is added, use the onAdded()
method:
io.layouts.onAdded(console.log);
Removed
To get notified when a Layout is removed, use the onRemoved()
method:
io.layouts.onRemoved(console.log);
Changed
To get notified when a Layout is changed, use the onChanged()
method:
io.layouts.onChanged(console.log);
Renamed
To get notified when a Layout is renamed, use the onRenamed()
method:
io.layouts.onRenamed(console.log);
Save & Update Context
When a Layout is saved, apps can store context data in it. When the Layout is restored, the context data is also restored and returned to the apps. Context data can be saved in all Layout types.
⚠️ Note that saving large volumes of custom data as window context (e.g., thousands of lines of table data) can lead to significant delays when saving a Layout. A Layout usually contains several (in some cases - many) apps and/or Workspaces (which can also contain many apps) and if one or more of the apps saves large amounts of context data each time a Layout is saved, this will significantly slow down the saving process. The methods for saving custom context work best with smaller amounts of data. If your app needs to save large amounts of data, you have to think about how to design this process better - for instance, you may store IDs, indices, etc., as context data, save the actual data to a database and when you restore the Layout, fetch the data using the data IDs saved as window context.
Saving Context Data
To save context data, apps can subscribe for Layout save requests using the onSaveRequested()
method. A Layout save request event is fired when the user attempts to save a Layout or close a window, Workspace, etc. The on onSaveRequested()
method accepts a callback which will be invoked when a Layout save request is triggered. The callback will receive as an argument a SaveRequestContext
object containing the Layout name, type and context. Use it to determine the type of the Layout and instruct your app to react accordingly:
const saveRequestHandler = (requestInfo) => {
// Get the Layout type.
const layoutType = requestInfo.layoutType;
// Return different context data depending on the Layout type.
if (layoutType === "ApplicationDefault") {
return { windowContext: { gridWidth: 42 } };
} else if (layoutType === "Global") {
return { windowContext: { gridWidth: 420 } };
} else {
// Return if not interested in other Layout types.
return;
};
};
io.layouts.onSaveRequested(saveRequestHandler);
The callback must return a SaveRequestResponse
object that has a windowContext
property.
After the Layout has been restored, the saved context data will be available in the window context:
// Extracting previously saved data from the window context.
const windowContext = await io.windows.my().getContext();
const gridWidth = windowContext.gridWidth;
Updating App Default Context
To manually update the context of the current window in its App Default Layout, use the updateDefaultContext()
method:
const context = { io: 42 };
await io.layouts.updateDefaultContext(context);
Updating Context of Apps in Global Layouts
To update the context that will be saved for the current app in the currently loaded Global Layout, use the updateAppContextInCurrent()
method. This method allows you to update the saved context for the current app in the Layout without having to save the entire Layout:
const context = { io: 42 };
await io.layouts.updateAppContextInCurrent(context);
Default Global Layout
io.Connect Desktop allows you to specify a default Global Layout that will be automatically loaded on start. You can get, set and clear the default Global Layout programmatically.
To get the current default Global Layout, use the getDefaultGlobal()
method:
// May return `undefined` if no default Global Layout has been set.
const defaultLayout = await io.layouts.getDefaultGlobal();
To set a default Global Layout, use the setDefaultGlobal()
method:
io.layouts.setDefaultGlobal("My Layout");
To clear the default Global Layout, use the clearDefaultGlobal()
method:
io.layouts.clearDefaultGlobal();
Reference
For a complete list of the available Layouts API methods and properties, see the Layouts API Reference Documentation.