|
|
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;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.