|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: //
1.1.1.7 root 8: // モニター
1.1 root 9: //
10:
1.1.1.6 root 11: #include "wxmonitor.h"
1.1.1.7 root 12: #include "wxmainframe.h"
1.1.1.9 root 13: #include "monitor.h"
1.1.1.7 root 14:
1.1.1.10 root 15: //#define WINDOW_DEBUG 1
16:
17: #if defined(WINDOW_DEBUG)
18: #define DPRINTF(fmt...) printf(fmt)
19: #else
20: #define DPRINTF(fmt...) /**/
21: #endif
22:
1.1.1.7 root 23: //
24: // モニターパネル
25: //
26:
27: // イベントテーブル
28: wxBEGIN_EVENT_TABLE(WXMonitorPanel, inherited)
29: EVT_TIMER(wxID_ANY, WXMonitorPanel::OnTimer)
30: wxEND_EVENT_TABLE()
31:
32: // コンストラクタ
1.1.1.9 root 33: WXMonitorPanel::WXMonitorPanel(wxWindow *parent, Monitor *monitor_)
34: : inherited(parent, monitor_->GetSize())
1.1.1.7 root 35: , monitor(monitor_)
36: {
37: timer.SetOwner(this);
38:
39: // 現在の設定値を適用
1.1.1.8 root 40: auto mainframe = dynamic_cast<WXMainFrame*>(GetParent()->GetParent());
41: SetRate(mainframe->GetMonitorRate());
1.1.1.7 root 42:
1.1.1.13! root 43: // 今の所パディングは変わらない。
! 44: monitor->SetPadding(WXTextScreen::DefaultPadding);
! 45: FontChanged();
! 46:
1.1.1.7 root 47: // 最初に一回描画を起こす
48: wxTimerEvent dummy(timer);
49: AddPendingEvent(dummy);
50: }
51:
52: // デストラクタ
53: WXMonitorPanel::~WXMonitorPanel()
54: {
55: }
56:
1.1.1.13! root 57: // フォントサイズ変更
! 58: void
! 59: WXMonitorPanel::FontChanged()
! 60: {
! 61: inherited::FontChanged();
! 62:
! 63: monitor->SetFontSize(font_width, font_height);
! 64: }
! 65:
1.1.1.7 root 66: // タイマーイベント
67: void
68: WXMonitorPanel::OnTimer(wxTimerEvent& event)
69: {
70: DoRefresh();
71: }
72:
73: // 画面を更新して再描画する。
74: //
75: // 通常はタイマーイベントにより更新間隔ごとに呼ばれるが、
76: // ユーザ操作により画面の更新が必要ならその都度直接これを呼ぶ。
77: void
78: WXMonitorPanel::DoRefresh()
79: {
1.1.1.13! root 80: bool updated = false;
! 81:
1.1.1.7 root 82: // モニタースクリーンを更新して
1.1.1.13! root 83: monitor->UpdateScreen(screen);
! 84: if (screen.GetBuf() != prevbuf) {
! 85: updated = true;
! 86: }
! 87:
! 88: // あればビットマップ描画を足して
! 89: if (monitor->UpdateBitmap(bitmap)) {
! 90: updated = true;
! 91: }
1.1.1.7 root 92:
93: // 必要なら再描画
1.1.1.13! root 94: if (updated) {
1.1.1.7 root 95: Refresh();
96: }
97: }
98:
99: // 画面更新頻度を Hz で設定する。
100: void
101: WXMonitorPanel::SetRate(int hz)
102: {
103: timer.Start(1000 / hz);
104: }
105:
106:
107: //
108: // モニターウィンドウ
109: //
1.1.1.6 root 110:
1.1 root 111: // コンストラクタ
1.1.1.5 root 112: WXMonitorWindow::WXMonitorWindow(wxWindow *parent, const wxString& name,
1.1.1.9 root 113: Monitor *monitor_)
1.1.1.5 root 114: : inherited(parent, wxID_ANY, name)
1.1 root 115: {
1.1.1.7 root 116: // モニタパネル
117: monpanel = new WXMonitorPanel(this, monitor_);
1.1.1.10 root 118: Fit();
1.1 root 119: }
120:
121: // デストラクタ
122: WXMonitorWindow::~WXMonitorWindow()
123: {
124: }
1.1.1.7 root 125:
126:
127: //
128: // 縦スクロールバー付きモニタウィンドウ
129: //
130:
131: // コンストラクタ
132: WXScrollMonitorWindow::WXScrollMonitorWindow(wxWindow *parent,
1.1.1.9 root 133: const wxString& name, Monitor *monitor_)
1.1.1.7 root 134: : inherited(parent, wxID_ANY, name, DEFAULT_STYLE | wxRESIZE_BORDER)
135: {
1.1.1.10 root 136: DPRINTF("%s begin\n", __method__);
137:
1.1.1.7 root 138: // +--------------+---------+
139: // | MonitorPanel | VScroll |
140: // +--------------+---------+
141:
142: // モニタパネル
143: monpanel = new WXMonitorPanel(this, monitor_);
144:
145: // スクロールバー
146: vscroll = new WXScrollBar(this, wxID_ANY, wxSB_VERTICAL);
147:
1.1.1.11 root 148: // 自前レイアウト。
149: SetMyLayout();
1.1.1.7 root 150:
151: // ウィンドウサイズを確定させる
1.1.1.10 root 152: FontChanged();
1.1.1.7 root 153:
154: // スクロールのために (パネル領域での) MouseWheel イベントもここで
155: // 受け取りたい。スクロールバー上のマウスホイール操作はスクロールバーが
156: // 処理しているので問題ないが、パネル領域でのマウスホイール操作はここ
157: // (wxFrame)ではなくパネルに対して飛んでくる。
158: // ここで一緒に処理したほうが楽なので、こちらに回す。
1.1.1.13! root 159: monpanel->Bind(wxEVT_MOUSEWHEEL,
! 160: &WXScrollMonitorWindow::OnMouseWheel, this);
1.1.1.7 root 161:
162: // スクロールバーからの位置変更通知
1.1.1.13! root 163: vscroll->Bind(NONO_EVT_SCROLL, &WXScrollMonitorWindow::OnScroll, this);
! 164:
1.1.1.10 root 165: DPRINTF("%s done\n", __method__);
1.1.1.7 root 166: }
167:
168: // デストラクタ
169: WXScrollMonitorWindow::~WXScrollMonitorWindow()
170: {
171: }
172:
1.1.1.10 root 173: void
174: WXScrollMonitorWindow::FontChanged()
1.1.1.7 root 175: {
1.1.1.10 root 176: monpanel->FontChanged();
177: vscroll->FontChanged();
178: DPRINTF("%s %d\n", __method__, monpanel->GetFontHeight());
179:
180: Fit();
1.1.1.7 root 181: }
182:
1.1.1.11 root 183: // 自前レイアウト方式のサイズに関する情報を返す。
184: bool
185: WXScrollMonitorWindow::GetMySizeHints(wxSize *newp, wxSize *minp, wxSize *maxp,
186: wxSize *incp)
1.1.1.7 root 187: {
1.1.1.11 root 188: auto psize = monpanel->GetSize();
189: auto vsize = vscroll->GetSize();
1.1.1.7 root 190:
1.1.1.11 root 191: // 幅は monpanel 幅 + スクロールバーの幅、高さは monpanel の高さで決まる。
192: // monpanel には四辺に Padding があることに注意。
193: int x = psize.x + vsize.x;
194: int min_y = std::max(vscroll->GetMinSize().y, monpanel->GetScreenHeight(1));
195: int new_y = std::max(psize.y, min_y);
196: wxSize newsize(x, new_y);
197: wxSize minsize(x, min_y);
198: wxSize maxsize(x, GetMaxClientSize().y);
199: wxSize incsize(0, monpanel->GetFontHeight());
200:
201: if (newp) *newp = newsize;
202: if (minp) *minp = minsize;
203: if (maxp) *maxp = maxsize;
204: if (incp) *incp = incsize;
205: return true;
1.1.1.10 root 206: }
1.1.1.7 root 207:
1.1.1.10 root 208: bool
209: WXScrollMonitorWindow::Layout()
210: {
1.1.1.11 root 211: if (MyLayout() == false) {
212: // コントロールを配置。
213: wxSize client = GetClientSize();
214: const wxSize vsize = vscroll->GetSize();
215:
216: int mon_width = client.x - vsize.x;
217: int mon_height = client.y;
218: // 最低でも 1px ないと GTK とかに怒られる。今は起きないはず?
219: if (__predict_false(mon_width < 1)) {
220: mon_width = 1;
221: }
222: if (__predict_false(mon_height < 1)) {
223: mon_height = 1;
224: }
1.1.1.10 root 225: #if defined(WINDOW_DEBUG)
1.1.1.11 root 226: const wxSize win = GetSize();
227: const wxSize minwin = GetMinSize();
228: printf("%s WinSize =(%d,%d) MinWin =(%d,%d) Shown=%u\n",
229: __method__, win.x, win.y, minwin.x, minwin.y, IsShown());
230: const wxSize min = GetMinClientSize();
231: printf("%s ClientSize=(%d,%d) MinClient=(%d,%d)\n",
232: __method__, client.x, client.y, min.x, min.y);
1.1.1.10 root 233: #endif
234:
1.1.1.11 root 235: monpanel->SetSize(0, 0, mon_width, mon_height);
236: vscroll->SetSize(mon_width, 0, vsize.x, mon_height);
1.1.1.10 root 237:
1.1.1.11 root 238: #if defined(WINDOW_DEBUG)
239: const wxSize monsize = monpanel->GetSize();
240: const wxSize vsize1 = vscroll->GetSize();
241: int py = monsize.y - monpanel->GetPaddingY();
242: int height = monpanel->GetFontHeight();
243: int row = (height != 0) ? (py / height) : 0;
244: int res = (height != 0) ? (py % height) : 0;
245: printf("%s mon=(%d,%d) vscroll=(%d,%d), row=%d%s\n", __method__,
246: monsize.x, monsize.y, vsize1.x, vsize1.y,
247: row, (res == 0 ? "" : "+"));
248: #endif
1.1.1.10 root 249:
1.1.1.11 root 250: // スクロールバーを再設定。
251: // 今の所ヘッダが常に1行ある。
252: static int HEADLINES = 1;
253: int pos = (int)monpanel->GetUserData();
254: int thumbsize = monpanel->GetRow() - HEADLINES;
255: int range = monpanel->GetMonitor()->GetMaxHeight() - HEADLINES;
256: int pagesize = thumbsize - 1;
257: if (pos > range - thumbsize) {
258: pos = range - thumbsize;
259: DoScroll(pos);
260: }
261: vscroll->SetScrollParam(pos, thumbsize, range, pagesize);
1.1.1.7 root 262: }
1.1.1.10 root 263: return true;
264: }
265:
1.1.1.7 root 266: // マウスホイールイベント (WXTextScreen 上で起きたやつをこっちに回してある)
267: void
268: WXScrollMonitorWindow::OnMouseWheel(wxMouseEvent& event)
269: {
270: // GetWheelRotation() は上(奥)向きに回すと +120、下(手前)に回すと -120。
271: // どこの決まりか知らんけど、スクロールバーのほうはホイール1段階で3行
272: // スクロールするのでそれに合わせる。
273: int pos = (int)monpanel->GetUserData();
274: pos = pos - event.GetWheelRotation() / 40;
275:
276: int maxpos = vscroll->GetRange() - vscroll->GetThumbSize();
277: if (pos < 0)
278: pos = 0;
279: if (pos > maxpos)
280: pos = maxpos;
281:
282: DoScroll(pos);
283: // スクロールバーの位置を追従
284: vscroll->SetThumbPosition(pos);
285: }
286:
287: // スクロールバーからの通知イベント
288: void
289: WXScrollMonitorWindow::OnScroll(wxScrollEvent& event)
290: {
291: DoScroll(event.GetPosition());
292: }
293:
294: // スクロール処理 (OnScroll() と OnMouseWheel() から呼ばれる)
295: void
296: WXScrollMonitorWindow::DoScroll(int pos)
297: {
298: // userdata が表示開始位置になっている
299: monpanel->SetUserData(pos);
300: monpanel->DoRefresh();
301: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.