636 lines
20 KiB
Perl
636 lines
20 KiB
Perl
package GEmeTool::View::PokemonEditorWindow;
|
|
|
|
use v5.16.3;
|
|
|
|
use strict;
|
|
use warnings;
|
|
use utf8;
|
|
|
|
use Moo;
|
|
|
|
use Glib::Object::Introspection;
|
|
use Glib::IO;
|
|
use Path::Tiny;
|
|
|
|
use Rsaves;
|
|
use Rsaves::Constants::Emerald::Species;
|
|
use Rsaves::Constants::Emerald::Natures;
|
|
use GEmeTool::Save::Pokemon;
|
|
use GEmeTool::Options;
|
|
use GEmeTool::DB;
|
|
|
|
Glib::Object::Introspection->setup(
|
|
basename => 'Gtk',
|
|
version => '4.0',
|
|
package => 'Gtk4',
|
|
);
|
|
|
|
Glib::Object::Introspection->setup(
|
|
basename => 'Gdk',
|
|
version => '4.0',
|
|
package => 'Gdk',
|
|
);
|
|
|
|
has pokemon => (
|
|
is => 'ro',
|
|
required => 1,
|
|
);
|
|
|
|
has _win => ( is => 'rw', );
|
|
|
|
has _selected_species => ( is => 'rw', );
|
|
|
|
has _save_callbacks => ( is => 'rw', default => sub { [] } );
|
|
|
|
has _current_personality => ( is => 'rw' );
|
|
|
|
has _iv_buffers => ( is => 'rw', default => sub { {} } );
|
|
has _ev_buffers => ( is => 'rw', default => sub { {} } );
|
|
|
|
my $root = path(__FILE__)->parent->parent->parent->parent;
|
|
my $width = 600;
|
|
my $height = 400;
|
|
|
|
my @stats =
|
|
( 'HP', 'Attack', 'Defense', 'Speed', 'SpecialAttack', 'SpecialDefense' );
|
|
|
|
sub start {
|
|
my $self = shift;
|
|
my $window = Gtk4::Window->new;
|
|
$self->_win($window);
|
|
$self->draw;
|
|
$window->present;
|
|
}
|
|
|
|
sub onSave {
|
|
my $self = shift;
|
|
my $func = shift;
|
|
my $save_callbacks = $self->_save_callbacks;
|
|
push @$save_callbacks, $func;
|
|
}
|
|
|
|
sub draw {
|
|
my $self = shift;
|
|
my $window = $self->_win;
|
|
$window->set_resizable(0);
|
|
my $pokemon = $self->pokemon;
|
|
$window->set_title( 'Editing Pokémon '
|
|
. Rsaves::translate_3rd_encoding( $pokemon->nickname ) );
|
|
$self->_current_personality( $pokemon->personality );
|
|
my $grid = Gtk4::Grid->new;
|
|
$grid->set_column_homogeneous(1);
|
|
my $canvas = Gtk4::DrawingArea->new;
|
|
$canvas->set_content_width(267);
|
|
$canvas->set_content_height(267);
|
|
$canvas->set_valign('start');
|
|
$canvas->set_halign('start');
|
|
$canvas->set_draw_func(
|
|
sub {
|
|
my $canvas = shift;
|
|
my $cairo = shift;
|
|
my $width = shift;
|
|
my $height = shift;
|
|
$cairo->scale( $width / 64, $height / 64 );
|
|
my $surface = Cairo::ImageSurface->create_from_png(
|
|
$root->child( $pokemon->get_front ) );
|
|
$cairo->set_source_surface( $surface, 0, 0 );
|
|
$cairo->get_source()->set_filter('nearest');
|
|
$cairo->paint;
|
|
}
|
|
);
|
|
$grid->attach( $canvas, 0, 0, 2, 2 );
|
|
my @species = (@Rsaves::Constants::Emerald::Species::SPECIES);
|
|
my $string_list = Gtk4::StringList->new( [@species] );
|
|
my $restore_button = Gtk4::Button->new_with_label('Restore from backup');
|
|
my $save_button = Gtk4::Button->new_with_label('Save changes');
|
|
my $delete_button = Gtk4::Button->new_with_label('Delete pokemon');
|
|
my $import_button = Gtk4::Button->new_with_label('Import .pk3');
|
|
my $export_button = Gtk4::Button->new_with_label('Export .pk3');
|
|
$self->_selected_species( $pokemon->species );
|
|
my $box_right_image = Gtk4::Box->new( 'vertical', 1 );
|
|
$box_right_image->set_margin_top(30);
|
|
$box_right_image->set_valign('start');
|
|
$box_right_image->set_halign('start');
|
|
my $box_ev = Gtk4::Box->new( 'vertical', 1 );
|
|
$grid->attach( $box_right_image, 2, 0, 2, 2 );
|
|
$grid->attach( $box_ev, 4, 0, 2, 2 );
|
|
$box_ev->append( Gtk4::Label->new('Select EV') );
|
|
$self->create_select_level($box_ev);
|
|
$self->create_select_evs($box_ev);
|
|
$self->create_change_nickname_entry($box_right_image);
|
|
$save_button->signal_connect(
|
|
clicked => sub {
|
|
$self->activate_save;
|
|
}
|
|
);
|
|
$delete_button->signal_connect(
|
|
clicked => sub {
|
|
$self->delete;
|
|
}
|
|
);
|
|
$import_button->signal_connect(
|
|
clicked => sub {
|
|
$self->activate_import_pk3;
|
|
}
|
|
);
|
|
$export_button->signal_connect(
|
|
clicked => sub {
|
|
$self->activate_export_pk3;
|
|
}
|
|
);
|
|
$restore_button->signal_connect(
|
|
clicked => sub {
|
|
$self->activate_restore;
|
|
}
|
|
);
|
|
$self->draw_dropdown_pokemon_list($box_right_image);
|
|
my $box_label_iv = Gtk4::Box->new( 'horizontal', 10 );
|
|
$box_label_iv->append( Gtk4::Label->new('Select IV') );
|
|
$box_right_image->append($box_label_iv);
|
|
$self->create_select_ivs($box_right_image);
|
|
$self->create_modify_personality($grid);
|
|
$grid->attach( $save_button, 4, 7, 1, 1 );
|
|
$grid->attach( $export_button, 3, 7, 1, 1 );
|
|
$grid->attach( $delete_button, 2, 7, 1, 1 );
|
|
$grid->attach( $import_button, 1, 7, 1, 1 );
|
|
$grid->attach( $restore_button, 0, 7, 1, 1 );
|
|
$window->set_child($grid);
|
|
}
|
|
|
|
sub activate_restore {
|
|
my $self = shift;
|
|
my $window = Gtk4::Window->new;
|
|
$window->set_title('Restore from backup');
|
|
my $scroll = Gtk4::ScrolledWindow->new;
|
|
my $grid = Gtk4::Grid->new;
|
|
my $backups = $self->get_backups;
|
|
my $i = 0;
|
|
for my $backup (@$backups) {
|
|
my $nickname = Rsaves::translate_3rd_encoding( $backup->{nickname} );
|
|
my $pokemon_name = $backup->{pokemon_name};
|
|
my $file = $backup->{file};
|
|
my $button =
|
|
Gtk4::Button->new_with_label( $nickname . '-' . $pokemon_name );
|
|
$button->signal_connect(
|
|
clicked => sub {
|
|
$self->activate_save;
|
|
$self->pokemon->backup;
|
|
$self->pokemon->copy(
|
|
GEmeTool::Save::Pokemon->load_from_file($file) );
|
|
$self->draw;
|
|
$window->close;
|
|
}
|
|
);
|
|
$grid->attach( $button, $i % 6, int( $i / 6 ), 1, 1 );
|
|
$i++;
|
|
}
|
|
$window->set_child($grid);
|
|
$window->present;
|
|
}
|
|
|
|
sub get_backups {
|
|
my $self = shift;
|
|
my $db = GEmeTool::DB->connect;
|
|
my $query = <<'EOF';
|
|
SELECT nickname, pokemon_name, file
|
|
FROM backups_pk3
|
|
ORDER BY date DESC;
|
|
EOF
|
|
my $result = $db->selectall_arrayref( $query, { Slice => {} } );
|
|
return $result;
|
|
}
|
|
|
|
sub activate_save {
|
|
my $self = shift;
|
|
my $pokemon = $self->pokemon;
|
|
$pokemon->backup;
|
|
$pokemon->species( $self->_selected_species );
|
|
$pokemon->personality( $self->_current_personality );
|
|
$self->recalculate_ivs;
|
|
$self->recalculate_evs;
|
|
for my $func ( @{ $self->_save_callbacks } ) {
|
|
$func->();
|
|
}
|
|
$pokemon->backup;
|
|
$self->draw;
|
|
}
|
|
|
|
sub activate_export_pk3 {
|
|
my $self = shift;
|
|
my $win = $self->_win;
|
|
my $dialog = Gtk4::FileDialog->new;
|
|
my $options = GEmeTool::Options->new;
|
|
my $last_dir = $options->get_last_dir_open;
|
|
if ( defined $last_dir && -d $last_dir ) {
|
|
my $curdir = Glib::IO::File::new_for_path($last_dir);
|
|
$dialog->set_initial_folder($curdir);
|
|
$dialog->set_initial_name(
|
|
Rsaves::translate_3rd_encoding( $self->pokemon->nickname ) . '-'
|
|
. $self->pokemon->pokemon_name
|
|
. '.pk3' );
|
|
}
|
|
$dialog->save(
|
|
$win, undef,
|
|
sub {
|
|
my ( $self_dialog, $res ) = @_;
|
|
if ( $res->had_error ) {
|
|
return;
|
|
}
|
|
my $file = $dialog->save_finish($res);
|
|
return if !defined $file;
|
|
$file = path( $file->get_path );
|
|
$self->pokemon->export_file($file);
|
|
}
|
|
);
|
|
}
|
|
|
|
sub delete {
|
|
my $self = shift;
|
|
$self->pokemon->backup;
|
|
$self->pokemon->copy( GEmeTool::Save::Pokemon->empty );
|
|
$self->draw;
|
|
}
|
|
|
|
sub activate_import_pk3 {
|
|
my $self = shift;
|
|
my $cancellable = Glib::IO::Cancellable->new;
|
|
my $dialog = Gtk4::FileDialog->new;
|
|
my $win = $self->_win;
|
|
my $options = GEmeTool::Options->new;
|
|
my $last_dir = $options->get_last_dir_open;
|
|
if ( defined $last_dir && -d $last_dir ) {
|
|
my $curdir = Glib::IO::File::new_for_path($last_dir);
|
|
$dialog->set_initial_folder($curdir);
|
|
}
|
|
$dialog->open(
|
|
$win,
|
|
$cancellable,
|
|
sub {
|
|
my ( $self_dialog, $res ) = @_;
|
|
if ( $res->had_error ) {
|
|
return;
|
|
}
|
|
my $file = $dialog->open_finish($res);
|
|
return if !defined $file;
|
|
$file = path( $file->get_path );
|
|
$options->set_last_dir_open( $file->parent . '' );
|
|
$self->activate_save;
|
|
$self->pokemon->copy(
|
|
GEmeTool::Save::Pokemon->load_from_file($file) );
|
|
$self->draw;
|
|
}
|
|
);
|
|
}
|
|
|
|
sub create_select_level {
|
|
my $self = shift;
|
|
my $box = shift;
|
|
my $pokemon = $self->pokemon;
|
|
my $box_level = Gtk4::Box->new( 'horizontal', 10 );
|
|
$box_level->append( Gtk4::Label->new('Lvl:') );
|
|
my $entry = Gtk4::Entry->new;
|
|
$entry->set_input_purpose('digits');
|
|
$entry->get_buffer->set_text( $pokemon->level, length $pokemon->level );
|
|
$box_level->append($entry);
|
|
$self->onSave(
|
|
sub {
|
|
my $text = $entry->get_buffer->get_text;
|
|
if ( $text !~ /^[0-9]+$/ ) {
|
|
return;
|
|
}
|
|
if ( $text > 100 ) {
|
|
$text = 100;
|
|
}
|
|
if ( $text < 2 ) {
|
|
$text = 2;
|
|
}
|
|
$pokemon->level($text);
|
|
}
|
|
);
|
|
$box->append($box_level);
|
|
}
|
|
|
|
sub recalculate_evs {
|
|
my $self = shift;
|
|
my $pokemon = $self->pokemon;
|
|
for my $key (@stats) {
|
|
my $text = $self->_ev_buffers->{$key}->get_text;
|
|
next if $text !~ /^[0-9]+$/;
|
|
if ( $text > 255 ) {
|
|
$text = 255;
|
|
}
|
|
if ( $text < 0 ) {
|
|
$text = 0;
|
|
}
|
|
$pokemon->evs(
|
|
{
|
|
$key => $text,
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
sub recalculate_ivs {
|
|
my $self = shift;
|
|
my $pokemon = $self->pokemon;
|
|
for my $key (@stats) {
|
|
my $text = $self->_iv_buffers->{$key}->get_text;
|
|
next if $text !~ /^[0-9]+$/;
|
|
if ( $text > 31 ) {
|
|
$text = 31;
|
|
}
|
|
if ( $text < 0 ) {
|
|
$text = 0;
|
|
}
|
|
$pokemon->ivs(
|
|
{
|
|
$key => $text,
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
sub create_select_evs {
|
|
my $self = shift;
|
|
my $box = shift;
|
|
my $ev_buffers = $self->_ev_buffers;
|
|
my $evs = $self->pokemon->evs;
|
|
|
|
for my $stat (@stats) {
|
|
my $box_stat = Gtk4::Box->new( 'horizontal', 10 );
|
|
my $entry = Gtk4::Entry->new;
|
|
$entry->set_input_purpose('digits');
|
|
$entry->get_buffer->set_text( $evs->{$stat}, length $evs->{$stat} );
|
|
$box_stat->append( Gtk4::Label->new($stat) );
|
|
$box_stat->append($entry);
|
|
$ev_buffers->{$stat} = $entry->get_buffer;
|
|
$box->append($box_stat);
|
|
}
|
|
}
|
|
|
|
sub create_select_ivs {
|
|
my $self = shift;
|
|
my $box = shift;
|
|
my $iv_buffers = $self->_iv_buffers;
|
|
my $ivs = $self->pokemon->ivs;
|
|
|
|
for my $stat (@stats) {
|
|
my $box_stat = Gtk4::Box->new( 'horizontal', 10 );
|
|
my $entry = Gtk4::Entry->new;
|
|
$entry->set_input_purpose('digits');
|
|
$entry->get_buffer->set_text( $ivs->{$stat}, length $ivs->{$stat} );
|
|
$box_stat->append( Gtk4::Label->new($stat) );
|
|
$box_stat->append($entry);
|
|
$iv_buffers->{$stat} = $entry->get_buffer;
|
|
$box->append($box_stat);
|
|
}
|
|
}
|
|
|
|
sub create_modify_personality {
|
|
my $self = shift;
|
|
my $grid = shift;
|
|
my $button = Gtk4::Button->new_with_label('Edit personality');
|
|
$button->signal_connect(
|
|
clicked => sub {
|
|
$self->open_window_personality;
|
|
}
|
|
);
|
|
$button->set_valign('start');
|
|
$button->set_halign('start');
|
|
$grid->attach( $button, 2, 2, 1, 1 );
|
|
}
|
|
|
|
sub open_window_personality {
|
|
my $self = shift;
|
|
my $window = Gtk4::Window->new;
|
|
$window->set_default_size( 600, 600 );
|
|
my $scroll = Gtk4::ScrolledWindow->new;
|
|
my $box_window = Gtk4::Box->new( 'vertical', 1 );
|
|
$box_window->append( Gtk4::Label->new('Select shiny') );
|
|
|
|
my $box_shiny = Gtk4::Box->new( 'horizontal', 1 );
|
|
my $shiny_dont_mind = Gtk4::ToggleButton->new_with_label('Do not matter');
|
|
my $shiny_yes = Gtk4::ToggleButton->new_with_label('Yes');
|
|
my $shiny_no = Gtk4::ToggleButton->new_with_label('No');
|
|
|
|
$shiny_dont_mind->set_active(1);
|
|
|
|
$shiny_yes->set_group($shiny_dont_mind);
|
|
$shiny_no->set_group($shiny_dont_mind);
|
|
|
|
$box_shiny->append($shiny_dont_mind);
|
|
$box_shiny->append($shiny_yes);
|
|
$box_shiny->append($shiny_no);
|
|
|
|
$box_window->append($box_shiny);
|
|
$box_window->append( Gtk4::Label->new('Select gender') );
|
|
|
|
my $box_gender = Gtk4::Box->new( 'horizontal', 1 );
|
|
my $gender_dont_mind = Gtk4::ToggleButton->new_with_label('Do not matter');
|
|
my $gender_male = Gtk4::ToggleButton->new_with_label('Male');
|
|
my $gender_female = Gtk4::ToggleButton->new_with_label('Female');
|
|
|
|
$gender_female->set_group($gender_male);
|
|
$gender_dont_mind->set_group($gender_male);
|
|
|
|
$gender_dont_mind->set_active(1);
|
|
|
|
$box_gender->append($gender_dont_mind);
|
|
$box_gender->append($gender_male);
|
|
$box_gender->append($gender_female);
|
|
|
|
$box_window->append($box_gender);
|
|
|
|
$box_window->append( Gtk4::Label->new('Select nature') );
|
|
|
|
my $box_natures = Gtk4::Box->new( 'vertical', 1 );
|
|
my @natures = @Rsaves::Constants::Emerald::Natures::NATURES;
|
|
my %toggle_nature =
|
|
map { $_ => Gtk4::ToggleButton->new_with_label($_) } @natures;
|
|
|
|
my $nature_dont_mind = Gtk4::ToggleButton->new_with_label('Do not matter');
|
|
$nature_dont_mind->set_active(1);
|
|
|
|
$box_natures->append($nature_dont_mind);
|
|
|
|
for my $nature (@natures) {
|
|
my $toggle = $toggle_nature{$nature};
|
|
$toggle->set_group($nature_dont_mind);
|
|
$box_natures->append($toggle);
|
|
}
|
|
|
|
$box_window->append($box_natures);
|
|
|
|
my $button_generate = Gtk4::Button->new_with_label('Generate personality');
|
|
$button_generate->signal_connect(
|
|
clicked => sub {
|
|
my @gender_buttons = ( $gender_male, $gender_female );
|
|
my $target_shiny = undef;
|
|
my $target_gender = undef;
|
|
my $target_nature = undef;
|
|
if ( $shiny_yes->get_active ) {
|
|
$target_shiny = 1;
|
|
}
|
|
if ( $shiny_no->get_active ) {
|
|
$target_shiny = 0;
|
|
}
|
|
for my $i ( 0 .. 1 ) {
|
|
if ( $gender_buttons[$i]->get_active ) {
|
|
$target_gender = $i;
|
|
last;
|
|
}
|
|
}
|
|
for my $i ( 0 .. 24 ) {
|
|
if ( $toggle_nature{ $natures[$i] }->get_active ) {
|
|
$target_nature = $i;
|
|
last;
|
|
}
|
|
}
|
|
my $personality =
|
|
$self->pokemon->generate_personality( $target_shiny,
|
|
$target_gender, $target_nature );
|
|
if ( defined $personality ) {
|
|
$self->_current_personality($personality);
|
|
}
|
|
$window->close;
|
|
}
|
|
);
|
|
$box_window->append($button_generate);
|
|
$scroll->set_child($box_window);
|
|
$window->set_child($scroll);
|
|
$window->present;
|
|
}
|
|
|
|
sub create_change_nickname_entry {
|
|
my $self = shift;
|
|
my $box = shift;
|
|
my $pokemon = $self->pokemon;
|
|
my $label = Gtk4::Label->new('Change the nickname:');
|
|
my $entry = Gtk4::Entry->new;
|
|
my $nickname = Rsaves::translate_3rd_encoding( $pokemon->nickname );
|
|
my $box_nickname = Gtk4::Box->new( 'horizontal', 10 );
|
|
$entry->get_buffer->set_text( $nickname, length $nickname );
|
|
$entry->set_halign('start');
|
|
$entry->set_valign('start');
|
|
$label->set_halign('start');
|
|
$label->set_valign('start');
|
|
$box_nickname->append($label);
|
|
$box_nickname->append($entry);
|
|
$box->append($box_nickname);
|
|
$self->onSave(
|
|
sub {
|
|
my $translated_nickname =
|
|
Rsaves::to_3rd_encoding( $entry->get_buffer->get_text );
|
|
if ( length $translated_nickname < 10 ) {
|
|
$translated_nickname .= chr(0xff);
|
|
my $length = length $translated_nickname;
|
|
$translated_nickname .= ( chr(0x00) ) x ( 10 - $length );
|
|
}
|
|
if ( length $translated_nickname > 10 ) {
|
|
$translated_nickname = substr $translated_nickname, 0, 10;
|
|
}
|
|
$pokemon->nickname($translated_nickname);
|
|
}
|
|
);
|
|
|
|
}
|
|
|
|
sub draw_dropdown_pokemon_list {
|
|
my $self = shift;
|
|
my $box = shift;
|
|
my $pokemon = $self->pokemon;
|
|
my $button_box = Gtk4::Box->new( 'horizontal', 1 );
|
|
my $box_popover = Gtk4::Box->new( 'vertical', 1 );
|
|
my $search_bar = Gtk4::SearchBar->new;
|
|
my $entry_search = Gtk4::SearchEntry->new;
|
|
my $button = Gtk4::ToggleButton->new;
|
|
my $popover_dropdown = Gtk4::Popover->new;
|
|
my $label_pokemon =
|
|
$self->label_pokemon( $pokemon->pokemon_name, $button_box );
|
|
my $scroll = Gtk4::ScrolledWindow->new;
|
|
my $box_pokemons = Gtk4::Box->new( 'vertical', 1 );
|
|
my @species = (@Rsaves::Constants::Emerald::Species::SPECIES);
|
|
|
|
my $func_on_select_dropdown = sub {
|
|
my $number = shift;
|
|
$label_pokemon->set_text( $species[$number] );
|
|
$self->_selected_species($number);
|
|
$popover_dropdown->popdown;
|
|
};
|
|
$entry_search->signal_connect(
|
|
'search-changed' => sub {
|
|
my $box_pokemons = Gtk4::Box->new( 'vertical', 1 );
|
|
$box_pokemons->set_vexpand(1);
|
|
$self->fill_dropdown( $box_pokemons, $func_on_select_dropdown,
|
|
$entry_search->get_text );
|
|
$scroll->set_child($box_pokemons);
|
|
}
|
|
);
|
|
|
|
$button_box->append($label_pokemon);
|
|
$button_box->append( Gtk4::Image->new_from_icon_name('pan-down-symbolic') );
|
|
$button->set_child($button_box);
|
|
$search_bar->set_child($entry_search);
|
|
$search_bar->set_search_mode(1);
|
|
$box_popover->append($search_bar);
|
|
$box_pokemons->set_vexpand(1);
|
|
$self->fill_dropdown( $box_pokemons, $func_on_select_dropdown );
|
|
$scroll->set_child($box_pokemons);
|
|
$box_popover->append($scroll);
|
|
$box_popover->set_vexpand(1);
|
|
$popover_dropdown->set_child($box_popover);
|
|
$button->signal_connect(
|
|
clicked => sub {
|
|
$popover_dropdown->popup;
|
|
}
|
|
);
|
|
$popover_dropdown->set_size_request( 100, 400 );
|
|
$button_box->append($popover_dropdown);
|
|
my $label_button = Gtk4::Label->new('Change species:');
|
|
my $box_dropdown = Gtk4::Box->new( 'horizontal', 10 );
|
|
$box_dropdown->append($label_button);
|
|
$box_dropdown->append($button);
|
|
$box->append($box_dropdown);
|
|
$label_button->set_valign('start');
|
|
$label_button->set_halign('start');
|
|
$button->set_valign('start');
|
|
$button->set_halign('start');
|
|
}
|
|
|
|
sub fill_dropdown {
|
|
my $self = shift;
|
|
my $box = shift;
|
|
my $func = shift;
|
|
my $filter = shift;
|
|
my @species = (@Rsaves::Constants::Emerald::Species::SPECIES);
|
|
for ( my $i = 0 ; $i < scalar @species ; $i++ ) {
|
|
my $number = $i;
|
|
if ( defined $filter
|
|
&& !( index( lc( $species[$i] ), lc($filter) ) >= 0 ) )
|
|
{
|
|
next;
|
|
}
|
|
my $label = Gtk4::Button->new_with_label( $species[$i] );
|
|
my $controller_gesture = Gtk4::GestureClick->new;
|
|
$controller_gesture->set_button(1);
|
|
$controller_gesture->signal_connect(
|
|
pressed => sub {
|
|
$func->($number);
|
|
}
|
|
);
|
|
$label->add_controller($controller_gesture);
|
|
$box->append($label);
|
|
}
|
|
}
|
|
|
|
sub label_pokemon {
|
|
my $self = shift;
|
|
my $name = shift;
|
|
my $button_box = shift;
|
|
my $label = Gtk4::Label->new($name);
|
|
$label->set_hexpand(1);
|
|
$label->set_halign('start');
|
|
return $label;
|
|
}
|
|
1;
|