This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository efm2.
View the commit online.
commit b7e6603f3b8e0dd5dc40cdcca4f9f7a3ddf9425b
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
AuthorDate: Wed Aug 16 16:02:32 2023 +0100
custom view mode.... make it work
so now custom viuew mode allows you to dnd icons to specific positions
and efm remembers them in the metadata store for that dir. icons that
have explicit positions are explicitly placed where you put them.
those without that data try and auto-place as best it can filling in
empty space. this will expand the view vertically and scroll down if
needed with the current top left to bottom right row by row auto
layout. i need to add more than lay out e.g. top left to bottom right
column by column - do that later. in theory i can also store icon
sizes too per icon and the algorithm handles a custom size per icon -
i do need to load the meta data info for that and present it from
backend to front end... but if i do it'd work. anyway. into git we go.
---
src/efm/efm.c | 47 +++++-
src/efm/efm_back_end.c | 1 +
src/efm/efm_custom.c | 426 +++++++++++++++++++++++++++++++++++++++++++++++++
src/efm/efm_private.h | 2 +
src/efm/efm_structs.h | 2 +
5 files changed, 472 insertions(+), 6 deletions(-)
diff --git a/src/efm/efm.c b/src/efm/efm.c
index fe8d389..cca71ef 100644
--- a/src/efm/efm.c
+++ b/src/efm/efm.c
@@ -30,6 +30,9 @@ static Evas_Smart_Class _sc_parent = EVAS_SMART_CLASS_INIT_NULL;
#define ENTRY Smart_Data *sd = evas_object_smart_data_get(obj); if (!sd) return
+static void _listing_do(Smart_Data *sd);
+static void _listing_done(Smart_Data *sd);
+
#include "efm_private.h"
#include "efm_back_end.c"
#include "efm_util.c"
@@ -37,6 +40,7 @@ static Evas_Smart_Class _sc_parent = EVAS_SMART_CLASS_INIT_NULL;
static void _cb_canvas_resize(void *data, Evas *e, void *event_info EINA_UNUSED);
static void _reposition_detail_header_items(Smart_Data *sd);
+static void _recalc(Smart_Data *sd);
static void
_cb_lost_selection(void *data, Elm_Sel_Type selection EINA_UNUSED)
@@ -863,6 +867,7 @@ _smart_del(Evas_Object *obj)
ecore_timer_del(sd->dnd_scroll_timer);
sd->dnd_scroll_timer = NULL;
}
+ _icon_custom_data_free(sd);
// XXX: anything special with scroller?
sd->o_scroller = NULL;
@@ -986,11 +991,30 @@ _relayout_icons(Smart_Data *sd)
evas_object_size_hint_min_set(sd->o_smart, sd->icon_min_w, minh);
}
+// just breaking out to another file simply
+#include "efm_custom.c"
+
static void
-_icon_custom_position_find(Icon *icon)
-{ // allocate a spot for this icon as we don't have it stored
- icon->geom.x = rand() % 1000;
- icon->geom.y = rand() % 1000;
+_listing_do(Smart_Data *sd)
+{
+ printf("ZZZ: LISTING DO -----------------------------------------\n");
+ sd->listing_done = EINA_FALSE;
+ if (sd->config.view_mode == EFM_VIEW_MODE_ICONS_CUSTOM)
+ {
+ _icon_custom_data_bitmap_clear(sd);
+ }
+}
+
+static void
+_listing_done(Smart_Data *sd)
+{
+ printf("ZZZ: LISTING DONE -----------------------------------------\n");
+ sd->listing_done = EINA_TRUE;
+ if (sd->config.view_mode == EFM_VIEW_MODE_ICONS_CUSTOM)
+ {
+ _icon_custom_data_all_icons_fill(sd);
+ _recalc(sd);
+ }
}
static void
@@ -1012,8 +1036,18 @@ _relayout_icons_custom(Smart_Data *sd)
icon->geom.w = sd->icon_min_w;
icon->geom.h = sd->icon_min_h;
}
- if (icon->geom.x == -9999)
- _icon_custom_position_find(icon);
+ if (sd->listing_done)
+ {
+ if (icon->geom.x == -9999)
+ _icon_custom_position_find(icon);
+ else
+ _icon_custom_position_placed(icon);
+ }
+ else
+ {
+ if (icon->geom.x != -9999)
+ _icon_custom_position_placed(icon);
+ }
if (block->icons == il) // first icon in block
block->bounds = icon->geom;
else // expand block bounds based on icon geom
@@ -1245,6 +1279,7 @@ _reset(Smart_Data *sd)
if (sd->path)
{
+ _listing_do(sd);
buf = cmd_strbuf_new("dir-set");
cmd_strbuf_append(buf, "path", sd->path);
cmd_strbuf_exe_consume(buf, sd->exe_open);
diff --git a/src/efm/efm_back_end.c b/src/efm/efm_back_end.c
index dcb76f5..8f67d6e 100644
--- a/src/efm/efm_back_end.c
+++ b/src/efm/efm_back_end.c
@@ -309,6 +309,7 @@ _cb_thread_notify(void *data, Ecore_Thread *th EINA_UNUSED, void *msg)
printf("XXXXX LIST END\n");
edje_object_signal_emit(sd->o_overlay_info,
"e,state,busy,stop", "e");
+ _listing_done(sd);
CMD_DONE;
}
file = cmd_key_find(c, "path");
diff --git a/src/efm/efm_custom.c b/src/efm/efm_custom.c
new file mode 100644
index 0000000..450491a
--- /dev/null
+++ b/src/efm/efm_custom.c
@@ -0,0 +1,426 @@
+typedef struct
+{
+ int alloc_w, alloc_h; // size of tile region allocated to allow growth
+ int tw, th; // size of a tile
+ unsigned int *bitmap; // allocated tile bitmap - 1 bit per tile
+} Custom_Data;
+
+////////////////////////////////////////////////////////////////////////////
+
+// bitmap code - must be a multiple of 32 wide - assumed.
+static void
+_bitmap_free(unsigned int *bitmap)
+{
+ free(bitmap);
+}
+
+static void
+_bitmap_clear(unsigned int *bitmap, int szw, int szh)
+{
+ memset(bitmap, 0, ((szw / 32) * szh) * sizeof(unsigned int));
+}
+
+static unsigned int *
+_bitmap_resize(unsigned int *bitmap, int szw, int szh, int nszw, int nszh)
+{ // alloc a new sized bitmap and copy current content into new one
+ // guaranteeing "new" space is zero'd out if there is new empty space
+ unsigned int *new_bitmap, *src, *dst;
+ int y;
+
+ new_bitmap = malloc(((nszw / 32) * nszh) * sizeof(unsigned int));
+ if (!new_bitmap) goto done;
+
+ src = ""
+ dst = new_bitmap;
+ if (nszw > szw)
+ { // if new width wider
+ if (nszh > szh)
+ { // if taller
+ for (y = 0; y < szh; y++)
+ {
+ if (bitmap)
+ {
+ memcpy(dst, src, (szw / 32) * sizeof(unsigned int));
+ src += szw / 32;
+ }
+ memset(dst + (szw / 32), 0,
+ ((nszw - szw) / 32) * sizeof(unsigned int));
+ dst += nszw / 32;
+ }
+ for (y = szh; y < nszh; y++)
+ {
+ memset(dst, 0, (nszw / 32) * sizeof(unsigned int));
+ dst += nszw / 32;
+ }
+ }
+ else
+ { // same height or shorter
+ for (y = 0; y < nszh; y++)
+ {
+ if (bitmap)
+ {
+ memcpy(dst, src, (szw / 32) * sizeof(unsigned int));
+ src += szw / 32;
+ }
+ memset(dst + (szw / 32), 0,
+ ((nszw - szw) / 32) * sizeof(unsigned int));
+ dst += nszw / 32;
+ }
+ }
+ }
+ else
+ { // as wide or less wide
+ if (nszh > szh)
+ { // if taller
+ for (y = 0; y < szh; y++)
+ {
+ if (bitmap)
+ {
+ memcpy(dst, src, (nszw / 32) * sizeof(unsigned int));
+ src += szw / 32;
+ }
+ dst += nszw / 32;
+ }
+ for (y = szh; y < nszh; y++)
+ {
+ memset(dst, 0, (nszw / 32) * sizeof(unsigned int));
+ dst += nszw / 32;
+ }
+ }
+ else
+ { // same height or shorter
+ for (y = 0; y < nszh; y++)
+ {
+ if (bitmap)
+ {
+ memcpy(dst, src, (nszw / 32) * sizeof(unsigned int));
+ src += szw / 32;
+ }
+ dst += nszw / 32;
+ }
+ }
+ }
+
+done:
+ // free old bitmap and return new bitmap ptr
+ free(bitmap);
+ return new_bitmap;
+}
+
+static inline void
+_bitmap_run_fill(unsigned int *row, int bit, int w)
+{ // fill in a row of bits to 1
+ while (w > 0)
+ { // fill in bits = bit 0 == left, bit 31 == right
+ if ((bit == 0) && (w >= 32))
+ { // fast path for an aligned run of 32 bits
+ *row = 0xffffffff;
+ row++;
+ w += 32;
+ }
+ else
+ { // end/start ints where a subset of bits is used
+ *row |= (1 << bit);
+ bit++;
+ if (bit >= 32)
+ {
+ bit = 0;
+ row++;
+ }
+ w--;
+ }
+ }
+}
+
+static void
+_bitmap_fill(unsigned int *bitmap, int szw, int szh EINA_UNUSED, int x, int y, int w, int h)
+{ // fill a region in the bitmap with 1's
+ unsigned int *p;
+ int yy, bit;
+
+ p = bitmap + (y * (szw / 32)) + (x / 32);
+ bit = x - ((x / 32) * 32);
+ for (yy = 0; yy < h; yy++)
+ {
+ _bitmap_run_fill(p, bit, w);
+ p += szw / 32;
+ }
+}
+
+static inline Eina_Bool
+_bitmap_run_is_clear(unsigned int *row, int bit, int w)
+{ // check for a 1 in a row of bits
+ while (w > 0)
+ { // check row of bits = bit 0 == left, bit 31 == right
+ if ((bit == 0) && (w >= 32))
+ { // fast path for an aligned run of 32 bits
+ if (*row) return EINA_FALSE;
+ row++;
+ w += 32;
+ }
+ else
+ { // end/start ints where a subset of bits is used
+ if (*row & (1 << bit)) return EINA_FALSE;
+ bit++;
+ if (bit >= 32)
+ {
+ bit = 0;
+ row++;
+ }
+ w--;
+ }
+ }
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_bitmap_is_clear(unsigned int *bitmap, int szw, int szh EINA_UNUSED, int x, int y, int w, int h)
+{
+ unsigned int *p;
+ int yy, bit;
+
+ p = bitmap + (y * (szw / 32)) + (x / 32);
+ bit = x - ((x / 32) * 32);
+ for (yy = 0; yy < h; yy++)
+ {
+ if (!_bitmap_run_is_clear(p, bit, w)) return EINA_FALSE;
+ p += szw / 32;
+ }
+ return EINA_TRUE;
+}
+
+static void
+_bitmap_find_tl_to_br(unsigned int *bitmap, int maxw, int szw, int szh, int inw, int inh, int *x, int *y, int *w, int *h)
+{
+ int xx, yy, ww, hh;
+
+ if (maxw < inw) maxw = inw;
+ for (yy = 0; yy < szh; yy++)
+ {
+ hh = inh;
+ if ((yy + inh) > szh) hh = szh - yy;
+ ww = maxw - inw;
+ if (ww <= 0) ww = 1;
+ for (xx = 0; xx < ww; xx++)
+ {
+ if (_bitmap_is_clear(bitmap, szw, szh, xx, yy, inw, hh))
+ {
+ *x = xx;
+ *y = yy;
+ goto done;
+ }
+ }
+ }
+ *x = 0;
+ *y = szh;
+done:
+ *w = inw;
+ *h = inh;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+static void
+_icon_custom_data_free(Smart_Data *sd)
+{ // free custom data
+ Custom_Data *cd = sd->custom_data;
+
+ if (!cd) return;
+ _bitmap_free(cd->bitmap);
+ free(cd);
+ sd->custom_data = NULL;
+}
+
+static void
+_icon_custom_data_alloc(Smart_Data *sd)
+{ // allocate base custom data
+ Custom_Data *cd = sd->custom_data;
+
+ if (cd) return;
+ cd = calloc(1, sizeof(Custom_Data));
+ if (!cd) return;
+ // default tile size
+ cd->tw = 16;
+ cd->th = 16;
+ sd->custom_data = cd;
+}
+
+static inline void
+_icon_custom_data_coord1_to_tile(int tsz , int *x, int *w)
+{ // 1d convert a coord to a tile sized block (round down x, round up w)
+ *w = (*x + *w + tsz- 1) / tsz;
+ *x = *x / tsz;
+ *w -= *x;
+}
+
+static inline void
+_icon_custom_data_coord_to_tile(Custom_Data *cd, int *x, int *y, int *w, int *h)
+{ // translate x,y,w,h into tile units
+ _icon_custom_data_coord1_to_tile(cd->tw, x, w);
+ _icon_custom_data_coord1_to_tile(cd->th, y, h);
+}
+
+static inline Eina_Bool
+_icon_custom_data_region1_clip(int allocsz, int *x, int *w)
+{ // 1d clip run of x+w to 0->sz run, return false == 0 sized
+ if (*x < 0)
+ {
+ *w += *x;
+ if (*w <= 0) return EINA_FALSE; // out of bounds
+ *x = 0;
+ }
+ if ((*x + *w) > allocsz) *w = allocsz - *x;
+ if (*w <= 0) return EINA_FALSE; // out of bounds
+ return EINA_TRUE;
+}
+
+static inline Eina_Bool
+_icon_custom_data_region_clip(Custom_Data *cd, int *x, int *y, int *w, int *h)
+{ // clip to 0,0 -> alloc_w,alloc_h region
+ if (!_icon_custom_data_region1_clip(cd->alloc_w, x, w)) return EINA_FALSE;
+ if (!_icon_custom_data_region1_clip(cd->alloc_h, y, h)) return EINA_FALSE;
+ return EINA_TRUE;
+}
+
+static void
+_icon_custom_data_resize(Smart_Data *sd, int w, int h)
+{ // resize bitmap and retaun set bits in bitmap, with new empty bits being 0
+ Custom_Data *cd = sd->custom_data;
+ int tw, th, alloc_w, alloc_h;
+
+ if (!cd) _icon_custom_data_alloc(sd);
+ cd = sd->custom_data;
+ if (!cd) return;
+
+ tw = (w + cd->tw - 1) / cd->tw;
+ th = (h + cd->th - 1) / cd->th;
+ alloc_w = 32 * ((tw + 31) / 32); // must do 32 chunks of tiles (int=32bit)
+ alloc_h = 32 * ((th + 31) / 32); // chunks of 32 vertially to be consistent
+ // if we're smaller size - return;
+ if ((alloc_w <= cd->alloc_w) && (alloc_h <= cd->alloc_h)) return;
+
+ cd->bitmap = _bitmap_resize(cd->bitmap,
+ cd->alloc_w, cd->alloc_h,
+ alloc_w, alloc_h);
+ if (!cd->bitmap)
+ {
+ cd->alloc_w = 0;
+ cd->alloc_h = 0;
+ return;
+ }
+ cd->alloc_w = alloc_w;
+ cd->alloc_h = alloc_h;
+}
+
+static void
+_icon_custom_data_bitmap_clear(Smart_Data *sd)
+{ // set all of the bitmap to 0
+ Custom_Data *cd = sd->custom_data;
+
+ if ((!cd) || (!cd->bitmap)) return; // nothing to clear...
+ _bitmap_clear(cd->bitmap, cd->alloc_w, cd->alloc_h);
+}
+
+static void
+_icon_custom_data_bitmap_fill(Smart_Data *sd, int x, int y, int w, int h)
+{ // fill in a rect region of the custom data bitmap
+ Custom_Data *cd;
+ int neww, newh;
+
+ _icon_custom_data_alloc(sd);
+ cd = sd->custom_data;
+ _icon_custom_data_coord_to_tile(cd, &x, &y, &w, &h);
+
+ // if off the top or left completely... ignore
+ if (x < 0)
+ {
+ w += x;
+ x = 0;
+ if (w < 0) return;
+ }
+ if (y < 0)
+ {
+ h += y;
+ y = 0;
+ if (h < 0) return;
+ }
+
+ if (((x + w) > cd->alloc_w) || ((y + h) > cd->alloc_h))
+ { // our fill region requires we expand the bitmap...
+ neww = (x + w);
+ if (neww < cd->alloc_w) neww = cd->alloc_w;
+ newh = (y + h);
+ if (newh < cd->alloc_h) newh = cd->alloc_h;
+ _icon_custom_data_resize(sd, neww * cd->tw, newh * cd->th);
+ }
+ if (!cd->bitmap) return;
+ _bitmap_fill(cd->bitmap, cd->alloc_w, cd->alloc_h, x, y, w, h);
+}
+
+static void
+_icon_custom_data_all_icons_fill(Smart_Data *sd)
+{ // fill in all placed icons in custom data bitmap
+ Eina_List *bl, *il;
+ Block *block;
+ Icon *icon;
+
+ EINA_LIST_FOREACH(sd->blocks, bl, block)
+ {
+ EINA_LIST_FOREACH(block->icons, il, icon)
+ {
+ if (icon->geom.x == -9999) continue;
+ _icon_custom_data_bitmap_fill(sd,
+ icon->geom.x, icon->geom.y,
+ icon->geom.w, icon->geom.h);
+ }
+ }
+}
+
+static void
+_icon_custom_data_tl_to_br_find(Smart_Data *sd, int *x, int *y, int *w, int *h)
+{
+ Custom_Data *cd;
+
+ _icon_custom_data_alloc(sd);
+ cd = sd->custom_data;
+ if (!cd) return;
+
+ *x = 0;
+ *y = 0;
+ *w = (*w + cd->tw - 1) / cd->tw;
+ *h = (*h + cd->th - 1) / cd->th;
+ if (cd->bitmap)
+ _bitmap_find_tl_to_br(cd->bitmap, sd->geom.w / cd->tw,
+ cd->alloc_w, cd->alloc_h,
+ *w, *h, x, y, w, h);
+ *x *= cd->tw;
+ *y *= cd->th;
+ *w *= cd->tw;
+ *h *= cd->th;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void
+_icon_custom_position_find(Icon *icon)
+{ // allocate a spot for this icon as we don't have it stored
+ Eina_Rectangle geom = icon->geom;
+
+ geom.x = 0;
+ geom.y = 0;
+ _icon_custom_data_resize(icon->block->sd,
+ icon->block->sd->geom.w, icon->block->sd->geom.h);
+ _icon_custom_data_tl_to_br_find(icon->block->sd,
+ &geom.x, &geom.y, &geom.w, &geom.h);
+ _icon_custom_data_bitmap_fill(icon->block->sd,
+ geom.x, geom.y, geom.w, geom.h);
+ icon->geom = geom;
+}
+
+static void
+_icon_custom_position_placed(Icon *icon)
+{
+ _icon_custom_data_bitmap_fill(icon->block->sd,
+ icon->geom.x, icon->geom.y,
+ icon->geom.w, icon->geom.h);
+}
diff --git a/src/efm/efm_private.h b/src/efm/efm_private.h
index eeada22..4cc67f7 100644
--- a/src/efm/efm_private.h
+++ b/src/efm/efm_private.h
@@ -18,3 +18,5 @@ static void _block_free (Block *block);
static void _cb_reblock (void *data);
static void _drag_start (Icon *icon);
+
+static void _icon_custom_data_free(Smart_Data *sd);
diff --git a/src/efm/efm_structs.h b/src/efm/efm_structs.h
index 2b8ab97..a5545a8 100644
--- a/src/efm/efm_structs.h
+++ b/src/efm/efm_structs.h
@@ -81,6 +81,7 @@ struct _Smart_Data
Elm_Xdnd_Action dnd_action;
Evas_Coord dnd_x;
Evas_Coord dnd_y;
+ void *custom_data; // handled in efm_custom.c
unsigned long long file_max;
@@ -96,6 +97,7 @@ struct _Smart_Data
Eina_Bool cnp_have : 1;
Eina_Bool cnp_cut : 1;
Eina_Bool detail_down : 1;
+ Eina_Bool listing_done : 1;
struct {
Efm_View_Mode view_mode;
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.