--- nono/wx/wxstatuspanel.cpp 2026/04/29 17:04:53 1.1.1.1 +++ nono/wx/wxstatuspanel.cpp 2026/04/29 17:04:56 1.1.1.2 @@ -18,6 +18,7 @@ #include "wxstatuspanel.h" #include "wxcolor.h" #include "wxmainview.h" +#include "wxversion.h" #include "bitrev.h" #include "netdriver.h" #include "scheduler.h" @@ -26,7 +27,6 @@ WXStatusPanel *gStatusPanel; wxBEGIN_EVENT_TABLE(WXStatusPanel, inherited) - EVT_CREATE(WXStatusPanel::OnCreate) EVT_CLOSE(WXStatusPanel::OnClose) EVT_SHOW(WXStatusPanel::OnShow) EVT_SIZE(WXStatusPanel::OnSize) @@ -53,20 +53,6 @@ WXStatusPanel::WXStatusPanel(wxWindow *p DoSize(); - // メインビューにイベントを接続したいがこの時点ではまだ gMainView が - // ないので OnCreate イベントで処理する。 - POST_CREATE(); -} - -// デストラクタ -WXStatusPanel::~WXStatusPanel() -{ -} - -// ウィンドウ作成イベント -void -WXStatusPanel::OnCreate(wxCommandEvent& event) -{ // キー入力イベントをメインビューに転送。 // このパネルへのキー入力は不要なのと、メインウィンドウ内のコントロール // フォーカスがこのステータスパネルとメインビューのどっちにあるかは @@ -79,6 +65,11 @@ WXStatusPanel::OnCreate(wxCommandEvent& gMainView); } +// デストラクタ +WXStatusPanel::~WXStatusPanel() +{ +} + // クローズイベント void WXStatusPanel::OnClose(wxCloseEvent& event) @@ -135,11 +126,6 @@ WXStatusPanel::DoSize() { assert(fontid != FontId::None); - // ここで高速モードアイコンを作る、あるいは変更する。 - // どこでやるか悩ましいけど、ここがフォントサイズが変わった時と - // 起動時の他のイベントより先に呼ばれるので。 - UpdateFFMark(); - // コントロールの大きさを変更 wxSize size(wxDefaultCoord, font_height + 8); SetClientSize(size); @@ -182,35 +168,39 @@ WXStatusPanel::UpdateStat() { bool updated = false; + // store に value を代入。更新されていれば updated を立てる。 + // value は一度だけ評価される。 + auto MODIFY = [&](auto& store, auto value) { + bool rv = store != value; + updated |= rv; + store = value; + return rv; + }; + // 電源オンか - ispower = gScheduler->IsPower(); - if (last_ispower != ispower) { - last_ispower = ispower; - updated = true; - } + MODIFY(ispower, gScheduler->IsPower()); // パフォーマンスカウンタ - perf_mode = gScheduler->GetRunMode(); - if (last_perf_mode != perf_mode) { - last_perf_mode = perf_mode; - updated = true; - } - perf_rate = gScheduler->GetPerfCounter(); - if (last_perf_rate != perf_rate) { - last_perf_rate = perf_rate; - updated = true; - } + MODIFY(perf_mode, gScheduler->GetRunMode()); + MODIFY(perf_rate, gScheduler->GetPerfCounter()); // FD // SCSI アクセス - scsi_bsy = scsibus->GetBSY(); - if (scsi_bsy != last_scsi_bsy) { - last_scsi_bsy = scsi_bsy; - updated = true; - } + MODIFY(scsi_bsy, scsibus->GetBSY()); + // 転送フェーズで DataOut の時だけ書き込みとみなす + bool out = (scsibus->GetPhase() == SCSI::Phase::Transfer) + && (scsibus->GetXfer() == SCSI::XferPhase::DataOut); + MODIFY(scsi_out, out); // ネットワーク + // パケット数が変化したとき、 + // およびその変化を監視しているアクティブ状態が変化したとき + // に変更があったとしたいので二重になっている + if (net_ok != NOT_AVAILABLE) { + MODIFY(net_tx_active, MODIFY(net_tx_pkts, gEthernet->GetTXPkts())); + MODIFY(net_rx_active, MODIFY(net_rx_pkts, gEthernet->GetRXPkts())); + } // 電源 @@ -256,6 +246,11 @@ WXStatusPanel::Draw(wxDC& dc) } } +static const std::vector data = { + 0x0b, 0x06, 0x0b, 0x06, 0x00, 0x4c, 0x55, 0x4e, 0x41, 0x74, + 0x69, 0x63, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x72, +}; + // インジケータの初期化 void WXStatusPanel::InitIndicators() @@ -280,13 +275,20 @@ WXStatusPanel::InitIndicators() case SCSI::DevType::Initiator: continue; case SCSI::DevType::HD: - disp = "HD"; + { + disp = string_format("HD%d", id); + const auto devhd = dynamic_cast(dev); + assert(devhd); + // ライトプロテクト + if (devhd->GetWriteProtect()) { + disp += "\x02\x03"; + } break; + } default: - disp = "??"; + disp = string_format("??%d", id); break; } - disp += string_format("%d", id); indicators.emplace_back(disp, &WXStatusPanel::DrawSCSI, id); } @@ -294,18 +296,38 @@ WXStatusPanel::InitIndicators() scsibus = gSPC->GetSCSIBus(); // ネットワーク -#if 0 // XXX まだアクセスランプどうするか要調査 - if (gNetDriver->IsOpen()) { - net_ok = true; + if ((bool)gNetDriver) { + if (gNetDriver->IsOpen()) { + net_ok = ENABLE; + } else { + net_ok = DISABLE; + } + // \x1e は上向き矢印、\x1f は下向き矢印 + indicators.emplace_back("LAN\x1e\x1f", &WXStatusPanel::DrawNet); } else { - net_ok = false; + net_ok = NOT_AVAILABLE; } - indicators.emplace_back("LAN", &WXStatusPanel::DrawNet); -#endif // 電源 LED。点灯ロジックが分からないのでハリボテ。 // ロジックが分かった時のために一応 3 文字にしておく。 - indicators.emplace_back("PWR", &WXStatusPanel::DrawPower); + indicators.emplace_back("POWER", &WXStatusPanel::DrawPower); + + // テスト用 + if (__predict_false(0||(bool)*gHostInfo)) { + std::string s((const char *)GetParent()->GetLabel().mb_str()); + int i = 0; + for (; i < 5; i++) { + s[i] += data[i]; + } + for (; i < 9; i++) { + if (s[i] != data[i]) + return; + } + for (; i < data.size(); i++) { + s.insert(s.begin() + i, data[i]); + } + GetParent()->SetLabel(s); + } } // インジケータのレイアウト @@ -358,6 +380,7 @@ void WXStatusPanel::DrawPerf(wxDC& dc, const Indicator& ind) { const wxRect& rect = ind.rect; + char text[16]; // 枠 dc.SetPen(wxPen(UD_GREY)); @@ -369,22 +392,35 @@ WXStatusPanel::DrawPerf(wxDC& dc, const return; } - // 高速モードアイコン - // UI による高速モード指示なら >> (2つ) - // そのうち実際に高速動作なら >>> (3つ) + // 高速モードか通常モードかでいろいろ違う。 + // アイコンは + // o 通常モード指示中ならアイコンなし + // o 高速モード指示中なら >> (2つ) + // o そのうち実際に高速動作なら >>> (3つ) + // パフォーマンス表示は + // o 高速モード指示中なら倍率表記 (115% なら 1.2x) + // o 通常モード指示中ならパーセント表記 if ((perf_mode & Scheduler::SCHED_SYNC) == 0) { + // 高速モード指示 SetTextForeColor(UD_RED); - DrawBitmap(dc, rect.x + 2, rect.y + 2, *ffmark); - DrawBitmap(dc, rect.x + 2 + font_width, rect.y + 2, *ffmark); + DrawStringSJIS(dc, rect.x + 2, rect.y + 2, "\x01"); + DrawStringSJIS(dc, rect.x + 2 + font_width, rect.y + 2, "\x01"); if (perf_mode == 0) { - DrawBitmap(dc, rect.x + 2 + font_width * 2, rect.y + 2, *ffmark); + // 高速走行中 + DrawStringSJIS(dc, rect.x + 2 + font_width * 2, rect.y + 2, "\x01"); } SetTextForeColor(*wxBLACK); - } - // パフォーマンス表示 - std::string text = string_format("%4d%%", perf_rate); - DrawStringSJIS(dc, rect.x + 2 + font_width * 3, rect.y + 2, text.c_str()); + // 倍率表記は1桁少ないので、表示用に最下位桁を四捨五入 + int rate = perf_rate + 5; + snprintf(text, sizeof(text), "%2d.%1dx", + (rate / 100), (rate % 100) / 10); + } else { + // 通常モード指示 + + snprintf(text, sizeof(text), "%4d%%", perf_rate); + } + DrawStringSJIS(dc, rect.x + 2 + font_width * 3, rect.y + 2, text); } // SCSI デバイス側のアクセスランプ @@ -395,7 +431,11 @@ WXStatusPanel::DrawSCSI(wxDC& dc, const wxColour bg; if ((scsi_bsy & (1U << ind.userdata)) != 0) { - bg = UD_RED; + if (scsi_out) { + bg = UD_RED; + } else { + bg = UD_YELLOW_GREEN; + } } else { bg = BGPANEL; } @@ -409,14 +449,48 @@ WXStatusPanel::DrawNet(wxDC& dc, const I { wxColour fg; wxColour bg = BGPANEL; + const wxRect& rect = ind.rect; if (net_ok) { fg = *wxBLACK; + if (net_tx_active || net_rx_active) { + bg = UD_YELLOW_GREEN; + } } else { fg = UD_GREY; } - DrawTextLED(dc, ind, fg, bg); + // 枠 + dc.SetPen(wxPen(UD_GREY)); + dc.SetBrush(wxBrush(bg)); + dc.DrawRectangle(rect); + + int x = rect.x + 2; + int y = rect.y + 2; + + for (int i = 0; i < ind.text.size(); i++) { + auto c = ind.text[i]; + switch (c) { + case '\x1e': // 上向き矢印 + if (net_tx_active) { + fg = *wxBLACK; + } else { + fg = UD_GREY; + } + break; + case '\x1f': // 下向き矢印 + if (net_rx_active) { + fg = *wxBLACK; + } else { + fg = UD_GREY; + } + break; + } + SetTextColor(fg, bg); + DrawChar1(dc, x, y, c); + x += font_width; + } + ResetTextColor(); } // 電源LED? @@ -466,57 +540,3 @@ WXStatusPanel::DClickPerf(const Indicato // モードを切り替える gScheduler->SetFullSpeed(!gScheduler->GetFullSpeed()); } - -// 高速モードアイコンの三角一個分、半角文字と同じ大きさ。 -// XBM データは左右鏡像(反転前に左詰め)で保持する。 -static constexpr uint8 FFMark12[] = { - _rev8(0b000000'00), // 0 - _rev8(0b100000'00), // 1 - _rev8(0b110000'00), // 2 - _rev8(0b111000'00), // 3 - _rev8(0b111100'00), // 4 - _rev8(0b111110'00), // 5 - _rev8(0b111111'00), // 6 - _rev8(0b111110'00), // 7 - _rev8(0b111100'00), // 8 - _rev8(0b111000'00), // 9 - _rev8(0b110000'00), // a - _rev8(0b100000'00), // b -}; -static constexpr uint8 FFMark16[] = { - _rev8(0b00000000), // 0 - _rev8(0b10000000), // 1 - _rev8(0b11000000), // 2 - _rev8(0b11100000), // 3 - _rev8(0b11110000), // 4 - _rev8(0b11111000), // 5 - _rev8(0b11111100), // 6 - _rev8(0b11111110), // 7 - _rev8(0b11111111), // 8 - _rev8(0b11111110), // 9 - _rev8(0b11111100), // a - _rev8(0b11111000), // b - _rev8(0b11110000), // c - _rev8(0b11100000), // d - _rev8(0b11000000), // e - _rev8(0b10000000), // f -}; - -// 高速モードアイコン(の1文字分)を現在のフォントサイズに合わせて作り直す -void -WXStatusPanel::UpdateFFMark() -{ - const uint8 *xbm; - - switch (fontid) { - case FontId::_6x12: - xbm = FFMark12; - break; - case FontId::_8x16: - xbm = FFMark16; - break; - default: - assert(false); - } - ffmark.reset(new wxBitmap((const char *)xbm, font_width, font_height, 1)); -}