Fran├žois Rappaz
and 1 contributors

sub SetPlData_todel { my ( $self, $row, $col, $data ) = @_;

    $self->{log}->logcroak("Array out of bounds")
      unless ( $row < $self->GetNumberRows && $col < $self->GetNumberCols );
    $$self{array}->[$row][$col]->SetPlData($data);
}

sub CanSetValueAs_todel { my ( $self, $row, $col, $type ) = @_; $self->{log}->debug("CanSetValueAs called with type $type"); return 1 if ( $row < $self->GetNumberRows && $col < $self->GetNumberCols ); return 0; }

sub CanGetValueAs_todel { my $self = shift; return $self->CanSetValueAs(@_); }

NAME

Wx::Perl::DbLinker::Wxdatasheet - a module that display data from a database in a tabular format using a WxGrid object

VERSION

See Version in Wx::Perl::DbLinker

SYNOPSIS

The code build a table having 6 columns: 3 text entries, 2 combo, 1 toogle. A dataManager object is needed for each combo, and a dataManager for the table itself. The example here use Rose::DB::Object to access the tables.

This gets the RdbDataManager that will populate the datasheet

        my $datasheet_rows = Gtk2::Ex::DbLinker::DbcDataManager->new(
                rs => $self->{schema}->resultset('Speak')->search_rs(
                        {langid => $self->{langid}, countryid => {'!=' => $self->{countryid} }}
                                                                )
                                ); 

If the grid hold combo(s), the RdbDataManagers for those combo rows are created:

                 $combodata = Gtk2::Ex::DbLinker::DbcDataManager->new(
                                rs => $self->{schema}->resultset('Country')->search_rs(undef, { order_by => 'country'} ),
                        );
They will be passed as parameters when C< Wx::Perl::DbLinker::Wxdatasheet->new()> is called.

The Wxdatasheet object with the columns description is created:

        my $grid = Wx::Perl::DbLinker::Wxdatasheet->new( 
                parent_widget=>$scrolledwindow, 
                fields => [
                                {name=>"countryid",
                                        renderer => "combo",    header_markup => "Country", data_manager=> $combodata, fieldnames => ["countryid", "country"],
                                        },      
                                   {name=>"langid", renderer=>"hidden"},

                                ],
                        after_update => => sub{ on_after_update($self, $self->{sf_list}->{dnav}, $list, "grid"); },
                borders_size => [20, 25], #horizontal: row_1: heigth, vertical : col_1: witdh

            );

$scrolledwindow is the widget that will received the grid. It is created before the grid creation:

       #$where_name is the name of the panel that will receive the grid
        my $where = Wx::Window::FindWindowById( Wx::XmlResource::GetXRCID($where_name), $top_panel );
        my $s = $where->GetSizer();
        $s = ( defined $s ? $s :  Wx::BoxSizer->new(wxVERTICAL));
        my $scrolledwindow = Wx::ScrolledWindow->new($where, wxID_ANY); #,    Wx::Point->new(0, 0), Wx::Size->new(400, 400),  wxVSCROLL | wxHSCROLL); 
        $scrolledwindow->SetScrollbars(1,1,1,1);
        $s->Add($scrolledwindow, 1, wxALL|wxEXPAND, 1);
        $where->SetSizer($s);

Once the grid has been created, it is added to $scrolledwindow:

        $s = Wx::BoxSizer->new(wxVERTICAL);
        $scrolledwindow->SetSizer($s);
        $s->Add($grid, 1, wxALL|wxEXPAND, 1);

To change the rows displayed in the table, the new set of rows is fetched. An object derived from Rose::DB::Object::Manager is passed to the Gt2::Ex::DbLinker::RdbDatamanager object using the query method:

        $grid->get_data_manager->query( $self->{schema}->resultset('Speak')->search_rs({langid => $new_value, countryid => {'!=' => $self->{countryid}} })  );
        $grid->update;

DESCRIPTION

This module automates the process of setting up a WxGrid based on field definitions you pass it. The first column show the state of the reccord : - blank : unchanged - ! : changed and not saved to the database - x : mark for deletion - o : locked

Steps for use:

  • Instanciate a xxxDataManager that will fetch a set of rows.

  • Get a reference to the Wx::Pane that will received the grid, add a Wx::ScrolledWindow using sizer.

  • Create a xxxDataManager holding the rows to display, if the datasheet has combo box, create the corresponding DataManager that hold the combo box content.

  • Create a Wxdatasheet object and pass it the following parameters: the scrolledwindow and a hash reference. The constructor return the Wx::Grid object that. Add the grid to the scrolledwindow using a sizer.

    You would then typically connect some buttons to methods such as inserting, deleting, etc.

METHODS

constructor

The new() method expects a list of parameters name and value or a hash reference of parameters name (keys) / value pairs.

The parameters are:

  • parent_widget a Wx::window object

  • data_manager a instance of a xxxDataManager object to populate the grid.

  • on_changed a code ref that will be called when a value is changed in the grid

  • on_row_select a code ref that will be called when a row is selected

  • border_size an array ref that holds the height of the field labels row and the width of the left column that displays the records state

  • fields a reference to an array of hash. Each hash defined a field, and has the following key / value pairs:

    • name / name of the field to display.

    • renderer / one of "text combo toggle hidden".

    • renderer_function for text render, a coderef can be pass to set the cell value. The function will received the row and column number and the base table object. For example, this method

                      sub display_url {
                              my ($self, $row, $col, $table) =@_;
                              my $column_no = $self->{foo}->colnumber_from_name( "fooid" ); # the column where a value is taken from
                              my $key_value = $table->GetValue($row, $column_no );
                              my $result="";
                              if ($key_value) {
                                      $result = "http://somewhere/on_the_internet/record.cgi?&fooid=" . $key_value;
                              } 
                              return $result;
                      }

      It can be passed to the Wxdatasheet constructor with

                      { fields =>  [{name=>"bar", renderer=>"text"},
                              {name=>"fooid"}, 
                              {name=>"url", renderer=>"text", renderer_function => sub {display_url ($self, @_);}},
                                   ], 
                        data_manager =>  ...
                        }

    if the renderer is a combo (Wx::ComboBox or Wx::ListBox) the following key / values are needed in the same hash reference:

    • data_manager / an instance holding the rows of the combo.

    • fieldnames / a reference to an array of the fields that populate the combo. The first one is the return value that correspond to the field given in name.

update();

Reflect in the user interface the changes made after the data manager has been queried, or on the datasheet creation.

get_data_manager();

Returns the data manager to be queried.

set_column_value($field_name, $value);

Set $value in $field_name for the grid current row (where the cursor is).

get_column_value($field_name);

Return the content of $field_name for the grid current row.

Methods applied to a row of data:

  • insert();

    Displays an empty rows.

  • delete();

    Marks the current row to be deleted. The delele itself will be done on apply.

  • apply();

    Create a new row in the DataManager and fetchs the values from the grid, and add this row to the database. Save changes on an existing row, or delete the row(s) marked for deletion. An array ref of fields name can be given to prevent these from being saved. This is usefull to change the row flag from modified to unmodif when the change are saved directly with the DataManager.

  • undo();

    Revert the row to the original state in displaying the values fetch from the database.

SUPPORT

Any Wx::Perl::DbLinker questions or problems can be posted to me (rappazf) on my gmail account.

The current state of the source can be extract using Mercurial from http://sourceforge.net/projects/wx-perl-dblinker/.

AUTHOR

François Rappaz <rappazf@gmail.com>

COPYRIGHT AND LICENSE

Copyright (c) 2016-2017 by François Rappaz. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.