| 103 | } |
| 104 | |
| 105 | void ScriptScreen::draw(void) const |
| 106 | { |
| 107 | ScriptConsole& console = ScriptConsole::get(); |
| 108 | ScriptLogView& log = ScriptLogView::get(); |
| 109 | Gfx::ClearScreen(COLOR_BG); |
| 110 | |
| 111 | /* ---- the one tile: the transcript, headed by the run's status -------- */ |
| 112 | // The status line is the header's note rather than a tile of its own: it is |
| 113 | // one short string, and a half-screen tile that only ever showed the last |
| 114 | // thing the log already says is a duplicate, not a pane. |
| 115 | const bool cancelling = ScriptRunner::get().cancelRequested(); |
| 116 | const std::string note = mFinished ? (mOutcome.cancelled ? i18n::t("scripts.aborted", {mOutcome.scriptName}) |
| 117 | : mOutcome.exitValue == 0 ? i18n::t("scripts.success", {mOutcome.scriptName}) |
| 118 | : i18n::t("scripts.failed", {mOutcome.scriptName})) |
| 119 | : cancelling ? i18n::t("transfer.cancelling") |
| 120 | : [] { |
| 121 | std::string status = ScriptRunner::get().bridge().statusText(); |
| 122 | return status.empty() ? i18n::t("scripts.working") : status; |
| 123 | }(); |
| 124 | |
| 125 | const int bodyY = ScriptTile::frame(ScriptTile::LOG_X, ScriptTile::LOG_Y, ScriptTile::LOG_W, ScriptTile::LOG_H, mName, note); |
| 126 | const int innerX = ScriptTile::LOG_X + ScriptTile::PAD; |
| 127 | const int innerW = ScriptTile::LOG_W - 2 * ScriptTile::PAD; |
| 128 | |
| 129 | const std::string lead = mFinished ? (UiKit::buttonGlyph("A") + " " + i18n::t("scripts.close")) |
| 130 | : cancelling ? i18n::t("transfer.cancelling") |
| 131 | : (UiKit::buttonGlyph("B") + " " + i18n::t("main.to_cancel")); |
| 132 | // The way back to a dialog the user pushed aside: while the log has focus |
| 133 | // its card is not drawn at all, so this hint is the only thing on screen |
| 134 | // saying the script is still waiting for an answer. |
| 135 | const std::string peek = (sLogFocus && currentOverlay) ? UiKit::buttonGlyph("Y") + " " + i18n::t("scripts.back_to_dialog") + " " : ""; |
| 136 | const std::string hints = lead + " " + peek + SCROLL_GLYPHS + " " + i18n::t("scripts.scroll_logs"); |
| 137 | ScriptTile::hints(ScriptTile::LOG_X, ScriptTile::logBodyBottom(), ScriptTile::LOG_W, hints); |
| 138 | |
| 139 | // Scrollback marker, immediately to the left of the hints rather than in |
| 140 | // place of them or off at the row's far edge: the keys stay named while the |
| 141 | // pane is off the tail, which is exactly when the user is looking for them. |
| 142 | if (log.scrollBack() > 0) { |
| 143 | const std::string back = "-" + std::to_string(log.scrollBack()); |
| 144 | u32 bw, bh, hw; |
| 145 | Gfx::GetTextDimensions(ScriptTile::NOTE_SIZE, back.c_str(), &bw, &bh); |
| 146 | Gfx::GetTextDimensions(ScriptTile::NOTE_SIZE, hints.c_str(), &hw, NULL); |
| 147 | const int x = ScriptTile::LOG_X + ScriptTile::LOG_W - ScriptTile::PAD - (int)hw - (int)bw - 12; |
| 148 | Gfx::DrawText(ScriptTile::NOTE_SIZE, x, ScriptTile::logBodyBottom() + (ScriptTile::HINT_H - (int)bh) / 2, COLOR_ACCENT_LIGHT, back.c_str()); |
| 149 | } |
| 150 | |
| 151 | /* ---- progress bars, stacked up from above the hint line -------------- */ |
| 152 | ScriptConsole::Layer bars[ScriptTile::MAX_BARS]; |
| 153 | const size_t barCount = ScriptTile::collectBars(console.progress(), bars); |
| 154 | |
| 155 | const int logBottom = ScriptTile::logBodyBottom() - (int)barCount * ScriptTile::BAR_ROW_H; |
| 156 | for (size_t i = 0; i < barCount; i++) { |
| 157 | ScriptTile::bar(innerX, logBottom + (int)i * ScriptTile::BAR_ROW_H + 8, innerW, bars[i]); |
| 158 | } |
| 159 | |
| 160 | const int rowH = logRowHeight(); |
| 161 | const int listTop = bodyY; |
| 162 | log.setViewportRows((logBottom - listTop) / rowH); |
nothing calls this directly
no test coverage detected