Tickit-Widget-Layout-Desktop

 view release on metacpan or  search on metacpan

lib/Tickit/Widget/Layout/Desktop/Window.pm  view on Meta::CPAN

=cut

method with_rb ($rb, $code) {
    $rb->save;
    $code->($rb);
    $rb->restore;
    $self;
}

=head2 content_rect

Represents the inner area of this window, i.e. the
content without the frame.

=cut

method content_rect {
    my $win = $self->window;
    $self->child->window->rect->translate(
        $win->top,
        $win->left
    )
}

method container { $self->{container} }

my %override = (
    southeast => 0x256D,
    northeast => 0x2570,
    southwest => 0x256E,
    northwest => 0x256f,
);

=head2 render_to_rb

Returns $self.

=cut

method render_to_rb ($rb, $rect) {
    my $win = $self->window or return;
    return unless $self->child->window;

    # If the exposed area does not overlap the frame, bail out now
    return if $self->content_rect->contains($rect);

    # Use a default pen for drawing all the line-related pieces
    $rb->setpen($self->get_style_pen);

    # First, work out any line intersections for our border.
    $self->with_rb($rb => sub {
        my $rb = shift;
        my ($top, $left) = ($win->top, $win->left);

        # We'll be rendering relative to the container
        $rb->translate(-$top, -$left);

        # Ask our container to ask all other floating
        # windows to render their frames on our context,
        # so we join line segments where expected
        $self->{container}->overlay($rb, $rect, $self);

        # Restore our origin
        # TODO would've thought ->restore should handle this?
        $rb->translate($top, $left);
    });

    my ($w, $h) = map $win->$_ - 1, qw(cols lines);
    my $text_pen = $self->get_style_pen('title');

    # This is a nasty hack - we want to know whether it's safe to draw
    # rounded corners, so we start by checking whether we have any line
    # cells already in place in the corners...

    # ... then we render our actual border, possibly using a different style for
    # active window...
    my $line = {
        round  => LINE_SINGLE,
        single => LINE_SINGLE,
        thick  => LINE_THICK,
        double => LINE_DOUBLE,
    }->{$self->get_style_values('linetype')};

    # So we first render the frame. This will pick up any adjoining lines from
    # our overlay, all being well.
    $rb->linebox_at(0, $h, 0, $w, $line);

    if($self->get_style_values('linetype') eq 'round') {
        my $limit = [
            $win->root->bottom,
            $win->root->right
        ];

        my @corner_char;
        CORNER:
        foreach my $corner ([0,0], [0,$w], [$h,0], [$h,$w]) {
            my ($y, $x) = @$corner;
            next CORNER if $y >= $limit->[0] or $x >= $limit->[1] or $x < 0 or $y < 0;

            # Apply our window offset... note that ->get_cell will segfault if
            # we're outside the render area, so the widget width had better be
            # correct here.
            my $cell = eval { $rb->get_cell($y, $x); };

            # If we have a line segment here, ->linemask should be an object...
            next CORNER unless $cell and my $linemask = $cell->linemask;

            # ... which we map to a "corner" type
            my $corners = join "", grep { $linemask->$_ == LINE_SINGLE } qw( north south east west );

            push @corner_char, [
                $y, $x, $override{$corners}, $cell->pen
            ] if exists $override{$corners};
        }
        # ... and finally we overdraw the corners.
        $rb->char_at(@$_) for @corner_char;
    }

    # Then the title
    my $txt = $self->format_label;
    $rb->text_at(0, (1 + $w - textwidth($txt)) >> 1, $txt, $text_pen);

    # and the icons for min/max/close.
    $rb->text_at(0, $w - 3, " ", $self->get_style_pen('maximise'));
    $rb->text_at(0, $w - 1, " ", $self->get_style_pen('maximise'));
    $rb->text_at(0, $w - 4, "\N{U+25CE}", $self->get_style_pen('maximise'));
    $rb->text_at(0, $w - 2, "\N{U+2612}", $self->get_style_pen('close'));

    $rb->text_at(0, 1, "[\N{U+25AA}]", $self->get_style_pen('control'));

    # Minimise isn't particularly useful, so let's not bother with that one.
    # $rb->text_at(0, $w - 5, "\N{U+238A}", Tickit::Pen->new(fg => 'hi-yellow'));
}

method format_label {
    ' ' . $self->label . ' ';
}

method render_frame ($rb, $target) {
    my $win = $self->window or return;

    my $line_type = LINE_SINGLE; #LINE_DOUBLE; #$self->is_active ? LINE_DOUBLE : LINE_SINGLE;

    $self->with_rb($rb, sub {
        my $rb = shift;



( run in 0.929 second using v1.01-cache-2.11-cpan-39bf76dae61 )