/*
* Copyright (C) 2000-2012 InfoChamp System Corporation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gk.engine.client.build;
import java.util.List;
import jfreecode.gwt.event.client.bus.EventBusIfc;
import jfreecode.gwt.event.client.bus.JsonConvert;
import org.gk.engine.client.IEngine;
import org.gk.engine.client.event.EventCenter;
import org.gk.engine.client.event.EventListener;
import org.gk.engine.client.gen.UIGen;
import org.gk.engine.client.utils.IRegExpUtils;
import org.gk.engine.client.utils.NodeUtils;
import org.gk.ui.client.com.IC;
import com.extjs.gxt.ui.client.core.XDOM;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.fx.Resizable;
import com.extjs.gxt.ui.client.widget.BoxComponent;
import com.extjs.gxt.ui.client.widget.Component;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.xml.client.Node;
/**
* GK核心元件
*
* <pre>
* 畫面元件根類別,提供共同的屬性設定
* </pre>
*
* @author I21890
* @since 2010/7/26
*/
public abstract class XComponent implements UIGen {
public static final String DATA = "_gk_data";
protected EventBusIfc bus = IEngine.bus;
protected String tag;
protected String content;
protected String id, type;
protected String width, height, enable, visible;
protected String init, bean, borders;
protected String tabIndex, style, title, clazz;
protected String resizable, preserveRatio, data;
protected String maxHeight, maxWidth, minHeight, minWidth;
protected Node node;
protected List widgets;
public XComponent() {
}
public XComponent(Node node, List widgets) {
this.node = node;
this.widgets = widgets;
tag = node.getNodeName();
id = getAttribute("id", tag + "-" + XDOM.getUniqueId());
type = getAttribute("type", "unknownComType");
width = getAttribute("width", "");
height = getAttribute("height", "");
enable = getAttribute("enable", "true");
visible = getAttribute("visible", "true");
init = getAttribute("init", "");
bean = getAttribute("bean", "");
borders = getAttribute("borders", "false");
tabIndex = getAttribute("tabIndex", "");
style = getAttribute("style", "");
clazz = getAttribute("class", "_none_");
title = getAttribute("title", "");
data = getAttribute("data", "");
resizable = getAttribute("resizable", "false");
preserveRatio = getAttribute("preserveRatio", "false");
maxHeight = getAttribute("maxHeight", "");
maxWidth = getAttribute("maxWidth", "");
minHeight = getAttribute("minHeight", "");
minWidth = getAttribute("minWidth", "");
EngineDataStore.addUIGenNode(id, this);
}
/**
* 將gul上的attribute data='' 轉成Map or List or String
*
* @return
*/
public Object getData() {
try {
char startChar = data.length() > 0 ? data.charAt(0) : ' ';
if (startChar == '{' || startChar == '[') {
JSONValue jsonObj = JSONParser.parseLenient(data);
if (jsonObj instanceof JSONObject) {
return JsonConvert.jsonToMap((JSONObject) jsonObj);
} else {
return JsonConvert.jsonToList((JSONArray) jsonObj);
}
} else {
return data;
}
} catch (Exception e) {
return "JSONParser exception!" + e.getMessage() + ",data [" + data
+ "]";
}
}
public String getTag() {
return tag;
}
public String getContent() {
return content;
}
public String getId() {
return id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getWidth() {
return width;
}
public String getHeight() {
return height;
}
public String getEnable() {
return enable;
}
public void setEnable(String enable) {
this.enable = enable;
}
public String getVisible() {
return visible;
}
public void setVisible(String hide) {
this.visible = hide;
}
public String getInit() {
return init;
}
public String getBean() {
return bean;
}
public String getBorders() {
return borders;
}
public String getTabIndex() {
return tabIndex;
}
public String getStyle() {
return style;
}
public String getClazz() {
return clazz;
}
public String getTitle() {
return title;
}
public Node getNode() {
return node;
}
public String getResizable() {
return resizable;
}
public String getPreserveRatio() {
return preserveRatio;
}
public String getMaxHeight() {
return maxHeight;
}
public String getMaxWidth() {
return maxWidth;
}
public String getMinHeight() {
return minHeight;
}
public String getMinWidth() {
return minWidth;
}
public List getWidgets() {
return widgets;
}
/**
* 元件建構完成後透過此方法初始化
*/
@Override
public void init() {
EventCenter.exec(id, init, this, null);
}
/**
* 回傳的資訊 (目前已完成檔案讀取)
*
* <pre>
* 當元件有設定動態語法File時,此方法會被調用, 注入取得的資訊
* </pre>
*
* @param eventId
* @param content
*/
public void onInfo(String eventId, String content) {
Object info;
if (JsonConvert.isJSONString(content)) {
info = JsonConvert.jsonString2Object(content);
} else {
info = content;
}
Component com = getComponent();
if (com instanceof IC) {
((IC) com).setInfo(info);
}
}
/**
* 元件建構後透過此方法設定屬性
*
* @param com
*/
protected void initComponent(Component com) {
com.setId(id);
if (!width.equals("")) {
com.setWidth(width);
}
if (!height.equals("")) {
com.setHeight(height);
}
if (!data.equals("")) {
com.setData(DATA, getData());
}
// 設定元件是否致能
boolean bool = Boolean.parseBoolean(enable);
if (com.isEnabled() != bool) {
com.setEnabled(!com.isEnabled());
}
// 設定元件是否不顯示
if (!Boolean.parseBoolean(visible)) {
com.setVisible(false);
}
com.setBorders(Boolean.parseBoolean(borders));
// tabIndex為數字才去setTabIndex
if (tabIndex.matches("\\d+")) {
com.setTabIndex(Integer.parseInt(tabIndex));
}
initStyleAttribute(com);
initClassAttribute(com);
// 判斷如果有設定title,就設定到元件中
if (!title.equals("")) {
com.setTitle(title);
}
// 设定Component是否可以resize
setResizePara(com);
EngineDataStore.addComponent(com.getId(), com);
}
/**
* 设定Component是否可以resize,及相关resize属性参数
*
* @param com
*/
public void setResizePara(Component com) {
// 如果resizable为true,其他相关属性才生效,同时判断com需为BoxComponent
if (Boolean.parseBoolean(resizable) && com instanceof BoxComponent) {
Resizable r = new Resizable((BoxComponent) com);
r.setDynamic(Boolean.parseBoolean(resizable));
// 是否保持宽高比例不变
r.setPreserveRatio(Boolean.parseBoolean(preserveRatio));
// 最大高度
if (maxHeight.matches(IRegExpUtils.POSITIVE_INTEGER)) {
r.setMaxHeight(Integer.parseInt(maxHeight));
}
// 最大宽度
if (maxWidth.matches(IRegExpUtils.POSITIVE_INTEGER)) {
r.setMaxWidth(Integer.parseInt(maxWidth));
}
// 最小高度
r.setMinHeight(getMinIntValue(minHeight, height, r.getMinHeight()));
// 最小宽度
r.setMinWidth(getMinIntValue(minWidth, width, r.getMinWidth()));
}
}
/**
* 取得最小int值,取值优先级:minVlue > value > defValue
*
* @param minValue
* @param value
* @param defValue
* @return int
*/
private int getMinIntValue(String minValue, String value, int defValue) {
boolean minFlag = minValue.matches(IRegExpUtils.POSITIVE_INTEGER);
boolean flag = value.matches(IRegExpUtils.POSITIVE_INTEGER);
return minFlag ? Integer.parseInt(minValue) : flag ? Integer
.parseInt(value) : defValue;
}
/**
* 取得屬性值
*
* @param nodeName
* @param defaultValue
* @return String
*/
public String getAttribute(String nodeName, String defaultValue) {
return NodeUtils.getNodeValue(node, nodeName, defaultValue);
}
@Override
public String toString() {
return id;
}
/**
* 將指定的Component添加指定的事件
*
* @param com
* 要進行監聽的元件
* @param eventType
* GXT的事件型別
* @param gulAttribute
* GUL屬性,例如 <grid onClick='xxx'/> , onClick就是gulAttribute
*/
protected void addEventListener(Component com, EventType eventType,
String gulAttribute) {
if (gulAttribute != null && !gulAttribute.equals("")) {
com.addListener(eventType,
new EventListener(id, gulAttribute, this));
}
}
/**
* <pre>
* 取得此物件生成的Component
* 此方法必須在GK引擎完成Render後才能使用
* </pre>
*
* @return Component
*/
public Component getComponent() {
return EngineDataStore.getComponent(id);
}
/**
* 初始化style屬性
*
* @param com
*/
private void initStyleAttribute(final Component com) {
final String[] styleAtt = style.split(";");
if (styleAtt.length == 0 || styleAtt[0].equals("")) {
return;
}
// 讓元件加入DOM後進行style設定,可覆寫原先style
com.addListener(Events.Render, new Listener<BaseEvent>() {
@Override
public void handleEvent(BaseEvent be) {
for (int i = 0; i < styleAtt.length; i++) {
String[] att = styleAtt[i].split(":");
if (att.length == 2) {
com.el()
.setStyleAttribute(att[0].trim(), att[1].trim());
}
}
}
});
}
/**
* 初始化class屬性
*
* @param com
*/
private void initClassAttribute(Component com) {
if (!clazz.equals("_none_")) {
com.setStyleName(clazz);
}
}
}