diff --git a/apps/font_book.cpp b/apps/font_book.cpp index c7da6e3..050ecbb 100644 --- a/apps/font_book.cpp +++ b/apps/font_book.cpp @@ -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) { diff --git a/apps/samples/list.cpp b/apps/samples/list.cpp index c556394..9966034 100644 --- a/apps/samples/list.cpp +++ b/apps/samples/list.cpp @@ -1,12 +1,17 @@ #include +#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"); diff --git a/apps/text_editor.cpp b/apps/text_editor.cpp index 78f5273..588b984 100644 --- a/apps/text_editor.cpp +++ b/apps/text_editor.cpp @@ -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) { diff --git a/desktop/list_view.cpp b/desktop/list_view.cpp index cbe6adb..5c0b7db 100644 --- a/desktop/list_view.cpp +++ b/desktop/list_view.cpp @@ -38,9 +38,6 @@ struct ListViewFixedString { }; struct ListViewFixedItem { - ListViewFixedString firstColumn; - // TODO Store the strings in an array per-ListViewColumn. - Array otherColumns; EsGeneric data; uint32_t iconID; }; @@ -51,6 +48,7 @@ struct ListViewColumn { uint32_t id; uint32_t flags; double width; + Array 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 = ®isteredColumns[(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); } diff --git a/desktop/os.header b/desktop/os.header index 8da9e55..7a2f120 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -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. diff --git a/desktop/settings.cpp b/desktop/settings.cpp index aa4328e..785f49e 100644 --- a/desktop/settings.cpp +++ b/desktop/settings.cpp @@ -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) { diff --git a/util/api_table.ini b/util/api_table.ini index d44df41..472c6f3 100644 --- a/util/api_table.ini +++ b/util/api_table.ini @@ -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