144 lines
3.9 KiB
C++
144 lines
3.9 KiB
C++
// -*- C++ -*-
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
//
|
|
// Copyright Jean Pierre Cimalando 2019-2020.
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// (See accompanying file LICENSE or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
#include "layout.h"
|
|
#include "reader.h"
|
|
#include <absl/strings/ascii.h>
|
|
#include <absl/strings/string_view.h>
|
|
#include <unordered_map>
|
|
#include <iostream>
|
|
|
|
///
|
|
typedef std::unordered_map<std::string, std::string> Metadata;
|
|
|
|
static Metadata metadata_from_comment(absl::string_view comment)
|
|
{
|
|
Metadata md;
|
|
|
|
while (!comment.empty()) {
|
|
absl::string_view line;
|
|
|
|
size_t pos = comment.find_first_of("\r\n");
|
|
if (pos != comment.npos) {
|
|
line = comment.substr(0, pos);
|
|
comment.remove_prefix(pos + 1);
|
|
}
|
|
else {
|
|
line = comment;
|
|
comment = {};
|
|
}
|
|
|
|
line = absl::StripAsciiWhitespace(line);
|
|
if (line.empty() || line[0] == '#')
|
|
continue;
|
|
|
|
std::string key, value;
|
|
pos = line.find_first_of('=');
|
|
if (pos != comment.npos) {
|
|
key = std::string(line.substr(0, pos));
|
|
value = std::string(line.substr(pos + 1));
|
|
}
|
|
else
|
|
key = std::string(line);
|
|
|
|
md.emplace(std::move(key), std::move(value));
|
|
}
|
|
|
|
return md;
|
|
}
|
|
|
|
///
|
|
static void codegen_item(int& idCounter, int parentId, int parentX, int parentY, const LayoutItem& item, absl::string_view oldTheme)
|
|
{
|
|
const Metadata md = metadata_from_comment(item.comment);
|
|
|
|
absl::string_view tag = "-1";
|
|
absl::string_view newTheme;
|
|
|
|
Metadata::const_iterator it;
|
|
it = md.find("tag");
|
|
if (it != md.end())
|
|
tag = it->second;
|
|
it = md.find("theme");
|
|
if (it != md.end())
|
|
newTheme = it->second;
|
|
|
|
absl::string_view currentTheme = newTheme.empty() ? oldTheme : newTheme;
|
|
|
|
int id = idCounter++;
|
|
int myX = item.x;
|
|
int myY = item.y;
|
|
if (parentId == -1) {
|
|
myX = 0;
|
|
myY = 0;
|
|
}
|
|
int relX = myX - parentX;
|
|
int relY = myY - parentY;
|
|
|
|
//std::cout << "// Begin " << id << " " << item.classname << " {" << item.label << "}" << "\n";
|
|
|
|
if (!newTheme.empty())
|
|
std::cout << "enterTheme(" << newTheme << ");\n";
|
|
|
|
absl::string_view label;
|
|
if (!item.label.empty() && item.labeltype != "NO_LABEL")
|
|
label = item.label;
|
|
|
|
absl::string_view align = "kCenterText";
|
|
if (item.align & 4)
|
|
align = "kLeftText";
|
|
else if (item.align & 8)
|
|
align = "kRightText";
|
|
|
|
std::cout << item.classname << "* const view__" << id << " = create" << item.classname << "(CRect(" << relX << ", " << relY << ", " << (relX + item.w) << ", " << (relY + item.h) << "), " << tag << ", \"" << label << "\", " << align << ", " << item.labelsize << ");\n";
|
|
|
|
if (!item.id.empty())
|
|
std::cout << item.id << " = view__" << id << ";\n";
|
|
|
|
if (parentId != -1)
|
|
std::cout << "view__" << parentId << "->addView(view__" << id << ");\n";
|
|
|
|
if (item.hidden)
|
|
std::cout << "view__" << id << "->setVisible(false);\n";
|
|
|
|
for (const LayoutItem& subItem : item.items)
|
|
codegen_item(idCounter, id, myX, myY, subItem, currentTheme);
|
|
|
|
if (!newTheme.empty())
|
|
std::cout << "enterTheme(" << oldTheme << ");\n";
|
|
|
|
//std::cout << "// End " << id << " " << item.classname << " {" << item.label << "}" << "\n";
|
|
}
|
|
|
|
static void codegen_layout(const LayoutItem& item)
|
|
{
|
|
int idCounter = 0;
|
|
codegen_item(idCounter, -1, 0, 0, item, "defaultTheme");
|
|
}
|
|
|
|
///
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if (argc != 2) {
|
|
std::cerr << "Please indicate a fluid design file.\n";
|
|
return 1;
|
|
}
|
|
|
|
Layout layout = read_file_layout(argv[1]);
|
|
|
|
if (layout.items.size() != 1) {
|
|
std::cerr << "There must be exactly 1 top level component.";
|
|
return 1;
|
|
}
|
|
|
|
std::cout << "/* This file is generated by the layout maker tool. */\n";
|
|
|
|
codegen_layout(layout.items[0]);
|
|
|
|
return 0;
|
|
}
|