|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.