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

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