{
   PASCAL SCRIPT / JavaScript

   Pascal Script file should be encoded with GBK or ASCII charset, while Javascript file uses UTF-8 encode.
   Include files in Pascal Script: {$INCLUDE fileName} or {$I fileName}
   Inlcude files in Javascript: #include "fileName"
   We do not support debuggine for Javascript now.

   Following properties and functions are declared in PASCAL style. When used in Javascript, first letters should be lowercased.
   For example:
     PASCAL：　　CurOut.Add('Current table: '+CurTable.Name);
     JAVASCRIPT：curOut.add("Current table: "+curTable.name);

Main variables:
var
  AllModels: TCtDataModelGraphList;
  CurModel: TCtDataModelGraph; 
  CurTable: TCtMetaTable;
  CurField: TCtMetaField;
  CurOut: TStrings;
  CurSettingsPanel: TDmlScriptControlList;

  Application: TApplication;
  Screen: TScreen;


   Pascal脚本须采用GBK或ASCII编码，JavaScript文件请使用UTF-8编码。
   Pascal脚本包含引用文件：{$INCLUDE 文件名} 或 {$I 文件名}
   JavaScript脚本包含引用文件：#include "文件名"
   JavaScript脚本目前不支持单步调试。
   JavaScript和Pascal脚本之间可以通过RunDmlScript函数互相混合调用。

  后面所列所有类的方法和属性均为Pascal方式，在JavaScript中使用时，首字母要小写，如：
     PASCAL：　　CurOut.Add('当前表名：'+CurTable.Name);
     JAVASCRIPT：curOut.add("当前表名："+curTable.name);


   以下为主要的全局变量，相关的类属性方法在后面有定义：
var
  AllModels: TCtDataModelGraphList;//所有模型列表。AllModels.CurDataModel为当前模型
  CurModel: TCtDataModelGraph; //当前模型（注：可能为空）
  CurTable: TCtMetaTable;//当前表（注：可能为空）
  CurField: TCtMetaField;//当前字段（注：可能为空）
  CurOut: TStrings;//当前输出设备
  CurSettingsPanel: TDmlScriptControlList;//当前参数面板（注：可能为空）

  Application: TApplication; //获取MainForm、ExeName
  Screen: TScreen; //可用于遍历窗体和获取当前活动的窗体、控件


  更多的内容，请参阅官网《EZDML常见问题》、《EZDML快速上手》、《EZDML配置文件说明》、《EZDML脚本配置》等文档。
}

unit DmlTablePS;

interface

