elm_code: use geometry of cells to paint a simple cursor
authorAndy Williams <andy@andywilliams.me>
Fri, 9 Dec 2016 15:53:38 +0000 (15:53 +0000)
committerAndy Williams <andy@andywilliams.me>
Fri, 9 Dec 2016 15:55:34 +0000 (15:55 +0000)
Also allows others to figure out where cells are :)

src/lib/elementary/elm_code_widget.c
src/lib/elementary/elm_code_widget.eo
src/lib/elementary/elm_code_widget_private.h
src/tests/elementary/elm_code_test_widget.c

index f0b54fe..a9011fe 100644 (file)
@@ -18,7 +18,6 @@ typedef enum {
    ELM_CODE_WIDGET_COLOR_GUTTER_BG = ELM_CODE_TOKEN_TYPE_COUNT,
    ELM_CODE_WIDGET_COLOR_GUTTER_FG,
    ELM_CODE_WIDGET_COLOR_WHITESPACE,
-   ELM_CODE_WIDGET_COLOR_CURSOR,
    ELM_CODE_WIDGET_COLOR_SELECTION,
 
    ELM_CODE_WIDGET_COLOR_COUNT
@@ -267,17 +266,31 @@ _elm_code_widget_fill_whitespace(Elm_Code_Widget *widget, Eina_Unicode character
 }
 
 static void
-_elm_code_widget_fill_cursor(Elm_Code_Widget *widget, unsigned int number,
-                             Evas_Textgrid_Cell *cells, int gutter, int w)
+_elm_code_widget_fill_cursor(Elm_Code_Widget *widget, unsigned int number, int gutter, int w)
 {
    Elm_Code_Widget_Data *pd;
+   Evas_Coord cx, cy, cw, ch;
 
    pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
 
    if (pd->editable && pd->focussed && pd->cursor_line == number)
      {
-        if (pd->cursor_col + gutter - 1 < (unsigned int) w)
-          cells[pd->cursor_col + gutter - 1].bg = ELM_CODE_WIDGET_COLOR_CURSOR;
+        if (pd->cursor_col + gutter - 1 >= (unsigned int) w)
+          return;
+
+        elm_code_widget_geometry_for_position_get(widget, pd->cursor_line, pd->cursor_col, &cx, &cy, &cw, &ch);
+
+        if (!pd->cursor_rect)
+          {
+             pd->cursor_rect = evas_object_rectangle_add(widget);
+
+             evas_object_color_set(pd->cursor_rect, 205, 205, 54, 192);
+
+             evas_object_resize(pd->cursor_rect, cw, ch);
+             evas_object_show(pd->cursor_rect);
+          }
+
+        evas_object_move(pd->cursor_rect, cx, cy);
      }
 }
 
@@ -364,7 +377,7 @@ _elm_code_widget_fill_line(Elm_Code_Widget *widget, Elm_Code_Line *line)
      }
 
    _elm_code_widget_fill_selection(widget, line, cells, gutter, w);
-   _elm_code_widget_fill_cursor(widget, line->number, cells, gutter, w);
+   _elm_code_widget_fill_cursor(widget, line->number, gutter, w);
    if (line->number < elm_code_file_lines_get(line->file))
      _elm_code_widget_fill_whitespace(widget, '\n', &cells[length + gutter]);
 
@@ -641,6 +654,34 @@ _elm_code_widget_position_at_coordinates_get(Eo *obj, Elm_Code_Widget_Data *pd,
    return !!line;
 }
 
+EOLIAN static Eina_Bool
+_elm_code_widget_geometry_for_position_get(Elm_Code_Widget *widget, Elm_Code_Widget_Data *pd, unsigned int row, int col,
+                                           Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   Elm_Code_Line *line;
+   Evas_Object *grid;
+   Evas_Coord cellw;
+   unsigned int length;
+   int gutter;
+
+   line = elm_code_file_line_get(pd->code->file, row);
+   if (!line)
+     return EINA_FALSE;
+
+   elm_code_line_text_get(line, &length);
+   _elm_code_widget_cell_size_get(widget, &cellw, h);
+   gutter = elm_obj_code_widget_text_left_gutter_width_get(widget);
+
+   grid = eina_list_nth(pd->grids, row - 1);
+   evas_object_geometry_get(grid, x, y, NULL, NULL);
+   if (x)
+     *x = (col - 1 + gutter) * cellw;
+   if (w)
+     *w = cellw;
+
+   return !!line && col <= (int) length;
+}
+
 static void
 _elm_code_widget_status_toggle(Elm_Code_Widget *widget, Elm_Code_Line *line)
 {
@@ -1694,8 +1735,6 @@ _elm_code_widget_setup_palette(Evas_Object *o)
                                     54, 54, 255, 255);
 
    // other styles that the widget uses
