#define LABEL_LAYER_SELECTION_THICCNESS 5.0f
+// TODO(#999): LabelLayer does not support UndoHistory
+
typedef enum {
LABEL_LAYER_IDLE = 0,
LABEL_LAYER_MOVE,
LABEL_LAYER_EDIT_ID
} LabelLayerState;
-// TODO(#963): LabelLayer cannot add the labels
-// TODO(#964): LabelLayer cannot modify the labels' id
struct LabelLayer {
Lt *lt;
LabelLayerState state;
/* TODO(#891): LabelLayer doesn't show the final position of Label after the animation */
for (size_t i = 0; i < n; ++i) {
- if (label_layer->state == LABEL_LAYER_EDIT_TEXT) {
+ if (label_layer->state == LABEL_LAYER_EDIT_TEXT && label_layer->selected == (int) i) {
if (edit_field_render_world(
label_layer->edit_field,
camera,
}
}
- if (label_layer->state == LABEL_LAYER_EDIT_ID) {
+ if (label_layer->state == LABEL_LAYER_EDIT_ID && label_layer->selected == (int)i) {
if (edit_field_render_world(
label_layer->edit_field,
camera,
trace_assert(label_layer);
const size_t n = dynarray_count(label_layer->texts);
+ char *ids = dynarray_data(label_layer->ids);
char *texts = dynarray_data(label_layer->texts);
Point *positions = dynarray_data(label_layer->positions);
for (size_t i = 0; i < n; ++i) {
- Rect boundary = sprite_font_boundary_box(
- font,
- positions[i],
- LABELS_SIZE,
- texts + i * LABEL_LAYER_TEXT_MAX_SIZE);
+ Rect boundary = rect_boundary2(
+ sprite_font_boundary_box(
+ font,
+ positions[i],
+ LABELS_SIZE,
+ texts + i * LABEL_LAYER_TEXT_MAX_SIZE),
+ sprite_font_boundary_box(
+ font,
+ vec_sub(
+ positions[i],
+ vec(0.0f, FONT_CHAR_HEIGHT)),
+ vec(1.0f, 1.0f),
+ ids + i * LABEL_LAYER_ID_MAX_SIZE));
if (rect_contains_point(boundary, position)) {
return (int) i;
return -1;
}
+static
+void label_layer_delete_nth_label(LabelLayer *label_layer,
+ size_t i)
+{
+ trace_assert(label_layer);
+ dynarray_delete_at(label_layer->ids, i);
+ dynarray_delete_at(label_layer->positions, i);
+ dynarray_delete_at(label_layer->colors, i);
+ dynarray_delete_at(label_layer->texts, i);
+}
+
+static
+int label_layer_add_label(LabelLayer *label_layer,
+ Point position,
+ Color color)
+{
+ trace_assert(label_layer);
+
+ // TODO(#982): id generation code is duplicated in label_layer, point_layer and rect_layer
+ char id[LABEL_LAYER_ID_MAX_SIZE];
+ for (size_t i = 0; i < LABEL_LAYER_ID_MAX_SIZE - 1; ++i) {
+ id[i] = (char) ('a' + rand() % ('z' - 'a' + 1));
+ }
+ id[LABEL_LAYER_ID_MAX_SIZE - 1] = '\0';
+
+ size_t n = dynarray_count(label_layer->ids);
+
+ dynarray_push(label_layer->ids, id);
+ dynarray_push(label_layer->positions, &position);
+ dynarray_push(label_layer->colors, &color);
+ dynarray_push_empty(label_layer->texts);
+
+ return (int) n;
+}
+
static
int label_layer_idle_event(LabelLayer *label_layer,
const SDL_Event *event,
label_layer->color_picker =
create_color_picker_from_rgba(colors[element]);
+ } else {
+ label_layer->selected = label_layer_add_label(
+ label_layer,
+ position,
+ color_picker_rgba(
+ &label_layer->color_picker));
+ label_layer->state = LABEL_LAYER_EDIT_TEXT;
+ edit_field_replace(
+ label_layer->edit_field,
+ texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE);
+ edit_field_restyle(
+ label_layer->edit_field,
+ LABELS_SIZE,
+ colors[label_layer->selected]);
+ SDL_StartTextInput();
}
} break;
}
SDL_StartTextInput();
}
} break;
+
+ case SDLK_DELETE: {
+ if (label_layer->selected >= 0) {
+ label_layer_delete_nth_label(
+ label_layer,
+ (size_t) label_layer->selected);
+ label_layer->selected = -1;
+ }
+ } break;
}
} break;
}
switch (event->type) {
case SDL_KEYDOWN: {
- if (event->key.keysym.sym == SDLK_RETURN) {
+ switch (event->key.keysym.sym) {
+ case SDLK_RETURN: {
char *text =
(char*)dynarray_data(label_layer->texts) + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE;
memset(text, 0, LABEL_LAYER_TEXT_MAX_SIZE);
memcpy(text, edit_field_as_text(label_layer->edit_field), LABEL_LAYER_TEXT_MAX_SIZE - 1);
label_layer->state = LABEL_LAYER_IDLE;
+ SDL_StopTextInput();
return 0;
+ } break;
+
+ case SDLK_ESCAPE: {
+ label_layer->state = LABEL_LAYER_IDLE;
+ SDL_StopTextInput();
+ return 0;
+ } break;
}
} break;
}
trace_assert(camera);
trace_assert(label_layer->selected >= 0);
-
switch (event->type) {
case SDL_KEYDOWN: {
- if (event->key.keysym.sym == SDLK_RETURN) {
+ switch (event->key.keysym.sym) {
+ case SDLK_RETURN: {
char *id =
(char*)dynarray_data(label_layer->ids) + label_layer->selected * LABEL_LAYER_ID_MAX_SIZE;
memset(id, 0, LABEL_LAYER_ID_MAX_SIZE);
memcpy(id, edit_field_as_text(label_layer->edit_field), LABEL_LAYER_ID_MAX_SIZE - 1);
label_layer->state = LABEL_LAYER_IDLE;
+ SDL_StopTextInput();
return 0;
+ } break;
+
+ case SDLK_ESCAPE: {
+ label_layer->state = LABEL_LAYER_IDLE;
+ SDL_StopTextInput();
+ return 0;
+ } break;
}
} break;
}
-
return edit_field_event(label_layer->edit_field, event);
}
int label_layer_event(LabelLayer *label_layer,
const SDL_Event *event,
- const Camera *camera)
+ const Camera *camera,
+ UndoHistory *undo_history)
{
trace_assert(label_layer);
trace_assert(event);
trace_assert(camera);
+ trace_assert(undo_history);
int changed = 0;
return -1;
}
- if (changed && label_layer->selected >= 0) {
- Color *colors = dynarray_data(label_layer->colors);
- colors[label_layer->selected] =
- color_picker_rgba(&label_layer->color_picker);
+ if (changed) {
+ if (label_layer->selected >= 0) {
+ Color *colors = dynarray_data(label_layer->colors);
+ colors[label_layer->selected] =
+ color_picker_rgba(&label_layer->color_picker);
+ }
+ return 0;
}
switch (label_layer->state) {