Sample7: Edit Widget.

The Edit Object allows the user to supply text input to the application, operating in single or multi line mode. In single line mode the text lenght is fixed at creation time, while in multi line mode it’s limited by the macro MAXINT. The EDIT Object provides a filter facility and five callbacks to control input on it. A callback can be set to intercept the ‘Enter’ key press; another one is called whenever the Object is about to lose the input focus; a callback is also available to intercept and optionally refuse user input; a callback can be set to receive notification by the EDIT whenever its content changes; the last callback notifies the cursor position changing. The EDIT Object has a validation status which can be set explicitly or within a callback. It’s possible to show the Object in different colors, depending on the validation status. Arrow keys move the cursor within the Object text, ‘Ins’ toggles the overwrite/insert mode.

/* C version */ /*  * sample 7  */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "mgui.h" #define IsEven(a)       (!((a)&1)) void ExitCB(MOBJECT obj, void *a, void *b) {    MShellDestroy((MOBJECT)b);    MGUITerm();    exit(0); } int ValidateString(char *ps) {    int val, even, old;    val = True;    old = IsEven(*ps);    if (*ps != '\0') {       for (ps++; *ps && val; ps++, old=even)          val = old ^ (even = IsEven(*ps));    }    return val; } void ValidateCB(MOBJECT edit, EDIT_VAL *ev, void *ii) {    ev->text_validated = ValidateString(ev->text);    if (!ev->text_validated && !ev->focus_lost)       ev->focus_leave = False; } void ValueChangeCB(MOBJECT edit, EDIT_CHANGE *ec, void *ii) {    char buff[128];    if (!strcmp(ec->current_text, "1234567890")) {       ec->exec = False;       return;    }    strncpy(buff, ec->current_text, ec->pos);    strcpy(buff + ec->pos, ec->change);    strcat(buff, ec->current_text + ec->pos + ec->len);    ec->exec = ValidateString(buff); } void NewValueCB(MOBJECT edit, char *new, void *label) {    MObjectSetText((MOBJECT )label, new); } void ActivateCB(MOBJECT edit, char *text, void *ed) {    static int notify;    notify ^= 1;    MEditSetTextExt((MOBJECT )ed, text, False, notify); } void NewPosCB(MOBJECT edit, EDIT_CURS *ec, void *label) {    char str[128];    sprintf(str, "%-3d - %-3d", ec->pos_y, ec->pos_x);    MObjectSetText((MOBJECT )label, str); } void MGUIMain(int argc, char **argv) {    MOBJECT shell, pb, edit, edit2, label;    MTColor black, white, seagreen, cadetblue;    black = MBlackColor();    white = MWhiteColor();    cadetblue = MAllocColor(0x60, 0x85, 0x95);    seagreen = MAllocColor(0x70, 0xa5, 0xa0);    shell = MCreateShell("Sample 7", SF_NO_CLOSE);    edit = MCreateEdit(shell, "", 20, DEFAULT_FONT);     MEditSetFilter(edit, DIGIT, "");    MEditSetValCallback(edit, ValidateCB, NULL);     MEditSetValidatedColors(edit, cadetblue, white);    MEditSetNotValidatedColors(edit, seagreen, black);    edit = MCreateEdit(shell, "", 20, DEFAULT_FONT);     MEditSetFilter(edit, DIGIT, "");    MEditSetValueChangeCallback(edit, ValueChangeCB, NULL);    label = MCreateLabel(shell, "", DEFAULT_FONT);    edit = MCreateClippedEdit(shell, "", 15, 20, DEFAULT_FONT);    MEditSetNewValueCallback(edit, NewValueCB, label);    edit2 = MCreateEdit(shell, "", 20, DEFAULT_FONT);    MEditSetFilter(edit2, UPALPHA, "_ ");    MEditSetActCallback(edit2, ActivateCB, edit);    label = MCreateLabel(shell, "", DEFAULT_FONT);    edit = MCreateClippedMLEdit(shell, "", 15, 4, DEFAULT_FONT);    MEditSetCursorPosCallback(edit, NewPosCB, label);    pb = MCreatePButton(shell, "Quit", TIMES_L_FONT);    MPButtonSetCallback(pb, ExitCB, shell);    MShellRealize(shell);    MMainLoop(); }
This example shows the use of the five callbacks available, each set in a different Object. The function ValidateString() returns ‘True’ when the text string argument consists of alternating even and odd ASCII characters. The ValidateCB() function is called when the first EDIT Object is about to lose input focus voluntarily (for example after pressing the ‘Tab’ key) or by force (for example if another window is activated or another Object is selected via MSelectObject()). The structure EDIT_VAL, passed as pointer in the second argument to the callback, is defined as follows :
typedef struct {
   char *text;      /* EDIT text */
   short len;      /* Text lenght */
   int key;      /* Key code originator (0 if not applicable) */
   unsigned focus_lost;    /* If True, EDIT will lose the focus anyway */
   unsigned focus_leave;   /* If set to False, EDIT will keep focus */
   unsigned text_changed;  /* If set to True EDIT redraws itself */
   unsigned text_validated; /* If set to True EDIT becomes validated */
} EDIT_VAL;
EDIT uses this structure to notify the callback about: the Object text (with the ‘text’field); current text lenght (with the ‘len’ field); the code of the key that caused the call (with the ‘key’field) which is equal to zero if the call occurs due to an event other than a key press; finally the ‘focus_lost’ field notifies whether the application can request the Object to keep the input focus or not. If the ‘focus_leave’ field is set by the callback to False (and ‘focus_lost’ is False), then the EDIT Object retains the input focus. Within the callback code the application can change the ‘text’ string and set the ‘text_changed’ field to True. In this case the Object will perform a redraw. The 'focus_leave' field is preset to True by the Object before calling the callback. If the application wants the EDIT to keep the input focus, then the callback code should set to False this field. It’s also possible to change the EDIT content from within this callback by directly writing the new value in the ‘text’ pointer and setting the ‘text_changed’ field to True.This feature should only be used in single- line EDIT Objects. The ‘text_validated’ field determines the desired validation status for the Object. The ValidateCB() in the above example uses the function ValidateString() to set the validation status. Moreover, if this status is False and the input focus not lost, the callback queries the Object to keep the input focus. The ValueChange callback is activated every time the content in the EDIT Object changes. This callback lets the application control the input in the EDIT and optionally inhibit a change when needed. In the following is described the structure passed to the callback as the second parameter:
typedef struct {
   char *current_text;   /* EDIT text before the change */
   char *change;      /* New text to be inserted */
   int pos;         /* Change start position */
   int len;         /* Changing text lenght */
   unsigned validate;   /* Validation flag */
   unsigned exec;      /* Change accepted by the callback */
} EDIT_CHANGE;
The first field points to the EDIT value before the change occurs, while the second points to the new text to inserted (eventually a null string). The ‘pos’ field specifies the insert position relative to the current text value. The new text, specified by ‘change’ will substitute ‘current_text’ starting from ‘pos’ and with lenght ‘len’ with the value in ‘change’. The ‘validate’ field is preset to False, unless the callback is called due to the application call to MEditSetTextExt(), in which case it has the value specified as the third argument in that call. This field can be changed within the callback to set the desired validation status. If the last field is set to False, then the change is refused. The callback function ValueChangeCB() in example 8 refuses a text modification when it has reached the value "1234567890". Otherwise the change is permitted only if the resulting new text causes a True return from the ValidateString() function. The NewValue callback is the simplest one that lets the application control the input. It receives as the Object data (second argument) directly the current text value, after the change occurs. The NewValueCB() in the above example uses its current text to set the value in a LABEL Object, identified by the callback application data (the third argument). Notice that the third EDIT in the example is created via a MCreateClippedEdit() function call. This function has an additional argument which lets the EDIT Object have an actual lenght greater than the visible one. The Activate callback, called by the EDIT Object when the ‘Enter’ key is pressed on it, receives as second argument the Object text. In the above example the ActivateCB() function is used to set its current text in the third EDIT Object. When the value of the ‘notify’ parameter passed to MEditSetTextExt() is a boolean True, the third Object will call its ValueChange callback. Functions MBlackColor() and MWhiteColor() respectively return the preallocated black and white color identifiers. The ‘seagreen’ and ‘cadetblue’ colors, allocated via the MAllocColor() function, should be freed with a call to MFreeColor() when no more needed. This is however not necessary since they are used for the entire program execution, and they are automatically freed by the MGUITerm() function call. A filter is set to the first EDIT Object making it accepts digit characters only. The validation status for this Object is highlighted with different colors. The filter set in the fourth EDIT lets it accept alphabetic characters, converted to upper case, and the additional character ‘_’. Last EDIT is a clipped multi-line type. A scrolled version is also available via the MCreateScrolledMLEdit(), with the same arguments. The CursorPosition callback is set to this Object in the example. It traces cursor position within the EDIT while it changes. The structure notified by the EDIT to this callback (a pointer to it as the second parameter) is described in the follwing:
typedef struct {
   int pos;      /* position in the stream */
   int pos_x;      /* position x */
   int pos_y;      /* position y */
} EDIT_CURS;

