function Widget() {

    this.defaultProfile = {
        title: ""
    }



    this.domModel = 
      { tag: "div", className: "window", id: "window", 
        childs: [
          { tag: "div", 
            childs: [
              { tag: "table", className: "plan_table", style: { width: "100%"},
                childs: [
                  { tag: "tr",
                    childs: [
                      { tag: "td", className: "window_caption_left" },
                      { tag: "td", className: "window_caption_middle",
                        childs: [
                          { tag: "div", className: "window_caption",
                            id: "caption" }
                        ]},
                      { tag: "td", className: "window_caption_right" }
                    ]}
                ]}
            ]},

          { tag: "div", className: "window_setting", id: "settings"},

          { tag: "div", className: "window_content",
            id: "content" },

          { tag: "div", className: "window_footer", id: "footer", 
            childs: [
              { tag: "table", className: "plan_table", style: {width: "100%"},
                childs: [
                  { tag: "tr",
                    childs: [
                      { tag: "td", className: "window_footer_left" },
                      { tag: "td", className: "window_footer_middle", innerHTML: "&nbsp;"},
                      { tag: "td", className: "window_footer_right" }
                    ]}
                ]}
            ]}
        ]}// domModel






    this.init = function() {
        this.elements = {};
        this.id = null;
        this.isReduced = false;
        this.isSettingsReduced = true;
        this.profile = {};
        this.isPreview = false;
    }

    this.init();




    this.open = function(parent, id, profile) {
        this.buildWindow(parent);
        this.buildInterface();
        if(this.elements.window) {
            this.elements.window.wid = this.id;
        }
        
        this.onOpen();
    }


    this.setParent = function(parentEl) {
        this.elements.window.parentNode.removeChild(this.elements.window);
        parentEl.appendChild(this.elements.window);
    }



    this.buildWindow = function(parent) {
        this.domModel.display = !this.cfg.isOpenHidden;

        if(this.cfg.hasDrag) {
            this.domModel.events = { onmouseover: "checkMouseInOut(1)", onmouseout: "checkMouseInOut(0)"}
        }

        this.buildDomModel(parent, this.domModel);

        var m = [];

        if(this.cfg.hasSizeBtn) {
            m.push(
                { tag: "div",
                  className: "caption_left_element",
                  display: false, 
                  id: "showhide_div",
                  childs: [
                    { tag: "div", id: "btn_hide", className: "btn_hide",
                      title: loc.text("wbtn_hide"),
                      events: {onclick: "switchSize()"} },
                    { tag: "div", id: "btn_show", className: "btn_show", 
                      title: loc.text("wbtn_show"),
                      events: {onclick: "switchSize()"},
                      display: false}
                  ]}
            );
        }



        if(this.cfg.hasIcon) {
            m.push(
                { tag: "div", id: "icon_div",
                  className: "caption_left_element",
                  childs: [
                    { tag: "img", id: "icon", src: "widgets/"+this.cfg.module.toLowerCase()+"/ico.gif",
                      style: { width: "16px", height: "16px"}}
                  ]}
            );
        }


        m.push(
            { tag: "div", id: "title", className: "caption_title" }
        );



        if(this.cfg.hasCloseBtn) {
             m.push(
                 { tag: "a", href: "void", 
                   title: loc.text("wbtn_close"),
                   className: "btn_close",
                   display: !this.cfg.hasDrag,
                   events: {onclick: "close()"},
                   id: "btn_close" }
             );
        }


        if(this.cfg.hasSettingsBtn) {
            m.push(
                 { tag: "a", href: "void", 
                   title: loc.text("wbtn_settings"),
                   className: "btn_settings",
                   display: !this.cfg.hasDrag,
                   events: {onclick: "switchSettings()"},
                   id: "btn_settings" }
            );
        }


        if(this.cfg.hasRefreshBtn) {
            m.push(
                 { tag: "a", href: "void", 
                   title: loc.text("wbtn_refresh"),
                   className: "btn_refresh",
                   display: !this.cfg.hasDrag,
                   events: {onclick: "refresh()"},
                   id: "btn_refresh" }
            );
        }

        this.buildDomModel(this.elements["caption"], m);
    }



    this.initDtagAndDrop = function() {
        if(this.cfg.hasDrag) {
            this.elements.caption.style.cursor = 'move';
            this.elements.window.drag = new Drag(this.elements.window, this.elements.caption);
        }
    }


    this.buildInterface = function() {
        if(!this.isPreview) {
            this.initDtagAndDrop();
        }
        this.buildDomModel(this.elements.settings, 
            { tag: "div", className: "settings_section",
              childs: [
                  {tag: "span", innerHTML: loc.text("inp_title"), className: "settings_label"},
                  {tag: "input", id: "input_title", type: "text", size: "15", className: "settings_control"}, 
                  {tag: "input", type: "button", value: loc.text("btn_set"), events: {onclick: "settingsSetTitle()"}, className: "settings_control"}
              ]}        
        );
        this.onBuildInterface();
    }


    this.disableOnClosePrompt = false;
    this.isForceClose = false;

    this.forceClose = function() {
        this.isForceClose = true;
        this.disableOnClosePrompt = true;
        this.close();
    }

    this.close = function() {
        var flag = (this.cfg.hasOnCloseConfirm && !this.disableOnClosePrompt) ? 
                   confirm(loc.text("desktop_confirm_widget_remove")) 
                   : 
                   true; 

        if(flag) {
            this.onClose();

            kernel.freeWidget(this.id);
            if(this.elements.window) {
                deleteEl(this.elements.window);

                this.elements.window.innerHTML = '';
                this.elements.window = null;
            }

            this.profile = false;
            this.save();

            if(this.cfg.hasDrag && !this.isForceClose) {
                desktop.savePanels();
            }
        }
    }




    this.setTitle = function(html) {
        this.elements.title.innerHTML = html;
    }


    this.checkMouseInOut = function(mouse_in) {
        if (mouse_in==1 || this.isSettingsReduced==false) {
           if(this.cfg.hasCloseBtn && !this.isPreview)    this.elements.btn_close.style.display = 'block';
           if(this.cfg.hasSettingsBtn) this.elements.btn_settings.style.display = 'block';
           if(this.cfg.hasRefreshBtn)  this.elements.btn_refresh.style.display = 'block';
           if(this.cfg.hasSizeBtn){
             this.elements.showhide_div.style.display = 'block';
             if(this.cfg.hasIcon) this.elements.icon_div.style.display = 'none';
           }

        }
        else {
           if(this.cfg.hasCloseBtn)    this.elements.btn_close.style.display = 'none';
           if(this.cfg.hasSettingsBtn) this.elements.btn_settings.style.display = 'none';
           if(this.cfg.hasRefreshBtn)  this.elements.btn_refresh.style.display = 'none';
           if(this.cfg.hasSizeBtn){
             this.elements.showhide_div.style.display = 'none';
             if(this.cfg.hasIcon) this.elements.icon_div.style.display = 'block';
           }
        }
    }


    this.switchSize = function() {
        if(this.isReduced) {
            this.show();
        } else {
            this.hide();
        }
    }


    this.show = function() {
        hideEl(this.elements.btn_show);
        showEl(this.elements.btn_hide);

        if(this.elements.content) {
            showEl(this.elements.content);
        }
        this.onShow();
        this.isReduced = false;
    }


    this.hide = function() {
        hideEl(this.elements.btn_hide);
        showEl(this.elements.btn_show);

        if(this.elements.content) {
            hideEl(this.elements.content);
        }

        this.hideSettings();
        this.onHide();
        this.isReduced = true;
    }



    this.switchSettings = function() {
        if(this.isSettingsReduced) {
            this.showSettings();
        } else {
            this.hideSettings();
        }
    }


    this.showSettings = function() {
        this.onShowSettings();
        showEl(this.elements.settings);
        this.isSettingsReduced = !this.isSettingsReduced;
    }


    this.hideSettings = function() {
        if(this.elements.settings) {
            hideEl(this.elements.settings);
            this.isSettingsReduced = !this.isSettingsReduced;
        }
    }


    this.attachEvent = function(el, e, cmd) {
        var wid = this.id;
        if(mozilla_nav) {
            el.setAttribute(e, "kernel.getWidget("+wid+")."+cmd+";");
        } else {
            el[e] = new Function("kernel.getWidget("+wid+")."+cmd+";");
        }
    }


    this.buildDomModel = function(parentEl, data) {
        if(data['tag']) {
            var el = document.createElement(data.tag);
            for (p in data) {
                switch(p) {
                    case null, "tag", "childs": break;

                    case "id":
                        this.elements[data.id] = el;
                        break;                    

                    case "style":
                        for(var s in data.style) {
                            el.style[s] = data.style[s];
                        }
                        break;


                    case "options":
                        for(var i in data.options) {
                            el.options.add(new Option(data.options[i].text, data.options[i].value));

                            if(data.options[i].isBold) {
                                el.options[el.options.length - 1].style.fontWeight = "bold";
                            }
                        }
                        break;

                    case "src":
                        var src = data.src;
                        if(src.indexOf("http") == -1) {
                            src = "http://"+baseUrl+src;
                            
                        }

                        if(ie_nav) {
                            var setSrc = function() { el.src = src }
                            setTimeout(setSrc, 200);
                        } else {
                            el.src = src;
                        }
                        break;

                    case "display":
                        if(!data[p]) {
                            el.style.display = 'none'; 
                        }
                        break;

                    case "href":
                        if(data.href == "void") {
                            el.href = "javascript:void(0);";
                        } else if(data.tag == "a") {
                            this.attachEvent(el, "onclick", data.href);
                            el.href = "javascript:void(0);";
                        } else {
                            el.href = data.href;
                        }
                        break;


                    case "html":
                        el.innerHTML = data.html;
                        break;

                    case "sysHref":
                        el.href = data.sysHref;
                        break;

                    case "events":
                        var wid = this.id;
                        if(typeof(data.events) == "object") {
                            for(var e in data.events) {
                                this.attachEvent(el, e, data.events[e]);
                            }
                        }
                        break;

                    case "sysEvents":
                        if(typeof(data.sysEvents) == "object") {
                            for(var e in data.sysEvents) {
                                el.setAttribute(e, data.sysEvents[e]+";");
                            }
                        }
                        break;

                    default:
                        el[p] = data[p];
                        break;
                }
            }

            parentEl.appendChild(el);

            if(data.tag == "table") {
                parentEl = el;
                var el = document.createElement("tbody");
                if(data.id) {
                    this.elements[data.id+"_tbody"] = el;
                } 
                parentEl.appendChild(el);
            }
            
            if(data.childs) {
                this.buildDomModel(el, data.childs);
            }

        } else {
            for(var e in data) {
                this.buildDomModel(parentEl, data[e]);
            }
        }

    }





    this.settingsSetTitle = function() {
        var t = trim(this.elements.input_title.value);
        if(t != this.profile.title) {
            this.profile.title = t
            this.setTitle(t);
            this.save();
        }
    }



    this.save = function() {
        profiler.saveProfile(this);
    }



    this.onOpen = function() {}
    this.onBuildInterface = function() {}
    this.onClose = function() {}
    this.onShow = function() {}
    this.onHide = function() {}
    this.onShowSettings = function() {}
    this.onDrag = function() {}

    this.timerHandler = function() {}
    this.refresh = function() {}
    this.dispatchMsg = function() {}




    // SYS

    this.hideElement = function(id) {
        if(this.elements[id]) {
            this.elements[id].style.display = 'none';
        }
    }


    this.showElement = function(id, display) {
        if(this.elements[id]) {
            this.elements[id].style.display = display ? display : 'block';
        }
    }

}