Refactor code to separate View/Logic; Add clue widget - crossword.koplugin - Unnamed repository; edit this file 'description' to name the repository.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 2634a8e4f825bef8761e798e488e121003bffdbe
 (DIR) parent 1dc559aef64abdc2dd6effc6e857586f839c9e20
 (HTM) Author: Scarlett <social@scarlettmcallister.com>
       Date:   Sat, 11 Dec 2021 16:54:23 -0400
       
       Refactor code to separate View/Logic; Add clue widget
       
       Diffstat:
         A gridclue.lua                        |      50 +++++++++++++++++++++++++++++++
         A gridrow.lua                         |      36 +++++++++++++++++++++++++++++++
         A gridsquare.lua                      |      78 +++++++++++++++++++++++++++++++
         A gridview.lua                        |     132 +++++++++++++++++++++++++++++++
         M main.lua                            |      40 ++++++++++++++-----------------
         A puzzle.lua                          |      56 +++++++++++++++++++++++++++++++
         D puzzlerow.lua                       |      37 -------------------------------
         D puzzlesquare.lua                    |      92 -------------------------------
         D puzzleview.lua                      |     120 -------------------------------
       
       9 files changed, 370 insertions(+), 271 deletions(-)
       ---
 (DIR) diff --git a/gridclue.lua b/gridclue.lua
       @@ -0,0 +1,50 @@
       +local Blitbuffer = require("ffi/blitbuffer")
       +local CenterContainer = require("ui/widget/container/centercontainer")
       +local InputContainer = require("ui/widget/container/inputcontainer")
       +local Font = require("ui/font")
       +local Geom = require("ui/geometry")
       +local FrameContainer = require("ui/widget/container/framecontainer")
       +local TextWidget = require("ui/widget/textwidget")
       +local TextBoxWidget = require("ui/widget/textboxwidget")
       +
       +local logger = require("logger")
       +
       +local GridClue = InputContainer:new{
       +    height = nil,
       +    width = nil,
       +    clue_font_face = "infofont",
       +    clue_font_size = nil,
       +    clue_value = nil,
       +}
       +
       +function GridClue:init()
       +    self.clue_font_size = TextBoxWidget:getFontSizeToFitHeight(self.height, 1, 0.3)
       +
       +    self.clue_widget = TextWidget:new{
       +        text = self.clue_value,
       +        face = Font:getFace(self.clue_font_face, self.clue_font_size),
       +        fgcolor = Blitbuffer.COLOR_WHITE,
       +        padding = 0,
       +        bold = true,
       +    }
       +
       +    self[1] = FrameContainer:new{
       +        width = self.width,
       +        height = self.height,
       +        padding = 0,
       +        margin = self.margin or 0,
       +        bordersize = 0,
       +        -- Keep the letter centered
       +        CenterContainer:new{
       +            dimen = Geom:new{
       +                w = self.width,
       +                h = self.height,
       +            },
       +            padding = 0,
       +            -- Add the letter
       +            self.clue_widget,
       +        },
       +    }
       +end
       +
       +return GridClue
 (DIR) diff --git a/gridrow.lua b/gridrow.lua
       @@ -0,0 +1,36 @@
       +local InputContainer = require("ui/widget/container/inputcontainer")
       +local HorizontalGroup = require("ui/widget/horizontalgroup")
       +local FrameContainer = require("ui/widget/container/framecontainer")
       +
       +local GridRow = InputContainer:new{
       +    width = nil,
       +    height = nil,
       +    padding = nil,
       +}
       +
       +function GridRow:init()
       +    self.squares = {}
       +end
       +
       +function GridRow:addSquare(square)
       +    table.insert(self.squares, square)
       +end
       +
       +function GridRow:update()
       +    local hori = HorizontalGroup:new{}
       +
       +    for num, square in ipairs(self.squares) do
       +        table.insert(hori, square)
       +    end
       +
       +    self[1] = FrameContainer:new{
       +        width = self.width,
       +        height = self.height,
       +        bordersize = 0,
       +        padding = 0,
       +        margin = 0,
       +        hori
       +    }
       +end
       +
       +return GridRow
 (DIR) diff --git a/gridsquare.lua b/gridsquare.lua
       @@ -0,0 +1,78 @@
       +local Blitbuffer = require("ffi/blitbuffer")
       +local CenterContainer = require("ui/widget/container/centercontainer")
       +local InputContainer = require("ui/widget/container/inputcontainer")
       +local Font = require("ui/font")
       +local Geom = require("ui/geometry")
       +local FrameContainer = require("ui/widget/container/framecontainer")
       +local OverlapGroup = require("ui/widget/overlapgroup")
       +local TextWidget = require("ui/widget/textwidget")
       +local TextBoxWidget = require("ui/widget/textboxwidget")
       +
       +local logger = require("logger")
       +
       +local GridSquare = InputContainer:new{
       +    height = nil,
       +    width = nil,
       +    letter_font_face = "infofont",
       +    letter_font_size = nil,
       +    number_font_face = "infont",
       +    number_font_size = nil,
       +    margin = nil,
       +    letter_value = nil,
       +    number_value = nil,
       +}
       +
       +function GridSquare:init()
       +    -- Set up the right bg color, letter, etc.
       +    local bg_color = self.letter_value ~= "." and
       +        Blitbuffer.COLOR_WHITE or
       +        Blitbuffer.COLOR_BLACK
       +
       +    self.letter_font_size = TextBoxWidget:getFontSizeToFitHeight(self.height, 1, 0.3)
       +    self.number_font_size = self.letter_font_size / 2
       +
       +    -- Maybe a letter input by the player.
       +    self.letter_widget = TextWidget:new{
       +        text = self.letter_value,
       +        face = Font:getFace(self.letter_font_face, self.letter_font_size),
       +        fgcolor = Blitbuffer.COLOR_BLACK,
       +        padding = 0,
       +        bold = true,
       +    }
       +    -- Maybe a number that corresponds to a question.
       +    self.number_widget = TextWidget:new{
       +        text = self.number_value,
       +        face = Font:getFace(self.number_font_face, self.number_font_size),
       +        fgcolor = Blitbuffer.COLOR_BLACK,
       +        padding = 0,
       +        bold = true,
       +    }
       +    -- This is the container for the letter and number.
       +    self[1] = FrameContainer:new{
       +        width = self.width,
       +        height = self.height,
       +        color = Blitbuffer.COLOR_WHITE,
       +        background = bg_color,
       +        padding = 0,
       +        margin = self.margin or 0,
       +        bordersize = 0,
       +        OverlapGroup:new{
       +            dimen = { w = self.width },
       +            padding = 0,
       +            -- Keep the letter centered
       +            CenterContainer:new{
       +                dimen = Geom:new{
       +                    w = self.width,
       +                    h = self.height,
       +                },
       +                padding = 0,
       +                -- Add the letter
       +                self.letter_widget,
       +            },
       +            -- Add the number
       +            self.number_widget,
       +        },
       +    }
       +end
       +
       +return GridSquare
 (DIR) diff --git a/gridview.lua b/gridview.lua
       @@ -0,0 +1,132 @@
       +local Blitbuffer = require("ffi/blitbuffer")
       +local Device = require("device")
       +local Screen = Device.screen
       +local Size = require("ui/size")
       +local Geom = require("ui/geometry")
       +local GestureRange = require("ui/gesturerange")
       +local FrameContainer = require("ui/widget/container/framecontainer")
       +local InputContainer = require("ui/widget/container/inputcontainer")
       +local VerticalGroup = require("ui/widget/verticalgroup")
       +local logger = require("logger")
       +
       +local GridRow = require("gridrow")
       +local GridSquare = require("gridsquare")
       +local GridClue = require("gridclue")
       +
       +local GridView = InputContainer:new{
       +    width = nil,
       +    height = nil,
       +    size = {
       +        cols = nil,
       +        rows = nil,
       +    },
       +    on_tap_callback = nil
       +}
       +
       +function GridView:init()
       +    self.dimen = Geom:new{
       +        w = self.width or Screen:getWidth(),
       +        h = self.height or Screen:getHeight(),
       +    }
       +    self.outer_padding = Size.padding.large
       +    self.inner_padding = Size.padding.small
       +    self.inner_dimen = Geom:new{
       +        w = self.dimen.w - 2 * self.outer_padding,
       +        h = self.dimen.h - self.outer_padding, -- no bottom padding
       +    }
       +    self.content_width = self.inner_dimen.w
       +    -- The pixel dimensions of the squares. Calculate the initial width based on the size
       +    -- of the device and the number of columns. Then make a minor adjustment to account for
       +    -- the margins. To do this, divide margin in 4 and multiply by the number of columns.
       +    self.square_margin = Size.border.window
       +    self.square_width = math.floor(
       +        (self.dimen.w - (2 * self.outer_padding) - (2 * self.inner_padding))
       +        / self.size.cols) - ((self.square_margin / 4) * (6)) -- 6 works here for some reason, although in my head
       +    -- (cont) it should be self.size.cols because that's what we're adjusting for.
       +    self.square_height = self.square_width
       +    -- Register the event listener
       +    self.ges_events.Tap = {
       +        GestureRange:new{
       +            ges = "tap",
       +            range = function()
       +                return self.dimen
       +            end,
       +        },
       +    }
       +end
       +
       +function GridView:render()
       +    -- Build the row and add the squares.
       +    self.rows_view = VerticalGroup:new { border = 0 }
       +    for i, l in ipairs(self.grid) do
       +        local row =  self:buildRow(l)
       +        table.insert(self.rows_view, row)
       +    end
       +    -- Build the clue.
       +    self.grid_clue = GridClue:new{
       +        width = self.inner_dimen.w,
       +        height = self.square_height,
       +        clue_value = self.active_clue
       +    }
       +    -- Build the container.
       +    self[1] = FrameContainer:new{
       +        width = self.dimen.w,
       +        height = self.dimen.h,
       +        padding = self.outer_padding,
       +        padding_bottom = 0,
       +        margin = 0,
       +        bordersize = 0,
       +        background = Blitbuffer.COLOR_BLACK,
       +        VerticalGroup:new{
       +            align = "center",
       +            background = Blitbuffer.COLOR_GRAY,
       +            -- Add the rows vertical group.
       +            self.rows_view,
       +            self.grid_clue,
       +        }
       +    }
       +end
       +
       +function GridView:onTap(_, ges)
       +    -- Temp for debuggery
       +    -- Find the square that's been tapped
       +    -- so we want to find the square
       +    -- and we can expedite that by getting the correct row, first,
       +    -- which is given by the square_height stuff... we will have to account for margins, too.
       +    -- self.square_margin
       +    -- self.square_height
       +    local y = ges.pos.y
       +    local x = ges.pos.x
       +    -- so, get the row number
       +    local row_num = math.ceil(x / (self.square_height))
       +    local col_num = math.ceil(y / self.square_width)
       +    -- If a callback's been set, we need to send back the
       +    -- coordinates so some genius can do something else.
       +    if self.on_tap_callback then
       +        self.on_tap_callback(row_num, col_num)
       +    end
       +end
       +
       +-- Given a table containing letters, build a row containing
       +-- squares with said letters.
       +function GridView:buildRow(squares, row_num)
       +    local row = GridRow:new{
       +        width = self.inner_dimen.w,
       +        height = self.square_height,
       +    }
       +    for col_num, square in ipairs(squares) do
       +        row:addSquare(GridSquare:new{
       +                width = self.square_width,
       +                height = self.square_height,
       +                pos_x = col_num,
       +                pos_y = row_num,
       +                margin = self.square_margin,
       +                letter_value = square.letter,
       +                number_value = square.number,
       +        })
       +    end
       +    row:update()
       +    return row
       +end
       +
       +return GridView
 (DIR) diff --git a/main.lua b/main.lua
       @@ -84,7 +84,7 @@ function Crossword:setPuzzlesDirectory()
            self:lazyInitialization()
        end
        
       -function Crossword:gameView()
       +function Crossword:loadPuzzle()
            local file_path = ("%s/%s"):format(self.puzzle_dir, "/1990/01/01.json")
            local file, err = io.open(file_path, "rb")
        
       @@ -95,33 +95,29 @@ function Crossword:gameView()
            local file_content = file:read("*all")
            file:close()
        
       -    local puzzle = json.decode(file_content)
       -    logger.dbg(puzzle)
       -    -- Create the grid, which contains the letters for
       -    -- each row.
       -    local grid = {}
       -    local row = {}
       -    for i, letter in ipairs(puzzle.grid) do
       -        table.insert(row, {
       -                letter = letter,
       -                number = puzzle.gridnums[i],
       -        })
       -        if i % 15 == 0 then
       -            table.insert(grid, row)
       -            row = {}
       -        end
       -    end
       +    local Puzzle = require("puzzle")
       +    local puzzle = Puzzle:new{}
       +    puzzle:init(json.decode(file_content))
       +    return puzzle
       +end
        
       -    local PuzzleView = require("puzzleview")
       -    PuzzleView = PuzzleView:new{
       +function Crossword:gameView()
       +    local puzzle = self:loadPuzzle()
       +
       +    local GridView = require("gridview")
       +    GridView = GridView:new{
                size = {
                    cols = puzzle.size.cols,
                    rows = puzzle.size.rows
                },
       -        grid = grid
       +        grid = puzzle.grid,
       +        active_clue = "This is the hint",
       +        on_tap_callback = function(row, col)
       +            logger.dbg(puzzle:getSquareAtPos(row, col))
       +        end
            }
       -
       -    UIManager:show(PuzzleView)
       +    UIManager:show(GridView)
       +    GridView:render()
        end
        
        return Crossword
 (DIR) diff --git a/puzzle.lua b/puzzle.lua
       @@ -0,0 +1,56 @@
       +local logger = require("logger")
       +
       +local Puzzle = {
       +    json_object = nil,
       +    size = {
       +        cols = nil,
       +        rows = nil,
       +    },
       +    grid = nil,
       +}
       +
       +function Puzzle:new(o)
       +    o = o or {}   -- create object if user does not provide one
       +    setmetatable(o, self)
       +    self.__index = self
       +    return o
       +end
       +
       +function Puzzle:init(json_object)
       +    -- Lazy error checking
       +    if not json_object then
       +        logger.dbg("Puzzle: json_object must be set for puzzle to be created.")
       +        return false
       +    end
       +    -- Onto the initialization
       +    self.size = json_object.size
       +    self.grid = {}
       +    local row = {} -- Start with an empty row to collect squares.
       +    for i, letter in ipairs(json_object.grid) do
       +        local grid_num = json_object.gridnums[i]
       +        -- Add a square to the row
       +        table.insert(row, {
       +                letter = letter and
       +                    letter or
       +                    "",
       +                number = grid_num ~= 0 and
       +                    tostring(grid_num) or
       +                    "",
       +        })
       +        -- Check whether to insert the row and reset the count.
       +        if i % self.size.cols == 0 then
       +            table.insert(self.grid, row)
       +            row = {} -- Empty the row table to collect the new set of squares.
       +        end
       +    end
       +end
       +
       +function Puzzle:getGrid()
       +    return self.grid
       +end
       +
       +function Puzzle:getSquareAtPos(row, col)
       +    return self.grid[row][col]
       +end
       +
       +return Puzzle
 (DIR) diff --git a/puzzlerow.lua b/puzzlerow.lua
       @@ -1,37 +0,0 @@
       -local InputContainer = require("ui/widget/container/inputcontainer")
       -local HorizontalGroup = require("ui/widget/horizontalgroup")
       -local HorizontalSpan = require("ui/widget/horizontalspan")
       -local FrameContainer = require("ui/widget/container/framecontainer")
       -
       -local Row = InputContainer:new{
       -    width = nil,
       -    height = nil,
       -    padding = nil,
       -}
       -
       -function Row:init()
       -    self.squares = {}
       -end
       -
       -function Row:addSquare(square)
       -    table.insert(self.squares, square)
       -end
       -
       -function Row:update()
       -    local hori = HorizontalGroup:new{}
       -
       -    for num, square in ipairs(self.squares) do
       -        table.insert(hori, square)
       -    end
       -
       -    self[1] = FrameContainer:new{
       -        width = self.width,
       -        height = self.height,
       -        bordersize = 0,
       -        padding = 0,
       -        margin = 0,
       -        hori
       -    }
       -end
       -
       -return Row
 (DIR) diff --git a/puzzlesquare.lua b/puzzlesquare.lua
       @@ -1,92 +0,0 @@
       -local Blitbuffer = require("ffi/blitbuffer")
       -local CenterContainer = require("ui/widget/container/centercontainer")
       -local InputContainer = require("ui/widget/container/inputcontainer")
       -local Font = require("ui/font")
       -local Geom = require("ui/geometry")
       -local FrameContainer = require("ui/widget/container/framecontainer")
       -local OverlapGroup = require("ui/widget/overlapgroup")
       -local TextWidget = require("ui/widget/textwidget")
       -local TextBoxWidget = require("ui/widget/textboxwidget")
       -
       -local logger = require("logger")
       -
       -local PuzzleSquare = InputContainer:new{
       -    letter_font_face = "infofont",
       -    letter_font_size = nil,
       -    number_font_face = "infont",
       -    number_font_size = nil,
       -    margin = nil,
       -    solve = nil,
       -}
       -
       -function PuzzleSquare:init()
       -    -- Lazy check to see if solve is set.
       -    if not self.solve then
       -        logger.dbg("PuzzleSquare: solve not set for square")
       -        return
       -    end
       -
       -    -- Set up the right bg color, letter, etc.
       -    local bg_color = self.solve.letter ~= "." and
       -        Blitbuffer.COLOR_WHITE or
       -        Blitbuffer.COLOR_BLACK
       -    local letter = self.solve.letter and
       -        self.solve.letter or
       -        ""
       -    local number = self.solve.number ~= 0 and
       -        tostring(self.solve.number) or
       -        ""
       -
       -    self.letter_font_size = TextBoxWidget:getFontSizeToFitHeight(self.height, 1, 0.3)
       -    self.number_font_size = self.letter_font_size / 2
       -
       -    -- This is the letter input by the player.
       -    self.letter = TextWidget:new{
       -        text = letter,
       -        face = Font:getFace(self.letter_font_face, self.letter_font_size),
       -        fgcolor = Blitbuffer.COLOR_BLACK,
       -        padding = 0,
       -        bold = true,
       -    }
       -    -- This is the number that corresponds to the question.
       -    -- Note that the number is not always set!
       -    self.number = TextWidget:new{
       -        text = number,
       -        face = Font:getFace(self.number_font_face, self.number_font_size),
       -        fgcolor = Blitbuffer.COLOR_BLACK,
       -        padding = 0,
       -        bold = true,
       -    }
       -    -- This is the container for the letter and number.
       -    self[1] = FrameContainer:new{
       -        width = self.width,
       -        height = self.height,
       -        color = Blitbuffer.COLOR_WHITE,
       -        background = bg_color,
       -        padding = 0,
       -        margin = self.margin or 0,
       -        bordersize = 0,
       -        OverlapGroup:new{
       -            dimen = { w = self.width },
       -            padding = 0,
       -            -- Keep the letter centered
       -            CenterContainer:new{
       -                dimen = Geom:new{
       -                    w = self.width,
       -                    h = self.height,
       -                },
       -                padding = 0,
       -                -- Add the letter
       -                self.letter,
       -            },
       -            -- Add the number
       -            self.number,
       -        },
       -    }
       -end
       -
       -function PuzzleSquare:onTap()
       -    logger.dbg("TA________________P")
       -end
       -
       -return PuzzleSquare
 (DIR) diff --git a/puzzleview.lua b/puzzleview.lua
       @@ -1,120 +0,0 @@
       -local Blitbuffer = require("ffi/blitbuffer")
       -local Device = require("device")
       -local Screen = Device.screen
       -local Size = require("ui/size")
       -local Geom = require("ui/geometry")
       -local FrameContainer = require("ui/widget/container/framecontainer")
       -local InputContainer = require("ui/widget/container/inputcontainer")
       -local OverlapGroup = require("ui/widget/overlapgroup")
       -local VerticalGroup = require("ui/widget/verticalgroup")
       -local HorizontalGroup = require("ui/widget/horizontalgroup")
       -local logger = require("logger")
       -
       -local PuzzleRow = require("puzzlerow")
       -local PuzzleSquare = require("puzzlesquare")
       -
       -
       -local PuzzleView = InputContainer:new{
       -    width = nil,
       -    height = nil,
       -    size = {
       -        cols = nil,
       -        rows = nil,
       -    }
       -}
       -
       -function PuzzleView:init()
       -
       -    -- Temp! This will be the puzzle object, eventually.
       -    local letters = {
       -        {"A","B",".","C","D","E"},
       -        {"B",".","C","D","E","C"},
       -    }
       -
       -    local puzzle_cols = #letters[1]
       -    local puzzle_rows = #letters
       -
       -    self.dimen = Geom:new{
       -        w = self.width or Screen:getWidth(),
       -        h = self.height or Screen:getHeight(),
       -    }
       -    self.outer_padding = Size.padding.large
       -    self.inner_padding = Size.padding.small
       -    self.inner_dimen = Geom:new{
       -        w = self.dimen.w - 2 * self.outer_padding,
       -        h = self.dimen.h - self.outer_padding, -- no bottom padding
       -    }
       -    self.content_width = self.inner_dimen.w
       -    -- The grid dimensions of the puzzle.
       -    --self.grid = {
       -    --    cols = puzzle_cols,
       -    --    rows = puzzle_rows,
       -    --}
       -    -- The pixel dimensions of the squares. Calculate the initial width based on the size
       -    -- of the device and the number of columns. Then make a minor adjustment to account for
       -    -- the margins. To do this, divide margin in 4 and multiply by the number of columns.
       -    self.square_margin = Size.border.window
       -    self.square_width = math.floor(
       -        (self.dimen.w - (2 * self.outer_padding) - (2 * self.inner_padding))
       -        / self.size.cols) - ((self.square_margin / 4) * (puzzle_cols))
       -    self.square_height = self.square_width
       -
       -    ------------------
       -    -- Add the squares
       -    self.rows_group = VerticalGroup:new{ border = 0 }
       -
       -    for i, l in ipairs(self.grid) do
       -        table.insert(self.rows_group, self:buildRow(l))
       -    end
       -
       -    ---------------
       -    -- Build the container
       -
       -    self[1] = FrameContainer:new{
       -        width = self.dimen.w,
       -        height = self.dimen.h,
       -        padding = self.outer_padding,
       -        padding_bottom = 0,
       -        margin = 0,
       -        bordersize = 0,
       -        background = Blitbuffer.COLOR_BLACK,
       -        VerticalGroup:new{
       -            align = "center",
       -            background = Blitbuffer.COLOR_GRAY,
       -            -- Add the rows vertical group.
       -            self.rows_group,
       -        }
       -    }
       -end
       -
       -function PuzzleView:create()
       -
       -end
       -
       --- Given a table containing letters, build a row containing
       --- squares with said letters.
       -function PuzzleView:buildRow(squares)
       -    local row = PuzzleRow:new{
       -        width = self.inner_dimen.w,
       -        height = self.square_height,
       -    }
       -    for i, square in ipairs(squares) do
       -        -- This needs a better name. It should be a combination of the user's input,
       -        -- plus also like the square solve thing (hints, etc.)
       -        local solve = {
       -            letter = square.letter,
       -            number = square.number,
       -        }
       -        local square = PuzzleSquare:new{
       -            width = self.square_width,
       -            height = self.square_height,
       -            margin = self.square_margin,
       -            solve = solve,
       -        }
       -        row:addSquare(square)
       -    end
       -    row:update()
       -    return row
       -end
       -
       -return PuzzleView