type
  TCtObject = class;
  TCtObjectList = class;
  TCtGlobList = class;
  
  TCTMetaFieldList = class;
  TCtMetaTableList = class;
  TCtDataModelGraph = class;
  TCtDataModelGraphList = class;
          

  TList = class(TObject)
  private
  protected
  public
    destructor Destroy; override;
    function Add(Item: TObject): Integer;
    procedure Clear; virtual;
    procedure Delete(Index: Integer);
    procedure Exchange(Index1, Index2: Integer);
    function IndexOf(Item: TObject): Integer;
    procedure Insert(Index: Integer; Item: TObject);
    procedure Move(CurIndex, NewIndex: Integer);
    function Remove(Item: TObject): Integer;
    procedure Pack;
    procedure Sort(Compare: TListSortCompare);
    property Capacity: Integer read FCapacity write SetCapacity;
    property Count: Integer read FCount write SetCount;
    property Items[Index: Integer]: TObject read Get write Put; default;
  end;
  
               
  //When reading Enum types in Javascript, you will get enum-name result of String type. You can also use integer type for setting enum values.
  //For example: curTable.dataLevel='cdtlDeleted'; or curTable.dataLevel=4;
  //枚举类型，在JavaScript中取值时将返回名称；传入参数时，可以用名称也可以用数值，如：curTable.dataLevel='cdtlDeleted'; 或 curTable.dataLevel=4;
  //CT数据级别
  TctDataLevel = (ctdlUnknown, ctdlNormal, ctdlNew, ctdlModify, ctdlDeleted, ctdlDraft, ctdlDebug);
  
  //CT对象基类，包含基本属性和串行化接口
  //guid:{E8D33D36-66DF-4568-8537-F24A1EDE0588}
  TCtObject = class(TObject)
  private
  protected
  public
    constructor Create; virtual;
    destructor Destroy; override;

    //排序
    procedure SortByOrderNo; virtual;
    procedure SortByName;

    //状态保存恢复接口
    procedure Reset; virtual;
    procedure AssignFrom(ACtObj: TCtObject); virtual;
    procedure LoadFromFile(fn: string); virtual;
    procedure SaveToFile(fn: string); virtual;
    function SaveToTempFile(ext: string): string; virtual; //保存到临时文件，返回临时文件名，ext为扩展名，默认为json
    function ExecCmd(ACmd, AParam1, AParam2: string): string; virtual;

    //基本属性：ID PID RID 名称 别名 类型 注释 创建时间和创建人 最后修改时间和修改人 数据级别
    property ID: Integer read FID write FID;
    property CtGuid: string read FCtGuid write FCtGuid;
    property PID: Integer read FPID write FPID;
    property RID: Integer read FRID write FRID;
    property Name: string read FName write FName;
    property Caption: string read FCaption write SetCaption;
    property TypeName: string read FTypeName write FTypeName;
    property Memo: string read FMemo write FMemo;
    property DisplayText: string read GetDisplayText;

    property CreateDate: TDateTime read FCreateDate write FCreateDate;
    property Creator: Integer read FCreator write FCreator;
    property CreatorName: string read FCreatorName write FCreatorName;
    property ModifyDate: TDateTime read FModifyDate write FModifyDate;
    property Modifier: Integer read FModifier write FModifier;
    property ModifierName: string read FModifierName write FModifierName;

    property DataLevel: TctDataLevel read FDataLevel write FDataLevel;
    //排序号
    property OrderNo: Double read FOrderNo write FOrderNo;

    property SubItems: TCtObjectList read GetSubitems write FSubitems;
    property HasSubItems: Boolean read GetHasSubItems;
    //父列表
    property ParentList: TCtObjectList read FParentList write FParentList;
    //所有对象全局列表
    property GlobeList: TCtGlobList read FGlobeList write SetGlobeList;
    //用户自定义对象
    property UserObjectList: TStrings read GetUserObjectList;
    property UserObjectCount: Integer read GetUserObjectCount;
    property UserObject[Index: string]: TObject read GetUserObject write SetUserObject;
    //参数转为TSTRINGS
    property ParamList: TStrings read GetParamList;
    property Param[Name: string]: string read GetParam write SetParam;
  end;

  { 自释放列表 }
  TCtAutoFreeList = class(TList)
  protected
  public
    constructor Create; virtual;
    destructor Destroy; override;

    //自动FREE
    property AutoFree: Boolean read FAutoFree write FAutoFree;
  end;

  TCtGlobList = class(TCtAutoFreeList)
  private
  protected
  public
  end;

  //CT对象列表，可新建、自动FREE，保存数据流，展开子项
  TCtObjectList = class(TCtGlobList)
  private
  protected
  public
    constructor Create; override;
    destructor Destroy; override;

    //状态保存恢复接口
    procedure AssignFrom(ACtObj: TCtObjectList); virtual;

    ///新建对象 ××××××××××××××注意：子类必须仍然保留使用此方法创建对象×××××××××××
    function NewObj: TCtObject; virtual;
    //展开子项
    procedure ExpandItem(AItem: TCtObject); virtual;
    //子项释放通知
    procedure NotifyChildFree(AItem: TCtObject); virtual;
    //创建全局列表，这样一个列表中就记录了同一棵树下的所有节点
    function CreateGlobeList: TCtGlobList; virtual;
    //获取子项
    function ItemByID(AID: Integer): TCtObject; virtual;
    function ItemByName(AName: string; bCaseSensive: Boolean = False): TCtObject; virtual;
    function NameOfID(AID: Integer): string; virtual;

    //删除无效节点
    procedure Pack; virtual;
    //仅删除（不FREE）
    procedure MereRemove(AItem: TCtObject); virtual;
    //排序
    procedure SortByOrderNo; virtual;
    //保存当前顺序
    procedure SaveCurrentOrder; virtual;
    //按名称排序（第二次执行为反序）
    procedure SortByName;

    property Items[Index: Integer]: TCtObject read GetCtItem write PutCtItem; default;
    //子类
    property ItemClass: TCtObjectClass read FItemClass write FItemClass;
    //所有对象全局列表
    //这样一个全局列表中记录了同一棵树下的所有节点
    property GlobeList: TCtGlobList read FGlobeList write FGlobeList;
  end;

  TCtMetaObject = class(TCtObject)
  private
  public
    property JsonStr: string read GetJsonStr write SetJsonStr;
    property MetaModified: Boolean read GetMetaModified write SetMetaModified;
    property IsSelected: Boolean read FIsSelected write FIsSelected; //是否被选中
  end;

  TCtMetaObjectList = class(TCtObjectList)
  end;

  { CT数据表 }
  //注意：TYPENAME为空或TABLE时才是表，为TEXT时是纯文字
  //为FUNCTION、PROCEDURE、PACKAGE时为存储过程
  //为DATASQL时表示插入数据的初始化SQL
  TCtMetaTable = class(TCtMetaObject)
  private
  protected
  public
    constructor Create; override;
    destructor Destroy; override;

    //状态保存恢复接口
    procedure Reset; override;
    procedure AssignFrom(ACtObj: TCtObject); override;

    function GetTableComments: string; virtual;
    function GetPrimaryKeyNames(AQuotDbType: string = ''): string;
    function IsText: boolean;virtual;
    function IsTable: boolean; virtual;
    function IsSqlText: boolean; virtual; 

    function GetTitleFieldName: string;
    function GetPrimaryKeyField: TCtMetaField; virtual;
    function FieldOfChildTable(ATbName: string): TCtMetaField; virtual; //获取引用子表的List字段 
    function IsManyToManyLinkTable: Boolean; virtual;
    function GetOneToManyInfo(bFKsOnly: Boolean): string; virtual;
    function GetManyToManyInfo: string; virtual;

    function GenSqlEx(bCreatTb: Boolean; bFK: Boolean; dbType: string = ''): string; virtual;
    function GenSql(dbType: string = ''): string; virtual;
    function GenSqlWithoutFK: string; virtual;
    function GenFKSql: string; virtual;
    function GenDqlDmlSql(dbType: string = ''): string; virtual;
    function GenSelectSql(maxRowCount: integer; dbType: string = ''): string; virtual;  

    function GetCustomConfigValue(AName: string): string; virtual;
    procedure SetCustomConfigValue(AName, AValue: string); virtual;
                  
    function GetSpecKeyNames(keyFieldTp: TCtKeyFieldType;
      AQuotDbType: string): string;
    function GetPossibleKeyName(keyFieldTp: TCtKeyFieldType): string;
    
    function GetDemoJsonData(ARowIndex: Integer; AOpt, AFields: string): string; virtual;
    
    property OwnerList: TCtMetaTableList read FOwnerList;

    //外部模块编号
    property CustomModId: Integer read FCustomModId write FCustomModId;
    //物理表名
    property RealTableName: string read GetRealTableName;   
    property PhysicalName: string read FPhysicalName write FPhysicalName;   
    //在界面上显示的名称
    property UIDisplayName: string read GetUIDisplayName; 
    property UIDisplayText: string read FUIDisplayText write FUIDisplayText; 
    //图形描述
    property GraphDesc: string read FGraphDesc write FGraphDesc;

    //元字段列表
    property MetaFields: TCTMetaFieldList read GetMetaFields;
    //主键字段名
    property KeyFieldName: string read GetKeyFieldName;

    //描述字
    property Describe: string read GetDescribe write SetDescribe;
    //粗略描述字（仅物理名+逻辑类型）
    property SketchyDescribe: string read GetSketchyDescribe; 
              
    //背景色
    property BgColor: integer read FBgColor write FBgColor;  
    //是否生成数据库
    property GenDatabase: boolean read FGenDatabase write FGenDatabase;
    //是否生成代码
    property GenCode: boolean read FGenCode write FGenCode;
    //发布类型 0不发布 1普通 2菜单
    property PublishType: TCtModulePublishType read FPublishType write FPublishType;  
    //视图SQL
    property ViewSQL: string read FViewSQL write FViewSQL;  
    //列表SQL
    property ListSQL: string read FListSQL write FListSQL;    
    //额外的数据库SQL
    property ExtraSQL: string read FExtraSQL write FExtraSQL;
    //前端界面逻辑
    property UILogic: string read FUILogic write FUILogic;
    //后端业务逻辑
    property BusinessLogic: string read FBusinessLogic write FBusinessLogic;
    //扩展属性
    property ExtraProps: string read FExtraProps write FExtraProps;
              
    //自定义配置
    property CustomConfigs: string read FCustomConfigs write FCustomConfigs;
    //脚本配置
    property ScriptRules: string read FScriptRules write FScriptRules;

    //权限角色
    property PurviewRoles: String        read FPurviewRoles write FPurviewRoles;
    //数据权限
    property DataPurview : String        read FDataPurview  write FDataPurview ;  
    //表是否只读
    property IsReadOnly: Boolean       read FIsReadOnly write FIsReadOnly;  
  end;

  { CT数据表列表 }
  TCtMetaTableList = class(TCtMetaObjectList)
  private
  protected
  public
    function NewTableItem: TCtMetaTable; virtual;

    property Items[Index: Integer]: TCtMetaTable read GetItem write PutItem; default;
    property OwnerModel: TCtDataModelGraph read FOwnerModel;
  end;

  TCtFieldDataType = (
    cfdtUnknow,
    cfdtString,
    cfdtInteger,
    cfdtFloat,
    cfdtDate,
    cfdtBool,
    cfdtEnum,
    cfdtBlob,
    cfdtObject,
    cfdtCalculate,
    cfdtList,
    cfdtFunction,
    cfdtEvent,
    cfdtOther);

  TCtKeyFieldType =
    (
    cfktNormal,
    cfktId,
    cfktPid,
    cfktRid,
    cfktName,
    cfktCaption,
    cfktComment,
    cfktTypeName,
    cfktOrgId,
    cfktPeriod,
    cfktCreatorId,
    cfktCreatorName,
    cfktCreateDate,
    cfktModifierId,
    cfktModifierName,
    cfktModifyDate,
    cfktVersionNo,
    cfktHistoryId,
    cfktLockStamp,
    cfktInstNo,
    cfktProcID,
    cfktURL,
    cfktStatus,
    cfktOrderNo,
    cfktOthers
    );

  TCtFieldIndexType =
    (
    cfitNone,
    cfitUnique,
    cfitNormal
    );

  TCtFieldDropDownMode =
    (
    cfddNone,
    cfddFixed,
    cfddEditable,
    cfddAppendable
    );

  TCtFieldFixColType =
    (
    cffcNone,
    cffcLeft,
    cffcRight
    );

  TCtTextAlignment =
    (
    cftaAuto,
    cftaLeft,
    cftaRight,
    cftaCenter
    );

  TCtModulePublishType =( cmptNone, cmptModule, cmptMenu );
                      
  { CT数据字段 }
  TCtMetaField = class(TCtMetaObject)
  private
  protected
  public
    constructor Create; override;
    destructor Destroy; override;

    //状态保存恢复接口
    procedure Reset; override;
    procedure AssignFrom(ACtObj: TCtObject); override;

    function GetLogicDataTypeName: string;
    function GetFieldTypeDesc(bPhy: Boolean = False; dbType: string = ''): string;
    function GetFieldComments: string;
    function GetFieldDefaultValDesc(dbType: string = ''): string;

    function GetConstraintStr: string;
    procedure SetConstraintStr(Value: string);
    function GetConstraintStrEx(bWithKeys, bWithRelate: boolean): string;
    procedure SetConstraintStrEx(Value: string; bForce: boolean);
                                
    function GetCustomConfigValue(AName: string): string;
    procedure SetCustomConfigValue(AName, AValue: string);

    function HasValidComplexIndex: boolean; 
    function IsLobField(dbType: string): boolean;
    function IsPK: Boolean;
    function IsFK: Boolean;
    function IsPhysicalField: Boolean;

    function PossibleKeyFieldType: TCtKeyFieldType;
    function CanDisplay(tp: string): boolean;
    function IsRequired: boolean;
    function GetLabelText: string;
    function PossibleEditorType: string;
    function PossibleTextAlign: TCtTextAlignment;

    function GenDemoData(ARowIndex: integer; AOpt: string; ADataSet: TDataSet): string;
    function PossibleDemoDataRule: string;
    function ExtractDropDownItemsFromMemo: string;

    function GetRelateTableObj: TCtMetaTable;
    function GetRelateTableField: TCtMetaField;
    function GetRelateTableTitleField: TCtMetaField;
    function GetRelateTableDemoJson(ARowIndex: Integer; AOpt: string): string;


    property OwnerList: TCtMetaFieldList read FOwnerList;
    property OwnerTable: TCtMetaTable read GetOwnerTable;


    //编号
    property ID;
    //表编号
    property RID;
    //名称
    property Name;
    //显示名称
    property DisplayName: string read FDisplayName write FDisplayName;
    //数据类型
    property DataType: TCtFieldDataType read FDataType write FDataType;
    //数据类型
    property DataTypeName: string read FDataTypeName write FDataTypeName;
    //关键字段类型_IdPidRid...
    property KeyFieldType: TCtKeyFieldType read FKeyFieldType write FKeyFieldType;
    //关联表
    property RelateTable: string read FRelateTable write FRelateTable;
    //关联表的物理名
    property RelateTableRealName: string read GetRelateTableRealName;
    //关联字段
    property RelateField: string read FRelateField write FRelateField;
    //索引类型_0无1唯一2普通
    property IndexType: TCtFieldIndexType read FIndexType write FIndexType;
    //索引字段
    property IndexFields: string read FIndexFields write FIndexFields;
    //数据库检查
    property DBCheck: string read FDBCheck write FDBCheck;
    //提示
    property Hint: string read FHint write FHint;
    //备注
    property Memo;
    //缺省值
    property DefaultValue: string read FDefaultValue write FDefaultValue;
    //是否可为空
    property Nullable: Boolean read GetNullable write FNullable;
    //最大长度
    property DataLength: Integer read FDataLength write FDataLength;
    //精度
    property DataScale: Integer read FDataScale write FDataScale;

    //链接
    property Url: string read FUrl write FUrl;
    //资源类型
    property ResType: string read FResType write FResType;
    //公式
    property Formula: string read FFormula write FFormula;
    //公式条件
    property FormulaCondition: string read FFormulaCondition write FFormulaCondition;
    //汇总函数
    property AggregateFun: string read FAggregateFun write FAggregateFun;
    //计量单位
    property MeasureUnit: string read FMeasureUnit write FMeasureUnit;
    //字段值检查规则
    property ValidateRule: string read FValidateRule write FValidateRule;
    //编辑器类型
    property EditorType: string read FEditorType write FEditorType;
    //标签文字
    property LabelText: string read FLabelText write FLabelText;
    //编辑器是否只读
    property EditorReadOnly: Boolean read FEditorReadOnly write FEditorReadOnly;
    //编辑器是否激活
    property EditorEnabled: Boolean read FEditorEnabled write FEditorEnabled;
    //显示格式
    property DisplayFormat: string read FDisplayFormat write FDisplayFormat;
    //输入格式
    property EditFormat: string read FEditFormat write FEditFormat;
    //字体名称
    property FontName: string read FFontName write FFontName;
    //字体大小
    property FontSize: Double read FFontSize write FFontSize;
    //字体样式
    property FontStyle: Integer read FFontStyle write FFontStyle;
    //前景颜色
    property ForeColor: Integer read FForeColor write FForeColor;
    //背景颜色
    property BackColor: Integer read FBackColor write FBackColor;
    //下拉列表
    property DropDownItems: string read FDropDownItems write FDropDownItems;
    //下拉模式_0无1选择2编辑3添加
    property DropDownMode: TCtFieldDropDownMode read FDropDownMode write FDropDownMode;
    //DML图形描述
    property GraphDesc: string read FGraphDesc write FGraphDesc;

    //显示级别
    property Visibility: Integer read FVisibility write FVisibility;
    //文字对齐
    property TextAlign: TAlignment read FTextAlign write FTextAlign;
    //列宽
    property ColWidth: Integer read FColWidth write FColWidth;
    //最大长度
    property MaxLength: Integer read FMaxLength write FMaxLength;
    //是否可搜索
    property Searchable: Boolean read FSearchable write FSearchable;
    //是否可查询
    property Queryable: Boolean read FQueryable write FQueryable;
    //是否可导出
    property Exportable: boolean read FExportable write FExportable;

    //初始值
    property InitValue: string read FInitValue write FInitValue;
    //值格式类型
    property ValueFormat: string read FValueFormat write FValueFormat;
    //最小值
    property ValueMin: string read FValueMin write FValueMin;
    //最大值
    property ValueMax: string read FValueMax write FValueMax;
    //扩展属性
    property ExtraProps: string read FExtraProps write FExtraProps;
    //自定义配置
    property CustomConfigs: string read FCustomConfigs write FCustomConfigs;

    
    //说明文字
    property ExplainText: string read FExplainText write FExplainText;

    //是否隐藏
    property IsHidden: boolean read FIsHidden write FIsHidden;
    //是否在列表中默认隐藏（可手工选择显示）
    property HideOnList: boolean read FHideOnList write FHideOnList;
    //是否编辑时隐藏
    property HideOnEdit: boolean read FHideOnEdit write FHideOnEdit;
    //是否查看（只读）时隐藏
    property HideOnView: boolean read FHideOnView write FHideOnView;

    //编辑器其它属性
    property EditorProps: string read FEditorProps write FEditorProps;
    //表单分组
    property SheetGroup: string read FSheetGroup write FSheetGroup;
    //列表头分组
    property ColGroup: string read FColGroup write FColGroup;
    //冻结列类型
    property FixColType: TCtFieldFixColType read FFixColType write FFixColType;
    //表格中自动合并相同列值
    property AutoMerge: boolean read FAutoMerge write FAutoMerge;
    //表格中显示过滤钮
    property ShowFilterBox: boolean read FShowFilterBox write FShowFilterBox;
    //表格中显示排序钮
    property ColSortable: boolean read FColSortable write FColSortable;

    //下拉SQL
    property DropDownSQL: string read FDropDownSQL write FDropDownSQL;

    //每行分几列（对复选列表、单选列表、按钮列表等有效）
    property ItemColCount: integer read FItemColCount write FItemColCount;


    //裁剪内容长度（多行文本，显示“更多”按钮）
    property TextClipSize: integer read FTextClipSize write FTextClipSize;


    //必填
    property Required: Boolean read FRequired write FRequired;

    //是否自动去除文字两头空格
    property AutoTrim: boolean read FAutoTrim write FAutoTrim;
    //生成测试数据规则
    property TestDataRules: string read FTestDataRules write FTestDataRules;
    //前端界面逻辑
    property UILogic: string read FUILogic write FUILogic;
    //后端业务逻辑
    property BusinessLogic: string read FBusinessLogic write FBusinessLogic;

  end;

  { CT数据字段列表 }
  TCtMetaFieldList = class(TCtObjectList)
  private
  protected
  public
    function NewMetaField: TCtMetaField;

    function FieldByName(AName: string): TCtMetaField;
    function FieldByDisplayName(ADispName: string): TCtMetaField;
    function FieldByLabelName(ALbName: string): TCtMetaField;

    property OwnerTable: TCtMetaTable read FOwnerTable;
    property Items[Index: Integer]: TCtMetaField read GetItem write PutItem; default;
  end;

  { 数据模型图 }
  TCtDataModelGraph = class(TCtMetaObject)
  private
  protected
  public
    constructor Create; override;
    destructor Destroy; override;

    //CT对象相关接口
    procedure Reset; override;
    procedure AssignFrom(ACtObj: TCtObject); override;
    
    function IsCatalog: boolean;
    function IsModel: boolean;    

    property ID; //       : Integer       read FID           write FID          ;
    property Name; //     : String        read FName         write FName        ;
    //显示名称
    property DisplayName: string read GetDisplayName;
    //图形区宽度
    property GraphWidth: Integer read FGraphWidth write FGraphWidth;
    //图形区高度
    property GraphHeight: Integer read FGraphHeight write FGraphHeight;
    //缺省数据连接
    property DefDbEngine: string read FDefDbEngine write FDefDbEngine;
    //数据连接名
    property DbConnectStr: string read FDbConnectStr write FDbConnectStr;
    //选项设置串
    property ConfigStr: string read FConfigStr write FConfigStr; 
    //路径
    property ModelPath: String  read FModelPath write FModelPath;      ;    
    //权限角色
    property PurviewRoles: String  read FPurviewRoles write FPurviewRoles;
    //发布类型 0不发布 1普通 2菜单
    property PublishType: TCtModulePublishType read FPublishType write FPublishType;
    //扩展属性
    property ExtraProps : String        read FExtraProps  write FExtraProps ; 
    //数据表
    property Tables: TCtMetaTableList read FTables write FTables;

    property OwnerList: TCtDataModelGraphList read FOwnerList;
  end;

  { 数据模型图列表 }
  TCtDataModelGraphList = class(TCtObjectList)
  private
  protected
  public
    procedure LoadFromFile(fn: string);
    procedure SaveToFile(fn: string);
    procedure SortByOrderNo; override;
    procedure Pack; override;
    function TableCount: Integer;
    function NewCatalogItem: TCtDataModelGraph; 
    function NewModelItem: TCtDataModelGraph;
    property CurDataModel: TCtDataModelGraph read GetCurDataModel write FCurDataModel;
    property Items[Index: Integer]: TCtDataModelGraph read GetItem write PutItem; default;
    property OnObjProgress: TMetaObjProgressEvent read FOnObjProgress write FOnObjProgress;
  end;

  { DML脚本控件 用于SettingsPanel }
  TDmlScriptControl = class(TObject)
  private
  public
    //是否有值
    function HasValue: Boolean;

    //编号
    property Id: Integer read FId write FId;
    //控件类型
    property ControlType: string read FControlType write FControlType;
    //名称
    property Name: string read FName write FName;
    //标题
    property Caption: string read FCaption write FCaption;
    //子项
    property Items: string read FItems write FItems;
    //值
    property Value: string read FValue write SetValue;
    //其它参数
    property Params: string read FParams write FParams;

    //描述字
    property TextDesc: string read GetTextDesc write SetTextDesc;
    //关联控件
    property Control: TControl read FControl write FControl;
  end;

  { DML脚本控件列表 用于SettingsPanel }
  TDmlScriptControlList = class(TList)
  public

    //获取指定面板项的值
    function GetItemValue(AName: string): string;
    //设置指定面板项的值
    procedure SetItemValue(AName: string; AValue: string);

    //重新生成所有控件
    procedure RegenControls;

    property Items[Index: Integer]: TDmlScriptControl read GetItem write PutItem; default;
    //当前按下的按钮名称，或当前编辑的文本框、下拉框等的名称
    property CurAction: string read FCurAction write FCurAction;
    //描述字，用于创建所有控件
    property TextDesc: string read GetTextDesc write SetTextDesc;
    //JSON值，只包含有值的内容
    property JsonValStr: string read GetJsonValStr write SetJsonValStr;
    //父容器，用于放置创建的子控件
    property ParentWnd: TWinControl read FParentWnd write FParentWnd;
  end;

  //主程序对象
  TApplication = class(TComponent)
  public
    function MessageBox(const Text, Caption: PChar; Flags: Longint = MB_OK): Integer;
    procedure Minimize;
    procedure Restore;
    procedure ProcessMessages;
    procedure Terminate;
    property Active: Boolean read FActive;
    property ExeName: string read GetExeName; //程序EXE文件的全路径
    property Handle: Cardinal read FHandle write SetHandle;
    property MainForm: TForm read FMainForm; //程序主窗口
    property Terminated: Boolean read FTerminate;
    property Title: string read GetTitle write SetTitle;
  end;

  //屏幕对象
  TScreen = class(TComponent)
  private
  public
    procedure DisableAlign;
    procedure EnableAlign;
    procedure Realign;
    procedure ResetFonts;
    property ActiveControl: TWinControl read FActiveControl;  //当前焦点所在控件
    property ActiveForm: TForm read FActiveForm; //当前焦点所在窗体
    property DesktopRect: TRect read GetDesktopRect;
    property DesktopHeight: Integer read GetDesktopHeight;
    property DesktopLeft: Integer read GetDesktopLeft;
    property DesktopTop: Integer read GetDesktopTop;
    property DesktopWidth: Integer read GetDesktopWidth;
    property WorkAreaRect: TRect read GetWorkAreaRect;
    property WorkAreaHeight: Integer read GetWorkAreaHeight;
    property WorkAreaLeft: Integer read GetWorkAreaLeft;
    property WorkAreaTop: Integer read GetWorkAreaTop;
    property WorkAreaWidth: Integer read GetWorkAreaWidth;
    property HintFont: TFont read FHintFont write SetHintFont;
    property IconFont: TFont read FIconFont write SetIconFont;
    property MenuFont: TFont read FMenuFont write SetMenuFont;
    property Fonts: TStrings read GetFonts;
    property FormCount: Integer read GetFormCount;
    property Forms[Index: Integer]: TForm read GetForm;
    property Height: Integer read GetHeight;
    property PixelsPerInch: Integer read FPixelsPerInch;
    property Width: Integer read GetWidth;
  end;


