23 changed files with 40596 additions and 105 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,3 @@
|
||||
1.7.3 |
||||
#First line must be a semantic version number |
||||
#all other lines are ignored. |
||||
@ -0,0 +1,446 @@
|
||||
# -*- tcl -*- |
||||
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt |
||||
# module template: shellspy/src/decktemplates/vendor/punk/modules/template_module-0.0.4.tm |
||||
# |
||||
# Please consider using a BSD or MIT style license for greatest compatibility with the Tcl ecosystem. |
||||
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository. |
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
# (C) 2025 |
||||
# |
||||
# @@ Meta Begin |
||||
# Application punk::layout 999999.0a1.0 |
||||
# Meta platform tcl |
||||
# Meta license MIT |
||||
# @@ Meta End |
||||
|
||||
|
||||
#EXPERIMENTAL |
||||
|
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
## Requirements |
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
|
||||
|
||||
package require Tcl 8.6- |
||||
package require punk::args |
||||
|
||||
#experimental layout library based on Nic Barker's Clay |
||||
# CLAY(CLAY_ID("parent"), { .layout = { .padding = CLAY_PADDING_ALL(8) } }) { |
||||
# // Child element 1 |
||||
# CLAY_TEXT(CLAY_STRING("Hello World"), CLAY_TEXT_CONFIG({ .fontSize = 16 })); |
||||
# // Child element 2 with red background |
||||
# CLAY(CLAY_ID("child"), { .backgroundColor = COLOR_RED }) { |
||||
# // etc |
||||
# } |
||||
# } |
||||
|
||||
#Tcl translation? |
||||
#CLAY ?-opt <val>..? ?childblock? |
||||
#eg |
||||
#CLAY -id <string> -layout <dict> -rectangle <dict> { childblock } |
||||
#where childblock is curly braced code block |
||||
|
||||
# clay -id "parent" -layout [dict create .padding [padding_all 8]] { |
||||
# clay_text "Hello World" [clay_textconfig {.fontsize 16}] |
||||
# clay -id "child" -config {.backgroundColor red} { |
||||
# # etc |
||||
# } |
||||
# } |
||||
|
||||
#for padding on a terminal - we are limited by cell_size - which is not square. (and may vary on terminals??) |
||||
# e.g punk::console::cell_size returns cell wxh |
||||
# -> 10x20 |
||||
# (either queried from terminal - or defaults to 10x20 if can't be queried) |
||||
#so the minimum 'even' padding we can have is 2 space for horizontal, 1 line vertical |
||||
#we can pad a minimum of 1 space horizontall (10 units) and a minimum of 1 line vertically (20 units) |
||||
# CLAY_PADDING {<l> <r> <t> <b>} |
||||
#how then should we handle .padding {16 16 8 8} - quantize by roundup to h 10 and v 20? |
||||
# -> {20 20 20 20} ? |
||||
# or round to nearest vertical and horizontal quanta? |
||||
# -> {20 20 0 0} |
||||
#either way - {16 16 16 16} goes to {20 20 20 20} - which is *close* to equal v h padding |
||||
# - but not perfect visually because fonts within a cell have baseline, topline etc internal padding too? |
||||
|
||||
#building a ui ? |
||||
#clay_begin_layout |
||||
# // build UI here |
||||
#set rendercommands [clay_end_layout] |
||||
#some_render_command $rendercommands |
||||
|
||||
|
||||
|
||||
|
||||
#eg2 (from introducing clay video https://www.youtube.com/watch?v=DYWTw19_8r4&t=2s) |
||||
#something like the following? |
||||
# (stopped at around the scroll point - need to work out console mouse features. punk::console::mouse_enable ...) |
||||
|
||||
#extracted out common layout 'sizing' for grow in both directions |
||||
#set layoutExpand { |
||||
# width CLAY_SIZING_GROW |
||||
# heigth CLAY_SIZING GROW |
||||
# } |
||||
#extracted out common background panel |
||||
#set contentBackgroundConfig { |
||||
# colour Term-grey |
||||
# frametype arc |
||||
# } |
||||
#proc RenderHeaderButton {} {} ;#?? |
||||
|
||||
#set documents [dict create\ |
||||
# Squirrels "The secret life of Squirrels"\ |
||||
# "Lorem Ipsum" "Orem ipsum dolor sit ..\netc blah"\ |
||||
# "Vacuum instructions" "Chapter 3: Getting Started"\ |
||||
# "Article 4" "Article 4"\ |
||||
# "Article 5" "Article 5"\ |
||||
# ] |
||||
|
||||
#set selectedDocumentIndex 0 |
||||
|
||||
|
||||
#clay_begin_layout |
||||
#clay -id "OuterContainer"\ |
||||
# -item [clay_rectangle {colour web-red}] |
||||
# -layout [clay_layout [dict create\ |
||||
# layoutDirection CLAY_TOP_TO_BOTTOM\ |
||||
# sizing $layoutExpand\ |
||||
# padding {16 16}\ |
||||
# childGap 16\ |
||||
# ]]\ |
||||
# { |
||||
# # Child elements |
||||
# clay -id "HeaderBar"\ |
||||
# -item [clay_rectangle $contentBackgroundConfig]\ |
||||
# -layout [clay_layout { |
||||
# sizing { |
||||
# height 60 |
||||
# width CLAY_SIZING_GROW |
||||
# } |
||||
# padding {8 8} |
||||
# childGap 8 |
||||
# childAlignment { |
||||
# y CLAY_ALIGN_Y_CENTER |
||||
# } |
||||
# }]\ |
||||
# { |
||||
# # Header buttons go here |
||||
# RenderheaderButton [clay_string "File"] |
||||
# RenderheaderButton [clay_string "Edit"] |
||||
# #push last 3 buttons to rhs by using a layout in between to take up the middle space |
||||
# CLAY -layout {sizing {width CLAY_SIZING_GROW}} {} |
||||
# RenderheaderButton [clay_string "Upload"] |
||||
# RenderheaderButton [clay_string "Media"] |
||||
# RenderheaderButton [clay_string "Support"] |
||||
# } |
||||
# clay -id "LowerContent"\ |
||||
# -layout [dict create sizing $layoutExpand childGap 16]\ |
||||
# { |
||||
# clay -id "Sidebar"\ |
||||
# -item [clay_rectangle $contentBackgroundConfig]\ |
||||
# -layout { |
||||
# layoutDirection CLAY_TOP_TO_BOTTOM |
||||
# padding {8 8} |
||||
# childgap {20} |
||||
# sizing { |
||||
# width = 60 |
||||
# height = CLAY_SIZING_GROW |
||||
# }\ |
||||
# }\ |
||||
# { |
||||
# #render dynamic data |
||||
# dict for {title data} $documents { |
||||
# clay -layout {padding {8 8}\ |
||||
# { |
||||
# #fontId, fontSize not really practical on terminal |
||||
# clay_text $title [clay_text_config { |
||||
# textColor cyan |
||||
# }] |
||||
# } |
||||
# } |
||||
# } |
||||
# clay -id "MainContent"\ |
||||
# -item [clay_rectangle $contentBackgroundConfig]\ |
||||
# -scroll {vertical true}\ |
||||
# -layout [dict create\ |
||||
# layoutDirection = CLAY_TOP_TO_BOTTOM\ |
||||
# childGap 20\ |
||||
# padding {16 16 20 20}\ |
||||
# sizing $layoutExpand\ |
||||
# ]\ |
||||
# { |
||||
# set selectedTitle [lindex [dict keys $documents] $selectedDocumentIndex] |
||||
# clay_text $selectedTitle [clay_text_config { |
||||
# textcolour {web-white bold} |
||||
# }] |
||||
# clay_text [dict get $documents $selectedTitle] [clay_text_config { |
||||
# textcolour {web-white} |
||||
# }] |
||||
# } |
||||
# } |
||||
# } |
||||
#set rendercommands [clay_end_layout] |
||||
|
||||
#CLAY_SIZING_GROW |
||||
#CLAY_SIZING_FIT ;#default |
||||
|
||||
tcl::namespace::eval punk::layout { |
||||
variable PUNKARGS |
||||
namespace eval argdoc { |
||||
variable PUNKARGS |
||||
namespace eval argdoc { |
||||
#non-colour SGR codes |
||||
set I "\x1b\[3m" ;# [a+ italic] |
||||
set NI "\x1b\[23m" ;# [a+ noitalic] |
||||
set B "\x1b\[1m" ;# [a+ bold] |
||||
set N "\x1b\[22m" ;# [a+ normal] |
||||
set T "\x1b\[1\;4m" ;# [a+ bold underline] |
||||
set NT "\x1b\[22\;24m\x1b\[4:0m" ;# [a+ normal nounderline] |
||||
} |
||||
} |
||||
|
||||
|
||||
#elementDeclaration |
||||
|
||||
#data structure (CLAY UIElement struct equivalent) |
||||
#set eg_element [dict create\ |
||||
# position {1 1}\ |
||||
# size {80 24}\ |
||||
# children [list]\ |
||||
#] |
||||
|
||||
|
||||
#elementConfig |
||||
#set eg_item [dict create\ |
||||
# type rectangle\ |
||||
# color {red bold}\ |
||||
# borderColor {yellow} |
||||
# frametype {}\ |
||||
#] |
||||
# etc |
||||
proc DrawRectangle {element} { |
||||
set position [dict get $element position] ;#x y |
||||
set size [dict get $element size] ;#width height |
||||
lassign $size w h |
||||
set bg [dict get $element color] |
||||
set borderColor [dict get $element borderColor] |
||||
set frametype [dict get $element frametype] |
||||
if {$frametype eq ""} { |
||||
#much faster than textblock::frame |
||||
set content [textblock::block $w $h "[a+ $bg] [a]"] |
||||
} else { |
||||
#slow - and frame background colours will always overlap the borders so we can never get a nicely filled arc frame for example |
||||
#The best bordered |
||||
set content [textblock::frame -type $frametype -ansibase [a+ $bg] -ansiborder [a+ $borderColor] -width $w -height $h " "] |
||||
} |
||||
} |
||||
proc RenderElement {element} { |
||||
|
||||
} |
||||
|
||||
|
||||
#TODO |
||||
#The clay_begin_layout - clay_end_layout structure suggests the main API may be better represented as an oo object maintaining state |
||||
#we may need to have multiple instances running concurrently |
||||
#Clay conceptually runs in 'immediate' mode - ie recalculating each full layout each time we need to render |
||||
|
||||
variable rendercommands |
||||
proc clay_begin_layout {} { |
||||
variable rendercommands |
||||
set rendercommands [dict create] |
||||
#...? |
||||
} |
||||
proc clay_end_layout {} { |
||||
variable rendercommands |
||||
|
||||
#...? |
||||
|
||||
return $rendercommands |
||||
} |
||||
|
||||
|
||||
namespace eval argdoc { |
||||
variable PUNKARGS |
||||
lappend PUNKARGS [list { |
||||
@id -id ::punk::layout::clay |
||||
@cmd -name punk::layout::clay |
||||
@opts |
||||
-id -type string |
||||
-item -type dict |
||||
-layout -type dict |
||||
-backgroundColor -type list -help\ |
||||
"ANSI colour codes as documented in punk::ansi::a?" |
||||
@values -min 0 -max 1 |
||||
childscript -type script |
||||
}] |
||||
} |
||||
#For initial proof of concept - we will use punk::args for *parsing* as well as documenting |
||||
#For final version - the extra overhead of punk::args::parse may not be suitable for large numbers of |
||||
#calls in 'immediate' mode - so punk::args::parse should be used on 'unhappy' paths only, |
||||
#with a fast switch statement used for actual option parsing. |
||||
#As performance is likely to be an issue - we should also avoid allowing 'prefixes' for arguments |
||||
proc clay {args} { |
||||
set argd [punk::args::parse $args withid ::punk::layout::clay] ;#temporary during concept development - todo: change to manual parsing for performance. |
||||
|
||||
} |
||||
# |
||||
|
||||
} |
||||
|
||||
|
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
# Secondary API namespace |
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
tcl::namespace::eval punk::layout::lib { |
||||
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase |
||||
tcl::namespace::path [tcl::namespace::parent] |
||||
|
||||
|
||||
#STEPS |
||||
#Fit Sizing -> Grow Sizing -> Positions -> Draw |
||||
#tree traversal |
||||
#(reverse breadth first) (breadth first) |
||||
# via OpenElement/CloseElement? (expand our grow containers |
||||
# into any available space) |
||||
|
||||
proc OpenElement {element} { |
||||
#pseudo... |
||||
#set layoutDirection $layoutconfig.layoutDirection |
||||
#if {$layoutDirection eq "CLAY_LEFT_TO_RIGHT"} { |
||||
#} else { |
||||
# #CLAY_TOP_TO_BOTTOM |
||||
#} |
||||
} |
||||
proc CloseElement {element} { |
||||
#element.parent.width += element.width |
||||
#element.parent.height += element.height |
||||
|
||||
} |
||||
|
||||
proc SizeContainersAlongAxis {is_x_axis totalSizeToDistribute} { |
||||
} |
||||
proc CalculateFinalLayout {} { |
||||
} |
||||
|
||||
|
||||
|
||||
} |
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
|
||||
|
||||
|
||||
#tcl::namespace::eval punk::layout::system { |
||||
#} |
||||
|
||||
|
||||
# == === === === === === === === === === === === === === === |
||||
# Sample 'about' function with punk::args documentation |
||||
# == === === === === === === === === === === === === === === |
||||
tcl::namespace::eval punk::layout { |
||||
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase |
||||
variable PUNKARGS |
||||
variable PUNKARGS_aliases |
||||
|
||||
lappend PUNKARGS [list { |
||||
@id -id "(package)punk::layout" |
||||
@package -name "punk::layout" -help\ |
||||
"EXPERIMENTAL - not done" |
||||
}] |
||||
|
||||
namespace eval argdoc { |
||||
#namespace for custom argument documentation |
||||
proc package_name {} { |
||||
return punk::layout |
||||
} |
||||
proc about_topics {} { |
||||
#info commands results are returned in an arbitrary order (like array keys) |
||||
set topic_funs [info commands [namespace current]::get_topic_*] |
||||
set about_topics [list] |
||||
foreach f $topic_funs { |
||||
set tail [namespace tail $f] |
||||
lappend about_topics [string range $tail [string length get_topic_] end] |
||||
} |
||||
#Adjust this function or 'default_topics' if a different order is required |
||||
return [lsort $about_topics] |
||||
} |
||||
proc default_topics {} {return [list Description *]} |
||||
|
||||
# ------------------------------------------------------------- |
||||
# get_topic_ functions add more to auto-include in about topics |
||||
# ------------------------------------------------------------- |
||||
proc get_topic_Description {} { |
||||
punk::args::lib::tstr [string trim { |
||||
package punk::layout |
||||
An experiment in using CLAY UI style layout on the terminal |
||||
INCOMPLETE... |
||||
status: notes and started framework only - nothing usable. |
||||
} \n] |
||||
} |
||||
proc get_topic_License {} { |
||||
return "MIT" |
||||
} |
||||
proc get_topic_Version {} { |
||||
return "$::punk::layout::version" |
||||
} |
||||
proc get_topic_Contributors {} { |
||||
set authors {{Julian Noble <julian@precisium.com.au}} |
||||
set contributors "" |
||||
foreach a $authors { |
||||
append contributors $a \n |
||||
} |
||||
if {[string index $contributors end] eq "\n"} { |
||||
set contributors [string range $contributors 0 end-1] |
||||
} |
||||
return $contributors |
||||
} |
||||
proc get_topic_concepts {} { |
||||
punk::args::lib::tstr -return string { |
||||
see Nic Barker's youtube video: How Clay's UI Layout Algorithm Works |
||||
https://www.youtube.com/watch?v=by9lQvpvMIc |
||||
} |
||||
} |
||||
# ------------------------------------------------------------- |
||||
} |
||||
|
||||
# we re-use the argument definition from punk::args::standard_about and override some items |
||||
set overrides [dict create] |
||||
dict set overrides @id -id "::punk::layout::about" |
||||
dict set overrides @cmd -name "punk::layout::about" |
||||
dict set overrides @cmd -help [string trim [punk::args::lib::tstr { |
||||
About punk::layout |
||||
}] \n] |
||||
dict set overrides topic -choices [list {*}[punk::layout::argdoc::about_topics] *] |
||||
dict set overrides topic -choicerestricted 1 |
||||
dict set overrides topic -default [punk::layout::argdoc::default_topics] ;#if -default is present 'topic' will always appear in parsed 'values' dict |
||||
set newdef [punk::args::resolved_def -antiglobs -package_about_namespace -override $overrides ::punk::args::package::standard_about *] |
||||
lappend PUNKARGS [list $newdef] |
||||
proc about {args} { |
||||
package require punk::args |
||||
#standard_about accepts additional choices for topic - but we need to normalize any abbreviations to full topic name before passing on |
||||
set argd [punk::args::parse $args withid ::punk::layout::about] |
||||
lassign [dict values $argd] _leaders opts values _received |
||||
punk::args::package::standard_about -package_about_namespace ::punk::layout::argdoc {*}$opts {*}[dict get $values topic] |
||||
} |
||||
} |
||||
# end of sample 'about' function |
||||
# == === === === === === === === === === === === === === === |
||||
|
||||
|
||||
# ----------------------------------------------------------------------------- |
||||
# register namespace(s) to have PUNKARGS,PUNKARGS_aliases variables checked |
||||
# ----------------------------------------------------------------------------- |
||||
# variable PUNKARGS |
||||
# variable PUNKARGS_aliases |
||||
namespace eval ::punk::args::register { |
||||
#use fully qualified so 8.6 doesn't find existing var in global namespace |
||||
lappend ::punk::args::register::NAMESPACES ::punk::layout |
||||
} |
||||
# ----------------------------------------------------------------------------- |
||||
|
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
## Ready |
||||
package provide punk::layout [tcl::namespace::eval punk::layout { |
||||
variable pkg punk::layout |
||||
variable version |
||||
set version 999999.0a1.0 |
||||
}] |
||||
return |
||||
|
||||
@ -0,0 +1,3 @@
|
||||
0.1.0 |
||||
#First line must be a semantic version number |
||||
#all other lines are ignored. |
||||
@ -1,3 +1,3 @@
|
||||
0.1.4 |
||||
0.1.5 |
||||
#First line must be a semantic version number |
||||
#all other lines are ignored. |
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,446 @@
|
||||
# -*- tcl -*- |
||||
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt |
||||
# module template: shellspy/src/decktemplates/vendor/punk/modules/template_module-0.0.4.tm |
||||
# |
||||
# Please consider using a BSD or MIT style license for greatest compatibility with the Tcl ecosystem. |
||||
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository. |
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
# (C) 2025 |
||||
# |
||||
# @@ Meta Begin |
||||
# Application punk::layout 0.1.0 |
||||
# Meta platform tcl |
||||
# Meta license MIT |
||||
# @@ Meta End |
||||
|
||||
|
||||
#EXPERIMENTAL |
||||
|
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
## Requirements |
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
|
||||
|
||||
package require Tcl 8.6- |
||||
package require punk::args |
||||
|
||||
#experimental layout library based on Nic Barker's Clay |
||||
# CLAY(CLAY_ID("parent"), { .layout = { .padding = CLAY_PADDING_ALL(8) } }) { |
||||
# // Child element 1 |
||||
# CLAY_TEXT(CLAY_STRING("Hello World"), CLAY_TEXT_CONFIG({ .fontSize = 16 })); |
||||
# // Child element 2 with red background |
||||
# CLAY(CLAY_ID("child"), { .backgroundColor = COLOR_RED }) { |
||||
# // etc |
||||
# } |
||||
# } |
||||
|
||||
#Tcl translation? |
||||
#CLAY ?-opt <val>..? ?childblock? |
||||
#eg |
||||
#CLAY -id <string> -layout <dict> -rectangle <dict> { childblock } |
||||
#where childblock is curly braced code block |
||||
|
||||
# clay -id "parent" -layout [dict create .padding [padding_all 8]] { |
||||
# clay_text "Hello World" [clay_textconfig {.fontsize 16}] |
||||
# clay -id "child" -config {.backgroundColor red} { |
||||
# # etc |
||||
# } |
||||
# } |
||||
|
||||
#for padding on a terminal - we are limited by cell_size - which is not square. (and may vary on terminals??) |
||||
# e.g punk::console::cell_size returns cell wxh |
||||
# -> 10x20 |
||||
# (either queried from terminal - or defaults to 10x20 if can't be queried) |
||||
#so the minimum 'even' padding we can have is 2 space for horizontal, 1 line vertical |
||||
#we can pad a minimum of 1 space horizontall (10 units) and a minimum of 1 line vertically (20 units) |
||||
# CLAY_PADDING {<l> <r> <t> <b>} |
||||
#how then should we handle .padding {16 16 8 8} - quantize by roundup to h 10 and v 20? |
||||
# -> {20 20 20 20} ? |
||||
# or round to nearest vertical and horizontal quanta? |
||||
# -> {20 20 0 0} |
||||
#either way - {16 16 16 16} goes to {20 20 20 20} - which is *close* to equal v h padding |
||||
# - but not perfect visually because fonts within a cell have baseline, topline etc internal padding too? |
||||
|
||||
#building a ui ? |
||||
#clay_begin_layout |
||||
# // build UI here |
||||
#set rendercommands [clay_end_layout] |
||||
#some_render_command $rendercommands |
||||
|
||||
|
||||
|
||||
|
||||
#eg2 (from introducing clay video https://www.youtube.com/watch?v=DYWTw19_8r4&t=2s) |
||||
#something like the following? |
||||
# (stopped at around the scroll point - need to work out console mouse features. punk::console::mouse_enable ...) |
||||
|
||||
#extracted out common layout 'sizing' for grow in both directions |
||||
#set layoutExpand { |
||||
# width CLAY_SIZING_GROW |
||||
# heigth CLAY_SIZING GROW |
||||
# } |
||||
#extracted out common background panel |
||||
#set contentBackgroundConfig { |
||||
# colour Term-grey |
||||
# frametype arc |
||||
# } |
||||
#proc RenderHeaderButton {} {} ;#?? |
||||
|
||||
#set documents [dict create\ |
||||
# Squirrels "The secret life of Squirrels"\ |
||||
# "Lorem Ipsum" "Orem ipsum dolor sit ..\netc blah"\ |
||||
# "Vacuum instructions" "Chapter 3: Getting Started"\ |
||||
# "Article 4" "Article 4"\ |
||||
# "Article 5" "Article 5"\ |
||||
# ] |
||||
|
||||
#set selectedDocumentIndex 0 |
||||
|
||||
|
||||
#clay_begin_layout |
||||
#clay -id "OuterContainer"\ |
||||
# -item [clay_rectangle {colour web-red}] |
||||
# -layout [clay_layout [dict create\ |
||||
# layoutDirection CLAY_TOP_TO_BOTTOM\ |
||||
# sizing $layoutExpand\ |
||||
# padding {16 16}\ |
||||
# childGap 16\ |
||||
# ]]\ |
||||
# { |
||||
# # Child elements |
||||
# clay -id "HeaderBar"\ |
||||
# -item [clay_rectangle $contentBackgroundConfig]\ |
||||
# -layout [clay_layout { |
||||
# sizing { |
||||
# height 60 |
||||
# width CLAY_SIZING_GROW |
||||
# } |
||||
# padding {8 8} |
||||
# childGap 8 |
||||
# childAlignment { |
||||
# y CLAY_ALIGN_Y_CENTER |
||||
# } |
||||
# }]\ |
||||
# { |
||||
# # Header buttons go here |
||||
# RenderheaderButton [clay_string "File"] |
||||
# RenderheaderButton [clay_string "Edit"] |
||||
# #push last 3 buttons to rhs by using a layout in between to take up the middle space |
||||
# CLAY -layout {sizing {width CLAY_SIZING_GROW}} {} |
||||
# RenderheaderButton [clay_string "Upload"] |
||||
# RenderheaderButton [clay_string "Media"] |
||||
# RenderheaderButton [clay_string "Support"] |
||||
# } |
||||
# clay -id "LowerContent"\ |
||||
# -layout [dict create sizing $layoutExpand childGap 16]\ |
||||
# { |
||||
# clay -id "Sidebar"\ |
||||
# -item [clay_rectangle $contentBackgroundConfig]\ |
||||
# -layout { |
||||
# layoutDirection CLAY_TOP_TO_BOTTOM |
||||
# padding {8 8} |
||||
# childgap {20} |
||||
# sizing { |
||||
# width = 60 |
||||
# height = CLAY_SIZING_GROW |
||||
# }\ |
||||
# }\ |
||||
# { |
||||
# #render dynamic data |
||||
# dict for {title data} $documents { |
||||
# clay -layout {padding {8 8}\ |
||||
# { |
||||
# #fontId, fontSize not really practical on terminal |
||||
# clay_text $title [clay_text_config { |
||||
# textColor cyan |
||||
# }] |
||||
# } |
||||
# } |
||||
# } |
||||
# clay -id "MainContent"\ |
||||
# -item [clay_rectangle $contentBackgroundConfig]\ |
||||
# -scroll {vertical true}\ |
||||
# -layout [dict create\ |
||||
# layoutDirection = CLAY_TOP_TO_BOTTOM\ |
||||
# childGap 20\ |
||||
# padding {16 16 20 20}\ |
||||
# sizing $layoutExpand\ |
||||
# ]\ |
||||
# { |
||||
# set selectedTitle [lindex [dict keys $documents] $selectedDocumentIndex] |
||||
# clay_text $selectedTitle [clay_text_config { |
||||
# textcolour {web-white bold} |
||||
# }] |
||||
# clay_text [dict get $documents $selectedTitle] [clay_text_config { |
||||
# textcolour {web-white} |
||||
# }] |
||||
# } |
||||
# } |
||||
# } |
||||
#set rendercommands [clay_end_layout] |
||||
|
||||
#CLAY_SIZING_GROW |
||||
#CLAY_SIZING_FIT ;#default |
||||
|
||||
tcl::namespace::eval punk::layout { |
||||
variable PUNKARGS |
||||
namespace eval argdoc { |
||||
variable PUNKARGS |
||||
namespace eval argdoc { |
||||
#non-colour SGR codes |
||||
set I "\x1b\[3m" ;# [a+ italic] |
||||
set NI "\x1b\[23m" ;# [a+ noitalic] |
||||
set B "\x1b\[1m" ;# [a+ bold] |
||||
set N "\x1b\[22m" ;# [a+ normal] |
||||
set T "\x1b\[1\;4m" ;# [a+ bold underline] |
||||
set NT "\x1b\[22\;24m\x1b\[4:0m" ;# [a+ normal nounderline] |
||||
} |
||||
} |
||||
|
||||
|
||||
#elementDeclaration |
||||
|
||||
#data structure (CLAY UIElement struct equivalent) |
||||
#set eg_element [dict create\ |
||||
# position {1 1}\ |
||||
# size {80 24}\ |
||||
# children [list]\ |
||||
#] |
||||
|
||||
|
||||
#elementConfig |
||||
#set eg_item [dict create\ |
||||
# type rectangle\ |
||||
# color {red bold}\ |
||||
# borderColor {yellow} |
||||
# frametype {}\ |
||||
#] |
||||
# etc |
||||
proc DrawRectangle {element} { |
||||
set position [dict get $element position] ;#x y |
||||
set size [dict get $element size] ;#width height |
||||
lassign $size w h |
||||
set bg [dict get $element color] |
||||
set borderColor [dict get $element borderColor] |
||||
set frametype [dict get $element frametype] |
||||
if {$frametype eq ""} { |
||||
#much faster than textblock::frame |
||||
set content [textblock::block $w $h "[a+ $bg] [a]"] |
||||
} else { |
||||
#slow - and frame background colours will always overlap the borders so we can never get a nicely filled arc frame for example |
||||
#The best bordered |
||||
set content [textblock::frame -type $frametype -ansibase [a+ $bg] -ansiborder [a+ $borderColor] -width $w -height $h " "] |
||||
} |
||||
} |
||||
proc RenderElement {element} { |
||||
|
||||
} |
||||
|
||||
|
||||
#TODO |
||||
#The clay_begin_layout - clay_end_layout structure suggests the main API may be better represented as an oo object maintaining state |
||||
#we may need to have multiple instances running concurrently |
||||
#Clay conceptually runs in 'immediate' mode - ie recalculating each full layout each time we need to render |
||||
|
||||
variable rendercommands |
||||
proc clay_begin_layout {} { |
||||
variable rendercommands |
||||
set rendercommands [dict create] |
||||
#...? |
||||
} |
||||
proc clay_end_layout {} { |
||||
variable rendercommands |
||||
|
||||
#...? |
||||
|
||||
return $rendercommands |
||||
} |
||||
|
||||
|
||||
namespace eval argdoc { |
||||
variable PUNKARGS |
||||
lappend PUNKARGS [list { |
||||
@id -id ::punk::layout::clay |
||||
@cmd -name punk::layout::clay |
||||
@opts |
||||
-id -type string |
||||
-item -type dict |
||||
-layout -type dict |
||||
-backgroundColor -type list -help\ |
||||
"ANSI colour codes as documented in punk::ansi::a?" |
||||
@values -min 0 -max 1 |
||||
childscript -type script |
||||
}] |
||||
} |
||||
#For initial proof of concept - we will use punk::args for *parsing* as well as documenting |
||||
#For final version - the extra overhead of punk::args::parse may not be suitable for large numbers of |
||||
#calls in 'immediate' mode - so punk::args::parse should be used on 'unhappy' paths only, |
||||
#with a fast switch statement used for actual option parsing. |
||||
#As performance is likely to be an issue - we should also avoid allowing 'prefixes' for arguments |
||||
proc clay {args} { |
||||
set argd [punk::args::parse $args withid ::punk::layout::clay] ;#temporary during concept development - todo: change to manual parsing for performance. |
||||
|
||||
} |
||||
# |
||||
|
||||
} |
||||
|
||||
|
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
# Secondary API namespace |
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
tcl::namespace::eval punk::layout::lib { |
||||
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase |
||||
tcl::namespace::path [tcl::namespace::parent] |
||||
|
||||
|
||||
#STEPS |
||||
#Fit Sizing -> Grow Sizing -> Positions -> Draw |
||||
#tree traversal |
||||
#(reverse breadth first) (breadth first) |
||||
# via OpenElement/CloseElement? (expand our grow containers |
||||
# into any available space) |
||||
|
||||
proc OpenElement {element} { |
||||
#pseudo... |
||||
#set layoutDirection $layoutconfig.layoutDirection |
||||
#if {$layoutDirection eq "CLAY_LEFT_TO_RIGHT"} { |
||||
#} else { |
||||
# #CLAY_TOP_TO_BOTTOM |
||||
#} |
||||
} |
||||
proc CloseElement {element} { |
||||
#element.parent.width += element.width |
||||
#element.parent.height += element.height |
||||
|
||||
} |
||||
|
||||
proc SizeContainersAlongAxis {is_x_axis totalSizeToDistribute} { |
||||
} |
||||
proc CalculateFinalLayout {} { |
||||
} |
||||
|
||||
|
||||
|
||||
} |
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
|
||||
|
||||
|
||||
#tcl::namespace::eval punk::layout::system { |
||||
#} |
||||
|
||||
|
||||
# == === === === === === === === === === === === === === === |
||||
# Sample 'about' function with punk::args documentation |
||||
# == === === === === === === === === === === === === === === |
||||
tcl::namespace::eval punk::layout { |
||||
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase |
||||
variable PUNKARGS |
||||
variable PUNKARGS_aliases |
||||
|
||||
lappend PUNKARGS [list { |
||||
@id -id "(package)punk::layout" |
||||
@package -name "punk::layout" -help\ |
||||
"EXPERIMENTAL - not done" |
||||
}] |
||||
|
||||
namespace eval argdoc { |
||||
#namespace for custom argument documentation |
||||
proc package_name {} { |
||||
return punk::layout |
||||
} |
||||
proc about_topics {} { |
||||
#info commands results are returned in an arbitrary order (like array keys) |
||||
set topic_funs [info commands [namespace current]::get_topic_*] |
||||
set about_topics [list] |
||||
foreach f $topic_funs { |
||||
set tail [namespace tail $f] |
||||
lappend about_topics [string range $tail [string length get_topic_] end] |
||||
} |
||||
#Adjust this function or 'default_topics' if a different order is required |
||||
return [lsort $about_topics] |
||||
} |
||||
proc default_topics {} {return [list Description *]} |
||||
|
||||
# ------------------------------------------------------------- |
||||
# get_topic_ functions add more to auto-include in about topics |
||||
# ------------------------------------------------------------- |
||||
proc get_topic_Description {} { |
||||
punk::args::lib::tstr [string trim { |
||||
package punk::layout |
||||
An experiment in using CLAY UI style layout on the terminal |
||||
INCOMPLETE... |
||||
status: notes and started framework only - nothing usable. |
||||
} \n] |
||||
} |
||||
proc get_topic_License {} { |
||||
return "MIT" |
||||
} |
||||
proc get_topic_Version {} { |
||||
return "$::punk::layout::version" |
||||
} |
||||
proc get_topic_Contributors {} { |
||||
set authors {{Julian Noble <julian@precisium.com.au}} |
||||
set contributors "" |
||||
foreach a $authors { |
||||
append contributors $a \n |
||||
} |
||||
if {[string index $contributors end] eq "\n"} { |
||||
set contributors [string range $contributors 0 end-1] |
||||
} |
||||
return $contributors |
||||
} |
||||
proc get_topic_concepts {} { |
||||
punk::args::lib::tstr -return string { |
||||
see Nic Barker's youtube video: How Clay's UI Layout Algorithm Works |
||||
https://www.youtube.com/watch?v=by9lQvpvMIc |
||||
} |
||||
} |
||||
# ------------------------------------------------------------- |
||||
} |
||||
|
||||
# we re-use the argument definition from punk::args::standard_about and override some items |
||||
set overrides [dict create] |
||||
dict set overrides @id -id "::punk::layout::about" |
||||
dict set overrides @cmd -name "punk::layout::about" |
||||
dict set overrides @cmd -help [string trim [punk::args::lib::tstr { |
||||
About punk::layout |
||||
}] \n] |
||||
dict set overrides topic -choices [list {*}[punk::layout::argdoc::about_topics] *] |
||||
dict set overrides topic -choicerestricted 1 |
||||
dict set overrides topic -default [punk::layout::argdoc::default_topics] ;#if -default is present 'topic' will always appear in parsed 'values' dict |
||||
set newdef [punk::args::resolved_def -antiglobs -package_about_namespace -override $overrides ::punk::args::package::standard_about *] |
||||
lappend PUNKARGS [list $newdef] |
||||
proc about {args} { |
||||
package require punk::args |
||||
#standard_about accepts additional choices for topic - but we need to normalize any abbreviations to full topic name before passing on |
||||
set argd [punk::args::parse $args withid ::punk::layout::about] |
||||
lassign [dict values $argd] _leaders opts values _received |
||||
punk::args::package::standard_about -package_about_namespace ::punk::layout::argdoc {*}$opts {*}[dict get $values topic] |
||||
} |
||||
} |
||||
# end of sample 'about' function |
||||
# == === === === === === === === === === === === === === === |
||||
|
||||
|
||||
# ----------------------------------------------------------------------------- |
||||
# register namespace(s) to have PUNKARGS,PUNKARGS_aliases variables checked |
||||
# ----------------------------------------------------------------------------- |
||||
# variable PUNKARGS |
||||
# variable PUNKARGS_aliases |
||||
namespace eval ::punk::args::register { |
||||
#use fully qualified so 8.6 doesn't find existing var in global namespace |
||||
lappend ::punk::args::register::NAMESPACES ::punk::layout |
||||
} |
||||
# ----------------------------------------------------------------------------- |
||||
|
||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||
## Ready |
||||
package provide punk::layout [tcl::namespace::eval punk::layout { |
||||
variable pkg punk::layout |
||||
variable version |
||||
set version 0.1.0 |
||||
}] |
||||
return |
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue