Increase wibox height depending on content - lua

I have a wibox with vertical layout and two text widgets:
local w = wibox {
width = 300,
height = 80,
ontop = true,
screen = mouse.screen,
}
w:setup {
{
id = 'header',
widget = wibox.widget.textbox
},
{
id = 'body',
widget = wibox.widget.textbox
},
id = 'text',
layout = wibox.layout.flex.vertical,
}
When string in 'body' textbox is short everything is ok, the widgets looks this way:
But if string is long, the size of the wibox is not enough to display it all so part of the string is cut out:
Is it possible to make wibox size change dynamically depending on size of the content?

I'm not quit sure what you want. If you want to adjust the height of the wibox for the content:
After you change the text of the textboxes, run something like the following code:
local t1 = w:get_children_by_id("header")[1]
local t2 = w:get_children_by_id("body")[1]
local h1 = t1:get_height_for_width(w.width, w.screen)
local h2 = t2:get_height_for_width(w.width, w.screen)
w.height = h1 + h2
If you want some extra empty space like in your first screenshot, you could add some number to the height. 42 is always a good answer. ;-)

Related

Awesome-WM - How to center a wibox.widget.textbox in a wibox.container?

I would like to know how to center a wibox.widget.textbox in wibox.container.background, because I would like to center the text in this image.
s.mytaglist = awful.widget.taglist {
screen = s,
filter = awful.widget.taglist.filter.all,
buttons = tag_list_buttons,
widget_template = {
id = 'background_role',
widget = wibox.container.background,
forced_width = 40,
{
layout = wibox.layout.fixed.horizontal,
{
id = 'text_role',
widget = wibox.widget.textbox,
},
},
},
}
I have try to add expand = "outside" but that doesn't work. Also, I doesn't want to use a wibox.container.margin, because it's not precise enough.
Thanks in advance for your help.
Set the align and valign properties of the textbox to "center" for horizontal and vertical center alignment.

How to make the width of a Text equal to the width of another implicitly measured Text?

There is a reader app with two Texts, one for the total number of pages and one for the current page. I want the width of the current page Text to be equal to the width of the total page Text, but the width of the total page Text is measured implicitly.
Currently, I can only specify the width like this:
Row {
Text(modifier = Modifier.width(32.dp), text = "1000") // total page
Slider(...)
Text(modifier = Modifier.width(32.dp), text = "1") // current page
}
To get render text layout, you can use onTextLayout. It has all information you may need, including size.
Then you can pass this size to second Text modifier:
var totalPageTextWidth by remember { mutableStateOf<Int?>(null) }
val widthModifier = totalPageTextWidth?.let { width ->
with(LocalDensity.current) {
Modifier.width(width.toDp())
}
} ?: Modifier
Text(
text = "1000",
onTextLayout = { totalPageTextWidth = it.size.width }
)
Text(
text = "1",
modifier = widthModifier
)

Jetpack Compose - Row Clipping Children When Width Increases

Here on the right , I have a list of items in a composable , Every item is inside a row , All the items are inside a column
All the children of the are getting clipped to fit the screen which I don't want , I want these items to render completely even if outside of screen since I have a zoomable container above them
As you can see how text in the text field is all in one line vertically rather than expanding the width , This is the problem
Code :
Row(
modifier = modifier.zIndex(3f),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
SimpleNodesList(
modifier = Modifier.padding(8.dp),
parentNode = state.center,
nodes = state.center.left,
renderRight = false,
)
SimpleNode(node = state.center, parentNode = null)
SimpleNodesList(
modifier = Modifier.padding(8.dp),
parentNode = state.center,
nodes = state.center.right,
renderLeft = false
)
}
Simple Nodes List is a column of rows , I have one column on left and one on the right , If the width of the left column increases , right row get's clipped by the screen
Using this modifier does the job for the row , In my case I also needed this layout modifier , wrapContentSize(unbounded = true) was working but children weren't clickable for some reason outside the bounds of the zoom container !
I also had to create a modifier zoomable rather than use a zoomable box , so the zoomable touch events would be dispatched on the this composable rather than the parent !
modifier = Modifier
.layout { measurable, constraints ->
val r =
measurable.measure(constraints = constraints.copy(maxWidth = Constraints.Infinity))
layout(r.measuredWidth, r.measuredHeight, placementBlock = {
r.placeWithLayer(0, 0, 0f) {
}
})
}
.wrapContentSize(unbounded = true)
If you are using hard-coded width for the text, applying Modifier.wrapContentSize() on every container might do the job
Use SimpleFlowRow in place of Row. It will fix the clipping issue.

Custom layout draws position 0 off screen when content is larger than screen