function ExecAppCmd(Cmd, param1, param2: String): String;
//获取环境参数 AName= WINUSER,COMPUTER,IP，也可以取PATH之类的系统环境变量（等同于GetEnvVar）
function GetEnv(const AName: string): string;
//获取系统环境变量（如PATH）
function GetEnvVar(const AName, ADef: string): string;
//设置或修改系统环境变量
procedure SetEnvVar(const AName, AValue: string);
//当前选中的对象（可能是表、字段、模型图）
function GetSelectedCtMetaObj: TCtMetaObject;
//把对象（可能是表、字段、模型图）输出为JSON字符串
function CtObjToJsonStr(ACtObj: TCtMetaObject; bFullProps, bSkipChild: Boolean): String;
//从JSON字符串中读取对象信息
function ReadCtObjFromJsonStr(ACtObj: TCtMetaObject; AJsonStr: String): Boolean;


procedure Sleep(milliseconds: Cardinal); //延时
         
function EncodeDate(Year, Month, Day: Word): TDateTime; //生成日期
function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime;//生成时间
function DayOfWeek(const DateTime: TDateTime): Word;//获取星期几
function Date: TDateTime;//当前日期
function Time: TDateTime;//当前时间
function Now: TDateTime;//当前日期和时间
function CurrentTimeMillis: Int64;//当前毫秒数
function DateTimeToJSTime(D: TDateTime): Int64;   //Delphi时间与JavaScript的毫秒数互转
function JSTimeToDateTime(tm: Int64): TDateTime;
    
