Compositing: Why do Layer.X() and Layer.Y() increase layer position instead of setting it? #597
-
|
I played around with composition in Bubbletea today and am genuinely very impressed. I noticed something though: I saved a layer in the model so i can move it in the update method. But instead of following my cursor it flew into space. Is saving layers in a model an anti-pattern that you want to discourage and should i instead create new layers on each render? My example code: package main
import (
"fmt"
"os"
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/charmbracelet/x/exp/charmtone"
)
type model struct {
pickles *lipgloss.Layer
melon *lipgloss.Layer
}
func main() {
p := tea.NewProgram(initialModel())
if _, err := p.Run(); err != nil {
fmt.Printf("Alas, there's been an error: %v", err)
os.Exit(1)
}
}
func initialModel() model {
return model{
pickles: lipgloss.NewLayer(newCard(false, "Pickles")).Z(5),
melon: lipgloss.NewLayer(newCard(false, "Bitter Melon")).Z(1),
}
}
func (m model) Init() tea.Cmd {
return nil
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if s := msg.String(); s == "ctrl+c" || s == "q" || s == "esc" {
return m, tea.Quit
}
case tea.MouseMsg:
// Need to subtract the old position first, to get proper placement.
m.pickles.X(msg.Mouse().X - m.pickles.GetX()).Y(msg.Mouse().Y - m.pickles.GetY())
return m, nil
}
// Return the updated model to the Bubble Tea runtime for processing.
// Note that we're not returning a command.
return m, nil
}
// newCard creates a little card with rounded borders and a text label.
func newCard(darkMode bool, text string) string {
lightDark := lipgloss.LightDark(darkMode)
return lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(charmtone.Charple).
Foreground(lightDark(charmtone.Iron, charmtone.Butter)).
Height(9).
Width(16).
PaddingTop(3).
Align(lipgloss.Center).
Render(text)
}
func (m model) View() tea.View {
var v tea.View
v.AltScreen = true
v.MouseMode = tea.MouseModeAllMotion
canvas := lipgloss.NewCanvas(
m.pickles,
)
v.SetContent(canvas)
return v
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
|
Keep an eye out for #591. With that being said, some of the concerns you've raised I think are being addressed. Additionally, see charmbracelet/bubbletea#1549. The combo of both, once complete, should make interacting with layers easier, for more complex apps. The newest planned changes include layer definitions themselves only being relative, but when combined into a compositor, being calculated in an absolute fashion, so you can use the new
Technically, yes, though if the generation of that layer is very compute-heavy for some reason (really shouldn't be, if your |
Beta Was this translation helpful? Give feedback.
Keep an eye out for #591. With that being said, some of the concerns you've raised I think are being addressed. Additionally, see charmbracelet/bubbletea#1549.
The combo of both, once complete, should make interacting with layers easier, for more complex apps. The newest planned changes include layer definitions themselves only being relative, but when combined into a compositor, being calculated in an absolute fashion, so you can use the new
OnMousecallback (previously, a canvas would handle hit detection usingHit(x. y int) (layerId string). That solution means you don't have to deal with absolute coordinates, and only relative coordinates to your layer.