Annotation of nono/wx/wxplanemonitor.cpp, revision 1.1.1.4

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // プレーン VRAM モニターウィンドウ
                      9: //
                     10: 
                     11: #include "wxplanemonitor.h"
                     12: #include "wxcolor.h"
                     13: #include "wxuimessage.h"
1.1.1.2   root       14: #include "bt45x.h"
1.1       root       15: #include "planevram.h"
                     16: #include "videoctlr.h"
                     17: 
1.1.1.3   root       18: //#define WINDOW_DEBUG 1
                     19: 
                     20: #if defined(WINDOW_DEBUG)
                     21: #define DPRINTF(fmt...) printf(fmt)
                     22: #else
                     23: #define DPRINTF(fmt...) /**/
                     24: #endif
                     25: 
1.1       root       26: enum {
                     27:        ID_PLANE0 = IDGROUP_PLANEVRAM,
                     28:        ID_PLANE1,
                     29:        ID_PLANE2,
                     30:        ID_PLANE3,
                     31:        ID_PLANE4,
                     32:        ID_PLANE5,
                     33:        ID_PLANE6,
                     34:        ID_PLANE7,
                     35:        ID_PALETTE,
                     36:        ID_SCALE,
                     37: 
                     38:        ID_local_end,   // 最後に置く (チェック用)
                     39: };
                     40: static_assert(ID_local_end - 1 <= (int)IDGROUP_PLANEVRAM_END, "ID exceeded");
                     41: 
                     42: #define ID_PLANE(id)   (ID_PLANE0 + (id))
                     43: 
                     44: //
                     45: // プレーン VRAM ビットマップ
                     46: //
                     47: 
1.1.1.2   root       48: // イベントテーブル
                     49: wxBEGIN_EVENT_TABLE(WXPlaneVRAMBitmapPanel, inherited)
                     50:        EVT_MOUSE_EVENTS(WXPlaneVRAMBitmapPanel::OnMouse)
                     51: wxEND_EVENT_TABLE()
                     52: 
