# CWM tutorial

## How to create simple dialog using CWM

This section describes how to create a simple dialog using CWM.

### Create structure for holding the data

The easiest is to use a map, where key is name of configuration file entry and value is its value.

    global map settings = $[
        "option1" : "value1",
        "option2" : "value2",
    ];

Additionally, this map can then be used as-is for exporting and importing settings.

### Create generic initialization and settings storing functions

They can (in most cases) look the following way:

    global define void MyInit (string widget_id) ``{
        UI::ChangeWidget (`id (widget_id), `Value,
            settings[widget_id]:"");
    }

    global define void MyStore (string widget_id, map event) ``{
        settings[widget_id] = UI::QueryWidget (`id (widget_id),
            `Value);
    }

They don't do anything else than to get current value from the map and change the widget appropriate way in case of init handler, and query the widget value and store it to the settings map in case of the store handler.

### Create the description of the widgets

It is a map with the same keys as the data map has, values are widget description maps.

    map widgets = $[
        "option1" : $[
            "label" : _("The &first option"),
            "widget" : `textentry,
            "help" : _("Some clever help"),
        ],
        "option2" : $[
            "label" : _("The second option"),
            "widget" : `radio_buttons,
            "items" : [
                [ "item1", _("&This is label of the first radio button") ],
                [ "item2", _("&And the second radio button") ],
            ],
            "help" : _("Next clever help"),
            "init" : ``(MyModule::RadioButtonsInit ()),
            "store" : ``(MyModule::RadioButtonsStore ()),
        ],
    ];

If you use radio button group, you can't use above mentioned handlers, because it is needed to use `CurrentButton instead of `Value. In this case the init and store callbacks must be set if fallback handlers use `Value property.

### Create other needed callbacks

For radio button group the callback will look following way:

    global define void RadioButtonsInit (string widget_id) ``{
        UI::ChangeWidget (`id (widget_id), `CurrentButton,
            settings[widget_id]:"");
    }

    global define void RadioButtonsStore (string widget_id, map event) ``{
        settings[widget_id] = UI::QueryWidget (`id (widget_id),
            `CurrentButton);
    }

### Create and run the dialog

It means to create dialog layout and call ShowAndRun with appropriate parameters. This should be contents of the function that is called from wizard sequencer.

    term contents = `VBox (
        "option1",
        `VSpacing (2),
        "option2"
    );

    map fallback_func = $[
        "init" : ``(MyModule::MyInit ()),
        "store" : ``(MyModule::MyStore ()),
    ];

    return CWM::ShowAndRun (["option1", "option2"], widgets,
        contents, _("Dialog caption"),
        Label::BackButton (), Label::NextButton (), fallback_func);

### Whole example (runnable)

/usr/share/YaST2/modules/MyModule.ycp

    {

    module "MyModule";

    import "CWM";

    global map settings = $[
        "option1" : "value1",
        "option2" : "item1",
    ];

    global define void MyInit (string widget_id) ``{
        UI::ChangeWidget (`id (widget_id), `Value,
            settings[widget_id]:"");
    }

    global define void MyStore (string widget_id, map event) ``{
        settings[widget_id] = UI::QueryWidget (`id (widget_id),
            `Value);
    }

    global map widgets = $[
        "option1" : $[
            "label" : _("The &first option"),
            "widget" : `textentry,
            "help" : _("Some clever help"),
        ],
        "option2" : $[
            "label" : _("The second option"),
            "widget" : `radio_buttons,
            "items" : [
                [ "item1", _("&This is label of the first radio button") ],
                [ "item2", _("&And the second radio button") ],
            ],
            "help" : _("Next clever help"),
            "init" : ``(MyModule::RadioButtonsInit ()),
            "store" : ``(MyModule::RadioButtonsStore ()),
        ],
    ];

    global define void RadioButtonsInit (string widget_id) ``{
        UI::ChangeWidget (`id (widget_id), `CurrentButton,
            settings[widget_id]:"");
    }

    global define void RadioButtonsStore (string widget_id, map event) ``{
        settings[widget_id] = UI::QueryWidget (`id (widget_id),
            `CurrentButton);
    }

    global define symbol RunMyDialog () ``{

        term contents = `VBox (
            "option1",
            `VSpacing (2),
            "option2"
        );

        map fallback_func = $[
            "init" : ``(MyModule::MyInit ()),
            "store" : ``(MyModule::MyStore ()),
        ];

        return CWM::ShowAndRun (["option1", "option2"], widgets,
            contents, _("Dialog caption"),
            Label::BackButton (), Label::NextButton (), fallback_func);
    }

    }

/usr/share/YaST2/clients/myexample.ycp

    {
        import "MyModule";
        import "Wizard";

        Wizard::CreateDialog ();

        y2error ("Configuration before dialog: %1", MyModule::settings);

        MyModule::RunMyDialog ();

        y2error ("Configuration after dialog: %1", MyModule::settings);

        UI::CloseDialog ();
    }