function DateToStr(D: TDateTime): string;//日期转字符串
function StrToDate(const s: string): TDateTime;//字符串转日期
function FormatDateTime(const fmt: string; D: TDateTime): string;
function TimeToStr(const DateTime: TDateTime): string;
function DateTimeToStr(const DateTime: TDateTime): string;
function StrToTime(const S: string): TDateTime;
function StrToTimeDef(const S: string; const Default: TDateTime): TDateTime;
function StrToDateTime(const S: string): TDateTime;
function StrToDateTimeDef(const S: string; const Default: TDateTime): TDateTime;


function FileAge(const FileName: string): Integer;//文件时间（微软格式）
function FileExists(const FileName: string): Boolean;
function DirectoryExists(const Directory: string): Boolean;
function ForceDirectories(Dir: string): Boolean;


function FileGetDate(Handle: Integer): Integer;//文件时间（微软格式）
function FileSetDate(Handle: Integer; Age: Integer): Integer;
function FileGetAttr(const FileName: string): Integer;
function FileSetAttr(const FileName: string; Attr: Integer): Integer;
function FileIsReadOnly(const FileName: string): Boolean;
function FileSetReadOnly(const FileName: string; ReadOnly: Boolean): Boolean;
function DeleteFile(const FileName: string): Boolean;
function RenameFile(const OldName, NewName: string): Boolean;
function ChangeFileExt(const FileName, Extension: string): string;
function ExtractFilePath(const FileName: string): string;
function ExtractFileDir(const FileName: string): string;
function ExtractFileDrive(const FileName: string): string;
function ExtractFileName(const FileName: string): string;
function ExtractFileExt(const FileName: string): string;
function ExpandFileName(const FileName: string): string;
function ExtractRelativePath(const BaseName, DestName: string): string;
function ExtractShortPathName(const FileName: string): string;
function FileSearch(const Name, DirList: string): string;
function DiskFree(Drive: Byte): Int64;
function DiskSize(Drive: Byte): Int64;
function FileDateToDateTime(FileDate: Integer): TDateTime;
function DateTimeToFileDate(DateTime: TDateTime): Integer;
function GetCurrentDir: string;
function SetCurrentDir(const Dir: string): Boolean;
function CreateDir(const Dir: string): Boolean;
function RemoveDir(const Dir: string): Boolean;
function StrToFloatDef(const S: string; const Default: Extended): Extended;

