|
|
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) ! 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: { ! 31: // テキストを SJIS に変換し std::string として保存しておく ! 32: wxCSConv conv("SJIS"); ! 33: sjistext = text.mb_str(conv); ! 34: ! 35: timer.SetOwner(this); ! 36: ! 37: FontChanged(); ! 38: } ! 39: ! 40: // デストラクタ ! 41: WXButton::~WXButton() ! 42: { ! 43: } ! 44: ! 45: bool ! 46: WXButton::Enable(bool enable_) ! 47: { ! 48: // 無効にするとイベントが来なくなるため、 ! 49: // 押し下げた状態で無効にする場合は押し下げを解放してからにする。 ! 50: if (enable_ == false && IsPressed()) { ! 51: Press(false); ! 52: } ! 53: ! 54: return inherited::Enable(enable_); ! 55: } ! 56: ! 57: void ! 58: WXButton::FontChanged() ! 59: { ! 60: inherited::FontChanged(); ! 61: ! 62: const auto& sz = GetClientSize(); ! 63: ! 64: // テキスト描画位置はセンタリング。 ! 65: // クライアント領域の上下左右 2 ピクセルはボタンの描画領域のため、 ! 66: // テキストは上下左右 2ピクセルずつを除いた部分。 ! 67: textsize.x = sjistext.size() * font_width; ! 68: textsize.y = font_height; ! 69: if (textsize.x > sz.x - 4) { ! 70: textsize.x = sz.x - 4; ! 71: } ! 72: if (textsize.y > sz.y - 4) { ! 73: textsize.y = sz.y - 4; ! 74: } ! 75: textpos.x = (sz.x - textsize.x) / 2; ! 76: textpos.y = (sz.y - textsize.y) / 2; ! 77: ! 78: Fill(); ! 79: } ! 80: ! 81: void ! 82: WXButton::OnMouse(wxMouseEvent& event) ! 83: { ! 84: if (event.LeftDown() || event.LeftDClick()) { ! 85: // ボタンを押して.. ! 86: Press(true); ! 87: ! 88: // 押しっぱなし判定のためタイマーを開始。 ! 89: timer.Start(500); ! 90: } ! 91: if (event.LeftUp()) { ! 92: Press(false); ! 93: } ! 94: } ! 95: ! 96: // タイマーイベント ! 97: void ! 98: WXButton::OnTimer(wxTimerEvent& event) ! 99: { ! 100: if (IsPressed()) { ! 101: // 左クリックが続いていたらもう一度 ! 102: Press(true); ! 103: ! 104: // キーリピートと同じ要領で2回目以降は短くする。 ! 105: timer.Start(100); ! 106: } else { ! 107: // 左クリックが終わっていたら終了 ! 108: timer.Stop(); ! 109: } ! 110: } ! 111: ! 112: // ボタンを押したか離したときの処理 ! 113: void ! 114: WXButton::Press(bool pressed_) ! 115: { ! 116: // 状態が変化すれば再描画 ! 117: if (pressed != pressed_) { ! 118: Refresh(); ! 119: } ! 120: ! 121: // 代入 ! 122: pressed = pressed_; ! 123: ! 124: // 状態変化に関わらず、今押していればイベント発行 ! 125: if (IsPressed()) { ! 126: wxCommandEvent newev(NONO_EVT_BUTTON, GetId()); ! 127: newev.SetEventObject(this); ! 128: AddPendingEvent(newev); ! 129: } ! 130: } ! 131: ! 132: void ! 133: WXButton::Draw() ! 134: { ! 135: // サイズ未指定の時など ! 136: const wxSize cs = GetClientSize(); ! 137: if (__predict_false(cs.x < 1 || cs.y < 1)) { ! 138: return; ! 139: } ! 140: ! 141: // 文字 ! 142: Color c = IsEnabled() ? UD_BLACK : UD_GREY; ! 143: DrawStringSJIS(c, textpos.x, textpos.y, sjistext.c_str()); ! 144: ! 145: // 枠 ! 146: int l = 0; ! 147: int t = 0; ! 148: int r = GetClientSize().x - 1; ! 149: int b = GetClientSize().y - 1; ! 150: ! 151: if (__predict_true(IsPressed() == false)) { ! 152: // この場合外寸 7x7、内寸 3x3。 ! 153: // 空白「 」のところが内側。 ! 154: // 「・」は背景色で塗りつぶす (オンオフ逆側の陰影があるため) ! 155: // ! 156: // □□□□□□■ <- (1) ! 157: // □・・・・灰■ <- (2) ! 158: // □・ 灰■ ! 159: // □・ 灰■ ! 160: // □・ 灰■ ! 161: // □灰灰灰灰灰■ <- (3) ! 162: // ■■■■■■■ <- (4) ! 163: // ^ ^ ^ ^ ! 164: //(5)(6) (7)(8) ! 165: ! 166: bitmap.DrawLineH(UD_WHITE, l, t, r); // (1) ! 167: bitmap.DrawLineH(BGPANEL, l + 1, t + 1, r -1); // (2) ! 168: bitmap.DrawLineH(UD_GREY, l + 1, b - 1, r); // (3) ! 169: bitmap.DrawLineH(UD_BLACK, l, b, r + 1); // (4) ! 170: bitmap.DrawLineV(UD_WHITE, l, t + 1, b); // (5) ! 171: bitmap.DrawLineV(BGPANEL, l + 1, t + 2, b - 1); // (6) ! 172: bitmap.DrawLineV(UD_GREY, r - 1, t + 1, b - 1); // (7) ! 173: bitmap.DrawLineV(UD_BLACK, r, t, b); // (8) ! 174: } else { ! 175: // ■■■■■■□ <- (1) ! 176: // ■灰灰灰灰灰□ <- (2) ! 177: // ■灰 ・□ ! 178: // ■灰 ・□ ! 179: // ■灰 ・□ ! 180: // ■灰・・・・□ <- (3) ! 181: // □□□□□□□ <- (4) ! 182: // ^ ^ ^ ^ ! 183: //(5)(6) (7)(8) ! 184: bitmap.DrawLineH(UD_BLACK, l, t, r); // (1) ! 185: bitmap.DrawLineH(UD_GREY, l + 1, t + 1, r); // (2) ! 186: bitmap.DrawLineH(BGPANEL, l + 2, b - 1, r); // (3) ! 187: bitmap.DrawLineH(UD_WHITE, l, b, r + 1); // (4) ! 188: bitmap.DrawLineV(UD_BLACK, l, t + 1, b); // (5) ! 189: bitmap.DrawLineV(UD_GREY, l + 1, t + 1, b); // (6) ! 190: bitmap.DrawLineV(BGPANEL, r - 1, t + 2, b); // (7) ! 191: bitmap.DrawLineV(UD_WHITE, r, t, b); // (8) ! 192: } ! 193: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.