00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pgSliderBar.h"
00016 #include "pgMouseWatcherParameter.h"
00017 #include "clockObject.h"
00018 #include "throw_event.h"
00019 #include "config_pgui.h"
00020 #include "throw_event.h"
00021 #include "transformState.h"
00022 #include "mouseButton.h"
00023
00024 TypeHandle PGSliderBar::_type_handle;
00025
00026
00027
00028
00029
00030
00031 PGSliderBar::
00032 PGSliderBar(const string &name)
00033 : PGItem(name)
00034 {
00035 set_cull_callback();
00036
00037 _min_value = 0.0f;
00038 _max_value = 1.0f;
00039 set_scroll_size(0.01f);
00040 set_page_size(0.1f);
00041 _ratio = 0.0f;
00042 _resize_thumb = false;
00043 _manage_pieces = false;
00044 _axis.set(1.0f, 0.0f, 0.0f);
00045 _needs_remanage = false;
00046 _needs_recompute = true;
00047 _needs_reposition = false;
00048 _scroll_button_held = NULL;
00049 _mouse_button_page = false;
00050 _dragging = false;
00051 _thumb_width = 0.1f;
00052
00053 set_active(true);
00054 }
00055
00056
00057
00058
00059
00060
00061 PGSliderBar::
00062 ~PGSliderBar() {
00063 }
00064
00065
00066
00067
00068
00069
00070 PGSliderBar::
00071 PGSliderBar(const PGSliderBar ©) :
00072 PGItem(copy),
00073 _min_value(copy._min_value),
00074 _max_value(copy._max_value),
00075 _scroll_value(copy._scroll_value),
00076 _scroll_ratio(copy._scroll_ratio),
00077 _page_value(copy._page_value),
00078 _page_ratio(copy._page_ratio),
00079 _ratio(copy._ratio),
00080 _resize_thumb(copy._resize_thumb),
00081 _manage_pieces(copy._manage_pieces),
00082 _axis(copy._axis)
00083 {
00084 _needs_remanage = false;
00085 _needs_recompute = true;
00086 _scroll_button_held = NULL;
00087 _mouse_button_page = false;
00088 _dragging = false;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 PandaNode *PGSliderBar::
00100 make_copy() const {
00101 LightReMutexHolder holder(_lock);
00102 return new PGSliderBar(*this);
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112 void PGSliderBar::
00113 press(const MouseWatcherParameter ¶m, bool background) {
00114 LightReMutexHolder holder(_lock);
00115 if (param.has_mouse()) {
00116 _mouse_pos = param.get_mouse();
00117 }
00118 if (get_active() && param.get_button() == MouseButton::one()) {
00119 if (_needs_recompute) {
00120 recompute();
00121 }
00122
00123 if (_range_x != 0.0f) {
00124 _mouse_button_page = true;
00125 _scroll_button_held = NULL;
00126 advance_page();
00127 _next_advance_time =
00128 ClockObject::get_global_clock()->get_frame_time() + scroll_initial_delay;
00129 }
00130 }
00131 PGItem::press(param, background);
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141 void PGSliderBar::
00142 release(const MouseWatcherParameter ¶m, bool background) {
00143 LightReMutexHolder holder(_lock);
00144 if (MouseButton::is_mouse_button(param.get_button())) {
00145 _mouse_button_page = false;
00146 }
00147 if (_dragging) {
00148 end_drag();
00149 }
00150 PGItem::release(param, background);
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 void PGSliderBar::
00160 move(const MouseWatcherParameter ¶m) {
00161 LightReMutexHolder holder(_lock);
00162 _mouse_pos = param.get_mouse();
00163 if (_dragging) {
00164
00165
00166
00167
00168
00169 continue_drag();
00170 }
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 bool PGSliderBar::
00199 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00200 LightReMutexHolder holder(_lock);
00201 if (_manage_pieces && _needs_remanage) {
00202 remanage();
00203 }
00204 if (_needs_recompute) {
00205 recompute();
00206 }
00207
00208 if (_scroll_button_held != (PGItem *)NULL &&
00209 _next_advance_time <= ClockObject::get_global_clock()->get_frame_time()) {
00210 advance_scroll();
00211 }
00212
00213 if (_mouse_button_page &&
00214 _next_advance_time <= ClockObject::get_global_clock()->get_frame_time()) {
00215 advance_page();
00216 }
00217
00218 if (_needs_reposition) {
00219 reposition();
00220 }
00221
00222 return PGItem::cull_callback(trav, data);
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232 void PGSliderBar::
00233 xform(const LMatrix4 &mat) {
00234 LightReMutexHolder holder(_lock);
00235 PGItem::xform(mat);
00236 _axis = _axis * mat;
00237
00238
00239
00240 if (_thumb_button != (PGButton *)NULL) {
00241 _thumb_button->clear_transform();
00242 }
00243
00244 _needs_remanage = true;
00245 _needs_recompute = true;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255 void PGSliderBar::
00256 adjust() {
00257 LightReMutexHolder holder(_lock);
00258 string event = get_adjust_event();
00259 play_sound(event);
00260 throw_event(event);
00261
00262 if (has_notify()) {
00263 get_notify()->slider_bar_adjust(this);
00264 }
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 void PGSliderBar::
00282 setup_scroll_bar(bool vertical, PN_stdfloat length, PN_stdfloat width, PN_stdfloat bevel) {
00283 LightReMutexHolder holder(_lock);
00284 set_state(0);
00285 clear_state_def(0);
00286
00287 if (vertical) {
00288 set_frame(-width / 2.0f, width / 2.0f, -length / 2.0f, length / 2.0f);
00289 _axis = LVector3::rfu(0.0f, 0.0f, -1.0f);
00290 } else {
00291 set_frame(-length / 2.0f, length / 2.0f, -width / 2.0f, width / 2.0f);
00292 _axis = LVector3::rfu(1.0f, 0.0f, 0.0f);
00293 }
00294
00295 PGFrameStyle style;
00296 style.set_color(0.6f, 0.6f, 0.6f, 1.0f);
00297 style.set_type(PGFrameStyle::T_flat);
00298 set_frame_style(0, style);
00299
00300 style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
00301 style.set_type(PGFrameStyle::T_bevel_out);
00302 style.set_width(bevel, bevel);
00303
00304
00305
00306 if (_thumb_button != (PGButton *)NULL) {
00307 remove_child(_thumb_button);
00308 set_thumb_button(NULL);
00309 }
00310 if (_left_button != (PGButton *)NULL) {
00311 remove_child(_left_button);
00312 set_left_button(NULL);
00313 }
00314 if (_right_button != (PGButton *)NULL) {
00315 remove_child(_right_button);
00316 set_right_button(NULL);
00317 }
00318
00319 PT(PGButton) thumb = new PGButton("thumb");
00320 thumb->setup("", bevel);
00321 thumb->set_frame(-width / 2.0f, width / 2.0f,
00322 -width / 2.0f, width / 2.0f);
00323 add_child(thumb);
00324 set_thumb_button(thumb);
00325
00326 PT(PGButton) left = new PGButton("left");
00327 left->setup("", bevel);
00328 left->set_frame(-width / 2.0f, width / 2.0f,
00329 -width / 2.0f, width / 2.0f);
00330 left->set_transform(TransformState::make_pos(((width - length) / 2.0f) * _axis));
00331 add_child(left);
00332 set_left_button(left);
00333
00334 PT(PGButton) right = new PGButton("right");
00335 right->setup("", bevel);
00336 right->set_frame(-width / 2.0f, width / 2.0f,
00337 -width / 2.0f, width / 2.0f);
00338 right->set_transform(TransformState::make_pos(((length - width) / 2.0f) * _axis));
00339 add_child(right);
00340 set_right_button(right);
00341
00342 set_resize_thumb(true);
00343 set_manage_pieces(true);
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 void PGSliderBar::
00356 setup_slider(bool vertical, PN_stdfloat length, PN_stdfloat width, PN_stdfloat bevel) {
00357 LightReMutexHolder holder(_lock);
00358 set_state(0);
00359 clear_state_def(0);
00360
00361 if (vertical) {
00362 set_frame(-width / 2.0f, width / 2.0f, -length / 2.0f, length / 2.0f);
00363 _axis = LVector3::rfu(0.0f, 0.0f, -1.0f);
00364 } else {
00365 set_frame(-length / 2.0f, length / 2.0f, -width / 2.0f, width / 2.0f);
00366 _axis = LVector3::rfu(1.0f, 0.0f, 0.0f);
00367 }
00368
00369 PGFrameStyle style;
00370 style.set_color(0.6f, 0.6f, 0.6f, 1.0f);
00371 style.set_type(PGFrameStyle::T_flat);
00372 style.set_visible_scale(1.0f, 0.25f);
00373 style.set_width(bevel, bevel);
00374 set_frame_style(0, style);
00375
00376
00377
00378 if (_thumb_button != (PGButton *)NULL) {
00379 remove_child(_thumb_button);
00380 set_thumb_button(NULL);
00381 }
00382 if (_left_button != (PGButton *)NULL) {
00383 remove_child(_left_button);
00384 set_left_button(NULL);
00385 }
00386 if (_right_button != (PGButton *)NULL) {
00387 remove_child(_right_button);
00388 set_right_button(NULL);
00389 }
00390
00391 PT(PGButton) thumb = new PGButton("thumb");
00392 thumb->setup(" ", bevel);
00393 thumb->set_frame(-width / 4.0f, width / 4.0f,
00394 -width / 2.0f, width / 2.0f);
00395 add_child(thumb);
00396 set_thumb_button(thumb);
00397
00398 set_resize_thumb(false);
00399 set_manage_pieces(true);
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 void PGSliderBar::
00412 set_active(bool active) {
00413 LightReMutexHolder holder(_lock);
00414 PGItem::set_active(active);
00415
00416
00417 if (_thumb_button != (PGButton *)NULL) {
00418 _thumb_button->set_active(active);
00419 }
00420 if (_left_button != (PGButton *)NULL) {
00421 _left_button->set_active(active);
00422 }
00423 if (_right_button != (PGButton *)NULL) {
00424 _right_button->set_active(active);
00425 }
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435 void PGSliderBar::
00436 remanage() {
00437 LightReMutexHolder holder(_lock);
00438 _needs_remanage = false;
00439
00440 const LVecBase4 &frame = get_frame();
00441
00442 PN_stdfloat width, length;
00443 if (fabs(_axis[0]) > fabs(_axis[1] + _axis[2])) {
00444
00445 width = frame[3] - frame[2];
00446 length = frame[1] - frame[0];
00447
00448 } else {
00449
00450 width = frame[1] - frame[0];
00451 length = frame[3] - frame[2];
00452 }
00453
00454 LVector3 center = LVector3::rfu((frame[0] + frame[1]) / 2.0f,
00455 0.0f,
00456 (frame[2] + frame[3]) / 2.0f);
00457
00458 if (_left_button != (PGButton *)NULL) {
00459 _left_button->set_frame(-width / 2.0f, width / 2.0f,
00460 -width / 2.0f, width / 2.0f);
00461 _left_button->set_transform(TransformState::make_pos(center + ((width - length) / 2.0f) * _axis));
00462 }
00463
00464 if (_right_button != (PGButton *)NULL) {
00465 _right_button->set_frame(-width / 2.0f, width / 2.0f,
00466 -width / 2.0f, width / 2.0f);
00467 _right_button->set_transform(TransformState::make_pos(center + ((length - width) / 2.0f) * _axis));
00468 }
00469
00470 if (_thumb_button != (PGButton *)NULL) {
00471 _thumb_button->set_frame(-width / 2.0f, width / 2.0f,
00472 -width / 2.0f, width / 2.0f);
00473 _thumb_button->set_transform(TransformState::make_pos(center));
00474 }
00475
00476 recompute();
00477 }
00478
00479
00480
00481
00482
00483
00484
00485 void PGSliderBar::
00486 recompute() {
00487 LightReMutexHolder holder(_lock);
00488 _needs_recompute = false;
00489
00490 if (_min_value != _max_value) {
00491 _scroll_ratio = fabs(_scroll_value / (_max_value - _min_value));
00492 _page_ratio = fabs(_page_value / (_max_value - _min_value));
00493
00494 } else {
00495 _scroll_ratio = 0.0f;
00496 _page_ratio = 0.0f;
00497 }
00498
00499 if (!has_frame()) {
00500 _min_x = 0.0f;
00501 _max_x = 0.0f;
00502 _thumb_width = 0.0f;
00503 _range_x = 0.0f;
00504 _thumb_start.set(0.0f, 0.0f, 0.0f);
00505
00506 } else {
00507 LVecBase4 frame = get_frame();
00508 reduce_region(frame, _left_button);
00509 reduce_region(frame, _right_button);
00510
00511 if (fabs(_axis[0]) > fabs(_axis[1] + _axis[2])) {
00512
00513
00514 _min_x = frame[0];
00515 _max_x = frame[1];
00516
00517 PN_stdfloat trough_width = _max_x - _min_x;
00518
00519 if (_thumb_button == (PGButton *)NULL) {
00520 _thumb_width = 0.0f;
00521 _range_x = 0.0f;
00522 _thumb_start.set(0.0f, 0.0f, 0.0f);
00523
00524 } else {
00525 const LVecBase4 &thumb_frame = _thumb_button->get_frame();
00526
00527 if (_resize_thumb) {
00528
00529
00530 _thumb_width = trough_width * min((PN_stdfloat)1.0, _page_ratio);
00531 _thumb_button->set_frame(-_thumb_width / 2.0f, _thumb_width / 2.0f,
00532 thumb_frame[2], thumb_frame[3]);
00533 } else {
00534
00535
00536 _thumb_width = thumb_frame[1] - thumb_frame[0];
00537 }
00538
00539 _range_x = trough_width - _thumb_width;
00540
00541 if (_axis[0] >= 0.0f) {
00542
00543 _thumb_start = (_min_x - thumb_frame[0]) * _axis;
00544 } else {
00545
00546 _thumb_start = (thumb_frame[1] - _max_x) * _axis;
00547 }
00548 _thumb_start += LVector3::rfu(0.0f, 0.0f, (frame[2] + frame[3]) / 2.0f);
00549 }
00550
00551 } else {
00552
00553
00554
00555 _min_x = frame[2];
00556 _max_x = frame[3];
00557
00558 PN_stdfloat trough_width = _max_x - _min_x;
00559
00560 if (_thumb_button == (PGButton *)NULL) {
00561 _thumb_width = 0.0f;
00562 _range_x = 0.0f;
00563 _thumb_start.set(0.0f, 0.0f, 0.0f);
00564
00565 } else {
00566 const LVecBase4 &thumb_frame = _thumb_button->get_frame();
00567
00568 if (_resize_thumb) {
00569
00570
00571 _thumb_width = trough_width * min((PN_stdfloat)1.0, _page_ratio);
00572 _thumb_button->set_frame(thumb_frame[0], thumb_frame[1],
00573 -_thumb_width / 2.0f, _thumb_width / 2.0f);
00574 } else {
00575
00576
00577 _thumb_width = thumb_frame[3] - thumb_frame[2];
00578 }
00579
00580 _range_x = trough_width - _thumb_width;
00581
00582 if (_axis[1] >= 0.0f && _axis[2] >= 0.0f) {
00583
00584 _thumb_start = (_min_x - thumb_frame[2]) * _axis;
00585 } else {
00586
00587 _thumb_start = (thumb_frame[3] - _max_x) * _axis;
00588 }
00589 _thumb_start += LVector3::rfu((frame[0] + frame[1]) / 2.0f, 0.0f, 0.0f);
00590 }
00591 }
00592 }
00593
00594 reposition();
00595 }
00596
00597
00598
00599
00600
00601
00602 void PGSliderBar::
00603 frame_changed() {
00604 LightReMutexHolder holder(_lock);
00605 PGItem::frame_changed();
00606 _needs_remanage = true;
00607 _needs_recompute = true;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616 void PGSliderBar::
00617 item_transform_changed(PGItem *) {
00618 LightReMutexHolder holder(_lock);
00619 _needs_recompute = true;
00620 }
00621
00622
00623
00624
00625
00626
00627
00628 void PGSliderBar::
00629 item_frame_changed(PGItem *) {
00630 LightReMutexHolder holder(_lock);
00631 _needs_recompute = true;
00632 }
00633
00634
00635
00636
00637
00638
00639
00640 void PGSliderBar::
00641 item_draw_mask_changed(PGItem *) {
00642 LightReMutexHolder holder(_lock);
00643 _needs_recompute = true;
00644 }
00645
00646
00647
00648
00649
00650
00651
00652 void PGSliderBar::
00653 item_press(PGItem *item, const MouseWatcherParameter ¶m) {
00654 LightReMutexHolder holder(_lock);
00655 if (param.has_mouse()) {
00656 _mouse_pos = param.get_mouse();
00657 }
00658 if (item == _left_button || item == _right_button) {
00659 _scroll_button_held = item;
00660 _mouse_button_page = false;
00661 advance_scroll();
00662 _next_advance_time =
00663 ClockObject::get_global_clock()->get_frame_time() + scroll_initial_delay;
00664
00665 } else if (item == _thumb_button) {
00666 _scroll_button_held = NULL;
00667 begin_drag();
00668 }
00669 }
00670
00671
00672
00673
00674
00675
00676
00677 void PGSliderBar::
00678 item_release(PGItem *item, const MouseWatcherParameter &) {
00679 LightReMutexHolder holder(_lock);
00680 if (item == _scroll_button_held) {
00681 _scroll_button_held = NULL;
00682
00683 } else if (item == _thumb_button) {
00684 _scroll_button_held = NULL;
00685 if (_dragging) {
00686 end_drag();
00687 }
00688 }
00689 }
00690
00691
00692
00693
00694
00695
00696
00697 void PGSliderBar::
00698 item_move(PGItem *item, const MouseWatcherParameter ¶m) {
00699 LightReMutexHolder holder(_lock);
00700 _mouse_pos = param.get_mouse();
00701 if (item == _thumb_button) {
00702 if (_dragging) {
00703 continue_drag();
00704 }
00705 }
00706 }
00707
00708
00709
00710
00711
00712
00713
00714
00715 void PGSliderBar::
00716 reposition() {
00717 _needs_reposition = false;
00718
00719 PN_stdfloat t = get_ratio();
00720
00721 if (_thumb_button != (PGButton *)NULL) {
00722 LPoint3 pos = (t * _range_x) * _axis + _thumb_start;
00723 CPT(TransformState) transform = TransformState::make_pos(pos);
00724 CPT(TransformState) orig_transform = _thumb_button->get_transform();
00725
00726
00727
00728 if (transform == orig_transform) {
00729
00730 } else if (*transform < *orig_transform || *orig_transform < *transform) {
00731 _thumb_button->set_transform(transform);
00732 }
00733 }
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743 void PGSliderBar::
00744 advance_scroll() {
00745 if (_scroll_button_held == _left_button) {
00746 internal_set_ratio(max(_ratio - _scroll_ratio, (PN_stdfloat)0.0));
00747
00748 } else if (_scroll_button_held == _right_button) {
00749 internal_set_ratio(min(_ratio + _scroll_ratio, (PN_stdfloat)1.0));
00750 }
00751
00752 _next_advance_time =
00753 ClockObject::get_global_clock()->get_frame_time() + scroll_continued_delay;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763 void PGSliderBar::
00764 advance_page() {
00765
00766
00767 LPoint3 mouse = mouse_to_local(_mouse_pos) - _thumb_start;
00768 PN_stdfloat target_ratio = mouse.dot(_axis) / _range_x;
00769
00770 PN_stdfloat t;
00771 if (target_ratio < _ratio) {
00772 t = max(_ratio - _page_ratio + _scroll_ratio, target_ratio);
00773
00774 } else {
00775 t = min(_ratio + _page_ratio - _scroll_ratio, target_ratio);
00776 }
00777 internal_set_ratio(t);
00778 if (t == target_ratio) {
00779
00780
00781 begin_drag();
00782 }
00783
00784 _next_advance_time =
00785 ClockObject::get_global_clock()->get_frame_time() + scroll_continued_delay;
00786 }
00787
00788
00789
00790
00791
00792
00793
00794 void PGSliderBar::
00795 begin_drag() {
00796 if (_needs_recompute) {
00797 recompute();
00798 }
00799 if (_range_x != 0.0f) {
00800 PN_stdfloat current_x = mouse_to_local(_mouse_pos).dot(_axis);
00801 _drag_start_x = current_x - get_ratio() * _range_x;
00802 _dragging = true;
00803 }
00804 }
00805
00806
00807
00808
00809
00810
00811
00812 void PGSliderBar::
00813 continue_drag() {
00814 if (_needs_recompute) {
00815 recompute();
00816 }
00817 if (_range_x != 0.0f) {
00818 PN_stdfloat current_x = mouse_to_local(_mouse_pos).dot(_axis);
00819 internal_set_ratio((current_x - _drag_start_x) / _range_x);
00820 }
00821 }
00822
00823
00824
00825
00826
00827
00828 void PGSliderBar::
00829 end_drag() {
00830 _dragging = false;
00831 }