procedure Beep;

function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
function Format(const Format: string; const Args: array of Variant): string;
procedure Randomize;
function RandomI(Range: Integer): Integer;
function RandomD: Double;
function CtGenGUID: String;

procedure Writeln(s: string);
function Readln(question: string): string;
procedure WriteLog(s: string);  //输出一行消息到日志文件（ezdml.log），会自动加时间
function InputBox(const ACaption, APrompt, ADefault: string): string;
function InputMemoQuery(const ACaption, APrompt: string; var Value: string; bReadOnly: Boolean): Boolean;
function Choice(const Msg: Variant; items: string; AInitVal: string): string;
procedure Toast(const Msg: Variant; closeTimeMs: Integer);

procedure RaiseErr(msg: string); //脚本报错，将中止脚本执行
procedure Abort;  //中止脚本执行
procedure RaiseErrOut(msg: string); //脚本报错并中止所有操作
procedure AbortOut; //中止所有操作
function CtCopyStream(src,dst: TStream; Count: LongInt): LongInt;
procedure ShowMessage(const Msg: string);
procedure MsgBox(const Msg: Variant);
procedure Alert(const Msg: Variant);
function EscapeXml(const XML: Variant): string;
function CodeTextForLang(txt, lan: string): string; //将文件转为编程语言代码（转义）
procedure ShellOpen(FileName, Parameters, Directory: String); //执行Shell的open命令
function OpenFileDialog(const ATitle, AFilter, AFileName: string; bMulti: Boolean): string;
function OpenPicDialog(const ATitle, AFilter, AFileName: string; bMulti: Boolean): string;
function ExtractCompStr(const Strsrc: string; const sCompS, sCompE: string; bCaseInsensitive: Boolean; const Def: string): string;
function AddOrModifyCompStr(const Strsrc, SubVal: string; const sCompS, sCompE: string; bCaseInsensitive: Boolean): string;
function RunCmd(cmd: string; timeout: Integer): string; //运行批处理命令，设置超时（秒），并返回结果（目前不支持超时处理，0表示等待执行结束无详细结果，-1等待执行结束无详细结果且不显示命令行窗口，-2、-3与0、-1类似但会返回控制台结果）
function StringExtToWideCode(Str: string): string; //字符串转成HEX格式
function WideCodeNarrow(Str: string): string;  //HEX格式转字符串

