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

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