Sample9: DrawArea Widget.

MGUI library provides drawing primitives that can be used to draw on any kind of Object. Objects in the library such as push-button or edit, automatically redraw themselves when required by a window realize or expose event occur. A special Object is provided to support user drawing: the DrawArea. Input/Output callbacks for this Object are available to interact with user input (mouse/keyboard events) and expose/resize events. The Expose callback notifies the application when a portion of the Object area needs to be redrawn (every time an area becomes visible). The Input callback is called by the Object when the user presses/releases a mouse button, when the mouse moves inside the DrawArea, and when a key is pressed while the Object owns the input focus. The Resize callback notifies the application about a resize request due to a user resize in the window or an arrangement request from the container before the window is realized. If the application sets the Input callback on a DrawArea, the mouse is automatically grabbed on a button press event so the Object can get mouse motion events even if they occur outside the Object’s area. Coordinates for drawing and coordinates of mouse position are always relative to the DrawArea Object.

/* C version */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "mgui.h" MTColor black, white, cadetblue, seagreen; void ExitCB(MENU_ITEM item, void *a, void *b) {    MShellDestroy((MOBJECT)b);    MGUITerm();    exit(0); } void DrawAreaExposeCB(MOBJECT obj, MEvent *pexp, void *a_data) {    int hsize, wsize;    wsize = MObjectGetWidth(obj);    hsize = MObjectGetHeight(obj);    MDrawLine(obj, 0, 0, wsize, hsize, black);    MDrawLine(obj, 0, hsize, wsize, 0, white);    MDrawFilledCircle(obj, wsize/2, hsize/2, wsize/4, cadetblue);    MDrawCircle(obj, wsize/2, hsize/2, wsize/4, black); } void DrawAreaResizeCB(MOBJECT obj, DRAWAREA_PREF *pref, void *label) {    char str[128];    sprintf(str, "Draw area size: %dx%d", pref->new_w, pref->new_h);    MObjectSetText((MOBJECT )label, str); } void DrawAreaInputCB(MOBJECT obj, MEvent *pe, void *a_data) {    static int x1, y1, x2, y2;    if (pe->type == E_BUTTON_PRESS) {       x1 = x2 = pe->mouse.x;       y1 = y2 = pe->mouse.y;       MDrawXorLine(obj, x1, y1, x2, y2);    }    else if (pe->type == E_MOTION) {       MDrawXorLine(obj, x1, y1, x2, y2);       x2 = pe->mouse.x;       y2 = pe->mouse.y;       MDrawXorLine(obj, x1, y1, x2, y2);    }    else if (pe->type == E_BUTTON_RELEASE) {       MDrawXorLine(obj, x1, y1, x2, y2);       x2 = pe->mouse.x;       y2 = pe->mouse.y;       MDrawLine(obj, x1, y1, x2, y2, seagreen);    } } void MGUIMain(int argc, char **argv) {    MOBJECT pbutton, shell, label, drawa;    black = MBlackColor();    white = MWhiteColor();    cadetblue = MAllocColor(0x60, 0x85, 0x95);    seagreen = MAllocColor(0x70, 0xa5, 0xa0);    shell = MCreateShell("Sample 9", SF_NO_CLOSE);    label = MCreateLabel(shell, "Try and resize the window", HELV_L_FONT);    drawa = MCreateDrawArea(shell, 256, 256);    MObjectSetCursor(drawa, MC_CROSSHAIR);    MObjectSetResize(drawa, True, True);    MDrawAreaSetExposeCallback(drawa, DrawAreaExposeCB, NULL);    MDrawAreaSetInputCallback(drawa, DrawAreaInputCB, NULL);    MDrawAreaSetResizeCallback(drawa, DrawAreaResizeCB, label);    pbutton = MCreatePButton(shell, "Close", TIMES_L_FONT);    MPButtonSetCallback(pbutton, ExitCB, shell);    MShellRealize(shell);    MMainLoop(); }
The DrawAreaExposeCB() callback receives, as the second argument, a pointer to an Event of type Expose which specifies the portion of the Object area to be redrawn. Before calling this callback the Object automatically sets a clipping area to prevent drawing outside that area. So, the application can decide whether to use or not the received area coordinates to make only useful redrawings. In both cases the output will occurr only in the clipped area. For simplicity the callback in the example simply redraws the entire Object with no care of the actual clipping area to be redrawn. The DrawAreaInputCB() callback handles mouse input events to draw lines. Notice that drawing in this Object is NOT REMEMBERED. The application must take care of storing in some way its drawings in order to be able to redraw them in the Expose callback and/or to save them on disk.

