|
|
nono 1.7.0
//
// nono
// Copyright (C) 2022 nono project
// Licensed under nono-license.txt
//
//
// ログレベル設定ウィンドウ
//
#include "wxlogsetting.h"
#include "wxbutton.h"
#include "wxtextscreen.h"
#include "mainapp.h"
#include <algorithm>
//
// パネル部分
//
enum {
ID_BUTTON0 = IDGROUP_LOGSETTING,
ID_local_end = ID_BUTTON0 + 100 * 2, // 適当
};
static_assert(ID_local_end - 1 <= (int)IDGROUP_LOGSETTING_END, "ID exceeded");
// コンストラクタ
WXLogSettingPanel::WXLogSettingPanel(wxWindow *parent)
: inherited(parent)
{
SetName("LogSettingPanel");
// エイリアスを持つオブジェクトだけ抜き出す
for (const auto obj : gMainApp.GetObjects()) {
if (obj->GetAliases().empty() == false) {
objs.emplace_back(obj);
}
}
// ログ名でソート。
// ただし普通にソートすると "(BusErr)" とかの括弧付きがアルファベット
// より上に来てしまうが、ここではこれらは重要ではないので下にしたい。
std::sort(objs.begin(), objs.end(), [](Object *a, Object *b) {
std::string aname = a->GetName();
std::string bname = b->GetName();
if (aname[0] == '(') {
aname[0] = '{';
}
if (bname[0] == '(') {
bname[0] = '{';
}
return aname < bname;
});
// 名前の最大長
maxnamelen = 0;
for (const auto obj : objs) {
maxnamelen = std::max(maxnamelen, (int)obj->GetName().length());
}
// ボタンを用意
int nbuttons = objs.size() * 2;
assertmsg(ID_BUTTON0 + nbuttons < ID_local_end, "nbuttons=%d", nbuttons);
for (int i = 0; i < nbuttons; i++) {
auto btn = new WXButton(this, ID_BUTTON0 + i, wxDefaultSize,
(i % 2 == 0 ? "<" : ">"));
buttons.push_back(btn);
// イベントを接続
btn->Bind(NONO_EVT_BUTTON, &WXLogSettingPanel::OnButton, this);
}
// Sizer 使わず自前でレイアウトする。
SetAutoLayout(true);
FontChanged();
}
// デストラクタ
WXLogSettingPanel::~WXLogSettingPanel()
{
}
// 桁数 col の左端ピクセル座標を返す
inline int
WXLogSettingPanel::Col2PX(int col) const
{
return col * GetFontWidth() + Padding;
}
// 行数 row の上端ピクセル座標を返す
inline int
WXLogSettingPanel::Row2PY(int row) const
{
// 縦はボタン描画の分少し広げてある
return row * (GetFontHeight() + 4) + Padding;
}
// フォントサイズ変更
void
WXLogSettingPanel::FontChanged()
{
inherited::FontChanged();
// 子コントロールに伝搬。
for (auto *btn : buttons) {
btn->FontChanged();
}
Fit();
}
void
WXLogSettingPanel::Fit()
{
// 行数×桁数を基本とする
int col = maxnamelen + 10;
int row = objs.size() + 1;
wxSize size(Col2PX(col) + Padding, Row2PY(row) + Padding);
// バックバッファのサイズを固定。
SetMinBitmapSize(size);
SetSize(size);
}
bool
WXLogSettingPanel::Layout()
{
// ボタンを再配置。
wxSize btnsize(GetFontWidth() * 2 + 4, GetFontHeight() + 4);
for (int i = 0, end = buttons.size(); i < end; i++) {
int x;
if (i % 2 == 0) {
x = Col2PX(maxnamelen + 1) + 2;
} else {
x = Col2PX(maxnamelen + 8) - 2;
}
int y = Row2PY((i / 2) + 1);
buttons[i]->SetSize(x - 2, y - 2, btnsize.x, btnsize.y);
}
return true;
}
// 描画本体
void
WXLogSettingPanel::Draw()
{
const int width = GetFontWidth();
const int height = GetFontHeight();
int row;
int y;
// ヘッダ
y = Row2PY(0);
DrawStringSJIS(Col2PX(0), y, "Name");
DrawStringSJIS(Col2PX(maxnamelen + 1), y, "LogLevel");
row = 1;
for (const auto obj : objs) {
Rect rect;
Color c;
y = Row2PY(row);
// 名前
DrawStringSJIS(Col2PX(0), y, obj->GetName().c_str());
// 値
char lvstr[2];
if (__predict_false(obj->loglevel < 0)) {
lvstr[0] = '-';
} else if (__predict_true(obj->loglevel < 10)) {
lvstr[0] = obj->loglevel + '0';
} else {
lvstr[0] = '?';
}
lvstr[1] = '\0';
DrawStringSJIS(Col2PX(maxnamelen + 5), y, lvstr);
// 値の枠
int x = Col2PX(maxnamelen + 4);
rect = Rect(x, y - 1, width * 3, height + 1);
int l = rect.x;
int t = rect.y;
int r = rect.GetRight();
int b = rect.GetBottom();
bitmap.DrawLineH(UD_GREY, l, t, r);
bitmap.DrawLineH(UD_WHITE, l, b, r + 1);
bitmap.DrawLineV(UD_GREY, l, t + 1, b);
bitmap.DrawLineV(UD_WHITE, r, t, b);
// ボタンは Layout() で配置してある
row++;
}
}
void
WXLogSettingPanel::OnButton(wxCommandEvent& event)
{
int n = event.GetId() - ID_BUTTON0; // ボタン番号
int idx = n / 2; // オブジェクト番号
bool isdown = (n % 2 == 0); // "<" なら true
Object *obj = objs[idx];
int level = obj->loglevel;
if (isdown) {
if (level > -1) {
level--;
}
} else {
// 今の所上限は未定だけど、表示上の都合で一桁にしておくか
if (level < 9) {
level++;
}
}
if (level != obj->loglevel) {
obj->SetLogLevel(level);
// レベルが上下端ならボタンを無効に、そうでなければ有効にする
int down;
int up;
if (isdown) {
down = n;
up = n + 1;
} else {
down = n - 1;
up = n;
}
buttons[down]->Enable((level > -1));
buttons[up]->Enable((level < 9));
Refresh();
}
}
//
// ウィンドウ
//
// コンストラクタ
WXLogSettingWindow::WXLogSettingWindow(wxWindow *parent)
: inherited(parent, wxID_ANY, _("Log Level Setting"))
{
new WXLogSettingPanel(this);
Fit();
}
// デストラクタ
WXLogSettingWindow::~WXLogSettingWindow()
{
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.