bar: clock to bottom above power; drop Archie's ball
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
2c65cf1138
commit
ee9e9ffbc7
1 changed files with 65 additions and 271 deletions
|
|
@ -1126,8 +1126,7 @@ in
|
||||||
|
|
||||||
// Archie — a black and tan dachshund with a red collar, living
|
// Archie — a black and tan dachshund with a red collar, living
|
||||||
// along the bottom of the screen. He trots about, wags, naps in
|
// along the bottom of the screen. He trots about, wags, naps in
|
||||||
// his bed, visits his bowl, and fetches a ball you can pick up
|
// his bed and visits his bowl.
|
||||||
// and fling with the mouse.
|
|
||||||
//
|
//
|
||||||
// The art is plain text, one character per pixel, so he can be
|
// The art is plain text, one character per pixel, so he can be
|
||||||
// redrawn by editing the picture instead of editing code. He walks
|
// redrawn by editing the picture instead of editing code. He walks
|
||||||
|
|
@ -1154,9 +1153,7 @@ in
|
||||||
"N": "#14100f", // nose and eye
|
"N": "#14100f", // nose and eye
|
||||||
"B": "#96602f", // kibble
|
"B": "#96602f", // kibble
|
||||||
"G": "#5a667a", // bed
|
"G": "#5a667a", // bed
|
||||||
"D": "#3a4454", // bed cushion
|
"D": "#3a4454" // bed cushion
|
||||||
"Y": "#c8d84a", // ball
|
|
||||||
"L": "#e4ee8c" // ball highlight
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Trotting: front leg forward, hind leg back, tail up. Paws
|
// Trotting: front leg forward, hind leg back, tail up. Paws
|
||||||
|
|
@ -1206,52 +1203,6 @@ in
|
||||||
"........TTT..........TTT....................",
|
"........TTT..........TTT....................",
|
||||||
"........TTTTT........TTTTT.................."
|
"........TTTTT........TTTTT.................."
|
||||||
]
|
]
|
||||||
// Galloping for the ball. A bound, not a trot: reaching, with
|
|
||||||
// the hind legs thrown back and the front legs stretched out
|
|
||||||
// ahead — then everything gathered under him. Same body and
|
|
||||||
// tail as walkB; it is entirely in the legs.
|
|
||||||
readonly property var runA: [
|
|
||||||
"...............................KKKKKKKK.....",
|
|
||||||
"..............................KKKKKKKKKK....",
|
|
||||||
"KKKK..........................KKKKKKKKKKK...",
|
|
||||||
"KKKK..........................KKKKK.KKKKK...",
|
|
||||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKK..TTKKKKK.",
|
|
||||||
".KKKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTTT.",
|
|
||||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTT..",
|
|
||||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTT.....",
|
|
||||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTKKKK..........",
|
|
||||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTTKKK..........",
|
|
||||||
"...KKKKKKKKKKKKKKKKKKKKKKKKTTTT.............",
|
|
||||||
".....KKKKKKKKKKKKKKKKKKKKKTTTT..............",
|
|
||||||
"....TTKKKKKKKKKKKKKKKKKKKTTTT...............",
|
|
||||||
".....TTTTT..............TTTT................",
|
|
||||||
"....TTTTT................TTTT...............",
|
|
||||||
"...TTTTT..................TTTT..............",
|
|
||||||
"..TTTTT....................TTTT.............",
|
|
||||||
"..TTTTT....................TTTT.............",
|
|
||||||
".TTTTTT....................TTTTTT..........."
|
|
||||||
]
|
|
||||||
readonly property var runB: [
|
|
||||||
"...............................KKKKKKKK.....",
|
|
||||||
"..............................KKKKKKKKKK....",
|
|
||||||
"KKKK..........................KKKKKKKKKKK...",
|
|
||||||
"KKKK..........................KKKKK.KKKKK...",
|
|
||||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKK..TTKKKKK.",
|
|
||||||
".KKKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTTT.",
|
|
||||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTT..",
|
|
||||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTT.....",
|
|
||||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTKKKK..........",
|
|
||||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTTKKK..........",
|
|
||||||
"...KKKKKKKKKKKKKKKKKKKKKKKKTTTT.............",
|
|
||||||
".....KKKKKKKKKKKKKKKKKKKKKTTTT..............",
|
|
||||||
"....TTKKKKKKKKKKKKKKKKKKKTTTT...............",
|
|
||||||
".........TTTTT........TTTT..................",
|
|
||||||
"..........TTTTT......TTTT...................",
|
|
||||||
"...........TTTTT....TTTT....................",
|
|
||||||
"............TTTTT..TTTT.....................",
|
|
||||||
"............TTTTT..TTTT.....................",
|
|
||||||
"............TTTTTTTTTTTT...................."
|
|
||||||
]
|
|
||||||
// Standing: walkA's planted legs, walkB's tail. Flipping
|
// Standing: walkA's planted legs, walkB's tail. Flipping
|
||||||
// between this and walkA is the wag.
|
// between this and walkA is the wag.
|
||||||
readonly property var wag: [
|
readonly property var wag: [
|
||||||
|
|
@ -1363,15 +1314,6 @@ in
|
||||||
"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG",
|
"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG",
|
||||||
"..GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.."
|
"..GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.."
|
||||||
]
|
]
|
||||||
readonly property var ballArt: [
|
|
||||||
"..YYY..",
|
|
||||||
".YLYYY.",
|
|
||||||
"YLYYYYY",
|
|
||||||
"YYYYYYY",
|
|
||||||
"YYYYYYY",
|
|
||||||
".YYYYY.",
|
|
||||||
"..YYY.."
|
|
||||||
]
|
|
||||||
|
|
||||||
property var frame: walkA
|
property var frame: walkA
|
||||||
|
|
||||||
|
|
@ -1395,79 +1337,18 @@ in
|
||||||
property int facing: 1 // 1 = right, -1 = left
|
property int facing: 1 // 1 = right, -1 = left
|
||||||
property string mode: "walk"
|
property string mode: "walk"
|
||||||
property real targetX: 0
|
property real targetX: 0
|
||||||
property string errand: "" // "" | "bowl" | "bed" | "ball"
|
property string errand: "" // "" | "bowl" | "bed"
|
||||||
property int hold: 0
|
property int hold: 0
|
||||||
// Ticks since he last got up. Past `tired` he takes himself
|
// Ticks since he last got up. Past `tired` he takes himself
|
||||||
// off to bed; the ball resets it, so a throw both wakes him
|
// off to bed.
|
||||||
// and buys him a fresh stretch of being up.
|
|
||||||
property int awake: 0
|
property int awake: 0
|
||||||
readonly property int tired: 2700 // 90s on his feet
|
readonly property int tired: 2700 // 90s on his feet
|
||||||
// Legs swap on distance covered, not on a tick count, so the
|
// Legs swap on distance covered, not on a tick count, so the
|
||||||
// gait stays in step whether he is ambling or running for the
|
// gait stays in step. 3 cells is exactly how far the feet
|
||||||
// ball. 3 cells is exactly how far the feet move in the art.
|
// move in the art.
|
||||||
property real stride: 0
|
property real stride: 0
|
||||||
property bool stepped: false
|
property bool stepped: false
|
||||||
|
|
||||||
// ── The ball ────────────────────────────────────────────
|
|
||||||
readonly property int ballSize: 7 * cell
|
|
||||||
property real ballX: 0
|
|
||||||
property real ballY: 0
|
|
||||||
property real ballVX: 0
|
|
||||||
property real ballVY: 0
|
|
||||||
property bool ballHeld: false // in your hand
|
|
||||||
property bool ballCarried: false // in his mouth
|
|
||||||
property bool ballThrown: false // he only fetches a fresh throw
|
|
||||||
property real lastBX: 0
|
|
||||||
property real lastBY: 0
|
|
||||||
property int carry: 0
|
|
||||||
|
|
||||||
// Where his mouth is, mirrored with him.
|
|
||||||
readonly property real mouthX: px + (facing > 0 ? 41 : 3) * cell
|
|
||||||
readonly property real mouthY: floorY - 13 * cell
|
|
||||||
|
|
||||||
// Exposed so Bar.qml can punch the ball out of the window's
|
|
||||||
// input mask — without it the whole surface is click-through
|
|
||||||
// here and you could never grab the thing.
|
|
||||||
readonly property real hitX: ballX - 6
|
|
||||||
readonly property real hitY: ballY - 6
|
|
||||||
readonly property real hitW: primary ? ballSize + 12 : 0
|
|
||||||
|
|
||||||
// At rest on the floor after a throw: that is his cue.
|
|
||||||
readonly property bool ballLoose: ballThrown && !ballHeld && !ballCarried
|
|
||||||
&& Math.abs(ballVX) < 0.3 && Math.abs(ballVY) < 0.3
|
|
||||||
&& ballY >= floorY - ballSize - 1
|
|
||||||
|
|
||||||
function ballTick() {
|
|
||||||
if (ballCarried) {
|
|
||||||
ballX = mouthX - ballSize / 2;
|
|
||||||
ballY = mouthY - ballSize / 2;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ballHeld) {
|
|
||||||
// Velocity comes from how fast you are dragging it, so
|
|
||||||
// letting go mid-swing throws it.
|
|
||||||
ballVX = Math.max(-45, Math.min(45, ballX - lastBX));
|
|
||||||
ballVY = Math.max(-45, Math.min(45, ballY - lastBY));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ballVY += 0.55;
|
|
||||||
ballX += ballVX;
|
|
||||||
ballY += ballVY;
|
|
||||||
let ground = floorY - ballSize;
|
|
||||||
if (ballY >= ground) {
|
|
||||||
ballY = ground;
|
|
||||||
if (Math.abs(ballVY) > 1.2) ballVY = -ballVY * 0.55;
|
|
||||||
else ballVY = 0;
|
|
||||||
ballVX *= 0.92; // rolling friction
|
|
||||||
if (Math.abs(ballVX) < 0.08) ballVX = 0;
|
|
||||||
}
|
|
||||||
if (ballY < 0) { ballY = 0; ballVY = Math.abs(ballVY) * 0.4; }
|
|
||||||
let bl = Theme.barWidth;
|
|
||||||
let br = archie.width - Theme.frameWidth - ballSize;
|
|
||||||
if (ballX < bl) { ballX = bl; ballVX = -ballVX * 0.6; }
|
|
||||||
if (ballX > br) { ballX = br; ballVX = -ballVX * 0.6; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── What he does next ───────────────────────────────────
|
// ── What he does next ───────────────────────────────────
|
||||||
function wander() {
|
function wander() {
|
||||||
mode = "walk";
|
mode = "walk";
|
||||||
|
|
@ -1475,7 +1356,7 @@ in
|
||||||
// Bed is not a random errand any more, it is what he does
|
// Bed is not a random errand any more, it is what he does
|
||||||
// when he has been up long enough. A dog sleeps most of
|
// when he has been up long enough. A dog sleeps most of
|
||||||
// the day; pottering about non-stop is the odd bit.
|
// the day; pottering about non-stop is the odd bit.
|
||||||
if (awake > tired && !ballCarried) {
|
if (awake > tired) {
|
||||||
errand = "bed";
|
errand = "bed";
|
||||||
targetX = bedLieX;
|
targetX = bedLieX;
|
||||||
return;
|
return;
|
||||||
|
|
@ -1483,9 +1364,8 @@ in
|
||||||
let dBowl = Math.abs(px - bowlStandX);
|
let dBowl = Math.abs(px - bowlStandX);
|
||||||
// Near enough to be worth it, and not already stood there
|
// Near enough to be worth it, and not already stood there
|
||||||
// — otherwise he marches half a minute for a snack, or
|
// — otherwise he marches half a minute for a snack, or
|
||||||
// rolls "go to the bowl" with his head already in it. No
|
// rolls "go to the bowl" with his head already in it.
|
||||||
// errands while he has the ball; he is busy.
|
if (Math.random() < 0.3 && dBowl > 80 && dBowl < 900) {
|
||||||
if (!ballCarried && Math.random() < 0.3 && dBowl > 80 && dBowl < 900) {
|
|
||||||
errand = "bowl";
|
errand = "bowl";
|
||||||
targetX = bowlStandX;
|
targetX = bowlStandX;
|
||||||
return;
|
return;
|
||||||
|
|
@ -1500,24 +1380,8 @@ in
|
||||||
px + dir * (150 + Math.random() * 550)));
|
px + dir * (150 + Math.random() * 550)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function chase() {
|
|
||||||
mode = "walk";
|
|
||||||
errand = "ball";
|
|
||||||
// Line his mouth up with it, approaching from whichever
|
|
||||||
// side he is already on.
|
|
||||||
let bc = ballX + ballSize / 2;
|
|
||||||
targetX = (px + cols * cell / 2 < bc) ? bc - 41 * cell : bc - 3 * cell;
|
|
||||||
targetX = Math.max(roamL - 60, Math.min(roamR + 60, targetX));
|
|
||||||
}
|
|
||||||
|
|
||||||
function arrive() {
|
function arrive() {
|
||||||
if (errand === "ball") {
|
if (errand === "bowl") {
|
||||||
ballCarried = true;
|
|
||||||
ballThrown = false;
|
|
||||||
carry = 400 + Math.random() * 500; // 13-30s of pride
|
|
||||||
mode = "idle";
|
|
||||||
hold = 40;
|
|
||||||
} else if (errand === "bowl") {
|
|
||||||
mode = "eat";
|
mode = "eat";
|
||||||
hold = 100 + Math.random() * 80;
|
hold = 100 + Math.random() * 80;
|
||||||
facing = 1;
|
facing = 1;
|
||||||
|
|
@ -1541,32 +1405,14 @@ in
|
||||||
if (placed || width <= 0) return;
|
if (placed || width <= 0) return;
|
||||||
placed = true;
|
placed = true;
|
||||||
px = roamL + Math.random() * (roamR - roamL);
|
px = roamL + Math.random() * (roamR - roamL);
|
||||||
ballX = Math.min(roamR, px + 300);
|
|
||||||
ballY = floorY - ballSize;
|
|
||||||
wander();
|
wander();
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
interval: 33; running: archie.primary; repeat: true
|
interval: 33; running: archie.primary; repeat: true
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
archie.ballTick();
|
|
||||||
archie.lastBX = archie.ballX;
|
|
||||||
archie.lastBY = archie.ballY;
|
|
||||||
|
|
||||||
// A thrown ball beats whatever else he was doing,
|
|
||||||
// sleeping included — that is how you wake him.
|
|
||||||
if (archie.ballLoose && archie.errand !== "ball") {
|
|
||||||
archie.awake = 0;
|
|
||||||
archie.chase();
|
|
||||||
}
|
|
||||||
archie.awake = archie.mode === "sleep" ? 0 : archie.awake + 1;
|
archie.awake = archie.mode === "sleep" ? 0 : archie.awake + 1;
|
||||||
|
|
||||||
if (archie.ballCarried && --archie.carry <= 0) {
|
|
||||||
archie.ballCarried = false;
|
|
||||||
archie.ballVX = 0;
|
|
||||||
archie.ballVY = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (archie.mode === "walk") {
|
if (archie.mode === "walk") {
|
||||||
// Arrival first: checking after the step makes him
|
// Arrival first: checking after the step makes him
|
||||||
// stride backwards when he is already there.
|
// stride backwards when he is already there.
|
||||||
|
|
@ -1574,21 +1420,15 @@ in
|
||||||
archie.arrive();
|
archie.arrive();
|
||||||
} else {
|
} else {
|
||||||
let dir = archie.targetX > archie.px ? 1 : -1;
|
let dir = archie.targetX > archie.px ? 1 : -1;
|
||||||
let run = archie.errand === "ball";
|
let sp = 1.5;
|
||||||
let sp = run ? 3.0 : 1.5;
|
|
||||||
archie.facing = dir;
|
archie.facing = dir;
|
||||||
archie.px += dir * sp;
|
archie.px += dir * sp;
|
||||||
archie.stride += sp;
|
archie.stride += sp;
|
||||||
// A gallop covers more ground per stride than
|
if (archie.stride >= 3 * archie.cell) {
|
||||||
// a trot, so the frames hold longer even though
|
|
||||||
// he is moving faster.
|
|
||||||
if (archie.stride >= (run ? 6 : 3) * archie.cell) {
|
|
||||||
archie.stride = 0;
|
archie.stride = 0;
|
||||||
archie.stepped = !archie.stepped;
|
archie.stepped = !archie.stepped;
|
||||||
}
|
}
|
||||||
archie.frame = run
|
archie.frame = archie.stepped ? archie.walkB : archie.walkA;
|
||||||
? (archie.stepped ? archie.runB : archie.runA)
|
|
||||||
: (archie.stepped ? archie.walkB : archie.walkA);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Breathing: in for a third of the cycle, then
|
// Breathing: in for a third of the cycle, then
|
||||||
|
|
@ -1659,39 +1499,6 @@ in
|
||||||
x: Math.round(archie.bowlX / archie.cell) * archie.cell
|
x: Math.round(archie.bowlX / archie.cell) * archie.cell
|
||||||
y: archie.floorY - height
|
y: archie.floorY - height
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite {
|
|
||||||
art: archie.ballArt; w: 7; h: 7
|
|
||||||
x: Math.round(archie.ballX / archie.cell) * archie.cell
|
|
||||||
y: Math.round(archie.ballY / archie.cell) * archie.cell
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grab handle for the ball, a little larger than the ball so
|
|
||||||
// it is catchable while it rolls.
|
|
||||||
MouseArea {
|
|
||||||
x: archie.hitX; y: archie.hitY
|
|
||||||
width: archie.hitW; height: archie.hitW
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
property real grabDX: 0
|
|
||||||
property real grabDY: 0
|
|
||||||
onPressed: (m) => {
|
|
||||||
let p = mapToItem(archie, m.x, m.y);
|
|
||||||
grabDX = p.x - archie.ballX;
|
|
||||||
grabDY = p.y - archie.ballY;
|
|
||||||
archie.ballCarried = false; // you may take it off him
|
|
||||||
archie.ballHeld = true;
|
|
||||||
}
|
|
||||||
onPositionChanged: (m) => {
|
|
||||||
if (!archie.ballHeld) return;
|
|
||||||
let p = mapToItem(archie, m.x, m.y);
|
|
||||||
archie.ballX = p.x - grabDX;
|
|
||||||
archie.ballY = p.y - grabDY;
|
|
||||||
}
|
|
||||||
onReleased: {
|
|
||||||
archie.ballHeld = false;
|
|
||||||
archie.ballThrown = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
@ -2011,16 +1818,6 @@ in
|
||||||
width: launcherPanel.visible ? launcherPanel.width : 0
|
width: launcherPanel.visible ? launcherPanel.width : 0
|
||||||
height: launcherPanel.visible ? launcherPanel.height : 0
|
height: launcherPanel.visible ? launcherPanel.height : 0
|
||||||
}
|
}
|
||||||
${lib.optionalString (!isMacbook) ''
|
|
||||||
// Archie's ball. The rest of this surface is click-through,
|
|
||||||
// so without a hole here you could never pick it up.
|
|
||||||
Region {
|
|
||||||
x: archieDog.hitX
|
|
||||||
y: archieDog.hitY
|
|
||||||
width: archieDog.hitW
|
|
||||||
height: archieDog.hitW
|
|
||||||
}
|
|
||||||
''}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
@ -4198,8 +3995,7 @@ in
|
||||||
precision: SystemClock.Minutes
|
precision: SystemClock.Minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Top cluster: logo, clock, workspaces — the three groups
|
// ── Top cluster: logo, workspaces — split by a hairline.
|
||||||
// that belong to "this machine, right now", split by hairlines.
|
|
||||||
// The server glance is NOT here: it anchors above the bottom
|
// The server glance is NOT here: it anchors above the bottom
|
||||||
// cluster instead, so adding a workspace grows this column
|
// cluster instead, so adding a workspace grows this column
|
||||||
// downward into empty space rather than shoving the stats.
|
// downward into empty space rather than shoving the stats.
|
||||||
|
|
@ -4244,58 +4040,6 @@ in
|
||||||
|
|
||||||
BarSep {}
|
BarSep {}
|
||||||
|
|
||||||
// Clock — HH over mm; "HH:mm" does not fit a 46px column.
|
|
||||||
Item {
|
|
||||||
id: clockText
|
|
||||||
width: Theme.barWidth
|
|
||||||
height: clockCol.height
|
|
||||||
property date now: sysClock.date
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: clockCol
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
SText {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
text: clockText.now.toLocaleTimeString(Qt.locale(), "HH")
|
|
||||||
font.pixelSize: 15
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
SText {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
text: clockText.now.toLocaleTimeString(Qt.locale(), "mm")
|
|
||||||
font.pixelSize: 15
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.base04
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anchors to the clock like every other dropdown
|
|
||||||
// anchors to its widget; the clamp in BarDropdown
|
|
||||||
// pulls it back on screen when it overhangs.
|
|
||||||
function openCalendar() {
|
|
||||||
bar.toggleDropdown(calPopup, function() {
|
|
||||||
let pos = clockText.mapToItem(bar.contentItem, 0, clockText.height / 2);
|
|
||||||
calPopup.dropdownY = pos.y;
|
|
||||||
calPopup.resetView();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
onClicked: clockText.openCalendar()
|
|
||||||
onEntered: {
|
|
||||||
if (bar.activeDropdown) {
|
|
||||||
if (bar.activeDropdown !== calPopup) clockText.openCalendar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BarSep {}
|
|
||||||
|
|
||||||
// Workspace dots: accent pill for the focused workspace,
|
// Workspace dots: accent pill for the focused workspace,
|
||||||
// dim dots otherwise. Stacked vertically now, so the
|
// dim dots otherwise. Stacked vertically now, so the
|
||||||
// focused pill grows along HEIGHT rather than width.
|
// focused pill grows along HEIGHT rather than width.
|
||||||
|
|
@ -4537,7 +4281,7 @@ in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Bottom cluster: status icons, tray, power button. Anchored
|
// ── Bottom cluster: status icons, tray, clock, power button. Anchored
|
||||||
// to the bottom edge; the server glance sits just above it and
|
// to the bottom edge; the server glance sits just above it and
|
||||||
// the OSD borrows that same slot while it is on screen.
|
// the OSD borrows that same slot while it is on screen.
|
||||||
Column {
|
Column {
|
||||||
|
|
@ -5005,6 +4749,56 @@ in
|
||||||
// as three clusters instead of one clump.
|
// as three clusters instead of one clump.
|
||||||
BarSep {}
|
BarSep {}
|
||||||
|
|
||||||
|
// Clock — HH over mm; "HH:mm" does not fit a 46px column.
|
||||||
|
Item {
|
||||||
|
id: clockText
|
||||||
|
width: Theme.barWidth
|
||||||
|
height: clockCol.height
|
||||||
|
property date now: sysClock.date
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: clockCol
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
SText {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
text: clockText.now.toLocaleTimeString(Qt.locale(), "HH")
|
||||||
|
font.pixelSize: 15
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
SText {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
text: clockText.now.toLocaleTimeString(Qt.locale(), "mm")
|
||||||
|
font.pixelSize: 15
|
||||||
|
font.weight: Font.Medium
|
||||||
|
color: Theme.base04
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anchors to the clock like every other dropdown
|
||||||
|
// anchors to its widget; the clamp in BarDropdown
|
||||||
|
// pulls it back on screen when it overhangs.
|
||||||
|
function openCalendar() {
|
||||||
|
bar.toggleDropdown(calPopup, function() {
|
||||||
|
let pos = clockText.mapToItem(bar.contentItem, 0, clockText.height / 2);
|
||||||
|
calPopup.dropdownY = pos.y;
|
||||||
|
calPopup.resetView();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: clockText.openCalendar()
|
||||||
|
onEntered: {
|
||||||
|
if (bar.activeDropdown) {
|
||||||
|
if (bar.activeDropdown !== calPopup) clockText.openCalendar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Power menu opener — bottom-left corner. Opens the same
|
// Power menu opener — bottom-left corner. Opens the same
|
||||||
// session menu as Super+L, which now unfolds from here.
|
// session menu as Super+L, which now unfolds from here.
|
||||||
Item {
|
Item {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue