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

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: 
1.1.1.7 ! root      194:        SetMaxSize(wxSize(virtual_width, virtual_height));
1.1       root      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: WXPlaneVRAMPanel::WXPlaneVRAMPanel(wxWindow *parent)
                    249:        : inherited(parent)
                    250: {
                    251:        // 表示パネル
                    252:        viewctl = new WXPlaneVRAMBitmapPanel(this);
                    253: 
                    254:        // スクロールバーを自分で持つ (配置は Layout() で行う)
                    255:        vscroll = new WXScrollBar(this, wxID_ANY, wxSB_VERTICAL);
                    256:        hscroll = new WXScrollBar(this, wxID_ANY, wxSB_HORIZONTAL);
                    257: 
                    258:        // 右下の空き地
                    259:        corner = new WXBitmapPanel(this);
                    260: 
                    261:        // Sizer 使わず自前でレイアウトする。
                    262:        SetAutoLayout(true);
1.1.1.7 ! root      263:        FontChanged();
1.1       root      264: 
                    265:        // スクロールバーからの通知イベントは表示パネルへ回す
                    266:        vscroll->Connect(NONO_EVT_SCROLL,
                    267:                wxScrollEventHandler(WXPlaneVRAMBitmapPanel::OnScroll), NULL, viewctl);
                    268:        hscroll->Connect(NONO_EVT_SCROLL,
                    269:                wxScrollEventHandler(WXPlaneVRAMBitmapPanel::OnScroll), NULL, viewctl);
1.1.1.3   root      270: 
                    271:        DPRINTF("Panel.ctor end\n");
1.1       root      272: }
                    273: 
                    274: // デストラクタ
                    275: WXPlaneVRAMPanel::~WXPlaneVRAMPanel()
                    276: {
                    277: }
                    278: 
1.1.1.3   root      279: // フォントサイズ変更
                    280: void
                    281: WXPlaneVRAMPanel::FontChanged()
                    282: {
                    283:        // このパネル自体はフォントを出力しないが
                    284:        // フォントサイズ変更に反応する必要があるため、用意している。
                    285: 
                    286:        // 自身がフォントを使わないので呼ばなくてもいいが、お作法として。
                    287:        inherited::FontChanged();
                    288:        DPRINTF("Panel.FontChanged %d\n", font_height);
                    289: 
                    290:        // SubWindow はパネルの FontChanged() までは呼んでくれるけど、
                    291:        // パネルが子を持ってるケースは自力で伝搬させるとかする必要がある。
                    292:        hscroll->FontChanged();
                    293:        vscroll->FontChanged();
                    294: 
1.1.1.7 ! root      295:        Fit();
        !           296: 
1.1.1.3   root      297:        DPRINTF("Panel.FontChanged end\n");
                    298: }
                    299: 
1.1       root      300: void
1.1.1.7 ! root      301: WXPlaneVRAMPanel::Fit()
1.1       root      302: {
1.1.1.7 ! root      303:        // 最小/最大サイズを再計算。
        !           304:        wxSize vmin = vscroll->GetMinSize();
        !           305:        wxSize hmin = hscroll->GetMinSize();
        !           306:        wxSize minsize(hmin.x + vmin.x, vmin.y + hmin.y);
        !           307:        wxSize maxsize(viewctl->virtual_width + vmin.x,
        !           308:                viewctl->virtual_height + hmin.y);
        !           309:        SetSizeHints(minsize, maxsize);
        !           310: 
        !           311:        // 新しいサイズはビューサイズから決定。
        !           312:        wxSize viewsize = viewctl->GetSize();
        !           313:        wxSize newsize(viewsize.x + vmin.x, viewsize.y + hmin.y);
        !           314:        DPRINTF("Panel.Fit (%d,%d) min=(%d,%d) max=(%d,%d)\n",
        !           315:                newsize.x, newsize.y, minsize.x, minsize.y, maxsize.x, maxsize.y);
        !           316:        SetSize(newsize);
        !           317: 
        !           318:        GetParent()->Fit();
        !           319: }
        !           320: 
        !           321: bool
        !           322: WXPlaneVRAMPanel::Layout()
        !           323: {
        !           324:        const wxSize size = GetSize();
        !           325:        DPRINTF("Panel.Layout size=(%d,%d)\n", size.x, size.y);
        !           326:        wxSize vscr = vscroll->GetSize();
        !           327:        wxSize hscr = hscroll->GetSize();
        !           328: 
        !           329:        // コントロールを配置。
        !           330:        int view_width  = size.x - vscr.x;
        !           331:        int view_height = size.y - hscr.y;
        !           332:        DPRINTF("Panel.Layout view=(%d,%d)\n", view_width, view_height);
        !           333: 
        !           334:        viewctl->SetSize(0, 0, view_width, view_height);
        !           335:        vscroll->SetSize(view_width, 0, vscr.x, view_height);
        !           336:        hscroll->SetSize(0, view_height, view_width, hscr.y);
        !           337:        corner->SetSize(view_width, view_height, vscr.x, hscr.y);
1.1       root      338: 
1.1.1.7 ! root      339:        SetScroll();
        !           340:        DPRINTF("Panel.Layout done\n");
1.1       root      341: 
1.1.1.7 ! root      342:        return true;
1.1       root      343: }
                    344: 
                    345: // サイズ変更処理。パネルサイズと倍率が変わったら呼ぶこと。
                    346: // 倍率が変わった場合もスクロールバーの再設定とかがあるため。
                    347: void
1.1.1.7 ! root      348: WXPlaneVRAMPanel::SetScroll()
1.1       root      349: {
1.1.1.7 ! root      350:        wxSize viewsize = viewctl->GetSize();
        !           351:        DPRINTF("Panel.%s: view=(%d,%d)\n", __func__, viewsize.x, viewsize.y);
1.1       root      352:        int virtual_width = viewctl->virtual_width;
                    353:        int virtual_height = viewctl->virtual_height;
                    354:        Rect& view = viewctl->view;
                    355: 
                    356:        // スクロールバーが右端まで行っている場合は右を固定したように見せる。
                    357:        // ただし全体が見えている場合は除く。
                    358: 
                    359:        if (view.x > 0 &&
                    360:            (view.x + view.w == virtual_width ||
                    361:             view.x + viewsize.x >= virtual_width))
                    362:        {
                    363:                view.x = virtual_width - viewsize.x;
                    364:                if (view.x < 0) {
                    365:                        view.x = 0;
                    366:                }
                    367:        }
                    368:        view.w = viewsize.x;
                    369: 
                    370:        // 下端も同様
                    371:        if (view.y > 0 &&
                    372:            (view.y + view.h >= virtual_height ||
1.1.1.7 ! root      373:             view.y + viewsize.y >= virtual_height))
1.1       root      374:        {
                    375:                view.y = virtual_height - viewsize.y;
                    376:                if (view.y < 0) {
                    377:                        view.y = 0;
                    378:                }
                    379:        }
                    380:        view.h = viewsize.y;
                    381: 
                    382:        // スクロールバー(横)を再設定
                    383:        assert(hscroll);
                    384:        int hpos = view.x;
                    385:        int hthumbsize = view.w;
                    386:        int hrange = virtual_width;
                    387:        int hpagesize = view.w;
                    388:        hscroll->SetScrollParam(hpos, hthumbsize, hrange, hpagesize);
                    389: 
                    390:        // スクロールバー(縦)を再設定
                    391:        assert(vscroll);
                    392:        int vpos = view.y;
                    393:        int vthumbsize = view.h;
                    394:        int vrange = virtual_height;
                    395:        int vpagesize = view.h;
                    396:        vscroll->SetScrollParam(vpos, vthumbsize, vrange, vpagesize);
                    397: }
                    398: 
                    399: // プレーン選択変更
                    400: void
                    401: WXPlaneVRAMPanel::EnablePlane(int plane, bool value)
                    402: {
                    403:        viewctl->EnablePlane(plane, value);
                    404: }
                    405: 
                    406: // パレット適用変更
                    407: void
                    408: WXPlaneVRAMPanel::EnablePalette(bool value)
                    409: {
                    410:        viewctl->EnablePalette(value);
                    411: }
                    412: 
                    413: // 倍率を設定
                    414: void
                    415: WXPlaneVRAMPanel::SetScale(int scale_)
                    416: {
                    417:        viewctl->SetScale(scale_);
                    418: 
1.1.1.7 ! root      419:        int vscr_width  = vscroll->GetSize().x;
        !           420:        int hscr_height = hscroll->GetSize().y;
        !           421:        SetMaxSize(wxSize(viewctl->virtual_width + vscr_width,
1.1       root      422:                viewctl->virtual_height + hscr_height));
                    423: 
1.1.1.7 ! root      424:        SetScroll();
1.1       root      425: }
                    426: 
                    427: 
                    428: //
                    429: // プレーン VRAM ウィンドウ
                    430: //
                    431: 
