--- nono/wx/wxmonitor.cpp 2026/04/29 17:05:44 1.1.1.10 +++ nono/wx/wxmonitor.cpp 2026/04/29 17:05:57 1.1.1.13 @@ -40,6 +40,10 @@ WXMonitorPanel::WXMonitorPanel(wxWindow auto mainframe = dynamic_cast(GetParent()->GetParent()); SetRate(mainframe->GetMonitorRate()); + // 今の所パディングは変わらない。 + monitor->SetPadding(WXTextScreen::DefaultPadding); + FontChanged(); + // 最初に一回描画を起こす wxTimerEvent dummy(timer); AddPendingEvent(dummy); @@ -50,6 +54,15 @@ WXMonitorPanel::~WXMonitorPanel() { } +// フォントサイズ変更 +void +WXMonitorPanel::FontChanged() +{ + inherited::FontChanged(); + + monitor->SetFontSize(font_width, font_height); +} + // タイマーイベント void WXMonitorPanel::OnTimer(wxTimerEvent& event) @@ -64,11 +77,21 @@ WXMonitorPanel::OnTimer(wxTimerEvent& ev void WXMonitorPanel::DoRefresh() { + bool updated = false; + // モニタースクリーンを更新して - MONITOR_UPDATE(monitor, screen); + monitor->UpdateScreen(screen); + if (screen.GetBuf() != prevbuf) { + updated = true; + } + + // あればビットマップ描画を足して + if (monitor->UpdateBitmap(bitmap)) { + updated = true; + } // 必要なら再描画 - if (screen.GetBuf() != prevbuf) { + if (updated) { Refresh(); } } @@ -122,8 +145,8 @@ WXScrollMonitorWindow::WXScrollMonitorWi // スクロールバー vscroll = new WXScrollBar(this, wxID_ANY, wxSB_VERTICAL); - // Sizer 使わず自前でレイアウトする。 - SetAutoLayout(true); + // 自前レイアウト。 + SetMyLayout(); // ウィンドウサイズを確定させる FontChanged(); @@ -133,12 +156,12 @@ WXScrollMonitorWindow::WXScrollMonitorWi // 処理しているので問題ないが、パネル領域でのマウスホイール操作はここ // (wxFrame)ではなくパネルに対して飛んでくる。 // ここで一緒に処理したほうが楽なので、こちらに回す。 - monpanel->Connect(wxEVT_MOUSEWHEEL, - wxMouseEventHandler(WXScrollMonitorWindow::OnMouseWheel), NULL, this); + monpanel->Bind(wxEVT_MOUSEWHEEL, + &WXScrollMonitorWindow::OnMouseWheel, this); // スクロールバーからの位置変更通知 - vscroll->Connect(NONO_EVT_SCROLL, - wxScrollEventHandler(WXScrollMonitorWindow::OnScroll), NULL, this); + vscroll->Bind(NONO_EVT_SCROLL, &WXScrollMonitorWindow::OnScroll, this); + DPRINTF("%s done\n", __method__); } @@ -157,134 +180,89 @@ WXScrollMonitorWindow::FontChanged() Fit(); } -void -WXScrollMonitorWindow::Fit() +// 自前レイアウト方式のサイズに関する情報を返す。 +bool +WXScrollMonitorWindow::GetMySizeHints(wxSize *newp, wxSize *minp, wxSize *maxp, + wxSize *incp) { - // inherited::Fit() は呼ばずに自力で行う。 + auto psize = monpanel->GetSize(); + auto vsize = vscroll->GetSize(); - 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); + // 幅は monpanel 幅 + スクロールバーの幅、高さは monpanel の高さで決まる。 + // monpanel には四辺に Padding があることに注意。 + int x = psize.x + vsize.x; + int min_y = std::max(vscroll->GetMinSize().y, monpanel->GetScreenHeight(1)); + int new_y = std::max(psize.y, min_y); + wxSize newsize(x, new_y); + wxSize minsize(x, min_y); + wxSize maxsize(x, GetMaxClientSize().y); + wxSize incsize(0, monpanel->GetFontHeight()); + + if (newp) *newp = newsize; + if (minp) *minp = minsize; + if (maxp) *maxp = maxsize; + if (incp) *incp = incsize; + return true; } bool WXScrollMonitorWindow::Layout() { - // inherited::Layout() は(実質何もしないので)、呼ばずに自力で行う。 - - wxSize client = GetClientSize(); - const wxSize win = GetSize(); - const wxSize margin = win - client; - const wxSize vsize = vscroll->GetSize(); - const wxSize monsize = monpanel->GetSize(); + if (MyLayout() == false) { + // コントロールを配置。 + wxSize client = GetClientSize(); + const wxSize vsize = vscroll->GetSize(); + + int mon_width = client.x - vsize.x; + int mon_height = client.y; + // 最低でも 1px ないと GTK とかに怒られる。今は起きないはず? + if (__predict_false(mon_width < 1)) { + mon_width = 1; + } + if (__predict_false(mon_height < 1)) { + mon_height = 1; + } #if defined(WINDOW_DEBUG) - const wxSize min = GetMinClientSize(); - int py = client.y - - monpanel->GetPaddingTop() - monpanel->GetPaddingBottom(); - int height = monpanel->GetFontHeight(); - int row = (height != 0) ? (py / height) : 0; - int res = (height != 0) ? (py % height) : 0; - wxSize minwin = GetMinSize(); - printf("%s begin: margin=(%d,%d) shown=%d\n", __method__, - margin.x, margin.y, IsShown()); - printf("%s WinSize =(%d,%d) MinWin =(%d,%d)\n", __method__, - win.x, win.y, minwin.x, minwin.y); - printf("%s ClientSize=(%d,%d) MinClient=(%d,%d)\n", __method__, - client.x, client.y, min.x, min.y); - printf("%s mon=(%d,%d) vscroll=(%d,%d), row=%d%s\n", __method__, - monsize.x, monsize.y, vsize.x, vsize.y, - row, (res == 0 ? "" : "+")); + const wxSize win = GetSize(); + const wxSize minwin = GetMinSize(); + printf("%s WinSize =(%d,%d) MinWin =(%d,%d) Shown=%u\n", + __method__, win.x, win.y, minwin.x, minwin.y, IsShown()); + const wxSize min = GetMinClientSize(); + printf("%s ClientSize=(%d,%d) MinClient=(%d,%d)\n", + __method__, client.x, client.y, min.x, min.y); #endif - if (oldmargin != margin) { - // ウィンドウマネージャ管轄のサイズが変わったので最小サイズを再設定。 - // ここでは出来ないのでこの関数を抜けた後 CallAfter 内で設定する。 - layout_pass2 = true; - oldmargin = margin; - CallAfter([this]() { - DoSizeHints(); - }); - DPRINTF("%s done(pass1)\n", __method__); - return true; - } else if (layout_pass2) { - // SetSizeHints() 後に呼ばれるところ。 - // なぜか設定したサイズと変わっている(ことがある?)ので、その場合は - // 仕方ないのでここで元の要求サイズに再設定する。 - // ウィンドウマネージャによっては表示サイズが変わらない(?)ので - // Hide()/Show() で叩き起こすと直るようだ??。 - layout_pass2 = false; - client.y = monsize.y; - DPRINTF("%s SetClientSize (%d,%d)\n", __method__, client.x, client.y); - SetClientSize(client); - Hide(); - Show(); - DPRINTF("%s done(pass2)\n", __method__); - return true; - } - - // コントロールを配置。 - int mon_width = client.x - vsize.x; - int mon_height = client.y; - // 最低でも 1px ないと GTK とかに怒られる。 - if (mon_width < 1) { - mon_width = 1; - } - if (mon_height < 1) { - mon_height = 1; - } + monpanel->SetSize(0, 0, mon_width, mon_height); + vscroll->SetSize(mon_width, 0, vsize.x, mon_height); - monpanel->SetSize(0, 0, mon_width, mon_height); - vscroll->SetSize(mon_width, 0, vsize.x, mon_height); +#if defined(WINDOW_DEBUG) + const wxSize monsize = monpanel->GetSize(); + const wxSize vsize1 = vscroll->GetSize(); + int py = monsize.y - monpanel->GetPaddingY(); + int height = monpanel->GetFontHeight(); + int row = (height != 0) ? (py / height) : 0; + int res = (height != 0) ? (py % height) : 0; + printf("%s mon=(%d,%d) vscroll=(%d,%d), row=%d%s\n", __method__, + monsize.x, monsize.y, vsize1.x, vsize1.y, + row, (res == 0 ? "" : "+")); +#endif - // スクロールバーを再設定。 - // 今の所ヘッダが常に1行ある。 - static int HEADLINES = 1; - int pos = (int)monpanel->GetUserData(); - int thumbsize = monpanel->GetRow() - HEADLINES; - int range = monpanel->GetMonitor()->GetMaxHeight() - HEADLINES; - int pagesize = thumbsize - 1; - if (pos > range - thumbsize) { - pos = range - thumbsize; - DoScroll(pos); + // スクロールバーを再設定。 + // 今の所ヘッダが常に1行ある。 + static int HEADLINES = 1; + int pos = (int)monpanel->GetUserData(); + int thumbsize = monpanel->GetRow() - HEADLINES; + int range = monpanel->GetMonitor()->GetMaxHeight() - HEADLINES; + int pagesize = thumbsize - 1; + if (pos > range - thumbsize) { + pos = range - thumbsize; + DoScroll(pos); + } + vscroll->SetScrollParam(pos, thumbsize, range, pagesize); } - vscroll->SetScrollParam(pos, thumbsize, range, pagesize); - - DPRINTF("%s done\n", __method__); - return true; } -// クライアントサイズと最大/最小サイズを計算する。 -// SetSizeHints() を実行し、設定すべきクライアントサイズを返す。 -wxSize -WXScrollMonitorWindow::DoSizeHints() -{ - auto psize = monpanel->GetSize(); - auto vsize = vscroll->GetSize(); - - // 幅は monpanel 幅 + スクロールバーの幅、高さは monpanel の高さで決まる。 - // monpanel には四辺に Padding があることに注意。 - int x = psize.x + vsize.x; - int min_y = std::max(vscroll->GetMinSize().y, - monpanel->GetScreenHeight(1)); - int new_y = std::max(psize.y, min_y); - wxSize minsize(x, min_y); - wxSize maxsize(x, GetMaxClientSize().y); - wxSize incsize(0, monpanel->GetFontHeight()); - wxSize minwin = ClientToWindowSize(minsize); - wxSize maxwin = ClientToWindowSize(maxsize); - wxSize newsize(x, new_y); - DPRINTF("%s MinWin=(%d,%d) RecommendClient=(%d,%d)\n", __method__, - minwin.x, minwin.y, newsize.x, newsize.y); - SetSizeHints(minwin, maxwin, incsize); - - return newsize; -} - // マウスホイールイベント (WXTextScreen 上で起きたやつをこっちに回してある) void WXScrollMonitorWindow::OnMouseWheel(wxMouseEvent& event)