From d43cd56d65555d4b298b7941234a75d25efb89df Mon Sep 17 00:00:00 2001 From: Mal Date: Sun, 9 Feb 2020 00:29:46 +0100 Subject: [PATCH] UI for adding rows and columns. --- tilorswift/js/Terrain.js | 36 ++++++++- tilorswift/js/Tilorswift.js | 6 +- tilorswift/js/dialog/DialogAddColumns.js | 28 +++++++ tilorswift/js/dialog/DialogAddRows.js | 28 +++++++ .../TilorswiftAddColumnsClickedEvent.js | 8 ++ .../js/events/TilorswiftAddColumnsEvent.js | 10 +++ .../events/TilorswiftAddRowsClickedEvent.js | 8 ++ .../js/events/TilorswiftAddRowsEvent.js | 10 +++ tilorswift/js/events/TilorswiftEvent.js | 7 ++ .../events/TilorswiftMenuEditClickedEvent.js | 9 +++ .../TilorswiftWidgetInsertRowsClickedEvent.js | 9 +++ tilorswift/js/menu/InsertRowsWidget.js | 46 ++++++++++++ tilorswift/js/module.js | 50 +++++++++++-- tilorswift/style.css | 74 +++++++++++++++++++ 14 files changed, 317 insertions(+), 12 deletions(-) create mode 100644 tilorswift/js/dialog/DialogAddColumns.js create mode 100644 tilorswift/js/dialog/DialogAddRows.js create mode 100644 tilorswift/js/events/TilorswiftAddColumnsClickedEvent.js create mode 100644 tilorswift/js/events/TilorswiftAddColumnsEvent.js create mode 100644 tilorswift/js/events/TilorswiftAddRowsClickedEvent.js create mode 100644 tilorswift/js/events/TilorswiftAddRowsEvent.js create mode 100644 tilorswift/js/events/TilorswiftMenuEditClickedEvent.js create mode 100644 tilorswift/js/events/TilorswiftWidgetInsertRowsClickedEvent.js create mode 100644 tilorswift/js/menu/InsertRowsWidget.js diff --git a/tilorswift/js/Terrain.js b/tilorswift/js/Terrain.js index e081946..addb5da 100644 --- a/tilorswift/js/Terrain.js +++ b/tilorswift/js/Terrain.js @@ -27,7 +27,7 @@ export default class Terrain this.htmlElement.style.height = this.tileset.getTileHeight() * this.tilesY + 'px'; for (let r = 0; r < this.tilesY; r++) { - this.insertRow(); + this._insertRow(); } window.addEventListener( @@ -48,15 +48,17 @@ export default class Terrain return this.tileset; } - addRows(quantity, index) + addRows(index, quantity = 1) { for (let q = 0; q < quantity; q++) { - this.insertRow(index); + this._insertRow(index); this.tilesY++; } + + this.htmlElement.style.height = this.tileset.getTileHeight() * this.tilesY + 'px'; } - insertRow(index = undefined) + _insertRow(index = undefined) { let row = []; let tr = document.createElement('tr'); @@ -77,6 +79,32 @@ export default class Terrain } } + addColumns(index, quantity = 1) + { + for (let c = 0; c < quantity; c++) { + this._insertColumn(index); + this.tilesX++; + } + + this.htmlElement.style.width = this.tileset.getTileWidth() * this.tilesX + 'px'; + } + + _insertColumn(index = undefined) + { + if (index === undefined || index > this.tilesX - 1) { + index = this.tilesX; + } + + for (let y = 0; y < this.tilesY; y++) { + let field = new Field(this.tileset); + this.fields[y] = this.fields[y].slice(0, index).concat(field).concat(this.fields[y].slice(index)); + + let htmlRow = this.htmlElement.childNodes[y]; + htmlRow.insertBefore(field.getElement(), htmlRow.childNodes[index]); + + } + } + setFieldIndex(x, y, index) { this.fields[y][x].setIndex(index); diff --git a/tilorswift/js/Tilorswift.js b/tilorswift/js/Tilorswift.js index 4310722..dc404e6 100644 --- a/tilorswift/js/Tilorswift.js +++ b/tilorswift/js/Tilorswift.js @@ -33,13 +33,13 @@ export default class Tilorswift { if (!terrain.hasEntrancePoint()) { alert('Es muss ein Startpunkt definiert sein!'); - return; + return false; } let filename = prompt('Dateiname', 'terrain.json'); if (filename === null) { - return; + return false; } let json = Tilorswift.getTerrainAsJson(terrain); @@ -49,5 +49,7 @@ export default class Tilorswift download.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(json)); download.click(); download.remove(); + + return true; } } \ No newline at end of file diff --git a/tilorswift/js/dialog/DialogAddColumns.js b/tilorswift/js/dialog/DialogAddColumns.js new file mode 100644 index 0000000..020b995 --- /dev/null +++ b/tilorswift/js/dialog/DialogAddColumns.js @@ -0,0 +1,28 @@ +import Dialog from "./Dialog.js"; +import TilorswiftAddColumnsEvent from "../events/TilorswiftAddColumnsEvent.js"; + +export default class DialogAddColumns extends Dialog +{ + constructor() { + super(); + this.inputPosition = this.createInputNumber('Einfügen vor Spalte'); + this.inputColumns = this.createInputNumber('Anzahl Spalten'); + this.buttonOk = this.createButton('OK'); + this.buttonOk.addEventListener( + 'click', + () => { + window.dispatchEvent(new TilorswiftAddColumnsEvent(this.getPosition(), this.getColumnCount())); + } + ) + } + + getPosition() + { + return this.inputPosition.value; + } + + getColumnCount() + { + return this.inputColumns.value; + } +} \ No newline at end of file diff --git a/tilorswift/js/dialog/DialogAddRows.js b/tilorswift/js/dialog/DialogAddRows.js new file mode 100644 index 0000000..853069b --- /dev/null +++ b/tilorswift/js/dialog/DialogAddRows.js @@ -0,0 +1,28 @@ +import Dialog from "./Dialog.js"; +import TilorswiftAddRowsEvent from "../events/TilorswiftAddRowsEvent.js"; + +export default class DialogAddRows extends Dialog +{ + constructor() { + super(); + this.inputPosition = this.createInputNumber('Einfügen vor Zeile'); + this.inputRows = this.createInputNumber('Anzahl Zeilen'); + this.buttonOk = this.createButton('OK'); + this.buttonOk.addEventListener( + 'click', + () => { + window.dispatchEvent(new TilorswiftAddRowsEvent(this.getPosition(), this.getRowsCount())); + } + ) + } + + getPosition() + { + return this.inputPosition.value; + } + + getRowsCount() + { + return this.inputRows.value; + } +} \ No newline at end of file diff --git a/tilorswift/js/events/TilorswiftAddColumnsClickedEvent.js b/tilorswift/js/events/TilorswiftAddColumnsClickedEvent.js new file mode 100644 index 0000000..26e8a4e --- /dev/null +++ b/tilorswift/js/events/TilorswiftAddColumnsClickedEvent.js @@ -0,0 +1,8 @@ +import TilorswiftEvent from "./TilorswiftEvent.js"; + +export default class TilorswiftAddColumnsClickedEvent extends Event +{ + constructor() { + super(TilorswiftEvent.ADD_COLUMNS_CLICKED); + } +} \ No newline at end of file diff --git a/tilorswift/js/events/TilorswiftAddColumnsEvent.js b/tilorswift/js/events/TilorswiftAddColumnsEvent.js new file mode 100644 index 0000000..bf816ab --- /dev/null +++ b/tilorswift/js/events/TilorswiftAddColumnsEvent.js @@ -0,0 +1,10 @@ +import TilorswiftEvent from "./TilorswiftEvent.js"; + +export default class TilorswiftAddColumnsEvent extends Event +{ + constructor(beforeColumn, columnCount) { + super(TilorswiftEvent.ADD_COLUMNS); + this.beforeColumn = beforeColumn; + this.columnCount = columnCount; + } +} \ No newline at end of file diff --git a/tilorswift/js/events/TilorswiftAddRowsClickedEvent.js b/tilorswift/js/events/TilorswiftAddRowsClickedEvent.js new file mode 100644 index 0000000..b941ab2 --- /dev/null +++ b/tilorswift/js/events/TilorswiftAddRowsClickedEvent.js @@ -0,0 +1,8 @@ +import TilorswiftEvent from "./TilorswiftEvent.js"; + +export default class TilorswiftAddRowsClickedEvent extends Event +{ + constructor() { + super(TilorswiftEvent.ADD_ROWS_CLICKED); + } +} \ No newline at end of file diff --git a/tilorswift/js/events/TilorswiftAddRowsEvent.js b/tilorswift/js/events/TilorswiftAddRowsEvent.js new file mode 100644 index 0000000..d7edbfa --- /dev/null +++ b/tilorswift/js/events/TilorswiftAddRowsEvent.js @@ -0,0 +1,10 @@ +import TilorswiftEvent from "./TilorswiftEvent.js"; + +export default class TilorswiftAddRowsEvent extends Event +{ + constructor(beforeRow, rowCount) { + super(TilorswiftEvent.ADD_ROWS); + this.beforeRow = beforeRow; + this.rowCount = rowCount; + } +} \ No newline at end of file diff --git a/tilorswift/js/events/TilorswiftEvent.js b/tilorswift/js/events/TilorswiftEvent.js index e48f1c0..aaec7e0 100644 --- a/tilorswift/js/events/TilorswiftEvent.js +++ b/tilorswift/js/events/TilorswiftEvent.js @@ -3,7 +3,14 @@ const TilorswiftEvent = { FIELD_ENTERED: 'fieldEntered', BUTTON_TILE_CLICKED: 'buttonTileClicked', MENU_SAVE_CLICKED: 'menuSaveClicked', + DIALOG_BUTTON_OK_CLICKED: 'dialogButtonOkClicked', + MENU_EDIT_CLICKED: 'menuEditClicked', SAVED: 'saved', + WIDGET_INSERT_ROWS_CLICKED: 'widgetInsertRowsClicked', + ADD_ROWS: 'addRows', + ADD_ROWS_CLICKED: 'addRowsClicked', + ADD_COLUMNS: 'addColumns', + ADD_COLUMNS_CLICKED: 'addColumnsClicked', }; export default TilorswiftEvent; \ No newline at end of file diff --git a/tilorswift/js/events/TilorswiftMenuEditClickedEvent.js b/tilorswift/js/events/TilorswiftMenuEditClickedEvent.js new file mode 100644 index 0000000..36f7df9 --- /dev/null +++ b/tilorswift/js/events/TilorswiftMenuEditClickedEvent.js @@ -0,0 +1,9 @@ +import TilorswiftEvent from "./TilorswiftEvent.js"; + +export default class TilorswiftMenuEditClickedEvent extends Event +{ + constructor() + { + super(TilorswiftEvent.MENU_EDIT_CLICKED); + } +} \ No newline at end of file diff --git a/tilorswift/js/events/TilorswiftWidgetInsertRowsClickedEvent.js b/tilorswift/js/events/TilorswiftWidgetInsertRowsClickedEvent.js new file mode 100644 index 0000000..8d97199 --- /dev/null +++ b/tilorswift/js/events/TilorswiftWidgetInsertRowsClickedEvent.js @@ -0,0 +1,9 @@ +import TilorswiftEvent from "./TilorswiftEvent.js"; + +export default class TilorswiftWidgetInsertRowsClickedEvent extends Event +{ + constructor() + { + super(TilorswiftEvent.WIDGET_INSERT_ROWS_CLICKED); + } +} \ No newline at end of file diff --git a/tilorswift/js/menu/InsertRowsWidget.js b/tilorswift/js/menu/InsertRowsWidget.js new file mode 100644 index 0000000..544c324 --- /dev/null +++ b/tilorswift/js/menu/InsertRowsWidget.js @@ -0,0 +1,46 @@ +import Widget from "./Widget.js"; +import BrushMode from "../BrushMode.js"; + +export default class InsertRowsWidget extends Widget +{ + constructor(widgetBar, brush) + { + super('+Zeile'); + this.elementRowsInput = document.createElement('input'); + this.elementButton = document.createElement('img'); + this.htmlElement = this.createElement(); + this.widgetBar = widgetBar; + this.brush = brush; + + this.elementButton.addEventListener( + 'click', + () => { + this.widgetBar.disableWidgets(); + this.enable(); + this.brush.mode = BrushMode.ADD_ROWS; + } + ); + } + + createElement() + { + let htmlElement = document.createElement('div'); + htmlElement.id = 'widget-insert-rows'; + + this.elementButton.src = 'graphics/button-add-row.svg'; + this.elementButton.id = 'widget-insert-rows-button'; + htmlElement.appendChild(this.elementButton); + + this.elementRowsInput.type = 'number'; + this.elementRowsInput.id = 'widget-insert-rows-input'; + this.elementRowsInput.value = 1; + htmlElement.appendChild(this.elementRowsInput); + + return htmlElement; + } + + getElement() + { + return this.htmlElement; + } +} \ No newline at end of file diff --git a/tilorswift/js/module.js b/tilorswift/js/module.js index ee87c88..d9afd7e 100644 --- a/tilorswift/js/module.js +++ b/tilorswift/js/module.js @@ -14,6 +14,10 @@ import WidgetBar from "./menu/WidgetBar.js"; import EntrancePointWidget from "./menu/EntrancePointWidget.js"; import Brush from "./Brush.js"; import BrushMode from "./BrushMode.js"; +import DialogAddRows from "./dialog/DialogAddRows.js"; +import DialogAddColumns from "./dialog/DialogAddColumns.js"; +import TilorswiftAddRowsClickedEvent from "./events/TilorswiftAddRowsClickedEvent.js"; +import TilorswiftAddColumnsClickedEvent from "./events/TilorswiftAddColumnsClickedEvent.js"; let loader = new FileLoader('../levels/level.json'); let image = new Image(); @@ -24,10 +28,10 @@ image.onload = function () { let map = document.getElementById('map'); map.appendChild(terrain.getElement()); + terrain.addColumns(200, 1); + let brush = new Brush(); - let tileset = new Tileset(image, 8, 3); - let widgetBar = new WidgetBar('widget-bar'); let tilesetPicker = new TilesetPickerWidget(tileset, brush); @@ -35,10 +39,10 @@ image.onload = function () { let entrancePicker = new EntrancePointWidget(widgetBar, brush); widgetBar.addWidget(entrancePicker); + document.body.appendChild(widgetBar.getElement()); let mouse = new Mouse(); - let mainbar = new MainMenu('mainbar'); let menuFile = new MenuGroup('Datei'); @@ -48,6 +52,11 @@ image.onload = function () { mainbar.addMenuGroup(menuFile); + let menuEdit = new MenuGroup('Bearbeiten'); + menuEdit.addMenuEntry(new MainMenuEntry('Zeilen einfügen...', TilorswiftAddRowsClickedEvent)); + menuEdit.addMenuEntry(new MainMenuEntry('Spalten einfügen...', TilorswiftAddColumnsClickedEvent)); + mainbar.addMenuGroup(menuEdit); + document.body.appendChild(mainbar.getElement()); window.addEventListener( @@ -91,7 +100,35 @@ image.onload = function () { } ); - /* Prevent Firefox's default drag and drop for images */ + window.addEventListener( + TilorswiftEvent.ADD_ROWS_CLICKED, + () => { + new DialogAddRows(); + } + ); + + window.addEventListener( + TilorswiftEvent.ADD_COLUMNS_CLICKED, + () => { + new DialogAddColumns(); + } + ); + + window.addEventListener( + TilorswiftEvent.ADD_ROWS, + function (event) { + terrain.addRows(event.beforeRow, event.rowCount); + } + ); + + window.addEventListener( + TilorswiftEvent.ADD_COLUMNS, + function (event) { + terrain.addColumns(event.beforeColumn, event.columnCount); + } + ); + + /* Prevents Firefox's annoying default drag and drop behavior for images */ document.addEventListener( 'dragstart', function (event) { @@ -102,8 +139,9 @@ image.onload = function () { window.addEventListener( TilorswiftEvent.MENU_SAVE_CLICKED, function () { - Tilorswift.saveTerrainToFile(terrain); - window.dispatchEvent(new TilorswiftSavedEvent()); + if (Tilorswift.saveTerrainToFile(terrain)) { + window.dispatchEvent(new TilorswiftSavedEvent()); + } } ); }; diff --git a/tilorswift/style.css b/tilorswift/style.css index 770fb99..fee7c25 100644 --- a/tilorswift/style.css +++ b/tilorswift/style.css @@ -131,6 +131,26 @@ body { cursor: pointer; } +#widget-insert-rows { + position: relative; + width: 96px; + height: 96px; + border: 1px solid black; +} + +#widget-insert-rows-button { + width: 100%; + cursor: pointer; +} + +#widget-insert-rows-input { + position: absolute; + width: 80%; + bottom: 0; + left: 0; + right: 0; +} + .field, .button-tile { border: 0; padding: 0; @@ -159,6 +179,60 @@ body { opacity: 0.5; } +.dialog { + display: flex; + justify-content: center; + align-items: center; + background-color: rgba(0, 0, 0, 0.25); + position: fixed; + left: 0; + top: 0; + right: 0; + bottom: 0; + z-index: 200; +} + +.dialog-box { + width: 500px; + background-color: #cccccc; + color: black; + padding: 20px; + box-shadow: 0 0 20px black; +} + +.dialog-message { + text-align: center; + color: black; + margin-bottom: 20px; +} + +.dialog-button-area { + display: flex; + justify-content: space-evenly; + width: 100%; +} + +.dialog-label { + width: 100%; +} + +.dialog-input-area { + width: 100%; +} + +.dialog-input { + width: 100%; + margin-bottom: 20px; +} + +.dialog-button { + padding: 5px 20px; + background-color: grey; + font-weight: bold; + color: white; + cursor: pointer; +} + /* tr:hover > td > .selection { opacity: 0.5;