ultimatepp/uppdev/Creator/main.cpp
cxl 351994a6cc Adding uppdev....
git-svn-id: svn://ultimatepp.org/upp/trunk@328 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-08-15 08:36:24 +00:00

412 lines
9.2 KiB
C++

#include <CtrlLib/CtrlLib.h>
#include <Esc/Esc.h>
struct FileTemplate {
String filename;
String condition;
String text;
};
enum { TEMPLATEITEM_ID, TEMPLATEITEM_FILENAME, TEMPLATEITEM_OPTION, TEMPLATEITEM_SELECT };
struct TemplateItem {
String label;
int type;
String id;
Vector<String> value;
String init;
};
struct PackageTemplate {
String name;
bool main;
Array<TemplateItem> item;
Array<FileTemplate> file;
};
int ReadTemplateType(CParser& p)
{
static char *nm[] = { "id", "filename", "option", "select" };
for(int i = 0; i < __countof(nm); i++)
if(p.Id(nm[i]))
return i;
p.ThrowError("Unknown type");
return 0;
}
PackageTemplate ReadTemplate(const char *filename)
{
PackageTemplate pt;
FileIn in(filename);
String header;
String l;
for(;;) {
if(in.IsEof())
break;
l = in.GetLine();
if(l[0] == '@' && l[1] == '@')
break;
header << l << '\n';
}
CParser p(header, filename);
p.PassId("template");
pt.name = p.ReadString();
pt.main = pt.sub = false;
for(;;) {
if(p.Id("main"))
pt.main = true;
else
if(p.Id("sub"))
pt.sub = true;
else
break;
}
p.PassChar(';');
while(!p.IsEof()) {
int type = ReadTemplateType(p);
TemplateItem& m = pt.item.Add();
m.type = type;
if(type == TEMPLATEITEM_SELECT) {
p.PassChar('(');
do
m.value.Add(p.ReadString());
while(p.Char(','));
p.PassChar(')');
}
m.label = p.ReadString();
m.id = p.ReadId();
if(p.Char('=')) {
const char *b = p.GetPtr();
while(!p.IsChar(';')) {
if(p.IsEof())
p.ThrowError("unexpected end of file");
p.SkipTerm();
}
m.init = String(b, p.GetPtr());
}
p.PassChar(';');
}
for(;;) {
pt.file.Add();
pt.file.Top().filename = l.Mid(2);
for(;;) {
if(in.IsEof())
return pt;
l = in.GetLine();
if(l[0] == '@' && l[1] == '@')
break;
if(l[0] == '?' && l[1] == '?')
pt.file.Top().condition = l.Mid(2);
else
pt.file.Top().text << l << "\r\n";
}
}
}
struct AppPreview : Ctrl {
virtual void Paint(Draw& w);
virtual void Layout();
ScrollBar sb;
struct Line : Moveable<Line> {
String text;
bool header;
};
Vector<Line> line;
void Scroll() { Refresh(); }
void Clear() { line.Clear(); Refresh(); sb.Set(0); }
void Add(const String& data, bool header = false);
typedef AppPreview CLASSNAME;
AppPreview() { SetFrame(InsetFrame()); AddFrame(sb); sb <<= THISBACK(Scroll); NoWantFocus(); }
};
int NoCr(int c)
{
return c == '\r' ? 0 : c;
}
void AppPreview::Layout()
{
sb.SetTotal(line.GetCount());
sb.SetPage(GetSize().cy / ScreenInfo().GetFontInfo(Courier(12)).GetHeight());
}
void AppPreview::Paint(Draw& w)
{
Size sz = GetSize();
FontInfo fi = w.GetFontInfo(Courier(12));
int y = 0;
int i = sb;
while(y < sz.cy) {
bool hdr = i < line.GetCount() && line[i].header;
w.DrawRect(0, y, sz.cx, fi.GetHeight(), hdr ? SLtCyan : SWhite);
if(i < line.GetCount())
w.DrawText(0, y, line[i].text, hdr ? Arial(12).Bold().Italic() : Courier(12), SBlack);
y += fi.GetHeight();
i++;
}
}
void AppPreview::Add(const String& data, bool header)
{
Vector<String> l = Split(Filter(data, NoCr), '\n', false);
for(int i = 0; i < l.GetCount(); i++) {
Line& q = line.Add();
const char *s = l[i];
while(*s == '\t') {
q.text << " ";
s++;
}
q.text << s;
q.header = header;
}
Refresh();
Layout();
}
#define LAYOUTFILE <Creator/main.lay>
#include <CtrlCore/lay.h>
struct TemplateDlg : public WithTemplateLayout<TopWindow>
{
AppPreview preview;
Array<PackageTemplate> pt;
Array<Label> label;
Array<Ctrl> ctrl;
DelayCallback delay;
const PackageTemplate& ActualTemplate();
void Preview();
void EnterTemplate();
void LoadNest(const char *path);
void Load(const char *paths);
void EnableCreate() { ok.Enable(!IsNull(package)); Inits(); }
void Inits();
ArrayMap<String, EscValue> MakeVars();
void Create();
typedef TemplateDlg CLASSNAME;
TemplateDlg();
};
TemplateDlg::TemplateDlg()
{
CtrlLayoutOKCancel(*this, "Create new main package");
delay <<= THISBACK(Preview);
delay.SetDelay(300);
templist.AddColumn("Template");
templist.WhenEnterRow = THISBACK(EnterTemplate);
ok.Disable();
package <<= THISBACK(EnableCreate);
}
const PackageTemplate& TemplateDlg::ActualTemplate()
{
if(templist.GetCursor() > 0)
return pt[templist.GetCursor() - 1];
static PackageTemplate t;
return t;
}
int IdFilter(int c)
{
return c == '_' || IsAlNum(c) ? c : 0;
}
int FilenameFilter(int c)
{
return c == '_' || IsAlNum(c) || c == '.' ? c : 0;
}
ArrayMap<String, EscValue> TemplateDlg::MakeVars()
{
const PackageTemplate& tp = ActualTemplate();
ArrayMap<String, EscValue> var;
var.Add("PACKAGE", (String)~package);
for(int i = 0; i < tp.item.GetCount(); i++)
var.Add(tp.item[i].id, EscFromStdValue(~ctrl[i]));
StdLib(var);
return var;
}
void TemplateDlg::Preview()
{
const PackageTemplate& tp = ActualTemplate();
ArrayMap<String, EscValue> var = MakeVars();
int sc = preview.sb;
preview.Clear();
for(int i = 0; i < tp.file.GetCount(); i++) {
const FileTemplate& ft = tp.file[i];
if(IsNull(ft.condition) || IsTrue(Evaluate(ft.condition, var))) {
preview.Add(Expand(ft.filename, var), true);
preview.Add(Expand(ft.text, var));
}
}
preview.sb = sc;
}
void TemplateDlg::Create()
{
const PackageTemplate& tp = ActualTemplate();
ArrayMap<String, EscValue> var = MakeVars();
for(int i = 0; i < tp.file.GetCount(); i++) {
const FileTemplate& ft = tp.file[i];
if(IsNull(ft.condition) || IsTrue(Evaluate(ft.condition, var))) {
String fn = Expand(ft.filename, var);
if(!IsNull(fn)) {
fn = AppendFileName(AppendFileName(~nest, (String)~package), fn);
RealizePath(fn);
SaveFile(fn, Expand(ft.text, var));
}
}
}
}
void TemplateDlg::Inits()
{
const PackageTemplate& tp = ActualTemplate();
ArrayMap<String, EscValue> var;
var.Add("PACKAGE", (String)~package);
for(int i = 0; i < tp.item.GetCount(); i++) {
String init = tp.item[i].init;
if(!IsNull(init) && !ctrl[i].IsModified()) {
ctrl[i] <<= StdValueFromEsc(Evaluate(init, var));
ctrl[i].ClearModify();
}
}
}
void TemplateDlg::EnterTemplate()
{
const PackageTemplate& tp = ActualTemplate();
ArrayMap<String, EscValue> var;
var.Add("PACKAGE", (String)~package);
StdLib(var);
label.Clear();
ctrl.Clear();
Point pos = templist.GetRect().BottomLeft();
pos.y += 8;
int cx = cancel.GetRect().right - pos.x;
for(int i = 0; i < tp.item.GetCount(); i++) {
const TemplateItem& m = tp.item[i];
if(m.type == TEMPLATEITEM_OPTION)
ctrl.Add(new Option).SetLabelText(m.label);
else {
label.Add().SetLabel(m.label).LeftPos(pos.x, cx).TopPos(pos.y);
Add(label.Top());
pos.y += label.Top().GetMinSize().cy;
switch(m.type) {
case TEMPLATEITEM_ID: {
EditField *e = new EditField;
e->SetFilter(IdFilter);
ctrl.Add(e);
break;
}
case TEMPLATEITEM_FILENAME: {
EditField *e = new EditField;
e->SetFilter(FilenameFilter);
ctrl.Add(e);
break;
}
case TEMPLATEITEM_SELECT: {
DropList *d = new DropList;
for(int i = 0; i < m.value.GetCount(); i++)
d->Add(m.value[i]);
ctrl.Add(d);
break;
}
}
}
Add(ctrl.Top());
ctrl.Top() << delay;
ctrl.Top().LeftPos(pos.x, cx).TopPos(pos.y);
pos.y += ctrl.Top().GetMinSize().cy + 10;
ctrl.Top().ClearModify();
}
Preview();
Inits();
}
void TemplateDlg::LoadNest(const char *path, bool main, bool sub)
{
FindFile ff(AppendFileName(path, "*.*"));
while(ff) {
String p = AppendFileName(path, ff.GetName());
if(ff.IsFolder())
LoadNest(p);
else
if(ToLower(GetFileExt(ff.GetName())) == ".upt") {
try {
PackageTemplate t = ReadTemplate(p);
if(main && t.main || sub && t.sub)
pt.Add() = t;
}
catch(CParser::Error e) {
Exclamation("Package template [* " + DeQtf(p) + "] is invalid&[* " + e);
}
}
ff.Next();
}
}
void TemplateDlg::Load(const char *paths, bool main, bool sub)
{
pt.Clear();
Vector<String> p = Split(paths, ';');
for(int i = 0; i < p.GetCount(); i++) {
LoadNest(p[i], name, sub);
nest.Add(p[i]);
}
Sort(pt, FieldRelation(&PackageTemplate::name, StdLess<String>()));
templist.Clear();
templist.Add("<empty>");
for(int i = 0; i < pt.GetCount(); i++)
templist.Add(pt[i].name);
if(nest.GetCount())
nest.SetIndex(0);
templist.GoBegin();
ActiveFocus(package);
}
void AppMain()
{
PackageTemplate pt;
try {
pt = ReadTemplate("f:/test.upt");
}
catch(CParser::Error& e) {
DUMP(e);
return;
}
DUMP(pt.name);
for(int i = 0; i < pt.item.GetCount(); i++) {
DUMP(pt.item[i].type);
DUMP(pt.item[i].label);
DUMP(pt.item[i].id);
DUMP(pt.item[i].init);
}
AppPreview pw;
for(int i = 0; i < pt.file.GetCount(); i++) {
LOG("--------------");
FileTemplate ft = pt.file[i];
DUMP(pt.file[i].filename);
DUMP(pt.file[i].condition);
DUMP(pt.file[i].text);
pw.Add(ft.filename, true);
pw.Add(ft.text);
}
TemplateDlg d;
d.Load("F:\\uppdev");
if(d.Run() == IDOK)
d.Create();
String s;
s.
}