Improve widget class generator including only required .h files

Instead of including "ui/ui.h" we can include the specific header file
for the used widgets in the .xml widget.
This commit is contained in:
David Capello 2018-06-08 15:52:10 -03:00
parent 7d96968ac3
commit e025d1a40a
14 changed files with 168 additions and 66 deletions

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2017 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -19,6 +19,7 @@
#include "app/ui/search_entry.h"
#include "doc/frame_tag.h"
#include "doc/sprite.h"
#include "ui/combobox.h"
#include "ui/window.h"
#include "goto_frame.xml.h"

View File

@ -31,12 +31,16 @@
#include "base/split_string.h"
#include "base/string.h"
#include "fmt/format.h"
#include "ui/alert.h"
#include "ui/graphics.h"
#include "ui/listitem.h"
#include "ui/message.h"
#include "ui/paint_event.h"
#include "ui/resize_event.h"
#include "ui/separator.h"
#include "ui/size_hint_event.h"
#include "ui/splitter.h"
#include "ui/system.h"
#include "keyboard_shortcuts.xml.h"

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2017 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -16,6 +16,7 @@
#include "app/transaction.h"
#include "doc/palette.h"
#include "doc/sprite.h"
#include "ui/manager.h"
#include "palette_size.xml.h"

View File

@ -27,6 +27,7 @@
#include "doc/image_ref.h"
#include "render/ordered_dither.h"
#include "render/quantization.h"
#include "ui/system.h"
#include "paste_text.xml.h"

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2015-2017 David Capello
// Copyright (C) 2015-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -23,6 +23,8 @@
#include "doc/context_observer.h"
#include "doc/documents_observer.h"
#include "doc/site.h"
#include "ui/listitem.h"
#include "ui/message.h"
#include "undo/undo_state.h"
#include "undo_history.xml.h"

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -16,6 +16,7 @@
#include "ui/manager.h"
#include "ui/message.h"
#include "ui/paint_event.h"
#include "ui/scale.h"
#include "ui/size_hint_event.h"
#include "ui/system.h"
#include "ui/theme.h"

View File

@ -35,6 +35,7 @@
#include "fmt/format.h"
#include "render/quantization.h"
#include "render/render.h"
#include "ui/listitem.h"
#include "open_sequence.xml.h"

View File

@ -17,6 +17,7 @@
#include "base/bind.h"
#include "base/fs.h"
#include "base/launcher.h"
#include "ui/alert.h"
#include "send_crash.xml.h"

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2017 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -26,7 +26,9 @@
#include "base/scoped_value.h"
#include "ui/box.h"
#include "ui/button.h"
#include "ui/manager.h"
#include "ui/message.h"
#include "ui/scale.h"
#include "ui/slider.h"
#include "ui/theme.h"

View File

@ -30,6 +30,9 @@
#include "she/system.h"
#include "ui/box.h"
#include "ui/button.h"
#include "ui/graphics.h"
#include "ui/listitem.h"
#include "ui/paint_event.h"
#include "ui/size_hint_event.h"
#include "ui/theme.h"
#include "ui/view.h"

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2017 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -22,6 +22,7 @@
#include "base/bind.h"
#include "ui/box.h"
#include "ui/button.h"
#include "ui/scale.h"
#include "ui/theme.h"
#include "ui/view.h"

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -13,6 +13,8 @@
#include "app/ui/keyboard_shortcuts.h"
#include "base/bind.h"
#include "obs/signal.h"
#include "ui/entry.h"
#include "ui/message.h"
#include <cctype>

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -13,6 +13,7 @@
#include "app/color_utils.h"
#include "app/ui/color_button.h"
#include "doc/user_data.h"
#include "ui/manager.h"
#include "user_data.xml.h"

View File

