2 Widget based utility functions.
4 Copyright (C) 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
5 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
6 The Free Software Foundation, Inc.
9 Miguel de Icaza, 1994, 1995, 1996
10 Radek Doulik, 1994, 1995
12 Andrej Borsenkow, 1995
13 Andrew Borodin <aborodin@vmail.ru>, 2009, 2010, 2011, 2012
15 This file is part of the Midnight Commander.
17 The Midnight Commander is free software: you can redistribute it
18 and/or modify it under the terms of the GNU General Public License as
19 published by the Free Software Foundation, either version 3 of the License,
20 or (at your option) any later version.
22 The Midnight Commander is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with this program. If not, see <http://www.gnu.org/licenses/>.
32 * \brief Source: quick dialog engine
38 #include <stdio.h> /* fprintf() */
40 #include "lib/global.h"
41 #include "lib/strutil.h" /* str_term_width1() */
42 #include "lib/util.h" /* tilde_expand() */
43 #include "lib/widget.h"
45 /*** global variables ****************************************************************************/
47 /*** file scope macro definitions ****************************************************************/
50 #define I18N(x) (x = x != NULL && *x != '\0' ? _(x) : x)
52 #define I18N(x) (x = x)
55 /*** file scope type declarations ****************************************************************/
60 quick_widget_t
*quick_widget
;
61 } quick_widget_item_t
;
63 /*** file scope variables ************************************************************************/
65 /* --------------------------------------------------------------------------------------------- */
66 /*** file scope functions ************************************************************************/
67 /* --------------------------------------------------------------------------------------------- */
70 quick_create_input (int y
, int x
, const quick_widget_t
* qw
)
74 in
= input_new (y
, x
, input_get_default_colors (), 8, qw
->u
.input
.text
, qw
->u
.input
.histname
,
75 qw
->u
.input
.completion_flags
);
77 in
->is_password
= qw
->u
.input
.is_passwd
;
78 in
->strip_password
= qw
->u
.input
.strip_passwd
;
83 /* --------------------------------------------------------------------------------------------- */
86 quick_create_labeled_input (GArray
* widgets
, int *y
, int x
, quick_widget_t
* quick_widget
,
89 quick_widget_item_t in
, label
;
91 label
.quick_widget
= g_new0 (quick_widget_t
, 1);
92 label
.quick_widget
->widget_type
= quick_label
;
93 label
.quick_widget
->options
= quick_widget
->options
;
94 /* FIXME: this should be turned in depend of label_location */
95 label
.quick_widget
->pos_flags
= quick_widget
->pos_flags
;
97 switch (quick_widget
->u
.input
.label_location
)
99 case input_label_above
:
100 label
.widget
= WIDGET (label_new (*y
, x
, I18N (quick_widget
->u
.input
.label_text
)));
101 *y
+= label
.widget
->lines
- 1;
102 g_array_append_val (widgets
, label
);
104 in
.widget
= WIDGET (quick_create_input (++(*y
), x
, quick_widget
));
105 in
.quick_widget
= quick_widget
;
106 g_array_append_val (widgets
, in
);
108 *width
= max (label
.widget
->cols
, in
.widget
->cols
);
111 case input_label_left
:
112 label
.widget
= WIDGET (label_new (*y
, x
, I18N (quick_widget
->u
.input
.label_text
)));
113 g_array_append_val (widgets
, label
);
115 in
.widget
= WIDGET (quick_create_input (*y
, x
+ label
.widget
->cols
+ 1, quick_widget
));
116 in
.quick_widget
= quick_widget
;
117 g_array_append_val (widgets
, in
);
119 *width
= label
.widget
->cols
+ in
.widget
->cols
+ 1;
122 case input_label_right
:
123 in
.widget
= WIDGET (quick_create_input (*y
, x
, quick_widget
));
124 in
.quick_widget
= quick_widget
;
125 g_array_append_val (widgets
, in
);
129 (*y
, x
+ in
.widget
->cols
+ 1, I18N (quick_widget
->u
.input
.label_text
)));
130 g_array_append_val (widgets
, label
);
132 *width
= label
.widget
->cols
+ in
.widget
->cols
+ 1;
135 case input_label_below
:
136 in
.widget
= WIDGET (quick_create_input (*y
, x
, quick_widget
));
137 in
.quick_widget
= quick_widget
;
138 g_array_append_val (widgets
, in
);
140 label
.widget
= WIDGET (label_new (++(*y
), x
, I18N (quick_widget
->u
.input
.label_text
)));
141 *y
+= label
.widget
->lines
- 1;
142 g_array_append_val (widgets
, label
);
144 *width
= max (label
.widget
->cols
, in
.widget
->cols
);
151 INPUT (in
.widget
)->label
= LABEL (label
.widget
);
152 /* cross references */
153 label
.quick_widget
->u
.label
.input
= in
.quick_widget
;
154 in
.quick_widget
->u
.input
.label
= label
.quick_widget
;
157 /* --------------------------------------------------------------------------------------------- */
158 /*** public functions ****************************************************************************/
159 /* --------------------------------------------------------------------------------------------- */
162 quick_dialog_skip (quick_dialog_t
* quick_dlg
, int nskip
)
166 int x
, y
; /* current positions */
167 int y1
= 0; /* bottom of 1st column in case of two columns */
168 int y2
= -1; /* start of two columns */
169 int width1
= 0; /* width of single column */
170 int width2
= 0; /* width of each of two columns */
171 gboolean have_groupbox
= FALSE
;
172 gboolean two_columns
= FALSE
;
173 gboolean put_buttons
= FALSE
;
175 /* x position of 1st column is 3 */
177 /* x position of 2nd column is 4 and it will be fixed later, after creation of all widgets */
182 quick_widget_t
*quick_widget
;
187 len
= str_term_width1 (I18N (quick_dlg
->title
)) + 6;
188 quick_dlg
->cols
= max (quick_dlg
->cols
, len
);
194 widgets
= g_array_sized_new (FALSE
, FALSE
, sizeof (quick_widget_item_t
), 8);
196 for (quick_widget
= quick_dlg
->widgets
; quick_widget
->widget_type
!= quick_end
; quick_widget
++)
198 quick_widget_item_t item
= { NULL
, quick_widget
};
201 switch (quick_widget
->widget_type
)
206 (++y
, x
, *quick_widget
->u
.checkbox
.state
,
207 I18N (quick_widget
->u
.checkbox
.text
)));
208 g_array_append_val (widgets
, item
);
209 width
= item
.widget
->cols
;
213 width2
= max (width2
, width
);
215 width1
= max (width1
, width
);
220 item
.widget
= WIDGET (button_new (++y
, x
, quick_widget
->u
.button
.action
,
221 quick_widget
->u
.button
.action
== B_ENTER
?
222 DEFPUSH_BUTTON
: NORMAL_BUTTON
,
223 I18N (quick_widget
->u
.button
.text
),
224 quick_widget
->u
.button
.callback
));
225 g_array_append_val (widgets
, item
);
226 width
= item
.widget
->cols
;
230 width2
= max (width2
, width
);
232 width1
= max (width1
, width
);
236 *quick_widget
->u
.input
.result
= NULL
;
238 if (quick_widget
->u
.input
.label_location
!= input_label_none
)
239 quick_create_labeled_input (widgets
, &y
, x
, quick_widget
, &width
);
242 item
.widget
= WIDGET (quick_create_input (y
, x
, quick_widget
));
243 g_array_append_val (widgets
, item
);
244 width
= item
.widget
->cols
;
249 width2
= max (width2
, width
);
251 width1
= max (width1
, width
);
255 item
.widget
= WIDGET (label_new (++y
, x
, I18N (quick_widget
->u
.label
.text
)));
256 g_array_append_val (widgets
, item
);
257 y
+= item
.widget
->lines
- 1;
258 width
= item
.widget
->cols
;
262 width2
= max (width2
, width
);
264 width1
= max (width1
, width
);
272 /* create the copy of radio_items to avoid mwmory leak */
273 items
= g_new (char *, quick_widget
->u
.radio
.count
+ 1);
274 for (i
= 0; i
< (size_t) quick_widget
->u
.radio
.count
; i
++)
275 items
[i
] = g_strdup (_(quick_widget
->u
.radio
.items
[i
]));
278 r
= radio_new (++y
, x
, quick_widget
->u
.radio
.count
, (const char **) items
);
279 r
->pos
= r
->sel
= *quick_widget
->u
.radio
.value
;
281 item
.widget
= WIDGET (r
);
282 g_array_append_val (widgets
, item
);
283 y
+= item
.widget
->lines
- 1;
284 width
= item
.widget
->cols
;
288 width2
= max (width2
, width
);
290 width1
= max (width1
, width
);
294 case quick_start_groupbox
:
295 I18N (quick_widget
->u
.groupbox
.title
);
296 len
= str_term_width1 (quick_widget
->u
.groupbox
.title
);
297 g
= groupbox_new (++y
, x
, 1, len
+ 4, quick_widget
->u
.groupbox
.title
);
298 item
.widget
= WIDGET (g
);
299 g_array_append_val (widgets
, item
);
300 have_groupbox
= TRUE
;
303 case quick_stop_groupbox
:
306 Widget
*w
= WIDGET (g
);
309 w
->lines
= y
+ 1 - w
->y
;
312 g_array_append_val (widgets
, item
);
316 case quick_separator
:
318 if (quick_widget
->u
.separator
.line
)
320 item
.widget
= WIDGET (hline_new (y
, x
, 1));
321 g_array_append_val (widgets
, item
);
325 case quick_start_columns
:
327 g_array_append_val (widgets
, item
);
331 case quick_next_column
:
337 case quick_stop_columns
:
340 g_array_append_val (widgets
, item
);
345 /* start put several buttons in bottom line */
346 if (quick_widget
->u
.separator
.space
)
350 if (quick_widget
->u
.separator
.line
)
351 item
.widget
= WIDGET (hline_new (y
, 1, -1));
354 g_array_append_val (widgets
, item
);
356 /* several buttons in bottom line */
359 for (; quick_widget
->widget_type
== quick_button
; quick_widget
++)
361 item
.widget
= WIDGET (button_new (y
, x
++, quick_widget
->u
.button
.action
,
362 quick_widget
->u
.button
.action
== B_ENTER
?
363 DEFPUSH_BUTTON
: NORMAL_BUTTON
,
364 I18N (quick_widget
->u
.button
.text
),
365 quick_widget
->u
.button
.callback
));
366 item
.quick_widget
= quick_widget
;
367 g_array_append_val (widgets
, item
);
368 blen
+= item
.widget
->cols
+ 1;
371 /* stop dialog build here */
373 quick_widget
->widget_type
= quick_end
;
382 /* adjust dialog width */
383 quick_dlg
->cols
= max (quick_dlg
->cols
, blen
+ 6);
395 len
= width2
* 2 + 7;
397 len
= max (len
, width1
+ 6);
400 quick_dlg
->cols
= max (quick_dlg
->cols
, len
);
401 width1
= quick_dlg
->cols
- 6;
402 width2
= (quick_dlg
->cols
- 7) / 2;
404 if (quick_dlg
->x
== -1 || quick_dlg
->y
== -1)
405 dd
= create_dlg (TRUE
, 0, 0, y
+ 3, quick_dlg
->cols
,
406 dialog_colors
, quick_dlg
->callback
, quick_dlg
->mouse
, quick_dlg
->help
,
407 quick_dlg
->title
, DLG_CENTER
| DLG_TRYUP
);
409 dd
= create_dlg (TRUE
, quick_dlg
->y
, quick_dlg
->x
, y
+ 3, quick_dlg
->cols
,
410 dialog_colors
, quick_dlg
->callback
, quick_dlg
->mouse
, quick_dlg
->help
,
411 quick_dlg
->title
, DLG_NONE
);
413 /* add widgets into the dialog */
414 x2
= x1
+ width2
+ 1;
417 x
= (WIDGET (dd
)->cols
- blen
) / 2;
419 for (i
= 0; i
< widgets
->len
; i
++)
421 quick_widget_item_t
*item
;
424 item
= &g_array_index (widgets
, quick_widget_item_t
, i
);
425 column_width
= two_columns
? width2
: width1
;
427 /* adjust widget width and x position */
428 switch (item
->quick_widget
->widget_type
)
432 quick_widget_t
*input
= item
->quick_widget
->u
.label
.input
;
434 if (input
!= NULL
&& input
->u
.input
.label_location
== input_label_right
)
436 /* location of this label will be adjusted later */
443 if (item
->widget
->x
!= x1
)
444 item
->widget
->x
= x2
;
446 item
->widget
->x
+= 2;
452 if (item
->widget
->x
!= x1
)
453 item
->widget
->x
= x2
;
455 item
->widget
->x
+= 2;
460 x
+= item
->widget
->cols
+ 1;
466 Widget
*label
= WIDGET (INPUT (item
->widget
)->label
);
467 int width
= column_width
;
472 switch (item
->quick_widget
->u
.input
.label_location
)
474 case input_label_left
:
475 /* label was adjusted before; adjust input line */
476 item
->widget
->x
= label
->x
+ label
->cols
+ 1 - WIDGET (label
->owner
)->x
;
477 item
->widget
->cols
= width
- label
->cols
- 1;
480 case input_label_right
:
482 item
->widget
->x
+ item
->widget
->cols
+ 1 - WIDGET (item
->widget
->owner
)->x
;
483 item
->widget
->cols
= width
- label
->cols
- 1;
487 if (item
->widget
->x
!= x1
)
488 item
->widget
->x
= x2
;
490 item
->widget
->x
+= 2;
491 item
->widget
->cols
= width
;
495 /* forced update internal variables of inpuit line */
496 input_set_origin (INPUT (item
->widget
), item
->widget
->x
, item
->widget
->cols
);
500 case quick_start_groupbox
:
501 g
= GROUPBOX (item
->widget
);
502 if (item
->widget
->x
!= x1
)
503 item
->widget
->x
= x2
;
504 item
->widget
->cols
= column_width
;
507 case quick_stop_groupbox
:
511 case quick_separator
:
512 if (item
->widget
!= NULL
)
516 Widget
*wg
= WIDGET (g
);
518 HLINE (item
->widget
)->auto_adjust_cols
= FALSE
;
519 item
->widget
->x
= wg
->x
+ 1 - WIDGET (wg
->owner
)->x
;
520 item
->widget
->cols
= wg
->cols
;
522 else if (two_columns
)
524 HLINE (item
->widget
)->auto_adjust_cols
= FALSE
;
525 if (item
->widget
->x
!= x1
)
526 item
->widget
->x
= x2
;
528 item
->widget
->cols
= column_width
+ 2;
531 HLINE (item
->widget
)->auto_adjust_cols
= TRUE
;
535 case quick_start_columns
:
539 case quick_stop_columns
:
544 /* several buttons in bottom line */
552 if (item
->widget
!= NULL
)
556 /* add widget into dialog */
557 item
->widget
->options
|= item
->quick_widget
->options
; /* FIXME: cannot reset flags, setup only */
558 id
= add_widget_autopos (dd
, item
->widget
, item
->quick_widget
->pos_flags
, NULL
);
559 if (item
->quick_widget
->id
!= NULL
)
560 *item
->quick_widget
->id
= id
;
566 dd
->current
= g_list_next (dd
->current
);
567 if (dd
->current
== NULL
)
568 dd
->current
= dd
->widgets
;
571 return_val
= run_dlg (dd
);
573 /* Get the data if we found something interesting */
574 if (return_val
!= B_CANCEL
)
575 for (i
= 0; i
< widgets
->len
; i
++)
577 quick_widget_item_t
*item
;
579 item
= &g_array_index (widgets
, quick_widget_item_t
, i
);
581 switch (item
->quick_widget
->widget_type
)
584 *item
->quick_widget
->u
.checkbox
.state
= CHECK (item
->widget
)->state
& C_BOOL
;
588 if ((quick_widget
->u
.input
.completion_flags
& INPUT_COMPLETE_CD
) != 0)
589 *item
->quick_widget
->u
.input
.result
=
590 tilde_expand (INPUT (item
->widget
)->buffer
);
592 *item
->quick_widget
->u
.input
.result
= g_strdup (INPUT (item
->widget
)->buffer
);
596 *item
->quick_widget
->u
.radio
.value
= RADIO (item
->widget
)->sel
;
606 /* destroy input labels created before */
607 for (i
= 0; i
< widgets
->len
; i
++)
609 quick_widget_item_t
*item
;
611 item
= &g_array_index (widgets
, quick_widget_item_t
, i
);
612 if (item
->quick_widget
->widget_type
== quick_input
)
613 g_free (item
->quick_widget
->u
.input
.label
);
616 g_array_free (widgets
, TRUE
);
621 /* --------------------------------------------------------------------------------------------- */