1.1.1.2   root      432: // ↓+-----------------------------+
                    433: //   | wx コントロール用パネル     |
                    434: //   +-----------------------------+
                    435: //   | WXTextScreen   *statuspanel | ← 情報欄
                    436: //   +-----------------------------+
                    437: //   | WXPlaneVRAMPanel *viewpanel | ← ビットマップ (スクロールバー込み)
                    438: //   +-----------------------------+
                    439: 
1.1       root      440: // イベントテーブル
                    441: wxBEGIN_EVENT_TABLE(WXPlaneVRAMWindow, inherited)
                    442:        EVT_COMMAND_RANGE(ID_PLANE0, ID_PLANE7, wxEVT_CHECKBOX,
                    443:                WXPlaneVRAMWindow::OnPlane)
                    444:        EVT_CHECKBOX(ID_PALETTE, WXPlaneVRAMWindow::OnApplyPalette)
                    445:        EVT_CHOICE(ID_SCALE, WXPlaneVRAMWindow::OnScale)
1.1.1.2   root      446:        EVT_TIMER(wxID_ANY, WXPlaneVRAMWindow::OnTimer)
1.1       root      447: wxEND_EVENT_TABLE()
                    448: 
                    449: // コンストラクタ
                    450: WXPlaneVRAMWindow::WXPlaneVRAMWindow(wxWindow *parent, const wxString& name)
                    451:        : inherited(parent, wxID_ANY, name,
                    452:                inherited::DEFAULT_STYLE | wxRESIZE_BORDER)
                    453: {
1.1.1.2   root      454:        // デバイスを取得
                    455:        planevram = GetPlaneVRAMDevice();
                    456: 
                    457:        int nplane = planevram->GetPlaneCount();
                    458: 
1.1.1.7 ! root      459:        // 上段、コントロールパネル(のまず下敷き)
1.1.1.2   root      460:        ctrlpanel = new wxPanel(this);
1.1.1.6   root      461:        ctrlpanel->SetName("WXPlaneVRAMWindow.CtrlPanel");
1.1       root      462: 
                    463:        // コントロールパネル用の横 Sizer
                    464:        auto *ctrlbox = new wxBoxSizer(wxHORIZONTAL);
                    465: 
1.1.1.2   root      466:        // プレーン選択チェックボックス
                    467:        auto *csbox = new wxStaticBoxSizer(wxHORIZONTAL, ctrlpanel,
                    468:                _("Planes to display"));
                    469:        // GTK3 標準のレンダリングだとコントロールの周りの空きがなさすぎて
                    470:        // 特にスタティックボックスは読みづらいので自力で少し空ける。どうして…。
                    471:        ctrlbox->Add(csbox, 0, wxALIGN_CENTER | wxALL, 3);
                    472:        // X68030 なら 4プレーン。
                    473:        // LUNA で 1bpp なら 4プレーン (上位3つは Disabled)、
                    474:        // LUNA で 4bpp なら 4プレーン、
                    475:        // LUNA で 8bpp なら 8プレーン。
                    476:        int nplane4 = (nplane == 1) ? 4 : nplane;
                    477:        for (int i = 0; i < nplane4; i++) {
                    478:                auto *ctrl = new wxCheckBox(ctrlpanel, ID_PLANE(i),
                    479:                        string_format("%d", i));
                    480:                planesw.push_back(ctrl);
                    481:        }
                    482:        // 降順に並べる
                    483:        for (int i = nplane4 - 1; i >= 0; i--) {
                    484:                csbox->Add(planesw[i]);
1.1       root      485:        }
                    486: 
                    487:        // パレット合成チェックボックス
                    488:        applysw = new wxCheckBox(ctrlpanel, ID_PALETTE, _("Apply palette"));
1.1.1.2   root      489:        ctrlbox->Add(applysw, 0, wxALIGN_CENTER | wxALL, 3);
1.1       root      490: 
                    491:        // セパレータを出したいのだが…
1.1.1.2   root      492:        ctrlbox->Add(new wxStaticText(ctrlpanel, wxID_ANY, "|"), 0,
                    493:                wxALIGN_CENTER | wxALL, 3);
1.1       root      494: 
                    495:        // 倍率
                    496:        wxString scale_choice[] = {
                    497:                "x1",
                    498:                "x2",
                    499:                "x4",
                    500:        };
                    501:        scalesw = new wxChoice(ctrlpanel, ID_SCALE,
                    502:                wxDefaultPosition, wxDefaultSize,
                    503:                countof(scale_choice), scale_choice);
1.1.1.2   root      504:        ctrlbox->Add(scalesw, 0, wxALIGN_CENTER | wxALL, 3);
1.1       root      505: 
                    506:        // sizer と下敷きパネルを紐付ける
                    507:        ctrlpanel->SetSizer(ctrlbox);
                    508:        ctrlbox->SetSizeHints(ctrlpanel);
                    509: 
1.1.1.7 ! root      510:        // 中段、情報パネルは大きさを固定
        !           511:        constexpr int status_col = 60;
        !           512:        statuspanel = new WXTextScreen(this, nnSize(status_col, nplane));
        !           513:        statuspanel->SetMinSize(statuspanel->GetBestSize());
        !           514: 
        !           515:        // 中段の右側の空き地用。
        !           516:        spacer = new WXBitmapPanel(this);
        !           517: 
        !           518:        // 下段、表示パネル。
        !           519:        // 大きさは適当だがフォントサイズを大きくした後で再び小さくすると
        !           520:        // このパネルはどうしたらいいのか難しいのと、最初から広いほうが見やすい
        !           521:        // というのもあるしね…ということにして、とりあえずステータスパネルを
        !           522:        // 最初からフォントサイズ 24 の時の幅にしておいて誤魔化す。高さは適当。
1.1       root      523:        viewpanel = new WXPlaneVRAMPanel(this);
1.1.1.7 ! root      524:        viewpanel->SetSize(wxSize(status_col * 12, status_col * 12 / 2));
1.1       root      525: 
1.1.1.7 ! root      526:        SetAutoLayout(true);
1.1.1.3   root      527:        FontChanged();
1.1       root      528: 
1.1.1.2   root      529:        // 1bpp ならプレーン選択はすべて無効、それ以外はすべて有効。
                    530:        if (nplane == 1) {
1.1       root      531:                for (int i = 0; i < planesw.size(); i++) {
                    532:                        planesw[i]->Enable(false);
                    533:                }
                    534:        }
                    535: 
                    536:        // 初期値をコントロールにセットする
                    537:        if (sticky_used) {
                    538:                // 前回の値があればそれを使う。
                    539:                for (int i = 0; i < planesw.size(); i++) {
                    540:                        planesw[i]->SetValue(sticky_plane[i]);
                    541:                }
                    542:                applysw->SetValue(sticky_apply);
                    543:                scalesw->SetSelection(sticky_scale);
                    544:        } else {
1.1.1.2   root      545:                if (nplane == 1) {
1.1       root      546:                        // 初回 1bpp なら #0 プレーンのみオン。
                    547:                        for (int i = 0; i < planesw.size(); i++) {
                    548:                                planesw[i]->SetValue((i == 0));
                    549:                        }
                    550:                        applysw->SetValue(true);
                    551:                } else {
                    552:                        // 初回 4bpp なら全プレーンオン。
                    553:                        for (int i = 0; i < planesw.size(); i++) {
                    554:                                planesw[i]->SetValue(true);
                    555:                        }
                    556:                        applysw->SetValue(true);
                    557:                }
                    558:                scalesw->SetSelection(0);
                    559:        }
                    560: 
                    561:        // SetValue() ではイベントが飛ばないので、
                    562:        // 直接呼び出してイベントが来たことにする。うーん…。
                    563:        for (int i = 0; i < planesw.size(); i++) {
                    564:                DoPlane(i, planesw[i]->IsChecked());
                    565:        }
                    566:        DoApplyPalette(applysw->IsChecked());
                    567:        DoScale(scalesw->GetSelection());
1.1.1.2   root      568: 
                    569:        // 更新タイマーはモニターパネル同様の 30Hz にしておく。
                    570:        timer.SetOwner(this);
                    571:        timer.Start(33);
1.1.1.3   root      572: 
                    573:        DPRINTF("Window.ctor end\n");
1.1       root      574: }
                    575: 
                    576: // デストラクタ
                    577: WXPlaneVRAMWindow::~WXPlaneVRAMWindow()
                    578: {
                    579: }
                    580: 
                    581: void
