create list sample application

This commit is contained in:
nakst 2021-11-14 17:17:28 +00:00
parent 02cc8d14fb
commit 83ea7cc2af
11 changed files with 96 additions and 53 deletions

View File

@ -47,7 +47,7 @@ EsListViewColumn folderOutputColumns[] = {
#define COLUMN_TYPE (1)
{ INTERFACE_STRING(FileManagerColumnType), ES_LIST_VIEW_COLUMN_HAS_MENU },
#define COLUMN_SIZE (2)
{ INTERFACE_STRING(FileManagerColumnSize), ES_LIST_VIEW_COLUMN_HAS_MENU | ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED },
{ INTERFACE_STRING(FileManagerColumnSize), ES_LIST_VIEW_COLUMN_HAS_MENU | ES_TEXT_H_RIGHT },
};
#define LOAD_FOLDER_BACK (1)

35
apps/samples/list.cpp Normal file
View File

@ -0,0 +1,35 @@
#include <essence.h>
EsListViewColumn columns[] = {
// Title Flags Initial width
{ "Name", -1, ES_FLAGS_DEFAULT, 150 },
{ "Age", -1, ES_TEXT_H_RIGHT, 100 },
{ "Favorite color", -1, ES_DRAW_CONTENT_RICH_TEXT, 150 },
};
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);
}
void _start() {
_init();
while (true) {
EsMessage *message = EsMessageReceive();
if (message->type == ES_MSG_INSTANCE_CREATE) {
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);
EsListViewSetColumns(list, columns, sizeof(columns) / sizeof(columns[0]));
AddPerson(list, "Alice", 20, "\a#e00]Red");
AddPerson(list, "Bob", 30, "\a#080]Green");
AddPerson(list, "Cameron", 40, "\a#00f]Blue");
}
}
}

5
apps/samples/list.ini Normal file
View File

@ -0,0 +1,5 @@
[general]
name=List
[build]
source=apps/samples/list.cpp

View File

