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