@ -13,10 +13,28 @@
#include "gen/common.h"
#include <iostream>
#include <set>
#include <vector>
typedef std::vector<TiXmlElement*> XmlElements;
namespace {
struct Item {
std::string xmlid;
std::string cppid;
std::string type;
std::string incl;
const Item& typeIncl(const char* type,
const char* incl) {
this->type = type;
this->incl = incl;
return *this;
}
};
}
static TiXmlElement* find_element_by_id(TiXmlElement* elem, const std::string& thisId)
{
const char* id = elem->Attribute("id");
@ -47,44 +65,102 @@ static void collect_widgets_with_ids(TiXmlElement* elem, XmlElements& widgets)
}
}
static std::string convert_type(const std::string& name,
const bool hasPref)
static Item convert_to_item(TiXmlElement* elem)
{
static std::string parent;
const std::string name = elem->Value();
if (name != "item")
parent = name;
if (name == "box") return "ui::Box";
if (name == "button") return "ui::Button";
if (name == "buttonset") return "app::ButtonSet";
if (name == "check") {
if (hasPref)
return "BoolPrefWidget<ui::CheckBox>";
else
return "ui::CheckBox";
Item item;
if (elem->Attribute("id")) {
item.xmlid = elem->Attribute("id");
item.cppid = convert_xmlid_to_cppid(item.xmlid, false);
}
if (name == "colorpicker") return "app::ColorButton";
if (name == "combobox") return "ui::ComboBox";
if (name == "dropdownbutton") return "app::DropDownButton";
if (name == "entry") return "ui::Entry";
if (name == "grid") return "ui::Grid";
if (name == "hbox") return "ui::HBox";
if (name == "item" && parent == "buttonset") return "app::ButtonSet::Item";
if (name == "label") return "ui::Label";
if (name == "link") return "ui::LinkLabel";
if (name == "listbox") return "ui::ListBox";
if (name == "panel") return "ui::Panel";
if (name == "popupwindow") return "ui::PopupWindow";
if (name == "radio") return "ui::RadioButton";
if (name == "search") return "app::SearchEntry";
if (name == "separator") return "ui::Separator";
if (name == "slider") return "ui::Slider";
if (name == "splitter") return "ui::Splitter";
if (name == "tipwindow") return "ui::TipWindow";
if (name == "vbox") return "ui::VBox";
if (name == "view") return "ui::View";
if (name == "window") return "ui::Window";
throw base::Exception("unknown widget name: " + name);
if (name == "box")
return item.typeIncl("ui::Box",
"ui/box.h");
if (name == "button")
return item.typeIncl("ui::Button",
"ui/button.h");
if (name == "buttonset")
return item.typeIncl("app::ButtonSet",
"app/ui/button_set.h");
if (name == "check") {
if (elem->Attribute("pref") != nullptr)
return item.typeIncl("BoolPrefWidget<ui::CheckBox>",
"app/ui/pref_widget.h");
else
return item.typeIncl("ui::CheckBox",
"ui/button.h");
}
if (name == "colorpicker")
return item.typeIncl("app::ColorButton",
"app/ui/color_button.h");
if (name == "combobox")
return item.typeIncl("ui::ComboBox",
"ui/combobox.h");
if (name == "dropdownbutton")
return item.typeIncl("app::DropDownButton",
"app/ui/drop_down_button.h");
if (name == "entry")
return item.typeIncl("ui::Entry",
"ui/entry.h");
if (name == "grid")
return item.typeIncl("ui::Grid",
"ui/grid.h");
if (name == "hbox")
return item.typeIncl("ui::HBox",
"ui/box.h");
if (name == "item" &&
parent == "buttonset")
return item.typeIncl("app::ButtonSet::Item",
"app/ui/button_set.h");
if (name == "label")
return item.typeIncl("ui::Label",
"ui/label.h");
if (name == "link")
return item.typeIncl("ui::LinkLabel",
"ui/link_label.h");
if (name == "listbox")
return item.typeIncl("ui::ListBox",
"ui/listbox.h");
if (name == "panel")
return item.typeIncl("ui::Panel",
"ui/panel.h");
if (name == "popupwindow")
return item.typeIncl("ui::PopupWindow",
"ui/popup_window.h");
if (name == "radio")
return item.typeIncl("ui::RadioButton",
"ui/button.h");
if (name == "search")
return item.typeIncl("app::SearchEntry",
"app/ui/search_entry.h");
if (name == "separator")
return item.typeIncl("ui::Separator",
"ui/separator.h");
if (name == "slider")
return item.typeIncl("ui::Slider",
"ui/slider.h");
if (name == "splitter")
return item.typeIncl("ui::Splitter",
"ui/splitter.h");
if (name == "tipwindow")
return item.typeIncl("ui::TipWindow",
"ui/tooltips.h");
if (name == "vbox")
return item.typeIncl("ui::VBox",
"ui/box.h");
if (name == "view")
return item.typeIncl("ui::View",
"ui/view.h");
if (name == "window")
return item.typeIncl("ui::Window",
"ui/window.h");
throw base::Exception("Unknown widget name: " + name);
}
void gen_ui_class(TiXmlDocument* doc,
@ -103,32 +179,47 @@ void gen_ui_class(TiXmlDocument* doc,
return;
}
XmlElements widgets;
collect_widgets_with_ids(elem, widgets);
std::vector<Item> items;
{
XmlElements xmlWidgets;
collect_widgets_with_ids(elem, xmlWidgets);
for (TiXmlElement* elem : xmlWidgets) {
const char* id = elem->Attribute("id");
if (!id)
continue;
items.push_back(convert_to_item(elem));
}
}
std::string className = convert_xmlid_to_cppid(widgetId, true);
std::string fnUpper = base::string_to_upper(base::get_file_title(inputFn));
std::string widgetType = convert_type(elem->Value(), false);
Item mainWidget = convert_to_item(elem);
std::set<std::string> headerFiles;
headerFiles.insert("app/find_widget.h");
headerFiles.insert("app/load_widget.h");
headerFiles.insert(mainWidget.incl);
for (const Item& item : items)
headerFiles.insert(item.incl);
std::cout
<< "#ifndef GENERATED_" << fnUpper << "_H_INCLUDED\n"
<< "#define GENERATED_" << fnUpper << "_H_INCLUDED\n"
<< "#pragma once\n"
<< "\n"
<< "#include \"app/find_widget.h\"\n"
<< "#include \"app/load_widget.h\"\n"
<< "#include \"app/ui/pref_widget.h\"\n"
<< "#include \"ui/ui.h\"\n"
<< "\n";
for (const auto& incl : headerFiles)
std::cout << "#include \"" << incl << "\"\n";
std::cout
<< "\n"
<< "namespace app {\n"
<< "namespace gen {\n"
<< "\n"
<< " class " << className << " : public " << widgetType << " {\n"
<< " class " << className << " : public " << mainWidget.type << " {\n"
<< " public:\n"
<< " " << className << "()";
// Special ctor for base class
if (widgetType == "ui::Window") {
if (mainWidget.type == "ui::Window") {
const char* desktop = elem->Attribute("desktop");
if (desktop && std::string(desktop) == "true")
std::cout
@ -143,11 +234,9 @@ void gen_ui_class(TiXmlDocument* doc,
<< " app::load_widget(\"" << base::get_file_name(inputFn) << "\", \"" << widgetId << "\", this);\n"
<< " app::finder(this)\n";
for (TiXmlElement* elem : widgets) {
const char* id = elem->Attribute("id");
std::string cppid = convert_xmlid_to_cppid(id, false);
for (const Item& item : items) {
std::cout
<< " >> \"" << id << "\" >> m_" << cppid << "\n";
<< " >> \"" << item.xmlid << "\" >> m_" << item.cppid << "\n";
}
std::cout
@ -155,26 +244,18 @@ void gen_ui_class(TiXmlDocument* doc,
<< " }\n"
<< "\n";
for (TiXmlElement* elem : widgets) {
const char* id = elem->Attribute("id");
const char* pref = elem->Attribute("pref");
std::string childType = convert_type(elem->Value(), (pref != nullptr));
std::string cppid = convert_xmlid_to_cppid(id, false);
for (const Item& item : items) {
std::cout
<< " " << childType << "* " << cppid << "() const { return m_" << cppid << "; }\n";
<< " " << item.type << "* " << item.cppid << "() const { return m_" << item.cppid << "; }\n";
}
std::cout
<< "\n"
<< " private:\n";
for (TiXmlElement* elem : widgets) {
const char* id = elem->Attribute("id");
const char* pref = elem->Attribute("pref");
std::string childType = convert_type(elem->Value(), (pref != nullptr));
std::string cppid = convert_xmlid_to_cppid(id, false);
for (const Item& item : items) {
std::cout
<< " " << childType << "* m_" << cppid << ";\n";
<< " " << item.type << "* m_" << item.cppid << ";\n";
}
std::cout