mirror of https://gitlab.com/nakst/essence
604 lines
27 KiB
C++
604 lines
27 KiB
C++
struct InspectorElementEntry {
|
|
EsElement *element;
|
|
EsRectangle takenBounds, givenBounds;
|
|
int depth;
|
|
};
|
|
|
|
struct InspectorWindow : EsInstance {
|
|
EsInstance *instance; // The instance being inspected.
|
|
|
|
EsListView *elementList;
|
|
Array<InspectorElementEntry> elements; // TODO This is being leaked.
|
|
InspectorElementEntry hoveredElement;
|
|
char *cCategoryFilter;
|
|
|
|
intptr_t selectedElement;
|
|
EsButton *alignH[6];
|
|
EsButton *alignV[6];
|
|
EsButton *direction[4];
|
|
EsTextbox *contentTextbox;
|
|
EsButton *addChildButton;
|
|
EsButton *addSiblingButton;
|
|
EsButton *visualizeRepaints;
|
|
EsButton *visualizeLayoutBounds;
|
|
EsButton *visualizePaintSteps;
|
|
EsListView *listEvents;
|
|
EsTextbox *textboxCategoryFilter;
|
|
};
|
|
|
|
int InspectorElementItemCallback(EsElement *element, EsMessage *message) {
|
|
InspectorWindow *inspector = (InspectorWindow *) element->instance;
|
|
|
|
if (message->type == ES_MSG_HOVERED_START) {
|
|
InspectorElementEntry *entry = &inspector->elements[EsListViewGetIndexFromItem(element)];
|
|
if (entry->element->parent) entry->element->parent->Repaint(true);
|
|
else entry->element->Repaint(true);
|
|
inspector->hoveredElement = *entry;
|
|
} else if (message->type == ES_MSG_HOVERED_END || message->type == ES_MSG_DESTROY) {
|
|
EsListViewIndex index = EsListViewGetIndexFromItem(element);
|
|
InspectorElementEntry *entry = &inspector->elements[index];
|
|
if (entry->element->parent) entry->element->parent->Repaint(true);
|
|
else entry->element->Repaint(true);
|
|
inspector->hoveredElement = {};
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void InspectorUpdateEditor(InspectorWindow *inspector) {
|
|
EsElement *e = inspector->selectedElement == -1 ? nullptr : inspector->elements[inspector->selectedElement].element;
|
|
|
|
bool isStack = e && e->messageClass == ProcessPanelMessage && !(e->flags & (ES_PANEL_Z_STACK | ES_PANEL_TABLE | ES_PANEL_SWITCHER));
|
|
bool alignHLeft = e ? (e->flags & ES_CELL_H_LEFT) : false, alignHRight = e ? (e->flags & ES_CELL_H_RIGHT) : false;
|
|
bool alignHExpand = e ? (e->flags & ES_CELL_H_EXPAND) : false, alignHShrink = e ? (e->flags & ES_CELL_H_SHRINK) : false;
|
|
bool alignHPush = e ? (e->flags & ES_CELL_H_PUSH) : false;
|
|
bool alignVTop = e ? (e->flags & ES_CELL_V_TOP) : false, alignVBottom = e ? (e->flags & ES_CELL_V_BOTTOM) : false;
|
|
bool alignVExpand = e ? (e->flags & ES_CELL_V_EXPAND) : false, alignVShrink = e ? (e->flags & ES_CELL_V_SHRINK) : false;
|
|
bool alignVPush = e ? (e->flags & ES_CELL_V_PUSH) : false;
|
|
bool stackHorizontal = isStack && (e->flags & ES_PANEL_HORIZONTAL);
|
|
bool stackReverse = isStack && (e->flags & ES_PANEL_REVERSE);
|
|
|
|
EsButtonSetCheck(inspector->alignH[0], (EsCheckState) (e && alignHLeft && !alignHRight), false);
|
|
EsButtonSetCheck(inspector->alignH[1], (EsCheckState) (e && alignHLeft == alignHRight), false);
|
|
EsButtonSetCheck(inspector->alignH[2], (EsCheckState) (e && !alignHLeft && alignHRight), false);
|
|
EsButtonSetCheck(inspector->alignH[3], (EsCheckState) (e && alignHExpand), false);
|
|
EsButtonSetCheck(inspector->alignH[4], (EsCheckState) (e && alignHShrink), false);
|
|
EsButtonSetCheck(inspector->alignH[5], (EsCheckState) (e && alignHPush), false);
|
|
|
|
EsButtonSetCheck(inspector->alignV[0], (EsCheckState) (e && alignVTop && !alignVBottom), false);
|
|
EsButtonSetCheck(inspector->alignV[1], (EsCheckState) (e && alignVTop == alignVBottom), false);
|
|
EsButtonSetCheck(inspector->alignV[2], (EsCheckState) (e && !alignVTop && alignVBottom), false);
|
|
EsButtonSetCheck(inspector->alignV[3], (EsCheckState) (e && alignVExpand), false);
|
|
EsButtonSetCheck(inspector->alignV[4], (EsCheckState) (e && alignVShrink), false);
|
|
EsButtonSetCheck(inspector->alignV[5], (EsCheckState) (e && alignVPush), false);
|
|
|
|
EsButtonSetCheck(inspector->direction[0], (EsCheckState) (isStack && stackHorizontal && stackReverse), false);
|
|
EsButtonSetCheck(inspector->direction[1], (EsCheckState) (isStack && stackHorizontal && !stackReverse), false);
|
|
EsButtonSetCheck(inspector->direction[2], (EsCheckState) (isStack && !stackHorizontal && stackReverse), false);
|
|
EsButtonSetCheck(inspector->direction[3], (EsCheckState) (isStack && !stackHorizontal && !stackReverse), false);
|
|
|
|
EsElementSetDisabled(inspector->alignH[0], !e);
|
|
EsElementSetDisabled(inspector->alignH[1], !e);
|
|
EsElementSetDisabled(inspector->alignH[2], !e);
|
|
EsElementSetDisabled(inspector->alignH[3], !e);
|
|
EsElementSetDisabled(inspector->alignH[4], !e);
|
|
EsElementSetDisabled(inspector->alignH[5], !e);
|
|
EsElementSetDisabled(inspector->alignV[0], !e);
|
|
EsElementSetDisabled(inspector->alignV[1], !e);
|
|
EsElementSetDisabled(inspector->alignV[2], !e);
|
|
EsElementSetDisabled(inspector->alignV[3], !e);
|
|
EsElementSetDisabled(inspector->alignV[4], !e);
|
|
EsElementSetDisabled(inspector->alignV[5], !e);
|
|
EsElementSetDisabled(inspector->direction[0], !isStack);
|
|
EsElementSetDisabled(inspector->direction[1], !isStack);
|
|
EsElementSetDisabled(inspector->direction[2], !isStack);
|
|
EsElementSetDisabled(inspector->direction[3], !isStack);
|
|
EsElementSetDisabled(inspector->addChildButton, !isStack);
|
|
EsElementSetDisabled(inspector->addSiblingButton, !e || !e->parent);
|
|
|
|
EsElementSetDisabled(inspector->textboxCategoryFilter, !e);
|
|
|
|
EsTextboxSelectAll(inspector->contentTextbox);
|
|
EsTextboxInsert(inspector->contentTextbox, "", 0, false);
|
|
|
|
if (e) {
|
|
#if 0
|
|
for (uintptr_t i = 0; i < sizeof(builtinStyles) / sizeof(builtinStyles[0]); i++) {
|
|
if (e->currentStyleKey.partHash == CalculateCRC64(EsLiteral(builtinStyles[i]))) {
|
|
EsTextboxInsert(inspector->styleTextbox, builtinStyles[i], -1, false);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (e->messageClass == ProcessButtonMessage) {
|
|
EsButton *button = (EsButton *) e;
|
|
EsElementSetDisabled(inspector->contentTextbox, false);
|
|
EsTextboxInsert(inspector->contentTextbox, button->label, button->labelBytes, false);
|
|
} else if (e->messageClass == ProcessTextDisplayMessage) {
|
|
EsTextDisplay *display = (EsTextDisplay *) e;
|
|
EsElementSetDisabled(inspector->contentTextbox, false);
|
|
EsTextboxInsert(inspector->contentTextbox, display->contents, display->textRuns[display->textRunCount].offset, false);
|
|
} else {
|
|
EsElementSetDisabled(inspector->contentTextbox, true);
|
|
}
|
|
} else {
|
|
EsElementSetDisabled(inspector->contentTextbox, true);
|
|
}
|
|
}
|
|
|
|
int InspectorElementListCallback(EsElement *element, EsMessage *message) {
|
|
InspectorWindow *inspector = (InspectorWindow *) element->instance;
|
|
|
|
if (message->type == ES_MSG_LIST_VIEW_GET_CONTENT) {
|
|
int column = message->getContent.columnID, index = message->getContent.index;
|
|
EsAssert(index >= 0 && index < (int) inspector->elements.Length());
|
|
InspectorElementEntry *entry = &inspector->elements[index];
|
|
|
|
if (column == 0) {
|
|
EsBufferFormat(message->getContent.buffer, "%z", entry->element->cName);
|
|
} else if (column == 1) {
|
|
EsBufferFormat(message->getContent.buffer, "%R", entry->element->GetWindowBounds(false));
|
|
} else if (column == 2) {
|
|
EsMessage m = *message;
|
|
m.type = ES_MSG_GET_INSPECTOR_INFORMATION;
|
|
EsMessageSend(entry->element, &m);
|
|
}
|
|
|
|
return ES_HANDLED;
|
|
} else if (message->type == ES_MSG_LIST_VIEW_GET_INDENT) {
|
|
message->getIndent.indent = inspector->elements[message->getIndent.index].depth;
|
|
return ES_HANDLED;
|
|
} else if (message->type == ES_MSG_LIST_VIEW_CREATE_ITEM) {
|
|
message->createItem.item->messageUser = InspectorElementItemCallback;
|
|
return ES_HANDLED;
|
|
} else if (message->type == ES_MSG_LIST_VIEW_SELECT) {
|
|
if (inspector->selectedElement != -1) {
|
|
inspector->elements[inspector->selectedElement].element->state &= ~UI_STATE_INSPECTING;
|
|
}
|
|
|
|
inspector->selectedElement = message->selectItem.isSelected ? message->selectItem.index : -1;
|
|
|
|
if (inspector->selectedElement != -1) {
|
|
EsElement *e = inspector->elements[inspector->selectedElement].element;
|
|
e->state |= UI_STATE_INSPECTING;
|
|
InspectorNotifyElementEvent(e, nullptr, "Viewing events from '%z'.\n", e->cName);
|
|
}
|
|
|
|
InspectorUpdateEditor(inspector);
|
|
return ES_HANDLED;
|
|
} else if (message->type == ES_MSG_LIST_VIEW_IS_SELECTED) {
|
|
message->selectItem.isSelected = message->selectItem.index == inspector->selectedElement;
|
|
return ES_HANDLED;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int InspectorContentTextboxCallback(EsElement *element, EsMessage *message) {
|
|
InspectorWindow *inspector = (InspectorWindow *) element->instance;
|
|
|
|
if (message->type == ES_MSG_TEXTBOX_EDIT_END) {
|
|
size_t newContentBytes;
|
|
char *newContent = EsTextboxGetContents(inspector->contentTextbox, &newContentBytes);
|
|
EsElement *e = inspector->elements[inspector->selectedElement].element;
|
|
|
|
if (e->messageClass == ProcessButtonMessage) {
|
|
EsButton *button = (EsButton *) e;
|
|
HeapDuplicate((void **) &button->label, &button->labelBytes, newContent, newContentBytes);
|
|
} else if (e->messageClass == ProcessTextDisplayMessage) {
|
|
EsTextDisplay *display = (EsTextDisplay *) e;
|
|
EsTextDisplaySetContents(display, newContent, newContentBytes);
|
|
} else {
|
|
EsAssert(false);
|
|
}
|
|
|
|
EsElementUpdateContentSize(e);
|
|
if (e->parent) EsElementUpdateContentSize(e->parent);
|
|
EsHeapFree(newContent);
|
|
return ES_HANDLED;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int InspectorTextboxCategoryFilterCallback(EsElement *element, EsMessage *message) {
|
|
InspectorWindow *inspector = (InspectorWindow *) element->instance;
|
|
|
|
if (message->type == ES_MSG_TEXTBOX_UPDATED) {
|
|
EsHeapFree(inspector->cCategoryFilter);
|
|
inspector->cCategoryFilter = EsTextboxGetContents((EsTextbox *) element);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
InspectorWindow *InspectorGet(EsElement *element) {
|
|
if (!element->window || !element->instance) return nullptr;
|
|
APIInstance *instance = (APIInstance *) element->instance->_private;
|
|
InspectorWindow *inspector = instance->attachedInspector;
|
|
if (!inspector || inspector->instance->window != element->window) return nullptr;
|
|
return inspector;
|
|
}
|
|
|
|
void InspectorNotifyElementEvent(EsElement *element, const char *cCategory, const char *cFormat, ...) {
|
|
if (~element->state & UI_STATE_INSPECTING) return;
|
|
InspectorWindow *inspector = InspectorGet(element);
|
|
if (!inspector) return;
|
|
if (inspector->cCategoryFilter && inspector->cCategoryFilter[0] && cCategory && EsCRTstrcmp(cCategory, inspector->cCategoryFilter)) return;
|
|
va_list arguments;
|
|
va_start(arguments, cFormat);
|
|
char _buffer[256];
|
|
EsBuffer buffer = { .out = (uint8_t *) _buffer, .bytes = sizeof(_buffer) };
|
|
if (cCategory) EsBufferFormat(&buffer, "%z: ", cCategory);
|
|
EsBufferFormatV(&buffer, cFormat, arguments);
|
|
va_end(arguments);
|
|
EsListViewIndex index = EsListViewFixedItemInsert(inspector->listEvents);
|
|
EsListViewFixedItemSetString(inspector->listEvents, index, 0, _buffer, buffer.position);
|
|
EsListViewScrollToEnd(inspector->listEvents);
|
|
}
|
|
|
|
void InspectorNotifyElementContentChanged(EsElement *element) {
|
|
InspectorWindow *inspector = InspectorGet(element);
|
|
if (!inspector) return;
|
|
|
|
for (uintptr_t i = 0; i < inspector->elements.Length(); i++) {
|
|
if (inspector->elements[i].element == element) {
|
|
EsListViewInvalidateContent(inspector->elementList, 0, i);
|
|
return;
|
|
}
|
|
}
|
|
|
|
EsAssert(false);
|
|
}
|
|
|
|
void InspectorNotifyElementMoved(EsElement *element, EsRectangle takenBounds) {
|
|
InspectorWindow *inspector = InspectorGet(element);
|
|
if (!inspector) return;
|
|
|
|
for (uintptr_t i = 0; i < inspector->elements.Length(); i++) {
|
|
if (inspector->elements[i].element == element) {
|
|
inspector->elements[i].takenBounds = takenBounds;
|
|
inspector->elements[i].givenBounds = takenBounds; // TODO.
|
|
EsListViewInvalidateContent(inspector->elementList, 0, i);
|
|
return;
|
|
}
|
|
}
|
|
|
|
EsAssert(false);
|
|
}
|
|
|
|
void InspectorNotifyElementDestroyed(EsElement *element) {
|
|
InspectorWindow *inspector = InspectorGet(element);
|
|
if (!inspector) return;
|
|
|
|
for (uintptr_t i = 0; i < inspector->elements.Length(); i++) {
|
|
if (inspector->elements[i].element == element) {
|
|
if (inspector->selectedElement == (intptr_t) i) {
|
|
inspector->selectedElement = -1;
|
|
InspectorUpdateEditor(inspector);
|
|
} else if (inspector->selectedElement > (intptr_t) i) {
|
|
inspector->selectedElement--;
|
|
}
|
|
|
|
EsListViewRemove(inspector->elementList, 0, i, 1);
|
|
inspector->elements.Delete(i);
|
|
return;
|
|
}
|
|
}
|
|
|
|
EsAssert(false);
|
|
}
|
|
|
|
void InspectorNotifyElementCreated(EsElement *element) {
|
|
InspectorWindow *inspector = InspectorGet(element);
|
|
if (!inspector) return;
|
|
|
|
ptrdiff_t indexInParent = -1;
|
|
|
|
for (uintptr_t i = 0; i < element->parent->children.Length(); i++) {
|
|
if (element->parent->children[i] == element) {
|
|
indexInParent = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
EsAssert(indexInParent != -1);
|
|
|
|
ptrdiff_t insertAfterIndex = -1;
|
|
|
|
for (uintptr_t i = 0; i < inspector->elements.Length(); i++) {
|
|
if (indexInParent == 0) {
|
|
if (inspector->elements[i].element == element->parent) {
|
|
insertAfterIndex = i;
|
|
break;
|
|
}
|
|
} else {
|
|
if (inspector->elements[i].element == element->parent->children[indexInParent - 1]) {
|
|
insertAfterIndex = i;
|
|
int baseDepth = inspector->elements[i++].depth;
|
|
|
|
for (; i < inspector->elements.Length(); i++) {
|
|
if (inspector->elements[i].depth > baseDepth) {
|
|
insertAfterIndex++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
EsAssert(insertAfterIndex != -1);
|
|
|
|
int depth = 0;
|
|
EsElement *ancestor = element->parent;
|
|
|
|
while (ancestor) {
|
|
depth++;
|
|
ancestor = ancestor->parent;
|
|
}
|
|
|
|
if (inspector->selectedElement > insertAfterIndex) {
|
|
inspector->selectedElement++;
|
|
}
|
|
|
|
InspectorElementEntry entry;
|
|
entry.element = element;
|
|
entry.depth = depth;
|
|
inspector->elements.Insert(entry, insertAfterIndex + 1);
|
|
EsListViewInsert(inspector->elementList, 0, insertAfterIndex + 1, 1);
|
|
}
|
|
|
|
void InspectorFindElementsRecursively(InspectorWindow *inspector, EsElement *element, int depth) {
|
|
InspectorElementEntry entry = {};
|
|
entry.element = element;
|
|
entry.depth = depth;
|
|
inspector->elements.Add(entry);
|
|
|
|
for (uintptr_t i = 0; i < element->children.Length(); i++) {
|
|
InspectorFindElementsRecursively(inspector, element->children[i], depth + 1);
|
|
}
|
|
}
|
|
|
|
void InspectorRefreshElementList(InspectorWindow *inspector) {
|
|
EsListViewRemoveAll(inspector->elementList, 0);
|
|
inspector->elements.Free();
|
|
InspectorFindElementsRecursively(inspector, inspector->instance->window, 0);
|
|
EsListViewInsert(inspector->elementList, 0, 0, inspector->elements.Length());
|
|
}
|
|
|
|
void InspectorNotifyElementPainted(EsElement *element, EsPainter *painter) {
|
|
InspectorWindow *inspector = InspectorGet(element);
|
|
if (!inspector) return;
|
|
|
|
InspectorElementEntry *entry = inspector->hoveredElement.element ? &inspector->hoveredElement : nullptr;
|
|
if (!entry) return;
|
|
|
|
EsRectangle bounds = ES_RECT_4(painter->offsetX, painter->offsetX + painter->width,
|
|
painter->offsetY, painter->offsetY + painter->height);
|
|
|
|
if (entry->element == element) {
|
|
EsDrawRectangle(painter, bounds, 0x607F7FFF, 0x60FFFF7F, element->style->insets);
|
|
} else if (entry->element->parent == element) {
|
|
if ((element->flags & ES_CELL_FILL) != ES_CELL_FILL) {
|
|
EsRectangle rectangle = entry->givenBounds;
|
|
rectangle.l += bounds.l, rectangle.r += bounds.l;
|
|
rectangle.t += bounds.t, rectangle.b += bounds.t;
|
|
// EsDrawBlock(painter, rectangle, 0x20FF7FFF);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define INSPECTOR_ALIGN_COMMAND(name, clear, set, toggle) \
|
|
void name (EsInstance *instance, EsElement *, EsCommand *) { \
|
|
InspectorWindow *inspector = (InspectorWindow *) instance; \
|
|
EsElement *e = inspector->elements[inspector->selectedElement].element; \
|
|
if (toggle) e->flags ^= set; \
|
|
else { e->flags &= ~(clear); e->flags |= set; } \
|
|
EsElementUpdateContentSize(e); \
|
|
if (e->parent) EsElementUpdateContentSize(e->parent); \
|
|
inspector->elementList->Repaint(true); \
|
|
InspectorUpdateEditor(inspector); \
|
|
}
|
|
|
|
INSPECTOR_ALIGN_COMMAND(InspectorHAlignLeft, ES_CELL_H_LEFT | ES_CELL_H_RIGHT, ES_CELL_H_LEFT, false);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorHAlignCenter, ES_CELL_H_LEFT | ES_CELL_H_RIGHT, ES_CELL_H_LEFT | ES_CELL_H_RIGHT, false);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorHAlignRight, ES_CELL_H_LEFT | ES_CELL_H_RIGHT, ES_CELL_H_RIGHT, false);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorHAlignExpand, 0, ES_CELL_H_EXPAND, true);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorHAlignShrink, 0, ES_CELL_H_SHRINK, true);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorHAlignPush, 0, ES_CELL_H_PUSH, true);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorVAlignTop, ES_CELL_V_TOP | ES_CELL_V_BOTTOM, ES_CELL_V_TOP, false);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorVAlignCenter, ES_CELL_V_TOP | ES_CELL_V_BOTTOM, ES_CELL_V_TOP | ES_CELL_V_BOTTOM, false);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorVAlignBottom, ES_CELL_V_TOP | ES_CELL_V_BOTTOM, ES_CELL_V_BOTTOM, false);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorVAlignExpand, 0, ES_CELL_V_EXPAND, true);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorVAlignShrink, 0, ES_CELL_V_SHRINK, true);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorVAlignPush, 0, ES_CELL_V_PUSH, true);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorDirectionLeft, ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE | ES_ELEMENT_LAYOUT_HINT_HORIZONTAL | ES_ELEMENT_LAYOUT_HINT_REVERSE,
|
|
ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE | ES_ELEMENT_LAYOUT_HINT_HORIZONTAL | ES_ELEMENT_LAYOUT_HINT_REVERSE, false);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorDirectionRight, ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE | ES_ELEMENT_LAYOUT_HINT_HORIZONTAL | ES_ELEMENT_LAYOUT_HINT_REVERSE,
|
|
ES_PANEL_HORIZONTAL | ES_ELEMENT_LAYOUT_HINT_HORIZONTAL, false);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorDirectionUp, ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE | ES_ELEMENT_LAYOUT_HINT_HORIZONTAL | ES_ELEMENT_LAYOUT_HINT_REVERSE,
|
|
ES_PANEL_REVERSE | ES_ELEMENT_LAYOUT_HINT_REVERSE, false);
|
|
INSPECTOR_ALIGN_COMMAND(InspectorDirectionDown, ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE | ES_ELEMENT_LAYOUT_HINT_HORIZONTAL | ES_ELEMENT_LAYOUT_HINT_REVERSE, 0, false);
|
|
|
|
void InspectorVisualizeRepaints(EsInstance *instance, EsElement *, EsCommand *) {
|
|
InspectorWindow *inspector = (InspectorWindow *) instance;
|
|
EsWindow *window = inspector->instance->window;
|
|
window->visualizeRepaints = !window->visualizeRepaints;
|
|
EsButtonSetCheck(inspector->visualizeRepaints, window->visualizeRepaints ? ES_CHECK_CHECKED : ES_CHECK_UNCHECKED, false);
|
|
}
|
|
|
|
void InspectorVisualizePaintSteps(EsInstance *instance, EsElement *, EsCommand *) {
|
|
InspectorWindow *inspector = (InspectorWindow *) instance;
|
|
EsWindow *window = inspector->instance->window;
|
|
window->visualizePaintSteps = !window->visualizePaintSteps;
|
|
EsButtonSetCheck(inspector->visualizePaintSteps, window->visualizePaintSteps ? ES_CHECK_CHECKED : ES_CHECK_UNCHECKED, false);
|
|
}
|
|
|
|
void InspectorVisualizeLayoutBounds(EsInstance *instance, EsElement *, EsCommand *) {
|
|
InspectorWindow *inspector = (InspectorWindow *) instance;
|
|
EsWindow *window = inspector->instance->window;
|
|
window->visualizeLayoutBounds = !window->visualizeLayoutBounds;
|
|
EsButtonSetCheck(inspector->visualizeLayoutBounds, window->visualizeLayoutBounds ? ES_CHECK_CHECKED : ES_CHECK_UNCHECKED, false);
|
|
EsElementRepaint(window);
|
|
}
|
|
|
|
void InspectorAddElement2(EsMenu *menu, EsGeneric context) {
|
|
InspectorWindow *inspector = (InspectorWindow *) menu->instance;
|
|
if (inspector->selectedElement == -1) return;
|
|
EsElement *e = inspector->elements[inspector->selectedElement].element;
|
|
int asSibling = context.u & 0x80;
|
|
context.u &= ~0x80;
|
|
|
|
if (asSibling) {
|
|
EsElementInsertAfter(e);
|
|
e = e->parent;
|
|
}
|
|
|
|
if (context.u == 1) {
|
|
EsButtonCreate(e);
|
|
} else if (context.u == 2) {
|
|
EsPanelCreate(e);
|
|
} else if (context.u == 3) {
|
|
EsSpacerCreate(e);
|
|
} else if (context.u == 4) {
|
|
EsTextboxCreate(e);
|
|
} else if (context.u == 5) {
|
|
EsTextDisplayCreate(e);
|
|
}
|
|
}
|
|
|
|
void InspectorAddElement(EsInstance *, EsElement *element, EsCommand *) {
|
|
EsMenu *menu = EsMenuCreate(element, ES_FLAGS_DEFAULT);
|
|
EsMenuAddItem(menu, 0, "Add button", -1, InspectorAddElement2, element->userData.u | 1);
|
|
EsMenuAddItem(menu, 0, "Add panel", -1, InspectorAddElement2, element->userData.u | 2);
|
|
EsMenuAddItem(menu, 0, "Add spacer", -1, InspectorAddElement2, element->userData.u | 3);
|
|
EsMenuAddItem(menu, 0, "Add textbox", -1, InspectorAddElement2, element->userData.u | 4);
|
|
EsMenuAddItem(menu, 0, "Add text display", -1, InspectorAddElement2, element->userData.u | 5);
|
|
EsMenuShow(menu);
|
|
}
|
|
|
|
void InspectorSetup(EsWindow *window) {
|
|
InspectorWindow *inspector = (InspectorWindow *) EsHeapAllocate(sizeof(InspectorWindow), true); // TODO Freeing this.
|
|
inspector->window = window;
|
|
InstanceSetup(inspector);
|
|
EsInstanceOpenReference(inspector);
|
|
|
|
inspector->instance = window->instance;
|
|
window->instance = inspector;
|
|
|
|
inspector->selectedElement = -1;
|
|
|
|
EsSplitter *splitter = EsSplitterCreate(window, ES_CELL_FILL | ES_SPLITTER_VERTICAL);
|
|
EsPanel *panel1 = EsPanelCreate(splitter, ES_CELL_FILL, ES_STYLE_PANEL_FILLED);
|
|
EsPanel *panel2 = EsPanelCreate(splitter, ES_CELL_FILL, ES_STYLE_PANEL_FILLED);
|
|
|
|
{
|
|
EsPanel *toolbar = EsPanelCreate(panel1, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_TOOLBAR);
|
|
inspector->visualizeRepaints = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR, 0, "Visualize repaints");
|
|
EsButtonOnCommand(inspector->visualizeRepaints, InspectorVisualizeRepaints);
|
|
inspector->visualizeLayoutBounds = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR, 0, "Visualize layout bounds");
|
|
EsButtonOnCommand(inspector->visualizeLayoutBounds, InspectorVisualizeLayoutBounds);
|
|
inspector->visualizePaintSteps = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR, 0, "Visualize paint steps");
|
|
EsButtonOnCommand(inspector->visualizePaintSteps, InspectorVisualizePaintSteps);
|
|
EsSpacerCreate(toolbar, ES_CELL_H_FILL);
|
|
}
|
|
|
|
inspector->elementList = EsListViewCreate(panel1, ES_CELL_FILL | ES_LIST_VIEW_COLUMNS | ES_LIST_VIEW_SINGLE_SELECT);
|
|
inspector->elementList->messageUser = InspectorElementListCallback;
|
|
EsListViewRegisterColumn(inspector->elementList, 0, "Name", -1, 0, 300);
|
|
EsListViewRegisterColumn(inspector->elementList, 1, "Bounds", -1, 0, 200);
|
|
EsListViewRegisterColumn(inspector->elementList, 2, "Information", -1, 0, 200);
|
|
EsListViewAddAllColumns(inspector->elementList);
|
|
EsListViewInsertGroup(inspector->elementList, 0);
|
|
|
|
{
|
|
EsPanel *toolbar = EsPanelCreate(panel1, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_TOOLBAR);
|
|
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 5, 0);
|
|
EsTextDisplayCreate(toolbar, ES_FLAGS_DEFAULT, 0, "Horizontal:");
|
|
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 5, 0);
|
|
inspector->alignH[0] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->alignH[0], ES_ICON_ALIGN_HORIZONTAL_LEFT);
|
|
EsButtonOnCommand(inspector->alignH[0], InspectorHAlignLeft);
|
|
inspector->alignH[1] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->alignH[1], ES_ICON_ALIGN_HORIZONTAL_CENTER);
|
|
EsButtonOnCommand(inspector->alignH[1], InspectorHAlignCenter);
|
|
inspector->alignH[2] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->alignH[2], ES_ICON_ALIGN_HORIZONTAL_RIGHT);
|
|
EsButtonOnCommand(inspector->alignH[2], InspectorHAlignRight);
|
|
inspector->alignH[3] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED, 0, "Expand");
|
|
EsButtonOnCommand(inspector->alignH[3], InspectorHAlignExpand);
|
|
inspector->alignH[4] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED, 0, "Shrink");
|
|
EsButtonOnCommand(inspector->alignH[4], InspectorHAlignShrink);
|
|
inspector->alignH[5] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED, 0, "Push");
|
|
EsButtonOnCommand(inspector->alignH[5], InspectorHAlignPush);
|
|
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 5, 0);
|
|
EsTextDisplayCreate(toolbar, ES_FLAGS_DEFAULT, 0, "Vertical:");
|
|
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 5, 0);
|
|
inspector->alignV[0] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->alignV[0], ES_ICON_ALIGN_VERTICAL_TOP);
|
|
EsButtonOnCommand(inspector->alignV[0], InspectorVAlignTop);
|
|
inspector->alignV[1] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->alignV[1], ES_ICON_ALIGN_VERTICAL_CENTER);
|
|
EsButtonOnCommand(inspector->alignV[1], InspectorVAlignCenter);
|
|
inspector->alignV[2] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->alignV[2], ES_ICON_ALIGN_VERTICAL_BOTTOM);
|
|
EsButtonOnCommand(inspector->alignV[2], InspectorVAlignBottom);
|
|
inspector->alignV[3] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED, 0, "Expand");
|
|
EsButtonOnCommand(inspector->alignV[3], InspectorVAlignExpand);
|
|
inspector->alignV[4] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED, 0, "Shrink");
|
|
EsButtonOnCommand(inspector->alignV[4], InspectorVAlignShrink);
|
|
inspector->alignV[5] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED, 0, "Push");
|
|
EsButtonOnCommand(inspector->alignV[5], InspectorVAlignPush);
|
|
}
|
|
|
|
{
|
|
EsPanel *toolbar = EsPanelCreate(panel1, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_TOOLBAR);
|
|
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 5, 0);
|
|
EsTextDisplayCreate(toolbar, ES_FLAGS_DEFAULT, 0, "Stack:");
|
|
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 5, 0);
|
|
inspector->direction[0] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->direction[0], ES_ICON_GO_PREVIOUS);
|
|
EsButtonOnCommand(inspector->direction[0], InspectorDirectionLeft);
|
|
inspector->direction[1] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->direction[1], ES_ICON_GO_NEXT);
|
|
EsButtonOnCommand(inspector->direction[1], InspectorDirectionRight);
|
|
inspector->direction[2] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->direction[2], ES_ICON_GO_UP);
|
|
EsButtonOnCommand(inspector->direction[2], InspectorDirectionUp);
|
|
inspector->direction[3] = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_DISABLED);
|
|
EsButtonSetIcon(inspector->direction[3], ES_ICON_GO_DOWN);
|
|
EsButtonOnCommand(inspector->direction[3], InspectorDirectionDown);
|
|
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 25, 0);
|
|
inspector->addChildButton = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_BUTTON_DROPDOWN | ES_ELEMENT_DISABLED | ES_BUTTON_COMPACT, 0, "Add child... ");
|
|
EsButtonOnCommand(inspector->addChildButton, InspectorAddElement);
|
|
inspector->addSiblingButton = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_BUTTON_DROPDOWN | ES_ELEMENT_DISABLED | ES_BUTTON_COMPACT, 0, "Add sibling... ");
|
|
inspector->addSiblingButton->userData.i = 0x80;
|
|
EsButtonOnCommand(inspector->addSiblingButton, InspectorAddElement);
|
|
}
|
|
|
|
{
|
|
EsPanel *toolbar = EsPanelCreate(panel1, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_TOOLBAR);
|
|
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 5, 0);
|
|
EsTextDisplayCreate(toolbar, ES_FLAGS_DEFAULT, 0, "Content:");
|
|
inspector->contentTextbox = EsTextboxCreate(toolbar, ES_ELEMENT_DISABLED | ES_TEXTBOX_EDIT_BASED);
|
|
inspector->contentTextbox->messageUser = InspectorContentTextboxCallback;
|
|
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 25, 0);
|
|
EsTextDisplayCreate(toolbar, ES_FLAGS_DEFAULT, 0, "Event category filter:");
|
|
inspector->textboxCategoryFilter = EsTextboxCreate(toolbar, ES_ELEMENT_DISABLED);
|
|
inspector->textboxCategoryFilter->messageUser = InspectorTextboxCategoryFilterCallback;
|
|
}
|
|
|
|
{
|
|
inspector->listEvents = EsListViewCreate(panel2, ES_CELL_FILL | ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
|
|
}
|
|
|
|
InspectorRefreshElementList(inspector);
|
|
|
|
APIInstance *instance = (APIInstance *) inspector->instance->_private;
|
|
instance->attachedInspector = inspector;
|
|
}
|