From db90e7907c0ac01bfa2ec6f83797e6bc3ded781a Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 18 Nov 2020 08:56:20 -0800 Subject: [PATCH] Qt: yet more status... Fix the minor problem of the status lines moving up or down a tiny amount when using the condensed (statuslines:2) layout and the condition line changed from empty to non-empty or vice versa. The widget used as filler when no conditions are shown needed to have non-empty label text (single space suffices) and also has to have its font set to the same value as the rest of status. (I previously tried a label of " " and also "_" but had left the font with its default value.) The adjustments to the prefix string when the value of Xp/Exp ("Level" -> "Lvl" -> "L") or Score ("Score" -> "Scr" -> "S") was too wide needed some fixing up. If shrinkage was needed, it was setting the value multiple times and any extra times confused field highlighting because it seemed to be assigning same value rather than a changed one. For condensed layout that moves Alignment to the Characteristics line, add a vertical separator line between Charisma and Alignment. --- win/Qt/qt_stat.cpp | 92 ++++++++++++++++++++++++++++------------------ win/Qt/qt_stat.h | 2 + 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/win/Qt/qt_stat.cpp b/win/Qt/qt_stat.cpp index a3bed62c6..133655e86 100644 --- a/win/Qt/qt_stat.cpp +++ b/win/Qt/qt_stat.cpp @@ -58,12 +58,6 @@ // judgement, for alignment and dungeon location) and "ignore" (don't // highlight, to suppress the bogus highlighting that currently happens // when toggling 'showexp' or 'showscore'). -// The condensed display (statuslines:2; Alignment with Characteristics -// instead of with Conditions and Time,Score on HP,...,Gold row) has -// vertical padding when the Conditions row is empty, but having the -// first Cond come On or the last one go Off still makes the rest of -// status shift a little as if the padding (same size icon plus empty -// text label) was slightly taller than a regular Cond. // extern "C" { @@ -114,7 +108,7 @@ NetHackQtStatusWindow::NetHackQtStatusWindow() : score(this,"Score"), // if SCORE_ON_BOTL defined and 'showscore' option On /* last two rows: alignment followed by conditions (icons over text) */ align(this,"Alignment"), - blank2(this, ""), // used to prevent Conditions row from being empty + blank2(this, " "), // used to prevent Conditions row from being empty hunger(this,""), encumber(this,""), stoned(this,"Stone"), // major conditions @@ -133,6 +127,8 @@ NetHackQtStatusWindow::NetHackQtStatusWindow() : hline1(this), // separators hline2(this), hline3(this), + vline1(this), // vertical separator between Characteristics and Alignment + vline2(this), // padding for row 2 to match row 1's separator; not shown /* miscellaneous; not display fields */ cursy(0), first_set(true), @@ -206,12 +202,18 @@ NetHackQtStatusWindow::NetHackQtStatusWindow() : ride.setIcon(p_ride); // separator lines - hline1.setFrameStyle(QFrame::HLine|QFrame::Sunken); - hline2.setFrameStyle(QFrame::HLine|QFrame::Sunken); - hline3.setFrameStyle(QFrame::HLine|QFrame::Sunken); + hline1.setFrameStyle(QFrame::HLine | QFrame::Sunken); + hline2.setFrameStyle(QFrame::HLine | QFrame::Sunken); + hline3.setFrameStyle(QFrame::HLine | QFrame::Sunken); hline1.setLineWidth(1); hline2.setLineWidth(1); hline3.setLineWidth(1); + // vertical separators for condensed layout (statuslines:2) + vline1.setFrameStyle(QFrame::VLine | QFrame::Sunken); + vline2.setFrameStyle(QFrame::VLine | QFrame::Sunken); + vline1.setLineWidth(1); // separates Alignment from Charisma + vline2.setLineWidth(1); + vline2.hide(); // padding to keep row 2 aligned with row 1, never shown // set up last but shown first (above name) via layout below */ QHBoxLayout *hpbar = InitHitpointBar(); @@ -239,6 +241,7 @@ NetHackQtStatusWindow::NetHackQtStatusWindow() : charbox->addWidget(&cha); if (!spreadout) { // when condensed, include Alignment with Characteristics + charbox->addWidget(&vline1); // show a short vertical separator charbox->addWidget(&align); } vbox->addLayout(charbox); @@ -261,6 +264,7 @@ NetHackQtStatusWindow::NetHackQtStatusWindow() : statbox->addWidget(&score); // usually empty column #5 #endif statbox->addWidget(&gold); // columns 6 and maybe empty 7 + statbox->addWidget(&vline2); // padding between 6 and 7; not shown statbox->addWidget(&time); } vbox->addLayout(statbox); @@ -328,10 +332,19 @@ void NetHackQtStatusWindow::doUpdate() power.setFont(normal); ac.setFont(normal); level.setFont(normal); + blank1.setFont(normal); // padding gold.setFont(normal); time.setFont(normal); score.setFont(normal); align.setFont(normal); + // blank2 is used as a dummy condition when Alignment has been moved + // elsewhere (statuslines:2) and no other conditions currently apply; + // it has a blank icon with a label of a single space (if the label + // is completely empty, the rest of status shifts down a little when + // one or more real conditions replace it and shifts up again when + // all conditions are removed and this one is reinstated--as if "" is + // slightly taller than " ") + blank2.setFont(normal); hunger.setFont(normal); encumber.setFont(normal); stoned.setFont(normal); @@ -762,40 +775,46 @@ void NetHackQtStatusWindow::updateStats() // might be too wide to fit static const char *const lvllbl[3] = { "Level:", "Lvl:", "L:" }; QFontMetrics fm(level.label->font()); - int startingpass = ::flags.showexp ? 0 : 3; - for (int i = startingpass; i < 6; ++i) { - // passes 0,1,2 are with Exp, 3,4,5 without (3 should always fit) + for (int i = ::flags.showexp ? 0 : 3; i < 4; ++i) { + // passes 0,1,2 are with Exp, 3 is without Exp and always fits if (i < 3) { - buf.sprintf("%s%ld/%ld", lvllbl[i], - (long) u.ulevel, (long) u.uexp); - level.setLabel(buf, NetHackQtLabelledIcon::NoNum, - (long) u.uexp); + buf.sprintf("%s%ld/%ld", lvllbl[i], (long) u.ulevel, u.uexp); } else { buf.sprintf("%s%ld", lvllbl[i - 3], (long) u.ulevel); - level.setLabel(buf, NetHackQtLabelledIcon::NoNum, - (long) u.ulevel); } - // 2: allow a couple of pixels at either end to be clipped off - if (fm.size(0, buf).width() <= (2 + level.width() + 2)) + // +2: allow a couple of pixels at either end to be clipped off + if (fm.size(0, buf).width() <= (2 + level.label->width() + 2)) break; } + level.setLabel(buf, NetHackQtLabelledIcon::NoNum, + // if we intended to show Exp but must settle + // for Xp due to width, we still want to use + // Exp for setLabel()'s Up|Down highlighting + ::flags.showexp ? u.uexp : (long) u.ulevel); } buf.sprintf("/%d", u.uenmax); - power.setLabel("Pow:", u.uen, buf); + power.setLabel("Pow:", (long) u.uen, buf); ac.setLabel("AC:", (long) u.uac); - // label prefix used to be "Au:", tty uses "$:" - gold.setLabel("Gold:", money_cnt(g.invent)); + // gold prefix used to be "Au:", tty uses "$:"; never too wide to fit; + // practical limit due to carrying capacity limit is less than 300K + long goldamt = money_cnt(g.invent); + goldamt = std::max(goldamt, 0L); // sanity; core's botl() does likewise + goldamt = std::min(goldamt, 99999999L); // ditto + gold.setLabel("Gold:", goldamt); text = NULL; - if (u.ualign.type==A_CHAOTIC) { - align.setIcon(p_chaotic); - text = "Chaotic"; - } else if (u.ualign.type==A_NEUTRAL) { - align.setIcon(p_neutral); - text = "Neutral"; + if (u.ualign.type == A_LAWFUL) { + align.setIcon(p_lawful); + text = "Lawful"; + } else if (u.ualign.type == A_NEUTRAL) { + align.setIcon(p_neutral); + text = "Neutral"; } else { - align.setIcon(p_lawful); - text = "Lawful"; + // Unaligned should never happen but handle it sanely if it does + align.setIcon(p_chaotic); + text = (u.ualign.type == A_CHAOTIC) ? "Chaotic" + : (u.ualign.type == A_NONE) ? "unaligned" + : "other?"; } if (text) { // false: don't highlight as 'became lower' even if the internal @@ -833,11 +852,11 @@ void NetHackQtStatusWindow::updateStats() QFontMetrics fm(score.label->font()); for (int i = 0; i < 3; ++i) { buf.sprintf("%s%ld", scrlbl[i], pts); - score.setLabel(buf, NetHackQtLabelledIcon::NoNum, pts); - // 2: allow a couple of pixels at either end to be clipped off + // +2: allow couple of pixels at either end to be clipped off if (fm.size(0, buf).width() <= (2 + score.width() + 2)) break; } + score.setLabel(buf, NetHackQtLabelledIcon::NoNum, pts); // with Xp/Exp, we fallback to Xp if the shortest label prefix // is still too long; here we just show a clipped value and // let user either live with it or turn 'showscore' off (or @@ -863,17 +882,18 @@ void NetHackQtStatusWindow::updateStats() wis.highlightWhenChanging(); cha.highlightWhenChanging(); - gold.highlightWhenChanging(); hp.highlightWhenChanging(); power.highlightWhenChanging(); ac.highlightWhenChanging(); ac.lowIsGood(); level.highlightWhenChanging(); - align.highlightWhenChanging(); + gold.highlightWhenChanging(); // don't highlight 'time' because it changes almost continuously //time.highlightWhenChanging(); score.highlightWhenChanging(); + align.highlightWhenChanging(); + hunger.highlightWhenChanging(); encumber.highlightWhenChanging(); stoned.highlightWhenChanging(); diff --git a/win/Qt/qt_stat.h b/win/Qt/qt_stat.h index 6464be047..4f24c7027 100644 --- a/win/Qt/qt_stat.h +++ b/win/Qt/qt_stat.h @@ -131,6 +131,8 @@ private: QFrame hline1; // between dlevel and characteristics QFrame hline2; // between characteristics and regular status fields QFrame hline3; // between regular fields and time,score or conditions + QFrame vline1; // for statuslines:2, between Cha and Alignment + QFrame vline2; // for statuslines:2, padding between Gold and Time int cursy; -- 2.50.1