diff --git a/1 - Blockcode/index.html b/1 - Blockcode/index.html new file mode 100644 index 0000000..0a532ea --- /dev/null +++ b/1 - Blockcode/index.html @@ -0,0 +1,46 @@ + + + + + Ch 1. Blockcode + + + + + +
+
+

Menu

+ +
+
+

+ Script: + + + + +

+
+
+
+
+

Examples:

+
+ +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/1 - Blockcode/resources/css/base.css b/1 - Blockcode/resources/css/base.css new file mode 100644 index 0000000..2728d36 --- /dev/null +++ b/1 - Blockcode/resources/css/base.css @@ -0,0 +1,44 @@ +ul, li { + list-style: none; + margin: 0em; + padding: 0em; +} + +div { padding: 0.5em; } + +#header { max-height: 4em; } +#menu { background-color: #FFDAB9; height: -webkit-fill-available; } +#script { background-color: #B0C4DE; height: -webkit-fill-available; } +#menu > .script-block { background-color: #FF7F4F !important; } +#script > .script-block, +.script-nest > .script-block { background-color: #1E90FF !important; } +#script .script-nest { background-color: #B0C4DE !important; } + +.flex-parent { + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + gap: 2em; +} + +.flex-child { + min-height: 12em; + width: auto; +} + +.script-block, +.script-nest, +.border { + border: 0.15em solid #000000; + border-radius: 0.6em; +} + +.script-block, +.script-nest { + display: block; + margin-top: 0.5em; + margin-bottom: 0.5em; + padding: 0.5em; +} + +.script-nest { background-color: #FFDAB9; } diff --git a/1 - Blockcode/resources/js/elements.js b/1 - Blockcode/resources/js/elements.js new file mode 100644 index 0000000..6819364 --- /dev/null +++ b/1 - Blockcode/resources/js/elements.js @@ -0,0 +1,168 @@ +class BaseScriptElement extends HTMLElement { + get prefix() { return 'BaseScriptElement'; } + constructor() { super(); } + + connectedCallback() { + this.innerHTML = ` +
  • + +
  • + `; + } + + action(...args) { console.log("Hello, World!"); } +} + +class BaseInputScriptElement extends BaseScriptElement { + get prefix() { return 'BaseInputScriptElement'; } + get defaultValue() { return '1'; } + get postfix() { return ''; } + get value() { return this.getElementsByClassName("script-input")[0].value; } + constructor() { super(); } + + connectedCallback() { + this.innerHTML = ` +
  • + + + +
  • + `; + } + + action() { console.log( this.value ); } +} + +class RepeatElement extends BaseInputScriptElement { + get prefix() { return 'Repeat'; } + get defaultValue() { return '10'; } + get children() { + return this.getElementsByClassName("script-nest")[0].children; + } + + connectedCallback() { + this.innerHTML = ` +
  • + + + + +
  • + `; + } + + action(Painter) { + for (let i = 0; i < this.value; i++) { + console.log(Painter.rotation) + for (const elm of this.children) { + elm.action(Painter); + } + } + } +} + +class LeftElement extends BaseInputScriptElement { + get prefix() { return 'Left'; } + get defaultValue() { return '5'; } + get postfix() { return 'degrees'; } + constructor() { super(); } + action(Painter) { Painter.rotation -= this.value; } +} + +class RightElement extends BaseInputScriptElement { + get prefix() { return 'Right'; } + get defaultValue() { return '5'; } + get postfix() { return 'degrees'; } + constructor() { super(); } + action(Painter) { Painter.rotation += this.value; } +} + +class ForwardElement extends BaseInputScriptElement { + get prefix() { return 'Forward'; } + get defaultValue() { return '10'; } + get postfix() { return 'steps'; } + constructor() { super(); } + action(Painter) { + let magnitude = this.value + let radians = Painter.rotation * (Math.PI / 180); + const x2 = Painter.x1 + magnitude * Math.cos(radians); + const y2 = Painter.y1 + magnitude * Math.sin(radians); + Painter.x1 = x2 + Painter.y1 = y2 + + if (Painter.isPenLifted) { + Painter.canvasContext.moveTo(x2, y2); + return; + } + + Painter.canvasContext.lineTo(x2, y2); + Painter.canvasContext.stroke(); + Painter.canvasContext.moveTo(x2, y2); + } +} + +class BackElement extends BaseInputScriptElement { + get prefix() { return 'Back'; } + get defaultValue() { return '10'; } + get postfix() { return 'steps'; } + constructor() { super(); } + action(Painter) { + let magnitude = this.value + let radians = (Painter.rotation + 180) % 360; + const x2 = Painter.x1 + magnitude * Math.cos(radians); + const y2 = Painter.y1 + magnitude * Math.sin(radians); + Painter.x1 = x2 + Painter.y1 = y2 + + if (Painter.isPenLifted) { + Painter.canvasContext.moveTo(x2, y2); + return; + } + + Painter.canvasContext.lineTo(x2, y2); + Painter.canvasContext.stroke(); + Painter.canvasContext.moveTo(x2, y2); + } +} + +class CircleElement extends BaseInputScriptElement { + get prefix() { return 'Circle'; } + get defaultValue() { return '20'; } + get postfix() { return 'radius'; } + constructor() { super(); } + action(Painter) { + Painter.canvasContext.beginPath(); + Painter.canvasContext.arc(95, 50, 40, 0, 2 * Math.PI); + Painter.canvasContext.stroke(); + } +} + +class PenUpElement extends BaseScriptElement { + get prefix() { return 'Pen Up'; } + constructor() { super(); } + action(Painter) { Painter.isPenLifted = true; } +} + +class PenDownElement extends BaseScriptElement { + get prefix() { return 'Pen Down'; } + constructor() { super(); } + action(Painter) { Painter.isPenLifted = false; } +} + +class BackToCenterElement extends BaseScriptElement { + get prefix() { return 'Back to Center'; } + constructor() { super(); } + action(Painter) { + Painter.x1 = Painter.canvas.width / 2 + Painter.y1 = Painter.canvas.height / 2 + Painter.canvasContext.moveTo( Painter.x1, Painter.y1 ); + } +} + +class HideTurtleElement extends BaseScriptElement { + get prefix() { return 'Hide Turtle'; } + constructor() { super(); } +} diff --git a/1 - Blockcode/resources/js/events.js b/1 - Blockcode/resources/js/events.js new file mode 100644 index 0000000..8faecdf --- /dev/null +++ b/1 - Blockcode/resources/js/events.js @@ -0,0 +1,24 @@ +window.onload = (eve) => { + setupMenuBlocks(); + setupDragAndDrop(); + setupScriptRunner(); +} + +clearBttn.onclick = (eve) => { + console.log("Clear"); +} + +saveBttn.onclick = (eve) => { + console.log("Save"); +} + +loadBttn.onclick = (eve) => { + console.log("Load"); +} + +runBttn.onclick = (eve) => { + console.log("Run"); + runScript(); +} + + diff --git a/1 - Blockcode/resources/js/globals.js b/1 - Blockcode/resources/js/globals.js new file mode 100644 index 0000000..311114d --- /dev/null +++ b/1 - Blockcode/resources/js/globals.js @@ -0,0 +1,24 @@ +const ScriptElms = { + "repeat-element": RepeatElement, + "left-element": LeftElement, + "right-element": RightElement, + "forward-element": ForwardElement, + "back-element": BackElement, + "circle-element": CircleElement, + "pen-up-element": PenUpElement, + "pen-down-element": PenDownElement, + "back-to-center-element": BackToCenterElement, + "hider-turtle-element": HideTurtleElement +}; + +let Painter = { + canvas: null, + canvasContext: null, + rotation: 0, + x1: 0, + y1: 0, + isPenLifted: false +} + +let draggedElm = null; + diff --git a/1 - Blockcode/resources/js/script-runner.js b/1 - Blockcode/resources/js/script-runner.js new file mode 100644 index 0000000..b631f1e --- /dev/null +++ b/1 - Blockcode/resources/js/script-runner.js @@ -0,0 +1,29 @@ +const setupScriptRunner = () => { + canvasContext = canvas.getContext("2d"); + Painter.canvas = canvas; + Painter.canvasContext = canvasContext; +} + +const runScript = () => { + setToCenter(); + resetRotation(); + clearCanvas(); + + for (const elm of script.children) { + elm.action(Painter); + } +} + +const setToCenter = () => { + Painter.x1 = Painter.canvas.width / 2 + Painter.y1 = Painter.canvas.height / 2 + Painter.canvasContext.moveTo( Painter.x1, Painter.y1 ); +} + +const clearCanvas = () => { + Painter.canvasContext.clearRect(0, 0, canvas.width, canvas.height); +} + +const resetRotation = () => { + Painter.rotation = 0; +} diff --git a/1 - Blockcode/resources/js/ui.js b/1 - Blockcode/resources/js/ui.js new file mode 100644 index 0000000..aa860be --- /dev/null +++ b/1 - Blockcode/resources/js/ui.js @@ -0,0 +1,61 @@ +const setupMenuBlocks = () => { + for (const [key, value] of Object.entries(ScriptElms)) { + customElements.define(key, value); + const elm = document.createElement(key); + elm.className = "script-block"; + elm.draggable = true + elm.ondragstart = dragStartHandler + menu.append(elm); + } +} + +const setupDragAndDrop = () => { + script.ondrop = dragDropHandler + script.ondragover = dragOverHandler + header.ondrop = dragDropHandler + header.ondragover = dragOverHandler + + const flexParents = document.getElementsByClassName("flex-parent"); + for (let i = 0; i < flexParents.length; i++) { + flexParents[i].ondrop = dragDropHandler + flexParents[i].ondragover = dragOverHandler + } +} + +const dragStartHandler = (eve) => { + draggedElm = eve.target; + console.debug("Node: ", draggedElm); + eve.dataTransfer.setData("text", eve.target.tagName.toLowerCase()); +} + +const dragOverHandler = (eve) => { eve.preventDefault(); } + +const dragDropHandler = (eve) => { + eve.preventDefault(); + eve.stopPropagation(); + + const tagTarget = eve.currentTarget; + + if ( + eve.currentTarget.id.toLowerCase() === "header" || + eve.currentTarget.classList.contains("flex-parent") + ) { + if ( draggedElm.parentNode.id.toLowerCase() !== "menu" ) { + destroyScriptBlock(draggedElm, tagTarget); + } + + return; + } + + addBlockToScript(draggedElm, tagTarget); +} + +const addBlockToScript = (draggedTarget, tagTarget) => { + const elm = draggedTarget.cloneNode(true); + elm.ondragstart = dragStartHandler + tagTarget.appendChild(elm); +} + +const destroyScriptBlock = (draggedTarget, tagTarget) => { + draggedTarget.remove(); +} diff --git a/Independent/pixilate/pixilate.html b/Independent/pixilate/pixilate.html new file mode 100644 index 0000000..a3e4732 --- /dev/null +++ b/Independent/pixilate/pixilate.html @@ -0,0 +1,507 @@ + + + + + + + + + + + + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + +
    +
    +
    + + + + + +
    +
    + +
    +
    + + +
    +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    + +
    +

    Color Palette

    + +
    + +
    +
    +
    + +
    + +
    + +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/Independent/pixilate/pixilate_image.png b/Independent/pixilate/pixilate_image.png new file mode 100644 index 0000000..8c1bcbb Binary files /dev/null and b/Independent/pixilate/pixilate_image.png differ diff --git a/README.md b/README.md index a1e6432..8229303 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # 500-Lines-or-Less +[500 Lines or Less](https://aosabook.org/en/500L/introduction.html) +> 500 Lines or Less focuses on the design decisions that programmers make in the small when they are building something new. + +# Notes +This repo constitutes my efforts to try to implement the respective chapter topic before reading how that chapter author achieved theirs.