1.1.1.7 ! root      582: WXPlaneVRAMWindow::Fit()
1.1       root      583: {
1.1.1.7 ! root      584:        // 全部準備出来る前に呼ばれることがある。spacer は見ないので不要。
        !           585:        if (ctrlpanel == NULL || statuspanel == NULL || viewpanel == NULL) {
        !           586:                return;
        !           587:        }
        !           588: 
        !           589:        // 最大最小サイズを設定。
        !           590:        DoSizeHints();
        !           591: 
        !           592:        // コントロールからウィンドウサイズを計算。
        !           593:        const wxSize& ctrlsize = ctrlpanel->GetSize();
        !           594:        const wxSize& statsize = statuspanel->GetSize();
        !           595:        const wxSize& viewsize = viewpanel->GetSize();
        !           596: 
        !           597:        int size_x = ctrlsize.x;
        !           598:        if (size_x < statsize.x) {
        !           599:                size_x = statsize.x;
        !           600:        }
        !           601:        if (size_x < viewsize.x) {
        !           602:                size_x = viewsize.x;
        !           603:        }
        !           604:        wxSize size(size_x, ctrlsize.y + statsize.y + viewsize.y);
        !           605:        DPRINTF("Window.Fit (%d,%d)\n", size.x, size.y);
        !           606:        SetClientSize(size);
        !           607: }
