|
|
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:
1.1.1.7 root 7: //
8: // サブウィンドウ
9: //
1.1.1.11! root 10: // wxWindow::SetSizeHints() の挙動がアレなのに対応するハック付き。
1.1.1.7 root 11:
1.1 root 12: #include "wxsubwindow.h"
1.1.1.7 root 13: #include "fontmanager.h"
1.1.1.2 root 14: #include "wxmainframe.h"
1.1.1.3 root 15: #include "wxtextscreen.h"
1.1 root 16:
17: //
1.1.1.7 root 18: // サブウィンドウ (基本クラス)
1.1 root 19: //
20:
1.1.1.11! root 21: //#define WINDOW_DEBUG 1
! 22:
! 23: #if defined(WINDOW_DEBUG)
! 24: #define DPRINTF(fmt...) printf(fmt)
! 25: #else
! 26: #define DPRINTF(fmt...) /**/
! 27: #endif
! 28:
1.1 root 29: // イベントテーブル
30: wxBEGIN_EVENT_TABLE(WXSubWindow, inherited)
31: EVT_CLOSE(WXSubWindow::OnClose)
32: wxEND_EVENT_TABLE()
33:
1.1.1.5 root 34: // コンストラクタ
1.1 root 35: WXSubWindow::WXSubWindow(wxWindow *parent, wxWindowID id, const wxString& name,
36: int style)
1.1.1.5 root 37: : inherited(parent, id, name, wxDefaultPosition, wxDefaultSize, style)
1.1 root 38: {
39: }
40:
41: // デストラクタ
42: WXSubWindow::~WXSubWindow()
43: {
44: }
45:
46: // クローズイベント
47: void
48: WXSubWindow::OnClose(wxCloseEvent& event)
49: {
50: // ウィンドウリストから自身を削除
1.1.1.9 root 51: auto mainframe = dynamic_cast<WXMainFrame*>(GetParent());
52: mainframe->DeleteWindow(this);
1.1 root 53: }
1.1.1.2 root 54:
1.1.1.7 root 55: // フォントサイズ変更
1.1.1.3 root 56: void
1.1.1.7 root 57: WXSubWindow::FontChanged()
1.1.1.3 root 58: {
1.1.1.7 root 59: // WXTextPanel 派生の子コントロールに対し FontChanged() を呼ぶ
60: for (auto child : GetChildren()) {
61: auto textpanel = dynamic_cast<WXTextPanel*>(child);
1.1.1.3 root 62: if (textpanel) {
1.1.1.7 root 63: textpanel->FontChanged();
1.1.1.3 root 64: }
65: }
66:
1.1.1.10 root 67: Fit();
1.1.1.7 root 68: }
69:
1.1.1.11! root 70: // 自前レイアウト方式を使うことを宣言する。
! 71: // ついでに必要な SetAutoLayout() も実行しておく。
! 72: // おそらくコンストラクタで使うことになるはず。
! 73: void
! 74: WXSubWindow::SetMyLayout()
! 75: {
! 76: my_layout = true;
! 77:
! 78: SetAutoLayout(true);
! 79: }
! 80:
! 81: // 中身の状況に応じてこのウィンドウの大きさを変更。
! 82: // 1) 自前方式か
! 83: // 2) このウィンドウに top sizer が指定されているか
! 84: // 3) 子コントロールが1つしかないか
! 85: // のいずれかの場合に使える。
1.1.1.10 root 86: //
1.1.1.11! root 87: // コントロールが複数あって上記のいずれでもない場合は、コントロールを
! 88: // どう配置するのか決定できないので、assert する。
1.1.1.7 root 89: void
1.1.1.10 root 90: WXSubWindow::Fit()
1.1.1.7 root 91: {
92: wxSize csize;
93:
1.1.1.11! root 94: if (my_layout) {
! 95: // 1) 自前方式なら継承先がサイズを知っている。
! 96: csize = DoMySizeHints();
! 97: assert(csize.x > 0);
! 98: assert(csize.y > 0);
1.1.1.7 root 99: } else {
1.1.1.11! root 100: auto *topsizer = GetSizer();
! 101: if (topsizer) {
! 102: // 2) Sizer があればそれがサイズを知っている。
! 103: csize = topsizer->ComputeFittingClientSize(this);
! 104: } else {
! 105: // 3) どちらでもない場合、子コントロールが1人なら対応出来る。
! 106: // これはネイティブの Fit() と等価のはず。
! 107: auto& children = GetChildren();
! 108: assert(children.GetCount() == 1);
! 109: auto child = children[0];
! 110: csize = child->GetSize();
! 111: }
1.1.1.7 root 112: }
113: SetClientSize(csize);
1.1.1.3 root 114: }
1.1.1.11! root 115:
! 116: // サイズが変わった場合に呼ばれて、子コントロールの再配置を行う。
! 117: bool
! 118: WXSubWindow::Layout()
! 119: {
! 120: if (my_layout) {
! 121: return MyLayout();
! 122: } else {
! 123: return inherited::Layout();
! 124: }
! 125: }
! 126:
! 127: // 自前方式の時の Layout()。
! 128: // 何度か呼び出されて仕事をしないと適切なサイズになってくれないため。
! 129: //
! 130: // Layout() は何かしたら true を返すので、ここもそれに倣う。
! 131: // MyLayout() が何かしたら true を返すので継承側は何もせずに true を返すこと。
! 132: // MyLayout() が false を返したら、継承側は子コントロールを配置してよい。
! 133: // その場合も呼び出し元には true を返すこと
! 134: // つまり、継承側はこうなるはず。
! 135: // bool Children::Layout() {
! 136: // if (MyLayout() == false) {
! 137: // ここで子コントロールを配置。
! 138: // }
! 139: // return true;
! 140: // }
! 141: bool
! 142: WXSubWindow::MyLayout()
! 143: {
! 144: wxSize client = GetClientSize();
! 145: const wxSize& win = GetSize();
! 146: const wxSize& border = win - client;
! 147:
! 148: if (border != prev_border) {
! 149: // ウィンドウマネージャ管轄のサイズが変わったので最小サイズを再設定。
! 150: my_layout_pass2 = true;
! 151: prev_border = border;
! 152: // ここでは出来ないのでこの関数を抜けた後 CallAfter 内で設定する。
! 153: CallAfter([this]() {
! 154: DoMySizeHints();
! 155: });
! 156: return true;
! 157:
! 158: } else if (my_layout_pass2) {
! 159: // SetSizeHints() 後に呼ばれるところ。
! 160: // なぜか設定したサイズと変わっている(ことがある?)ので、その場合は
! 161: // 仕方ないのでここで元の要求サイズに再設定する。
! 162: // ウィンドウマネージャによっては表示サイズが変わらない(?)ので
! 163: // Hide()/Show() で叩き起こすと直るようだ??。
! 164: my_layout_pass2 = false;
! 165: DPRINTF("%s ClientSize(%d,%d)->", __method__, client.x, client.y);
! 166: GetMySizeHints(&client, NULL, NULL, NULL);
! 167: DPRINTF("(%d,%d)\n", client.x, client.y);
! 168: SetClientSize(client);
! 169:
! 170: Hide();
! 171: Show();
! 172:
! 173: DPRINTF("%s done(pass2)\n", __method__);
! 174: return true;
! 175: }
! 176:
! 177: // ここまで来るとようやくコントロールを再配置を継承側で行える。
! 178: // それを示すため false を返す。
! 179: // wxTopLevelWindow::Layout() は何かすれば true、
! 180: // sizer がないか子コントロールが複数あって何も出来ることがない場合は
! 181: // false を返すと書いてあるので都合よく借りておく。
! 182: DPRINTF("%s done false\n", __method__);
! 183: return false;
! 184: }
! 185:
! 186: // SetSizeHints() を実行して、希望するクライアントサイズを返す。
! 187: // 自前方式に対応していない場合は何もせず wxDefaultSize を返す。
! 188: wxSize
! 189: WXSubWindow::DoMySizeHints()
! 190: {
! 191: wxSize newsize;
! 192: wxSize minsize;
! 193: wxSize maxsize;
! 194: wxSize incsize;
! 195:
! 196: if (GetMySizeHints(&newsize, &minsize, &maxsize, &incsize)) {
! 197: wxSize minwin = ClientToWindowSize(minsize);
! 198: wxSize maxwin = ClientToWindowSize(maxsize);
! 199: SetSizeHints(minwin, maxwin, incsize);
! 200: return newsize;
! 201: } else {
! 202: // 対応していない。
! 203: return wxDefaultSize;
! 204: }
! 205: }
! 206:
! 207: // 自前方式のサイズに関する情報を取得する。
! 208: // 継承先で用意すること。ここにあるのは継承しなかった時の何もしない版。
! 209: //
! 210: // 継承側はそれぞれ以下の値を書き戻して true を返す。
! 211: // *newsz は希望するクライアントサイズ。子コントロールの配置とサイズで決まる。
! 212: // *minsz は最小クライアントサイズ。指定しないなら (-1, -1)。
! 213: // *maxsz は最大クライアントサイズ。指定しないなら (-1, -1)。
! 214: // *incsz はウィンドウサイズ変更時の増減サイズ。
! 215: // newsz, minsz, maxsz, incsz はいずれも NULL でなければ代入する。
! 216: bool
! 217: WXSubWindow::GetMySizeHints(wxSize *newsz, wxSize *minsz, wxSize *maxsz,
! 218: wxSize *incsz)
! 219: {
! 220: return false;
! 221: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.