function GetClassName(v: TObject):string; //仅限Pascal脚本，JS直接调obj._className
function CreateComponent(AOwner: TComponent; const AClassName: string): TComponent;
procedure ReadDfmComponents(ARoot: TComponent; const Dfm: string);
function FindChildComp(AOwner: TComponent; const AName: string): TComponent;
procedure SetCompPropValue(AComponent: TComponent; AKey, sValue: string);
function GetCompPropValue(AComponent: TComponent; AKey: string): string;
function GetCompPropObject(AComponent: TComponent; AKey: string): TObject;
procedure SetCompPropObject(AComponent: TComponent; AKey: string; sValue: TObject);

function Utf8Encode(const WS: WideString): String;
function Utf8Decode(const S: String): WideString;

function URLEncode(const msg: String): String;
function URLDecode(const url: string): string;
function Utf8URLEncode(const msg: String): String;

function GetPointerByObj(v: TObject): Integer;
function GetObjByPointer( p: Integer):TObject;
function GetPointerByStr(var v: string): Integer;
function GetStrByPointer( p: Integer):string;
function GetPointerByWStr(var v: WideString): Integer;
function GetWStrByPointer( p: Integer):WideString;
function Send_Msg(AHandle: Integer; Msg: Integer; wParam: Integer; lParam: Integer): Integer;
function Send_StrMsg(AHandle: Integer; Msg: Integer; wParam: WideString; lParam: WideString): WideString;