I'm trying to write a calendar/excel like screen where you can diagonally scroll the content and the column/row headers stay in place.
It's using a custom layout with placeables, where the layout is the whole drawable space, and then the events are drawn within the box where they are needed.
For example
Column 0 starts at X=0 Y=0, and each column is some width. So column 1 draws at 0, column 2 at 20, column 3 at 40 etc.
It all works correctly until the content size becomes larger than the visible width of the screen, the content that starts at position 0 starts getting drawn off screen, such as at -20. Almost like it's centering the content...
Here's some pics of whats happening when the size fits and then doesn't fit
I think it might have something to do with alignment lines in the custom layout but if it does i can't figure out what it wants me to do... I've tried alignments on the column set to start as well to no avail.
Here's a bare bones example of the problem
#Composable
fun ScheduleTest(columnList: List<String>) {
val headerWidth = 150
Column {
HeaderTest(columnList, headerWidth)
}
}
#Composable
fun HeaderTest(
columnList: List<String>,
headerWidth: Int,
headerContent: #Composable (title: String) -> Unit = { title ->
Text(title)
},
) {
val numberOfHeaders = columnList.count()
Layout(
content = {
columnList.forEach { header ->
Box {
headerContent(header)
}
}
}
) { measureables, constraints ->
val height = 45.dp.roundToPx()
val totalWidth = headerWidth * numberOfHeaders
val placeWithHeader = measureables.map { measurable ->
val placeable = measurable.measure(
constraints.copy(
minWidth = headerWidth,
maxWidth = headerWidth,
minHeight = height,
maxHeight = height,
)
)
placeable
}
layout(width = totalWidth, height = height) {
placeWithHeader.forEachIndexed { index, placeable ->
val offset = index * headerWidth
placeable.place(offset, 0)
}
}
}
}
I was helped with this on another forum but they didn't answer it here.
I wasn't constraining the main layouts width and height
val height = 45.dp.roundToPx()
val totalWidth = headerWidth * numberOfHeaders
the contract of layout is that the width/height passed to layout must
be in range of the constraints, if you violate that, your measurable
gets clamped to the constraints and your placement is centered in the
clamped space where your parent placed you
I needed to add constraints to it
val height = 45.dp.roundToPx().coerceIn(constraints.minHeight, constraints.maxHeight)
val totalWidth = headerWidth * numberOfHeaders.coerceIn(constraints.minWidth, constraints.maxWidth)

Awesome 3.5 - two panels (wiboxes) at the top

Before migrating to Awesome 3.5.1 I had two panels at the top of my screen (on top of each other, sort of) and none at the bottom. The code I used to achieve this pre-3.5.* is below:
-- Create the wibox
mywibox[s] = awful.wibox({ position = "top", height = "32", screen = s })
-- Add widgets to the wibox - order matters
mywibox[s].widgets = {
{
{
-- Upper left section
mylauncher,
mytaglist[s],
mypromptbox[s],
-- My custom widgets, separators etc...
layout = awful.widget.layout.horizontal.leftright
},
{
-- Upper right section
mylayoutbox[s],
mytextclock,
-- More widgets, separators, etc...
s == 1 and mysystray or nil,
layout = awful.widget.layout.horizontal.rightleft
},
},
{
-- Lower section (only the tasklist)
mytasklist[s],
},
layout = awful.widget.layout.vertical.flex,
height = mywibox[s].height
}
Now I'm having a hard time trying to figure out how to achieve the same with the 3.5 configuration. At the moment I use pretty basic one panel (with most of the widgets) on top, and one (with the tasklist) at the bottom. The code can be seen below:
-- Create the wibox
mywibox[s] = awful.wibox({ position = "top", height = "18", screen = s })
mywibox2[s] = awful.wibox({ position = "bottom", height = "18", screen = s })
-- Widgets that are aligned to the left
local left_layout = wibox.layout.fixed.horizontal()
left_layout:add(mylauncher)
left_layout:add(mytaglist[s])
left_layout:add(mypromptbox[s])
-- My custom widgets, separators, etc...
-- Widgets that are aligned to the right
local right_layout = wibox.layout.fixed.horizontal()
if s == 1 then right_layout:add(wibox.widget.systray()) end
-- My custom widgets, separators, etc...
right_layout:add(mytextclock)
right_layout:add(mylayoutbox[s])
-- Now bring it all together
local layout = wibox.layout.align.horizontal()
layout:set_left(left_layout)
layout:set_right(right_layout)
local layout2 = wibox.layout.align.horizontal()
layout2:set_middle(mytasklist[s])
mywibox[s]:set_widget(layout)
mywibox2[s]:set_widget(layout2)
If anyone has ideas how to edit my current rc.lua to make it work as the upper code did in Awesome 3.4.*, that'd be greatly appreciated.
You could try something like this, no idea if it does exactly what you want (32 is the height of your wibox according to your code):
local const = wibox.layout.constraint()
const:set_widget(layout)
const:set_strategy("exact")
const:set_height(32/2)
local l = wibox.layout.fixed.vertical()
l:add(const)
l:add(mytasklist[s])
mywibox[s]:set_widget(l)
First it creates a "constraint" layout which makes sure that the layout "layout" (the widgets that should be shown on the top) always get a size of 16px. Then it stacks this constraint layout ontop of the tasklist and displays the result in the wibox.
Some of this code could be shortened a bit in the latest version, but I am not sure if 3.5.1 has those convenience arguments already.
I've done similar with following code:
wiboxes["top"]=awful.wibox({position="top",height=26})
local top_layout = wibox.layout.fixed.horizontal()
sublayout["cpu"] = wibox.layout.fixed.horizontal()
for i=2,3 do
sublayout["cpu" .. i] = wibox.layout.fixed.horizontal()
sublayout["cpu" .. i]:add(graphs["cpu"]..i) -- the graphs table already initialized
sublayout["cpu" .. i]:add(textboxes["cpu"]..i) -- textboxes table already initialized
sublayout["cpu"]:add(sublayout["cpu"..i)
end
.....
top_layout:add(sublayout["cpu"])
.....
wiboxes["top"]:set_widget(top_layout)
With this code I've two graphs and textboxes to see the CPUs usage (every core), first is on top, second is down. It should work with taglist or any other widget.

Resources