App-InvestSim

 view release on metacpan or  search on metacpan

lib/App/InvestSim/GUI.pm  view on Meta::CPAN

# reference that gets the beautified content of the field.
sub setup_entry {
  my ($widget, $var, $format, $validate, $textvar) = @_;
  my $right_justified = (Tkx::SplitList($widget->m_configure('-justify')))[-1] eq 'right';
  my $refresh = sub {
    $widget->m_delete(0, 'end');
    $widget->m_insert(0, $format->($$var));
    $$textvar = $format->($$var) if $textvar;
  };
  push @all_refresh_actions, $refresh;
  $widget->g_bind("<FocusIn>", sub { focus_in_field($widget, $var, $right_justified) });
  $widget->g_bind("<FocusOut>", sub { focus_out_field($widget, $var, $right_justified, $refresh) });
  # The validation function will receive the new string and the event 'key' or
  # 'forced' (could be 'focusin' or 'focusout' but we don't validate on these
  # event).
  $widget->m_configure(-validate => 'none', -validatecommand => [ sub { $has_changes = 1; $validate->(@_) }, Tkx::Ev('%P', '%V')]);
}

my $currently_selected;
sub set_core_table_selected_state {
  my ($widget) = @_;
  $currently_selected->m_state('!selected') if $currently_selected;

lib/App/InvestSim/GUI.pm  view on Meta::CPAN

  $modes[INVESTMENT_RETURN] = "Rendement de l'opération";
  $modes_format[INVESTMENT_RETURN] = \&format_percent;
  {
    my $frame = $root->new_ttk__frame(-padding => 5);
    $frame->g_grid(-column => 1, -row => 1, -sticky => "nwes");
    $frame->g_grid_columnconfigure(0, -weight => 1); # So that it extends to the whole width.

    $modes_combobox = $frame->new_ttk__combobox(-state => 'readonly', -values => \@modes, -justify => 'center');
    $modes_combobox->g_grid(-column => 0, -row => 0, -sticky => "we");
    $modes_combobox->m_current(MONTHLY_PAYMENT);
    $modes_combobox->g_bind('<<ComboboxSelected>>', \&update_displayed_mode);
  }

  # Build the core table with the computation output.
  {
    my $frame = $root->new_ttk__frame(-padding => 3);
    $frame->g_grid(-column => 1, -row => 2, -sticky => "nwes");
     # So that it extends to the same width as column 0 of the top bar. All other
     # columns have a fixed width that is the same as the matching column in the
     # top bar.
    $frame->g_grid_columnconfigure(0, -weight => 1);

lib/App/InvestSim/GUI.pm  view on Meta::CPAN

      my $w = $frame->new_ttk__entry(-width => ENTRY_WIDTH, -justify => 'right');
      $w->g_grid(-column => 0, -row => $j + 1, -sticky => "we");
      setup_entry($w, \$loan_amounts->[$j], \&format_euro, $validate_amount);
    }
    for my $i (0..NUM_LOAN_DURATION-1) {
      for my $j (0..NUM_LOAN_AMOUNT-1) {
        my $e = $frame->new_ttk__entry(-width => ENTRY_WIDTH, -textvariable => \$core_display_values[$i][$j],
                                       -state => 'readonly', -justify => 'right', -takefocus => 0,
                                       -style => 'DataTable.TEntry');
        $e->g_grid(-column => $i + 1, -row => $j + 1, -sticky => "we");
        $e->g_bind('<FocusIn>', sub { set_core_table_selected_state($e);
                                      update_displayed_table($i, $j) });
      }
    }
  }

  # Build the right bar with some other input values and the output values not 
  # depending on the loan parameters.
  {
    my $frame = $root->new_ttk__frame(-padding => 3);
    $frame->g_grid(-column => 2, -row => 0, -rowspan => 3, -sticky => "we");

lib/App/InvestSim/GUI.pm  view on Meta::CPAN

  }

  # Finally, we create a small menu.
  {
    my $menu = $root->new_menu;
    $root->configure(-menu => $menu);
    my $file = $menu->new_menu;
    $menu->m_add_cascade(-menu => $file, -label => "Fichier", -underline => 0);
    $file->m_add_command(-label => "Nouveau", -accelerator => 'Ctrl+N', -underline => 0,
                         -command => sub { init_values(); refresh_all_fields() });
    $root->g_bind('<Control-n>', sub { init_values(); refresh_all_fields() });
    $file->m_add_command(-label => "Ouvrir...", -accelerator => 'Ctrl+O', -underline => 0,
                         -command => sub { open_values(); refresh_all_fields() });
    $root->g_bind('<Control-o>', sub { open_values(); refresh_all_fields() });
    $file->m_add_command(-label => "Enregistrer", -accelerator => 'Ctrl+S', -underline => 0, -command => \&save_values);
    $root->g_bind('<Control-s>', \&save_values);
    $file->m_add_command(-label => "Enregistrer sous...", -accelerator => 'Ctrl+Alt+S',  -underline => 12,-command => \&save_values_as);
    $root->g_bind('<Control-Alt-s>', \&save_values_as);
    $file->add_separator();
    $file->m_add_command(-label => "Quitter", -accelerator => 'Alt+F4',  -underline => 0,-command => sub { $root->g_destroy() });
    # The binding for Alt-F4 is automatically supplied by Windows and can't be
    # overriden. It will destroy the window. We catch it as well as the menu entry
    # using the following bind command.
    # If we bind to $root, then the event triggers for all contained widget.
    $root->g_bind('<Destroy>', [sub { autosave() if $_[0] eq '.' }, Tkx::Ev('%W')]);

    my $options = $menu->new_menu;
    $menu->m_add_cascade(-menu => $options, -label => "Options", -underline => 0);
    my $automatic_duration = \$values{automatic_duration};
    $options->m_add_checkbutton(-label => "Durée automatique", -variable => $automatic_duration, -onvalue => 1, -offvalue => 0, -accelerator => 'Ctrl+D');
    $root->g_bind('<Control-d>', sub { $$automatic_duration = 1 - $$automatic_duration });

    my $taxes = $menu->new_menu;
    $menu->m_add_cascade(-menu => $taxes, -label => "Fiscalité", -underline => 1);
    my $pinel_menu = $taxes->new_menu;
    my @pinel_zone = ('Zone A bis', 'Zone A', 'Zone B1', 'Zone B2');
    my $disable_pinel_zone = sub {  
      for my $z (@pinel_zone) {
        $pinel_menu->m_entryconfigure($z, -state => 'disabled');
      }
    };

lib/App/InvestSim/GUI.pm  view on Meta::CPAN

    
    my $pinel_zone = \$values{pinel_zone};
    for my $i (0..$#pinel_zone) {
      $pinel_menu->add_radiobutton(-label => $pinel_zone[$i], -variable => $pinel_zone,
                                   -value => $i, -command => \&calculate_all);
    }
  }

  # When Return is pressed, we first move the focus, to force a re-computation of
  # the variables holding behind the currently edited field, if any.
  $root->g_bind('<Return>', sub {
      Tkx::focus('.');
      calculate_all();
    });

  # We're done, we can show the UI.
  $root->g_wm_deiconify();
}

# Update the values displayed in the core value table.
my @computed_values; # The output of compute_all()



( run in 1.222 second using v1.01-cache-2.11-cpan-2398b32b56e )