function TextToShortCut(Text: string): TShortCut;

function ChnToPY(Value: string): string;
function AutoCapProc(AName, sType: string): string;

function GetGParamValue(AName: string): string; //设置全局参数字符值
function GetGParamObject(AName: string): TObject; //设置全局参数对象值
procedure SetGParamValue(AName, AValue: string); //获取全局参数字符值
procedure SetGParamObject(AName: string; AObject: TObject); //获取全局参数对象值
procedure SetGParamValueEx(AName, AValue: string; AObject: TObject); //设置全局参数的字符和对象值

function IsReservedKeyworkd(str: string): Boolean;

function GetDbQuotName(AName, dbType: string): string;
function GetIdxName(ATbn, AFieldName: string): string;

function GetAppDefTempPath: string;  //获取临时文件路径
function GetAppTempFileName(filename: string): string; //获取临时文件名
function GetUnusedFileName(AFileName: string): string; //获取可用的文件名，如果文件已经存在，会自动加数字到文件名上

function Clipboard: TClipboard;  //获取剪贴板对象

function GenData(ARule: string): string; //调用指定规则生成演示数据
function GenDataEx(AField: TCtMetaField; ARule, ADef: string; ARowIndex: integer;
  AOpt: string; ADataSet: TDataSet): string; //为指定字段、行号生成演示数据

