Skip to content
This repository has been archived by the owner on Nov 28, 2023. It is now read-only.

A pull request to give the option of merging a few of the changes I've applied #8

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c5b68f4
Added button to arrange as Columns
johnman Mar 4, 2020
c9acc63
Added a basic example of trying to add a chart to a column
johnman Mar 4, 2020
6399347
Improvements to formatting and bug fix
johnman Mar 4, 2020
bf269d9
Update frame-styles.css
johnman Mar 12, 2020
6e9f49a
added native window extension as an example
rdepena Mar 11, 2020
f819624
added remote urls for the public.json
rdepena Mar 11, 2020
813f0fa
changed readme to reflect changes to provider customization
rdepena Mar 12, 2020
740de66
better english
rdepena Mar 12, 2020
90b0d90
better better english
rdepena Mar 12, 2020
010262e
Update README.md
rdepena Mar 12, 2020
7814e29
Added an app that has a main window
johnman Mar 24, 2020
4c21135
Updated readme.md
johnman Mar 24, 2020
df94b31
2nd sample - restore snapshot button didn't work
johnman Mar 24, 2020
68ab32c
Updated logic to demostrate context
johnman Mar 29, 2020
a782a9f
resatoring config file to working order.
johnman Mar 29, 2020
6293513
Updated the readme to include links
johnman Mar 29, 2020
3cc1a6f
Updated the readme
johnman Mar 29, 2020
aa28876
toggle fixed button
tgoc99 Apr 7, 2020
b4bad75
fixed becomes locked
tgoc99 Apr 8, 2020
664ef8b
Merge remote-tracking branch 'upstream/master'
johnman Apr 21, 2020
f5d3be1
Merge remote-tracking branch 'upstream/dev/tgoc99/fixed-layout'
johnman Apr 21, 2020
5bb79a4
Refactored the code a bit. Added clone, pin & lock
johnman Apr 23, 2020
334dee8
Updated readme
johnman Apr 24, 2020
ebd1422
MainWin now saves on close all from taskbar
johnman Apr 29, 2020
643e538
Updated to show marking a tab no close no drag
johnman May 5, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 79 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,21 @@ This project seed includes the following [Platform API](https://openfin.co/platf
* Examples of visual customization via CSS
* Examples of visual customization by providing a custom Platform Window
* Examples of behavioral customization by overriding the Platform APIs
* Examples of how to make use of the platform apis to treat views inside of a window as a group with shared context and how messages could be shared to views in a group and how you can maintain that relationship when you pull out a view from a window (so there is a linked relationship).
* How your view can make use of knowledge of it being moved from window to window and how it can keep track of the number of views that exist so it can react to that.
* How you can lock all the views on a window (to prevent views from being pulled out or views dragged in and to also hide the tabs if they are not needed).
* How you can pin platform windows so they are always on top.


[![Click to watch on Vimeo](openfin-seed-project-first-demo-preview.png)](https://vimeo.com/401935037)
[Launch in OpenFin](https://openfin.github.io/start/?manifest=https%3A%2F%2Fopenfin.github.io%2Fplatform-api-project-seed%2Fpublic.json)

## How to use this repository:

* Clone this repository
* Install the dependencies: `npm install`
* Start the live-server and launch the application: `npm start`
* To launch the default application: Start the live-server and launch the application: `npm start`
* To launch the main window application: Start the live-server and launch the application: `npm run mainwindow`

## Understanding the code

Expand All @@ -30,25 +37,93 @@ This project seed includes the following [Platform API](https://openfin.co/platf
* A [stylesheet](https://developers.openfin.co/docs/platform-api#section-standard-window-customization) is linked in the [platform-window.html](platform-window.html) file, and allows for [visual customization](styles/frame-styles.css). For a complete view of all properties, please refer to the [example stylesheet](https://github.com/openfin/layouts-v2-style-examples)

### Platform Window
The [platform-window.html](platform-window.html) file contains the [layout-container](https://developers.openfin.co/docs/platform-api#section-5-2-complete-window-customization) element and two custom elements: `left-menu` and `title-bar`. These elements, in conjunction with the [js/left-menu.js](js/left-menu.js) and [js/title-bar.js](js/title-bar.js) files, enable the following functionality:
The [platform-window.html](platform-window.html) file contains the [layout-container](https://developers.openfin.co/docs/platform-api#section-5-2-complete-window-customization) element and two custom elements: `left-menu` and `title-bar`. These elements, in conjunction with the [js/platform-window.js](js/platform-window.js) file, enable the following functionality:

##### left-menu
Provides examples of the following functionality:
* Adding a View to an existing Window
* Adding a View that makes use of shared context if there is more than one view of that type
* Adding a View in a new Window
* Saving the Window's current Layout
* Restoring the Window's current Layout
* Creating a regular OpenFin Window
* Saving/Restoring Platform Snapshots
* Applying a preset arrangement on the current window (Grid, Tabs, Rows)
* Applying a preset arrangement on the current window (Grid, Tabs, Rows, Columns)
* Added a view New View Tab Example that showed a way of preventing specific tabs from being moved or closed (this is just to give an idea of an approach if needed)

##### title-bar
Provides examples of the following functionality:
* Draggable area
* Save/Restore a layout
* Lock/Unlock the current layout
* Pin/Unpin window so it is always on top
* Close/Maximize/Minimize buttons

### Provider
Our [custom Provider](js/platform-provider.js) includes an [extension](js/external-window-snapshot.js) that will look for a pre-configured list of [externalWindows](https://cdn.openfin.co/docs/javascript/15.80.49.21/ExternalWindow.html) (the default being the provided [my_platform_notes.txt](my_platform_notes.txt) file opened in notepad.exe) and:

* Override `getSnapshot` to include a [externalWindows](https://cdn.openfin.co/docs/javascript/15.80.49.21/ExternalWindow.html) section containing information on any any external window included in the configuration.
* Override `applySnapshot` to look for an [externalWindows](https://cdn.openfin.co/docs/javascript/15.80.49.21/ExternalWindow.html) section and restore the position and state of any external window included in the configuration.

## Understanding the second example- Main Window Example

This is similar to the main example but is configured to act like an application that has a main window and child windows that may or may not use the platform layout.

This example also shows how you can automatically capture layout when the main window closes (to local storage but it could be any store) and have the main window support a layout but not close if the last view is removed.

[![Click to watch on Vimeo](openfin-seed-project-second-demo-preview.png)](https://vimeo.com/401942382)

### Platform configuration
* [Platform configuration](https://developers.openfin.co/docs/platform-api#section-1-launching-a-platform) has been included in the provided [app-window-main.json](app-window-main.json) file. This config does not include a default window as this is managed by the custom provider: [provider-window-main.html](provider-window-main.html)
* The [defaultWindowOptions](https://developers.openfin.co/docs/platform-api#section-standard-window-customization) key in the provided `app-window-main.json` will instruct the platform to replace our Standard Window with the provided [platform-window-common.html](platform-window-common.html) file for new windows.
* The [commands](https://developers.openfin.co/docs/platform-api#section-5-3-using-keyboard-commands) key in the provided `app-window-main.json` will allow keyboard access to the next tab command.
* The [providerUrl]() key in the provided `app-window-main.json` will allow you to make custom changes to the Platform APIs, by pointing to a hosted [provider-window-main.html](provider-window-main.html) file. (STARTING IN v15.80.50.x)

### CSS Customization
* A [stylesheet](https://developers.openfin.co/docs/platform-api#section-standard-window-customization) is linked in the [platform-window-common.html](platform-window-common.html) file, and allows for [visual customization](styles/frame-styles.css). For a complete view of all properties, please refer to the [example stylesheet](https://github.com/openfin/layouts-v2-style-examples)
* A [stylesheet](https://developers.openfin.co/docs/platform-api#section-standard-window-customization) is linked in the [platform-window-main.html](platform-window-main.html) file, and allows for [main window visual customization](styles/frame-styles-window-main.css) with some additional classes that only apply to the main window. For a complete view of all properties, please refer to the [example stylesheet](https://github.com/openfin/layouts-v2-style-examples)

### Platform Window Common
The [platform-window-common.html](platform-window-common.html) file contains the [layout-container](https://developers.openfin.co/docs/platform-api#section-5-2-complete-window-customization) element and one custom element: `title-bar-common`. This element, in conjunction with the [js/title-bar-common.js](js/title-bar-common.js) file, enable the following functionality:

##### title-bar-common
Provides examples of the following functionality:
* Draggable area
* Save/Restore a layout
* Lock/Unlock the current layout
* Pin/Unpin window so it is always on top
* Clone the current window (experimental)
* Close/Maximize/Minimize buttons

### Platform Window Main
The [platform-window-main.html](platform-window-main.html) file contains the [layout-container](https://developers.openfin.co/docs/platform-api#section-5-2-complete-window-customization) element and two custom elements: `left-menu` and `title-bar-main`. These elements, in conjunction with the [js/left-menu.js](js/left-menu.js) and [js/title-bar-main.js](js/title-bar-main.js) files, enable the following functionality:

##### left-menu
Provides examples of the following functionality:
* Adding a View to an existing Window
* Adding a View that makes use of shared context if there is more than one view of that type
* Adding a View in a new Window
* Creating a regular OpenFin Window
* Saving/Restoring Platform Snapshots
* Applying a preset arrangement on the current window (Grid, Tabs, Rows, Columns)
* Added a view New View Tab Example that showed a way of preventing specific tabs from being moved or closed (this is just to give an idea of an approach if needed)

##### title-bar-main
Provides examples of the following functionality:
* Same button functionality as title-bar-common (except clone)
* When you close the window it saves a snapshot of the layout for all windows before closing the whole application.
* If the window is being closed because you have dragged the last view out of the main window into another window it adds a default view and doesn't close the window. If you want to have layout support in the main window then you must have at least one default view that you always want displayed or you have a main window without layout support.
* If only one view remains in the main window then it removes the close icon via the custom class in the [main window visual customization](styles/frame-styles-window-main.css) stylesheet and removes it when more than one view exists.


### Provider
Our [custom Provider](js/platform-provider.js) includes an [extension](js/external-window-snapshot.js) that will look for a pre-configured list of [externalWindows](https://cdn.openfin.co/docs/javascript/15.80.49.21/ExternalWindow.html) (the default being the provided [my_platform_notes.txt](my_platform_notes.txt) file opened in notepad.exe) and:

* Override `getSnapshot` to include a [externalWindows](https://cdn.openfin.co/docs/javascript/15.80.49.21/ExternalWindow.html) section containing information on any any external window included in the configuration.
* Override `applySnapshot` to look for an [externalWindows](https://cdn.openfin.co/docs/javascript/15.80.49.21/ExternalWindow.html) section and restore the position and state of any external window included in the configuration.

We also include an additional script [custom Provider Window Main](js/platform-provider-window-main.js) that:

* Checks for the last saved snapshot
* If retrieved, clears it and uses the local copy to launch the last saved set of windows
* If there is no snapshot it uses a default snapshot

55 changes: 55 additions & 0 deletions app-window-main.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"runtime": {
"arguments": "--v=1 --inspect",
"version": "alpha"
},
"shortcut": {
"company": "OpenFin",
"description": "Platform app seed local with a main window",
"icon": "https://openfin.github.io/golden-prototype/favicon.ico",
"name": "Platform app seed local main window"
},
"platform": {
"uuid": "platform_main_window_customization_local",
"applicationIcon": "https://openfin.github.io/golden-prototype/favicon.ico",
"autoShow": false,
"providerUrl": "http://localhost:5556/provider-window-main.html",
"permissions": {
"ExternalWindow": {
"wrap": true
},
"System": {
"getAllExternalWindows": true,
"launchExternalProcess": true,
"readRegistryValue": false,
"terminateExternalProcess": true
}
},
"defaultWindowOptions": {
"url": "http://localhost:5556/platform-window-common.html",
"contextMenu": true,
"defaultWidth": 600,
"defaultHeight": 600,
"defaultLeft": 0,
"defaultTop": 0,
"saveWindowState": false,
"backgroundThrottling": true
},
"defaultViewOptions": {
"experimental": {
"childWindows": true
}
},
"commands": [
{
"command": "stack.nextTab",
"keys": "Ctrl+Tab"
}
]
},
"snapshot": {
"windows": [

]
}
}
2 changes: 1 addition & 1 deletion app.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"runtime": {
"arguments": "--v=1 --inspect",
"version": "canary"
"version": "alpha"
},
"shortcut": {
"company": "OpenFin",
Expand Down
3 changes: 3 additions & 0 deletions js/component-name-generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function componentNameGenerator() {
return `component_A${Date.now() + Math.floor(Math.random() * 10000)}`;
}
34 changes: 34 additions & 0 deletions js/components/header/clone-layout-component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { html, render } from 'https://unpkg.com/[email protected]/lit-html.js';

class CloneLayoutComponent extends HTMLElement {

constructor() {
super();
this.render = this.render.bind(this);
this.render();
}

async clone() {
let winLayout = fin.Platform.Layout.getCurrentSync();
let config = await winLayout.getConfig();

// work around (this is not the official way this is a workaround until I can investigate why the name of the views is trying to be re-used)
let content = JSON.stringify(config.content);
content = content.replace(/internal-generated-view-/gi, 'internal-generated-view-' + Date.now() + "-");

fin.Platform.getCurrentSync().createWindow({
layout: {
content: JSON.parse(content)
}
});
}

async render() {
const clone = html`
<div class="button" style='height:unset' title='Clone this layout' @click=${() => this.clone().catch(console.error)}>🧬</div>
`;
return render(clone, this);
}
}

customElements.define('clone-layout', CloneLayoutComponent);
41 changes: 41 additions & 0 deletions js/components/header/lock-unlock-component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { html, render } from 'https://unpkg.com/[email protected]/lit-html.js';
import { isLayoutLocked, lockLayout, unlockLayout } from '../../layout-locking.js';

class LockUnlockComponent extends HTMLElement {

constructor() {
super();
this.render = this.render.bind(this);
this.render();
}

async lockLayout() {
await lockLayout();
this.saveLockStatus(true);
this.render();
}

saveLockStatus(isLocked) {
sessionStorage.setItem(fin.me.identity.name + '-locked', isLocked);
}

async unlockLayout() {
await unlockLayout();
this.saveLockStatus(false);
this.render();
}

async render() {
const lockUnlock = html`

${ sessionStorage.getItem(fin.me.identity.name + '-locked') === "true" ? html`
<div class="button" style='height:unset' title='Unlock this layout' @click=${() => this.unlockLayout().catch(console.error)}>🔓</div>`
: html`
<div class="button" style='height:unset' title='Lock this layout' @click=${() => this.lockLayout().catch(console.error)}>🔒</div>
`}
`;
return render(lockUnlock, this);
}
}

customElements.define('lock-unlock', LockUnlockComponent);
41 changes: 41 additions & 0 deletions js/components/header/pin-unpin-component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { html, render } from 'https://unpkg.com/[email protected]/lit-html.js';
import { isPinned, pin, unPin } from '../../pin-unpin.js';

class PinUnPinComponent extends HTMLElement {

constructor() {
super();
this.render = this.render.bind(this);
this.render();
}

async pin() {
await pin();
this.savePinStatus(true);
this.render();
}

savePinStatus(isPinned) {
sessionStorage.setItem(fin.me.identity.name + '-pinned', isPinned);
}

async unpin() {
await unPin();
this.savePinStatus(false);
this.render();
}

async render() {
const pinUnpin = html`

${ sessionStorage.getItem(fin.me.identity.name + '-pinned') === "true" ? html`
<div class="button" style='height:unset' title='Unpin this window so it isn't always on top' @click=${() => this.unpin().catch(console.error)}>📌</div>`
: html`
<div class="button" style='height:unset' title='Pin this window so it is always on top' @click=${() => this.pin().catch(console.error)}>📍</div>
`}
`;
return render(pinUnpin, this);
}
}

customElements.define('pin-unpin', PinUnPinComponent);
69 changes: 69 additions & 0 deletions js/components/header/save-restore-layout-component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { html, render } from 'https://unpkg.com/[email protected]/lit-html.js';
import { isLayoutLocked } from '../../layout-locking.js';
import hostViewContainer from '../../host-view-container.js';

class SaveRestoreLayoutComponent extends HTMLElement {

constructor() {
super();
this.render = this.render.bind(this);
this._viewContainerOptions = {};
this.render();
}

saveLockStatus(isLocked) {
sessionStorage.setItem(fin.me.identity.name + '-locked', isLocked);
}

async saveWindowLayout() {
let winLayout;
let winLayoutConfig;

try {
console.log("About to capture and stored the current window layout.");
winLayout = fin.Platform.Layout.getCurrentSync();
winLayoutConfig = await winLayout.getConfig();
sessionStorage.setItem(fin.me.identity.name, JSON.stringify(winLayoutConfig));
this._viewContainerOptions = hostViewContainer.getAllOptions();
console.log("Captured and stored the current window layout.");
this.render();
} catch (err) {
console.error("Error trying to capture the layout of this window.", err);
}

}

async restoreWindowLayout() {
const storedWinLayout = sessionStorage.getItem(fin.me.identity.name);
if (storedWinLayout) {
let winLayout = JSON.parse(storedWinLayout);
let isWinLayoutLocked = await isLayoutLocked(winLayout);
this.saveLockStatus(isWinLayoutLocked);
await fin.Platform.Layout.getCurrentSync().replace(winLayout);

// if the view tab example view exists on this window we wish to re-apply any changes that were present
if(this._viewContainerOptions !== undefined) {
setTimeout(()=> {
console.log("Trying to restore view container settings");
// because we tie into the tab created event elsewhere we will need to wait a while before applying the captured snapshot
hostViewContainer.updateAllOptions(this._viewContainerOptions);
}, 500);
}
} else {
throw new Error("No snapshot found in sessionstorage");
}
}

async render() {
const saveRestoreLayout = html`

<div class="button" style='height:unset' title='Save this window layout' @click=${async () => this.saveWindowLayout().catch(console.error)}>💾</div>
${ sessionStorage.getItem(fin.me.identity.name) !== null ? html`
<div class="button" style='height:unset' title='Restore this window layout' @click=${async () => this.restoreWindowLayout().catch(console.error)}>📂</div>`
: html``}
`;
return render(saveRestoreLayout, this);
}
}

customElements.define('save-restore-layout', SaveRestoreLayoutComponent);
Loading