excessive / DOMy

A DOM-like GUI framework for the *awesome* LÖVE framework
Other
32 stars 2 forks source link

Styles Syntax #5

Closed karai17 closed 9 years ago

karai17 commented 9 years ago

What is the community's opinion of the current styles syntax? The way I have designed it is to organize various scopes since Lua does not have symbols like CSS. The way that this would work would be that for every instance of an object type, the parser will check the styles or see if any styles are defined and apply them. The parser will then check if there is an ID, and if there is a style for that ID. Any ID styles will override Object styles. Finally the parser will check classes (in the order given) and apply them.

Default->Object_Style->ID_Style->Class1_Style->Class2_Style->Class3_Style->...

The properties are mostly stolen from CSS though I plan to review them and make them more game oriented and less document oriented.

I am unsure if I should enforce ID styles tot he first instance of an ID (as an ID should be unique) or just enforce IDs in scripting.

pablomayobre commented 9 years ago

I would love if someone could do some metatable magic and allow for things like:

id("Header")*image{
    --Styles to be applied to every image in the element with id Header
}

which would be similar to:

#Header>img{
    /*Styles to be applied to every image in the element with id Header*/
}
pablomayobre commented 9 years ago

Maybe some especific styles, like if an element with type button and class warning gets an specific style you could use the + symbol in that case

class("warning")+button{
    --Styles
}
class("mylist"):nth-child(3){
    --Styles
}

You could get to a really similar syntax... You could even go for a JQuery like syntax for classes and ids:

D(".myclass"){
    --Styles
}
karai17 commented 9 years ago

I do like the idea of conditional formatting, but I am not very good with metatables. If someone else would like to post some example code on how this could be achieved, I'd be very happy to rewrite the styles spec.

pablomayobre commented 9 years ago

Well they are actually metamethods they are not that hard... I'll work on an example for tomorrow if no one answered 'til then

Basically the S() function and all the elements (image, button and such) return a table, with a metatable appended, there you have a function for __add, __mul and __call.

__call Stores it self as part of objects and receives a table as argument, that table is the styles applied to the selected classes, ids and elements and returns nil

_mul Stores the parent (that is the left operator which will be a table containing it's own parent or additions) in a table. Then it returns a table with the same metamethods listed here

__add The same as __mul but instead of storing the left operator as a parent stores it as an addition

__call will need to check the additions and parents and style accordingly. To do this it will need to parse the table which was passed to it as self

karai17 commented 9 years ago

So talking with @LPGhatguy, we came up with an interesting syntax (that we plan on refining a little more) that will be very similar to CSS yet remain as valid Lua:

local red = { 255, 0, 0, 255 }

-- All frame elements that have the class "red"
style("frame.red") { color=red }

-- All elements with the class "red" that are descended from a "frame" element
style("frame .red") { color=red }

-- All "text" elements that are descended from an element with the id "frame"
-- All elements with the class "red"
style("#frame text", ".red") { color=red }

-- All elements with the class "red" that are descended from an element with
-- the id "contact" that is descended from a "frame" element
style("frame #contact .red") { color=red }

Once we get this fully figured out, I will implement stylesheets. :)

pablomayobre commented 9 years ago

Nice! Like it better than the metatables approach

karai17 commented 9 years ago

Alright so I think I have a decent setup now. I may start working on a parser soon, once I figure out exactly how I want to store the styles.

local styles = {}

-- append styles from this file to "styles"
import("assets/styles/import.lua", styles)

local white = { 255, 255, 255, 255 }
local red   = { 255, 0, 0, 255 }
local empty = { 0, 0, 0, 0 }

local mix = {
    padding = empty,
    border  = empty,
    margin  = empty,
}

local frame = {
    text_color = white,
    width      = 300,
    height     = 500,
    padding    = { 5, 5, 5, 5 },
}

-- apply all properties from the first table to the second without over riding anything
mixin(mix, frame)

local more_styles = {
    -- all frame elements
    { "frame", frame },

    -- the element with the "hotbar" id
    -- all elements with the "red" class
    { "#hotbar", ".red", {
        text_color = red,
    }},

    -- the element with the "hotbar" id
    { "#hotbar", {
        -- all image elements descended from the element with the "hotbar" id
        { "image", {
            width  = 32,
            height = 32,
        }},
    }},

    -- all image elements with the "large" class
    { "image.large", {
        width  = 64,
        height = 64,
    }},

    -- all elements with the "image_list" class
    { ".image_list", {
        -- the last image descended from an element with the "image_list" class
        { "image:last", {
            opacity = 0.5,
        }},
    }},
}

-- apply all properties from the first query to the second without over riding anything
extend(".red", ".image_list image:last")

-- append all of the style declarations from "more_styles" to "styles"
append(more_styles, styles)

return styles

Parser

  1. The parser will read in each key from the styles table as a style
  2. The parser will determine the rules for each condition in the style
  3. The parser will check sequential keys (1 -> n) via ipairs in search of descendents
    • A descendent is defined as a table whose first sequential key is a string
  4. The parser will gather all of the appropriate elements to apply the styles to
  5. The parser will assume that all conditions are met once ipairs finishes
  6. The parser will assume the final key in ipairs is filled with styles and verify/apply them
    • This will be run with pairs and all sequential keys will be ignored

Symbols

karai17 commented 9 years ago

This is now mostly implemented. I haven't tested my environmental variables yet, pseudo-classes still need to be implemented, as do nested tables.

karai17 commented 9 years ago

Nested tables work now!

karai17 commented 9 years ago

I'm going to close this issue. I have notes in my code and in my tests about the pseudo classes and environmental functions. The purpose of this issue was to come up with a style syntax and I am very happy with the results. :)