-   evas_object_textgrid_palette_set(o, EVAS_TEXTGRID_PALETTE_STANDARD, ELM_CODE_WIDGET_COLOR_CURSOR,
-                                    205, 205, 54, 255);
    evas_object_textgrid_palette_set(o, EVAS_TEXTGRID_PALETTE_STANDARD, ELM_CODE_WIDGET_COLOR_SELECTION,
                                     51, 153, 255, 255);
    evas_object_textgrid_palette_set(o, EVAS_TEXTGRID_PALETTE_STANDARD, ELM_CODE_WIDGET_COLOR_GUTTER_BG,
index 471eef1..dbc0e30 100644 (file)
@@ -199,6 +199,18 @@ class Elm.Code_Widget (Elm.Layout, Elm.Interface.Atspi.Text)
          }
          return: bool; [[$true if a line exists at these coordinates]]
       }
+      geometry_for_position_get {
+         [[Get the geometry for the cell at the specified position.]]
+         params {
+            row: uint; [[The row for the requested position]]
+            col: int; [[The column for the requested position]]
+            x: ptr(Evas.Coord); [[The x coordinate of the cell at specified position]]
+            y: ptr(Evas.Coord); [[The y coordinate of the cell at specified position]]
+            w: ptr(Evas.Coord); [[The width of the cell at specified position]]
+            h: ptr(Evas.Coord); [[The height of the cell at specified position]]
+         }
+         return: bool; [[$true if a cell exists at the specified position]]
+      }
 
       text_left_gutter_width_get {
         [[Get the column width of the gutter]]
index 7dca9d0..42ed274 100644 (file)
@@ -22,6 +22,8 @@ typedef struct
    double gravity_x, gravity_y;
 
    unsigned int cursor_line, cursor_col;
+   Evas_Object *cursor_rect;
+
    Eina_Bool editable, focussed;
    Eina_Bool show_line_numbers;
    unsigned int line_width_marker, tabstop;
index 191c272..94c7fa3 100644 (file)
@@ -103,9 +103,45 @@ START_TEST (elm_code_widget_construct_nocode)
 }
 END_TEST
 
+START_TEST (elm_code_widget_position)
+{
+   Elm_Code *code;
+   Elm_Code_Widget *widget;
+   Evas_Object *win;
+   Evas_Coord x, y, w, h, x2, y2, w2, h2;
+
+   elm_init(1, NULL);
+   code = elm_code_create();
+
+   win = elm_win_add(NULL, "entry", ELM_WIN_BASIC);
+   widget = elm_code_widget_add(win, code);
+   evas_object_show(widget);
+   evas_object_resize(widget, 100, 100);
+
+   elm_code_file_line_append(code->file, "some content", 12, NULL);
+   elm_code_file_line_append(code->file, "more", 4, NULL);
+
+   elm_code_widget_geometry_for_position_get(widget, 1, 1, &x, &y, &w, &h);
+   elm_code_widget_geometry_for_position_get(widget, 1, 2, &x2, &y2, &w2, &h2);
+   ck_assert(x2 > x);
+   ck_assert(y2 == y);
+   ck_assert(w2 == w);
+   ck_assert(h2 == h);
+
+   elm_code_widget_geometry_for_position_get(widget, 2, 1, &x2, &y2, &w2, &h2);
+   ck_assert(x2 == x);
+   ck_assert(w2 == w);
+   ck_assert(h2 == h);
+
+   elm_code_free(code);
+   elm_shutdown();
+}
+END_TEST
+
 void elm_code_test_widget(TCase *tc)
 {
    tcase_add_test(tc, elm_code_widget_token_render_simple_test);
    tcase_add_test(tc, elm_code_widget_construct);
    tcase_add_test(tc, elm_code_widget_construct_nocode);
+   tcase_add_test(tc, elm_code_widget_position);
 }