* 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>
71 lines
2.1 KiB
QML
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
|
|
}
|
|
}
|
|
}
|