Construct Tk::Widget
'ConfigModelWizard'
;
my
$logger
= Log::Log4perl::get_logger(
'Tk::Wizard'
);
my
@fbe1
=
qw/-fill both -expand 1/
;
my
@fxe1
=
qw/-fill x -expand 1/
;
my
@fx
=
qw/-fill x /
;
sub
ClassInit {
my
(
$class
,
$mw
) =
@_
;
}
sub
Populate {
my
(
$cw
,
$args
) =
@_
;
foreach
my
$parm
(
qw/-root/
) {
my
$attr
=
$parm
;
$attr
=~ s/^-//;
$cw
->{
$attr
} =
delete
$args
->{
$parm
}
or croak
"Missing $parm arg\n"
;
}
foreach
my
$parm
(
qw/-from_widget -stop_on_important -store_cb -show_cb -end_cb -font/
) {
my
$attr
=
$parm
;
$attr
=~ s/^-//;
$cw
->{
$attr
} =
delete
$args
->{
$parm
};
}
$logger
->info(
"Creating wizard widget"
);
$cw
->{show_cb} ||=
sub
{ };
$cw
->{store_cb} ||=
sub
{ };
$cw
->{has_stopped} = 0;
my
$title
=
delete
$args
->{
'-title'
}
||
"config wizard "
.
$cw
->{root}->config_class_name;
$cw
->Label(
-text
=>
"Configuration of "
.
$cw
->{root}->config_class_name,
)->
pack
;
my
$ed
=
$cw
->{ed_frame} =
$cw
->Frame->
pack
(
qw/-pady 0 -fill both -expand 1 -anchor n/
);
$cw
->{ed_frame}->packPropagate(0);
$args
->{-title} =
$title
;
$cw
->Advertise(
ed_frame
=>
$ed
, );
$cw
->ConfigSpecs(
-font
=> [[
'SELF'
,
'DESCENDANTS'
],
'font'
,
'Font'
,
$cw
->{font} ],
-width
=> [
$ed
,
undef
,
undef
, 600 ],
-height
=> [
$ed
,
undef
,
undef
, 400 ],
DEFAULT
=> [
$ed
]
);
$cw
->{font} //=
$cw
->cget(
'-font'
);
$cw
->SUPER::Populate(
$args
);
}
sub
save {
my
$cw
=
shift
;
$cw
->check();
$logger
->info(
"Saving data in default directory with instance write_back"
);
$cw
->{root}->instance->write_back();
}
sub
leaf_cb {
my
(
$cw
,
$scanner
,
$data_ref
,
$node
,
$element_name
,
$index
,
$leaf_object
) =
@_
;
$cw
->{has_stopped} = 1;
$cw
->{show_cb}->(
$leaf_object
);
$cw
->{ed_w} =
$cw
->{ed_frame}->ConfigModelLeafEditor(
-item
=>
$leaf_object
,
-store_cb
=>
$cw
->{store_cb},
-font
=>
$cw
->{font},
)->
pack
(
@fbe1
);
}
sub
list_element_cb {
my
(
$cw
,
$scanner
,
$data_ref
,
$node
,
$element_name
,
@indexes
) =
@_
;
$cw
->{has_stopped} = 1;
my
$obj
=
$node
->fetch_element(
$element_name
);
$cw
->{show_cb}->(
$obj
);
$cw
->{ed_w} =
$cw
->{ed_frame}->ConfigModelListEditor(
-item
=>
$obj
,
-store_cb
=>
$cw
->{store_cb},
-font
=>
$cw
->{font},
)->
pack
(
@fbe1
);
}
sub
hash_element_cb {
my
(
$cw
,
$scanner
,
$data_ref
,
$node
,
$element_name
,
@keys
) =
@_
;
$cw
->{has_stopped} = 1;
my
$obj
=
$node
->fetch_element(
$element_name
);
$cw
->{show_cb}->(
$obj
);
$cw
->{ed_w} =
$cw
->{ed_frame}->ConfigModelHashEditor(
-item
=>
$obj
,
-store_cb
=>
$cw
->{store_cb},
-font
=>
$cw
->{font},
)->
pack
(
@fbe1
);
}
sub
check_list_element_cb {
my
(
$cw
,
$scanner
,
$data_ref
,
$node
,
$element_name
,
@items
) =
@_
;
$cw
->{has_stopped} = 1;
my
$obj
=
$node
->fetch_element(
$element_name
);
$cw
->{show_cb}->(
$obj
);
$cw
->{ed_w} =
$cw
->{ed_frame}->ConfigModelCheckListEditor(
-item
=>
$obj
,
-store_cb
=>
$cw
->{store_cb},
-font
=>
$cw
->{font},
)->
pack
(
@fbe1
);
}
sub
prepare_wizard {
my
(
$cw
,
%args
) =
@_
;
my
$text
=
'The wizard will scan all configuration items and stop on '
.
'"important" items or on error (like missing mandatory values). If no '
.
'"important" item and no error are found, the wizard will exit immediately'
;
my
$edf
=
$cw
->{ed_frame};
my
$textw
=
$edf
->ROText(
qw/-relief flat -wrap word -height 8/
,
-font
=>
$cw
->{font});
$textw
->insert(
end
=>
$text
);
$textw
->
pack
(
qw/-side top -anchor n/
,
@fxe1
);
my
$stop_on_warn
= 0;
$edf
->Checkbutton(
-text
=>
'stop on warning'
,
-variable
=> \
$stop_on_warn
,
-font
=>
$cw
->{font})
->
pack
(
qw/-side top -anchor w/
);
$edf
->Button(
-text
=>
'OK'
,
-font
=>
$cw
->{font},
-command
=>
sub
{
$cw
->start_wizard(
stop_on_warning
=>
$stop_on_warn
) }
)->
pack
(
qw/-side right -anchor e/
);
$edf
->Button(
-text
=>
'cancel'
,
-font
=>
$cw
->{font},
-command
=>
sub
{
$cw
->destroy_wizard() }
)->
pack
(
qw/-side left -anchor w/
);
}
sub
start_wizard {
my
(
$cw
,
%args
) =
@_
;
my
$button_f
=
$cw
->Frame->
pack
(
qw/-pady 0 -fill x -expand 1/
);
$cw
->{has_stopped} = 0;
my
$back
=
$button_f
->Button(
-text
=>
'Back'
,
-font
=>
$cw
->{font},
-command
=>
sub
{
$cw
->{keep_wiz_editor} = 0;
$cw
->{wizard}->go_backward;
} );
$back
->
pack
(
qw/-side left -fill x -expand 1/
);
my
$stop
=
$button_f
->Button(
-text
=>
'Store and stop'
,
-font
=>
$cw
->{font},
-command
=>
sub
{
$cw
->{ed_w}->store
if
$cw
->{ed_w}->can(
'store'
);
$cw
->{keep_wiz_editor} = 0;
$cw
->{wizard}->bail_out;
} );
$stop
->
pack
(
qw/-side left -fill x -expand 1/
);
my
$quit
=
$button_f
->Button(
-text
=>
'quit wizard'
,
-font
=>
$cw
->{font},
-command
=>
sub
{
$cw
->{keep_wiz_editor} = 0;
$cw
->{wizard}->bail_out;
} );
$quit
->
pack
(
qw/-side left -fill x -expand 1/
);
my
$forw
=
$button_f
->Button(
-text
=>
'Next'
,
-font
=>
$cw
->{font},
-command
=>
sub
{
$cw
->{keep_wiz_editor} = 0;
$cw
->{wizard}->go_forward;
} );
$forw
->
pack
(
qw/-side right -fill x -expand 1/
);
$cw
->{keep_wiz_editor} = 1;
my
%cb_table
;
foreach
my
$cb_key
(
qw/leaf_cb check_list_element_cb
list_element_cb hash_element_cb/
) {
$cb_table
{
$cb_key
} =
sub
{
my
(
$scanner
,
$data_ref
,
$node
,
$element_name
) =
@_
;
my
@all_args
=
@_
;
$logger
->info(
"$cb_key (element $element_name) called on '"
,
$node
->name,
"'->'$element_name'"
);
map
{
$_
->destroy
if
Tk::Exists(
$_
) }
$cw
->{ed_frame}->children;
$cw
->{keep_wiz_editor} = 1;
try
{
$cw
->
$cb_key
(
@all_args
);
}
catch
{
$cw
->{keep_wiz_editor} = 0;
};
my
$loop_c
= 0;
$logger
->debug(
"$cb_key wizard entered local loop "
, ++
$loop_c
);
$cw
->DoOneEvent()
while
$cw
->{keep_wiz_editor};
$logger
->debug(
"$cb_key wizard exited local loop "
,
$loop_c
);
};
}
my
@wiz_args
= (
%cb_table
);
foreach
(
qw/warning important/
) {
push
@wiz_args
,
"call_back_on_$_"
=>
$args
{
"stop_on_$_"
}
if
defined
$args
{
"stop_on_$_"
};
}
$cw
->{wizard} =
$cw
->{root}->instance->iterator(
@wiz_args
);
$cw
->{wizard}->start;
$cw
->destroy_wizard;
}
sub
destroy_wizard {
my
$cw
=
shift
;
delete
$cw
->{ed_w};
delete
$cw
->{wizard};
$logger
->debug(
"Destroying wizard"
);
$cw
->destroy;
if
(
defined
$cw
->{end_cb} ) {
$logger
->debug(
"Calling end_cb"
);
$cw
->{end_cb}->(
$cw
->{has_stopped} );
}
}
1;