better fixed item storage with columns

This commit is contained in:
nakst 2021-11-21 09:09:45 +00:00
parent a4374b3aa5
commit 4f00b61da9
7 changed files with 101 additions and 62 deletions

View File

@ -238,24 +238,24 @@ void VariantsPopupCreate(Instance *instance, EsElement *element, EsCommand *) {
EsPanel *panel = EsPanelCreate(menu, ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_POPUP);
EsListView *list = EsListViewCreate(panel, ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal100), 1);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal200), 2);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal300), 3);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal400), 4);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal500), 5);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal600), 6);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal700), 7);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal800), 8);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal900), 9);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic100), 11);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic200), 12);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic300), 13);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic400), 14);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic500), 15);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic600), 16);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic700), 17);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic800), 18);
EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic900), 19);
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 1), 0, INTERFACE_STRING(FontBookVariantNormal100));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 2), 0, INTERFACE_STRING(FontBookVariantNormal200));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 3), 0, INTERFACE_STRING(FontBookVariantNormal300));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 4), 0, INTERFACE_STRING(FontBookVariantNormal400));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 5), 0, INTERFACE_STRING(FontBookVariantNormal500));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 6), 0, INTERFACE_STRING(FontBookVariantNormal600));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 7), 0, INTERFACE_STRING(FontBookVariantNormal700));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 8), 0, INTERFACE_STRING(FontBookVariantNormal800));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 9), 0, INTERFACE_STRING(FontBookVariantNormal900));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 11), 0, INTERFACE_STRING(FontBookVariantItalic100));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 12), 0, INTERFACE_STRING(FontBookVariantItalic200));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 13), 0, INTERFACE_STRING(FontBookVariantItalic300));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 14), 0, INTERFACE_STRING(FontBookVariantItalic400));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 15), 0, INTERFACE_STRING(FontBookVariantItalic500));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 16), 0, INTERFACE_STRING(FontBookVariantItalic600));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 17), 0, INTERFACE_STRING(FontBookVariantItalic700));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 18), 0, INTERFACE_STRING(FontBookVariantItalic800));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 19), 0, INTERFACE_STRING(FontBookVariantItalic900));
EsListViewFixedItemSelect(list, instance->fontVariant);
list->messageUser = [] (EsElement *element, EsMessage *message) {

View File

@ -1,12 +1,17 @@
#include <essence.h>
#define COLUMN_NAME (0)
#define COLUMN_AGE (1)
#define COLUMN_FAVORITE_COLOR (2)
void AddPerson(EsListView *list, const char *name, int age, const char *favoriteColor) {
char ageString[16];
EsStringFormat(ageString, sizeof(ageString), "%d%c", age, 0);
EsListViewIndex index = EsListViewFixedItemInsert(list, name);
EsListViewFixedItemAddString(list, index, ageString);
EsListViewFixedItemAddString(list, index, favoriteColor);
EsListViewIndex index = EsListViewFixedItemInsert(list);
EsListViewFixedItemSet(list, index, COLUMN_NAME, name);
EsListViewFixedItemSet(list, index, COLUMN_AGE, ageString);
EsListViewFixedItemSet(list, index, COLUMN_FAVORITE_COLOR, favoriteColor);
}
void _start() {
@ -19,9 +24,9 @@ void _start() {
EsInstance *instance = EsInstanceCreate(message, "List", -1);
EsPanel *wrapper = EsPanelCreate(instance->window, ES_CELL_FILL, ES_STYLE_PANEL_WINDOW_DIVIDER);
EsListView *list = EsListViewCreate(wrapper, ES_CELL_FILL | ES_LIST_VIEW_COLUMNS | ES_LIST_VIEW_FIXED_ITEMS);
EsListViewRegisterColumn(list, 0, "Name", -1, ES_FLAGS_DEFAULT, 150);
EsListViewRegisterColumn(list, 1, "Age", -1, ES_TEXT_H_RIGHT, 100);
EsListViewRegisterColumn(list, 2, "Favorite color", -1, ES_DRAW_CONTENT_RICH_TEXT, 150);
EsListViewRegisterColumn(list, COLUMN_NAME, "Name", -1, ES_FLAGS_DEFAULT, 150);
EsListViewRegisterColumn(list, COLUMN_AGE, "Age", -1, ES_TEXT_H_RIGHT, 100);
EsListViewRegisterColumn(list, COLUMN_FAVORITE_COLOR, "Favorite color", -1, ES_DRAW_CONTENT_RICH_TEXT, 150);
EsListViewAddAllColumns(list);
AddPerson(list, "Alice", 20, "\a#e00]Red");
AddPerson(list, "Bob", 30, "\a#080]Green");

View File

@ -141,15 +141,18 @@ void FormatPopupCreate(Instance *instance) {
if (currentSize < presetTextSizes[0]) {
// The current size is not in the list; add it.
EsListViewFixedItemInsert(list, buffer, EsStringFormat(buffer, sizeof(buffer), "%d pt", currentSize), currentSize);
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, currentSize), 0, buffer,
EsStringFormat(buffer, sizeof(buffer), "%d pt", currentSize));
}
for (uintptr_t i = 0; i < presetSizeCount; i++) {
EsListViewFixedItemInsert(list, buffer, EsStringFormat(buffer, sizeof(buffer), "%d pt", presetTextSizes[i]), presetTextSizes[i]);
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, presetTextSizes[i]), 0, buffer,
EsStringFormat(buffer, sizeof(buffer), "%d pt", presetTextSizes[i]));
if (currentSize > presetTextSizes[i] && (i == presetSizeCount - 1 || (i != presetSizeCount - 1 && currentSize < presetTextSizes[i + 1]))) {
// The current size is not in the list; add it.
EsListViewFixedItemInsert(list, buffer, EsStringFormat(buffer, sizeof(buffer), "%d pt", currentSize), currentSize);
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, currentSize), 0, buffer,
EsStringFormat(buffer, sizeof(buffer), "%d pt", currentSize));
}
}
@ -174,9 +177,9 @@ void FormatPopupCreate(Instance *instance) {
EsPanel *column = EsPanelCreate(panel, ES_FLAGS_DEFAULT, &styleFormatPopupColumn);
EsTextDisplayCreate(column, ES_CELL_H_EXPAND, ES_STYLE_TEXT_LABEL, INTERFACE_STRING(CommonFormatLanguage));
EsListView *list = EsListViewCreate(column, ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
EsListViewFixedItemInsert(list, INTERFACE_STRING(CommonFormatPlainText), 0);
EsListViewFixedItemInsert(list, "C/C++", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C);
EsListViewFixedItemInsert(list, "Ini", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI);
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, 0), 0, INTERFACE_STRING(CommonFormatPlainText));
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C), 0, "C/C++", -1);
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI), 0, "Ini", -1);
EsListViewFixedItemSelect(list, instance->syntaxHighlightingLanguage);
list->messageUser = [] (EsElement *element, EsMessage *message) {

View File

@ -38,9 +38,6 @@ struct ListViewFixedString {
};
struct ListViewFixedItem {
ListViewFixedString firstColumn;
// TODO Store the strings in an array per-ListViewColumn.
Array<ListViewFixedString> otherColumns;
EsGeneric data;
uint32_t iconID;
};
@ -51,6 +48,7 @@ struct ListViewColumn {
uint32_t id;
uint32_t flags;
double width;
Array<ListViewFixedString> items;
};
int ListViewProcessItemMessage(EsElement *element, EsMessage *message);
@ -1184,6 +1182,7 @@ struct EsListView : EsElement {
EsRectangle bounds = EsRectangleAddBorder(element->GetBounds(), element->style->insets);
for (uintptr_t i = item->startAtSecondColumn ? 1 : 0; i < activeColumns.Length(); i++) {
m.getContent.activeColumnIndex = i;
m.getContent.columnID = registeredColumns[activeColumns[i]].id;
m.getContent.icon = 0;
buffer.position = 0;
@ -1679,16 +1678,12 @@ struct EsListView : EsElement {
}
for (uintptr_t i = 0; i < registeredColumns.Length(); i++) {
EsHeapFree(registeredColumns[i].title);
}
for (uintptr_t i = 0; i < fixedItems.Length(); i++) {
for (uintptr_t j = 0; j < fixedItems[i].otherColumns.Length(); j++) {
EsHeapFree(fixedItems[i].otherColumns[j].string);
for (uintptr_t j = 0; j < registeredColumns[i].items.Length(); j++) {
EsHeapFree(registeredColumns[i].items[j].string);
}
EsHeapFree(fixedItems[i].firstColumn.string);
fixedItems[i].otherColumns.Free();
EsHeapFree(registeredColumns[i].title);
registeredColumns[i].items.Free();
}
EsHeapFree(emptyMessage);
@ -1889,8 +1884,8 @@ struct EsListView : EsElement {
EsAssert(index < fixedItems.Length());
ListViewFixedString emptyString = {};
ListViewFixedItem *item = &fixedItems[index];
ListViewFixedString *string = message->getContent.columnID == 0 ? &item->firstColumn
: message->getContent.columnID <= item->otherColumns.Length() ? &item->otherColumns[message->getContent.columnID - 1] : &emptyString;
ListViewColumn *column = &registeredColumns[(flags & ES_LIST_VIEW_COLUMNS) ? activeColumns[message->getContent.activeColumnIndex] : 0];
ListViewFixedString *string = index < column->items.Length() ? &column->items[index] : &emptyString;
EsBufferFormat(message->getContent.buffer, "%s", string->bytes, string->string);
if (!activeColumns.Length() || message->getContent.columnID == registeredColumns[activeColumns[0]].id) message->getContent.icon = item->iconID;
} else if (message->type == ES_MSG_LIST_VIEW_IS_SELECTED && (flags & ES_LIST_VIEW_FIXED_ITEMS)) {
@ -2306,6 +2301,7 @@ int ListViewColumnSplitterMessage(EsElement *element, EsMessage *message) {
void EsListViewAddAllColumns(EsListView *view) {
EsElementDestroyContents(view->columnHeader);
EsAssert(view->flags & ES_LIST_VIEW_COLUMNS); // List view does not have columns flag set.
view->activeColumns.Free();
for (uintptr_t i = 0; i < view->registeredColumns.Length(); i++) {
@ -2329,7 +2325,6 @@ void EsListViewAddAllColumns(EsListView *view) {
void EsListViewRegisterColumn(EsListView *view, uint32_t id, const char *title, ptrdiff_t titleBytes, uint32_t flags, double initialWidth) {
EsMessageMutexCheck();
EsAssert(view->flags & ES_LIST_VIEW_COLUMNS); // List view does not have columns flag set.
if (!initialWidth) {
initialWidth = (view->registeredColumns.Length() ? view->secondaryCellStyle : view->primaryCellStyle)->preferredWidth / theming.scale;
@ -2436,17 +2431,17 @@ void EsListViewInvalidateContent(EsListView *view, EsListViewIndex group, EsList
}
}
EsListViewIndex EsListViewFixedItemInsert(EsListView *view, const char *string, ptrdiff_t stringBytes, EsGeneric data, EsListViewIndex index, uint32_t iconID) {
EsListViewIndex EsListViewFixedItemInsert(EsListView *view, EsGeneric data, EsListViewIndex index, uint32_t iconID) {
EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS);
if (stringBytes == -1) {
stringBytes = EsCStringLength(string);
}
if (!view->groups.Length()) {
EsListViewInsertGroup(view, 0, ES_FLAGS_DEFAULT);
}
if (!view->registeredColumns.Length()) {
EsListViewRegisterColumn(view, 0, nullptr, 0);
}
if (index == -1) {
index = view->fixedItems.Length();
}
@ -2455,14 +2450,24 @@ EsListViewIndex EsListViewFixedItemInsert(EsListView *view, const char *string,
ListViewFixedItem item = {};
item.data = data;
item.iconID = iconID;
HeapDuplicate((void **) &item.firstColumn.string, &item.firstColumn.bytes, string, stringBytes);
view->fixedItems.Insert(item, index);
ListViewFixedString emptyString = {};
for (uintptr_t i = 0; i < view->registeredColumns.Length(); i++) {
ListViewColumn *column = &view->registeredColumns[i];
if (column->items.Length() >= (uintptr_t) index) {
column->items.InsertPointer(&emptyString, index);
}
}
EsListViewInsert(view, 0, index, 1);
return index;
}
void EsListViewFixedItemAddString(EsListView *view, EsListViewIndex index, const char *string, ptrdiff_t stringBytes) {
void EsListViewFixedItemSet(EsListView *view, EsListViewIndex index, uint32_t columnID, const char *string, ptrdiff_t stringBytes) {
EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS);
EsMessageMutexCheck();
EsAssert(index >= 0 && index < (intptr_t) view->fixedItems.Length());
@ -2472,7 +2477,26 @@ void EsListViewFixedItemAddString(EsListView *view, EsListViewIndex index, const
HeapDuplicate((void **) &fixedString, &outBytes, string, fixedString.bytes);
if (outBytes == fixedString.bytes) {
view->fixedItems[index].otherColumns.Add(fixedString);
ListViewColumn *column = nullptr;
for (uintptr_t i = 0; i < view->registeredColumns.Length(); i++) {
if (view->registeredColumns[i].id == columnID) {
column = &view->registeredColumns[i];
break;
}
}
EsAssert(column);
// Make sure that the column's array of items has been updated to match to the size of fixedItems.
if (column->items.Length() < view->fixedItems.Length()) {
uintptr_t oldLength = column->items.Length();
column->items.SetLength(view->fixedItems.Length());
EsMemoryZero(&column->items[oldLength], (view->fixedItems.Length() - oldLength) * sizeof(column->items[0]));
}
EsHeapFree(column->items[index].string);
column->items[index] = fixedString;
EsListViewInvalidateContent(view, 0, index);
}
}
@ -2516,14 +2540,20 @@ bool EsListViewFixedItemRemove(EsListView *view, EsGeneric data) {
if (found) {
EsListViewRemove(view, 0, index, 1);
ListViewFixedItem item = view->fixedItems[index];
for (uintptr_t i = 0; i < item.otherColumns.Length(); i++) {
EsHeapFree(item.otherColumns[i].string);
for (uintptr_t i = 0; i < view->registeredColumns.Length(); i++) {
ListViewColumn *column = &view->registeredColumns[i];
if ((uintptr_t) index < column->items.Length()) {
EsHeapFree(column->items[index].string);
column->items.Delete(index);
if (!column->items.Length()) {
column->items.Free();
}
}
}
EsHeapFree(item.firstColumn.string);
item.otherColumns.Free();
view->fixedItems.Delete(index);
}

View File

@ -1634,10 +1634,11 @@ struct EsMessageCreateItem {
struct EsMessageGetContent {
EsListViewIndex index;
EsListViewIndex group;
EsBuffer *buffer;
uint32_t icon;
uint32_t drawContentFlags;
uint32_t columnID;
EsBuffer *buffer;
uint16_t activeColumnIndex;
};
struct EsMessageGetIndent {
@ -2588,9 +2589,9 @@ function void EsListViewInsert(EsListView *view, EsListViewIndex group, EsListVi
function void EsListViewRemove(EsListView *view, EsListViewIndex group, EsListViewIndex firstIndex, EsListViewIndex count);
function void EsListViewRemoveAll(EsListView *view, EsListViewIndex group);
// (Fixed items.)
function EsListViewIndex EsListViewFixedItemInsert(EsListView *view, STRING string = BLANK_STRING, EsGeneric data = ES_NULL, EsListViewIndex index = -1, uint32_t iconID = 0);
function EsListViewIndex EsListViewFixedItemInsert(EsListView *view, EsGeneric data = ES_NULL, EsListViewIndex index = -1, uint32_t iconID = 0);
function bool EsListViewFixedItemRemove(EsListView *view, EsGeneric data); // Returns false if the item was not found.
function void EsListViewFixedItemAddString(EsListView *view, EsListViewIndex index, STRING string = BLANK_STRING); // For additional columns.
function void EsListViewFixedItemSet(EsListView *view, EsListViewIndex index, uint32_t columnID, STRING string = BLANK_STRING);
function bool EsListViewFixedItemFindIndex(EsListView *view, EsGeneric data, EsListViewIndex *index); // Returns false if the item was not found.
function bool EsListViewFixedItemSelect(EsListView *view, EsGeneric data); // Returns false if the item was not found.
function bool EsListViewFixedItemGetSelected(EsListView *view, EsGeneric *data); // Returns false if no item was selected.

View File

@ -649,7 +649,7 @@ void SettingsPageKeyboard(EsElement *element, SettingsPage *page) {
while (EsINIParse(&s)) {
if (s.key[0] != ';') {
EsListViewFixedItemInsert(list, s.value, s.valueBytes, s.key);
EsListViewFixedItemSet(list, EsListViewFixedItemInsert(list, s.key), 0, s.value, s.valueBytes);
EsAssert(s.keyBytes == 2);
if (s.key[0] + ((uint16_t) s.key[1] << 8) == api.global->keyboardLayout) {

View File

@ -142,6 +142,7 @@ EsMutexAcquire=140
EsMutexDestroy=141
EsMutexRelease=142
EsListViewAddAllColumns=143
EsListViewFixedItemSet=144
EsSchedulerYield=145
EsSleep=146
EsSpinlockAcquire=147
@ -420,7 +421,6 @@ EsTimerCancel=421
EsSliderSetValue=422
EsClipboardCloseAndAdd=423
EsListViewFixedItemInsert=424
EsListViewFixedItemAddString=425
EsListViewFixedItemFindIndex=426
EsListViewFixedItemSelect=427
EsListViewFixedItemGetSelected=428