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

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

unix.superglobalmegacorp.com

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