Skip to content

Instantly share code, notes, and snippets.

@tomfejer
Created December 1, 2018 10:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomfejer/c9747a7815bc3531b0ad600dc80dec59 to your computer and use it in GitHub Desktop.
Save tomfejer/c9747a7815bc3531b0ad600dc80dec59 to your computer and use it in GitHub Desktop.
import ApplicationUI = prezi_plugin_api.ApplicationUI;
import UIRoot = prezi_plugin_api.UIRoot;
import MenuId = prezi_plugin_api.MenuId;
import FillKind = prezi_cet_model_editor.base.FillKind;
declare var require: any;
type UiState = {
// Define the state of your plugin here
themeColors?: prezi_cet_model_editor.base.ThemeColors;
textColors: Array<any>;
backgroundUrl?: string;
backgroundTint?: prezi_cet_model_editor.base.ColorFilter;
Vibrant?: any;
vibrantColors: prezi_cet_model_editor.base.StyleColor[];
locks: boolean[];
autoColorText: boolean;
};
class Main implements prezi_plugin_api.EditorPlugin {
init(applicationApi: prezi_plugin_api.ApplicationApi) {
const uiRoot = applicationApi.declareUI<UiState>(
{
vibrantColors: [],
textColors: [
{
r: 0,
g: 0,
b: 0,
a: 1
},
{
r: 255,
g: 255,
b: 255,
a: 1
}
],
locks: [false, false, false, false, false],
autoColorText: false
},
(state, ui) => {
// Create menuItems, sidebars here
this.createMenuItem(ui, state, uiRoot);
this.createSidebar(ui, state, uiRoot);
}
);
applicationApi.onDocumentChange(rctx => {
let state = uiRoot.getState();
const themeColors = rctx.reader.read(readApi => {
return readApi.styleSheet.themeColors;
});
const backgroundUrl = rctx.reader.read(readApi => {
return readApi.background.imageAsset == null
? null
: readApi.background.imageAsset.url;
});
const backgroundTint: prezi_cet_model_editor.base.ColorFilter = rctx.reader.read(
readApi => {
return readApi.background.colorFilter;
}
);
if (
backgroundUrl !== state.backgroundUrl &&
state.Vibrant != null &&
backgroundUrl != null
) {
this.calculateVibrantColors(backgroundUrl, uiRoot);
}
uiRoot.setState({
...state,
themeColors: themeColors,
backgroundUrl: backgroundUrl,
backgroundTint: backgroundTint
});
});
}
createMenuItem(ui: ApplicationUI, state: UiState, uiRoot: UIRoot<UiState>) {
ui.menuItem({
id: "colorTest1",
parent: MenuId.Lab,
weight: 6,
title: "Color Scheme Test",
onClick: () => {
if (!this.isLoaded(state)) {
require([
"//client-js.prezi.com/release/lib/vibrant/Vibrant.min.js"
], () => {
uiRoot.setState({ Vibrant: (window as any).Vibrant });
// open the sidebar once initialized.
uiRoot.sidebar.open("colorTestSidebarId");
if (uiRoot.getState().vibrantColors.length === 0) {
this.calculateVibrantColors(
uiRoot.getState().backgroundUrl,
uiRoot
);
}
});
} else {
uiRoot.sidebar.open("colorTestSidebarId");
}
},
icon: prezi_plugin_api.IconId.Cog
});
}
colorPickerTitles: string[] = [
"Scheme color 1",
"Scheme color 2",
"Scheme color 3",
"Scheme color 4",
"Scheme color 5",
"Primary text color",
"Body text color"
];
createSidebar(ui: ApplicationUI, state: UiState, uiRoot: UIRoot<UiState>) {
return ui.createSidebar({
id: "colorTestSidebarId",
root: {
title: "Color Scheme Designer",
content: !this.isLoaded(state)
? [
ui.sidebar.spinner(
prezi_plugin_api.SpinnerColor.blue,
prezi_plugin_api.SpinnerSize.m
)
]
: [
ui.sidebar.containerWithColoredBackground({
content: [
ui.sidebar.sectionHeader("Scheme name"),
ui.sidebar.inputField({
id: "basic-input-field",
placeholderText: "Untitled scheme",
disabled: true
}),
ui.sidebar.label("")
]
}),
ui.sidebar.label(""),
this.createVibrantPaletteButton(ui, state, uiRoot),
ui.sidebar.separator(),
this.createRandomPaletteButton(ui, state, uiRoot),
ui.sidebar.separator(),
this.createPaletteColorPicker(ui, state, uiRoot, 1),
this.createPaletteColorPicker(ui, state, uiRoot, 2),
this.createPaletteColorPicker(ui, state, uiRoot, 3),
this.createPaletteColorPicker(ui, state, uiRoot, 4),
this.createPaletteColorPicker(ui, state, uiRoot, 5),
ui.sidebar.separator(),
this.createTextColorPicker(ui, state, uiRoot, 0),
this.createTextColorPicker(ui, state, uiRoot, 1),
ui.sidebar.label(""),
this.createAutoColorCheckbox(ui, state, uiRoot),
ui.sidebar.separator(),
ui.sidebar.sectionHeader("Display font"),
ui.sidebar.inputField({
id: "basic-input-field",
placeholderText: "default",
disabled: true
}),
ui.sidebar.label(""),
ui.sidebar.sectionHeader("Body font"),
ui.sidebar.inputField({
id: "basic-input-field",
placeholderText: "default",
disabled: true
}),
ui.sidebar.label(""),
ui.sidebar.separator(),
ui.sidebar.sectionHeader("Title text style"),
ui.sidebar.button(
prezi_plugin_api.ButtonSize.Large,
prezi_plugin_api.ButtonAlign.Start,
{
type: prezi_plugin_api.ButtonType.Ghost,
id: "bold",
content: { icon: prezi_plugin_api.IconId.Bold },
disabled: true
},
{
type: prezi_plugin_api.ButtonType.Ghost,
id: "italic",
content: { icon: prezi_plugin_api.IconId.Italic },
disabled: true
},
{
type: prezi_plugin_api.ButtonType.Ghost,
id: "textBackground",
content: { icon: prezi_plugin_api.IconId.TextBackground },
disabled: true
}
),
ui.sidebar.label(""),
ui.sidebar.sectionHeader("Subtitle text style"),
ui.sidebar.button(
prezi_plugin_api.ButtonSize.Large,
prezi_plugin_api.ButtonAlign.Start,
{
type: prezi_plugin_api.ButtonType.Ghost,
id: "bold",
content: { icon: prezi_plugin_api.IconId.Bold },
disabled: true
},
{
type: prezi_plugin_api.ButtonType.Ghost,
id: "italic",
content: { icon: prezi_plugin_api.IconId.Italic },
disabled: true
},
{
type: prezi_plugin_api.ButtonType.Ghost,
id: "textBackground",
content: { icon: prezi_plugin_api.IconId.TextBackground },
disabled: true
}
),
ui.sidebar.label(""),
ui.sidebar.sectionHeader("Body text style"),
ui.sidebar.button(
prezi_plugin_api.ButtonSize.Large,
prezi_plugin_api.ButtonAlign.Start,
{
type: prezi_plugin_api.ButtonType.Ghost,
id: "bold",
content: { icon: prezi_plugin_api.IconId.Bold },
disabled: true
},
{
type: prezi_plugin_api.ButtonType.Ghost,
id: "italic",
content: { icon: prezi_plugin_api.IconId.Italic },
disabled: true
},
{
type: prezi_plugin_api.ButtonType.Ghost,
id: "textBackground",
content: { icon: prezi_plugin_api.IconId.TextBackground },
disabled: true
}
),
ui.sidebar.label(""),
// this.createLocks(ui, state, uiRoot),
// ui.sidebar.label("")
ui.sidebar.separator(),
ui.sidebar.button(
prezi_plugin_api.ButtonSize.Small,
prezi_plugin_api.ButtonAlign.Center,
{
id: "clearStyle",
type: prezi_plugin_api.ButtonType.Ghost,
content: { text: "Clear inline style" },
disabled: true
}
)
],
footer: [
ui.sidebar.separator(),
ui.sidebar.button(
prezi_plugin_api.ButtonSize.Large,
prezi_plugin_api.ButtonAlign.Center,
{
type: prezi_plugin_api.ButtonType.Blue,
id: "save-theme",
content: { text: "Save scheme" },
disabled: true
},
{
type: prezi_plugin_api.ButtonType.Gray,
id: "delete-theme",
content: { icon: prezi_plugin_api.IconId.Trash },
disabled: true
}
)
]
}
});
}
createVibrantPaletteButton(
ui: ApplicationUI,
state: UiState,
uiRoot: UIRoot<UiState>
) {
return ui.sidebar.button(
prezi_plugin_api.ButtonSize.Large,
prezi_plugin_api.ButtonAlign.Center,
{
id: "vibrantPaletteButton",
type: prezi_plugin_api.ButtonType.Gray,
content: { text: "Generate from background" },
disabled: state.backgroundUrl == null || this.allTrue(state.locks),
onClick: ctx => {
ctx.runner.executeApiCommand({
name: "set style colors",
run: pluginEditorApi => {
let len = state.vibrantColors.length;
var i = 0;
pluginEditorApi.styleSheet.themeColors = {
color1:
len > 0 && !state.locks[0]
? state.vibrantColors[i++]
: pluginEditorApi.styleSheet.themeColors.color1,
color2:
len > 1 && !state.locks[1]
? state.vibrantColors[i++]
: pluginEditorApi.styleSheet.themeColors.color2,
color3:
len > 2 && !state.locks[2]
? state.vibrantColors[i++]
: pluginEditorApi.styleSheet.themeColors.color3,
color4:
len > 3 && !state.locks[3]
? state.vibrantColors[i++]
: pluginEditorApi.styleSheet.themeColors.color4,
color5:
len > 4 && !state.locks[4]
? state.vibrantColors[i++]
: pluginEditorApi.styleSheet.themeColors.color5
};
this.updatePdom(pluginEditorApi, state);
}
});
}
}
);
}
createRandomPaletteButton(
ui: ApplicationUI,
state: UiState,
uiRoot: UIRoot<UiState>
) {
return ui.sidebar.button(
prezi_plugin_api.ButtonSize.Large,
prezi_plugin_api.ButtonAlign.Center,
{
id: "randomPaletteButton",
type: prezi_plugin_api.ButtonType.Gray,
content: { text: "Randomize palette" },
disabled: this.allTrue(state.locks),
onClick: ctx => {
this.setRandomStyleColors(ctx, state);
}
}
);
}
calculateVibrantColors(background: string, uiRoot: UIRoot<UiState>) {
var img = document.createElement("img");
img.crossOrigin = "Anonymous";
img.setAttribute("src", background);
img.addEventListener("load", () => {
var vibrant = new (<any>window).Vibrant(img, 64, 1);
var swatches = vibrant.swatches();
var newVibrantColors: prezi_cet_model_editor.base.StyleColor[] = [];
var i = 1;
for (var swatch in swatches) {
if (swatches.hasOwnProperty(swatch) && swatches[swatch]) {
let color = this.hexToStyleColor(swatches[swatch].getHex());
if (i <= 5) {
newVibrantColors.push(color);
i++;
}
}
}
uiRoot.setState({
...uiRoot.getState(),
vibrantColors: newVibrantColors
});
});
}
getTextColor(state: UiState, n: number) {
const color = state.textColors[n];
return {
r: color.r,
g: color.g,
b: color.b,
a: 1
};
}
getStyleColor(state: UiState, n: number) {
switch (n) {
case 1:
return {
r: state.themeColors.color1.r,
g: state.themeColors.color1.g,
b: state.themeColors.color1.b,
a: 1
};
case 2:
return {
r: state.themeColors.color2.r,
g: state.themeColors.color2.g,
b: state.themeColors.color2.b,
a: 1
};
case 3:
return {
r: state.themeColors.color3.r,
g: state.themeColors.color3.g,
b: state.themeColors.color3.b,
a: 1
};
case 4:
return {
r: state.themeColors.color4.r,
g: state.themeColors.color4.g,
b: state.themeColors.color4.b,
a: 1
};
case 5:
return {
r: state.themeColors.color5.r,
g: state.themeColors.color5.g,
b: state.themeColors.color5.b,
a: 1
};
}
throw new Error("out of range");
}
setStyleColor(
ctx: prezi_plugin_api.PluginCtx,
state: UiState,
color: prezi_widgets.ColorData,
n: number
) {
ctx.runner.executeApiCommand({
name: "set style color " + n,
run: pluginEditorApi => {
pluginEditorApi.styleSheet.themeColors = {
color1:
n === 1 ? color : pluginEditorApi.styleSheet.themeColors.color1,
color2:
n === 2 ? color : pluginEditorApi.styleSheet.themeColors.color2,
color3:
n === 3 ? color : pluginEditorApi.styleSheet.themeColors.color3,
color4:
n === 4 ? color : pluginEditorApi.styleSheet.themeColors.color4,
color5:
n === 5 ? color : pluginEditorApi.styleSheet.themeColors.color5
};
this.updatePdom(pluginEditorApi, state);
}
});
}
setTextColor(
ctx: prezi_plugin_api.PluginCtx,
state: UiState,
uiRoot: UIRoot<UiState>,
color: prezi_widgets.ColorData,
n: number
) {
const currentTextColors = state.textColors;
const newTextColors = currentTextColors.map((currentColor, i) =>
i === n ? color : currentColor
);
uiRoot.setState({
...state,
textColors: newTextColors
});
ctx.runner.executeApiCommand({
name: "set text color " + n,
run: pluginEditorApi => {
this.updatePdom(pluginEditorApi, uiRoot.getState());
}
});
}
setRandomStyleColors(ctx: prezi_plugin_api.PluginCtx, state: UiState) {
ctx.runner.executeApiCommand({
name: "set random style color",
run: pluginEditorApi => {
pluginEditorApi.styleSheet.themeColors = {
color1: state.locks[0]
? pluginEditorApi.styleSheet.themeColors.color1
: this.randomColor(),
color2: state.locks[1]
? pluginEditorApi.styleSheet.themeColors.color2
: this.randomColor(),
color3: state.locks[2]
? pluginEditorApi.styleSheet.themeColors.color3
: this.randomColor(),
color4: state.locks[3]
? pluginEditorApi.styleSheet.themeColors.color4
: this.randomColor(),
color5: state.locks[4]
? pluginEditorApi.styleSheet.themeColors.color5
: this.randomColor()
};
this.updatePdom(pluginEditorApi, state);
}
});
}
createTextColorPicker(
ui: ApplicationUI,
state: UiState,
uiRoot: UIRoot<UiState>,
n: number
) {
return ui.sidebar.colorPicker({
label: this.colorPickerTitles[n + 5],
id: "textColorPicker" + n,
disabled: true,
fills: {
solidFill: {
fillKind: FillKind.solid,
color: this.getTextColor(state, n)
},
current: FillKind.solid,
hasAlpha: false
},
onChange: (ctx, event) => {
if (event.isFinal) {
let color = event.newFill.color;
let newColor = { r: color.r, g: color.g, b: color.b, a: 1 };
this.setTextColor(ctx, state, uiRoot, newColor, n);
}
}
});
}
createPaletteColorPicker(
ui: ApplicationUI,
state: UiState,
uiRoot: UIRoot<UiState>,
n: number
) {
return ui.sidebar.colorPicker({
label:
this.colorPickerTitles[n - 1] + (state.locks[n - 1] ? " (locked)" : ""),
id: "paletteColorPicker" + n,
fills: {
solidFill: {
fillKind: FillKind.solid,
color: this.getStyleColor(state, n)
},
current: FillKind.solid,
hasAlpha: false
},
onChange: (ctx, event) => {
if (event.isFinal) {
let color = event.newFill.color;
let newColor = { r: color.r, g: color.g, b: color.b, a: 1 };
this.setStyleColor(ctx, state, newColor, n);
}
}
});
}
createAutoColorCheckbox(
ui: ApplicationUI,
state: UiState,
uiRoot: UIRoot<UiState>
) {
return ui.sidebar.checkbox({
checked: state.autoColorText,
disabled: true,
label: state.autoColorText
? "Auto Text Color enabled"
: "Auto Text Color disabled",
onCheck: (ctx, checked) => {
uiRoot.setState({ autoColorText: checked });
}
});
}
toggleLock(state: UiState, n: number): boolean[] {
let newLocks = [...state.locks];
newLocks[n] = !newLocks[n];
return newLocks;
}
createLocks(ui: ApplicationUI, state: UiState, uiRoot: UIRoot<UiState>) {
let buttons = ui.sidebar.button(
prezi_plugin_api.ButtonSize.Small,
prezi_plugin_api.ButtonAlign.Center,
{
type: state.locks[0]
? prezi_plugin_api.ButtonType.Blue
: prezi_plugin_api.ButtonType.Ghost,
id: "paletteLockButton1",
content: { icon: prezi_plugin_api.IconId.Lock },
onClick: ctx => {
uiRoot.setState({
...uiRoot.getState(),
locks: this.toggleLock(state, 0)
});
}
},
{
type: state.locks[1]
? prezi_plugin_api.ButtonType.Blue
: prezi_plugin_api.ButtonType.Ghost,
id: "paletteLockButton2",
content: { icon: prezi_plugin_api.IconId.Lock },
onClick: ctx => {
uiRoot.setState({
...uiRoot.getState(),
locks: this.toggleLock(state, 1)
});
}
},
{
type: state.locks[2]
? prezi_plugin_api.ButtonType.Blue
: prezi_plugin_api.ButtonType.Ghost,
id: "paletteLockButton3",
content: { icon: prezi_plugin_api.IconId.Lock },
onClick: ctx => {
uiRoot.setState({
...uiRoot.getState(),
locks: this.toggleLock(state, 2)
});
}
},
{
type: state.locks[3]
? prezi_plugin_api.ButtonType.Blue
: prezi_plugin_api.ButtonType.Ghost,
id: "paletteLockButton4",
content: { icon: prezi_plugin_api.IconId.Lock },
onClick: ctx => {
uiRoot.setState({
...uiRoot.getState(),
locks: this.toggleLock(state, 3)
});
}
},
{
type: state.locks[4]
? prezi_plugin_api.ButtonType.Blue
: prezi_plugin_api.ButtonType.Ghost,
id: "paletteLockButton5",
content: { icon: prezi_plugin_api.IconId.Lock },
onClick: ctx => {
uiRoot.setState({
...uiRoot.getState(),
locks: this.toggleLock(state, 4)
});
}
}
);
return ui.sidebar.containerWithColoredBackground({
content: [ui.sidebar.sectionHeader("Lock colors"), buttons]
});
}
updatePdom(
pluginEditorApi: prezi_cet_model_editor.basePlugin.BasePluginEditorApi,
state: UiState
) {
let themeColors = pluginEditorApi.styleSheet.themeColors;
this.setBackgroundColor(pluginEditorApi, themeColors.color1);
this.setColorAndBorderOfStyleBlock(
pluginEditorApi,
themeColors.color2,
themeColors.color4,
"frame1"
);
this.setColorAndBorderOfStyleBlock(
pluginEditorApi,
themeColors.color3,
themeColors.color4,
"frame2"
);
this.setColorAndBorderOfStyleBlock(
pluginEditorApi,
themeColors.color3,
themeColors.color4,
"frame3"
);
this.setColorOfStyleBlock(
pluginEditorApi,
state.textColors[0] /*color6*/,
"title",
"zText"
);
this.setColorOfStyleBlock(
pluginEditorApi,
state.textColors[0] /*color6*/,
"subtitle",
"zText"
);
this.setColorOfStyleBlock(
pluginEditorApi,
state.textColors[0] /*color6*/,
"body",
"zText"
);
this.setColorOfStyleBlock(
pluginEditorApi,
state.textColors[1] /*color7*/,
"subtitle_2",
"zText"
);
this.setColorOfStyleBlock(
pluginEditorApi,
state.textColors[1] /*color7*/,
"body_2",
"zText"
);
this.setColorAndBorderOfStyleBlock(
pluginEditorApi,
themeColors.color1,
themeColors.color4,
"poly1"
);
this.setColorAndBorderOfStyleBlock(
pluginEditorApi,
themeColors.color2,
themeColors.color4,
"poly2"
);
this.setColorAndBorderOfStyleBlock(
pluginEditorApi,
themeColors.color3,
themeColors.color4,
"poly3"
);
this.setColorAndBorderOfStyleBlock(
pluginEditorApi,
themeColors.color4,
themeColors.color4,
"poly4"
);
this.setColorAndBorderOfStyleBlock(
pluginEditorApi,
themeColors.color5,
themeColors.color4,
"poly5"
);
this.setColorOfStyleBlock(pluginEditorApi, themeColors.color1, "line1");
this.setColorOfStyleBlock(pluginEditorApi, themeColors.color2, "line2");
this.setColorOfStyleBlock(pluginEditorApi, themeColors.color3, "line3");
this.setColorOfStyleBlock(pluginEditorApi, themeColors.color4, "line4");
this.setColorOfStyleBlock(pluginEditorApi, themeColors.color5, "line5");
this.setColorOfStyleBlock(pluginEditorApi, themeColors.color4, "chainLink");
}
setBackgroundColor(
pluginEditorApi: prezi_cet_model_editor.basePlugin.BasePluginEditorApi,
color: prezi_cet_model_editor.base.StyleColor
) {
pluginEditorApi.background.fill = {
fillKind: FillKind.solid,
color: this.styleColorToColorData(color)
};
}
setColorOfStyleBlock(
pluginEditorApi: prezi_cet_model_editor.basePlugin.BasePluginEditorApi,
color: prezi_cet_model_editor.base.StyleColor,
className: string,
typeName?: string
) {
const styleDeclarationEditor = pluginEditorApi.styleSheet.ensure(
className,
typeName
);
let styleBlock = styleDeclarationEditor.styleBlock;
styleDeclarationEditor.styleBlock = {
...styleBlock,
fill: {
...styleBlock.fill,
color: this.styleColorToColorData(color)
}
};
}
setColorAndBorderOfStyleBlock(
pluginEditorApi: prezi_cet_model_editor.basePlugin.BasePluginEditorApi,
color: prezi_cet_model_editor.base.StyleColor,
border: prezi_cet_model_editor.base.StyleColor,
className: string,
typeName?: string
) {
const styleDeclarationEditor = pluginEditorApi.styleSheet.ensure(
className,
typeName
);
let styleBlock = styleDeclarationEditor.styleBlock;
styleDeclarationEditor.styleBlock = {
...styleBlock,
fill: {
...styleBlock.fill,
fillKind: FillKind.solid,
alpha: 1,
color: this.styleColorToColorData(color)
},
border: {
...styleBlock.border,
color: this.styleColorToColorData(border),
alpha: 1
}
};
}
/* Utilities */
hexToWidgetColor(hex: string): prezi_cet_model_editor.base.ColorData {
var bigint = parseInt(hex.substr(1), 16);
var r = (bigint >> 16) & 255;
var g = (bigint >> 8) & 255;
var b = bigint & 255;
return { r: r, g: g, b: b, a: 1 };
}
hexToStyleColor(hex: string): prezi_cet_model_editor.base.StyleColor {
var bigint = parseInt(hex.substr(1), 16);
var r = (bigint >> 16) & 255;
var g = (bigint >> 8) & 255;
var b = bigint & 255;
return { r: r, g: g, b: b };
}
styleColorToColorData(
styleColor: prezi_cet_model_editor.base.StyleColor
): prezi_cet_model_editor.base.ColorData {
return { r: styleColor.r, g: styleColor.g, b: styleColor.b, a: 1 };
}
randomColor(): prezi_cet_model_editor.base.ColorData {
return {
r: Math.floor(Math.random() * 256),
g: Math.floor(Math.random() * 256),
b: Math.floor(Math.random() * 256),
a: 1
};
}
allTrue(arr: boolean[]): boolean {
for (let b of arr) {
if (!b) {
return false;
}
}
return true;
}
processMessage() {}
private isLoaded(state: UiState) {
return state.Vibrant != null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment