1 /*$
2 Copyright (C) 2013-2020 Azel.
3
4 This file is part of AzPainter.
5
6 AzPainter is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 AzPainter is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 $*/
19
20 /*****************************************
21 * mContainerView
22 *****************************************/
23
24 #include "mDef.h"
25 #include "mWidget.h"
26 #include "mEvent.h"
27 #include "mScrollBar.h"
28 #include "mWidget_pv.h"
29
30 #include "mContainerView.h"
31
32
33 /*********************//**
34
35 @defgroup containerview mContainerView
36 @brief コンテナを垂直スクロールできるビュー
37
38 - 内容ウィジェットはこのウィジェットの子として作成し、mContainerViewData::area にウィジェットポインタをセットする。
39
40 <h2>継承</h2>
41 mWidget \> mContainerView
42
43 @ingroup group_widget
44 @{
45
46 @file mContainerView.h
47
48 @struct mContainerView
49 @struct mContainerViewData
50 @enum MCONTAINERVIEW_STYLE
51
52 *************************/
53
54
55
56 /** スクロールバー、イベントハンドラ */
57
_scrollbar_evhandle(mWidget * wg,mEvent * ev)58 static int _scrollbar_evhandle(mWidget *wg,mEvent *ev)
59 {
60 //ホイールでスクロール
61
62 if(ev->type == MEVENT_SCROLL
63 && (ev->scr.dir == MEVENT_SCROLL_DIR_DOWN || ev->scr.dir == MEVENT_SCROLL_DIR_UP))
64 {
65 mScrollBar *scr = M_SCROLLBAR(wg);
66 mContainerView *p = M_CONTAINERVIEW(scr->wg.param);
67
68 if(mScrollBarMovePos(scr, (ev->scr.dir == MEVENT_SCROLL_DIR_UP)? -30: 30))
69 mWidgetMove(M_WIDGET(p->cv.area), 0, -(scr->sb.pos));
70
71 return 1;
72 }
73
74 return mScrollBarEventHandle(wg, ev);
75 }
76
77 /** スクロールバー操作時 */
78
_scrollbar_handle(mScrollBar * scrb,int pos,int flags)79 static void _scrollbar_handle(mScrollBar *scrb,int pos,int flags)
80 {
81 mContainerView *p = M_CONTAINERVIEW(scrb->wg.param);
82
83 if(flags & MSCROLLBAR_N_HANDLE_F_CHANGE)
84 mWidgetMove(M_WIDGET(p->cv.area), 0, -pos);
85 }
86
87 /** スクロール情報セット */
88
_set_scrollinfo(mContainerView * p)89 static void _set_scrollinfo(mContainerView *p)
90 {
91 mScrollBarSetStatus(p->cv.scrv, 0, (p->cv.area)? p->cv.area->hintH: 0, p->wg.h);
92 }
93
94 /** スクロールバーの表示/非表示
95 *
96 * @return 表示の有無が変化したか */
97
_showScrollBar(mContainerView * p)98 static mBool _showScrollBar(mContainerView *p)
99 {
100 int fscr;
101 mBool ret = FALSE;
102
103 if(p->cv.style & MCONTAINERVIEW_S_FIX_SCROLL)
104 fscr = 1;
105 else
106 fscr = (p->cv.area && p->cv.area->hintH > p->wg.h);
107
108 if(mWidgetIsVisible(M_WIDGET(p->cv.scrv)) != fscr)
109 {
110 mWidgetShow(M_WIDGET(p->cv.scrv), fscr);
111 ret = TRUE;
112 }
113
114 return ret;
115 }
116
117 /** レイアウト */
118
_layout_handle(mWidget * wg)119 static void _layout_handle(mWidget *wg)
120 {
121 mContainerView *p = M_CONTAINERVIEW(wg);
122 int fscr,h;
123
124 fscr = mWidgetIsVisible(M_WIDGET(p->cv.scrv));
125
126 //内容
127
128 if(p->cv.area)
129 {
130 /* 内容の高さの方が長ければ、内容の最大高さのサイズにする。
131 * ウィジェットの高さの方が大きければ、そのまま */
132
133 h = (p->cv.area)->hintH;
134
135 mWidgetMoveResize(p->cv.area,
136 0, -(p->cv.scrv)->sb.pos,
137 wg->w - (fscr? MSCROLLBAR_WIDTH: 0),
138 (h > wg->h)? h: wg->h);
139 }
140
141 //スクロールバー
142
143 if(fscr)
144 {
145 mWidgetMoveResize(M_WIDGET(p->cv.scrv),
146 wg->w - MSCROLLBAR_WIDTH, 0, MSCROLLBAR_WIDTH, wg->h);
147 }
148 }
149
150 /** サイズ変更時 */
151
_onsize_handle(mWidget * wg)152 static void _onsize_handle(mWidget *wg)
153 {
154 mContainerView *p = M_CONTAINERVIEW(wg);
155
156 _set_scrollinfo(p);
157
158 _showScrollBar(p);
159 }
160
161 /** 推奨サイズ計算 */
162
_calchint_handle(mWidget * wg)163 static void _calchint_handle(mWidget *wg)
164 {
165 mWidget *area = M_CONTAINERVIEW(wg)->cv.area;
166
167 //[!] 高さはセットしない
168
169 if(area)
170 {
171 __mWidgetCalcHint(area);
172
173 wg->hintW = area->hintW + MSCROLLBAR_WIDTH;
174 }
175 }
176
177
178 //========================
179 // main
180 //========================
181
182
183 /** 作成 */
184
mContainerViewNew(int size,mWidget * parent,uint32_t style)185 mContainerView *mContainerViewNew(int size,mWidget *parent,uint32_t style)
186 {
187 mContainerView *p;
188 mScrollBar *scr;
189
190 if(size < sizeof(mContainerView)) size = sizeof(mContainerView);
191
192 p = (mContainerView *)mWidgetNew(size, parent);
193 if(!p) return NULL;
194
195 p->wg.layout = _layout_handle;
196 p->wg.onSize = _onsize_handle;
197 p->wg.calcHint = _calchint_handle;
198 p->wg.draw = mWidgetHandleFunc_draw_drawBkgnd;
199
200 p->cv.style = style;
201
202 //スクロールバー
203
204 p->cv.scrv = scr = mScrollBarNew(0, M_WIDGET(p), MSCROLLBAR_S_VERT);
205
206 scr->wg.notifyTarget = MWIDGET_NOTIFYTARGET_PARENT;
207 scr->wg.param = (intptr_t)p;
208 scr->wg.fEventFilter |= MWIDGET_EVENTFILTER_SCROLL;
209 scr->wg.event = _scrollbar_evhandle;
210 scr->sb.handle = _scrollbar_handle;
211
212 return p;
213 }
214
215 /** 構成を行う
216 *
217 * 中身の状態が変わった時に手動で更新したい場合。\n
218 * mWidgetReLayout() を使う場合は実行しなくて良い。\n
219 * スクロールバーの有無の再判定と再レイアウトを行う。 */
220
mContainerViewConstruct(mContainerView * p)221 void mContainerViewConstruct(mContainerView *p)
222 {
223 /* 中身の高さが変わった場合があるので、常に再レイアウトを行う */
224
225 _showScrollBar(p);
226 _set_scrollinfo(p);
227
228 _layout_handle(M_WIDGET(p));
229 }
230
231 /* @} */
232