Skip to content

Commit

Permalink
Updated nonogram solver UI layout and styling
Browse files Browse the repository at this point in the history
  • Loading branch information
askrepps committed Aug 9, 2022
1 parent f887b76 commit 1604130
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 82 deletions.
173 changes: 95 additions & 78 deletions nonograms-web/src/jsMain/kotlin/com/askrepps/nonogram/WebMain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ import kotlinx.html.DIV
import kotlinx.html.InputType
import kotlinx.html.a
import kotlinx.html.br
import kotlinx.html.classes
import kotlinx.html.div
import kotlinx.html.dom.append
import kotlinx.html.img
import kotlinx.html.input
import kotlinx.html.js.div
import kotlinx.html.js.onClickFunction
import kotlinx.html.js.onInputFunction
import kotlinx.html.p
import kotlinx.html.style
import kotlinx.html.sub
import kotlinx.html.table
import kotlinx.html.td
Expand Down Expand Up @@ -121,96 +122,115 @@ private fun renderSolverPage(
solution: PuzzleSolution? = null,
error: Exception? = null
): Unit = renderPage {
p {
+"Number of rows:"
}
input {
type = InputType.text
value = rowsInput
onInputFunction = {
rowsInput = it.inputValue
div {
classes = setOf("nonogram-puzzle-input-group")
div {
classes = setOf("nonogram-puzzle-input-item")
p {
classes = setOf("nonogram-puzzle-input-label")
+"Number of rows:"
}
input {
type = InputType.text
value = rowsInput
onInputFunction = {
rowsInput = it.inputValue
}
}
}
}
br
p {
+"Number of columns:"
}
input {
type = InputType.text
value = columnsInput
onInputFunction = {
columnsInput = it.inputValue
div {
classes = setOf("nonogram-puzzle-input-item")
p {
classes = setOf("nonogram-puzzle-input-label")
+"Number of columns:"
}
input {
type = InputType.text
value = columnsInput
onInputFunction = {
columnsInput = it.inputValue
}
}
}
}
br
p {
+"Row hints (1 row of space-separated hints per line)"
+"Enter one row or column of space-separated hints per line"
}
textArea(rows = "10", cols = "10") {
+rowHintsInput
onInputFunction = {
rowHintsInput = it.inputValue
div {
classes = setOf("nonogram-puzzle-input-group")
div {
classes = setOf("nonogram-puzzle-input-item")
p {
classes = setOf("nonogram-puzzle-input-label")
+"Row hints"
}
textArea(rows = "10", cols = "10") {
+rowHintsInput
onInputFunction = {
rowHintsInput = it.inputValue
}
}
}
}
br
p {
+"Column hints (1 column of space-separated hints per line)"
}
textArea(rows = "10", cols = "10") {
+columnHintsInput
onInputFunction = {
columnHintsInput = it.inputValue
div {
classes = setOf("nonogram-puzzle-input-item")
p {
classes = setOf("nonogram-puzzle-input-label")
+"Column hints"
}
textArea(rows = "10", cols = "10") {
+columnHintsInput
onInputFunction = {
columnHintsInput = it.inputValue
}
}
}
}
br
br
input {
type = InputType.button
value = "Solve"
style = "margin-right: 10px"
onClickFunction = {
solveEnteredPuzzle()
div {
classes = setOf("nonogram-action-button-group")
input {
classes = setOf("nonogram-action-button")
type = InputType.button
value = "Solve"
onClickFunction = {
solveEnteredPuzzle()
}
}
}
input {
type = InputType.button
value = "Clear"
style = "margin-right: 10px"
onClickFunction = {
rowsInput = ""
columnsInput = ""
rowHintsInput = ""
columnHintsInput = ""
renderSolverPage()
input {
classes = setOf("nonogram-action-button")
type = InputType.button
value = "Clear"
onClickFunction = {
rowsInput = ""
columnsInput = ""
rowHintsInput = ""
columnHintsInput = ""
renderSolverPage()
}
}
}
input {
type = InputType.button
value = "Example"
style = "margin-right: 10px"
onClickFunction = {
rowsInput = EXAMPLE_ROWS_INPUT
columnsInput = EXAMPLE_COLUMNS_INPUT
rowHintsInput = EXAMPLE_ROW_HINTS_INPUT
columnHintsInput = EXAMPLE_COLUMN_HINTS_INPUT
renderSolverPage()
input {
classes = setOf("nonogram-action-button")
type = InputType.button
value = "Example"
onClickFunction = {
rowsInput = EXAMPLE_ROWS_INPUT
columnsInput = EXAMPLE_COLUMNS_INPUT
rowHintsInput = EXAMPLE_ROW_HINTS_INPUT
columnHintsInput = EXAMPLE_COLUMN_HINTS_INPUT
renderSolverPage()
}
}
}
if (puzzleDefinition != null) {
br
br
addResultsTable(puzzleDefinition, solution)
}
if (error != null) {
br
br
p {
style = "color: red;"
classes = setOf("nonogram-error-message")
+(error.message ?: "Unknown error occurred")
}
}
br
br
addFooter()
}

Expand Down Expand Up @@ -251,21 +271,19 @@ private fun solveEnteredPuzzle() {
}
}

private const val HINT_CELL_STYLE = "text-align: center; vertical-align: middle; min-width: 21px; min-height: 21px;"

private fun DIV.addResultsTable(puzzleDefinition: PuzzleDefinition, solution: PuzzleSolution?) {
val state = solution?.state ?: PuzzleState(puzzleDefinition.rows, puzzleDefinition.columns)
val hintTableRows = puzzleDefinition.columnHints.maxByOrNull { it.size }?.size ?: 0
val hintTableColumns = puzzleDefinition.rowHints.maxByOrNull { it.size }?.size ?: 0
val totalTableColumns = state.columns + hintTableColumns

table {
style = "border-collapse: collapse;"
classes = setOf("nonogram-solution-table")
for (hintRow in 0 until hintTableRows) {
tr {
for (column in 0 until totalTableColumns) {
td {
style = HINT_CELL_STYLE
classes = setOf("nonogram-solution-hint-cell")
val hintColumnIndex = column - hintTableColumns
if (hintColumnIndex in puzzleDefinition.columnHints.indices) {
val hints = puzzleDefinition.columnHints[hintColumnIndex]
Expand All @@ -286,8 +304,8 @@ private fun DIV.addResultsTable(puzzleDefinition: PuzzleDefinition, solution: Pu
tr {
for (column in 0 until totalTableColumns) {
td {
style = HINT_CELL_STYLE
if (column < hintTableColumns) {
classes = setOf("nonogram-solution-hint-cell")
val hints = puzzleDefinition.rowHints[puzzleRow]
val hintIndex = hints.size - hintTableColumns + column
if (hintIndex in hints.indices) {
Expand All @@ -296,10 +314,9 @@ private fun DIV.addResultsTable(puzzleDefinition: PuzzleDefinition, solution: Pu
+""
}
} else {
style = "border: 1px solid black;"
classes = setOf("nonogram-solution-grid-cell")
val puzzleColumn = column - hintTableColumns
img {
style = "vertical-align: middle;"
src = state.getCell(puzzleRow, puzzleColumn).symbolImage
}
}
Expand All @@ -318,7 +335,7 @@ private fun DIV.addResultsTable(puzzleDefinition: PuzzleDefinition, solution: Pu

private fun DIV.addFooter() {
sub {
+"Version 1.0.0"
+"Version 1.1.0"
}
br
sub {
Expand All @@ -327,7 +344,7 @@ private fun DIV.addFooter() {
br
sub {
a {
href = "3RD-PARTY-LICENSES.txt"
href = "nonogram-solver-third-party-notices.txt"
+"Third-Party License Notice"
}
}
Expand Down
Binary file modified nonograms-web/src/jsMain/resources/fill.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions nonograms-web/src/jsMain/resources/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<html>
<head>
<title>Nonogram Solver</title>
<link rel="stylesheet" href="/nonograms-web.css" />
</head>
<body>
<div id="nonogram-solver-root"></div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
This website contains the following 3rd party libraries:
The nonogram solver application contains the following 3rd party libraries:

org.jetbrains.kotlin:kotlin-stdlib-common:1.6.10
org.jetbrains.kotlin:kotlin-stdlib-js:1.6.10
org.jetbrains.kotlinx:kotlinx-html-common:0.7.3
org.jetbrains.kotlin:kotlin-stdlib-js:1.7.10
org.jetbrains.kotlinx:kotlinx-html-js:0.7.3

All 3rd party libraries were licensed under the terms of the
Expand Down
78 changes: 78 additions & 0 deletions nonograms-web/src/jsMain/resources/nonograms-web.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* MIT License
*
* Copyright (c) 2022 Andrew Krepps
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

.nonogram-puzzle-input-group {
display: flex;
flex-direction: row;
justify-content: left;
align-items: center;
flex-wrap: wrap;
padding: 8px;
padding-left: 0px;
}

.nonogram-puzzle-input-item {
margin: 8px;
margin-left: 0px;
}

.nonogram-puzzle-input-label {
margin-top: 0px;
margin-bottom: 4px;
}

.nonogram-action-button {
margin-right: 8px;
}

.nonogram-solution-table {
table-layout: fixed;
border-spacing: 0px;
}

.nonogram-solution-table > td {
margin: 0px;
padding: 1px;
background-color: white;
}

.nonogram-solution-hint-cell {
text-align: center;
vertical-align: middle;
min-width: 32px;
min-height: 32px;
}

.nonogram-solution-grid-cell {
border: 1px solid black;
}

.nonogram-solution-grid-cell > img {
text-align: center;
vertical-align: middle;
}

.nonogram-error-message {
color: red;
}
Binary file modified nonograms-web/src/jsMain/resources/open.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified nonograms-web/src/jsMain/resources/x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1604130

Please sign in to comment.