Tuesday, July 27, 2010

Assignment:Case Study 5

EFI Send me Frameworks has a very interesting problem to solve. The UI of the application can be implemented for multiple platforms to name a few browser, wxWidget, MFC, Xwindows, etc. The application has 10 dialogs and each dialog has fixed number of controls on it. The controls can be like labels, text boxes, list boxes, buttons,etc. The idea is that anyone should be able to implement UI in their choice of technology. The application decides what control will be placed where and application also wants that some of the predefined events to be generated in response to the user input. Each Dialog is rendered based on the application intent, it means that if User Login Dialog needs to be rendered than application wants two labels, two text boxes and two buttons with Cancel and OK on it to be displayed. On click of Ok and Cancel the relevant events needs to be generated.

You need to design the application interface to support such a behavior. Don’t focus on events and layouts. What are the things you would consider when designing such a system? What all behavior you want to abstract? For people from .Net background, please focus on Web and Desktop solution.

The focus should be on creation and class hierarchy, don’t get lost with the function names and their signature.

4 comments:

  1. Hi,

    I have not seen the implementation of send me. I have tried to solve the issue using following three patterns:
    1. Model View Controller
    2. Bridge
    3. Observer

    There are several views(Browser View, wxWidgets UI etc.) I have taken an example with an arbitrary View1. Corresponding to each view there is a controller. In my example, for class View1 it is Controller1(). To link up the correct Views with the correct controllers Bridge pattern is used. Bridge class keeps a poiner to IController(base class of all the controllers) and delegates the view events to the corresponding controller.

    On recieving an event, controller intimates the Model class to change its state.

    Model class in return intimates the state change to the View as View registered to Model class using observer pattern.

    class View1
    {
    private:
    Bridge bridge;

    public:

    View1()
    {
    bridge = new Bridge();
    InitializeComponents();
    // Register to the model class state change events. Using observer patter.
    }

    void ButtonClick()
    {
    bridge.ButtonClick();
    }
    }
    };

    class Bridge
    {
    private:
    IController *controller;

    public:
    Bridge()
    {
    // Initialize the controller depending upon view type
    }

    void ButtonClick()
    {
    controller.ButtonClick();
    }
    };

    class IController() // Abstract Class
    {
    public:
    virtual void ButtonClick() = 0;
    };

    class Controller1: public IController // Handles the operation corresponding to view1
    {
    private:
    Model model;
    public:
    void ButtonClick()
    {
    model.ButtonClick();
    // intimate the model and initiate its state change
    }
    };

    class Model
    {
    public:
    void ButtonClick()
    {
    // Change the state
    // intimate view to change itself()
    }
    };

    ReplyDelete
  2. Didn't think about any patterns. Just trying to find a solution.

    class UIPlugin
    {
    virtual CreateDialog(vecControls controls) = 0;
    };

    class MFCUIPlugin : public UIPlugin
    {
    public:
    CreateDialog(vecControls controls, EventCallback* pEventCallback*)
    {
    m_pEventCallback = pEventCallback;
    //create dialog.
    }
    OnButtonClick()
    {
    //find the contol id and event type
    m_pEventCallback->ProcessEvent(controlId, eventtype);
    }

    EventCallback* m_pEventCallback;

    };

    class wxUIPlugin : public UIPlugin
    {
    public:
    CreateDialog(vecControls controls, EventCallback* pEventCallback*);

    };


    struct control
    {
    int type;
    int controlId,
    int order;
    int layout;
    bool bGenerateEvent;
    int eventtype;
    };
    typedef vector vecControls;

    class EventCallback
    {
    virtual ProcessEvent(int controlId, int eventType) = 0;
    };

    class Dialog
    {
    public:

    virtual GetControls();

    Create(UIPlugin* uiplugin)
    {
    GetControls();
    uiplugin->CreateDialog(controls, this);
    }

    vecControls controls;

    };

    class LoginDialog : public Dialog, EventCallback
    {
    public:
    void GetControls()
    {
    //fill controls
    }

    ProcessEvent(int controlId, int eventType)
    {
    switch(controlId)
    {
    case ok:
    // login
    }
    }
    };

    class ExitDialog : public Dialog, EventCallback
    {
    public:
    void GetControls()
    {
    //fill controls
    }
    ProcessEvent(int controlId, int eventType)
    {

    switch(controlId)
    {
    case ok:
    // exit
    }
    }
    };

    int main()
    {
    UIPlugin* pMFCPlugin = new MFCUIPlugin();
    Dialog* pDialg = new LoginDialog();
    pDialg.Create(pMFCPlugin);

    UIPlugin* pwxPlugin = new wxUIPlugin();
    Dialog* pDialg = new ExitDialog();
    pDialg.Create(pwxPlugin);

    return 0;
    }

    ReplyDelete
  3. My solution is illustrated at http://picasaweb.google.com/lh/photo/u24tV5ejgCFbDJsX4EbLIBEszIbJdwF3z7f_o_wRMro?feat=directlink

    ReplyDelete
  4. class button
    {
    public:
    virtual button(printmeServer *svr)
    :_svr(svr){}
    virtual void draw(int x,int y,stlye_e st) = 0;
    private:
    server *_svr;
    };

    class window
    {
    public:
    virtual window(printmeServer *svr)
    :_svr(svr){}
    virtual void draw(int x,int y,stlye_e st) = 0;
    };

    class menu
    {
    public:
    virtual menu(printmeServer *svr)
    :_svr(svr){}
    virtual void draw(int x,int y,stlye_e st) = 0;
    };

    class server
    {
    public: virtual void postEvents() = 0;
    }

    class printmeServer: public server
    {
    public:
    void postEvents(event_e evt)
    {
    switch(evt)
    {
    }
    }
    };

    //the user can now derver button, window, etc to implement classes

    ReplyDelete