--- nono/wx/wxsoftkey.cpp 2026/04/29 17:05:07 1.1.1.10 +++ nono/wx/wxsoftkey.cpp 2026/04/29 17:05:16 1.1.1.13 @@ -4,10 +4,15 @@ // Licensed under nono-license.txt // +// +// ソフトウェアキーボード +// + #include "wxsoftkey.h" +#include "fontmanager.h" #include "wxcolor.h" +#include "wxmainframe.h" #include "wxmainview.h" -#include "wxtextscreen.h" #include "wxuimessage.h" #include "sram.h" @@ -28,7 +33,6 @@ wxBEGIN_EVENT_TABLE(WXSoftKeyPanel, inhe EVT_LEFT_UP(WXSoftKeyPanel::OnLeftUp) EVT_LEFT_DCLICK(WXSoftKeyPanel::OnLeftDClick) EVT_RIGHT_DOWN(WXSoftKeyPanel::OnRightDown) - EVT_PAINT(WXSoftKeyPanel::OnPaint) EVT_TIMER(wxID_ANY, WXSoftKeyPanel::OnTimer) wxEND_EVENT_TABLE() @@ -38,12 +42,15 @@ WXSoftKeyPanel::WXSoftKeyPanel(wxWindow : inherited(parent) , keydata(keydata_) { + // デバイスを取得 + keyboard = GetKeyboard(); + timer.SetOwner(this); u_width = u_width_; u_height = u_height_; - DoSize(); + FontChanged(); // トグル動作にするキー toggle.emplace(KC_SHIFT, 0); @@ -57,16 +64,23 @@ WXSoftKeyPanel::WXSoftKeyPanel(wxWindow std::fill(persistence.begin(), persistence.end(), 0); // このパネルへのキー入力はメインビューへのキー入力と同じ。 + auto mainframe = dynamic_cast(GetParent()->GetParent()); + auto mainview = mainframe->GetMainView(); Connect(wxEVT_CHAR, wxCharEventHandler(WXMainView::OnChar), NULL, - gMainView); + mainview); Connect(wxEVT_KEY_UP, wxKeyEventHandler(WXMainView::OnKeyUp), NULL, - gMainView); + mainview); Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(WXMainView::OnKeyDown), NULL, - gMainView); + mainview); // VM からの通知を受け取る WXUIMessage::Connect(UIMessage::KEYBOARD, this, wxCommandEventHandler(WXSoftKeyPanel::OnKeyChanged)); + + // 初期タイトルを保存しといて.. + title = dynamic_cast(parent)->GetTitle(); + // キーボードの接続状況でタイトルを更新する + UpdateTitle(); } // デストラクタ @@ -83,16 +97,34 @@ WXSoftKeyPanel::~WXSoftKeyPanel() timer.Stop(); - WXUIMessage::Disconnect(UIMessage::KEYBOARD, + WXUIMessage::Disconnect(UIMessage::KEYBOARD, this, wxCommandEventHandler(WXSoftKeyPanel::OnKeyChanged)); } +// キーボードの接続状況によって親フレームのタイトルを更新する。 +// ついでにメンバ変数を更新する。 +void +WXSoftKeyPanel::UpdateTitle() +{ + auto parent = dynamic_cast(GetParent()); + assert(parent); + + // 次回比較用にメンバ変数に覚えておく + connected = keyboard->IsConnected(); + + if (connected) { + parent->SetTitle(title); + } else { + parent->SetTitle(title + _(" (disconnected)")); + } +} + // color.Keytop の初期化(補間)。 // num はキートップの種類の数。1 か 2 void WXSoftKeyPanel::InitColorKeytop(int num) { - wxColour pressed = UD_BLUE; + Color pressed = UD_BLUE; auto f = [](int a, int b, int x) { return a * x / 100 + b * (100 - x) / 100; @@ -103,38 +135,19 @@ WXSoftKeyPanel::InitColorKeytop(int num) for (int i = 0; i < num; i++) { for (int j = 1; j < 10; j++) { int n = j * 100 / 9; - color.Keytop[i][j] = wxColour( - f(pressed.Red(), color.Keytop[i][0].Red(), n), - f(pressed.Green(), color.Keytop[i][0].Green(), n), - f(pressed.Blue(), color.Keytop[i][0].Blue(), n)); + color.Keytop[i][j] = Color( + f(pressed.r, color.Keytop[i][0].r, n), + f(pressed.g, color.Keytop[i][0].g, n), + f(pressed.b, color.Keytop[i][0].b, n)); } } } -// フォントサイズ変更 (外部インタフェース) +// フォントサイズ変更 void -WXSoftKeyPanel::SetFontSize(FontId new_fontid) +WXSoftKeyPanel::FontChanged() { - // 同じなら何もしない - if (fontid == new_fontid) { - return; - } - - // フォントを更新 - UpdateFont(new_fontid); - - // サイズ変更処理 - DoSize(); -} - -// サイズ変更処理 -// サイズを変更したい時に呼ぶ (サイズが変更されたらではない)。 -// ここではサイズは fontsize にのみ依存しているので、フォントサイズが -// 変化/確定した時に呼び出すこと。 -void -WXSoftKeyPanel::DoSize() -{ - assert(fontid != FontId::None); + inherited::FontChanged(); // このパネル内の描画の基本単位 unit = font_height / 4; @@ -148,9 +161,9 @@ WXSoftKeyPanel::DoSize() // | | | | // --+---+---+--(A)--+------(B) // | | | - // | [ | | - // | | Enter | - // --+---+---+--(F)-(E) | + // | [ | Enter | + // | | | + // --+---+---+--(F)-(E) - - (G) // | | | | // | : | ] | | // | | | | @@ -158,32 +171,29 @@ WXSoftKeyPanel::DoSize() // | | // _ | SHIFT | // + // Enter キーの上半分 A-B-G-F を enter_top。F-G の線分を含む。 + // Enter キーの下半分 E-G-C-D を enter_btm。E-G の線分を含む。 const keydata_t& keybs = FindKeydata(KC_BS); const keydata_t& keyleft = FindKeydata(KC_bracketleft); const keydata_t& keyright = FindKeydata(KC_bracketright); const keydata_t& keyscore = FindKeydata(KC_underscore); - // 各点のピクセル座標 - enter_points = { - { keyleft.right() * unit, keyleft.y * unit }, // A - { keybs.right() * unit, keyleft.y * unit }, // B - { keybs.right() * unit, keyscore.y * unit }, // C - { keyright.right() * unit, keyscore.y * unit }, // D - { keyright.right() * unit, keyright.y * unit }, // E - { keyleft.right() * unit, keyright.y * unit }, // F - }; - // 当たり判定用のリージョン - enter_region = wxRegion(enter_points.size(), enter_points.data()); + enter_top.SetLTRB( + keyleft.right() * unit, keyleft.y * unit, + keybs.right() * unit, keyright.y * unit); + enter_btm.SetLTRB( + keyright.right() * unit, keyright.y * unit, + keybs.right() * unit, keyscore.y * unit); - // コントロールの大きさを変更 + // アイコンを変更。参照順序の関係で下のほうにおいてある…。 + InitIcon(); + + // バックバッファのサイズを固定する wxSize size(u_width * unit, u_height * unit); + SetFixedSize(size); + + // コントロールの大きさを変更 SetClientSize(size); SetMinClientSize(size); - - // ビットマップ作成 - bitmap.Create(size.x, size.y); - - // 再描画を指示 - Refresh(); } void @@ -223,32 +233,22 @@ WXSoftKeyPanel::OnKeyChanged(wxCommandEv // ソフトウェアキーボードの KeyUp() で開放された場合のどちらも // ここでクリア。 for (auto& k : toggle) { - if (gKeyboard->IsPressed(k.first) == false) { + if (keyboard->IsPressed(k.first) == false) { k.second = 0; } } - Refresh(); -} + // 接続状況が変わっていたらタイトルを更新。 + if (keyboard->IsConnected() != connected) { + UpdateTitle(); + } -// 描画イベント (UI スレッドから呼ばれる) -void -WXSoftKeyPanel::OnPaint(wxPaintEvent& event) -{ - // メモリ DC に描画 - wxMemoryDC memDC; - memDC.SelectObject(bitmap); - Draw(memDC); - - // 実画面 DC にコピー - wxPaintDC dstDC(this); - wxSize size = bitmap.GetSize(); - dstDC.Blit(0, 0, size.x, size.y, &memDC, 0, 0); + Refresh(); } // 描画本体 void -WXSoftKeyPanel::Draw(wxDC& dc) +WXSoftKeyPanel::Draw() { bool timer_start = false; @@ -260,19 +260,21 @@ WXSoftKeyPanel::Draw(wxDC& dc) if ((2 < persistence[KC_SHIFT_L] && persistence[KC_SHIFT_L] < 10) || (2 < persistence[KC_SHIFT_R] && persistence[KC_SHIFT_R] < 10) || (2 < persistence[KC_SHIFT] && persistence[KC_SHIFT] < 10) || - gKeyboard->IsShift()) + keyboard->IsShift()) { modifier = ModShift; } else { modifier = ModNormal; } - dc.SetPen(wxPen(color.Background)); - dc.SetBrush(wxBrush(color.Background)); - dc.DrawRectangle(wxPoint(0, 0), GetSize()); + auto text_color = color.Text; + + // キーボードが接続されていないときは刻印をグレーにしておく + if (keyboard->IsConnected() == false) { + text_color = UD_GREY; + } + SetTextForeColor(text_color); - dc.SetPen(color.Text); - SetTextForeColor(color.Text); for (const auto& key : keydata) { int c = persistence[key.keycode]; if (0 < c && c < 10) { @@ -281,7 +283,7 @@ WXSoftKeyPanel::Draw(wxDC& dc) timer_start = true; } else { // そうでない場合に限り、現在の状態を問い合わせる - bool is_pressed = gKeyboard->IsPressed(key.keycode); + bool is_pressed = keyboard->IsPressed(key.keycode); if (is_pressed) { // 押されている c = 10; @@ -298,13 +300,14 @@ WXSoftKeyPanel::Draw(wxDC& dc) } SetTextBackColor(color.Keytop[key.coltype][c]); - dc.SetBrush(color.Keytop[key.coltype][c]); - // エンターキーだけ枠の描き方が違うので別処理 - if (__predict_false(key.x < 0)) { - DrawEnterKey(dc); + // エンターキーとブザー表示は描き方が違うので別処理 + if (__predict_false(key.keycode == KC_enter)) { + DrawEnterKey(); + } else if (__predict_false(key.keycode == KC_buzzer)) { + DrawBuzzer(key); } else { - DrawKey(dc, key); + DrawKey(key); } } @@ -317,14 +320,16 @@ WXSoftKeyPanel::Draw(wxDC& dc) // 指定のキーを一つ (枠から刻印まで) 描画する。 void -WXSoftKeyPanel::DrawKey(wxDC& dc, const keydata_t& key) +WXSoftKeyPanel::DrawKey(const keydata_t& key) { uint attr = TA::Normal; // 枠 - wxPoint pt(key.x * unit, key.y * unit); - wxSize sz(key.w * unit + 1, key.h * unit + 1); - dc.DrawRectangle(pt, sz); + Rect rect( + key.x * unit, key.y * unit, + key.w * unit + 1, key.h * unit + 1); + bitmap.FillRect(palette[0], rect); + bitmap.DrawRect(color.Text, rect); // 刻印を選択 const char *disp = key.disp[modifier]; @@ -342,7 +347,9 @@ WXSoftKeyPanel::DrawKey(wxDC& dc, const // Shift_JIS に変換 wxString utfstr(disp, wxConvUTF8); - const char *sjis = (const char *)utfstr.mb_str(conv); + // mb_str() をキャストせずに一度保持しておく必要がある (scan-build 対策) + auto mbstr = utfstr.mb_str(conv); + const char *sjis = (const char *)mbstr; // 改行があれば2行に分割 char sjis1[8] {}; char sjis2[8] {}; @@ -367,78 +374,190 @@ WXSoftKeyPanel::DrawKey(wxDC& dc, const // LED を描画 (機種によって色々違うので個別クラス側で処理) if (key.led >= 0) { - const wxPen oldpen = dc.GetPen(); - const wxBrush oldbrush = dc.GetBrush(); - - y += DrawLED(dc, key); - - dc.SetPen(oldpen); - dc.SetBrush(oldbrush); + y += DrawLED(key); } // 文字を描画 - pt = wxPoint(x * unit + 1, y * unit + 1); + x = x * unit + 1; + y = y * unit + 1; if (strcmp(disp, EnterMark) == 0) { - DrawEnterMark(dc, pt); + bitmap.DrawBitmap(x, y, *enter_icon, palette); } else { if (lf == NULL) { // 1行の場合 - DrawStringSJIS(dc, pt.x, pt.y, sjis, attr); + DrawStringSJIS(x, y, sjis, attr); } else { // 2行の場合 - DrawStringSJIS(dc, pt.x, pt.y, sjis1); - pt.y += 4 * unit; - DrawStringSJIS(dc, pt.x, pt.y, sjis2); + DrawStringSJIS(x, y, sjis1); + y += 4 * unit; + DrawStringSJIS(x, y, sjis2); } } } // エンターキー void -WXSoftKeyPanel::DrawEnterKey(wxDC& dc) +WXSoftKeyPanel::DrawEnterKey() { - // エンターキーを描画 - dc.DrawPolygon(enter_points.size(), enter_points.data()); + // 矩形の内側を背景色で塗りつぶす。 + bitmap.FillRect(palette[0], enter_top); + bitmap.FillRect(palette[0], enter_btm); + + // 周囲の線分 + // (A)-(B) + bitmap.DrawLineH(color.Text, + enter_top.x, enter_top.y, enter_top.GetRight()); + // (B)-(C) + bitmap.DrawLineV(color.Text, + enter_top.GetRight(), enter_top.y, enter_btm.GetBottom()); + // (C)-(D) + bitmap.DrawLineH(color.Text, + enter_btm.GetRight(), enter_btm.GetBottom(), enter_btm.x); + // (D)-(E) + bitmap.DrawLineV(color.Text, + enter_btm.x, enter_btm.GetBottom(), enter_btm.y); + // (E)-(F) + bitmap.DrawLineH(color.Text, + enter_btm.x, enter_top.GetBottom(), enter_top.x); + // (F)-(A) + bitmap.DrawLineV(color.Text, + enter_top.x, enter_top.GetBottom(), enter_top.y); // エンター記号を描画 - DrawEnterMark(dc, wxPoint( - (enter_points[0].x + enter_points[1].x) / 2 - (4 / 2), - (enter_points[1].y + enter_points[2].y) / 2 - (4 / 2))); -} - -// 指定の位置にエンター記号を描画する (エンターキー全体の描画ではない)。 -// メインキーとテンキーの両方で同じ図柄を使う。 -// 大きさは (3unit, 4unit) なので実質全角1文字分くらい。 -void -WXSoftKeyPanel::DrawEnterMark(wxDC& dc, const wxPoint& basep) -{ - // エンター記号は幅 3 unit、高さ 4 unit。 - // +0 +1 +2 +3 - // +0 .. .. .. 1. - // .. .. .. 1. - // +1 .. .. .. 1. - // .. .. .. 1. - // +2 .. 1. .. 1. - // .1 .. .. 1. - // +3 11 11 11 1. - // .1 .. .. .. - // +4 .. 1. .. .. - // .. .. .. .. - static const std::vector> entermark { - { 3, 0 }, - { 3, 3 }, // │ - { 0, 3 }, // ─ - { 1, 2 }, // / - { 0, 3 }, // (一筆書きなので戻る) - { 1, 4 }, // \ - }; - for (int i = 1; i < entermark.size(); i++) { - auto start = entermark[i - 1]; - auto end = entermark[i]; - wxPoint startp(start.first * unit, start.second * unit); - wxPoint endp(end.first * unit, end.second * unit); - dc.DrawLine(basep + startp, basep + endp); + bitmap.DrawBitmap( + (enter_top.x + enter_top.GetRight()) / 2 - (4 / 2), + (enter_top.y + enter_btm.GetBottom()) / 2 - (4 / 2), + *enter_icon, palette); +} + +// ブザー表示(キーに相当)を描画 +void +WXSoftKeyPanel::DrawBuzzer(const keydata_t& key) +{ + Color fg; + + // 枠。キーではないので薄くしておく。 + Rect rect( + key.x * unit, key.y * unit, + key.w * unit + 1, key.h * unit + 1); + bitmap.FillRect(palette[0], rect); + bitmap.DrawRect(UD_GREY, rect); + + // テキスト色は本来呼び出し元の DrawKey() で設定してあるが、 + // ここはキーではないので非発声時の文字色だけ薄くしたい。 + // 発声時はキー押下と同じにする。 + fg = GetTextForeColor(); + if (persistence[key.keycode] == 0) { + SetTextForeColor(UD_GREY); + } + + // 刻印 (モディファイヤの影響を受けないと分かっているので常に [0]) + const char *disp = key.disp[0]; + assert(disp); + + // センタリング + int x = key.x + (key.w - strlen(disp) * 2) / 2; + int y = key.y + (key.h - 4) / 2; + + // 文字を描画 + x = x * unit + 1; + y = y * unit + 1; + DrawStringSJIS(x, y, disp, TA::Normal); + + // 前景色を元に戻す + SetTextForeColor(fg); +} + +#define B(x) (0b##x) +#define B2(x) (B(x) >> 8), (B(x) & 0xff) +#define B3(x) (B(x) >> 16), ((B(x) >> 8) & 0xff), (B(x) & 0xff) + +static const uint8 EnterIcon12[] = { // 12x12 + B2(000000000000'0000), // 0 + B2(000000001110'0000), // 1 + B2(000000001010'0000), // 2 + B2(000000001010'0000), // 3 + B2(000000001010'0000), // 4 + B2(001100001010'0000), // 5 + B2(010111110010'0000), // 6 + B2(100000000010'0000), // 7 + B2(010111111100'0000), // 8 + B2(001100000000'0000), // 9 + B2(000000000000'0000), // a + B2(000000000000'0000), // b +}; + +static const uint8 EnterIcon16[] = { // 16x16 + B2(0000000000111110), // 0 + B2(0000000000100010), // 1 + B2(0000000000100010), // 2 + B2(0000000000100010), // 3 + B2(0000000000100010), // 4 + B2(0000000000100010), // 5 + B2(0000000000100010), // 6 + B2(0000110000100010), // 7 + B2(0001010000100010), // 8 + B2(0010011111000010), // 9 + B2(0100000000000010), // a + B2(1000000000000010), // b + B2(0100000000000010), // c + B2(0010011111111100), // d + B2(0001010000000000), // e + B2(0000110000000000), // f +}; + +static const uint8 EnterIcon24[] = { // 24x24 + B3(00000000'00000001'11111100), // 0 + B3(00000000'00000001'11111100), // 1 + B3(00000000'00000001'10001100), // 2 + B3(00000000'00000001'10001100), // 3 + B3(00000000'00000001'10001100), // 4 + B3(00000000'00000001'10001100), // 5 + B3(00000000'00000001'10001100), // 6 + B3(00000000'00000001'10001100), // 7 + B3(00000000'00000001'10001100), // 8 + B3(00000000'11000001'10001100), // 9 + B3(00000001'11000001'10001100), // 10 + B3(00000011'11000001'10001100), // 11 + B3(00000110'11000001'10001100), // 12 + B3(00001100'11111111'10001100), // 13 + B3(00011000'11111111'10001100), // 14 + B3(00110000'00000000'00001100), // 15 + B3(01100000'00000000'00001100), // 16 + B3(00110000'00000000'00001100), // 17 + B3(00011000'11111111'11111100), // 18 + B3(00001100'11111111'11111000), // 19 + B3(00000110'11000000'00000000), // 20 + B3(00000011'11000000'00000000), // 21 + B3(00000001'11000000'00000000), // 22 + B3(00000000'11000000'00000000), // 23 +}; + +// アイコンを初期化する。FontChanged() から呼ばれる。 +// ソース先頭のほうにデータの羅列を置きたくないが、 +// 容量不詳の配列の解決が面倒なのでこれだけ下のほうのここに置いてある。 +void +WXSoftKeyPanel::InitIcon() +{ + const int width = font_width; + const int height = font_height; + const uint8 *icon; + + switch (height) { + case 12: + icon = EnterIcon12; + break; + case 16: + icon = EnterIcon16; + break; + case 24: + icon = EnterIcon24; + break; + default: + PANIC("Unexpected font_height=%d", height); } + + enter_icon.reset(new BitmapI1(icon, width * 2, height)); } // keycode に対応する keydata を返す @@ -451,7 +570,7 @@ WXSoftKeyPanel::FindKeydata(uint keycode } } // 見付からないはずはない - assertmsg(0, "keycode %d not found", keycode); + PANIC("keycode %d not found", keycode); } // マウス左クリック (Down) イベント @@ -475,7 +594,7 @@ WXSoftKeyPanel::DoLeftDown(uint code) // トグルキーはここで完結。LeftUp では何もしない。 // second のクリアは KeyUp() からコールバックされる OnKeyChanged() // で行っている。 - if (gKeyboard->IsPressed(code)) { + if (keyboard->IsPressed(code)) { KeyUp(code); } else { KeyDown(code); @@ -544,7 +663,7 @@ WXSoftKeyPanel::OnRightDown(wxMouseEvent if (key != NULL) { uint code = key->keycode; - if (gKeyboard->IsPressed(code)) { + if (keyboard->IsPressed(code)) { // 押されていたら開放 KeyUp(code); } else { @@ -560,7 +679,7 @@ const keydata_t * WXSoftKeyPanel::GetKeydataFromPoint(const wxPoint& pt) const { // エンターキーだけ先に別判定 - if (enter_region.Contains(pt) == wxInRegion) { + if (enter_top.Contains(pt.x, pt.y) || enter_btm.Contains(pt.x, pt.y)) { return &FindKeydata(KC_enter); } @@ -586,7 +705,7 @@ void WXSoftKeyPanel::KeyDown(uint code) { // VM に通知 (Keyboard がホストに通知する) - gKeyboard->MakeKey(code); + keyboard->MakeKey(code); } // このキーが放された処理 @@ -594,7 +713,7 @@ void WXSoftKeyPanel::KeyUp(uint code) { // VM に通知 (Keyboard がホストに通知する) - gKeyboard->BreakKey(code); + keyboard->BreakKey(code); } @@ -610,11 +729,11 @@ WXLunaSoftKeyPanel::WXLunaSoftKeyPanel(w // BS キーの左隣 (0x5c) は円記号ではなくバックスラッシュ。 // それを SHIFT したやつ(0x7c) は破線でないパイプ。 // そのもう一つ左隣 (0x7e) はオーバーラインではなくチルダ。 - SetGlyph5C(true); - SetGlyph7E(true); + gFontManager->SetGlyph5C(true); + gFontManager->SetGlyph7E(true); // 白黒モデル共通 - color.Border = *wxBLACK; + color.Border = UD_BLACK; color.LED[0] = UD_RED; // キートップの濃淡はユニバーサルデザインの推奨色ではないけど @@ -622,17 +741,20 @@ WXLunaSoftKeyPanel::WXLunaSoftKeyPanel(w if (1) { // 白モデル color.Background = UD_LIGHT_GREY; // 現物新品は何色だったんだろう - color.Text = *wxBLACK; - color.Keytop[0][0] = *wxWHITE; - color.Keytop[1][0] = wxColour(200, 200, 203); + color.Text = UD_BLACK; + color.Keytop[0][0] = UD_WHITE; + color.Keytop[1][0] = Color(200, 200, 203); } else { // 黒モデル - color.Background = *wxBLACK; - color.Text = *wxWHITE; - color.Keytop[0][0] = wxColour(50, 50, 53); - color.Keytop[1][0] = *wxBLACK; + color.Background = UD_BLACK; + color.Text = UD_WHITE; + color.Keytop[0][0] = Color(50, 50, 53); + color.Keytop[1][0] = UD_BLACK; } InitColorKeytop(2); + + SetBitmapBGColor(color.Background); + Fill(); } // デストラクタ @@ -642,25 +764,27 @@ WXLunaSoftKeyPanel::~WXLunaSoftKeyPanel( // LED を描画して刻印描画のための y offset を返す。 int -WXLunaSoftKeyPanel::DrawLED(wxDC& dc, const keydata_t& key) +WXLunaSoftKeyPanel::DrawLED(const keydata_t& key) { - const std::vector& led = gKeyboard->GetLED(); + const std::vector& led = keyboard->GetLED(); + Color fg; + Color bg; if (led[key.led]) { // 点灯時は赤、枠は黒 - dc.SetPen(color.Border); - dc.SetBrush(color.LED[0]); + fg = color.Border; + bg = color.LED[0]; } else { // 消灯時は元のキートップの色で、枠は薄めにしたい // (枠の色は今の所全モデル共通なので ColorPalette に含めていない) - dc.SetPen(UD_GREY); - dc.SetBrush(color.Keytop[key.coltype][0]); + fg = UD_GREY; + bg = color.Keytop[key.coltype][0]; } // LED を左肩に描く - wxPoint pt = wxPoint(key.x * unit + 2, key.y * unit + 2); - wxSize sz = wxSize(4 * unit - 2, 3 * unit - 2); - dc.DrawRectangle(pt, sz); + Rect rect(key.x * unit + 2, key.y * unit + 2, 4 * unit - 2, 3 * unit - 2); + bitmap.FillRect(bg, rect); + bitmap.DrawRect(fg, rect); // そのため文字は少し下げる return +1; @@ -689,6 +813,7 @@ WXLunaSoftKeyPanel::keydata { { 111, L0, 15, H, 1,-1, KC_F8, { "PF8" } }, { 126, L0, 15, H, 1,-1, KC_F9, { "PF9" } }, { 141, L0, 15, H, 1,-1, KC_F10, { "PF10" } }, + { 210, L0+1, 14, H-2, 1,-1, KC_buzzer, { "Buzzer" } }, { 2, L1, 12, H, 1,-1, KC_ESC, { "ESC" } }, { 14, L1, 10, H, 0,-1, KC_1, { "1", "!" } }, @@ -805,19 +930,23 @@ WXX68kSoftKeyPanel::WXX68kSoftKeyPanel(w : inherited(parent, keydata, 235, 54) { // X68k では SRAM 設定に同期させる。 - uint8 sw = gSRAM->Peek8(0xed0059); - SetGlyph5C((sw & 0x01)); - SetGlyph7E((sw & 0x02)); - SetGlyph7C((sw & 0x04)); + const auto sram = GetSRAMDevice(); + uint8 sw = sram->Peek8(0xed0059); + gFontManager->SetGlyph5C((sw & 0x01)); + gFontManager->SetGlyph7E((sw & 0x02)); + gFontManager->SetGlyph7C((sw & 0x04)); // とりあえず黒のみ - color.Background = wxColour(50, 50, 53); - color.Text = *wxWHITE; - color.Border = *wxBLACK; + color.Background = Color(50, 50, 53); + color.Text = UD_WHITE; + color.Border = UD_BLACK; color.LED[0] = UD_RED; color.LED[1] = UD_YELLOW_GREEN; - color.Keytop[0][0] = *wxBLACK; + color.Keytop[0][0] = UD_BLACK; InitColorKeytop(1); + + SetBitmapBGColor(color.Background); + Fill(); } // デストラクタ @@ -827,9 +956,11 @@ WXX68kSoftKeyPanel::~WXX68kSoftKeyPanel( // LED を描画して刻印描画のための y offset を返す。 int -WXX68kSoftKeyPanel::DrawLED(wxDC& dc, const keydata_t& key) +WXX68kSoftKeyPanel::DrawLED(const keydata_t& key) { - const std::vector& led = gKeyboard->GetLED(); + const std::vector& led = keyboard->GetLED(); + Color fg; + Color bg; // 色を選択 // idx 刻印 色 @@ -843,19 +974,20 @@ WXX68kSoftKeyPanel::DrawLED(wxDC& dc, co // 6 全角 緑 if (led[key.led]) { int n = (key.led < 5) ? 0 : 1; - dc.SetPen(color.LED[n]); - dc.SetBrush(color.LED[n]); + fg = color.LED[n]; + bg = color.LED[n]; } else { // 消灯時は元のキートップの色で、枠は薄めにしたい // (枠の色は今の所全モデル共通なので ColorPalette に含めていない) - dc.SetPen(UD_GREY); - dc.SetBrush(color.Keytop[key.coltype][0]); + fg = UD_GREY; + bg = color.Keytop[key.coltype][0]; } // LED は中央前方(画面でいうと下) - wxPoint pt = wxPoint((key.x + 3) * unit, (key.y + key.h - 2) * unit); - wxSize sz = wxSize(4 * unit, 2 * unit); - dc.DrawRectangle(pt, sz); + Rect rect((key.x + 3) * unit, (key.y + key.h - 2) * unit, + 4 * unit, 2 * unit); + bitmap.FillRect(bg, rect); + bitmap.DrawRect(fg, rect); // そのため文字は少し上げる return -1; @@ -984,7 +1116,7 @@ WXX68kSoftKeyPanel::keydata { { 193, L4, 10, H, 0,-1, KC_PAD_1, { "1" } }, { 203, L4, 10, H, 0,-1, KC_PAD_2, { "2" } }, { 213, L4, 10, H, 0,-1, KC_PAD_3, { "3" } }, - { 223, L4, 10, HT,0,-1, KC_PAD_enter, { "\xb\xc\xd\xe" } }, + { 223, L4, 10, HT,0,-1, KC_PAD_enter, { "\xb\xc\xe\xf" } }, { 193, L5, 10, H, 0,-1, KC_PAD_0, { "0" } }, { 203, L5, 10, H, 0,-1, KC_PAD_comma, { "," } }, { 213, L5, 10, H, 0,-1, KC_PAD_decimal, { "." } }, @@ -999,22 +1131,16 @@ WXX68kSoftKeyPanel::keydata { // // コンストラクタ -WXSoftKeyWindow::WXSoftKeyWindow(wxWindow *parent, vmtype_t vmtype) +WXSoftKeyWindow::WXSoftKeyWindow(wxWindow *parent, VMType vmtype) : inherited(parent, wxID_ANY, _("Software Keyboard")) { - wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL); - - if (vmtype == VMTYPE_X68030) { + if (vmtype == VMType::X68030) { panel = new WXX68kSoftKeyPanel(this); } else { panel = new WXLunaSoftKeyPanel(this); } - topsizer->Add(panel, 0, wxEXPAND); - - SetSizer(topsizer); - // 大きさをそれに固定 - Fit(); + DoSize(); } // デストラクタ