--- nono/wx/wxlogmonitor.cpp 2026/04/29 17:05:12 1.1.1.10 +++ nono/wx/wxlogmonitor.cpp 2026/04/29 17:05:44 1.1.1.13 @@ -11,45 +11,47 @@ #include "wxlogmonitor.h" #include "logger.h" #include "mainapp.h" +#include "monitor.h" #include "sjis.h" -// イベントテーブル -wxBEGIN_EVENT_TABLE(WXLogMonitor, inherited) - EVT_SIZE(WXLogMonitor::OnSize) -wxEND_EVENT_TABLE() +//#define WINDOW_DEBUG 1 + +#if defined(WINDOW_DEBUG) +#define DPRINTF(fmt...) printf(fmt) +#else +#define DPRINTF(fmt...) /**/ +#endif // コンストラクタ WXLogMonitor::WXLogMonitor(wxWindow *parent) : inherited(parent, wxID_ANY, _("Log"), DEFAULT_STYLE | wxRESIZE_BORDER) { + DPRINTF("%s begin\n", __method__); col = 80; row = 40; - monitor.obj = &log; - monitor.func = ToMonitorCallback(&LogMonitor::MonitorUpdate); - monitor.SetSize(col, row); - // プライベート利用なので Regist() は不要 + // プライベート利用なので Regist() しない。 + monitor.reset(new Monitor(-1, &log)); + monitor->func = ToMonitorCallback(&LogMonitor::MonitorUpdate); + monitor->SetSize(col, row); log.Init(this); - // → // +------------+---------+ // | TextScreen | VScroll | // +------------+---------+ - wxBoxSizer *topsizer = new wxBoxSizer(wxHORIZONTAL); - // テキストスクリーン - screen = new WXMonitorPanel(this, monitor); - topsizer->Add(screen, 1, wxEXPAND); + screen = new WXMonitorPanel(this, monitor.get()); // スクロールバー vscroll = new WXScrollBar(this, wxID_ANY, wxSB_VERTICAL); - topsizer->Add(vscroll, 0, wxEXPAND); - SetSizer(topsizer); + // Sizer 使わず自前でレイアウトする。 + SetAutoLayout(true); + // ウィンドウサイズを確定させる - DoSize(); + FontChanged(); // スクロールのために (パネル領域での) MouseWheel イベントもここで // 受け取りたい。スクロールバー上のマウスホイール操作はスクロールバーが @@ -59,12 +61,13 @@ WXLogMonitor::WXLogMonitor(wxWindow *par screen->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(WXLogMonitor::OnMouseWheel), NULL, this); - // スクロールバーからの位置変更通知 + // スクロールバーからの位置変更通知イベントは表示パネルへ回す。 vscroll->Connect(NONO_EVT_SCROLL, wxScrollEventHandler(WXLogMonitor::OnScroll), NULL, this); // XXX ログウィンドウのコピーはまだ動いてない screen->DisconnectContextMenu(); + DPRINTF("%s done\n", __method__); } // デストラクタ @@ -72,21 +75,100 @@ WXLogMonitor::~WXLogMonitor() { } -bool -WXLogMonitor::Layout() +void +WXLogMonitor::FontChanged() { - // 縦リサイズ可能レイアウト - return LayoutTextVResize(screen); + screen->FontChanged(); + vscroll->FontChanged(); + DPRINTF("%s %d\n", __method__, screen->GetFontHeight()); + + Fit(); } -// サイズ変更イベント void -WXLogMonitor::OnSize(wxSizeEvent& event) +WXLogMonitor::Fit() +{ + // inherited::Fit() は呼ばずに自力で行う。 + + wxSize newsize = DoSizeHints(); +#if defined(WINDOW_DEBUG) + wxSize newwin = ClientToWindowSize(newsize); + printf("%s (%d,%d) client=(%d,%d)\n", __method__, + newwin.x, newwin.y, newsize.x, newsize.y); +#endif + SetClientSize(newsize); +} + +bool +WXLogMonitor::Layout() { - inherited::OnSize(event); + // inherited::Layout() は(実質何もしないので)、呼ばずに自力で行う。 + + wxSize client = GetClientSize(); + const wxSize win = GetSize(); + const wxSize margin = win - client; + const wxSize vsize = vscroll->GetSize(); + const wxSize monsize = screen->GetSize(); + + // wxmonitor.cpp の Layout() 内のコメント参照。 + if (oldmargin != margin) { + layout_pass2 = true; + oldmargin = margin; + CallAfter([this]() { + DoSizeHints(); + }); + return true; + } else if (layout_pass2) { + layout_pass2 = false; + client.y = monsize.y; + SetClientSize(client); + Hide(); + Show(); + return true; + } + + // コントロールを配置。 + int panel_width = client.x - vsize.x; + int panel_height = client.y; + // 最低でも 1px ないと GTK とかに怒られる。 + if (panel_width < 1) { + panel_width = 1; + } + if (panel_height < 1) { + panel_height = 1; + } + + screen->SetSize(0, 0, panel_width, panel_height); + vscroll->SetSize(panel_width, 0, vsize.x, panel_height); // スクロールバーを再設定 SetScroll(); + + DPRINTF("%s done\n", __method__); + + return true; +} + +// クライアントサイズと最大/最小サイズを計算する。 +// SetSizeHints() を実行し、設定すべきクライアントサイズを返す。 +wxSize +WXLogMonitor::DoSizeHints() +{ + auto ssize = screen->GetSize(); + auto vsize = vscroll->GetSize(); + DPRINTF("%s screen=(%d,%d) vscroll=(%d,%d)\n", __method__, + ssize.x, ssize.y, vsize.x, vsize.y); + + int x = ssize.x + vsize.x; + int min_y = std::max(vscroll->GetMinSize().y, screen->GetScreenHeight(1)); + int new_y = std::max(ssize.y, min_y); + wxSize minsize(x, min_y); + wxSize maxsize(x, GetMaxClientSize().y); + wxSize incsize(0, screen->GetFontHeight()); + SetSizeHints(ClientToWindowSize(minsize), ClientToWindowSize(maxsize), + incsize); + + return wxSize(x, new_y); } // スクロールバーを再設定 @@ -175,7 +257,7 @@ WXLogMonitor::DoScroll(int pos) // コンストラクタ LogMonitor::LogMonitor() - : inherited("LogMonitor") + : inherited(OBJ_LOGMONITOR) { } @@ -239,7 +321,9 @@ LogMonitor::MonitorUpdate(Monitor *, Tex // 画面コピー logbuf.Locate(0, srcY); for (int i = 0; i < parent->col * parent->row; i++) { - screen.Putc(logbuf.Getc()); + uint16 ch = logbuf.Getc(); + logbuf.Ascend(); + screen.Putc(ch); } }