1.1.1.3   root      608: 
1.1.1.7 ! root      609: void
        !           610: WXPlaneVRAMWindow::DoSizeHints()
        !           611: {
        !           612:        // 最小サイズを再計算。
        !           613:        const wxSize& ctrlmin = ctrlpanel->GetMinSize();
        !           614:        const wxSize& statmin = statuspanel->GetMinSize();
        !           615:        const wxSize& viewmin = viewpanel->GetMinSize();
        !           616:        DPRINTF("Window.%s ctrlmin=(%d,%d) statmin=(%d,%d) viewmin=(%d,%d)\n",
        !           617:                __func__,
        !           618:                ctrlmin.x, ctrlmin.y, statmin.x, statmin.y, viewmin.x, viewmin.y);
        !           619: 
        !           620:        int minsize_x = ctrlmin.x;
        !           621:        if (minsize_x < statmin.x) {
        !           622:                minsize_x = statmin.x;
        !           623:        }
        !           624:        if (minsize_x < viewmin.x) {
        !           625:                minsize_x = viewmin.x;
        !           626:        }
        !           627:        min_height = ctrlmin.y + statmin.y + viewmin.y;
        !           628:        wxSize minsize(minsize_x, min_height);
1.1.1.3   root      629: 
1.1.1.7 ! root      630:        // 最大サイズは viewsize に依存しそうだから手抜き。
        !           631:        const wxSize& viewmax = viewpanel->GetMaxSize();
        !           632:        wxSize maxsize(viewmax.x, ctrlmin.y + statmin.y + viewmax.y);
        !           633: 
        !           634:        // 最大最小サイズを再設定。
        !           635:        DPRINTF("Window.%s min=(%d,%d), max=(%d,%d)\n", __func__,
        !           636:                minsize.x, minsize.y, maxsize.x, maxsize.y);
        !           637:        SetSizeHints(wxDefaultCoord, wxDefaultCoord);
        !           638:        SetSizeHints(ClientToWindowSize(minsize), ClientToWindowSize(maxsize));
        !           639: }
        !           640: 
        !           641: bool
        !           642: WXPlaneVRAMWindow::Layout()
        !           643: {
        !           644:        // sizer があるので呼ばないといけない。
        !           645:        bool r = inherited::Layout();
        !           646: 
        !           647:        // 全部準備出来る前に呼ばれることがある。
        !           648:        if (ctrlpanel == NULL || statuspanel == NULL || viewpanel == NULL ||
        !           649:                spacer == NULL)
        !           650:        {
        !           651:                return r;
        !           652:        }
        !           653: 
        !           654:        wxSize client = GetClientSize();
        !           655:        DPRINTF("Window.Layout (%d,%d)\n", client.x, client.y);
        !           656:        const wxSize& ctrlsize = ctrlpanel->GetSize();
        !           657:        const wxSize& statsize = statuspanel->GetSize();
        !           658: 
        !           659:        // wxmonitor.cpp の Layout() 内のコメント参照。
        !           660:        wxSize min = GetMinClientSize();
        !           661:        if (min.y >= min_height) {
        !           662:                // 正常なリサイズなのでこのサイズを覚えておく。
        !           663:                correct_clientsize = client;
        !           664:        } else {
        !           665:                // 変なリサイズが行われたので、やり直す。
        !           666:                client = correct_clientsize;
        !           667:                DoSizeHints();
        !           668:                SetClientSize(client);
        !           669: 
        !           670:                min = GetMinClientSize();
        !           671:                DPRINTF("Window.%s patch client=(%d,%d) min=(%d,%d)\n", __func__,
        !           672:                        client.x, client.y, min.x, min.y);
        !           673: 
        !           674:                // SetClientSize() によってこの場で Layout() が呼ばれて戻ってきた
        !           675:                // はずなので、これ以降はもう処理しなくていい。
        !           676:                return true;
        !           677:        }
        !           678: 
        !           679:        ctrlpanel->SetSize(0, 0, client.x, ctrlsize.y);
        !           680:        statuspanel->SetSize(0, ctrlsize.y, statsize.x, statsize.y);
        !           681:        viewpanel->SetSize(0, ctrlsize.y + statsize.y,
        !           682:                client.x, client.y - ctrlsize.y - statsize.y);
        !           683: 
        !           684:        // ステータスパネル右に空き地が出来るなら埋める。
        !           685:        if (statsize.x < client.x) {
        !           686:                spacer->SetSize(statsize.x, ctrlsize.y,
        !           687:                        client.x - statsize.x, statsize.y);
        !           688:                spacer->Show();
        !           689:        } else {
        !           690:                spacer->Hide();
        !           691:        }
        !           692: 
        !           693:        return true;
1.1       root      694: }
                    695: 
                    696: // プレーン選択のチェックボックスイベント
                    697: void
                    698: WXPlaneVRAMWindow::OnPlane(wxCommandEvent& event)
                    699: {
                    700:        int plane = event.GetId() - ID_PLANE0;
                    701:        bool value = event.IsChecked();
                    702: 
                    703:        DoPlane(plane, value);
                    704: }
                    705: 
                    706: // プレーン選択 ON/OFF 処理
                    707: void
                    708: WXPlaneVRAMWindow::DoPlane(int plane, bool value)
                    709: {
                    710:        // コントロールに指示
                    711:        viewpanel->EnablePlane(plane, value);
                    712: 
                    713:        // 値を保存
                    714:        sticky_plane[plane] = value;
                    715:        sticky_used = true;
                    716: }
                    717: 
                    718: // パレット合成のチェックボックスイベント
                    719: void
                    720: WXPlaneVRAMWindow::OnApplyPalette(wxCommandEvent& event)
                    721: {
                    722:        bool value = event.IsChecked();
                    723: 
                    724:        DoApplyPalette(value);
                    725: }
                    726: 
                    727: // パレット合成 ON/OFF 処理
                    728: void
                    729: WXPlaneVRAMWindow::DoApplyPalette(bool value)
                    730: {
                    731:        // コントロールに指示
                    732:        viewpanel->EnablePalette(value);
                    733: 
                    734:        // 値を保存
                    735:        sticky_apply = value;
                    736:        sticky_used = true;
                    737: }
                    738: 
                    739: // 倍率変更イベント
                    740: void
                    741: WXPlaneVRAMWindow::OnScale(wxCommandEvent& event)
                    742: {
                    743:        int scale_index = event.GetSelection();
                    744: 
                    745:        DoScale(scale_index);
                    746: }
                    747: 
                    748: // 倍率変更処理
                    749: void
                    750: WXPlaneVRAMWindow::DoScale(int scale_index)
                    751: {
                    752:        viewpanel->SetScale(1 << scale_index);
                    753: 
                    754:        // 最大サイズは表示部の最大サイズから
1.1.1.7 ! root      755:        wxSize maxsize = viewpanel->GetMaxSize();
        !           756:        maxsize.y += ctrlpanel->GetMinSize().y;
        !           757:        maxsize.y += statuspanel->GetMinSize().y;
1.1       root      758:        SetMaxClientSize(maxsize);
                    759: 
                    760:        // 保存しておくのはインデックスのほう
                    761:        sticky_scale = scale_index;
                    762: }
                    763: 
1.1.1.2   root      764: // タイマーイベント
                    765: void
                    766: WXPlaneVRAMWindow::OnTimer(wxTimerEvent& event)
                    767: {
                    768:        viewpanel->Refresh();
                    769: 
                    770:        // この位置の情報で screen を更新
                    771:        TextScreen& screen = statuspanel->GetScreen();
                    772:        const wxPoint& cursor = viewpanel->GetCursor();
                    773: 
                    774:        // UpdateInfo() は cursor.x が範囲外の時の描画も行っている。
                    775:        planevram->UpdateInfo(screen, cursor.x, cursor.y);
                    776:        statuspanel->Refresh();
                    777: }
                    778: 
1.1       root      779: // static 変数
1.1.1.2   root      780: std::array<bool, WXPlaneVRAMWindow::MAX_PLANES> WXPlaneVRAMWindow::sticky_plane;
1.1       root      781: bool WXPlaneVRAMWindow::sticky_apply;
                    782: int WXPlaneVRAMWindow::sticky_scale;
                    783: 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.