00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pgScrollFrame.h"
00016
00017 TypeHandle PGScrollFrame::_type_handle;
00018
00019
00020
00021
00022
00023
00024 PGScrollFrame::
00025 PGScrollFrame(const string &name) : PGVirtualFrame(name)
00026 {
00027 set_cull_callback();
00028
00029 _needs_remanage = false;
00030 _needs_recompute_canvas = false;
00031 _needs_recompute_clip = false;
00032 _has_virtual_frame = false;
00033 _virtual_frame.set(0.0f, 0.0f, 0.0f, 0.0f);
00034 _manage_pieces = false;
00035 _auto_hide = false;
00036 _horizontal_slider = NULL;
00037 _vertical_slider = NULL;
00038 }
00039
00040
00041
00042
00043
00044
00045 PGScrollFrame::
00046 ~PGScrollFrame() {
00047 set_horizontal_slider(NULL);
00048 set_vertical_slider(NULL);
00049 }
00050
00051
00052
00053
00054
00055
00056 PGScrollFrame::
00057 PGScrollFrame(const PGScrollFrame ©) :
00058 PGVirtualFrame(copy),
00059 _has_virtual_frame(copy._has_virtual_frame),
00060 _virtual_frame(copy._virtual_frame),
00061 _manage_pieces(copy._manage_pieces),
00062 _auto_hide(copy._auto_hide)
00063 {
00064 _needs_remanage = false;
00065 _needs_recompute_canvas = true;
00066 _needs_recompute_clip = true;
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 PandaNode *PGScrollFrame::
00078 make_copy() const {
00079 LightReMutexHolder holder(_lock);
00080 return new PGScrollFrame(*this);
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 bool PGScrollFrame::
00109 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00110 LightReMutexHolder holder(_lock);
00111 if (_manage_pieces && _needs_remanage) {
00112 remanage();
00113 }
00114 if (_needs_recompute_clip) {
00115 recompute_clip();
00116 }
00117 if (_needs_recompute_canvas) {
00118 recompute_canvas();
00119 }
00120 return PGVirtualFrame::cull_callback(trav, data);
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130 void PGScrollFrame::
00131 xform(const LMatrix4 &mat) {
00132 LightReMutexHolder holder(_lock);
00133 PGVirtualFrame::xform(mat);
00134
00135 _needs_remanage = true;
00136 _needs_recompute_clip = true;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145 void PGScrollFrame::
00146 setup(PN_stdfloat width, PN_stdfloat height,
00147 PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top,
00148 PN_stdfloat slider_width, PN_stdfloat bevel) {
00149 LightReMutexHolder holder(_lock);
00150 set_state(0);
00151 clear_state_def(0);
00152
00153 set_frame(0, width, 0, height);
00154
00155 PGFrameStyle style;
00156 style.set_width(bevel, bevel);
00157
00158 style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
00159 style.set_type(PGFrameStyle::T_ridge);
00160 set_frame_style(0, style);
00161
00162 set_clip_frame(bevel, width - bevel,
00163 bevel, height - bevel);
00164
00165 set_virtual_frame(left, right, bottom, top);
00166
00167
00168
00169 if (_horizontal_slider != (PGSliderBar *)NULL) {
00170 remove_child(_horizontal_slider);
00171 set_horizontal_slider(NULL);
00172 }
00173 if (_vertical_slider != (PGSliderBar *)NULL) {
00174 remove_child(_vertical_slider);
00175 set_vertical_slider(NULL);
00176 }
00177
00178
00179 PT(PGSliderBar) horizontal_slider = new PGSliderBar("horizontal");
00180 horizontal_slider->setup_scroll_bar(false, width - slider_width - bevel * 2, slider_width, bevel);
00181 horizontal_slider->set_transform(TransformState::make_pos(LVector3::rfu(width / 2.0f - slider_width / 2.0f, 0, slider_width / 2.0f + bevel)));
00182 add_child(horizontal_slider);
00183 set_horizontal_slider(horizontal_slider);
00184
00185 PT(PGSliderBar) vertical_slider = new PGSliderBar("vertical");
00186 vertical_slider->setup_scroll_bar(true, width - slider_width - bevel * 2, slider_width, bevel);
00187 add_child(vertical_slider);
00188 vertical_slider->set_transform(TransformState::make_pos(LVector3::rfu(width - slider_width / 2.0f - bevel, 0, width / 2.0f + slider_width / 2.0f)));
00189 set_vertical_slider(vertical_slider);
00190
00191 set_manage_pieces(true);
00192 set_auto_hide(true);
00193 }
00194
00195
00196
00197
00198
00199
00200
00201 void PGScrollFrame::
00202 remanage() {
00203 LightReMutexHolder holder(_lock);
00204 _needs_remanage = false;
00205
00206 const LVecBase4 &frame = get_frame();
00207 LVecBase4 clip = get_frame_style(get_state()).get_internal_frame(frame);
00208
00209
00210
00211 bool got_horizontal = false;
00212 PN_stdfloat horizontal_width = 0.0f;
00213 if (_horizontal_slider != (PGSliderBar *)NULL) {
00214 got_horizontal = true;
00215 const LVecBase4 &slider_frame = _horizontal_slider->get_frame();
00216 horizontal_width = slider_frame[3] - slider_frame[2];
00217 }
00218
00219 bool got_vertical = false;
00220 PN_stdfloat vertical_width = 0.0f;
00221 if (_vertical_slider != (PGSliderBar *)NULL) {
00222 got_vertical = true;
00223 const LVecBase4 &slider_frame = _vertical_slider->get_frame();
00224 vertical_width = slider_frame[1] - slider_frame[0];
00225 }
00226
00227 if (_auto_hide) {
00228
00229
00230
00231 PN_stdfloat clip_width = clip[1] - clip[0];
00232 PN_stdfloat clip_height = clip[3] - clip[2];
00233
00234
00235 const LVecBase4 &virtual_frame = get_virtual_frame();
00236 PN_stdfloat virtual_width = virtual_frame[1] - virtual_frame[0];
00237 PN_stdfloat virtual_height = virtual_frame[3] - virtual_frame[2];
00238
00239 if (virtual_width <= clip_width &&
00240 virtual_height <= clip_height) {
00241
00242 got_horizontal = false;
00243 got_vertical = false;
00244
00245 } else {
00246 if (virtual_width <= clip_width - vertical_width) {
00247
00248 got_horizontal = false;
00249 }
00250
00251 if (virtual_height <= clip_height - horizontal_width) {
00252
00253 got_vertical = false;
00254
00255
00256 if (virtual_width <= clip_width) {
00257 got_horizontal = false;
00258 }
00259 }
00260 }
00261
00262
00263 if (_horizontal_slider != (PGSliderBar *)NULL) {
00264 if (got_horizontal) {
00265 _horizontal_slider->set_overall_hidden(false);
00266 } else {
00267 _horizontal_slider->set_overall_hidden(true);
00268 _horizontal_slider->set_ratio(0.0f);
00269 horizontal_width = 0.0f;
00270 }
00271 }
00272 if (_vertical_slider != (PGSliderBar *)NULL) {
00273 if (got_vertical) {
00274 _vertical_slider->set_overall_hidden(false);
00275 } else {
00276 _vertical_slider->set_overall_hidden(true);
00277 _vertical_slider->set_ratio(0.0f);
00278 vertical_width = 0.0f;
00279 }
00280 }
00281
00282
00283
00284
00285 _needs_remanage = false;
00286 }
00287
00288
00289 if (got_horizontal && _horizontal_slider->is_overall_hidden()) {
00290 got_horizontal = false;
00291 horizontal_width = 0.0f;
00292 }
00293 if (got_vertical && _vertical_slider->is_overall_hidden()) {
00294 got_vertical = false;
00295 vertical_width = 0.0f;
00296 }
00297
00298 if (got_horizontal) {
00299 _horizontal_slider->set_frame(clip[0], clip[1] - vertical_width,
00300 clip[2], clip[2] + horizontal_width);
00301 _horizontal_slider->clear_transform();
00302 }
00303 if (got_vertical) {
00304 _vertical_slider->set_frame(clip[1] - vertical_width, clip[1],
00305 clip[2] + horizontal_width, clip[3]);
00306 _vertical_slider->clear_transform();
00307 }
00308
00309
00310 recompute();
00311 }
00312
00313
00314
00315
00316
00317
00318 void PGScrollFrame::
00319 frame_changed() {
00320 LightReMutexHolder holder(_lock);
00321 PGVirtualFrame::frame_changed();
00322 _needs_remanage = true;
00323 _needs_recompute_clip = true;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332 void PGScrollFrame::
00333 item_transform_changed(PGItem *) {
00334 LightReMutexHolder holder(_lock);
00335 _needs_recompute_clip = true;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344 void PGScrollFrame::
00345 item_frame_changed(PGItem *) {
00346 LightReMutexHolder holder(_lock);
00347 _needs_recompute_clip = true;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356 void PGScrollFrame::
00357 item_draw_mask_changed(PGItem *) {
00358 LightReMutexHolder holder(_lock);
00359 _needs_remanage = true;
00360 _needs_recompute_clip = true;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 void PGScrollFrame::
00370 slider_bar_adjust(PGSliderBar *) {
00371 LightReMutexHolder holder(_lock);
00372 _needs_recompute_canvas = true;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381 void PGScrollFrame::
00382 recompute_clip() {
00383 LightReMutexHolder holder(_lock);
00384 _needs_recompute_clip = false;
00385 _needs_recompute_canvas = true;
00386
00387
00388 LVecBase4 clip = get_frame_style(get_state()).get_internal_frame(get_frame());
00389 reduce_region(clip, _horizontal_slider);
00390 reduce_region(clip, _vertical_slider);
00391
00392 set_clip_frame(clip);
00393
00394 if (_horizontal_slider != (PGSliderBar *)NULL) {
00395 _horizontal_slider->set_page_size((clip[1] - clip[0]) / (_virtual_frame[1] - _virtual_frame[0]));
00396 }
00397 if (_vertical_slider != (PGSliderBar *)NULL) {
00398 _vertical_slider->set_page_size((clip[3] - clip[2]) / (_virtual_frame[3] - _virtual_frame[2]));
00399 }
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409 void PGScrollFrame::
00410 recompute_canvas() {
00411 LightReMutexHolder holder(_lock);
00412 _needs_recompute_canvas = false;
00413
00414 const LVecBase4 &clip = get_clip_frame();
00415
00416 PN_stdfloat x = interpolate_canvas(clip[0], clip[1],
00417 _virtual_frame[0], _virtual_frame[1],
00418 _horizontal_slider);
00419
00420 PN_stdfloat y = interpolate_canvas(clip[3], clip[2],
00421 _virtual_frame[3], _virtual_frame[2],
00422 _vertical_slider);
00423
00424 get_canvas_node()->set_transform(TransformState::make_pos(LVector3::rfu(x, 0, y)));
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434 PN_stdfloat PGScrollFrame::
00435 interpolate_canvas(PN_stdfloat clip_min, PN_stdfloat clip_max,
00436 PN_stdfloat canvas_min, PN_stdfloat canvas_max,
00437 PGSliderBar *slider_bar) {
00438 LightReMutexHolder holder(_lock);
00439 PN_stdfloat t = 0.0f;
00440 if (slider_bar != (PGSliderBar *)NULL) {
00441 t = slider_bar->get_ratio();
00442 }
00443
00444 PN_stdfloat min = clip_min - canvas_min;
00445 PN_stdfloat max = clip_max - canvas_max;
00446
00447 return min + t * (max - min);
00448 }