--- nono/wx/wxmonitor.cpp 2026/04/29 17:05:16 1.1.1.8 +++ nono/wx/wxmonitor.cpp 2026/04/29 17:05:53 1.1.1.12 @@ -10,6 +10,15 @@ #include "wxmonitor.h" #include "wxmainframe.h" +#include "monitor.h" + +//#define WINDOW_DEBUG 1 + +#if defined(WINDOW_DEBUG) +#define DPRINTF(fmt...) printf(fmt) +#else +#define DPRINTF(fmt...) /**/ +#endif // // モニターパネル @@ -21,8 +30,8 @@ wxBEGIN_EVENT_TABLE(WXMonitorPanel, inhe wxEND_EVENT_TABLE() // コンストラクタ -WXMonitorPanel::WXMonitorPanel(wxWindow *parent, Monitor& monitor_) - : inherited(parent, monitor_.GetSize()) +WXMonitorPanel::WXMonitorPanel(wxWindow *parent, Monitor *monitor_) + : inherited(parent, monitor_->GetSize()) , monitor(monitor_) { timer.SetOwner(this); @@ -56,7 +65,7 @@ void WXMonitorPanel::DoRefresh() { // モニタースクリーンを更新して - MONITOR_UPDATE(monitor, screen); + monitor->Update(screen); // 必要なら再描画 if (screen.GetBuf() != prevbuf) { @@ -78,12 +87,12 @@ WXMonitorPanel::SetRate(int hz) // コンストラクタ WXMonitorWindow::WXMonitorWindow(wxWindow *parent, const wxString& name, - Monitor& monitor_) + Monitor *monitor_) : inherited(parent, wxID_ANY, name) { // モニタパネル monpanel = new WXMonitorPanel(this, monitor_); - DoSize(); + Fit(); } // デストラクタ @@ -96,35 +105,28 @@ WXMonitorWindow::~WXMonitorWindow() // 縦スクロールバー付きモニタウィンドウ // -// イベントテーブル -wxBEGIN_EVENT_TABLE(WXScrollMonitorWindow, inherited) - EVT_SIZE(WXScrollMonitorWindow::OnSize) -wxEND_EVENT_TABLE() - // コンストラクタ WXScrollMonitorWindow::WXScrollMonitorWindow(wxWindow *parent, - const wxString& name, Monitor& monitor_) + const wxString& name, Monitor *monitor_) : inherited(parent, wxID_ANY, name, DEFAULT_STYLE | wxRESIZE_BORDER) { - // → + DPRINTF("%s begin\n", __method__); + // +--------------+---------+ // | MonitorPanel | VScroll | // +--------------+---------+ - wxBoxSizer *topsizer = new wxBoxSizer(wxHORIZONTAL); - // モニタパネル monpanel = new WXMonitorPanel(this, monitor_); - topsizer->Add(monpanel, 1, wxEXPAND); // スクロールバー vscroll = new WXScrollBar(this, wxID_ANY, wxSB_VERTICAL); - topsizer->Add(vscroll, 0, wxEXPAND); - SetSizer(topsizer); + // 自前レイアウト。 + SetMyLayout(); // ウィンドウサイズを確定させる - DoSize(); + FontChanged(); // スクロールのために (パネル領域での) MouseWheel イベントもここで // 受け取りたい。スクロールバー上のマウスホイール操作はスクロールバーが @@ -137,6 +139,7 @@ WXScrollMonitorWindow::WXScrollMonitorWi // スクロールバーからの位置変更通知 vscroll->Connect(NONO_EVT_SCROLL, wxScrollEventHandler(WXScrollMonitorWindow::OnScroll), NULL, this); + DPRINTF("%s done\n", __method__); } // デストラクタ @@ -144,32 +147,97 @@ WXScrollMonitorWindow::~WXScrollMonitorW { } -bool -WXScrollMonitorWindow::Layout() +void +WXScrollMonitorWindow::FontChanged() { - // 縦リサイズ可能レイアウト - return LayoutTextVResize(monpanel); + monpanel->FontChanged(); + vscroll->FontChanged(); + DPRINTF("%s %d\n", __method__, monpanel->GetFontHeight()); + + Fit(); } -// サイズ変更イベント -void -WXScrollMonitorWindow::OnSize(wxSizeEvent& event) +// 自前レイアウト方式のサイズに関する情報を返す。 +bool +WXScrollMonitorWindow::GetMySizeHints(wxSize *newp, wxSize *minp, wxSize *maxp, + wxSize *incp) { - inherited::OnSize(event); + auto psize = monpanel->GetSize(); + auto vsize = vscroll->GetSize(); - // 今の所ヘッダが常に1行ある - static int HEADLINES = 1; + // 幅は 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; +} - // スクロールバーを再設定 - 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); +bool +WXScrollMonitorWindow::Layout() +{ + 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 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 + + 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); + } + vscroll->SetScrollParam(pos, thumbsize, range, pagesize); } - vscroll->SetScrollParam(pos, thumbsize, range, pagesize); + return true; } // マウスホイールイベント (WXTextScreen 上で起きたやつをこっちに回してある)