mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 22:02:49 -06:00
373 lines
8.2 KiB
C++
373 lines
8.2 KiB
C++
#include "ide.h"
|
|
|
|
int ReadTemplateType(CParser& p)
|
|
{
|
|
static const char *nm[] = { "id", "filename", "option", "select", "text" };
|
|
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";
|
|
}
|
|
}
|
|
}
|
|
|
|
int NoCr(int c)
|
|
{
|
|
return c == '\r' ? 0 : c;
|
|
}
|
|
|
|
AppPreview::AppPreview()
|
|
{
|
|
SetFrame(ViewFrame());
|
|
AddFrame(sb);
|
|
sb <<= THISBACK(Scroll);
|
|
NoWantFocus();
|
|
}
|
|
|
|
AppPreview::~AppPreview() {}
|
|
|
|
void AppPreview::MouseWheel(Point p, int zdelta, dword keyflags) {
|
|
sb.Wheel(zdelta);
|
|
}
|
|
|
|
void AppPreview::Layout()
|
|
{
|
|
sb.SetTotal(line.GetCount());
|
|
sb.SetPage(GetSize().cy / Courier(12).Info().GetHeight());
|
|
}
|
|
|
|
void AppPreview::Paint(Draw& w)
|
|
{
|
|
Size sz = GetSize();
|
|
FontInfo fi = Courier(12).Info();
|
|
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 ? LtCyan : SColorPaper);
|
|
if(i < line.GetCount())
|
|
w.DrawText(0, y, line[i].text, hdr ? Arial(12).Bold().Italic() : Courier(12), SColorText);
|
|
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();
|
|
}
|
|
|
|
int FilterPackageName(int c)
|
|
{
|
|
return c == '_' || IsAlNum(c) || c == '/' ? c : c == '\\' ? '/' : 0;
|
|
}
|
|
|
|
TemplateDlg::TemplateDlg()
|
|
{
|
|
CtrlLayoutOKCancel(*this, "Create new package");
|
|
Sizeable().Zoomable();
|
|
description <<= THISBACK(Preview);
|
|
delay <<= THISBACK(Preview);
|
|
delay.SetDelay(300);
|
|
templist.AddColumn("Template");
|
|
templist.WhenEnterRow = THISBACK(EnterTemplate);
|
|
ok.Disable();
|
|
package <<= THISBACK(EnableCreate);
|
|
package.SetFilter(FilterPackageName);
|
|
Icon(IdeImg::CreatePackage());
|
|
}
|
|
|
|
TemplateDlg::~TemplateDlg() {}
|
|
|
|
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;
|
|
}
|
|
|
|
String ToUpper_Caps(const String& name)
|
|
{
|
|
String output("");
|
|
int str_len = name.GetLength();
|
|
for (int i = 0; i < str_len; ++i)
|
|
{
|
|
int ch = name[i];
|
|
if (IsAlNum(ch))
|
|
{
|
|
output += ToUpper(ch);
|
|
if (i < str_len - 1)
|
|
if (IsLower(ch) && IsUpper(name[i + 1]))
|
|
output += '_';
|
|
}
|
|
else
|
|
output += '_';
|
|
}
|
|
return output;
|
|
}
|
|
|
|
ArrayMap<String, EscValue> TemplateDlg::MakeVars0()
|
|
{
|
|
ArrayMap<String, EscValue> var;
|
|
String n = ~package;
|
|
int q = n.ReverseFind('/');
|
|
var.Add("PACKAGE", q >= 0 ? n.Mid(q + 1) : n);
|
|
var.Add("PACKAGE_TOUPPER", ToUpper(n));
|
|
var.Add("PACKAGE_TOUPPER_CAPS", ToUpper_Caps(n));
|
|
var.Add("DESCRIPTION", String(~description));
|
|
return var;
|
|
}
|
|
|
|
ArrayMap<String, EscValue> TemplateDlg::MakeVars()
|
|
{
|
|
const PackageTemplate& tp = ActualTemplate();
|
|
ArrayMap<String, EscValue> var = MakeVars0();
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
Package p;
|
|
String f = AppendFileName(AppendFileName(~nest, (String)~package), (String)~package + ".upp");
|
|
p.Load(f);
|
|
p.description = ~description;
|
|
p.Save(f);
|
|
}
|
|
|
|
void TemplateDlg::Inits()
|
|
{
|
|
const PackageTemplate& tp = ActualTemplate();
|
|
ArrayMap<String, EscValue> var = MakeVars0();
|
|
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.Create<Option>().SetLabel(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(i, m.value[i]);
|
|
if(m.value.GetCount())
|
|
d->SetIndex(0);
|
|
ctrl.Add(d);
|
|
break;
|
|
}
|
|
case TEMPLATEITEM_TEXT: {
|
|
EditField *e = new EditField;
|
|
ctrl.Add(e);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Add(ctrl.Top());
|
|
ctrl.Top() << delay;
|
|
ctrl.Top().LeftPos(pos.x, cx).TopPos(pos.y);
|
|
pos.y += ctrl.Top().GetMinSize().cy + 6;
|
|
ctrl.Top().ClearModify();
|
|
}
|
|
Inits();
|
|
Preview();
|
|
}
|
|
|
|
void TemplateDlg::LoadNest(const char *path, bool main, bool recurse)
|
|
{
|
|
FindFile ff(AppendFileName(path, "*.*"));
|
|
while(ff) {
|
|
String p = AppendFileName(path, ff.GetName());
|
|
if(ff.IsFolder()) {
|
|
if(recurse)
|
|
LoadNest(p, main);
|
|
}
|
|
else
|
|
if(ToLower(GetFileExt(ff.GetName())) == ".upt") {
|
|
try {
|
|
PackageTemplate t = ReadTemplate(p);
|
|
if(main && t.main || !main && t.sub)
|
|
pt.Add() = t;
|
|
}
|
|
catch(CParser::Error e) {
|
|
Exclamation("Package template [* " + DeQtf(p) + "] is invalid&[* " + e);
|
|
}
|
|
}
|
|
ff.Next();
|
|
}
|
|
}
|
|
|
|
void TemplateDlg::Load(const Vector<String>& p, bool main)
|
|
{
|
|
pt.Clear();
|
|
for(int i = 0; i < p.GetCount(); i++) {
|
|
LoadNest(p[i], main);
|
|
nest.Add(p[i]);
|
|
}
|
|
LoadNest(GetLocalDir(), main);
|
|
LoadNest(GetFileFolder(ConfigFile("x")), main, false);
|
|
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);
|
|
}
|