--- nono/wx/wxlogsetting.cpp 2026/04/29 17:05:08 1.1.1.1 +++ nono/wx/wxlogsetting.cpp 2026/04/29 17:05:44 1.1.1.4 @@ -9,6 +9,7 @@ // #include "wxlogsetting.h" +#include "wxbutton.h" #include "wxcolor.h" #include "wxtextscreen.h" #include "mainapp.h" @@ -18,19 +19,23 @@ // パネル部分 // -// イベントテーブル -wxBEGIN_EVENT_TABLE(WXLogSettingPanel, inherited) - EVT_LEFT_DOWN(WXLogSettingPanel::OnLeftDown) - EVT_LEFT_UP(WXLogSettingPanel::OnLeftUp) -wxEND_EVENT_TABLE() +enum { + ID_BUTTON0 = IDGROUP_LOGSETTING, + ID_local_end = ID_BUTTON0 + 100 * 2, // 適当 +}; +static_assert(ID_local_end - 1 <= (int)IDGROUP_LOGSETTING_END, "ID exceeded"); // コンストラクタ WXLogSettingPanel::WXLogSettingPanel(wxWindow *parent) : inherited(parent) { + SetName("LogSettingPanel"); + // エイリアスを持つオブジェクトだけ抜き出す for (const auto obj : gMainApp.GetObjects()) { - if (obj->GetAliases().empty() == false) { + if (obj->GetAliases().empty() == false && + obj->GetId() != OBJ_LOGMONITOR) + { objs.emplace_back(obj); } } @@ -56,6 +61,21 @@ WXLogSettingPanel::WXLogSettingPanel(wxW maxnamelen = std::max(maxnamelen, (int)obj->GetName().length()); } + // ボタンを用意 + int nbuttons = objs.size() * 2; + assertmsg(ID_BUTTON0 + nbuttons < ID_local_end, "nbuttons=%d", nbuttons); + for (int i = 0; i < nbuttons; i++) { + auto btn = new WXButton(this, ID_BUTTON0 + i, wxDefaultSize, + (i % 2 == 0 ? "<" : ">")); + buttons.push_back(btn); + + // イベントを接続 + btn->Connect(NONO_EVT_BUTTON, + wxCommandEventHandler(WXLogSettingPanel::OnButton), NULL, this); + } + + // Sizer 使わず自前でレイアウトする。 + SetAutoLayout(true); FontChanged(); } @@ -76,23 +96,7 @@ inline int WXLogSettingPanel::Row2PY(int row) const { // 縦はボタン描画の分少し広げてある - return row * (GetFontHeight() + 3) + Padding; -} - -// ピクセル x が含まれる桁を返す。 -// py がパディング領域を指していると(テキストとしての)範囲外の値を返す。 -inline int -WXLogSettingPanel::PX2Col(int px) const -{ - return (px - Padding) / GetFontWidth(); -} - -// ピクセル y が含まれる行を返す。 -// py がパディング領域を指していると(テキストとしての)範囲外の値を返す。 -inline int -WXLogSettingPanel::PY2Row(int py) const -{ - return (py - Padding) / (GetFontHeight() + 3); + return row * (GetFontHeight() + 4) + Padding; } // フォントサイズ変更 @@ -101,67 +105,45 @@ WXLogSettingPanel::FontChanged() { inherited::FontChanged(); + // 子コントロールに伝搬。 + for (auto *btn : buttons) { + btn->FontChanged(); + } + + Fit(); +} + +void +WXLogSettingPanel::Fit() +{ // 行数×桁数を基本とする int col = maxnamelen + 10; int row = objs.size() + 1; + wxSize size(Col2PX(col) + Padding, Row2PY(row) + Padding); - int width = Col2PX(col) + Padding; - int height = Row2PY(row) + Padding; - SetClientSize(width, height); - SetMinClientSize(wxSize(width, height)); + // バックバッファのサイズを固定。 + SetMinBitmapSize(size); + + SetSize(size); } -// ボタンのようなものを描画する。rect は外寸。 -void -WXLogSettingPanel::DrawButton(const Rect& rect, bool button_pressed) +bool +WXLogSettingPanel::Layout() { - int l = rect.x; - int t = rect.y; - int r = rect.GetRight(); - int b = rect.GetBottom(); - - if (__predict_true(button_pressed == false)) { - // この場合外寸 7x7、内寸 3x3。 - // 空白「 」のところが内側。 - // 「・」は背景色で塗りつぶす (オンオフ逆側の陰影があるため) - // - // □□□□□□■ <- (1) - // □・・・・灰■ <- (2) - // □・   灰■ - // □・   灰■ - // □・   灰■ - // □灰灰灰灰灰■ <- (3) - // ■■■■■■■ <- (4) - // ^ ^ ^ ^ - //(5)(6) (7)(8) - - bitmap.DrawLineH(UD_WHITE, l, t, r); // (1) - bitmap.DrawLineH(BGPANEL, l + 1, t + 1, r -1); // (2) - bitmap.DrawLineH(UD_GREY, l + 1, b - 1, r); // (3) - bitmap.DrawLineH(UD_BLACK, l, b, r + 1); // (4) - bitmap.DrawLineV(UD_WHITE, l, t + 1, b); // (5) - bitmap.DrawLineV(BGPANEL, l + 1, t + 2, b - 1); // (6) - bitmap.DrawLineV(UD_GREY, r - 1, t + 1, b - 1); // (7) - bitmap.DrawLineV(UD_BLACK, r, t, b); // (8) - } else { - // ■■■■■■□ <- (1) - // ■灰灰灰灰灰□ <- (2) - // ■灰   ・□ - // ■灰   ・□ - // ■灰   ・□ - // ■灰・・・・□ <- (3) - // □□□□□□□ <- (4) - // ^ ^ ^ ^ - //(5)(6) (7)(8) - bitmap.DrawLineH(UD_BLACK, l, t, r); // (1) - bitmap.DrawLineH(UD_GREY, l + 1, t + 1, r); // (2) - bitmap.DrawLineH(BGPANEL, l + 2, b - 1, r); // (3) - bitmap.DrawLineH(UD_WHITE, l, b, r + 1); // (4) - bitmap.DrawLineV(UD_BLACK, l, t + 1, b); // (5) - bitmap.DrawLineV(UD_GREY, l + 1, t + 1, b); // (6) - bitmap.DrawLineV(BGPANEL, r - 1, t + 2, b); // (7) - bitmap.DrawLineV(UD_WHITE, r, t, b); // (8) + // ボタンを再配置。 + wxSize btnsize(GetFontWidth() * 2 + 4, GetFontHeight() + 4); + for (int i = 0, end = buttons.size(); i < end; i++) { + int x; + if (i % 2 == 0) { + x = Col2PX(maxnamelen + 1) + 2; + } else { + x = Col2PX(maxnamelen + 8) - 2; + } + int y = Row2PY((i / 2) + 1); + buttons[i]->SetSize(x - 2, y - 2, btnsize.x, btnsize.y); } + + return true; } // 描画本体 @@ -185,19 +167,9 @@ WXLogSettingPanel::Draw() y = Row2PY(row); + // 名前 DrawStringSJIS(Col2PX(0), y, obj->GetName().c_str()); - // 左ボタン (領域はテキスト2文字分) - int x = Col2PX(maxnamelen + 1); - if (obj->loglevel < 0) { - c = UD_GREY; - } else { - c = GetTextForeColor(); - } - DrawStringSJIS(c, x + (width / 2), y, "<"); - rect = Rect(x, y - 1, width * 2 + 2, height + 2); - DrawButton(rect, (row == -pressed)); - // 値 char lvstr[2]; if (__predict_false(obj->loglevel < 0)) { @@ -211,7 +183,7 @@ WXLogSettingPanel::Draw() DrawStringSJIS(Col2PX(maxnamelen + 5), y, lvstr); // 値の枠 - x = Col2PX(maxnamelen + 4); + int x = Col2PX(maxnamelen + 4); rect = Rect(x, y - 1, width * 3, height + 1); int l = rect.x; int t = rect.y; @@ -222,68 +194,51 @@ WXLogSettingPanel::Draw() bitmap.DrawLineV(UD_GREY, l, t + 1, b); bitmap.DrawLineV(UD_WHITE, r, t, b); - // 右ボタン - x = Col2PX(maxnamelen + 8); - if (obj->loglevel >= 9) { - c = UD_GREY; - } else { - c = GetTextForeColor(); - } - DrawStringSJIS(c, x + (width / 2), y, ">"); - rect = Rect(x, y - 1, width * 2 + 2, height + 2); - DrawButton(rect, (row == pressed)); + // ボタンは Layout() で配置してある row++; } } -// 左クリック (Down) イベント void -WXLogSettingPanel::OnLeftDown(wxMouseEvent& event) +WXLogSettingPanel::OnButton(wxCommandEvent& event) { - const wxPoint& pos = event.GetPosition(); - int x = PX2Col(pos.x); - int y = PY2Row(pos.y); - - // 上下のパディング領域とヘッダ行を先に除いておく - // (左右は影響しないので放置でいい) - if (y < 1 || y >= objs.size()) { - return; - } + int n = event.GetId() - ID_BUTTON0; // ボタン番号 + int idx = n / 2; // オブジェクト番号 + bool isdown = (n % 2 == 0); // "<" なら true - Object *obj = objs[y - 1]; + Object *obj = objs[idx]; int level = obj->loglevel; - // クリックされた場所がボタンの位置か - if (maxnamelen + 1 <= x && x <= maxnamelen + 2) { + if (isdown) { if (level > -1) { level--; } - // "<" ボタンは負数で覚えておく (0 はないので大丈夫) - pressed = -y; - } else if (maxnamelen + 8 <= x) { + } else { // 今の所上限は未定だけど、表示上の都合で一桁にしておくか if (level < 9) { level++; } - // ">" ボタンは正数で覚えておく - pressed = y; } if (level != obj->loglevel) { obj->SetLogLevel(level); - } - Refresh(); -} + // レベルが上下端ならボタンを無効に、そうでなければ有効にする + int down; + int up; + if (isdown) { + down = n; + up = n + 1; + } else { + down = n - 1; + up = n; + } + buttons[down]->Enable((level > -1)); + buttons[up]->Enable((level < 9)); -// 左クリック (Up) イベント -void -WXLogSettingPanel::OnLeftUp(wxMouseEvent& event) -{ - // クリックを上げた場所は問わない - pressed = 0; - Refresh(); + Refresh(); + } } @@ -295,9 +250,8 @@ WXLogSettingPanel::OnLeftUp(wxMouseEvent WXLogSettingWindow::WXLogSettingWindow(wxWindow *parent) : inherited(parent, wxID_ANY, _("Log Level Setting")) { - panel = new WXLogSettingPanel(this); - - DoSize(); + new WXLogSettingPanel(this); + Fit(); } // デストラクタ