--- nono/wx/wxbutton.cpp 2026/04/29 17:05:16 1.1 +++ nono/wx/wxbutton.cpp 2026/04/29 17:05:58 1.1.1.3 @@ -9,7 +9,6 @@ // #include "wxbutton.h" -#include "wxcolor.h" // 通知イベント。 // このボタンが押された時にイベントが発生する。 @@ -19,6 +18,7 @@ wxDEFINE_EVENT(NONO_EVT_BUTTON, wxComman // イベント wxBEGIN_EVENT_TABLE(WXButton, inherited) + EVT_SIZE(WXButton::OnSize) EVT_MOUSE_EVENTS(WXButton::OnMouse) EVT_TIMER(wxID_ANY, WXButton::OnTimer) wxEND_EVENT_TABLE() @@ -28,6 +28,8 @@ WXButton::WXButton(wxWindow *parent, wxW const wxSize& size, const wxString& text, const wxPoint& position) : inherited(parent, id, position, size) { + SetName("Button[" + text + "]"); + // テキストを SJIS に変換し std::string として保存しておく wxCSConv conv("SJIS"); sjistext = text.mb_str(conv); @@ -59,23 +61,46 @@ WXButton::FontChanged() { inherited::FontChanged(); - const auto& sz = GetClientSize(); - - // テキスト描画位置はセンタリング。 - // クライアント領域の上下左右 2 ピクセルはボタンの描画領域のため、 - // テキストは上下左右 2ピクセルずつを除いた部分。 + // テキスト部分のメトリックはここで決まる。 textsize.x = sjistext.size() * font_width; textsize.y = font_height; - if (textsize.x > sz.x - 4) { - textsize.x = sz.x - 4; - } - if (textsize.y > sz.y - 4) { - textsize.y = sz.y - 4; - } - textpos.x = (sz.x - textsize.x) / 2; - textpos.y = (sz.y - textsize.y) / 2; + Fit(); + + // テキストサイズが変わったのでキャンバスを一旦破棄。 Fill(); + Refresh(); +} + +void +WXButton::Fit() +{ + // 現在のテキストが入る最小サイズを求める。 + // テキストの上下左右 2ピクセルずつがボタン描画用のスペース。 + wxSize minsize(textsize.x + 2 + 2, textsize.y + 2 + 2); + + // バックバッファのサイズを固定。 + SetMinBitmapSize(minsize); + + // 最小サイズの影響を受けさせる。 + SetMinSize(minsize); + wxSize size = GetSize(); + size.x = std::max(size.x, minsize.x); + size.y = std::max(size.y, minsize.y); + if (size != GetSize()) { + SetSize(size); + } +} + +void +WXButton::OnSize(wxSizeEvent& event) +{ + // サイズが変わったらセンタリングを維持。 + const wxSize size = event.GetSize(); + textpos.x = (size.x - textsize.x) / 2; + textpos.y = (size.y - textsize.y) / 2; + + event.Skip(); } void @@ -132,9 +157,8 @@ WXButton::Press(bool pressed_) void WXButton::Draw() { - // サイズ未指定の時など - const wxSize cs = GetClientSize(); - if (__predict_false(cs.x < 1 || cs.y < 1)) { + // 起きないはずだけど一応。 + if (__predict_false(fixedsize.x < 1 || fixedsize.y < 1)) { return; } @@ -142,11 +166,21 @@ WXButton::Draw() Color c = IsEnabled() ? UD_BLACK : UD_GREY; DrawStringSJIS(c, textpos.x, textpos.y, sjistext.c_str()); - // 枠 + // ボタンの枠はバックバッファではなく表示枠に合わせて描画する。 + // ただし枠の描画には最低でも 4x4 ピクセルが必要なので、 + // 足りない時は仕方ないのでバックバッファのサイズで描画するか。 + wxSize size = GetSize(); + if (size.x < 4) { + size.x = fixedsize.x; + } + if (size.y < 4) { + size.y = fixedsize.y; + } + int l = 0; int t = 0; - int r = GetClientSize().x - 1; - int b = GetClientSize().y - 1; + int r = size.x - 1; + int b = size.y - 1; if (__predict_true(IsPressed() == false)) { // この場合外寸 7x7、内寸 3x3。