Group
Extension

Padre-Plugin-WebGUI/lib/Padre/Plugin/WebGUI/Assets.pm

package Padre::Plugin::WebGUI::Assets;
BEGIN {
  $Padre::Plugin::WebGUI::Assets::VERSION = '1.002';
}

# ABSTRACT: WebGUI Asset Tree

use strict;
use warnings;

use Padre::Current ();
use Padre::Logger;
use Padre::Util ();
use Padre::Wx   ();

use base 'Wx::TreeCtrl';

# generate fast accessors
use Class::XSAccessor getters => {
    plugin    => 'plugin',
    connected => 'connected',
    url       => 'url',
};


sub new {
    my $class  = shift;
    my $plugin = shift;

    my $self = $class->SUPER::new( $plugin->main->right, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize,
        Wx::wxTR_HIDE_ROOT | Wx::wxTR_SINGLE | Wx::wxTR_HAS_BUTTONS | Wx::wxTR_LINES_AT_ROOT | Wx::wxBORDER_NONE );

    $self->{plugin} = $plugin;

    # Register event handlers..
    Wx::Event::EVT_TREE_ITEM_ACTIVATED(
        $self, $self,
        sub {
            $self->on_tree_item_activated( $_[1] );
        },
    );

    $self->Hide;

    # Create image list
    my $imglist = Wx::ImageList->new( 16, 16 );
    $self->AssignImageList($imglist);
    $imglist->Add( Padre::Wx::Icon::find('status/padre-plugin') );

    return $self;
}


sub right { $_[0]->GetParent }


sub main { $_[0]->GetGrandParent }


sub gettext_label { Wx::gettext('Asset Tree') }


sub clear { $_[0]->DeleteAllItems }


sub update_gui {
    my $self = shift;
    if ( $self->connected ) {
        $self->update_gui_connected;
    }
    else {
        $self->update_gui_disconnected;
    }
}


sub update_gui_disconnected {
    my $self = shift;

    $self->{connected} = 0;

    $self->Freeze;
    $self->clear;

    my $root = $self->AddRoot( Wx::gettext('Asset Tree'), -1, -1, Wx::TreeItemData->new('') );
    my $connect = $self->AppendItem( $root, 'Connect', -1, -1, Wx::TreeItemData->new( { connect => 1 } ), );
    $self->SetItemTextColour( $connect, Wx::Colour->new( 0x00, 0x00, 0x7f ) );
    $self->SetItemImage( $connect, 0 );
    $self->GetBestSize;

    $self->Thaw;
}


sub update_gui_connected {
    my $self = shift;

    $self->{connected} = 1;

    # Show loading indicator
    $self->Freeze;
    $self->clear;

    my $tmp_root = $self->AddRoot( Wx::gettext('Asset Tree'), -1, -1, Wx::TreeItemData->new('') );
    my $status = $self->AppendItem( $tmp_root, 'Loading..', -1, -1, Wx::TreeItemData->new( { loading => 1 } ), );
    $self->SetItemTextColour( $status, Wx::Colour->new( 0x00, 0x00, 0x7f ) );
    $self->SetItemImage( $status, 0 );
    $self->GetBestSize;

    $self->Thaw;

    # Force window update
    $self->Update;

    # Now actually connect..
    $self->Freeze;
    $self->clear;

    my $root = $self->AddRoot( Wx::gettext('Asset Tree'), -1, -1, Wx::TreeItemData->new('') );
    my $refresh = $self->AppendItem( $root, 'Refresh', -1, -1, Wx::TreeItemData->new( { refresh => 1 } ), );
    $self->SetItemTextColour( $refresh, Wx::Colour->new( 0x00, 0x00, 0x7f ) );
    $self->SetItemImage( $refresh, 0 );

    if ( my $assets = $self->build_asset_tree ) {
        update_treectrl( $self, $assets, $root );

        # Register right-click event handler
        Wx::Event::EVT_TREE_ITEM_RIGHT_CLICK( $self, $self, \&on_tree_item_right_click, );

        $self->GetBestSize;
        $self->Thaw;
    }
    else {

        # Reset back to disconnected state
        $self->GetBestSize;
        $self->Thaw;
        $self->update_gui_disconnected;
    }
}


sub build_asset_tree {
    my $self = shift;

    # Create a user agent object
    use LWP::UserAgent;
    my $ua       = LWP::UserAgent->new;
    my $response = $ua->get( $self->url . '?op=padre&func=list' );
    unless ( $response->header('Padre-Plugin-WebGUI') ) {
        $self->main->error("The server does not appear to have the Padre::Plugin::WebGUI content handler installed");
        return;
    }
    if ( !$response->is_success ) {
        $self->main->error( "The server said:\n" . $response->status_line );
        return;
    }

    my $assets = $response->content;

    # TRACE($assets) if DEBUG;

    use JSON;
    $assets = eval { decode_json($assets) };
    if ($@) {
        TRACE($@) if DEBUG;
        $self->main->error("The server sent an invalid response, please try again (and check the logs)");
        return;
    }
    else {
        return $assets;
    }
}


