ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC/UI.pm
(Generate patch)

Comparing deliantra/Deliantra-Client/DC/UI.pm (file contents):
Revision 1.185 by root, Mon May 8 17:23:08 2006 UTC vs.
Revision 1.192 by root, Tue May 9 22:49:32 2006 UTC

232 $self->{y} = $y; 232 $self->{y} = $y;
233 $self->update; 233 $self->update;
234 } 234 }
235 235
236 if ($self->{w} != $w || $self->{h} != $h) { 236 if ($self->{w} != $w || $self->{h} != $h) {
237 $self->{w} = $w; 237 $CFClient::UI::ROOT->{size_alloc}{$self} = [$self, $w, $h];
238 $self->{h} = $h;
239
240 $self->size_allocate ($w, $h);
241 $self->update;
242 $self->emit (size_allocate => $w, $h);
243 } 238 }
244} 239}
245 240
246sub size_allocate { 241sub size_allocate {
247 # nothing to be done 242 # nothing to be done
255 my ($self) = @_; 250 my ($self) = @_;
256 251
257 $_->reconfigure 252 $_->reconfigure
258 for $self->children; 253 for $self->children;
259 254
260 $_->check_size; 255 $self->check_size;
256 $CFClient::UI::ROOT->{size_alloc}{$self} = [$self, $self->{w}, $self->{h}];
257 $self->update;
261} 258}
262 259
263sub set_max_size { 260sub set_max_size {
264 my ($self, $w, $h) = @_; 261 my ($self, $w, $h) = @_;
265 262
266 delete $self->{max_w}; $self->{max_w} = $w if $w; 263 delete $self->{max_w}; $self->{max_w} = $w if $w;
267 delete $self->{max_h}; $self->{max_h} = $h if $h; 264 delete $self->{max_h}; $self->{max_h} = $h if $h;
268}
269
270# return top left coordinates
271sub _topleft {
272 my ($self, $x, $y) = @_;
273
274 $self->{parent}
275 or Carp::confess "no parent widget in _topleft\n";#d#
276
277 $self->{parent}->_topleft ($x + $self->{x}, $y + $self->{y});
278} 265}
279 266
280# translate global coordinates to local coordinate system 267# translate global coordinates to local coordinate system
281sub coord2local { 268sub coord2local {
282 my ($self, $x, $y) = @_; 269 my ($self, $x, $y) = @_;
283 270
284 my ($X, $Y) = $self->_topleft; 271 $self->{parent}->coord2local ($x - $self->{x}, $y - $self->{y})
285 ($x - $X, $y - $Y)
286} 272}
287 273
288# translate local coordinates to global coordinate system 274# translate local coordinates to global coordinate system
289sub coord2global { 275sub coord2global {
290 my ($self, $x, $y) = @_; 276 my ($self, $x, $y) = @_;
291 277
292 my ($X, $Y) = $self->_topleft; 278 $self->{parent}->coord2global ($x + $self->{x}, $y + $self->{y})
293 ($x + $X, $y + $Y)
294} 279}
295 280
296sub focus_in { 281sub focus_in {
297 my ($self) = @_; 282 my ($self) = @_;
298 283
395} 380}
396 381
397sub set_parent { 382sub set_parent {
398 my ($self, $parent) = @_; 383 my ($self, $parent) = @_;
399 384
385 $self->{_tree_depth} = $parent->{_tree_depth} + 1;
400 Scalar::Util::weaken ($self->{parent} = $parent); 386 Scalar::Util::weaken ($self->{parent} = $parent);
401} 387}
402 388
403sub check_size { 389sub check_size {
404 my ($self) = @_; 390 my ($self) = @_;
405 391
406 $self->{parent} 392 $CFClient::UI::ROOT->{check_size}{$self} = $self;
407 or return 1;
408
409 my ($w, $h) = $self->{user_w} && $self->{user_h}
410 ? @$self{qw(user_w user_h)}
411 : $self->size_request;
412
413 if ($w != $self->{req_w} || $h != $self->{req_h}) {
414 $self->{req_w} = $w;
415 $self->{req_h} = $h;
416
417 $self->{parent}->check_size
418 or $self->size_allocate (
419 (List::Util::max $self->{w}, $w),
420 (List::Util::max $self->{h}, $h),
421 );
422
423 1
424 } else {
425 0
426 }
427} 393}
428 394
429sub update { 395sub update {
430 my ($self) = @_; 396 my ($self) = @_;
431 397
528 494
529 $self 495 $self
530} 496}
531 497
532sub add { 498sub add {
533 my ($self, $child) = @_; 499 my ($self, @widgets) = @_;
534 500
535 $child->set_parent ($self); 501 $_->set_parent ($self)
502 for @widgets;
536 503
537 use sort 'stable'; 504 use sort 'stable';
538 505
539 $self->{children} = [ 506 $self->{children} = [
540 sort { $a->{z} <=> $b->{z} } 507 sort { $a->{z} <=> $b->{z} }
541 @{$self->{children}}, $child 508 @{$self->{children}}, @widgets
542 ]; 509 ];
543 510
544 $child->check_size; 511 $_->check_size
512 for @widgets;
513
545 $self->update; 514 $self->update;
546} 515}
547 516
548sub children { 517sub children {
549 @{ $_[0]{children} } 518 @{ $_[0]{children} }
739 $self->{view_y} = int $y; 708 $self->{view_y} = int $y;
740 709
741 $self->update; 710 $self->update;
742} 711}
743 712
744# hmm, this does not work for topleft of $self... but we should not aks for that 713# hmm, this does not work for topleft of $self... but we should not ask for that
745sub _topleft { 714sub coord2local {
746 my ($self, $x, $y) = @_; 715 my ($self, $x, $y) = @_;
747 716
748 $self->SUPER::_topleft ($x - $self->{view_x}, $y - $self->{view_y}) 717 $self->SUPER::coord2local ($x + $self->{view_x}, $y + $self->{view_y})
718}
719
720sub coord2global {
721 my ($self, $x, $y) = @_;
722
723 $x = List::Util::min $self->{w}, $x - $self->{view_x};
724 $y = List::Util::min $self->{h}, $y - $self->{view_y};
725
726 $self->SUPER::coord2global ($x, $y)
749} 727}
750 728
751sub find_widget { 729sub find_widget {
752 my ($self, $x, $y) = @_; 730 my ($self, $x, $y) = @_;
753 731
1322 1300
1323 delete $self->{texture}; 1301 delete $self->{texture};
1324 $self->SUPER::update; 1302 $self->SUPER::update;
1325} 1303}
1326 1304
1327sub reconfigure {
1328 my ($self) = @_;
1329
1330 delete $self->{texture};
1331}
1332
1333sub set_text { 1305sub set_text {
1334 my ($self, $text) = @_; 1306 my ($self, $text) = @_;
1335 1307
1336 return if $self->{text} eq "T$text"; 1308 return if $self->{text} eq "T$text";
1337 $self->{text} = "T$text"; 1309 $self->{text} = "T$text";
1338 1310
1339 $self->{layout}->set_text ($text); 1311 $self->{layout}->set_text ($text);
1340 1312
1341 delete $self->{texture};
1342 $self->update; 1313 $self->update;
1343 $self->check_size; 1314 $self->check_size;
1344} 1315}
1345 1316
1346sub set_markup { 1317sub set_markup {
1349 return if $self->{text} eq "M$markup"; 1320 return if $self->{text} eq "M$markup";
1350 $self->{text} = "M$markup"; 1321 $self->{text} = "M$markup";
1351 1322
1352 $self->{layout}->set_markup ($markup); 1323 $self->{layout}->set_markup ($markup);
1353 1324
1354 delete $self->{texture};
1355 $self->update; 1325 $self->update;
1356 $self->check_size; 1326 $self->check_size;
1357} 1327}
1358 1328
1359sub size_request { 1329sub size_request {
1390sub set_fontsize { 1360sub set_fontsize {
1391 my ($self, $fontsize) = @_; 1361 my ($self, $fontsize) = @_;
1392 1362
1393 $self->{fontsize} = $fontsize; 1363 $self->{fontsize} = $fontsize;
1394 delete $self->{texture}; 1364 delete $self->{texture};
1365
1366 $self->update;
1395 $self->check_size; 1367 $self->check_size;
1396 $self->update;
1397} 1368}
1398 1369
1399sub _draw { 1370sub _draw {
1400 my ($self) = @_; 1371 my ($self) = @_;
1401 1372
2501 } 2472 }
2502} 2473}
2503 2474
2504############################################################################# 2475#############################################################################
2505 2476
2506package CFClient::UI::Menu; 2477package CFClient::UI::InventoryItem;
2507 2478
2508our @ISA = CFClient::UI::FancyFrame::; 2479our @ISA = CFClient::UI::HBox::;
2509
2510use CFClient::OpenGL;
2511 2480
2512sub new { 2481sub new {
2513 my $class = shift; 2482 my $class = shift;
2514 2483
2515 my $self = $class->SUPER::new (
2516 items => [],
2517 z => 100,
2518 @_,
2519 );
2520
2521 $self->add ($self->{vbox} = new CFClient::UI::VBox);
2522
2523 for my $item (@{ $self->{items} }) {
2524 my ($widget, $cb) = @$item;
2525
2526 # handle various types of items, only text for now
2527 if (!ref $widget) {
2528 $widget = new CFClient::UI::Label
2529 can_hover => 1,
2530 can_events => 1,
2531 text => $widget;
2532 }
2533
2534 $self->{item}{$widget} = $item;
2535
2536 $self->{vbox}->add ($widget);
2537 }
2538
2539 $self
2540}
2541
2542# popup given the event (must be a mouse button down event currently)
2543sub popup {
2544 my ($self, $ev) = @_;
2545
2546 $self->emit ("popdown");
2547
2548 # maybe save $GRAB? must be careful about events...
2549 $GRAB = $self;
2550 $self->{button} = $ev->{button};
2551
2552 $self->show;
2553 $self->move ($ev->{x} - $self->{w} * 0.5, $ev->{y} - $self->{h} * 0.5);
2554}
2555
2556sub mouse_motion {
2557 my ($self, $ev, $x, $y) = @_;
2558
2559 # TODO: should use vbox->find_widget or so
2560 $HOVER = $ROOT->find_widget ($ev->{x}, $ev->{y});
2561 $self->{hover} = $self->{item}{$HOVER};
2562}
2563
2564sub button_up {
2565 my ($self, $ev, $x, $y) = @_;
2566
2567 if ($ev->{button} == $self->{button}) {
2568 undef $GRAB;
2569 $self->hide;
2570
2571 $self->emit ("popdown");
2572 $self->{hover}[1]->() if $self->{hover};
2573 }
2574}
2575
2576#############################################################################
2577
2578package CFClient::UI::Root;
2579
2580our @ISA = CFClient::UI::Container::;
2581
2582use CFClient::OpenGL;
2583
2584sub check_size {
2585 my ($self) = @_;
2586
2587 $self->configure (0, 0, $::WIDTH, $::HEIGHT);
2588}
2589
2590sub size_request {
2591 ($::WIDTH, $::HEIGHT)
2592}
2593
2594sub configure {
2595 my ($self, $x, $y, $w, $h) = @_;
2596
2597 $self->SUPER::configure ($x, $y, $w, $h);
2598
2599 for my $child (@{$self->{children}}) {
2600 my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)};
2601
2602 $X = List::Util::max 0, List::Util::min $w - $W, $X;
2603 $Y = List::Util::max 0, List::Util::min $h - $H, $Y;
2604 $child->configure ($X, $Y, $W,$H);
2605 }
2606}
2607
2608sub _topleft {
2609 my ($self, $x, $y) = @_;
2610
2611 ($x, $y)
2612}
2613
2614sub update {
2615 my ($self) = @_;
2616
2617 $self->check_size;
2618 ::refresh ();
2619}
2620
2621sub add {
2622 my ($self, $child) = @_;
2623
2624 # integerize window positions
2625 $child->{x} = int $child->{x};
2626 $child->{y} = int $child->{y};
2627
2628 $self->SUPER::add ($child);
2629}
2630
2631sub on_refresh {
2632 my ($self, $id, $cb) = @_;
2633
2634 $self->{refresh_hook}{$id} = $cb;
2635}
2636
2637sub draw {
2638 my ($self) = @_;
2639
2640 while (my $rcb = delete $self->{refresh_hook}) {
2641 $_->() for values %$rcb;
2642 }
2643
2644 glViewport 0, 0, $::WIDTH, $::HEIGHT;
2645 glClearColor +($::CFG->{fow_intensity}) x 3, 1;
2646 glClear GL_COLOR_BUFFER_BIT;
2647
2648 glMatrixMode GL_PROJECTION;
2649 glLoadIdentity;
2650 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000 , 10000;
2651 glMatrixMode GL_MODELVIEW;
2652 glLoadIdentity;
2653
2654 $self->_draw;
2655}
2656
2657#############################################################################
2658
2659package CFClient::UI::InventoryItem;
2660
2661our @ISA = CFClient::UI::HBox::;
2662
2663sub new {
2664 my $class = shift;
2665
2666 my %args = @_; 2484 my %args = @_;
2667 2485
2668 my $item = $args{item}; 2486 my $item = delete $args{item};
2669 2487
2670 my $desc = $item->{nrof} < 2 2488 my $desc = $item->{nrof} < 2
2671 ? $item->{name} 2489 ? $item->{name}
2672 : "$item->{nrof} $item->{name_pl}"; 2490 : "$item->{nrof} $item->{name_pl}";
2673 2491
2702 2520
2703 1 2521 1
2704 }, 2522 },
2705 %args 2523 %args
2706 ); 2524 );
2525
2707 $self->add(new CFClient::UI::Face 2526 $self->add (new CFClient::UI::Face
2708 can_events => 0, 2527 can_events => 0,
2709 face => $item->{face}, 2528 face => $item->{face},
2710 anim => $item->{anim}, 2529 anim => $item->{anim},
2711 animspeed => $item->{animspeed}); 2530 animspeed => $item->{animspeed},
2531 );
2532
2712 $self->add(new CFClient::UI::Label 2533 $self->add (new CFClient::UI::Label
2713 can_events => 0, 2534 can_events => 0,
2714 text => $desc); 2535 text => $desc,
2536 );
2715 2537
2716 $self 2538 $self
2717} 2539}
2718 2540
2719############################################################################# 2541#############################################################################
2746 for my $item (@items) { 2568 for my $item (@items) {
2747 my $desc = $item->{nrof} < 2 2569 my $desc = $item->{nrof} < 2
2748 ? $item->{name} 2570 ? $item->{name}
2749 : "$item->{nrof} $item->{name_pl}"; 2571 : "$item->{nrof} $item->{name_pl}";
2750 2572
2751 $self->{scrolled}->add (new CFClient::UI::InventoryItem item => $item); 2573 $self->{scrolled}->add ($item->{widget} ||= new CFClient::UI::InventoryItem item => $item);
2752 } 2574 }
2753 2575
2754# $range->{range} = [$self->{pos}, 0, $self->{max_pos}, $page]; 2576# $range->{range} = [$self->{pos}, 0, $self->{max_pos}, $page];
2755} 2577}
2756 2578
2757sub size_request { 2579sub size_request {
2758 my ($self) = @_; 2580 my ($self) = @_;
2759 ($self->{req_w}, $self->{req_h}); 2581 ($self->{req_w}, $self->{req_h});
2582}
2583
2584#############################################################################
2585
2586package CFClient::UI::Menu;
2587
2588our @ISA = CFClient::UI::FancyFrame::;
2589
2590use CFClient::OpenGL;
2591
2592sub new {
2593 my $class = shift;
2594
2595 my $self = $class->SUPER::new (
2596 items => [],
2597 z => 100,
2598 @_,
2599 );
2600
2601 $self->add ($self->{vbox} = new CFClient::UI::VBox);
2602
2603 for my $item (@{ $self->{items} }) {
2604 my ($widget, $cb) = @$item;
2605
2606 # handle various types of items, only text for now
2607 if (!ref $widget) {
2608 $widget = new CFClient::UI::Label
2609 can_hover => 1,
2610 can_events => 1,
2611 text => $widget;
2612 }
2613
2614 $self->{item}{$widget} = $item;
2615
2616 $self->{vbox}->add ($widget);
2617 }
2618
2619 $self
2620}
2621
2622# popup given the event (must be a mouse button down event currently)
2623sub popup {
2624 my ($self, $ev) = @_;
2625
2626 $self->emit ("popdown");
2627
2628 # maybe save $GRAB? must be careful about events...
2629 $GRAB = $self;
2630 $self->{button} = $ev->{button};
2631
2632 $self->show;
2633 $self->move ($ev->{x} - $self->{w} * 0.5, $ev->{y} - $self->{h} * 0.5);
2634}
2635
2636sub mouse_motion {
2637 my ($self, $ev, $x, $y) = @_;
2638
2639 # TODO: should use vbox->find_widget or so
2640 $HOVER = $ROOT->find_widget ($ev->{x}, $ev->{y});
2641 $self->{hover} = $self->{item}{$HOVER};
2642}
2643
2644sub button_up {
2645 my ($self, $ev, $x, $y) = @_;
2646
2647 if ($ev->{button} == $self->{button}) {
2648 undef $GRAB;
2649 $self->hide;
2650
2651 $self->emit ("popdown");
2652 $self->{hover}[1]->() if $self->{hover};
2653 }
2654}
2655
2656#############################################################################
2657
2658package CFClient::UI::Root;
2659
2660our @ISA = CFClient::UI::Container::;
2661
2662use CFClient::OpenGL;
2663
2664sub new {
2665 my $class = shift;
2666
2667 $class->SUPER::new (
2668 @_,
2669 )
2670}
2671
2672sub configure {
2673 my ($self, $x, $y, $w, $h) = @_;
2674
2675 $self->{w} = $w;
2676 $self->{h} = $h;
2677}
2678
2679sub check_size {
2680 my ($self) = @_;
2681
2682 $self->size_allocate ($self->{w}, $self->{h})
2683 if $self->{w};
2684}
2685
2686sub size_request {
2687 my ($self) = @_;
2688
2689 ($self->{w}, $self->{h})
2690}
2691
2692sub size_allocate {
2693 my ($self, $w, $h) = @_;
2694
2695 my $old_w = $self->{old_w};
2696 my $old_h = $self->{old_h};
2697
2698 if ($old_w && $old_h) {
2699 for my $child ($self->children) {
2700 $child->{x} = int 0.5 + $child->{x} * $w / $old_w;
2701 $child->{w} = int 0.5 + $child->{w} * $w / $old_w;
2702 $child->{req_w} = int 0.5 + $child->{req_w} * $w / $old_w if exists $child->{req_w};
2703 $child->{user_w} = int 0.5 + $child->{user_w} * $w / $old_w if exists $child->{user_w};
2704 $child->{y} = int 0.5 + $child->{y} * $h / $old_h;
2705 $child->{h} = int 0.5 + $child->{h} * $h / $old_h;
2706 $child->{req_h} = int 0.5 + $child->{req_h} * $h / $old_h if exists $child->{req_h};
2707 $child->{user_h} = int 0.5 + $child->{user_h} * $h / $old_h if exists $child->{user_h};
2708 }
2709 }
2710
2711 for my $child ($self->children) {
2712 my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)};
2713
2714 $X = List::Util::max 0, List::Util::min $w - $W, $X;
2715 $Y = List::Util::max 0, List::Util::min $h - $H, $Y;
2716 $child->configure ($X, $Y, $W, $H);
2717 }
2718
2719 $self->{old_w} = $w;
2720 $self->{old_h} = $h;
2721}
2722
2723sub coord2local {
2724 my ($self, $x, $y) = @_;
2725
2726 ($x, $y)
2727}
2728
2729sub coord2global {
2730 my ($self, $x, $y) = @_;
2731
2732 ($x, $y)
2733}
2734
2735sub update {
2736 my ($self) = @_;
2737
2738 $self->check_size;
2739 $::WANT_REFRESH++;
2740}
2741
2742sub add {
2743 my ($self, $child) = @_;
2744
2745 # integerise window positions
2746 $child->{x} = int $child->{x};
2747 $child->{y} = int $child->{y};
2748
2749 $self->SUPER::add ($child);
2750}
2751
2752sub on_refresh {
2753 my ($self, $id, $cb) = @_;
2754
2755 $self->{refresh_hook}{$id} = $cb;
2756}
2757
2758sub draw {
2759 my ($self) = @_;
2760
2761 if ($self->{check_size}) {
2762 my @queue = ([], []);
2763
2764 for (;;) {
2765 if ($self->{check_size}) {
2766 # heuristic: check containers last
2767 push @{ $queue[ ! ! $_->isa ("CFClient::UI::Container") ] }, $_
2768 for values %{delete $self->{check_size}}
2769 }
2770
2771 my $widget = (pop @{ $queue[0] }) || (pop @{ $queue[1] }) || last;
2772
2773 my ($w, $h) = $widget->{user_w} && $widget->{user_h}
2774 ? @$widget{qw(user_w user_h)}
2775 : $widget->size_request;
2776
2777 if ($w != $widget->{req_w} || $h != $widget->{req_h}) {
2778 $widget->{req_w} = $w;
2779 $widget->{req_h} = $h;
2780
2781 $self->{size_alloc}{$widget} = [$widget, $widget->{w}, $widget->{h}];
2782
2783 $widget->{parent}->check_size
2784 if $widget->{parent};
2785 }
2786 }
2787 }
2788
2789 while ($self->{size_alloc}) {
2790 for (values %{delete $self->{size_alloc}}) {
2791 my ($widget, $w, $h) = @$_;
2792
2793 $widget->{w} = $w;
2794 $widget->{h} = $h;
2795 $widget->size_allocate ($w, $h);
2796 $widget->emit (size_allocate => $w, $h);
2797 }
2798 }
2799
2800 while ($self->{refresh_hook}) {
2801 $_->()
2802 for values %{delete $self->{refresh_hook}};
2803 }
2804
2805 glViewport 0, 0, $::WIDTH, $::HEIGHT;
2806 glClearColor +($::CFG->{fow_intensity}) x 3, 1;
2807 glClear GL_COLOR_BUFFER_BIT;
2808
2809 glMatrixMode GL_PROJECTION;
2810 glLoadIdentity;
2811 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000 , 10000;
2812 glMatrixMode GL_MODELVIEW;
2813 glLoadIdentity;
2814
2815 $self->_draw;
2760} 2816}
2761 2817
2762############################################################################# 2818#############################################################################
2763 2819
2764package CFClient::UI; 2820package CFClient::UI;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines