ultimatepp/uppdev/Theming/Theme.cpp
cxl 4a1c627474 Adding uppdev....
git-svn-id: svn://ultimatepp.org/upp/trunk@328 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-08-15 08:36:24 +00:00

245 lines
6.4 KiB
C++

#include "Theming.h"
String Themed::GetClass() const
{
CParser p(typeid(*this).name());
String n;
while(!p.IsEof()) {
if(p.IsId())
n = p.ReadId();
else
p.SkipTerm();
}
return n;
}
struct ThemeData : Moveable<ThemeData> {
VectorMap<String, String> property;
VectorMap<String, Image> image;
};
struct ChildThemeData : ThemeData, Moveable<ChildThemeData> {
Ctrl::LogPos pos;
};
struct ClassTheme : Moveable<ClassTheme> {
ThemeData data;
VectorMap<String, ChildThemeData> child;
void Load(const char *dir, const char *cls);
};
Point ReadNums(CParser& p) {
Point pt;
pt.x = p.ReadInt();
p.PassChar(',');
pt.y = p.ReadInt();
return pt;
}
void LoadProp(FileIn& in, VectorMap<String, String>& prop)
{
while(!in.IsEof()) {
String ln = in.GetLine();
CParser p(ln);
if(p.Char(';'))
break;
if(p.IsId()) {
String& d = prop.GetAdd(p.ReadId());
p.SkipSpaces();
d = p.GetPtr();
}
}
}
void ClassTheme::Load(const char *dir, const char *cls)
{
String imgdir = AppendFileName(dir, String(cls) + ".image");
FindFile ff(AppendFileName(imgdir, "*.png"));
while(ff) {
Vector<String> v = Split(ff.GetName(), '.');
if(v.GetCount() == 6) {
Image m = StreamRaster::LoadFileAny(AppendFileName(imgdir, ff.GetName()));
ImageBuffer b(m);
b.SetHotSpot(Point(atoi(v[1]), atoi(v[2])));
b.Set2ndSpot(Point(atoi(v[3]), atoi(v[4])));
m = b;
int q = v[0].Find('-');
if(q >= 0)
child.GetAdd(v[0].Mid(0, q)).image.GetAdd(v[0].Mid(q + 1)) = m;
else
data.image.GetAdd(v[0]) = m;
}
ff.Next();
}
FileIn in(AppendFileName(dir, String(cls) + ".class"));
if(!in) return;
LoadProp(in, data.property);
while(!in.IsEof()) {
String ln = in.GetLine();
CParser p(ln);
if(p.IsId()) {
String id = p.ReadId();
ChildThemeData& m = child.GetAdd(id);
while(!p.IsEof()) {
if(p.Id("left")) {
Point pt = ReadNums(p);
m.pos.x = Ctrl::PosLeft(pt.x, pt.y);
}
else
if(p.Id("right")) {
Point pt = ReadNums(p);
m.pos.x = Ctrl::PosRight(pt.x, pt.y);
}
else
if(p.Id("hsize")) {
Point pt = ReadNums(p);
m.pos.x = Ctrl::PosSize(pt.x, pt.y);
}
else
if(p.Id("hcenter")) {
Point pt = ReadNums(p);
m.pos.x = Ctrl::PosCenter(pt.x, pt.y);
}
else
if(p.Id("top")) {
Point pt = ReadNums(p);
m.pos.y = Ctrl::PosLeft(pt.x, pt.y);
}
else
if(p.Id("bottom")) {
Point pt = ReadNums(p);
m.pos.y = Ctrl::PosRight(pt.x, pt.y);
}
else
if(p.Id("vsize")) {
Point pt = ReadNums(p);
m.pos.y = Ctrl::PosSize(pt.x, pt.y);
}
else
if(p.Id("vcenter")) {
Point pt = ReadNums(p);
m.pos.y = Ctrl::PosCenter(pt.x, pt.y);
}
}
LoadProp(in, m.property);
}
}
}
VectorMap<String, ClassTheme> theme;
void Themed::LoadTheme(const char *dir)
{
theme.Clear();
FindFile ff(AppendFileName(dir, "*.class"));
while(ff) {
String cls = ToLower(GetFileTitle(ff.GetName()));
theme.GetAdd(cls).Load(dir, cls);
ff.Next();
}
}
void Themed::ReadTheme()
{
int q = theme.Find(ToLower(GetClass()));
if(q < 0) return;
ClassTheme& cm = theme[q];
ThemeProperties tm(cm.data.property, cm.data.image, true);
Properties(tm);
Ctrl *p = dynamic_cast<Ctrl *>(this);
if(p)
for(Ctrl *q = p->GetFirstChild(); q; q = q->GetNext()) {
Themed *t = dynamic_cast<Themed *>(q);
if(t) {
int i = cm.child.Find(t->GetClass());
if(i >= 0) {
ThemeProperties tm(cm.child[i].property, cm.child[i].image, true);
t->Properties(tm);
}
i = cm.child.Find(t->id);
if(i >= 0) {
q->SetPos(cm.child[i].pos);
ThemeProperties tm(cm.child[i].property, cm.child[i].image, true);
t->Properties(tm);
}
}
}
}
String FillRight(const String& text, int n)
{
int q = n - text.GetLength();
return q > 0 ? text + String(' ', q) : text;
}
void SaveProp(FileOut& out, VectorMap<String, String>& prop, const char *tab)
{
for(int i = 0; i < prop.GetCount(); i++)
out << tab << FillRight(prop.GetKey(i), 8) << " " << prop[i] << "\r\n";
out << ";\r\n\r\n";
}
void SaveImages(const char *dir, const char *prefix, const VectorMap<String, Image>& img)
{
for(int i = 0; i < img.GetCount(); i++) {
String fn;
if(prefix)
fn << prefix;
Point p1 = img[i].GetHotSpot();
Point p2 = img[i].Get2ndSpot();
fn << img.GetKey(i) << '.' << p1.x << '.' << p1.y << '.' << p2.x << '.' << p2.y << ".png";
PNGEncoder().SaveFile(AppendFileName(dir, fn), img[i]);
}
}
static String sWriteDir;
void Themed::SetWrite(const char *writedir)
{
sWriteDir = writedir;
}
void Themed::WriteTheme()
{
if(IsNull(sWriteDir))
return;
RealizeDirectory(sWriteDir);
String imgdir = AppendFileName(sWriteDir, GetClass() + ".image");
FileOut out(AppendFileName(sWriteDir, GetClass() + ".class"));
VectorMap<String, String> prop;
VectorMap<String, Image> img;
ThemeProperties tm(prop, img, false);
Properties(tm);
RealizeDirectory(imgdir);
SaveImages(imgdir, NULL, img);
SaveProp(out, prop, "");
Ctrl *p = dynamic_cast<Ctrl *>(this);
if(p)
for(Ctrl *q = p->GetFirstChild(); q; q = q->GetNext()) {
Themed *t = dynamic_cast<Themed *>(q);
if(t && t->id.GetCount()) {
// prop.Clear();
// ThemeProperties tm(prop, img, false);
// t->Properties(tm);
out << t->id;
Ctrl::LogPos pos = q->GetPos();
switch(pos.x.GetAlign()) {
case Ctrl::LEFT: out << Format(" left %d, %d", pos.x.GetA(), pos.x.GetB()); break;
case Ctrl::RIGHT: out << Format(" right %d, %d", pos.x.GetA(), pos.x.GetB()); break;
case Ctrl::SIZE: out << Format(" hsize %d, %d", pos.x.GetA(), pos.x.GetB()); break;
case Ctrl::CENTER: out << Format(" hcenter %d, %d", pos.x.GetB(), pos.x.GetA()); break;
}
switch(pos.y.GetAlign()) {
case Ctrl::TOP: out << Format(" top %d, %d", pos.y.GetA(), pos.y.GetB()); break;
case Ctrl::BOTTOM: out << Format(" bottom %d, %d", pos.y.GetA(), pos.y.GetB()); break;
case Ctrl::SIZE: out << Format(" vsize %d, %d", pos.y.GetA(), pos.y.GetB()); break;
case Ctrl::CENTER: out << Format(" vcenter %d, %d", pos.y.GetB(), pos.y.GetA()); break;
}
out << "\r\n";
// SaveProp(out, prop, " ");
}
}
}
void Themed::Properties(ThemeProperties& x) {}