# vDialog

Class to build a modeless dialog.

## Synopsis

Header:
  `<v/vdialog.h>`
Class name:
  vDialog
Hierarchy:
  (vBaseWindow,vCmdParent) ->vDialog
Contains:
  CommandObject

## Description

The `vDialog` class is used to build modeless dialogs. Since most dialogs will require a response to the commands they define, you will almost always derive your own subclass based on `vDialog`, and override the `DialogCommand` method to handle those commands. Note that `vDialog` is multiply derived from the `vBaseWindow` and the `vCmdParent` classes.

## Constructor

#### vDialog(vBaseWindow* parent)

#### vDialog(vApp* parent)

#### vDialog(vBaseWindow* parent, int isModal = 0, char* title = "")

#### vDialog(vApp* parent, int isModal = 0, char* title = "")

A dialog is constructed by calling it with a pointer to a vBaseWindow or vApp, which is usually the 'this' of the object that creates the `vDialog`. The `isModal` parameter indicates if the dialog should be modal or modeless. You would usually use the default of 0. The modal flag is used by the derived `vModalDialog` class. The `title` parameter can be used to set a title for your dialog (see `SetDialogTitle` for information on titles). If you create a derived dialog class, you might provide a `parent` and a `title` in your constructor, and provide the 0 for the `isModal` flag in the call to the `vDialog` constructor.

The constructor builds an empty dialog. The `AddDialogCmds` method must be called in order to build a useful dialog, which you would usually do from within the constructor of your derived dialog class.

IMPORTANT! When you derive your own `vDialog` objects, you should write constructors for both the `vBaseWindow*` and `vApp*` versions. These two different constructors allow dialogs to be used both from windows directly, and from the `vApp` code as well. Normally, you would construct a dialog from a window. Occasionally, it will be useful to build a dialog from the vApp that applies to all windows, and not just the window that constructed it.

#### void vDialog::AddDialogCmds(CommandObject* cList)

This method is used to add a list of commands to a dialog. It is called after the dialog object has been created. You can usually do this in the constructor for your derived Dialog class. This method is passed an array of `CommandObject` structures.

#### void vDialog::SetDialogTitle(char* title)

This can be used to dynamically change the title of any object derived from a `vDialog` object. Note that the title will not always be displayed. This depends on the host system. For example, the user can set up their X window manager to not show decorations on transient windows, which is how dialogs are implemented on X. You should write your applications to provide a meaningful title as they are often helpful when displayed.

### Example

This example shows the steps required to use a dialog object. Note that the example uses the `vDialog` class directly, and thus only uses the default behavior of responding to the `OK` button.

    #include <v/vdialog.h>
        CommandObject cmdList[] =           // list of the commands
          {
            {C_Label, lbl1, 0, "Label",NoList,CA_MainMsg,isSens,0,0},
            {C_Button, M_OK, M_OK, " OK ", NoList,
                CA_DefaultButton, isSens,lbl1,0},
            {C_EndOfList,0,0,0,0,CA_None,0,0}  // This ends list
          };
        ...
        vDialog curDialog(this,0,"Sample Dialog"); // create dialog instance

        curDialog.AddDialogCmds(cmdList);          // add the commands

        curDialog.ShowDialog("Sample modeless dialog."); // invoke
        ...

This example creates a simple modeless dialog with a label and an OK button placed below the label (see the description of layout control below). `ShowDialog` displays the dialog, and the `vDialog::DialogCommand` method will be invoked with the id (2) and value (`M_OK`) of the OK button when it is pressed.

Use the `vModalDialog` class to define modal dialogs.

The `CommandObject` structure includes the following:

        typedef struct CommandObject
          {
            CmdType cmdType;    // what kind of item is this
            ItemVal cmdId;      // unique id for the item
            ItemVal retVal;     // initial value
                                //  depends on type of command
            char* title;        // string for label or title
            void* itemList;     // a list of stuff to use for the cmd
                                //  depends on type of command
            CmdAttribute attrs; // list of attributes of command
            unsigned
                 Sensitive:1;   // if item is sensitive or not
            ItemVal cFrame;     // if item part of a frame
            ItemVal cRightOf;   // Item placed left of this id
            ItemVal cBelow;     // Item placed below this one
            int size;           // Used for size information
    	char* tip;          // tool tip string
          } CommandObject;

Placements of command objects within the dialog box are controlled by the `cRightOf` and `cBelow` fields. By specifying where an object goes in relation to other command objects in the dialog, it is simple to get a very pleasing layout of the dialog. The exact spacing of command objects is controlled by the `vDialog` class, but the application can used `C_Blank` command objects to help control spacing.