function IfElse(const ABool, TrueVal, FalseVal: variant): variant; //判断如果ABool为真假则取不同的值，此函数仅用于PASCAL脚本（显然JS不需要这个）

function GetCtDropDownItemsText(items: string): string; //从下拉配置（值=显示名，一行一个）中获取显示名列表（去掉每一行=左边的值）
function GetCtDropDownTextOfValue(val, items: string): string; //根据值获取下拉项对应的显示名
function GetCtDropDownValueOfText(txt, items: string): string; //根据显示名获取下拉项对应的值

function IsEnglish: Boolean; //当前语言是否为英文
function CurDbType: String;  //当前数据库连接类型
function ExecCtDbLogon(DbType, database, username, password: string; bSavePwd, bAutoLogin, bShowDialog: Boolean; opt: string): string; //执行数据库连接，DbType不为空时可指定数据服务名、用户名和密码
function ExecSql(sql, opts: string): TDataSet; //尝试执行SQL，结果如果非空，需要自行Free

//获取HTTP网络请求执行结果。
//PostData为要提交的内容，如果需要提交文件，可如下方式指定：[POST_LOCAL_FILE]C:\temp\test1.log[/POST_LOCAL_FILE]，如果需要将返回内容下载保存到文件，可指定PostData为：[SAVE_TO_FILE]C:\temp\download\test2.txt[/SAVE_TO_FILE]
//Opts中含[SHOW_PROGRESS]表示需要时显示进度（默认延时1秒）,相关参数如：[SHOW_PROGRESS][WAIT_TICKS=延时毫秒数][TITLE=提交][MSG=正在提交...][CANCEL_MSG=要中止提交操作吗？][READ_TIMEOUT=超时毫秒数][NO_REDIR]（禁止重定向）
function GetUrlData(URL: string; PostData: string; Opts: string): string; 

//从参数面板取值
function CurAction: string;//当前按下的按钮，已过时，请用CurSettingsPanel.CurAction代替
function GetParamValue(AName: string): string;//获取某个面板项的值，已过时，请用CurSettingsPanel.GetItemValue代替
function GetParamValueDef(AName,ADef: string): string;

procedure SyncTableProps(Tb: TCtMetaTable); //修改了表属性后，同步属性到模型中其它所有同名的表

procedure RunDmlScript(AFileName, AScript: string); //运行脚本，文件后缀名决定脚本类型，AScript为脚本内容，为空则从文件加载
procedure PrintVar(const AVal: Variant); //往CurOut中输出内容（不换行）

//以下全局变量，在JavaScript中使用时，首字母要小写，如：curOut.add("当前主窗口："+application.mainForm.caption);
var
  Application: TApplication; //获取MainForm、ExeName
  Screen: TScreen; //可用于遍历窗体和获取当前活动的窗体、控件

  AllModels: TCtDataModelGraphList;//所有模型列表。AllModels.CurDataModel为当前模型
  CurModel: TCtDataModelGraph; //当前模型（注：可能为空）
  CurTable: TCtMetaTable;//当前表（注：可能为空）
  CurField: TCtMetaField;//当前字段（注：可能为空）
  CurOut: TStrings;//当前输出设备
  CurSettingsPanel: TDmlScriptControlList;//当前参数面板（注：可能为空）

//Settings panel config string (need add /**/ in Javascript)
//参数设置面板配置格式如下，包括(*和*)（Javascript下还需要在前后加/**/注释），属性间不能有空格，放在PAS文件的最前面：
(*[SettingsPanel]
Control="Label";Caption="Please choose the parameters";Params="[FULLWIDTH][HEIGHT=40]"
Control="Edit";Name="Author";Caption="Your name";";Value="huz";Params="[FULLWIDTH]"
Control="Edit";Name="IsTest";Caption="Test flag";";Value="1";Params="[HIDDEN]"
Control="Memo";Name="Introduce";Caption="Introduce";";Value="Your info..#13#10 to be continued..";Params="[FULLWIDTH][HEIGHT=80]"
Control="ComboBox";Name="GenType";Caption="Generate type";Items="Type1,Type2,Type3";Value="Type1"
Control="RadioBox";Name="Param1";Caption="Param1";Items="V1,V2,V3";Value="V1"
Control="CheckBox";Name="Param2";Caption="Param2";Items="V1";Value="V2"
Control="Button";Name="Help";Caption="Click here for help";";Value="Help..."
[/SettingsPanel]*)


implementation

end.
 