// C++ version #include <stdio.h> #include <string.h> #include "mguipp.h" class CaAppl : public CmAppl { public:    void start(int, char **); }; CaAppl appInstance; class CaMainWindow : public CmShell {    CmDrawArea *drawa;    CmLabel *label;    CmSharedColor *seagreen, *cadetblue, *black, *white;    int x1, y1, x2, y2; public:    CaMainWindow(const char *title, int flags);    ~CaMainWindow();    void drawAreaExposeCB(MEvent *);    void drawAreaInputCB(MEvent *);    void drawAreaResizeCB(DRAWAREA_PREF *);    void exitCB(int); }; CaMainWindow::~CaMainWindow() {     delete seagreen;     delete cadetblue;     delete black;     delete white; } void CaMainWindow::exitCB(int) {    delete this;    CmAppl::end(0); } void CaAppl::start(int argc, char **argv) {    CaMainWindow *win = new CaMainWindow("Example 9", SF_NO_CLOSE);    win->realize();    mainLoop(); } void CaMainWindow::drawAreaExposeCB(MEvent *pexp) {    int hsize, wsize;    wsize = drawa->getWidth();    hsize = drawa->getHeight();    drawa->drawLine(0, 0, wsize, hsize, black);    drawa->drawLine(0, hsize, wsize, 0, white);    drawa->drawFilledCircle(wsize/2, hsize/2, wsize/4, cadetblue);    drawa->drawCircle(wsize/2, hsize/2, wsize/4, black); } void CaMainWindow::drawAreaResizeCB(DRAWAREA_PREF *pref) {    char str[128];    sprintf(str, "Draw area size: %dx%d", pref->new_w, pref->new_h);    label->setText(str); } void CaMainWindow::drawAreaInputCB(MEvent *pe) {    if (pe->type == E_BUTTON_PRESS)    {       x1 = x2 = pe->mouse.x;       y1 = y2 = pe->mouse.y;       drawa->drawXorLine(x1, y1, x2, y2);    }    else if (pe->type == E_MOTION)    {       drawa->drawXorLine(x1, y1, x2, y2);       x2 = pe->mouse.x;       y2 = pe->mouse.y;       drawa->drawXorLine(x1, y1, x2, y2);    }    else if (pe->type == E_BUTTON_RELEASE) {       drawa->drawXorLine(x1, y1, x2, y2);       x2 = pe->mouse.x;       y2 = pe->mouse.y;       drawa->drawLine(x1, y1, x2, y2, seagreen);    } } CaMainWindow::CaMainWindow(const char *title, int flags) : CmShell(title, flags) {    x1 = x2 = y1 = y2 = 0;    black = new CmSharedColor(0, 0, 0);    white = new CmSharedColor(0xff, 0xff, 0xff);    cadetblue = new CmSharedColor(0x60, 0x85, 0x95);    seagreen = new CmSharedColor(0x70, 0xa5, 0xa0);    label = new CmLabel(this, "Try and resize the window", HELV_MEDIUM);    drawa = new CmDrawArea(this, 256, 256);    drawa->setExposeCallback(this, (EVENT_CB)drawAreaExposeCB);    drawa->setInputCallback(this, (EVENT_CB)drawAreaInputCB);    drawa->setResizeCallback(this, (DRAWAREAPREF_CB)drawAreaResizeCB);    drawa->setResize(True, True);    drawa->setCursor(MC_CROSSHAIR);    CmPushButton *pb = new CmPushButton(this, " Ok ", TIMES_MEDIUM);    pb->setCallback(this, (VOID_CB)exitCB); }
Screenshot

Back