--- nono/wx/wxstatuspanel.cpp 2026/04/29 17:05:19 1.1.1.7 +++ nono/wx/wxstatuspanel.cpp 2026/04/29 17:05:57 1.1.1.16 @@ -19,22 +19,153 @@ #include "wxstatuspanel.h" #include "fontmanager.h" -#include "wxcolor.h" #include "wxmainframe.h" #include "wxmainview.h" #include "wxuimessage.h" -#include "wxversion.h" #include "fdc.h" #include "hostnet.h" +#include "mpu.h" #include "newsctlr.h" #include "power.h" -#include "spc.h" +#include "scsi.h" +#include "scsidomain.h" #include "syncer.h" +#include "virtio_block.h" +#include "virtio_scsi.h" + +// +// インジケータ情報 (ほぼ構造体) +// +class Indicator +{ + public: + // インジケータの識別子 + enum { + NONE = 0, + PERF, + POWER, + SCSI0, + SCSI1, + SCSI2, + SCSI3, + SCSI4, + SCSI5, + SCSI6, + SCSI7, + VBLK0, + VBLK1, + VBLK2, + VBLK3, + VBLK4, + VBLK5, + VBLK6, + VBLK7, + LAN0, + LAN1, + FDD0, + FDD1, + FDD2, + FDD3, + NEWSLED1, + NEWSLED2, + }; + protected: + using dispfunc_t = void (WXStatusPanel::*)(const Indicator *); + using eventfunc_t = void (WXStatusPanel::*)(const Indicator *); + public: + Indicator() { } + // 文字列の長さだけ指定する場合 + Indicator(int id_, dispfunc_t draw_, int minlen_, Status *stat_) { + id = id_; + draw = draw_; + stat = stat_; + minlen = minlen_; + } + // 文字列で指定する場合 + Indicator(int id_, dispfunc_t draw_, const std::string& text_, + Status *stat_) + : Indicator(id_, draw_, text_.length(), stat_) + { + text = text_; + } + virtual ~Indicator(); + + // インジケータ識別子 + int id {}; + + // 対応する状態 + Status *stat {}; + + // 枠内の最小文字列長。 + // 枠の大きさはこの文字列長と text.length() の長いほうで描画される。 + int minlen {}; + + // 表示する文字列。 + std::string text {}; + + // 描画関数 (必須) + dispfunc_t draw {}; + + // ダブルクリックの処理関数 (必要なら) + eventfunc_t dclick {}; + + // コンテキストメニューの処理関数 (必要なら) + eventfunc_t contextmenu {}; + + // 対応するデバイス (必要なら) + Device *dev {}; + + // ToolTip を表示するためのダミーパネル + wxPanel *panel {}; + + // 枠の位置と大きさは panel.GetRect() で取得できる (実行時に計算する) + Rect rect {}; + + public: + // SCSI なら SCSI ID を返す。そうでなければ -1 を返す。 + int GetSCSIID() const; + + // FDD ならユニット番号を返す。そうでなければ -1 を返す。 + int GetFDUnit() const; +}; + +// デストラクタ +Indicator::~Indicator() +{ +} + +// SCSI なら SCSI ID を返す。そうでなければ -1 を返す。 +int +Indicator::GetSCSIID() const +{ + int scsiid = id - SCSI0; + if (0 <= scsiid && scsiid <= 7) { + return scsiid; + } else { + return -1; + } +} + +// FDD ならユニット番号を返す。そうでなければ -1 を返す。 +int +Indicator::GetFDUnit() const +{ + int unit = id - FDD0; + if (0 <= unit && unit <= 3) { + return unit; + } else { + return -1; + } +} + + +// +// ステータスパネル +// wxBEGIN_EVENT_TABLE(WXStatusPanel, inherited) EVT_CLOSE(WXStatusPanel::OnClose) EVT_SHOW(WXStatusPanel::OnShow) - EVT_SIZE(WXStatusPanel::OnSize) EVT_TIMER(wxID_ANY, WXStatusPanel::OnTimer) EVT_LEFT_DCLICK(WXStatusPanel::OnLeftDClick) EVT_CONTEXT_MENU(WXStatusPanel::OnContextMenu) @@ -52,6 +183,8 @@ WXStatusPanel::WXStatusPanel(wxWindow *p : inherited(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, STATUS_PANEL_STYLE) { + SetName("WXStatusPanel"); + timer.SetOwner(this); power = GetPowerDevice(); @@ -60,6 +193,7 @@ WXStatusPanel::WXStatusPanel(wxWindow *p // インジケータ用のパラメータを用意。 InitIndicators(); + SetAutoLayout(true); FontChanged(); // キー入力イベントをメインビューに転送。 @@ -70,10 +204,9 @@ WXStatusPanel::WXStatusPanel(wxWindow *p // キー入力イベントは全部メインビューに飛ばす。 auto mainframe = dynamic_cast(GetParent()); auto mainview = mainframe->GetMainView(); - Connect(wxEVT_KEY_UP, wxKeyEventHandler(WXMainView::OnKeyUp), NULL, - mainview); - Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(WXMainView::OnKeyDown), NULL, - mainview); + Bind(wxEVT_KEY_UP, &WXMainView::OnKeyUp, mainview); + Bind(wxEVT_KEY_DOWN, &WXMainView::OnKeyDown, mainview); + Bind(wxEVT_CHAR, &WXMainView::OnChar, mainview); // VM からの通知を受け取る WXUIMessage::Connect(UIMessage::SCSI_MEDIA_CHANGE, this, @@ -101,6 +234,28 @@ WXStatusPanel::~WXStatusPanel() wxCommandEventHandler(WXStatusPanel::OnLEDChanged)); } +// 初期化 +void +WXStatusPanel::Init() +{ + // ここで最初に一回、全メディアの状態更新を能動的に行う。 + for (const auto ind : indicators) { + int id; + id = ind->GetSCSIID(); + if (id >= 0) { + wxCommandEvent event(NONO_EVT_UIMESSAGE); + event.SetInt(id); + OnSCSIMediaChanged(event); + } + id = ind->GetFDUnit(); + if (id >= 0) { + wxCommandEvent event(NONO_EVT_UIMESSAGE); + event.SetInt(id); + OnFDDMediaChanged(event); + } + } +} + // クローズイベント void WXStatusPanel::OnClose(wxCloseEvent& event) @@ -155,33 +310,19 @@ WXStatusPanel::FontChanged() } accmark.reset(new BitmapI8(src, font_height, font_height)); - // インジケータを再レイアウト - LayoutIndicators(); - - // コントロールの大きさを変更 - wxSize size = GetClientSize(); - size.y = font_height + 8; - SetClientSize(size); + Fit(); } -// サイズ変更イベント void -WXStatusPanel::OnSize(wxSizeEvent& event) +WXStatusPanel::Fit() { - // Mac ではウィンドウ作成時に 0 以下の値が来ることがある。 - // GTK では 1 で来ることがある。 - const wxSize& size = event.GetSize(); - if (size.x <= 1 || size.y <= 1) { - return; - } - - // 親クラス - inherited::OnSize(event); + wxSize size = LayoutIndicators(); - LayoutIndicators(); + // バックバッファのサイズを固定。 + SetMinBitmapSize(size); - // 再描画を指示 - Refresh(); + SetMinSize(size); + SetSize(size); } // タイマーイベント @@ -193,12 +334,7 @@ WXStatusPanel::OnTimer(wxTimerEvent& eve } } -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, -}; - -// store に value を代入。更新されていれば updated を立てる。 +// store に value を代入。更新されていれば true を返す。 // value は引数に渡す時に一度だけ評価される。 #define MODIFY(store, value_) ({ \ bool mod_; \ @@ -218,40 +354,153 @@ static const std::vector data = { class Status { public: - virtual ~Status() = default; + virtual ~Status(); // 情報取得メソッド virtual bool Poll() = 0; }; +// デストラクタ +Status::~Status() +{ +} + +// Read/Write が別の3値タイプのアクセスインジケータ用 +enum class RWStatus : uint8 { + None = 0, + Read = 1, + Write = 2, +}; + // -// SCSI 情報 +// SCSI 情報 (Bus/VirtIO 共通) // class StatusSCSI : public Status { public: - StatusSCSI(SCSIBus *scsibus_) { + std::array active {}; +}; + +// +// SCSIBus 情報 +// +class StatusSCSIBus : public StatusSCSI +{ + public: + StatusSCSIBus(SCSIBus *scsibus_) { scsibus = scsibus_; } - virtual ~StatusSCSI() override = default; + ~StatusSCSIBus() override; bool Poll() override { - bool mod = false; - mod |= MODIFY(bsy, scsibus->GetBSY()); + uint8 bsy = scsibus->GetBSY(); // 転送フェーズで DataOut の時だけ書き込みとみなす bool out = (scsibus->GetPhase() == SCSI::Phase::Transfer) && (scsibus->GetXfer() == SCSI::XferPhase::DataOut); - mod |= MODIFY(dataout, out); + + bool mod = false; + for (uint id = 0; id < 8; id++) { + RWStatus newactive; + if (__predict_false((bsy & (1U << id)) != 0)) { + if (out) { + newactive = RWStatus::Write; + } else { + newactive = RWStatus::Read; + } + } else { + newactive = RWStatus::None; + } + mod |= MODIFY(active[id], newactive); + } return mod; } - uint8 bsy {}; // BSY (ID0-7) - bool dataout {}; // DataOut フェーズなら true - private: SCSIBus *scsibus {}; }; +// デストラクタ +StatusSCSIBus::~StatusSCSIBus() +{ +} + +// +// VirtIOSCSI 情報 +// +class StatusVSCSI : public StatusSCSI +{ + public: + StatusVSCSI(VirtIOSCSIDevice *dev_) { + dev = dev_; + } + ~StatusVSCSI() override = default; + + bool Poll() override { + std::array newacc; + dev->GetAccess(&newacc); + bool mod = false; + for (uint id = 0; id < 8; id++) { + bool rmod = MODIFY(access[id * 2 + 0], newacc[id * 2 + 0]); + bool wmod = MODIFY(access[id * 2 + 1], newacc[id * 2 + 1]); + + RWStatus newactive; + if (wmod) { + newactive = RWStatus::Write; + } else if (rmod) { + newactive = RWStatus::Read; + } else { + newactive = RWStatus::None; + } + mod |= MODIFY(active[id], newactive); + } + return mod; + } + + std::array access {}; + + private: + VirtIOSCSIDevice *dev {}; +}; + +// +// VirtIOBlock 情報 +// +class StatusVBlk : public Status +{ + public: + StatusVBlk(VirtIOBlockDevice *dev_) { + dev = dev_; + } + ~StatusVBlk() override; + + bool Poll() override { + bool rmod = MODIFY(access_read, dev->GetAccessRead()); + bool wmod = MODIFY(access_write, dev->GetAccessWrite()); + RWStatus newactive; + if (wmod) { + newactive = RWStatus::Write; + } else if (rmod) { + newactive = RWStatus::Read; + } else { + newactive = RWStatus::None; + } + return MODIFY(active, newactive); + } + + // アクセス状況 + uint32 access_read {}; + uint32 access_write {}; + RWStatus active {}; + + private: + VirtIOBlockDevice *dev {}; +}; + +// デストラクタ +StatusVBlk::~StatusVBlk() +{ +} + // // ネットワーク情報 // @@ -261,7 +510,7 @@ class StatusNet : public Status StatusNet(HostNetDevice *hostnet_) { hostnet = hostnet_; } - virtual ~StatusNet() override = default; + ~StatusNet() override; bool Poll() override { // パケット数が変化したとき、および @@ -286,6 +535,11 @@ class StatusNet : public Status HostNetDevice *hostnet {}; }; +// デストラクタ +StatusNet::~StatusNet() +{ +} + // // FDD 情報 // @@ -295,7 +549,7 @@ class StatusFDD : public Status StatusFDD(FDDDevice *fdd_) { fdd = fdd_; } - virtual ~StatusFDD() override = default; + ~StatusFDD() override; bool Poll() override { bool mod = false; @@ -310,6 +564,11 @@ class StatusFDD : public Status FDDDevice *fdd {}; }; +// デストラクタ +StatusFDD::~StatusFDD() +{ +} + // // NEWS の LED 情報 // @@ -319,7 +578,7 @@ class StatusNEWS : public Status StatusNEWS(NewsCtlrDevice *newsctlr_) { newsctlr = newsctlr_; } - virtual ~StatusNEWS() override = default; + ~StatusNEWS() override; bool Poll() override { return MODIFY(led, newsctlr->GetLED()); @@ -330,6 +589,11 @@ class StatusNEWS : public Status NewsCtlrDevice *newsctlr {}; }; +// デストラクタ +StatusNEWS::~StatusNEWS() +{ +} + // インジケータの初期化 void @@ -339,20 +603,23 @@ WXStatusPanel::InitIndicators() Indicator *ind; // パフォーマンスカウンタ - ind = new Indicator(Indicator::PERF, &WXStatusPanel::DrawPerf, - 8/* >>>9999% */, NULL); + // 0123456789012345 + // >>> 99.9x 100MHz + auto mpu = gMainApp.FindObject(OBJ_MPU); + assert(mpu); + clock_khz = mpu->GetClockSpeed(); + ind = new Indicator(Indicator::PERF, &WXStatusPanel::DrawPerf, 15, NULL); ind->dclick = &WXStatusPanel::DClickPerf; indicators.emplace_back(ind); // SCSI - // SPC の接続済みデバイスリストから取得。 - // (ホストアダプタ2つ目のことは考えてない) - auto spc = gMainApp.FindObject(OBJ_SPC); - if (spc) { - stat = new StatusSCSI(spc->GetSCSIBus()); + // 接続済みデバイスリストから取得。 + auto scsibus = gMainApp.FindObject(OBJ_SCSIBUS); + if (scsibus) { + stat = new StatusSCSIBus(scsibus); stats.emplace_back(stat); - const std::vector& conn = spc->GetConnectedDevices(); + const auto& conn = scsibus->GetDomain()->GetConnectedDevices(); for (const auto& dev : conn) { SCSI::DevType devtype = dev->GetDevType(); if (devtype == SCSI::DevType::Initiator) { @@ -360,12 +627,68 @@ WXStatusPanel::InitIndicators() } int scsiid = dev->GetMyID(); - // 文字列は OnSCSIMediaChanged() でセットする。 + std::string label = string_format("%s%d", + SCSI::GetDevTypeName(devtype), scsiid); + const auto disk = dynamic_cast(dev); + if (disk && disk->GetWriteMode() == SCSIDisk::RW::WriteIgnore) { + label += "\x02\x03"; + } ind = new Indicator(Indicator::SCSI0 + scsiid, - &WXStatusPanel::DrawSCSI, 3, stat); + &WXStatusPanel::DrawSCSI, label, stat); ind->contextmenu = &WXStatusPanel::ContextMenuCD; ind->dev = dev; ind->panel = new wxPanel(this); + ind->panel->SetName("WXStatusPanel.SCSI"); + // このパネルがフォーカスを受け取らないようにする。 + // StatusPanel がフォーカスを持っていてもキー入力を MainFrame に渡す + // ようにしているため、StatusPanel のフォーカスを奪ってはいけない。 + ind->panel->SetCanFocus(false); + + indicators.emplace_back(ind); + } + } + + // VirtIOBlock + for (int i = 0; i < 8; i++) { + auto dev = gMainApp.FindObject(OBJ_VIRTIO_BLOCK(i)); + if (dev) { + stat = new StatusVBlk(dev); + stats.emplace_back(stat); + + std::string label = string_format("VB%u", i); + if (dev->GetWriteMode() == SCSIDisk::RW::WriteIgnore) { + label += "\x02\x03"; + } + ind = new Indicator(Indicator::VBLK0 + i, &WXStatusPanel::DrawVBlk, + label, stat); + ind->dev = dev; + indicators.emplace_back(ind); + } + } + + // VirtIOSCSI + auto vscsi = gMainApp.FindObject(OBJ_VIRTIO_SCSI); + if (vscsi) { + stat = new StatusVSCSI(vscsi); + stats.emplace_back(stat); + + const auto& conn = vscsi->GetDomain()->GetConnectedDevices(); + for (const auto& dev : conn) { + SCSI::DevType devtype = dev->GetDevType(); + int scsiid = dev->GetMyID(); + + std::string label = string_format("%s%d", + SCSI::GetDevTypeName(devtype), scsiid); + const auto disk = dynamic_cast(dev); + if (disk && disk->GetWriteMode() == SCSIDisk::RW::WriteIgnore) { + label += "\x02\x03"; + } + ind = new Indicator(Indicator::SCSI0 + scsiid, + &WXStatusPanel::DrawSCSI, label, stat); + ind->contextmenu = &WXStatusPanel::ContextMenuCD; + ind->dev = dev; + ind->panel = new wxPanel(this); + ind->panel->SetName("WXStatusPanel.VSCSI"); // このパネルがフォーカスを受け取らないようにする。 // StatusPanel がフォーカスを持っていてもキー入力を MainFrame に渡す // ようにしているため、StatusPanel のフォーカスを奪ってはいけない。 @@ -409,13 +732,19 @@ WXStatusPanel::InitIndicators() stat = new StatusFDD(fdd); stats.emplace_back(stat); + // 後ろの4文字分のスペースは LED アイコン用の場所取り。 + std::string label = string_format("FD%d ", fdd->GetUnitNo()); + if (fdd->GetWriteMode() == FDDDevice::RW::WriteIgnore) { + label += "\x02\x03"; + } + // 文字列は OnFDDMediaChanged() でセットする。 ind = new Indicator(Indicator::FDD0 + unit, - &WXStatusPanel::DrawFD, 7, stat); - + &WXStatusPanel::DrawFD, label, stat); ind->contextmenu = &WXStatusPanel::ContextMenuFD; ind->dev = fdd; ind->panel = new wxPanel(this); + ind->panel->SetName("WXStatusPanel.FD"); // フォーカスを受け取らない。少し上の CD のところ参照。 ind->panel->SetCanFocus(false); @@ -442,27 +771,12 @@ WXStatusPanel::InitIndicators() ind = new Indicator(Indicator::POWER, &WXStatusPanel::DrawPower, "POWER", NULL); indicators.emplace_back(ind); - - // テスト用 - 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); - } } -// インジケータのレイアウト -void +// インジケータの配置位置を求める。 +// ind->rect を更新するがここで描画とかはしない。 +// 戻り値はインジケータの配置に必要な最小サイズ。 +wxSize WXStatusPanel::LayoutIndicators() { int x; @@ -493,23 +807,39 @@ WXStatusPanel::LayoutIndicators() x += 1; // この x が最小サイズなのでこれをコントロールに設定。 - // (コントロールのサイズは WXMainFrame::Layout() が設定する) - SetMinClientSize(wxSize(x, font_height + 8)); + wxSize size(x, h + 2 + 2); + return size; +} + +// レイアウト +bool +WXStatusPanel::Layout() +{ + if (indicators.empty()) { + return false; + } + + // レイアウトの計算はビットマップサイズに対して行う。 + // 起動直後に何かの拍子で随分小さいサイズにリサイズされることがあったり + // また実画面が小さくてそもそも入り切らないような場合でも、 + // ビットマップは常に最低限描画できるサイズを保証してあるので。 + // それを画面に転送しても見た目は事故るがとりあえず死にはしないので。 + wxSize size(bitmap.GetWidth(), bitmap.GetHeight()); + + // 配置情報をリセット。(左寄せ相当になる) + wxSize minsize = LayoutIndicators(); - // 全員を一旦右寄せ - wxSize sz = GetClientSize(); - int offsetx = sz.x - x; + // 全員を一旦右寄せ。 + int offsetx = size.x - minsize.x; for (auto ind : indicators) { ind->rect.Offset(offsetx, 0); } // そのうちパフォーマンスカウンタだけ中央寄せまで戻す - if (indicators.size() > 0) { - auto p = indicators.front(); - x = (sz.x / 2) - (p->rect.w / 2); - if (p->rect.x > x) { - p->rect.x = x; - } + auto perf = indicators.front(); + int x = (size.x / 2) - (perf->rect.w / 2); + if (perf->rect.x > x) { + perf->rect.x = x; } // パネルをもっていれば、パネルをその位置に(再)設定。 @@ -521,6 +851,7 @@ WXStatusPanel::LayoutIndicators() } refresh_background = true; + return true; } // 状態をチェック。 @@ -556,13 +887,13 @@ WXStatusPanel::Draw() if (refresh_background) { refresh_background = false; bitmap.Fill(BGPANEL); - } - // なんとなく見栄えのため上下に薄い線を引く。 - // 四方を線で囲むとオーバーレイウィンドウのように見えるので上下だけ。 - wxSize size = GetSize(); - bitmap.DrawLineH(UD_GREY, 0, 0, size.x); - bitmap.DrawLineH(UD_GREY, 0, size.y - 1, size.x); + // なんとなく見栄えのため上下に薄い線を引く。 + // 四方を線で囲むとオーバーレイウィンドウのように見えるので上下だけ。 + wxSize size = GetSize(); + bitmap.DrawLineH(UD_GREY, 0, 0, size.x); + bitmap.DrawLineH(UD_GREY, 0, size.y - 1, size.x); + } // 各インジケータを描画 for (auto ind : indicators) { @@ -596,7 +927,7 @@ WXStatusPanel::DrawPerf(const Indicator // パフォーマンス表示は // o 高速モード指示中なら倍率表記 (115% なら 1.2x) // o 通常モード指示中ならパーセント表記 - if ((perf_mode & Syncer::SCHED_SYNC) == 0) { + if ((perf_mode & Syncer::SYNCMODE_SYNC) == 0) { // 高速モード指示 if (perf_mode == 0) { // 高速走行中 @@ -606,15 +937,28 @@ WXStatusPanel::DrawPerf(const Indicator } // 倍率表記は1桁少ないので、表示用に最下位桁を四捨五入 - int rate = perf_rate + 5; - snprintf(text, sizeof(text), "%2d.%1dx", - (rate / 100), (rate % 100) / 10); + uint rate = perf_rate + 5; + if (rate < 100 * 100) { + // 2桁倍までなら "99.9x" のように小数以下1桁まで。 + snprintf(text, sizeof(text), "%2u.%1ux", + (rate / 100), (rate % 100) / 10); + } else if (rate < 10000 * 100) { + // 3桁倍、4桁倍だと整数部のみ。"9999x" + snprintf(text, sizeof(text), "%4ux", rate / 100); + } else { + // どうする? + strlcpy(text, "9999x", sizeof(text)); + } } else { // 通常モード指示 ffmark = " "; - snprintf(text, sizeof(text), "%4d%%", perf_rate); + snprintf(text, sizeof(text), "%4u%%", perf_rate); } + // クロックスピード(MHz)も四捨五入。 + uint eff_khz = (clock_khz * perf_rate + 50) / 100; + snprintf(text + 5, sizeof(text) - 5, "%4uMHz", (eff_khz + 500) / 1000); + DrawStringSJIS(UD_RED, rect.x + 2, rect.y + 2, ffmark); DrawStringSJIS(rect.x + 2 + font_width * 3, rect.y + 2, text); } @@ -628,11 +972,9 @@ WXStatusPanel::DrawSCSI(const Indicator Color fg; Color bg; int scsiid; - uint idmask; scsiid = ind->GetSCSIID(); assertmsg(scsiid >= 0, "id=%d", ind->id); - idmask = 1U << scsiid; if (scsi_loaded[scsiid]) { fg = UD_BLACK; @@ -640,12 +982,30 @@ WXStatusPanel::DrawSCSI(const Indicator fg = UD_GREY; } - if ((stat->bsy & idmask) != 0) { - if (stat->dataout) { - bg = UD_RED; - } else { - bg = UD_YELLOW_GREEN; - } + if (stat->active[scsiid] == RWStatus::Write) { + bg = UD_RED; + } else if (stat->active[scsiid] == RWStatus::Read) { + bg = UD_YELLOW_GREEN; + } else { + bg = BGPANEL; + } + + DrawTextLED(ind, fg, bg); +} + +// VirtIOBlock デバイスのアクセスランプ。 +void +WXStatusPanel::DrawVBlk(const Indicator *ind) +{ + const StatusVBlk *stat = dynamic_cast(ind->stat); + Color fg; + Color bg; + + fg = UD_BLACK; + if (stat->active == RWStatus::Write) { + bg = UD_RED; + } else if (stat->active == RWStatus::Read) { + bg = UD_YELLOW_GREEN; } else { bg = BGPANEL; } @@ -766,7 +1126,7 @@ WXStatusPanel::DrawFD(const Indicator *i pal[IN] = pal[BG]; break; } - bitmap.DrawBitmap(dx, dy, *accmark, pal); + bitmap.DrawBitmapI8(dx, dy, *accmark, pal); } /*static*/ const uint8 @@ -917,7 +1277,7 @@ void WXStatusPanel::DClickPerf(const Indicator *ind) { // モードを切り替える - syncer->RequestFullSpeed(!syncer->GetFullSpeed()); + syncer->NotifyFullSpeed(!syncer->GetFullSpeed()); } // コンテキストメニューイベント @@ -1012,24 +1372,11 @@ WXStatusPanel::OnSCSIMediaChanged(wxComm } ind->panel->SetToolTip(tip); - // 書き込み無視だけ、これによって shutdown が必要かどうかという - // オペレーションに違いが出るため表示する。 - // 無駄に幅を取らないためメディア挿入時のみ表示。 - // MO のライトプロテクト表示は必要になったら考える…。 - ind->text = string_format("%s%d", SCSI::GetDevTypeName(devtype), scsiid); - if (new_loaded) { - if (disk->GetWriteMode() == SCSIDisk::RW::WriteIgnore) { - ind->text += "\x02\x03"; - } - } - // メディアのロード状態が変われば (再配置して) 再描画。 // 通常周期のタイマーによる更新チェックではメディア状態はチェックして // いないので、ここで自発的に行う。 if (scsi_loaded[scsiid] != new_loaded) { scsi_loaded[scsiid] = new_loaded; - - LayoutIndicators(); Refresh(); } } @@ -1078,22 +1425,11 @@ WXStatusPanel::OnFDDMediaChanged(wxComma } ind->panel->SetToolTip(tip); - ind->text = string_format("FD%d", fdd->GetUnitNo()); - // 書き込み無視だけ表示する。無駄に幅を取らないためメディア挿入時のみ表示。 - // 4文字分のマークの後ろに "WI" を追加。 - if (new_loaded) { - if (fdd->GetWriteMode() == FDDDevice::RW::WriteIgnore) { - ind->text += " \x02\x03"; - } - } - // メディアのロード状態が変われば (再配置して) 再描画。 // 通常周期のタイマーによる更新チェックではメディア状態はチェックして // いないので、ここで自発的に行う。 if (fd_loaded[unit] != new_loaded) { fd_loaded[unit] = new_loaded; - - LayoutIndicators(); Refresh(); } } @@ -1109,32 +1445,3 @@ WXStatusPanel::OnLEDChanged(wxCommandEve Refresh(); } } - - -// -// インジケータ情報 -// - -// SCSI なら SCSI ID を返す。そうでなければ -1 を返す。 -int -Indicator::GetSCSIID() const -{ - int scsiid = id - SCSI0; - if (0 <= scsiid && scsiid <= 7) { - return scsiid; - } else { - return -1; - } -} - -// FDD ならユニット番号を返す。そうでなければ -1 を返す。 -int -Indicator::GetFDUnit() const -{ - int unit = id - FDD0; - if (0 <= unit && unit <= 3) { - return unit; - } else { - return -1; - } -}