Annotation of nono/wx/wxbutton.cpp, revision 1.1.1.2

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2022 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // 独自ボタン
                      9: //
                     10: 
                     11: #include "wxbutton.h"
                     12: #include "wxcolor.h"
                     13: 
                     14: // 通知イベント。
                     15: // このボタンが押された時にイベントが発生する。
                     16: // 引数は wxCommandEvent だが、イベントタイプは EVT_BUTTON ではなく
                     17: // NONO_EVT_BUTTON を使用していることが異なる。
                     18: wxDEFINE_EVENT(NONO_EVT_BUTTON, wxCommandEvent);
                     19: 
                     20: // イベント
                     21: wxBEGIN_EVENT_TABLE(WXButton, inherited)
1.1.1.2 ! root       22:        EVT_SIZE(WXButton::OnSize)
1.1       root       23:        EVT_MOUSE_EVENTS(WXButton::OnMouse)
                     24:        EVT_TIMER(wxID_ANY, WXButton::OnTimer)
                     25: wxEND_EVENT_TABLE()
                     26: 
                     27: // コンストラクタ
                     28: WXButton::WXButton(wxWindow *parent, wxWindowID id,
                     29:        const wxSize& size, const wxString& text, const wxPoint& position)
                     30:        : inherited(parent, id, position, size)
                     31: {
1.1.1.2 ! root       32:        SetName("Button[" + text + "]");
        !            33: 
1.1       root       34:        // テキストを SJIS に変換し std::string として保存しておく
                     35:        wxCSConv conv("SJIS");
                     36:        sjistext = text.mb_str(conv);
                     37: 
                     38:        timer.SetOwner(this);
                     39: 
                     40:        FontChanged();
                     41: }
                     42: 
                     43: // デストラクタ
                     44: WXButton::~WXButton()
                     45: {
                     46: }
                     47: 
                     48: bool
                     49: WXButton::Enable(bool enable_)
                     50: {
                     51:        // 無効にするとイベントが来なくなるため、
                     52:        // 押し下げた状態で無効にする場合は押し下げを解放してからにする。
                     53:        if (enable_ == false && IsPressed()) {
                     54:                Press(false);
                     55:        }
                     56: 
                     57:        return inherited::Enable(enable_);
                     58: }
                     59: 
                     60: void
                     61: WXButton::FontChanged()
                     62: {
                     63:        inherited::FontChanged();
                     64: 
1.1.1.2 ! root       65:        // テキスト部分のメトリックはここで決まる。
1.1       root       66:        textsize.x = sjistext.size() * font_width;
                     67:        textsize.y = font_height;
                     68: 
1.1.1.2 ! root       69:        Fit();
        !            70: 
        !            71:        // テキストサイズが変わったのでキャンバスを一旦破棄。
1.1       root       72:        Fill();
1.1.1.2 ! root       73:        Refresh();
        !            74: }
        !            75: 
        !            76: void
        !            77: WXButton::Fit()
        !            78: {
        !            79:        // 現在のテキストが入る最小サイズを求める。
        !            80:        // テキストの上下左右 2ピクセルずつがボタン描画用のスペース。
        !            81:        wxSize minsize(textsize.x + 2 + 2, textsize.y + 2 + 2);
        !            82: 
        !            83:        // バックバッファのサイズを固定。
        !            84:        SetMinBitmapSize(minsize);
        !            85: 
        !            86:        // 最小サイズの影響を受けさせる。
        !            87:        SetMinSize(minsize);
        !            88:        wxSize size = GetSize();
        !            89:        size.x = std::max(size.x, minsize.x);
        !            90:        size.y = std::max(size.y, minsize.y);
        !            91:        if (size != GetSize()) {
        !            92:                SetSize(size);
        !            93:        }
        !            94: }
        !            95: 
        !            96: void
        !            97: WXButton::OnSize(wxSizeEvent& event)
        !            98: {
        !            99:        // サイズが変わったらセンタリングを維持。
        !           100:        const wxSize size = event.GetSize();
        !           101:        textpos.x = (size.x - textsize.x) / 2;
        !           102:        textpos.y = (size.y - textsize.y) / 2;
        !           103: 
        !           104:        event.Skip();
1.1       root      105: }
                    106: 
                    107: void
                    108: WXButton::OnMouse(wxMouseEvent& event)
                    109: {
                    110:        if (event.LeftDown() || event.LeftDClick()) {
                    111:                // ボタンを押して..
                    112:                Press(true);
                    113: 
                    114:                // 押しっぱなし判定のためタイマーを開始。
                    115:                timer.Start(500);
                    116:        }
                    117:        if (event.LeftUp()) {
                    118:                Press(false);
                    119:        }
                    120: }
                    121: 
                    122: // タイマーイベント
                    123: void
                    124: WXButton::OnTimer(wxTimerEvent& event)
                    125: {
                    126:        if (IsPressed()) {
                    127:                // 左クリックが続いていたらもう一度
                    128:                Press(true);
                    129: 
                    130:                // キーリピートと同じ要領で2回目以降は短くする。
                    131:                timer.Start(100);
                    132:        } else {
                    133:                // 左クリックが終わっていたら終了
                    134:                timer.Stop();
                    135:        }
                    136: }
                    137: 
                    138: // ボタンを押したか離したときの処理
                    139: void
                    140: WXButton::Press(bool pressed_)
                    141: {
                    142:        // 状態が変化すれば再描画
                    143:        if (pressed != pressed_) {
                    144:                Refresh();
                    145:        }
                    146: 
                    147:        // 代入
                    148:        pressed = pressed_;
                    149: 
                    150:        // 状態変化に関わらず、今押していればイベント発行
                    151:        if (IsPressed()) {
                    152:                wxCommandEvent newev(NONO_EVT_BUTTON, GetId());
                    153:                newev.SetEventObject(this);
                    154:                AddPendingEvent(newev);
                    155:        }
                    156: }
                    157: 
                    158: void
                    159: WXButton::Draw()
                    160: {
1.1.1.2 ! root      161:        // 起きないはずだけど一応。
        !           162:        if (__predict_false(fixedsize.x < 1 || fixedsize.y < 1)) {
1.1       root      163:                return;
                    164:        }
                    165: 
                    166:        // 文字
                    167:        Color c = IsEnabled() ? UD_BLACK : UD_GREY;
                    168:        DrawStringSJIS(c, textpos.x, textpos.y, sjistext.c_str());
                    169: 
1.1.1.2 ! root      170:        // ボタンの枠はバックバッファではなく表示枠に合わせて描画する。
        !           171:        // ただし枠の描画には最低でも 4x4 ピクセルが必要なので、
        !           172:        // 足りない時は仕方ないのでバックバッファのサイズで描画するか。
        !           173:        wxSize size = GetSize();
        !           174:        if (size.x < 4) {
        !           175:                size.x = fixedsize.x;
        !           176:        }
        !           177:        if (size.y < 4) {
        !           178:                size.y = fixedsize.y;
        !           179:        }
        !           180: 
1.1       root      181:        int l = 0;
                    182:        int t = 0;
1.1.1.2 ! root      183:        int r = size.x - 1;
        !           184:        int b = size.y - 1;
1.1       root      185: 
                    186:        if (__predict_true(IsPressed() == false)) {
                    187:                // この場合外寸 7x7、内寸 3x3。
                    188:                // 空白「 」のところが内側。
                    189:                // 「・」は背景色で塗りつぶす (オンオフ逆側の陰影があるため)
                    190:                //
                    191:                // □□□□□□■ <- (1)
                    192:                // □・・・・灰■ <- (2)
                    193:                // □・   灰■
                    194:                // □・   灰■
                    195:                // □・   灰■
                    196:                // □灰灰灰灰灰■ <- (3)
                    197:                // ■■■■■■■ <- (4)
                    198:                // ^ ^       ^ ^
                    199:                //(5)(6)    (7)(8)
                    200: 
                    201:                bitmap.DrawLineH(UD_WHITE, l, t, r);                            // (1)
                    202:                bitmap.DrawLineH(BGPANEL,  l + 1, t + 1, r -1);         // (2)
                    203:                bitmap.DrawLineH(UD_GREY,  l + 1, b - 1, r);            // (3)
                    204:                bitmap.DrawLineH(UD_BLACK, l, b, r + 1);                        // (4)
                    205:                bitmap.DrawLineV(UD_WHITE, l, t + 1, b);                        // (5)
                    206:                bitmap.DrawLineV(BGPANEL,  l + 1, t + 2, b - 1);        // (6)
                    207:                bitmap.DrawLineV(UD_GREY,  r - 1, t + 1, b - 1);        // (7)
                    208:                bitmap.DrawLineV(UD_BLACK, r, t, b);                            // (8)
                    209:        } else {
                    210:                // ■■■■■■□ <- (1)
                    211:                // ■灰灰灰灰灰□ <- (2)
                    212:                // ■灰   ・□
                    213:                // ■灰   ・□
                    214:                // ■灰   ・□
                    215:                // ■灰・・・・□ <- (3)
                    216:                // □□□□□□□ <- (4)
                    217:                // ^ ^       ^ ^
                    218:                //(5)(6)    (7)(8)
                    219:                bitmap.DrawLineH(UD_BLACK, l, t, r);                            // (1)
                    220:                bitmap.DrawLineH(UD_GREY,  l + 1, t + 1, r);            // (2)
                    221:                bitmap.DrawLineH(BGPANEL,  l + 2, b - 1, r);            // (3)
                    222:                bitmap.DrawLineH(UD_WHITE, l, b, r + 1);                        // (4)
                    223:                bitmap.DrawLineV(UD_BLACK, l, t + 1, b);                        // (5)
                    224:                bitmap.DrawLineV(UD_GREY,  l + 1, t + 1, b);            // (6)
                    225:                bitmap.DrawLineV(BGPANEL,  r - 1, t + 2, b);            // (7)
                    226:                bitmap.DrawLineV(UD_WHITE, r, t, b);                            // (8)
                    227:        }
                    228: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.