1.1       root       53: // コンストラクタ
                     54: WXPlaneVRAMBitmapPanel::WXPlaneVRAMBitmapPanel(wxWindow *parent)
                     55:        : inherited(parent)
                     56: {
1.1.1.2   root       57:        // デバイスを取得
                     58:        planevram = GetPlaneVRAMDevice();
                     59:        // どちらか一方は NULL のはず
                     60:        bt45x = gMainApp.FindObject<BT45xDevice>(OBJ_BT45x);
                     61:        videoctlr = gMainApp.FindObject<VideoCtlrDevice>(OBJ_VIDEOCTLR);
                     62: 
                     63:        plane_width  = planevram->GetComposite().GetWidth();
                     64:        plane_height = planevram->GetComposite().GetHeight();
1.1       root       65: 
                     66:        // まず等倍でセット
                     67:        scale = 1;
                     68:        SetScale(1);
                     69: 
1.1.1.2   root       70:        cursor = wxDefaultPosition;
                     71: 
1.1       root       72:        // VM からの通知を受け取る
                     73:        WXUIMessage::Connect(UIMessage::PALETTE, this,
                     74:                wxCommandEventHandler(WXPlaneVRAMBitmapPanel::OnPaletteChanged));
                     75: }
                     76: 
                     77: // デストラクタ
                     78: WXPlaneVRAMBitmapPanel::~WXPlaneVRAMBitmapPanel()
                     79: {
1.1.1.2   root       80:        WXUIMessage::Disconnect(UIMessage::PALETTE, this,
1.1       root       81:                wxCommandEventHandler(WXPlaneVRAMBitmapPanel::OnPaletteChanged));
                     82: }
                     83: 
                     84: // XXX 実際にはこの辺かどこかで更新チェックをしないといけない。
                     85: // 今は表示領域を毎回描画しているので無駄。
                     86: 
                     87: // ビットマッププレーンの内容を描画する
                     88: void
                     89: WXPlaneVRAMBitmapPanel::Draw()
                     90: {
                     91:        assert(view.GetRight()  < virtual_width);
                     92:        assert(view.GetBottom() < virtual_height);
                     93: 
1.1.1.2   root       94:        const BitmapI8& src = planevram->GetComposite();
1.1       root       95: 
                     96:        if (scale > 1) {
                     97:                Rect dr(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
                     98:                bitmap.DrawScale(dr, src, &pal[0], view.x, scale, 1, view.y, scale, 1);
                     99:        } else {
                    100:                bitmap.DrawBitmap(0, 0, src, &pal[0], view);
                    101:        }
                    102: }
                    103: 
                    104: // プレーン選択変更
                    105: void
                    106: WXPlaneVRAMBitmapPanel::EnablePlane(int plane, bool value)
                    107: {
                    108:        if (value) {
                    109:                planemask |= 1U << plane;
                    110:        } else {
                    111:                planemask &= ~(1U << plane);
                    112:        }
                    113: 
                    114:        // パレット生成
                    115:        GenPalette();
                    116: }
                    117: 
                    118: // パレット適用変更
                    119: void
                    120: WXPlaneVRAMBitmapPanel::EnablePalette(bool value)
                    121: {
                    122:        apply_palette = value;
                    123: 
                    124:        // パレット生成
                    125:        GenPalette();
                    126: }
                    127: 
                    128: // VM からのパレット変更通知
                    129: void
                    130: WXPlaneVRAMBitmapPanel::OnPaletteChanged(wxCommandEvent& event)
                    131: {
                    132:        // パレット生成
                    133:        GenPalette();
                    134: }
                    135: 
                    136: // パレット生成
                    137: void
                    138: WXPlaneVRAMBitmapPanel::GenPalette()
                    139: {
                    140:        if (apply_palette) {
                    141:                // パレットを適用する場合
1.1.1.4 ! root      142:                // (雑に X680x0/LUNA 対応)
        !           143:                const std::vector<ColorXBGR> *vmpal;
1.1.1.2   root      144:                if (videoctlr) {
1.1.1.4 ! root      145:                        vmpal = &videoctlr->GetHostPalette();
1.1       root      146:                } else {
1.1.1.4 ! root      147:                        vmpal = &bt45x->GetHostPalette();
1.1       root      148:                }
1.1.1.4 ! root      149:                int vmpal_size = vmpal->size();
        !           150:                const Color bg = (*vmpal)[0].ToColor();
        !           151:                int d = 0;
        !           152:                int s;
        !           153:                for (; d < pal.size(); d++) {
        !           154:                        s = d % vmpal_size;
        !           155:                        if ((s & planemask)) {
        !           156:                                pal[d] = (*vmpal)[s].ToColor();
1.1       root      157:                        } else {
1.1.1.4 ! root      158:                                pal[d] = bg;
1.1       root      159:                        }
                    160:                }
                    161:        } else {
                    162:                // パレットを適用しない場合
                    163:                for (int i = 0; i < pal.size(); i++) {
                    164:                        if ((i & planemask)) {
                    165:                                pal[i] = Color(255, 255, 255);
                    166:                        } else {
                    167:                                pal[i] = Color(0, 0, 0);
                    168:                        }
                    169:                }
                    170:        }
                    171: }
                    172: 
                    173: // 倍率を設定
                    174: void
                    175: WXPlaneVRAMBitmapPanel::SetScale(int scale_)
                    176: {
                    177:        int before = scale;
                    178: 
                    179:        scale = scale_;
                    180: 
                    181:        // 仮想画面の大きさを計算
                    182:        virtual_width = plane_width * scale;
                    183:        virtual_height = plane_height * scale;
                    184: 
                    185:        // ビューのスケール変換は前後のスケールがいるのでここでやる
                    186:        view.x = view.x * scale / before;
                    187:        view.y = view.y * scale / before;
                    188:        view.w = view.w * scale / before;
                    189:        view.h = view.h * scale / before;
                    190: 
                    191:        SetMaxClientSize(wxSize(virtual_width, virtual_height));
                    192: }
                    193: 
                    194: // スクロール位置変更通知
                    195: void
                    196: WXPlaneVRAMBitmapPanel::OnScroll(wxScrollEvent& event)
                    197: {
                    198:        int orient = event.GetOrientation();
                    199:        int pos = event.GetPosition();
                    200: 
                    201:        if (orient == wxHORIZONTAL) {
                    202:                view.x = pos;
                    203:        } else {
                    204:                view.y = pos;
                    205:        }
                    206: }
                    207: 
1.1.1.2   root      208: // マウスイベント
                    209: void
                    210: WXPlaneVRAMBitmapPanel::OnMouse(wxMouseEvent& event)
                    211: {
                    212:        auto window = dynamic_cast<WXPlaneVRAMWindow*>(GetGrandParent());
                    213:        assert(window);
                    214: 
                    215:        // pt はこのパネル左上からの位置
                    216:        const wxPoint& pt = event.GetPosition();
                    217: 
                    218:        // pt がパネル内の座標なのに Leaving() になることがある。
                    219:        // pt がパネル外の座標なのに Leaving() にならないことがある。
                    220:        if (event.Leaving() == false && GetClientRect().Contains(pt)) {
                    221:                // cursor は仮想画面上の座標
                    222:                cursor.x = (view.x + pt.x) / scale;
                    223:                cursor.y = (view.y + pt.y) / scale;
                    224:                assertmsg(cursor.x < plane_width,  "cursor.x=%d", cursor.x);
                    225:                assertmsg(cursor.y < plane_height, "cursor.y=%d", cursor.y);
                    226:        } else {
                    227:                cursor = wxDefaultPosition;
                    228:        }
                    229: }
                    230: 
1.1       root      231: 
                    232: //
                    233: // プレーン VRAM パネル
                    234: //
                    235: 
1.1.1.2   root      236: // +------------------------+------------------+
                    237: // | WXPlaneVRAMBitmapPanel | WXScrollBar(V)   |
                    238: // | VRAM 表示パネル        | 縦スクロールバー |
                    239: // +------------------------+------------------+
                    240: // | WXScrollBar(H)         | WXBitmapPanel    |
                    241: // | 横スクロールバー       | 空き地           |
                    242: // +------------------------+------------------+
                    243: 
1.1       root      244: // イベントテーブル
                    245: wxBEGIN_EVENT_TABLE(WXPlaneVRAMPanel, inherited)
                    246:        EVT_SIZE(WXPlaneVRAMPanel::OnSize)
                    247: wxEND_EVENT_TABLE()
                    248: 
                    249: // コンストラクタ
                    250: WXPlaneVRAMPanel::WXPlaneVRAMPanel(wxWindow *parent)
                    251:        : inherited(parent)
                    252: {
                    253:        // 表示パネル
                    254:        viewctl = new WXPlaneVRAMBitmapPanel(this);
                    255: 
                    256:        // スクロールバーを自分で持つ (配置は Layout() で行う)
                    257:        vscroll = new WXScrollBar(this, wxID_ANY, wxSB_VERTICAL);
                    258:        hscroll = new WXScrollBar(this, wxID_ANY, wxSB_HORIZONTAL);
                    259: 
                    260:        // 右下の空き地
                    261:        corner = new WXBitmapPanel(this);
                    262: 
                    263:        // Sizer 使わず自前でレイアウトする。
                    264:        SetAutoLayout(true);
                    265: 
                    266:        // スクロールバーからの通知イベントは表示パネルへ回す
                    267:        vscroll->Connect(NONO_EVT_SCROLL,
                    268:                wxScrollEventHandler(WXPlaneVRAMBitmapPanel::OnScroll), NULL, viewctl);
                    269:        hscroll->Connect(NONO_EVT_SCROLL,
                    270:                wxScrollEventHandler(WXPlaneVRAMBitmapPanel::OnScroll), NULL, viewctl);
1.1.1.3   root      271: 
                    272:        DPRINTF("Panel.ctor end\n");
1.1       root      273: }
                    274: 
                    275: // デストラクタ
                    276: WXPlaneVRAMPanel::~WXPlaneVRAMPanel()
                    277: {
                    278: }
                    279: 
                    280: bool
                    281: WXPlaneVRAMPanel::Layout()
                    282: {
1.1.1.3   root      283:        DPRINTF("Panel.Layout\n");
1.1       root      284:        if (inherited::Layout() == false) {
                    285:                return false;
                    286:        }
                    287: 
                    288:        const wxSize size = GetClientSize();
1.1.1.3   root      289:        DPRINTF("Panel.Layout inherited, client=(%d,%d)\n", size.x, size.y);
                    290:        wxSize vscr = vscroll->GetClientSize();
                    291:        wxSize hscr = hscroll->GetClientSize();
                    292:        DPRINTF("Panel.Layout vscr=(%d,%d) hscr=(%d,%d)\n",
                    293:                vscr.x, vscr.y, hscr.x, hscr.y);
                    294:        // 主方向(スクロール方向) の最小サイズ
                    295:        int vmin = vscroll->GetMinLength();
                    296:        int hmin = hscroll->GetMinLength();
                    297: 
                    298:        // 最小サイズはスクロールバーの大きさで制約がかかる。
                    299:        // (VRAM パネルなので実際はもっと広くてもいいかも知れない)
                    300:        SetMinClientSize(wxSize(hmin + vscr.x, vmin + hscr.y));
                    301:        SetMaxClientSize(wxSize(viewctl->virtual_width + vscr.x,
                    302:                viewctl->virtual_height + hscr.y));
                    303: 
                    304: #if defined(WINDOW_DEBUG)
                    305:        const wxSize& min = GetMinClientSize();
                    306:        const wxSize& max = GetMaxClientSize();
                    307:        const wxSize& cli = GetClientSize();
                    308:        printf("Panel.Layout min=(%d,%d) max=(%d,%d) client=(%d,%d)\n",
                    309:                min.x, min.y, max.x, max.y, cli.x, cli.y);
                    310: #endif
                    311: 
                    312:        // コントロールを配置
                    313:        int view_width  = size.x - vscr.x;
                    314:        int view_height = size.y - hscr.y;
                    315:        DPRINTF("Panel.Layout view=(%d,%d)\n", view_width, view_height);
                    316:        // 最低でも 1px ないと GTK とかに怒られる
                    317:        if (view_width < 1) {
                    318:                view_width = 1;
                    319:        }
                    320:        if (view_height < 1) {
                    321:                view_height = 1;
                    322:        }
                    323: 
1.1       root      324:        viewctl->SetSize(0, 0, view_width, view_height);
1.1.1.3   root      325:        vscroll->SetSize(view_width, 0, vscr.x, view_height);
                    326:        hscroll->SetSize(0, view_height, view_width, hscr.y);
                    327:        corner->SetSize(view_width, view_height, vscr.x, hscr.y);
1.1       root      328: 
                    329:        // XXX 内部のコントロールのサイズが確定してからでないと DoSize() できない
                    330:        DoSize(size);
1.1.1.3   root      331:        DPRINTF("Panel.Layout done\n");
1.1       root      332: 
                    333:        return true;
                    334: }
                    335: 
1.1.1.3   root      336: // フォントサイズ変更
                    337: void
                    338: WXPlaneVRAMPanel::FontChanged()
                    339: {
                    340:        // このパネル自体はフォントを出力しないが
                    341:        // フォントサイズ変更に反応する必要があるため、用意している。
                    342: 
                    343:        // 自身がフォントを使わないので呼ばなくてもいいが、お作法として。
                    344:        inherited::FontChanged();
                    345:        DPRINTF("Panel.FontChanged %d\n", font_height);
                    346: 
                    347:        // SubWindow はパネルの FontChanged() までは呼んでくれるけど、
                    348:        // パネルが子を持ってるケースは自力で伝搬させるとかする必要がある。
                    349:        hscroll->FontChanged();
                    350:        vscroll->FontChanged();
                    351: 
                    352:        // レイアウト変更も手動で指示。
                    353:        Layout();
                    354:        DPRINTF("Panel.FontChanged end\n");
                    355: }
                    356: 
1.1       root      357: // サイズ変更イベント
                    358: void
                    359: WXPlaneVRAMPanel::OnSize(wxSizeEvent& event)
                    360: {
                    361:        // Mac ではウィンドウ作成時に 0 以下の値が来ることがある。
                    362:        // GTK では 1 で来ることがある。
                    363:        wxSize size = event.GetSize();
1.1.1.3   root      364:        DPRINTF("Panel.OnSize (%d,%d)\n", size.x, size.y);
1.1       root      365:        if (size.x <= 1 || size.y <= 1) {
                    366:                return;
                    367:        }
                    368: 
                    369:        // Layout() を呼ぶために必要
                    370:        event.Skip();
                    371: 
                    372:        // XXX レイアウトが終わった後でないと DoSize() できない
                    373: //     DoSize(size);
                    374: }
                    375: 
                    376: // サイズ変更処理。パネルサイズと倍率が変わったら呼ぶこと。
                    377: // 倍率が変わった場合もスクロールバーの再設定とかがあるため。
                    378: void
                    379: WXPlaneVRAMPanel::DoSize(wxSize size)
                    380: {
                    381:        wxSize viewsize = viewctl->GetClientSize();
1.1.1.3   root      382:        DPRINTF("Panel.DoSize: view=(%d,%d)\n", viewsize.x, viewsize.y);
1.1       root      383:        int virtual_width = viewctl->virtual_width;
                    384:        int virtual_height = viewctl->virtual_height;
                    385:        Rect& view = viewctl->view;
                    386: 
                    387:        // スクロールバーが右端まで行っている場合は右を固定したように見せる。
                    388:        // ただし全体が見えている場合は除く。
                    389: 
                    390:        if (view.x > 0 &&
                    391:            (view.x + view.w == virtual_width ||
                    392:             view.x + viewsize.x >= virtual_width))
                    393:        {
                    394:                view.x = virtual_width - viewsize.x;
                    395:                if (view.x < 0) {
                    396:                        view.x = 0;
                    397:                }
                    398:        }
                    399:        view.w = viewsize.x;
                    400: 
                    401:        // 下端も同様
                    402:        if (view.y > 0 &&
                    403:            (view.y + view.h >= virtual_height ||
                    404:             view.y + size.y >= virtual_height))
                    405:        {
                    406:                view.y = virtual_height - viewsize.y;
                    407:                if (view.y < 0) {
                    408:                        view.y = 0;
                    409:                }
                    410:        }
                    411:        view.h = viewsize.y;
                    412: 
                    413:        // スクロールバー(横)を再設定
                    414:        assert(hscroll);
                    415:        int hpos = view.x;
                    416:        int hthumbsize = view.w;
                    417:        int hrange = virtual_width;
                    418:        int hpagesize = view.w;
                    419:        hscroll->SetScrollParam(hpos, hthumbsize, hrange, hpagesize);
                    420: 
                    421:        // スクロールバー(縦)を再設定
                    422:        assert(vscroll);
                    423:        int vpos = view.y;
                    424:        int vthumbsize = view.h;
                    425:        int vrange = virtual_height;
                    426:        int vpagesize = view.h;
                    427:        vscroll->SetScrollParam(vpos, vthumbsize, vrange, vpagesize);
                    428: }
                    429: 
                    430: // プレーン選択変更
                    431: void
                    432: WXPlaneVRAMPanel::EnablePlane(int plane, bool value)
                    433: {
                    434:        viewctl->EnablePlane(plane, value);
                    435: }
                    436: 
                    437: // パレット適用変更
                    438: void
                    439: WXPlaneVRAMPanel::EnablePalette(bool value)
                    440: {
                    441:        viewctl->EnablePalette(value);
                    442: }
                    443: 
                    444: // 倍率を設定
                    445: void
                    446: WXPlaneVRAMPanel::SetScale(int scale_)
                    447: {
                    448:        viewctl->SetScale(scale_);
                    449: 
                    450:        int vscr_width  = vscroll->GetClientSize().x;
                    451:        int hscr_height = hscroll->GetClientSize().y;
                    452:        SetMaxClientSize(wxSize(viewctl->virtual_width + vscr_width,
                    453:                viewctl->virtual_height + hscr_height));
                    454: 
                    455:        DoSize(GetSize());
                    456: }
                    457: 
                    458: 
                    459: //
                    460: // プレーン VRAM ウィンドウ
                    461: //
                    462: 
1.1.1.2   root      463: // ↓+-----------------------------+
                    464: //   | wx コントロール用パネル     |
                    465: //   +-----------------------------+
                    466: //   | WXTextScreen   *statuspanel | ← 情報欄
                    467: //   +-----------------------------+
                    468: //   | WXPlaneVRAMPanel *viewpanel | ← ビットマップ (スクロールバー込み)
                    469: //   +-----------------------------+
                    470: 
1.1       root      471: // イベントテーブル
                    472: wxBEGIN_EVENT_TABLE(WXPlaneVRAMWindow, inherited)
                    473:        EVT_COMMAND_RANGE(ID_PLANE0, ID_PLANE7, wxEVT_CHECKBOX,
                    474:                WXPlaneVRAMWindow::OnPlane)
                    475:        EVT_CHECKBOX(ID_PALETTE, WXPlaneVRAMWindow::OnApplyPalette)
                    476:        EVT_CHOICE(ID_SCALE, WXPlaneVRAMWindow::OnScale)
1.1.1.2   root      477:        EVT_TIMER(wxID_ANY, WXPlaneVRAMWindow::OnTimer)
1.1       root      478: wxEND_EVENT_TABLE()
                    479: 
                    480: // コンストラクタ
                    481: WXPlaneVRAMWindow::WXPlaneVRAMWindow(wxWindow *parent, const wxString& name)
                    482:        : inherited(parent, wxID_ANY, name,
                    483:                inherited::DEFAULT_STYLE | wxRESIZE_BORDER)
                    484: {
1.1.1.2   root      485:        // デバイスを取得
                    486:        planevram = GetPlaneVRAMDevice();
                    487: 
                    488:        int nplane = planevram->GetPlaneCount();
                    489: 
1.1       root      490:        auto *topsizer = new wxBoxSizer(wxVERTICAL);
                    491: 
                    492:        // 上にコントロールパネル(のまず下敷き)
1.1.1.2   root      493:        ctrlpanel = new wxPanel(this);
1.1       root      494:        topsizer->Add(ctrlpanel, 0, wxEXPAND);
                    495: 
                    496:        // コントロールパネル用の横 Sizer
                    497:        auto *ctrlbox = new wxBoxSizer(wxHORIZONTAL);
                    498: 
1.1.1.2   root      499:        // プレーン選択チェックボックス
                    500:        auto *csbox = new wxStaticBoxSizer(wxHORIZONTAL, ctrlpanel,
                    501:                _("Planes to display"));
                    502:        // GTK3 標準のレンダリングだとコントロールの周りの空きがなさすぎて
                    503:        // 特にスタティックボックスは読みづらいので自力で少し空ける。どうして…。
                    504:        ctrlbox->Add(csbox, 0, wxALIGN_CENTER | wxALL, 3);
                    505:        // X68030 なら 4プレーン。
                    506:        // LUNA で 1bpp なら 4プレーン (上位3つは Disabled)、
                    507:        // LUNA で 4bpp なら 4プレーン、
                    508:        // LUNA で 8bpp なら 8プレーン。
                    509:        int nplane4 = (nplane == 1) ? 4 : nplane;
                    510:        for (int i = 0; i < nplane4; i++) {
                    511:                auto *ctrl = new wxCheckBox(ctrlpanel, ID_PLANE(i),
                    512:                        string_format("%d", i));
                    513:                planesw.push_back(ctrl);
                    514:        }
                    515:        // 降順に並べる
                    516:        for (int i = nplane4 - 1; i >= 0; i--) {
                    517:                csbox->Add(planesw[i]);
1.1       root      518:        }
                    519: 
                    520:        // パレット合成チェックボックス
                    521:        applysw = new wxCheckBox(ctrlpanel, ID_PALETTE, _("Apply palette"));
1.1.1.2   root      522:        ctrlbox->Add(applysw, 0, wxALIGN_CENTER | wxALL, 3);
1.1       root      523: 
                    524:        // セパレータを出したいのだが…
1.1.1.2   root      525:        ctrlbox->Add(new wxStaticText(ctrlpanel, wxID_ANY, "|"), 0,
                    526:                wxALIGN_CENTER | wxALL, 3);
1.1       root      527: 
                    528:        // 倍率
                    529:        wxString scale_choice[] = {
                    530:                "x1",
                    531:                "x2",
                    532:                "x4",
                    533:        };
                    534:        scalesw = new wxChoice(ctrlpanel, ID_SCALE,
                    535:                wxDefaultPosition, wxDefaultSize,
                    536:                countof(scale_choice), scale_choice);
1.1.1.2   root      537:        ctrlbox->Add(scalesw, 0, wxALIGN_CENTER | wxALL, 3);
1.1       root      538: 
                    539:        // sizer と下敷きパネルを紐付ける
                    540:        ctrlpanel->SetSizer(ctrlbox);
                    541:        ctrlbox->SetSizeHints(ctrlpanel);
                    542: 
1.1.1.3   root      543:        // 情報パネルは大きさを固定
                    544:        statuspanel = new WXTextScreen(this, nnSize(60, nplane));
                    545:        statuspanel->SetMinClientSize(statuspanel->GetDesiredSize());
1.1.1.2   root      546:        topsizer->Add(statuspanel, 0, wxEXPAND);
                    547: 
1.1       root      548:        viewpanel = new WXPlaneVRAMPanel(this);
                    549:        topsizer->Add(viewpanel, 1, wxEXPAND);
                    550: 
                    551:        SetSizer(topsizer);
                    552: 
1.1.1.3   root      553:        FontChanged();
1.1       root      554: 
1.1.1.2   root      555:        // 1bpp ならプレーン選択はすべて無効、それ以外はすべて有効。
                    556:        if (nplane == 1) {
1.1       root      557:                for (int i = 0; i < planesw.size(); i++) {
                    558:                        planesw[i]->Enable(false);
                    559:                }
                    560:        }
                    561: 
                    562:        // 初期値をコントロールにセットする
                    563:        if (sticky_used) {
                    564:                // 前回の値があればそれを使う。
                    565:                for (int i = 0; i < planesw.size(); i++) {
                    566:                        planesw[i]->SetValue(sticky_plane[i]);
                    567:                }
                    568:                applysw->SetValue(sticky_apply);
                    569:                scalesw->SetSelection(sticky_scale);
                    570:        } else {
1.1.1.2   root      571:                if (nplane == 1) {
1.1       root      572:                        // 初回 1bpp なら #0 プレーンのみオン。
                    573:                        for (int i = 0; i < planesw.size(); i++) {
                    574:                                planesw[i]->SetValue((i == 0));
                    575:                        }
                    576:                        applysw->SetValue(true);
                    577:                } else {
                    578:                        // 初回 4bpp なら全プレーンオン。
                    579:                        for (int i = 0; i < planesw.size(); i++) {
                    580:                                planesw[i]->SetValue(true);
                    581:                        }
                    582:                        applysw->SetValue(true);
                    583:                }
                    584:                scalesw->SetSelection(0);
                    585:        }
                    586: 
                    587:        // SetValue() ではイベントが飛ばないので、
                    588:        // 直接呼び出してイベントが来たことにする。うーん…。
                    589:        for (int i = 0; i < planesw.size(); i++) {
                    590:                DoPlane(i, planesw[i]->IsChecked());
                    591:        }
                    592:        DoApplyPalette(applysw->IsChecked());
                    593:        DoScale(scalesw->GetSelection());
1.1.1.2   root      594: 
                    595:        // 更新タイマーはモニターパネル同様の 30Hz にしておく。
                    596:        timer.SetOwner(this);
                    597:        timer.Start(33);
1.1.1.3   root      598: 
                    599:        DPRINTF("Window.ctor end\n");
1.1       root      600: }
                    601: 
                    602: // デストラクタ
                    603: WXPlaneVRAMWindow::~WXPlaneVRAMWindow()
                    604: {
                    605: }
                    606: 
                    607: void
                    608: WXPlaneVRAMWindow::FontChanged()
                    609: {
1.1.1.3   root      610:        DPRINTF("Window.FontChanged\n");
                    611:        inherited::FontChanged();
                    612:        DPRINTF("Window.FontChanged inherited\n");
                    613: 
                    614:        // 子コントロールのサイズが変わったのでウィンドウサイズを再計算。
                    615:        // 最小サイズは上コントロール部と情報パネルの横幅のうち大きい方が基準。
                    616:        wxSize minsize = ctrlpanel->GetMinClientSize();
                    617:        const wxSize& statsize = statuspanel->GetDesiredSize();
                    618:        const wxSize& statmin __unused = statuspanel->GetMinClientSize();
                    619:        const wxSize& viewmin __unused = viewpanel->GetMinClientSize();
                    620:        DPRINTF("Window.FontChanged ctrl.min=(%d,%d)\n", minsize.x, minsize.y);
                    621:        DPRINTF("Window.FontChanged stat.min=(%d,%d) des=(%d,%d)\n",
                    622:                statmin.x, statmin.y, statsize.x, statsize.y);
                    623:        DPRINTF("Window.FontChanged view.min=(%d,%d)\n", viewmin.x, viewmin.y);
                    624: 
                    625:        minsize.x = std::max(minsize.x, statsize.x);
                    626:        minsize.y += statsize.y;
                    627:        minsize.y += viewmin.y;
                    628:        DPRINTF("Window.FontChanged SetMin=(%d,%d)\n", minsize.x, minsize.y);
                    629:        SetMinClientSize(minsize);
                    630:        SetClientSize(minsize);
                    631:        Layout();
                    632: 
                    633:        DPRINTF("Window.FontChanged end\n");
1.1       root      634: }
                    635: 
                    636: // プレーン選択のチェックボックスイベント
                    637: void
                    638: WXPlaneVRAMWindow::OnPlane(wxCommandEvent& event)
                    639: {
                    640:        int plane = event.GetId() - ID_PLANE0;
                    641:        bool value = event.IsChecked();
                    642: 
                    643:        DoPlane(plane, value);
                    644: }
                    645: 
                    646: // プレーン選択 ON/OFF 処理
                    647: void
                    648: WXPlaneVRAMWindow::DoPlane(int plane, bool value)
                    649: {
                    650:        // コントロールに指示
                    651:        viewpanel->EnablePlane(plane, value);
                    652: 
                    653:        // 値を保存
                    654:        sticky_plane[plane] = value;
                    655:        sticky_used = true;
                    656: }
                    657: 
                    658: // パレット合成のチェックボックスイベント
                    659: void
                    660: WXPlaneVRAMWindow::OnApplyPalette(wxCommandEvent& event)
                    661: {
                    662:        bool value = event.IsChecked();
                    663: 
                    664:        DoApplyPalette(value);
                    665: }
                    666: 
                    667: // パレット合成 ON/OFF 処理
                    668: void
                    669: WXPlaneVRAMWindow::DoApplyPalette(bool value)
                    670: {
                    671:        // コントロールに指示
                    672:        viewpanel->EnablePalette(value);
                    673: 
                    674:        // 値を保存
                    675:        sticky_apply = value;
                    676:        sticky_used = true;
                    677: }
                    678: 
                    679: // 倍率変更イベント
                    680: void
                    681: WXPlaneVRAMWindow::OnScale(wxCommandEvent& event)
                    682: {
                    683:        int scale_index = event.GetSelection();
                    684: 
                    685:        DoScale(scale_index);
                    686: }
                    687: 
                    688: // 倍率変更処理
                    689: void
                    690: WXPlaneVRAMWindow::DoScale(int scale_index)
                    691: {
                    692:        viewpanel->SetScale(1 << scale_index);
                    693: 
                    694:        // 最大サイズは表示部の最大サイズから
                    695:        wxSize maxsize = viewpanel->GetMaxClientSize();
                    696:        maxsize.y += ctrlpanel->GetMinClientSize().y;
1.1.1.2   root      697:        maxsize.y += statuspanel->GetMinClientSize().y;
1.1       root      698:        SetMaxClientSize(maxsize);
                    699: 
                    700:        // 保存しておくのはインデックスのほう
                    701:        sticky_scale = scale_index;
                    702: }
                    703: 
1.1.1.2   root      704: // タイマーイベント
                    705: void
                    706: WXPlaneVRAMWindow::OnTimer(wxTimerEvent& event)
                    707: {
                    708:        viewpanel->Refresh();
                    709: 
                    710:        // この位置の情報で screen を更新
                    711:        TextScreen& screen = statuspanel->GetScreen();
                    712:        const wxPoint& cursor = viewpanel->GetCursor();
                    713: 
                    714:        // UpdateInfo() は cursor.x が範囲外の時の描画も行っている。
                    715:        planevram->UpdateInfo(screen, cursor.x, cursor.y);
                    716:        statuspanel->Refresh();
                    717: }
                    718: 
1.1       root      719: // static 変数
1.1.1.2   root      720: std::array<bool, WXPlaneVRAMWindow::MAX_PLANES> WXPlaneVRAMWindow::sticky_plane;
1.1       root      721: bool WXPlaneVRAMWindow::sticky_apply;
                    722: int WXPlaneVRAMWindow::sticky_scale;
                    723: bool WXPlaneVRAMWindow::sticky_used;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.