--- nono/wx/wxlcdwindow.cpp 2026/04/29 17:04:56 1.1.1.3 +++ nono/wx/wxlcdwindow.cpp 2026/04/29 17:05:12 1.1.1.6 @@ -9,9 +9,8 @@ // #include "wxlcdwindow.h" -#include "wxbitmapbuf.h" #include "wxcolor.h" -#include "wxtextscreen.h" +#include "wxuimessage.h" #include "lcd.h" // パネルの大きさ (定数) @@ -24,109 +23,59 @@ // LUNA LCD パネル // -// イベントテーブル -wxBEGIN_EVENT_TABLE(WXLCDPanel, inherited) - EVT_TIMER(wxID_ANY, WXLCDPanel::OnTimer) - EVT_PAINT(WXLCDPanel::OnPaint) -wxEND_EVENT_TABLE() - // コンストラクタ WXLCDPanel::WXLCDPanel(wxWindow *parent) - : inherited(parent, wxID_ANY, wxDefaultPosition, - wxSize(PANEL_WIDTH, PANEL_HEIGHT)) + : inherited(parent, wxSize(PANEL_WIDTH, PANEL_HEIGHT)) { - bitmap.Create(PANEL_WIDTH, PANEL_HEIGHT); - - count = (uint32)-1; ddram = gLCD->GetDDRAM(); - // 更新タイマー。そんなに応答速度速くなくていい - timer.SetOwner(this); - timer.Start(50); + // VM からの通知を受け取る + WXUIMessage::Connect(UIMessage::LCD, this, + wxCommandEventHandler(WXLCDPanel::OnLCDChanged)); + + SetBitmapBGColor(UD_CREAM); } // デストラクタ WXLCDPanel::~WXLCDPanel() { + WXUIMessage::Disconnect(UIMessage::LCD, + wxCommandEventHandler(WXLCDPanel::OnLCDChanged)); } -// タイマーイベント +// LCD 状態変更イベント (UIMessage) void -WXLCDPanel::OnTimer(wxTimerEvent& event) +WXLCDPanel::OnLCDChanged(wxCommandEvent& event) { - uint32 devcount; - - // 更新があれば.. - devcount = gLCD->GetCounter(); - if (count != devcount) { - count = devcount; - - // 再描画を起こす - Refresh(); - } -} - -// 描画イベント (UI スレッドから呼ばれる) -void -WXLCDPanel::OnPaint(wxPaintEvent& event) -{ - // メモリ DC に描画 - wxMemoryDC memDC; - memDC.SelectObject(bitmap); - Draw(memDC); - - // 実画面 DC にコピー - wxPaintDC dstDC(this); - dstDC.Blit(0, 0, PANEL_WIDTH, PANEL_HEIGHT, &memDC, 0, 0); + Refresh(); } // バックグラウンドバッファに描画 void -WXLCDPanel::Draw(wxDC& dc) +WXLCDPanel::Draw() { - // 背景 - dc.SetPen(UD_CREAM); - dc.SetBrush(UD_CREAM); - dc.DrawRectangle(wxPoint(0, 0), bitmap.GetSize()); - for (int y = 0; y < 2; y++) { for (int x = 0; x < 16; x++) { uint8 ch = ddram[0x40 * y + x]; - DrawChar(dc, x, y, ch); + DrawChar(x, y, ch); } } } // 1文字描画 void -WXLCDPanel::DrawChar(wxDC& dc, int x, int y, uint8 ch) +WXLCDPanel::DrawChar(int x, int y, uint8 ch) { - wxSize dotsize = wxSize(N, N); + const Color pal[2] = { UD_YELLOW_GREEN, UD_BROWN }; const uint8 *font; font = gLCD->GetFont(ch); + BitmapI1 src(font, 5, 8); - for (int py = 0; py < 8; py++) { - uint8 line = *font++; - line <<= 3; - for (int px = 0; px < 5; px++) { - wxColour color; - if ((int8)line < 0) { - color = UD_BROWN; - } else { - color = UD_YELLOW_GREEN; - } - dc.SetPen(color); - dc.SetBrush(color); - dc.DrawRectangle( - wxPoint((1 + x * 6 + px) * N, (1 + y * 9 + py) * N), - dotsize); - - line <<= 1; - } - } + bitmap.DrawScaleUp((1 + x * 6) * N, (1 + y * 9) * N, N, src, pal); } + // // LCD ウィンドウ // @@ -135,14 +84,9 @@ WXLCDPanel::DrawChar(wxDC& dc, int x, in WXLCDWindow::WXLCDWindow(wxWindow *parent) : inherited(parent, wxID_ANY, _("Front LCD")) { - wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL); - panel = new WXLCDPanel(this); - topsizer->Add(panel, 0, wxEXPAND); - SetSizer(topsizer); - // 大きさをそれに固定 - Fit(); + DoSize(); } // デストラクタ @@ -150,23 +94,19 @@ WXLCDWindow::~WXLCDWindow() { } + // // LCD キャラクタパネル // -#define CP_WIDTH (N * (1 + 6 * (16 + 1 + 16))) -#define CP_HEIGHT (N * (1 + 9 * 8)) - -// イベントテーブル -wxBEGIN_EVENT_TABLE(WXLCDCharPanel, inherited) - EVT_PAINT(WXLCDCharPanel::OnPaint) -wxEND_EVENT_TABLE() +#define PAD (1) +#define CP_WIDTH (N * (PAD + 6 * (16 + 1 + 16) + PAD)) +#define CP_HEIGHT (N * (PAD + 9 * 8 + PAD)) // コンストラクタ WXLCDCharPanel::WXLCDCharPanel(wxWindow *parent) : inherited(parent, wxSize(CP_WIDTH, CP_HEIGHT)) { - bitmap.Create(CP_WIDTH, CP_HEIGHT); } // デストラクタ @@ -174,59 +114,23 @@ WXLCDCharPanel::~WXLCDCharPanel() { } -// 描画イベント (UI スレッドから呼ばれる) -void -WXLCDCharPanel::OnPaint(wxPaintEvent& event) -{ - // メモリ DC に描画 - wxMemoryDC memDC; - memDC.SelectObject(bitmap); - Draw(memDC); - - // 実画面 DC にコピー - wxPaintDC dstDC(this); - dstDC.Blit(0, 0, CP_WIDTH, CP_HEIGHT, &memDC, 0, 0); -} - // バックグラウンドバッファに描画 void -WXLCDCharPanel::Draw(wxDC& dc) +WXLCDCharPanel::Draw() { - wxSize dotsize = wxSize(N, N); - - // 背景 - dc.SetPen(BGPANEL); - dc.SetBrush(BGPANEL); - dc.DrawRectangle(wxPoint(0, 0), bitmap.GetSize()); + const Color pal[2] = { UD_WHITE, UD_BLACK }; // フォントは 5x8 (最下行はカーソル用に空けてあるので実際は 5x7)。 // 実際には 0xe0 以降には 5x10 フォントが混在しているのだが、その // モードはサポートしていないので今の所全部 5x8 としてある。 // cx, cy はこの文字の左上座標 (スケール前) - int cx = 1; - int cy = 1; + int cx = PAD; + int cy = PAD; for (int ch = 0; ch < 256; ch++) { const uint8 *font = gLCD->GetFont(ch); - for (int py = 0; py < 8; py++) { - uint8 line = *font++; - line <<= 3; - for (int px = 0; px < 5; px++) { - wxColour color; - if ((int8)line < 0) { - color = *wxBLACK; - } else { - color = *wxWHITE; - } - dc.SetPen(color); - dc.SetBrush(color); - dc.DrawRectangle( - wxPoint((cx + px) * N, (cy + py) * N), - dotsize); - - line <<= 1; - } - } + BitmapI1 src(font, 5, 8); + bitmap.DrawScaleUp(cx * N, cy * N, N, src, pal); cx += 6; if (ch % 16 == 15) { @@ -242,6 +146,7 @@ WXLCDCharPanel::Draw(wxDC& dc) } } + // // LCD モニタウィンドウ // @@ -250,56 +155,27 @@ WXLCDCharPanel::Draw(wxDC& dc) WXLCDMonitor::WXLCDMonitor(wxWindow *parent) : inherited(parent, wxID_ANY, _("LCD")) { - // top - // | +--------------------------+ - // v | 上余白 | - // +------+------------+------+ - // |左余白| TextScreen |右余白| - // +------+-----------++------+ - // |左余白| CharPanel | 右余白| - // +------+-----------+-------+ - // | 下余白 | - // +--------------------------+ - wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL); - - // 上余白 - topsizer->Add(new WXPaddingPanel(this), 0, wxEXPAND); - - // 2段目 - wxBoxSizer *hbox1 = new wxBoxSizer(wxHORIZONTAL); - topsizer->Add(hbox1, 0, wxEXPAND); - - // 2段目の左余白 - hbox1->Add(new WXPaddingPanel(this), 0, wxEXPAND); - - monpanel = new WXTextScreen(this, gMonitorManager.Get(ID_MONITOR_LCD)); - hbox1->Add(monpanel, 0, wxEXPAND); - - // 2段目の右余白 - // ここの1でこの右余白が空き全部を使用するので空き地が埋まる - hbox1->Add(new WXPaddingPanel(this), 1, wxEXPAND); - - // 3段目 - wxBoxSizer *hbox2 = new wxBoxSizer(wxHORIZONTAL); - topsizer->Add(hbox2, 0, wxEXPAND); - - // 3段目の左余白 - hbox2->Add(new WXPaddingPanel(this), 0, wxEXPAND); + // +------------+ + // | TextScreen | + // +------------+ + // | CharPanel | + // +------------+ + auto *topsizer = new wxBoxSizer(wxVERTICAL); + + // 上段、テキストスクリーン + monpanel = new WXMonitorPanel(this, gMonitorManager->Get(ID_MONITOR_LCD)); + // 下辺は CharPanel の上余白が隣接しているため、自分のほうは付けない。 + monpanel->SetPadding(-1, -1, -1, 0); + topsizer->Add(monpanel, 0, wxEXPAND); + // 下段、キャラクタパネル chrpanel = new WXLCDCharPanel(this); - hbox2->Add(chrpanel, 0, wxEXPAND); - - // 3段目の右余白 - // ここの1でこの右余白が空き全部を使用するので空き地が埋まる - hbox2->Add(new WXPaddingPanel(this), 1, wxEXPAND); - - // 下余白 - topsizer->Add(new WXPaddingPanel(this), 0, wxEXPAND); + topsizer->Add(chrpanel, 0, wxEXPAND); SetSizer(topsizer); // 大きさをそれに固定 - Fit(); + SetClientSize(GetSizer()->GetMinSize()); } // デストラクタ