[ui] Update passage code to use an ECS hierarchy

It's not quite complete in that entities need to be created for the
objects, and passage text object might get additional components in the
hierarchy, but the direct use of views has been replaced by the use of a
hierarchy object with the same tree structure, and now has text objects
for paragraphs and the entire passage.
This commit is contained in:
Bill Currie 2022-10-27 19:47:10 +09:00
parent 80c0beff89
commit 45e47a6df0
4 changed files with 96 additions and 86 deletions

View file

@ -44,12 +44,12 @@ typedef struct psg_text_s {
typedef struct passage_s {
const char *text; ///< Not owned by passage
struct view_s *view; ///< hierarchy of views representing passage
psg_text_t *text_objects; ///< all text objects in passage
unsigned num_text_objects; ///< number of text objects in passage
struct ecs_registry_s *reg; ///< Owning ECS registry
struct hierarchy_s *hierarchy; ///< hierarchy of text objects
} passage_t;
passage_t *Passage_ParseText (const char *text);
passage_t *Passage_ParseText (const char *text, struct ecs_registry_s *reg);
void Passage_Delete (passage_t *passage);
int Passage_IsSpace (const char *text) __attribute__((pure));

View file

@ -39,8 +39,29 @@
#include "QF/qtypes.h"
#include "QF/sys.h"
#include "QF/ui/view.h"
#include "QF/ecs/component.h"
#include "QF/ui/passage.h"
#include "QF/ui/view.h"
enum {
passage_type_text_obj,
passage_type_count
};
static const component_t passage_components[passage_type_count] = {
[passage_type_text_obj] = {
.size = sizeof (psg_text_t),
.name = "Text",
},
};
static const hierarchy_type_t passage_type = {
.num_components = passage_type_count,
.components = passage_components,
};
VISIBLE int
Passage_IsSpace (const char *text)
@ -69,110 +90,100 @@ Passage_IsSpace (const char *text)
return 0;
}
static void
add_text_view (view_t *paragraph_view, psg_text_t *text_object, int suppress)
{
view_t *text_view = view_new (0, 0, 0, 0, grav_flow);
text_view->data = text_object;
text_view->bol_suppress = suppress;
view_add (paragraph_view, text_view);
}
VISIBLE passage_t *
Passage_ParseText (const char *text)
Passage_ParseText (const char *text, ecs_registry_t *reg)
{
passage_t *passage = malloc (sizeof (passage_t));
passage->text = text;
passage->num_text_objects = 0;
passage->view = view_new (0, 0, 10, 10, grav_northwest);
passage->text_objects = 0;
passage->reg = reg;
if (!*text) {
return passage;
}
unsigned num_paragraphs = 1;
unsigned num_text_objects = 1;
int parsing_space = Passage_IsSpace (text);
passage->num_text_objects = 1;
for (const char *c = text; *c; c++) {
int size;
if ((size = Passage_IsSpace (c))) {
if (!parsing_space) {
passage->num_text_objects++;
num_text_objects++;
}
parsing_space = 1;
c += size - 1;
} else if (*c == '\n') {
if (c[1]) {
num_paragraphs++;
passage->num_text_objects += !Passage_IsSpace (c + 1);
num_text_objects += !Passage_IsSpace (c + 1);
}
} else {
if (parsing_space) {
passage->num_text_objects++;
num_text_objects++;
}
parsing_space = 0;
}
}
passage->hierarchy = Hierarchy_New (reg, &passage_type, 0);
Hierarchy_Reserve (passage->hierarchy,
1 + num_paragraphs + num_text_objects);
#if 0
printf ("num_paragraphs %d, num_text_objects %d\n", num_paragraphs,
passage->num_text_objects);
#endif
passage->text_objects = malloc (passage->num_text_objects
* sizeof (psg_text_t));
Hierarchy_InsertHierarchy (passage->hierarchy, 0, nullent, 0);
for (unsigned i = 0; i < num_paragraphs; i++) {
view_t *view = view_new (0, 0, 10, 10, grav_northwest);
view->flow_size = 1;
view_add (passage->view, view);
Hierarchy_InsertHierarchy (passage->hierarchy, 0, 0, 0);
}
num_paragraphs = 0;
hierarchy_t *h = passage->hierarchy;
psg_text_t *passage_obj = h->components[passage_type_text_obj];
psg_text_t *par_obj = &passage_obj[h->childIndex[0]];
psg_text_t *text_obj = &passage_obj[h->childIndex[1]];
*par_obj = *text_obj = (psg_text_t) { };
Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0);
parsing_space = Passage_IsSpace (text);
psg_text_t *text_object = passage->text_objects;
text_object->text = 0;
text_object->size = 0;
view_t *paragraph_view = passage->view->children[num_paragraphs++];
add_text_view (paragraph_view, text_object, parsing_space);
for (const char *c = text; *c; c++) {
int size;
if ((size = Passage_IsSpace (c))) {
if (!parsing_space) {
text_object->size = c - text - text_object->text;
(++text_object)->text = c - text;
add_text_view (paragraph_view, text_object, 1);
Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0);
text_obj->size = c - text - text_obj->text;
(++text_obj)->text = c - text;
}
parsing_space = 1;
c += size - 1;
} else if (*c == '\n') {
text_object->size = c - text - text_object->text;
text_obj->size = c - text - text_obj->text;
par_obj->size = c - text - par_obj->text;
if (c[1]) {
(++text_object)->text = c + 1 - text;
paragraph_view = passage->view->children[num_paragraphs++];
add_text_view (paragraph_view, text_object, 0);
(++par_obj)->text = c + 1 - text;
Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0);
(++text_obj)->text = c + 1 - text;
parsing_space = Passage_IsSpace (c + 1);
}
} else {
if (parsing_space) {
text_object->size = c - text - text_object->text;
(++text_object)->text = c - text;
add_text_view (paragraph_view, text_object, 0);
Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0);
text_obj->size = c - text - text_obj->text;
(++text_obj)->text = c - text;
}
parsing_space = 0;
if (!c[1]) {
text_object->size = c + 1 - text - text_object->text;
text_obj->size = c + 1 - text - text_obj->text;
par_obj->size = c + 1 - text - par_obj->text;
passage_obj->size = c + 1 - text - passage_obj->text;
}
}
}
#if 0
for (int i = 0; i < passage->view->num_children; i++) {
paragraph_view = passage->view->children[i];
for (int j = 0; j < paragraph_view->num_children; j++) {
view_t *text_view = paragraph_view->children[j];
psg_text_t *to = text_view->data;
printf ("%3d %3d %d %4d %4d '%.*s'\n", i, j,
text_view->bol_suppress,
to->text, to->size, to->size, text + to->text);
}
for (uint32_t i = 0; i < passage->hierarchy->num_objects; i++) {
psg_text_t *to = &passage_obj[i];
printf ("%3d %4d %4d '%.*s'\n", i,
to->text, to->size, to->size, text + to->text);
}
#endif
return passage;
@ -181,9 +192,6 @@ Passage_ParseText (const char *text)
VISIBLE void
Passage_Delete (passage_t *passage)
{
if (passage->view) {
view_delete (passage->view);
}
free (passage->text_objects);
Hierarchy_Delete (passage->hierarchy);
free (passage);
}

View file

@ -18,8 +18,8 @@ libs_ui_test_test_flow_size_LDADD=libs/ui/libQFui.la
libs_ui_test_test_flow_size_DEPENDENCIES=libs/ui/libQFui.la
libs_ui_test_test_passage_SOURCES=libs/ui/test/test-passage.c
libs_ui_test_test_passage_LDADD=libs/ui/libQFui.la
libs_ui_test_test_passage_DEPENDENCIES=libs/ui/libQFui.la
libs_ui_test_test_passage_LDADD=libs/ui/libQFui.la libs/ecs/libQFecs.la
libs_ui_test_test_passage_DEPENDENCIES=libs/ui/libQFui.la libs/ecs/libQFecs.la
libs_ui_test_test_txtbuffer_SOURCES=libs/ui/test/test-txtbuffer.c
libs_ui_test_test_txtbuffer_LDADD=libs/ui/libQFui.la

View file

@ -5,6 +5,7 @@
#include "QF/ui/view.h"
#include "QF/ui/passage.h"
#include "QF/ecs/component.h"
static const char test_text[] = {
"Guarding the entrance to the Grendal "
@ -49,61 +50,61 @@ int
main (void)
{
int ret = 0;
ecs_registry_t *registry = ECS_NewRegistry ();
passage_t *passage = Passage_ParseText (test_text);
if (passage->view->num_children != 3) {
passage_t *passage = Passage_ParseText (test_text, registry);
if (passage->hierarchy->childCount[0] != 3) {
ret = 1;
printf ("incorrect number of paragraphs: %d\n",
passage->view->num_children);
passage->hierarchy->childCount[0]);
}
if (passage->num_text_objects != 140) {
if (passage->hierarchy->num_objects != 144) {
ret = 1;
printf ("incorrect number of text objects: %d\n",
passage->num_text_objects);
passage->hierarchy->num_objects);
}
if (passage->view->children[0]->num_children != 49) {
if (passage->hierarchy->childCount[1] != 49) {
ret = 1;
printf ("incorrect number of text objects in first paragraph: %d\n",
passage->view->children[0]->num_children);
passage->hierarchy->childCount[1]);
}
if (passage->view->children[1]->num_children != 90) {
if (passage->hierarchy->childCount[2] != 90) {
ret = 1;
printf ("incorrect number of text objects in second paragraph: %d\n",
passage->view->children[1]->num_children);
passage->hierarchy->childCount[2]);
}
if (passage->view->children[2]->num_children != 1) {
if (passage->hierarchy->childCount[3] != 1) {
ret = 1;
printf ("incorrect number of text objects in third paragraph: %d\n",
passage->view->children[1]->num_children);
passage->hierarchy->childCount[3]);
}
view_t *text_view = passage->view->children[1]->children[0];
psg_text_t *to = text_view->data;
uint32_t *childIndex = passage->hierarchy->childIndex;
psg_text_t *text_objs = passage->hierarchy->components[0];
psg_text_t *to = &text_objs[childIndex[2] + 0];
if (to->size != 2 && (passage->text[to->text] != ' '
&& passage->text[to->text + 1] != ' ')) {
ret = 1;
printf ("second paragram does not begin with double space: %d '%.*s'\n",
to->size, to->size, passage->text + to->text);
}
if (text_view->bol_suppress) {
ret = 1;
printf ("second paragram indent suppressed\n");
}
for (int i = 0; i < passage->view->num_children; i++) {
view_t *paragraph_view = passage->view->children[i];
for (int j = 0; j < paragraph_view->num_children; j++) {
view_t *text_view = paragraph_view->children[j];
psg_text_t *to = text_view->data;
//if (text_view->bol_suppress) {
// ret = 1;
// printf ("second paragram indent suppressed\n");
//}
for (uint32_t i = 0; i < passage->hierarchy->childCount[0]; i++) {
for (uint32_t j = 0; j < passage->hierarchy->childCount[1 + i]; j++) {
psg_text_t *to = &text_objs[childIndex[1 + i] + j];
unsigned is_space = Passage_IsSpace (passage->text + to->text);
if (i == 1 && j == 0) {
// second paragraph indent, tested above
continue;
}
if ((!!is_space) != text_view->bol_suppress) {
ret = 1;
printf ("text/suppress mismatch %d [%d '%.*s'] %d %d\n",
text_view->bol_suppress, to->size, to->size,
passage->text + to->text, i, j);
}
//if ((!!is_space) != text_view->bol_suppress) {
// ret = 1;
// printf ("text/suppress mismatch %d [%d '%.*s'] %d %d\n",
// text_view->bol_suppress, to->size, to->size,
// passage->text + to->text, i, j);
//}
if (is_space) {
if (!check_non_space (passage->text, to)) {
continue;
@ -120,5 +121,6 @@ main (void)
}
Passage_Delete (passage);
ECS_DelRegistry (registry);
return ret;
}