The various types of command objects that can be added include (with suggested id prefix in parens):

        C_EndOfList:   Used to denote end of command list
        C_Blank:       filler to help RightOfs, Belows work (blk)
        C_BoxedLabel:  a label with a box (bxl)
        C_Button:      Button (btn)
        C_CheckBox:    Checked Item (chk)
        C_ColorButton: Colored button (cbt)
        C_ColorLabel:  Colored label (clb)
        C_ComboBox:    Popup combo list (cbx)
        C_Frame:       General purpose frame (frm)
        C_Icon:        a display only Icon (ico)
        C_IconButton:  a command button Icon (icb)
        C_Label:       Regular text label (lbl)
        C_List:        List of items (lst)
        C_ProgressBar: Bar to show progress (pbr)
        C_RadioButton: Radio button (rdb)
        C_Slider:      Slider to enter value (sld)
        C_Spinner:     Spinner value entry (spn)
        C_TextIn:      Text input field (txi)
        C_Text:        wrapping text out (txt)
        C_ToggleButton: a toggle button (tbt)
        C_ToggleFrame: a toggle frame (tfr)
        C_ToggleIconButton:  a toggle Icon button (tib)

These command values are passed to the `vDialog::DialogCommand` function, which you override to interpret commands.

#### virtual void CancelDialog()

This method is used to cancel any action that took place in the dialog. The values of any items in the dialog are reset to their original values, and the This method is automatically invoked when the user selects a button with the value `M_Cancel` and the `DialogCommand` method invoked as appropriate to reset values of check boxes and so on. `CancelDialog` can also be invoked by the application code.

#### virtual void CloseDialog()

The `CloseDialog` is used to close the dialog. It can be called by user code, and is automatically invoked if the user selects the `M_Done` or `M_OK` buttons and the the user either doesn't override the `DialogCommand` or calls the default `DialogCommand` from any derived `DialogCommand` methods.

#### virtual void DialogCommand(ItemVal Id, ItemVal Val, CmdType Type)

This method is invoked when a user selects some command item of the dialog. The default `DialogCommand` method will normally be overridden by a user derived class. It is useful to call the default `DialogCommand` from the derived method for default handling of the `M_Cancel` and `M_OK` buttons.

The `Id` parameter is the value of the `cmdId` field of the `CommandObject` structure. The `Val` parameter is the `retVal` value, and the `Type` is the `cmdType`.

The user defined `DialogCommand` is where most of the work defined by the dialog is done. Typically the derived `DialogCommand` will have a `switch` statement with a `case` for each of the command `cmdId` values defined for items in the dialog.

#### void DialogDisplayed()

This method is called by the V runtime system after a dialog has actually been displayed on the screen. This method is especially useful to override to set values of dialog controls with `SetValue` and `SetString`.

It is important to understand that the dialog does not get displayed until `ShowDialog` or `ShowModalDialog` has been called. There is a very important practical limitation implied by this, especially for modal dialogs. The values of controls cannot be changed until the dialog has been displayed, even though the `vDialog` object may exist. Thus, you can't call `SetValue` or `SetString` until after you call `ShowDialog` for modeless dialogs, or `ShowModalDialog` for modal dialogs. Since `ShowModalDialog` does not return until the user has closed the dialog, you must override `DialogDisplayed` if you want to change the values of controls in a modal dialog dynamically.

For most applications, this is not a problem because the static definitions of controls in the `CommandObject` definition will be usually be what is needed. However, if you need to create a dialog that has those values changed at runtime, then the easiest way is to include the required `SetValue` and `SetString` calls inside the overridden `DialogDisplayed`.

#### void GetDialogPosition(int& left, int& top, int& width, int& height)

Returns the position and size of `this` dialog. These values reflect the actual position and size on the screen of the dialog. The intent of this method is to allow you to find out where a dialog is so position it so that it doesn't cover a window.

#### virtual int GetTextIn(ItemVal Id, char* str, int maxlen)

This method is called by the application to retrieve any text entered into any `C_TextIn` items included in the dialog box. It will usually be called after the dialog is closed. You call `GetTextIn` with the `Id` of the TextIn command, the address of a buffer (`str`), and the size of `str` in `maxlen`.

#### virtual int GetValue(ItemVal Id)

This method is called by the user code to retrieve values of command items, usually after the dialog is closed. The most typical use is to get the index of any item selected by the user in a `C_List` or `C_ComboBox`.

#### int IsDisplayed()