@ -28,16 +28,16 @@ struct Instance : EsInstance {
EsListViewColumn listViewProcessesColumns[] = {
{ "Name", -1, 0, 150 },
{ "PID", -1, ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED, 120 },
{ "Memory", -1, ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED, 120 },
{ "CPU", -1, ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED, 120 },
{ "Handles", -1, ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED, 120 },
{ "Threads", -1, ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED, 120 },
{ "PID", -1, ES_TEXT_H_RIGHT, 120 },
{ "Memory", -1, ES_TEXT_H_RIGHT, 120 },
{ "CPU", -1, ES_TEXT_H_RIGHT, 120 },
{ "Handles", -1, ES_TEXT_H_RIGHT, 120 },
{ "Threads", -1, ES_TEXT_H_RIGHT, 120 },
};
EsListViewColumn listViewContextSwitchesColumns[] = {
{ "Time stamp (ms)", -1, ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED, 150 },
{ "CPU", -1, ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED, 150 },
{ "Time stamp (ms)", -1, ES_TEXT_H_RIGHT, 150 },
{ "CPU", -1, ES_TEXT_H_RIGHT, 150 },
{ "Process", -1, 0, 150 },
{ "Thread", -1, 0, 150 },
{ "Count", -1, 0, 150 },

View File

@ -193,6 +193,15 @@ const EsStyle styleButtonGroupContainer = {
},
};
const EsStyle styleClockButton = {
.inherit = ES_STYLE_TASK_BAR_EXTRA,
.metrics = {
.mask = ES_THEME_METRICS_TEXT_FIGURES,
.textFigures = ES_TEXT_FIGURE_TABULAR,
},
};
struct {
Array<InstalledApplication *> installedApplications;
Array<ApplicationInstance *> allApplicationInstances;
@ -371,10 +380,6 @@ int ReorderListLayout(ReorderList *list, int additionalRightMargin, bool clampDr
size_t childCount = list->items.Length();
if (!childCount) {
return 0;
}
int totalWidth = 0;
uintptr_t nonExitingChildCount = 0;
@ -394,8 +399,8 @@ int ReorderListLayout(ReorderList *list, int additionalRightMargin, bool clampDr
widthClamped = true;
}
int targetWidth = totalWidth / nonExitingChildCount;
int extraWidth = totalWidth % nonExitingChildCount;
int targetWidth = nonExitingChildCount ? totalWidth / nonExitingChildCount : -1;
int extraWidth = nonExitingChildCount ? totalWidth % nonExitingChildCount : 0;
list->targetWidth = targetWidth;
list->extraWidth = extraWidth;
@ -575,7 +580,7 @@ void WindowTabDestroy(WindowTab *tab) {
if (container->taskBarButton) {
container->taskBarButton->exiting = true;
container->taskBarButton->containerWindow = nullptr;
EsElementRelayout(&desktop.taskBar);
EsElementRelayout(container->taskBarButton->parent);
// The button is destroyed by ReorderItemAnimate, once the exit animation completes.
}
@ -2652,7 +2657,7 @@ void DesktopSetup() {
desktop.tasksButton = EsButtonCreate(panel, ES_ELEMENT_HIDDEN, ES_STYLE_TASK_BAR_BUTTON);
desktop.tasksButton->messageUser = TaskBarTasksButtonMessage;
EsButton *clockButton = EsButtonCreate(panel, ES_BUTTON_TABULAR | ES_BUTTON_COMPACT, ES_STYLE_TASK_BAR_EXTRA);
EsButton *clockButton = EsButtonCreate(panel, ES_BUTTON_COMPACT, &styleClockButton);
clockButton->cName = "current time";
EsThreadCreate(TaskBarClockUpdateThread, nullptr, clockButton);

View File

@ -3920,8 +3920,7 @@ int ProcessButtonMessage(EsElement *element, EsMessage *message) {
EsDrawContent(message->painter, element,
ES_RECT_2S(message->painter->width, message->painter->height),
button->label, button->labelBytes, button->iconID,
((button->flags & ES_BUTTON_DROPDOWN) ? ES_DRAW_CONTENT_MARKER_DOWN_ARROW : 0)
| ((button->flags & ES_BUTTON_TABULAR) ? ES_DRAW_CONTENT_TABULAR : 0));
((button->flags & ES_BUTTON_DROPDOWN) ? ES_DRAW_CONTENT_MARKER_DOWN_ARROW : 0));
} else if (message->type == ES_MSG_PAINT_ICON) {
if (button->imageDisplay) {
EsRectangle imageSize = ES_RECT_2S(button->imageDisplay->width, button->imageDisplay->height);
@ -4233,7 +4232,7 @@ int ProcessMenuItemMessage(EsElement *element, EsMessage *message) {
EsDrawContent(message->painter, element,
ES_RECT_2S(message->painter->width, message->painter->height),
(const char *) _buffer, buffer.position, 0, ES_DRAW_CONTENT_CHANGE_ALIGNMENT | ES_TEXT_H_RIGHT | ES_TEXT_V_CENTER);
(const char *) _buffer, buffer.position, 0, ES_TEXT_H_RIGHT);
} else if (message->type == ES_MSG_GET_WIDTH) {
uint8_t _buffer[64];
EsBuffer buffer = { .out = _buffer, .bytes = sizeof(_buffer) };

View File

@ -1193,18 +1193,9 @@ struct EsListView : EsElement {
&& ES_HANDLED == EsMessageSend(this, &m)) {
bool useSelectedCellStyle = (item->element->customStyleState & THEME_STATE_SELECTED) && (flags & ES_LIST_VIEW_CHOICE_SELECT);
UIStyle *style = useSelectedCellStyle ? selectedCellStyle : i ? secondaryCellStyle : primaryCellStyle;
uint8_t previousTextAlign = style->textAlign;
if (columns[i].flags & ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED) {
style->textAlign ^= ES_TEXT_H_RIGHT | ES_TEXT_H_LEFT;
}
style->PaintText(message->painter, element, bounds,
(char *) _buffer, buffer.position, m.getContent.icon,
(columns[i].flags & ES_LIST_VIEW_COLUMN_TABULAR) ? ES_DRAW_CONTENT_TABULAR : ES_FLAGS_DEFAULT,
i ? nullptr : &selection);
style->textAlign = previousTextAlign;
columns[i].flags, i ? nullptr : &selection);
}
bounds.l += columns[i].width * theming.scale + secondaryCellStyle->gapMajor;

View File

@ -379,13 +379,15 @@ define ES_TEXT_PLAN_CLIP_UNBREAKABLE_LINES (1 << 11)
define ES_TEXT_PLAN_NO_FONT_SUBSTITUTION (1 << 12)
// ...plus alignment flags.
define ES_DRAW_CONTENT_CHANGE_ALIGNMENT (1 << 8)
define ES_DRAW_CONTENT_TABULAR (1 << 8)
define ES_DRAW_CONTENT_MARKER_DOWN_ARROW (1 << 9)
define ES_DRAW_CONTENT_MARKER_UP_ARROW (1 << 10)
define ES_DRAW_CONTENT_TABULAR (1 << 11)
define ES_DRAW_CONTENT_RICH_TEXT (1 << 12)
// ...plus alignment flags, if CHANGE_ALIGNMENT set.
define ES_LIST_VIEW_COLUMN_HAS_MENU (1 << 16) // The header can be clicked to open a menu.
// ...plus draw content flags and alignment flags.
define ES_FILE_READ_SHARED (0x1) // Read-only. The file can still be opened for writing.
define ES_FILE_READ (0x2) // Read-only. The file will not openable for writing. This will fail if the file is already opened for writing.
define ES_FILE_WRITE_SHARED (0x4) // Read-write. The file can still be opened for writing. This will fail if the file is already opened for exclusive writing.
@ -514,7 +516,6 @@ define ES_BUTTON_CHECKBOX (1 << 10)
define ES_BUTTON_RADIOBOX (1 << 11)
define ES_BUTTON_CANCEL (1 << 12)
define ES_BUTTON_PUSH (1 << 13)
define ES_BUTTON_TABULAR (1 << 14) // Use tabular text figures.
define ES_MENU_ITEM_CHECKED (ES_CHECK_CHECKED)
define ES_COLOR_WELL_HAS_OPACITY (1 << 0)
@ -542,10 +543,6 @@ define ES_LIST_VIEW_GROUP_HAS_FOOTER (1 << 1) // The last item in the group is
define ES_LIST_VIEW_GROUP_INDENT (1 << 2) // Indent the group's items (excluding the header and footer).
define ES_LIST_VIEW_GROUP_COLLAPSABLE (1 << 3) // The group can be collapsed.
define ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED (1 << 0) // The column's contents is right-aligned.
define ES_LIST_VIEW_COLUMN_HAS_MENU (1 << 1) // The header can be clicked to open a menu.
define ES_LIST_VIEW_COLUMN_TABULAR (1 << 2) // Use tabular text figures (so that digits are aligned).
define ES_MENU_AT_CURSOR (1 << 0)
define ES_MENU_MAXIMUM_HEIGHT (1 << 1)
@ -627,6 +624,7 @@ define ES_THEME_METRICS_FONT_WEIGHT (1 << 20)
define ES_THEME_METRICS_ICON_SIZE (1 << 21)
define ES_THEME_METRICS_IS_ITALIC (1 << 22)
define ES_THEME_METRICS_LAYOUT_VERTICAL (1 << 23)
define ES_THEME_METRICS_TEXT_FIGURES (1 << 24)
define ES_WINDOW_MOVE_MAXIMIZED (1 << 0)
define ES_WINDOW_MOVE_ADJUST_TO_FIT_SCREEN (1 << 1)
@ -1331,7 +1329,8 @@ struct EsThemeMetrics {
int32_t maximumWidth, maximumHeight;
int32_t gapMajor, gapMinor, gapWrap;
uint32_t textColor, selectedBackground, selectedText, iconColor;
int textAlign, textSize, fontFamily, fontWeight, iconSize;
int32_t textAlign, textSize, fontFamily, fontWeight, iconSize;
uint8_t textFigures;
bool isItalic, layoutVertical;
};

View File

@ -2686,6 +2686,17 @@ void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
textRun->style.decorations |= ES_TEXT_DECORATION_UNDERLINE;
} else if (c == '2' /* secondary color */) {
textRun->style.color = GetConstantNumber("textSecondary");
} else if (c == '#' /* custom color */) {
char string[9];
size_t bytes = 0;
while (bytes < sizeof(string)) {
if (i >= inStringBytes || inString[i] == ']') break;
string[bytes++] = inString[i++];
}
textRun->style.color = EsColorParse(string, bytes);
goto parsedFormat;
}
}

View File

@ -207,6 +207,7 @@ typedef struct ThemeMetrics {
uint32_t textColor, selectedBackground, selectedText, iconColor;
int8_t textAlign, fontWeight;
int16_t textSize, iconSize;
uint8_t textFigures;
bool isItalic, layoutVertical;
} ThemeMetrics;
@ -1200,24 +1201,16 @@ typedef struct ThemeAnimation {
struct UIStyle {
intptr_t referenceCount;
uint32_t observedStyleStateMask;
bool IsStateChangeObserved(uint16_t state1, uint16_t state2);
// General information.
uint8_t textAlign;
uint16_t textSize;
uint32_t textColor;
EsFont font;
EsRectangle insets, borders;
uint16_t preferredWidth, preferredHeight;
int16_t gapMajor, gapMinor, gapWrap;
uint32_t observedStyleStateMask;
EsRectangle paintOutsets, opaqueInsets;
float scale;
EsThemeAppearance *appearance; // An optional, custom appearance provided by the application.
// Data.
@ -1242,7 +1235,7 @@ struct UIStyle {
// Misc.
bool IsRegionCompletelyOpaque(EsRectangle region, int width, int height);
bool IsStateChangeObserved(uint16_t state1, uint16_t state2);
inline void GetTextStyle(EsTextStyle *style);
};
@ -1326,8 +1319,6 @@ bool ThemeInitialise() {
}
void ThemeStyleCopyInlineMetrics(UIStyle *style) {
style->textSize = style->metrics->textSize;
style->textColor = style->metrics->textColor;
style->font.family = style->metrics->fontFamily;
style->font.weight = style->metrics->fontWeight;
style->font.italic = style->metrics->isItalic;
@ -1547,6 +1538,7 @@ void ThemeStylePrepare(UIStyle *style, UIStyleKey key) {
if (customMetrics->mask & ES_THEME_METRICS_GAP_MINOR) style->metrics->gapMinor = customMetrics->gapMinor;
if (customMetrics->mask & ES_THEME_METRICS_GAP_WRAP) style->metrics->gapWrap = customMetrics->gapWrap;
if (customMetrics->mask & ES_THEME_METRICS_TEXT_COLOR) style->metrics->textColor = customMetrics->textColor;
if (customMetrics->mask & ES_THEME_METRICS_TEXT_FIGURES) style->metrics->textFigures = customMetrics->textFigures;
if (customMetrics->mask & ES_THEME_METRICS_SELECTED_BACKGROUND) style->metrics->selectedBackground = customMetrics->selectedBackground;
if (customMetrics->mask & ES_THEME_METRICS_SELECTED_TEXT) style->metrics->selectedText = customMetrics->selectedText;
if (customMetrics->mask & ES_THEME_METRICS_ICON_COLOR) style->metrics->iconColor = customMetrics->iconColor;
@ -1933,13 +1925,18 @@ void UIStyle::PaintText(EsPainter *painter, EsElement *element, EsRectangle rect
if (textBytes) {
EsTextPlanProperties properties = {};
properties.flags = (flags & ES_DRAW_CONTENT_CHANGE_ALIGNMENT) ? (flags & 0xFF) : textAlign;
properties.flags = textAlign;
if (flags & ES_TEXT_H_LEFT) properties.flags = (properties.flags & ~(ES_TEXT_H_CENTER | ES_TEXT_H_RIGHT)) | ES_TEXT_H_LEFT;
if (flags & ES_TEXT_H_CENTER) properties.flags = (properties.flags & ~(ES_TEXT_H_LEFT | ES_TEXT_H_RIGHT)) | ES_TEXT_H_CENTER;
if (flags & ES_TEXT_H_RIGHT) properties.flags = (properties.flags & ~(ES_TEXT_H_LEFT | ES_TEXT_H_CENTER)) | ES_TEXT_H_RIGHT;
if (flags & ES_TEXT_V_TOP) properties.flags = (properties.flags & ~(ES_TEXT_V_CENTER | ES_TEXT_V_BOTTOM)) | ES_TEXT_V_TOP;
if (flags & ES_TEXT_V_CENTER) properties.flags = (properties.flags & ~(ES_TEXT_V_TOP | ES_TEXT_V_BOTTOM)) | ES_TEXT_V_CENTER;
if (flags & ES_TEXT_V_BOTTOM) properties.flags = (properties.flags & ~(ES_TEXT_V_TOP | ES_TEXT_V_CENTER)) | ES_TEXT_V_BOTTOM;
EsTextRun textRun[2] = {};
textRun[1].offset = textBytes;
textRun[0].style.font = font;
textRun[0].style.size = textSize;
textRun[0].style.color = textColor;
GetTextStyle(&textRun[0].style);
if (flags & ES_DRAW_CONTENT_TABULAR) {
textRun[0].style.figures = ES_TEXT_FIGURE_TABULAR;
@ -2038,6 +2035,7 @@ inline void UIStyle::GetTextStyle(EsTextStyle *style) {
style->font = font;
style->size = metrics->textSize;
style->color = metrics->textColor;
style->figures = metrics->textFigures;
}
bool UIStyle::IsStateChangeObserved(uint16_t state1, uint16_t state2) {

Binary file not shown.