// C++ version #include <stdio.h> #include <string.h> #include "mguipp.h" #define IsEven(a)       (!((a)&1)) class CaAppl : public CmAppl { public:    void start(int, char **); }; CaAppl appInstance; class CaMainWindow : public CmShell {    CmLabel *label;    CmLabel *pos_label;    CmEditField *edit; public:    CaMainWindow(const char *title, int flags);    int validateString(char *ps);    void validateCB(EDIT_VAL *ev);    void valueChangeCB(EDIT_CHANGE *ec);    void newValueCB(char *newText);    void activateCB(char *newText);    void newPosCB(EDIT_CURS *ec);    void exitCB(void); }; void CaMainWindow::exitCB(void) {    delete this;    CmAppl::end(0); } void CaAppl::start(int argc, char **argv) {    CaMainWindow *win = new CaMainWindow("Example 7", SF_NO_CLOSE);    win->realize();    mainLoop(); } CaMainWindow::CaMainWindow(const char *title, int flags) : CmShell(title, flags) {    CmEditField *ef;    CmEditWindow *ew;    CmPushButton *pb;    CmSharedColor black(0, 0, 0);    CmSharedColor white(0xff, 0xff, 0xff);    CmSharedColor cadetblue(0x60, 0x85, 0x95);    CmSharedColor seagreen(0x70, 0xa5, 0xa0);    ef = new CmEditField(this, "", 20, DEFAULT_FONT);     ef->setFilter(DIGIT, "");    ef->setValidateCallback(this, (EDITVAL_CB)validateCB);     ef->setValidatedColors(&cadetblue, &white);    ef->setInvalidatedColors(&seagreen, &black);    ef = new CmEditField(this, "", 20, DEFAULT_FONT);     ef->setFilter(DIGIT, "");    ef->setValueChangeCallback(this, (EDITCHANGE_CB)valueChangeCB);    label =new CmLabel(this, "", DEFAULT_FONT);    edit = new CmEditField(this, "", 15, 20, DEFAULT_FONT);    edit->setNewValueCallback(edit, (STRING_CB)newValueCB);    ef = new CmEditField(this, "", 20, DEFAULT_FONT);    ef->setFilter(UPALPHA, "_ ");    ef->setActivateCallback(this, (STRING_CB)activateCB);    pos_label = new CmLabel(this, "", DEFAULT_FONT);    ew = new CmEditWindow(this, "", 15, 4, DEFAULT_FONT);    ew->setCursorCallback(this, (EDITCURS_CB)newPosCB);    pb = new CmPushButton(this, "Quit", TIMES_MEDIUM);    pb->setCallback(this, (VOID_CB)exitCB); } int CaMainWindow::validateString(char *ps) {    int val, even, old;    val = True;    old = IsEven(*ps);    if (*ps != '\0') {       for (ps++; *ps && val; ps++, old=even)          val = old ^ (even = IsEven(*ps));    }    return val; } void CaMainWindow::validateCB(EDIT_VAL *ev) {    ev->text_validated = validateString(ev->text);    if (!ev->text_validated && !ev->focus_lost)       ev->focus_leave = False; } void CaMainWindow::valueChangeCB(EDIT_CHANGE *ec) {    char buff[128];    if (!strcmp(ec->current_text, "1234567890")) {       ec->exec = False;       return;    }    strncpy(buff, ec->current_text, ec->pos);    strcpy(buff + ec->pos, ec->change);    strcat(buff, ec->current_text + ec->pos + ec->len);    ec->exec = validateString(buff); } void CaMainWindow::newValueCB(char *newText) {    label->setText(newText); } void CaMainWindow::activateCB(char *text) {    static int notify;    notify ^= 1;    edit->setTextExt(text, False, notify); } void CaMainWindow::newPosCB(EDIT_CURS *ec) {    char str[128];    sprintf(str, "%-3d - %-3d", ec->pos_y, ec->pos_x);    pos_label->setText(str); }
Screenshot

Back