Files
omarchy/shell/plugins/panels/elsewhen/ArcText.qml
T
David Heinemeier HanssonandClaude Opus 5.5 e7218e36f2 Move Elsewhen into Omarchy as omarchy.elsewhen (#13429)
* Move Elsewhen into Omarchy as omarchy.elsewhen

The world clock ships in the shell tree instead of its own package. A
migration renames existing bar entries with their settings and removes
the retired package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Remove Elsewhen's shelved Earth row, overlap band and sky tint

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Tidy Elsewhen's models, data helper and docs, and drop currency

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Restructure Elsewhen's panel and globe on the shared shell components

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Show Elsewhen's bar globe upright

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Use the shared city search for Elsewhen's globe jump bar

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep legacy Elsewhen entries single and retry offline geocodes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fetch Elsewhen's weather with curl instead of a Python helper

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 21:15:00 +02:00

71 lines
2.1 KiB
QML

import QtQuick
import qs.Commons
import "Arc.js" as Arc
// One line of text arched over what sits below it, each character turned to
// follow the curve. A Text per character keeps rendering identical to the
// neighbouring Text items, which a Canvas would not. No eliding.
Item {
id: root
property string text: ""
// How far the ends drop below the middle.
property real rise: 6
property string fontFamily: Style.font.family
property int pixelSize: Style.font.caption
property color color: Color.foreground
FontMetrics {
id: metrics
font.family: root.fontFamily
font.pixelSize: root.pixelSize
}
readonly property var glyphs: text.split("")
readonly property var placed: {
// advanceWidth does not register the font as a dependency.
var _ = metrics.font.family + metrics.font.pixelSize
var widths = []
for (var i = 0; i < glyphs.length; i++) widths.push(metrics.advanceWidth(glyphs[i]))
return Arc.layout(widths, rise, false)
}
// Room for the end characters' corners once they are turned.
readonly property real slack: Math.round(metrics.height / 2)
implicitWidth: Math.ceil(placed.width) + 2 * slack
implicitHeight: Math.ceil(placed.height + metrics.height)
readonly property real originX: (width - placed.width) / 2
Repeater {
model: root.glyphs.length
Text {
required property int index
// The count changes a beat before the arrays behind it do.
readonly property string glyph: root.glyphs[index] || ""
readonly property var spot: root.placed.chars[index] || { x: 0, y: 0, rotation: 0 }
// Exactly one advance wide, so the glyph's middle is where the arc put it.
width: metrics.advanceWidth(glyph)
height: metrics.height
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
x: root.originX + spot.x
y: spot.y
rotation: spot.rotation
transformOrigin: Item.Center
textFormat: Text.PlainText
text: glyph
color: root.color
font.family: root.fontFamily
font.pixelSize: root.pixelSize
renderType: Text.QtRendering // native rendering ignores the rotation
}
}
}