commit 263ff5f89589bbc43d2abf785c7d3ce9231e8e77 Author: mdelfede Date: Sat Jun 7 22:31:27 2008 +0000 changed svn layout git-svn-id: svn://ultimatepp.org/upp/trunk@281 f0d560ea-af0d-0410-9eb7-867de7ffcac7 diff --git a/examples/AddressBook/AddressBook.cpp b/examples/AddressBook/AddressBook.cpp new file mode 100644 index 000000000..91d84f369 --- /dev/null +++ b/examples/AddressBook/AddressBook.cpp @@ -0,0 +1,204 @@ +// This is an upp conversion of qt example, see +// http://doc.trolltech.com/3.0/addressbook-example.html + +#include +#include + +using namespace Upp; + +#define LAYOUTFILE +#include + +class AddressBook : public WithAddressBookLayout { + WithModifyLayout modify; + WithSearchLayout search; + FileSel fs; + String filename; + + void SetupSearch(); + void Add(); + void Change(); + void Search(); + void Open(); + void Save(); + void SaveAs(); + void Print(); + void Quit(); + void FileMenu(Bar& bar); + void MainMenu(Bar& bar); + + typedef AddressBook CLASSNAME; + +public: + void Serialize(Stream& s); + + AddressBook(); +}; + +AddressBook::AddressBook() +{ + CtrlLayout(*this, "Address book"); + CtrlLayout(modify); + CtrlLayout(search); + tab.Add(modify, "Modify"); + tab.Add(search, "Search"); + ActiveFocus(search.name); + search.oname = true; + search.oname <<= search.osurname <<= search.oaddress + <<= search.oemail <<= THISBACK(SetupSearch); + array.AddColumn("Name"); + array.AddColumn("Surname"); + array.AddColumn("Address"); + array.AddColumn("Email"); + modify.add <<= THISBACK(Add); + modify.change <<= THISBACK(Change); + search.search <<= THISBACK(Search); + SetupSearch(); + fs.AllFilesType(); + menu.Set(THISBACK(MainMenu)); +} + +void AddressBook::FileMenu(Bar& bar) +{ + bar.Add("Open..", CtrlImg::open(), THISBACK(Open)); + bar.Add("Save", CtrlImg::save(), THISBACK(Save)); + bar.Add("Save as..", CtrlImg::save_as(), THISBACK(SaveAs)); + bar.Separator(); + bar.Add("Print", CtrlImg::print(), THISBACK(Print)); + bar.Separator(); + bar.Add("Quit", THISBACK(Quit)); +} + +void AddressBook::MainMenu(Bar& bar) +{ + bar.Add("File", THISBACK(FileMenu)); +} + +void AddressBook::SetupSearch() +{ + search.name.Enable(search.oname); + search.surname.Enable(search.osurname); + search.address.Enable(search.oaddress); + search.email.Enable(search.oemail); +} + +void AddressBook::Add() +{ + array.Add(~modify.name, ~modify.surname, ~modify.address, ~modify.email); + array.GoEnd(); + modify.name <<= modify.surname <<= modify.address <<= modify.email <<= Null; + ActiveFocus(modify.name); +} + +void AddressBook::Change() +{ + if(array.IsCursor()) { + array.Set(0, ~modify.name); + array.Set(1, ~modify.surname); + array.Set(2, ~modify.address); + array.Set(3, ~modify.email); + } +} + +bool Contains(const String& text, const String& substr) +{ + for(const char *s = text; s <= text.End() - substr.GetLength(); s++) + if(strncmp(s, substr, substr.GetLength()) == 0) + return true; + return false; +} + +void AddressBook::Search() +{ + if(!array.GetCount()) return; + bool sc = true; + array.ClearSelection(); + for(int i = 0; i < array.GetCount(); i++) { + if((!search.oname || Contains(array.Get(i, 0), ~search.name)) && + (!search.osurname || Contains(array.Get(i, 1), ~search.surname)) && + (!search.oaddress || Contains(array.Get(i, 2), ~search.address)) && + (!search.oemail || Contains(array.Get(i, 3), ~search.email))) { + array.Select(i); + if(sc) { + array.SetCursor(i); + array.CenterCursor(); + sc = false; + }; + } + } +} + +void AddressBook::Open() +{ + if(!fs.ExecuteOpen()) return; + filename = fs; + FileIn in(filename); + if(!in) { + Exclamation("Unable to open [* " + DeQtf(filename)); + return; + } + array.Clear(); + while(!in.IsEof()) { + Vector q; + for(int i = 0; i < 4; i++) + q.Add(in.GetLine()); + array.Add(q); + } +} + +void AddressBook::Save() +{ + if(IsEmpty(filename)) { + SaveAs(); + return; + } + FileOut out(filename); + if(!out) { + Exclamation("Unable to open " + filename); + return; + } + for(int i = 0; i < array.GetCount(); i++) + for(int q = 0; q < 4; q++) + out.PutLine(String(array.Get(i, q))); +} + +void AddressBook::SaveAs() +{ + if(!fs.ExecuteSaveAs()) return; + filename = fs; + Save(); +} + +void AddressBook::Print() +{ + String qtf; + qtf = "{{1:1:1:1 Name:: Surname:: Address:: Email"; + for(int i = 0; i < array.GetCount(); i++) + for(int q = 0; q < 4; q++) + qtf << ":: " << DeQtf((String)array.Get(i, q)); + Report report; + report << qtf; + Perform(report); +} + +void AddressBook::Quit() +{ + Break(); +} + +void AddressBook::Serialize(Stream& s) +{ + int version = 0; + s / version; + s % search.oname % search.osurname % search.oaddress % search.oemail; + s % fs; + SetupSearch(); +} + +GUI_APP_MAIN +{ + AddressBook ab; + LoadFromFile(ab); + ab.Run(); + StoreToFile(ab); +} diff --git a/examples/AddressBook/AddressBook.lay b/examples/AddressBook/AddressBook.lay new file mode 100644 index 000000000..49af3166a --- /dev/null +++ b/examples/AddressBook/AddressBook.lay @@ -0,0 +1,30 @@ +LAYOUT(AddressBookLayout, 512, 456) + ITEM(MenuBar, menu, LeftPosZ(0, 216).TopPosZ(0, 20)) + ITEM(TabCtrl, tab, LeftPosZ(8, 496).TopPosZ(32, 84)) + ITEM(ArrayCtrl, array, LeftPosZ(8, 496).TopPosZ(124, 324)) +END_LAYOUT + +LAYOUT(ModifyLayout, 480, 52) + ITEM(Label, dv___0, SetLabel(t_("&Name")).LeftPosZ(8, 48).TopPosZ(8, 15)) + ITEM(EditField, name, LeftPosZ(8, 96).TopPosZ(28, 19)) + ITEM(Label, dv___2, SetLabel(t_("&Surname")).LeftPosZ(108, 48).TopPosZ(8, 15)) + ITEM(EditField, surname, LeftPosZ(108, 96).TopPosZ(28, 19)) + ITEM(Label, dv___4, SetLabel(t_("&Address")).LeftPosZ(208, 48).TopPosZ(8, 15)) + ITEM(EditField, address, LeftPosZ(208, 96).TopPosZ(28, 19)) + ITEM(Label, dv___6, SetLabel(t_("&Email")).LeftPosZ(308, 48).TopPosZ(8, 15)) + ITEM(EditField, email, LeftPosZ(308, 96).TopPosZ(28, 19)) + ITEM(Button, add, SetLabel(t_("Ad&d")).LeftPosZ(416, 56).TopPosZ(4, 20)) + ITEM(Button, change, SetLabel(t_("&Change")).LeftPosZ(416, 56).TopPosZ(28, 20)) +END_LAYOUT + +LAYOUT(SearchLayout, 480, 56) + ITEM(Option, oname, SetLabel(t_("&Name")).LeftPosZ(8, 56).TopPosZ(8, 18)) + ITEM(EditField, name, LeftPosZ(8, 96).TopPosZ(28, 19)) + ITEM(Option, osurname, SetLabel(t_("&Surname")).LeftPosZ(108, 64).TopPosZ(8, 18)) + ITEM(EditField, surname, LeftPosZ(108, 96).TopPosZ(28, 19)) + ITEM(Option, oaddress, SetLabel(t_("&Address")).LeftPosZ(208, 64).TopPosZ(8, 18)) + ITEM(EditField, address, LeftPosZ(208, 96).TopPosZ(28, 19)) + ITEM(Option, oemail, SetLabel(t_("&Email")).LeftPosZ(308, 52).TopPosZ(8, 18)) + ITEM(EditField, email, LeftPosZ(308, 96).TopPosZ(28, 19)) + ITEM(Button, search, SetLabel(t_("&Search")).LeftPosZ(416, 56).TopPosZ(28, 20)) +END_LAYOUT diff --git a/examples/AddressBook/AddressBook.upp b/examples/AddressBook/AddressBook.upp new file mode 100644 index 000000000..baf64d82a --- /dev/null +++ b/examples/AddressBook/AddressBook.upp @@ -0,0 +1,13 @@ +description "Simple address book application"; + +uses + CtrlLib, + Report; + +file + AddressBook.cpp, + AddressBook.lay; + +mainconfig + "" = "GUI"; + diff --git a/examples/AddressBookXML/AddressBook.cpp b/examples/AddressBookXML/AddressBook.cpp new file mode 100644 index 000000000..8a988e708 --- /dev/null +++ b/examples/AddressBookXML/AddressBook.cpp @@ -0,0 +1,232 @@ +#include +#include + +using namespace Upp; + +#define LAYOUTFILE +#include + +class AddressBook : public WithAddressBookLayout { + WithModifyLayout modify; + WithSearchLayout search; + FileSel fs; + String filename; + + void SetupSearch(); + void Add(); + void Change(); + void Search(); + void Open(); + void Save(); + void SaveAs(); + void Print(); + void Quit(); + void FileMenu(Bar& bar); + void MainMenu(Bar& bar); + + typedef AddressBook CLASSNAME; + +public: + void Serialize(Stream& s); + + AddressBook(); +}; + +AddressBook::AddressBook() +{ + CtrlLayout(*this, "Address book"); + CtrlLayout(modify); + CtrlLayout(search); + tab.Add(modify, "Modify"); + tab.Add(search, "Search"); + ActiveFocus(search.name); + search.oname = true; + search.oname <<= search.osurname <<= search.oaddress + <<= search.oemail <<= THISBACK(SetupSearch); + array.AddColumn("Name"); + array.AddColumn("Surname"); + array.AddColumn("Address"); + array.AddColumn("Email"); + modify.add <<= THISBACK(Add); + modify.change <<= THISBACK(Change); + search.search <<= THISBACK(Search); + SetupSearch(); + fs.AllFilesType(); + menu.Set(THISBACK(MainMenu)); +} + +void AddressBook::FileMenu(Bar& bar) +{ + bar.Add("Open..", CtrlImg::open(), THISBACK(Open)); + bar.Add("Save", CtrlImg::save(), THISBACK(Save)); + bar.Add("Save as..", CtrlImg::save_as(), THISBACK(SaveAs)); + bar.Separator(); + bar.Add("Print", CtrlImg::print(), THISBACK(Print)); + bar.Separator(); + bar.Add("Quit", THISBACK(Quit)); +} + +void AddressBook::MainMenu(Bar& bar) +{ + bar.Add("File", THISBACK(FileMenu)); +} + +void AddressBook::SetupSearch() +{ + search.name.Enable(search.oname); + search.surname.Enable(search.osurname); + search.address.Enable(search.oaddress); + search.email.Enable(search.oemail); +} + +void AddressBook::Add() +{ + array.Add(~modify.name, ~modify.surname, ~modify.address, ~modify.email); + array.GoEnd(); + modify.name <<= modify.surname <<= modify.address <<= modify.email <<= Null; + ActiveFocus(modify.name); +} + +void AddressBook::Change() +{ + if(array.IsCursor()) { + array.Set(0, ~modify.name); + array.Set(1, ~modify.surname); + array.Set(2, ~modify.address); + array.Set(3, ~modify.email); + } +} + +bool Contains(const String& text, const String& substr) +{ + for(const char *s = text; s <= text.End() - substr.GetLength(); s++) + if(strncmp(s, substr, substr.GetLength()) == 0) + return true; + return false; +} + +void AddressBook::Search() +{ + if(!array.GetCount()) return; + bool sc = true; + array.ClearSelection(); + for(int i = 0; i < array.GetCount(); i++) { + if((!search.oname || Contains(array.Get(i, 0), ~search.name)) && + (!search.osurname || Contains(array.Get(i, 1), ~search.surname)) && + (!search.oaddress || Contains(array.Get(i, 2), ~search.address)) && + (!search.oemail || Contains(array.Get(i, 3), ~search.email))) { + array.Select(i); + if(sc) { + array.SetCursor(i); + array.CenterCursor(); + sc = false; + }; + } + } +} + +void AddressBook::Open() +{ + if(!fs.ExecuteOpen()) return; + filename = fs; + array.Clear(); + try { + String d = LoadFile(filename); + XmlParser p(d); + while(!p.IsTag()) + p.Skip(); + p.PassTag("AddressBook"); + while(!p.IsEof()) { + if(p.Tag("person")) { + String name; + String surname; + String address; + String email; + while(!p.End()) { + if(p.Tag("name")) + name = p.ReadText(); + else + if(p.Tag("surname")) + surname = p.ReadText(); + else + if(p.Tag("address")) + address = p.ReadText(); + else + if(p.Tag("email")) + email = p.ReadText(); + else { + p.Skip(); + continue; + } + p.PassEnd(); + } + array.Add(name, surname, address, email); + } + else + p.Skip(); + } + } + catch(XmlError) { + Exclamation("Error reading the input file!"); + } +} + +void AddressBook::Save() +{ + if(IsEmpty(filename)) { + SaveAs(); + return; + } + String xml; + for(int i = 0; i < array.GetCount(); i++) + xml << + XmlTag("person") ( + XmlTag("name").Text(array.Get(i, 0)) + + XmlTag("surname").Text(array.Get(i, 1)) + + XmlTag("address").Text(array.Get(i, 2)) + + XmlTag("email").Text(array.Get(i, 3)) + ); + if(!SaveFile(filename, XmlDoc("AddressBook", xml))) + Exclamation("Error saving the file!"); +} + +void AddressBook::SaveAs() +{ + if(!fs.ExecuteSaveAs()) return; + filename = fs; + Save(); +} + +void AddressBook::Print() +{ + String qtf; + qtf = "{{1:1:1:1 Name:: Surname:: Address:: Email"; + for(int i = 0; i < array.GetCount(); i++) + for(int q = 0; q < 4; q++) + qtf << ":: " << DeQtf((String)array.Get(i, q)); + Report report; + report << qtf; + Perform(report); +} + +void AddressBook::Quit() +{ + Break(); +} + +void AddressBook::Serialize(Stream& s) +{ + int version = 0; + s / version; + s % search.oname % search.osurname % search.oaddress % search.oemail; + s % fs; + SetupSearch(); +} + +GUI_APP_MAIN +{ + AddressBook ab; + LoadFromFile(ab); + ab.Run(); + StoreToFile(ab); +} diff --git a/examples/AddressBookXML/AddressBook.lay b/examples/AddressBookXML/AddressBook.lay new file mode 100644 index 000000000..af6a2c9cf --- /dev/null +++ b/examples/AddressBookXML/AddressBook.lay @@ -0,0 +1,30 @@ +LAYOUT(AddressBookLayout, 516, 456) + ITEM(MenuBar, menu, LeftPosZ(0, 200).TopPosZ(0, 20)) + ITEM(TabCtrl, tab, LeftPosZ(8, 500).TopPosZ(32, 84)) + ITEM(ArrayCtrl, array, LeftPosZ(8, 500).TopPosZ(124, 324)) +END_LAYOUT + +LAYOUT(ModifyLayout, 480, 52) + ITEM(Label, dv___0, SetLabel(t_("&Name")).LeftPosZ(8, 48).TopPosZ(8, 15)) + ITEM(EditField, name, LeftPosZ(8, 96).TopPosZ(28, 19)) + ITEM(Label, dv___2, SetLabel(t_("&Surname")).LeftPosZ(108, 48).TopPosZ(8, 15)) + ITEM(EditField, surname, LeftPosZ(108, 96).TopPosZ(28, 19)) + ITEM(Label, dv___4, SetLabel(t_("&Address")).LeftPosZ(208, 48).TopPosZ(8, 15)) + ITEM(EditField, address, LeftPosZ(208, 96).TopPosZ(28, 19)) + ITEM(Label, dv___6, SetLabel(t_("&Email")).LeftPosZ(308, 48).TopPosZ(8, 15)) + ITEM(EditField, email, LeftPosZ(308, 96).TopPosZ(28, 19)) + ITEM(Button, add, SetLabel(t_("Ad&d")).LeftPosZ(416, 56).TopPosZ(4, 20)) + ITEM(Button, change, SetLabel(t_("&Change")).LeftPosZ(416, 56).TopPosZ(28, 20)) +END_LAYOUT + +LAYOUT(SearchLayout, 480, 56) + ITEM(Option, oname, SetLabel(t_("&Name")).LeftPosZ(8, 56).TopPosZ(8, 18)) + ITEM(EditField, name, LeftPosZ(8, 96).TopPosZ(28, 19)) + ITEM(Option, osurname, SetLabel(t_("&Surname")).LeftPosZ(108, 64).TopPosZ(8, 18)) + ITEM(EditField, surname, LeftPosZ(108, 96).TopPosZ(28, 19)) + ITEM(Option, oaddress, SetLabel(t_("&Address")).LeftPosZ(208, 64).TopPosZ(8, 18)) + ITEM(EditField, address, LeftPosZ(208, 96).TopPosZ(28, 19)) + ITEM(Option, oemail, SetLabel(t_("&Email")).LeftPosZ(308, 52).TopPosZ(8, 18)) + ITEM(EditField, email, LeftPosZ(308, 96).TopPosZ(28, 19)) + ITEM(Button, search, SetLabel(t_("&Search")).LeftPosZ(416, 56).TopPosZ(28, 20)) +END_LAYOUT diff --git a/examples/AddressBookXML/AddressBookXML.upp b/examples/AddressBookXML/AddressBookXML.upp new file mode 100644 index 000000000..a253aa3a9 --- /dev/null +++ b/examples/AddressBookXML/AddressBookXML.upp @@ -0,0 +1,13 @@ +description "Address book application, uses XML to store data (using SAX like U++ classes)"; + +uses + CtrlLib, + Report; + +file + AddressBook.cpp, + AddressBook.lay; + +mainconfig + "" = "GUI"; + diff --git a/examples/AddressBookXML2/AddressBook.cpp b/examples/AddressBookXML2/AddressBook.cpp new file mode 100644 index 000000000..88925af8c --- /dev/null +++ b/examples/AddressBookXML2/AddressBook.cpp @@ -0,0 +1,228 @@ +#include +#include + +using namespace Upp; + +#define LAYOUTFILE +#include + +#define TAG_ADDRESSBOOK "AddressBook" +#define TAG_PERSON "person" +#define TAG_NAME "name" +#define TAG_SURNAME "surname" +#define TAG_ADDRESS "address" +#define TAG_EMAIL "email" + +class AddressBook : public WithAddressBookLayout { + WithModifyLayout modify; + WithSearchLayout search; + FileSel fs; + String filename; + + void SetupSearch(); + void Add(); + void Change(); + void Search(); + void Open(); + void Save(); + void SaveAs(); + void Print(); + void Quit(); + void FileMenu(Bar& bar); + void MainMenu(Bar& bar); + + typedef AddressBook CLASSNAME; + +public: + void Serialize(Stream& s); + + AddressBook(); +}; + +AddressBook::AddressBook() +{ + CtrlLayout(*this, "Address book"); + CtrlLayout(modify); + CtrlLayout(search); + tab.Add(modify, "Modify"); + tab.Add(search, "Search"); + ActiveFocus(search.name); + search.oname = true; + search.oname <<= search.osurname <<= search.oaddress + <<= search.oemail <<= THISBACK(SetupSearch); + array.AddColumn(TAG_NAME, "Name"); + array.AddColumn(TAG_SURNAME, "Surname"); + array.AddColumn(TAG_ADDRESS, "Address"); + array.AddColumn(TAG_EMAIL, "Email"); + modify.add <<= THISBACK(Add); + modify.change <<= THISBACK(Change); + search.search <<= THISBACK(Search); + SetupSearch(); + fs.AllFilesType(); + menu.Set(THISBACK(MainMenu)); +} + +void AddressBook::FileMenu(Bar& bar) +{ + bar.Add("Open..", CtrlImg::open(), THISBACK(Open)); + bar.Add("Save", CtrlImg::save(), THISBACK(Save)); + bar.Add("Save as..", CtrlImg::save_as(), THISBACK(SaveAs)); + bar.Separator(); + bar.Add("Print", CtrlImg::print(), THISBACK(Print)); + bar.Separator(); + bar.Add("Quit", THISBACK(Quit)); +} + +void AddressBook::MainMenu(Bar& bar) +{ + bar.Add("File", THISBACK(FileMenu)); +} + +void AddressBook::SetupSearch() +{ + search.name.Enable(search.oname); + search.surname.Enable(search.osurname); + search.address.Enable(search.oaddress); + search.email.Enable(search.oemail); +} + +void AddressBook::Add() +{ + array.Add(~modify.name, ~modify.surname, ~modify.address, ~modify.email); + array.GoEnd(); + modify.name <<= modify.surname <<= modify.address <<= modify.email <<= Null; + ActiveFocus(modify.name); +} + +void AddressBook::Change() +{ + if(array.IsCursor()) { + array.Set(0, ~modify.name); + array.Set(1, ~modify.surname); + array.Set(2, ~modify.address); + array.Set(3, ~modify.email); + } +} + +bool Contains(const String& text, const String& substr) +{ + for(const char *s = text; s <= text.End() - substr.GetLength(); s++) + if(strncmp(s, substr, substr.GetLength()) == 0) + return true; + return false; +} + +void AddressBook::Search() +{ + if(!array.GetCount()) return; + bool sc = true; + array.ClearSelection(); + for(int i = 0; i < array.GetCount(); i++) { + if((!search.oname || Contains(array.Get(i, 0), ~search.name)) && + (!search.osurname || Contains(array.Get(i, 1), ~search.surname)) && + (!search.oaddress || Contains(array.Get(i, 2), ~search.address)) && + (!search.oemail || Contains(array.Get(i, 3), ~search.email))) { + array.Select(i); + if(sc) { + array.SetCursor(i); + array.CenterCursor(); + sc = false; + }; + } + } +} + +void AddressBook::Open() +{ + if(!fs.ExecuteOpen()) return; + filename = fs; + array.Clear(); + try { + String d = LoadFile(filename); + XmlNode n = ParseXML(d); + if(n.GetCount()==0 || n[0].GetTag() != TAG_ADDRESSBOOK) + throw XmlError("No AddressBook tag"); + const XmlNode &ab = n[0]; + array.SetCount(ab.GetCount()); + for(int i=0; i < ab.GetCount(); i++){ + const XmlNode &person = ab[i]; + for(int j=0; j < person.GetCount(); j++){ + const XmlNode &prop = person[j]; + if(prop.IsTag(TAG_NAME)) + array.Set(i, TAG_NAME, prop[0].GetText()); + else + if(prop.IsTag(TAG_SURNAME)) + array.Set(i, TAG_SURNAME, prop[0].GetText()); + else + if(prop.IsTag(TAG_ADDRESS)) + array.Set(i, TAG_ADDRESS, prop[0].GetText()); + else + if(prop.IsTag(TAG_EMAIL)) + array.Set(i, TAG_EMAIL, prop[0].GetText()); + } + } + } + catch(XmlError &e) { + Exclamation("Error reading the input file:&" + DeQtf(e) ); + } +} + +void AddressBook::Save() +{ + if(IsEmpty(filename)) { + SaveAs(); + return; + } + XmlNode n; + XmlNode &ab = n.Add(TAG_ADDRESSBOOK); + for(int i=0; i < array.GetCount(); i++) { + XmlNode &person = ab.Add(TAG_PERSON); + person.Add(TAG_NAME).Add().CreateText(array.Get(i, TAG_NAME)); + person.Add(TAG_SURNAME).Add().CreateText(array.Get(i, TAG_SURNAME)); + person.Add(TAG_ADDRESS).Add().CreateText(array.Get(i, TAG_ADDRESS)); + person.Add(TAG_EMAIL).Add().CreateText(array.Get(i, TAG_EMAIL)); + } + if(!SaveFile(filename, AsXML(n))) + Exclamation("Error saving the file!"); +} + +void AddressBook::SaveAs() +{ + if(!fs.ExecuteSaveAs()) return; + filename = fs; + Save(); +} + +void AddressBook::Print() +{ + String qtf; + qtf = "{{1:1:1:1 Name:: Surname:: Address:: Email"; + for(int i = 0; i < array.GetCount(); i++) + for(int q = 0; q < 4; q++) + qtf << ":: " << DeQtf((String)array.Get(i, q)); + Report report; + report << qtf; + Perform(report); +} + +void AddressBook::Quit() +{ + Break(); +} + +void AddressBook::Serialize(Stream& s) +{ + int version = 0; + s / version; + s % search.oname % search.osurname % search.oaddress % search.oemail; + s % fs; + SetupSearch(); +} + +GUI_APP_MAIN +{ + AddressBook ab; + LoadFromFile(ab); + ab.Run(); + StoreToFile(ab); +} diff --git a/examples/AddressBookXML2/AddressBook.lay b/examples/AddressBookXML2/AddressBook.lay new file mode 100644 index 000000000..98f9f2884 --- /dev/null +++ b/examples/AddressBookXML2/AddressBook.lay @@ -0,0 +1,30 @@ +LAYOUT(AddressBookLayout, 532, 456) + ITEM(MenuBar, menu, LeftPosZ(0, 200).TopPosZ(0, 20)) + ITEM(TabCtrl, tab, LeftPosZ(8, 516).TopPosZ(32, 84)) + ITEM(ArrayCtrl, array, LeftPosZ(8, 516).TopPosZ(124, 324)) +END_LAYOUT + +LAYOUT(ModifyLayout, 480, 52) + ITEM(Label, dv___0, SetLabel(t_("&Name")).LeftPosZ(8, 48).TopPosZ(8, 15)) + ITEM(EditField, name, LeftPosZ(8, 96).TopPosZ(28, 19)) + ITEM(Label, dv___2, SetLabel(t_("&Surname")).LeftPosZ(108, 48).TopPosZ(8, 15)) + ITEM(EditField, surname, LeftPosZ(108, 96).TopPosZ(28, 19)) + ITEM(Label, dv___4, SetLabel(t_("&Address")).LeftPosZ(208, 48).TopPosZ(8, 15)) + ITEM(EditField, address, LeftPosZ(208, 96).TopPosZ(28, 19)) + ITEM(Label, dv___6, SetLabel(t_("&Email")).LeftPosZ(308, 48).TopPosZ(8, 15)) + ITEM(EditField, email, LeftPosZ(308, 96).TopPosZ(28, 19)) + ITEM(Button, add, SetLabel(t_("Ad&d")).LeftPosZ(416, 56).TopPosZ(4, 20)) + ITEM(Button, change, SetLabel(t_("&Change")).LeftPosZ(416, 56).TopPosZ(28, 20)) +END_LAYOUT + +LAYOUT(SearchLayout, 480, 56) + ITEM(Option, oname, SetLabel(t_("&Name")).LeftPosZ(8, 56).TopPosZ(8, 18)) + ITEM(EditField, name, LeftPosZ(8, 96).TopPosZ(28, 19)) + ITEM(Option, osurname, SetLabel(t_("&Surname")).LeftPosZ(108, 64).TopPosZ(8, 18)) + ITEM(EditField, surname, LeftPosZ(108, 96).TopPosZ(28, 19)) + ITEM(Option, oaddress, SetLabel(t_("&Address")).LeftPosZ(208, 64).TopPosZ(8, 18)) + ITEM(EditField, address, LeftPosZ(208, 96).TopPosZ(28, 19)) + ITEM(Option, oemail, SetLabel(t_("&Email")).LeftPosZ(308, 52).TopPosZ(8, 18)) + ITEM(EditField, email, LeftPosZ(308, 96).TopPosZ(28, 19)) + ITEM(Button, search, SetLabel(t_("&Search")).LeftPosZ(416, 56).TopPosZ(28, 20)) +END_LAYOUT diff --git a/examples/AddressBookXML2/AddressBookXML2.upp b/examples/AddressBookXML2/AddressBookXML2.upp new file mode 100644 index 000000000..5425b838e --- /dev/null +++ b/examples/AddressBookXML2/AddressBookXML2.upp @@ -0,0 +1,13 @@ +description "Address book application, uses XML to store data (using DOM like U++ classes)"; + +uses + CtrlLib, + Report; + +file + AddressBook.cpp, + AddressBook.lay; + +mainconfig + "" = "GUI"; + diff --git a/examples/AnimatedHello/AnimatedHello.upp b/examples/AnimatedHello/AnimatedHello.upp new file mode 100644 index 000000000..1064f098c --- /dev/null +++ b/examples/AnimatedHello/AnimatedHello.upp @@ -0,0 +1,11 @@ +description "Animated Hello world example"; + +uses + CtrlLib; + +file + Hello.cpp; + +mainconfig + "" = "GUI"; + diff --git a/examples/AnimatedHello/Hello.cpp b/examples/AnimatedHello/Hello.cpp new file mode 100644 index 000000000..ce3912a59 --- /dev/null +++ b/examples/AnimatedHello/Hello.cpp @@ -0,0 +1,62 @@ +// This is Upp conversion of Qt example, see +// http://doc.trolltech.com/3.0/hello-example.html + +#include + +using namespace Upp; + +class HelloWorld : public TopWindow { +public: + virtual void LeftDown(Point, dword); + virtual void Paint(Draw& w); + +private: + String text; + + void Animate() { Refresh(); } + +public: + typedef HelloWorld CLASSNAME; + + HelloWorld& Text(const String& t) { text = t; Refresh(); return *this; } + + HelloWorld(); +}; + +HelloWorld::HelloWorld() +{ + SetTimeCallback(-40, THISBACK(Animate)); + BackPaint(); + Zoomable().Sizeable(); + SetRect(0, 0, 260, 80); +} + +void HelloWorld::LeftDown(Point, dword) +{ + Close(); +} + +void HelloWorld::Paint(Draw& w) +{ + Size sz = GetSize(); + static int sin_tbl[16] = { + 0, 38, 71, 92, 100, 92, 71, 38, 0, -38, -71, -92, -100, -92, -71, -38 + }; + w.DrawRect(sz, White); + Size tsz = GetTextSize(text, Roman(32)); + Point pos = (sz - tsz) / 2; + for(int i = 0; i < text.GetLength(); i++) { + int q = (i + GetTickCount() / 40) & 15; + w.DrawText(pos.x, pos.y + sin_tbl[q] * (sz.cy - 32) / 200, + ~text + i, Roman(32), HsvColorf(q / 15.0, 1, 0.5), 1); + pos.x += Roman(32).Info()[text[i]]; + } +} + +GUI_APP_MAIN +{ + HelloWorld hw; + hw.Title("Hello world example"); + hw.Text(Nvl(Join(CommandLine(), " "), "Hello world !")); + hw.Run(); +} diff --git a/examples/Bombs/Bombs.upp b/examples/Bombs/Bombs.upp new file mode 100644 index 000000000..4bd77b366 --- /dev/null +++ b/examples/Bombs/Bombs.upp @@ -0,0 +1,13 @@ +description "Mine sweeping game"; + +uses + CtrlLib; + +file + main.cpp, + bombs.rc, + bombs.iml; + +mainconfig + "" = "GUI"; + diff --git a/examples/Bombs/bombs.iml b/examples/Bombs/bombs.iml new file mode 100644 index 000000000..709f204de --- /dev/null +++ b/examples/Bombs/bombs.iml @@ -0,0 +1,21 @@ +IMAGE_META(icon_file, "icon.ico") +IMAGE_META(icon_large, "Small") +IMAGE_META(icon_bpp, "8") +IMAGE_BEGIN(Small) + IMAGE_SCAN("\1\0\0\377\1\0\0\377\1\0\0\377") + IMAGE_SCAN("\1\0\0\377") + IMAGE_SCAN("ɂ\0\0\377\0\377\377\1\0\0\377") + IMAGE_SCAN("\2\377\377\377\0\0\377\0\377\377\1\0\0\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\2\377\377\377\0\377\377") + IMAGE_SCAN("ń\377\377\377\3\0\0\0\377\377\377\0\0\377\1\0\0\377") + IMAGE_SCAN("Â\377\377\377\0\0\0\377\377\377\1\0\0\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\377\377\377\0\0\0\1\377\377\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\377\377\377\0\0\0\1\377\377\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\377\377\377\0\0\0\1\377\377\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\1\377\377\377\0\0\0\1\377\377\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\1\377\377\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\1\377\377\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\1\377\377\377") + IMAGE_SCAN("‚\377\377\377\0\0\0\377\377\377") + IMAGE_SCAN("Ĉ\377\377\377") +IMAGE_PACKED(Small, "\2\20\0\0\0\20\0\0\0\377\377\377\377\1\0\0\0\0\0\0\0") diff --git a/examples/Bombs/bombs.rc b/examples/Bombs/bombs.rc new file mode 100644 index 000000000..f4762d006 --- /dev/null +++ b/examples/Bombs/bombs.rc @@ -0,0 +1 @@ +5555 ICON DISCARDABLE "icon.ico" diff --git a/examples/Bombs/icon.ico b/examples/Bombs/icon.ico new file mode 100644 index 000000000..147e3267c Binary files /dev/null and b/examples/Bombs/icon.ico differ diff --git a/examples/Bombs/main.cpp b/examples/Bombs/main.cpp new file mode 100644 index 000000000..828f4051c --- /dev/null +++ b/examples/Bombs/main.cpp @@ -0,0 +1,225 @@ +#include + +using namespace Upp; + +class Bombs : public TopWindow { +public: + virtual void Paint(Draw& w); + virtual void LeftDown(Point p, dword flags); + virtual void RightDown(Point p, dword flags); + +private: + Size level; + int cx, cy; + int normal_cells, bombs; + Buffer field; + MenuBar menu; + StatusBar status; + + byte& Field(int x, int y) { return field[x + y * cx]; } + + enum { + HIDDEN = 16, + BOMB = 32, + MARK = 64, + EXPLODED = 128, + + UNIT = 30, + }; + + void About(); + + void File(Bar& menu); + void Game(Bar& menu); + void Menu(Bar& menu); + + void ShowStatus(); + void Level(Size sz); + + void Uncover(int x, int y); + void Generate(); + void UncoverAll(); + +public: + typedef Bombs CLASSNAME; + Bombs(); +}; + +void Bombs::Generate() +{ + cx = level.cx; + cy = level.cy; + field.Alloc(cx * cy); + for(int i = cx * cy - 1; i >= 0; i--) + field[i] = (rand() & 15) < 3 ? HIDDEN|BOMB : HIDDEN; + normal_cells = 0; + for(int x = 0; x < cx; x++) + for(int y = 0; y < cy; y++) + if((Field(x, y) & BOMB) == 0) { + normal_cells++; + for(int xx = -1; xx <= 1; xx++) + for(int yy = -1; yy <= 1; yy++) + if((xx || yy) && x + xx >= 0 && x + xx < cx && y + yy >= 0 && y + yy < cy && + (Field(x + xx, y + yy) & BOMB)) + Field(x, y)++; + } + bombs = cx * cy - normal_cells; + Rect r = GetRect(); + r.SetSize(AddFrameSize(UNIT * cx, UNIT * cy)); + SetRect(r); + ShowStatus(); + Refresh(); +} + +void Bombs::UncoverAll() +{ + for(int i = cx * cy - 1; i >= 0; i--) + field[i] &= ~HIDDEN; + Refresh(); +} + +void Bombs::Paint(Draw& w) +{ + for(int x = 0; x < cx; x++) + for(int y = 0; y < cy; y++) { + byte f = Field(x, y); + w.DrawRect(x * UNIT, y * UNIT + UNIT - 1, UNIT, 1, SBlack); + w.DrawRect(x * UNIT + UNIT - 1, y * UNIT, 1, UNIT, SBlack); + w.DrawRect(x * UNIT, y * UNIT, UNIT - 1, UNIT - 1, + (f & (HIDDEN|MARK)) ? SLtGray : f & BOMB ? SLtRed : SWhite); + String txt; + Color ink = SBlack; + Color cross = Null; + if(f & MARK) { + txt = "M"; + ink = SLtRed; + if((f & (HIDDEN|BOMB)) == BOMB) { + ink = SLtBlue; + cross = SLtRed; + } + } + else + if(!(f & HIDDEN)) + if(f & BOMB) + txt = "B"; + else { + f = f & 15; + txt = String(f + '0', 1); + ink = f == 0 ? SLtGreen : f == 1 ? SLtBlue : SBlack; + } + Size tsz = GetTextSize(txt, Roman(2 * UNIT / 3)); + w.DrawText(x * UNIT + (UNIT - tsz.cx) / 2, y * UNIT + (UNIT - tsz.cy) / 2, + txt, Roman(2 * UNIT / 3), ink); + if(f & EXPLODED) + cross = SLtBlue; + w.DrawLine(x * UNIT, y * UNIT, x * UNIT + UNIT - 1, y * UNIT + UNIT - 1, 1, cross); + w.DrawLine(x * UNIT, y * UNIT + UNIT - 1, x * UNIT + UNIT - 1, y * UNIT, 1, cross); + } +} + +void Bombs::Uncover(int x, int y) +{ + if(x >= 0 && x < cx && y >= 0 && y < cy) { + byte& f = Field(x, y); + if((f & (HIDDEN|MARK)) == HIDDEN) { + if(f & BOMB) { + f |= EXPLODED; + normal_cells = 0; + UncoverAll(); + return; + } + if((f &= ~HIDDEN) == 0) + for(int xx = -1; xx <= 1; xx++) + for(int yy = -1; yy <= 1; yy++) + if(xx || yy) + Uncover(x + xx, y + yy); + normal_cells--; + if(normal_cells == 0) { + UncoverAll(); + PromptOK("[*@4A6 Nice!]&You have found all the bombs!"); + } + } + } +} + +void Bombs::LeftDown(Point p, dword flags) +{ + if(!normal_cells) + return; + p /= UNIT; + Uncover(p.x, p.y); + Refresh(); + ShowStatus(); +} + +void Bombs::RightDown(Point p, dword flags) +{ + if(!normal_cells) + return; + p /= UNIT; + if(Field(p.x, p.y) & HIDDEN) { + Field(p.x, p.y) ^= MARK; + Refresh(); + } +} + +void Bombs::ShowStatus() +{ + status = Format("%d bombs, %d cells remaining", bombs, normal_cells); +} + +void Bombs::Level(Size sz) +{ + level = sz; +} + +void Bombs::About() +{ + PromptOK("[*A9/ uBombs]&[A5 Ultimate`+`+ example]"); +} + +void Bombs::File(Bar& menu) +{ + menu.Add("Exit", Breaker(IDOK)); + menu.Separator(); + menu.Add("About..", THISBACK(About)); +} + +void Bombs::Game(Bar& menu) +{ + menu.Add("Restart", THISBACK(Generate)); + menu.Separator(); + menu.Add("Easy", THISBACK1(Level, Size(10, 10))) + .Check(level.cx == 10); + menu.Add("Medium", THISBACK1(Level, Size(15, 15))) + .Check(level.cx == 15); + menu.Add("Difficult", THISBACK1(Level, Size(25, 20))) + .Check(level.cx == 25); +} + +void Bombs::Menu(Bar& menu) +{ + menu.Add("File", THISBACK(File)); + menu.Add("Game", THISBACK(Game)); +} + +#define IMAGECLASS BombsImg +#define IMAGEFILE +#include + +Bombs::Bombs() +{ + level = Size(10, 10); + AddFrame(menu); + menu.Set(THISBACK(Menu)); + AddFrame(status); + AddFrame(InsetFrame()); + Title("uBombs"); + Icon(BombsImg::Small()); + Generate(); +} + +GUI_APP_MAIN +{ + Bombs().Run(); +} diff --git a/examples/Button/Button.cpp b/examples/Button/Button.cpp new file mode 100644 index 000000000..55f486e87 --- /dev/null +++ b/examples/Button/Button.cpp @@ -0,0 +1,40 @@ +#include + +// http://java.sun.com/docs/books/tutorial/uiswing/start/swingTour.html + +using namespace Upp; + +struct ButtonApp : TopWindow { + int count; + Button button; + Label label; + + void RefreshLabel() + { + label = Format("Number of button clicks %d", count); + } + void Click() + { + ++count; + RefreshLabel(); + } + + typedef ButtonApp CLASSNAME; + + ButtonApp() + { + count = 0; + button <<= THISBACK(Click); + button.SetLabel("&I'm an Ultimate++ button!"); + Add(button.VCenterPos(20).HCenterPos(200)); + Add(label.BottomPos(0, 20).HCenterPos(200)); + label.SetAlign(ALIGN_CENTER); + Sizeable().Zoomable(); + RefreshLabel(); + } +}; + +GUI_APP_MAIN +{ + ButtonApp().Run(); +} diff --git a/examples/Button/Button.upp b/examples/Button/Button.upp new file mode 100644 index 000000000..f89c502e2 --- /dev/null +++ b/examples/Button/Button.upp @@ -0,0 +1,11 @@ +description "Counting button clicks"; + +uses + CtrlLib; + +file + Button.cpp; + +mainconfig + "" = "GUI"; + diff --git a/examples/Clock/Clock.upp b/examples/Clock/Clock.upp new file mode 100644 index 000000000..50702206a --- /dev/null +++ b/examples/Clock/Clock.upp @@ -0,0 +1,11 @@ +description "Analogue / digital clock"; + +uses + CtrlLib; + +file + main.cpp; + +mainconfig + "" = "GUI"; + diff --git a/examples/Clock/main.cpp b/examples/Clock/main.cpp new file mode 100644 index 000000000..816d0b9a3 --- /dev/null +++ b/examples/Clock/main.cpp @@ -0,0 +1,63 @@ +#include + +using namespace Upp; + +struct App : TopWindow { + void PaintPtr(Draw& w, double pos, double m, int d, Color color, Size sz2) + { + w.DrawLine(sz2.cx, sz2.cy, + sz2.cx + int(m * sin(pos * 2 * M_PI) * sz2.cx), + sz2.cy - int(m * cos(pos * 2 * M_PI) * sz2.cy), + d, color); + } + + void PaintCenteredText(Draw& w, int x, int y, const char *text, Font fnt, Color c) + { + Size tsz = GetTextSize(text, fnt); + w.DrawText(x - tsz.cx / 2, y - tsz.cy / 2, text, fnt, c); + } + + virtual void Paint(Draw& w) + { + Size sz = GetSize(); + w.DrawRect(sz, SLtGray); + sz -= 6; + w.Offset(3, 3); + Size sz2 = sz / 2; + w.DrawEllipse(0, 0, sz.cx, sz.cy, SWhite, 3, SBlack); + Font fnt = Arial(min(sz.cx, sz.cy) / 10); + for(int i = 1; i <= 12; i++) { + int d = i % 3 == 0 ? 3 : 2; + PaintCenteredText(w, sz2.cx + int(0.8 * sin(i * M_PI / 6) * sz2.cx), + sz2.cy - int(0.8 * cos(i * M_PI / 6) * sz2.cy), + AsString(i), i % 3 ? fnt : fnt().Bold(), SBlack); + } + Date date = GetSysDate(); + PaintCenteredText(w, sz.cx / 2, 3 * sz.cy / 5, GetLanguageInfo().FormatDate(date), + fnt().Bold(), SLtBlue); + double tm = double(GetSysTime() - ToTime(date)); + PaintPtr(w, tm / 60, 0.75, 1, SRed, sz2); + PaintPtr(w, tm / 3600, 0.6, 2, SCyan, sz2); + PaintPtr(w, tm / 3600 / 12, 0.5, 4, SBlack, sz2); + w.End(); + } + + void Timer() + { + Refresh(); + } + + App() + { + SetRect(0, 0, 150, 150); + Sizeable().Zoomable(); + BackPaint(); + SetTimeCallback(-1000, callback(this, &App::Timer)); + Title("Clock"); + } +}; + +GUI_APP_MAIN +{ + App().Run(); +} diff --git a/examples/CodeMetric/Analyse.cpp b/examples/CodeMetric/Analyse.cpp new file mode 100644 index 000000000..f385f46ce --- /dev/null +++ b/examples/CodeMetric/Analyse.cpp @@ -0,0 +1,120 @@ +#include +#include "Analyse.h" + + +bool ContainsAt(const String &source, const String &pattern, int pos = 0) +{ + return pos >= 0 + && pos + pattern.GetLength() <= source.GetLength() + && 0 == memcmp(source.Begin() + pos, pattern.Begin(), pattern.GetLength()); +} + +bool StartsWith(const String &source, const String &pattern) +{ + return ContainsAt(source, pattern, 0); +} + +bool EndsWith(const String &source, const String &pattern) +{ + return ContainsAt(source, pattern, source.GetLength() - pattern.GetLength()); +} + +String InsertNestingToSignature(String natural, String nesting) +{ + if(StartsWith(nesting, "::")) + nesting.Remove(0, 2); + if(nesting.GetCount() && !EndsWith(nesting, "::")) + nesting << "::"; + + int pos = natural.Find('('); // find the first opening parenthesis + pos--; + while(pos >= 0 && !iscid(natural[pos])) // skip over non-id chars before paren. + pos--; + if(pos < 0) return ""; + while(pos >= 0 && iscid(natural[pos])) // skip over last id before paren + pos--; + natural.Insert(pos+1, nesting); + return natural; +} + +int BodyPos(const Vector &pos) +{ + for(int i = 0; i < pos.GetCount(); i++) + if(pos[i].impl) + return pos[i].line; + return 0; +} + +CodeMetric::CodeMetric(const String &fileContent) : + orphanLines(0), blankLines(0), commentLines(0) +{ + StringStream stream(fileContent); + CppBase base; + Parser parser; + parser.whenFnEnd = THISBACK(StoreMetric); + parser.Do(stream, Vector(), base, "file", THISBACK(StoreError)); + + const SrcFile &srcFile = parser.getPreprocessedFile(); + + commentLines = srcFile.commentLinesRemoved; + blankLines = srcFile.blankLinesRemoved; + orphanLines = parser.symbolsOutsideFunctions.GetStat(';'); + totalLLOC = orphanLines; + sumCC1 = sumCC2 = sumDepth = 0; + + for(int i = 0; i < functions.GetCount(); i++) { + totalLLOC += functions[i].logicalLinesOfCode; + sumCC1 += functions[i].cyclomaticComplexity1; + sumCC2 += functions[i].cyclomaticComplexity2; + sumDepth += functions[i].scopeDepth; + } +} + + +String CodeMetric::ToString() const +{ + String s; + s << "LLOC: " << totalLLOC + << ", Blank: " << blankLines + << ", Comments: " << commentLines; + if(errors != "") + s << "\nErrors:\n" << errors; + return s; +} + +void CodeMetric::StoreError(int line, const String &msg) +{ + errors << "line " << line << ": " << msg << "\n"; +} + +int CodeMetric::LogicalLinesOfCode(const LexSymbolStat &symbolStat) +{ + static Vector oneLiners( + Vector() << tk_if << tk_else << tk_switch << tk_case + << tk_for << tk_do << tk_while << tk_try << tk_catch + << tk_struct << tk_class << tk_namespace + << tk_public << tk_private << tk_protected + << ';'); + return symbolStat.SumStat( oneLiners ); +} + +void CodeMetric::StoreMetric(const Parser::FunctionStat & functionStat) +{ + static Vector cc1_symbols( + Vector() << tk_if << tk_case << tk_for << tk_while << tk_catch); + + static Vector cc2_symbols( + Vector() << t_and << t_or << '?'); + + + FunctionEntry &entry = functions.Add(); + + entry.pos = BodyPos(functionStat.cppItem.pos); + entry.name = InsertNestingToSignature(functionStat.cppItem.natural, + functionStat.nesting); + int cc1 = 1 + functionStat.symbolStat.SumStat( cc1_symbols ); + entry.cyclomaticComplexity1 = cc1; + entry.cyclomaticComplexity2 = cc1 + functionStat.symbolStat.SumStat( cc2_symbols ); + entry.logicalLinesOfCode = 2 + LogicalLinesOfCode(functionStat.symbolStat); + entry.scopeDepth = functionStat.maxScopeDepth; +} diff --git a/examples/CodeMetric/Analyse.h b/examples/CodeMetric/Analyse.h new file mode 100644 index 000000000..744903656 --- /dev/null +++ b/examples/CodeMetric/Analyse.h @@ -0,0 +1,36 @@ +#ifndef _CppAnalyse_Analyze_h_ +#define _CppAnalyse_Analyze_h_ + +#include + +using namespace Upp; + +struct CodeMetric +{ +public: + struct FunctionEntry : public Moveable + { + String name; + int pos; + int cyclomaticComplexity1; + int cyclomaticComplexity2; + int logicalLinesOfCode; + int scopeDepth; + }; + + int orphanLines, blankLines, commentLines; + int totalLLOC, sumCC1, sumCC2, sumDepth; + Vector functions; + String errors; + + explicit CodeMetric(const String &fileContent); + String ToString() const; + +private: + typedef CodeMetric CLASSNAME; + void StoreError(int line, const String &msg); + void StoreMetric(const Parser::FunctionStat & functionStat); + int LogicalLinesOfCode(const LexSymbolStat &symbolStat); +}; + +#endif diff --git a/examples/CodeMetric/AnalyseGui.h b/examples/CodeMetric/AnalyseGui.h new file mode 100644 index 000000000..a16cc02fb --- /dev/null +++ b/examples/CodeMetric/AnalyseGui.h @@ -0,0 +1,36 @@ +#ifndef _CppAnalyse_AnalyseGui_h +#define _CppAnalyse_AnalyseGui_h + +#include + +using namespace Upp; + +class WarningDisplay : public Display +{ + int limit; + Color warningColor; +public: + WarningDisplay(int limit, Color warningColor = Color(255, 128, 128)); + void PaintBackground(Draw& w, const Rect& r, const Value& q, + Color ink, Color paper, dword style) const; +}; + +class AnalyseGui : public TopWindow +{ +public: + typedef AnalyseGui CLASSNAME; + MenuBar menu; + Splitter splitter; + LineEdit source; + ArrayCtrl chart; + LineEdit textMetric; + WarningDisplay ccDisplay, llocDisplay, depthDisplay; + + AnalyseGui(); + void MainMenu(Bar& menu); + void Open(); + void UpdateMetric(); + void GotoFunction(); +}; + +#endif diff --git a/examples/CodeMetric/AnalyseGui.iml b/examples/CodeMetric/AnalyseGui.iml new file mode 100644 index 000000000..939a03cbd --- /dev/null +++ b/examples/CodeMetric/AnalyseGui.iml @@ -0,0 +1,18 @@ +IMAGE_BEGIN(GaugeIcon) + IMAGE_SCAN("Ƅ\377\377\377") + IMAGE_SCAN("Ă\377\377\377\0\0\0\377\377\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\2\377\377\377\0\0\0\377\377\377\0\0\0\1\377\377\377") + IMAGE_SCAN("\3\377\377\377\0\0\377\377\377\377\1\0\0\0\377\377\377\3\0\0\0\377\377\377") + IMAGE_SCAN("\2\377\377\377\0\0\0\0\0\377\1\377\377\377\377\5\0\0\0\0\0\0\377\377\377") + IMAGE_SCAN("\3\377\377\377\0\0\0\377\377\377\0\0\377\1\377\377\377\377\5\0\0\0\377\377\377\0\0\0\377\377\377") + IMAGE_SCAN("\2\377\377\377\0\0\0\377\377\377\1\377\0\0\377\1\377\377\377\377\1\0\0\0\1\377\377\377") + IMAGE_SCAN("\2\377\377\377\0\0\0\377\377\377\1\377\0\0\377\1\0\0\0\377\377\377\1\0\0\0\1\377\377\377") + IMAGE_SCAN("\1\377\377\377\0\0\0\377\377\377\3\377\0\0\377\0\0\0\377\377\377\0\0\0\1\377\377\377") + IMAGE_SCAN("\2\377\377\377\0\0\0\0\377\0\1\377\377\377\377\1\377\0\0\377\1\0\0\0\1\377\377\377") + IMAGE_SCAN("\2\377\377\377\0\0\0\0\377\0\1\377\377\377\377\1\377\0\0\377\2\0\0\0\377\377\377") + IMAGE_SCAN("\2\377\377\377\0\0\0\0\377\0\377\377\377\0\0\377\2\0\0\0\377\377\377") + IMAGE_SCAN("\4\377\377\377\0\0\0\0\377\0\0\0\0\377\377\377\4\0\0\0\0\0\377\0\0\0\377\377\377") + IMAGE_SCAN("\3\377\377\377\0\0\0\0\377\0\377\377\377\3\0\0\377\0\0\0\377\377\377") + IMAGE_SCAN("Ĉ\377\377\377") + IMAGE_SCAN("Ƅ\377\377\377") +IMAGE_PACKED(GaugeIcon, "\2\20\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") diff --git a/examples/CodeMetric/CodeMetric.upp b/examples/CodeMetric/CodeMetric.upp new file mode 100644 index 000000000..819be53a3 --- /dev/null +++ b/examples/CodeMetric/CodeMetric.upp @@ -0,0 +1,16 @@ +description "Investigating C++ cyclometric complexity"; + +uses + CtrlLib, + CppBase; + +file + AnalyseGui.h, + Analyse.h, + AnalyseGui.iml, + Analyse.cpp, + main.cpp; + +mainconfig + "" = "GUI"; + diff --git a/examples/CodeMetric/icon.ico b/examples/CodeMetric/icon.ico new file mode 100644 index 000000000..4012786aa Binary files /dev/null and b/examples/CodeMetric/icon.ico differ diff --git a/examples/CodeMetric/main.cpp b/examples/CodeMetric/main.cpp new file mode 100644 index 000000000..168369656 --- /dev/null +++ b/examples/CodeMetric/main.cpp @@ -0,0 +1,127 @@ +#include "AnalyseGui.h" +#include "Analyse.h" + +#define IMAGECLASS Images +#define IMAGEFILE +#include + +String defaultCode = + "/*" + " This tool measures certain source code metrics.\n" + " You can type, paste, or load the code you would like measure into this text area.\n" + " Metrics provided are:\n" + " - Cyclomatic complexity 1: counts the decision points per method, thus estimating the\n" + " number of testcases needed for each method.\n" + " - Cyclomatic complexity 2: CC1 extended with the implicit decisions created by the\n" + " && || and ?: operators. Evaluation:\n" + " CC2 1-10 simple, low risk method\n" + " CC2 10-20 moderate complexity & risk method\n" + " CC2 21-50 high complexity & risk method\n" + " CC2 >50 too complex, untestable method, should be refactored\n" + " - Depth: measures deepest scope embedding level per method. This estimates the human\n" + " memory needed to keep in mind the current context. Any methods with depth > 5 is\n" + " considered too complex, and candidate for refactoring\n" + " - Logical Lines Of Code: estimates the amount of source code per method in a way\n" + " which is mostly independent from code formatting style. Methods longer than 80 LLOC are\n" + " too long, and should be refactored.\n" + "*/\n" + "int main()\n" + "{\n" + " return 0;\n" + "}\n"; + +String defaultTitle = "CodeMetric GUI"; + + +WarningDisplay::WarningDisplay(int limit, Color warningColor) : + limit(limit), warningColor(warningColor) +{ +} + +void WarningDisplay::PaintBackground(Draw& w, const Rect& r, const Value& q, + Color ink, Color paper, dword style) const +{ + int v = (int)q; + if(v >= limit) + paper = warningColor; + Display::PaintBackground(w, r, q, ink, paper, style); +} + +void AnalyseGui::MainMenu(Bar &bar) +{ + bar.Add("Load file", THISBACK(Open)); +} + +void AnalyseGui::Open() +{ + FileSelector fsel; + fsel.ExecuteOpen("Select file"); + String fileName = fsel.Get(); + if(fileName == "") + return; + source <<= LoadFile(fileName); + UpdateMetric(); + Title(defaultTitle + " [" + fileName + "]"); +} + +void AnalyseGui::UpdateMetric() +{ + String s = ~source; + CodeMetric metric(s); + chart.Clear(); + for(int i = 0; i < metric.functions.GetCount(); i++) + { + CodeMetric::FunctionEntry & entry = + metric.functions[i]; + chart.Add(entry.name, + entry.pos, + entry.cyclomaticComplexity1, + entry.cyclomaticComplexity2, + entry.logicalLinesOfCode, + entry.scopeDepth); + } + + textMetric.SetData(metric.ToString()); +} + +void AnalyseGui::GotoFunction() +{ + int cursor = chart.GetCursor(); + if(cursor >= 0 && cursor < chart.GetCount()) + { + int pos = (int)chart.Get(cursor, 1); + source.SetCursor( source.GetPos(pos) ); + source.CenterCursor(); + } +} + +AnalyseGui::AnalyseGui() : + ccDisplay(50), llocDisplay(80), depthDisplay(5) +{ + Title(defaultTitle); + Icon(Images::GaugeIcon); + AddFrame(menu); + menu.Set( THISBACK(MainMenu) ); + source <<= THISBACK(UpdateMetric); + source <<= defaultCode; + textMetric.SetEditable(false); + chart.AddColumn("Function", 80); + chart.AddColumn("Pos", 15); + chart.AddColumn("CC1", 15).SetDisplay(ccDisplay); + chart.AddColumn("CC2", 15).SetDisplay(ccDisplay); + chart.AddColumn("LLOC", 15).SetDisplay(llocDisplay); + chart.AddColumn("Depth", 15).SetDisplay(depthDisplay); + chart.WhenLeftDouble = THISBACK(GotoFunction); + UpdateMetric(); + splitter.Vert() << source << chart << textMetric; + splitter.SetPos(9000, 1); + splitter.SetPos(6500, 0); + Add(splitter.SizePos()); + Sizeable().Zoomable(); +} + + +GUI_APP_MAIN +{ + AnalyseGui().Run(); +} diff --git a/examples/Color/Color.h b/examples/Color/Color.h new file mode 100644 index 000000000..d2d5aeb68 --- /dev/null +++ b/examples/Color/Color.h @@ -0,0 +1,16 @@ +#ifndef _Color_Color_h +#define _Color_Color_h + +#include + +using namespace Upp; + +class ColorWindow : public TopWindow { +public: + typedef Color CLASSNAME; + ColorWindow(); + + virtual void Paint(Draw& draw); +}; + +#endif diff --git a/examples/Color/Color.upp b/examples/Color/Color.upp new file mode 100644 index 000000000..1001e278e --- /dev/null +++ b/examples/Color/Color.upp @@ -0,0 +1,12 @@ +description "Paints text using different colors"; + +uses + CtrlLib; + +file + Color.h, + main.cpp; + +mainconfig + "" = "GUI"; + diff --git a/examples/Color/main.cpp b/examples/Color/main.cpp new file mode 100644 index 000000000..ce053b94c --- /dev/null +++ b/examples/Color/main.cpp @@ -0,0 +1,21 @@ +#include "Color.h" + +ColorWindow::ColorWindow() +{ + Sizeable().Zoomable(); + SetRect(100, 100, 100, 100); +} + +void ColorWindow::Paint(Draw& draw) +{ + draw.DrawRect(draw.GetClip(), White()); + for(int i = 0; i < 16; i++) { + Color c(i & 1 ? 255 : 0, i & 2 ? 255 : 0, i & 4 ? 255 : 0); + draw.DrawText(0, i * 30, AsString(c), Arial(30).Underline(), c); + } +} + +GUI_APP_MAIN +{ + ColorWindow().Run(); +} diff --git a/examples/CompDir/CompDir.h b/examples/CompDir/CompDir.h new file mode 100644 index 000000000..c4dd06364 --- /dev/null +++ b/examples/CompDir/CompDir.h @@ -0,0 +1,10 @@ +#ifndef _CompDir_CompDir_h +#define _CompDir_CompDir_h + +#include + +using namespace Upp; + +#include "textdiff.h" + +#endif diff --git a/examples/CompDir/CompDir.iml b/examples/CompDir/CompDir.iml new file mode 100644 index 000000000..f2afb8dbc --- /dev/null +++ b/examples/CompDir/CompDir.iml @@ -0,0 +1,102 @@ +IMAGE_BEGIN(a_file) + IMAGE_SCAN("Œ\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0\0\1\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\3\0\0\0\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\0\0\0") + IMAGE_SCAN("ˆ\0\0\0") +IMAGE_PACKED(a_file, "\2\20\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") +IMAGE_BEGIN(b_file) + IMAGE_SCAN("Œ\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0\377\0\1\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0\377\0\1\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0\377\0\1\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0\377\0\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\3\0\0\0\377\0\0\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\0\0\0") + IMAGE_SCAN("ˆ\0\0\0") +IMAGE_PACKED(b_file, "\2\20\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") +IMAGE_BEGIN(ab_file) + IMAGE_SCAN("Œ\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\12\0\0\0\0\377\0\0\0\0\0\377\0\0\0\0\0\377\0\0\0\0\0\377\0\0\0\0\0\377\0\0\0\0") + IMAGE_SCAN("‚\0\0\0\12\377\0\0\0\0\377\0\0\0\0\377\0\0\0\0\377\0\0\0\0\377\0\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\0\0\0\377\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\1\0\0\0\377\0\1\0\0\0\377\0\0\1\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\0\0\0\2\377\0\0\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\0\0\0\0") + IMAGE_SCAN("ˆ\0\0\0") +IMAGE_PACKED(ab_file, "\2\20\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") +IMAGE_BEGIN(a_dir) + IMAGE_SCAN("") + IMAGE_SCAN("") + IMAGE_SCAN("…\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\377\377\1\0\0\0") + IMAGE_SCAN("\0\0\0") + IMAGE_SCAN("\2\0\0\0\0\377\0\377\377\377\2\0\377\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\0\377\0\0\1\0\0\0") + IMAGE_SCAN("Œ\0\0\0") +IMAGE_PACKED(a_dir, "\2\20\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") +IMAGE_BEGIN(b_dir) + IMAGE_SCAN("") + IMAGE_SCAN("") + IMAGE_SCAN("…\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\377\377\1\0\0\0") + IMAGE_SCAN("\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\0\377\377\377\2\377\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\0\0\1\0\0\0") + IMAGE_SCAN("Œ\0\0\0") +IMAGE_PACKED(b_dir, "\2\20\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") +IMAGE_BEGIN(ab_dir) + IMAGE_SCAN("") + IMAGE_SCAN("") + IMAGE_SCAN("…\0\0\0") + IMAGE_SCAN("\1\0\0\0\377\377\377\1\0\0\0") + IMAGE_SCAN("\0\0\0") + IMAGE_SCAN("\2\0\0\0\0\377\0\377\377\377\2\377\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\1\0\0\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\1\0\0\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\1\0\0\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\1\0\0\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\1\0\0\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\377\377\377\0\377\0\1\0\0\0\377\0\2\0\0\0\0") + IMAGE_SCAN("\2\0\0\0\0\377\0\0\1\0\0\0") + IMAGE_SCAN("Œ\0\0\0") +IMAGE_PACKED(ab_dir, "\2\20\0\0\0\20\0\0\0\0\0\0\0\377\377\377\377\0\0\0\0") diff --git a/examples/CompDir/CompDir.lay b/examples/CompDir/CompDir.lay new file mode 100644 index 000000000..c6655a7b5 --- /dev/null +++ b/examples/CompDir/CompDir.lay @@ -0,0 +1,15 @@ +#ifdef LAYOUTFILE + +LAYOUT(CompareDirLayout, 496, 492) + ITEM(Label, dv___0, SetLabel(t_("Folder &A:")).LeftPosZ(4, 52).TopPosZ(4, 19)) + ITEM(EditField, path_a, HSizePosZ(56, 4).TopPosZ(4, 19)) + ITEM(Label, dv___2, SetLabel(t_("Folder &B:")).LeftPosZ(4, 52).TopPosZ(26, 19)) + ITEM(EditField, path_b, HSizePosZ(56, 4).TopPosZ(26, 19)) + ITEM(Label, dv___4, SetLabel(t_("File &mask:")).LeftPosZ(4, 52).TopPosZ(48, 19)) + ITEM(EditField, file_mask, HSizePosZ(56, 68).TopPosZ(48, 19)) + ITEM(Button, refresh, SetLabel(t_("&Refresh")).RightPosZ(4, 60).TopPosZ(48, 18)) + ITEM(Splitter, splitter, HSizePosZ(4, 4).VSizePosZ(70, 4)) +END_LAYOUT + +#endif + diff --git a/examples/CompDir/CompDir.upp b/examples/CompDir/CompDir.upp new file mode 100644 index 000000000..cb5a27857 --- /dev/null +++ b/examples/CompDir/CompDir.upp @@ -0,0 +1,16 @@ +description "Compares directory contents"; + +uses + CtrlLib; + +file + CompDir.h, + textdiff.h, + textdiff.cpp, + main.cpp, + CompDir.lay, + CompDir.iml; + +mainconfig + "" = "GUI"; + diff --git a/examples/CompDir/main.cpp b/examples/CompDir/main.cpp new file mode 100644 index 000000000..f161f2c01 --- /dev/null +++ b/examples/CompDir/main.cpp @@ -0,0 +1,286 @@ +#include "CompDir.h" +#pragma hdrstop + +#define LAYOUTFILE +#include + +#define IMAGEFILE +#define IMAGECLASS CompDirImg +#include + +String NormalizePathCase(String fn) +{ +#ifdef PLATFORM_WIN32 // !PATH_CASE + return ToLower(fn); +#else + return fn; +#endif +} + +static String ExpandTabs(String line, int tabsize = 4) +{ + String out; + int pos = 0; + for(const char *p = line; *p; p++) + if(*p == '\t') { + int left = tabsize - pos % tabsize; + out.Cat(' ', left); + pos += left; + } + else { + out.Cat(*p); + pos++; + } + return out; +} + +class DlgCompareDir : public WithCompareDirLayout { +public: + typedef DlgCompareDir CLASSNAME; + DlgCompareDir(); + + void Run(); + + void Serialize(Stream& stream); + +private: + void CmdRefresh(); + void DoTreeCursor(); + int Refresh(String rel_path, int parent); + void DoBrowse(Ctrl *field); + void ToolTree(Bar& bar); + String GetTreePath() const; + +private: + struct FileInfo : Moveable + { + FileInfo() {} + FileInfo(String name, int64 size, Time time) : name(name), size(size), time(time) {} + + String name; + int64 size; + Time time; + }; + + bool FetchDir(String dir, VectorMap& files, VectorMap& dirs); + + FrameRight