|
|
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 "wxlogsetting.h"
1.1.1.2 root 12: #include "wxbutton.h"
1.1 root 13: #include "wxtextscreen.h"
14: #include "mainapp.h"
15: #include <algorithm>
16:
17: //
18: // パネル部分
19: //
20:
1.1.1.2 root 21: enum {
22: ID_BUTTON0 = IDGROUP_LOGSETTING,
1.1.1.3 root 23: ID_local_end = ID_BUTTON0 + 100 * 2, // 適当
1.1.1.2 root 24: };
25: static_assert(ID_local_end - 1 <= (int)IDGROUP_LOGSETTING_END, "ID exceeded");
1.1 root 26:
27: // コンストラクタ
28: WXLogSettingPanel::WXLogSettingPanel(wxWindow *parent)
29: : inherited(parent)
30: {
1.1.1.4 root 31: SetName("LogSettingPanel");
32:
1.1 root 33: // エイリアスを持つオブジェクトだけ抜き出す
34: for (const auto obj : gMainApp.GetObjects()) {
1.1.1.5 root 35: if (obj->GetAliases().empty() == false) {
1.1 root 36: objs.emplace_back(obj);
37: }
38: }
39:
40: // ログ名でソート。
41: // ただし普通にソートすると "(BusErr)" とかの括弧付きがアルファベット
42: // より上に来てしまうが、ここではこれらは重要ではないので下にしたい。
43: std::sort(objs.begin(), objs.end(), [](Object *a, Object *b) {
44: std::string aname = a->GetName();
45: std::string bname = b->GetName();
46: if (aname[0] == '(') {
47: aname[0] = '{';
48: }
49: if (bname[0] == '(') {
50: bname[0] = '{';
51: }
52: return aname < bname;
53: });
54:
55: // 名前の最大長
56: maxnamelen = 0;
57: for (const auto obj : objs) {
58: maxnamelen = std::max(maxnamelen, (int)obj->GetName().length());
59: }
60:
1.1.1.2 root 61: // ボタンを用意
62: int nbuttons = objs.size() * 2;
63: assertmsg(ID_BUTTON0 + nbuttons < ID_local_end, "nbuttons=%d", nbuttons);
64: for (int i = 0; i < nbuttons; i++) {
65: auto btn = new WXButton(this, ID_BUTTON0 + i, wxDefaultSize,
66: (i % 2 == 0 ? "<" : ">"));
67: buttons.push_back(btn);
68:
69: // イベントを接続
1.1.1.6 ! root 70: btn->Bind(NONO_EVT_BUTTON, &WXLogSettingPanel::OnButton, this);
1.1.1.2 root 71: }
72:
73: // Sizer 使わず自前でレイアウトする。
74: SetAutoLayout(true);
1.1 root 75: FontChanged();
76: }
77:
78: // デストラクタ
79: WXLogSettingPanel::~WXLogSettingPanel()
80: {
81: }
82:
83: // 桁数 col の左端ピクセル座標を返す
84: inline int
85: WXLogSettingPanel::Col2PX(int col) const
86: {
87: return col * GetFontWidth() + Padding;
88: }
89:
90: // 行数 row の上端ピクセル座標を返す
91: inline int
92: WXLogSettingPanel::Row2PY(int row) const
93: {
94: // 縦はボタン描画の分少し広げてある
1.1.1.2 root 95: return row * (GetFontHeight() + 4) + Padding;
1.1 root 96: }
97:
1.1.1.4 root 98: // フォントサイズ変更
99: void
100: WXLogSettingPanel::FontChanged()
1.1 root 101: {
1.1.1.4 root 102: inherited::FontChanged();
103:
104: // 子コントロールに伝搬。
105: for (auto *btn : buttons) {
106: btn->FontChanged();
1.1.1.2 root 107: }
1.1 root 108:
1.1.1.4 root 109: Fit();
110: }
111:
112: void
113: WXLogSettingPanel::Fit()
114: {
115: // 行数×桁数を基本とする
116: int col = maxnamelen + 10;
117: int row = objs.size() + 1;
118: wxSize size(Col2PX(col) + Padding, Row2PY(row) + Padding);
119:
120: // バックバッファのサイズを固定。
121: SetMinBitmapSize(size);
122:
123: SetSize(size);
124: }
1.1.1.2 root 125:
1.1.1.4 root 126: bool
127: WXLogSettingPanel::Layout()
128: {
129: // ボタンを再配置。
130: wxSize btnsize(GetFontWidth() * 2 + 4, GetFontHeight() + 4);
1.1.1.2 root 131: for (int i = 0, end = buttons.size(); i < end; i++) {
132: int x;
133: if (i % 2 == 0) {
134: x = Col2PX(maxnamelen + 1) + 2;
135: } else {
136: x = Col2PX(maxnamelen + 8) - 2;
137: }
138: int y = Row2PY((i / 2) + 1);
1.1.1.4 root 139: buttons[i]->SetSize(x - 2, y - 2, btnsize.x, btnsize.y);
1.1.1.2 root 140: }
141:
142: return true;
1.1 root 143: }
144:
145: // 描画本体
146: void
147: WXLogSettingPanel::Draw()
148: {
149: const int width = GetFontWidth();
150: const int height = GetFontHeight();
151: int row;
152: int y;
153:
154: // ヘッダ
155: y = Row2PY(0);
156: DrawStringSJIS(Col2PX(0), y, "Name");
157: DrawStringSJIS(Col2PX(maxnamelen + 1), y, "LogLevel");
158:
159: row = 1;
160: for (const auto obj : objs) {
161: Rect rect;
162: Color c;
163:
164: y = Row2PY(row);
165:
1.1.1.2 root 166: // 名前
1.1 root 167: DrawStringSJIS(Col2PX(0), y, obj->GetName().c_str());
168:
169: // 値
170: char lvstr[2];
171: if (__predict_false(obj->loglevel < 0)) {
172: lvstr[0] = '-';
173: } else if (__predict_true(obj->loglevel < 10)) {
174: lvstr[0] = obj->loglevel + '0';
175: } else {
176: lvstr[0] = '?';
177: }
178: lvstr[1] = '\0';
179: DrawStringSJIS(Col2PX(maxnamelen + 5), y, lvstr);
180:
181: // 値の枠
1.1.1.2 root 182: int x = Col2PX(maxnamelen + 4);
1.1 root 183: rect = Rect(x, y - 1, width * 3, height + 1);
184: int l = rect.x;
185: int t = rect.y;
186: int r = rect.GetRight();
187: int b = rect.GetBottom();
188: bitmap.DrawLineH(UD_GREY, l, t, r);
189: bitmap.DrawLineH(UD_WHITE, l, b, r + 1);
190: bitmap.DrawLineV(UD_GREY, l, t + 1, b);
191: bitmap.DrawLineV(UD_WHITE, r, t, b);
192:
1.1.1.2 root 193: // ボタンは Layout() で配置してある
1.1 root 194:
195: row++;
196: }
197: }
198:
199: void
1.1.1.2 root 200: WXLogSettingPanel::OnButton(wxCommandEvent& event)
1.1 root 201: {
1.1.1.2 root 202: int n = event.GetId() - ID_BUTTON0; // ボタン番号
203: int idx = n / 2; // オブジェクト番号
204: bool isdown = (n % 2 == 0); // "<" なら true
1.1 root 205:
1.1.1.2 root 206: Object *obj = objs[idx];
1.1 root 207: int level = obj->loglevel;
208:
1.1.1.2 root 209: if (isdown) {
1.1 root 210: if (level > -1) {
211: level--;
212: }
1.1.1.2 root 213: } else {
1.1 root 214: // 今の所上限は未定だけど、表示上の都合で一桁にしておくか
215: if (level < 9) {
216: level++;
217: }
218: }
219:
220: if (level != obj->loglevel) {
221: obj->SetLogLevel(level);
222:
1.1.1.2 root 223: // レベルが上下端ならボタンを無効に、そうでなければ有効にする
224: int down;
225: int up;
226: if (isdown) {
227: down = n;
228: up = n + 1;
229: } else {
230: down = n - 1;
231: up = n;
232: }
233: buttons[down]->Enable((level > -1));
234: buttons[up]->Enable((level < 9));
1.1 root 235:
1.1.1.2 root 236: Refresh();
237: }
1.1 root 238: }
239:
240:
241: //
242: // ウィンドウ
243: //
244:
245: // コンストラクタ
246: WXLogSettingWindow::WXLogSettingWindow(wxWindow *parent)
247: : inherited(parent, wxID_ANY, _("Log Level Setting"))
248: {
1.1.1.4 root 249: new WXLogSettingPanel(this);
250: Fit();
1.1 root 251: }
252:
253: // デストラクタ
254: WXLogSettingWindow::~WXLogSettingWindow()
255: {
256: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.