This returns true if the dialog object is currently displayed, and false if it isn't. Typically, it will make sense only to have a single displayed instance of any dialog, and your code will want to create only one instance of any dialog. Since modal dialogs allow the user to continue to interact with the parent window, you must prevent multiple calls to `ShowDialog`. One way would be to make the command that displays the dialog to be insensitive. `IsDisplayed()` is provided as an alternative method. You can check the `IsDisplayed()` status before calling `ShowDialog`.

#### virtual void SetDialogPosition(int left, int top)

Moves `this` dialog to the location `left` and `top`. This function can be used to move dialogs so they don't cover other windows.

#### virtual void SetValue(ItemVal Id, ItemVal val, ItemSetType type)

This method is used to change the state of dialog command items. The `ItemSetType` parameter is used to control what is set. Not all dialog command items can use all types of settings. The possibilities include:

Checked The `Checked` type is used to change the checked status of check boxes. V will normally handle checkboxes, but if you implement a command such as Check All, you can use `SetValue` to change the check state according to `ItemVal val`.

Sensitive The `Sensitive` type is used to change the sensitivity of a dialog command.

Value The `Value` type is used primarily to preselect the item specified by `ItemVal val` in a list or combo box list.

ChangeList, ChangeListPtr Lists, Combo Boxes, and Spinners use the `itemList` field of the defining `CommandObject` to specify an appropriate list. `SetValue` provides two ways to change the list values associated with these controls.

The key to using `ChangeListPtr` and `ChangeList` is an understanding of just how the controls use the list. When a list type control is instantiated, it keeps a private copy of the pointer to the original list as specified in the `itemList` field of the defining `CommandObject`.

So if you want to change the original list, then `ChangeList` is used. The original list may be longer or shorter, but it must be in the same place. Remember that a NULL entry marks the end of the list. So you could allocate a 100 item array, for example, and then reuse it to hold 0 to 100 items.

Call `SetValue` with `type` set to `ChangeList`. This will cause the list to be updated. Note that you must not change the `itemList` pointer used when you defined the list or combo box. The contents of the list can change, but the pointer must be the same. The `val` parameter is not used for `ChangeList`.

Sometimes, especially for regular list controls, a statically sized list just won't work. Using `ChangeListPtr` allows you to use dynamically created list, but with a small coding penalty. To use `ChangeListPtr`, you must first modify the contents of the `itemList` field of the original `CommandObject` definition to point the the new list. Then call `SetValue` with `ChangeListPtr`. Note that this will both update the pointer, and update the contents of the list. You don't need to call again with `ChangeList`.

The following illustrates using both types of list change:

      char* comboList[] = {
        "Bruce", "Katrina", "Risa", "Van", 0 };
      char* list1[] = {"1", "2", "3", 0};
      char* list2[] = {"A", "B", "C", "D", 0};

      // The definition of the dialog
      CommandObject ListExample[] = {
        {C_ComboBox,100,0,"",(void*)comboList,CA_None,isSens,0,0,0},
        {C_List,200,0,"",(void*)list1,CA_None,isSens,0,0,0},
        ...
        };
       ...

        // Change the contents of the combo list
        comboList[0] = "Wampler";  // Change Bruce to Wampler
        SetValue(200,0,ChangeList);
       ...
        // Change to a new list entirely for list
        // Note that we have to change ListExample[1], the
        // original definition of the list control.
        ListExample[1].itemList = (void*)list2;  // change to list2
        SetValue(100,0,ChangeListPtr);
       ...

Note that this example uses static definitions of lists. It is perfectly fine to use completely dynamic lists: you just have to dynamically fill in the appropriate `itemList` field of the defining `CommandObject`.

Please see the description of `DialogDisplayed` for an important discussion of setting dialog control values.

#### virtual void SetString(ItemVal Id, char* str)

This method is called to set the string values of dialog items. This can include the labels on check boxes and radio buttons and labels, as well as the text value of a Text item.

Please see the description of `DialogDisplayed` for an important discussion of setting dialog control values.

#### virtual void ShowDialog(char* message)

After the dialog has been defined, it must then be displayed by calling the `ShowDialog` method. If a `C_Label` was defined with a `CA_MainMsg` attribute, then the message provided to `ShowDialog` will be used for that label.

`ShowDialog` returns to the calling code as soon as the dialog is displayed. It is up to the `DialogCommand` method to then handle command input to the dialog, and to close the dialog when done.

Please see the description of `DialogDisplayed` for an important discussion of setting dialog control values.

## Derived Methods

None.

## Inherited Methods

None.

## See Also

vModalDialog