diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index 9ad7488..48a498a 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -740,7 +740,6 @@ int WindowTabMessage(EsElement *element, EsMessage *message) { instance->title, instance->titleBytes, instance->iconID); } else if (message->type == ES_MSG_ANIMATE) { message->animate.complete = ReorderItemAnimate(tab, message->animate.deltaMs, "windowTabEntranceDuration"); - } else if (message->type == ES_MSG_MOUSE_LEFT_DOWN) { } else if (message->type == ES_MSG_MOUSE_LEFT_DRAG) { EsElementSetDisabled(band->GetChild(0), true); @@ -847,6 +846,13 @@ int WindowTabMessage(EsElement *element, EsMessage *message) { EsMenuShow(menu); } else if (message->type == ES_MSG_MOUSE_MIDDLE_UP && ((element->state & UI_STATE_HOVERED) || (tab->closeButton->state & UI_STATE_HOVERED))) { + if (EsButtonGetCheck(tab->closeButton) == ES_CHECK_CHECKED) { + // The tab contains a modified document, so it will probably popup a dialog after it receives the close request. + // Therefore, we should switch to that tab. + tab->BringToFront(); + WindowTabActivate(tab); + } + WindowTabClose(tab); } else if (message->type == ES_MSG_REORDER_ITEM_TEST) { } else { diff --git a/res/Theme Source.dat b/res/Theme Source.dat index 4839f2c..7deafaa 100644 Binary files a/res/Theme Source.dat and b/res/Theme Source.dat differ diff --git a/res/Themes/Theme.dat b/res/Themes/Theme.dat index 1d4a958..1ec34d7 100644 Binary files a/res/Themes/Theme.dat and b/res/Themes/Theme.dat differ diff --git a/util/designer/designer.c b/util/designer/designer.c index 590c7d0..0b71755 100644 --- a/util/designer/designer.c +++ b/util/designer/designer.c @@ -1664,7 +1664,6 @@ enum ObjectType { OBJ_VAR_COLOR = 0x40, OBJ_VAR_INT, OBJ_VAR_TEXT_STYLE, - OBJ_VAR_ICON_STYLE, OBJ_VAR_CONTOUR_STYLE, OBJ_PAINT_OVERWRITE = 0x60, @@ -1724,7 +1723,7 @@ void ObjectAddObjectProperty(Object2 *object, const char *cName, uint64_t value) arrput(object->properties, property); } -uint64_t ExportPaint2(Paint *paint, int *x, int y, Object2 **objects, uint64_t *idAllocator) { +uint64_t ExportPaint2(Paint *paint, int *x, int y, Object2 **objects, uint64_t *idAllocator, Layer *layer) { char cPropertyName[PROPERTY_NAME_SIZE]; if (!paint->tag) { @@ -1768,6 +1767,67 @@ uint64_t ExportPaint2(Paint *paint, int *x, int y, Object2 **objects, uint64_t * *x += 100; arrput(*objects, object); + + if (layer) { + for (uintptr_t i = 0; i < arrlenu(layer->sequences); i++) { + Sequence *s = layer->sequences[i]; + assert(arrlenu(s->keyframes) == 1); + Keyframe *keyframe = s->keyframes[0]; + + uint32_t stateBits = 0; + if (s->flagFocused) stateBits |= THEME_STATE_FOCUSED; + if (s->flagChecked) stateBits |= THEME_STATE_CHECKED; + if (s->flagIndeterminate) stateBits |= THEME_STATE_INDETERMINATE; + if (s->flagDefault) stateBits |= THEME_STATE_DEFAULT_BUTTON; + if (s->flagItemFocus) stateBits |= THEME_STATE_FOCUSED_ITEM; + if (s->flagListFocus) stateBits |= THEME_STATE_LIST_FOCUSED; + if (s->flagBeforeEnter) stateBits |= THEME_STATE_BEFORE_ENTER; + if (s->flagAfterExit) stateBits |= THEME_STATE_AFTER_EXIT; + if (s->flagSelected) stateBits |= THEME_STATE_SELECTED; + + Object2 override = { .type = object.type, .id = ++(*idAllocator) }; + ObjectAddIntegerProperty(&override, "_graphX", *x); + ObjectAddIntegerProperty(&override, "_graphY", y); + ObjectAddIntegerProperty(&override, "_graphW", 80); + ObjectAddIntegerProperty(&override, "_graphH", 60); + ObjectAddObjectProperty(&override, "_parent", object.id); + ObjectAddIntegerProperty(&override, "_primaryState", s->primaryState); + ObjectAddIntegerProperty(&override, "_stateBits", stateBits); + ObjectAddIntegerProperty(&override, "_duration", s->duration); + + bool addObject = false; + + for (uintptr_t i = 0; i < arrlenu(keyframe->properties); i++) { + Property *property = &keyframe->properties[i]; + + if (layer->base.tag == LayerBase_box + 1 && property->path[0] == (uint32_t) -2 && property->path[1] == 8 + && property->path[2] == 0 && property->path[3] == 2 && property->path[4] == 2) { + assert(property->path[5] == 2 && property->path[7] == 0); + RfGrowableBuffer state = { 0 }; + state.s.op = RF_OP_LOAD; + state.s.access = RfReadGrowableBuffer; + state.data = property->data; + RfItem item = GradientStop_Type.fields[GradientStop_color].item; + uint32_t value; item.type->op(&state.s, &item, &value); + char cPropertyName[PROPERTY_NAME_SIZE]; + snprintf(cPropertyName, sizeof(cPropertyName), "stops_%d_color", property->path[6]); + ObjectAddObjectProperty(&override, cPropertyName, ColorLookupPointer(value)->object2ID); + addObject = true; + } else { + continue; + } + } + + if (addObject) { + arrput(*objects, override); + object.id = override.id; + *x += 100; + } else { + arrfree(override.properties); + } + } + } + return object.id; } else if (paint->tag == Paint_radialGradient + 1) { Object2 object = { .type = OBJ_PAINT_RADIAL_GRADIENT, .id = ++(*idAllocator) }; @@ -1805,6 +1865,63 @@ uint64_t ExportPaint2(Paint *paint, int *x, int y, Object2 **objects, uint64_t * ObjectAddObjectProperty(&object, "color", ColorLookupPointer(paint->overwrite.color)->object2ID); *x += 100; arrput(*objects, object); + + if (layer) { + for (uintptr_t i = 0; i < arrlenu(layer->sequences); i++) { + Sequence *s = layer->sequences[i]; + assert(arrlenu(s->keyframes) == 1); + Keyframe *keyframe = s->keyframes[0]; + + uint32_t stateBits = 0; + if (s->flagFocused) stateBits |= THEME_STATE_FOCUSED; + if (s->flagChecked) stateBits |= THEME_STATE_CHECKED; + if (s->flagIndeterminate) stateBits |= THEME_STATE_INDETERMINATE; + if (s->flagDefault) stateBits |= THEME_STATE_DEFAULT_BUTTON; + if (s->flagItemFocus) stateBits |= THEME_STATE_FOCUSED_ITEM; + if (s->flagListFocus) stateBits |= THEME_STATE_LIST_FOCUSED; + if (s->flagBeforeEnter) stateBits |= THEME_STATE_BEFORE_ENTER; + if (s->flagAfterExit) stateBits |= THEME_STATE_AFTER_EXIT; + if (s->flagSelected) stateBits |= THEME_STATE_SELECTED; + + Object2 override = { .type = object.type, .id = ++(*idAllocator) }; + ObjectAddIntegerProperty(&override, "_graphX", *x); + ObjectAddIntegerProperty(&override, "_graphY", y); + ObjectAddIntegerProperty(&override, "_graphW", 80); + ObjectAddIntegerProperty(&override, "_graphH", 60); + ObjectAddObjectProperty(&override, "_parent", object.id); + ObjectAddIntegerProperty(&override, "_primaryState", s->primaryState); + ObjectAddIntegerProperty(&override, "_stateBits", stateBits); + ObjectAddIntegerProperty(&override, "_duration", s->duration); + + bool addObject = false; + + for (uintptr_t i = 0; i < arrlenu(keyframe->properties); i++) { + Property *property = &keyframe->properties[i]; + + if (layer->base.tag == LayerBase_box + 1 && property->path[0] == (uint32_t) -2 && property->path[1] == 8 + && property->path[2] == 0 && property->path[3] == 2 && property->path[4] == 3) { + assert(property->path[5] == 0); + RfGrowableBuffer state = { 0 }; + state.s.op = RF_OP_LOAD; + state.s.access = RfReadGrowableBuffer; + state.data = property->data; + RfItem item = PaintOverwrite_Type.fields[PaintOverwrite_color].item; + uint32_t value; item.type->op(&state.s, &item, &value); + ObjectAddObjectProperty(&override, "color", ColorLookupPointer(value)->object2ID); + addObject = true; + } else { + continue; + } + } + + if (addObject) { + arrput(*objects, override); + object.id = override.id; + *x += 100; + } + } + } + return object.id; } else { assert(false); @@ -1837,10 +1954,137 @@ uint64_t ExportFillMode2(PathFillMode *fill, int *x, int y, Object2 **objects, u } } +void ExportProperty2(Layer *layer, Property *property, Object2 *override) { + bool unhandled = false; + + RfGrowableBuffer state = { 0 }; + state.s.op = RF_OP_LOAD; + state.s.access = RfReadGrowableBuffer; + state.data = property->data; + + if (property->path[0] == (uint32_t) -2 && property->path[1] == 8 && property->path[2] == 0) { + if (layer->base.tag == LayerBase_box + 1) { + if (property->path[3] == LayerBox_borders && property->path[4] == Rectangle8_l) { + RfItem item = Rectangle8_Type.fields[Rectangle8_l].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "borders0", value); + } else if (property->path[3] == LayerBox_borders && property->path[4] == Rectangle8_r) { + RfItem item = Rectangle8_Type.fields[Rectangle8_r].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "borders1", value); + } else if (property->path[3] == LayerBox_borders && property->path[4] == Rectangle8_t) { + RfItem item = Rectangle8_Type.fields[Rectangle8_t].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "borders2", value); + } else if (property->path[3] == LayerBox_borders && property->path[4] == Rectangle8_b) { + RfItem item = Rectangle8_Type.fields[Rectangle8_b].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "borders3", value); + } else if (property->path[3] == LayerBox_corners && property->path[4] == Corners8_tl) { + RfItem item = Corners8_Type.fields[Corners8_tl].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "corners0", value); + } else if (property->path[3] == LayerBox_corners && property->path[4] == Corners8_tr) { + RfItem item = Corners8_Type.fields[Corners8_tr].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "corners1", value); + } else if (property->path[3] == LayerBox_corners && property->path[4] == Corners8_bl) { + RfItem item = Corners8_Type.fields[Corners8_bl].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "corners2", value); + } else if (property->path[3] == LayerBox_corners && property->path[4] == Corners8_br) { + RfItem item = Corners8_Type.fields[Corners8_br].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "corners3", value); + } else if (property->path[3] == LayerBox_mainPaint && property->path[4] == Paint_solid && property->path[5] == PaintSolid_color) { + RfItem item = PaintSolid_Type.fields[PaintSolid_color].item; + uint32_t value; item.type->op(&state.s, &item, &value); + ObjectAddObjectProperty(override, "mainPaint", ColorLookupPointer(value)->object2ID); + } else if (property->path[3] == LayerBox_borderPaint && property->path[4] == Paint_solid && property->path[5] == PaintSolid_color) { + RfItem item = PaintSolid_Type.fields[PaintSolid_color].item; + uint32_t value; item.type->op(&state.s, &item, &value); + ObjectAddObjectProperty(override, "borderPaint", ColorLookupPointer(value)->object2ID); + } else if (property->path[3] == LayerBox_mainPaint && property->path[4] == Paint_overwrite && property->path[5] == PaintOverwrite_color) { + fprintf(stderr, "\t>>\n"); + } else { + unhandled = true; + } + } else if (layer->base.tag == LayerBase_metrics + 1) { + if (property->path[3] == LayerMetrics_textSize || property->path[3] == LayerMetrics_selectedText) { + // Ignore. + } else if (property->path[3] == LayerMetrics_textColor) { + RfItem item = LayerMetrics_Type.fields[LayerMetrics_textColor].item; + uint32_t value; item.type->op(&state.s, &item, &value); + ObjectAddObjectProperty(override, "textColor", ColorLookupPointer(value)->object2ID); + } else if (property->path[3] == LayerMetrics_iconColor) { + RfItem item = LayerMetrics_Type.fields[LayerMetrics_iconColor].item; + uint32_t value; item.type->op(&state.s, &item, &value); + ObjectAddObjectProperty(override, "iconColor", ColorLookupPointer(value)->object2ID); + } else { + unhandled = true; + } + } else if (layer->base.tag == LayerBase_path + 1) { + if (property->path[3] == LayerPath_alpha) { + RfItem item = LayerPath_Type.fields[LayerPath_alpha].item; + int16_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "alpha", value); + } else if (property->path[3] == LayerPath_fills && property->path[4] == 0 && property->path[5] == PathFill_paint + && property->path[6] == Paint_solid && property->path[7] == PaintSolid_color) { + RfItem item = PaintSolid_Type.fields[PaintSolid_color].item; + uint32_t value; item.type->op(&state.s, &item, &value); + ObjectAddObjectProperty(override, "fills_0_paint", ColorLookupPointer(value)->object2ID); + ObjectAddIntegerProperty(override, "fills_count", 1); + } else { + unhandled = true; + } + } else { + unhandled = true; + } + } else if (property->path[0] == (uint32_t) -2 && property->path[1] == 5) { + if (layer->base.tag == LayerBase_box + 1) { + if (property->path[2] == Rectangle8_l) { + RfItem item = Rectangle8_Type.fields[Rectangle8_l].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "offset0", value - layer->offset.l); + } else if (property->path[2] == Rectangle8_r) { + RfItem item = Rectangle8_Type.fields[Rectangle8_r].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "offset1", value - layer->offset.r); + } else if (property->path[2] == Rectangle8_t) { + RfItem item = Rectangle8_Type.fields[Rectangle8_t].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "offset2", value - layer->offset.t); + } else if (property->path[2] == Rectangle8_b) { + RfItem item = Rectangle8_Type.fields[Rectangle8_b].item; + int8_t value; item.type->op(&state.s, &item, &value); + ObjectAddIntegerProperty(override, "offset3", value - layer->offset.b); + } + } else { + unhandled = true; + } + } else { + unhandled = true; + } + + assert(!unhandled); + +#if 0 + if (unhandled) { + fprintf(stderr, "\tunhandled on %s: ", LayerBase_Type.fields[layer->base.tag - 1].cName); + + for (uintptr_t i = 0; property->path[i] != RF_PATH_TERMINATOR; i++) { + fprintf(stderr, "%d, ", property->path[i]); + } + + fprintf(stderr, "\n"); + } +#endif +} + void ActionExportDesigner2(void *cp) { - // TODO Exporting sequences. // TODO Inherited text styles. // TODO Merging identical layers and styles. + // TODO Auto-name override layers. Object2 *objects = NULL; uint64_t objectIDAllocator = 0; @@ -1896,12 +2140,12 @@ void ActionExportDesigner2(void *cp) { Style *style = styleSet.styles[i]; Object2 layerGroup = { .type = OBJ_LAYER_GROUP, .id = ++objectIDAllocator }; - Object2 metrics = { 0 }, textStyle = { 0 }, iconStyle = { 0 }; + Object2 metrics = { 0 }, textStyle = { 0 }; int32_t layerCount = 0; for (uintptr_t i = 0; i < arrlenu(style->layers); i++) { Layer *layer = LayerLookup(style->layers[i]); - bool addToLayerGroup = false, addToObjects = false; + bool addToLayerGroup = false; Object2 object = { 0 }; if (layer->base.tag == LayerBase_box + 1) { @@ -1919,16 +2163,14 @@ void ActionExportDesigner2(void *cp) { ObjectAddIntegerProperty(&object, "autoCorners", box->autoCorners); ObjectAddIntegerProperty(&object, "autoBorders", box->autoBorders); ObjectAddIntegerProperty(&object, "shadowHiding", box->shadowHiding); - ObjectAddObjectProperty(&object, "mainPaint", ExportPaint2(&box->mainPaint, &x, y, &objects, &objectIDAllocator)); - ObjectAddObjectProperty(&object, "borderPaint", ExportPaint2(&box->borderPaint, &x, y, &objects, &objectIDAllocator)); + ObjectAddObjectProperty(&object, "mainPaint", ExportPaint2(&box->mainPaint, &x, y, &objects, &objectIDAllocator, layer)); + ObjectAddObjectProperty(&object, "borderPaint", ExportPaint2(&box->borderPaint, &x, y, &objects, &objectIDAllocator, NULL)); addToLayerGroup = true; - addToObjects = true; } else if (layer->base.tag == LayerBase_text + 1) { object.type = OBJ_LAYER_TEXT, object.id = ++objectIDAllocator; ObjectAddObjectProperty(&object, "color", ColorLookupPointer(layer->base.text.color)->object2ID); ObjectAddIntegerProperty(&object, "blur", layer->base.text.blur); addToLayerGroup = true; - addToObjects = true; } else if (layer->base.tag == LayerBase_path + 1) { object.type = OBJ_LAYER_PATH, object.id = ++objectIDAllocator; LayerPath *path = &layer->base.path; @@ -1955,72 +2197,138 @@ void ActionExportDesigner2(void *cp) { for (uintptr_t i = 0; i < arrlenu(path->fills); i++) { sprintf(cPropertyName, "fills_%d_paint", (int) i); - ObjectAddObjectProperty(&object, cPropertyName, ExportPaint2(&path->fills[i].paint, &x, y, &objects, &objectIDAllocator)); + ObjectAddObjectProperty(&object, cPropertyName, ExportPaint2(&path->fills[i].paint, &x, y, &objects, &objectIDAllocator, NULL)); sprintf(cPropertyName, "fills_%d_mode", (int) i); ObjectAddObjectProperty(&object, cPropertyName, ExportFillMode2(&path->fills[i].mode, &x, y, &objects, &objectIDAllocator)); } addToLayerGroup = true; - addToObjects = true; - } else { - object.type = OBJ_LAYER_METRICS, object.id = ++objectIDAllocator; + } else if (layer->base.tag == LayerBase_metrics + 1) { LayerMetrics *m = &layer->base.metrics; - ObjectAddIntegerProperty(&object, "clipEnabled", m->clipEnabled); - ObjectAddIntegerProperty(&object, "wrapText", m->wrapText); - ObjectAddIntegerProperty(&object, "ellipsis", m->ellipsis); - ObjectAddIntegerProperty(&object, "insets0", m->insets.l); - ObjectAddIntegerProperty(&object, "insets1", m->insets.r); - ObjectAddIntegerProperty(&object, "insets2", m->insets.t); - ObjectAddIntegerProperty(&object, "insets3", m->insets.b); - ObjectAddIntegerProperty(&object, "clipInsets0", m->clipInsets.l); - ObjectAddIntegerProperty(&object, "clipInsets1", m->clipInsets.r); - ObjectAddIntegerProperty(&object, "clipInsets2", m->clipInsets.t); - ObjectAddIntegerProperty(&object, "clipInsets3", m->clipInsets.b); - ObjectAddIntegerProperty(&object, "preferredWidth", m->preferredSize.width); - ObjectAddIntegerProperty(&object, "preferredHeight", m->preferredSize.height); - ObjectAddIntegerProperty(&object, "minimumWidth", m->minimumSize.width); - ObjectAddIntegerProperty(&object, "minimumHeight", m->minimumSize.height); - ObjectAddIntegerProperty(&object, "maximumWidth", m->maximumSize.width); - ObjectAddIntegerProperty(&object, "maximumHeight", m->maximumSize.height); - ObjectAddIntegerProperty(&object, "gapMajor", m->gaps.major); - ObjectAddIntegerProperty(&object, "gapMinor", m->gaps.minor); - ObjectAddIntegerProperty(&object, "gapWrap", m->gaps.wrap); - ObjectAddIntegerProperty(&object, "cursor", m->cursor); - ObjectAddIntegerProperty(&object, "horizontalTextAlign", m->textHorizontalAlign + 1); - ObjectAddIntegerProperty(&object, "verticalTextAlign", m->textVerticalAlign + 1); assert(!m->globalOffset.l && !m->globalOffset.r && !m->globalOffset.t && !m->globalOffset.b); - addToObjects = true; - metrics = object; - textStyle.type = OBJ_VAR_TEXT_STYLE, textStyle.id = ++objectIDAllocator; - ObjectAddIntegerProperty(&textStyle, "_graphX", x); - ObjectAddIntegerProperty(&textStyle, "_graphY", y); - ObjectAddIntegerProperty(&textStyle, "_graphW", 80); - ObjectAddIntegerProperty(&textStyle, "_graphH", 60); - ObjectAddObjectProperty(&textStyle, "textColor", ColorLookupPointer(m->textColor)->object2ID); - ObjectAddObjectProperty(&textStyle, "selectedBackground", ColorLookupPointer(m->selectedBackground)->object2ID); - ObjectAddObjectProperty(&textStyle, "selectedText", ColorLookupPointer(m->selectedText)->object2ID); - ObjectAddIntegerProperty(&textStyle, "textSize", m->textSize); - ObjectAddIntegerProperty(&textStyle, "fontWeight", m->fontWeight); - ObjectAddIntegerProperty(&textStyle, "isItalic", m->italic); - ObjectAddIntegerProperty(&textStyle, "fontFamily", m->fontFamily == FONT_FAMILY_MONO ? 0xFFFD : 0xFFFF); - arrput(objects, textStyle); - x += 100; + object.type = OBJ_VAR_TEXT_STYLE, object.id = ++objectIDAllocator; + ObjectAddObjectProperty(&object, "textColor", ColorLookupPointer(m->textColor)->object2ID); + ObjectAddObjectProperty(&object, "selectedBackground", ColorLookupPointer(m->selectedBackground)->object2ID); + ObjectAddObjectProperty(&object, "selectedText", ColorLookupPointer(m->selectedText)->object2ID); + ObjectAddIntegerProperty(&object, "textSize", m->textSize); + ObjectAddIntegerProperty(&object, "fontWeight", m->fontWeight); + ObjectAddIntegerProperty(&object, "isItalic", m->italic); + ObjectAddIntegerProperty(&object, "fontFamily", m->fontFamily == FONT_FAMILY_MONO ? 0xFFFD : 0xFFFF); + ObjectAddIntegerProperty(&object, "iconSize", m->iconSize); + ObjectAddObjectProperty(&object, "iconColor", ColorLookupPointer(m->iconColor)->object2ID); + textStyle = object; - iconStyle.type = OBJ_VAR_ICON_STYLE, iconStyle.id = ++objectIDAllocator; - ObjectAddIntegerProperty(&iconStyle, "_graphX", x); - ObjectAddIntegerProperty(&iconStyle, "_graphY", y); - ObjectAddIntegerProperty(&iconStyle, "_graphW", 80); - ObjectAddIntegerProperty(&iconStyle, "_graphH", 60); - ObjectAddIntegerProperty(&iconStyle, "iconSize", m->iconSize); - ObjectAddObjectProperty(&iconStyle, "iconColor", ColorLookupPointer(m->iconColor)->object2ID); - arrput(objects, iconStyle); + metrics.type = OBJ_LAYER_METRICS, metrics.id = ++objectIDAllocator; + ObjectAddIntegerProperty(&metrics, "clipEnabled", m->clipEnabled); + ObjectAddIntegerProperty(&metrics, "wrapText", m->wrapText); + ObjectAddIntegerProperty(&metrics, "ellipsis", m->ellipsis); + ObjectAddIntegerProperty(&metrics, "insets0", m->insets.l); + ObjectAddIntegerProperty(&metrics, "insets1", m->insets.r); + ObjectAddIntegerProperty(&metrics, "insets2", m->insets.t); + ObjectAddIntegerProperty(&metrics, "insets3", m->insets.b); + ObjectAddIntegerProperty(&metrics, "clipInsets0", m->clipInsets.l); + ObjectAddIntegerProperty(&metrics, "clipInsets1", m->clipInsets.r); + ObjectAddIntegerProperty(&metrics, "clipInsets2", m->clipInsets.t); + ObjectAddIntegerProperty(&metrics, "clipInsets3", m->clipInsets.b); + ObjectAddIntegerProperty(&metrics, "preferredWidth", m->preferredSize.width); + ObjectAddIntegerProperty(&metrics, "preferredHeight", m->preferredSize.height); + ObjectAddIntegerProperty(&metrics, "minimumWidth", m->minimumSize.width); + ObjectAddIntegerProperty(&metrics, "minimumHeight", m->minimumSize.height); + ObjectAddIntegerProperty(&metrics, "maximumWidth", m->maximumSize.width); + ObjectAddIntegerProperty(&metrics, "maximumHeight", m->maximumSize.height); + ObjectAddIntegerProperty(&metrics, "gapMajor", m->gaps.major); + ObjectAddIntegerProperty(&metrics, "gapMinor", m->gaps.minor); + ObjectAddIntegerProperty(&metrics, "gapWrap", m->gaps.wrap); + ObjectAddIntegerProperty(&metrics, "cursor", m->cursor); + ObjectAddIntegerProperty(&metrics, "horizontalTextAlign", m->textHorizontalAlign + 1); + ObjectAddIntegerProperty(&metrics, "verticalTextAlign", m->textVerticalAlign + 1); + ObjectAddIntegerProperty(&metrics, "_graphX", x); + ObjectAddIntegerProperty(&metrics, "_graphY", y); + ObjectAddIntegerProperty(&metrics, "_graphW", 80); + ObjectAddIntegerProperty(&metrics, "_graphH", 60); + arrput(objects, metrics); x += 100; + } else { + assert(false); } + ObjectAddIntegerProperty(&object, "_graphX", x); + ObjectAddIntegerProperty(&object, "_graphY", y); + ObjectAddIntegerProperty(&object, "_graphW", 80); + ObjectAddIntegerProperty(&object, "_graphH", 60); + arrput(objects, object); + x += 100; + + uint64_t previousOverrideID = object.id; + + for (uintptr_t i = 0; i < arrlenu(layer->sequences); i++) { + Sequence *s = layer->sequences[i]; + assert(arrlenu(s->keyframes) == 1); + Keyframe *keyframe = s->keyframes[0]; + + char buffer[256]; + snprintf(buffer, sizeof(buffer), "%s%s%s%s%s%s%s%s%s%s", + ((StringOption *) PrimaryState_Type.fields[s->primaryState].item.options)->string, + s->flagFocused ? " (focused)" : "", + s->flagChecked ? " (checked)" : "", + s->flagIndeterminate ? " (indeterminate)" : "", + s->flagDefault ? " (default)" : "", + s->flagItemFocus ? " (list item focus)" : "", + s->flagListFocus ? " (list focus)" : "", + s->flagBeforeEnter ? " (before enter)" : "", + s->flagAfterExit ? " (after exit)" : "", + s->flagSelected ? " (selected)" : ""); + fprintf(stderr, "%.*s:%.*s:%s:%d\n", (int) style->name.byteCount, (char *) style->name.buffer, + (int) layer->name.byteCount, (char *) layer->name.buffer, buffer, s->duration); + + uint32_t stateBits = 0; + if (s->flagFocused) stateBits |= THEME_STATE_FOCUSED; + if (s->flagChecked) stateBits |= THEME_STATE_CHECKED; + if (s->flagIndeterminate) stateBits |= THEME_STATE_INDETERMINATE; + if (s->flagDefault) stateBits |= THEME_STATE_DEFAULT_BUTTON; + if (s->flagItemFocus) stateBits |= THEME_STATE_FOCUSED_ITEM; + if (s->flagListFocus) stateBits |= THEME_STATE_LIST_FOCUSED; + if (s->flagBeforeEnter) stateBits |= THEME_STATE_BEFORE_ENTER; + if (s->flagAfterExit) stateBits |= THEME_STATE_AFTER_EXIT; + if (s->flagSelected) stateBits |= THEME_STATE_SELECTED; + + Object2 override = { .type = object.type, .id = ++objectIDAllocator }; + ObjectAddIntegerProperty(&override, "_graphX", x); + ObjectAddIntegerProperty(&override, "_graphY", y); + ObjectAddIntegerProperty(&override, "_graphW", 80); + ObjectAddIntegerProperty(&override, "_graphH", 60); + ObjectAddObjectProperty(&override, "_parent", previousOverrideID); + ObjectAddIntegerProperty(&override, "_primaryState", s->primaryState); + ObjectAddIntegerProperty(&override, "_stateBits", stateBits); + ObjectAddIntegerProperty(&override, "_duration", s->duration); + + bool addObject = false; + + for (uintptr_t i = 0; i < arrlenu(keyframe->properties); i++) { + Property *property = &keyframe->properties[i]; + + if (layer->base.tag == LayerBase_box + 1 && property->path[0] == (uint32_t) -2 && property->path[1] == 8 && property->path[2] == 0 + && property->path[3] == 2 && (property->path[4] == 2 || property->path[4] == 3)) { + continue; + } + + ExportProperty2(layer, property, &override); + addObject = true; + } + + if (addObject) { + arrput(objects, override); + previousOverrideID = override.id; + x += 100; + } else { + arrfree(override.properties); + } + } + if (addToLayerGroup) { sprintf(cPropertyName, "layers_%d_layer", layerCount); - ObjectAddObjectProperty(&layerGroup, cPropertyName, object.id); + ObjectAddObjectProperty(&layerGroup, cPropertyName, previousOverrideID); sprintf(cPropertyName, "layers_%d_offset0", layerCount); ObjectAddIntegerProperty(&layerGroup, cPropertyName, layer->offset.l); sprintf(cPropertyName, "layers_%d_offset1", layerCount); @@ -2041,15 +2349,6 @@ void ActionExportDesigner2(void *cp) { ObjectAddIntegerProperty(&layerGroup, cPropertyName, layer->mode); layerCount++; } - - if (addToObjects) { - ObjectAddIntegerProperty(&object, "_graphX", x); - ObjectAddIntegerProperty(&object, "_graphY", y); - ObjectAddIntegerProperty(&object, "_graphW", 80); - ObjectAddIntegerProperty(&object, "_graphH", 60); - arrput(objects, object); - x += 100; - } } { @@ -2074,7 +2373,6 @@ void ActionExportDesigner2(void *cp) { ObjectAddObjectProperty(&object, "appearance", layerGroup.id); ObjectAddObjectProperty(&object, "metrics", metrics.id); ObjectAddObjectProperty(&object, "textStyle", textStyle.id); - ObjectAddObjectProperty(&object, "iconStyle", iconStyle.id); arrput(objects, object); x += 100; } diff --git a/util/designer2.cpp b/util/designer2.cpp index 9da21c2..c99dcab 100644 --- a/util/designer2.cpp +++ b/util/designer2.cpp @@ -16,12 +16,13 @@ // x86_64-w64-mingw32-gcc -O3 -o bin/designer2.exe -D UI_WINDOWS util/designer2.cpp -DUNICODE -lgdi32 -luser32 -lkernel32 -Wl,--subsystem,windows -fno-exceptions -fno-rtti // TODO Needed to replace the old designer: -// Import and reorganize old theming data. +// Import old theming data. // Export. // Prototyping display: previewing state transitions. // TODO Additional features: -// Scrollbars? +// In a conditional layer, properties from conditional linked objects (such as a gradient paint) should show if their conditions match. +// Scrollbars on the canvas? // Icons for different object types (especially color overwrite objects). // Fix moving/resizing objects when zoomed in. // Path layers: dashed contours. @@ -35,6 +36,9 @@ // Get text rendering on non-Essence platforms. // Proper bezier path editor. // Path boolean operations. +// Timeline editor for applying a given state change, with rows for possibly many different layers. + +// TODO Reorganize old theming data! ////////////////////////////////////////////////////////////// @@ -271,7 +275,6 @@ enum ObjectType : uint8_t { OBJ_VAR_COLOR = 0x40, OBJ_VAR_INT, OBJ_VAR_TEXT_STYLE, - OBJ_VAR_ICON_STYLE, OBJ_VAR_CONTOUR_STYLE, OBJ_PAINT_OVERWRITE = 0x60, @@ -409,11 +412,11 @@ bool ObjectMatchesPreviewState(Object *object) { && ((stateBits & canvas->previewStateBits) == stateBits); } -Property *PropertyFindOrInherit(bool first, Object *object, const char *cName, uint8_t type = 0) { +Property *PropertyFindOrInherit(Object *object, const char *cName, uint8_t type = 0) { uintptr_t depth = 0; while (object && (depth++ < 100)) { - if (first || !ObjectIsConditional(object) || (canvas->previewStateActive && ObjectMatchesPreviewState(object))) { + if (!ObjectIsConditional(object) || (canvas->previewStateActive && ObjectMatchesPreviewState(object))) { // Return the value if the object has this property. Property *property = PropertyFind(object, cName); if (property) return type && property->type != type ? nullptr : property; @@ -424,24 +427,23 @@ Property *PropertyFindOrInherit(bool first, Object *object, const char *cName, u // Go to the inheritance parent object. Property *property = PropertyFind(object, "_parent", PROP_OBJECT); object = ObjectFind(property ? property->object : 0); - first = false; } return nullptr; } -int32_t PropertyFindOrInheritReadInt32(bool first, Object *object, const char *cName, int32_t defaultValue = 0) { - Property *property = PropertyFindOrInherit(first, object, cName, PROP_INT); +int32_t PropertyFindOrInheritReadInt32(Object *object, const char *cName, int32_t defaultValue = 0) { + Property *property = PropertyFindOrInherit(object, cName, PROP_INT); return property ? property->integer : defaultValue; } -float PropertyFindOrInheritReadFloat(bool first, Object *object, const char *cName, float defaultValue = 0) { - Property *property = PropertyFindOrInherit(first, object, cName, PROP_FLOAT); +float PropertyFindOrInheritReadFloat(Object *object, const char *cName, float defaultValue = 0) { + Property *property = PropertyFindOrInherit(object, cName, PROP_FLOAT); return property ? property->floating : defaultValue; } -Object *PropertyFindOrInheritReadObject(bool first, Object *object, const char *cName) { - Property *property = PropertyFindOrInherit(first, object, cName, PROP_OBJECT); +Object *PropertyFindOrInheritReadObject(Object *object, const char *cName) { + Property *property = PropertyFindOrInherit(object, cName, PROP_OBJECT); return property ? ObjectFind(property->object) : nullptr; } @@ -1372,7 +1374,7 @@ void InspectorPopulate() { UIButtonCreate(0, UI_BUTTON_SMALL, "Rename", -1)->invoke = InspectorRenameObject; UIParentPop(); - bool inheritWithAnimation = object->type == OBJ_VAR_TEXT_STYLE || object->type == OBJ_VAR_ICON_STYLE + bool inheritWithAnimation = object->type == OBJ_VAR_TEXT_STYLE || object->type == OBJ_LAYER_BOX || object->type == OBJ_LAYER_TEXT || object->type == OBJ_LAYER_PATH || object->type == OBJ_PAINT_OVERWRITE || object->type == OBJ_PAINT_LINEAR_GRADIENT || object->type == OBJ_PAINT_RADIAL_GRADIENT || object->type == OBJ_VAR_CONTOUR_STYLE; @@ -1421,7 +1423,6 @@ void InspectorPopulate() { InspectorAddLink(object, "Appearance:", "appearance"); InspectorAddLink(object, "Metrics:", "metrics"); InspectorAddLink(object, "Text style:", "textStyle"); - InspectorAddLink(object, "Icon style:", "iconStyle"); InspectorAddBooleanToggle(object, "Public style", "isPublic"); } else if (object->type == OBJ_VAR_COLOR) { InspectorBind(&UIColorPickerCreate(&UIPanelCreate(0, 0)->e, UI_COLOR_PICKER_HAS_OPACITY)->e, object->id, "color", INSPECTOR_COLOR_PICKER); @@ -1504,7 +1505,7 @@ void InspectorPopulate() { InspectorAddRadioSwitch(object, "Monospaced", "fontFamily", ES_FONT_MONOSPACED); InspectorBind(&UIButtonCreate(0, UI_BUTTON_SMALL, "X", 1)->e, object->id, "fontFamily", INSPECTOR_REMOVE_BUTTON); UIParentPop(); - } else if (object->type == OBJ_VAR_ICON_STYLE) { + InspectorAddLink(object, "Icon color:", "iconColor"); InspectorAddInteger(object, "Icon size:", "iconSize"); } else if (object->type == OBJ_VAR_CONTOUR_STYLE) { @@ -1833,14 +1834,11 @@ uint32_t GraphGetColorFromProperty(Property *property) { void ExportGradientStopArray(Object *object, EsBuffer *data, size_t stopCount) { for (uintptr_t i = 0; i < stopCount; i++) { char cPropertyName[PROPERTY_NAME_SIZE]; - sprintf(cPropertyName, "stops_%d_color", (int32_t) i); - Property *color = PropertyFind(object, cPropertyName, PROP_OBJECT); - sprintf(cPropertyName, "stops_%d_position", (int32_t) i); - Property *position = PropertyFind(object, cPropertyName, PROP_OBJECT); - ThemeGradientStop stop = {}; - stop.color = GraphGetColor(ObjectFind(color ? color->object : 0)); - stop.position = GraphGetIntegerFromProperty(position); + sprintf(cPropertyName, "stops_%d_color", (int32_t) i); + stop.color = GraphGetColor(PropertyFindOrInheritReadObject(object, cPropertyName)); + sprintf(cPropertyName, "stops_%d_position", (int32_t) i); + stop.position = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, cPropertyName, PROP_INT)); EsBufferWrite(data, &stop, sizeof(stop)); } } @@ -1859,18 +1857,18 @@ int8_t ExportPaint(Object *object, EsBuffer *data, int depth = 0) { return THEME_PAINT_SOLID; } else if (object->type == OBJ_PAINT_OVERWRITE) { - ExportPaint(PropertyFindOrInheritReadObject(false, object, "color"), data, depth + 1); + ExportPaint(PropertyFindOrInheritReadObject(object, "color"), data, depth + 1); return THEME_PAINT_OVERWRITE; } else if (object->type == OBJ_PAINT_LINEAR_GRADIENT) { if (data) { ThemePaintLinearGradient paint = {}; - paint.transform[0] = PropertyFindOrInheritReadFloat(false, object, "transformX"); - paint.transform[1] = PropertyFindOrInheritReadFloat(false, object, "transformY"); - paint.transform[2] = PropertyFindOrInheritReadFloat(false, object, "transformStart"); - paint.stopCount = PropertyFindOrInheritReadInt32(false, object, "stops_count"); - paint.useGammaInterpolation = !!PropertyFindOrInheritReadInt32(false, object, "useGammaInterpolation"); - paint.useSystemColor = !!PropertyFindOrInheritReadInt32(false, object, "useSystemColor"); - paint.repeatMode = PropertyFindOrInheritReadInt32(false, object, "repeatMode"); + paint.transform[0] = PropertyFindOrInheritReadFloat(object, "transformX"); + paint.transform[1] = PropertyFindOrInheritReadFloat(object, "transformY"); + paint.transform[2] = PropertyFindOrInheritReadFloat(object, "transformStart"); + paint.stopCount = PropertyFindOrInheritReadInt32(object, "stops_count"); + paint.useGammaInterpolation = !!PropertyFindOrInheritReadInt32(object, "useGammaInterpolation"); + paint.useSystemColor = !!PropertyFindOrInheritReadInt32(object, "useSystemColor"); + paint.repeatMode = PropertyFindOrInheritReadInt32(object, "repeatMode"); EsBufferWrite(data, &paint, sizeof(paint)); ExportGradientStopArray(object, data, paint.stopCount); } @@ -1879,15 +1877,15 @@ int8_t ExportPaint(Object *object, EsBuffer *data, int depth = 0) { } else if (object->type == OBJ_PAINT_RADIAL_GRADIENT) { if (data) { ThemePaintRadialGradient paint = {}; - paint.transform[0] = PropertyFindOrInheritReadFloat(false, object, "transform0"); - paint.transform[1] = PropertyFindOrInheritReadFloat(false, object, "transform1"); - paint.transform[2] = PropertyFindOrInheritReadFloat(false, object, "transform2"); - paint.transform[3] = PropertyFindOrInheritReadFloat(false, object, "transform3"); - paint.transform[4] = PropertyFindOrInheritReadFloat(false, object, "transform4"); - paint.transform[5] = PropertyFindOrInheritReadFloat(false, object, "transform5"); - paint.stopCount = PropertyFindOrInheritReadInt32(false, object, "stops_count"); - paint.useGammaInterpolation = !!PropertyFindOrInheritReadInt32(false, object, "useGammaInterpolation"); - paint.repeatMode = PropertyFindOrInheritReadInt32(false, object, "repeatMode"); + paint.transform[0] = PropertyFindOrInheritReadFloat(object, "transform0"); + paint.transform[1] = PropertyFindOrInheritReadFloat(object, "transform1"); + paint.transform[2] = PropertyFindOrInheritReadFloat(object, "transform2"); + paint.transform[3] = PropertyFindOrInheritReadFloat(object, "transform3"); + paint.transform[4] = PropertyFindOrInheritReadFloat(object, "transform4"); + paint.transform[5] = PropertyFindOrInheritReadFloat(object, "transform5"); + paint.stopCount = PropertyFindOrInheritReadInt32(object, "stops_count"); + paint.useGammaInterpolation = !!PropertyFindOrInheritReadInt32(object, "useGammaInterpolation"); + paint.repeatMode = PropertyFindOrInheritReadInt32(object, "repeatMode"); EsBufferWrite(data, &paint, sizeof(paint)); ExportGradientStopArray(object, data, paint.stopCount); } @@ -1898,37 +1896,37 @@ int8_t ExportPaint(Object *object, EsBuffer *data, int depth = 0) { } } -void ExportLayerBox(bool first, Object *object, EsBuffer *data) { - Property *mainPaint = PropertyFindOrInherit(first, object, "mainPaint", PROP_OBJECT); - Property *borderPaint = PropertyFindOrInherit(first, object, "borderPaint", PROP_OBJECT); +void ExportLayerBox(Object *object, EsBuffer *data) { + Property *mainPaint = PropertyFindOrInherit(object, "mainPaint", PROP_OBJECT); + Property *borderPaint = PropertyFindOrInherit(object, "borderPaint", PROP_OBJECT); ThemeLayerBox box = {}; box.mainPaintType = ExportPaint(ObjectFind(mainPaint ? mainPaint->object : 0), nullptr); box.borderPaintType = ExportPaint(ObjectFind(borderPaint ? borderPaint->object : 0), nullptr); - box.borders.l = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "borders0")); - box.borders.r = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "borders1")); - box.borders.t = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "borders2")); - box.borders.b = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "borders3")); - box.corners.tl = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "corners0")); - box.corners.tr = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "corners1")); - box.corners.bl = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "corners2")); - box.corners.br = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "corners3")); - if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "isBlurred" ))) box.flags |= THEME_LAYER_BOX_IS_BLURRED; - if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "autoCorners" ))) box.flags |= THEME_LAYER_BOX_AUTO_CORNERS; - if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "autoBorders" ))) box.flags |= THEME_LAYER_BOX_AUTO_BORDERS; - if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "shadowHiding"))) box.flags |= THEME_LAYER_BOX_SHADOW_HIDING; + box.borders.l = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "borders0")); + box.borders.r = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "borders1")); + box.borders.t = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "borders2")); + box.borders.b = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "borders3")); + box.corners.tl = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "corners0")); + box.corners.tr = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "corners1")); + box.corners.bl = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "corners2")); + box.corners.br = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "corners3")); + if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "isBlurred" ))) box.flags |= THEME_LAYER_BOX_IS_BLURRED; + if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "autoCorners" ))) box.flags |= THEME_LAYER_BOX_AUTO_CORNERS; + if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "autoBorders" ))) box.flags |= THEME_LAYER_BOX_AUTO_BORDERS; + if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "shadowHiding"))) box.flags |= THEME_LAYER_BOX_SHADOW_HIDING; EsBufferWrite(data, &box, sizeof(box)); ExportPaint(ObjectFind(mainPaint ? mainPaint->object : 0), data); ExportPaint(ObjectFind(borderPaint ? borderPaint->object : 0), data); } -void ExportLayerPath(bool first, Object *object, EsBuffer *data) { - Property *pointCount = PropertyFindOrInherit(false, object, "points_count", PROP_INT); - Property *fillCount = PropertyFindOrInherit(false, object, "fills_count", PROP_INT); +void ExportLayerPath(Object *object, EsBuffer *data) { + Property *pointCount = PropertyFindOrInherit(object, "points_count", PROP_INT); + Property *fillCount = PropertyFindOrInherit(object, "fills_count", PROP_INT); ThemeLayerPath path = {}; - if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "pathFillEvenOdd"))) path.flags |= THEME_LAYER_PATH_FILL_EVEN_ODD; - if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "pathClosed"))) path.flags |= THEME_LAYER_PATH_CLOSED; - path.alpha = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "alpha")); + if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "pathFillEvenOdd"))) path.flags |= THEME_LAYER_PATH_FILL_EVEN_ODD; + if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "pathClosed"))) path.flags |= THEME_LAYER_PATH_CLOSED; + path.alpha = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "alpha")); path.pointCount = pointCount ? pointCount->integer : 0; path.fillCount = fillCount ? fillCount->integer : 0; EsBufferWrite(data, &path, sizeof(path)); @@ -1939,7 +1937,7 @@ void ExportLayerPath(bool first, Object *object, EsBuffer *data) { Property *property; #define LAYER_PATH_WRITE_POINT(x) \ sprintf(cPropertyName, "points_%d_" #x, (int32_t) i); \ - property = PropertyFindOrInherit(first, object, cPropertyName, PROP_FLOAT); \ + property = PropertyFindOrInherit(object, cPropertyName, PROP_FLOAT); \ EsBufferWrite(data, property ? &property->floating : &zero, sizeof(float)); LAYER_PATH_WRITE_POINT(x0); LAYER_PATH_WRITE_POINT(y0); @@ -1954,11 +1952,11 @@ void ExportLayerPath(bool first, Object *object, EsBuffer *data) { ThemeLayerPathFill fill = {}; sprintf(cPropertyName, "fills_%d_paint", (int32_t) i); - Object *paint = PropertyFindOrInheritReadObject(first, object, cPropertyName); + Object *paint = PropertyFindOrInheritReadObject(object, cPropertyName); fill.paintAndFillType |= ExportPaint(paint, nullptr); sprintf(cPropertyName, "fills_%d_mode", (int32_t) i); - Object *mode = PropertyFindOrInheritReadObject(first, object, cPropertyName); + Object *mode = PropertyFindOrInheritReadObject(object, cPropertyName); // TODO Dashed contours. @@ -1973,12 +1971,12 @@ void ExportLayerPath(bool first, Object *object, EsBuffer *data) { if (mode && mode->type == OBJ_VAR_CONTOUR_STYLE) { ThemeLayerPathFillContour contour = {}; - contour.miterLimit = PropertyFindOrInheritReadFloat(first, mode, "miterLimit"); - contour.internalWidth = PropertyFindOrInheritReadInt32(first, mode, "internalWidth"); - contour.externalWidth = PropertyFindOrInheritReadInt32(first, mode, "externalWidth"); - contour.mode = PropertyFindOrInheritReadInt32(first, mode, "joinMode") - | (PropertyFindOrInheritReadInt32(first, mode, "capMode") << 2) - | (PropertyFindOrInheritReadInt32(first, mode, "integerWidthsOnly") ? 0x80 : 0); + contour.miterLimit = PropertyFindOrInheritReadFloat(mode, "miterLimit"); + contour.internalWidth = PropertyFindOrInheritReadInt32(mode, "internalWidth"); + contour.externalWidth = PropertyFindOrInheritReadInt32(mode, "externalWidth"); + contour.mode = PropertyFindOrInheritReadInt32(mode, "joinMode") + | (PropertyFindOrInheritReadInt32(mode, "capMode") << 2) + | (PropertyFindOrInheritReadInt32(mode, "integerWidthsOnly") ? 0x80 : 0); EsBufferWrite(data, &contour, sizeof(contour)); } } @@ -2077,16 +2075,16 @@ void CanvasDrawLayer(Object *object, UIRectangle bounds, UIPainter *painter, int } if (object->type == OBJ_LAYER_BOX) { - bounds.l += PropertyFindOrInheritReadInt32(depth == 0, object, "offset0") * canvas->zoom; - bounds.r += PropertyFindOrInheritReadInt32(depth == 0, object, "offset1") * canvas->zoom; - bounds.t += PropertyFindOrInheritReadInt32(depth == 0, object, "offset2") * canvas->zoom; - bounds.b += PropertyFindOrInheritReadInt32(depth == 0, object, "offset3") * canvas->zoom; + bounds.l += PropertyFindOrInheritReadInt32(object, "offset0") * canvas->zoom; + bounds.r += PropertyFindOrInheritReadInt32(object, "offset1") * canvas->zoom; + bounds.t += PropertyFindOrInheritReadInt32(object, "offset2") * canvas->zoom; + bounds.b += PropertyFindOrInheritReadInt32(object, "offset3") * canvas->zoom; uint8_t buffer[4096]; EsBuffer data = { .out = buffer, .bytes = sizeof(buffer) }; ThemeLayer layer = { .position = { .r = 100, .b = 100 }, .type = THEME_LAYER_BOX }; EsBufferWrite(&data, &layer, sizeof(layer)); - ExportLayerBox(depth == 0, object, &data); + ExportLayerBox(object, &data); CanvasDrawLayerFromData(painter, bounds, data); } else if (object->type == OBJ_LAYER_TEXT) { #ifdef OS_ESSENCE @@ -2115,7 +2113,7 @@ void CanvasDrawLayer(Object *object, UIRectangle bounds, UIPainter *painter, int EsBuffer data = { .out = buffer, .bytes = sizeof(buffer) }; ThemeLayer layer = { .position = { .r = 100, .b = 100 }, .type = THEME_LAYER_PATH }; EsBufferWrite(&data, &layer, sizeof(layer)); - ExportLayerPath(depth == 0, object, &data); + ExportLayerPath(object, &data); CanvasDrawLayerFromData(painter, bounds, data); } else if (object->type == OBJ_LAYER_GROUP) { int32_t layerCount = PropertyReadInt32(object, "layers_count"); @@ -2178,20 +2176,19 @@ void CanvasDrawStyle(Object *object, UIRectangle bounds, UIPainter *painter, int textStyle.size = GraphGetIntegerFromProperty(PropertyFindOrInherit(false, object, "textSize")) * canvas->zoom; textStyle.color = GraphGetColorFromProperty(PropertyFindOrInherit(false, object, "textColor")); EsDrawTextSimple((_EsPainter *) &themePainter, ui.instance->window, bounds, "Sample", -1, textStyle, ES_TEXT_H_CENTER | ES_TEXT_V_CENTER); - } else if (object->type == OBJ_VAR_ICON_STYLE) { +#if 0 EsDrawStandardIcon((_EsPainter *) &themePainter, ES_ICON_GO_NEXT_SYMBOLIC, GraphGetIntegerFromProperty(PropertyFindOrInherit(false, object, "iconSize")), bounds, GraphGetColorFromProperty(PropertyFindOrInherit(false, object, "iconColor"))); +#endif } #endif if (object->type == OBJ_STYLE) { - Property *appearance = PropertyFindOrInherit(false, object, "appearance"); - Property *textStyle = PropertyFindOrInherit(false, object, "textStyle"); - Property *iconStyle = PropertyFindOrInherit(false, object, "iconStyle"); + Property *appearance = PropertyFindOrInherit(object, "appearance"); + Property *textStyle = PropertyFindOrInherit(object, "textStyle"); if (appearance) CanvasDrawLayer(ObjectFind(appearance->object), bounds, painter, depth + 1); if (textStyle) CanvasDrawStyle(ObjectFind(textStyle->object), bounds, painter, depth + 1); - else if (iconStyle) CanvasDrawStyle(ObjectFind(iconStyle->object), bounds, painter, depth + 1); } } @@ -2268,6 +2265,7 @@ int CanvasMessage(UIElement *element, UIMessage message, int di, void *dp) { UIRectangle selectionIntersection = UIRectangleIntersection(bounds, selectionBounds); bool isSelected = (object->flags & OBJECT_IS_SELECTED) == (inspectorPickData == nullptr) || (canvas->selecting && UI_RECT_VALID(selectionIntersection)); + bool isConditional = ObjectIsConditional(object); if (!canvas->showPrototype) { if (isSelected) { @@ -2281,7 +2279,7 @@ int CanvasMessage(UIElement *element, UIMessage message, int di, void *dp) { UIDrawBlock(painter, UI_RECT_4(bounds.l + 1, bounds.r + 1, bounds.b, bounds.b + 1), 0xFF404040); UIDrawBlock(painter, UI_RECT_4(bounds.r, bounds.r + 1, bounds.t + 1, bounds.b + 1), 0xFF404040); - if (ObjectIsConditional(object)) { + if (isConditional) { UIRectangle indicator = UI_RECT_4(bounds.l - ui.glyphWidth, bounds.l, bounds.t, bounds.t + ui.glyphHeight); UIDrawBlock(painter, indicator, 0xFFFFFF00); UIDrawString(painter, indicator, "?", -1, 0xFF000000, UI_ALIGN_CENTER, nullptr); @@ -2297,6 +2295,12 @@ int CanvasMessage(UIElement *element, UIMessage message, int di, void *dp) { buffer, -1, 0xFF000000, UI_ALIGN_CENTER, nullptr); } + if (isConditional) { + canvas->previewStateActive = true; + canvas->previewPrimaryState = PropertyReadInt32(object, "_primaryState"); + canvas->previewStateBits = PropertyReadInt32(object, "_stateBits"); + } + if (object->type == OBJ_VAR_INT || object->type == OBJ_MOD_MULTIPLY) { int32_t value = GraphGetInteger(object); char buffer[32]; @@ -2315,17 +2319,23 @@ int CanvasMessage(UIElement *element, UIMessage message, int di, void *dp) { snprintf(buffer, sizeof(buffer), "%.8X", color); UIRectangle area = UI_RECT_4(bounds.l, bounds.r, bounds.t, bounds.t + UIMeasureStringHeight()); UIDrawString(painter, area, buffer, -1, isLight ? 0xFF000000 : 0xFFFFFFFF, UI_ALIGN_CENTER, nullptr); - } else if (object->type == OBJ_VAR_TEXT_STYLE || object->type == OBJ_VAR_ICON_STYLE || object->type == OBJ_STYLE) { + } else if (object->type == OBJ_VAR_TEXT_STYLE || object->type == OBJ_STYLE) { CanvasDrawStyle(object, bounds, painter); } else if (object->type == OBJ_INSTANCE) { Property *style = PropertyFind(object, "style", PROP_OBJECT); canvas->previewStateActive = object->id == selectedObjectID; CanvasDrawStyle(ObjectFind(style ? style->object : 0), bounds, painter); - canvas->previewStateActive = false; } else { // TODO Preview for the metrics layer. Show the preferred size, insets and gaps? // TODO Preview for OBJ_VAR_CONTOUR_STYLE. } + + canvas->previewStateActive = false; + + if (!canvas->showPrototype) { + canvas->previewPrimaryState = THEME_PRIMARY_STATE_IDLE; + canvas->previewStateBits = 0; + } } if (canvas->showArrows && !canvas->showPrototype) { @@ -2615,7 +2625,6 @@ void ObjectAddCommand(void *) { UIMenuAddItem(menu, 0, "Color variable", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_COLOR); UIMenuAddItem(menu, 0, "Integer variable", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_INT); UIMenuAddItem(menu, 0, "Text style", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_TEXT_STYLE); - UIMenuAddItem(menu, 0, "Icon style", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_ICON_STYLE); UIMenuAddItem(menu, 0, "Contour style", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_CONTOUR_STYLE); UIMenuAddItem(menu, 0, "Metrics", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_LAYER_METRICS); UIMenuAddItem(menu, 0, "Overwrite paint", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_PAINT_OVERWRITE);