This repository has been archived on 2026-05-12. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
PaintPlay/Controls/Toolbar/Toolbar.js
adrianvic 59426d62fb first
2023-12-21 14:33:34 -03:00

1092 lines
No EOL
50 KiB
JavaScript

////////////////////////////////////////////////////////////
//// © Microsoft. All rights reserved. ////
////////////////////////////////////////////////////////////
/// <reference path="../../WinJS/js/base.js" />
/// <reference path="../../WinJS/js/ui.js" />
/// <reference path="../../WinJS/js/controls.js" />
/// <reference path="../../JS/CommandBar/CommandBar.js" />
/// <reference path="../../JS/CommandBar/Flyout.js" />
/// <reference path="../ColorPicker/ColorPicker.js" />
/// <reference path="../Canvas/Painter.js" />
(function (AppNS) {
"use strict";
var CanvasManager = AppNS.CanvasManager;
var WinUtils = WinJS.Utilities;
var WinUI = WinJS.UI;
var pointerDown;
var ToolbarManager = WinJS.Namespace.defineWithParent(AppNS, "ToolbarManager", {
showUndo: function () { },
hideUndo: function () { },
fragmentLoad: function (root, state) {
WinUI.processAll();
var currentBrush = state.toolName || CanvasManager.ToolNames.Marker;
var currentWidth = state.width || 10;
var currentColorId = state.colorId || 0; // Middle color
var currentColorString;
var commmandBarHost = root.querySelector(".commandBar");
var ViewManagement = Windows.UI.ViewManagement;
var appLayout = ViewManagement.ApplicationLayout.getForCurrentView();
var layoutState = ViewManagement.ApplicationLayoutState;
var currentLayoutState = ViewManagement.ApplicationLayout.value;
var redrawBrushPreviews = true;
var redrawSizePreviews = true;
var redrawOptionPreviews = true;
var currentCommandName;
var toolStateId = {};
var commandNames = {
brush: "brush",
size: "size",
option: "option",
more: "more",
undo: "undo",
clear: "clear",
brushSnapped: "brush-snapped",
sizeSnapped: "size-snapped",
colorpicker: "colorpicker"
};
// Set color picker full and fill widths to the remaining toolbar width, the numbers represent the space occupied in the toolbar by other elements, such as commands and margins.
var colorPickerFullWidth = state.toolbarWidth - 613;
var colorPickerFillWidth = state.toolbarWidth - 913;
var unSnappedLeftMargin = 30;
var spaceForLeftCommands = unSnappedLeftMargin + 300;
var tool;
// Style classes enum
var classes = {
colorPickerContainer: "colorpickerContainer",
toolbarFlyout: "toolbar-flyout",
brushPreview: "brush-preview",
selectedPreview: "selectedPreview",
brushWidthThick: "brush-width-thick",
brushWidthThin: "brush-width-thin",
panModeToggle: "pan-mode-toggle",
commandToolbarUndo: "command_toolbar_undo",
commandToolbarOption: "command_toolbar_option",
commandToolbarSize: "command_toolbar_size",
commandToolbarBrush: "command_toolbar_brush",
commandToolbarMore: "command_toolbar_more",
brushPreviewPrefix: "brush-preview-",
sizePreviewPrefix: "size-preview-",
optionPreviewPrefix: "option-preview-",
winCommandBarHoriz: "win-commandBar-horiz",
winMediaFlyoutBackground: "win-mediaFlyout-background",
toolbarFlyoutBackground: "toolbar-flyout-background",
canvasFlyoutBackground: "canvas-flyout-background",
brushFlyout: "brush-flyout",
sizeFlyout: "size-flyout",
optionFlyout: "option-flyout",
commandLabel: "commandLabel",
moreFlyout: "more-flyout",
undoButton: "undo-button",
clearButton: "clear-button",
appBar: "appBar"
};
var appBar = document.getElementById(classes.appBar);
var styles = {
hidden: "hidden",
visible: "visible"
};
// Helper functions to hide and show elements
var hideElement = function (e) {
e.style.visibility = styles.hidden;
};
var showElement = function (e) {
e.style.visibility = styles.visible;
};
var previewIndexTypes = {
size: 0,
option: 1
};
// Helper functions to hide and show dismiss targets
var closeFlyouts = function () {
dismissAllFlyouts();
restoreCommand(currentCommandName);
currentCommandName = null;
hideElement(toolbarFlyoutDismissArea);
};
var hideToolbarDismissArea = function () {
hideElement(toolbarFlyoutDismissArea);
};
var showDismissAreas = function () {
showElement(toolbarFlyoutDismissArea);
};
var restoreCommand = function (commandName) {
// If this is an option or brush command, restore it accordingly; otherwise restore it to original
if (commandName === commandNames.option || commandName === commandNames.brush) {
commandBar.setCommandState(commandName, toolStateId[currentBrush]);
} else {
commandBar.setCommandState(commandName, 0);
}
};
// Create and initialize dismiss area over toolbar
var toolbarFlyoutDismissArea = document.createElement("div");
toolbarFlyoutDismissArea.className = classes.toolbarFlyoutBackground;
toolbarFlyoutDismissArea.style.left = spaceForLeftCommands + "px";
toolbarFlyoutDismissArea.style.minHeight = appBar.offsetHeight + "px";
toolbarFlyoutDismissArea.style.minWidth = state.toolbarWidth - spaceForLeftCommands + "px";
hideElement(toolbarFlyoutDismissArea);
toolbarFlyoutDismissArea.addEventListener("click", closeFlyouts);
root.appendChild(toolbarFlyoutDismissArea);
// Helper function to get persisted preview indexes
var getPersistedPreviewIndex = function (indexType, toolName) {
var index = null;
switch (indexType) {
case previewIndexTypes.size:
if (state.currentSizePreviewIndexes) {
index = state.currentSizePreviewIndexes[toolName];
}
break;
case previewIndexTypes.option:
if (state.currentOptionPreviewIndexes) {
index = state.currentOptionPreviewIndexes[toolName];
}
break;
}
return index;
}
// Command groups
var leftGroup = new WinUI.CommandGroup("leftGroup", WinUI.CommandStack.left);
var rightGroup = new WinUI.CommandGroup("rightGroup", WinUI.CommandStack.right);
var colorGroup = new WinUI.CommandGroup("colorGroup", WinUI.CommandStack.left);
// Commands
var moreCommand = new WinUI.Command(commandNames.more, [{
payload: {
name: commandNames.more
},
templateValues: {
commandName: "More", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/moreIcon40px.{{state}}.png"
}
},
{
payload: {
name: commandNames.more
},
templateValues: {
commandName: "More", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/moreIcon40px.{{state}}.png"
}
}], 1);
var toolName;
var brushCommandStates = [];
for (toolName in CanvasManager.ToolCards) {
brushCommandStates.push({
payload: {
name: commandNames.brush
},
templateValues: {
commandName: CanvasManager.ToolCards[toolName].label,
imageUrl: "/Res/brushIcon40px.{{state}}.png"
}
},
{
payload: {
name: commandNames.brush
},
templateValues: {
commandName: CanvasManager.ToolCards[toolName].label,
imageUrl: "/Res/brushIcon40px.press.png"
}
});
}
brushCommandStates.push({
payload: {
name: commandNames.brush
},
templateValues: {
commandName: "Pan mode", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/panmodeOptionIcon40px.{{state}}.png"
}
},
{
payload: {
name: commandNames.brush
},
templateValues: {
commandName: "Pan mode", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/panmodeOptionIcon40px.press.png"
}
});
var panModeStateId = brushCommandStates.length - 1;
var brushCommand = new WinUI.Command(commandNames.brush, brushCommandStates, 1);
var sizeCommand = new WinUI.Command(commandNames.size, [{
payload: {
name: commandNames.size
},
templateValues: {
commandName: "Size", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/sizeIcon40px.{{state}}.png"
}
},
{
payload: {
name: commandNames.size
},
templateValues: {
commandName: "Size", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/sizeIcon40px.press.png"
}
}], 1);
var brushCommandSnapped = new WinUI.Command(commandNames.brushSnapped, [{
payload: {
name: commandNames.brush
},
templateValues: {
commandName: "Brush", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/brushIcon40px.{{state}}.png"
}
},
{
payload: {
name: commandNames.brush
},
templateValues: {
commandName: "Brush", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/brushIcon40px.press.png"
}
}], 1);
var sizeCommandSnapped = new WinUI.Command(commandNames.sizeSnapped, [{
payload: {
name: commandNames.size
},
templateValues: {
commandName: "Size", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/sizeIcon40px.{{state}}.png"
}
},
{
payload: {
name: commandNames.size
},
templateValues: {
commandName: "Size", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/sizeIcon40px.press.png"
}
}], 1);
var optionCommandStates = [];
for (toolName in CanvasManager.ToolCards) {
optionCommandStates.push({
payload: {
name: commandNames.option
},
templateValues: {
commandName: CanvasManager.ToolCards[toolName].optionLabel,
imageUrl: "/Res/" + CanvasManager.ToolCards[toolName].optionKey + "OptionIcon40px.{{state}}.png"
}
},
{
payload: {
name: commandNames.option,
toolName: toolName
},
templateValues: {
commandName: CanvasManager.ToolCards[toolName].optionLabel,
imageUrl: "/Res/" + CanvasManager.ToolCards[toolName].optionKey + "OptionIcon40px.press.png"
}
});
}
var optionCommand = new WinUI.Command(commandNames.option, optionCommandStates, 1);
var undoCommand = new WinUI.Command(commandNames.undo, [{
payload: {
name: commandNames.undo
},
templateValues: {
commandName: "Undo", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/undoIcon40px.{{state}}.png"
}
},
{
payload: {
name: commandNames.undo
},
templateValues: {
commandName: "Undo", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/undoIcon40px.press.png"
}
}], 1);
var clearCommand = new WinUI.Command(commandNames.clear, [{
payload: {
name: commandNames.clear
},
templateValues: {
commandName: "Clear", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/newIcon40px.{{state}}.png"
}
},
{
payload: {
name: commandNames.clear
},
templateValues: {
commandName: "Clear", // TODO: Win8Apps WORK 92: Add localization support
imageUrl: "/Res/newIcon40px.press.png"
}
}], 1);
// Color picker
var colorPickerCommand = new WinUI.Command(commandNames.colorpicker, [{
payload: {
name: commandNames.colorpicker
},
templateValues: {
commandName: "Color picker"
}
}], 1);
colorPickerCommand.hostedElement = document.createElement("span");
colorPickerCommand.hostedElement.className = classes.colorPickerContainer;
var colorPicker = new Microsoft.Paint.ColorPicker(colorPickerCommand.hostedElement,
ToolbarManager.ToolbarColors, { height: 40, width: colorPickerFullWidth, hoverHeightGrowth: 2, hoverWidthGrowth: 1.75, bottomPosition: 20, selectedWidthGrowth: 1.25, selectedHeightGrowth: 1.25, affectedNeighbors: 3 });
// Disable automatic state change
brushCommand.advanceState = false;
sizeCommand.advanceState = false;
brushCommandSnapped.advanceState = false;
sizeCommandSnapped.advanceState = false;
optionCommand.advanceState = false;
undoCommand.advanceState = false;
clearCommand.advanceState = false;
colorPickerCommand.advanceState = false;
moreCommand.advanceState = false;
// Disable hiding the appbar on invoke
brushCommand.hideOnInvoke = false;
sizeCommand.hideOnInvoke = false;
brushCommandSnapped.hideOnInvoke = false;
sizeCommandSnapped.hideOnInvoke = false;
optionCommand.hideOnInvoke = false;
undoCommand.hideOnInvoke = false;
clearCommand.hideOnInvoke = false;
colorPickerCommand.hideOnInvoke = false;
moreCommand.hideOnInvoke = false;
// Add commands to groups
leftGroup.addCommand(brushCommand);
leftGroup.addCommand(sizeCommand);
leftGroup.addCommand(optionCommand);
rightGroup.addCommand(moreCommand);
rightGroup.addCommand(undoCommand);
rightGroup.addCommand(clearCommand);
rightGroup.addCommand(brushCommandSnapped);
rightGroup.addCommand(sizeCommandSnapped);
colorGroup.addCommand(colorPickerCommand);
var getCommandNamesForLayout = function (layout) {
var commandNamesForLayout = null;
if (layout === layoutState.fullScreen) {
commandNamesForLayout = [commandNames.brush, commandNames.size, commandNames.option, commandNames.undo, commandNames.clear, commandNames.colorpicker];
} else if (layout === layoutState.filled) {
commandNamesForLayout = [commandNames.brush, commandNames.size, commandNames.option, commandNames.colorpicker, commandNames.more];
} else if (layout === layoutState.snapped) {
commandNamesForLayout = [commandNames.brush, commandNames.size];
}
return commandNamesForLayout;
};
// Instantiate command bar
var commandBar = new WinUI.CommandBar(commmandBarHost, {
orientation: "horizontal",
commandGroups: [leftGroup, rightGroup, colorGroup],
ariaLabel: "Toolbar",
uniqueId: "toolbar"
});
// Helper function to draw previews
var drawPreview = function (preview, newColor, width, tool, optionKey, optionValue, offsetY) {
preview.canvas.clear();
if (newColor) {
var color = new AppNS.Painter.Graphics.Color();
color.fromString(newColor);
preview.color = color;
}
if (tool) {
preview.tool = tool;
}
if (width) {
preview.tool.width = width;
}
if (optionKey && optionValue) {
if (tool === CanvasManager.ToolNames.Brush) {
preview.tool[optionKey] = (optionValue || preview.tool[optionKey]) / 5;
} else {
preview.tool[optionKey] = (optionValue || preview.tool[optionKey]);
}
}
if (!offsetY) {
offsetY = 25;
}
var startX = 50;
var endX = 200;
// Draw eraser preview on top of marker stroke
if (tool === CanvasManager.ToolNames.Eraser) {
// Draw the background
var width = 20;
var height = 2;
var ctx = preview.canvas.context;
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = preview.color.toString();
ctx.fillRect(width, height, preview.canvas.domCanvas.width - 2 * width, preview.canvas.domCanvas.height - 2 * height);
// Draw the eraser stroke
preview.drawStart({ x: startX + 10, y: offsetY - 3 });
preview.draw({ x: 130, y: offsetY + 3 });
preview.draw({ x: 170, y: offsetY - 3 });
preview.drawStop({ x: endX, y: offsetY + 3 });
} else {
preview.drawStart({ x: startX, y: offsetY });
preview.draw({ x: startX + 5, y: offsetY });
preview.draw({ x: startX + 50, y: offsetY });
preview.draw({ x: startX + 75, y: offsetY });
preview.draw({ x: startX + 100, y: offsetY });
preview.draw({ x: startX + 110, y: offsetY });
preview.draw({ x: startX + 115, y: offsetY });
preview.draw({ x: startX + 120, y: offsetY });
preview.draw({ x: startX + 125, y: offsetY });
preview.draw({ x: endX, y: offsetY });
preview.draw({ x: endX + 5, y: offsetY });
preview.drawStop({ x: endX + 10, y: offsetY });
}
};
// Flyouts
var brushFlyout = document.getElementById(classes.brushFlyout);
var sizeFlyout = document.getElementById(classes.sizeFlyout);
var optionFlyout = document.getElementById(classes.optionFlyout);
var moreFlyout = document.getElementById(classes.moreFlyout);
brushFlyout.addEventListener("afterhide", hideToolbarDismissArea);
sizeFlyout.addEventListener("afterhide", hideToolbarDismissArea);
optionFlyout.addEventListener("afterhide", hideToolbarDismissArea);
// Brush flyout
var brushFlyoutPreviews = [];
var brushFlyoutDomElements = {};
// Create canvases for brush previews
var i = 0;
var len = 0;
// Add pan mode toggle
var panModeDiv = document.createElement("div");
panModeDiv.className = classes.panModeToggle;
panModeDiv.innerHTML = "Pan mode";
panModeDiv.addEventListener("MSPointerOut", function (event) {
if (pointerDown) {
WinUtils.removeClass(event.currentTarget, classes.selectedPreview);
WinUtils.addClass(currentBrushPreview, classes.selectedPreview);
pointerDown = false;
}
});
panModeDiv.addEventListener("MSPointerDown", function (event) {
pointerDown = true;
WinUtils.removeClass(currentBrushPreview, classes.selectedPreview);
WinUtils.addClass(event.currentTarget, classes.selectedPreview);
});
panModeDiv.addEventListener("MSPointerUp", function (event) {
if (pointerDown) {
AppNS.CanvasManager.canvasBlocked = true;
AppNS.CanvasManager.canvasPannable = true;
hideFlyout(brushFlyout);
currentBrushPreview = event.currentTarget;
commandBar.setCommandState(commandNames.brush, panModeStateId);
pointerDown = false;
closeFlyouts();
}
});
brushFlyout.appendChild(panModeDiv);
for (toolName in CanvasManager.ToolCards) {
var brushPreviewCanvas = document.createElement("canvas");
brushFlyoutDomElements[toolName] = brushPreviewCanvas;
brushFlyoutPreviews[i] = new AppNS.Painter.Painter(brushPreviewCanvas);
toolStateId[toolName] = 2 * i;
if (toolName === AppNS.CanvasManager.ToolNames.Crayon) {
// Create texture image for crayon
var textureImage = new Image(40, 40);
var crayonPainter = brushFlyoutPreviews[i];
textureImage.addEventListener("load", function () {
var card = CanvasManager.ToolCards[CanvasManager.ToolNames.Crayon];
var tool = new card.toolClass();
tool.setTexture(textureImage);
tool.size = card.supportedSizes[card.defaultSizeIndex];
tool[card.optionKey] = card.optionValues[card.defaultOptionIndex];
crayonPainter.loadTool(tool, CanvasManager.ToolNames.Crayon);
drawPreview(crayonPainter, AppNS.ToolbarManager.ToolbarColors[currentColorId], 30, CanvasManager.ToolNames.Crayon);
});
textureImage.src = "../Controls/Paint/Res/crayon_texture.png";
} else {
var card = CanvasManager.ToolCards[toolName];
var tool = new card.toolClass();
tool.size = card.supportedSizes[card.defaultSizeIndex];
if (toolName !== CanvasManager.ToolNames.Eraser) {
tool[card.optionKey] = card.optionValues[card.defaultOptionIndex];
}
brushFlyoutPreviews[i].loadTool(tool, toolName);
}
brushFlyoutPreviews[i].loadTool(tool, toolName);
// Set default option value in tool
if (toolName !== CanvasManager.ToolNames.Eraser) {
tool[CanvasManager.ToolCards[toolName].optionKey] = CanvasManager.ToolCards[toolName].optionValues[CanvasManager.ToolCards[toolName].defaultOptionIndex];
}
brushPreviewCanvas.id = classes.brushPreviewPrefix + toolName;
brushPreviewCanvas.className = classes.brushPreview;
brushPreviewCanvas.addEventListener("MSPointerOut", function (event) {
if (pointerDown) {
WinUtils.removeClass(event.currentTarget, classes.selectedPreview);
WinUtils.addClass(currentBrushPreview, classes.selectedPreview);
pointerDown = false;
}
});
brushPreviewCanvas.addEventListener("MSPointerDown", function (event) {
pointerDown = true;
WinUtils.removeClass(currentBrushPreview, classes.selectedPreview);
WinUtils.addClass(event.currentTarget, classes.selectedPreview);
});
brushPreviewCanvas.addEventListener("MSPointerUp", function (event) {
if (pointerDown) {
if (CanvasManager.canvasPannable) {
AppNS.CanvasManager.canvasBlocked = false;
AppNS.CanvasManager.canvasPannable = false;
}
var selectedTool = event.currentTarget.id.substr(14);
if (currentBrush === CanvasManager.ToolNames.Eraser && selectedTool !== CanvasManager.ToolNames.Eraser) {
showElement(document.getElementById(classes.commandToolbarOption));
}
if (selectedTool === CanvasManager.ToolNames.Eraser) {
hideElement(document.getElementById(classes.commandToolbarOption));
} else {
commandBar.setCommandState(commandNames.option, toolStateId[selectedTool]);
}
// Set tool to be drawn with to the selected tool
CanvasManager.tool = selectedTool;
// Set the option command label if the selected tool is not the eraser and we are not in snap view
if (selectedTool !== CanvasManager.ToolNames.Eraser && currentLayoutState !== layoutState.snapped) {
document.querySelector("#" + classes.commandToolbarOption + " ." + classes.commandLabel).innerText = CanvasManager.ToolCards[selectedTool].optionLabel; // TODO: Win8Bugs 423768 CommandBar - Provide API to change command text
redrawOptionPreviews = true;
}
// Remove previous highlights
WinUtils.removeClass(currentSizePreview[currentBrush], classes.selectedPreview);
if (currentBrush !== CanvasManager.ToolNames.Eraser) {
WinUtils.removeClass(currentOptionPreview[currentBrush], classes.selectedPreview);
}
// If there's no previous selection for size, set the default
if (!currentSizePreview[selectedTool]) {
currentSizePreview[selectedTool] = sizeFlyoutDomElements[CanvasManager.ToolCards[selectedTool].defaultSizeIndex];
}
// If there's no previous selection for option, set the default
if (!currentOptionPreview[selectedTool] && selectedTool !== CanvasManager.ToolNames.Eraser) {
currentOptionPreview[selectedTool] = optionFlyoutDomElements[CanvasManager.ToolCards[selectedTool].defaultOptionIndex];
}
// Apply size and option selections
WinUtils.addClass(currentSizePreview[selectedTool], classes.selectedPreview);
if (selectedTool !== CanvasManager.ToolNames.Eraser) {
WinUtils.addClass(currentOptionPreview[selectedTool], classes.selectedPreview);
}
// Apply brush selection
currentBrushPreview = event.currentTarget;
lastBrushPreview = event.currentTarget;
redrawSizePreviews = true;
commandBar.setCommandState(commandNames.brush, toolStateId[selectedTool]);
currentBrush = selectedTool;
closeFlyouts();
pointerDown = false;
}
});
brushFlyout.appendChild(brushPreviewCanvas);
brushPreviewCanvas.height = brushPreviewCanvas.offsetHeight;
brushPreviewCanvas.width = brushPreviewCanvas.offsetWidth;
i++;
}
var currentBrushPreview;
if (state.toolName) {
currentBrushPreview = brushFlyoutDomElements[state.toolName];
} else {
currentBrushPreview = brushFlyoutDomElements[currentBrush];
}
WinUtils.addClass(currentBrushPreview, classes.selectedPreview);
var lastBrushPreview = currentBrushPreview;
// Size flyout
var sizeFlyoutPreviews = [];
var sizeFlyoutDomElements = [];
// Create canvases for size previews
for (i = 0, len = CanvasManager.ToolCards[currentBrush].supportedSizes.length; i < len; i++) {
var sizePreviewCanvas = document.createElement("canvas");
sizeFlyoutDomElements[i] = sizePreviewCanvas;
if (i < 3) {
sizePreviewCanvas.className = classes.brushWidthThick;
} else {
sizePreviewCanvas.className = classes.brushWidthThin;
}
sizePreviewCanvas.id = classes.sizePreviewPrefix + i;
sizeFlyoutPreviews[i] = new AppNS.Painter.Painter(sizePreviewCanvas);
CanvasManager.loadAllTools(sizeFlyoutPreviews[i]);
sizeFlyout.appendChild(sizePreviewCanvas);
sizePreviewCanvas.addEventListener("MSPointerOut", function (event) {
if (pointerDown) {
WinUtils.removeClass(event.currentTarget, classes.selectedPreview);
WinUtils.addClass(currentSizePreview[currentBrush], classes.selectedPreview);
pointerDown = false;
}
});
sizePreviewCanvas.addEventListener("MSPointerDown", function (event) {
pointerDown = true;
WinUtils.removeClass(currentSizePreview[currentBrush], classes.selectedPreview);
WinUtils.addClass(event.currentTarget, classes.selectedPreview);
});
sizePreviewCanvas.addEventListener("MSPointerUp", function (event) {
if (pointerDown) {
var selectedSize = event.currentTarget.id.substr(13);
CanvasManager.toolWidth = CanvasManager.ToolCards[currentBrush].supportedSizes[selectedSize];
currentWidth = CanvasManager.ToolCards[currentBrush].supportedSizes[selectedSize];
currentSizePreview[currentBrush] = event.currentTarget;
closeFlyouts();
pointerDown = false;
}
});
sizePreviewCanvas.height = sizePreviewCanvas.offsetHeight;
sizePreviewCanvas.width = sizePreviewCanvas.offsetWidth;
}
var currentSizePreview = {};
// Set default size preview
if (state.currentSizePreviewIndexes) {
for (toolName in state.currentSizePreviewIndexes) {
currentSizePreview[toolName] = sizeFlyoutDomElements[getPersistedPreviewIndex(previewIndexTypes.size, toolName)];
}
} else {
currentSizePreview[currentBrush] = sizeFlyoutDomElements[CanvasManager.ToolCards[currentBrush].defaultSizeIndex];
}
WinUtils.addClass(currentSizePreview[currentBrush], classes.selectedPreview);
// Option flyout
var optionFlyoutPreviews = [];
var optionFlyoutDomElements = [];
// Create canvases for option previews
for (i = 0, len = CanvasManager.ToolCards[currentBrush].optionValues.length; i < len; i++) {
var optionPreviewCanvas = document.createElement("canvas");
optionPreviewCanvas.id = classes.optionPreviewPrefix + i;
optionFlyoutPreviews[i] = new AppNS.Painter.Painter(optionPreviewCanvas);
optionFlyoutDomElements[i] = optionPreviewCanvas;
CanvasManager.loadAllTools(optionFlyoutPreviews[i]);
optionFlyout.appendChild(optionPreviewCanvas);
optionPreviewCanvas.className = classes.brushWidthThin;
optionPreviewCanvas.addEventListener("MSPointerOut", function (event) {
if (pointerDown) {
WinUtils.removeClass(event.currentTarget, classes.selectedPreview);
WinUtils.addClass(currentOptionPreview[currentBrush], classes.selectedPreview);
pointerDown = false;
}
});
optionPreviewCanvas.addEventListener("MSPointerDown", function (event) {
pointerDown = true;
WinUtils.removeClass(currentOptionPreview[currentBrush], classes.selectedPreview);
WinUtils.addClass(event.currentTarget, classes.selectedPreview);
});
optionPreviewCanvas.addEventListener("MSPointerUp", function (event) {
if (pointerDown) {
var selectedOption = event.currentTarget.id.substr(15);
// Set new option
if (CanvasManager.ToolCards[currentBrush].optionKey) {
CanvasManager.setToolProperty(CanvasManager.ToolCards[currentBrush].optionKey, CanvasManager.ToolCards[currentBrush].optionValues[selectedOption]);
}
currentOptionPreview[currentBrush] = event.currentTarget;
closeFlyouts();
pointerDown = false;
}
});
optionPreviewCanvas.height = optionPreviewCanvas.offsetHeight;
optionPreviewCanvas.width = optionPreviewCanvas.offsetWidth;
}
var currentOptionPreview = {};
// Set default option preview
if (state.currentOptionPreviewIndexes) {
for (toolName in state.currentOptionPreviewIndexes) {
currentOptionPreview[toolName] = optionFlyoutDomElements[getPersistedPreviewIndex(previewIndexTypes.option, toolName)];
}
} else {
currentOptionPreview[currentBrush] = optionFlyoutDomElements[CanvasManager.ToolCards[currentBrush].defaultOptionIndex];
}
WinUtils.addClass(currentOptionPreview[currentBrush], classes.selectedPreview);
// Helper function to render brush options on canvases
var renderBrushOptions = function (previews, brush) {
for (i = 0, len = previews.length; i < len; i++) {
drawPreview(previews[i], null, null, brush, CanvasManager.ToolCards[brush].optionKey, CanvasManager.ToolCards[brush].optionValues[i]);
}
};
function hideUndo() {
if (!CanvasManager.canUndo() && currentLayoutState === layoutState.fullScreen) {
hideElement(document.getElementById(classes.commandToolbarUndo));
}
}
// Shows the undo button if in the fullscreen state and the canvas can undo
function showUndo() {
if (currentLayoutState === layoutState.fullScreen && CanvasManager.canUndo() && appBar.style.visibility === styles.visible) {
showElement(document.getElementById(classes.commandToolbarUndo));
}
}
WinUI.getControl(appBar).addEventListener("beforeshow", function () {
if (CanvasManager.canUndo() && currentLayoutState === layoutState.fullScreen) {
showElement(document.getElementById(classes.commandToolbarUndo));
}
});
AppNS.ToolbarManager.hideUndo = hideUndo;
AppNS.ToolbarManager.showUndo = showUndo;
// Command event listeners
commandBar.addEventListener("commandinvoked", function (event) {
// Set command state to clicked
if (event.payload.name === commandNames.brush || event.payload.name === commandNames.option) {
commandBar.setCommandState(event.payload.name, toolStateId[currentBrush] + 1);
} else if (event.payload.name !== commandNames.undo && event.payload.name !== commandNames.clear) {
commandBar.setCommandState(event.payload.name, 1);
}
if (currentCommandName) {
restoreCommand(currentCommandName);
}
currentCommandName = event.payload.name;
switch (currentCommandName) {
case commandNames.brush:
if (brushFlyout.style.visibility !== styles.visible) {
dismissAllFlyouts();
showDismissAreas();
if (redrawBrushPreviews) {
var i = 0;
for (toolName in CanvasManager.ToolCards) {
drawPreview(brushFlyoutPreviews[i], currentColorString, 30, toolName);
i++;
}
redrawBrushPreviews = false;
}
showFlyout(brushFlyout, document.getElementById(classes.commandToolbarBrush), "top");
} else {
closeFlyouts();
}
break;
case commandNames.size:
if (sizeFlyout.style.visibility !== styles.visible) {
dismissAllFlyouts();
showDismissAreas();
if (redrawSizePreviews) {
for (var i = 0, len = CanvasManager.ToolCards[currentBrush].supportedSizes.length; i < len; i++) {
if (i < 3) {
drawPreview(sizeFlyoutPreviews[i], currentColorString, CanvasManager.ToolCards[currentBrush].supportedSizes[i], currentBrush, null, null, 50);
} else {
drawPreview(sizeFlyoutPreviews[i], currentColorString, CanvasManager.ToolCards[currentBrush].supportedSizes[i], currentBrush);
}
}
redrawSizePreviews = false;
}
showFlyout(sizeFlyout, document.getElementById(classes.commandToolbarSize), "top");
} else {
closeFlyouts();
}
break;
case commandNames.option:
if (optionFlyout.style.visibility !== styles.visible) {
dismissAllFlyouts();
showDismissAreas();
if (redrawOptionPreviews) {
if (CanvasManager.ToolCards[currentBrush].optionKey) {
for (var i = 0, len = CanvasManager.ToolCards[currentBrush].optionValues.length; i < len; i++) {
drawPreview(optionFlyoutPreviews[i], currentColorString, 30, currentBrush, CanvasManager.ToolCards[currentBrush].optionKey, CanvasManager.ToolCards[currentBrush].optionValues[i]);
}
}
redrawOptionPreviews = false;
}
showFlyout(optionFlyout, document.getElementById(classes.commandToolbarOption), "top");
} else {
closeFlyouts();
}
break;
case commandNames.undo:
CanvasManager.undoCanvas()
break;
case commandNames.clear:
CanvasManager.clearCanvas();
break;
case commandNames.more:
if (moreFlyout.style.visibility !== styles.visible) {
dismissAllFlyouts();
showDismissAreas();
showFlyout(moreFlyout, document.getElementById(classes.commandToolbarMore), "top");
} else {
closeFlyouts();
}
break;
}
});
document.getElementById(classes.undoButton).addEventListener("click", function () {
CanvasManager.undoCanvas();
closeFlyouts();
});
document.getElementById(classes.clearButton).addEventListener("click", function () {
CanvasManager.clearCanvas();
closeFlyouts();
});
colorPicker.addEventListener("colorselected", function (event) {
CanvasManager.color = event.payload.color;
currentColorId = event.payload.colorId;
currentColorString = event.payload.color;
redrawBrushPreviews = true;
redrawSizePreviews = true;
redrawOptionPreviews = true;
});
// Preselect color
colorPicker.selectColor(currentColorId);
// Helper functions for showing and hiding flyouts
var showFlyout = function (flyout, anchor, position) {
WinUI.getControl(flyout).show(anchor, position);
};
var hideFlyout = function (flyout) {
WinUI.getControl(flyout).hide();
};
// Helper function to dismiss all flyouts
var dismissAllFlyouts = function () {
hideFlyout(brushFlyout);
hideFlyout(sizeFlyout);
hideFlyout(optionFlyout);
};
// Helper function to restore brush and option commands to the selected state
var restoreBrushCommands = function () {
commandBar.setCommandState(commandNames.brush, toolStateId[currentBrush]);
commandBar.setCommandState(commandNames.option, toolStateId[currentBrush]);
};
var changeLayout = function (newLayout) {
/// <summary>
/// Changes the toolbar layout to a specified layout such as snap or fill
/// </summary>
/// <param name='newLayout'>
/// layoutState to be changed to
/// </param>
if (newLayout === layoutState.fullScreen) {
panModeDiv.style.display = "none";
CanvasManager.canvasBlocked = false;
CanvasManager.canvasPannable = false;
WinUtils.removeClass(currentBrushPreview, classes.selectedPreview);
WinUtils.addClass(lastBrushPreview, classes.selectedPreview);
currentBrushPreview = lastBrushPreview;
colorPicker.width = colorPickerFullWidth;
commandBar.setCommands(getCommandNamesForLayout(layoutState.fullScreen))
.then(restoreBrushCommands);
} else {
panModeDiv.style.display = "block";
if (newLayout === layoutState.snapped) {
if (currentLayoutState !== layoutState.snapped) {
// Center command icons
document.querySelector(".win-commandBar-horiz").style.marginLeft = (window.innerWidth - 200) / 2 + "px";
}
commandBar.setCommands(getCommandNamesForLayout(layoutState.snapped))
.then(restoreBrushCommands);
} else if (newLayout === layoutState.filled) {
colorPicker.width = colorPickerFillWidth;
commandBar.setCommands(getCommandNamesForLayout(layoutState.filled))
.then(restoreBrushCommands);
}
}
if (currentLayoutState === layoutState.snapped && newLayout !== currentLayoutState) {
document.querySelector("." + classes.winCommandBarHoriz).style.marginLeft = unSnappedLeftMargin + "px";
}
currentLayoutState = newLayout;
};
// Set commands
if (currentLayoutState === layoutState.fullScreen) {
commandBar.setCommands(getCommandNamesForLayout(layoutState.fullScreen));
} else {
changeLayout(currentLayoutState);
}
// Hide undo if no undo data was persisted
if (!state.undoBlobNames && currentLayoutState === layoutState.fullScreen) {
hideElement(document.getElementById(classes.commandToolbarUndo));
}
// Initialize commands with persisted state
if (state.toolName) {
var commandStateId = toolStateId[state.toolName];
commandBar.setCommandState(commandNames.brush, commandStateId);
if (state.toolName !== CanvasManager.ToolNames.Eraser) {
commandBar.setCommandState(commandNames.option, commandStateId);
}
}
// Show appbar
commandBar.show();
WinJS.Namespace.defineWithParent(AppNS, "ToolbarManager", {
toolName: {
get: function () {
/// <summary>
/// Gets the current tool name
/// </summary>
/// <returns>
/// String
/// </returns>
return currentBrush;
}
},
colorId: {
get: function () {
/// <summary>
/// Gets the current color id
/// </summary>
/// <returns>
/// Number
/// </returns>
return currentColorId;
}
},
optionValueIndex: {
get: function () {
/// <summary>
/// Gets the current option value index for the current tool
/// </summary>
/// <returns>
/// Number
/// </returns>
return parseInt(currentOptionPreview[currentBrush].id.substr(15));
}
},
currentSizePreviewIndexes: {
get: function () {
/// <summary>
/// Gets the an object with the current size index for all the tools
/// </summary>
/// <returns>
/// Object. Keys are tool names, values are the size index for that tool
/// </returns>
var sizePreviewIndexes = {};
for (toolName in currentSizePreview) {
sizePreviewIndexes[toolName] = parseInt(currentSizePreview[toolName].id.substr(13));
}
return sizePreviewIndexes;
}
},
currentOptionPreviewIndexes: {
get: function () {
/// <summary>
/// Gets the an object with the current size index for all the tools
/// </summary>
/// <returns>
/// An object in which keys are tool names and values are the size index for that tool
/// </returns>
var optionPreviewIndexes = {};
for (toolName in currentOptionPreview) {
optionPreviewIndexes[toolName] = parseInt(currentOptionPreview[toolName].id.substr(15));
}
return optionPreviewIndexes;
}
},
changeLayout: changeLayout
});
}
});
})(Microsoft.Paint);