Workspaces

A workspace's purpose within Finsemble is to save and restore the end user's window state and position. In other words, a workspace is simply a collection of windows that persist between sessions. Before we dive too deeply into it, it might be beneficial to revisit the definitions of component, workspace, and window.


What types of windows live in the workspace?

The easiest way to understand what is and isn't stored in the workspace is to ask yourself this question: "Does the component need to exist across multiple workspaces?" If the answer is "Yes," then it is not stored in the workspace. Our menus, toolbars, dialogs, and chat windows are not stored in the workspace.

In the diagram below, the red components are application-level components. They're workspace independent. The blue components are part of the workspace and will restore at the proper place when a new session is started. Workspace

Why the distinction between window and component?

We only allow one component per window. Despite the one to one relationship, windows have very different concerns from components. The window shouldn't concern itself with the symbol on the chart, and the chart shouldn't concern itself with where it is placed on the screen. The functional and semantic distinction allows us to speak more clearly when discussing problems. It also speeds up debugging—you don't need to look in the component to figure out an issue with the window's state.


Saving workspaces

All saved workspace information is stored in Finsemble's default storage using the topic finsemble.workspace. This is the basic structure of a workspace:

[{
    "name": "Workspace1",
    "windows": [],
    "groups": {}
},

Name

The key fsblWorkspaces contains a list of workspaces. If a user had two workspaces named "Workspace1" and "Workspace2," fsblWorkspaces would list these workspaces as separate entries.

There is also storage key for each workspace that duplicates the workspace name and data. Note: Because this data is duplicated, it is likely to change in the future.

A window descriptor for each window is stored with the key "Workspace Name" + "Window Name". So the descriptor for "Welcome Component-1" in "Workspace1" would be stored with the key Workspace1Welcome Component-1. Currently, Finsemble stores almost every property on our internal representation of a window to the descriptor.

Windows

In the workspace data, the windows list is just a list of window names.

Groups

When windows are snapped or grouped together, that information is stored in the groups object. The names of groups are randomly generated GUIDs. The only requirement is they be unique.

Every window can be a part of up to two groups. When windows are snapped, they join a group with the isMovable property false. When they are grouped, they are part of a group with the isMovable property true. Grouped windows are also treated as snapped together, so that they can accept new windows snapping to them. Thus, when windows are grouped they are part of both a movable and a non-movable group.

Example: If you have two welcome components in a workspace named "Workspace1," the workspace would look like this:

{
    "name": "Workspace1",
    "windows": ["Welcome Component-1", "Welcome Component-2"],
    "groups": {
        "6533ebe7-8b06-4105-a317-1add95da904c": {
            "windowNames": ["Welcome Component-1", "Welcome Component-2"],
            "isMovable": true
        },
        "7be79940-9213-4094-b363-44f97cd1c7e3": {
            "windowNames": ["Welcome Component-1", "Welcome Component-2"],
            "isMovable": false
        }
    }
}

By default, Finsemble does not automatically overwrite the stored state of a workspace. There is nothing stopping a developer from creating this kind of auto-saving feature; however, to demonstrate how workspace saving works out of the box, imagine the code below was run:

    FSBL.Clients.WorkspaceClient.load({
        name: 'Workspace1'
    });
    //This is what's pulled from storage.
    //Workspace1 = {
    //    name:'Workspace1',
    //    windows:['AdvancedChart1234', 'SimpleChart12333']
    //}

When FSBL.Clients.WorkspaceClient.load is invoked, the application will go off and find Workspace1 in the application's default storage. From there, it will load that data into the activeWorkspace. Any change that the user makes is persisted to activeWorkspace, not Workspace1. Because we aren't automatically overwriting what the user has saved in storage, we need to know when to ask the user if they would like to overwrite their saved workspace.

When a window changes its state or position, it tells the Workspace Service that there's been a change in app or window state, and that the activeWorkspace should be considered "dirty." This only happens once. On subsequent state changes, all windows are aware that the workspace is dirty. Now, any UI that saves or loads workspaces can check if the workspace is "dirty"; if so, the program can ask the user if they'd like to save their changes before switching workspaces.


check   A workspace is a collection of windows whose state and position persist between sessions.
 


Further reading

Now that you have an understanding of what a workspace is, check out the Workspace API Documentation. It's full of helpful examples that will clarify and reinforce the information covered in this tutorial.

Understanding how the Finsemble application handles start-up will provide additional context. That tutorial can be found here.

To learn how components link and share data, proceed on to Linking.