sub edit_asset {
    my $self = shift;
    my $item = shift;

    # Create new editor tab
    my $main = $self->main;
    $main->on_new();
    my $editor = $main->current->editor or return;
    my $doc = $editor->{Document};

    # Set WebGUI Asset mime-type and rebless
    my %registered_documents = $self->plugin->registered_documents;
    my $mimetype             = lc $item->{className};
    $mimetype =~ s/.*:://;
    $mimetype = "application/x-webgui-$mimetype";

    # Fall-back to generic 'asset' mime-type
    $mimetype = "application/x-webgui-asset" unless $registered_documents{$mimetype};
    TRACE("Using mimetype: $mimetype for $item->{className}") if DEBUG;
    $doc->set_mimetype($mimetype);

    # Rebless
    $doc->editor->padre_setup;
    $doc->rebless;

    return unless $doc->isa('Padre::Document::WebGUI::Asset');

    # Load asset
    $doc->load_asset( $item->{assetId}, $self->url );

    # Fake-save tab so that it isn't in the unsaved state
    my $id   = $main->find_id_of_editor($editor);
    my $page = $main->notebook->GetPage($id);
    $page->SetSavePoint;

    # Set tab icon
    if ( my $icon = $self->get_item_icon( $item->{icon} ) ) {
        $main->notebook->SetPageBitmap( $id, $icon );
    }

    $main->refresh;
}


sub on_tree_item_right_click {
    my ( $self, $event ) = @_;

    my $showMenu = 0;
    my $menu     = Wx::Menu->new;
    my $item     = $self->GetPlData( $event->GetItem );

    if ( defined $item ) {
        my $submenu;

        $submenu = $menu->Append( -1, Wx::gettext("Details..") );
        Wx::Event::EVT_MENU(
            $self, $submenu,
            sub {
                $self->on_tree_item_activated( $event, { action => 'details' } );
            },
        );

        $submenu = $menu->Append( -1, Wx::gettext("Edit") );
        Wx::Event::EVT_MENU(
            $self, $submenu,
            sub {
                $self->edit_asset($item);
            },
        );

        $showMenu++;
    }

    if ( $showMenu > 0 ) {
        my $x = $event->GetPoint->x;
        my $y = $event->GetPoint->y;
        $self->PopupMenu( $menu, $x, $y );
    }

    return;
}


sub on_tree_item_activated {
    my ( $self, $event, $opts ) = @_;
    $opts ||= {};

    # Get the target item
    my $item = $self->GetPlData( $event->GetItem );
    return if not defined $item;

    if ( $item->{connect} ) {
        my $url =
          $self->main->prompt( 'Enter a URL to connect to, for example: http://admin:123qwe@dev.localhost.localdomain',
            'Connect To Server', 'wg_url' );
        return unless $url;
        $self->{url} = $url;
        $self->update_gui_connected;
        return;
    }

    elsif ( $item->{refresh} ) {
        $self->update_gui_connected;
        return;
    }

    elsif ( $opts->{action} && $opts->{action} eq 'details' ) {
        my $str = q{};
        for my $key ( sort keys %$item ) {
            $str .= qq{$key:\t\t $item->{$key}\n};
        }
        $self->main->error($str);
    }

    else {

        # Default event is double-click
        $self->edit_asset($item);
    }

    return;
}

my $image_lookup;


sub get_item_image {
    my $self = shift;
    my $icon = shift;

    $icon =~ s{.*/}{};
    my $imglist = $self->GetImageList;
    if ( !$image_lookup->{$icon} ) {
        my $index = $imglist->Add(
            Wx::Bitmap->new( $self->plugin->plugin_directory_share . "/icons/16x16/$icon", Wx::wxBITMAP_TYPE_GIF ) );
        $image_lookup->{$icon} = $index;
    }
    return $image_lookup->{$icon} || 0;
}


sub get_item_icon {
    my $self  = shift;
    my $icon  = shift;
    my $index = $self->get_item_image($icon);
    return $self->GetImageList->GetIcon($index);
}


sub update_treectrl {
    my ( $self, $items, $parent ) = @_;

    foreach my $item ( @{$items} ) {
        my $node = $self->AppendItem( $parent, $item->{menuTitle}, -1, -1, Wx::TreeItemData->new( {%$item} ), );
        $self->SetItemTextColour( $node, Wx::Colour->new( 0x00, 0x00, 0x7f ) );
        $self->SetItemImage( $node, $self->get_item_image( $item->{icon} ) );

        # Recurse, adding children to $node
        update_treectrl( $self, $item->{children}, $node );
    }

    return;
}


1;

__END__
=pod

=head1 NAME

Padre::Plugin::WebGUI::Assets - WebGUI Asset Tree

=head1 VERSION

version 1.002

=head1 METHODS

=head2 plugin

Accessor

=head2 connected

Accessor

=head2 url

Accessor

=head2 new

constructor

=head2 right

Accessor

=head2 main

Accessor

=head2 gettext_label

Accessor

=head2 clear

Accessor

=head2 update_gui

=head2 update_gui_disconnected

=head2 update_gui_connected

=head2 build_asset_tree

generate the list of assets
todo - make this lazy-load for better performance

=head2 edit_asset

=head2 on_tree_item_right_click

=head2 on_tree_item_activated

event handler for item activation

=head2 get_item_image

=head2 get_item_icon

=head2 update_treectrl

=head2 TRACE

=head1 AUTHOR

Patrick Donelan <pdonelan@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2011 by Patrick Donelan.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut



Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.