The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Prima::RubberBand - draw rubberbands

DESCRIPTION

The motivation for this module was that I was tired to see corrupted screens on Windows 7 when dragging rubberbands in Prima code. Even though MS somewhere warned of not doing any specific hacks to circumvent the bug, I decided to give it a go anyway.

This module thus is a Prima::Widget/rect_focus with a safeguard. The only thing it can do is to draw a static rubberband - but also remember the last coordinates drawn, so cleaning comes for free.

The idea is that a rubberband object is meant to be a short-lived one: as soon as it get instantiatet it draws itself on the screen. When it is destroyed, the rubberband is erased too.

SYNOPSIS

        use strict;
        use Prima qw(Application RubberBand);
        
        sub xordraw
        {
                my ($self, @new_rect) = @_;
                $::application-> rubberband( @new_rect ?
                        ( rect => \@new_rect ) :
                        ( destroy => 1 )
                );
        }
        
        Prima::MainWindow-> create(
                onMouseDown => sub {
                        my ( $self, $btn, $mod, $x, $y) = @_;
                        $self-> {anchor} = [$self-> client_to_screen( $x, $y)];
                        xordraw( $self, @{$self-> {anchor}}, $self-> client_to_screen( $x, $y));
                        $self-> capture(1);
                },
                onMouseMove => sub {
                        my ( $self, $mod, $x, $y) = @_;
                        xordraw( $self, @{$self-> {anchor}}, $self-> client_to_screen( $x, $y)) if $self-> {anchor};
                },
                onMouseUp => sub {
                        my ( $self, $btn, $mod, $x, $y) = @_;
                        xordraw if delete $self-> {anchor};
                        $self-> capture(0);
                },
        );
        
        run Prima;

API

new %properties

Creates a new RubberBand instance. See description of properties below.

Properties

breadth INTEGER = 1

Defines rubberband breadth, in pixels.

canvas = $::application

Sets the painting surface, and also the widget (it must be a widget) used for drawing.

clipRect X1, Y1, X2, Y2

Defines the clipping rectangle, in inclusive-inclusive coordinates. If set to [-1,-1,-1,-1], means no clipping is done.

mode STRING = 'auto'

The module implements two techniques, standard classic 'xor' (using .rect_focus method) and a conservative method that uses widgets instead of drawing on a canvas ('full'). The 'auto' mode checks the system and selects the appropriate mode.

Allowed modes: auto, xor, full

rect X1, Y1, X2, Y2

Defines the band geometry, in inclusive-inclusive coordinates. The band is drawn so that its body is always inside these coordinates, no matter what breadth is.

Methods

hide

Hides the band, if drawn

has_clip_rect

Cheks whether clipRect contains an actual clippring rectange or it is empty.

set %profile

Applies all properties

left, right, top, bottom, width, height, origin, size

Same shortcuts as in Prima::Widget, but read-only.

show

Show the band, if invisible

Prima::Widget interface

The module adds a single method to Prima::Widget namespace, rubberband (see example of use in the synopsis).

rubberband(%profile)

Instantiates a Prima::RubberBand with %profile, also sets canvas to $self unless canvas is set explicitly.

rubberband()

Returns the existing Prima::RubberBand object

rubberband(destroy => 1)

Destroys the existing Prima::RubberBand object

AUTHOR

Dmitry Karasik, <dmitry@karasik.eu.org>.

SEE ALSO

"rect_focus" in Prima::Widget, "grip.pl" in examples

Windows 7 Aero mode

Quote from http://blogs.msdn.com/b/greg_schechter/archive/2006/05/02/588934.aspx :

"One particularly dangerous practice is writing to the screen, either through the use of GetDC(NULL) and writing to that, or attempting to do XOR rubber-band lines, etc ... Since the UCE doesn't know about it, it may get cleared in the next frame refresh, or it may persist for a very long time, depending on what else needs to be updated on the screen. (We really don't allow direct writing to the primary anyhow, for that very reason... if you try to access the DirectDraw primary, for instance, the DWM will turn off until the accessing application exits)"

This quote seems to explain the effect why screen sometimes gets badly corrupted when using a normal xor rubberband. UCE ( Update Compatibility Evaluator ?? ) seems to be hacky enough to recognize some situations, but not all. It seems that depending on which widget received mouse button just before initialting rubberband drawing matters somehow. Anyway, the module tries to see if we're under Windows 7 aero, and if so, turns the 'full' mode on.