Add settings for theme, grid, and checkerboard
parent
d2b90298cd
commit
ac6964eeab
|
@ -9,7 +9,7 @@
|
||||||
import { LoadedFile, PixelsPlaceUndoable, SelectionClearUndoable, SelectionSetUndoable } from './types/file'
|
import { LoadedFile, PixelsPlaceUndoable, SelectionClearUndoable, SelectionSetUndoable } from './types/file'
|
||||||
|
|
||||||
import "carbon-components-svelte/css/all.css"
|
import "carbon-components-svelte/css/all.css"
|
||||||
import { Tabs, Tab, TabContent, Theme, Button, Modal, Truncate, ButtonSet, NumberInput, Dropdown } from "carbon-components-svelte"
|
import { Tabs, Tab, TabContent, Theme, Button, Modal, Truncate, ButtonSet, NumberInput, Dropdown, Checkbox, TextInput } from "carbon-components-svelte"
|
||||||
import { ComposedModal } from "carbon-components-svelte"
|
import { ComposedModal } from "carbon-components-svelte"
|
||||||
|
|
||||||
import { OverflowMenu, OverflowMenuItem } from "carbon-components-svelte"
|
import { OverflowMenu, OverflowMenuItem } from "carbon-components-svelte"
|
||||||
|
@ -25,6 +25,9 @@
|
||||||
import type { PixelPosition } from './types/shapes.js';
|
import type { PixelPosition } from './types/shapes.js';
|
||||||
import ColorSelector from './components/ColorSelector.svelte';
|
import ColorSelector from './components/ColorSelector.svelte';
|
||||||
import ColorIndex from './components/ColorIndex.svelte';
|
import ColorIndex from './components/ColorIndex.svelte';
|
||||||
|
import CheckerboardSettingsModal from './components/CheckerboardSettingsModal.svelte';
|
||||||
|
import GridSettingsModal from './components/GridSettingsModal.svelte';
|
||||||
|
import ThemeSettingsModal from './components/ThemeSettingsModal.svelte';
|
||||||
|
|
||||||
let theme: 'white'|'g10'|'g80'|'g90'|'g100' = 'g90'
|
let theme: 'white'|'g10'|'g80'|'g90'|'g100' = 'g90'
|
||||||
|
|
||||||
|
@ -82,6 +85,21 @@
|
||||||
let importCanvas: Canvas = null
|
let importCanvas: Canvas = null
|
||||||
|
|
||||||
let showPreview: boolean = false
|
let showPreview: boolean = false
|
||||||
|
let showGridSettings: boolean = false
|
||||||
|
let showCheckerboardSettings: boolean = false
|
||||||
|
let showThemeSettings: boolean = false
|
||||||
|
|
||||||
|
let showGrid: boolean = true
|
||||||
|
let showCheckerboard: boolean = true
|
||||||
|
|
||||||
|
let gridMajorSize: number = 16
|
||||||
|
let gridMinorSize: number = 8
|
||||||
|
let gridMajorColor: string = '#0000ff'
|
||||||
|
let gridMinorColor: string = '#006666'
|
||||||
|
|
||||||
|
let checkerboardSize: number = 8
|
||||||
|
let checkerboardColor1: string = '#888888'
|
||||||
|
let checkerboardColor2: string = '#444444'
|
||||||
|
|
||||||
let toolSelection = new SelectionTool()
|
let toolSelection = new SelectionTool()
|
||||||
let toolMagicWand = new MagicWandTool()
|
let toolMagicWand = new MagicWandTool()
|
||||||
|
@ -199,6 +217,18 @@
|
||||||
Redo <Redo/>
|
Redo <Redo/>
|
||||||
</OverflowMenuItem>
|
</OverflowMenuItem>
|
||||||
</OverflowMenu>
|
</OverflowMenu>
|
||||||
|
<OverflowMenu size="sm">
|
||||||
|
<div slot="menu">View</div>
|
||||||
|
<OverflowMenuItem>
|
||||||
|
<Checkbox on:click={(e)=>e.stopPropagation()} bind:checked={showGrid} labelText="Grid" />
|
||||||
|
</OverflowMenuItem>
|
||||||
|
<OverflowMenuItem text="Change Grid..." on:click={()=>showGridSettings = true} />
|
||||||
|
<OverflowMenuItem hasDivider>
|
||||||
|
<Checkbox on:click={(e)=>e.stopPropagation()} bind:checked={showCheckerboard} labelText="Checkerboard" />
|
||||||
|
</OverflowMenuItem>
|
||||||
|
<OverflowMenuItem text="Change Checkerboard..." on:click={()=>showCheckerboardSettings = true} />
|
||||||
|
<OverflowMenuItem hasDivider text="Theme..." on:click={()=>showThemeSettings = true} />
|
||||||
|
</OverflowMenu>
|
||||||
<OverflowMenu size="sm">
|
<OverflowMenu size="sm">
|
||||||
<div slot="menu">Windows</div>
|
<div slot="menu">Windows</div>
|
||||||
<OverflowMenuItem text="Preview" on:click={() => showPreview = true}/>
|
<OverflowMenuItem text="Preview" on:click={() => showPreview = true}/>
|
||||||
|
@ -277,7 +307,7 @@
|
||||||
<Shortcut global cmd={'swapFile'+index} keys={['F'+(index+1)]} on:trigger={()=>selectFile(file, index)} />
|
<Shortcut global cmd={'swapFile'+index} keys={['F'+(index+1)]} on:trigger={()=>selectFile(file, index)} />
|
||||||
</Shortcuts>
|
</Shortcuts>
|
||||||
<TabContent>
|
<TabContent>
|
||||||
<Editor2D bind:file={file} refresh={refresh} bind:primaryColorIndex={primaryColorIndex} bind:secondaryColorIndex={secondaryColorIndex} bind:currentTool={currentTool} brushSize={brushSize} brushType={brushType} />
|
<Editor2D bind:file={file} refresh={refresh} bind:primaryColorIndex={primaryColorIndex} bind:secondaryColorIndex={secondaryColorIndex} bind:currentTool={currentTool} brushSize={brushSize} brushType={brushType} showCheckerboard={showCheckerboard} checkerboardSize={checkerboardSize} checkerboardColor1={checkerboardColor1} checkerboardColor2={checkerboardColor2} />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
{/each}
|
{/each}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
@ -292,7 +322,17 @@
|
||||||
<StackPreview files={files} />
|
<StackPreview files={files} />
|
||||||
</FloatingPanel>
|
</FloatingPanel>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if showGridSettings}
|
||||||
|
<GridSettingsModal bind:open={showGridSettings} bind:majorSize={gridMajorSize} bind:minorSize={gridMinorSize} bind:majorColor={gridMajorColor} bind:minorColor={gridMinorColor} />
|
||||||
|
{/if}
|
||||||
|
{#if showCheckerboardSettings}
|
||||||
|
<CheckerboardSettingsModal bind:open={showCheckerboardSettings} bind:size={checkerboardSize} bind:color1={checkerboardColor1} bind:color2={checkerboardColor2} />
|
||||||
|
{/if}
|
||||||
|
{#if showThemeSettings}
|
||||||
|
<ThemeSettingsModal bind:open={showThemeSettings} bind:theme={theme} />
|
||||||
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
<ComposedModal bind:open={showImport} size="sm" preventCloseOnClickOutside on:click:button--primary={engageImport}>
|
<ComposedModal bind:open={showImport} size="sm" preventCloseOnClickOutside on:click:button--primary={engageImport}>
|
||||||
<Importer
|
<Importer
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<script lang='ts'>
|
||||||
|
import { Column, Grid, Modal, NumberInput, Row, TextInput } from "carbon-components-svelte";
|
||||||
|
|
||||||
|
export let size: number = 8
|
||||||
|
export let color1: string = "#888888"
|
||||||
|
export let color2: string = "#444444"
|
||||||
|
|
||||||
|
let pendingSize: number = size
|
||||||
|
let pendingColor1: string = color1
|
||||||
|
let pendingColor2: string = color2
|
||||||
|
|
||||||
|
$: {
|
||||||
|
pendingSize = size
|
||||||
|
pendingColor1 = color1
|
||||||
|
pendingColor2 = color2
|
||||||
|
}
|
||||||
|
|
||||||
|
let changed: boolean = false
|
||||||
|
$: {
|
||||||
|
changed = size !== pendingSize || color1 !== pendingColor1 || color2 !== pendingColor2
|
||||||
|
}
|
||||||
|
|
||||||
|
export let open: boolean = false
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
preventCloseOnClickOutside
|
||||||
|
bind:open
|
||||||
|
modalHeading="Checkerboard Settings"
|
||||||
|
primaryButtonText="Apply"
|
||||||
|
secondaryButtonText="Cancel"
|
||||||
|
on:close={() => open = false}
|
||||||
|
on:click:button--secondary={() => open = false}
|
||||||
|
on:submit={() => {
|
||||||
|
size = pendingSize
|
||||||
|
color1 = pendingColor1
|
||||||
|
color2 = pendingColor2
|
||||||
|
open = false
|
||||||
|
}}
|
||||||
|
primaryButtonDisabled={!changed}
|
||||||
|
>
|
||||||
|
<Grid narrow condensed fullWidth>
|
||||||
|
<Column>
|
||||||
|
<Row>
|
||||||
|
<NumberInput id="size" label="Size" min={1} max={512} step={1} bind:value={pendingSize}/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<TextInput id="color1" labelText="Color 1" bind:value={pendingColor1}/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<TextInput id="color2" labelText="Color 2" bind:value={pendingColor2}/>
|
||||||
|
</Row>
|
||||||
|
</Column>
|
||||||
|
</Grid>
|
||||||
|
</Modal>
|
|
@ -0,0 +1,62 @@
|
||||||
|
<script lang='ts'>
|
||||||
|
import { Column, Grid, Modal, NumberInput, Row, TextInput } from "carbon-components-svelte";
|
||||||
|
|
||||||
|
export let majorSize: number = 16
|
||||||
|
export let minorSize: number = 8
|
||||||
|
export let majorColor: string = "#0000ff"
|
||||||
|
export let minorColor: string = "#006666"
|
||||||
|
|
||||||
|
let pendingMajorSize: number = majorSize
|
||||||
|
let pendingMinorSize: number = minorSize
|
||||||
|
let pendingMajorColor: string = majorColor
|
||||||
|
let pendingMinorColor: string = minorColor
|
||||||
|
|
||||||
|
$: {
|
||||||
|
pendingMajorSize = majorSize
|
||||||
|
pendingMinorSize = minorSize
|
||||||
|
pendingMajorColor = majorColor
|
||||||
|
pendingMinorColor = minorColor
|
||||||
|
}
|
||||||
|
|
||||||
|
let changed: boolean = false
|
||||||
|
$: {
|
||||||
|
changed = majorSize !== pendingMajorSize || minorSize !== pendingMinorSize || majorColor !== pendingMajorColor || minorColor !== pendingMinorColor
|
||||||
|
}
|
||||||
|
|
||||||
|
export let open: boolean = false
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
preventCloseOnClickOutside
|
||||||
|
bind:open
|
||||||
|
modalHeading="Grid Settings"
|
||||||
|
primaryButtonText="Apply"
|
||||||
|
secondaryButtonText="Cancel"
|
||||||
|
on:close={() => open = false}
|
||||||
|
on:click:button--secondary={() => open = false}
|
||||||
|
on:submit={() => {
|
||||||
|
majorSize = pendingMajorSize
|
||||||
|
minorSize = pendingMinorSize
|
||||||
|
majorColor = pendingMajorColor
|
||||||
|
minorColor = pendingMinorColor
|
||||||
|
open = false
|
||||||
|
}}
|
||||||
|
primaryButtonDisabled={!changed}
|
||||||
|
>
|
||||||
|
<Grid narrow condensed fullWidth>
|
||||||
|
<Column>
|
||||||
|
<Row>
|
||||||
|
<NumberInput id="size" label="Major Size" min={1} max={512} step={1} bind:value={pendingMajorSize}/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<TextInput id="color1" labelText="Major Color" bind:value={pendingMajorColor}/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<NumberInput id="size" label="Minor Size" min={1} max={512} step={1} bind:value={pendingMinorSize}/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<TextInput id="color2" labelText="Minor Color" bind:value={pendingMinorColor}/>
|
||||||
|
</Row>
|
||||||
|
</Column>
|
||||||
|
</Grid>
|
||||||
|
</Modal>
|
|
@ -0,0 +1,55 @@
|
||||||
|
<script lang='ts'>
|
||||||
|
import { Column, Dropdown, Grid, Modal, NumberInput, Row, TextInput } from "carbon-components-svelte";
|
||||||
|
|
||||||
|
export let theme: 'white'|'g10'|'g80'|'g90'|'g100' = "g90"
|
||||||
|
|
||||||
|
let pendingId: 'white'|'g10'|'g80'|'g90'|'g100' = theme
|
||||||
|
|
||||||
|
$: {
|
||||||
|
pendingId = theme
|
||||||
|
}
|
||||||
|
|
||||||
|
let changed: boolean = false
|
||||||
|
$: {
|
||||||
|
changed = theme !== pendingId
|
||||||
|
}
|
||||||
|
|
||||||
|
export let open: boolean = false
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
hasScrollingContent
|
||||||
|
preventCloseOnClickOutside
|
||||||
|
bind:open
|
||||||
|
modalHeading="Theme Settings"
|
||||||
|
primaryButtonText="Apply"
|
||||||
|
secondaryButtonText="Cancel"
|
||||||
|
on:close={() => open = false}
|
||||||
|
on:click:button--secondary={() => open = false}
|
||||||
|
on:submit={() => {
|
||||||
|
theme = pendingId
|
||||||
|
open = false
|
||||||
|
}}
|
||||||
|
primaryButtonDisabled={!changed}
|
||||||
|
>
|
||||||
|
<Dropdown
|
||||||
|
size="sm"
|
||||||
|
label="Theme"
|
||||||
|
bind:selectedId={pendingId}
|
||||||
|
items={[
|
||||||
|
{id: 'white', text: 'White'},
|
||||||
|
{id: 'g10', text: 'Gray 10'},
|
||||||
|
{id: 'g80', text: 'Gray 80'},
|
||||||
|
{id: 'g90', text: 'Gray 90 (default)'},
|
||||||
|
{id: 'g100', text: 'Gray 100'},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<div class='kludge'></div>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div.kludge {
|
||||||
|
min-height: 50vh;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -14,7 +14,14 @@
|
||||||
export let layer: data.Layer
|
export let layer: data.Layer
|
||||||
export let refresh: {}
|
export let refresh: {}
|
||||||
|
|
||||||
|
export let showCheckerboard: boolean = true
|
||||||
export let checkerboardSize: number = 8
|
export let checkerboardSize: number = 8
|
||||||
|
export let checkerboardColor1: string = '#888888'
|
||||||
|
export let checkerboardColor2: string = '#444444'
|
||||||
|
|
||||||
|
$: ((...args) => {
|
||||||
|
canvasDirty = true
|
||||||
|
})(showCheckerboard, checkerboardSize, checkerboardColor1, checkerboardColor2)
|
||||||
|
|
||||||
let offsetX: number
|
let offsetX: number
|
||||||
let offsetY: number
|
let offsetY: number
|
||||||
|
@ -174,16 +181,16 @@
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.imageSmoothingEnabled = false
|
ctx.imageSmoothingEnabled = false
|
||||||
ctx.scale(zoom, zoom)
|
ctx.scale(zoom, zoom)
|
||||||
{
|
if (showCheckerboard) {
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
ctx.fillStyle = '#888888'
|
ctx.fillStyle = checkerboardColor1
|
||||||
ctx.rect(offsetX, offsetY, file.canvas.width, file.canvas.height)
|
ctx.rect(offsetX, offsetY, file.canvas.width, file.canvas.height)
|
||||||
ctx.fill()
|
ctx.fill()
|
||||||
|
|
||||||
let rows = file.canvas.height / checkerboardSize
|
let rows = file.canvas.height / checkerboardSize
|
||||||
let cols = file.canvas.width / checkerboardSize
|
let cols = file.canvas.width / checkerboardSize
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
ctx.fillStyle = '#444444'
|
ctx.fillStyle = checkerboardColor2
|
||||||
for (let r = 0; r < rows; r++) {
|
for (let r = 0; r < rows; r++) {
|
||||||
for (let c = 0; c < cols; c++) {
|
for (let c = 0; c < cols; c++) {
|
||||||
if (r % 2 === 0 && c % 2 === 1 || r % 2 === 1 && c % 2 === 0) {
|
if (r % 2 === 0 && c % 2 === 1 || r % 2 === 1 && c % 2 === 0) {
|
||||||
|
|
Loading…
Reference in New Issue