--- nono/wx/wxtextscreen.cpp 2026/04/29 17:05:08 1.1.1.8 +++ nono/wx/wxtextscreen.cpp 2026/04/29 17:05:57 1.1.1.15 @@ -10,7 +10,6 @@ #include "wxtextscreen.h" #include "fontmanager.h" -#include "wxcolor.h" #include "wxmainframe.h" #include "sjis.h" PRAGMA_PUSH_WARNINGS @@ -20,38 +19,27 @@ PRAGMA_POP_WARNINGS // イベントテーブル wxBEGIN_EVENT_TABLE(WXTextScreen, inherited) EVT_SIZE(WXTextScreen::OnSize) - EVT_TIMER(wxID_ANY, WXTextScreen::OnTimer) EVT_MENU(wxID_COPY, WXTextScreen::OnCopy) wxEND_EVENT_TABLE() // コンストラクタ -WXTextScreen::WXTextScreen(wxWindow *parent, Monitor& monitor_) +WXTextScreen::WXTextScreen(wxWindow *parent, const nnSize& screensize) : inherited(parent) - , monitor(monitor_) { + SetName("WXTextScreen"); + pad_left = DefaultPadding; pad_top = DefaultPadding; pad_right = DefaultPadding; pad_bottom = DefaultPadding; - // モニタサイズから初期サイズを決定 - nnSize ms = monitor.GetSize(); - Init(ms.width, ms.height); + Init(screensize.width, screensize.height); FontChanged(); // コンテキストメニューイベントを動的に追加 // (コンテキストメニューを表示したくない人があとから外せるようにするため) ConnectContextMenu(); - - timer.SetOwner(this); - - // 現在の設定値を適用 - SetRate(gMainFrame->GetMonitorRate()); - - // 最初に一回描画を起こす - wxTimerEvent dummy(timer); - AddPendingEvent(dummy); } // デストラクタ @@ -63,7 +51,7 @@ WXTextScreen::~WXTextScreen() void WXTextScreen::Init(int col, int row) { - ts.Init(col, row); + screen.Init(col, row); prevbuf.resize(col * row); InvalidateText(); } @@ -75,13 +63,6 @@ WXTextScreen::InvalidateText() std::fill(prevbuf.begin(), prevbuf.end(), 0xffff); } -// 画面更新頻度を Hz で設定する。 -void -WXTextScreen::SetRate(int hz) -{ - timer.Start(1000 / hz); -} - // フォントサイズ変更 (外部インタフェース) void WXTextScreen::FontChanged() @@ -93,115 +74,104 @@ WXTextScreen::FontChanged() InvalidateText(); // コントロールの大きさを変更 - DoSize(); + Fit(); } -// (自発的な)サイズ変更。 -// ts の行数桁数、font_{width,height}、四方のパディングのいずれかが -// 変わった場合に呼ぶこと。 void -WXTextScreen::DoSize() +WXTextScreen::Fit() { - wxSize size = wxSize( - ts.GetCol() * font_width + pad_left + pad_right, - ts.GetRow() * font_height + pad_top + pad_bottom); - SetClientSize(size); - SetMinClientSize(size); + // 指定の (row, col) にパディングを加味した大きさにする、 + // なので GetSize() ではない。 + wxSize size(GetScreenWidth(GetCol()), GetScreenHeight(GetRow())); + + // バックバッファのサイズを固定。 + SetMinBitmapSize(size); + + SetSize(size); + SetMinSize(size); } -// サイズ変更イベント void WXTextScreen::OnSize(wxSizeEvent& event) { - // Mac ではウィンドウ作成時に 0 以下の値が来ることがある - // GTK では 1 で来ることがある - const wxSize& size = event.GetSize(); - if (size.x <= 1 || size.y <= 1) { - return; - } - - // 親クラス - inherited::OnSize(event); + const wxSize& size = GetSize(); // テキストサイズが変わった時だけテキストバッファを再構成。 // (フォントサイズを変えると桁数×行数が変わらず画面サイズが変わる // ということは起きることに注意) int sw = size.x - pad_left - pad_right; int sh = size.y - pad_top - pad_bottom; - if (__predict_false(sw < 0)) { - sw = 0; - } - if (__predict_false(sh < 0)) { - sh = 0; + int col = (font_width != 0) ? (sw / font_width) : 0; + int row = (font_height != 0) ? (sh / font_height) : 0; + if (__predict_false(col < 1 || row < 1)) { + return; } - int col = sw / font_width; - int row = sh / font_height; - if (col != ts.GetCol() || row != ts.GetRow()) { + + if (col != screen.GetCol() || row != screen.GetRow()) { Init(col, row); } else { // テキストバッファを再構成しなくても全域を再描画する必要がある InvalidateText(); } -} + // サイズが変わったらどちらにしてもパディングも塗り直す。 + draw_padding = true; -// タイマーイベント -void -WXTextScreen::OnTimer(wxTimerEvent& event) -{ - DoRefresh(); -} - -// 画面を更新して再描画する。 -// -// 通常はタイマーイベントにより更新間隔ごとに呼ばれるが、 -// ユーザ操作により画面の更新が必要ならその都度直接これを呼ぶ。 -void -WXTextScreen::DoRefresh() -{ - // モニタースクリーンを更新して - MONITOR_UPDATE(monitor, ts); - // 必要なら再描画 - if (ts.GetBuf() != prevbuf) { - Refresh(); - } + event.Skip(); } // テキストバッファの内容をパネルのバックグラウンドバッファに描画する。 void WXTextScreen::Draw() { - auto text = ts.GetBuf().begin(); + if (__predict_false(draw_padding)) { + draw_padding = false; + auto bgcol = GetTextBackColor(); + // パディングを塗るだけでいいのだが手抜き。 + bitmap.Fill(bgcol); + } + + auto text = screen.GetBuf().begin(); auto prev = prevbuf.begin(); - int col = ts.GetCol(); - int row = ts.GetRow(); - uint prevattr = (uint)-1; + int col = screen.GetCol(); + int row = screen.GetRow(); + uint prevcolor = (uint)-1; int py = pad_top; for (int y = 0; y < row; y++, py += font_height) { int px = pad_left; for (int x = 0; x < col; ) { uint16 data = *text; - uint attr = (data & 0xff00); - uint chr = (data & 0xff); + uint attr = (data & 0xf000); + uint color = (data & 0x0f00); + uint chr = (data & 0x00ff); // 属性(色)を変更 - if (__predict_false(attr != prevattr)) { - switch (attr) { - case TA::On: - SetTextColor(BGPANEL, UD_BLACK); - break; + if (__predict_false(color != prevcolor)) { + switch (color) { case TA::Off: SetTextColor(UD_BLACK, UD_LIGHT_GREY); break; case TA::Disable: SetTextColor(UD_GREY, BGPANEL); break; + case TA::Reverse: + SetTextColor(BGPANEL, UD_BLACK); + break; + case TA::ReverseRed: + SetTextColor(BGPANEL, UD_RED); + break; + case TA::ReverseGreen: + SetTextColor(UD_BLACK, UD_GREEN); + break; + case TA::ReverseOrange: + SetTextColor(UD_BLACK, UD_ORANGE); + break; default: ResetTextColor(); break; } - prevattr = attr; + prevcolor = color; } if (__predict_true(SJIS::IsHankaku(chr))) { @@ -243,6 +213,22 @@ WXTextScreen::Draw() } } +// 桁数が col_ の時の横幅 [pixel] を取得。 +int +WXTextScreen::GetScreenWidth(int col_) const +{ + int w = GetFontWidth() * col_ + GetPaddingX(); + return w; +} + +// 行数が row_ の時の高さ [pixel] を取得。 +int +WXTextScreen::GetScreenHeight(int row_) const +{ + int h = GetFontHeight() * row_ + GetPaddingY(); + return h; +} + // パディングサイズ変更。 // 負数なら変更しない。 void @@ -261,7 +247,7 @@ WXTextScreen::SetPadding(int l, int t, i pad_bottom = b; } - DoSize(); + Fit(); } // クライアント座標 pos をテキスト座標(桁、行)に変換して返す @@ -299,7 +285,7 @@ WXTextScreen::OnContextMenu(wxContextMen { wxMenu *menu = new wxMenu(); - menu->Append(wxID_COPY, _T("&Copy")); + menu->Append(wxID_COPY, _("&Copy All")); PopupMenu(menu); } @@ -308,10 +294,10 @@ WXTextScreen::OnContextMenu(wxContextMen void WXTextScreen::OnCopy(wxCommandEvent& ev) { - int col = ts.GetCol(); - int row = ts.GetRow(); + int col = screen.GetCol(); + int row = screen.GetRow(); - const std::vector& src = ts.GetBuf(); + const std::vector& src = screen.GetBuf(); auto s = src.begin(); std::vector buf;