--- nono/wx/wxsoftkey.cpp 2026/04/29 17:05:04 1.1.1.9 +++ nono/wx/wxsoftkey.cpp 2026/04/29 17:05:08 1.1.1.11 @@ -4,10 +4,14 @@ // Licensed under nono-license.txt // +// +// ソフトウェアキーボード +// + #include "wxsoftkey.h" +#include "fontmanager.h" #include "wxcolor.h" #include "wxmainview.h" -#include "wxtextscreen.h" #include "wxuimessage.h" #include "sram.h" @@ -28,7 +32,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() @@ -43,12 +46,16 @@ WXSoftKeyPanel::WXSoftKeyPanel(wxWindow u_width = u_width_; u_height = u_height_; - DoSize(); + FontChanged(); + + // トグル動作にするキー + toggle.emplace(KC_SHIFT, 0); + toggle.emplace(KC_SHIFT_L, 0); + toggle.emplace(KC_SHIFT_R, 0); + toggle.emplace(KC_CTRL, 0); // 残光の初期化。 // persistence は keydata 分の配列ではなく共通キーコード分の配列。 - // 使われない領域も多いが、共通キーコードから keydata 番号への逆引きは - // 面倒なので。 persistence.resize(KC_max); std::fill(persistence.begin(), persistence.end(), 0); @@ -63,13 +70,24 @@ WXSoftKeyPanel::WXSoftKeyPanel(wxWindow // VM からの通知を受け取る WXUIMessage::Connect(UIMessage::KEYBOARD, this, wxCommandEventHandler(WXSoftKeyPanel::OnKeyChanged)); + + // 初期タイトルを保存しといて.. + title = dynamic_cast(parent)->GetTitle(); + // キーボードの接続状況でタイトルを更新する + UpdateTitle(); } // デストラクタ WXSoftKeyPanel::~WXSoftKeyPanel() { - // SHIFT キーのワンショットは解放する? + // ウィンドウクローズでトグルキーのワンショットは開放する // (長押しは開放しない) + for (const auto& k : toggle) { + auto code = k.second; + if (code) { + KeyUp(code); + } + } timer.Stop(); @@ -77,12 +95,30 @@ WXSoftKeyPanel::~WXSoftKeyPanel() wxCommandEventHandler(WXSoftKeyPanel::OnKeyChanged)); } +// キーボードの接続状況によって親フレームのタイトルを更新する。 +// ついでにメンバ変数を更新する。 +void +WXSoftKeyPanel::UpdateTitle() +{ + auto parent = dynamic_cast(GetParent()); + assert(parent); + + // 次回比較用にメンバ変数に覚えておく + connected = gKeyboard->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; @@ -93,38 +129,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; @@ -138,9 +155,9 @@ WXSoftKeyPanel::DoSize() // | | | | // --+---+---+--(A)--+------(B) // | | | - // | [ | | - // | | Enter | - // --+---+---+--(F)-(E) | + // | [ | Enter | + // | | | + // --+---+---+--(F)-(E) - - (G) // | | | | // | : | ] | | // | | | | @@ -148,32 +165,23 @@ 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); // コントロールの大きさを変更 wxSize size(u_width * unit, u_height * unit); SetClientSize(size); SetMinClientSize(size); - - // ビットマップ作成 - bitmap.Create(size.x, size.y); - - // 再描画を指示 - Refresh(); } void @@ -208,27 +216,27 @@ WXSoftKeyPanel::OnKeyChanged(wxCommandEv persistence[keycode] = 9; } - Refresh(); -} + // トグルキーが開放されていたらトグル情報をクリアする。 + // ハードウェアキーボードを含む VM 側で開放された場合と、 + // ソフトウェアキーボードの KeyUp() で開放された場合のどちらも + // ここでクリア。 + for (auto& k : toggle) { + if (gKeyboard->IsPressed(k.first) == false) { + k.second = 0; + } + } -// 描画イベント (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); + // 接続状況が変わっていたらタイトルを更新。 + if (gKeyboard->IsConnected() != connected) { + UpdateTitle(); + } + + Refresh(); } // 描画本体 void -WXSoftKeyPanel::Draw(wxDC& dc) +WXSoftKeyPanel::Draw() { bool timer_start = false; @@ -247,12 +255,14 @@ WXSoftKeyPanel::Draw(wxDC& dc) modifier = ModNormal; } - dc.SetPen(wxPen(color.Background)); - dc.SetBrush(wxBrush(color.Background)); - dc.DrawRectangle(wxPoint(0, 0), GetSize()); + auto text_color = color.Text; + + // キーボードが接続されていないときは刻印をグレーにしておく + if (gKeyboard->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) { @@ -278,13 +288,12 @@ 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); + DrawEnterKey(); } else { - DrawKey(dc, key); + DrawKey(key); } } @@ -293,24 +302,20 @@ WXSoftKeyPanel::Draw(wxDC& dc) } else { timer.Stop(); } - -#if 0 - // X68k キーボードだとどこに表示するか - SetTextBackColor(color.Background); - wxString utfstr(wxT("右クリックで長押し")); - const char *sjis = (const char *)utfstr.mb_str(conv); - DrawStringSJIS(dc, 190 * unit, 2 * unit, sjis, TA::Disable); -#endif } // 指定のキーを一つ (枠から刻印まで) 描画する。 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]; @@ -318,9 +323,19 @@ WXSoftKeyPanel::DrawKey(wxDC& dc, const disp = key.disp[0]; } + // トグルキーのワンショット押しは太字で表示を区別したい + const auto it = toggle.find(key.keycode); + if (it != toggle.end()) { + if (it->second) { + attr = TA::Em; + } + } + // 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] {}; @@ -345,78 +360,116 @@ 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); + DrawEnterMark(x, y); } else { if (lf == NULL) { // 1行の場合 - DrawStringSJIS(dc, pt.x, pt.y, sjis); + 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))); -} + DrawEnterMark( + (enter_top.x + enter_top.GetRight()) / 2 - (4 / 2), + (enter_top.y + enter_btm.GetBottom()) / 2 - (4 / 2)); +} + +#define B(x) (0b##x >> 8), (0b##x & 0xff) + +static constexpr uint8 EnterMark12[] = { + B(000000000000'0000), // 0 + B(000000001110'0000), // 1 + B(000000001010'0000), // 2 + B(000000001010'0000), // 3 + B(000000001010'0000), // 4 + B(001100001010'0000), // 5 + B(010111110010'0000), // 6 + B(100000000010'0000), // 7 + B(010111111100'0000), // 8 + B(001100000000'0000), // 9 + B(000000000000'0000), // a + B(000000000000'0000), // b +}; +static constexpr uint8 EnterMark16[] = { + B(0000000000111110), // 0 + B(0000000000100010), // 1 + B(0000000000100010), // 2 + B(0000000000100010), // 3 + B(0000000000100010), // 4 + B(0000000000100010), // 5 + B(0000000000100010), // 6 + B(0000110000100010), // 7 + B(0001010000100010), // 8 + B(0010011111000010), // 9 + B(0100000000000010), // a + B(1000000000000010), // b + B(0100000000000010), // c + B(0010011111111100), // d + B(0001010000000000), // e + B(0000110000000000), // f +}; // 指定の位置にエンター記号を描画する (エンターキー全体の描画ではない)。 // メインキーとテンキーの両方で同じ図柄を使う。 // 大きさは (3unit, 4unit) なので実質全角1文字分くらい。 void -WXSoftKeyPanel::DrawEnterMark(wxDC& dc, const wxPoint& basep) +WXSoftKeyPanel::DrawEnterMark(int px, int py) { - // エンター記号は幅 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); + const uint8 *mark; + + switch (font_height) { + case 12: + mark = EnterMark12; + break; + case 16: + mark = EnterMark16; + break; + default: + PANIC("Unexpected font_height=%d", font_height); } + BitmapI1 src(mark, font_height, font_height); + bitmap.DrawBitmap(px, py, src, palette); } // keycode に対応する keydata を返す @@ -429,21 +482,7 @@ WXSoftKeyPanel::FindKeydata(uint keycode } } // 見付からないはずはない - assertmsg(0, "keycode %d not found", keycode); -} - -// keycode が SHIFT キーなら true を返す -// (SHIFT キーが押されているかとかではない) -/*static*/ bool -WXSoftKeyPanel::IsShiftKey(uint keycode) -{ - if (keycode == KC_SHIFT_L || - keycode == KC_SHIFT_R || - keycode == KC_SHIFT) - { - return true; - } - return false; + PANIC("keycode %d not found", keycode); } // マウス左クリック (Down) イベント @@ -454,40 +493,30 @@ WXSoftKeyPanel::OnLeftDown(wxMouseEvent& const keydata_t *key = GetKeydataFromPoint(pt); if (key != NULL) { - DoLeftDown(key); + DoLeftDown(key->keycode); } } // マウス左クリック (Down) 処理 void -WXSoftKeyPanel::DoLeftDown(const keydata_t *key) +WXSoftKeyPanel::DoLeftDown(uint code) { - assert(key); - - // SHIFT キーの左クリックはトグル状動作。 - // SHIFT 状態で押すと、すべての SHIFT キーを開放。 - // 非 SHIFT 状態で押すと、次のキー押下までこの SHIFT キーを押下維持。 - if (IsShiftKey(key->keycode)) { - if (gKeyboard->IsShift()) { - // SHIFT 状態で SHIFT キーが押されたのですべての SHIFT キーを開放 - if (key->keycode == KC_SHIFT) { - KeyUp(*key); - } else { - KeyUp(FindKeydata(KC_SHIFT_L)); - KeyUp(FindKeydata(KC_SHIFT_R)); - } + auto it = toggle.find(code); + if (it != toggle.end()) { + // トグルキーはここで完結。LeftUp では何もしない。 + // second のクリアは KeyUp() からコールバックされる OnKeyChanged() + // で行っている。 + if (gKeyboard->IsPressed(code)) { + KeyUp(code); } else { - // 非 SHIFT 状態で SHIFT キーが押されたのでこのキーを押下 - KeyDown(*key); - shift_hold = false; + KeyDown(code); + it->second = code; } - - // SHIFT キーなら LeftUp では何もしない - leftdown_key = NULL; + leftdown_key = KC_none; } else { - // SHIFT 以外のキーは押下して LeftUp のために覚えておく - KeyDown(*key); - leftdown_key = key; + // トグルでない通常キーはここで押下して LeftUp のために覚えておく + KeyDown(code); + leftdown_key = code; } } @@ -497,27 +526,21 @@ WXSoftKeyPanel::OnLeftUp(wxMouseEvent& e { // Up 時は、これが起きた地点のキーコードではなく // 直近に LeftDown したキーコードをターゲットにする。 - const keydata_t *key = leftdown_key; + uint code = leftdown_key; - if (key != NULL) { - KeyUp(*key); + if (code != KC_none) { + KeyUp(code); - // キーが離された時、長押しでない SHIFT キーがあれば開放 - if (gKeyboard->IsShift() && shift_hold == false) { - // XXX どの SHIFT が存在するのか分からないのがなんかアレ - if (gKeyboard->IsPressed(KC_SHIFT_L)) { - KeyUp(FindKeydata(KC_SHIFT_L)); - } - if (gKeyboard->IsPressed(KC_SHIFT_R)) { - KeyUp(FindKeydata(KC_SHIFT_R)); - } - if (gKeyboard->IsPressed(KC_SHIFT)) { - KeyUp(FindKeydata(KC_SHIFT)); + // 通常キーが離されたら、トグルキーはすべて開放 + for (const auto& k : toggle) { + auto tcode = k.second; + if (tcode) { + KeyUp(tcode); } } } - leftdown_key = NULL; + leftdown_key = KC_none; } // マウス左ダブルクリックイベント @@ -537,7 +560,7 @@ WXSoftKeyPanel::OnLeftDClick(wxMouseEven const keydata_t *key = GetKeydataFromPoint(pt); if (key != NULL) { - DoLeftDown(key); + DoLeftDown(key->keycode); } } @@ -554,14 +577,10 @@ WXSoftKeyPanel::OnRightDown(wxMouseEvent uint code = key->keycode; if (gKeyboard->IsPressed(code)) { // 押されていたら開放 - KeyUp(*key); + KeyUp(code); } else { // 押されてなければ長押し開始 - KeyDown(*key); - - if (IsShiftKey(key->keycode)) { - shift_hold = true; - } + KeyDown(code); } } } @@ -572,7 +591,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); } @@ -595,20 +614,16 @@ WXSoftKeyPanel::GetKeydataFromPoint(cons // このキーが押された処理 void -WXSoftKeyPanel::KeyDown(const keydata_t& key) +WXSoftKeyPanel::KeyDown(uint code) { - uint code = key.keycode; - // VM に通知 (Keyboard がホストに通知する) gKeyboard->MakeKey(code); } // このキーが放された処理 void -WXSoftKeyPanel::KeyUp(const keydata_t& key) +WXSoftKeyPanel::KeyUp(uint code) { - uint code = key.keycode; - // VM に通知 (Keyboard がホストに通知する) gKeyboard->BreakKey(code); } @@ -626,11 +641,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; // キートップの濃淡はユニバーサルデザインの推奨色ではないけど @@ -638,17 +653,19 @@ 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); } // デストラクタ @@ -658,25 +675,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(); + 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; @@ -822,18 +841,20 @@ WXX68kSoftKeyPanel::WXX68kSoftKeyPanel(w { // X68k では SRAM 設定に同期させる。 uint8 sw = gSRAM->Peek8(0xed0059); - SetGlyph5C((sw & 0x01)); - SetGlyph7E((sw & 0x02)); - SetGlyph7C((sw & 0x04)); + 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); } // デストラクタ @@ -843,9 +864,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(); + Color fg; + Color bg; // 色を選択 // idx 刻印 色 @@ -859,19 +882,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; @@ -1018,19 +1042,13 @@ WXX68kSoftKeyPanel::keydata { WXSoftKeyWindow::WXSoftKeyWindow(wxWindow *parent, vmtype_t vmtype) : inherited(parent, wxID_ANY, _("Software Keyboard")) { - wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL); - if (vmtype == VMTYPE_X68030) { panel = new WXX68kSoftKeyPanel(this); } else { panel = new WXLunaSoftKeyPanel(this); } - topsizer->Add(panel, 0, wxEXPAND); - - SetSizer(topsizer); - // 大きさをそれに固定 - Fit(); + DoSize(); } // デストラクタ