Compilation: don't compile dialogs separately.
[gnumeric.git] / src / dialogs / dialog-random-generator.c
blobabd05328ff73432bbef6e0512a42d914dea53111
1 /*
2 * dialog-random-generator.c:
4 * Authors:
5 * Jukka-Pekka Iivonen <jiivonen@hutcs.cs.hut.fi>
6 * Andreas J. Guelzow <aguelzow@taliesin.ca>
8 * (C) Copyright 2000, 2001 by Jukka-Pekka Iivonen <jiivonen@hutcs.cs.hut.fi>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <https://www.gnu.org/licenses/>.
24 #include <gnumeric-config.h>
25 #include <glib/gi18n-lib.h>
26 #include <gnumeric.h>
27 #include "dialogs.h"
28 #include "help.h"
29 #include "tool-dialogs.h"
30 #include "random-generator.h"
32 #include <workbook.h>
33 #include <workbook-control.h>
34 #include <wbc-gtk.h>
35 #include <workbook-view.h>
36 #include <gui-util.h>
37 #include <parse-util.h>
38 #include <gnm-format.h>
39 #include <dao-gui-utils.h>
40 #include <sheet.h>
41 #include <expr.h>
42 #include <number-match.h>
43 #include <ranges.h>
44 #include <selection.h>
45 #include <value.h>
46 #include <commands.h>
48 #include <widgets/gnumeric-expr-entry.h>
49 #include <widgets/gnm-dao.h>
51 #include <gtk/gtk.h>
52 #include <string.h>
55 /**********************************************/
56 /* Generic guru items */
57 /**********************************************/
60 #define RANDOM_KEY "analysistools-random-dialog"
62 typedef struct {
63 GnmGenericToolState base;
64 GtkWidget *distribution_grid;
65 GtkWidget *distribution_combo;
66 GtkWidget *par1_label;
67 GtkWidget *par1_entry;
68 GtkWidget *par1_expr_entry;
69 GtkWidget *par2_label;
70 GtkWidget *par2_entry;
71 GtkWidget *vars_entry;
72 GtkWidget *count_entry;
73 random_distribution_t distribution;
74 } RandomToolState;
77 /**********************************************/
78 /* Begin of random tool code */
79 /**********************************************/
81 typedef struct {
82 GtkWidget *dialog;
83 GtkWidget *distribution_grid;
84 GtkWidget *distribution_combo;
85 GtkWidget *par1_label, *par1_entry;
86 GtkWidget *par2_label, *par2_entry;
87 } random_tool_callback_t;
89 /* Name to show in list and parameter labels for a random distribution */
90 typedef struct {
91 random_distribution_t dist;
92 const char *name;
93 const char *label1;
94 const char *label2;
95 gboolean par1_is_range;
96 } DistributionStrs;
98 /* Distribution strings for Random Number Generator */
99 static const DistributionStrs distribution_strs[] = {
100 /* The most commonly used are listed first. I think uniform, gaussian
101 * and discrete are the most commonly used, or what do you think? */
103 { UniformDistribution,
104 N_("Uniform"), N_("_Lower Bound:"), N_("_Upper Bound:"), FALSE },
105 { UniformIntDistribution,
106 N_("Uniform Integer"), N_("_Lower Bound:"), N_("_Upper Bound:"),
107 FALSE },
108 { NormalDistribution,
109 N_("Normal"), N_("_Mean:"), N_("_Standard Deviation:"), FALSE },
110 { DiscreteDistribution,
111 N_("Discrete"), N_("_Value And Probability Input Range:"), NULL,
112 TRUE },
114 /* The others are in alphabetical order. */
116 { BernoulliDistribution,
117 N_("Bernoulli"), N_("_p Value:"), NULL, FALSE },
118 { BetaDistribution,
119 N_("Beta"), N_("_a Value:"), N_("_b Value:"), FALSE },
120 { BinomialDistribution,
121 N_("Binomial"), N_("_p Value:"), N_("N_umber of Trials:"), FALSE },
122 { CauchyDistribution,
123 N_("Cauchy"), N_("_a Value:"), NULL, FALSE },
124 { ChisqDistribution,
125 N_("Chisq"), N_("_nu Value:"), NULL, FALSE },
126 { ExponentialDistribution,
127 N_("Exponential"), N_("_b Value:"), NULL, FALSE },
128 { ExponentialPowerDistribution,
129 N_("Exponential Power"), N_("_a Value:"), N_("_b Value:"), FALSE },
130 { FdistDistribution,
131 N_("F"), N_("nu_1 Value:"), N_("nu_2 Value:"), FALSE },
132 { GammaDistribution,
133 N_("Gamma"), N_("_a Value:"), N_("_b Value:"), FALSE },
134 { GaussianTailDistribution,
135 N_("Gaussian Tail"), N_("_a Value:"), N_("_Sigma"), FALSE },
136 { GeometricDistribution,
137 N_("Geometric"), N_("_p Value:"), NULL, FALSE },
138 { Gumbel1Distribution,
139 N_("Gumbel (Type I)"), N_("_a Value:"), N_("_b Value:"), FALSE },
140 { Gumbel2Distribution,
141 N_("Gumbel (Type II)"), N_("_a Value:"), N_("_b Value:"), FALSE },
142 { LandauDistribution,
143 N_("Landau"), NULL, NULL, FALSE },
144 { LaplaceDistribution,
145 N_("Laplace"), N_("_a Value:"), NULL, FALSE },
146 { LevyDistribution,
147 N_("Levy alpha-Stable"), N_("_c Value:"), N_("_alpha:"), FALSE },
148 { LogarithmicDistribution,
149 N_("Logarithmic"), N_("_p Value:"), NULL, FALSE },
150 { LogisticDistribution,
151 N_("Logistic"), N_("_a Value:"), NULL, FALSE },
152 { LognormalDistribution,
153 N_("Lognormal"), N_("_Zeta Value:"), N_("_Sigma"), FALSE },
154 { NegativeBinomialDistribution,
155 N_("Negative Binomial"), N_("_p Value:"),
156 N_("N_umber of Failures"), FALSE },
157 { ParetoDistribution,
158 N_("Pareto"), N_("_a Value:"), N_("_b Value:"), FALSE },
159 { PoissonDistribution,
160 N_("Poisson"), N_("_Lambda:"), NULL, FALSE },
161 { RayleighDistribution,
162 N_("Rayleigh"), N_("_Sigma:"), NULL, FALSE },
163 { RayleighTailDistribution,
164 N_("Rayleigh Tail"), N_("_a Value:"), N_("_Sigma:"), FALSE },
165 { TdistDistribution,
166 N_("Student t"), N_("nu Value:"), NULL, FALSE },
167 { WeibullDistribution,
168 N_("Weibull"), N_("_a Value:"), N_("_b Value:"), FALSE },
169 { 0, NULL, NULL, NULL, FALSE }
173 * distribution_strs_find
174 * @dist Distribution enum
176 * Find the strings record, given distribution enum.
177 * Returns pointer to strings record.
179 static const DistributionStrs *
180 distribution_strs_find (random_distribution_t dist)
182 int i;
184 for (i = 0; distribution_strs[i].name != NULL; i++)
185 if (distribution_strs[i].dist == dist)
186 return &distribution_strs[i];
188 return &distribution_strs[0];
192 * combo_get_distribution
193 * @combo combo widget with distribution list
195 * Find from combo the distribution the user selected
197 static random_distribution_t
198 combo_get_distribution (GtkWidget *combo)
200 return distribution_strs[gtk_combo_box_get_active (GTK_COMBO_BOX (combo))].dist;
204 * random_tool_update_sensitivity:
205 * @dummy:
206 * @state:
208 * Update the dialog widgets sensitivity if the only items of interest
209 * are the standard input (one range) and output items.
211 static void
212 random_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
213 RandomToolState *state)
215 gboolean ready = FALSE;
216 gint count, vars;
217 gnm_float a_float, b_float, from_val, to_val, p_val;
218 GnmValue *disc_prob_range;
219 random_distribution_t the_dist;
221 the_dist = combo_get_distribution (state->distribution_combo);
223 ready = ((entry_to_int (GTK_ENTRY (state->vars_entry), &vars, FALSE) == 0 &&
224 vars > 0) &&
225 (entry_to_int (GTK_ENTRY (state->count_entry), &count, FALSE) == 0 &&
226 count > 0) &&
227 gnm_dao_is_ready (GNM_DAO (state->base.gdao)));
229 switch (the_dist) {
230 case NormalDistribution:
231 ready = ready && entry_to_float (GTK_ENTRY (state->par1_entry), &a_float,
232 FALSE) == 0 &&
233 entry_to_float (GTK_ENTRY (state->par2_entry), &a_float,
234 FALSE) == 0;
235 break;
236 case BernoulliDistribution:
237 ready = ready &&
238 entry_to_float (GTK_ENTRY (state->par1_entry), &p_val, FALSE) == 0 &&
239 p_val <= 1.0 && p_val > 0.0;
240 break;
241 case BetaDistribution:
242 ready = ready &&
243 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0;
244 ready = ready &&
245 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0;
246 break;
247 case PoissonDistribution:
248 ready = ready &&
249 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
250 a_float > 0.0;
251 break;
252 case ExponentialDistribution:
253 ready = ready &&
254 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
255 a_float > 0.0;
256 break;
257 case ExponentialPowerDistribution:
258 ready = ready &&
259 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
260 a_float > 0.0;
261 ready = ready &&
262 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
263 b_float > 0.0;
264 break;
265 case CauchyDistribution:
266 ready = ready &&
267 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
268 a_float > 0.0;
269 break;
270 case ChisqDistribution:
271 ready = ready &&
272 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
273 a_float > 0.0;
274 break;
275 case LandauDistribution:
276 ready = TRUE;
277 break;
278 case LaplaceDistribution:
279 ready = ready &&
280 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
281 a_float > 0.0;
282 break;
283 case GaussianTailDistribution:
284 ready = ready &&
285 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
286 a_float > 0.0;
287 ready = ready &&
288 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
289 b_float > 0.0;
290 break;
291 case RayleighDistribution:
292 ready = ready &&
293 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
294 a_float > 0.0;
295 break;
296 case RayleighTailDistribution:
297 ready = ready &&
298 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
299 a_float > 0.0;
300 ready = ready &&
301 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
302 b_float > 0.0;
303 break;
304 case ParetoDistribution:
305 ready = ready &&
306 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
307 a_float > 0.0;
308 ready = ready &&
309 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
310 b_float > 0.0;
311 break;
312 case LevyDistribution:
313 ready = ready &&
314 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
315 a_float > 0.0;
316 ready = ready &&
317 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
318 b_float > 0.0;
319 break;
320 case FdistDistribution:
321 ready = ready &&
322 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
323 a_float > 0.0;
324 ready = ready &&
325 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
326 b_float > 0.0;
327 break;
328 case LognormalDistribution:
329 ready = ready &&
330 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
331 a_float > 0.0;
332 ready = ready &&
333 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
334 b_float > 0.0;
335 break;
336 case TdistDistribution:
337 ready = ready &&
338 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
339 a_float > 0.0;
340 break;
341 case WeibullDistribution:
342 ready = ready &&
343 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
344 a_float > 0.0;
345 ready = ready &&
346 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
347 b_float > 0.0;
348 break;
349 case GeometricDistribution:
350 ready = ready &&
351 entry_to_float (GTK_ENTRY (state->par1_entry), &p_val, FALSE) == 0 &&
352 p_val >= 0.0 && p_val <= 1;
353 break;
354 case LogarithmicDistribution:
355 ready = ready &&
356 entry_to_float (GTK_ENTRY (state->par1_entry), &p_val, FALSE) == 0 &&
357 p_val >= 0.0 && p_val <= 1;
358 break;
359 case LogisticDistribution:
360 ready = ready &&
361 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
362 a_float > 0.0;
363 break;
364 case GammaDistribution:
365 ready = ready &&
366 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
367 a_float > 0.0;
368 ready = ready &&
369 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
370 b_float > 0.0;
371 break;
372 case Gumbel1Distribution:
373 case Gumbel2Distribution:
374 ready = ready &&
375 entry_to_float (GTK_ENTRY (state->par1_entry), &a_float, FALSE) == 0 &&
376 a_float > 0.0;
377 ready = ready &&
378 entry_to_float (GTK_ENTRY (state->par2_entry), &b_float, FALSE) == 0 &&
379 b_float > 0.0;
380 break;
381 case BinomialDistribution:
382 ready = ready &&
383 entry_to_float (GTK_ENTRY (state->par1_entry), &p_val, FALSE) == 0 &&
384 entry_to_int (GTK_ENTRY (state->par2_entry), &count, FALSE) == 0 &&
385 p_val <= 1.0 && p_val > 0.0 &&
386 count > 0;
387 break;
388 case NegativeBinomialDistribution:
389 ready = ready &&
390 entry_to_float (GTK_ENTRY (state->par1_entry), &p_val, FALSE) == 0 &&
391 entry_to_int (GTK_ENTRY (state->par2_entry), &count, FALSE) == 0 &&
392 p_val <= 1.0 && p_val > 0.0 &&
393 count > 0;
394 break;
395 case DiscreteDistribution:
396 disc_prob_range = gnm_expr_entry_parse_as_value
397 (GNM_EXPR_ENTRY (state->par1_expr_entry), state->base.sheet);
398 ready = ready && disc_prob_range != NULL;
399 value_release (disc_prob_range);
400 break;
401 case UniformIntDistribution:
402 ready = ready &&
403 entry_to_float (GTK_ENTRY (state->par1_entry), &from_val, FALSE) == 0 &&
404 entry_to_float (GTK_ENTRY (state->par2_entry), &to_val, FALSE) == 0 &&
405 from_val <= to_val;
406 break;
407 case UniformDistribution:
408 default:
409 ready = ready &&
410 entry_to_float (GTK_ENTRY (state->par1_entry), &from_val, FALSE) == 0 &&
411 entry_to_float (GTK_ENTRY (state->par2_entry), &to_val, FALSE) == 0 &&
412 from_val <= to_val;
413 break;
416 gtk_widget_set_sensitive (state->base.apply_button, ready);
417 gtk_widget_set_sensitive (state->base.ok_button, ready);
421 * distribution_parbox_config
422 * @p Callback data
423 * @dist Distribution
425 * Configure parameter widgets given random distribution.
427 * Set labels and accelerators, and hide/show entry fields as needed.
430 static void
431 distribution_parbox_config (RandomToolState *state,
432 random_distribution_t dist)
434 GtkWidget *par1_entry;
435 const DistributionStrs *ds = distribution_strs_find (dist);
437 if (ds->par1_is_range) {
438 par1_entry = state->par1_expr_entry;
439 gtk_widget_hide (state->par1_entry);
440 } else {
441 par1_entry = state->par1_entry;
442 gtk_widget_hide (state->par1_expr_entry);
444 if (ds->label1 != NULL) {
445 gtk_label_set_text_with_mnemonic (GTK_LABEL (state->par1_label),
446 _(ds->label1));
447 gtk_label_set_mnemonic_widget (GTK_LABEL (state->par1_label),
448 par1_entry);
449 gtk_widget_show (par1_entry);
450 } else {
451 gtk_label_set_text (GTK_LABEL (state->par1_label), "");
452 gtk_widget_hide (par1_entry);
455 if (ds->label2 != NULL) {
456 gtk_label_set_text_with_mnemonic (GTK_LABEL (state->par2_label),
457 _(ds->label2));
458 gtk_label_set_mnemonic_widget (GTK_LABEL (state->par2_label),
459 state->par2_entry);
460 gtk_widget_show (state->par2_entry);
461 } else {
462 gtk_label_set_text (GTK_LABEL (state->par2_label), "");
463 gtk_widget_hide (state->par2_entry);
468 * distribution_callback
469 * @widget Not used
470 * @p Callback data
472 * Configure the random distribution parameters widgets for the distribution
473 * which was selected.
475 static void
476 distribution_callback (G_GNUC_UNUSED GtkWidget *widget,
477 RandomToolState *state)
479 random_distribution_t dist;
481 dist = combo_get_distribution (state->distribution_combo);
482 distribution_parbox_config (state, dist);
487 * dialog_random_realized:
488 * @widget
489 * @state:
491 * Make initial geometry of distribution table permanent.
493 * The dialog is constructed with the distribution_grid containing the widgets
494 * which need the most space. At construction time, we do not know how large
495 * the distribution_grid needs to be, but we do know when the dialog is
496 * realized. This callback for "realized" makes this size the user specified
497 * size so that the table will not shrink when we later change label texts and
498 * hide/show widgets.
501 static void
502 dialog_random_realized (GtkWidget *widget, RandomToolState *state)
504 GtkWidget *t = state->distribution_grid;
505 GtkWidget *l = state->par1_label;
506 GtkAllocation a;
508 gtk_widget_get_allocation (t, &a);
509 gtk_widget_set_size_request (t, a.width, a.height);
511 gtk_widget_get_allocation (l, &a);
512 gtk_widget_set_size_request (l, a.width, a.height);
514 distribution_callback (widget, state);
519 * random_tool_ok_clicked_cb:
520 * @button:
521 * @state:
523 * Retrieve the information from the dialog and call the appropriate tool.
524 * Note that we assume that the ok_button is only active if the entry fields
525 * contain sensible data.
527 static void
528 random_tool_ok_clicked_cb (GtkWidget *button, RandomToolState *state)
530 data_analysis_output_t *dao;
531 tools_data_random_t *data;
533 gint err;
535 data = g_new0 (tools_data_random_t, 1);
536 dao = parse_output ((GnmGenericToolState *)state, NULL);
538 data->wbc = GNM_WBC (state->base.wbcg);
540 err = entry_to_int (GTK_ENTRY (state->vars_entry), &data->n_vars, FALSE);
541 err = entry_to_int (GTK_ENTRY (state->count_entry), &data->count, FALSE);
543 data->distribution = state->distribution =
544 combo_get_distribution (state->distribution_combo);
545 switch (state->distribution) {
546 case NormalDistribution:
547 err = entry_to_float (GTK_ENTRY (state->par1_entry),
548 &data->param.normal.mean, TRUE);
549 err = entry_to_float (GTK_ENTRY (state->par2_entry),
550 &data->param.normal.stdev, TRUE);
551 break;
552 case BernoulliDistribution:
553 err = entry_to_float (GTK_ENTRY (state->par1_entry),
554 &data->param.bernoulli.p, TRUE);
555 break;
556 case BetaDistribution:
557 err = entry_to_float (GTK_ENTRY (state->par1_entry),
558 &data->param.beta.a, TRUE);
559 err = entry_to_float (GTK_ENTRY (state->par1_entry),
560 &data->param.beta.b, TRUE);
561 break;
562 case PoissonDistribution:
563 err = entry_to_float (GTK_ENTRY (state->par1_entry),
564 &data->param.poisson.lambda, TRUE);
565 break;
566 case ExponentialDistribution:
567 err = entry_to_float (GTK_ENTRY (state->par1_entry),
568 &data->param.exponential.b, TRUE);
569 break;
570 case ExponentialPowerDistribution:
571 err = entry_to_float (GTK_ENTRY (state->par1_entry),
572 &data->param.exppow.a, TRUE);
573 err = entry_to_float (GTK_ENTRY (state->par2_entry),
574 &data->param.exppow.b, TRUE);
575 break;
576 case CauchyDistribution:
577 err = entry_to_float (GTK_ENTRY (state->par1_entry),
578 &data->param.cauchy.a, TRUE);
579 break;
580 case LandauDistribution:
581 break;
582 case LaplaceDistribution:
583 err = entry_to_float (GTK_ENTRY (state->par1_entry),
584 &data->param.laplace.a, TRUE);
585 break;
586 case GaussianTailDistribution:
587 err = entry_to_float (GTK_ENTRY (state->par1_entry),
588 &data->param.gaussian_tail.a, TRUE);
589 err = entry_to_float (GTK_ENTRY (state->par2_entry),
590 &data->param.gaussian_tail.sigma, TRUE);
591 break;
592 case ChisqDistribution:
593 err = entry_to_float (GTK_ENTRY (state->par1_entry),
594 &data->param.chisq.nu, TRUE);
595 break;
596 case LogarithmicDistribution:
597 err = entry_to_float (GTK_ENTRY (state->par1_entry),
598 &data->param.logarithmic.p, TRUE);
599 break;
600 case LogisticDistribution:
601 err = entry_to_float (GTK_ENTRY (state->par1_entry),
602 &data->param.logistic.a, TRUE);
603 break;
604 case RayleighDistribution:
605 err = entry_to_float (GTK_ENTRY (state->par1_entry),
606 &data->param.rayleigh.sigma, TRUE);
607 break;
608 case RayleighTailDistribution:
609 err = entry_to_float (GTK_ENTRY (state->par1_entry),
610 &data->param.rayleigh_tail.a, TRUE);
611 err = entry_to_float (GTK_ENTRY (state->par2_entry),
612 &data->param.rayleigh_tail.sigma, TRUE);
613 break;
614 case LognormalDistribution:
615 err = entry_to_float (GTK_ENTRY (state->par1_entry),
616 &data->param.lognormal.zeta, TRUE);
617 err = entry_to_float (GTK_ENTRY (state->par2_entry),
618 &data->param.lognormal.sigma, TRUE);
619 break;
620 case LevyDistribution:
621 err = entry_to_float (GTK_ENTRY (state->par1_entry),
622 &data->param.levy.c, TRUE);
623 err = entry_to_float (GTK_ENTRY (state->par2_entry),
624 &data->param.levy.alpha, TRUE);
625 break;
626 case FdistDistribution:
627 err = entry_to_float (GTK_ENTRY (state->par1_entry),
628 &data->param.fdist.nu1, TRUE);
629 err = entry_to_float (GTK_ENTRY (state->par2_entry),
630 &data->param.fdist.nu2, TRUE);
631 break;
632 case ParetoDistribution:
633 err = entry_to_float (GTK_ENTRY (state->par1_entry),
634 &data->param.pareto.a, TRUE);
635 err = entry_to_float (GTK_ENTRY (state->par2_entry),
636 &data->param.pareto.b, TRUE);
637 break;
638 case TdistDistribution:
639 err = entry_to_float (GTK_ENTRY (state->par1_entry),
640 &data->param.tdist.nu, TRUE);
641 break;
642 case WeibullDistribution:
643 err = entry_to_float (GTK_ENTRY (state->par1_entry),
644 &data->param.weibull.a, TRUE);
645 err = entry_to_float (GTK_ENTRY (state->par2_entry),
646 &data->param.weibull.b, TRUE);
647 break;
648 case GeometricDistribution:
649 err = entry_to_float (GTK_ENTRY (state->par1_entry),
650 &data->param.geometric.p, TRUE);
651 break;
652 case GammaDistribution:
653 err = entry_to_float (GTK_ENTRY (state->par1_entry),
654 &data->param.gamma.a, TRUE);
655 err = entry_to_float (GTK_ENTRY (state->par2_entry),
656 &data->param.gamma.b, TRUE);
657 break;
658 case Gumbel1Distribution:
659 case Gumbel2Distribution:
660 err = entry_to_float (GTK_ENTRY (state->par1_entry),
661 &data->param.gumbel.a, TRUE);
662 err = entry_to_float (GTK_ENTRY (state->par2_entry),
663 &data->param.gumbel.b, TRUE);
664 break;
665 case BinomialDistribution:
666 err = entry_to_float (GTK_ENTRY (state->par1_entry),
667 &data->param.binomial.p, TRUE);
668 err = entry_to_int (GTK_ENTRY (state->par2_entry),
669 &data->param.binomial.trials, TRUE);
670 break;
671 case NegativeBinomialDistribution:
672 err = entry_to_float (GTK_ENTRY (state->par1_entry),
673 &data->param.negbinom.p, TRUE);
674 err = entry_to_int (GTK_ENTRY (state->par2_entry),
675 &data->param.negbinom.f, TRUE);
676 break;
677 case DiscreteDistribution:
678 data->param.discrete.range = gnm_expr_entry_parse_as_value (
679 GNM_EXPR_ENTRY (state->par1_expr_entry),
680 state->base.sheet);
681 break;
682 case UniformIntDistribution:
683 err = entry_to_float (GTK_ENTRY (state->par1_entry),
684 &data->param.uniform.lower_limit, TRUE);
685 err = entry_to_float (GTK_ENTRY (state->par2_entry),
686 &data->param.uniform.upper_limit, TRUE);
687 break;
688 case UniformDistribution:
689 default:
690 err = entry_to_float (GTK_ENTRY (state->par1_entry),
691 &data->param.uniform.lower_limit, TRUE);
692 err = entry_to_float (GTK_ENTRY (state->par2_entry),
693 &data->param.uniform.upper_limit, TRUE);
694 break;
697 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg),
698 state->base.sheet,
699 dao, data, tool_random_engine, TRUE) &&
700 (button == state->base.ok_button))
701 gtk_widget_destroy (state->base.dialog);
705 * dialog_random_tool_init:
706 * @state:
708 * Create the dialog (guru).
711 static void
712 dialog_random_tool_init (RandomToolState *state)
714 int i, dist_str_no;
715 const DistributionStrs *ds;
716 /* GList *distribution_type_strs = NULL;*/
717 GtkGrid *grid;
718 GtkListStore *store;
719 GtkTreeIter iter;
720 GtkCellRenderer *renderer;
721 GnmRange const *first;
723 state->distribution = UniformDistribution;
725 state->distribution_grid = go_gtk_builder_get_widget (state->base.gui,
726 "distribution-grid");
727 state->distribution_combo = go_gtk_builder_get_widget (state->base.gui,
728 "distribution_combo");
729 state->par1_entry = go_gtk_builder_get_widget (state->base.gui, "par1_entry");
730 state->par1_label = go_gtk_builder_get_widget (state->base.gui, "par1_label");
731 state->par2_label = go_gtk_builder_get_widget (state->base.gui, "par2_label");
732 state->par2_entry = go_gtk_builder_get_widget (state->base.gui, "par2_entry");
733 state->vars_entry = go_gtk_builder_get_widget (state->base.gui, "vars_entry");
734 state->count_entry = go_gtk_builder_get_widget (state->base.gui, "count_entry");
735 int_to_entry (GTK_ENTRY (state->count_entry), 1);
737 renderer = (GtkCellRenderer*) gtk_cell_renderer_text_new();
738 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (state->distribution_combo), renderer, TRUE);
739 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (state->distribution_combo), renderer,
740 "text", 0,
741 NULL);
742 store = gtk_list_store_new (1, G_TYPE_STRING);
743 gtk_combo_box_set_model (GTK_COMBO_BOX (state->distribution_combo),
744 GTK_TREE_MODEL (store));
745 g_object_unref (store);
746 for (i = 0, dist_str_no = 0; distribution_strs[i].name != NULL; i++) {
747 gtk_list_store_append (store, &iter);
748 gtk_list_store_set (store, &iter,
749 0, _(distribution_strs[i].name),
750 -1);
751 if (distribution_strs[i].dist == state->distribution)
752 dist_str_no = i;
754 gtk_combo_box_set_active (GTK_COMBO_BOX (state->distribution_combo),
755 dist_str_no);
757 ds = distribution_strs_find (UniformDistribution);
758 gtk_label_set_text_with_mnemonic (GTK_LABEL (state->par1_label),
759 _(ds->label1));
761 g_signal_connect (state->distribution_combo,
762 "changed",
763 G_CALLBACK (distribution_callback), state);
764 g_signal_connect (state->distribution_combo,
765 "changed",
766 G_CALLBACK (random_tool_update_sensitivity_cb), state);
768 grid = GTK_GRID (go_gtk_builder_get_widget (state->base.gui, "distribution-grid"));
769 state->par1_expr_entry = GTK_WIDGET (gnm_expr_entry_new (state->base.wbcg, TRUE));
770 gnm_expr_entry_set_flags (GNM_EXPR_ENTRY (state->par1_expr_entry),
771 GNM_EE_SINGLE_RANGE, GNM_EE_MASK);
772 gtk_widget_set_hexpand (state->par1_expr_entry, TRUE);
773 gtk_grid_attach (grid, state->par1_expr_entry, 1, 1, 1, 1);
774 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
775 GTK_WIDGET (state->par1_expr_entry));
777 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
778 GTK_WIDGET (state->par1_entry));
779 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
780 GTK_WIDGET (state->par2_entry));
781 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
782 GTK_WIDGET (state->vars_entry));
783 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
784 GTK_WIDGET (state->count_entry));
786 g_signal_connect (G_OBJECT (state->base.dialog),
787 "realize",
788 G_CALLBACK (dialog_random_realized), state);
789 g_signal_connect_after (G_OBJECT (state->vars_entry),
790 "changed",
791 G_CALLBACK (random_tool_update_sensitivity_cb), state);
792 g_signal_connect_after (G_OBJECT (state->count_entry),
793 "changed",
794 G_CALLBACK (random_tool_update_sensitivity_cb), state);
795 g_signal_connect_after (G_OBJECT (state->par1_entry),
796 "changed",
797 G_CALLBACK (random_tool_update_sensitivity_cb), state);
798 g_signal_connect_after (G_OBJECT (state->par2_entry),
799 "changed",
800 G_CALLBACK (random_tool_update_sensitivity_cb), state);
801 g_signal_connect_after (G_OBJECT (state->par1_expr_entry),
802 "changed",
803 G_CALLBACK (random_tool_update_sensitivity_cb), state);
805 first = selection_first_range (state->base.sv, NULL, NULL);
806 if (first != NULL) {
807 dialog_tool_preset_to_range (&state->base);
808 int_to_entry (GTK_ENTRY (state->count_entry),
809 first->end.row - first->start.row + 1);
810 int_to_entry (GTK_ENTRY (state->vars_entry),
811 first->end.col - first->start.col + 1);
814 random_tool_update_sensitivity_cb (NULL, state);
819 * dialog_random_tool:
820 * @wbcg:
821 * @sheet:
823 * Show the dialog (guru).
827 dialog_random_tool (WBCGtk *wbcg, Sheet *sheet)
829 RandomToolState *state;
831 if (wbcg == NULL) {
832 return 1;
836 /* Only pop up one copy per workbook */
837 if (gnm_dialog_raise_if_exists (wbcg, RANDOM_KEY)) {
838 return 0;
841 state = g_new (RandomToolState, 1);
843 if (dialog_tool_init ((GnmGenericToolState *)state, wbcg, sheet,
844 GNUMERIC_HELP_LINK_RANDOM_GENERATOR,
845 "res:ui/random-generation.ui", "Random",
846 _("Could not create the Random Tool dialog."),
847 RANDOM_KEY,
848 G_CALLBACK (random_tool_ok_clicked_cb), NULL,
849 G_CALLBACK (random_tool_update_sensitivity_cb),
851 return 0;
854 gnm_dao_set_put (GNM_DAO (state->base.gdao), FALSE, FALSE);
855 dialog_random_tool_init (state);
856 gtk_widget_show (state->base.dialog);
858 return 0;