SOL9 2.0 Class: View

 SOL9 C++ Class Library  SOL9 Samples  SOL9 Tutorial  SOL9 FAQ  SOL9 ClassTree 

Source code

/*
 * View.h 
 * Copyright (c) 2009 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


// SOL++2000

// 1999.08.14
// 2000.02.18
// 2001.03.11 to-arai: Added a create method.
#pragma once

#include <sol\Window.h>
#include <sol\Application.h>

#include <sol\Args.h>
#include <sol\CallbackList.h>
#include <sol\HandlerList.h>
#include <sol\Dimension.h>
#include <sol\LinkedList.h>
#include <sol\Layoutable.h>
#include <sol\stdio.h>
#include <sol\Font.h>
#include <sol\InvalidWindowException.h>


namespace SOL {

class Font;
class Layoutable;

class View :public Window, public Layoutable {
private:
    View*            parent;
    Font*            font;    
    CallbackList    callbackList;
    HandlerList        handlerList;
    Boolean            editable;
    Boolean            destructable;
    Dimension        preferredSize;
  
  public:
    static const long    DEFAULT_WIN_CLASS_STYLE = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;


protected:
     virtual long destroy(Event& event)
    {
        ::PostQuitMessage(0);
        return 0L;
    }

protected:
     virtual long defaultProc(Event& event)
    {
        return ::DefWindowProc(getWindow(), event.getMessage(),
                   event.getWParam(),
                   event.getLParam());
    }

protected:
    View(View* parview)
        :parent(parview),
        font(null),
        editable(False),
        destructable(True),
        preferredSize(100, 100)
    {
        //
    }

public:
    View()
        :parent(null),
        font(null),
        editable(False),
        destructable(True),
        preferredSize(100, 100)
    {
    }

public:
    View(View* parview, const TCHAR* name, Args& args)
        :parent(parview),
        font(null),
        editable(False),
        destructable(True),
        preferredSize(100, 100)
    {
        Boolean rc = create(parview, name, args);
        if (rc == False) {
            throw InvalidWindowException("Failed to create a window");
        }
    }


public:
    ~View()
    {
        HWND hwnd = getWindow();
        if(isWindow() && destructable) {
            destroyWindow();
        }
        Application::remove(hwnd);
    }

public:
    virtual void    addCallback(const TCHAR* name, Object* object,
               Callback proc, void* data)
    {
        if(parent) {
            parent -> addCallback(name, (const Key)getWindow(), object, 
                            proc, data);
        }
    }


public:
    void    addCallback(const TCHAR* name, const Key key, Object* object,
               Callback proc, void* data)
    {
        callbackList.add(name, key, object, proc, data);
    }


public:
    void    addEventHandler(UINT message, Object* object,
                   Handler proc, void* data)
    {
        handlerList.add(message, object, proc, data);
    }

public:
    void    callCallback(const TCHAR* name, const Key key, 
            void* value, Event& event)
    {
        callbackList.call(name, key, value, event);
    }


    // 2000.02.10
public:
    virtual Boolean create(View* parview, const TCHAR* name, Args& args)
    {
        Boolean rc = False;

        parent = parview;
        font   = null;
        editable = False;
        destructable = True;

        // If a window were created, return False.
        if (getWindow()) {
            return rc;
        }

        if (args.get(XmNdialogUnit)) {
            args.toPixelUnit();
        }

        TCHAR* className = (TCHAR*)args.get(XmNclassName);
        if (className == NULL) {
            className = _T("View");
            args.set(XmNclassName, (ulong)className);
        }

        if (args.get(XmNpredefined) == False){
            //Application::
            registerClass(args);
        }

        HFONT hfont = NULL;

        HWND hparent = NULL;
        Font* pfont =NULL;

        if (parent) {
            hparent = parent->getWindow();

            //If parent has a Font, then we use it.
            pfont    = parent->getFont();
            if (pfont) {
                hfont = pfont->getFont();
            }
        }
        Application& applet = Application::getApplet(NULL);
        HINSTANCE hInstance = applet.getInstance();

        HWND hwnd = ::CreateWindowEx((DWORD)args.get(XmNexStyle),
                className, name,
                (DWORD)args.get(XmNstyle),
                (int) args.get(XmNx),
                (int) args.get(XmNy),
                (int) args.get(XmNwidth),
                (int) args.get(XmNheight),
                hparent, NULL,
                hInstance,    //Application::getInstance(),
                (LPSTR)args.get(XmNparam));

        if(hwnd) {
            setWindow(hwnd);

            Application::add(hwnd, this);
            setViewId((int)args.get(XmNid));
        
            //<added date="2008/06/27">
            TCHAR* useDefaultFont = (TCHAR*)args.get(XmNuseDefaultFont);

            if (hfont && useDefaultFont) {
                SendMessage(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(True,0));
                if (pfont) {
                    setFont(pfont);
                }
            }
            //</added>
            if(parent == NULL) {
                addEventHandler(WM_DESTROY, this,
                     (Handler)&View::destroy, NULL);
               }
            rc = True;
        }
        else {
             ::MessageBox(NULL, _T("SOL++: Failed to CreateWindow"),
                 className, (int)MB_OK);
        }
        return rc;
    }

    BOOL registerClass(Args& args)
    {
        //Application& applet = getInstance();
        Application& applet = Application::getApplet(NULL);
        HINSTANCE hInstance = applet.getInstance();

        WNDCLASS wc;
        TCHAR* className = (TCHAR*)args.get(XmNclassName);
        if (::GetClassInfo(hInstance, className, &wc)) {
            return TRUE;
        }
        HINSTANCE    prevInstance = applet.getPrevInstance(); 

        if (!prevInstance) {
        
            memset(&wc, 0, sizeof(WNDCLASS));
            wc.hCursor     = LoadCursor(NULL, IDC_ARROW);
            wc.hIcon     = LoadIcon(NULL, IDI_APPLICATION);
            wc.lpszClassName = className;
            wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
            wc.hInstance     = hInstance;
            wc.style         = DEFAULT_WIN_CLASS_STYLE;
            //CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
            wc.lpfnWndProc   = View::procedure;

            ulong val=0;
            if (args.get(XmNclassStyle, &val)) {
                wc.style      = (unsigned int)val;
            }
            if (args.get(XmNclsExtra, &val)) {
                wc.cbClsExtra = (unsigned int)val;
            }
            if (args.get(XmNwndExtra, &val)) {
                wc.cbWndExtra  = (unsigned int)val;
            }
            if (args.get(XmNwndProc, &val)) {
                wc.lpfnWndProc = (WNDPROC)val;
            }
            if (args.get(XmNbackground, &val)) {
                wc.hbrBackground = (HBRUSH)val;
            }
            if (args.get(XmNicon, &val)) {
                wc.hIcon      = (HICON)val;
            }
            if (args.get(XmNcursor, &val)) {
                wc.hCursor    = (HCURSOR)val;
            }
            return ::RegisterClass(&wc);
            }
        return FALSE;
    }

    // 2001.03.11
public:
    virtual Boolean create(View* parview)
    {
        parent    = parview;
        font    = null;
        editable = False;
        destructable = True;
        Dimension d(100,100);
        preferredSize.set(d);
        return True;
    }

public:
    virtual void disable()
    {
        show(SW_HIDE);
        enableWindow(False);
        show(SW_NORMAL);
    }

public:
    virtual long  dispatch(Event& event)
    {
        ulong value = NULL;
 
        if(handlerList.call(event, &value)) {
            return value;
        }
        return defaultProc(event);
    }

public:
    virtual void  enable()
    {
        show(SW_HIDE);
        enableWindow(True);
        show(SW_NORMAL);
    }

public:
    ulong get(const TCHAR* name)
    {
        ulong val;
        Args args;
        args.set(name, (ulong)&val);
        getValues(args);
        return val;
    }


public:
    void get(const TCHAR* name, ulong* val)
    {
        Args args;
        args.set(name, (ulong)val);
        getValues(args);
    }
    
public:
    virtual Arg*  getCallbackTable(int* num)
    {
        *num = 0;
        return NULL;
    }

public:
    virtual const TCHAR* getCallbackName(Event& event)
    {
        int  num = 0;
        Arg* table = NULL;

        table = getCallbackTable(&num);

        ulong val = (ulong)event.getNotification();
        const TCHAR* name = XmNactivateCallback;
        for(int i = 0; i<num; i++) {
            if(table[i].value == val) {
                name = table[i].name;
                break;                    
            } 
        }
        return name;
    }

public:
    void    getGeometry(int& x, int& y, int& width, int& height)
    {
        RECT r;
        getWindowRect(&r);
        x     = r.left;
        y     = r.top;
        width  = r.right  - r.left;
        height = r.bottom - r.top;

        if(parent) {
            POINT p;
            p.x = x;
            p.y = y;
            parent -> toClient(&p);
            x = p.x;
            y = p.y;
        }
    }

public:
    void    getNormalPlacement(RECT* r)
    {
        WINDOWPLACEMENT pl;
        pl.length = sizeof(WINDOWPLACEMENT);
        pl.showCmd = SW_SHOWNORMAL;
        getPlacement(&pl);
        *r = pl.rcNormalPosition;
    }

public:
    View*    getParent() { 
        return parent; 
    }
    
public:
    void    getSize(int& width, int& height)
    {
        RECT r;
        getWindowRect(&r);
        width  = r.right  - r.left;
        height = r.bottom - r.top;
    }

public:
    void    getLocation(int& x, int& y)
    {
        int width, height;
        getGeometry(x, y, width, height);
    }

public:
    int        getViewId() { 
        return getId(); 
    }
    
public:
    virtual void    layout(int x, int y, int w, int h)
    {
        reshape(x, y, w, h);
    }

public:
    Boolean    isEditable() { 
        return editable; 
    }
    
public:
    void    map() { 
        show(SW_NORMAL); 
    }

public:
    virtual void    getValues(Args& args)
    {
        int x, y, w, h;
        getGeometry(x, y, w, h);

        Arg ar[4];
        XtSetArg(ar[0], XmNx,     x);
        XtSetArg(ar[1], XmNy,     y);
        XtSetArg(ar[2], XmNwidth, w);
        XtSetArg(ar[3], XmNheight,h);

        HINSTANCE ins = getInstanceHandle();

        int num   = args.getCount();
        Arg* arg  = args.getArgList();

        LONG style   = getWindowLong(GWL_STYLE);
        LONG exStyle = getWindowLong(GWL_EXSTYLE);
        for(int j = 0; j<num; j++) {
            const TCHAR*   name  = arg[j].name;
            ulong* val  = (ulong*)arg[j].value;
            if(name == XmNstyle) {
                *val = style;
                continue;
            }
            if(name == XmNexStyle) {
                *val = exStyle;
                continue;
            }
            if(name == XmNid) {
                *val = getViewId();
                continue;
            }
            if(name == XmNinstance) {
                *val = (ulong)ins;
                continue;
            }
            if(name == XmNgroup) {
                *val = False;
                if(style & WS_GROUP) 
                    *val = True;
                continue;
            }
            if(name == XmNacceptFiles) {
                *val = False;
                if(exStyle & WS_EX_ACCEPTFILES)
                    *val = True;
                continue;
            }
    
            if(name == XmNlabelString) {
                int len = getTextLength();
                TCHAR* buff = new TCHAR[len+1];
                getText(buff, len+1);
                *val = (ulong)buff;
            }
        
            for(int i = 0; i<4; i++) {
                if(name == ar[i].name) {
                     *val = (ulong)ar[i].value;
                }
            }
        }
    }


public:
    static long CALLBACK procedure(HWND hwnd, UINT message, 
            WPARAM wParam, LPARAM lParam)
    {
        Event event(message, wParam, lParam);

        View* view = Application::lookup(hwnd);

        if (view && view->isWindow()) {
            return view -> dispatch(event);
        }
        return ::DefWindowProc(hwnd, message, wParam, lParam);
    }

public:
    void    removeEventHandler()
    {
        handlerList.clear();
    }

public:
    void    set(const TCHAR* name, ulong val)
    {
        Args args;
        args.set(name, val);
        setValues(args);
    }


public:
    void    setDestructable(Boolean val) { 
        destructable = val;
    }

public:
    void    setEditable(Boolean val) { 
        editable = val; 
    }
    
public:
    void    setLocation(int x, int y)
    {
        int xx, yy, width, height;

        getGeometry(xx, yy, width, height);
        reshape(x, y, width, height);
        update(NULL);
    }

public:
    void    setSize(int w, int h)
    {
        int xx, yy, width, height;

        getGeometry(xx, yy, width, height);
        reshape(xx, yy, w, h);
        update(NULL);
    }

    
public:
    void    setParent(View* parent1) { 
        parent = parent1; 
    }

public:
    void    setViewId(int id)
    {
        setId(id);
        DWORD style = getWindowLong(GWL_STYLE);
        if(style & WS_CHILD) {
            setWindowLong(GWL_ID, id);
        }
    }


public:
    void    setVisible(Boolean flag) 
    {
        if (flag) 
            map();
        else 
            unmap();
    }

public:
    virtual void    setValues(Args& args)
    {
        int x, y, w, h;

        getGeometry(x, y, w, h); 
        Arg ar[4];
        XtSetArg(ar[0], XmNx,     x);
        XtSetArg(ar[1], XmNy,     y);
        XtSetArg(ar[2], XmNwidth, w);
        XtSetArg(ar[3], XmNheight,h);

        Boolean mustmove = False;
        int num  = args.getCount();
        Arg* arg = args.getArgList();
        int i, j;
        for(j = 0; j<num; j++) {
            for(i = 0; i<4; i++) {
                if(ar[i].name == arg[j].name) {
                     ar[i].value = arg[j].value;
                    mustmove = True;
                }
            }
        }
        Boolean config = (Boolean)args.get(XmNnoConfiguration);
        if(!config) {
            if(mustmove && (ar[2].value != (ulong)CW_USEDEFAULT) ||
                       (ar[3].value != (ulong)CW_USEDEFAULT)) {
                reshape((int)ar[0].value, (int)ar[1].value,
                     (int)ar[2].value, (int)ar[3].value);
            }
        }
        ulong val;
        LONG style   = getWindowLong(GWL_STYLE);
        LONG exStyle = getWindowLong(GWL_EXSTYLE);

        if(args.get(XmNgroup, &val)) {
            if(val) {
                style |= WS_GROUP;
            }
            else {
                if(style & WS_GROUP) 
                    style ^= WS_GROUP;
            }
            setWindowLong(GWL_STYLE, style);
        }

        if(args.get(XmNacceptFiles, &val)) {
            if(val) {
                exStyle |= WS_EX_ACCEPTFILES;
            }
            else {
                if(exStyle & WS_EX_ACCEPTFILES)
                    exStyle ^= WS_EX_ACCEPTFILES;
            }
            setWindowLong(GWL_EXSTYLE, exStyle);
        }
        if(args.get(XmNlabelString, &val)) {
            setText((TCHAR*)val);
        }

        if(args.get(XmNid, &val)) {
            setViewId((int)val);
        }
    }


public:
    void    getStyle(Args& args, Arg* arg, int num)
    {
        DWORD style = (DWORD)getWindowLong(GWL_STYLE);

        for(int i = 0; i<num; i++) {
            ulong* val = (ulong*)args.get(arg[i].name);
            if(val) {
                *val = False;
                if(style & (DWORD)arg[i].value)
                    *val = True;
            }
        }
    }

public:
    void    unmap() { 
        show(SW_HIDE); 
    }

public:
    void    refresh(RECT* rect)
    {
        invalidate(rect);
        update();
    }

public:
    void refresh(int x, int y, int width, int height)
    {
        RECT rect;
        rect.left   = x;
        rect.top    = y;
        rect.right  = x+width;
        rect.bottom = y+height;
        invalidate(&rect);
        update();
    }


public:
    void    updateStyle(Args& args, Arg* arg, int num)
    {
        for(int i = 0; i<num; i++) {
            DWORD style = (DWORD)getWindowLong(GWL_STYLE);
            ulong val;
            DWORD st = (DWORD)arg[i].value;
            if(args.get(arg[i].name, &val)) {
                if(val) {
                    style |= st;
                }
                else {
                    if(style & st)
                        style ^= st;
                }
                setWindowLong(GWL_STYLE, style);
            }
        }
    }


public:
    Font*    getFont() { 
        return font; 
    }

    virtual void    setFont(HFONT hfont) {
            send(WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE,0));
    }

    virtual void    setFont(Font* font)
    {
        this->font = font;
        if(font) {
            send(WM_SETFONT, (WPARAM)font->getFont(),
                    MAKELPARAM(True,0));
        }
    }

    virtual void    setFont(Font& font1)
    {
        font = &font1;
        if(font) {
            send(WM_SETFONT, (WPARAM)font->getFont(),
                    MAKELPARAM(True,0));
        }
    }


    void setSysCursor(const TCHAR* name)
    {
        ::SetCursor(::LoadCursor(NULL, name));        
    }

    virtual void getPreferredSize(Dimension& d) 
    {
        preferredSize.get(d);
    }


    virtual void setPreferredSize(Dimension& d) 
    {
        setSize(d.getWidth(), d.getHeight());
        preferredSize.set(d);
    }


public:
    BOOL getDisplayFont(LOGFONT& lf) {
        
        NONCLIENTMETRICS ncm;
        memset(&ncm, 0, sizeof(ncm)); 
        ncm.cbSize = sizeof(ncm); 

        BOOL rc = SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0); 
        if (rc) {
            lf = ncm.lfMessageFont; 
        }
        return rc;
    }

    //2009/11/01
public:
    operator HWND(){
        return (HWND)Window::getWindow();
    }
};

}



Last modified: 19 Dec 2009

Copyright (c) 2009 Antillia.com ALL RIGHTS RESERVED.