Browse code

Try background loading for preview images

Dario Rodriguez authored on 28/09/2025 17:00:52
Showing 1 changed files
... ...
@@ -520,8 +520,13 @@ im_body_draw(body_t *body, mousedata_t *mousedata, int windowwidth, int windowhe
520 520
                 IMDEBUG("begin draw");
521 521
                 maxw=windowwidth;
522 522
                 maxh=windowheight-body->whxy.y;
523
-                if(body->bigtexture.has_texture==0 || strcmp(body->bigtexture.currentpath,body->texture.currentpath)!=0)
523
+                if(body->bigtexture.has_texture==0 || strcmp(body->bigtexture.currentpath,body->texture.currentpath)!=0) {
524
+#if 1
525
+fprintf(stderr,"~~~ TEXTURE_LOAD FOR BIGTEXTURE \"%s\"\n",body->texture.currentpath);
526
+#endif
527
+                        bg_add(body->bg,body->texture.currentpath,1);
524 528
                         texture_load(&(body->bigtexture),body->texture.currentpath,maxw,maxh,body->bg);
529
+                }
525 530
                 if(body->bigtexture.has_texture && strcmp(body->bigtexture.currentpath,body->texture.currentpath)==0) {
526 531
                         int x0,y0;
527 532
                         x0=0;
... ...
@@ -529,7 +534,10 @@ im_body_draw(body_t *body, mousedata_t *mousedata, int windowwidth, int windowhe
529 534
                         texture_draw(&(body->bigtexture),x0,y0,maxw,maxh);
530 535
                         return(0); /* all done */
531 536
                 } else {
537
+#if 0
538
+#warning TEMP
532 539
                         body->flag_drawbigtexture=0; /* error loading big texture, draw screen normally */
540
+#endif
533 541
                 }
534 542
         }
535 543
         /* calculate positions */
... ...
@@ -716,7 +724,7 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
716 724
                                                                 thumb->has_failedload=1;
717 725
                                                         }
718 726
                                                 } else if(bgload==NULL) {
719
-                                                        bg_add(body->bg,fullpath);
727
+                                                        bg_add(body->bg,fullpath,0);
720 728
                                                 }
721 729
                                         }
722 730
                                         if(thumb->has_texture!=0) {
... ...
@@ -784,7 +792,7 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
784 792
                                 }
785 793
                         }
786 794
                         if(imageundermouse[0]!='\0')
787
-                                bg_add(body->bg,imageundermouse); /* to prioritise loading this image */
795
+                                bg_add(body->bg,imageundermouse,0); /* to prioritise loading this image */
788 796
                         for(;k<dirdata->listing.usedelems;k++) {
789 797
                                 elem=dirdata->listing.elems+k;
790 798
                                 if(elem->name[0]!='f' && elem->name[0]!='l')
... ...
@@ -1124,11 +1132,15 @@ texture_load(texture_t *texture, char *fullpath, int maxw, int maxh, bg_t *bg)
1124 1132
                 texture->has_texture=0;
1125 1133
                 texture->has_failedload=0;
1126 1134
         }
1127
-        texture->currentpath[0]='\0';
1128 1135
         if(bg!=NULL && (bgload=bg_get(bg,texture->currentpath))!=NULL && bgload->has_data!=0) {
1129 1136
                 im=ImageCopy(bgload->image);
1130 1137
         } else {
1138
+#if 0
1139
+#warning TEST CODE
1140
+                return(-1); /* if not loaded in background, return -1 to indicate "not ready" */
1141
+#else
1131 1142
                 im=global_loadimage(fullpath);
1143
+#endif
1132 1144
         }
1133 1145
         if(IsImageValid(im)) {
1134 1146
                 imutil_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
Browse code

Prioritize loading image under cursor. Use sleep in background thread. Use nanosleep instead of select for sleeping.

Dario Rodriguez authored on 28/09/2025 11:09:14
Showing 1 changed files
... ...
@@ -35,7 +35,7 @@
35 35
 #define SCROLLTHRESHOLD (LEFTIMAGESIDELEN/3)
36 36
 #define WHEELSTEP LEFTIMAGESIDELEN
37 37
 #define SEP '/'
38
-#define SIZEBGLOAD 256
38
+#define SIZEBGLOAD (3*((DEFAULTWIDTH+(LEFTIMAGESIDELEN-1))/LEFTIMAGESIDELEN)*((DEFAULTHEIGHT+(LEFTIMAGESIDELEN-1))/LEFTIMAGESIDELEN))
39 39
 #define DEFAULTDIRDATAHEIGHT 492
40 40
 #define ADDREMOVEDIRDATAHEIGHT 128
41 41
 #define UTF8DOWNARROW "\xe2\x86\x86" /* U+2186 in UTF-8 */
... ...
@@ -45,7 +45,13 @@
45 45
 #define BLOCKDIRDATA 16
46 46
 
47 47
 #define MYFUNC "UNKNOWN"
48
+#if 0
48 49
 #define IMDEBUG(a) fprintf(stderr,"%s:%i: %s: %s\n",__FILE__,__LINE__,MYFUNC,a)
50
+#define IMDEBUG2(a) fprintf(stderr,"%s:%i: %s: ",__FILE__,__LINE__,MYFUNC),fprintf a
51
+#else
52
+#define IMDEBUG(a)
53
+#define IMDEBUG2(a)
54
+#endif
49 55
 
50 56
 // RIGHTSIDEMARGIN=FONTBIGSIZE/2
51 57
 
... ...
@@ -495,6 +501,7 @@ im_body_draw(body_t *body, mousedata_t *mousedata, int windowwidth, int windowhe
495 501
         int xoff,yoff;
496 502
         thumb_t *thumb;
497 503
         char statustooltip[1024];
504
+        char imageundermouse[1024];
498 505
         thumb_t *selectedthumb;
499 506
         IMDEBUG("Pre-sanitycheck");
500 507
         if(body==NULL)
... ...
@@ -549,18 +556,15 @@ im_body_draw(body_t *body, mousedata_t *mousedata, int windowwidth, int windowhe
549 556
                 rayui_scrollablerectadd(body->rayui,mousedata,&whxy,"body.leftside",body->dirdata[body->currentdirdata]->leftscrollpos,(int (*)(void *, Vector2))im_body_tryselect,body,SCROLLTHRESHOLD);
550 557
         }
551 558
         DrawRectangle(body->whxy.x,body->whxy.y,body->leftsize, body->whxy.h, (Color){ 215, 215, 215, 255 } );
552
-fprintf(stderr,"%ix%i+%i+%i\n",body->leftsize, body->whxy.h,body->whxy.x,body->whxy.y);
559
+        IMDEBUG2((stderr,"%ix%i+%i+%i\n",body->leftsize, body->whxy.h,body->whxy.x,body->whxy.y));
553 560
         /* draw right side background */
554
-#if 1
555
-fprintf(stderr,"body->whxy:%ix%i+%i+%i\n",UNROLLWHXY(body->whxy));
556
-fprintf(stderr,"body->leftsize:%i\n",body->leftsize);
557
-#endif
561
+        IMDEBUG2((stderr,"body->whxy:%ix%i+%i+%i\n",UNROLLWHXY(body->whxy)));
562
+        IMDEBUG2((stderr,"body->leftsize:%i\n",body->leftsize));
558 563
         IMDEBUG("draw right bg");
559 564
         DrawRectangle(body->whxy.x+body->leftsize,body->whxy.y,body->whxy.w-body->leftsize, body->whxy.h, (Color){ 227, 227, 227, 255 } );
560
-fprintf(stderr,"DrawRectangle(body->whxy.x(%i)+body->leftsize(%i),body->whxy.y(%i),body->whxy.w(%i)-body->leftsize(%i), body->whxy.h(%i), (Color){ 227, 227, 227, 255 } );\n"
561
-        ,body->whxy.x,body->leftsize,body->whxy.y,body->whxy.w,body->leftsize, body->whxy.h);
562
-
563
-fprintf(stderr,"%ix%i+%i+%i\n",body->whxy.w-body->leftsize, body->whxy.h,body->whxy.x+body->leftsize,body->whxy.y);
565
+        IMDEBUG2((stderr,"DrawRectangle(body->whxy.x(%i)+body->leftsize(%i),body->whxy.y(%i),body->whxy.w(%i)-body->leftsize(%i), body->whxy.h(%i), (Color){ 227, 227, 227, 255 } );\n"
566
+        ,body->whxy.x,body->leftsize,body->whxy.y,body->whxy.w,body->leftsize, body->whxy.h));
567
+        IMDEBUG2((stderr,"%ix%i+%i+%i\n",body->whxy.w-body->leftsize, body->whxy.h,body->whxy.x+body->leftsize,body->whxy.y));
564 568
         /* reset lazy load marks */
565 569
         bg_resetmarks(body->bg);
566 570
         /* first pass, draw leftside, second pass, draw all of rightside */
... ...
@@ -648,6 +652,7 @@ DrawRectangle(UNROLLXYWH(body->backwhxy),((Color){ 0,255,0,255 })); /* hit zone
648 652
                                 FILLWHXY(thumb->screenwhxy,0,0,0,0);
649 653
                         }
650 654
                         /* files */
655
+                        imageundermouse[0]='\0';
651 656
                         for(k=0,lastx=lasty=0;k<dirdata->listing.usedelems;k++) {
652 657
                                 Texture2D *te;
653 658
                                 whxy_t *whxy;
... ...
@@ -669,6 +674,10 @@ DrawRectangle(UNROLLXYWH(body->backwhxy),((Color){ 0,255,0,255 })); /* hit zone
669 674
                                 /* show image */
670 675
                                 has_imagedrawn=0;
671 676
                                 if(is_imagefilename(elem->name+1) && !(thumb->screenwhxy.y>(body->whxy.y+body->whxy.h) || (thumb->screenwhxy.y+thumb->screenwhxy.h)<body->whxy.y)) {
677
+                                        if(is_global_insidewhxy(mousedata->mousepos,&(thumb->screenwhxy),0)) {
678
+                                                snprintf(imageundermouse,sizeof(imageundermouse),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
679
+                                                imageundermouse[sizeof(imageundermouse)-1]='\0';
680
+                                        }
672 681
                                         if(thumb->has_texture==0 && thumb->has_failedload==0) {
673 682
                                                 bgload_t *bgload;
674 683
                                                 char fullpath[2048];
... ...
@@ -774,6 +783,8 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
774 783
                                         selectedthumb=thumb;
775 784
                                 }
776 785
                         }
786
+                        if(imageundermouse[0]!='\0')
787
+                                bg_add(body->bg,imageundermouse); /* to prioritise loading this image */
777 788
                         for(;k<dirdata->listing.usedelems;k++) {
778 789
                                 elem=dirdata->listing.elems+k;
779 790
                                 if(elem->name[0]!='f' && elem->name[0]!='l')
Browse code

Change ordering of background image loading to last added

Dario Rodriguez authored on 22/09/2025 17:20:32
Showing 1 changed files
... ...
@@ -30,7 +30,8 @@
30 30
 
31 31
 #define DEFAULTWIDTH 1280
32 32
 #define DEFAULTHEIGHT 768
33
-#define LEFTIMAGESIDELEN 326
33
+//#define LEFTIMAGESIDELEN 326
34
+#define LEFTIMAGESIDELEN 64
34 35
 #define SCROLLTHRESHOLD (LEFTIMAGESIDELEN/3)
35 36
 #define WHEELSTEP LEFTIMAGESIDELEN
36 37
 #define SEP '/'
Browse code

Move video init and mouse logic to rayui.c/rayui.h . Move background loading to bg.c/bg.h

Dario Rodriguez authored on 20/09/2025 18:36:52
Showing 1 changed files
... ...
@@ -1,40 +1,11 @@
1 1
 /*
2 2
  * imgmover.c
3 3
  *
4
- * Simple C application using raylib to move images between directories.
4
+ * Simple C application using raylib to cselect/rotate/classify/arrange photos.
5 5
  *
6 6
  * History:
7
- *      20250119 Creation. Menu bar.
8
- *      20250123 Load font.
9
- *      20250213 Support sticky drop-down menus.
10
- *      20250216 Modularize menu handling.
11
- *      20250222 Able to list files.
12
- *      20250223 Draw pane titles and main dir list.
13
- *      20250224 Draw right dir list and store elem positions.
14
- *      20250225 Draw image placeholders
15
- *      20250226 Fix rightside positions
16
- *      20250228 Navigate directories
17
- *      20250301 Aesthetic fixes for leftside.
18
- *               Basic image loading.
19
- *               Show big image on hover.
20
- *               Preserve aspect ratio of big image.
21
- *      20250305 Scrollable left pane.
22
- *      20250308 Show statustooltip on image hover.
23
- *               Scrollwheel support for leftside.
24
- *               Fix thumb aspect ratio.
25
- *      20250311 Fix bug because of stray CloseWindow() call.
26
- *               Add show using all window with right button.
27
- *      20250316 Add android target support.
28
- *               Delay loading images if over fps deadline.
29
- *               Scroll by finger. Big image on double click.
30
- *      20250319 Add-dirdata button.
31
- *      20250320 Fix add-dirdata button appearance.
32
- *               Dirdata colors. Select dirdata.
33
- *      20250329 Background loading of thumbnails.
34
- *      20250330 Refine background loading.
35
- *      20250413 Background loading for windows target.
36
- *      20250420 Fix background loading for windows target.
37
- *      20250427 Start move image functionality.
7
+ *      20250902 Rewrite using parts of old prototype.
8
+ *      20250920 Reimplemented all scroll functionality.
38 9
  *
39 10
  * Author: Dario Rodriguez dario@darionomono.com
40 11
  * (c) Dario Rodriguez 2025
... ...
@@ -54,152 +25,32 @@
54 25
 #include "win32_pipe.h"
55 26
 #endif
56 27
 
57
-#include "raylib.h"
58
-#include "roboto_regular.c"
28
+#include "rayui.h"
29
+#include "bg.h"
59 30
 
60
-#define UTF8DOWNARROW "\xe2\x86\x86" /* U+2186 in UTF-8 */
61
-
62
-//#ifndef ANDROID
63
-//#define SIMANDROID
64
-//#endif
65
-
66
-#define TARGETFPS 30
67
-
68
-#if defined(ANDROID) || defined(SIMANDROID)
69
-#define ROOTDIR "/sdcard/"
70
-#define DEFAULTWIDTH 2400
71
-#define DEFAULTHEIGHT 1080
72
-#define LEFTSIZE 1600
73
-#define DEFAULTDIRDATAHEIGHT 492
74
-#define DEFAULTDIRDATATRIANGLEW 100
75
-#define LEFTIMAGESIDELEN 326
76
-#define FONTSIZE 64
77
-#define FONTBIGSIZE 96
78
-#define FONTHUGESIZE 128
79
-#define ADDREMOVEDIRDATAHEIGHT 128
80
-#else
81
-#if !defined(__linux__) && !defined(ANDROID)
82
-#define ROOTDIR "Z:\\"
83
-#define SEP "\\"
84
-#else
85
-//#define ROOTDIR "/var/www/default/animeshot/"
86
-#define ROOTDIR "/"
87
-#define SEP "/"
88
-#endif
89 31
 #define DEFAULTWIDTH 1280
90 32
 #define DEFAULTHEIGHT 768
91
-#define LEFTSIZE 720
92
-#define DEFAULTDIRDATAHEIGHT 150
93
-#define DEFAULTDIRDATATRIANGLEW 35
94
-#define LEFTIMAGESIDELEN 125
95
-#define FONTSIZE 18
96
-#define FONTBIGSIZE 32
97
-#define FONTHUGESIZE 48
98
-#define ADDREMOVEDIRDATAHEIGHT 128
99
-#endif
100
-
33
+#define LEFTIMAGESIDELEN 326
101 34
 #define SCROLLTHRESHOLD (LEFTIMAGESIDELEN/3)
102
-
103
-
104
-#if defined(SIMANDROID)
105
-#undef ROOTDIR
106
-#define ROOTDIR "/var/www/default/animeshot/"
107
-#endif
108
-
109 35
 #define WHEELSTEP LEFTIMAGESIDELEN
110
-
111
-
36
+#define SEP '/'
37
+#define SIZEBGLOAD 256
38
+#define DEFAULTDIRDATAHEIGHT 492
39
+#define ADDREMOVEDIRDATAHEIGHT 128
40
+#define UTF8DOWNARROW "\xe2\x86\x86" /* U+2186 in UTF-8 */
41
+#define DEFAULTDIRDATATRIANGLEW 35
112 42
 #define BLOCKLISTINGBUF 2048
113 43
 #define BLOCKLISTINGELEMS 1024
114 44
 #define BLOCKDIRDATA 16
115
-#define SIZEBGLOAD 256
116 45
 
117
-#ifndef FILLXY
118
-#define FILLXY(xywh,valx,valy) (xywh).x=(valx),(xywh).y=(valy)
119
-#endif
46
+#define MYFUNC "UNKNOWN"
47
+#define IMDEBUG(a) fprintf(stderr,"%s:%i: %s: %s\n",__FILE__,__LINE__,MYFUNC,a)
120 48
 
121
-#ifndef FILLWH
122
-#define FILLWH(xywh,valw,valh) (xywh).w=(valw),(xywh).h=(valh)
123
-#endif
124
-
125
-#ifndef FILLXYWH
126
-#define FILLXYWH(xywh,valx,valy,valw,valh) (xywh).x=(valx),(xywh).y=(valy),(xywh).w=(valw),(xywh).h=(valh)
127
-#endif
128
-
129
-#ifndef UNROLLXYWH
130
-#define UNROLLXYWH(xywh) (xywh).x,(xywh).y,(xywh).w,(xywh).h
131
-#endif
132
-
133
-#ifndef UNROLLWHXY
134
-#define UNROLLWHXY(xywh) (xywh).w,(xywh).h,(xywh).x,(xywh).y
135
-#endif
136
-
137
-#ifndef RD
138
-#define RD 0
139
-#endif
140
-
141
-#ifndef WR
142
-#define WR 1
143
-#endif
144
-
145
-#if !defined(__linux__) && !defined(ANDROID)
146
-int MessageBoxA(void *hWnd,void *lpText,void *lpCaption,unsigned int uType);
147
-#define messagebox(str) MessageBoxA(NULL,str,"imgmover",0);
148
-#else
149
-#define messagebox(str) fprintf(stderr,"%s\n",str);
150
-#endif
151
-
152
-
153
-
154
-#if !defined(__linux__) && !defined(ANDROID) && RAYLIB_VERSION_MAJOR==5 && RAYLIB_VERSION_MINOR==0
155
-/* the old raylib used in the windows build lacks this function */
156
-bool IsImageValid(Image image)
157
-{
158
-    bool result = false;
159
-
160
-    if ((image.data != NULL) &&     // Validate pixel data available
161
-        (image.width > 0) &&        // Validate image width
162
-        (image.height > 0) &&       // Validate image height
163
-        (image.format > 0) &&       // Validate image format
164
-        (image.mipmaps > 0)) result = true; // Validate image mipmaps (at least 1 for basic mipmap level)
165
-
166
-    return result;
167
-}
168
-#endif
169
-
170
-typedef struct xywh_t {
171
-        int x;
172
-        int y;
173
-        int w;
174
-        int h;
175
-} xywh_t;
176
-
177
-typedef struct font_t {
178
-        Font font;
179
-        int height;
180
-} font_t;
181
-
182
-typedef struct menudata_t {
183
-        char *title;
184
-        xywh_t xywh;
185
-        int sizeoptions;
186
-        char **options;
187
-        xywh_t optionsxywh;
188
-        int flag_open;
189
-        int flag_stickyopen;
190
-        int currentoption;
191
-} menudata_t;
192
-
193
-typedef struct menubar_t {
194
-        int height;
195
-        int sizemenudata;
196
-        menudata_t **menudata;
197
-        font_t *ptrfont;
198
-} menubar_t;
49
+// RIGHTSIDEMARGIN=FONTBIGSIZE/2
199 50
 
200 51
 typedef struct thumb_t {
201
-        xywh_t xywh;
202
-        xywh_t screenxywh;
52
+        whxy_t whxy;
53
+        whxy_t screenwhxy;
203 54
         Texture2D texture;
204 55
         int has_texture;
205 56
         int has_failedload;
... ...
@@ -218,9 +69,9 @@ typedef struct listing_t {
218 69
         int sizebuf;
219 70
         int usedbuf;
220 71
         char *buf;
221
-        int has_leftxywh;
222
-        int has_rightxywh;
223
-        xywh_t lastleftxywh;
72
+        int has_leftwhxy;
73
+        int has_rightwhxy;
74
+        whxy_t lastleftwhxy;
224 75
 } listing_t;
225 76
 
226 77
 typedef struct dirdata_t {
... ...
@@ -237,35 +88,14 @@ typedef struct texture_t {
237 88
         int textureh;
238 89
         int has_texture;
239 90
         int has_failedload;
240
-        xywh_t source; /* be able to detect a "double click" */
91
+        whxy_t source; /* be able to detect a "double click" */
241 92
 } texture_t;
242 93
 
243
-typedef struct bgload_t {
244
-        /* main/thread ownership management */
245
-        int lended_to_thread; // written from main, read from thread
246
-        int thread_finished; // written from thread, read from main
247
-        int is_todo;  // written from main, read from thread
248
-        int has_mark;  // written/read from main
249
-        /* data only accessed from owner */
250
-        char path[1024]; // to use only from owner
251
-        Image image; // to use only from owner
252
-        int has_data; // to use only from owner
253
-        int has_failedload; // to use only from owner
254
-} bgload_t;
255
-
256
-typedef struct bg_t {
257
-        int sizebgload;
258
-        bgload_t *bgload;
259
-        int pipe[2];
260
-        pthread_t thread;
261
-        pthread_attr_t tattr;
262
-        int flag_threadstarted;
263
-} bg_t;
264
-
265 94
 typedef struct body_t {
95
+        rayui_t *rayui;
266 96
         char *rootdir;
267
-        xywh_t xywh;
268
-        xywh_t backxywh;
97
+        whxy_t whxy;
98
+        whxy_t backwhxy;
269 99
         int leftsize;
270 100
         int sizedirdata;
271 101
         dirdata_t **dirdata;
... ...
@@ -278,223 +108,74 @@ typedef struct body_t {
278 108
         int is_displayingtexture;
279 109
         texture_t bigtexture;
280 110
         int flag_drawbigtexture;
281
-        xywh_t dirdataadd;
111
+        whxy_t dirdataadd;
282 112
         Font roundedbox;
283 113
         bg_t *bg;
284 114
         char selectedpath[2048];
285 115
 } body_t;
286 116
 
117
+
287 118
 typedef struct im_t {
288
-        int windowinit;
289
-        int w;
290
-        int h;
291
-        menubar_t *menubar;
119
+        rayui_t *rayui;
120
+        mousedata_t mousedata;
292 121
         body_t *body;
293
-        font_t *font;
294
-        font_t *fontbig;
295
-        font_t *fonthuge;
296 122
 } im_t;
297 123
 
298
-
299
-im_t *im_init(char *menus, char *rootdir);
124
+im_t *im_init(char *rootdir);
300 125
 void im_free(im_t *im);
301 126
 
302
-font_t *im_font_init(int size);
303
-void im_font_free(font_t *font);
304
-
305
-menubar_t *im_menubar_init(char *menus, font_t *font);
306
-void im_menubar_free(menubar_t *menubar);
307
-
308
-int im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail, char **sel_menu, char **sel_submenu);
309
-int im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight, int *needs_nextredraw);
310
-
311
-body_t *im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir, int windowwidth, int windowheight);
127
+body_t *im_body_init(rayui_t *rayui, int w, int h, int x, int y, int leftsidesize, char *rootdir);
312 128
 void im_body_free(body_t *body);
313 129
 
314 130
 int im_body_add(body_t *body,char *dir);
315 131
 int im_body_tryselect(body_t *body, Vector2 mousepos);
316 132
 
133
+int im_body_mouse(body_t *body, mousedata_t *mousedata);
134
+int im_body_draw(body_t *body, mousedata_t *mousedata, int windowwidth, int windowheight, int *needs_nextredraw);
317 135
 
318
-int im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
319
-int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight, int *needs_nextredraw, int scrollspeed);
320
-
136
+static int strptrcmp(void *a,void *b);
321 137
 int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort);
322 138
 void listing_freedata(listing_t *listing);
323
-int listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_left);
139
+int listing_fillwhxy(listing_t *listing, font_t *font, int w, int sidelen, int is_left, int rightsidemargin);
140
+
141
+int is_imagefilename(char *filename);
324 142
 
325 143
 int texture_load(texture_t *texture, char *fullpath, int maxw, int maxh, bg_t *bg);
326 144
 int texture_draw(texture_t *texture, int x0, int y0, int maxw, int maxh);
327 145
 int texture_freedata(texture_t *texture);
328 146
 
329
-int imutil_menu_count(char *menus);
330
-char *imutil_menu_get(char *menus, int targetn, int *len);
331
-int imutil_submenu_count(char *menus);
332
-char *imutil_submenu_get(char *menus, int targetn, int *len);
333
-char *imutil_strduplen(char *str, int len);
334
-int is_imutil_insidexywh(Vector2 pos, xywh_t *xywh, int margin);
335 147
 int imutil_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh);
336
-int menudata_pos2option(menudata_t *menudata, Vector2 pos);
337
-int *getcodepoints(int *sizecodepoints);
338
-int is_imagefilename(char *filename);
339
-Image imutil_loadimage(const char *filename);
340
-void imutil_fpsreset(void);
341
-int imutil_fpsleft(void);
342
-long long imutil_milliseconds(void);
343
-
344
-bg_t *bg_init(int sizebgload);
345
-void bg_free(bg_t *bg);
346
-int bg_resetmarks(bg_t *bg);
347
-bgload_t *bg_get(bg_t *bg, char *path);
348
-int bg_add(bg_t *bg, char *path);
349
-int bg_freeunmarked(bg_t *bg);
350 148
 
351
-void *bg_thread(void *);
352
-
353
-static int mypipe(int fds[2]);
354
-static int mypiperead(int fd, char *buf, int count);
355
-static int mypipewrite(int fd, char *buf, int count);
356 149
 
357 150
 int
358 151
 main(int argc, char *argv[])
359 152
 {
360 153
         im_t *im;
361
-        Vector2 mousepos,wheel,oldmousepos,scrollstartpos;
362
-        int flag_ignorelmb;
363
-        int lmbpressed,lmbreleased,lmbdown,rmbdown,oldlmbdown,oldrmbdown;
364
-        int click_avail;
365
-        int has_mousechanges;
154
+        char *rootdir;
366 155
         int needs_nextredraw;
367
-        long long scrollstart;
368
-        long long scrolllast;
369
-        int scrollspeed;
370
-        int is_scrolling;
371
-        int leftscrollposstart;
372
-        char *sel_menu,*sel_submenu;
373
-#if !defined(__linux__) && !defined(ANDROID)
374
-        win32pipe_init();
375
-#endif
376
-        if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n",ROOTDIR))==NULL) {
377
-                messagebox("Couldn't init interface");
156
+        if(argc<2 || strcmp(argv[argc-1],"--help")==0) {
157
+                global_messagebox("imgmover\n\nSyntax: %s <rootdirectory>\n",(argc>0)?argv[0]:"imgmover");
158
+                return(1);
159
+        }
160
+        rootdir=argv[1];
161
+        bg_staticinit();
162
+        if((im=im_init(rootdir))==NULL) {
163
+                global_messagebox("%s","Couldn't init");
378 164
                 return(1);
379 165
         }
380
-        flag_ignorelmb=0;
381
-        mousepos=(Vector2) {.x=0,.y=0};
382
-        lmbdown=rmbdown=-1;
383
-        needs_nextredraw=1;
384
-        scrollstart=0;
385
-        is_scrolling=0;
386
-        im->body->selectedpath[0]='\0';
387 166
         while(!WindowShouldClose()) {
388
-                imutil_fpsreset();
389
-                oldmousepos=mousepos;
390
-                mousepos=GetMousePosition();
391
-                wheel=GetMouseWheelMoveV();
392
-                lmbpressed=IsMouseButtonPressed(0);
393
-                lmbreleased=IsMouseButtonReleased(0);
394
-                oldlmbdown=lmbdown;
395
-                lmbdown=IsMouseButtonDown(0);
396
-                oldrmbdown=rmbdown;
397
-                rmbdown=IsMouseButtonDown(1);
398
-                click_avail=1;
399
-                has_mousechanges=(lmbdown!=oldlmbdown || rmbdown!=oldrmbdown || mousepos.x!=oldmousepos.x || mousepos.y!=oldmousepos.y || wheel.x!=0 || wheel.y!=0)?1:0;
167
+                rayui_timereset(im->rayui);
400 168
                 needs_nextredraw=0;
401
-                /* mouse process scrolling */
402
-                if(lmbdown==1 && oldlmbdown==0 && scrollstart==0 && mousepos.y>im->body->xywh.y) {
403
-                        scrollstart=imutil_milliseconds();
404
-                        scrollstartpos=mousepos;
405
-                        leftscrollposstart=im->body->dirdata[im->body->currentdirdata]->leftscrollpos;
406
-                }
407
-                if(scrollstart!=0 && lmbdown==0) {
408
-                        scrollstart=0;
409
-                        if(is_scrolling)
410
-                                click_avail=0; /* this click is the mouseup of the scroll */
411
-                }
412
-                is_scrolling=(scrollstart==0)?0:is_scrolling;
413
-                if(is_scrolling==0 && scrollstart!=0) {
414
-                        float t;
415
-                        t=scrollstartpos.y-mousepos.y;
416
-                        t=(t<0)?-t:t;
417
-                        if(t>SCROLLTHRESHOLD) {
418
-                                is_scrolling=1;
419
-                                scrolllast=0;
420
-                        }
421
-                        t=scrollstartpos.x-mousepos.x;
422
-                        t=(t<0)?-t:t;
423
-                        if(t>SCROLLTHRESHOLD) {
424
-                                is_scrolling=0,scrollstart=0;
425
-                                im_body_tryselect(im->body,scrollstartpos);
426
-                                if(im->body->selectedpath[0]!='\0')
427
-                                        click_avail=0;
428
-                        }
429
-                }
430
-                if(is_scrolling) {
431
-                        long long tcur,tdif;
432
-                        long long ycur;
433
-                        tcur=imutil_milliseconds();
434
-                        tdif=tcur-scrolllast;
435
-                        ycur=scrollstartpos.y-mousepos.y;
436
-                        scrollspeed=(tdif>0)?(oldmousepos.y-mousepos.y)*100000/tdif:0;
437
-                        im->body->dirdata[im->body->currentdirdata]->leftscrollpos=leftscrollposstart+ycur;
438
-                        scrolllast=tcur;
439
-                }
440
-                if(is_scrolling==0 && scrollspeed!=0) {
441
-                        scrollspeed=scrollspeed*4/5;
442
-                        im->body->dirdata[im->body->currentdirdata]->leftscrollpos+=scrollspeed;
443
-                }
444
-                /* mouse process clicks on menus */
445
-                if(click_avail) {
446
-                        sel_menu=sel_submenu=NULL;
447
-                        im_menubar_mouse(im->menubar, mousepos, lmbpressed, lmbreleased, lmbdown, &click_avail, &sel_menu, &sel_submenu);
448
-                        if(sel_menu!=NULL && sel_submenu!=NULL) {
449
-
450
-#if 1
451
-fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
452
-#endif
453
-                                if(strcmp(sel_submenu,"Salir")==0)
454
-                                        break; /* exit from main loop */
455
-                        }
456
-                }
457
-                if(click_avail)
458
-                        im_body_mouse(im->body, mousepos, wheel, lmbpressed, lmbreleased, lmbdown, &click_avail);
169
+                rayui_getmousedata(im->rayui,&(im->mousedata));
170
+                /* process mouse actions */
171
+                if(im->mousedata.click_avail)
172
+                        im_body_mouse(im->body, &(im->mousedata));
459 173
                 /* draw screen contents */
460 174
                 BeginDrawing();
461 175
                 ClearBackground(RAYWHITE);
462
-                im_body_draw(im->body,mousepos,lmbdown,rmbdown,im->w,im->h,&needs_nextredraw,scrollspeed);
463
-                im_menubar_draw(im->menubar,im->w,im->h,&needs_nextredraw);
464
-#if 0
465
-{
466
- int i,j;
467
- Vector2 v2;
468
- listing_t listing={0};
469
- if(listing_get(&listing,"..",".",1)==0) {
470
-   i=2;
471
-     v2.x=(float) (im->font->height/2);
472
-     v2.y=(float) ((im->font->height+im->font->height/2)*i+(im->font->height/4));
473
-     DrawTextEx(im->font->font
474
-       ,SEP
475
-       ,v2
476
-       ,im->font->height
477
-       ,0
478
-       ,((Color){ 45, 45, 45, 255 })
479
-     );
480
-   for(j=0;j<listing.usedelems;j++) {
481
-     Color c;
482
-     i++;
483
-     c=((Color){ 45, 45, 45, 255 });
484
-     v2.x=(float) (im->font->height/2);
485
-     v2.y=(float) ((im->font->height+im->font->height/2)*i+(im->font->height/4));
486
-     DrawTextEx(im->font->font
487
-       ,listing.elems[j].name
488
-       ,v2
489
-       ,im->font->height
490
-       ,0
491
-       ,c
492
-     );
493
-   }
494
- }
495
-}
496
-#endif
497
-                if(has_mousechanges==0 && needs_nextredraw==0 && scrollspeed==0) {
176
+                rayui_scrollablerectreset(im->rayui,&(im->mousedata));
177
+                im_body_draw(im->body,&(im->mousedata),im->rayui->w,im->rayui->h,&needs_nextredraw);
178
+                if(needs_nextredraw==0 && im->mousedata.has_mousechanges==0 && im->mousedata.scrollspeed==0) {
498 179
                         /* Wait for new events when calling EndDrawing() */
499 180
                         EnableEventWaiting();
500 181
                 } else {
... ...
@@ -504,39 +185,26 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
504 185
                 EndDrawing();
505 186
         }
506 187
         im_free(im),im=NULL;
507
-#if !defined(__linux__) && !defined(ANDROID)
508
-        win32pipe_fini();
509
-#endif
188
+        bg_staticfini();
510 189
         return(0);
511 190
 }
512 191
 
192
+
513 193
 im_t *
514
-im_init(char *menus, char *rootdir)
194
+im_init(char *rootdir)
515 195
 {
516 196
         im_t *im;
517 197
         char *errstr;
518
-        if(menus==NULL)
519
-                return(NULL); /* sanity check failed */
520 198
         if((im=calloc(1,sizeof(im_t)))==NULL) {
521 199
                 im_free(im),im=NULL;
522 200
                 return(NULL); /* insuf. mem. */
523 201
         }
524
-        /* init window */
525
-        SetTraceLogLevel(LOG_ERROR);
526
-        InitWindow((im->w=DEFAULTWIDTH),(im->h=DEFAULTHEIGHT),"Image Mover");
527
-        im->windowinit=1;
528
-        SetTargetFPS(30);
529
-        /* init fonts and contents */
530
-        if((errstr="Couldn't init font")==NULL
531
-          || (im->font=im_font_init(FONTSIZE))==NULL
532
-          || (im->fontbig=im_font_init(FONTBIGSIZE))==NULL
533
-          || (im->fonthuge=im_font_init(FONTHUGESIZE))==NULL
534
-          || (errstr="Couldn't init menus")==NULL
535
-          || (im->menubar=im_menubar_init(menus,im->font))==NULL
202
+        if((errstr="init interface")==NULL
203
+          || (im->rayui=rayui_init(DEFAULTWIDTH,DEFAULTHEIGHT,"Image Mover",NULL))==NULL
536 204
           || (errstr="Couldn't init interface data")==NULL
537
-          || (im->body=im_body_init(0,im->menubar->height, im->font, im->fontbig, im->fonthuge, LEFTSIZE, rootdir,im->w,im->h))==NULL
205
+          || (im->body=im_body_init(im->rayui,im->rayui->w,im->rayui->h, 0, 0, im->rayui->w*2/3, rootdir))==NULL
538 206
         ) {
539
-                messagebox(errstr);
207
+                global_messagebox("Couldn't %s",errstr);
540 208
                 im_free(im),im=NULL;
541 209
                 return(NULL); /* insuf. mem. */
542 210
         }
... ...
@@ -550,299 +218,21 @@ im_free(im_t *im)
550 218
 {
551 219
         if(im==NULL)
552 220
                 return;
553
-        if(im->menubar!=NULL)
554
-                im_menubar_free(im->menubar),im->menubar=NULL;
555 221
         if(im->body!=NULL)
556 222
                 im_body_free(im->body),im->body=NULL;
557
-        if(im->font!=NULL)
558
-                im_font_free(im->font),im->font=NULL;
559
-        if(im->fontbig!=NULL)
560
-                im_font_free(im->fontbig),im->fontbig=NULL;
561
-        if(im->fonthuge!=NULL)
562
-                im_font_free(im->fonthuge),im->fonthuge=NULL;
563
-        if(im->windowinit)
564
-                CloseWindow(),im->windowinit=0;
223
+        if(im->rayui!=NULL)
224
+                rayui_free(im->rayui),im->rayui=NULL;
565 225
         free(im),im=NULL;
566
-        return;
567
-}
568
-
569
-font_t *
570
-im_font_init(int size)
571
-{
572
-        font_t *font;
573
-        int sizecodepoints;
574
-        int *codepoints;
575
-        if((font=calloc(1,sizeof(font_t)))==NULL)
576
-                return(NULL); /* insuf. mem. */
577
-        font->height=size;
578
-        codepoints=getcodepoints(&sizecodepoints);
579
-        font->font=LoadFontFromMemory(".ttf",(const unsigned char *)roboto_regular,sizeof(roboto_regular)-1,font->height,codepoints,sizecodepoints);
580
-        return(font);
581
-}
582
-
583
-void
584
-im_font_free(font_t *font)
585
-{
586
-        if(font==NULL)
587
-                return;
588
-        /* NOTE: Cannot call UnloadFont(font->font) as the data was not malloc'd; see https://github.com/raysan5/raylib/blob/master/examples/others/embedded_files_loading.c */
589
-        free(font),font=NULL;
590
-        return;
591
-}
592
-
593
-menubar_t *
594
-im_menubar_init(char *menus, font_t *font)
595
-{
596
-        int i,j;
597
-        char *str,*substr;
598
-        int len,sublen;
599
-        menubar_t *menubar;
600
-        menudata_t *menudata;
601
-        if(menus==NULL || font==NULL)
602
-                return(NULL); /* sanity check failed */
603
-        if((menubar=calloc(1,sizeof(menubar_t)))==NULL
604
-          || (menubar->sizemenudata=imutil_menu_count(menus))<=0
605
-          || (menubar->menudata=calloc(menubar->sizemenudata,sizeof(menudata_t)))==NULL
606
-        ) {
607
-                im_menubar_free(menubar),menubar=NULL;
608
-                return(NULL); /* insuf. mem. */
609
-        }
610
-        menubar->ptrfont=font;
611
-        menubar->height=font->height+font->height/2;
612
-        /* init menus */
613
-        for(i=0;i<menubar->sizemenudata;i++) {
614
-                if((menudata=menubar->menudata[i]=calloc(1,sizeof(menudata_t)))==NULL
615
-                  || (str=imutil_menu_get(menus,i,&len))==NULL
616
-                  || (menudata->title=imutil_strduplen(str,len))==NULL
617
-                  || (menudata->sizeoptions=imutil_submenu_count(str))<=0
618
-                  || (menudata->options=calloc(menudata->sizeoptions,sizeof(char *)))==NULL
619
-                ) {
620
-                        im_menubar_free(menubar),menubar=NULL;
621
-                        return(NULL); /* insuf. mem. */
622
-                }
623
-                for(j=0;j<menudata->sizeoptions;j++) {
624
-                        if((substr=imutil_submenu_get(str,j,&sublen))==NULL
625
-                          || (menudata->options[j]=imutil_strduplen(substr,sublen))==NULL
626
-                        ) {
627
-                                im_menubar_free(menubar),menubar=NULL;
628
-                                return(NULL); /* insuf. mem. */
629
-                        }
630
-                }
631
-        }
632
-#if 0
633
-        /* test imutil_menu_xxx */
634
-        int n,m,l,ml,len,mlen;
635
-        char *ptr,*mptr;
636
-        for(n=0,l=imutil_menu_count(menus);n<l;n++) {
637
-                ptr=imutil_menu_get(menus,n,&len);
638
-                fprintf(stderr,"menu[%i]:\"",n);
639
-                fwrite(ptr,1,len,stderr);
640
-                fprintf(stderr,"\"->");
641
-                for(m=0,ml=imutil_submenu_count(ptr);m<ml;m++) {
642
-                        mptr=imutil_submenu_get(ptr,m,&mlen);
643
-                        fprintf(stderr,"|\"");
644
-                        fwrite(mptr,1,mlen,stderr);
645
-                        fprintf(stderr,"\"");
646
-                }
647
-                fprintf(stderr,"\n");
648
-        }
649
-#endif
650
-#if 0
651
-        /* test menudata */
652
-        for(i=0;i<menubar->sizemenudata;i++) {
653
-                fprintf(stderr,"menu[%i]:\"%s\"->",i,menubar->menudata[i]->title);
654
-                for(j=0;j<menubar->menudata[i]->sizeoptions;j++)
655
-                        fprintf(stderr,"|\"%s\"",menubar->menudata[i]->options[j]);
656
-                fprintf(stderr,"\n");
657
-        }
658
-#endif
659
-        return(menubar);
660
-}
661
-
662
-void
663
-im_menubar_free(menubar_t *menubar)
664
-{
665
-        int i,j;
666
-        menudata_t *menudata;
667
-        if(menubar==NULL)
668
-                return;
669
-        if(menubar->menudata!=NULL) {
670
-                for(i=0;i<menubar->sizemenudata;i++) {
671
-                        if((menudata=menubar->menudata[i])==NULL)
672
-                                continue;
673
-                        if(menudata->title!=NULL)
674
-                                free(menudata->title),menudata->title=NULL;
675
-                        if(menudata->options!=NULL) {
676
-                                for(j=0;j<menudata->sizeoptions;j++) {
677
-                                        if(menudata->options[j]!=NULL)
678
-                                                free(menudata->options[j]),menudata->options[j]=NULL;
679
-                                }
680
-                                free(menudata->options),menudata->options=NULL,menudata->sizeoptions=0;
681
-                        }
682
-                        free(menubar->menudata[i]),menubar->menudata[i]=NULL,menudata=NULL;
683
-                }
684
-                free(menubar->menudata),menubar->menudata=NULL,menubar->sizemenudata=0;
685
-        }
686
-        free(menubar),menubar=NULL;
687
-        return;
688
-}
689
-
690
-int
691
-im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail, char **sel_menu, char **sel_submenu)
692
-{
693
-        int flag_outsideall;
694
-        int i,j;
695
-        if(menubar==NULL || click_avail==NULL || sel_menu==NULL || sel_submenu==NULL)
696
-                return(-1);
697
-        *click_avail=1;
698
-        *sel_menu=NULL;
699
-        *sel_submenu=NULL;
700
-        flag_outsideall=1;
701
-#if 0
702
-if(lmbpressed || lmbdown)
703
- fprintf(stderr,"in_menubar_mouse: lmbpressed:%i lmbdown:%i\n",lmbpressed,lmbdown);
704
-#endif
705
-        for(i=0;i<menubar->sizemenudata;i++) {
706
-                int insidetitle,currentoption;
707
-                insidetitle=is_imutil_insidexywh(mousepos,&(menubar->menudata[i]->xywh),0);
708
-                currentoption=menudata_pos2option(menubar->menudata[i],mousepos);
709
-                flag_outsideall=(currentoption!=-1 || insidetitle)?0:flag_outsideall;
710
-                if(lmbreleased && insidetitle) {
711
-                        for(j=0;j<menubar->sizemenudata;j++) {
712
-                                menubar->menudata[j]->flag_stickyopen=(j==i)?1:0;
713
-                                menubar->menudata[j]->flag_open=0;
714
-                                menubar->menudata[j]->currentoption=-1;
715
-                        }
716
-                } else if((lmbpressed || lmbdown) && insidetitle) {
717
-                        for(j=0;j<menubar->sizemenudata;j++) {
718
-                                menubar->menudata[j]->flag_open=(j==i)?1:0;
719
-                                menubar->menudata[j]->flag_stickyopen=0;
720
-                                menubar->menudata[j]->currentoption=-1;
721
-                        }
722
-                } else if((lmbdown || menubar->menudata[i]->flag_stickyopen) && currentoption!=-1) {
723
-                        for(j=0;j<menubar->sizemenudata;j++) {
724
-                                if(lmbreleased==0 || j!=i || menubar->menudata[i]->flag_stickyopen==0) {
725
-                                        menubar->menudata[j]->flag_open=(j==i)?menubar->menudata[i]->flag_open:0;
726
-                                        menubar->menudata[j]->flag_stickyopen=(j==i)?menubar->menudata[i]->flag_stickyopen:0;
727
-                                        menubar->menudata[j]->currentoption=(j==i)?currentoption:-1;
728
-                                } else {
729
-                                        menubar->menudata[j]->flag_open=0;
730
-                                        menubar->menudata[j]->flag_stickyopen=0;
731
-                                        menubar->menudata[j]->currentoption=-1;
732
-                                        /* has selected this submenu */
733
-                                        *click_avail=0;
734
-                                        *sel_menu=menubar->menudata[j]->title;
735
-                                        *sel_submenu=menubar->menudata[j]->options[currentoption];
736
-                                }
737
-                        }
738
-                } else if(menubar->menudata[i]->flag_stickyopen && currentoption==-1) {
739
-                        if(lmbreleased) {
740
-                                menubar->menudata[i]->flag_open=0;
741
-                                menubar->menudata[i]->flag_stickyopen=0;
742
-                        }
743
-                        menubar->menudata[i]->currentoption=-1;
744
-                } else if(lmbreleased && currentoption!=-1) {
745
-                        for(j=0;j<menubar->sizemenudata;j++) {
746
-                                menubar->menudata[j]->flag_open=0;
747
-                                menubar->menudata[j]->flag_stickyopen=0;
748
-                                menubar->menudata[j]->currentoption=-1;
749
-                        }
750
-                        /* has selected this submenu */
751
-                        *click_avail=0;
752
-                        *sel_menu=menubar->menudata[i]->title;
753
-                        *sel_submenu=menubar->menudata[i]->options[currentoption];
754
-                } else if(lmbdown==0) {
755
-                        menubar->menudata[i]->flag_open=0;
756
-                        menubar->menudata[i]->flag_stickyopen=0;
757
-                        menubar->menudata[i]->currentoption=-1;
758
-                }
759
-        }
760
-        if(flag_outsideall) {
761
-                for(j=0;j<menubar->sizemenudata;j++) {
762
-                        menubar->menudata[j]->currentoption=-1;
763
-                }
764
-        }
765
-        /* update click_avail */
766
-        for(j=0;j<menubar->sizemenudata;j++) {
767
-                if(menubar->menudata[j]->flag_open || menubar->menudata[j]->flag_stickyopen) {
768
-                        *click_avail=0;
769
-                        break;
770
-                }
771
-        }
772
-        return(0);
773
-}
774
-
775
-int
776
-im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight, int *needs_nextredraw)
777
-{
778
-        int i,j,k,x;
779
-        menudata_t *menudata;
780
-        font_t *font;
781
-        if(menubar==NULL)
782
-                return(-1); /* sanity check failed */
783
-        font=menubar->ptrfont;
784
-        DrawRectangle(0,0,windowwidth, font->height+font->height/2, (Color){ 235, 235, 235, 235 } );
785
-        for(i=0,x=0;i<menubar->sizemenudata;i++) {
786
-                Vector2 v2;
787
-                menudata=menubar->menudata[i];
788
-                v2=MeasureTextEx(font->font,menudata->title,font->height,0);
789
-                FILLXYWH(menudata->xywh,x,0,((int)v2.x)+font->height,font->height+font->height/2);
790
-                v2.x=(float) (menudata->xywh.x+font->height/2);
791
-                v2.y=(float) (menudata->xywh.y+font->height/4);
792
-                DrawTextEx(font->font
793
-                  ,menudata->title
794
-                  ,v2
795
-                  ,font->height
796
-                  ,0
797
-                  ,(Color){ 45, 45, 45, 255 }
798
-                );
799
-                if(menudata->flag_open || menudata->flag_stickyopen) {
800
-                        int underline_height=3;
801
-                        int maxw;
802
-                        DrawRectangle(menudata->xywh.x,menudata->xywh.y+menudata->xywh.h-underline_height,menudata->xywh.w,underline_height, (Color){ 53,132,228,255 } );
803
-                        for(j=0,maxw=0;j<menudata->sizeoptions;j++) {
804
-                                v2=MeasureTextEx(font->font,menudata->options[j],font->height,0);
805
-                                maxw=(((int)(v2.x))>maxw)?((int)(v2.x)):maxw;
806
-                        }
807
-                        maxw=(maxw<(menudata->xywh.w+font->height))?(menudata->xywh.w+font->height):maxw;
808
-                        maxw+=font->height;
809
-                        FILLXYWH(menudata->optionsxywh,menudata->xywh.x+1,menudata->xywh.y+menudata->xywh.h+2,maxw,(font->height+font->height/2)*menudata->sizeoptions);
810
-                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y-2,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y-2,(Color){ 255,255,255,255 } );
811
-                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y,menudata->optionsxywh.x-1,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 255,255,255,255 } );
812
-                        DrawLine(menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 192,192,192,255 } );
813
-                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y+menudata->optionsxywh.h+1,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 192,192,192,255 } );
814
-                        DrawRectangle(menudata->optionsxywh.x,menudata->optionsxywh.y,menudata->optionsxywh.w,menudata->optionsxywh.h,(Color){ 235, 235, 235, 235 });
815
-                        for(k=0;k<menudata->sizeoptions;k++) {
816
-                                Color c;
817
-                                c=(k==menudata->currentoption)?((Color){ 255,255,255,255 }):((Color){ 45, 45, 45, 255 });
818
-                                if(k==menudata->currentoption)
819
-                                        DrawRectangle(menudata->optionsxywh.x+1,menudata->optionsxywh.y+(font->height+(font->height/2))*k,menudata->optionsxywh.w-2,font->height+font->height/2,(Color){ 53,132,228,255 });
820
-                                v2.x=(float) (menudata->optionsxywh.x+font->height/2);
821
-                                v2.y=(float) (menudata->optionsxywh.y+(font->height/4)+(font->height+(font->height/2))*k);
822
-                                DrawTextEx(font->font
823
-                                  ,menudata->options[k]
824
-                                  ,v2
825
-                                  ,font->height
826
-                                  ,0
827
-                                  ,c
828
-                                );
829
-                        }
830
-                } else {
831
-                        FILLXYWH(menudata->optionsxywh,0,0,0,0);
832
-                }
833
-                x=menudata->xywh.x+menudata->xywh.w;
834
-        }
835
-        return(0);
836 226
 }
837 227
 
838 228
 body_t *
839
-im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir, int windowwidth, int windowheight)
229
+im_body_init(rayui_t *rayui, int w, int h, int x, int y, int leftsidesize, char *rootdir)
840 230
 {
841 231
         body_t *body;
842 232
         char *errstr;
843
-        static char sep[]={SEP};
844
-        if(font==NULL || fontbig==NULL || fonthuge==NULL || rootdir==NULL) {
845
-                messagebox("im_body_init sanity check failed");
233
+        static char sep[]={SEP,'\0'};
234
+        if(rayui->font==NULL || rayui->fontbig==NULL || rayui->fonthuge==NULL || rootdir==NULL) {
235
+                global_messagebox("im_body_init sanity check failed");
846 236
                 return(NULL); /* sanity check failed */
847 237
         }
848 238
         if((errstr="Insuf. mem. for body")==NULL
... ...
@@ -852,21 +242,25 @@ im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int
852 242
           || (errstr="Error init bg")==NULL
853 243
           || (body->bg=bg_init(SIZEBGLOAD))==NULL
854 244
         ) {
855
-                messagebox(errstr);
245
+                global_messagebox("%s",errstr);
856 246
                 im_body_free(body),body=NULL;
857 247
                 return(NULL);
858 248
         }
859
-        FILLXYWH(body->xywh,x,y,windowwidth-x,windowheight-y);
860
-        body->leftsize=leftsize;
861
-        body->ptrfont=font;
862
-        body->ptrfontbig=fontbig;
863
-        body->ptrfonthuge=fonthuge;
864
-        if(body->rootdir[0]!='\0' && strcmp(body->rootdir,SEP)!=0 && body->rootdir[strlen(body->rootdir)-1]==sep[0])
249
+        body->rayui=rayui;
250
+        FILLWHXY(body->whxy,w,h,x,y);
251
+#if 1
252
+fprintf(stderr,"im_body_init: %ix%i+%i+%i\n",UNROLLWHXY(body->whxy));
253
+#endif
254
+        body->leftsize=leftsidesize;
255
+        body->ptrfont=rayui->font;
256
+        body->ptrfontbig=rayui->fontbig;
257
+        body->ptrfonthuge=rayui->fonthuge;
258
+        if(body->rootdir[0]!='\0' && strcmp(body->rootdir,sep)!=0 && body->rootdir[strlen(body->rootdir)-1]==sep[0])
865 259
                 body->rootdir[strlen(body->rootdir)-1]='\0'; /* rootdir doesn't need the final '/' */
866 260
         /* init rounded box glyph (a really big zero) */
867 261
         {
868 262
                 int codepoints[]={'O','+','-'};
869
-                body->roundedbox=LoadFontFromMemory(".ttf",(const unsigned char *)roboto_regular,sizeof(roboto_regular)-1,ADDREMOVEDIRDATAHEIGHT*4,codepoints,sizeof(codepoints)/sizeof(codepoints[0]));
263
+                body->roundedbox=LoadFontFromMemory(".ttf",rayui->defaultfontdata,rayui->sizedefaultfontdata,ADDREMOVEDIRDATAHEIGHT*4,codepoints,sizeof(codepoints)/sizeof(codepoints[0]));
870 264
         }
871 265
         return(body);
872 266
 }
... ...
@@ -942,12 +336,12 @@ im_body_tryselect(body_t *body, Vector2 mousepos)
942 336
         if(body==NULL || body->currentdirdata<0 || body->currentdirdata>=body->sizedirdata || body->dirdata[body->currentdirdata]==NULL || body->currentdirdata>=body->sizedirdata)
943 337
                 return(-1); /* sanity check failed */
944 338
         body->selectedpath[0]='\0';
945
-        if(!is_imutil_insidexywh(mousepos,&(body->xywh),0) || mousepos.x>body->leftsize)
339
+        if(!is_global_insidewhxy(mousepos,&(body->whxy),0) || mousepos.x>body->leftsize)
946 340
                 return(-1); /* outside leftside */
947 341
         listing=&(body->dirdata[body->currentdirdata]->listing);
948 342
         for(i=0;i<listing->usedelems;i++) {
949 343
                 elem=listing->elems+i;
950
-                if(is_imutil_insidexywh(mousepos,&(elem->left.screenxywh),0)) {
344
+                if(is_global_insidewhxy(mousepos,&(elem->left.screenwhxy),0)) {
951 345
                         strncpy(body->selectedpath,elem->name,sizeof(body->selectedpath));
952 346
                         body->selectedpath[sizeof(body->selectedpath)-1]='\0';
953 347
                         return(0); /* found */
... ...
@@ -956,39 +350,40 @@ im_body_tryselect(body_t *body, Vector2 mousepos)
956 350
         return(-1); /* no thumbnail found for pos */
957 351
 }
958 352
 
959
-
960 353
 int
961
-im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail)
354
+im_body_mouse(body_t *body, mousedata_t *mousedata)
962 355
 {
963 356
         int i;
964 357
         char *ptr;
965 358
         dirdata_t *dirdata;
966 359
         listingdata_t *ld;
967 360
         int margin;
968
-        if(body==NULL || click_avail==NULL || body->currentdirdata<0 || body->currentdirdata>=body->sizedirdata || body->dirdata[body->currentdirdata]==NULL)
361
+        if(body==NULL || mousedata==NULL || body->currentdirdata<0 || body->currentdirdata>=body->sizedirdata || body->dirdata[body->currentdirdata]==NULL)
969 362
                 return(-1); /* sanity check error */
970 363
         dirdata=body->dirdata[body->currentdirdata];
971 364
         /* wheel */
972
-        body->dirdata[body->currentdirdata]->leftscrollpos-=(int)wheel.y*WHEELSTEP;
365
+        body->dirdata[body->currentdirdata]->leftscrollpos-=(int)mousedata->wheel.y*WHEELSTEP;
366
+        if(is_rayui_scrolling(body->rayui,mousedata,"body.leftside",&(body->dirdata[body->currentdirdata]->leftscrollpos)))
367
+                fprintf(stderr,"SCROLLING bosy.leftside newscrollpos:%i\n",body->dirdata[body->currentdirdata]->leftscrollpos); /* nothing to do, will fix coors for both wheel and scrolling in the next lines */
973 368
         body->dirdata[body->currentdirdata]->leftscrollpos=(body->dirdata[body->currentdirdata]->leftscrollpos<0)?0:body->dirdata[body->currentdirdata]->leftscrollpos;
974
-        if(body->dirdata[body->currentdirdata]->leftscrollpos>dirdata->listing.lastleftxywh.y)
975
-                body->dirdata[body->currentdirdata]->leftscrollpos=dirdata->listing.lastleftxywh.y;
369
+        if(body->dirdata[body->currentdirdata]->leftscrollpos>dirdata->listing.lastleftwhxy.y)
370
+                body->dirdata[body->currentdirdata]->leftscrollpos=dirdata->listing.lastleftwhxy.y;
976 371
         /* check if we have to process a click */
977
-        if(*click_avail==0 || lmbreleased==0)
372
+        if(mousedata->click_avail==0 || mousedata->lmbreleased==0)
978 373
                 return(0); /* nothing else to do */
979 374
         /* show image in full screen */
980 375
         if(body->flag_drawbigtexture) {
981
-                if(lmbreleased)
376
+                if(mousedata->lmbreleased)
982 377
                         body->flag_drawbigtexture=0;
983 378
                 return(0); /* nothing else to do */
984 379
         }
985 380
         margin=body->ptrfont->height/4;
986
-        if(body->is_displayingtexture && lmbreleased && is_imutil_insidexywh(mousepos,&(body->texture.source),margin) && body->selectedpath[0]=='\0') {
381
+        if(body->is_displayingtexture && mousedata->lmbreleased && is_global_insidewhxy(mousedata->mousepos,&(body->texture.source),margin) && body->selectedpath[0]=='\0') {
987 382
                 body->flag_drawbigtexture=1;
988 383
                 return(0); /* nothing else to do */
989 384
         }
990 385
         /* leftside backbutton */
991
-        if(is_imutil_insidexywh(mousepos,&(body->backxywh),0)) {
386
+        if(is_global_insidewhxy(mousedata->mousepos,&(body->backwhxy),0)) {
992 387
                 static char sep[]={SEP};
993 388
                 if((ptr=strrchr(dirdata->dirname,sep[0]))!=NULL) {
994 389
                         /* previous dir */
... ...
@@ -999,7 +394,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
999 394
                 }
1000 395
                 listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
1001 396
                 body->dirdata[body->currentdirdata]->leftscrollpos=0;
1002
-                *click_avail=0;
397
+                mousedata->click_avail=0;
1003 398
                 return(0);
1004 399
         }
1005 400
         /* leftside directories */
... ...
@@ -1007,11 +402,11 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
1007 402
                 ld=dirdata->listing.elems+i;
1008 403
                 if(ld->name[0]!='d')
1009 404
                         continue;
1010
-                if(is_imutil_insidexywh(mousepos,&(ld->left.screenxywh),0)) {
405
+                if(is_global_insidewhxy(mousedata->mousepos,&(ld->left.screenwhxy),0)) {
1011 406
                         char *newname,*oldprefix;
1012 407
                         int l,l0,l1;
1013 408
                         static char sep[]={SEP};
1014
-                        oldprefix=(strcmp(dirdata->dirname,SEP)==0)?"":dirdata->dirname;
409
+                        oldprefix=(dirdata->dirname[0]==SEP && dirdata->dirname[1]=='\0')?"":dirdata->dirname;
1015 410
                         l0=strlen(oldprefix);
1016 411
                         l1=strlen(ld->name+1);
1017 412
                         l=l0+((l0>0)?1:0)+l1+1;
... ...
@@ -1027,48 +422,48 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
1027 422
                         dirdata->dirname=newname;
1028 423
                         listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
1029 424
                         body->dirdata[body->currentdirdata]->leftscrollpos=0;
1030
-                        *click_avail=0;
425
+                        mousedata->click_avail=0;
1031 426
                         return(0);
1032 427
                 }
1033 428
         }
1034 429
         /* dirdata processing */
1035 430
         if(body->selectedpath[0]=='\0') {
1036 431
                 /* dirdata select */
1037
-                if(mousepos.x>body->leftsize && mousepos.y>body->xywh.y) {
432
+                if(mousedata->mousepos.x>body->leftsize && mousedata->mousepos.y>body->whxy.y) {
1038 433
                         int righty;
1039
-                        for(righty=body->xywh.y,i=0;i<body->sizedirdata;i++) {
434
+                        for(righty=body->whxy.y,i=0;i<body->sizedirdata;i++) {
1040 435
                                 if(body->dirdata[i]==NULL)
1041 436
                                         continue;
1042
-                                if(mousepos.y>=righty && mousepos.y<(righty+body->dirdata[i]->height) && i!=body->currentdirdata) {
437
+                                if(mousedata->mousepos.y>=righty && mousedata->mousepos.y<(righty+body->dirdata[i]->height) && i!=body->currentdirdata) {
1043 438
                                         body->currentdirdata=i;
1044
-                                        *click_avail=0;
439
+                                        mousedata->click_avail=0;
1045 440
                                         return(0);
1046 441
                                 }
1047 442
                                 righty+=body->dirdata[i]->height;
1048 443
                         }
1049 444
                 }
1050 445
                 /* detect click on "add dirdata" button */
1051
-                if(is_imutil_insidexywh(mousepos,&(body->dirdataadd),0)) {
446
+                if(is_global_insidewhxy(mousedata->mousepos,&(body->dirdataadd),0)) {
1052 447
                         im_body_add(body,body->dirdata[body->currentdirdata]->dirname);
1053
-                        *click_avail=0;
448
+                        mousedata->click_avail=0;
1054 449
                         return(0);
1055 450
                 }
1056 451
                 /* dirdata remove */
1057 452
 #warning TODO
1058 453
         }
1059 454
         /* unselect selectedpath */
1060
-        if(lmbpressed==0 && body->selectedpath[0]!='\0') {
1061
-                if(mousepos.x>body->leftsize && mousepos.y>body->xywh.y) {
455
+        if(mousedata->lmbpressed==0 && body->selectedpath[0]!='\0') {
456
+                if(mousedata->mousepos.x>body->leftsize && mousedata->mousepos.y>body->whxy.y) {
1062 457
                         int righty;
1063
-                        for(righty=body->xywh.y,i=0;i<body->sizedirdata;i++) {
458
+                        for(righty=body->whxy.y,i=0;i<body->sizedirdata;i++) {
1064 459
                                 if(body->dirdata[i]==NULL)
1065 460
                                         continue;
1066
-                                if(mousepos.y>=righty && mousepos.y<(righty+body->dirdata[i]->height) && i!=body->currentdirdata && strcmp(body->dirdata[i]->dirname,body->dirdata[body->currentdirdata]->dirname)!=0) {
461
+                                if(mousedata->mousepos.y>=righty && mousedata->mousepos.y<(righty+body->dirdata[i]->height) && i!=body->currentdirdata && strcmp(body->dirdata[i]->dirname,body->dirdata[body->currentdirdata]->dirname)!=0) {
1067 462
 #warning TODO
1068 463
 #if 1
1069 464
 fprintf(stderr,"WOULD MOVE \"%s/%s\" to \"%s\"\n",body->dirdata[body->currentdirdata]->dirname,body->selectedpath+1,body->dirdata[i]->dirname);
1070 465
 #endif
1071
-                                        *click_avail=0;
466
+                                        mousedata->click_avail=0;
1072 467
                                         break;
1073 468
                                 }
1074 469
                                 righty+=body->dirdata[i]->height;
... ...
@@ -1079,8 +474,13 @@ fprintf(stderr,"WOULD MOVE \"%s/%s\" to \"%s\"\n",body->dirdata[body->currentdir
1079 474
         return(0);
1080 475
 }
1081 476
 
477
+#ifdef MYFUNC
478
+#undef MYFUNC
479
+#define MYFUNC "im_body_draw"
480
+#endif
481
+
1082 482
 int
1083
-im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight, int *needs_nextredraw, int scrollspeed)
483
+im_body_draw(body_t *body, mousedata_t *mousedata, int windowwidth, int windowheight, int *needs_nextredraw)
1084 484
 {
1085 485
         int i,k,margin,righty;
1086 486
         int lastx,lasty;
... ...
@@ -1095,12 +495,13 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
1095 495
         thumb_t *thumb;
1096 496
         char statustooltip[1024];
1097 497
         thumb_t *selectedthumb;
498
+        IMDEBUG("Pre-sanitycheck");
1098 499
         if(body==NULL)
1099 500
                 return(-1);
1100 501
         font=body->ptrfont;
1101 502
         fontbig=body->ptrfontbig;
1102 503
         fonthuge=body->ptrfonthuge;
1103
-        FILLXYWH(body->backxywh,0,0,0,0);
504
+        FILLWHXY(body->backwhxy,0,0,0,0);
1104 505
         margin=font->height/4;
1105 506
         body->is_displayingtexture=0;
1106 507
         selectedthumb=NULL;
... ...
@@ -1108,14 +509,15 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
1108 509
         if(body->flag_drawbigtexture && body->texture.has_texture) {
1109 510
                 /* draw image in full screen */
1110 511
                 int maxw,maxh;
512
+                IMDEBUG("begin draw");
1111 513
                 maxw=windowwidth;
1112
-                maxh=windowheight-body->xywh.y;
514
+                maxh=windowheight-body->whxy.y;
1113 515
                 if(body->bigtexture.has_texture==0 || strcmp(body->bigtexture.currentpath,body->texture.currentpath)!=0)
1114 516
                         texture_load(&(body->bigtexture),body->texture.currentpath,maxw,maxh,body->bg);
1115 517
                 if(body->bigtexture.has_texture && strcmp(body->bigtexture.currentpath,body->texture.currentpath)==0) {
1116 518
                         int x0,y0;
1117 519
                         x0=0;
1118
-                        y0=body->xywh.y;
520
+                        y0=body->whxy.y;
1119 521
                         texture_draw(&(body->bigtexture),x0,y0,maxw,maxh);
1120 522
                         return(0); /* all done */
1121 523
                 } else {
... ...
@@ -1123,30 +525,47 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
1123 525
                 }
1124 526
         }
1125 527
         /* calculate positions */
528
+        IMDEBUG("calculate positions");
1126 529
         for(i=0;i<body->sizedirdata;i++) {
1127 530
                 if(body->dirdata[i]==NULL)
1128 531
                         continue;
1129
-                if(body->dirdata[i]->listing.has_rightxywh==0) {
532
+                if(body->dirdata[i]->listing.has_rightwhxy==0) {
1130 533
                         int sidelen;
1131 534
                         sidelen=body->dirdata[i]->height-(fontbig->height+fontbig->height/4+font->height+margin*4+fontbig->height/4);
1132
-                        listing_fillxywh(&(body->dirdata[i]->listing),body->ptrfont,body->xywh.w-(body->xywh.x+body->leftsize),sidelen,0);
1133
-                        body->dirdata[i]->listing.has_rightxywh=1;
535
+                        listing_fillwhxy(&(body->dirdata[i]->listing),body->ptrfont,body->whxy.w-(body->whxy.x+body->leftsize),sidelen,0,0);
536
+                        body->dirdata[i]->listing.has_rightwhxy=1;
1134 537
                 }
1135
-                if(i==body->currentdirdata && body->dirdata[i]->listing.has_leftxywh==0) {
1136
-                        listing_fillxywh(&(body->dirdata[i]->listing),body->ptrfont,body->leftsize,LEFTIMAGESIDELEN,1);
1137
-                        body->dirdata[i]->listing.has_leftxywh=1;
538
+                if(i==body->currentdirdata && body->dirdata[i]->listing.has_leftwhxy==0) {
539
+                        listing_fillwhxy(&(body->dirdata[i]->listing),body->ptrfont,body->leftsize,LEFTIMAGESIDELEN,1,0);
540
+                        body->dirdata[i]->listing.has_leftwhxy=1;
1138 541
                 }
1139 542
         }
1140 543
         /* draw left side background */
1141
-        DrawRectangle(body->xywh.x,body->xywh.y,body->leftsize, body->xywh.h, (Color){ 215, 215, 215, 255 } );
544
+        IMDEBUG("draw left bg");
545
+        {
546
+                whxy_t whxy;
547
+                FILLWHXY(whxy,body->leftsize, body->whxy.h,body->whxy.x,body->whxy.y);
548
+                rayui_scrollablerectadd(body->rayui,mousedata,&whxy,"body.leftside",body->dirdata[body->currentdirdata]->leftscrollpos,(int (*)(void *, Vector2))im_body_tryselect,body,SCROLLTHRESHOLD);
549
+        }
550
+        DrawRectangle(body->whxy.x,body->whxy.y,body->leftsize, body->whxy.h, (Color){ 215, 215, 215, 255 } );
551
+fprintf(stderr,"%ix%i+%i+%i\n",body->leftsize, body->whxy.h,body->whxy.x,body->whxy.y);
1142 552
         /* draw right side background */
1143
-        DrawRectangle(body->xywh.x+body->leftsize,body->xywh.y,body->xywh.w-body->leftsize, body->xywh.h, (Color){ 227, 227, 227, 255 } );
553
+#if 1
554
+fprintf(stderr,"body->whxy:%ix%i+%i+%i\n",UNROLLWHXY(body->whxy));
555
+fprintf(stderr,"body->leftsize:%i\n",body->leftsize);
556
+#endif
557
+        IMDEBUG("draw right bg");
558
+        DrawRectangle(body->whxy.x+body->leftsize,body->whxy.y,body->whxy.w-body->leftsize, body->whxy.h, (Color){ 227, 227, 227, 255 } );
559
+fprintf(stderr,"DrawRectangle(body->whxy.x(%i)+body->leftsize(%i),body->whxy.y(%i),body->whxy.w(%i)-body->leftsize(%i), body->whxy.h(%i), (Color){ 227, 227, 227, 255 } );\n"
560
+        ,body->whxy.x,body->leftsize,body->whxy.y,body->whxy.w,body->leftsize, body->whxy.h);
561
+
562
+fprintf(stderr,"%ix%i+%i+%i\n",body->whxy.w-body->leftsize, body->whxy.h,body->whxy.x+body->leftsize,body->whxy.y);
1144 563
         /* reset lazy load marks */
1145 564
         bg_resetmarks(body->bg);
1146 565
         /* first pass, draw leftside, second pass, draw all of rightside */
1147 566
         statustooltip[0]='\0';
1148 567
         for(is_leftside=1,flag_skiprightside=flag_skipall=0;is_leftside>=0 && flag_skiprightside==0 && flag_skipall==0;is_leftside--) {
1149
-                for(i=(is_leftside)?body->currentdirdata:0,righty=body->xywh.y;flag_skipall==0 && ((is_leftside && i==body->currentdirdata) || (!is_leftside && i<body->sizedirdata));i++) {
568
+                for(i=(is_leftside)?body->currentdirdata:0,righty=body->whxy.y;flag_skipall==0 && ((is_leftside && i==body->currentdirdata) || (!is_leftside && i<body->sizedirdata));i++) {
1150 569
                         int sidelen;
1151 570
                         if((dirdata=body->dirdata[i])==NULL)
1152 571
                                 continue;
... ...
@@ -1154,24 +573,24 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
1154 573
                                 continue; /* this element is not in leftside */
1155 574
                         sidelen=(is_leftside)?LEFTIMAGESIDELEN:dirdata->height-(fontbig->height+fontbig->height/4+font->height+margin*4+fontbig->height/4);
1156 575
                         /* draw left side back arrow if is_leftside and not in root dir */
1157
-                        if(is_leftside && !(dirdata->dirname[0]=='\0' || strcmp(dirdata->dirname,SEP)==0)) {
576
+                        if(is_leftside && !(dirdata->dirname[0]=='\0' || (dirdata->dirname[0]==SEP && dirdata->dirname[1]=='\0'))) {
1158 577
                                 m2=MeasureTextEx(fontbig->font,UTF8DOWNARROW,fontbig->height,0);
1159
-                                v2.x=(float) (body->xywh.x+fontbig->height/2);
1160
-                                v2.y=(float) (body->xywh.y+fontbig->height/4+(fontbig->height-v2.x)/2)-body->dirdata[body->currentdirdata]->leftscrollpos;
1161
-                                FILLXYWH(body->backxywh,v2.x-fontbig->height/4,v2.y-fontbig->height/8,m2.x+fontbig->height/4,m2.x+fontbig->height/4);
578
+                                v2.x=(float) (body->whxy.x+fontbig->height/2);
579
+                                v2.y=(float) (body->whxy.y+fontbig->height/4+(fontbig->height-v2.x)/2)-body->dirdata[body->currentdirdata]->leftscrollpos;
580
+                                FILLWHXY(body->backwhxy,m2.x+fontbig->height/4,m2.x+fontbig->height/4,v2.x-fontbig->height/4,v2.y-fontbig->height/8);
1162 581
 #if 0
1163 582
 DrawTexture(fontbig->font.texture, 0, 0, WHITE); /* font glyphs -- see https://github.com/raysan5/raylib/issues/2022 */
1164
-DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone */
583
+DrawRectangle(UNROLLXYWH(body->backwhxy),((Color){ 0,255,0,255 })); /* hit zone */
1165 584
 #endif
1166 585
                                 if((v2.y+fontbig->height)>=0)
1167 586
                                         DrawTextPro(fontbig->font,UTF8DOWNARROW,(Vector2){v2.x+m2.x,v2.y},(Vector2){0,0},90.0,fontbig->height,0,(Color){65,65,65,255});
1168 587
                         }
1169 588
                         if(is_leftside) {
1170 589
                                 /* ...dirname */
1171
-                                v2.y=(float) (body->xywh.y+fontbig->height/4-body->dirdata[body->currentdirdata]->leftscrollpos);
590
+                                v2.y=(float) (body->whxy.y+fontbig->height/4-body->dirdata[body->currentdirdata]->leftscrollpos);
1172 591
                                 if((v2.y+fontbig->height)>=0) {
1173 592
                                         m2=MeasureTextEx(fontbig->font,dirdata->dirname,fontbig->height,0);
1174
-                                        v2.x=(float) (body->xywh.x+fontbig->height/2)+(body->leftsize-(body->xywh.x+fontbig->height)-m2.x)/2;
593
+                                        v2.x=(float) (body->whxy.x+fontbig->height/2)+(body->leftsize-(body->whxy.x+fontbig->height)-m2.x)/2;
1175 594
                                         DrawTextEx(fontbig->font
1176 595
                                           ,dirdata->dirname
1177 596
                                           ,v2
... ...
@@ -1182,13 +601,13 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
1182 601
                                 }
1183 602
                         } else { /* rightside */
1184 603
                                 /* ...bg */
1185
-                                DrawRectangle(body->xywh.x+body->leftsize,righty,body->xywh.w-body->leftsize, dirdata->height,(i==body->currentdirdata)?((Color){ 168, 168, 168, 255 }):((Color){ 227, 227, 227, 255 }));
604
+                                DrawRectangle(body->whxy.x+body->leftsize,righty,body->whxy.w-body->leftsize, dirdata->height,(i==body->currentdirdata)?((Color){ 168, 168, 168, 255 }):((Color){ 227, 227, 227, 255 }));
1186 605
                                 /* ...bottom separator */
1187
-                                DrawRectangle(body->xywh.x+body->leftsize,righty+dirdata->height-1,body->xywh.w-body->leftsize, 1, (Color){ 221, 221, 221, 255 } );
606
+                                DrawRectangle(body->whxy.x+body->leftsize,righty+dirdata->height-1,body->whxy.w-body->leftsize, 1, (Color){ 221, 221, 221, 255 } );
1188 607
                                 /* ...dirname */
1189 608
                                 DrawTextEx(fontbig->font
1190 609
                                   ,dirdata->dirname
1191
-                                  ,(Vector2) {body->xywh.x+body->leftsize+fontbig->height/2,righty+fontbig->height/4}
610
+                                  ,(Vector2) {body->whxy.x+body->leftsize+fontbig->height/2,righty+fontbig->height/4}
1192 611
                                   ,fontbig->height
1193 612
                                   ,0
1194 613
                                   ,(i==body->currentdirdata)?((Color){ 240, 240, 240, 255 }):((Color){ 65, 65, 65, 255 })
... ...
@@ -1196,7 +615,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
1196 615
                         }
1197 616
                         /* directories */
1198 617
                         xoff=((is_leftside)?0:body->leftsize);
1199
-                        yoff=((is_leftside)?body->xywh.y:righty)+fontbig->height/4+fontbig->height+font->height/4-(is_leftside?body->dirdata[body->currentdirdata]->leftscrollpos:0);
618
+                        yoff=((is_leftside)?body->whxy.y:righty)+fontbig->height/4+fontbig->height+font->height/4-(is_leftside?body->dirdata[body->currentdirdata]->leftscrollpos:0);
1200 619
                         if(is_leftside && dirdata->dirname[0]=='\0')
1201 620
                                 yoff-=fontbig->height/4+fontbig->height;
1202 621
                         for(k=0,lastx=lasty=0;k<dirdata->listing.usedelems;k++) {
... ...
@@ -1204,51 +623,51 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
1204 623
                                 thumb=(is_leftside)?&(elem->left):&(elem->right);
1205 624
                                 if(elem->name[0]!='d' || strcmp(elem->name,"d.")==0 || strcmp(elem->name,"d..")==0) {
1206 625
                                         if(elem->name[0]=='d')
1207
-                                                FILLXYWH(thumb->screenxywh,0,0,0,0);
626
+                                                FILLWHXY(thumb->screenwhxy,0,0,0,0);
1208 627
                                         continue;
1209 628
                                 }
1210
-                                if((thumb->xywh.y+yoff)>(body->xywh.y+body->xywh.h) || thumb->xywh.w==0 || thumb->xywh.h==0) {
629
+                                if((thumb->whxy.y+yoff)>(body->whxy.y+body->whxy.h) || thumb->whxy.w==0 || thumb->whxy.h==0) {
1211 630
 #warning TODO: if !is_leftside, draw "..." in huge font using lastx,lasty as reference
1212 631
                                         break;
1213 632
                                 }
1214
-                                if((thumb->xywh.y+yoff+thumb->xywh.h)<0) {
1215
-                                        FILLXYWH(thumb->screenxywh,0,0,0,0);
633
+                                if((thumb->whxy.y+yoff+thumb->whxy.h)<0) {
634
+                                        FILLWHXY(thumb->screenwhxy,0,0,0,0);
1216 635
                                         continue;
1217 636
                                 }
1218
-                                FILLXYWH(thumb->screenxywh,thumb->xywh.x+xoff,thumb->xywh.y+yoff,thumb->xywh.w,thumb->xywh.h);
1219
-                                DrawRectangleLines(UNROLLXYWH(thumb->screenxywh),((Color){ 65, 65, 65, 255 }));
1220
-                                DrawTextEx(font->font,elem->name+1,(Vector2){thumb->screenxywh.x+margin,thumb->screenxywh.y+margin},font->height,0,((Color){ 65, 65, 65, 255 }));
1221
-                                lastx=thumb->screenxywh.x+thumb->screenxywh.w,lasty=thumb->screenxywh.y+thumb->screenxywh.h;
637
+                                FILLWHXY(thumb->screenwhxy,thumb->whxy.w,thumb->whxy.h,thumb->whxy.x+xoff,thumb->whxy.y+yoff);
638
+                                DrawRectangleLines(thumb->screenwhxy.x,thumb->screenwhxy.y,thumb->screenwhxy.w,thumb->screenwhxy.h,((Color){ 65, 65, 65, 255 }));
639
+                                DrawTextEx(font->font,elem->name+1,(Vector2){thumb->screenwhxy.x+margin,thumb->screenwhxy.y+margin},font->height,0,((Color){ 65, 65, 65, 255 }));
640
+                                lastx=thumb->screenwhxy.x+thumb->screenwhxy.w,lasty=thumb->screenwhxy.y+thumb->screenwhxy.h;
1222 641
                         }
1223 642
                         for(;k<dirdata->listing.usedelems;k++) {
1224 643
                                 elem=dirdata->listing.elems+k;
1225 644
                                 if(elem->name[0]!='d')
1226 645
                                         continue;
1227 646
                                 thumb=(is_leftside)?&(elem->left):&(elem->right);
1228
-                                FILLXYWH(thumb->screenxywh,0,0,0,0);
647
+                                FILLWHXY(thumb->screenwhxy,0,0,0,0);
1229 648
                         }
1230 649
                         /* files */
1231 650
                         for(k=0,lastx=lasty=0;k<dirdata->listing.usedelems;k++) {
1232 651
                                 Texture2D *te;
1233
-                                xywh_t *xywh;
652
+                                whxy_t *whxy;
1234 653
                                 elem=dirdata->listing.elems+k;
1235 654
                                 thumb=(is_leftside)?&(elem->left):&(elem->right);
1236
-                                xywh=&(thumb->xywh);
655
+                                whxy=&(thumb->whxy);
1237 656
                                 te=&(thumb->texture);
1238 657
                                 int has_imagedrawn;
1239 658
                                 if(elem->name[0]!='f' && elem->name[0]!='l')
1240 659
                                         continue;
1241
-                                if((xywh->y+yoff)>(body->xywh.y+body->xywh.h) || xywh->w==0 || xywh->h==0) {
660
+                                if((whxy->y+yoff)>(body->whxy.y+body->whxy.h) || whxy->w==0 || whxy->h==0) {
1242 661
 #warning TODO: if !is_leftside, draw "..." in huge font using lastx,lasty as reference
1243 662
                                         break;
1244 663
                                 }
1245
-                                if(is_leftside && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
664
+                                if(is_leftside && is_global_insidewhxy(mousedata->mousepos,&(thumb->screenwhxy),margin)) {
1246 665
                                         strncpy(statustooltip,elem->name+1,sizeof(statustooltip));
1247 666
                                         statustooltip[sizeof(statustooltip)-1]='\0';
1248 667
                                 }
1249 668
                                 /* show image */
1250 669
                                 has_imagedrawn=0;
1251
-                                if(is_imagefilename(elem->name+1) && !(thumb->screenxywh.y>(body->xywh.y+body->xywh.h) || (thumb->screenxywh.y+thumb->screenxywh.h)<body->xywh.y)) {
670
+                                if(is_imagefilename(elem->name+1) && !(thumb->screenwhxy.y>(body->whxy.y+body->whxy.h) || (thumb->screenwhxy.y+thumb->screenwhxy.h)<body->whxy.y)) {
1252 671
                                         if(thumb->has_texture==0 && thumb->has_failedload==0) {
1253 672
                                                 bgload_t *bgload;
1254 673
                                                 char fullpath[2048];
... ...
@@ -1291,16 +710,16 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1291 710
                                                 }
1292 711
                                         }
1293 712
                                         if(thumb->has_texture!=0) {
1294
-                                                FILLXYWH(thumb->screenxywh,xywh->x+xoff,xywh->y+yoff,xywh->w,xywh->h);
1295
-                                                DrawTexture(*te,thumb->screenxywh.x,thumb->screenxywh.y,WHITE);
713
+                                                FILLWHXY(thumb->screenwhxy,whxy->w,whxy->h,whxy->x+xoff,whxy->y+yoff);
714
+                                                DrawTexture(*te,thumb->screenwhxy.x,thumb->screenwhxy.y,WHITE);
1296 715
                                                 has_imagedrawn=1;
1297
-                                                lastx=xywh->x+xywh->w,lasty=xywh->y+xywh->h+yoff;
1298
-                                                if(is_leftside && rmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin) && scrollspeed==0) {
716
+                                                lastx=whxy->x+whxy->w,lasty=whxy->y+whxy->h+yoff;
717
+                                                if(is_leftside && mousedata->rmbdown==0 && is_global_insidewhxy(mousedata->mousepos,&(thumb->screenwhxy),margin) && mousedata->scrollspeed==0) {
1299 718
                                                         /* draw image in rightside */
1300 719
                                                         char fullpath[2048];
1301 720
                                                         int maxw,maxh;
1302 721
                                                         maxw=windowwidth-(body->leftsize-DEFAULTDIRDATATRIANGLEW);
1303
-                                                        maxh=windowheight-body->xywh.y;
722
+                                                        maxh=windowheight-body->whxy.y;
1304 723
                                                         snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
1305 724
                                                         fullpath[sizeof(fullpath)-1]='\0';
1306 725
                                                         if((body->texture.has_texture==0 && !(body->texture.has_failedload && strcmp(body->texture.currentpath,fullpath)==0))
... ...
@@ -1311,10 +730,10 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1311 730
                                                         if(body->texture.has_texture && strcmp(body->texture.currentpath,fullpath)==0) {
1312 731
                                                                 int x0,y0;
1313 732
                                                                 x0=body->leftsize-DEFAULTDIRDATATRIANGLEW;
1314
-                                                                y0=body->xywh.y;
733
+                                                                y0=body->whxy.y;
1315 734
                                                                 texture_draw(&(body->texture),x0,y0,maxw,maxh);
1316 735
                                                                 body->is_displayingtexture=1;
1317
-                                                                memcpy(&(body->texture.source),&(thumb->screenxywh),sizeof(body->texture.source));
736
+                                                                memcpy(&(body->texture.source),&(thumb->screenwhxy),sizeof(body->texture.source));
1318 737
                                                                 flag_skiprightside=1;
1319 738
                                                         }
1320 739
                                                 }
... ...
@@ -1323,15 +742,15 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1323 742
                                 if(has_imagedrawn==0) {
1324 743
                                         char *ptr;
1325 744
                                         char shortname[1024];
1326
-                                        xywh_t *pos;
745
+                                        whxy_t *pos;
1327 746
                                         int l;
1328 747
                                         font_t *myfont=(is_leftside)?fonthuge:font;
1329
-                                        pos=is_leftside?&(elem->left.xywh):&(elem->right.xywh);
1330
-                                        FILLXYWH(thumb->screenxywh,xywh->x+xoff,xywh->y+yoff,xywh->w,xywh->h);
1331
-                                        DrawRectangle(UNROLLXYWH(thumb->screenxywh),((Color){0,0,0,64}));
748
+                                        pos=is_leftside?&(elem->left.whxy):&(elem->right.whxy);
749
+                                        FILLWHXY(thumb->screenwhxy,whxy->w,whxy->h,whxy->x+xoff,whxy->y+yoff);
750
+                                        DrawRectangle(thumb->screenwhxy.x,thumb->screenwhxy.y,thumb->screenwhxy.w,thumb->screenwhxy.h,((Color){0,0,0,64}));
1332 751
                                         if((ptr=strchr(elem->name+1,'.'))!=NULL) {
1333 752
                                                 m2=MeasureTextEx(myfont->font,ptr,myfont->height,0);
1334
-                                                DrawTextEx(myfont->font,ptr,(Vector2){xywh->x+xoff+(sidelen-m2.x)/2,xywh->y+yoff+(font->height)/2+(xywh->w-myfont->height)/2},myfont->height,0,(Color){ 0,0,0,96 });
753
+                                                DrawTextEx(myfont->font,ptr,(Vector2){whxy->x+xoff+(sidelen-m2.x)/2,whxy->y+yoff+(font->height)/2+(whxy->w-myfont->height)/2},myfont->height,0,(Color){ 0,0,0,96 });
1335 754
                                         }
1336 755
                                         ptr=(ptr==NULL)?elem->name+1:ptr;
1337 756
                                         l=(ptr-(elem->name+1));
... ...
@@ -1340,17 +759,17 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1340 759
                                         shortname[l]='\0';
1341 760
                                         DrawRectangle(pos->x+xoff,pos->y+yoff,pos->w,font->height+font->height/2,((Color){0,0,0,64}));
1342 761
                                         DrawTextEx(font->font,shortname,(Vector2){pos->x+xoff+font->height/4,pos->y+yoff+font->height/4},font->height,0,(Color){ 192,192,192,255 });
1343
-                                        lastx=xywh->x+xoff+xywh->w,lasty=xywh->y+yoff+xywh->h;
762
+                                        lastx=whxy->x+xoff+whxy->w,lasty=whxy->y+yoff+whxy->h;
1344 763
                                 }
1345 764
                                 /* show selected rectangle */
1346 765
                                 if(is_leftside && strcmp(body->selectedpath,elem->name)==0) {
1347 766
                                         Color c=((Color){0,0,255,64});
1348
-                                        DrawRectangle(UNROLLXYWH(thumb->screenxywh),c);
767
+                                        DrawRectangle(thumb->screenwhxy.x,thumb->screenwhxy.y,thumb->screenwhxy.w,thumb->screenwhxy.h,c);
1349 768
                                         c=((Color){0,0,255,255});
1350
-                                        DrawRectangle(thumb->screenxywh.x,thumb->screenxywh.y,thumb->screenxywh.w,2,c);
1351
-                                        DrawRectangle(thumb->screenxywh.x,thumb->screenxywh.y+2,2,thumb->screenxywh.h-4,c);
1352
-                                        DrawRectangle(thumb->screenxywh.x+thumb->screenxywh.w-2,thumb->screenxywh.y+2,2,thumb->screenxywh.h-4,c);
1353
-                                        DrawRectangle(thumb->screenxywh.x,thumb->screenxywh.y+thumb->screenxywh.h-2,thumb->screenxywh.w,2,c);
769
+                                        DrawRectangle(thumb->screenwhxy.x,thumb->screenwhxy.y,thumb->screenwhxy.w,2,c);
770
+                                        DrawRectangle(thumb->screenwhxy.x,thumb->screenwhxy.y+2,2,thumb->screenwhxy.h-4,c);
771
+                                        DrawRectangle(thumb->screenwhxy.x+thumb->screenwhxy.w-2,thumb->screenwhxy.y+2,2,thumb->screenwhxy.h-4,c);
772
+                                        DrawRectangle(thumb->screenwhxy.x,thumb->screenwhxy.y+thumb->screenwhxy.h-2,thumb->screenwhxy.w,2,c);
1354 773
                                         selectedthumb=thumb;
1355 774
                                 }
1356 775
                         }
... ...
@@ -1359,7 +778,7 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1359 778
                                 if(elem->name[0]!='f' && elem->name[0]!='l')
1360 779
                                         continue;
1361 780
                                 thumb=(is_leftside)?&(elem->left):&(elem->right);
1362
-                                FILLXYWH(thumb->screenxywh,0,0,0,0);
781
+                                FILLWHXY(thumb->screenwhxy,0,0,0,0);
1363 782
                         }
1364 783
                         /* ...finishing touchs */
1365 784
                         if(is_leftside) {
... ...
@@ -1367,29 +786,29 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1367 786
                         } else {
1368 787
                                 if(i==body->currentdirdata) {
1369 788
                                         /* draw right side "current" marker inside left side area */
1370
-                                        DrawTriangle((Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)}, (Vector2){((float)body->xywh.x)+body->leftsize-DEFAULTDIRDATATRIANGLEW,((float)righty)+dirdata->height/2}, (Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)+dirdata->height-1}, (Color){ 168, 168, 168, 255 } );
1371
-                                } else if(body->selectedpath[0]!='\0' && mousepos.x>body->leftsize && mousepos.y>=righty && mousepos.y<(righty+dirdata->height) && strcmp(body->dirdata[i]->dirname,body->dirdata[body->currentdirdata]->dirname)!=0) {
1372
-                                        xywh_t xywh;
789
+                                        DrawTriangle((Vector2){((float)body->whxy.x)+body->leftsize,((float)righty)}, (Vector2){((float)body->whxy.x)+body->leftsize-DEFAULTDIRDATATRIANGLEW,((float)righty)+dirdata->height/2}, (Vector2){((float)body->whxy.x)+body->leftsize,((float)righty)+dirdata->height-1}, (Color){ 168, 168, 168, 255 } );
790
+                                } else if(body->selectedpath[0]!='\0' && mousedata->mousepos.x>body->leftsize && mousedata->mousepos.y>=righty && mousedata->mousepos.y<(righty+dirdata->height) && strcmp(body->dirdata[i]->dirname,body->dirdata[body->currentdirdata]->dirname)!=0) {
791
+                                        whxy_t whxy;
1373 792
                                         Color c=((Color){0,0,255,64});
1374
-                                        FILLXYWH(xywh,body->leftsize,righty,body->xywh.w-body->leftsize,dirdata->height);
1375
-                                        DrawRectangle(UNROLLXYWH(xywh),c);
793
+                                        FILLWHXY(whxy,body->whxy.w-body->leftsize,dirdata->height,body->leftsize,righty);
794
+                                        DrawRectangle(whxy.x,whxy.y,whxy.w,whxy.h,c);
1376 795
                                         c=((Color){0,0,255,255});
1377
-                                        DrawRectangle(xywh.x,xywh.y,xywh.w,2,c);
1378
-                                        DrawRectangle(xywh.x,xywh.y+2,2,xywh.h-4,c);
1379
-                                        DrawRectangle(xywh.x+xywh.w-2,xywh.y+2,2,xywh.h-4,c);
1380
-                                        DrawRectangle(xywh.x,xywh.y+xywh.h-2,xywh.w,2,c);
796
+                                        DrawRectangle(whxy.x,whxy.y,whxy.w,2,c);
797
+                                        DrawRectangle(whxy.x,whxy.y+2,2,whxy.h-4,c);
798
+                                        DrawRectangle(whxy.x+whxy.w-2,whxy.y+2,2,whxy.h-4,c);
799
+                                        DrawRectangle(whxy.x,whxy.y+whxy.h-2,whxy.w,2,c);
1381 800
                                 }
1382 801
                                 /* advance to next element */
1383 802
                                 righty+=dirdata->height;
1384 803
                         }
1385 804
                 }
1386 805
         }
1387
-        if(flag_skiprightside==0 && (righty+DEFAULTDIRDATAHEIGHT)<=(body->xywh.y+body->xywh.h)) {
806
+        if(flag_skiprightside==0 && (righty+DEFAULTDIRDATAHEIGHT)<=(body->whxy.y+body->whxy.h)) {
1388 807
                 GlyphInfo gi;
1389 808
                 int xoff;
1390 809
                 int margin;
1391 810
                 margin=20;
1392
-                FILLXYWH(body->dirdataadd,(body->xywh.x+body->xywh.w-ADDREMOVEDIRDATAHEIGHT-margin),righty+margin,ADDREMOVEDIRDATAHEIGHT,ADDREMOVEDIRDATAHEIGHT);
811
+                FILLWHXY(body->dirdataadd,(body->whxy.x+body->whxy.w-ADDREMOVEDIRDATAHEIGHT-margin),righty+margin,ADDREMOVEDIRDATAHEIGHT,ADDREMOVEDIRDATAHEIGHT);
1393 812
                 gi=GetGlyphInfo(body->roundedbox,'O');
1394 813
                 xoff=0;
1395 814
                 DrawTexturePro(body->roundedbox.texture
... ...
@@ -1413,10 +832,10 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1413 832
         } else {
1414 833
                 memset(&(body->dirdataadd),0,sizeof(body->dirdataadd));
1415 834
         }
1416
-        /* if moving elem, show line from orig to mousepos */
835
+        /* if moving elem, show line from orig to mousedata->mousepos */
1417 836
         if(body->selectedpath[0]!='\0' && selectedthumb!=NULL) {
1418 837
                 Color c=((Color){0,0,255,255});
1419
-                DrawLineEx((Vector2){(float)(selectedthumb->screenxywh.x+selectedthumb->screenxywh.w/2),(float)(selectedthumb->screenxywh.y+selectedthumb->screenxywh.h/2)},mousepos,2.0,c);
838
+                DrawLineEx((Vector2){(float)(selectedthumb->screenwhxy.x+selectedthumb->screenwhxy.w/2),(float)(selectedthumb->screenwhxy.y+selectedthumb->screenwhxy.h/2)},mousedata->mousepos,2.0,c);
1420 839
         }
1421 840
         /* show tooltip */
1422 841
         if(statustooltip[0]!='\0') {
... ...
@@ -1425,242 +844,21 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1425 844
                 DrawTextEx(font->font,statustooltip,(Vector2){margin,windowheight-1-margin-font->height},font->height,0,(Color){ 255,255,255,128 });
1426 845
         }
1427 846
         /* free not used bg load items (only if idle, as it takes time) */
1428
-        if(scrollspeed==0 && *needs_nextredraw==0)
847
+        if(mousedata->scrollspeed==0 && *needs_nextredraw==0)
1429 848
                 bg_freeunmarked(body->bg);
1430 849
         return(0);
1431 850
 }
1432 851
 
1433
-int
1434
-texture_load(texture_t *texture, char *fullpath, int maxw, int maxh, bg_t *bg)
1435
-{ 
1436
-        Image im;
1437
-        int neww,newh;
1438
-        bgload_t *bgload;
1439
-        if(texture==NULL || fullpath==NULL)
1440
-                return(-1); /* sanity check failed */
1441
-        if(texture->has_texture) {
1442
-                UnloadTexture(texture->texture);
1443
-                texture->currentpath[0]='\0';
1444
-                texture->has_texture=0;
1445
-                texture->has_failedload=0;
1446
-        }
1447
-        texture->currentpath[0]='\0';
1448
-        if(bg!=NULL && (bgload=bg_get(bg,texture->currentpath))!=NULL && bgload->has_data!=0) {
1449
-                im=ImageCopy(bgload->image);
1450
-        } else {
1451
-                im=imutil_loadimage(fullpath);
1452
-        }
1453
-        if(IsImageValid(im)) {
1454
-                imutil_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
1455
-                ImageResize(&im,neww,newh);
1456
-                texture->texture=LoadTextureFromImage(im);
1457
-                UnloadImage(im);
1458
-                strncpy(texture->currentpath,fullpath,sizeof(texture->currentpath));
1459
-                texture->currentpath[sizeof(texture->currentpath)-1]='\0';
1460
-                texture->has_texture=1;
1461
-                texture->has_failedload=0;
1462
-                texture->texturew=neww;
1463
-                texture->textureh=newh;
1464
-        } else {
1465
-                strncpy(texture->currentpath,fullpath,sizeof(texture->currentpath));
1466
-                texture->currentpath[sizeof(texture->currentpath)-1]='\0';
1467
-                texture->has_texture=0;
1468
-                texture->has_failedload=1;
1469
-        }
1470
-        return(0);
1471
-}
1472
-
1473
-int
1474
-texture_draw(texture_t *texture, int x0, int y0, int maxw, int maxh)
1475
-{
1476
-        if(texture==NULL || texture->has_texture==0)
1477
-                return(-1); /* sanity check failed */
1478
-        DrawRectangle(x0,y0,maxw,maxh,(Color){ 215, 215, 215, 255 } );
1479
-        DrawTexture(texture->texture,x0+(maxw-texture->texturew)/2,y0+(maxh-texture->textureh)/2,WHITE);
1480
-        return(0);
1481
-}
1482
-
1483
-int
1484
-texture_freedata(texture_t *texture)
1485
-{
1486
-        if(texture==NULL)
1487
-                return(-1); /* sanity check failed */
1488
-        if(texture->has_texture) {
1489
-                UnloadTexture(texture->texture);
1490
-                texture->currentpath[0]='\0';
1491
-                texture->has_texture=0;
1492
-                texture->has_failedload=0;
1493
-        }
1494
-        return(0);
1495
-}
1496
-
1497
-int
1498
-imutil_menu_count(char *menus)
1499
-{
1500
-        int n;
1501
-        char *ptr,*next;
1502
-        if(menus==NULL)
1503
-                return(0); /* sanity check error */
1504
-        for(ptr=menus,n=0;(next=strchr(ptr,'\n'))!=NULL;ptr=next+1) {
1505
-                if(next[1]=='\n') {
1506
-                        next++;
1507
-                        n++;
1508
-                }
1509
-        }
1510
-        return(n);
1511
-}
1512
-
1513
-char *
1514
-imutil_menu_get(char *menus, int targetn, int *len)
1515
-{
1516
-        int n;
1517
-        char *ptr,*next,*end;
1518
-        int is_title;
1519
-        if(len!=NULL)
1520
-                *len=0;
1521
-        if(menus==NULL || targetn<0)
1522
-                return(NULL); /* sanity check error */
1523
-        end=menus+strlen(menus);
1524
-        for(ptr=menus,is_title=1,n=0;(next=strchr(ptr,'\n'))!=NULL;ptr=next+1) {
1525
-                if(targetn==n && is_title==1) {
1526
-                        if(len!=NULL)
1527
-                                *len=next-ptr;
1528
-                        return(ptr); /* found, return start of menu string */
1529
-                }
1530
-                is_title=0;
1531
-                if(next[1]=='\n') {
1532
-                        n++;
1533
-                        next++;
1534
-                        is_title=1;
1535
-                }
1536
-        }
1537
-        return(end); /* not found, return end of menus */
1538
-}
1539
-
1540
-int
1541
-imutil_submenu_count(char *menus)
1542
-{
1543
-        int subn;
1544
-        char *ptr,*next;
1545
-        if(menus==NULL)
1546
-                return(0); /* sanity check error */
1547
-        next=strchr(menus,'\n');
1548
-        if(next==NULL)
1549
-                return(0); /* no title */
1550
-        for(subn=0,ptr=next+1;(next=strchr(ptr,'\n'))!=NULL;ptr=next+1) {
1551
-                subn++;
1552
-                if(next[1]=='\n')
1553
-                        break;
1554
-        }
1555
-        return(subn);
1556
-}
1557
-
1558
-char *
1559
-imutil_submenu_get(char *menus, int targetsubn, int *len)
1560
-{
1561
-        char *ptr,*next,*end;
1562
-        int subn;
1563
-        if(len!=NULL)
1564
-                *len=0;
1565
-        if(menus==NULL || targetsubn<0)
1566
-                return(NULL); /* sanity check error */
1567
-        end=menus+strlen(menus);
1568
-        next=strchr(menus,'\n');
1569
-        if(next==NULL)
1570
-                return(end); /* no title */
1571
-        for(ptr=next+1,subn=0;(next=strchr(ptr,'\n'))!=NULL;ptr=next+1,subn++) {
1572
-                if(targetsubn==subn) {
1573
-                        if(len!=NULL)
1574
-                                *len=next-ptr;
1575
-                        return(ptr);
1576
-                }
1577
-                if(next[1]=='\n')
1578
-                        break; /* "\n\n" marks the end of submenus */
1579
-        }
1580
-        return(end);
1581
-}
1582
-
1583
-char *
1584
-imutil_strduplen(char *str, int len)
1585
-{
1586
-        char *res;
1587
-        if(len<0 || (str==NULL && len!=0))
1588
-                return(NULL);
1589
-        if((res=malloc(len+1))==NULL)
1590
-                return(NULL);
1591
-        memcpy(res,str,len);
1592
-        res[len]='\0';
1593
-        return(res);
1594
-}
1595
-
1596
-int
1597
-is_imutil_insidexywh(Vector2 pos, xywh_t *xywh, int margin)
1598
-{
1599
-        if(xywh==NULL)
1600
-                return(0); /* sanity check error */
1601
-        if(pos.x>=(float)(xywh->x-margin)
1602
-          && pos.x<=(float)(xywh->x+xywh->w+margin)
1603
-          && pos.y>=(float)(xywh->y-margin)
1604
-          && pos.y<=(float)(xywh->y+xywh->h+margin)
1605
-        ) {
1606
-                return(1);
1607
-        }
1608
-        return(0);
1609
-}
1610
-
1611
-int
1612
-imutil_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh)
1613
-{
1614
-        if(neww==NULL || newh==NULL || w==0 || h==0 || maxw==0 || maxh==0)
1615
-                return(-1);
1616
-        if((w/h)>(maxw/maxh) || (maxw==maxh && w>h)) {
1617
-                *neww=maxw;
1618
-                *newh=h*maxw/w;
1619
-        } else { /* (w/h)<=(maxw/maxh) */
1620
-                *newh=maxh;
1621
-                *neww=w*maxh/h;
1622
-        }
1623
-        return(0);
1624
-}
1625
-
1626
-
1627
-int
1628
-menudata_pos2option(menudata_t *menudata, Vector2 pos)
1629
-{
1630
-        int n,h;
1631
-        if(menudata==NULL
1632
-          || (menudata->flag_open==0 && menudata->flag_stickyopen==0)
1633
-          || is_imutil_insidexywh(pos, &(menudata->optionsxywh),0)==0
1634
-        ) {
1635
-                return(-1);
1636
-        }
1637
-        h=(menudata->sizeoptions==0)?0:menudata->optionsxywh.h/menudata->sizeoptions;
1638
-        n=(((int)pos.y)-menudata->optionsxywh.y)/h;
1639
-        return(n);
1640
-}
1641
-
1642
-int *
1643
-getcodepoints(int *sizecodepoints)
1644
-{
1645
-        static int codepoints[]={
1646
-/* Basic Latin */
1647
-32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
1648
-/* Latin-1 Supplement */
1649
-160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
1650
-/* down arrow (U+2186 -- this font doesn't have arrows, this is old roman numeral 50 */
1651
-(0x21<<8)|0x86,
1652
-};
1653
-        if(sizecodepoints!=NULL)
1654
-                *sizecodepoints=(int) (sizeof(codepoints)/sizeof(codepoints[0]));
1655
-        return(codepoints);
1656
-}
1657
-
1658 852
 static int
1659 853
 strptrcmp(void *a,void *b)
1660 854
 {
1661 855
         return(strcmp(((listingdata_t *)a)->name,((listingdata_t *)b)->name));
1662 856
 }
1663 857
 
858
+#ifdef MYFUNC
859
+#undef MYFUNC
860
+#define MYFUNC "listing_get"
861
+#endif
1664 862
 int
1665 863
 listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort)
1666 864
 {
... ...
@@ -1689,11 +887,11 @@ listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort
1689 887
         /* reset struct */
1690 888
         listing->usedelems=listing->usedbuf=0;
1691 889
         memset(listing->elems,0,sizeof(listingdata_t)*listing->sizeelems);
1692
-        listing->has_leftxywh=listing->has_rightxywh=0;
890
+        listing->has_leftwhxy=listing->has_rightwhxy=0;
1693 891
         /* fill listing */
1694 892
         if(pathprefix==NULL && parampath==NULL)
1695 893
                 return(-1); /* nothing to fill */
1696
-        snprintf(path,sizeof(path),"%s%s%s",(pathprefix!=NULL)?pathprefix:"",SEP,(parampath!=NULL)?parampath:"");
894
+        snprintf(path,sizeof(path),"%s%c%s",(pathprefix!=NULL)?pathprefix:"",SEP,(parampath!=NULL)?parampath:"");
1697 895
         path[sizeof(path)-1]='\0';
1698 896
         if((d=opendir(path))==NULL)
1699 897
                 return(-1); /* dir not found */
... ...
@@ -1714,7 +912,7 @@ listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort
1714 912
                         char stpath[2048];
1715 913
                         struct stat st;
1716 914
                         mode_t m;
1717
-                        snprintf(stpath,sizeof(stpath),"%s%s%s",path,SEP,de->d_name);
915
+                        snprintf(stpath,sizeof(stpath),"%s%c%s",path,SEP,de->d_name);
1718 916
                         stpath[sizeof(stpath)-1]='\0';
1719 917
                         if(stat(stpath,&st)==0 && (m=(st.st_mode&S_IFMT))!=0) {
1720 918
                                 dtype=(m==S_IFBLK)?'b'
... ...
@@ -1767,6 +965,7 @@ listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort
1767 965
                 listing->elems[listing->usedelems++].name=listing->buf+listing->usedbuf;
1768 966
                 listing->buf[listing->usedbuf++]=dtype;
1769 967
                 memcpy(listing->buf+listing->usedbuf,de->d_name,l+1);
968
+IMDEBUG(listing->buf+listing->usedbuf);
1770 969
                 listing->usedbuf+=l+1;
1771 970
         }
1772 971
         closedir(d),d=NULL;
... ...
@@ -1804,7 +1003,7 @@ listing_freedata(listing_t *listing)
1804 1003
 }
1805 1004
 
1806 1005
 int
1807
-listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_leftside)
1006
+listing_fillwhxy(listing_t *listing, font_t *font, int w, int sidelen, int is_leftside, int rightsidemargin)
1808 1007
 {
1809 1008
         int x0,y0,x1;
1810 1009
         int k,x,y;
... ...
@@ -1816,14 +1015,14 @@ listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_le
1816 1015
                 return(-1); /* sanity check failed */
1817 1016
         margin=font->height/4;
1818 1017
         if(is_leftside)
1819
-                memset(&(listing->lastleftxywh),0,sizeof(listing->lastleftxywh));
1018
+                memset(&(listing->lastleftwhxy),0,sizeof(listing->lastleftwhxy));
1820 1019
         /* directories */
1821 1020
         if(is_leftside) {
1822 1021
                 x0=font->height/2;
1823 1022
                 x1=w-DEFAULTDIRDATATRIANGLEW-font->height/2;
1824 1023
                 y0=0;
1825 1024
         } else {
1826
-                x0=FONTBIGSIZE/2;
1025
+                x0=rightsidemargin;
1827 1026
                 x1=w-font->height/2;
1828 1027
                 y0=0;
1829 1028
         }
... ...
@@ -1836,12 +1035,12 @@ listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_le
1836 1035
                 if((x+margin*2+m2.x)>x1 && !(is_leftside==0 && y>y0))
1837 1036
                         x=x0,y+=font->height+margin*2+font->height/4;
1838 1037
                 if(is_leftside==0 && y>y0) {
1839
-                        FILLXYWH(thumb->xywh,0,0,0,0);
1038
+                        FILLWHXY(thumb->whxy,0,0,0,0);
1840 1039
                         continue;
1841 1040
                 }
1842
-                FILLXYWH(thumb->xywh,x,y,margin*2+m2.x,margin*2+font->height);
1843
-                if(is_leftside && (thumb->xywh.y+thumb->xywh.h)>(listing->lastleftxywh.y+listing->lastleftxywh.h))
1844
-                        memcpy(&(listing->lastleftxywh),&(thumb->xywh),sizeof(xywh_t));
1041
+                FILLWHXY(thumb->whxy,margin*2+m2.x,margin*2+font->height,x,y);
1042
+                if(is_leftside && (thumb->whxy.y+thumb->whxy.h)>(listing->lastleftwhxy.y+listing->lastleftwhxy.h))
1043
+                        memcpy(&(listing->lastleftwhxy),&(thumb->whxy),sizeof(whxy_t));
1845 1044
                 x+=margin*2+m2.x+font->height/4;
1846 1045
         }
1847 1046
         y+=((x==x0)?0:font->height+margin*2+font->height/4);
... ...
@@ -1856,18 +1055,18 @@ listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_le
1856 1055
                 if(elem->name[0]!='f' && elem->name[0]!='l')
1857 1056
                         continue;
1858 1057
                 if(!is_leftside && y>y0) {
1859
-                        FILLXYWH(thumb->xywh,0,0,0,0);
1058
+                        FILLWHXY(thumb->whxy,0,0,0,0);
1860 1059
                         continue;
1861 1060
                 }
1862 1061
                 if((x+margin*2+sidelen)>x1 && !(is_leftside==0 && y>y0))
1863 1062
                         x=x0,y+=sidelen+margin*2;
1864 1063
                 if(is_leftside==0 && y>y0) {
1865
-                        FILLXYWH(thumb->xywh,0,0,0,0);
1064
+                        FILLWHXY(thumb->whxy,0,0,0,0);
1866 1065
                         continue;
1867 1066
                 }
1868
-                FILLXYWH(thumb->xywh,x,y,sidelen,sidelen);
1869
-                if(is_leftside && (thumb->xywh.y+thumb->xywh.h)>(listing->lastleftxywh.y+listing->lastleftxywh.h))
1870
-                        memcpy(&(listing->lastleftxywh),&(thumb->xywh),sizeof(xywh_t));
1067
+                FILLWHXY(thumb->whxy,sidelen,sidelen,x,y);
1068
+                if(is_leftside && (thumb->whxy.y+thumb->whxy.h)>(listing->lastleftwhxy.y+listing->lastleftwhxy.h))
1069
+                        memcpy(&(listing->lastleftwhxy),&(thumb->whxy),sizeof(whxy_t));
1871 1070
                 x+=margin*2+sidelen;
1872 1071
         }
1873 1072
         return(0);
... ...
@@ -1899,313 +1098,82 @@ is_imagefilename(char *filename)
1899 1098
         return(0); /* not in the knownext list */
1900 1099
 }
1901 1100
 
1902
-#ifdef ANDROID
1903
-Image
1904
-imutil_loadimage(const char *filename)
1905
-{
1906
-        unsigned char *filedata=NULL;
1907
-        FILE *f=NULL;
1908
-        struct stat st;
1909
-        Image img;
1910
-        char *ext;
1911
-        if((f=fopen(filename,"r"))==NULL
1912
-          || fstat(fileno(f),&st)!=0
1913
-          || st.st_size<=0
1914
-          || (filedata=(unsigned char *)malloc(st.st_size))==NULL
1915
-          || fread(filedata,1,st.st_size,f)!=st.st_size
1916
-        ) {
1917
-                if(f!=NULL)
1918
-                        fclose(f),f=NULL;
1919
-                if(filedata!=NULL)
1920
-                        free(filedata),filedata=NULL;
1921
-                return((Image){0});
1922
-        }
1923
-        fclose(f);
1924
-        ext=strchr(filename,'.');
1925
-        ext=(ext==NULL)?filename+strlen(filename):ext;
1926
-        img=LoadImageFromMemory(ext,filedata,st.st_size);
1927
-        free(filedata),filedata=NULL;
1928
-        return(img);
1929
-}
1930
-#else
1931
-Image
1932
-imutil_loadimage(const char *filename)
1933
-{
1934
-        return(LoadImage(filename));
1935
-}
1936
-#endif
1937
-
1938
-static void
1939
-intimutil_fpsdata(struct timeval **deadline)
1940
-{
1941
-        static struct timeval mydeadline;
1942
-        *deadline=&(mydeadline);
1943
-        return;
1944
-}
1945
-
1946
-void
1947
-imutil_fpsreset(void)
1948
-{
1949
-        struct timeval *deadline;
1950
-        long deadlineincr;
1951
-        intimutil_fpsdata(&deadline);
1952
-        gettimeofday(deadline,NULL);
1953
-        deadlineincr=1000000L/TARGETFPS;
1954
-        deadline->tv_usec+=deadlineincr;
1955
-        deadline->tv_sec+=(deadline->tv_usec)/1000000L;
1956
-        deadline->tv_usec%=1000000L;
1957
-}
1958
-
1959 1101
 int
1960
-imutil_fpsleft(void)
1961
-{
1962
-        struct timeval *deadline,now;
1963
-        intimutil_fpsdata(&deadline);
1964
-        gettimeofday(&now,NULL);
1965
-        if(deadline->tv_sec<now.tv_sec || (deadline->tv_sec==now.tv_sec && deadline->tv_usec<now.tv_usec))
1966
-                return(0);
1967
-        return(1);
1968
-}
1969
-
1970
-long long
1971
-imutil_milliseconds(void)
1972
-{
1973
-        long long res;
1974
-        struct timeval now;
1975
-        gettimeofday(&now,NULL);
1976
-        res=((long long) (now.tv_sec))*1000000L+((long long) (now.tv_usec));
1977
-        return(res);
1978
-}
1979
-
1980
-bg_t *
1981
-bg_init(int sizebgload)
1102
+texture_load(texture_t *texture, char *fullpath, int maxw, int maxh, bg_t *bg)
1982 1103
 {
1983
-        bg_t *bg;
1984
-        char *errstr;
1985
-        bg=NULL;
1986
-        if((errstr="Insuf. mem. for bg")==NULL
1987
-          || (bg=calloc(1,sizeof(bg_t)))==NULL
1988
-          || (errstr="Error init pipes (please check program is not blocked in firewall)")==NULL
1989
-          || (bg->pipe[0]=bg->pipe[1]=-1)!=-1
1990
-          || mypipe(bg->pipe)!=0
1991
-          || (errstr="Insuf mem bgload")==NULL
1992
-          || (bg->bgload=calloc(sizebgload,sizeof(bgload_t)))==NULL
1993
-          || (bg->sizebgload=sizebgload)!=sizebgload
1994
-          || (errstr="pthread attr init error")==NULL
1995
-          || pthread_attr_init(&(bg->tattr))!=0
1996
-          || (errstr="pthread create error")==NULL
1997
-          || pthread_create(&(bg->thread),&(bg->tattr),bg_thread,(void *)bg)!=0
1998
-          || (bg->flag_threadstarted=1)!=1
1999
-        ) {
2000
-                messagebox(errstr);
2001
-                bg_free(bg);
2002
-                return(NULL);
1104
+        Image im;
1105
+        int neww,newh;
1106
+        bgload_t *bgload;
1107
+        if(texture==NULL || fullpath==NULL)
1108
+                return(-1); /* sanity check failed */
1109
+        if(texture->has_texture) {
1110
+                UnloadTexture(texture->texture);
1111
+                texture->currentpath[0]='\0';
1112
+                texture->has_texture=0;
1113
+                texture->has_failedload=0;
2003 1114
         }
2004
-        return(bg);
2005
-}
2006
-
2007
-
2008
-void
2009
-bg_free(bg_t *bg)
2010
-{
2011
-        int i;
2012
-        if(bg==NULL)
2013
-                return; /* nothing to do */
2014
-        if(bg->flag_threadstarted) {
2015
-                char dummy=1;
2016
-#if 1
2017
-fprintf(stderr,"bg_free: notifying thread to exit\n");
2018
-#endif
2019
-                mypipewrite(bg->pipe[WR],&dummy,1);
2020
-#if 1
2021
-fprintf(stderr,"bg_free: joining thread\n");
2022
-#endif
2023
-                pthread_join(bg->thread,NULL);
2024
-#if 1
2025
-fprintf(stderr,"bg_free: thread joined OK\n");
2026
-#endif
2027
-                bg->flag_threadstarted=0;
1115
+        texture->currentpath[0]='\0';
1116
+        if(bg!=NULL && (bgload=bg_get(bg,texture->currentpath))!=NULL && bgload->has_data!=0) {
1117
+                im=ImageCopy(bgload->image);
1118
+        } else {
1119
+                im=global_loadimage(fullpath);
2028 1120
         }
2029
-        if(bg->pipe[0]!=-1)
2030
-                close(bg->pipe[0]),bg->pipe[0]=-1;
2031
-        if(bg->pipe[1]!=-1)
2032
-                close(bg->pipe[1]),bg->pipe[1]=-1;
2033
-        if(bg->bgload!=NULL) {
2034
-                bgload_t *bgload;
2035
-                for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
2036
-                        if(bgload->has_data) {
2037
-                                UnloadImage(bgload->image);
2038
-                                bgload->has_data=0;
2039
-                        }
2040
-                }
2041
-                free(bg->bgload),bg->bgload=NULL,bg->sizebgload=0;
1121
+        if(IsImageValid(im)) {
1122
+                imutil_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
1123
+                ImageResize(&im,neww,newh);
1124
+                texture->texture=LoadTextureFromImage(im);
1125
+                UnloadImage(im);
1126
+                strncpy(texture->currentpath,fullpath,sizeof(texture->currentpath));
1127
+                texture->currentpath[sizeof(texture->currentpath)-1]='\0';
1128
+                texture->has_texture=1;
1129
+                texture->has_failedload=0;
1130
+                texture->texturew=neww;
1131
+                texture->textureh=newh;
1132
+        } else {
1133
+                strncpy(texture->currentpath,fullpath,sizeof(texture->currentpath));
1134
+                texture->currentpath[sizeof(texture->currentpath)-1]='\0';
1135
+                texture->has_texture=0;
1136
+                texture->has_failedload=1;
2042 1137
         }
2043
-        return;
1138
+        return(0);
2044 1139
 }
2045 1140
 
2046 1141
 int
2047
-bg_resetmarks(bg_t *bg)
1142
+texture_draw(texture_t *texture, int x0, int y0, int maxw, int maxh)
2048 1143
 {
2049
-        int i;
2050
-        bgload_t *bgload;
2051
-        if(bg==NULL)
2052
-                return(-1);
2053
-        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++)
2054
-                bgload->has_mark=0;
1144
+        if(texture==NULL || texture->has_texture==0)
1145
+                return(-1); /* sanity check failed */
1146
+        DrawRectangle(x0,y0,maxw,maxh,(Color){ 215, 215, 215, 255 } );
1147
+        DrawTexture(texture->texture,x0+(maxw-texture->texturew)/2,y0+(maxh-texture->textureh)/2,WHITE);
2055 1148
         return(0);
2056 1149
 }
2057 1150
 
2058
-bgload_t *
2059
-bg_get(bg_t *bg, char *path)
2060
-{
2061
-        int i;
2062
-        bgload_t *bgload;
2063
-        if(bg==NULL)
2064
-                return(NULL);
2065
-        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
2066
-                if(bgload->thread_finished && bgload->has_data && strcmp(path,bgload->path)==0) {
2067
-                        bgload->has_mark=1;
2068
-#if 1
2069
-fprintf(stderr,"bg_get: \"%s\"\n",bgload->path);
2070
-#endif
2071
-                        return(bgload);
2072
-                }
2073
-        }
2074
-        return(NULL);
2075
-}
2076
-
2077 1151
 int
2078
-bg_add(bg_t *bg, char *path)
1152
+texture_freedata(texture_t *texture)
2079 1153
 {
2080
-        int i;
2081
-        bgload_t *bgload;
2082
-        char dummy;
2083
-        if(bg==NULL)
2084
-                return(-1);
2085
-        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
2086
-                if(bgload->lended_to_thread && strcmp(path,bgload->path)==0) {
2087
-                        bgload->is_todo=1;
2088
-                        bgload->has_mark=1;
2089
-                        dummy=0;
2090
-                        mypipewrite(bg->pipe[WR],&dummy,1);
2091
-                        return(0); /* already on list */
2092
-                }
2093
-        }
2094
-        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
2095
-                if(bgload->lended_to_thread==0) {
2096
-                        memset(bgload,0,sizeof(bgload_t));
2097
-                        strncpy(bgload->path,path,sizeof(bgload->path));
2098
-                        bgload->path[sizeof(bgload->path)-1]='\0';
2099
-                        bgload->is_todo=1;
2100
-                        bgload->has_mark=1;
2101
-                        dummy=0;
2102
-                        bgload->lended_to_thread=1;
2103
-                        mypipewrite(bg->pipe[WR],&dummy,1);
2104
-                        return(0); /* added to list */
2105
-                }
1154
+        if(texture==NULL)
1155
+                return(-1); /* sanity check failed */
1156
+        if(texture->has_texture) {
1157
+                UnloadTexture(texture->texture);
1158
+                texture->currentpath[0]='\0';
1159
+                texture->has_texture=0;
1160
+                texture->has_failedload=0;
2106 1161
         }
2107
-        return(-1); /* couldn't add */
1162
+        return(0);
2108 1163
 }
2109 1164
 
2110 1165
 int
2111
-bg_freeunmarked(bg_t *bg)
1166
+imutil_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh)
2112 1167
 {
2113
-        int i;
2114
-        bgload_t *bgload;
2115
-        if(bg==NULL)
1168
+        if(neww==NULL || newh==NULL || w==0 || h==0 || maxw==0 || maxh==0)
2116 1169
                 return(-1);
2117
-        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
2118
-                if(bgload->lended_to_thread && bgload->thread_finished && bgload->has_mark==0) {
2119
-                        if(bgload->has_data) {
2120
-#if 1
2121
-fprintf(stderr,"bg: Unloading: \"%s\"\n",bgload->path);
2122
-#endif
2123
-                                UnloadImage(bgload->image);
2124
-                                bgload->has_data=0;
2125
-                        }
2126
-#if 1
2127
-else {
2128
-fprintf(stderr,"bg: Cancelling: \"%s\"\n",bgload->path);
2129
-}
2130
-#endif
2131
-                        memset(bgload,0,sizeof(bgload_t));
2132
-                }
1170
+        if((w/h)>(maxw/maxh) || (maxw==maxh && w>h)) {
1171
+                *neww=maxw;
1172
+                *newh=h*maxw/w;
1173
+        } else { /* (w/h)<=(maxw/maxh) */
1174
+                *newh=maxh;
1175
+                *neww=w*maxh/h;
2133 1176
         }
2134 1177
         return(0);
2135 1178
 }
2136 1179
 
2137
-void *
2138
-bg_thread(void *parambg)
2139
-{
2140
-        bg_t *bg;
2141
-        char dummy;
2142
-        bg=(bg_t *)parambg;
2143
-        int i;
2144
-        bgload_t *bgload;
2145
-        while(1) {
2146
-                mypiperead(bg->pipe[RD],&dummy,1);
2147
-#if 1
2148
-fprintf(stderr,"Thread received byte: %i\n",(int)((unsigned char)dummy));
2149
-#endif
2150
-                if(dummy!=0)
2151
-                        break; /* was told to exit */
2152
-                for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
2153
-                        if(bgload->lended_to_thread==0)
2154
-                                continue;
2155
-                        if(bgload->is_todo==0) {
2156
-                                bgload->thread_finished=1;
2157
-                                continue;
2158
-                        }
2159
-                        if(bgload->has_data==0 && bgload->has_failedload==0) {
2160
-                                bgload->image=imutil_loadimage(bgload->path);
2161
-                                if(IsImageValid(bgload->image))
2162
-                                        bgload->has_data=1;
2163
-                                else
2164
-                                        bgload->has_failedload=1;
2165
-                                bgload->thread_finished=1;
2166
-                        }
2167
-                }
2168
-        }
2169
-        pthread_exit(NULL);
2170
-        return(NULL);
2171
-}
2172
-
2173
-#if !defined(__linux__) && !defined(ANDROID)
2174
-static int
2175
-mypipe(int fds[2])
2176
-{
2177
-        return(win32pipe_pipe(fds));
2178
-}
2179
-
2180
-static int
2181
-mypiperead(int fd, char *buf, int count)
2182
-{
2183
-        return(win32pipe_read(fd,buf,count));
2184
-}
2185
-
2186
-static int
2187
-mypipewrite(int fd, char *buf, int count)
2188
-{
2189
-        return(win32pipe_write(fd,buf,count));
2190
-}
2191
-#else
2192
-static int
2193
-mypipe(int fds[2])
2194
-{
2195
-        return(pipe(fds));
2196
-}
2197
-
2198
-static int
2199
-mypiperead(int fd, char *buf, int count)
2200
-{
2201
-        return(read(fd,buf,count));
2202
-}
2203
-
2204
-static int
2205
-mypipewrite(int fd, char *buf, int count)
2206
-{
2207
-        return(write(fd,buf,count));
2208
-}
2209
-#endif
2210
-
2211
-
Browse code

windows: rework zig toolchain setup and fix compilation with raylib 5.5

Dario Rodriguez authored on 25/07/2025 14:13:54
Showing 1 changed files
... ...
@@ -100,6 +100,7 @@
100 100
 
101 101
 #define SCROLLTHRESHOLD (LEFTIMAGESIDELEN/3)
102 102
 
103
+
103 104
 #if defined(SIMANDROID)
104 105
 #undef ROOTDIR
105 106
 #define ROOTDIR "/var/www/default/animeshot/"
... ...
@@ -150,7 +151,7 @@ int MessageBoxA(void *hWnd,void *lpText,void *lpCaption,unsigned int uType);
150 151
 
151 152
 
152 153
 
153
-#if !defined(__linux__) && !defined(ANDROID)
154
+#if !defined(__linux__) && !defined(ANDROID) && RAYLIB_VERSION_MAJOR==5 && RAYLIB_VERSION_MINOR==0
154 155
 /* the old raylib used in the windows build lacks this function */
155 156
 bool IsImageValid(Image image)
156 157
 {
... ...
@@ -397,7 +398,7 @@ main(int argc, char *argv[])
397 398
                 click_avail=1;
398 399
                 has_mousechanges=(lmbdown!=oldlmbdown || rmbdown!=oldrmbdown || mousepos.x!=oldmousepos.x || mousepos.y!=oldmousepos.y || wheel.x!=0 || wheel.y!=0)?1:0;
399 400
                 needs_nextredraw=0;
400
-                /* process scrolling */
401
+                /* mouse process scrolling */
401 402
                 if(lmbdown==1 && oldlmbdown==0 && scrollstart==0 && mousepos.y>im->body->xywh.y) {
402 403
                         scrollstart=imutil_milliseconds();
403 404
                         scrollstartpos=mousepos;
... ...
@@ -440,7 +441,7 @@ main(int argc, char *argv[])
440 441
                         scrollspeed=scrollspeed*4/5;
441 442
                         im->body->dirdata[im->body->currentdirdata]->leftscrollpos+=scrollspeed;
442 443
                 }
443
-                /* process clicks on menus */
444
+                /* mouse process clicks on menus */
444 445
                 if(click_avail) {
445 446
                         sel_menu=sel_submenu=NULL;
446 447
                         im_menubar_mouse(im->menubar, mousepos, lmbpressed, lmbreleased, lmbdown, &click_avail, &sel_menu, &sel_submenu);
Browse code

Fix windows pipe init, add debug messages for windows using messagebox

Dario Rodriguez authored on 25/07/2025 08:00:50
Showing 1 changed files
... ...
@@ -141,6 +141,14 @@
141 141
 #define WR 1
142 142
 #endif
143 143
 
144
+#if !defined(__linux__) && !defined(ANDROID)
145
+int MessageBoxA(void *hWnd,void *lpText,void *lpCaption,unsigned int uType);
146
+#define messagebox(str) MessageBoxA(NULL,str,"imgmover",0);
147
+#else
148
+#define messagebox(str) fprintf(stderr,"%s\n",str);
149
+#endif
150
+
151
+
144 152
 
145 153
 #if !defined(__linux__) && !defined(ANDROID)
146 154
 /* the old raylib used in the windows build lacks this function */
... ...
@@ -365,9 +373,7 @@ main(int argc, char *argv[])
365 373
         win32pipe_init();
366 374
 #endif
367 375
         if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n",ROOTDIR))==NULL) {
368
-#if !defined(__linux__) && !defined(ANDROID)
369
-                MessageBoxA(NULL,"Couldn't init interface","imgmover",0);
370
-#endif
376
+                messagebox("Couldn't init interface");
371 377
                 return(1);
372 378
         }
373 379
         flag_ignorelmb=0;
... ...
@@ -507,6 +513,7 @@ im_t *
507 513
 im_init(char *menus, char *rootdir)
508 514
 {
509 515
         im_t *im;
516
+        char *errstr;
510 517
         if(menus==NULL)
511 518
                 return(NULL); /* sanity check failed */
512 519
         if((im=calloc(1,sizeof(im_t)))==NULL) {
... ...
@@ -519,12 +526,16 @@ im_init(char *menus, char *rootdir)
519 526
         im->windowinit=1;
520 527
         SetTargetFPS(30);
521 528
         /* init fonts and contents */
522
-        if((im->font=im_font_init(FONTSIZE))==NULL
529
+        if((errstr="Couldn't init font")==NULL
530
+          || (im->font=im_font_init(FONTSIZE))==NULL
523 531
           || (im->fontbig=im_font_init(FONTBIGSIZE))==NULL
524 532
           || (im->fonthuge=im_font_init(FONTHUGESIZE))==NULL
533
+          || (errstr="Couldn't init menus")==NULL
525 534
           || (im->menubar=im_menubar_init(menus,im->font))==NULL
535
+          || (errstr="Couldn't init interface data")==NULL
526 536
           || (im->body=im_body_init(0,im->menubar->height, im->font, im->fontbig, im->fonthuge, LEFTSIZE, rootdir,im->w,im->h))==NULL
527 537
         ) {
538
+                messagebox(errstr);
528 539
                 im_free(im),im=NULL;
529 540
                 return(NULL); /* insuf. mem. */
530 541
         }
... ...
@@ -827,13 +838,20 @@ body_t *
827 838
 im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir, int windowwidth, int windowheight)
828 839
 {
829 840
         body_t *body;
841
+        char *errstr;
830 842
         static char sep[]={SEP};
831
-        if(font==NULL || fontbig==NULL || fonthuge==NULL || rootdir==NULL)
843
+        if(font==NULL || fontbig==NULL || fonthuge==NULL || rootdir==NULL) {
844
+                messagebox("im_body_init sanity check failed");
832 845
                 return(NULL); /* sanity check failed */
833
-        if((body=calloc(1,sizeof(body_t)))==NULL
846
+        }
847
+        if((errstr="Insuf. mem. for body")==NULL
848
+          || (body=calloc(1,sizeof(body_t)))==NULL
849
+          || (errstr="Insuf. mem. for rootdir str")==NULL
834 850
           || (body->rootdir=strdup(rootdir))==NULL
851
+          || (errstr="Error init bg")==NULL
835 852
           || (body->bg=bg_init(SIZEBGLOAD))==NULL
836 853
         ) {
854
+                messagebox(errstr);
837 855
                 im_body_free(body),body=NULL;
838 856
                 return(NULL);
839 857
         }
... ...
@@ -1962,16 +1980,23 @@ bg_t *
1962 1980
 bg_init(int sizebgload)
1963 1981
 {
1964 1982
         bg_t *bg;
1983
+        char *errstr;
1965 1984
         bg=NULL;
1966
-        if((bg=calloc(1,sizeof(bg_t)))==NULL
1985
+        if((errstr="Insuf. mem. for bg")==NULL
1986
+          || (bg=calloc(1,sizeof(bg_t)))==NULL
1987
+          || (errstr="Error init pipes (please check program is not blocked in firewall)")==NULL
1967 1988
           || (bg->pipe[0]=bg->pipe[1]=-1)!=-1
1968 1989
           || mypipe(bg->pipe)!=0
1990
+          || (errstr="Insuf mem bgload")==NULL
1969 1991
           || (bg->bgload=calloc(sizebgload,sizeof(bgload_t)))==NULL
1970 1992
           || (bg->sizebgload=sizebgload)!=sizebgload
1993
+          || (errstr="pthread attr init error")==NULL
1971 1994
           || pthread_attr_init(&(bg->tattr))!=0
1995
+          || (errstr="pthread create error")==NULL
1972 1996
           || pthread_create(&(bg->thread),&(bg->tattr),bg_thread,(void *)bg)!=0
1973 1997
           || (bg->flag_threadstarted=1)!=1
1974 1998
         ) {
1999
+                messagebox(errstr);
1975 2000
                 bg_free(bg);
1976 2001
                 return(NULL);
1977 2002
         }
Browse code

In windows, show error messagebox when cannot init

Dario Rodriguez authored on 23/07/2025 21:34:18
Showing 1 changed files
... ...
@@ -59,9 +59,9 @@
59 59
 
60 60
 #define UTF8DOWNARROW "\xe2\x86\x86" /* U+2186 in UTF-8 */
61 61
 
62
-#ifndef ANDROID
63
-#define SIMANDROID
64
-#endif
62
+//#ifndef ANDROID
63
+//#define SIMANDROID
64
+//#endif
65 65
 
66 66
 #define TARGETFPS 30
67 67
 
... ...
@@ -78,7 +78,14 @@
78 78
 #define FONTHUGESIZE 128
79 79
 #define ADDREMOVEDIRDATAHEIGHT 128
80 80
 #else
81
-#define ROOTDIR "/var/www/default/animeshot/"
81
+#if !defined(__linux__) && !defined(ANDROID)
82
+#define ROOTDIR "Z:\\"
83
+#define SEP "\\"
84
+#else
85
+//#define ROOTDIR "/var/www/default/animeshot/"
86
+#define ROOTDIR "/"
87
+#define SEP "/"
88
+#endif
82 89
 #define DEFAULTWIDTH 1280
83 90
 #define DEFAULTHEIGHT 768
84 91
 #define LEFTSIZE 720
... ...
@@ -100,7 +107,6 @@
100 107
 
101 108
 #define WHEELSTEP LEFTIMAGESIDELEN
102 109
 
103
-#define SEP "/"
104 110
 
105 111
 #define BLOCKLISTINGBUF 2048
106 112
 #define BLOCKLISTINGELEMS 1024
... ...
@@ -359,6 +365,9 @@ main(int argc, char *argv[])
359 365
         win32pipe_init();
360 366
 #endif
361 367
         if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n",ROOTDIR))==NULL) {
368
+#if !defined(__linux__) && !defined(ANDROID)
369
+                MessageBoxA(NULL,"Couldn't init interface","imgmover",0);
370
+#endif
362 371
                 return(1);
363 372
         }
364 373
         flag_ignorelmb=0;
Browse code

Start move image functionality

Dario Rodriguez authored on 27/04/2025 18:32:43
Showing 1 changed files
... ...
@@ -34,6 +34,7 @@
34 34
  *      20250330 Refine background loading.
35 35
  *      20250413 Background loading for windows target.
36 36
  *      20250420 Fix background loading for windows target.
37
+ *      20250427 Start move image functionality.
37 38
  *
38 39
  * Author: Dario Rodriguez dario@darionomono.com
39 40
  * (c) Dario Rodriguez 2025
... ...
@@ -265,6 +266,7 @@ typedef struct body_t {
265 266
         xywh_t dirdataadd;
266 267
         Font roundedbox;
267 268
         bg_t *bg;
269
+        char selectedpath[2048];
268 270
 } body_t;
269 271
 
270 272
 typedef struct im_t {
... ...
@@ -295,6 +297,8 @@ body_t *im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthu
295 297
 void im_body_free(body_t *body);
296 298
 
297 299
 int im_body_add(body_t *body,char *dir);
300
+int im_body_tryselect(body_t *body, Vector2 mousepos);
301
+
298 302
 
299 303
 int im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
300 304
 int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight, int *needs_nextredraw, int scrollspeed);
... ...
@@ -363,6 +367,7 @@ main(int argc, char *argv[])
363 367
         needs_nextredraw=1;
364 368
         scrollstart=0;
365 369
         is_scrolling=0;
370
+        im->body->selectedpath[0]='\0';
366 371
         while(!WindowShouldClose()) {
367 372
                 imutil_fpsreset();
368 373
                 oldmousepos=mousepos;
... ...
@@ -399,8 +404,12 @@ main(int argc, char *argv[])
399 404
                         }
400 405
                         t=scrollstartpos.x-mousepos.x;
401 406
                         t=(t<0)?-t:t;
402
-                        if(t>SCROLLTHRESHOLD)
407
+                        if(t>SCROLLTHRESHOLD) {
403 408
                                 is_scrolling=0,scrollstart=0;
409
+                                im_body_tryselect(im->body,scrollstartpos);
410
+                                if(im->body->selectedpath[0]!='\0')
411
+                                        click_avail=0;
412
+                        }
404 413
                 }
405 414
                 if(is_scrolling) {
406 415
                         long long tcur,tdif;
... ...
@@ -668,7 +677,7 @@ im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbre
668 677
         *sel_menu=NULL;
669 678
         *sel_submenu=NULL;
670 679
         flag_outsideall=1;
671
-#if 1
680
+#if 0
672 681
 if(lmbpressed || lmbdown)
673 682
  fprintf(stderr,"in_menubar_mouse: lmbpressed:%i lmbdown:%i\n",lmbpressed,lmbdown);
674 683
 #endif
... ...
@@ -896,6 +905,30 @@ im_body_add(body_t *body,char *dir)
896 905
         return(0);
897 906
 }
898 907
 
908
+int
909
+im_body_tryselect(body_t *body, Vector2 mousepos)
910
+{
911
+        int i;
912
+        listing_t *listing;
913
+        listingdata_t *elem;
914
+        if(body==NULL || body->currentdirdata<0 || body->currentdirdata>=body->sizedirdata || body->dirdata[body->currentdirdata]==NULL || body->currentdirdata>=body->sizedirdata)
915
+                return(-1); /* sanity check failed */
916
+        body->selectedpath[0]='\0';
917
+        if(!is_imutil_insidexywh(mousepos,&(body->xywh),0) || mousepos.x>body->leftsize)
918
+                return(-1); /* outside leftside */
919
+        listing=&(body->dirdata[body->currentdirdata]->listing);
920
+        for(i=0;i<listing->usedelems;i++) {
921
+                elem=listing->elems+i;
922
+                if(is_imutil_insidexywh(mousepos,&(elem->left.screenxywh),0)) {
923
+                        strncpy(body->selectedpath,elem->name,sizeof(body->selectedpath));
924
+                        body->selectedpath[sizeof(body->selectedpath)-1]='\0';
925
+                        return(0); /* found */
926
+                }
927
+        }
928
+        return(-1); /* no thumbnail found for pos */
929
+}
930
+
931
+
899 932
 int
900 933
 im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail)
901 934
 {
... ...
@@ -922,7 +955,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
922 955
                 return(0); /* nothing else to do */
923 956
         }
924 957
         margin=body->ptrfont->height/4;
925
-        if(body->is_displayingtexture && lmbreleased && is_imutil_insidexywh(mousepos,&(body->texture.source),margin)) {
958
+        if(body->is_displayingtexture && lmbreleased && is_imutil_insidexywh(mousepos,&(body->texture.source),margin) && body->selectedpath[0]=='\0') {
926 959
                 body->flag_drawbigtexture=1;
927 960
                 return(0); /* nothing else to do */
928 961
         }
... ...
@@ -970,28 +1003,51 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
970 1003
                         return(0);
971 1004
                 }
972 1005
         }
973
-        /* dirdata select */
974
-        if(mousepos.x>body->leftsize && mousepos.y>body->xywh.y) {
975
-                int righty;
976
-                for(righty=body->xywh.y,i=0;i<body->sizedirdata;i++) {
977
-                        if(body->dirdata[i]==NULL)
978
-                                continue;
979
-                        if(mousepos.y>=righty && mousepos.y<(righty+body->dirdata[i]->height) && i!=body->currentdirdata) {
980
-                                body->currentdirdata=i;
981
-                                *click_avail=0;
982
-                                return(0);
1006
+        /* dirdata processing */
1007
+        if(body->selectedpath[0]=='\0') {
1008
+                /* dirdata select */
1009
+                if(mousepos.x>body->leftsize && mousepos.y>body->xywh.y) {
1010
+                        int righty;
1011
+                        for(righty=body->xywh.y,i=0;i<body->sizedirdata;i++) {
1012
+                                if(body->dirdata[i]==NULL)
1013
+                                        continue;
1014
+                                if(mousepos.y>=righty && mousepos.y<(righty+body->dirdata[i]->height) && i!=body->currentdirdata) {
1015
+                                        body->currentdirdata=i;
1016
+                                        *click_avail=0;
1017
+                                        return(0);
1018
+                                }
1019
+                                righty+=body->dirdata[i]->height;
983 1020
                         }
984
-                        righty+=body->dirdata[i]->height;
985 1021
                 }
1022
+                /* detect click on "add dirdata" button */
1023
+                if(is_imutil_insidexywh(mousepos,&(body->dirdataadd),0)) {
1024
+                        im_body_add(body,body->dirdata[body->currentdirdata]->dirname);
1025
+                        *click_avail=0;
1026
+                        return(0);
1027
+                }
1028
+                /* dirdata remove */
1029
+#warning TODO
986 1030
         }
987
-        /* detect click on "add dirdata" button */
988
-        if(is_imutil_insidexywh(mousepos,&(body->dirdataadd),0)) {
989
-                im_body_add(body,body->dirdata[body->currentdirdata]->dirname);
990
-                *click_avail=0;
991
-                return(0);
992
-        }
993
-        /* dirdata remove */
1031
+        /* unselect selectedpath */
1032
+        if(lmbpressed==0 && body->selectedpath[0]!='\0') {
1033
+                if(mousepos.x>body->leftsize && mousepos.y>body->xywh.y) {
1034
+                        int righty;
1035
+                        for(righty=body->xywh.y,i=0;i<body->sizedirdata;i++) {
1036
+                                if(body->dirdata[i]==NULL)
1037
+                                        continue;
1038
+                                if(mousepos.y>=righty && mousepos.y<(righty+body->dirdata[i]->height) && i!=body->currentdirdata && strcmp(body->dirdata[i]->dirname,body->dirdata[body->currentdirdata]->dirname)!=0) {
994 1039
 #warning TODO
1040
+#if 1
1041
+fprintf(stderr,"WOULD MOVE \"%s/%s\" to \"%s\"\n",body->dirdata[body->currentdirdata]->dirname,body->selectedpath+1,body->dirdata[i]->dirname);
1042
+#endif
1043
+                                        *click_avail=0;
1044
+                                        break;
1045
+                                }
1046
+                                righty+=body->dirdata[i]->height;
1047
+                        }
1048
+                }
1049
+                body->selectedpath[0]='\0';
1050
+        }
995 1051
         return(0);
996 1052
 }
997 1053
 
... ...
@@ -1010,6 +1066,7 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
1010 1066
         int xoff,yoff;
1011 1067
         thumb_t *thumb;
1012 1068
         char statustooltip[1024];
1069
+        thumb_t *selectedthumb;
1013 1070
         if(body==NULL)
1014 1071
                 return(-1);
1015 1072
         font=body->ptrfont;
... ...
@@ -1018,6 +1075,7 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
1018 1075
         FILLXYWH(body->backxywh,0,0,0,0);
1019 1076
         margin=font->height/4;
1020 1077
         body->is_displayingtexture=0;
1078
+        selectedthumb=NULL;
1021 1079
         /* if we are displaying a full screenimage... */
1022 1080
         if(body->flag_drawbigtexture && body->texture.has_texture) {
1023 1081
                 /* draw image in full screen */
... ...
@@ -1256,6 +1314,17 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1256 1314
                                         DrawTextEx(font->font,shortname,(Vector2){pos->x+xoff+font->height/4,pos->y+yoff+font->height/4},font->height,0,(Color){ 192,192,192,255 });
1257 1315
                                         lastx=xywh->x+xoff+xywh->w,lasty=xywh->y+yoff+xywh->h;
1258 1316
                                 }
1317
+                                /* show selected rectangle */
1318
+                                if(is_leftside && strcmp(body->selectedpath,elem->name)==0) {
1319
+                                        Color c=((Color){0,0,255,64});
1320
+                                        DrawRectangle(UNROLLXYWH(thumb->screenxywh),c);
1321
+                                        c=((Color){0,0,255,255});
1322
+                                        DrawRectangle(thumb->screenxywh.x,thumb->screenxywh.y,thumb->screenxywh.w,2,c);
1323
+                                        DrawRectangle(thumb->screenxywh.x,thumb->screenxywh.y+2,2,thumb->screenxywh.h-4,c);
1324
+                                        DrawRectangle(thumb->screenxywh.x+thumb->screenxywh.w-2,thumb->screenxywh.y+2,2,thumb->screenxywh.h-4,c);
1325
+                                        DrawRectangle(thumb->screenxywh.x,thumb->screenxywh.y+thumb->screenxywh.h-2,thumb->screenxywh.w,2,c);
1326
+                                        selectedthumb=thumb;
1327
+                                }
1259 1328
                         }
1260 1329
                         for(;k<dirdata->listing.usedelems;k++) {
1261 1330
                                 elem=dirdata->listing.elems+k;
... ...
@@ -1271,6 +1340,16 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1271 1340
                                 if(i==body->currentdirdata) {
1272 1341
                                         /* draw right side "current" marker inside left side area */
1273 1342
                                         DrawTriangle((Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)}, (Vector2){((float)body->xywh.x)+body->leftsize-DEFAULTDIRDATATRIANGLEW,((float)righty)+dirdata->height/2}, (Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)+dirdata->height-1}, (Color){ 168, 168, 168, 255 } );
1343
+                                } else if(body->selectedpath[0]!='\0' && mousepos.x>body->leftsize && mousepos.y>=righty && mousepos.y<(righty+dirdata->height) && strcmp(body->dirdata[i]->dirname,body->dirdata[body->currentdirdata]->dirname)!=0) {
1344
+                                        xywh_t xywh;
1345
+                                        Color c=((Color){0,0,255,64});
1346
+                                        FILLXYWH(xywh,body->leftsize,righty,body->xywh.w-body->leftsize,dirdata->height);
1347
+                                        DrawRectangle(UNROLLXYWH(xywh),c);
1348
+                                        c=((Color){0,0,255,255});
1349
+                                        DrawRectangle(xywh.x,xywh.y,xywh.w,2,c);
1350
+                                        DrawRectangle(xywh.x,xywh.y+2,2,xywh.h-4,c);
1351
+                                        DrawRectangle(xywh.x+xywh.w-2,xywh.y+2,2,xywh.h-4,c);
1352
+                                        DrawRectangle(xywh.x,xywh.y+xywh.h-2,xywh.w,2,c);
1274 1353
                                 }
1275 1354
                                 /* advance to next element */
1276 1355
                                 righty+=dirdata->height;
... ...
@@ -1306,6 +1385,12 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1306 1385
         } else {
1307 1386
                 memset(&(body->dirdataadd),0,sizeof(body->dirdataadd));
1308 1387
         }
1388
+        /* if moving elem, show line from orig to mousepos */
1389
+        if(body->selectedpath[0]!='\0' && selectedthumb!=NULL) {
1390
+                Color c=((Color){0,0,255,255});
1391
+                DrawLineEx((Vector2){(float)(selectedthumb->screenxywh.x+selectedthumb->screenxywh.w/2),(float)(selectedthumb->screenxywh.y+selectedthumb->screenxywh.h/2)},mousepos,2.0,c);
1392
+        }
1393
+        /* show tooltip */
1309 1394
         if(statustooltip[0]!='\0') {
1310 1395
                 m2=MeasureTextEx(font->font,statustooltip,font->height,0);
1311 1396
                 DrawRectangle(0,windowheight-1-margin*2-font->height,m2.x+margin*2,font->height+margin*2,((Color){0,0,0,96}));
Browse code

Fix background loading for windows target

Dario Rodriguez authored on 20/04/2025 18:08:53
Showing 1 changed files
... ...
@@ -33,6 +33,7 @@
33 33
  *      20250329 Background loading of thumbnails.
34 34
  *      20250330 Refine background loading.
35 35
  *      20250413 Background loading for windows target.
36
+ *      20250420 Fix background loading for windows target.
36 37
  *
37 38
  * Author: Dario Rodriguez dario@darionomono.com
38 39
  * (c) Dario Rodriguez 2025
... ...
@@ -48,6 +49,9 @@
48 49
 #include <sys/stat.h>
49 50
 #include <sys/time.h>
50 51
 #include <pthread.h>
52
+#if !defined(__linux__) && !defined(ANDROID)
53
+#include "win32_pipe.h"
54
+#endif
51 55
 
52 56
 #include "raylib.h"
53 57
 #include "roboto_regular.c"
... ...
@@ -328,6 +332,8 @@ int bg_freeunmarked(bg_t *bg);
328 332
 void *bg_thread(void *);
329 333
 
330 334
 static int mypipe(int fds[2]);
335
+static int mypiperead(int fd, char *buf, int count);
336
+static int mypipewrite(int fd, char *buf, int count);
331 337
 
332 338
 int
333 339
 main(int argc, char *argv[])
... ...
@@ -345,6 +351,9 @@ main(int argc, char *argv[])
345 351
         int is_scrolling;
346 352
         int leftscrollposstart;
347 353
         char *sel_menu,*sel_submenu;
354
+#if !defined(__linux__) && !defined(ANDROID)
355
+        win32pipe_init();
356
+#endif
348 357
         if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n",ROOTDIR))==NULL) {
349 358
                 return(1);
350 359
         }
... ...
@@ -470,6 +479,9 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
470 479
                 EndDrawing();
471 480
         }
472 481
         im_free(im),im=NULL;
482
+#if !defined(__linux__) && !defined(ANDROID)
483
+        win32pipe_fini();
484
+#endif
473 485
         return(0);
474 486
 }
475 487
 
... ...
@@ -656,6 +668,10 @@ im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbre
656 668
         *sel_menu=NULL;
657 669
         *sel_submenu=NULL;
658 670
         flag_outsideall=1;
671
+#if 1
672
+if(lmbpressed || lmbdown)
673
+ fprintf(stderr,"in_menubar_mouse: lmbpressed:%i lmbdown:%i\n",lmbpressed,lmbdown);
674
+#endif
659 675
         for(i=0;i<menubar->sizemenudata;i++) {
660 676
                 int insidetitle,currentoption;
661 677
                 insidetitle=is_imutil_insidexywh(mousepos,&(menubar->menudata[i]->xywh),0);
... ...
@@ -1877,8 +1893,17 @@ bg_free(bg_t *bg)
1877 1893
                 return; /* nothing to do */
1878 1894
         if(bg->flag_threadstarted) {
1879 1895
                 char dummy=1;
1880
-                write(bg->pipe[WR],&dummy,1);
1896
+#if 1
1897
+fprintf(stderr,"bg_free: notifying thread to exit\n");
1898
+#endif
1899
+                mypipewrite(bg->pipe[WR],&dummy,1);
1900
+#if 1
1901
+fprintf(stderr,"bg_free: joining thread\n");
1902
+#endif
1881 1903
                 pthread_join(bg->thread,NULL);
1904
+#if 1
1905
+fprintf(stderr,"bg_free: thread joined OK\n");
1906
+#endif
1882 1907
                 bg->flag_threadstarted=0;
1883 1908
         }
1884 1909
         if(bg->pipe[0]!=-1)
... ...
@@ -1934,7 +1959,7 @@ bg_add(bg_t *bg, char *path)
1934 1959
 {
1935 1960
         int i;
1936 1961
         bgload_t *bgload;
1937
-        int dummy;
1962
+        char dummy;
1938 1963
         if(bg==NULL)
1939 1964
                 return(-1);
1940 1965
         for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
... ...
@@ -1942,7 +1967,7 @@ bg_add(bg_t *bg, char *path)
1942 1967
                         bgload->is_todo=1;
1943 1968
                         bgload->has_mark=1;
1944 1969
                         dummy=0;
1945
-                        write(bg->pipe[WR],&dummy,1);
1970
+                        mypipewrite(bg->pipe[WR],&dummy,1);
1946 1971
                         return(0); /* already on list */
1947 1972
                 }
1948 1973
         }
... ...
@@ -1955,7 +1980,7 @@ bg_add(bg_t *bg, char *path)
1955 1980
                         bgload->has_mark=1;
1956 1981
                         dummy=0;
1957 1982
                         bgload->lended_to_thread=1;
1958
-                        write(bg->pipe[WR],&dummy,1);
1983
+                        mypipewrite(bg->pipe[WR],&dummy,1);
1959 1984
                         return(0); /* added to list */
1960 1985
                 }
1961 1986
         }
... ...
@@ -1998,7 +2023,10 @@ bg_thread(void *parambg)
1998 2023
         int i;
1999 2024
         bgload_t *bgload;
2000 2025
         while(1) {
2001
-                read(bg->pipe[RD],&dummy,1);
2026
+                mypiperead(bg->pipe[RD],&dummy,1);
2027
+#if 1
2028
+fprintf(stderr,"Thread received byte: %i\n",(int)((unsigned char)dummy));
2029
+#endif
2002 2030
                 if(dummy!=0)
2003 2031
                         break; /* was told to exit */
2004 2032
                 for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
... ...
@@ -2019,20 +2047,45 @@ bg_thread(void *parambg)
2019 2047
                 }
2020 2048
         }
2021 2049
         pthread_exit(NULL);
2050
+        return(NULL);
2022 2051
 }
2023 2052
 
2024 2053
 #if !defined(__linux__) && !defined(ANDROID)
2025
-#include "win32_pipe.h"
2026 2054
 static int
2027 2055
 mypipe(int fds[2])
2028 2056
 {
2029
-        return(win32_pipe(fds));
2057
+        return(win32pipe_pipe(fds));
2058
+}
2059
+
2060
+static int
2061
+mypiperead(int fd, char *buf, int count)
2062
+{
2063
+        return(win32pipe_read(fd,buf,count));
2064
+}
2065
+
2066
+static int
2067
+mypipewrite(int fd, char *buf, int count)
2068
+{
2069
+        return(win32pipe_write(fd,buf,count));
2030 2070
 }
2031 2071
 #else
2032 2072
 static int
2033
-mypipe(char fds[2])
2073
+mypipe(int fds[2])
2034 2074
 {
2035 2075
         return(pipe(fds));
2036 2076
 }
2077
+
2078
+static int
2079
+mypiperead(int fd, char *buf, int count)
2080
+{
2081
+        return(read(fd,buf,count));
2082
+}
2083
+
2084
+static int
2085
+mypipewrite(int fd, char *buf, int count)
2086
+{
2087
+        return(write(fd,buf,count));
2088
+}
2037 2089
 #endif
2038 2090
 
2091
+
Browse code

Background loading for windows target

Dario Rodriguez authored on 13/04/2025 15:31:58
Showing 1 changed files
... ...
@@ -32,6 +32,7 @@
32 32
  *               Dirdata colors. Select dirdata.
33 33
  *      20250329 Background loading of thumbnails.
34 34
  *      20250330 Refine background loading.
35
+ *      20250413 Background loading for windows target.
35 36
  *
36 37
  * Author: Dario Rodriguez dario@darionomono.com
37 38
  * (c) Dario Rodriguez 2025
... ...
@@ -326,6 +327,8 @@ int bg_freeunmarked(bg_t *bg);
326 327
 
327 328
 void *bg_thread(void *);
328 329
 
330
+static int mypipe(int fds[2]);
331
+
329 332
 int
330 333
 main(int argc, char *argv[])
331 334
 {
... ...
@@ -1852,7 +1855,7 @@ bg_init(int sizebgload)
1852 1855
         bg=NULL;
1853 1856
         if((bg=calloc(1,sizeof(bg_t)))==NULL
1854 1857
           || (bg->pipe[0]=bg->pipe[1]=-1)!=-1
1855
-          || pipe(bg->pipe)!=0
1858
+          || mypipe(bg->pipe)!=0
1856 1859
           || (bg->bgload=calloc(sizebgload,sizeof(bgload_t)))==NULL
1857 1860
           || (bg->sizebgload=sizebgload)!=sizebgload
1858 1861
           || pthread_attr_init(&(bg->tattr))!=0
... ...
@@ -2018,3 +2021,18 @@ bg_thread(void *parambg)
2018 2021
         pthread_exit(NULL);
2019 2022
 }
2020 2023
 
2024
+#if !defined(__linux__) && !defined(ANDROID)
2025
+#include "win32_pipe.h"
2026
+static int
2027
+mypipe(int fds[2])
2028
+{
2029
+        return(win32_pipe(fds));
2030
+}
2031
+#else
2032
+static int
2033
+mypipe(char fds[2])
2034
+{
2035
+        return(pipe(fds));
2036
+}
2037
+#endif
2038
+
Browse code

Refine background loading

Dario Rodriguez authored on 30/03/2025 18:20:54
Showing 1 changed files
... ...
@@ -31,6 +31,7 @@
31 31
  *      20250320 Fix add-dirdata button appearance.
32 32
  *               Dirdata colors. Select dirdata.
33 33
  *      20250329 Background loading of thumbnails.
34
+ *      20250330 Refine background loading.
34 35
  *
35 36
  * Author: Dario Rodriguez dario@darionomono.com
36 37
  * (c) Dario Rodriguez 2025
... ...
@@ -291,7 +292,7 @@ void im_body_free(body_t *body);
291 292
 int im_body_add(body_t *body,char *dir);
292 293
 
293 294
 int im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
294
-int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight, int *needs_nextredraw);
295
+int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight, int *needs_nextredraw, int scrollspeed);
295 296
 
296 297
 int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort);
297 298
 void listing_freedata(listing_t *listing);
... ...
@@ -421,7 +422,7 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
421 422
                 /* draw screen contents */
422 423
                 BeginDrawing();
423 424
                 ClearBackground(RAYWHITE);
424
-                im_body_draw(im->body,mousepos,lmbdown,rmbdown,im->w,im->h,&needs_nextredraw);
425
+                im_body_draw(im->body,mousepos,lmbdown,rmbdown,im->w,im->h,&needs_nextredraw,scrollspeed);
425 426
                 im_menubar_draw(im->menubar,im->w,im->h,&needs_nextredraw);
426 427
 #if 0
427 428
 {
... ...
@@ -976,7 +977,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
976 977
 }
977 978
 
978 979
 int
979
-im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight, int *needs_nextredraw)
980
+im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight, int *needs_nextredraw, int scrollspeed)
980 981
 {
981 982
         int i,k,margin,righty;
982 983
         int lastx,lasty;
... ...
@@ -1142,7 +1143,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
1142 1143
                                 }
1143 1144
                                 /* show image */
1144 1145
                                 has_imagedrawn=0;
1145
-                                if(is_imagefilename(elem->name+1)) {
1146
+                                if(is_imagefilename(elem->name+1) && !(thumb->screenxywh.y>(body->xywh.y+body->xywh.h) || (thumb->screenxywh.y+thumb->screenxywh.h)<body->xywh.y)) {
1146 1147
                                         if(thumb->has_texture==0 && thumb->has_failedload==0) {
1147 1148
                                                 bgload_t *bgload;
1148 1149
                                                 char fullpath[2048];
... ...
@@ -1189,7 +1190,7 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1189 1190
                                                 DrawTexture(*te,thumb->screenxywh.x,thumb->screenxywh.y,WHITE);
1190 1191
                                                 has_imagedrawn=1;
1191 1192
                                                 lastx=xywh->x+xywh->w,lasty=xywh->y+xywh->h+yoff;
1192
-                                                if(is_leftside && rmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
1193
+                                                if(is_leftside && rmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin) && scrollspeed==0) {
1193 1194
                                                         /* draw image in rightside */
1194 1195
                                                         char fullpath[2048];
1195 1196
                                                         int maxw,maxh;
... ...
@@ -1291,8 +1292,9 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1291 1292
                 DrawRectangle(0,windowheight-1-margin*2-font->height,m2.x+margin*2,font->height+margin*2,((Color){0,0,0,96}));
1292 1293
                 DrawTextEx(font->font,statustooltip,(Vector2){margin,windowheight-1-margin-font->height},font->height,0,(Color){ 255,255,255,128 });
1293 1294
         }
1294
-        /* free not used bg load items */
1295
-        bg_freeunmarked(body->bg);
1295
+        /* free not used bg load items (only if idle, as it takes time) */
1296
+        if(scrollspeed==0 && *needs_nextredraw==0)
1297
+                bg_freeunmarked(body->bg);
1296 1298
         return(0);
1297 1299
 }
1298 1300
 
Browse code

Background loading of thumbnails

Dario Rodriguez authored on 29/03/2025 20:03:59
Showing 1 changed files
... ...
@@ -30,6 +30,7 @@
30 30
  *      20250319 Add-dirdata button.
31 31
  *      20250320 Fix add-dirdata button appearance.
32 32
  *               Dirdata colors. Select dirdata.
33
+ *      20250329 Background loading of thumbnails.
33 34
  *
34 35
  * Author: Dario Rodriguez dario@darionomono.com
35 36
  * (c) Dario Rodriguez 2025
... ...
@@ -44,6 +45,7 @@
44 45
 #include <dirent.h>
45 46
 #include <sys/stat.h>
46 47
 #include <sys/time.h>
48
+#include <pthread.h>
47 49
 
48 50
 #include "raylib.h"
49 51
 #include "roboto_regular.c"
... ...
@@ -96,6 +98,7 @@
96 98
 #define BLOCKLISTINGBUF 2048
97 99
 #define BLOCKLISTINGELEMS 1024
98 100
 #define BLOCKDIRDATA 16
101
+#define SIZEBGLOAD 256
99 102
 
100 103
 #ifndef FILLXY
101 104
 #define FILLXY(xywh,valx,valy) (xywh).x=(valx),(xywh).y=(valy)
... ...
@@ -117,6 +120,15 @@
117 120
 #define UNROLLWHXY(xywh) (xywh).w,(xywh).h,(xywh).x,(xywh).y
118 121
 #endif
119 122
 
123
+#ifndef RD
124
+#define RD 0
125
+#endif
126
+
127
+#ifndef WR
128
+#define WR 1
129
+#endif
130
+
131
+
120 132
 #if !defined(__linux__) && !defined(ANDROID)
121 133
 /* the old raylib used in the windows build lacks this function */
122 134
 bool IsImageValid(Image image)
... ...
@@ -206,6 +218,28 @@ typedef struct texture_t {
206 218
         xywh_t source; /* be able to detect a "double click" */
207 219
 } texture_t;
208 220
 
221
+typedef struct bgload_t {
222
+        /* main/thread ownership management */
223
+        int lended_to_thread; // written from main, read from thread
224
+        int thread_finished; // written from thread, read from main
225
+        int is_todo;  // written from main, read from thread
226
+        int has_mark;  // written/read from main
227
+        /* data only accessed from owner */
228
+        char path[1024]; // to use only from owner
229
+        Image image; // to use only from owner
230
+        int has_data; // to use only from owner
231
+        int has_failedload; // to use only from owner
232
+} bgload_t;
233
+
234
+typedef struct bg_t {
235
+        int sizebgload;
236
+        bgload_t *bgload;
237
+        int pipe[2];
238
+        pthread_t thread;
239
+        pthread_attr_t tattr;
240
+        int flag_threadstarted;
241
+} bg_t;
242
+
209 243
 typedef struct body_t {
210 244
         char *rootdir;
211 245
         xywh_t xywh;
... ...
@@ -224,6 +258,7 @@ typedef struct body_t {
224 258
         int flag_drawbigtexture;
225 259
         xywh_t dirdataadd;
226 260
         Font roundedbox;
261
+        bg_t *bg;
227 262
 } body_t;
228 263
 
229 264
 typedef struct im_t {
... ...
@@ -262,7 +297,7 @@ int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort)
262 297
 void listing_freedata(listing_t *listing);
263 298
 int listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_left);
264 299
 
265
-int texture_load(texture_t *texture, char *fullpath, int maxw, int maxh);
300
+int texture_load(texture_t *texture, char *fullpath, int maxw, int maxh, bg_t *bg);
266 301
 int texture_draw(texture_t *texture, int x0, int y0, int maxw, int maxh);
267 302
 int texture_freedata(texture_t *texture);
268 303
 
... ...
@@ -281,6 +316,15 @@ void imutil_fpsreset(void);
281 316
 int imutil_fpsleft(void);
282 317
 long long imutil_milliseconds(void);
283 318
 
319
+bg_t *bg_init(int sizebgload);
320
+void bg_free(bg_t *bg);
321
+int bg_resetmarks(bg_t *bg);
322
+bgload_t *bg_get(bg_t *bg, char *path);
323
+int bg_add(bg_t *bg, char *path);
324
+int bg_freeunmarked(bg_t *bg);
325
+
326
+void *bg_thread(void *);
327
+
284 328
 int
285 329
 main(int argc, char *argv[])
286 330
 {
... ...
@@ -412,7 +456,7 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
412 456
  }
413 457
 }
414 458
 #endif
415
-                if(has_mousechanges==0 && needs_nextredraw==0) {
459
+                if(has_mousechanges==0 && needs_nextredraw==0 && scrollspeed==0) {
416 460
                         /* Wait for new events when calling EndDrawing() */
417 461
                         EnableEventWaiting();
418 462
                 } else {
... ...
@@ -750,6 +794,7 @@ im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int
750 794
                 return(NULL); /* sanity check failed */
751 795
         if((body=calloc(1,sizeof(body_t)))==NULL
752 796
           || (body->rootdir=strdup(rootdir))==NULL
797
+          || (body->bg=bg_init(SIZEBGLOAD))==NULL
753 798
         ) {
754 799
                 im_body_free(body),body=NULL;
755 800
                 return(NULL);
... ...
@@ -792,6 +837,8 @@ im_body_free(body_t *body)
792 837
         if(body->rootdir!=NULL)
793 838
                 free(body->rootdir),body->rootdir=NULL;
794 839
         /* NOTE: Cannot call UnloadFont(body->roundedbox) as the data was not malloc'd; see https://github.com/raysan5/raylib/blob/master/examples/others/embedded_files_loading.c */
840
+        if(body->bg!=NULL)
841
+                bg_free(body->bg),body->bg=NULL;
795 842
         free(body),body=NULL;
796 843
         return;
797 844
 }
... ...
@@ -958,7 +1005,7 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
958 1005
                 maxw=windowwidth;
959 1006
                 maxh=windowheight-body->xywh.y;
960 1007
                 if(body->bigtexture.has_texture==0 || strcmp(body->bigtexture.currentpath,body->texture.currentpath)!=0)
961
-                        texture_load(&(body->bigtexture),body->texture.currentpath,maxw,maxh);
1008
+                        texture_load(&(body->bigtexture),body->texture.currentpath,maxw,maxh,body->bg);
962 1009
                 if(body->bigtexture.has_texture && strcmp(body->bigtexture.currentpath,body->texture.currentpath)==0) {
963 1010
                         int x0,y0;
964 1011
                         x0=0;
... ...
@@ -988,6 +1035,8 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
988 1035
         DrawRectangle(body->xywh.x,body->xywh.y,body->leftsize, body->xywh.h, (Color){ 215, 215, 215, 255 } );
989 1036
         /* draw right side background */
990 1037
         DrawRectangle(body->xywh.x+body->leftsize,body->xywh.y,body->xywh.w-body->leftsize, body->xywh.h, (Color){ 227, 227, 227, 255 } );
1038
+        /* reset lazy load marks */
1039
+        bg_resetmarks(body->bg);
991 1040
         /* first pass, draw leftside, second pass, draw all of rightside */
992 1041
         statustooltip[0]='\0';
993 1042
         for(is_leftside=1,flag_skiprightside=flag_skipall=0;is_leftside>=0 && flag_skiprightside==0 && flag_skipall==0;is_leftside--) {
... ...
@@ -1094,40 +1143,45 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
1094 1143
                                 /* show image */
1095 1144
                                 has_imagedrawn=0;
1096 1145
                                 if(is_imagefilename(elem->name+1)) {
1097
-                                        if(thumb->has_texture==0 && thumb->has_failedload==0 && imutil_fpsleft()==0) {
1098
-                                                *needs_nextredraw=1;
1099
-                                        } else if(thumb->has_texture==0 && thumb->has_failedload==0) {
1100
-                                                Image im;
1146
+                                        if(thumb->has_texture==0 && thumb->has_failedload==0) {
1147
+                                                bgload_t *bgload;
1101 1148
                                                 char fullpath[2048];
1149
+                                                *needs_nextredraw=1;
1102 1150
                                                 snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
1103 1151
                                                 fullpath[sizeof(fullpath)-1]='\0';
1104
-                                                im=imutil_loadimage(fullpath);
1105
-                                                if(IsImageValid(im)) {
1106
-                                                        int neww,newh;
1107
-                                                        Image im2,impixel;
1152
+                                                bgload=bg_get(body->bg,fullpath);
1153
+                                                if(bgload!=NULL && bgload->has_data!=0) {
1154
+                                                        Image im;
1155
+                                                        im=ImageCopy(bgload->image);
1156
+                                                        if(IsImageValid(im)) {
1157
+                                                                int neww,newh;
1158
+                                                                Image im2,impixel;
1108 1159
 #if 1
1109 1160
 fprintf(stderr,"Loaded %s\n",fullpath);
1110 1161
 {
1111 1162
 int oldw=im.width,oldh=im.height;
1112 1163
 #endif
1113
-                                                        im2=GenImageColor(sidelen,sidelen,(Color){0,0,0,255});
1114
-                                                        imutil_aspectmaximize(im.width,im.height,sidelen,sidelen,&neww,&newh);
1115
-                                                        ImageResize(&im,neww,newh);
1116
-                                                        impixel=ImageCopy(im);
1117
-                                                        ImageResize(&impixel,1,1);
1164
+                                                                im2=GenImageColor(sidelen,sidelen,(Color){0,0,0,255});
1165
+                                                                imutil_aspectmaximize(im.width,im.height,sidelen,sidelen,&neww,&newh);
1166
+                                                                ImageResize(&im,neww,newh);
1167
+                                                                impixel=ImageCopy(im);
1168
+                                                                ImageResize(&impixel,1,1);
1118 1169
 #if 1
1119 1170
 if(neww>sidelen || newh>sidelen)
1120 1171
 fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidelen,oldw,oldh,neww,newh);
1121 1172
 }
1122 1173
 #endif
1123
-                                                        ImageDraw(&im2,impixel,(Rectangle) {0,0,1,1},(Rectangle) {0,0,sidelen,sidelen},(Color){255,255,255,255});
1124
-                                                        ImageDraw(&im2,im,(Rectangle) {0,0,neww,newh},(Rectangle) {(sidelen-neww)/2,(sidelen-newh)/2,neww,newh},(Color){255,255,255,255});
1125
-                                                        *te=LoadTextureFromImage(im2);
1126
-                                                        UnloadImage(im);
1127
-                                                        UnloadImage(im2);
1128
-                                                        thumb->has_texture=1;
1129
-                                                } else {
1130
-                                                        thumb->has_failedload=1;
1174
+                                                                ImageDraw(&im2,impixel,(Rectangle) {0,0,1,1},(Rectangle) {0,0,sidelen,sidelen},(Color){255,255,255,255});
1175
+                                                                ImageDraw(&im2,im,(Rectangle) {0,0,neww,newh},(Rectangle) {(sidelen-neww)/2,(sidelen-newh)/2,neww,newh},(Color){255,255,255,255});
1176
+                                                                *te=LoadTextureFromImage(im2);
1177
+                                                                UnloadImage(im);
1178
+                                                                UnloadImage(im2);
1179
+                                                                thumb->has_texture=1;
1180
+                                                        } else {
1181
+                                                                thumb->has_failedload=1;
1182
+                                                        }
1183
+                                                } else if(bgload==NULL) {
1184
+                                                        bg_add(body->bg,fullpath);
1131 1185
                                                 }
1132 1186
                                         }
1133 1187
                                         if(thumb->has_texture!=0) {
... ...
@@ -1146,7 +1200,7 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1146 1200
                                                         if((body->texture.has_texture==0 && !(body->texture.has_failedload && strcmp(body->texture.currentpath,fullpath)==0))
1147 1201
                                                           || strcmp(body->texture.currentpath,fullpath)!=0
1148 1202
                                                         ) {
1149
-                                                                texture_load(&(body->texture),fullpath,maxw,maxh);
1203
+                                                                texture_load(&(body->texture),fullpath,maxw,maxh,body->bg);
1150 1204
                                                         }
1151 1205
                                                         if(body->texture.has_texture && strcmp(body->texture.currentpath,fullpath)==0) {
1152 1206
                                                                 int x0,y0;
... ...
@@ -1237,14 +1291,17 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1237 1291
                 DrawRectangle(0,windowheight-1-margin*2-font->height,m2.x+margin*2,font->height+margin*2,((Color){0,0,0,96}));
1238 1292
                 DrawTextEx(font->font,statustooltip,(Vector2){margin,windowheight-1-margin-font->height},font->height,0,(Color){ 255,255,255,128 });
1239 1293
         }
1294
+        /* free not used bg load items */
1295
+        bg_freeunmarked(body->bg);
1240 1296
         return(0);
1241 1297
 }
1242 1298
 
1243 1299
 int
1244
-texture_load(texture_t *texture, char *fullpath, int maxw, int maxh)
1300
+texture_load(texture_t *texture, char *fullpath, int maxw, int maxh, bg_t *bg)
1245 1301
 { 
1246 1302
         Image im;
1247 1303
         int neww,newh;
1304
+        bgload_t *bgload;
1248 1305
         if(texture==NULL || fullpath==NULL)
1249 1306
                 return(-1); /* sanity check failed */
1250 1307
         if(texture->has_texture) {
... ...
@@ -1254,7 +1311,11 @@ texture_load(texture_t *texture, char *fullpath, int maxw, int maxh)
1254 1311
                 texture->has_failedload=0;
1255 1312
         }
1256 1313
         texture->currentpath[0]='\0';
1257
-        im=imutil_loadimage(fullpath);
1314
+        if(bg!=NULL && (bgload=bg_get(bg,texture->currentpath))!=NULL && bgload->has_data!=0) {
1315
+                im=ImageCopy(bgload->image);
1316
+        } else {
1317
+                im=imutil_loadimage(fullpath);
1318
+        }
1258 1319
         if(IsImageValid(im)) {
1259 1320
                 imutil_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
1260 1321
                 ImageResize(&im,neww,newh);
... ...
@@ -1782,3 +1843,176 @@ imutil_milliseconds(void)
1782 1843
         return(res);
1783 1844
 }
1784 1845
 
1846
+bg_t *
1847
+bg_init(int sizebgload)
1848
+{
1849
+        bg_t *bg;
1850
+        bg=NULL;
1851
+        if((bg=calloc(1,sizeof(bg_t)))==NULL
1852
+          || (bg->pipe[0]=bg->pipe[1]=-1)!=-1
1853
+          || pipe(bg->pipe)!=0
1854
+          || (bg->bgload=calloc(sizebgload,sizeof(bgload_t)))==NULL
1855
+          || (bg->sizebgload=sizebgload)!=sizebgload
1856
+          || pthread_attr_init(&(bg->tattr))!=0
1857
+          || pthread_create(&(bg->thread),&(bg->tattr),bg_thread,(void *)bg)!=0
1858
+          || (bg->flag_threadstarted=1)!=1
1859
+        ) {
1860
+                bg_free(bg);
1861
+                return(NULL);
1862
+        }
1863
+        return(bg);
1864
+}
1865
+
1866
+
1867
+void
1868
+bg_free(bg_t *bg)
1869
+{
1870
+        int i;
1871
+        if(bg==NULL)
1872
+                return; /* nothing to do */
1873
+        if(bg->flag_threadstarted) {
1874
+                char dummy=1;
1875
+                write(bg->pipe[WR],&dummy,1);
1876
+                pthread_join(bg->thread,NULL);
1877
+                bg->flag_threadstarted=0;
1878
+        }
1879
+        if(bg->pipe[0]!=-1)
1880
+                close(bg->pipe[0]),bg->pipe[0]=-1;
1881
+        if(bg->pipe[1]!=-1)
1882
+                close(bg->pipe[1]),bg->pipe[1]=-1;
1883
+        if(bg->bgload!=NULL) {
1884
+                bgload_t *bgload;
1885
+                for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
1886
+                        if(bgload->has_data) {
1887
+                                UnloadImage(bgload->image);
1888
+                                bgload->has_data=0;
1889
+                        }
1890
+                }
1891
+                free(bg->bgload),bg->bgload=NULL,bg->sizebgload=0;
1892
+        }
1893
+        return;
1894
+}
1895
+
1896
+int
1897
+bg_resetmarks(bg_t *bg)
1898
+{
1899
+        int i;
1900
+        bgload_t *bgload;
1901
+        if(bg==NULL)
1902
+                return(-1);
1903
+        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++)
1904
+                bgload->has_mark=0;
1905
+        return(0);
1906
+}
1907
+
1908
+bgload_t *
1909
+bg_get(bg_t *bg, char *path)
1910
+{
1911
+        int i;
1912
+        bgload_t *bgload;
1913
+        if(bg==NULL)
1914
+                return(NULL);
1915
+        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
1916
+                if(bgload->thread_finished && bgload->has_data && strcmp(path,bgload->path)==0) {
1917
+                        bgload->has_mark=1;
1918
+#if 1
1919
+fprintf(stderr,"bg_get: \"%s\"\n",bgload->path);
1920
+#endif
1921
+                        return(bgload);
1922
+                }
1923
+        }
1924
+        return(NULL);
1925
+}
1926
+
1927
+int
1928
+bg_add(bg_t *bg, char *path)
1929
+{
1930
+        int i;
1931
+        bgload_t *bgload;
1932
+        int dummy;
1933
+        if(bg==NULL)
1934
+                return(-1);
1935
+        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
1936
+                if(bgload->lended_to_thread && strcmp(path,bgload->path)==0) {
1937
+                        bgload->is_todo=1;
1938
+                        bgload->has_mark=1;
1939
+                        dummy=0;
1940
+                        write(bg->pipe[WR],&dummy,1);
1941
+                        return(0); /* already on list */
1942
+                }
1943
+        }
1944
+        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
1945
+                if(bgload->lended_to_thread==0) {
1946
+                        memset(bgload,0,sizeof(bgload_t));
1947
+                        strncpy(bgload->path,path,sizeof(bgload->path));
1948
+                        bgload->path[sizeof(bgload->path)-1]='\0';
1949
+                        bgload->is_todo=1;
1950
+                        bgload->has_mark=1;
1951
+                        dummy=0;
1952
+                        bgload->lended_to_thread=1;
1953
+                        write(bg->pipe[WR],&dummy,1);
1954
+                        return(0); /* added to list */
1955
+                }
1956
+        }
1957
+        return(-1); /* couldn't add */
1958
+}
1959
+
1960
+int
1961
+bg_freeunmarked(bg_t *bg)
1962
+{
1963
+        int i;
1964
+        bgload_t *bgload;
1965
+        if(bg==NULL)
1966
+                return(-1);
1967
+        for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
1968
+                if(bgload->lended_to_thread && bgload->thread_finished && bgload->has_mark==0) {
1969
+                        if(bgload->has_data) {
1970
+#if 1
1971
+fprintf(stderr,"bg: Unloading: \"%s\"\n",bgload->path);
1972
+#endif
1973
+                                UnloadImage(bgload->image);
1974
+                                bgload->has_data=0;
1975
+                        }
1976
+#if 1
1977
+else {
1978
+fprintf(stderr,"bg: Cancelling: \"%s\"\n",bgload->path);
1979
+}
1980
+#endif
1981
+                        memset(bgload,0,sizeof(bgload_t));
1982
+                }
1983
+        }
1984
+        return(0);
1985
+}
1986
+
1987
+void *
1988
+bg_thread(void *parambg)
1989
+{
1990
+        bg_t *bg;
1991
+        char dummy;
1992
+        bg=(bg_t *)parambg;
1993
+        int i;
1994
+        bgload_t *bgload;
1995
+        while(1) {
1996
+                read(bg->pipe[RD],&dummy,1);
1997
+                if(dummy!=0)
1998
+                        break; /* was told to exit */
1999
+                for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
2000
+                        if(bgload->lended_to_thread==0)
2001
+                                continue;
2002
+                        if(bgload->is_todo==0) {
2003
+                                bgload->thread_finished=1;
2004
+                                continue;
2005
+                        }
2006
+                        if(bgload->has_data==0 && bgload->has_failedload==0) {
2007
+                                bgload->image=imutil_loadimage(bgload->path);
2008
+                                if(IsImageValid(bgload->image))
2009
+                                        bgload->has_data=1;
2010
+                                else
2011
+                                        bgload->has_failedload=1;
2012
+                                bgload->thread_finished=1;
2013
+                        }
2014
+                }
2015
+        }
2016
+        pthread_exit(NULL);
2017
+}
2018
+
Browse code

Dirdata colors. Select dirdata

Dario Rodriguez authored on 20/03/2025 18:20:45
Showing 1 changed files
... ...
@@ -29,6 +29,7 @@
29 29
  *               Scroll by finger. Big image on double click.
30 30
  *      20250319 Add-dirdata button.
31 31
  *      20250320 Fix add-dirdata button appearance.
32
+ *               Dirdata colors. Select dirdata.
32 33
  *
33 34
  * Author: Dario Rodriguez dario@darionomono.com
34 35
  * (c) Dario Rodriguez 2025
... ...
@@ -192,6 +193,7 @@ typedef struct dirdata_t {
192 193
         int height;
193 194
         char *dirname;
194 195
         listing_t listing;
196
+        int leftscrollpos;
195 197
 } dirdata_t;
196 198
 
197 199
 typedef struct texture_t {
... ...
@@ -212,7 +214,6 @@ typedef struct body_t {
212 214
         int sizedirdata;
213 215
         dirdata_t **dirdata;
214 216
         int currentdirdata;
215
-        int leftscrollpos;
216 217
         int rightscrollpos;
217 218
         font_t *ptrfont;
218 219
         font_t *ptrfontbig;
... ...
@@ -323,7 +324,7 @@ main(int argc, char *argv[])
323 324
                 if(lmbdown==1 && oldlmbdown==0 && scrollstart==0 && mousepos.y>im->body->xywh.y) {
324 325
                         scrollstart=imutil_milliseconds();
325 326
                         scrollstartpos=mousepos;
326
-                        leftscrollposstart=im->body->leftscrollpos;
327
+                        leftscrollposstart=im->body->dirdata[im->body->currentdirdata]->leftscrollpos;
327 328
                 }
328 329
                 if(scrollstart!=0 && lmbdown==0) {
329 330
                         scrollstart=0;
... ...
@@ -351,12 +352,12 @@ main(int argc, char *argv[])
351 352
                         tdif=tcur-scrolllast;
352 353
                         ycur=scrollstartpos.y-mousepos.y;
353 354
                         scrollspeed=(tdif>0)?(oldmousepos.y-mousepos.y)*100000/tdif:0;
354
-                        im->body->leftscrollpos=leftscrollposstart+ycur;
355
+                        im->body->dirdata[im->body->currentdirdata]->leftscrollpos=leftscrollposstart+ycur;
355 356
                         scrolllast=tcur;
356 357
                 }
357 358
                 if(is_scrolling==0 && scrollspeed!=0) {
358 359
                         scrollspeed=scrollspeed*4/5;
359
-                        im->body->leftscrollpos+=scrollspeed;
360
+                        im->body->dirdata[im->body->currentdirdata]->leftscrollpos+=scrollspeed;
360 361
                 }
361 362
                 /* process clicks on menus */
362 363
                 if(click_avail) {
... ...
@@ -840,10 +841,10 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
840 841
                 return(-1); /* sanity check error */
841 842
         dirdata=body->dirdata[body->currentdirdata];
842 843
         /* wheel */
843
-        body->leftscrollpos-=(int)wheel.y*WHEELSTEP;
844
-        body->leftscrollpos=(body->leftscrollpos<0)?0:body->leftscrollpos;
845
-        if(body->leftscrollpos>dirdata->listing.lastleftxywh.y)
846
-                body->leftscrollpos=dirdata->listing.lastleftxywh.y;
844
+        body->dirdata[body->currentdirdata]->leftscrollpos-=(int)wheel.y*WHEELSTEP;
845
+        body->dirdata[body->currentdirdata]->leftscrollpos=(body->dirdata[body->currentdirdata]->leftscrollpos<0)?0:body->dirdata[body->currentdirdata]->leftscrollpos;
846
+        if(body->dirdata[body->currentdirdata]->leftscrollpos>dirdata->listing.lastleftxywh.y)
847
+                body->dirdata[body->currentdirdata]->leftscrollpos=dirdata->listing.lastleftxywh.y;
847 848
         /* check if we have to process a click */
848 849
         if(*click_avail==0 || lmbreleased==0)
849 850
                 return(0); /* nothing else to do */
... ...
@@ -869,7 +870,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
869 870
                         dirdata->dirname[0]='\0';
870 871
                 }
871 872
                 listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
872
-                body->leftscrollpos=0;
873
+                body->dirdata[body->currentdirdata]->leftscrollpos=0;
873 874
                 *click_avail=0;
874 875
                 return(0);
875 876
         }
... ...
@@ -897,13 +898,25 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
897 898
                         free(dirdata->dirname),dirdata->dirname=NULL;
898 899
                         dirdata->dirname=newname;
899 900
                         listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
900
-                        body->leftscrollpos=0;
901
+                        body->dirdata[body->currentdirdata]->leftscrollpos=0;
901 902
                         *click_avail=0;
902 903
                         return(0);
903 904
                 }
904 905
         }
905 906
         /* dirdata select */
906
-#warning TODO
907
+        if(mousepos.x>body->leftsize && mousepos.y>body->xywh.y) {
908
+                int righty;
909
+                for(righty=body->xywh.y,i=0;i<body->sizedirdata;i++) {
910
+                        if(body->dirdata[i]==NULL)
911
+                                continue;
912
+                        if(mousepos.y>=righty && mousepos.y<(righty+body->dirdata[i]->height) && i!=body->currentdirdata) {
913
+                                body->currentdirdata=i;
914
+                                *click_avail=0;
915
+                                return(0);
916
+                        }
917
+                        righty+=body->dirdata[i]->height;
918
+                }
919
+        }
907 920
         /* detect click on "add dirdata" button */
908 921
         if(is_imutil_insidexywh(mousepos,&(body->dirdataadd),0)) {
909 922
                 im_body_add(body,body->dirdata[body->currentdirdata]->dirname);
... ...
@@ -989,7 +1002,7 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
989 1002
                         if(is_leftside && !(dirdata->dirname[0]=='\0' || strcmp(dirdata->dirname,SEP)==0)) {
990 1003
                                 m2=MeasureTextEx(fontbig->font,UTF8DOWNARROW,fontbig->height,0);
991 1004
                                 v2.x=(float) (body->xywh.x+fontbig->height/2);
992
-                                v2.y=(float) (body->xywh.y+fontbig->height/4+(fontbig->height-v2.x)/2)-body->leftscrollpos;
1005
+                                v2.y=(float) (body->xywh.y+fontbig->height/4+(fontbig->height-v2.x)/2)-body->dirdata[body->currentdirdata]->leftscrollpos;
993 1006
                                 FILLXYWH(body->backxywh,v2.x-fontbig->height/4,v2.y-fontbig->height/8,m2.x+fontbig->height/4,m2.x+fontbig->height/4);
994 1007
 #if 0
995 1008
 DrawTexture(fontbig->font.texture, 0, 0, WHITE); /* font glyphs -- see https://github.com/raysan5/raylib/issues/2022 */
... ...
@@ -1000,7 +1013,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
1000 1013
                         }
1001 1014
                         if(is_leftside) {
1002 1015
                                 /* ...dirname */
1003
-                                v2.y=(float) (body->xywh.y+fontbig->height/4-body->leftscrollpos);
1016
+                                v2.y=(float) (body->xywh.y+fontbig->height/4-body->dirdata[body->currentdirdata]->leftscrollpos);
1004 1017
                                 if((v2.y+fontbig->height)>=0) {
1005 1018
                                         m2=MeasureTextEx(fontbig->font,dirdata->dirname,fontbig->height,0);
1006 1019
                                         v2.x=(float) (body->xywh.x+fontbig->height/2)+(body->leftsize-(body->xywh.x+fontbig->height)-m2.x)/2;
... ...
@@ -1023,12 +1036,12 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
1023 1036
                                   ,(Vector2) {body->xywh.x+body->leftsize+fontbig->height/2,righty+fontbig->height/4}
1024 1037
                                   ,fontbig->height
1025 1038
                                   ,0
1026
-                                  ,(Color){ 240, 240, 240, 255 }
1039
+                                  ,(i==body->currentdirdata)?((Color){ 240, 240, 240, 255 }):((Color){ 65, 65, 65, 255 })
1027 1040
                                 );
1028 1041
                         }
1029 1042
                         /* directories */
1030 1043
                         xoff=((is_leftside)?0:body->leftsize);
1031
-                        yoff=((is_leftside)?body->xywh.y:righty)+fontbig->height/4+fontbig->height+font->height/4-(is_leftside?body->leftscrollpos:0);
1044
+                        yoff=((is_leftside)?body->xywh.y:righty)+fontbig->height/4+fontbig->height+font->height/4-(is_leftside?body->dirdata[body->currentdirdata]->leftscrollpos:0);
1032 1045
                         if(is_leftside && dirdata->dirname[0]=='\0')
1033 1046
                                 yoff-=fontbig->height/4+fontbig->height;
1034 1047
                         for(k=0,lastx=lasty=0;k<dirdata->listing.usedelems;k++) {
Browse code

Fix add-dirdata button appearance

Dario Rodriguez authored on 20/03/2025 17:50:35
Showing 1 changed files
... ...
@@ -28,6 +28,7 @@
28 28
  *               Delay loading images if over fps deadline.
29 29
  *               Scroll by finger. Big image on double click.
30 30
  *      20250319 Add-dirdata button.
31
+ *      20250320 Fix add-dirdata button appearance.
31 32
  *
32 33
  * Author: Dario Rodriguez dario@darionomono.com
33 34
  * (c) Dario Rodriguez 2025
... ...
@@ -77,7 +78,7 @@
77 78
 #define FONTSIZE 18
78 79
 #define FONTBIGSIZE 32
79 80
 #define FONTHUGESIZE 48
80
-#define ADDREMOVEDIRDATAHEIGHT 64
81
+#define ADDREMOVEDIRDATAHEIGHT 128
81 82
 #endif
82 83
 
83 84
 #define SCROLLTHRESHOLD (LEFTIMAGESIDELEN/3)
... ...
@@ -1204,6 +1205,8 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1204 1205
                   ,0.0
1205 1206
                   ,(Color){ 168, 168, 168, 255 }
1206 1207
                 );
1208
+                DrawRectangle(body->dirdataadd.x+13+12,body->dirdataadd.y+13,body->dirdataadd.w-26-24, (float)body->dirdataadd.h-26,(Color){ 168, 168, 168, 255 });
1209
+                DrawRectangle(body->dirdataadd.x+13,body->dirdataadd.y+13+12,body->dirdataadd.w-26, (float)body->dirdataadd.h-26-24,(Color){ 168, 168, 168, 255 });
1207 1210
                 xoff+=gi.image.width+4;
1208 1211
                 gi=GetGlyphInfo(body->roundedbox,'+');
1209 1212
                 DrawTexturePro(body->roundedbox.texture
... ...
@@ -1211,7 +1214,7 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1211 1214
                   ,(Rectangle) { (float) body->dirdataadd.x+30-2, (float) body->dirdataadd.y+30, (float) body->dirdataadd.w-60, (float)body->dirdataadd.h-60}
1212 1215
                   ,(Vector2){0.0,0.0}
1213 1216
                   ,0.0
1214
-                  ,(Color){ 168, 168, 168, 255 }
1217
+                  ,(Color){ 227, 227, 227, 255 }
1215 1218
                 );
1216 1219
         } else {
1217 1220
                 memset(&(body->dirdataadd),0,sizeof(body->dirdataadd));
Browse code

Add-dirdata button

Dario Rodriguez authored on 19/03/2025 22:23:01
Showing 1 changed files
... ...
@@ -27,6 +27,7 @@
27 27
  *      20250316 Add android target support.
28 28
  *               Delay loading images if over fps deadline.
29 29
  *               Scroll by finger. Big image on double click.
30
+ *      20250319 Add-dirdata button.
30 31
  *
31 32
  * Author: Dario Rodriguez dario@darionomono.com
32 33
  * (c) Dario Rodriguez 2025
... ...
@@ -58,12 +59,13 @@
58 59
 #define DEFAULTWIDTH 2400
59 60
 #define DEFAULTHEIGHT 1080
60 61
 #define LEFTSIZE 1600
61
-#define DEFAULTDIRDATAHEIGHT 520
62
+#define DEFAULTDIRDATAHEIGHT 492
62 63
 #define DEFAULTDIRDATATRIANGLEW 100
63 64
 #define LEFTIMAGESIDELEN 326
64 65
 #define FONTSIZE 64
65 66
 #define FONTBIGSIZE 96
66 67
 #define FONTHUGESIZE 128
68
+#define ADDREMOVEDIRDATAHEIGHT 128
67 69
 #else
68 70
 #define ROOTDIR "/var/www/default/animeshot/"
69 71
 #define DEFAULTWIDTH 1280
... ...
@@ -75,6 +77,7 @@
75 77
 #define FONTSIZE 18
76 78
 #define FONTBIGSIZE 32
77 79
 #define FONTHUGESIZE 48
80
+#define ADDREMOVEDIRDATAHEIGHT 64
78 81
 #endif
79 82
 
80 83
 #define SCROLLTHRESHOLD (LEFTIMAGESIDELEN/3)
... ...
@@ -217,6 +220,8 @@ typedef struct body_t {
217 220
         int is_displayingtexture;
218 221
         texture_t bigtexture;
219 222
         int flag_drawbigtexture;
223
+        xywh_t dirdataadd;
224
+        Font roundedbox;
220 225
 } body_t;
221 226
 
222 227
 typedef struct im_t {
... ...
@@ -754,6 +759,11 @@ im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int
754 759
         body->ptrfonthuge=fonthuge;
755 760
         if(body->rootdir[0]!='\0' && strcmp(body->rootdir,SEP)!=0 && body->rootdir[strlen(body->rootdir)-1]==sep[0])
756 761
                 body->rootdir[strlen(body->rootdir)-1]='\0'; /* rootdir doesn't need the final '/' */
762
+        /* init rounded box glyph (a really big zero) */
763
+        {
764
+                int codepoints[]={'O','+','-'};
765
+                body->roundedbox=LoadFontFromMemory(".ttf",(const unsigned char *)roboto_regular,sizeof(roboto_regular)-1,ADDREMOVEDIRDATAHEIGHT*4,codepoints,sizeof(codepoints)/sizeof(codepoints[0]));
766
+        }
757 767
         return(body);
758 768
 }
759 769
 
... ...
@@ -779,6 +789,7 @@ im_body_free(body_t *body)
779 789
         texture_freedata(&(body->bigtexture));
780 790
         if(body->rootdir!=NULL)
781 791
                 free(body->rootdir),body->rootdir=NULL;
792
+        /* NOTE: Cannot call UnloadFont(body->roundedbox) as the data was not malloc'd; see https://github.com/raysan5/raylib/blob/master/examples/others/embedded_files_loading.c */
782 793
         free(body),body=NULL;
783 794
         return;
784 795
 }
... ...
@@ -890,6 +901,15 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
890 901
                         return(0);
891 902
                 }
892 903
         }
904
+        /* dirdata select */
905
+#warning TODO
906
+        /* detect click on "add dirdata" button */
907
+        if(is_imutil_insidexywh(mousepos,&(body->dirdataadd),0)) {
908
+                im_body_add(body,body->dirdata[body->currentdirdata]->dirname);
909
+                *click_avail=0;
910
+                return(0);
911
+        }
912
+        /* dirdata remove */
893 913
 #warning TODO
894 914
         return(0);
895 915
 }
... ...
@@ -1169,6 +1189,33 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1169 1189
                         }
1170 1190
                 }
1171 1191
         }
1192
+        if(flag_skiprightside==0 && (righty+DEFAULTDIRDATAHEIGHT)<=(body->xywh.y+body->xywh.h)) {
1193
+                GlyphInfo gi;
1194
+                int xoff;
1195
+                int margin;
1196
+                margin=20;
1197
+                FILLXYWH(body->dirdataadd,(body->xywh.x+body->xywh.w-ADDREMOVEDIRDATAHEIGHT-margin),righty+margin,ADDREMOVEDIRDATAHEIGHT,ADDREMOVEDIRDATAHEIGHT);
1198
+                gi=GetGlyphInfo(body->roundedbox,'O');
1199
+                xoff=0;
1200
+                DrawTexturePro(body->roundedbox.texture
1201
+                  ,(Rectangle){0.0+xoff,0.0,(float)gi.image.width+5,(float)gi.image.height+2}
1202
+                  ,(Rectangle) { (float) body->dirdataadd.x, (float) body->dirdataadd.y, (float) body->dirdataadd.w, (float)body->dirdataadd.h}
1203
+                  ,(Vector2){0.0,0.0}
1204
+                  ,0.0
1205
+                  ,(Color){ 168, 168, 168, 255 }
1206
+                );
1207
+                xoff+=gi.image.width+4;
1208
+                gi=GetGlyphInfo(body->roundedbox,'+');
1209
+                DrawTexturePro(body->roundedbox.texture
1210
+                  ,(Rectangle){xoff,0.0,(float)gi.image.width,(float)gi.image.height}
1211
+                  ,(Rectangle) { (float) body->dirdataadd.x+30-2, (float) body->dirdataadd.y+30, (float) body->dirdataadd.w-60, (float)body->dirdataadd.h-60}
1212
+                  ,(Vector2){0.0,0.0}
1213
+                  ,0.0
1214
+                  ,(Color){ 168, 168, 168, 255 }
1215
+                );
1216
+        } else {
1217
+                memset(&(body->dirdataadd),0,sizeof(body->dirdataadd));
1218
+        }
1172 1219
         if(statustooltip[0]!='\0') {
1173 1220
                 m2=MeasureTextEx(font->font,statustooltip,font->height,0);
1174 1221
                 DrawRectangle(0,windowheight-1-margin*2-font->height,m2.x+margin*2,font->height+margin*2,((Color){0,0,0,96}));
Browse code

Scroll by finger. Big image on double click

Dario Rodriguez authored on 16/03/2025 16:22:19
Showing 1 changed files
... ...
@@ -26,6 +26,7 @@
26 26
  *               Add show using all window with right button.
27 27
  *      20250316 Add android target support.
28 28
  *               Delay loading images if over fps deadline.
29
+ *               Scroll by finger. Big image on double click.
29 30
  *
30 31
  * Author: Dario Rodriguez dario@darionomono.com
31 32
  * (c) Dario Rodriguez 2025
... ...
@@ -46,7 +47,9 @@
46 47
 
47 48
 #define UTF8DOWNARROW "\xe2\x86\x86" /* U+2186 in UTF-8 */
48 49
 
50
+#ifndef ANDROID
49 51
 #define SIMANDROID
52
+#endif
50 53
 
51 54
 #define TARGETFPS 30
52 55
 
... ...
@@ -74,6 +77,8 @@
74 77
 #define FONTHUGESIZE 48
75 78
 #endif
76 79
 
80
+#define SCROLLTHRESHOLD (LEFTIMAGESIDELEN/3)
81
+
77 82
 #if defined(SIMANDROID)
78 83
 #undef ROOTDIR
79 84
 #define ROOTDIR "/var/www/default/animeshot/"
... ...
@@ -192,6 +197,7 @@ typedef struct texture_t {
192 197
         int textureh;
193 198
         int has_texture;
194 199
         int has_failedload;
200
+        xywh_t source; /* be able to detect a "double click" */
195 201
 } texture_t;
196 202
 
197 203
 typedef struct body_t {
... ...
@@ -208,7 +214,9 @@ typedef struct body_t {
208 214
         font_t *ptrfontbig;
209 215
         font_t *ptrfonthuge;
210 216
         texture_t texture;
217
+        int is_displayingtexture;
211 218
         texture_t bigtexture;
219
+        int flag_drawbigtexture;
212 220
 } body_t;
213 221
 
214 222
 typedef struct im_t {
... ...
@@ -264,17 +272,23 @@ int is_imagefilename(char *filename);
264 272
 Image imutil_loadimage(const char *filename);
265 273
 void imutil_fpsreset(void);
266 274
 int imutil_fpsleft(void);
275
+long long imutil_milliseconds(void);
267 276
 
268 277
 int
269 278
 main(int argc, char *argv[])
270 279
 {
271 280
         im_t *im;
272
-        Vector2 mousepos,wheel,oldmousepos;
281
+        Vector2 mousepos,wheel,oldmousepos,scrollstartpos;
273 282
         int flag_ignorelmb;
274 283
         int lmbpressed,lmbreleased,lmbdown,rmbdown,oldlmbdown,oldrmbdown;
275 284
         int click_avail;
276 285
         int has_mousechanges;
277 286
         int needs_nextredraw;
287
+        long long scrollstart;
288
+        long long scrolllast;
289
+        int scrollspeed;
290
+        int is_scrolling;
291
+        int leftscrollposstart;
278 292
         char *sel_menu,*sel_submenu;
279 293
         if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n",ROOTDIR))==NULL) {
280 294
                 return(1);
... ...
@@ -283,6 +297,8 @@ main(int argc, char *argv[])
283 297
         mousepos=(Vector2) {.x=0,.y=0};
284 298
         lmbdown=rmbdown=-1;
285 299
         needs_nextredraw=1;
300
+        scrollstart=0;
301
+        is_scrolling=0;
286 302
         while(!WindowShouldClose()) {
287 303
                 imutil_fpsreset();
288 304
                 oldmousepos=mousepos;
... ...
@@ -296,21 +312,57 @@ main(int argc, char *argv[])
296 312
                 rmbdown=IsMouseButtonDown(1);
297 313
                 click_avail=1;
298 314
                 has_mousechanges=(lmbdown!=oldlmbdown || rmbdown!=oldrmbdown || mousepos.x!=oldmousepos.x || mousepos.y!=oldmousepos.y || wheel.x!=0 || wheel.y!=0)?1:0;
299
-                needs_nextredraw=(has_mousechanges==0 && needs_nextredraw==0)?0:1;
300
-                if(needs_nextredraw==0) {
301
-                        BeginDrawing();
302
-                        EndDrawing();
303
-                        continue;
304
-                }
305 315
                 needs_nextredraw=0;
316
+                /* process scrolling */
317
+                if(lmbdown==1 && oldlmbdown==0 && scrollstart==0 && mousepos.y>im->body->xywh.y) {
318
+                        scrollstart=imutil_milliseconds();
319
+                        scrollstartpos=mousepos;
320
+                        leftscrollposstart=im->body->leftscrollpos;
321
+                }
322
+                if(scrollstart!=0 && lmbdown==0) {
323
+                        scrollstart=0;
324
+                        if(is_scrolling)
325
+                                click_avail=0; /* this click is the mouseup of the scroll */
326
+                }
327
+                is_scrolling=(scrollstart==0)?0:is_scrolling;
328
+                if(is_scrolling==0 && scrollstart!=0) {
329
+                        float t;
330
+                        t=scrollstartpos.y-mousepos.y;
331
+                        t=(t<0)?-t:t;
332
+                        if(t>SCROLLTHRESHOLD) {
333
+                                is_scrolling=1;
334
+                                scrolllast=0;
335
+                        }
336
+                        t=scrollstartpos.x-mousepos.x;
337
+                        t=(t<0)?-t:t;
338
+                        if(t>SCROLLTHRESHOLD)
339
+                                is_scrolling=0,scrollstart=0;
340
+                }
341
+                if(is_scrolling) {
342
+                        long long tcur,tdif;
343
+                        long long ycur;
344
+                        tcur=imutil_milliseconds();
345
+                        tdif=tcur-scrolllast;
346
+                        ycur=scrollstartpos.y-mousepos.y;
347
+                        scrollspeed=(tdif>0)?(oldmousepos.y-mousepos.y)*100000/tdif:0;
348
+                        im->body->leftscrollpos=leftscrollposstart+ycur;
349
+                        scrolllast=tcur;
350
+                }
351
+                if(is_scrolling==0 && scrollspeed!=0) {
352
+                        scrollspeed=scrollspeed*4/5;
353
+                        im->body->leftscrollpos+=scrollspeed;
354
+                }
306 355
                 /* process clicks on menus */
307 356
                 if(click_avail) {
308 357
                         sel_menu=sel_submenu=NULL;
309 358
                         im_menubar_mouse(im->menubar, mousepos, lmbpressed, lmbreleased, lmbdown, &click_avail, &sel_menu, &sel_submenu);
310 359
                         if(sel_menu!=NULL && sel_submenu!=NULL) {
360
+
311 361
 #if 1
312 362
 fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
313 363
 #endif
364
+                                if(strcmp(sel_submenu,"Salir")==0)
365
+                                        break; /* exit from main loop */
314 366
                         }
315 367
                 }
316 368
                 if(click_avail)
... ...
@@ -353,6 +405,13 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
353 405
  }
354 406
 }
355 407
 #endif
408
+                if(has_mousechanges==0 && needs_nextredraw==0) {
409
+                        /* Wait for new events when calling EndDrawing() */
410
+                        EnableEventWaiting();
411
+                } else {
412
+                        /* EndDrawing() doesn't wait for new events, returns immediately */
413
+                        DisableEventWaiting();
414
+                }
356 415
                 EndDrawing();
357 416
         }
358 417
         im_free(im),im=NULL;
... ...
@@ -764,6 +823,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
764 823
         char *ptr;
765 824
         dirdata_t *dirdata;
766 825
         listingdata_t *ld;
826
+        int margin;
767 827
         if(body==NULL || click_avail==NULL || body->currentdirdata<0 || body->currentdirdata>=body->sizedirdata || body->dirdata[body->currentdirdata]==NULL)
768 828
                 return(-1); /* sanity check error */
769 829
         dirdata=body->dirdata[body->currentdirdata];
... ...
@@ -775,6 +835,17 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
775 835
         /* check if we have to process a click */
776 836
         if(*click_avail==0 || lmbreleased==0)
777 837
                 return(0); /* nothing else to do */
838
+        /* show image in full screen */
839
+        if(body->flag_drawbigtexture) {
840
+                if(lmbreleased)
841
+                        body->flag_drawbigtexture=0;
842
+                return(0); /* nothing else to do */
843
+        }
844
+        margin=body->ptrfont->height/4;
845
+        if(body->is_displayingtexture && lmbreleased && is_imutil_insidexywh(mousepos,&(body->texture.source),margin)) {
846
+                body->flag_drawbigtexture=1;
847
+                return(0); /* nothing else to do */
848
+        }
778 849
         /* leftside backbutton */
779 850
         if(is_imutil_insidexywh(mousepos,&(body->backxywh),0)) {
780 851
                 static char sep[]={SEP};
... ...
@@ -845,6 +916,25 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windo
845 916
         fonthuge=body->ptrfonthuge;
846 917
         FILLXYWH(body->backxywh,0,0,0,0);
847 918
         margin=font->height/4;
919
+        body->is_displayingtexture=0;
920
+        /* if we are displaying a full screenimage... */
921
+        if(body->flag_drawbigtexture && body->texture.has_texture) {
922
+                /* draw image in full screen */
923
+                int maxw,maxh;
924
+                maxw=windowwidth;
925
+                maxh=windowheight-body->xywh.y;
926
+                if(body->bigtexture.has_texture==0 || strcmp(body->bigtexture.currentpath,body->texture.currentpath)!=0)
927
+                        texture_load(&(body->bigtexture),body->texture.currentpath,maxw,maxh);
928
+                if(body->bigtexture.has_texture && strcmp(body->bigtexture.currentpath,body->texture.currentpath)==0) {
929
+                        int x0,y0;
930
+                        x0=0;
931
+                        y0=body->xywh.y;
932
+                        texture_draw(&(body->bigtexture),x0,y0,maxw,maxh);
933
+                        return(0); /* all done */
934
+                } else {
935
+                        body->flag_drawbigtexture=0; /* error loading big texture, draw screen normally */
936
+                }
937
+        }
848 938
         /* calculate positions */
849 939
         for(i=0;i<body->sizedirdata;i++) {
850 940
                 if(body->dirdata[i]==NULL)
... ...
@@ -1011,7 +1101,7 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1011 1101
                                                 DrawTexture(*te,thumb->screenxywh.x,thumb->screenxywh.y,WHITE);
1012 1102
                                                 has_imagedrawn=1;
1013 1103
                                                 lastx=xywh->x+xywh->w,lasty=xywh->y+xywh->h+yoff;
1014
-                                                if(is_leftside && lmbdown==0 && rmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
1104
+                                                if(is_leftside && rmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
1015 1105
                                                         /* draw image in rightside */
1016 1106
                                                         char fullpath[2048];
1017 1107
                                                         int maxw,maxh;
... ...
@@ -1029,31 +1119,11 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1029 1119
                                                                 x0=body->leftsize-DEFAULTDIRDATATRIANGLEW;
1030 1120
                                                                 y0=body->xywh.y;
1031 1121
                                                                 texture_draw(&(body->texture),x0,y0,maxw,maxh);
1122
+                                                                body->is_displayingtexture=1;
1123
+                                                                memcpy(&(body->texture.source),&(thumb->screenxywh),sizeof(body->texture.source));
1032 1124
                                                                 flag_skiprightside=1;
1033 1125
                                                         }
1034 1126
                                                 }
1035
-                                                if(is_leftside && lmbdown==0 && rmbdown!=0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
1036
-                                                        /* draw image in full screen */
1037
-                                                        char fullpath[2048];
1038
-                                                        int maxw,maxh;
1039
-                                                        maxw=windowwidth;
1040
-                                                        maxh=windowheight-body->xywh.y;
1041
-                                                        snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
1042
-                                                        fullpath[sizeof(fullpath)-1]='\0';
1043
-                                                        if((body->bigtexture.has_texture==0 && !(body->bigtexture.has_failedload && strcmp(body->bigtexture.currentpath,fullpath)==0))
1044
-                                                          || strcmp(body->bigtexture.currentpath,fullpath)!=0
1045
-                                                        ) {
1046
-                                                                texture_load(&(body->bigtexture),fullpath,maxw,maxh);
1047
-                                                        }
1048
-                                                        if(body->bigtexture.has_texture && strcmp(body->bigtexture.currentpath,fullpath)==0) {
1049
-                                                                int x0,y0;
1050
-                                                                x0=0;
1051
-                                                                y0=body->xywh.y;
1052
-                                                                texture_draw(&(body->bigtexture),x0,y0,maxw,maxh);
1053
-                                                                flag_skipall=1;
1054
-                                                                break;
1055
-                                                        }
1056
-                                                }
1057 1127
                                         }
1058 1128
                                 }
1059 1129
                                 if(has_imagedrawn==0) {
... ...
@@ -1639,3 +1709,13 @@ imutil_fpsleft(void)
1639 1709
         return(1);
1640 1710
 }
1641 1711
 
1712
+long long
1713
+imutil_milliseconds(void)
1714
+{
1715
+        long long res;
1716
+        struct timeval now;
1717
+        gettimeofday(&now,NULL);
1718
+        res=((long long) (now.tv_sec))*1000000L+((long long) (now.tv_usec));
1719
+        return(res);
1720
+}
1721
+
Browse code

Delay loading images if over fps deadline

Dario Rodriguez authored on 16/03/2025 12:04:54
Showing 1 changed files
... ...
@@ -25,6 +25,7 @@
25 25
  *      20250311 Fix bug because of stray CloseWindow() call.
26 26
  *               Add show using all window with right button.
27 27
  *      20250316 Add android target support.
28
+ *               Delay loading images if over fps deadline.
28 29
  *
29 30
  * Author: Dario Rodriguez dario@darionomono.com
30 31
  * (c) Dario Rodriguez 2025
... ...
@@ -38,6 +39,7 @@
38 39
 #include <sys/types.h>
39 40
 #include <dirent.h>
40 41
 #include <sys/stat.h>
42
+#include <sys/time.h>
41 43
 
42 44
 #include "raylib.h"
43 45
 #include "roboto_regular.c"
... ...
@@ -46,6 +48,8 @@
46 48
 
47 49
 #define SIMANDROID
48 50
 
51
+#define TARGETFPS 30
52
+
49 53
 #if defined(ANDROID) || defined(SIMANDROID)
50 54
 #define ROOTDIR "/sdcard/"
51 55
 #define DEFAULTWIDTH 2400
... ...
@@ -229,7 +233,7 @@ menubar_t *im_menubar_init(char *menus, font_t *font);
229 233
 void im_menubar_free(menubar_t *menubar);
230 234
 
231 235
 int im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail, char **sel_menu, char **sel_submenu);
232
-int im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight);
236
+int im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight, int *needs_nextredraw);
233 237
 
234 238
 body_t *im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir, int windowwidth, int windowheight);
235 239
 void im_body_free(body_t *body);
... ...
@@ -237,7 +241,7 @@ void im_body_free(body_t *body);
237 241
 int im_body_add(body_t *body,char *dir);
238 242
 
239 243
 int im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
240
-int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight);
244
+int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight, int *needs_nextredraw);
241 245
 
242 246
 int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort);
243 247
 void listing_freedata(listing_t *listing);
... ...
@@ -258,28 +262,47 @@ int menudata_pos2option(menudata_t *menudata, Vector2 pos);
258 262
 int *getcodepoints(int *sizecodepoints);
259 263
 int is_imagefilename(char *filename);
260 264
 Image imutil_loadimage(const char *filename);
265
+void imutil_fpsreset(void);
266
+int imutil_fpsleft(void);
261 267
 
262 268
 int
263 269
 main(int argc, char *argv[])
264 270
 {
265 271
         im_t *im;
266
-        Vector2 mousepos,wheel;
272
+        Vector2 mousepos,wheel,oldmousepos;
267 273
         int flag_ignorelmb;
268
-        int lmbpressed,lmbreleased,lmbdown,rmbdown;
274
+        int lmbpressed,lmbreleased,lmbdown,rmbdown,oldlmbdown,oldrmbdown;
269 275
         int click_avail;
276
+        int has_mousechanges;
277
+        int needs_nextredraw;
270 278
         char *sel_menu,*sel_submenu;
271 279
         if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n",ROOTDIR))==NULL) {
272 280
                 return(1);
273 281
         }
274 282
         flag_ignorelmb=0;
283
+        mousepos=(Vector2) {.x=0,.y=0};
284
+        lmbdown=rmbdown=-1;
285
+        needs_nextredraw=1;
275 286
         while(!WindowShouldClose()) {
287
+                imutil_fpsreset();
288
+                oldmousepos=mousepos;
276 289
                 mousepos=GetMousePosition();
277 290
                 wheel=GetMouseWheelMoveV();
278 291
                 lmbpressed=IsMouseButtonPressed(0);
279 292
                 lmbreleased=IsMouseButtonReleased(0);
293
+                oldlmbdown=lmbdown;
280 294
                 lmbdown=IsMouseButtonDown(0);
295
+                oldrmbdown=rmbdown;
281 296
                 rmbdown=IsMouseButtonDown(1);
282 297
                 click_avail=1;
298
+                has_mousechanges=(lmbdown!=oldlmbdown || rmbdown!=oldrmbdown || mousepos.x!=oldmousepos.x || mousepos.y!=oldmousepos.y || wheel.x!=0 || wheel.y!=0)?1:0;
299
+                needs_nextredraw=(has_mousechanges==0 && needs_nextredraw==0)?0:1;
300
+                if(needs_nextredraw==0) {
301
+                        BeginDrawing();
302
+                        EndDrawing();
303
+                        continue;
304
+                }
305
+                needs_nextredraw=0;
283 306
                 /* process clicks on menus */
284 307
                 if(click_avail) {
285 308
                         sel_menu=sel_submenu=NULL;
... ...
@@ -292,13 +315,11 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
292 315
                 }
293 316
                 if(click_avail)
294 317
                         im_body_mouse(im->body, mousepos, wheel, lmbpressed, lmbreleased, lmbdown, &click_avail);
295
-
296
-
297 318
                 /* draw screen contents */
298 319
                 BeginDrawing();
299 320
                 ClearBackground(RAYWHITE);
300
-                im_body_draw(im->body,mousepos,lmbdown,rmbdown,im->w,im->h);
301
-                im_menubar_draw(im->menubar,im->w,im->h);
321
+                im_body_draw(im->body,mousepos,lmbdown,rmbdown,im->w,im->h,&needs_nextredraw);
322
+                im_menubar_draw(im->menubar,im->w,im->h,&needs_nextredraw);
302 323
 #if 0
303 324
 {
304 325
  int i,j;
... ...
@@ -592,7 +613,7 @@ im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbre
592 613
 }
593 614
 
594 615
 int
595
-im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight)
616
+im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight, int *needs_nextredraw)
596 617
 {
597 618
         int i,j,k,x;
598 619
         menudata_t *menudata;
... ...
@@ -803,7 +824,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
803 824
 }
804 825
 
805 826
 int
806
-im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight)
827
+im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight, int *needs_nextredraw)
807 828
 {
808 829
         int i,k,margin,righty;
809 830
         int lastx,lasty;
... ...
@@ -949,7 +970,9 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
949 970
                                 /* show image */
950 971
                                 has_imagedrawn=0;
951 972
                                 if(is_imagefilename(elem->name+1)) {
952
-                                        if(thumb->has_texture==0 && thumb->has_failedload==0) {
973
+                                        if(thumb->has_texture==0 && thumb->has_failedload==0 && imutil_fpsleft()==0) {
974
+                                                *needs_nextredraw=1;
975
+                                        } else if(thumb->has_texture==0 && thumb->has_failedload==0) {
953 976
                                                 Image im;
954 977
                                                 char fullpath[2048];
955 978
                                                 snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
... ...
@@ -1584,3 +1607,35 @@ imutil_loadimage(const char *filename)
1584 1607
 }
1585 1608
 #endif
1586 1609
 
1610
+static void
1611
+intimutil_fpsdata(struct timeval **deadline)
1612
+{
1613
+        static struct timeval mydeadline;
1614
+        *deadline=&(mydeadline);
1615
+        return;
1616
+}
1617
+
1618
+void
1619
+imutil_fpsreset(void)
1620
+{
1621
+        struct timeval *deadline;
1622
+        long deadlineincr;
1623
+        intimutil_fpsdata(&deadline);
1624
+        gettimeofday(deadline,NULL);
1625
+        deadlineincr=1000000L/TARGETFPS;
1626
+        deadline->tv_usec+=deadlineincr;
1627
+        deadline->tv_sec+=(deadline->tv_usec)/1000000L;
1628
+        deadline->tv_usec%=1000000L;
1629
+}
1630
+
1631
+int
1632
+imutil_fpsleft(void)
1633
+{
1634
+        struct timeval *deadline,now;
1635
+        intimutil_fpsdata(&deadline);
1636
+        gettimeofday(&now,NULL);
1637
+        if(deadline->tv_sec<now.tv_sec || (deadline->tv_sec==now.tv_sec && deadline->tv_usec<now.tv_usec))
1638
+                return(0);
1639
+        return(1);
1640
+}
1641
+
Browse code

Add android target support

Dario Rodriguez authored on 16/03/2025 11:18:47
Showing 1 changed files
... ...
@@ -24,6 +24,7 @@
24 24
  *               Fix thumb aspect ratio.
25 25
  *      20250311 Fix bug because of stray CloseWindow() call.
26 26
  *               Add show using all window with right button.
27
+ *      20250316 Add android target support.
27 28
  *
28 29
  * Author: Dario Rodriguez dario@darionomono.com
29 30
  * (c) Dario Rodriguez 2025
... ...
@@ -41,23 +42,40 @@
41 42
 #include "raylib.h"
42 43
 #include "roboto_regular.c"
43 44
 
44
-#define DEFAULTWIDTH 1280
45
-#define DEFAULTHEIGHT 768
46
-
47 45
 #define UTF8DOWNARROW "\xe2\x86\x86" /* U+2186 in UTF-8 */
48 46
 
47
+#define SIMANDROID
48
+
49
+#if defined(ANDROID) || defined(SIMANDROID)
50
+#define ROOTDIR "/sdcard/"
51
+#define DEFAULTWIDTH 2400
52
+#define DEFAULTHEIGHT 1080
53
+#define LEFTSIZE 1600
54
+#define DEFAULTDIRDATAHEIGHT 520
55
+#define DEFAULTDIRDATATRIANGLEW 100
56
+#define LEFTIMAGESIDELEN 326
57
+#define FONTSIZE 64
58
+#define FONTBIGSIZE 96
59
+#define FONTHUGESIZE 128
60
+#else
61
+#define ROOTDIR "/var/www/default/animeshot/"
62
+#define DEFAULTWIDTH 1280
63
+#define DEFAULTHEIGHT 768
49 64
 #define LEFTSIZE 720
50 65
 #define DEFAULTDIRDATAHEIGHT 150
51 66
 #define DEFAULTDIRDATATRIANGLEW 35
52 67
 #define LEFTIMAGESIDELEN 125
53
-
54 68
 #define FONTSIZE 18
55 69
 #define FONTBIGSIZE 32
56 70
 #define FONTHUGESIZE 48
71
+#endif
57 72
 
58
-#define WHEELSTEP LEFTIMAGESIDELEN
59
-
73
+#if defined(SIMANDROID)
74
+#undef ROOTDIR
60 75
 #define ROOTDIR "/var/www/default/animeshot/"
76
+#endif
77
+
78
+#define WHEELSTEP LEFTIMAGESIDELEN
61 79
 
62 80
 #define SEP "/"
63 81
 
... ...
@@ -85,7 +103,7 @@
85 103
 #define UNROLLWHXY(xywh) (xywh).w,(xywh).h,(xywh).x,(xywh).y
86 104
 #endif
87 105
 
88
-#ifndef __linux__
106
+#if !defined(__linux__) && !defined(ANDROID)
89 107
 /* the old raylib used in the windows build lacks this function */
90 108
 bool IsImageValid(Image image)
91 109
 {
... ...
@@ -235,10 +253,11 @@ int imutil_submenu_count(char *menus);
235 253
 char *imutil_submenu_get(char *menus, int targetn, int *len);
236 254
 char *imutil_strduplen(char *str, int len);
237 255
 int is_imutil_insidexywh(Vector2 pos, xywh_t *xywh, int margin);
238
-int im_util_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh);
256
+int imutil_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh);
239 257
 int menudata_pos2option(menudata_t *menudata, Vector2 pos);
240 258
 int *getcodepoints(int *sizecodepoints);
241 259
 int is_imagefilename(char *filename);
260
+Image imutil_loadimage(const char *filename);
242 261
 
243 262
 int
244 263
 main(int argc, char *argv[])
... ...
@@ -935,7 +954,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
935 954
                                                 char fullpath[2048];
936 955
                                                 snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
937 956
                                                 fullpath[sizeof(fullpath)-1]='\0';
938
-                                                im=LoadImage(fullpath);
957
+                                                im=imutil_loadimage(fullpath);
939 958
                                                 if(IsImageValid(im)) {
940 959
                                                         int neww,newh;
941 960
                                                         Image im2,impixel;
... ...
@@ -945,7 +964,7 @@ fprintf(stderr,"Loaded %s\n",fullpath);
945 964
 int oldw=im.width,oldh=im.height;
946 965
 #endif
947 966
                                                         im2=GenImageColor(sidelen,sidelen,(Color){0,0,0,255});
948
-                                                        im_util_aspectmaximize(im.width,im.height,sidelen,sidelen,&neww,&newh);
967
+                                                        imutil_aspectmaximize(im.width,im.height,sidelen,sidelen,&neww,&newh);
949 968
                                                         ImageResize(&im,neww,newh);
950 969
                                                         impixel=ImageCopy(im);
951 970
                                                         ImageResize(&impixel,1,1);
... ...
@@ -1079,9 +1098,9 @@ texture_load(texture_t *texture, char *fullpath, int maxw, int maxh)
1079 1098
                 texture->has_failedload=0;
1080 1099
         }
1081 1100
         texture->currentpath[0]='\0';
1082
-        im=LoadImage(fullpath);
1101
+        im=imutil_loadimage(fullpath);
1083 1102
         if(IsImageValid(im)) {
1084
-                im_util_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
1103
+                imutil_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
1085 1104
                 ImageResize(&im,neww,newh);
1086 1105
                 texture->texture=LoadTextureFromImage(im);
1087 1106
                 UnloadImage(im);
... ...
@@ -1239,7 +1258,7 @@ is_imutil_insidexywh(Vector2 pos, xywh_t *xywh, int margin)
1239 1258
 }
1240 1259
 
1241 1260
 int
1242
-im_util_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh)
1261
+imutil_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh)
1243 1262
 {
1244 1263
         if(neww==NULL || newh==NULL || w==0 || h==0 || maxw==0 || maxh==0)
1245 1264
                 return(-1);
... ...
@@ -1529,3 +1548,39 @@ is_imagefilename(char *filename)
1529 1548
         return(0); /* not in the knownext list */
1530 1549
 }
1531 1550
 
1551
+#ifdef ANDROID
1552
+Image
1553
+imutil_loadimage(const char *filename)
1554
+{
1555
+        unsigned char *filedata=NULL;
1556
+        FILE *f=NULL;
1557
+        struct stat st;
1558
+        Image img;
1559
+        char *ext;
1560
+        if((f=fopen(filename,"r"))==NULL
1561
+          || fstat(fileno(f),&st)!=0
1562
+          || st.st_size<=0
1563
+          || (filedata=(unsigned char *)malloc(st.st_size))==NULL
1564
+          || fread(filedata,1,st.st_size,f)!=st.st_size
1565
+        ) {
1566
+                if(f!=NULL)
1567
+                        fclose(f),f=NULL;
1568
+                if(filedata!=NULL)
1569
+                        free(filedata),filedata=NULL;
1570
+                return((Image){0});
1571
+        }
1572
+        fclose(f);
1573
+        ext=strchr(filename,'.');
1574
+        ext=(ext==NULL)?filename+strlen(filename):ext;
1575
+        img=LoadImageFromMemory(ext,filedata,st.st_size);
1576
+        free(filedata),filedata=NULL;
1577
+        return(img);
1578
+}
1579
+#else
1580
+Image
1581
+imutil_loadimage(const char *filename)
1582
+{
1583
+        return(LoadImage(filename));
1584
+}
1585
+#endif
1586
+
Browse code

Add show using all window with right button

Dario Rodriguez authored on 11/03/2025 20:08:02
Showing 1 changed files
... ...
@@ -22,6 +22,8 @@
22 22
  *      20250308 Show statustooltip on image hover.
23 23
  *               Scrollwheel support for leftside.
24 24
  *               Fix thumb aspect ratio.
25
+ *      20250311 Fix bug because of stray CloseWindow() call.
26
+ *               Add show using all window with right button.
25 27
  *
26 28
  * Author: Dario Rodriguez dario@darionomono.com
27 29
  * (c) Dario Rodriguez 2025
... ...
@@ -161,6 +163,15 @@ typedef struct dirdata_t {
161 163
         listing_t listing;
162 164
 } dirdata_t;
163 165
 
166
+typedef struct texture_t {
167
+        char currentpath[2048];
168
+        Texture2D texture;
169
+        int texturew;
170
+        int textureh;
171
+        int has_texture;
172
+        int has_failedload;
173
+} texture_t;
174
+
164 175
 typedef struct body_t {
165 176
         char *rootdir;
166 177
         xywh_t xywh;
... ...
@@ -174,12 +185,8 @@ typedef struct body_t {
174 185
         font_t *ptrfont;
175 186
         font_t *ptrfontbig;
176 187
         font_t *ptrfonthuge;
177
-        char currenttexture[2048];
178
-        Texture2D texture;
179
-        int texturew;
180
-        int textureh;
181
-        int has_texture;
182
-        int has_failedload;
188
+        texture_t texture;
189
+        texture_t bigtexture;
183 190
 } body_t;
184 191
 
185 192
 typedef struct im_t {
... ...
@@ -212,12 +219,16 @@ void im_body_free(body_t *body);
212 219
 int im_body_add(body_t *body,char *dir);
213 220
 
214 221
 int im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
215
-int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int windowheight);
222
+int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight);
216 223
 
217 224
 int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort);
218 225
 void listing_freedata(listing_t *listing);
219 226
 int listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_left);
220 227
 
228
+int texture_load(texture_t *texture, char *fullpath, int maxw, int maxh);
229
+int texture_draw(texture_t *texture, int x0, int y0, int maxw, int maxh);
230
+int texture_freedata(texture_t *texture);
231
+
221 232
 int imutil_menu_count(char *menus);
222 233
 char *imutil_menu_get(char *menus, int targetn, int *len);
223 234
 int imutil_submenu_count(char *menus);
... ...
@@ -235,7 +246,7 @@ main(int argc, char *argv[])
235 246
         im_t *im;
236 247
         Vector2 mousepos,wheel;
237 248
         int flag_ignorelmb;
238
-        int lmbpressed,lmbreleased,lmbdown;
249
+        int lmbpressed,lmbreleased,lmbdown,rmbdown;
239 250
         int click_avail;
240 251
         char *sel_menu,*sel_submenu;
241 252
         if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n",ROOTDIR))==NULL) {
... ...
@@ -248,6 +259,7 @@ main(int argc, char *argv[])
248 259
                 lmbpressed=IsMouseButtonPressed(0);
249 260
                 lmbreleased=IsMouseButtonReleased(0);
250 261
                 lmbdown=IsMouseButtonDown(0);
262
+                rmbdown=IsMouseButtonDown(1);
251 263
                 click_avail=1;
252 264
                 /* process clicks on menus */
253 265
                 if(click_avail) {
... ...
@@ -266,7 +278,7 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
266 278
                 /* draw screen contents */
267 279
                 BeginDrawing();
268 280
                 ClearBackground(RAYWHITE);
269
-                im_body_draw(im->body,mousepos,lmbdown,im->w,im->h);
281
+                im_body_draw(im->body,mousepos,lmbdown,rmbdown,im->w,im->h);
270 282
                 im_menubar_draw(im->menubar,im->w,im->h);
271 283
 #if 0
272 284
 {
... ...
@@ -352,10 +364,8 @@ im_free(im_t *im)
352 364
                 im_font_free(im->fontbig),im->fontbig=NULL;
353 365
         if(im->fonthuge!=NULL)
354 366
                 im_font_free(im->fonthuge),im->fonthuge=NULL;
355
-#if 1 /* not working as intended */
356 367
         if(im->windowinit)
357 368
                 CloseWindow(),im->windowinit=0;
358
-#endif
359 369
         free(im),im=NULL;
360 370
         return;
361 371
 }
... ...
@@ -666,12 +676,8 @@ im_body_free(body_t *body)
666 676
                 }
667 677
                 free(body->dirdata),body->dirdata=NULL,body->sizedirdata=0;
668 678
         }
669
-        if(body->has_texture) {
670
-                UnloadTexture(body->texture);
671
-                body->currenttexture[0]='\0';
672
-                body->has_texture=0;
673
-                body->has_failedload=0;
674
-        }
679
+        texture_freedata(&(body->texture));
680
+        texture_freedata(&(body->bigtexture));
675 681
         if(body->rootdir!=NULL)
676 682
                 free(body->rootdir),body->rootdir=NULL;
677 683
         free(body),body=NULL;
... ...
@@ -778,7 +784,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
778 784
 }
779 785
 
780 786
 int
781
-im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int windowheight)
787
+im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int rmbdown, int windowwidth, int windowheight)
782 788
 {
783 789
         int i,k,margin,righty;
784 790
         int lastx,lasty;
... ...
@@ -788,6 +794,7 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int w
788 794
         font_t *font,*fontbig,*fonthuge;
789 795
         int is_leftside;
790 796
         int flag_skiprightside;
797
+        int flag_skipall;
791 798
         int xoff,yoff;
792 799
         thumb_t *thumb;
793 800
         char statustooltip[1024];
... ...
@@ -819,8 +826,8 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int w
819 826
         DrawRectangle(body->xywh.x+body->leftsize,body->xywh.y,body->xywh.w-body->leftsize, body->xywh.h, (Color){ 227, 227, 227, 255 } );
820 827
         /* first pass, draw leftside, second pass, draw all of rightside */
821 828
         statustooltip[0]='\0';
822
-        for(is_leftside=1,flag_skiprightside=0;is_leftside>=0 && flag_skiprightside==0;is_leftside--) {
823
-                for(i=(is_leftside)?body->currentdirdata:0,righty=body->xywh.y;(is_leftside && i==body->currentdirdata) || (!is_leftside && i<body->sizedirdata);i++) {
829
+        for(is_leftside=1,flag_skiprightside=flag_skipall=0;is_leftside>=0 && flag_skiprightside==0 && flag_skipall==0;is_leftside--) {
830
+                for(i=(is_leftside)?body->currentdirdata:0,righty=body->xywh.y;flag_skipall==0 && ((is_leftside && i==body->currentdirdata) || (!is_leftside && i<body->sizedirdata));i++) {
824 831
                         int sidelen;
825 832
                         if((dirdata=body->dirdata[i])==NULL)
826 833
                                 continue;
... ...
@@ -962,56 +969,49 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
962 969
                                                 DrawTexture(*te,thumb->screenxywh.x,thumb->screenxywh.y,WHITE);
963 970
                                                 has_imagedrawn=1;
964 971
                                                 lastx=xywh->x+xywh->w,lasty=xywh->y+xywh->h+yoff;
965
-                                                if(is_leftside && lmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
972
+                                                if(is_leftside && lmbdown==0 && rmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
966 973
                                                         /* draw image in rightside */
967
-                                                        char path[2048];
974
+                                                        char fullpath[2048];
968 975
                                                         int maxw,maxh;
969
-                                                        snprintf(path,sizeof(path),"%s/%s",dirdata->dirname,elem->name+1);
970
-                                                        path[sizeof(path)-1]='\0';
971 976
                                                         maxw=windowwidth-(body->leftsize-DEFAULTDIRDATATRIANGLEW);
972 977
                                                         maxh=windowheight-body->xywh.y;
973
-                                                        if((body->has_texture==0 && !(body->has_failedload && strcmp(body->currenttexture,path)==0))
974
-                                                          || strcmp(body->currenttexture,path)!=0
978
+                                                        snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
979
+                                                        fullpath[sizeof(fullpath)-1]='\0';
980
+                                                        if((body->texture.has_texture==0 && !(body->texture.has_failedload && strcmp(body->texture.currentpath,fullpath)==0))
981
+                                                          || strcmp(body->texture.currentpath,fullpath)!=0
975 982
                                                         ) {
976
-                                                                Image im;
977
-                                                                int neww,newh;
978
-                                                                char fullpath[2048];
979
-                                                                if(body->has_texture) {
980
-                                                                        UnloadTexture(body->texture);
981
-                                                                        body->currenttexture[0]='\0';
982
-                                                                        body->has_texture=0;
983
-                                                                        body->has_failedload=0;
984
-                                                                }
985
-                                                                snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
986
-                                                                fullpath[sizeof(fullpath)-1]='\0';
987
-                                                                im=LoadImage(fullpath);
988
-                                                                if(IsImageValid(im)) {
989
-                                                                        im_util_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
990
-                                                                        ImageResize(&im,neww,newh);
991
-                                                                        body->texture=LoadTextureFromImage(im);
992
-                                                                        UnloadImage(im);
993
-                                                                        strncpy(body->currenttexture,fullpath,sizeof(body->currenttexture));
994
-                                                                        body->currenttexture[sizeof(body->currenttexture)-1]='\0';
995
-                                                                        body->has_texture=1;
996
-                                                                        body->has_failedload=0;
997
-                                                                        body->texturew=neww;
998
-                                                                        body->textureh=newh;
999
-                                                                } else {
1000
-                                                                        strncpy(body->currenttexture,fullpath,sizeof(body->currenttexture));
1001
-                                                                        body->currenttexture[sizeof(body->currenttexture)-1]='\0';
1002
-                                                                        body->has_texture=0;
1003
-                                                                        body->has_failedload=1;
1004
-                                                                }
983
+                                                                texture_load(&(body->texture),fullpath,maxw,maxh);
1005 984
                                                         }
1006
-                                                        if(body->has_texture) {
985
+                                                        if(body->texture.has_texture && strcmp(body->texture.currentpath,fullpath)==0) {
1007 986
                                                                 int x0,y0;
1008 987
                                                                 x0=body->leftsize-DEFAULTDIRDATATRIANGLEW;
1009 988
                                                                 y0=body->xywh.y;
1010
-                                                                DrawRectangle(x0,y0,maxw,maxh,(Color){ 215, 215, 215, 255 } );
1011
-                                                                DrawTexture(body->texture,x0+(maxw-body->texturew)/2,y0+(maxh-body->textureh)/2,WHITE);
989
+                                                                texture_draw(&(body->texture),x0,y0,maxw,maxh);
1012 990
                                                                 flag_skiprightside=1;
1013 991
                                                         }
1014 992
                                                 }
993
+                                                if(is_leftside && lmbdown==0 && rmbdown!=0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
994
+                                                        /* draw image in full screen */
995
+                                                        char fullpath[2048];
996
+                                                        int maxw,maxh;
997
+                                                        maxw=windowwidth;
998
+                                                        maxh=windowheight-body->xywh.y;
999
+                                                        snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
1000
+                                                        fullpath[sizeof(fullpath)-1]='\0';
1001
+                                                        if((body->bigtexture.has_texture==0 && !(body->bigtexture.has_failedload && strcmp(body->bigtexture.currentpath,fullpath)==0))
1002
+                                                          || strcmp(body->bigtexture.currentpath,fullpath)!=0
1003
+                                                        ) {
1004
+                                                                texture_load(&(body->bigtexture),fullpath,maxw,maxh);
1005
+                                                        }
1006
+                                                        if(body->bigtexture.has_texture && strcmp(body->bigtexture.currentpath,fullpath)==0) {
1007
+                                                                int x0,y0;
1008
+                                                                x0=0;
1009
+                                                                y0=body->xywh.y;
1010
+                                                                texture_draw(&(body->bigtexture),x0,y0,maxw,maxh);
1011
+                                                                flag_skipall=1;
1012
+                                                                break;
1013
+                                                        }
1014
+                                                }
1015 1015
                                         }
1016 1016
                                 }
1017 1017
                                 if(has_imagedrawn==0) {
... ...
@@ -1065,6 +1065,65 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1065 1065
         return(0);
1066 1066
 }
1067 1067
 
1068
+int
1069
+texture_load(texture_t *texture, char *fullpath, int maxw, int maxh)
1070
+{ 
1071
+        Image im;
1072
+        int neww,newh;
1073
+        if(texture==NULL || fullpath==NULL)
1074
+                return(-1); /* sanity check failed */
1075
+        if(texture->has_texture) {
1076
+                UnloadTexture(texture->texture);
1077
+                texture->currentpath[0]='\0';
1078
+                texture->has_texture=0;
1079
+                texture->has_failedload=0;
1080
+        }
1081
+        texture->currentpath[0]='\0';
1082
+        im=LoadImage(fullpath);
1083
+        if(IsImageValid(im)) {
1084
+                im_util_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
1085
+                ImageResize(&im,neww,newh);
1086
+                texture->texture=LoadTextureFromImage(im);
1087
+                UnloadImage(im);
1088
+                strncpy(texture->currentpath,fullpath,sizeof(texture->currentpath));
1089
+                texture->currentpath[sizeof(texture->currentpath)-1]='\0';
1090
+                texture->has_texture=1;
1091
+                texture->has_failedload=0;
1092
+                texture->texturew=neww;
1093
+                texture->textureh=newh;
1094
+        } else {
1095
+                strncpy(texture->currentpath,fullpath,sizeof(texture->currentpath));
1096
+                texture->currentpath[sizeof(texture->currentpath)-1]='\0';
1097
+                texture->has_texture=0;
1098
+                texture->has_failedload=1;
1099
+        }
1100
+        return(0);
1101
+}
1102
+
1103
+int
1104
+texture_draw(texture_t *texture, int x0, int y0, int maxw, int maxh)
1105
+{
1106
+        if(texture==NULL || texture->has_texture==0)
1107
+                return(-1); /* sanity check failed */
1108
+        DrawRectangle(x0,y0,maxw,maxh,(Color){ 215, 215, 215, 255 } );
1109
+        DrawTexture(texture->texture,x0+(maxw-texture->texturew)/2,y0+(maxh-texture->textureh)/2,WHITE);
1110
+        return(0);
1111
+}
1112
+
1113
+int
1114
+texture_freedata(texture_t *texture)
1115
+{
1116
+        if(texture==NULL)
1117
+                return(-1); /* sanity check failed */
1118
+        if(texture->has_texture) {
1119
+                UnloadTexture(texture->texture);
1120
+                texture->currentpath[0]='\0';
1121
+                texture->has_texture=0;
1122
+                texture->has_failedload=0;
1123
+        }
1124
+        return(0);
1125
+}
1126
+
1068 1127
 int
1069 1128
 imutil_menu_count(char *menus)
1070 1129
 {
Browse code

Fix bug because of stray CloswWindow() call

Dario Rodriguez authored on 11/03/2025 19:34:03
Showing 1 changed files
... ...
@@ -303,7 +303,6 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
303 303
 #endif
304 304
                 EndDrawing();
305 305
         }
306
-        CloseWindow();
307 306
         im_free(im),im=NULL;
308 307
         return(0);
309 308
 }
... ...
@@ -353,7 +352,7 @@ im_free(im_t *im)
353 352
                 im_font_free(im->fontbig),im->fontbig=NULL;
354 353
         if(im->fonthuge!=NULL)
355 354
                 im_font_free(im->fonthuge),im->fonthuge=NULL;
356
-#if 0 /* not working as intended */
355
+#if 1 /* not working as intended */
357 356
         if(im->windowinit)
358 357
                 CloseWindow(),im->windowinit=0;
359 358
 #endif
... ...
@@ -656,8 +655,6 @@ im_body_free(body_t *body)
656 655
         dirdata_t *dirdata;
657 656
         if(body==NULL)
658 657
                 return; /* nothing to do */
659
-        if(body->rootdir!=NULL)
660
-                free(body->rootdir),body->rootdir=NULL;
661 658
         if(body->dirdata!=NULL) {
662 659
                 for(i=0;i<body->sizedirdata;i++) {
663 660
                         if((dirdata=body->dirdata[i])==NULL)
... ...
@@ -675,6 +672,8 @@ im_body_free(body_t *body)
675 672
                 body->has_texture=0;
676 673
                 body->has_failedload=0;
677 674
         }
675
+        if(body->rootdir!=NULL)
676
+                free(body->rootdir),body->rootdir=NULL;
678 677
         free(body),body=NULL;
679 678
         return;
680 679
 }
... ...
@@ -923,9 +922,8 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
923 922
                                 }
924 923
                                 /* show image */
925 924
                                 has_imagedrawn=0;
926
-#if 1
927 925
                                 if(is_imagefilename(elem->name+1)) {
928
-                                        if(thumb->has_texture==0) {
926
+                                        if(thumb->has_texture==0 && thumb->has_failedload==0) {
929 927
                                                 Image im;
930 928
                                                 char fullpath[2048];
931 929
                                                 snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
... ...
@@ -955,6 +953,8 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
955 953
                                                         UnloadImage(im);
956 954
                                                         UnloadImage(im2);
957 955
                                                         thumb->has_texture=1;
956
+                                                } else {
957
+                                                        thumb->has_failedload=1;
958 958
                                                 }
959 959
                                         }
960 960
                                         if(thumb->has_texture!=0) {
... ...
@@ -1014,7 +1014,6 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
1014 1014
                                                 }
1015 1015
                                         }
1016 1016
                                 }
1017
-#endif
1018 1017
                                 if(has_imagedrawn==0) {
1019 1018
                                         char *ptr;
1020 1019
                                         char shortname[1024];
Browse code

Fix thumb aspect ratio

Dario Rodriguez authored on 08/03/2025 22:10:42
Showing 1 changed files
... ...
@@ -21,6 +21,7 @@
21 21
  *      20250305 Scrollable left pane.
22 22
  *      20250308 Show statustooltip on image hover.
23 23
  *               Scrollwheel support for leftside.
24
+ *               Fix thumb aspect ratio.
24 25
  *
25 26
  * Author: Dario Rodriguez dario@darionomono.com
26 27
  * (c) Dario Rodriguez 2025
... ...
@@ -222,7 +223,7 @@ char *imutil_menu_get(char *menus, int targetn, int *len);
222 223
 int imutil_submenu_count(char *menus);
223 224
 char *imutil_submenu_get(char *menus, int targetn, int *len);
224 225
 char *imutil_strduplen(char *str, int len);
225
-int is_imutil_insidexywh(Vector2 pos, xywh_t *xywh);
226
+int is_imutil_insidexywh(Vector2 pos, xywh_t *xywh, int margin);
226 227
 int im_util_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh);
227 228
 int menudata_pos2option(menudata_t *menudata, Vector2 pos);
228 229
 int *getcodepoints(int *sizecodepoints);
... ...
@@ -494,7 +495,7 @@ im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbre
494 495
         flag_outsideall=1;
495 496
         for(i=0;i<menubar->sizemenudata;i++) {
496 497
                 int insidetitle,currentoption;
497
-                insidetitle=is_imutil_insidexywh(mousepos,&(menubar->menudata[i]->xywh));
498
+                insidetitle=is_imutil_insidexywh(mousepos,&(menubar->menudata[i]->xywh),0);
498 499
                 currentoption=menudata_pos2option(menubar->menudata[i],mousepos);
499 500
                 flag_outsideall=(currentoption!=-1 || insidetitle)?0:flag_outsideall;
500 501
                 if(lmbreleased && insidetitle) {
... ...
@@ -730,7 +731,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
730 731
         if(*click_avail==0 || lmbreleased==0)
731 732
                 return(0); /* nothing else to do */
732 733
         /* leftside backbutton */
733
-        if(is_imutil_insidexywh(mousepos,&(body->backxywh))) {
734
+        if(is_imutil_insidexywh(mousepos,&(body->backxywh),0)) {
734 735
                 static char sep[]={SEP};
735 736
                 if((ptr=strrchr(dirdata->dirname,sep[0]))!=NULL) {
736 737
                         /* previous dir */
... ...
@@ -749,7 +750,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int
749 750
                 ld=dirdata->listing.elems+i;
750 751
                 if(ld->name[0]!='d')
751 752
                         continue;
752
-                if(is_imutil_insidexywh(mousepos,&(ld->left.screenxywh))) {
753
+                if(is_imutil_insidexywh(mousepos,&(ld->left.screenxywh),0)) {
753 754
                         char *newname,*oldprefix;
754 755
                         int l,l0,l1;
755 756
                         static char sep[]={SEP};
... ...
@@ -916,7 +917,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
916 917
 #warning TODO: if !is_leftside, draw "..." in huge font using lastx,lasty as reference
917 918
                                         break;
918 919
                                 }
919
-                                if(is_leftside && is_imutil_insidexywh(mousepos,&(thumb->screenxywh))) {
920
+                                if(is_leftside && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
920 921
                                         strncpy(statustooltip,elem->name+1,sizeof(statustooltip));
921 922
                                         statustooltip[sizeof(statustooltip)-1]='\0';
922 923
                                 }
... ...
@@ -931,12 +932,28 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
931 932
                                                 fullpath[sizeof(fullpath)-1]='\0';
932 933
                                                 im=LoadImage(fullpath);
933 934
                                                 if(IsImageValid(im)) {
935
+                                                        int neww,newh;
936
+                                                        Image im2,impixel;
934 937
 #if 1
935 938
 fprintf(stderr,"Loaded %s\n",fullpath);
939
+{
940
+int oldw=im.width,oldh=im.height;
941
+#endif
942
+                                                        im2=GenImageColor(sidelen,sidelen,(Color){0,0,0,255});
943
+                                                        im_util_aspectmaximize(im.width,im.height,sidelen,sidelen,&neww,&newh);
944
+                                                        ImageResize(&im,neww,newh);
945
+                                                        impixel=ImageCopy(im);
946
+                                                        ImageResize(&impixel,1,1);
947
+#if 1
948
+if(neww>sidelen || newh>sidelen)
949
+fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidelen,oldw,oldh,neww,newh);
950
+}
936 951
 #endif
937
-                                                        ImageResize(&im,sidelen,sidelen);
938
-                                                        *te=LoadTextureFromImage(im);
952
+                                                        ImageDraw(&im2,impixel,(Rectangle) {0,0,1,1},(Rectangle) {0,0,sidelen,sidelen},(Color){255,255,255,255});
953
+                                                        ImageDraw(&im2,im,(Rectangle) {0,0,neww,newh},(Rectangle) {(sidelen-neww)/2,(sidelen-newh)/2,neww,newh},(Color){255,255,255,255});
954
+                                                        *te=LoadTextureFromImage(im2);
939 955
                                                         UnloadImage(im);
956
+                                                        UnloadImage(im2);
940 957
                                                         thumb->has_texture=1;
941 958
                                                 }
942 959
                                         }
... ...
@@ -945,7 +962,7 @@ fprintf(stderr,"Loaded %s\n",fullpath);
945 962
                                                 DrawTexture(*te,thumb->screenxywh.x,thumb->screenxywh.y,WHITE);
946 963
                                                 has_imagedrawn=1;
947 964
                                                 lastx=xywh->x+xywh->w,lasty=xywh->y+xywh->h+yoff;
948
-                                                if(is_leftside && lmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh))) {
965
+                                                if(is_leftside && lmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh),margin)) {
949 966
                                                         /* draw image in rightside */
950 967
                                                         char path[2048];
951 968
                                                         int maxw,maxh;
... ...
@@ -1149,14 +1166,14 @@ imutil_strduplen(char *str, int len)
1149 1166
 }
1150 1167
 
1151 1168
 int
1152
-is_imutil_insidexywh(Vector2 pos, xywh_t *xywh)
1169
+is_imutil_insidexywh(Vector2 pos, xywh_t *xywh, int margin)
1153 1170
 {
1154 1171
         if(xywh==NULL)
1155 1172
                 return(0); /* sanity check error */
1156
-        if(pos.x>=(float)(xywh->x)
1157
-          && pos.x<=(float)(xywh->x+xywh->w)
1158
-          && pos.y>=(float)(xywh->y)
1159
-          && pos.y<=(float)(xywh->y+xywh->h)
1173
+        if(pos.x>=(float)(xywh->x-margin)
1174
+          && pos.x<=(float)(xywh->x+xywh->w+margin)
1175
+          && pos.y>=(float)(xywh->y-margin)
1176
+          && pos.y<=(float)(xywh->y+xywh->h+margin)
1160 1177
         ) {
1161 1178
                 return(1);
1162 1179
         }
... ...
@@ -1168,7 +1185,7 @@ im_util_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh)
1168 1185
 {
1169 1186
         if(neww==NULL || newh==NULL || w==0 || h==0 || maxw==0 || maxh==0)
1170 1187
                 return(-1);
1171
-        if((w/h)>(maxw/maxh)) {
1188
+        if((w/h)>(maxw/maxh) || (maxw==maxh && w>h)) {
1172 1189
                 *neww=maxw;
1173 1190
                 *newh=h*maxw/w;
1174 1191
         } else { /* (w/h)<=(maxw/maxh) */
... ...
@@ -1185,7 +1202,7 @@ menudata_pos2option(menudata_t *menudata, Vector2 pos)
1185 1202
         int n,h;
1186 1203
         if(menudata==NULL
1187 1204
           || (menudata->flag_open==0 && menudata->flag_stickyopen==0)
1188
-          || is_imutil_insidexywh(pos, &(menudata->optionsxywh))==0
1205
+          || is_imutil_insidexywh(pos, &(menudata->optionsxywh),0)==0
1189 1206
         ) {
1190 1207
                 return(-1);
1191 1208
         }
Browse code

Scrollwheel support for leftside

Dario Rodriguez authored on 08/03/2025 20:17:43
Showing 1 changed files
... ...
@@ -20,6 +20,7 @@
20 20
  *               Preserve aspect ratio of big image.
21 21
  *      20250305 Scrollable left pane.
22 22
  *      20250308 Show statustooltip on image hover.
23
+ *               Scrollwheel support for leftside.
23 24
  *
24 25
  * Author: Dario Rodriguez dario@darionomono.com
25 26
  * (c) Dario Rodriguez 2025
... ...
@@ -51,6 +52,8 @@
51 52
 #define FONTBIGSIZE 32
52 53
 #define FONTHUGESIZE 48
53 54
 
55
+#define WHEELSTEP LEFTIMAGESIDELEN
56
+
54 57
 #define ROOTDIR "/var/www/default/animeshot/"
55 58
 
56 59
 #define SEP "/"
... ...
@@ -148,6 +151,7 @@ typedef struct listing_t {
148 151
         char *buf;
149 152
         int has_leftxywh;
150 153
         int has_rightxywh;
154
+        xywh_t lastleftxywh;
151 155
 } listing_t;
152 156
 
153 157
 typedef struct dirdata_t {
... ...
@@ -206,7 +210,7 @@ void im_body_free(body_t *body);
206 210
 
207 211
 int im_body_add(body_t *body,char *dir);
208 212
 
209
-int im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
213
+int im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
210 214
 int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int windowheight);
211 215
 
212 216
 int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort);
... ...
@@ -228,7 +232,7 @@ int
228 232
 main(int argc, char *argv[])
229 233
 {
230 234
         im_t *im;
231
-        Vector2 mousepos;
235
+        Vector2 mousepos,wheel;
232 236
         int flag_ignorelmb;
233 237
         int lmbpressed,lmbreleased,lmbdown;
234 238
         int click_avail;
... ...
@@ -239,6 +243,7 @@ main(int argc, char *argv[])
239 243
         flag_ignorelmb=0;
240 244
         while(!WindowShouldClose()) {
241 245
                 mousepos=GetMousePosition();
246
+                wheel=GetMouseWheelMoveV();
242 247
                 lmbpressed=IsMouseButtonPressed(0);
243 248
                 lmbreleased=IsMouseButtonReleased(0);
244 249
                 lmbdown=IsMouseButtonDown(0);
... ...
@@ -254,7 +259,7 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
254 259
                         }
255 260
                 }
256 261
                 if(click_avail)
257
-                        im_body_mouse(im->body, mousepos, lmbpressed, lmbreleased, lmbdown, &click_avail);
262
+                        im_body_mouse(im->body, mousepos, wheel, lmbpressed, lmbreleased, lmbdown, &click_avail);
258 263
 
259 264
 
260 265
                 /* draw screen contents */
... ...
@@ -707,7 +712,7 @@ im_body_add(body_t *body,char *dir)
707 712
 }
708 713
 
709 714
 int
710
-im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail)
715
+im_body_mouse(body_t *body, Vector2 mousepos, Vector2 wheel, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail)
711 716
 {
712 717
         int i;
713 718
         char *ptr;
... ...
@@ -715,9 +720,15 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
715 720
         listingdata_t *ld;
716 721
         if(body==NULL || click_avail==NULL || body->currentdirdata<0 || body->currentdirdata>=body->sizedirdata || body->dirdata[body->currentdirdata]==NULL)
717 722
                 return(-1); /* sanity check error */
718
-        if(*click_avail==0 || lmbreleased==0)
719
-                return(0); /* nothing to do */
720 723
         dirdata=body->dirdata[body->currentdirdata];
724
+        /* wheel */
725
+        body->leftscrollpos-=(int)wheel.y*WHEELSTEP;
726
+        body->leftscrollpos=(body->leftscrollpos<0)?0:body->leftscrollpos;
727
+        if(body->leftscrollpos>dirdata->listing.lastleftxywh.y)
728
+                body->leftscrollpos=dirdata->listing.lastleftxywh.y;
729
+        /* check if we have to process a click */
730
+        if(*click_avail==0 || lmbreleased==0)
731
+                return(0); /* nothing else to do */
721 732
         /* leftside backbutton */
722 733
         if(is_imutil_insidexywh(mousepos,&(body->backxywh))) {
723 734
                 static char sep[]={SEP};
... ...
@@ -729,6 +740,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
729 740
                         dirdata->dirname[0]='\0';
730 741
                 }
731 742
                 listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
743
+                body->leftscrollpos=0;
732 744
                 *click_avail=0;
733 745
                 return(0);
734 746
         }
... ...
@@ -737,7 +749,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
737 749
                 ld=dirdata->listing.elems+i;
738 750
                 if(ld->name[0]!='d')
739 751
                         continue;
740
-                if(is_imutil_insidexywh(mousepos,&(ld->left.xywh))) {
752
+                if(is_imutil_insidexywh(mousepos,&(ld->left.screenxywh))) {
741 753
                         char *newname,*oldprefix;
742 754
                         int l,l0,l1;
743 755
                         static char sep[]={SEP};
... ...
@@ -756,6 +768,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
756 768
                         free(dirdata->dirname),dirdata->dirname=NULL;
757 769
                         dirdata->dirname=newname;
758 770
                         listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
771
+                        body->leftscrollpos=0;
759 772
                         *click_avail=0;
760 773
                         return(0);
761 774
                 }
... ...
@@ -780,17 +793,6 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int w
780 793
         char statustooltip[1024];
781 794
         if(body==NULL)
782 795
                 return(-1);
783
-#if 1
784
-#warning TESTING LEFTSCROLL
785
-body->leftscrollpos=(int) mousepos.y;
786
-{
787
- static int lastlsp=-1;
788
- if(body->leftscrollpos!=lastlsp) {
789
-  lastlsp=body->leftscrollpos;
790
-  fprintf(stderr,"leftscrollpos:%i\n",body->leftscrollpos);
791
- }
792
-}
793
-#endif
794 796
         font=body->ptrfont;
795 797
         fontbig=body->ptrfontbig;
796 798
         fonthuge=body->ptrfonthuge;
... ...
@@ -1368,6 +1370,8 @@ listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_le
1368 1370
         if(listing==NULL || font==NULL)
1369 1371
                 return(-1); /* sanity check failed */
1370 1372
         margin=font->height/4;
1373
+        if(is_leftside)
1374
+                memset(&(listing->lastleftxywh),0,sizeof(listing->lastleftxywh));
1371 1375
         /* directories */
1372 1376
         if(is_leftside) {
1373 1377
                 x0=font->height/2;
... ...
@@ -1391,6 +1395,8 @@ listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_le
1391 1395
                         continue;
1392 1396
                 }
1393 1397
                 FILLXYWH(thumb->xywh,x,y,margin*2+m2.x,margin*2+font->height);
1398
+                if(is_leftside && (thumb->xywh.y+thumb->xywh.h)>(listing->lastleftxywh.y+listing->lastleftxywh.h))
1399
+                        memcpy(&(listing->lastleftxywh),&(thumb->xywh),sizeof(xywh_t));
1394 1400
                 x+=margin*2+m2.x+font->height/4;
1395 1401
         }
1396 1402
         y+=((x==x0)?0:font->height+margin*2+font->height/4);
... ...
@@ -1415,6 +1421,8 @@ listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_le
1415 1421
                         continue;
1416 1422
                 }
1417 1423
                 FILLXYWH(thumb->xywh,x,y,sidelen,sidelen);
1424
+                if(is_leftside && (thumb->xywh.y+thumb->xywh.h)>(listing->lastleftxywh.y+listing->lastleftxywh.h))
1425
+                        memcpy(&(listing->lastleftxywh),&(thumb->xywh),sizeof(xywh_t));
1418 1426
                 x+=margin*2+sidelen;
1419 1427
         }
1420 1428
         return(0);
Browse code

Show statustooltip on image hover

Dario Rodriguez authored on 08/03/2025 19:39:08
Showing 1 changed files
... ...
@@ -19,6 +19,7 @@
19 19
  *               Show big image on hover.
20 20
  *               Preserve aspect ratio of big image.
21 21
  *      20250305 Scrollable left pane.
22
+ *      20250308 Show statustooltip on image hover.
22 23
  *
23 24
  * Author: Dario Rodriguez dario@darionomono.com
24 25
  * (c) Dario Rodriguez 2025
... ...
@@ -776,6 +777,7 @@ im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int w
776 777
         int flag_skiprightside;
777 778
         int xoff,yoff;
778 779
         thumb_t *thumb;
780
+        char statustooltip[1024];
779 781
         if(body==NULL)
780 782
                 return(-1);
781 783
 #if 1
... ...
@@ -814,6 +816,7 @@ body->leftscrollpos=(int) mousepos.y;
814 816
         /* draw right side background */
815 817
         DrawRectangle(body->xywh.x+body->leftsize,body->xywh.y,body->xywh.w-body->leftsize, body->xywh.h, (Color){ 227, 227, 227, 255 } );
816 818
         /* first pass, draw leftside, second pass, draw all of rightside */
819
+        statustooltip[0]='\0';
817 820
         for(is_leftside=1,flag_skiprightside=0;is_leftside>=0 && flag_skiprightside==0;is_leftside--) {
818 821
                 for(i=(is_leftside)?body->currentdirdata:0,righty=body->xywh.y;(is_leftside && i==body->currentdirdata) || (!is_leftside && i<body->sizedirdata);i++) {
819 822
                         int sidelen;
... ...
@@ -911,6 +914,10 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
911 914
 #warning TODO: if !is_leftside, draw "..." in huge font using lastx,lasty as reference
912 915
                                         break;
913 916
                                 }
917
+                                if(is_leftside && is_imutil_insidexywh(mousepos,&(thumb->screenxywh))) {
918
+                                        strncpy(statustooltip,elem->name+1,sizeof(statustooltip));
919
+                                        statustooltip[sizeof(statustooltip)-1]='\0';
920
+                                }
914 921
                                 /* show image */
915 922
                                 has_imagedrawn=0;
916 923
 #if 1
... ...
@@ -1032,6 +1039,11 @@ fprintf(stderr,"Loaded %s\n",fullpath);
1032 1039
                         }
1033 1040
                 }
1034 1041
         }
1042
+        if(statustooltip[0]!='\0') {
1043
+                m2=MeasureTextEx(font->font,statustooltip,font->height,0);
1044
+                DrawRectangle(0,windowheight-1-margin*2-font->height,m2.x+margin*2,font->height+margin*2,((Color){0,0,0,96}));
1045
+                DrawTextEx(font->font,statustooltip,(Vector2){margin,windowheight-1-margin-font->height},font->height,0,(Color){ 255,255,255,128 });
1046
+        }
1035 1047
         return(0);
1036 1048
 }
1037 1049
 
Browse code

Scrollable left pane

Dario Rodriguez authored on 05/03/2025 21:11:23
Showing 1 changed files
... ...
@@ -18,6 +18,7 @@
18 18
  *               Basic image loading.
19 19
  *               Show big image on hover.
20 20
  *               Preserve aspect ratio of big image.
21
+ *      20250305 Scrollable left pane.
21 22
  *
22 23
  * Author: Dario Rodriguez dario@darionomono.com
23 24
  * (c) Dario Rodriguez 2025
... ...
@@ -73,6 +74,10 @@
73 74
 #define UNROLLXYWH(xywh) (xywh).x,(xywh).y,(xywh).w,(xywh).h
74 75
 #endif
75 76
 
77
+#ifndef UNROLLWHXY
78
+#define UNROLLWHXY(xywh) (xywh).w,(xywh).h,(xywh).x,(xywh).y
79
+#endif
80
+
76 81
 #ifndef __linux__
77 82
 /* the old raylib used in the windows build lacks this function */
78 83
 bool IsImageValid(Image image)
... ...
@@ -121,8 +126,10 @@ typedef struct menubar_t {
121 126
 
122 127
 typedef struct thumb_t {
123 128
         xywh_t xywh;
129
+        xywh_t screenxywh;
124 130
         Texture2D texture;
125 131
         int has_texture;
132
+        int has_failedload;
126 133
 } thumb_t;
127 134
 
128 135
 typedef struct listingdata_t {
... ...
@@ -138,6 +145,8 @@ typedef struct listing_t {
138 145
         int sizebuf;
139 146
         int usedbuf;
140 147
         char *buf;
148
+        int has_leftxywh;
149
+        int has_rightxywh;
141 150
 } listing_t;
142 151
 
143 152
 typedef struct dirdata_t {
... ...
@@ -159,11 +168,12 @@ typedef struct body_t {
159 168
         font_t *ptrfont;
160 169
         font_t *ptrfontbig;
161 170
         font_t *ptrfonthuge;
162
-        char currenttexture[1024];
171
+        char currenttexture[2048];
163 172
         Texture2D texture;
164 173
         int texturew;
165 174
         int textureh;
166 175
         int has_texture;
176
+        int has_failedload;
167 177
 } body_t;
168 178
 
169 179
 typedef struct im_t {
... ...
@@ -190,7 +200,7 @@ void im_menubar_free(menubar_t *menubar);
190 200
 int im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail, char **sel_menu, char **sel_submenu);
191 201
 int im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight);
192 202
 
193
-body_t *im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir);
203
+body_t *im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir, int windowwidth, int windowheight);
194 204
 void im_body_free(body_t *body);
195 205
 
196 206
 int im_body_add(body_t *body,char *dir);
... ...
@@ -200,6 +210,7 @@ int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, i
200 210
 
201 211
 int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort);
202 212
 void listing_freedata(listing_t *listing);
213
+int listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_left);
203 214
 
204 215
 int imutil_menu_count(char *menus);
205 216
 char *imutil_menu_get(char *menus, int targetn, int *len);
... ...
@@ -310,7 +321,7 @@ im_init(char *menus, char *rootdir)
310 321
           || (im->fontbig=im_font_init(FONTBIGSIZE))==NULL
311 322
           || (im->fonthuge=im_font_init(FONTHUGESIZE))==NULL
312 323
           || (im->menubar=im_menubar_init(menus,im->font))==NULL
313
-          || (im->body=im_body_init(0,im->menubar->height, im->font, im->fontbig, im->fonthuge, LEFTSIZE, rootdir))==NULL
324
+          || (im->body=im_body_init(0,im->menubar->height, im->font, im->fontbig, im->fonthuge, LEFTSIZE, rootdir,im->w,im->h))==NULL
314 325
         ) {
315 326
                 im_free(im),im=NULL;
316 327
                 return(NULL); /* insuf. mem. */
... ...
@@ -609,7 +620,7 @@ im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight)
609 620
 }
610 621
 
611 622
 body_t *
612
-im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir)
623
+im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir, int windowwidth, int windowheight)
613 624
 {
614 625
         body_t *body;
615 626
         static char sep[]={SEP};
... ...
@@ -621,7 +632,7 @@ im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int
621 632
                 im_body_free(body),body=NULL;
622 633
                 return(NULL);
623 634
         }
624
-        FILLXY(body->xywh,x,y);
635
+        FILLXYWH(body->xywh,x,y,windowwidth-x,windowheight-y);
625 636
         body->leftsize=leftsize;
626 637
         body->ptrfont=font;
627 638
         body->ptrfontbig=fontbig;
... ...
@@ -653,7 +664,9 @@ im_body_free(body_t *body)
653 664
         }
654 665
         if(body->has_texture) {
655 666
                 UnloadTexture(body->texture);
667
+                body->currenttexture[0]='\0';
656 668
                 body->has_texture=0;
669
+                body->has_failedload=0;
657 670
         }
658 671
         free(body),body=NULL;
659 672
         return;
... ...
@@ -753,59 +766,89 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
753 766
 int
754 767
 im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int windowheight)
755 768
 {
756
-        int i,x,y,k,margin,righty;
769
+        int i,k,margin,righty;
770
+        int lastx,lasty;
757 771
         dirdata_t *dirdata;
758 772
         listingdata_t *elem;
759 773
         Vector2 v2,m2;
760 774
         font_t *font,*fontbig,*fonthuge;
761 775
         int is_leftside;
762 776
         int flag_skiprightside;
777
+        int xoff,yoff;
778
+        thumb_t *thumb;
763 779
         if(body==NULL)
764 780
                 return(-1);
781
+#if 1
782
+#warning TESTING LEFTSCROLL
783
+body->leftscrollpos=(int) mousepos.y;
784
+{
785
+ static int lastlsp=-1;
786
+ if(body->leftscrollpos!=lastlsp) {
787
+  lastlsp=body->leftscrollpos;
788
+  fprintf(stderr,"leftscrollpos:%i\n",body->leftscrollpos);
789
+ }
790
+}
791
+#endif
765 792
         font=body->ptrfont;
766 793
         fontbig=body->ptrfontbig;
767 794
         fonthuge=body->ptrfonthuge;
768
-        FILLWH(body->xywh,windowwidth-body->xywh.x,windowheight-body->xywh.y);
769 795
         FILLXYWH(body->backxywh,0,0,0,0);
796
+        margin=font->height/4;
797
+        /* calculate positions */
798
+        for(i=0;i<body->sizedirdata;i++) {
799
+                if(body->dirdata[i]==NULL)
800
+                        continue;
801
+                if(body->dirdata[i]->listing.has_rightxywh==0) {
802
+                        int sidelen;
803
+                        sidelen=body->dirdata[i]->height-(fontbig->height+fontbig->height/4+font->height+margin*4+fontbig->height/4);
804
+                        listing_fillxywh(&(body->dirdata[i]->listing),body->ptrfont,body->xywh.w-(body->xywh.x+body->leftsize),sidelen,0);
805
+                        body->dirdata[i]->listing.has_rightxywh=1;
806
+                }
807
+                if(i==body->currentdirdata && body->dirdata[i]->listing.has_leftxywh==0) {
808
+                        listing_fillxywh(&(body->dirdata[i]->listing),body->ptrfont,body->leftsize,LEFTIMAGESIDELEN,1);
809
+                        body->dirdata[i]->listing.has_leftxywh=1;
810
+                }
811
+        }
770 812
         /* draw left side background */
771 813
         DrawRectangle(body->xywh.x,body->xywh.y,body->leftsize, body->xywh.h, (Color){ 215, 215, 215, 255 } );
772 814
         /* draw right side background */
773 815
         DrawRectangle(body->xywh.x+body->leftsize,body->xywh.y,body->xywh.w-body->leftsize, body->xywh.h, (Color){ 227, 227, 227, 255 } );
774 816
         /* first pass, draw leftside, second pass, draw all of rightside */
775 817
         for(is_leftside=1,flag_skiprightside=0;is_leftside>=0 && flag_skiprightside==0;is_leftside--) {
776
-                for(i=(is_leftside)?body->currentdirdata:0,y=righty=body->xywh.y;(is_leftside && i==body->currentdirdata) || (!is_leftside && i<body->sizedirdata);i++) {
777
-                        int x0,y0,x1,y1;
818
+                for(i=(is_leftside)?body->currentdirdata:0,righty=body->xywh.y;(is_leftside && i==body->currentdirdata) || (!is_leftside && i<body->sizedirdata);i++) {
778 819
                         int sidelen;
779 820
                         if((dirdata=body->dirdata[i])==NULL)
780 821
                                 continue;
781 822
                         if(is_leftside && !(i==body->currentdirdata))
782 823
                                 continue; /* this element is not in leftside */
783
-                        margin=font->height/4;
784 824
                         sidelen=(is_leftside)?LEFTIMAGESIDELEN:dirdata->height-(fontbig->height+fontbig->height/4+font->height+margin*4+fontbig->height/4);
785 825
                         /* draw left side back arrow if is_leftside and not in root dir */
786 826
                         if(is_leftside && !(dirdata->dirname[0]=='\0' || strcmp(dirdata->dirname,SEP)==0)) {
787 827
                                 m2=MeasureTextEx(fontbig->font,UTF8DOWNARROW,fontbig->height,0);
788 828
                                 v2.x=(float) (body->xywh.x+fontbig->height/2);
789
-                                v2.y=(float) (body->xywh.y+fontbig->height/4+(fontbig->height-v2.x)/2);
829
+                                v2.y=(float) (body->xywh.y+fontbig->height/4+(fontbig->height-v2.x)/2)-body->leftscrollpos;
790 830
                                 FILLXYWH(body->backxywh,v2.x-fontbig->height/4,v2.y-fontbig->height/8,m2.x+fontbig->height/4,m2.x+fontbig->height/4);
791 831
 #if 0
792 832
 DrawTexture(fontbig->font.texture, 0, 0, WHITE); /* font glyphs -- see https://github.com/raysan5/raylib/issues/2022 */
793 833
 DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone */
794 834
 #endif
795
-                                DrawTextPro(fontbig->font,UTF8DOWNARROW,(Vector2){v2.x+m2.x,v2.y},(Vector2){0,0},90.0,fontbig->height,0,(Color){65,65,65,255});
835
+                                if((v2.y+fontbig->height)>=0)
836
+                                        DrawTextPro(fontbig->font,UTF8DOWNARROW,(Vector2){v2.x+m2.x,v2.y},(Vector2){0,0},90.0,fontbig->height,0,(Color){65,65,65,255});
796 837
                         }
797 838
                         if(is_leftside) {
798 839
                                 /* ...dirname */
799
-                                m2=MeasureTextEx(fontbig->font,dirdata->dirname,fontbig->height,0);
800
-                                v2.x=(float) (body->xywh.x+fontbig->height/2)+(body->leftsize-(body->xywh.x+fontbig->height)-m2.x)/2;
801
-                                v2.y=(float) (body->xywh.y+fontbig->height/4);
802
-                                DrawTextEx(fontbig->font
803
-                                  ,dirdata->dirname
804
-                                  ,v2
805
-                                  ,fontbig->height
806
-                                  ,0
807
-                                  ,(Color){ 65, 65, 65, 255 }
808
-                                );
840
+                                v2.y=(float) (body->xywh.y+fontbig->height/4-body->leftscrollpos);
841
+                                if((v2.y+fontbig->height)>=0) {
842
+                                        m2=MeasureTextEx(fontbig->font,dirdata->dirname,fontbig->height,0);
843
+                                        v2.x=(float) (body->xywh.x+fontbig->height/2)+(body->leftsize-(body->xywh.x+fontbig->height)-m2.x)/2;
844
+                                        DrawTextEx(fontbig->font
845
+                                          ,dirdata->dirname
846
+                                          ,v2
847
+                                          ,fontbig->height
848
+                                          ,0
849
+                                          ,(Color){ 65, 65, 65, 255 }
850
+                                        );
851
+                                }
809 852
                         } else { /* rightside */
810 853
                                 /* ...bg */
811 854
                                 DrawRectangle(body->xywh.x+body->leftsize,righty,body->xywh.w-body->leftsize, dirdata->height,(i==body->currentdirdata)?((Color){ 168, 168, 168, 255 }):((Color){ 227, 227, 227, 255 }));
... ...
@@ -821,166 +864,160 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
821 864
                                 );
822 865
                         }
823 866
                         /* directories */
824
-                        if(is_leftside) {
825
-                                x0=body->xywh.x+font->height/2;
826
-                                x1=body->xywh.x+body->leftsize-DEFAULTDIRDATATRIANGLEW-font->height/2;
827
-                                y0=body->xywh.y+font->height/4+m2.y+font->height/2;
828
-                                y1=body->xywh.y+body->xywh.h-DEFAULTDIRDATATRIANGLEW-font->height/2;
829
-                        } else {
830
-                                x0=body->xywh.x+body->leftsize+fontbig->height/2;
831
-                                x1=body->xywh.x+body->xywh.w-font->height/2;
832
-                                y0=righty+fontbig->height/4+fontbig->height+margin;
833
-                                y1=y0+margin*2+font->height-1;
834
-                        }
835
-                        for(k=0,x=x0,y=y0;k<dirdata->listing.usedelems;k++) {
836
-                                Color c=(is_leftside)?((Color){ 65, 65, 65, 255 }):((Color){ 240, 240, 240, 255 });
867
+                        xoff=((is_leftside)?0:body->leftsize);
868
+                        yoff=((is_leftside)?body->xywh.y:righty)+fontbig->height/4+fontbig->height+font->height/4-(is_leftside?body->leftscrollpos:0);
869
+                        if(is_leftside && dirdata->dirname[0]=='\0')
870
+                                yoff-=fontbig->height/4+fontbig->height;
871
+                        for(k=0,lastx=lasty=0;k<dirdata->listing.usedelems;k++) {
837 872
                                 elem=dirdata->listing.elems+k;
838
-                                if(elem->name[0]!='d' || strcmp(elem->name,"d.")==0 || strcmp(elem->name,"d..")==0)
839
-                                        continue;
840
-                                if(y>y1)
873
+                                thumb=(is_leftside)?&(elem->left):&(elem->right);
874
+                                if(elem->name[0]!='d' || strcmp(elem->name,"d.")==0 || strcmp(elem->name,"d..")==0) {
875
+                                        if(elem->name[0]=='d')
876
+                                                FILLXYWH(thumb->screenxywh,0,0,0,0);
841 877
                                         continue;
842
-                                m2=MeasureTextEx(font->font,elem->name+1,font->height,0);
843
-                                if((x+margin*2+m2.x)>x1) {
844
-                                        if(!is_leftside) {
845
-                                                DrawTextEx(fonthuge->font
846
-                                                  ,"..."
847
-                                                  ,(Vector2) {x+margin,y+(fontbig->height-fonthuge->height)}
848
-                                                  ,fonthuge->height
849
-                                                  ,0
850
-                                                  ,c
851
-                                                );
852
-                                         }
853
-                                        x=x0,y+=font->height+margin*2+font->height/4;
854
-                                        if(y>y1)
855
-                                                continue;
856 878
                                 }
857
-                                if(is_leftside) {
858
-                                        FILLXYWH(elem->left.xywh,x,y,margin*2+m2.x,margin*2+font->height);
859
-                                        DrawRectangleLines(UNROLLXYWH(elem->left.xywh),c);
860
-                                } else {
861
-                                        FILLXYWH(elem->right.xywh,x,y,margin*2+m2.x,margin*2+font->height);
862
-                                        DrawRectangleLines(UNROLLXYWH(elem->right.xywh),c);
879
+                                if((thumb->xywh.y+yoff)>(body->xywh.y+body->xywh.h) || thumb->xywh.w==0 || thumb->xywh.h==0) {
880
+#warning TODO: if !is_leftside, draw "..." in huge font using lastx,lasty as reference
881
+                                        break;
882
+                                }
883
+                                if((thumb->xywh.y+yoff+thumb->xywh.h)<0) {
884
+                                        FILLXYWH(thumb->screenxywh,0,0,0,0);
885
+                                        continue;
863 886
                                 }
864
-                                DrawTextEx(font->font,elem->name+1,(Vector2){x+margin,y+margin},font->height,0,c);
865
-                                x+=margin*2+m2.x+font->height/4;
887
+                                FILLXYWH(thumb->screenxywh,thumb->xywh.x+xoff,thumb->xywh.y+yoff,thumb->xywh.w,thumb->xywh.h);
888
+                                DrawRectangleLines(UNROLLXYWH(thumb->screenxywh),((Color){ 65, 65, 65, 255 }));
889
+                                DrawTextEx(font->font,elem->name+1,(Vector2){thumb->screenxywh.x+margin,thumb->screenxywh.y+margin},font->height,0,((Color){ 65, 65, 65, 255 }));
890
+                                lastx=thumb->screenxywh.x+thumb->screenxywh.w,lasty=thumb->screenxywh.y+thumb->screenxywh.h;
866 891
                         }
867
-                        /* files */
868
-                        if(is_leftside) {
869
-                                y0=(x==x0)?y:y+font->height+margin*2+font->height/4;
870
-                                sidelen=LEFTIMAGESIDELEN;
871
-                        } else {
872
-                                y0=righty+dirdata->height-sidelen-margin-fontbig->height/4;
873
-                                y1=y0+sidelen+margin;
874
-                                x0-=margin;
892
+                        for(;k<dirdata->listing.usedelems;k++) {
893
+                                elem=dirdata->listing.elems+k;
894
+                                if(elem->name[0]!='d')
895
+                                        continue;
896
+                                thumb=(is_leftside)?&(elem->left):&(elem->right);
897
+                                FILLXYWH(thumb->screenxywh,0,0,0,0);
875 898
                         }
876
-                        for(k=0,x=x0,y=y0;k<dirdata->listing.usedelems;k++) {
899
+                        /* files */
900
+                        for(k=0,lastx=lasty=0;k<dirdata->listing.usedelems;k++) {
901
+                                Texture2D *te;
902
+                                xywh_t *xywh;
877 903
                                 elem=dirdata->listing.elems+k;
904
+                                thumb=(is_leftside)?&(elem->left):&(elem->right);
905
+                                xywh=&(thumb->xywh);
906
+                                te=&(thumb->texture);
907
+                                int has_imagedrawn;
878 908
                                 if(elem->name[0]!='f' && elem->name[0]!='l')
879 909
                                         continue;
880
-                                if(y>y1)
881
-                                        continue;
882
-                                if((x+margin*2+sidelen)>x1) {
883
-                                        if(!is_leftside) {
884
-                                                DrawTextEx(fonthuge->font
885
-                                                  ,"..."
886
-                                                  ,(Vector2) {x+margin,y+(sidelen-fonthuge->height)}
887
-                                                  ,fonthuge->height
888
-                                                  ,0
889
-                                                  ,(Color){ 0,0,0,64 }
890
-                                                );
891
-                                         }
892
-                                        x=x0,y+=sidelen+margin*2;
893
-                                        if(y>y1)
894
-                                                continue;
910
+                                if((xywh->y+yoff)>(body->xywh.y+body->xywh.h) || xywh->w==0 || xywh->h==0) {
911
+#warning TODO: if !is_leftside, draw "..." in huge font using lastx,lasty as reference
912
+                                        break;
895 913
                                 }
896
-                                if(is_leftside) {
897
-                                        FILLXYWH(elem->left.xywh,x+margin,y+margin,sidelen,sidelen);
898
-                                        DrawRectangle(UNROLLXYWH(elem->left.xywh),((Color){0,0,0,64}));
899
-                                } else {
900
-                                        FILLXYWH(elem->right.xywh,x+margin,y+margin,sidelen,sidelen);
901
-                                        DrawRectangle(UNROLLXYWH(elem->right.xywh),((Color){0,0,0,64}));
914
+                                /* show image */
915
+                                has_imagedrawn=0;
916
+#if 1
917
+                                if(is_imagefilename(elem->name+1)) {
918
+                                        if(thumb->has_texture==0) {
919
+                                                Image im;
920
+                                                char fullpath[2048];
921
+                                                snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
922
+                                                fullpath[sizeof(fullpath)-1]='\0';
923
+                                                im=LoadImage(fullpath);
924
+                                                if(IsImageValid(im)) {
925
+#if 1
926
+fprintf(stderr,"Loaded %s\n",fullpath);
927
+#endif
928
+                                                        ImageResize(&im,sidelen,sidelen);
929
+                                                        *te=LoadTextureFromImage(im);
930
+                                                        UnloadImage(im);
931
+                                                        thumb->has_texture=1;
932
+                                                }
933
+                                        }
934
+                                        if(thumb->has_texture!=0) {
935
+                                                FILLXYWH(thumb->screenxywh,xywh->x+xoff,xywh->y+yoff,xywh->w,xywh->h);
936
+                                                DrawTexture(*te,thumb->screenxywh.x,thumb->screenxywh.y,WHITE);
937
+                                                has_imagedrawn=1;
938
+                                                lastx=xywh->x+xywh->w,lasty=xywh->y+xywh->h+yoff;
939
+                                                if(is_leftside && lmbdown==0 && is_imutil_insidexywh(mousepos,&(thumb->screenxywh))) {
940
+                                                        /* draw image in rightside */
941
+                                                        char path[2048];
942
+                                                        int maxw,maxh;
943
+                                                        snprintf(path,sizeof(path),"%s/%s",dirdata->dirname,elem->name+1);
944
+                                                        path[sizeof(path)-1]='\0';
945
+                                                        maxw=windowwidth-(body->leftsize-DEFAULTDIRDATATRIANGLEW);
946
+                                                        maxh=windowheight-body->xywh.y;
947
+                                                        if((body->has_texture==0 && !(body->has_failedload && strcmp(body->currenttexture,path)==0))
948
+                                                          || strcmp(body->currenttexture,path)!=0
949
+                                                        ) {
950
+                                                                Image im;
951
+                                                                int neww,newh;
952
+                                                                char fullpath[2048];
953
+                                                                if(body->has_texture) {
954
+                                                                        UnloadTexture(body->texture);
955
+                                                                        body->currenttexture[0]='\0';
956
+                                                                        body->has_texture=0;
957
+                                                                        body->has_failedload=0;
958
+                                                                }
959
+                                                                snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
960
+                                                                fullpath[sizeof(fullpath)-1]='\0';
961
+                                                                im=LoadImage(fullpath);
962
+                                                                if(IsImageValid(im)) {
963
+                                                                        im_util_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
964
+                                                                        ImageResize(&im,neww,newh);
965
+                                                                        body->texture=LoadTextureFromImage(im);
966
+                                                                        UnloadImage(im);
967
+                                                                        strncpy(body->currenttexture,fullpath,sizeof(body->currenttexture));
968
+                                                                        body->currenttexture[sizeof(body->currenttexture)-1]='\0';
969
+                                                                        body->has_texture=1;
970
+                                                                        body->has_failedload=0;
971
+                                                                        body->texturew=neww;
972
+                                                                        body->textureh=newh;
973
+                                                                } else {
974
+                                                                        strncpy(body->currenttexture,fullpath,sizeof(body->currenttexture));
975
+                                                                        body->currenttexture[sizeof(body->currenttexture)-1]='\0';
976
+                                                                        body->has_texture=0;
977
+                                                                        body->has_failedload=1;
978
+                                                                }
979
+                                                        }
980
+                                                        if(body->has_texture) {
981
+                                                                int x0,y0;
982
+                                                                x0=body->leftsize-DEFAULTDIRDATATRIANGLEW;
983
+                                                                y0=body->xywh.y;
984
+                                                                DrawRectangle(x0,y0,maxw,maxh,(Color){ 215, 215, 215, 255 } );
985
+                                                                DrawTexture(body->texture,x0+(maxw-body->texturew)/2,y0+(maxh-body->textureh)/2,WHITE);
986
+                                                                flag_skiprightside=1;
987
+                                                        }
988
+                                                }
989
+                                        }
902 990
                                 }
903
-                                {
991
+#endif
992
+                                if(has_imagedrawn==0) {
904 993
                                         char *ptr;
905 994
                                         char shortname[1024];
906 995
                                         xywh_t *pos;
907 996
                                         int l;
908
-                                        Texture2D *te;
909
-                                        int *has_texture;
910 997
                                         font_t *myfont=(is_leftside)?fonthuge:font;
911 998
                                         pos=is_leftside?&(elem->left.xywh):&(elem->right.xywh);
912
-                                        te=is_leftside?&(elem->left.texture):&(elem->right.texture);
913
-                                        has_texture=is_leftside?&(elem->left.has_texture):&(elem->right.has_texture);
999
+                                        FILLXYWH(thumb->screenxywh,xywh->x+xoff,xywh->y+yoff,xywh->w,xywh->h);
1000
+                                        DrawRectangle(UNROLLXYWH(thumb->screenxywh),((Color){0,0,0,64}));
914 1001
                                         if((ptr=strchr(elem->name+1,'.'))!=NULL) {
915 1002
                                                 m2=MeasureTextEx(myfont->font,ptr,myfont->height,0);
916
-                                                DrawTextEx(myfont->font,ptr,(Vector2){x+margin+(sidelen-m2.x)/2,y+(font->height)/2+margin+(sidelen-myfont->height)/2},myfont->height,0,(Color){ 0,0,0,96 });
1003
+                                                DrawTextEx(myfont->font,ptr,(Vector2){xywh->x+xoff+(sidelen-m2.x)/2,xywh->y+yoff+(font->height)/2+(xywh->w-myfont->height)/2},myfont->height,0,(Color){ 0,0,0,96 });
917 1004
                                         }
918 1005
                                         ptr=(ptr==NULL)?elem->name+1:ptr;
919 1006
                                         l=(ptr-(elem->name+1));
920 1007
                                         l=(l>=sizeof(shortname))?sizeof(shortname)-1:l;
921 1008
                                         memcpy(shortname,elem->name+1,l);
922 1009
                                         shortname[l]='\0';
923
-                                        DrawRectangle(pos->x,pos->y,pos->w,font->height+font->height/2,((Color){0,0,0,64}));
924
-                                        DrawTextEx(font->font,shortname,(Vector2){pos->x+font->height/4,pos->y+font->height/4},font->height,0,(Color){ 192,192,192,255 });
925
-                                        /* show image */
926
-                                        if(is_imagefilename(elem->name+1)) {
927
-                                                if(*has_texture==0) {
928
-                                                        Image im;
929
-                                                        char fullpath[2048];
930
-                                                        snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
931
-                                                        fullpath[sizeof(fullpath)-1]='\0';
932
-                                                        im=LoadImage(fullpath);
933
-                                                        if(IsImageValid(im)) {
934
-                                                                ImageResize(&im,sidelen,sidelen);
935
-                                                                *te=LoadTextureFromImage(im);
936
-                                                                UnloadImage(im);
937
-                                                                *has_texture=1;
938
-                                                        }
939
-                                                }
940
-                                                if(*has_texture!=0) {
941
-                                                        DrawTexture(*te,pos->x,pos->y,WHITE);
942
-                                                        if(is_leftside && lmbdown==0 && is_imutil_insidexywh(mousepos,pos)) {
943
-                                                                /* draw image in rightside */
944
-                                                                char path[2048];
945
-                                                                int maxw,maxh;
946
-                                                                snprintf(path,sizeof(path),"%s/%s",dirdata->dirname,elem->name+1);
947
-                                                                path[sizeof(path)-1]='\0';
948
-                                                                maxw=windowwidth-(body->leftsize-DEFAULTDIRDATATRIANGLEW);
949
-                                                                maxh=windowheight-body->xywh.y;
950
-                                                                if(body->has_texture==0 || strcmp(body->currenttexture,path)!=0) {
951
-                                                                        Image im;
952
-                                                                        int neww,newh;
953
-                                                                        char fullpath[2048];
954
-                                                                        if(body->has_texture) {
955
-                                                                                UnloadTexture(body->texture);
956
-                                                                                body->has_texture=0;
957
-                                                                        }
958
-                                                                        snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
959
-                                                                        fullpath[sizeof(fullpath)-1]='\0';
960
-                                                                        im=LoadImage(fullpath);
961
-                                                                        if(IsImageValid(im)) {
962
-                                                                                im_util_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
963
-                                                                                ImageResize(&im,neww,newh);
964
-                                                                                body->texture=LoadTextureFromImage(im);
965
-                                                                                UnloadImage(im);
966
-                                                                                body->has_texture=1;
967
-                                                                                body->texturew=neww;
968
-                                                                                body->textureh=newh;
969
-                                                                        }
970
-                                                                }
971
-                                                                if(body->has_texture) {
972
-                                                                        int x0,y0;
973
-                                                                        x0=body->leftsize-DEFAULTDIRDATATRIANGLEW;
974
-                                                                        y0=body->xywh.y;
975
-                                                                        DrawRectangle(x0,y0,maxw,maxh,(Color){ 215, 215, 215, 255 } );
976
-                                                                        DrawTexture(body->texture,x0+(maxw-body->texturew)/2,y0+(maxh-body->textureh)/2,WHITE);
977
-                                                                        flag_skiprightside=1;
978
-                                                                }
979
-                                                        }
980
-                                                }
981
-                                        }
1010
+                                        DrawRectangle(pos->x+xoff,pos->y+yoff,pos->w,font->height+font->height/2,((Color){0,0,0,64}));
1011
+                                        DrawTextEx(font->font,shortname,(Vector2){pos->x+xoff+font->height/4,pos->y+yoff+font->height/4},font->height,0,(Color){ 192,192,192,255 });
1012
+                                        lastx=xywh->x+xoff+xywh->w,lasty=xywh->y+yoff+xywh->h;
982 1013
                                 }
983
-                                x+=margin*2+sidelen;
1014
+                        }
1015
+                        for(;k<dirdata->listing.usedelems;k++) {
1016
+                                elem=dirdata->listing.elems+k;
1017
+                                if(elem->name[0]!='f' && elem->name[0]!='l')
1018
+                                        continue;
1019
+                                thumb=(is_leftside)?&(elem->left):&(elem->right);
1020
+                                FILLXYWH(thumb->screenxywh,0,0,0,0);
984 1021
                         }
985 1022
                         /* ...finishing touchs */
986 1023
                         if(is_leftside) {
... ...
@@ -1182,15 +1219,18 @@ listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort
1182 1219
                 if(ld->left.has_texture) {
1183 1220
                         UnloadTexture(ld->left.texture);
1184 1221
                         ld->left.has_texture=0;
1222
+                        ld->left.has_failedload=0;
1185 1223
                 }
1186 1224
                 if(ld->right.has_texture) {
1187 1225
                         UnloadTexture(ld->right.texture);
1188 1226
                         ld->right.has_texture=0;
1227
+                        ld->right.has_failedload=0;
1189 1228
                 }
1190 1229
         }
1191 1230
         /* reset struct */
1192 1231
         listing->usedelems=listing->usedbuf=0;
1193 1232
         memset(listing->elems,0,sizeof(listingdata_t)*listing->sizeelems);
1233
+        listing->has_leftxywh=listing->has_rightxywh=0;
1194 1234
         /* fill listing */
1195 1235
         if(pathprefix==NULL && parampath==NULL)
1196 1236
                 return(-1); /* nothing to fill */
... ...
@@ -1289,10 +1329,12 @@ listing_freedata(listing_t *listing)
1289 1329
                         if(ld->left.has_texture) {
1290 1330
                                 UnloadTexture(ld->left.texture);
1291 1331
                                 ld->left.has_texture=0;
1332
+                                ld->left.has_failedload=0;
1292 1333
                         }
1293 1334
                         if(ld->right.has_texture) {
1294 1335
                                 UnloadTexture(ld->right.texture);
1295 1336
                                 ld->right.has_texture=0;
1337
+                                ld->right.has_failedload=0;
1296 1338
                         }
1297 1339
                 }
1298 1340
                 free(listing->elems),listing->elems=NULL,listing->sizeelems=listing->usedelems=0;
... ...
@@ -1302,6 +1344,70 @@ listing_freedata(listing_t *listing)
1302 1344
         return;
1303 1345
 }
1304 1346
 
1347
+int
1348
+listing_fillxywh(listing_t *listing, font_t *font, int w, int sidelen, int is_leftside)
1349
+{
1350
+        int x0,y0,x1;
1351
+        int k,x,y;
1352
+        Vector2 m2;
1353
+        int margin;
1354
+        listingdata_t *elem;
1355
+        thumb_t *thumb;
1356
+        if(listing==NULL || font==NULL)
1357
+                return(-1); /* sanity check failed */
1358
+        margin=font->height/4;
1359
+        /* directories */
1360
+        if(is_leftside) {
1361
+                x0=font->height/2;
1362
+                x1=w-DEFAULTDIRDATATRIANGLEW-font->height/2;
1363
+                y0=0;
1364
+        } else {
1365
+                x0=FONTBIGSIZE/2;
1366
+                x1=w-font->height/2;
1367
+                y0=0;
1368
+        }
1369
+        for(k=0,x=x0,y=y0;k<listing->usedelems;k++) {
1370
+                elem=listing->elems+k;
1371
+                thumb=(is_leftside)?&(elem->left):&(elem->right);
1372
+                if(elem->name[0]!='d' || strcmp(elem->name,"d.")==0 || strcmp(elem->name,"d..")==0)
1373
+                        continue;
1374
+                m2=MeasureTextEx(font->font,elem->name+1,font->height,0);
1375
+                if((x+margin*2+m2.x)>x1 && !(is_leftside==0 && y>y0))
1376
+                        x=x0,y+=font->height+margin*2+font->height/4;
1377
+                if(is_leftside==0 && y>y0) {
1378
+                        FILLXYWH(thumb->xywh,0,0,0,0);
1379
+                        continue;
1380
+                }
1381
+                FILLXYWH(thumb->xywh,x,y,margin*2+m2.x,margin*2+font->height);
1382
+                x+=margin*2+m2.x+font->height/4;
1383
+        }
1384
+        y+=((x==x0)?0:font->height+margin*2+font->height/4);
1385
+        /* files */
1386
+        if(is_leftside)
1387
+                y0=y;
1388
+        else
1389
+                y0+=margin*2+font->height+margin;
1390
+        for(k=0,x=x0,y=y0;k<listing->usedelems;k++) {
1391
+                elem=listing->elems+k;
1392
+                thumb=(is_leftside)?&(elem->left):&(elem->right);
1393
+                if(elem->name[0]!='f' && elem->name[0]!='l')
1394
+                        continue;
1395
+                if(!is_leftside && y>y0) {
1396
+                        FILLXYWH(thumb->xywh,0,0,0,0);
1397
+                        continue;
1398
+                }
1399
+                if((x+margin*2+sidelen)>x1 && !(is_leftside==0 && y>y0))
1400
+                        x=x0,y+=sidelen+margin*2;
1401
+                if(is_leftside==0 && y>y0) {
1402
+                        FILLXYWH(thumb->xywh,0,0,0,0);
1403
+                        continue;
1404
+                }
1405
+                FILLXYWH(thumb->xywh,x,y,sidelen,sidelen);
1406
+                x+=margin*2+sidelen;
1407
+        }
1408
+        return(0);
1409
+}
1410
+
1305 1411
 int
1306 1412
 is_imagefilename(char *filename)
1307 1413
 {
Browse code

Preserve aspect ratio of big image

Dario Rodriguez authored on 02/03/2025 11:17:15
Showing 1 changed files
... ...
@@ -17,6 +17,7 @@
17 17
  *      20250301 Aesthetic fixes for leftside.
18 18
  *               Basic image loading.
19 19
  *               Show big image on hover.
20
+ *               Preserve aspect ratio of big image.
20 21
  *
21 22
  * Author: Dario Rodriguez dario@darionomono.com
22 23
  * (c) Dario Rodriguez 2025
... ...
@@ -118,13 +119,15 @@ typedef struct menubar_t {
118 119
         font_t *ptrfont;
119 120
 } menubar_t;
120 121
 
121
-typedef struct listingdata_t {
122
-        xywh_t leftxywh;
123
-        Texture2D lefttexture;
124
-        int has_lefttexture;
122
+typedef struct thumb_t {
125 123
         xywh_t xywh;
126 124
         Texture2D texture;
127 125
         int has_texture;
126
+} thumb_t;
127
+
128
+typedef struct listingdata_t {
129
+        thumb_t left;
130
+        thumb_t right;
128 131
         char *name; /* first byte in the name is the type, next is the name, i.e. a directory is "dhome" and a file is "f.bashrc" (this is done for easier sorting) */
129 132
 } listingdata_t;
130 133
 
... ...
@@ -158,6 +161,8 @@ typedef struct body_t {
158 161
         font_t *ptrfonthuge;
159 162
         char currenttexture[1024];
160 163
         Texture2D texture;
164
+        int texturew;
165
+        int textureh;
161 166
         int has_texture;
162 167
 } body_t;
163 168
 
... ...
@@ -191,7 +196,7 @@ void im_body_free(body_t *body);
191 196
 int im_body_add(body_t *body,char *dir);
192 197
 
193 198
 int im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
194
-int im_body_draw(body_t *body, Vector2 mousepos, int windowwidth, int windowheight);
199
+int im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int windowheight);
195 200
 
196 201
 int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort);
197 202
 void listing_freedata(listing_t *listing);
... ...
@@ -202,6 +207,7 @@ int imutil_submenu_count(char *menus);
202 207
 char *imutil_submenu_get(char *menus, int targetn, int *len);
203 208
 char *imutil_strduplen(char *str, int len);
204 209
 int is_imutil_insidexywh(Vector2 pos, xywh_t *xywh);
210
+int im_util_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh);
205 211
 int menudata_pos2option(menudata_t *menudata, Vector2 pos);
206 212
 int *getcodepoints(int *sizecodepoints);
207 213
 int is_imagefilename(char *filename);
... ...
@@ -242,7 +248,7 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
242 248
                 /* draw screen contents */
243 249
                 BeginDrawing();
244 250
                 ClearBackground(RAYWHITE);
245
-                im_body_draw(im->body,mousepos,im->w,im->h);
251
+                im_body_draw(im->body,mousepos,lmbdown,im->w,im->h);
246 252
                 im_menubar_draw(im->menubar,im->w,im->h);
247 253
 #if 0
248 254
 {
... ...
@@ -717,7 +723,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
717 723
                 ld=dirdata->listing.elems+i;
718 724
                 if(ld->name[0]!='d')
719 725
                         continue;
720
-                if(is_imutil_insidexywh(mousepos,&(ld->leftxywh))) {
726
+                if(is_imutil_insidexywh(mousepos,&(ld->left.xywh))) {
721 727
                         char *newname,*oldprefix;
722 728
                         int l,l0,l1;
723 729
                         static char sep[]={SEP};
... ...
@@ -745,7 +751,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
745 751
 }
746 752
 
747 753
 int
748
-im_body_draw(body_t *body, Vector2 mousepos, int windowwidth, int windowheight)
754
+im_body_draw(body_t *body, Vector2 mousepos, int lmbdown, int windowwidth, int windowheight)
749 755
 {
750 756
         int i,x,y,k,margin,righty;
751 757
         dirdata_t *dirdata;
... ...
@@ -849,11 +855,11 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
849 855
                                                 continue;
850 856
                                 }
851 857
                                 if(is_leftside) {
852
-                                        FILLXYWH(elem->leftxywh,x,y,margin*2+m2.x,margin*2+font->height);
853
-                                        DrawRectangleLines(UNROLLXYWH(elem->leftxywh),c);
858
+                                        FILLXYWH(elem->left.xywh,x,y,margin*2+m2.x,margin*2+font->height);
859
+                                        DrawRectangleLines(UNROLLXYWH(elem->left.xywh),c);
854 860
                                 } else {
855
-                                        FILLXYWH(elem->xywh,x,y,margin*2+m2.x,margin*2+font->height);
856
-                                        DrawRectangleLines(UNROLLXYWH(elem->xywh),c);
861
+                                        FILLXYWH(elem->right.xywh,x,y,margin*2+m2.x,margin*2+font->height);
862
+                                        DrawRectangleLines(UNROLLXYWH(elem->right.xywh),c);
857 863
                                 }
858 864
                                 DrawTextEx(font->font,elem->name+1,(Vector2){x+margin,y+margin},font->height,0,c);
859 865
                                 x+=margin*2+m2.x+font->height/4;
... ...
@@ -888,11 +894,11 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
888 894
                                                 continue;
889 895
                                 }
890 896
                                 if(is_leftside) {
891
-                                        FILLXYWH(elem->leftxywh,x+margin,y+margin,sidelen,sidelen);
892
-                                        DrawRectangle(UNROLLXYWH(elem->leftxywh),((Color){0,0,0,64}));
897
+                                        FILLXYWH(elem->left.xywh,x+margin,y+margin,sidelen,sidelen);
898
+                                        DrawRectangle(UNROLLXYWH(elem->left.xywh),((Color){0,0,0,64}));
893 899
                                 } else {
894
-                                        FILLXYWH(elem->xywh,x+margin,y+margin,sidelen,sidelen);
895
-                                        DrawRectangle(UNROLLXYWH(elem->xywh),((Color){0,0,0,64}));
900
+                                        FILLXYWH(elem->right.xywh,x+margin,y+margin,sidelen,sidelen);
901
+                                        DrawRectangle(UNROLLXYWH(elem->right.xywh),((Color){0,0,0,64}));
896 902
                                 }
897 903
                                 {
898 904
                                         char *ptr;
... ...
@@ -902,9 +908,9 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
902 908
                                         Texture2D *te;
903 909
                                         int *has_texture;
904 910
                                         font_t *myfont=(is_leftside)?fonthuge:font;
905
-                                        pos=is_leftside?&(elem->leftxywh):&(elem->xywh);
906
-                                        te=is_leftside?&(elem->lefttexture):&(elem->texture);
907
-                                        has_texture=is_leftside?&(elem->has_lefttexture):&(elem->has_texture);
911
+                                        pos=is_leftside?&(elem->left.xywh):&(elem->right.xywh);
912
+                                        te=is_leftside?&(elem->left.texture):&(elem->right.texture);
913
+                                        has_texture=is_leftside?&(elem->left.has_texture):&(elem->right.has_texture);
908 914
                                         if((ptr=strchr(elem->name+1,'.'))!=NULL) {
909 915
                                                 m2=MeasureTextEx(myfont->font,ptr,myfont->height,0);
910 916
                                                 DrawTextEx(myfont->font,ptr,(Vector2){x+margin+(sidelen-m2.x)/2,y+(font->height)/2+margin+(sidelen-myfont->height)/2},myfont->height,0,(Color){ 0,0,0,96 });
... ...
@@ -933,13 +939,17 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
933 939
                                                 }
934 940
                                                 if(*has_texture!=0) {
935 941
                                                         DrawTexture(*te,pos->x,pos->y,WHITE);
936
-                                                        if(is_leftside && is_imutil_insidexywh(mousepos,pos)) {
942
+                                                        if(is_leftside && lmbdown==0 && is_imutil_insidexywh(mousepos,pos)) {
937 943
                                                                 /* draw image in rightside */
938 944
                                                                 char path[2048];
945
+                                                                int maxw,maxh;
939 946
                                                                 snprintf(path,sizeof(path),"%s/%s",dirdata->dirname,elem->name+1);
940 947
                                                                 path[sizeof(path)-1]='\0';
948
+                                                                maxw=windowwidth-(body->leftsize-DEFAULTDIRDATATRIANGLEW);
949
+                                                                maxh=windowheight-body->xywh.y;
941 950
                                                                 if(body->has_texture==0 || strcmp(body->currenttexture,path)!=0) {
942 951
                                                                         Image im;
952
+                                                                        int neww,newh;
943 953
                                                                         char fullpath[2048];
944 954
                                                                         if(body->has_texture) {
945 955
                                                                                 UnloadTexture(body->texture);
... ...
@@ -949,15 +959,22 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
949 959
                                                                         fullpath[sizeof(fullpath)-1]='\0';
950 960
                                                                         im=LoadImage(fullpath);
951 961
                                                                         if(IsImageValid(im)) {
952
-                                                                                ImageResize(&im,windowwidth-body->leftsize,windowheight-body->xywh.y);
962
+                                                                                im_util_aspectmaximize(im.width,im.height,maxw,maxh,&neww,&newh);
963
+                                                                                ImageResize(&im,neww,newh);
953 964
                                                                                 body->texture=LoadTextureFromImage(im);
954 965
                                                                                 UnloadImage(im);
955 966
                                                                                 body->has_texture=1;
967
+                                                                                body->texturew=neww;
968
+                                                                                body->textureh=newh;
956 969
                                                                         }
957 970
                                                                 }
958 971
                                                                 if(body->has_texture) {
959
-                                                                       DrawTexture(body->texture,body->leftsize,body->xywh.y,WHITE);
960
-                                                                       flag_skiprightside=1;
972
+                                                                        int x0,y0;
973
+                                                                        x0=body->leftsize-DEFAULTDIRDATATRIANGLEW;
974
+                                                                        y0=body->xywh.y;
975
+                                                                        DrawRectangle(x0,y0,maxw,maxh,(Color){ 215, 215, 215, 255 } );
976
+                                                                        DrawTexture(body->texture,x0+(maxw-body->texturew)/2,y0+(maxh-body->textureh)/2,WHITE);
977
+                                                                        flag_skiprightside=1;
961 978
                                                                 }
962 979
                                                         }
963 980
                                                 }
... ...
@@ -967,9 +984,12 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
967 984
                         }
968 985
                         /* ...finishing touchs */
969 986
                         if(is_leftside) {
970
-                                /* draw right side "current" marker inside left side area */
971
-                                DrawTriangle((Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)}, (Vector2){((float)body->xywh.x)+body->leftsize-DEFAULTDIRDATATRIANGLEW,((float)righty)+dirdata->height/2}, (Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)+dirdata->height-1}, (Color){ 168, 168, 168, 255 } );
987
+                                ;
972 988
                         } else {
989
+                                if(i==body->currentdirdata) {
990
+                                        /* draw right side "current" marker inside left side area */
991
+                                        DrawTriangle((Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)}, (Vector2){((float)body->xywh.x)+body->leftsize-DEFAULTDIRDATATRIANGLEW,((float)righty)+dirdata->height/2}, (Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)+dirdata->height-1}, (Color){ 168, 168, 168, 255 } );
992
+                                }
973 993
                                 /* advance to next element */
974 994
                                 righty+=dirdata->height;
975 995
                         }
... ...
@@ -1092,6 +1112,22 @@ is_imutil_insidexywh(Vector2 pos, xywh_t *xywh)
1092 1112
         return(0);
1093 1113
 }
1094 1114
 
1115
+int
1116
+im_util_aspectmaximize(int w, int h, int maxw, int maxh, int *neww, int *newh)
1117
+{
1118
+        if(neww==NULL || newh==NULL || w==0 || h==0 || maxw==0 || maxh==0)
1119
+                return(-1);
1120
+        if((w/h)>(maxw/maxh)) {
1121
+                *neww=maxw;
1122
+                *newh=h*maxw/w;
1123
+        } else { /* (w/h)<=(maxw/maxh) */
1124
+                *newh=maxh;
1125
+                *neww=w*maxh/h;
1126
+        }
1127
+        return(0);
1128
+}
1129
+
1130
+
1095 1131
 int
1096 1132
 menudata_pos2option(menudata_t *menudata, Vector2 pos)
1097 1133
 {
... ...
@@ -1143,13 +1179,13 @@ listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort
1143 1179
         /* free old textures */
1144 1180
         for(i=0;i<listing->usedelems;i++) {
1145 1181
                 ld=listing->elems+i;
1146
-                if(ld->has_lefttexture) {
1147
-                        UnloadTexture(ld->lefttexture);
1148
-                        ld->has_lefttexture=0;
1182
+                if(ld->left.has_texture) {
1183
+                        UnloadTexture(ld->left.texture);
1184
+                        ld->left.has_texture=0;
1149 1185
                 }
1150
-                if(ld->has_texture) {
1151
-                        UnloadTexture(ld->texture);
1152
-                        ld->has_texture=0;
1186
+                if(ld->right.has_texture) {
1187
+                        UnloadTexture(ld->right.texture);
1188
+                        ld->right.has_texture=0;
1153 1189
                 }
1154 1190
         }
1155 1191
         /* reset struct */
... ...
@@ -1250,13 +1286,13 @@ listing_freedata(listing_t *listing)
1250 1286
                 listingdata_t *ld;
1251 1287
                 for(i=0;i<listing->usedelems;i++) {
1252 1288
                         ld=listing->elems+i;
1253
-                        if(ld->has_lefttexture) {
1254
-                                UnloadTexture(ld->lefttexture);
1255
-                                ld->has_lefttexture=0;
1289
+                        if(ld->left.has_texture) {
1290
+                                UnloadTexture(ld->left.texture);
1291
+                                ld->left.has_texture=0;
1256 1292
                         }
1257
-                        if(ld->has_texture) {
1258
-                                UnloadTexture(ld->texture);
1259
-                                ld->has_texture=0;
1293
+                        if(ld->right.has_texture) {
1294
+                                UnloadTexture(ld->right.texture);
1295
+                                ld->right.has_texture=0;
1260 1296
                         }
1261 1297
                 }
1262 1298
                 free(listing->elems),listing->elems=NULL,listing->sizeelems=listing->usedelems=0;
Browse code

Show big image on hover

Dario Rodriguez authored on 01/03/2025 22:32:30
Showing 1 changed files
... ...
@@ -16,6 +16,7 @@
16 16
  *      20250228 Navigate directories
17 17
  *      20250301 Aesthetic fixes for leftside.
18 18
  *               Basic image loading.
19
+ *               Show big image on hover.
19 20
  *
20 21
  * Author: Dario Rodriguez dario@darionomono.com
21 22
  * (c) Dario Rodriguez 2025
... ...
@@ -155,6 +156,9 @@ typedef struct body_t {
155 156
         font_t *ptrfont;
156 157
         font_t *ptrfontbig;
157 158
         font_t *ptrfonthuge;
159
+        char currenttexture[1024];
160
+        Texture2D texture;
161
+        int has_texture;
158 162
 } body_t;
159 163
 
160 164
 typedef struct im_t {
... ...
@@ -187,7 +191,7 @@ void im_body_free(body_t *body);
187 191
 int im_body_add(body_t *body,char *dir);
188 192
 
189 193
 int im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
190
-int im_body_draw(body_t *body, int windowwidth, int windowheight);
194
+int im_body_draw(body_t *body, Vector2 mousepos, int windowwidth, int windowheight);
191 195
 
192 196
 int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort);
193 197
 void listing_freedata(listing_t *listing);
... ...
@@ -238,7 +242,7 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
238 242
                 /* draw screen contents */
239 243
                 BeginDrawing();
240 244
                 ClearBackground(RAYWHITE);
241
-                im_body_draw(im->body,im->w,im->h);
245
+                im_body_draw(im->body,mousepos,im->w,im->h);
242 246
                 im_menubar_draw(im->menubar,im->w,im->h);
243 247
 #if 0
244 248
 {
... ...
@@ -641,6 +645,10 @@ im_body_free(body_t *body)
641 645
                 }
642 646
                 free(body->dirdata),body->dirdata=NULL,body->sizedirdata=0;
643 647
         }
648
+        if(body->has_texture) {
649
+                UnloadTexture(body->texture);
650
+                body->has_texture=0;
651
+        }
644 652
         free(body),body=NULL;
645 653
         return;
646 654
 }
... ...
@@ -737,7 +745,7 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
737 745
 }
738 746
 
739 747
 int
740
-im_body_draw(body_t *body, int windowwidth, int windowheight)
748
+im_body_draw(body_t *body, Vector2 mousepos, int windowwidth, int windowheight)
741 749
 {
742 750
         int i,x,y,k,margin,righty;
743 751
         dirdata_t *dirdata;
... ...
@@ -745,6 +753,7 @@ im_body_draw(body_t *body, int windowwidth, int windowheight)
745 753
         Vector2 v2,m2;
746 754
         font_t *font,*fontbig,*fonthuge;
747 755
         int is_leftside;
756
+        int flag_skiprightside;
748 757
         if(body==NULL)
749 758
                 return(-1);
750 759
         font=body->ptrfont;
... ...
@@ -756,13 +765,13 @@ im_body_draw(body_t *body, int windowwidth, int windowheight)
756 765
         DrawRectangle(body->xywh.x,body->xywh.y,body->leftsize, body->xywh.h, (Color){ 215, 215, 215, 255 } );
757 766
         /* draw right side background */
758 767
         DrawRectangle(body->xywh.x+body->leftsize,body->xywh.y,body->xywh.w-body->leftsize, body->xywh.h, (Color){ 227, 227, 227, 255 } );
759
-        for(i=0,y=righty=body->xywh.y;i<body->sizedirdata;i++) {
760
-                if((dirdata=body->dirdata[i])==NULL)
761
-                        continue;
762
-                /* two passes for each dirdata, first leftside, then rightside */
763
-                for(is_leftside=1;is_leftside>=0;is_leftside--) {
768
+        /* first pass, draw leftside, second pass, draw all of rightside */
769
+        for(is_leftside=1,flag_skiprightside=0;is_leftside>=0 && flag_skiprightside==0;is_leftside--) {
770
+                for(i=(is_leftside)?body->currentdirdata:0,y=righty=body->xywh.y;(is_leftside && i==body->currentdirdata) || (!is_leftside && i<body->sizedirdata);i++) {
764 771
                         int x0,y0,x1,y1;
765 772
                         int sidelen;
773
+                        if((dirdata=body->dirdata[i])==NULL)
774
+                                continue;
766 775
                         if(is_leftside && !(i==body->currentdirdata))
767 776
                                 continue; /* this element is not in leftside */
768 777
                         margin=font->height/4;
... ...
@@ -922,8 +931,36 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
922 931
                                                                 *has_texture=1;
923 932
                                                         }
924 933
                                                 }
925
-                                                if(*has_texture!=0)
934
+                                                if(*has_texture!=0) {
926 935
                                                         DrawTexture(*te,pos->x,pos->y,WHITE);
936
+                                                        if(is_leftside && is_imutil_insidexywh(mousepos,pos)) {
937
+                                                                /* draw image in rightside */
938
+                                                                char path[2048];
939
+                                                                snprintf(path,sizeof(path),"%s/%s",dirdata->dirname,elem->name+1);
940
+                                                                path[sizeof(path)-1]='\0';
941
+                                                                if(body->has_texture==0 || strcmp(body->currenttexture,path)!=0) {
942
+                                                                        Image im;
943
+                                                                        char fullpath[2048];
944
+                                                                        if(body->has_texture) {
945
+                                                                                UnloadTexture(body->texture);
946
+                                                                                body->has_texture=0;
947
+                                                                        }
948
+                                                                        snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
949
+                                                                        fullpath[sizeof(fullpath)-1]='\0';
950
+                                                                        im=LoadImage(fullpath);
951
+                                                                        if(IsImageValid(im)) {
952
+                                                                                ImageResize(&im,windowwidth-body->leftsize,windowheight-body->xywh.y);
953
+                                                                                body->texture=LoadTextureFromImage(im);
954
+                                                                                UnloadImage(im);
955
+                                                                                body->has_texture=1;
956
+                                                                        }
957
+                                                                }
958
+                                                                if(body->has_texture) {
959
+                                                                       DrawTexture(body->texture,body->leftsize,body->xywh.y,WHITE);
960
+                                                                       flag_skiprightside=1;
961
+                                                                }
962
+                                                        }
963
+                                                }
927 964
                                         }
928 965
                                 }
929 966
                                 x+=margin*2+sidelen;
Browse code

Basic image loading

Dario Rodriguez authored on 01/03/2025 22:04:42
Showing 1 changed files
... ...
@@ -14,7 +14,8 @@
14 14
  *      20250225 Draw image placeholders
15 15
  *      20250226 Fix rightside positions
16 16
  *      20250228 Navigate directories
17
- *      20250301 Aestetic fixes for leftside.
17
+ *      20250301 Aesthetic fixes for leftside.
18
+ *               Basic image loading.
18 19
  *
19 20
  * Author: Dario Rodriguez dario@darionomono.com
20 21
  * (c) Dario Rodriguez 2025
... ...
@@ -70,6 +71,22 @@
70 71
 #define UNROLLXYWH(xywh) (xywh).x,(xywh).y,(xywh).w,(xywh).h
71 72
 #endif
72 73
 
74
+#ifndef __linux__
75
+/* the old raylib used in the windows build lacks this function */
76
+bool IsImageValid(Image image)
77
+{
78
+    bool result = false;
79
+
80
+    if ((image.data != NULL) &&     // Validate pixel data available
81
+        (image.width > 0) &&        // Validate image width
82
+        (image.height > 0) &&       // Validate image height
83
+        (image.format > 0) &&       // Validate image format
84
+        (image.mipmaps > 0)) result = true; // Validate image mipmaps (at least 1 for basic mipmap level)
85
+
86
+    return result;
87
+}
88
+#endif
89
+
73 90
 typedef struct xywh_t {
74 91
         int x;
75 92
         int y;
... ...
@@ -102,7 +119,11 @@ typedef struct menubar_t {
102 119
 
103 120
 typedef struct listingdata_t {
104 121
         xywh_t leftxywh;
122
+        Texture2D lefttexture;
123
+        int has_lefttexture;
105 124
         xywh_t xywh;
125
+        Texture2D texture;
126
+        int has_texture;
106 127
         char *name; /* first byte in the name is the type, next is the name, i.e. a directory is "dhome" and a file is "f.bashrc" (this is done for easier sorting) */
107 128
 } listingdata_t;
108 129
 
... ...
@@ -179,6 +200,7 @@ char *imutil_strduplen(char *str, int len);
179 200
 int is_imutil_insidexywh(Vector2 pos, xywh_t *xywh);
180 201
 int menudata_pos2option(menudata_t *menudata, Vector2 pos);
181 202
 int *getcodepoints(int *sizecodepoints);
203
+int is_imagefilename(char *filename);
182 204
 
183 205
 int
184 206
 main(int argc, char *argv[])
... ...
@@ -580,6 +602,7 @@ body_t *
580 602
 im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir)
581 603
 {
582 604
         body_t *body;
605
+        static char sep[]={SEP};
583 606
         if(font==NULL || fontbig==NULL || fonthuge==NULL || rootdir==NULL)
584 607
                 return(NULL); /* sanity check failed */
585 608
         if((body=calloc(1,sizeof(body_t)))==NULL
... ...
@@ -593,6 +616,8 @@ im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int
593 616
         body->ptrfont=font;
594 617
         body->ptrfontbig=fontbig;
595 618
         body->ptrfonthuge=fonthuge;
619
+        if(body->rootdir[0]!='\0' && strcmp(body->rootdir,SEP)!=0 && body->rootdir[strlen(body->rootdir)-1]==sep[0])
620
+                body->rootdir[strlen(body->rootdir)-1]='\0'; /* rootdir doesn't need the final '/' */
596 621
         return(body);
597 622
 }
598 623
 
... ...
@@ -865,8 +890,12 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
865 890
                                         char shortname[1024];
866 891
                                         xywh_t *pos;
867 892
                                         int l;
893
+                                        Texture2D *te;
894
+                                        int *has_texture;
868 895
                                         font_t *myfont=(is_leftside)?fonthuge:font;
869 896
                                         pos=is_leftside?&(elem->leftxywh):&(elem->xywh);
897
+                                        te=is_leftside?&(elem->lefttexture):&(elem->texture);
898
+                                        has_texture=is_leftside?&(elem->has_lefttexture):&(elem->has_texture);
870 899
                                         if((ptr=strchr(elem->name+1,'.'))!=NULL) {
871 900
                                                 m2=MeasureTextEx(myfont->font,ptr,myfont->height,0);
872 901
                                                 DrawTextEx(myfont->font,ptr,(Vector2){x+margin+(sidelen-m2.x)/2,y+(font->height)/2+margin+(sidelen-myfont->height)/2},myfont->height,0,(Color){ 0,0,0,96 });
... ...
@@ -878,6 +907,24 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
878 907
                                         shortname[l]='\0';
879 908
                                         DrawRectangle(pos->x,pos->y,pos->w,font->height+font->height/2,((Color){0,0,0,64}));
880 909
                                         DrawTextEx(font->font,shortname,(Vector2){pos->x+font->height/4,pos->y+font->height/4},font->height,0,(Color){ 192,192,192,255 });
910
+                                        /* show image */
911
+                                        if(is_imagefilename(elem->name+1)) {
912
+                                                if(*has_texture==0) {
913
+                                                        Image im;
914
+                                                        char fullpath[2048];
915
+                                                        snprintf(fullpath,sizeof(fullpath),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
916
+                                                        fullpath[sizeof(fullpath)-1]='\0';
917
+                                                        im=LoadImage(fullpath);
918
+                                                        if(IsImageValid(im)) {
919
+                                                                ImageResize(&im,sidelen,sidelen);
920
+                                                                *te=LoadTextureFromImage(im);
921
+                                                                UnloadImage(im);
922
+                                                                *has_texture=1;
923
+                                                        }
924
+                                                }
925
+                                                if(*has_texture!=0)
926
+                                                        DrawTexture(*te,pos->x,pos->y,WHITE);
927
+                                        }
881 928
                                 }
882 929
                                 x+=margin*2+sidelen;
883 930
                         }
... ...
@@ -1048,15 +1095,30 @@ strptrcmp(void *a,void *b)
1048 1095
 int
1049 1096
 listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort)
1050 1097
 {
1051
-        int l;
1098
+        int i,l;
1052 1099
         DIR *d;
1053 1100
         struct dirent *de;
1054 1101
         unsigned char dtype;
1055 1102
         char path[1024];
1103
+        listingdata_t *ld;
1056 1104
         if(listing==NULL)
1057 1105
                 return(-1); /* sanity check failed */
1106
+        /* free old textures */
1107
+        for(i=0;i<listing->usedelems;i++) {
1108
+                ld=listing->elems+i;
1109
+                if(ld->has_lefttexture) {
1110
+                        UnloadTexture(ld->lefttexture);
1111
+                        ld->has_lefttexture=0;
1112
+                }
1113
+                if(ld->has_texture) {
1114
+                        UnloadTexture(ld->texture);
1115
+                        ld->has_texture=0;
1116
+                }
1117
+        }
1118
+        /* reset struct */
1058 1119
         listing->usedelems=listing->usedbuf=0;
1059 1120
         memset(listing->elems,0,sizeof(listingdata_t)*listing->sizeelems);
1121
+        /* fill listing */
1060 1122
         if(pathprefix==NULL && parampath==NULL)
1061 1123
                 return(-1); /* nothing to fill */
1062 1124
         snprintf(path,sizeof(path),"%s%s%s",(pathprefix!=NULL)?pathprefix:"",SEP,(parampath!=NULL)?parampath:"");
... ...
@@ -1146,10 +1208,50 @@ listing_freedata(listing_t *listing)
1146 1208
 {
1147 1209
         if(listing==NULL)
1148 1210
                 return; /* nothing to do */
1149
-        if(listing->elems!=NULL)
1211
+        if(listing->elems!=NULL) {
1212
+                int i;
1213
+                listingdata_t *ld;
1214
+                for(i=0;i<listing->usedelems;i++) {
1215
+                        ld=listing->elems+i;
1216
+                        if(ld->has_lefttexture) {
1217
+                                UnloadTexture(ld->lefttexture);
1218
+                                ld->has_lefttexture=0;
1219
+                        }
1220
+                        if(ld->has_texture) {
1221
+                                UnloadTexture(ld->texture);
1222
+                                ld->has_texture=0;
1223
+                        }
1224
+                }
1150 1225
                 free(listing->elems),listing->elems=NULL,listing->sizeelems=listing->usedelems=0;
1226
+        }
1151 1227
         if(listing->buf!=NULL)
1152 1228
                 free(listing->buf),listing->buf=NULL,listing->sizebuf=listing->usedbuf=0;
1153 1229
         return;
1154 1230
 }
1155 1231
 
1232
+int
1233
+is_imagefilename(char *filename)
1234
+{
1235
+        char *ptr;
1236
+        int i;
1237
+        char *knownext[]={".jpg",".jpeg",".JPG",".JPEG",".Jpg",".Jpeg"
1238
+                         ,".png",".PNG",".Png"
1239
+                         ,".tga",".TGA",".Tga"
1240
+                         ,".bmp",".BMP",".Bmp"
1241
+                         ,".psd",".PSD",".Psd"
1242
+                         ,".gif",".GIF",".Gif"
1243
+                         ,".hdr",".HDR",".Hdr"
1244
+                         ,".pic",".PIC",".Pic"
1245
+                         ,".pnm",".PNM",".Pnm"
1246
+        };
1247
+        if(filename==NULL)
1248
+                return(0); /* sanity check failed */
1249
+        if((ptr=strrchr(filename,'.'))==NULL)
1250
+                return(0); /* no extension found */
1251
+        for(i=0;i<(sizeof(knownext)/sizeof(knownext[0]));i++) {
1252
+                if(strcmp(ptr,knownext[i])==0)
1253
+                        return(1); /* it has a known ext */
1254
+        }
1255
+        return(0); /* not in the knownext list */
1256
+}
1257
+
Browse code

Aesthetic fixes for leftside

Dario Rodriguez authored on 01/03/2025 20:14:21
Showing 1 changed files
... ...
@@ -13,6 +13,8 @@
13 13
  *      20250224 Draw right dir list and store elem positions.
14 14
  *      20250225 Draw image placeholders
15 15
  *      20250226 Fix rightside positions
16
+ *      20250228 Navigate directories
17
+ *      20250301 Aestetic fixes for leftside.
16 18
  *
17 19
  * Author: Dario Rodriguez dario@darionomono.com
18 20
  * (c) Dario Rodriguez 2025
... ...
@@ -38,7 +40,7 @@
38 40
 #define LEFTSIZE 720
39 41
 #define DEFAULTDIRDATAHEIGHT 150
40 42
 #define DEFAULTDIRDATATRIANGLEW 35
41
-#define LEFTIMAGESIDELEN 130
43
+#define LEFTIMAGESIDELEN 125
42 44
 
43 45
 #define FONTSIZE 18
44 46
 #define FONTBIGSIZE 32
... ...
@@ -282,7 +284,7 @@ im_init(char *menus, char *rootdir)
282 284
                 return(NULL); /* insuf. mem. */
283 285
         }
284 286
         /* add the starting directory */
285
-        im_body_add(im->body,"/");
287
+        im_body_add(im->body,"");
286 288
         return(im);
287 289
 }
288 290
 
... ...
@@ -667,11 +669,15 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
667 669
         if(is_imutil_insidexywh(mousepos,&(body->backxywh))) {
668 670
                 static char sep[]={SEP};
669 671
                 if((ptr=strrchr(dirdata->dirname,sep[0]))!=NULL) {
672
+                        /* previous dir */
670 673
                         *ptr='\0';
671
-                        listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
672
-                        *click_avail=0;
673
-                        return(0);
674
+                } else {
675
+                        /* root dir */
676
+                        dirdata->dirname[0]='\0';
674 677
                 }
678
+                listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
679
+                *click_avail=0;
680
+                return(0);
675 681
         }
676 682
         /* leftside directories */
677 683
         for(i=0;i<dirdata->listing.usedelems;i++) {
... ...
@@ -683,13 +689,17 @@ im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, i
683 689
                         int l,l0,l1;
684 690
                         static char sep[]={SEP};
685 691
                         oldprefix=(strcmp(dirdata->dirname,SEP)==0)?"":dirdata->dirname;
686
-                        l=(l0=strlen(oldprefix))+1+(l1=strlen(ld->name+1))+1;
692
+                        l0=strlen(oldprefix);
693
+                        l1=strlen(ld->name+1);
694
+                        l=l0+((l0>0)?1:0)+l1+1;
687 695
                         if((newname=malloc(l))==NULL)
688 696
                                 return(-1); /* insuf. mem. */
689
-                        memcpy(newname,oldprefix,l0);
690
-                        newname[l0]=sep[0];
691
-                        memcpy(newname+l0+1,ld->name+1,l1);
692
-                        newname[l0+1+l1]='\0';
697
+                        if(l0>0) {
698
+                                memcpy(newname,oldprefix,l0);
699
+                                newname[l0]=sep[0];
700
+                        }
701
+                        memcpy(newname+l0+((l0>0)?1:0),ld->name+1,l1);
702
+                        newname[l0+((l0>0)?1:0)+l1]='\0';
693 703
                         free(dirdata->dirname),dirdata->dirname=NULL;
694 704
                         dirdata->dirname=newname;
695 705
                         listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
... ...
@@ -734,9 +744,9 @@ im_body_draw(body_t *body, int windowwidth, int windowheight)
734 744
                         sidelen=(is_leftside)?LEFTIMAGESIDELEN:dirdata->height-(fontbig->height+fontbig->height/4+font->height+margin*4+fontbig->height/4);
735 745
                         /* draw left side back arrow if is_leftside and not in root dir */
736 746
                         if(is_leftside && !(dirdata->dirname[0]=='\0' || strcmp(dirdata->dirname,SEP)==0)) {
737
-                                v2.x=(float) (body->xywh.x+fontbig->height/2);
738
-                                v2.y=(float) (body->xywh.y+fontbig->height/4);
739 747
                                 m2=MeasureTextEx(fontbig->font,UTF8DOWNARROW,fontbig->height,0);
748
+                                v2.x=(float) (body->xywh.x+fontbig->height/2);
749
+                                v2.y=(float) (body->xywh.y+fontbig->height/4+(fontbig->height-v2.x)/2);
740 750
                                 FILLXYWH(body->backxywh,v2.x-fontbig->height/4,v2.y-fontbig->height/8,m2.x+fontbig->height/4,m2.x+fontbig->height/4);
741 751
 #if 0
742 752
 DrawTexture(fontbig->font.texture, 0, 0, WHITE); /* font glyphs -- see https://github.com/raysan5/raylib/issues/2022 */
... ...
@@ -773,7 +783,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
773 783
                         /* directories */
774 784
                         if(is_leftside) {
775 785
                                 x0=body->xywh.x+font->height/2;
776
-                                x1=body->xywh.x+body->leftsize-font->height/2;
786
+                                x1=body->xywh.x+body->leftsize-DEFAULTDIRDATATRIANGLEW-font->height/2;
777 787
                                 y0=body->xywh.y+font->height/4+m2.y+font->height/2;
778 788
                                 y1=body->xywh.y+body->xywh.h-DEFAULTDIRDATATRIANGLEW-font->height/2;
779 789
                         } else {
Browse code

Navigate directories

Dario Rodriguez authored on 28/02/2025 19:33:08
Showing 1 changed files
... ...
@@ -654,6 +654,49 @@ im_body_add(body_t *body,char *dir)
654 654
 int
655 655
 im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail)
656 656
 {
657
+        int i;
658
+        char *ptr;
659
+        dirdata_t *dirdata;
660
+        listingdata_t *ld;
661
+        if(body==NULL || click_avail==NULL || body->currentdirdata<0 || body->currentdirdata>=body->sizedirdata || body->dirdata[body->currentdirdata]==NULL)
662
+                return(-1); /* sanity check error */
663
+        if(*click_avail==0 || lmbreleased==0)
664
+                return(0); /* nothing to do */
665
+        dirdata=body->dirdata[body->currentdirdata];
666
+        /* leftside backbutton */
667
+        if(is_imutil_insidexywh(mousepos,&(body->backxywh))) {
668
+                static char sep[]={SEP};
669
+                if((ptr=strrchr(dirdata->dirname,sep[0]))!=NULL) {
670
+                        *ptr='\0';
671
+                        listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
672
+                        *click_avail=0;
673
+                        return(0);
674
+                }
675
+        }
676
+        /* leftside directories */
677
+        for(i=0;i<dirdata->listing.usedelems;i++) {
678
+                ld=dirdata->listing.elems+i;
679
+                if(ld->name[0]!='d')
680
+                        continue;
681
+                if(is_imutil_insidexywh(mousepos,&(ld->leftxywh))) {
682
+                        char *newname,*oldprefix;
683
+                        int l,l0,l1;
684
+                        static char sep[]={SEP};
685
+                        oldprefix=(strcmp(dirdata->dirname,SEP)==0)?"":dirdata->dirname;
686
+                        l=(l0=strlen(oldprefix))+1+(l1=strlen(ld->name+1))+1;
687
+                        if((newname=malloc(l))==NULL)
688
+                                return(-1); /* insuf. mem. */
689
+                        memcpy(newname,oldprefix,l0);
690
+                        newname[l0]=sep[0];
691
+                        memcpy(newname+l0+1,ld->name+1,l1);
692
+                        newname[l0+1+l1]='\0';
693
+                        free(dirdata->dirname),dirdata->dirname=NULL;
694
+                        dirdata->dirname=newname;
695
+                        listing_get(&(dirdata->listing),body->rootdir,dirdata->dirname,1);
696
+                        *click_avail=0;
697
+                        return(0);
698
+                }
699
+        }
657 700
 #warning TODO
658 701
         return(0);
659 702
 }
... ...
@@ -689,8 +732,8 @@ im_body_draw(body_t *body, int windowwidth, int windowheight)
689 732
                                 continue; /* this element is not in leftside */
690 733
                         margin=font->height/4;
691 734
                         sidelen=(is_leftside)?LEFTIMAGESIDELEN:dirdata->height-(fontbig->height+fontbig->height/4+font->height+margin*4+fontbig->height/4);
692
-                        if(is_leftside) {
693
-                                /* draw left side back arrow */
735
+                        /* draw left side back arrow if is_leftside and not in root dir */
736
+                        if(is_leftside && !(dirdata->dirname[0]=='\0' || strcmp(dirdata->dirname,SEP)==0)) {
694 737
                                 v2.x=(float) (body->xywh.x+fontbig->height/2);
695 738
                                 v2.y=(float) (body->xywh.y+fontbig->height/4);
696 739
                                 m2=MeasureTextEx(fontbig->font,UTF8DOWNARROW,fontbig->height,0);
Browse code

Fix rightside positions

Dario Rodriguez authored on 27/02/2025 19:13:15
Showing 1 changed files
... ...
@@ -12,6 +12,7 @@
12 12
  *      20250223 Draw pane titles and main dir list.
13 13
  *      20250224 Draw right dir list and store elem positions.
14 14
  *      20250225 Draw image placeholders
15
+ *      20250226 Fix rightside positions
15 16
  *
16 17
  * Author: Dario Rodriguez dario@darionomono.com
17 18
  * (c) Dario Rodriguez 2025
... ...
@@ -37,7 +38,7 @@
37 38
 #define LEFTSIZE 720
38 39
 #define DEFAULTDIRDATAHEIGHT 150
39 40
 #define DEFAULTDIRDATATRIANGLEW 35
40
-#define LEFTIMAGESIDELEN 150
41
+#define LEFTIMAGESIDELEN 130
41 42
 
42 43
 #define FONTSIZE 18
43 44
 #define FONTBIGSIZE 32
... ...
@@ -686,6 +687,8 @@ im_body_draw(body_t *body, int windowwidth, int windowheight)
686 687
                         int sidelen;
687 688
                         if(is_leftside && !(i==body->currentdirdata))
688 689
                                 continue; /* this element is not in leftside */
690
+                        margin=font->height/4;
691
+                        sidelen=(is_leftside)?LEFTIMAGESIDELEN:dirdata->height-(fontbig->height+fontbig->height/4+font->height+margin*4+fontbig->height/4);
689 692
                         if(is_leftside) {
690 693
                                 /* draw left side back arrow */
691 694
                                 v2.x=(float) (body->xywh.x+fontbig->height/2);
... ...
@@ -721,7 +724,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
721 724
                                   ,(Vector2) {body->xywh.x+body->leftsize+fontbig->height/2,righty+fontbig->height/4}
722 725
                                   ,fontbig->height
723 726
                                   ,0
724
-                                  ,(Color){ 65, 65, 65, 255 }
727
+                                  ,(Color){ 240, 240, 240, 255 }
725 728
                                 );
726 729
                         }
727 730
                         /* directories */
... ...
@@ -733,11 +736,11 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
733 736
                         } else {
734 737
                                 x0=body->xywh.x+body->leftsize+fontbig->height/2;
735 738
                                 x1=body->xywh.x+body->xywh.w-font->height/2;
736
-                                y0=righty+fontbig->height/4+fontbig->height+font->height/4;
739
+                                y0=righty+fontbig->height/4+fontbig->height+margin;
737 740
                                 y1=y0+margin*2+font->height-1;
738 741
                         }
739
-                        margin=font->height/4;
740 742
                         for(k=0,x=x0,y=y0;k<dirdata->listing.usedelems;k++) {
743
+                                Color c=(is_leftside)?((Color){ 65, 65, 65, 255 }):((Color){ 240, 240, 240, 255 });
741 744
                                 elem=dirdata->listing.elems+k;
742 745
                                 if(elem->name[0]!='d' || strcmp(elem->name,"d.")==0 || strcmp(elem->name,"d..")==0)
743 746
                                         continue;
... ...
@@ -751,7 +754,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
751 754
                                                   ,(Vector2) {x+margin,y+(fontbig->height-fonthuge->height)}
752 755
                                                   ,fonthuge->height
753 756
                                                   ,0
754
-                                                  ,(Color){ 65, 65, 65, 255 }
757
+                                                  ,c
755 758
                                                 );
756 759
                                          }
757 760
                                         x=x0,y+=font->height+margin*2+font->height/4;
... ...
@@ -760,12 +763,12 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
760 763
                                 }
761 764
                                 if(is_leftside) {
762 765
                                         FILLXYWH(elem->leftxywh,x,y,margin*2+m2.x,margin*2+font->height);
763
-                                        DrawRectangleLines(UNROLLXYWH(elem->leftxywh),((Color){0,0,0,255}));
766
+                                        DrawRectangleLines(UNROLLXYWH(elem->leftxywh),c);
764 767
                                 } else {
765 768
                                         FILLXYWH(elem->xywh,x,y,margin*2+m2.x,margin*2+font->height);
766
-                                        DrawRectangleLines(UNROLLXYWH(elem->xywh),((Color){0,0,0,255}));
769
+                                        DrawRectangleLines(UNROLLXYWH(elem->xywh),c);
767 770
                                 }
768
-                                DrawTextEx(font->font,elem->name+1,(Vector2){x+margin,y+margin},font->height,0,(Color){ 65, 65, 65, 255 });
771
+                                DrawTextEx(font->font,elem->name+1,(Vector2){x+margin,y+margin},font->height,0,c);
769 772
                                 x+=margin*2+m2.x+font->height/4;
770 773
                         }
771 774
                         /* files */
... ...
@@ -773,9 +776,9 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
773 776
                                 y0=(x==x0)?y:y+font->height+margin*2+font->height/4;
774 777
                                 sidelen=LEFTIMAGESIDELEN;
775 778
                         } else {
776
-                                y0=righty; //y0+margin*2+font->height+font->height/2;
777
-                                y1=righty+dirdata->height-fontbig->height/4;
778
-                                sidelen=y1-y0-1;
779
+                                y0=righty+dirdata->height-sidelen-margin-fontbig->height/4;
780
+                                y1=y0+sidelen+margin;
781
+                                x0-=margin;
779 782
                         }
780 783
                         for(k=0,x=x0,y=y0;k<dirdata->listing.usedelems;k++) {
781 784
                                 elem=dirdata->listing.elems+k;
... ...
@@ -790,7 +793,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
790 793
                                                   ,(Vector2) {x+margin,y+(sidelen-fonthuge->height)}
791 794
                                                   ,fonthuge->height
792 795
                                                   ,0
793
-                                                  ,(Color){ 65, 65, 65, 255 }
796
+                                                  ,(Color){ 0,0,0,64 }
794 797
                                                 );
795 798
                                          }
796 799
                                         x=x0,y+=sidelen+margin*2;
... ...
@@ -809,10 +812,11 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
809 812
                                         char shortname[1024];
810 813
                                         xywh_t *pos;
811 814
                                         int l;
815
+                                        font_t *myfont=(is_leftside)?fonthuge:font;
812 816
                                         pos=is_leftside?&(elem->leftxywh):&(elem->xywh);
813 817
                                         if((ptr=strchr(elem->name+1,'.'))!=NULL) {
814
-                                                m2=MeasureTextEx(fonthuge->font,ptr,fonthuge->height,0);
815
-                                                DrawTextEx(fonthuge->font,ptr,(Vector2){x+margin+(sidelen-m2.x)/2,y+margin+(sidelen-fonthuge->height)/2},fonthuge->height,0,(Color){ 65, 65, 65, 255 });
818
+                                                m2=MeasureTextEx(myfont->font,ptr,myfont->height,0);
819
+                                                DrawTextEx(myfont->font,ptr,(Vector2){x+margin+(sidelen-m2.x)/2,y+(font->height)/2+margin+(sidelen-myfont->height)/2},myfont->height,0,(Color){ 0,0,0,96 });
816 820
                                         }
817 821
                                         ptr=(ptr==NULL)?elem->name+1:ptr;
818 822
                                         l=(ptr-(elem->name+1));
... ...
@@ -820,7 +824,7 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
820 824
                                         memcpy(shortname,elem->name+1,l);
821 825
                                         shortname[l]='\0';
822 826
                                         DrawRectangle(pos->x,pos->y,pos->w,font->height+font->height/2,((Color){0,0,0,64}));
823
-                                        DrawTextEx(font->font,shortname,(Vector2){pos->x+font->height/4,pos->y+font->height/4},font->height,0,(Color){ 255, 255, 255, 255 });
827
+                                        DrawTextEx(font->font,shortname,(Vector2){pos->x+font->height/4,pos->y+font->height/4},font->height,0,(Color){ 192,192,192,255 });
824 828
                                 }
825 829
                                 x+=margin*2+sidelen;
826 830
                         }
... ...
@@ -834,67 +838,6 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
834 838
                         }
835 839
                 }
836 840
         }
837
-#if 0
838
-        /* example from menubar */
839
-        int i,j,k,x;
840
-        menudata_t *menudata;
841
-        font_t *font;
842
-        if(menubar==NULL || font==NULL)
843
-                return(-1); /* sanity check failed */
844
-        font=menubar->ptrfont;
845
-        DrawRectangle(0,0,windowwidth, font->height+font->height/2, (Color){ 235, 235, 235, 235 } );
846
-        for(i=0,x=0;i<menubar->sizemenudata;i++) {
847
-                Vector2 v2;
848
-                menudata=menubar->menudata[i];
849
-                v2=MeasureTextEx(font->font,menudata->title,font->height,0);
850
-                FILLXYWH(menudata->xywh,x,0,((int)v2.x)+font->height,font->height+font->height/2);
851
-                v2.x=(float) (menudata->xywh.x+font->height/2);
852
-                v2.y=(float) (menudata->xywh.y+font->height/4);
853
-                DrawTextEx(font->font
854
-                  ,menudata->title
855
-                  ,v2
856
-                  ,font->height
857
-                  ,0
858
-                  ,(Color){ 45, 45, 45, 255 }
859
-                );
860
-                if(menudata->flag_open || menudata->flag_stickyopen) {
861
-                        int underline_height=3;
862
-                        int maxw;
863
-                        DrawRectangle(menudata->xywh.x,menudata->xywh.y+menudata->xywh.h-underline_height,menudata->xywh.w,underline_height, (Color){ 53,132,228,255 } );
864
-                        for(j=0,maxw=0;j<menudata->sizeoptions;j++) {
865
-                                v2=MeasureTextEx(font->font,menudata->options[j],font->height,0);
866
-                                maxw=(((int)(v2.x))>maxw)?((int)(v2.x)):maxw;
867
-                        }
868
-                        maxw=(maxw<(menudata->xywh.w+font->height))?(menudata->xywh.w+font->height):maxw;
869
-                        maxw+=font->height;
870
-                        FILLXYWH(menudata->optionsxywh,menudata->xywh.x+1,menudata->xywh.y+menudata->xywh.h+2,maxw,(font->height+font->height/2)*menudata->sizeoptions);
871
-                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y-2,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y-2,(Color){ 255,255,255,255 } );
872
-                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y,menudata->optionsxywh.x-1,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 255,255,255,255 } );
873
-                        DrawLine(menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 192,192,192,255 } );
874
-                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y+menudata->optionsxywh.h+1,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 192,192,192,255 } );
875
-                        DrawRectangle(menudata->optionsxywh.x,menudata->optionsxywh.y,menudata->optionsxywh.w,menudata->optionsxywh.h,(Color){ 235, 235, 235, 235 });
876
-                        for(k=0;k<menudata->sizeoptions;k++) {
877
-                                Color c;
878
-                                c=(k==menudata->currentoption)?((Color){ 255,255,255,255 }):((Color){ 45, 45, 45, 255 });
879
-                                if(k==menudata->currentoption)
880
-                                        DrawRectangle(menudata->optionsxywh.x+1,menudata->optionsxywh.y+(font->height+(font->height/2))*k,menudata->optionsxywh.w-2,font->height+font->height/2,(Color){ 53,132,228,255 });
881
-                                v2.x=(float) (menudata->optionsxywh.x+font->height/2);
882
-                                v2.y=(float) (menudata->optionsxywh.y+(font->height/4)+(font->height+(font->height/2))*k);
883
-                                DrawTextEx(font->font
884
-                                  ,menudata->options[k]
885
-                                  ,v2
886
-                                  ,font->height
887
-                                  ,0
888
-                                  ,c
889
-                                );
890
-                        }
891
-                } else {
892
-                        FILLXYWH(menudata->optionsxywh,0,0,0,0);
893
-                }
894
-                x=menudata->xywh.x+menudata->xywh.w;
895
-        }
896
-        return(0);
897
-#endif
898 841
         return(0);
899 842
 }
900 843
 
Browse code

Draw image placeholders

Dario Rodriguez authored on 25/02/2025 17:32:53
Showing 1 changed files
... ...
@@ -10,6 +10,8 @@
10 10
  *      20250216 Modularize menu handling.
11 11
  *      20250222 Able to list files.
12 12
  *      20250223 Draw pane titles and main dir list.
13
+ *      20250224 Draw right dir list and store elem positions.
14
+ *      20250225 Draw image placeholders
13 15
  *
14 16
  * Author: Dario Rodriguez dario@darionomono.com
15 17
  * (c) Dario Rodriguez 2025
... ...
@@ -35,6 +37,7 @@
35 37
 #define LEFTSIZE 720
36 38
 #define DEFAULTDIRDATAHEIGHT 150
37 39
 #define DEFAULTDIRDATATRIANGLEW 35
40
+#define LEFTIMAGESIDELEN 150
38 41
 
39 42
 #define FONTSIZE 18
40 43
 #define FONTBIGSIZE 32
... ...
@@ -680,6 +683,7 @@ im_body_draw(body_t *body, int windowwidth, int windowheight)
680 683
                 /* two passes for each dirdata, first leftside, then rightside */
681 684
                 for(is_leftside=1;is_leftside>=0;is_leftside--) {
682 685
                         int x0,y0,x1,y1;
686
+                        int sidelen;
683 687
                         if(is_leftside && !(i==body->currentdirdata))
684 688
                                 continue; /* this element is not in leftside */
685 689
                         if(is_leftside) {
... ...
@@ -727,9 +731,9 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
727 731
                                 y0=body->xywh.y+font->height/4+m2.y+font->height/2;
728 732
                                 y1=body->xywh.y+body->xywh.h-DEFAULTDIRDATATRIANGLEW-font->height/2;
729 733
                         } else {
730
-                                x0=body->xywh.x+body->leftsize+font->height/2;
734
+                                x0=body->xywh.x+body->leftsize+fontbig->height/2;
731 735
                                 x1=body->xywh.x+body->xywh.w-font->height/2;
732
-                                y0=righty+fontbig->height/2+m2.y+font->height/4;
736
+                                y0=righty+fontbig->height/4+fontbig->height+font->height/4;
733 737
                                 y1=y0+margin*2+font->height-1;
734 738
                         }
735 739
                         margin=font->height/4;
... ...
@@ -741,17 +745,85 @@ DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone
741 745
                                         continue;
742 746
                                 m2=MeasureTextEx(font->font,elem->name+1,font->height,0);
743 747
                                 if((x+margin*2+m2.x)>x1) {
748
+                                        if(!is_leftside) {
749
+                                                DrawTextEx(fonthuge->font
750
+                                                  ,"..."
751
+                                                  ,(Vector2) {x+margin,y+(fontbig->height-fonthuge->height)}
752
+                                                  ,fonthuge->height
753
+                                                  ,0
754
+                                                  ,(Color){ 65, 65, 65, 255 }
755
+                                                );
756
+                                         }
744 757
                                         x=x0,y+=font->height+margin*2+font->height/4;
745 758
                                         if(y>y1)
746 759
                                                 continue;
747 760
                                 }
748
-                                FILLXYWH(elem->leftxywh,x,y,margin*2+m2.x,margin*2+font->height);
749
-                                DrawRectangleLines(UNROLLXYWH(elem->leftxywh),((Color){0,0,0,255}));
761
+                                if(is_leftside) {
762
+                                        FILLXYWH(elem->leftxywh,x,y,margin*2+m2.x,margin*2+font->height);
763
+                                        DrawRectangleLines(UNROLLXYWH(elem->leftxywh),((Color){0,0,0,255}));
764
+                                } else {
765
+                                        FILLXYWH(elem->xywh,x,y,margin*2+m2.x,margin*2+font->height);
766
+                                        DrawRectangleLines(UNROLLXYWH(elem->xywh),((Color){0,0,0,255}));
767
+                                }
750 768
                                 DrawTextEx(font->font,elem->name+1,(Vector2){x+margin,y+margin},font->height,0,(Color){ 65, 65, 65, 255 });
751 769
                                 x+=margin*2+m2.x+font->height/4;
752 770
                         }
753
-
754
-#warning TODO SHOW FILES
771
+                        /* files */
772
+                        if(is_leftside) {
773
+                                y0=(x==x0)?y:y+font->height+margin*2+font->height/4;
774
+                                sidelen=LEFTIMAGESIDELEN;
775
+                        } else {
776
+                                y0=righty; //y0+margin*2+font->height+font->height/2;
777
+                                y1=righty+dirdata->height-fontbig->height/4;
778
+                                sidelen=y1-y0-1;
779
+                        }
780
+                        for(k=0,x=x0,y=y0;k<dirdata->listing.usedelems;k++) {
781
+                                elem=dirdata->listing.elems+k;
782
+                                if(elem->name[0]!='f' && elem->name[0]!='l')
783
+                                        continue;
784
+                                if(y>y1)
785
+                                        continue;
786
+                                if((x+margin*2+sidelen)>x1) {
787
+                                        if(!is_leftside) {
788
+                                                DrawTextEx(fonthuge->font
789
+                                                  ,"..."
790
+                                                  ,(Vector2) {x+margin,y+(sidelen-fonthuge->height)}
791
+                                                  ,fonthuge->height
792
+                                                  ,0
793
+                                                  ,(Color){ 65, 65, 65, 255 }
794
+                                                );
795
+                                         }
796
+                                        x=x0,y+=sidelen+margin*2;
797
+                                        if(y>y1)
798
+                                                continue;
799
+                                }
800
+                                if(is_leftside) {
801
+                                        FILLXYWH(elem->leftxywh,x+margin,y+margin,sidelen,sidelen);
802
+                                        DrawRectangle(UNROLLXYWH(elem->leftxywh),((Color){0,0,0,64}));
803
+                                } else {
804
+                                        FILLXYWH(elem->xywh,x+margin,y+margin,sidelen,sidelen);
805
+                                        DrawRectangle(UNROLLXYWH(elem->xywh),((Color){0,0,0,64}));
806
+                                }
807
+                                {
808
+                                        char *ptr;
809
+                                        char shortname[1024];
810
+                                        xywh_t *pos;
811
+                                        int l;
812
+                                        pos=is_leftside?&(elem->leftxywh):&(elem->xywh);
813
+                                        if((ptr=strchr(elem->name+1,'.'))!=NULL) {
814
+                                                m2=MeasureTextEx(fonthuge->font,ptr,fonthuge->height,0);
815
+                                                DrawTextEx(fonthuge->font,ptr,(Vector2){x+margin+(sidelen-m2.x)/2,y+margin+(sidelen-fonthuge->height)/2},fonthuge->height,0,(Color){ 65, 65, 65, 255 });
816
+                                        }
817
+                                        ptr=(ptr==NULL)?elem->name+1:ptr;
818
+                                        l=(ptr-(elem->name+1));
819
+                                        l=(l>=sizeof(shortname))?sizeof(shortname)-1:l;
820
+                                        memcpy(shortname,elem->name+1,l);
821
+                                        shortname[l]='\0';
822
+                                        DrawRectangle(pos->x,pos->y,pos->w,font->height+font->height/2,((Color){0,0,0,64}));
823
+                                        DrawTextEx(font->font,shortname,(Vector2){pos->x+font->height/4,pos->y+font->height/4},font->height,0,(Color){ 255, 255, 255, 255 });
824
+                                }
825
+                                x+=margin*2+sidelen;
826
+                        }
755 827
                         /* ...finishing touchs */
756 828
                         if(is_leftside) {
757 829
                                 /* draw right side "current" marker inside left side area */
Browse code

Draw right dir list and store elem positions

Dario Rodriguez authored on 24/02/2025 20:23:39
Showing 1 changed files
... ...
@@ -94,10 +94,16 @@ typedef struct menubar_t {
94 94
         font_t *ptrfont;
95 95
 } menubar_t;
96 96
 
97
+typedef struct listingdata_t {
98
+        xywh_t leftxywh;
99
+        xywh_t xywh;
100
+        char *name; /* first byte in the name is the type, next is the name, i.e. a directory is "dhome" and a file is "f.bashrc" (this is done for easier sorting) */
101
+} listingdata_t;
102
+
97 103
 typedef struct listing_t {
98 104
         int sizeelems;
99 105
         int usedelems;
100
-        char **elems; /* first byte in the elem is the type, next is the name, i.e. a directory is "dhome" and a file is "f.bashrc" */
106
+        listingdata_t *elems;
101 107
         int sizebuf;
102 108
         int usedbuf;
103 109
         char *buf;
... ...
@@ -229,7 +235,7 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
229 235
      v2.x=(float) (im->font->height/2);
230 236
      v2.y=(float) ((im->font->height+im->font->height/2)*i+(im->font->height/4));
231 237
      DrawTextEx(im->font->font
232
-       ,listing.elems[j]
238
+       ,listing.elems[j].name
233 239
        ,v2
234 240
        ,im->font->height
235 241
        ,0
... ...
@@ -653,8 +659,10 @@ im_body_draw(body_t *body, int windowwidth, int windowheight)
653 659
 {
654 660
         int i,x,y,k,margin,righty;
655 661
         dirdata_t *dirdata;
662
+        listingdata_t *elem;
656 663
         Vector2 v2,m2;
657 664
         font_t *font,*fontbig,*fonthuge;
665
+        int is_leftside;
658 666
         if(body==NULL)
659 667
                 return(-1);
660 668
         font=body->ptrfont;
... ...
@@ -669,66 +677,90 @@ im_body_draw(body_t *body, int windowwidth, int windowheight)
669 677
         for(i=0,y=righty=body->xywh.y;i<body->sizedirdata;i++) {
670 678
                 if((dirdata=body->dirdata[i])==NULL)
671 679
                         continue;
672
-                /* draw left side if appropiate */
673
-                if(i==body->currentdirdata) {
680
+                /* two passes for each dirdata, first leftside, then rightside */
681
+                for(is_leftside=1;is_leftside>=0;is_leftside--) {
674 682
                         int x0,y0,x1,y1;
675
-                        /* draw left side */
676
-                        /* ...back arrow */
677
-                        v2.x=(float) (body->xywh.x+fontbig->height/2);
678
-                        v2.y=(float) (body->xywh.y+fontbig->height/4);
679
-                        m2=MeasureTextEx(fontbig->font,UTF8DOWNARROW,fontbig->height,0);
680
-                        FILLXYWH(body->backxywh,v2.x-fontbig->height/4,v2.y-fontbig->height/8,m2.x+fontbig->height/4,m2.x+fontbig->height/4);
683
+                        if(is_leftside && !(i==body->currentdirdata))
684
+                                continue; /* this element is not in leftside */
685
+                        if(is_leftside) {
686
+                                /* draw left side back arrow */
687
+                                v2.x=(float) (body->xywh.x+fontbig->height/2);
688
+                                v2.y=(float) (body->xywh.y+fontbig->height/4);
689
+                                m2=MeasureTextEx(fontbig->font,UTF8DOWNARROW,fontbig->height,0);
690
+                                FILLXYWH(body->backxywh,v2.x-fontbig->height/4,v2.y-fontbig->height/8,m2.x+fontbig->height/4,m2.x+fontbig->height/4);
681 691
 #if 0
682 692
 DrawTexture(fontbig->font.texture, 0, 0, WHITE); /* font glyphs -- see https://github.com/raysan5/raylib/issues/2022 */
683 693
 DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone */
684 694
 #endif
685
-                        DrawTextPro(fontbig->font,UTF8DOWNARROW,(Vector2){v2.x+m2.x,v2.y},(Vector2){0,0},90.0,fontbig->height,0,(Color){65,65,65,255});
686
-                        /* ...dirname */
687
-                        m2=MeasureTextEx(fontbig->font,dirdata->dirname,fontbig->height,0);
688
-                        v2.x=(float) (body->xywh.x+fontbig->height/2)+(body->leftsize-(body->xywh.x+fontbig->height)-m2.x)/2;
689
-                        v2.y=(float) (body->xywh.y+fontbig->height/4);
690
-                        DrawTextEx(fontbig->font
691
-                          ,dirdata->dirname
692
-                          ,v2
693
-                          ,fontbig->height
694
-                          ,0
695
-                          ,(Color){ 65, 65, 65, 255 }
696
-                        );
695
+                                DrawTextPro(fontbig->font,UTF8DOWNARROW,(Vector2){v2.x+m2.x,v2.y},(Vector2){0,0},90.0,fontbig->height,0,(Color){65,65,65,255});
696
+                        }
697
+                        if(is_leftside) {
698
+                                /* ...dirname */
699
+                                m2=MeasureTextEx(fontbig->font,dirdata->dirname,fontbig->height,0);
700
+                                v2.x=(float) (body->xywh.x+fontbig->height/2)+(body->leftsize-(body->xywh.x+fontbig->height)-m2.x)/2;
701
+                                v2.y=(float) (body->xywh.y+fontbig->height/4);
702
+                                DrawTextEx(fontbig->font
703
+                                  ,dirdata->dirname
704
+                                  ,v2
705
+                                  ,fontbig->height
706
+                                  ,0
707
+                                  ,(Color){ 65, 65, 65, 255 }
708
+                                );
709
+                        } else { /* rightside */
710
+                                /* ...bg */
711
+                                DrawRectangle(body->xywh.x+body->leftsize,righty,body->xywh.w-body->leftsize, dirdata->height,(i==body->currentdirdata)?((Color){ 168, 168, 168, 255 }):((Color){ 227, 227, 227, 255 }));
712
+                                /* ...bottom separator */
713
+                                DrawRectangle(body->xywh.x+body->leftsize,righty+dirdata->height-1,body->xywh.w-body->leftsize, 1, (Color){ 221, 221, 221, 255 } );
714
+                                /* ...dirname */
715
+                                DrawTextEx(fontbig->font
716
+                                  ,dirdata->dirname
717
+                                  ,(Vector2) {body->xywh.x+body->leftsize+fontbig->height/2,righty+fontbig->height/4}
718
+                                  ,fontbig->height
719
+                                  ,0
720
+                                  ,(Color){ 65, 65, 65, 255 }
721
+                                );
722
+                        }
697 723
                         /* directories */
698
-                        x0=body->xywh.x+font->height/2;
699
-                        x1=body->xywh.x+body->leftsize-font->height/2;
700
-                        y0=body->xywh.y+font->height/4+m2.y+font->height/2;
701
-                        y1=body->xywh.y+body->xywh.h-font->height/2;
724
+                        if(is_leftside) {
725
+                                x0=body->xywh.x+font->height/2;
726
+                                x1=body->xywh.x+body->leftsize-font->height/2;
727
+                                y0=body->xywh.y+font->height/4+m2.y+font->height/2;
728
+                                y1=body->xywh.y+body->xywh.h-DEFAULTDIRDATATRIANGLEW-font->height/2;
729
+                        } else {
730
+                                x0=body->xywh.x+body->leftsize+font->height/2;
731
+                                x1=body->xywh.x+body->xywh.w-font->height/2;
732
+                                y0=righty+fontbig->height/2+m2.y+font->height/4;
733
+                                y1=y0+margin*2+font->height-1;
734
+                        }
702 735
                         margin=font->height/4;
703 736
                         for(k=0,x=x0,y=y0;k<dirdata->listing.usedelems;k++) {
704
-                                m2=MeasureTextEx(font->font,dirdata->listing.elems[k]+1,font->height,0);
705
-                                if((x+margin*2+m2.x)>x1)
737
+                                elem=dirdata->listing.elems+k;
738
+                                if(elem->name[0]!='d' || strcmp(elem->name,"d.")==0 || strcmp(elem->name,"d..")==0)
739
+                                        continue;
740
+                                if(y>y1)
741
+                                        continue;
742
+                                m2=MeasureTextEx(font->font,elem->name+1,font->height,0);
743
+                                if((x+margin*2+m2.x)>x1) {
706 744
                                         x=x0,y+=font->height+margin*2+font->height/4;
707
-#warning TODO: store the bounding box of the element
708
-                                DrawRectangleLines(x,y,margin*2+m2.x,margin*2+font->height,((Color){0,0,0,255}));
709
-                                DrawTextEx(font->font,dirdata->listing.elems[k]+1,(Vector2){x+margin,y+margin},font->height,0,(Color){ 65, 65, 65, 255 });
745
+                                        if(y>y1)
746
+                                                continue;
747
+                                }
748
+                                FILLXYWH(elem->leftxywh,x,y,margin*2+m2.x,margin*2+font->height);
749
+                                DrawRectangleLines(UNROLLXYWH(elem->leftxywh),((Color){0,0,0,255}));
750
+                                DrawTextEx(font->font,elem->name+1,(Vector2){x+margin,y+margin},font->height,0,(Color){ 65, 65, 65, 255 });
710 751
                                 x+=margin*2+m2.x+font->height/4;
711 752
                         }
712 753
 
713
-#warning TODO
714
-                        /* draw right side "current" marker inside left side area */
715
-                        DrawTriangle((Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)}, (Vector2){((float)body->xywh.x)+body->leftsize-DEFAULTDIRDATATRIANGLEW,((float)righty)+dirdata->height/2}, (Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)+dirdata->height-1}, (Color){ 168, 168, 168, 255 } );
754
+#warning TODO SHOW FILES
755
+                        /* ...finishing touchs */
756
+                        if(is_leftside) {
757
+                                /* draw right side "current" marker inside left side area */
758
+                                DrawTriangle((Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)}, (Vector2){((float)body->xywh.x)+body->leftsize-DEFAULTDIRDATATRIANGLEW,((float)righty)+dirdata->height/2}, (Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)+dirdata->height-1}, (Color){ 168, 168, 168, 255 } );
759
+                        } else {
760
+                                /* advance to next element */
761
+                                righty+=dirdata->height;
762
+                        }
716 763
                 }
717
-                /* draw right side */
718
-                /* ...bg */
719
-                DrawRectangle(body->xywh.x+body->leftsize,righty,body->xywh.w-body->leftsize, dirdata->height,(i==body->currentdirdata)?((Color){ 168, 168, 168, 255 }):((Color){ 227, 227, 227, 255 }));
720
-                /* ...bottom separator */
721
-                DrawRectangle(body->xywh.x+body->leftsize,righty+dirdata->height-1,body->xywh.w-body->leftsize, 1, (Color){ 221, 221, 221, 255 } );
722
-                /* ...dirname */
723
-                DrawTextEx(fontbig->font
724
-                  ,dirdata->dirname
725
-                  ,(Vector2) {body->xywh.x+body->leftsize+fontbig->height/2,righty+fontbig->height/4}
726
-                  ,fontbig->height
727
-                  ,0
728
-                  ,(Color){ 65, 65, 65, 255 }
729
-                );
730
-                /* advance to next element */
731
-                righty+=dirdata->height;
732 764
         }
733 765
 #if 0
734 766
         /* example from menubar */
... ...
@@ -942,7 +974,7 @@ getcodepoints(int *sizecodepoints)
942 974
 static int
943 975
 strptrcmp(void *a,void *b)
944 976
 {
945
-        return(strcmp(*((char **)a),*((char **)b)));
977
+        return(strcmp(((listingdata_t *)a)->name,((listingdata_t *)b)->name));
946 978
 }
947 979
 
948 980
 int
... ...
@@ -956,6 +988,7 @@ listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort
956 988
         if(listing==NULL)
957 989
                 return(-1); /* sanity check failed */
958 990
         listing->usedelems=listing->usedbuf=0;
991
+        memset(listing->elems,0,sizeof(listingdata_t)*listing->sizeelems);
959 992
         if(pathprefix==NULL && parampath==NULL)
960 993
                 return(-1); /* nothing to fill */
961 994
         snprintf(path,sizeof(path),"%s%s%s",(pathprefix!=NULL)?pathprefix:"",SEP,(parampath!=NULL)?parampath:"");
... ...
@@ -998,12 +1031,13 @@ listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort
998 1031
                 }
999 1032
                 /* check for space for this elem (and get space if necessary) */
1000 1033
                 if(listing->usedelems==listing->sizeelems) {
1001
-                        char **newelems;
1002
-                        if((newelems=realloc(listing->elems,sizeof(char *)*(listing->sizeelems+BLOCKLISTINGELEMS)))==NULL) {
1034
+                        listingdata_t *newelems;
1035
+                        if((newelems=realloc(listing->elems,sizeof(listingdata_t)*(listing->sizeelems+BLOCKLISTINGELEMS)))==NULL) {
1003 1036
                                 closedir(d),d=NULL;
1004 1037
                                 return(-1); /* insuf. mem. */
1005 1038
                         }
1006 1039
                         listing->elems=newelems;
1040
+                        memset(listing->elems+listing->sizeelems,0,sizeof(listingdata_t)*BLOCKLISTINGELEMS);
1007 1041
                         listing->sizeelems+=BLOCKLISTINGELEMS;
1008 1042
                 }
1009 1043
                 /* check for space for this elem data (and get space if necessary) */
... ...
@@ -1021,21 +1055,21 @@ listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort
1021 1055
                         }
1022 1056
                         /* the elem data buffer has a new pointer, fix previous entries */
1023 1057
                         for(i=0;i<listing->usedelems;i++) {
1024
-                                off=(listing->elems[i])-listing->buf;
1025
-                                listing->elems[i]=newbuf+off;
1058
+                                off=(listing->elems[i].name)-listing->buf;
1059
+                                listing->elems[i].name=newbuf+off;
1026 1060
                         }
1027 1061
                         listing->buf=newbuf;
1028 1062
                         listing->sizebuf+=BLOCKLISTINGELEMS;
1029 1063
                 }
1030 1064
                 /* store the data */
1031
-                listing->elems[listing->usedelems++]=listing->buf+listing->usedbuf;
1065
+                listing->elems[listing->usedelems++].name=listing->buf+listing->usedbuf;
1032 1066
                 listing->buf[listing->usedbuf++]=dtype;
1033 1067
                 memcpy(listing->buf+listing->usedbuf,de->d_name,l+1);
1034 1068
                 listing->usedbuf+=l+1;
1035 1069
         }
1036 1070
         closedir(d),d=NULL;
1037 1071
         if(flag_sort)
1038
-                qsort(listing->elems,listing->usedelems,sizeof(char *),(int (*)(const void *, const void *)) strptrcmp);
1072
+                qsort(listing->elems,listing->usedelems,sizeof(listingdata_t ),(int (*)(const void *, const void *)) strptrcmp);
1039 1073
         return(0);
1040 1074
 }
1041 1075
 
Browse code

Draw pane titles and main dir list

Dario Rodriguez authored on 23/02/2025 21:01:31
Showing 1 changed files
... ...
@@ -9,6 +9,7 @@
9 9
  *      20250213 Support sticky drop-down menus.
10 10
  *      20250216 Modularize menu handling.
11 11
  *      20250222 Able to list files.
12
+ *      20250223 Draw pane titles and main dir list.
12 13
  *
13 14
  * Author: Dario Rodriguez dario@darionomono.com
14 15
  * (c) Dario Rodriguez 2025
... ...
@@ -29,13 +30,23 @@
29 30
 #define DEFAULTWIDTH 1280
30 31
 #define DEFAULTHEIGHT 768
31 32
 
33
+#define UTF8DOWNARROW "\xe2\x86\x86" /* U+2186 in UTF-8 */
34
+
32 35
 #define LEFTSIZE 720
33
-#define RIGHTELEMHEIGHT 280
36
+#define DEFAULTDIRDATAHEIGHT 150
37
+#define DEFAULTDIRDATATRIANGLEW 35
38
+
39
+#define FONTSIZE 18
40
+#define FONTBIGSIZE 32
41
+#define FONTHUGESIZE 48
42
+
43
+#define ROOTDIR "/var/www/default/animeshot/"
34 44
 
35 45
 #define SEP "/"
36 46
 
37 47
 #define BLOCKLISTINGBUF 2048
38 48
 #define BLOCKLISTINGELEMS 1024
49
+#define BLOCKDIRDATA 16
39 50
 
40 51
 #ifndef FILLXY
41 52
 #define FILLXY(xywh,valx,valy) (xywh).x=(valx),(xywh).y=(valy)
... ...
@@ -65,7 +76,6 @@ typedef struct font_t {
65 76
         int height;
66 77
 } font_t;
67 78
 
68
-
69 79
 typedef struct menudata_t {
70 80
         char *title;
71 81
         xywh_t xywh;
... ...
@@ -78,8 +88,10 @@ typedef struct menudata_t {
78 88
 } menudata_t;
79 89
 
80 90
 typedef struct menubar_t {
91
+        int height;
81 92
         int sizemenudata;
82 93
         menudata_t **menudata;
94
+        font_t *ptrfont;
83 95
 } menubar_t;
84 96
 
85 97
 typedef struct listing_t {
... ...
@@ -97,33 +109,54 @@ typedef struct dirdata_t {
97 109
         listing_t listing;
98 110
 } dirdata_t;
99 111
 
100
-typedef struct im_t {
101
-        int windowinit;
102
-        int w;
103
-        int h;
112
+typedef struct body_t {
113
+        char *rootdir;
114
+        xywh_t xywh;
115
+        xywh_t backxywh;
116
+        int leftsize;
104 117
         int sizedirdata;
105 118
         dirdata_t **dirdata;
106 119
         int currentdirdata;
107 120
         int leftscrollpos;
108 121
         int rightscrollpos;
122
+        font_t *ptrfont;
123
+        font_t *ptrfontbig;
124
+        font_t *ptrfonthuge;
125
+} body_t;
126
+
127
+typedef struct im_t {
128
+        int windowinit;
129
+        int w;
130
+        int h;
109 131
         menubar_t *menubar;
132
+        body_t *body;
110 133
         font_t *font;
134
+        font_t *fontbig;
135
+        font_t *fonthuge;
111 136
 } im_t;
112 137
 
113 138
 
114
-im_t *im_init(char *menus);
139
+im_t *im_init(char *menus, char *rootdir);
115 140
 void im_free(im_t *im);
116 141
 
117
-font_t *im_font_init(void);
142
+font_t *im_font_init(int size);
118 143
 void im_font_free(font_t *font);
119 144
 
120
-menubar_t *im_menubar_init(char *menus);
145
+menubar_t *im_menubar_init(char *menus, font_t *font);
121 146
 void im_menubar_free(menubar_t *menubar);
122 147
 
123 148
 int im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail, char **sel_menu, char **sel_submenu);
124
-int im_menubar_draw(menubar_t *menubar, font_t *font, int windowwidth, int windowheight);
149
+int im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight);
125 150
 
126
-int listing_get(listing_t *listing, char *path, int flag_sort);
151
+body_t *im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir);
152
+void im_body_free(body_t *body);
153
+
154
+int im_body_add(body_t *body,char *dir);
155
+
156
+int im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail);
157
+int im_body_draw(body_t *body, int windowwidth, int windowheight);
158
+
159
+int listing_get(listing_t *listing, char *pathprefix, char *path, int flag_sort);
127 160
 void listing_freedata(listing_t *listing);
128 161
 
129 162
 int imutil_menu_count(char *menus);
... ...
@@ -144,7 +177,7 @@ main(int argc, char *argv[])
144 177
         int lmbpressed,lmbreleased,lmbdown;
145 178
         int click_avail;
146 179
         char *sel_menu,*sel_submenu;
147
-        if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n"))==NULL) {
180
+        if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n",ROOTDIR))==NULL) {
148 181
                 return(1);
149 182
         }
150 183
         flag_ignorelmb=0;
... ...
@@ -164,16 +197,21 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
164 197
 #endif
165 198
                         }
166 199
                 }
200
+                if(click_avail)
201
+                        im_body_mouse(im->body, mousepos, lmbpressed, lmbreleased, lmbdown, &click_avail);
202
+
203
+
167 204
                 /* draw screen contents */
168 205
                 BeginDrawing();
169 206
                 ClearBackground(RAYWHITE);
170
-                im_menubar_draw(im->menubar,im->font,im->w,im->h);
171
-#if 1
207
+                im_body_draw(im->body,im->w,im->h);
208
+                im_menubar_draw(im->menubar,im->w,im->h);
209
+#if 0
172 210
 {
173 211
  int i,j;
174 212
  Vector2 v2;
175 213
  listing_t listing={0};
176
- if(listing_get(&listing,".." SEP ".",1)==0) {
214
+ if(listing_get(&listing,"..",".",1)==0) {
177 215
    i=2;
178 216
      v2.x=(float) (im->font->height/2);
179 217
      v2.y=(float) ((im->font->height+im->font->height/2)*i+(im->font->height/4));
... ...
@@ -209,14 +247,12 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
209 247
 }
210 248
 
211 249
 im_t *
212
-im_init(char *menus)
250
+im_init(char *menus, char *rootdir)
213 251
 {
214 252
         im_t *im;
215 253
         if(menus==NULL)
216 254
                 return(NULL); /* sanity check failed */
217
-        if((im=calloc(1,sizeof(im_t)))==NULL
218
-          || (im->menubar=im_menubar_init(menus))==NULL
219
-        ) {
255
+        if((im=calloc(1,sizeof(im_t)))==NULL) {
220 256
                 im_free(im),im=NULL;
221 257
                 return(NULL); /* insuf. mem. */
222 258
         }
... ...
@@ -225,35 +261,36 @@ im_init(char *menus)
225 261
         InitWindow((im->w=DEFAULTWIDTH),(im->h=DEFAULTHEIGHT),"Image Mover");
226 262
         im->windowinit=1;
227 263
         SetTargetFPS(30);
228
-        /* init font */
229
-        if((im->font=im_font_init())==NULL) {
264
+        /* init fonts and contents */
265
+        if((im->font=im_font_init(FONTSIZE))==NULL
266
+          || (im->fontbig=im_font_init(FONTBIGSIZE))==NULL
267
+          || (im->fonthuge=im_font_init(FONTHUGESIZE))==NULL
268
+          || (im->menubar=im_menubar_init(menus,im->font))==NULL
269
+          || (im->body=im_body_init(0,im->menubar->height, im->font, im->fontbig, im->fonthuge, LEFTSIZE, rootdir))==NULL
270
+        ) {
230 271
                 im_free(im),im=NULL;
231 272
                 return(NULL); /* insuf. mem. */
232 273
         }
274
+        /* add the starting directory */
275
+        im_body_add(im->body,"/");
233 276
         return(im);
234 277
 }
235 278
 
236 279
 void
237 280
 im_free(im_t *im)
238 281
 {
239
-        int i;
240 282
         if(im==NULL)
241 283
                 return;
242 284
         if(im->menubar!=NULL)
243 285
                 im_menubar_free(im->menubar),im->menubar=NULL;
244
-        if(im->dirdata!=NULL) {
245
-                dirdata_t *dirdata;
246
-                for(i=0;i<im->sizedirdata;i++) {
247
-                        if((dirdata=im->dirdata[i])==NULL)
248
-                                continue;
249
-                        if(dirdata->dirname!=NULL)
250
-                                free(dirdata->dirname),dirdata->dirname=NULL;
251
-                        listing_freedata(&(dirdata->listing));
252
-                }
253
-                free(im->dirdata),im->dirdata=NULL,im->sizedirdata=0;
254
-        }
286
+        if(im->body!=NULL)
287
+                im_body_free(im->body),im->body=NULL;
255 288
         if(im->font!=NULL)
256 289
                 im_font_free(im->font),im->font=NULL;
290
+        if(im->fontbig!=NULL)
291
+                im_font_free(im->fontbig),im->fontbig=NULL;
292
+        if(im->fonthuge!=NULL)
293
+                im_font_free(im->fonthuge),im->fonthuge=NULL;
257 294
 #if 0 /* not working as intended */
258 295
         if(im->windowinit)
259 296
                 CloseWindow(),im->windowinit=0;
... ...
@@ -263,14 +300,14 @@ im_free(im_t *im)
263 300
 }
264 301
 
265 302
 font_t *
266
-im_font_init(void)
303
+im_font_init(int size)
267 304
 {
268 305
         font_t *font;
269 306
         int sizecodepoints;
270 307
         int *codepoints;
271 308
         if((font=calloc(1,sizeof(font_t)))==NULL)
272 309
                 return(NULL); /* insuf. mem. */
273
-        font->height=18;
310
+        font->height=size;
274 311
         codepoints=getcodepoints(&sizecodepoints);
275 312
         font->font=LoadFontFromMemory(".ttf",(const unsigned char *)roboto_regular,sizeof(roboto_regular)-1,font->height,codepoints,sizecodepoints);
276 313
         return(font);
... ...
@@ -281,22 +318,20 @@ im_font_free(font_t *font)
281 318
 {
282 319
         if(font==NULL)
283 320
                 return;
284
-#if 0 /* not working as intended */
285
-        UnloadFont(font->font);
286
-#endif
321
+        /* NOTE: Cannot call UnloadFont(font->font) as the data was not malloc'd; see https://github.com/raysan5/raylib/blob/master/examples/others/embedded_files_loading.c */
287 322
         free(font),font=NULL;
288 323
         return;
289 324
 }
290 325
 
291 326
 menubar_t *
292
-im_menubar_init(char *menus)
327
+im_menubar_init(char *menus, font_t *font)
293 328
 {
294 329
         int i,j;
295 330
         char *str,*substr;
296 331
         int len,sublen;
297 332
         menubar_t *menubar;
298 333
         menudata_t *menudata;
299
-        if(menus==NULL)
334
+        if(menus==NULL || font==NULL)
300 335
                 return(NULL); /* sanity check failed */
301 336
         if((menubar=calloc(1,sizeof(menubar_t)))==NULL
302 337
           || (menubar->sizemenudata=imutil_menu_count(menus))<=0
... ...
@@ -305,6 +340,8 @@ im_menubar_init(char *menus)
305 340
                 im_menubar_free(menubar),menubar=NULL;
306 341
                 return(NULL); /* insuf. mem. */
307 342
         }
343
+        menubar->ptrfont=font;
344
+        menubar->height=font->height+font->height/2;
308 345
         /* init menus */
309 346
         for(i=0;i<menubar->sizemenudata;i++) {
310 347
                 if((menudata=menubar->menudata[i]=calloc(1,sizeof(menudata_t)))==NULL
... ...
@@ -465,12 +502,242 @@ im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbre
465 502
 }
466 503
 
467 504
 int
468
-im_menubar_draw(menubar_t *menubar, font_t *font, int windowwidth, int windowheight)
505
+im_menubar_draw(menubar_t *menubar, int windowwidth, int windowheight)
469 506
 {
470 507
         int i,j,k,x;
471 508
         menudata_t *menudata;
509
+        font_t *font;
510
+        if(menubar==NULL)
511
+                return(-1); /* sanity check failed */
512
+        font=menubar->ptrfont;
513
+        DrawRectangle(0,0,windowwidth, font->height+font->height/2, (Color){ 235, 235, 235, 235 } );
514
+        for(i=0,x=0;i<menubar->sizemenudata;i++) {
515
+                Vector2 v2;
516
+                menudata=menubar->menudata[i];
517
+                v2=MeasureTextEx(font->font,menudata->title,font->height,0);
518
+                FILLXYWH(menudata->xywh,x,0,((int)v2.x)+font->height,font->height+font->height/2);
519
+                v2.x=(float) (menudata->xywh.x+font->height/2);
520
+                v2.y=(float) (menudata->xywh.y+font->height/4);
521
+                DrawTextEx(font->font
522
+                  ,menudata->title
523
+                  ,v2
524
+                  ,font->height
525
+                  ,0
526
+                  ,(Color){ 45, 45, 45, 255 }
527
+                );
528
+                if(menudata->flag_open || menudata->flag_stickyopen) {
529
+                        int underline_height=3;
530
+                        int maxw;
531
+                        DrawRectangle(menudata->xywh.x,menudata->xywh.y+menudata->xywh.h-underline_height,menudata->xywh.w,underline_height, (Color){ 53,132,228,255 } );
532
+                        for(j=0,maxw=0;j<menudata->sizeoptions;j++) {
533
+                                v2=MeasureTextEx(font->font,menudata->options[j],font->height,0);
534
+                                maxw=(((int)(v2.x))>maxw)?((int)(v2.x)):maxw;
535
+                        }
536
+                        maxw=(maxw<(menudata->xywh.w+font->height))?(menudata->xywh.w+font->height):maxw;
537
+                        maxw+=font->height;
538
+                        FILLXYWH(menudata->optionsxywh,menudata->xywh.x+1,menudata->xywh.y+menudata->xywh.h+2,maxw,(font->height+font->height/2)*menudata->sizeoptions);
539
+                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y-2,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y-2,(Color){ 255,255,255,255 } );
540
+                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y,menudata->optionsxywh.x-1,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 255,255,255,255 } );
541
+                        DrawLine(menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 192,192,192,255 } );
542
+                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y+menudata->optionsxywh.h+1,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 192,192,192,255 } );
543
+                        DrawRectangle(menudata->optionsxywh.x,menudata->optionsxywh.y,menudata->optionsxywh.w,menudata->optionsxywh.h,(Color){ 235, 235, 235, 235 });
544
+                        for(k=0;k<menudata->sizeoptions;k++) {
545
+                                Color c;
546
+                                c=(k==menudata->currentoption)?((Color){ 255,255,255,255 }):((Color){ 45, 45, 45, 255 });
547
+                                if(k==menudata->currentoption)
548
+                                        DrawRectangle(menudata->optionsxywh.x+1,menudata->optionsxywh.y+(font->height+(font->height/2))*k,menudata->optionsxywh.w-2,font->height+font->height/2,(Color){ 53,132,228,255 });
549
+                                v2.x=(float) (menudata->optionsxywh.x+font->height/2);
550
+                                v2.y=(float) (menudata->optionsxywh.y+(font->height/4)+(font->height+(font->height/2))*k);
551
+                                DrawTextEx(font->font
552
+                                  ,menudata->options[k]
553
+                                  ,v2
554
+                                  ,font->height
555
+                                  ,0
556
+                                  ,c
557
+                                );
558
+                        }
559
+                } else {
560
+                        FILLXYWH(menudata->optionsxywh,0,0,0,0);
561
+                }
562
+                x=menudata->xywh.x+menudata->xywh.w;
563
+        }
564
+        return(0);
565
+}
566
+
567
+body_t *
568
+im_body_init(int x, int y, font_t *font, font_t *fontbig, font_t *fonthuge, int leftsize, char *rootdir)
569
+{
570
+        body_t *body;
571
+        if(font==NULL || fontbig==NULL || fonthuge==NULL || rootdir==NULL)
572
+                return(NULL); /* sanity check failed */
573
+        if((body=calloc(1,sizeof(body_t)))==NULL
574
+          || (body->rootdir=strdup(rootdir))==NULL
575
+        ) {
576
+                im_body_free(body),body=NULL;
577
+                return(NULL);
578
+        }
579
+        FILLXY(body->xywh,x,y);
580
+        body->leftsize=leftsize;
581
+        body->ptrfont=font;
582
+        body->ptrfontbig=fontbig;
583
+        body->ptrfonthuge=fonthuge;
584
+        return(body);
585
+}
586
+
587
+void
588
+im_body_free(body_t *body)
589
+{
590
+        int i;
591
+        dirdata_t *dirdata;
592
+        if(body==NULL)
593
+                return; /* nothing to do */
594
+        if(body->rootdir!=NULL)
595
+                free(body->rootdir),body->rootdir=NULL;
596
+        if(body->dirdata!=NULL) {
597
+                for(i=0;i<body->sizedirdata;i++) {
598
+                        if((dirdata=body->dirdata[i])==NULL)
599
+                                continue;
600
+                        if(dirdata->dirname!=NULL)
601
+                                free(dirdata->dirname),dirdata->dirname=NULL;
602
+                        listing_freedata(&(dirdata->listing));
603
+                        free(dirdata),dirdata=body->dirdata[i]=NULL;
604
+                }
605
+                free(body->dirdata),body->dirdata=NULL,body->sizedirdata=0;
606
+        }
607
+        free(body),body=NULL;
608
+        return;
609
+}
610
+
611
+int
612
+im_body_add(body_t *body,char *dir)
613
+{
614
+        int i;
615
+        dirdata_t *dirdata;
616
+        if(body==NULL || dir==NULL)
617
+                return(-1); /* sanity check failed */
618
+        for(i=0;i<body->sizedirdata;i++) {
619
+                if(body->dirdata[i]==NULL)
620
+                        break;
621
+        }
622
+        if(i==body->sizedirdata) {
623
+                /* dirdata container full, add more slots */
624
+                dirdata_t **newdirdata;
625
+                if((newdirdata=realloc(body->dirdata,sizeof(dirdata_t *)*(body->sizedirdata+BLOCKDIRDATA)))==NULL)
626
+                        return(-1); /* insuf. mem. */
627
+                body->dirdata=newdirdata;
628
+                memset(body->dirdata+body->sizedirdata,0,sizeof(dirdata_t *)*BLOCKDIRDATA);
629
+                body->sizedirdata+=BLOCKDIRDATA;
630
+        }
631
+        if((dirdata=body->dirdata[i]=calloc(1,sizeof(dirdata_t)))==NULL
632
+          || (dirdata->dirname=strdup(dir))==NULL
633
+        ) {
634
+                if(dirdata!=NULL)
635
+                        free(dirdata),dirdata=body->dirdata[i]=NULL;
636
+                return(-1); /* insuf. mem. */
637
+        }
638
+        dirdata->height=DEFAULTDIRDATAHEIGHT;
639
+        dirdata->dirname=strdup(dir);
640
+        listing_get(&(dirdata->listing),body->rootdir,dir,1);
641
+        return(0);
642
+}
643
+
644
+int
645
+im_body_mouse(body_t *body, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail)
646
+{
647
+#warning TODO
648
+        return(0);
649
+}
650
+
651
+int
652
+im_body_draw(body_t *body, int windowwidth, int windowheight)
653
+{
654
+        int i,x,y,k,margin,righty;
655
+        dirdata_t *dirdata;
656
+        Vector2 v2,m2;
657
+        font_t *font,*fontbig,*fonthuge;
658
+        if(body==NULL)
659
+                return(-1);
660
+        font=body->ptrfont;
661
+        fontbig=body->ptrfontbig;
662
+        fonthuge=body->ptrfonthuge;
663
+        FILLWH(body->xywh,windowwidth-body->xywh.x,windowheight-body->xywh.y);
664
+        FILLXYWH(body->backxywh,0,0,0,0);
665
+        /* draw left side background */
666
+        DrawRectangle(body->xywh.x,body->xywh.y,body->leftsize, body->xywh.h, (Color){ 215, 215, 215, 255 } );
667
+        /* draw right side background */
668
+        DrawRectangle(body->xywh.x+body->leftsize,body->xywh.y,body->xywh.w-body->leftsize, body->xywh.h, (Color){ 227, 227, 227, 255 } );
669
+        for(i=0,y=righty=body->xywh.y;i<body->sizedirdata;i++) {
670
+                if((dirdata=body->dirdata[i])==NULL)
671
+                        continue;
672
+                /* draw left side if appropiate */
673
+                if(i==body->currentdirdata) {
674
+                        int x0,y0,x1,y1;
675
+                        /* draw left side */
676
+                        /* ...back arrow */
677
+                        v2.x=(float) (body->xywh.x+fontbig->height/2);
678
+                        v2.y=(float) (body->xywh.y+fontbig->height/4);
679
+                        m2=MeasureTextEx(fontbig->font,UTF8DOWNARROW,fontbig->height,0);
680
+                        FILLXYWH(body->backxywh,v2.x-fontbig->height/4,v2.y-fontbig->height/8,m2.x+fontbig->height/4,m2.x+fontbig->height/4);
681
+#if 0
682
+DrawTexture(fontbig->font.texture, 0, 0, WHITE); /* font glyphs -- see https://github.com/raysan5/raylib/issues/2022 */
683
+DrawRectangle(UNROLLXYWH(body->backxywh),((Color){ 0,255,0,255 })); /* hit zone */
684
+#endif
685
+                        DrawTextPro(fontbig->font,UTF8DOWNARROW,(Vector2){v2.x+m2.x,v2.y},(Vector2){0,0},90.0,fontbig->height,0,(Color){65,65,65,255});
686
+                        /* ...dirname */
687
+                        m2=MeasureTextEx(fontbig->font,dirdata->dirname,fontbig->height,0);
688
+                        v2.x=(float) (body->xywh.x+fontbig->height/2)+(body->leftsize-(body->xywh.x+fontbig->height)-m2.x)/2;
689
+                        v2.y=(float) (body->xywh.y+fontbig->height/4);
690
+                        DrawTextEx(fontbig->font
691
+                          ,dirdata->dirname
692
+                          ,v2
693
+                          ,fontbig->height
694
+                          ,0
695
+                          ,(Color){ 65, 65, 65, 255 }
696
+                        );
697
+                        /* directories */
698
+                        x0=body->xywh.x+font->height/2;
699
+                        x1=body->xywh.x+body->leftsize-font->height/2;
700
+                        y0=body->xywh.y+font->height/4+m2.y+font->height/2;
701
+                        y1=body->xywh.y+body->xywh.h-font->height/2;
702
+                        margin=font->height/4;
703
+                        for(k=0,x=x0,y=y0;k<dirdata->listing.usedelems;k++) {
704
+                                m2=MeasureTextEx(font->font,dirdata->listing.elems[k]+1,font->height,0);
705
+                                if((x+margin*2+m2.x)>x1)
706
+                                        x=x0,y+=font->height+margin*2+font->height/4;
707
+#warning TODO: store the bounding box of the element
708
+                                DrawRectangleLines(x,y,margin*2+m2.x,margin*2+font->height,((Color){0,0,0,255}));
709
+                                DrawTextEx(font->font,dirdata->listing.elems[k]+1,(Vector2){x+margin,y+margin},font->height,0,(Color){ 65, 65, 65, 255 });
710
+                                x+=margin*2+m2.x+font->height/4;
711
+                        }
712
+
713
+#warning TODO
714
+                        /* draw right side "current" marker inside left side area */
715
+                        DrawTriangle((Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)}, (Vector2){((float)body->xywh.x)+body->leftsize-DEFAULTDIRDATATRIANGLEW,((float)righty)+dirdata->height/2}, (Vector2){((float)body->xywh.x)+body->leftsize,((float)righty)+dirdata->height-1}, (Color){ 168, 168, 168, 255 } );
716
+                }
717
+                /* draw right side */
718
+                /* ...bg */
719
+                DrawRectangle(body->xywh.x+body->leftsize,righty,body->xywh.w-body->leftsize, dirdata->height,(i==body->currentdirdata)?((Color){ 168, 168, 168, 255 }):((Color){ 227, 227, 227, 255 }));
720
+                /* ...bottom separator */
721
+                DrawRectangle(body->xywh.x+body->leftsize,righty+dirdata->height-1,body->xywh.w-body->leftsize, 1, (Color){ 221, 221, 221, 255 } );
722
+                /* ...dirname */
723
+                DrawTextEx(fontbig->font
724
+                  ,dirdata->dirname
725
+                  ,(Vector2) {body->xywh.x+body->leftsize+fontbig->height/2,righty+fontbig->height/4}
726
+                  ,fontbig->height
727
+                  ,0
728
+                  ,(Color){ 65, 65, 65, 255 }
729
+                );
730
+                /* advance to next element */
731
+                righty+=dirdata->height;
732
+        }
733
+#if 0
734
+        /* example from menubar */
735
+        int i,j,k,x;
736
+        menudata_t *menudata;
737
+        font_t *font;
472 738
         if(menubar==NULL || font==NULL)
473 739
                 return(-1); /* sanity check failed */
740
+        font=menubar->ptrfont;
474 741
         DrawRectangle(0,0,windowwidth, font->height+font->height/2, (Color){ 235, 235, 235, 235 } );
475 742
         for(i=0,x=0;i<menubar->sizemenudata;i++) {
476 743
                 Vector2 v2;
... ...
@@ -523,6 +790,8 @@ im_menubar_draw(menubar_t *menubar, font_t *font, int windowwidth, int windowhei
523 790
                 x=menudata->xywh.x+menudata->xywh.w;
524 791
         }
525 792
         return(0);
793
+#endif
794
+        return(0);
526 795
 }
527 796
 
528 797
 int
... ...
@@ -662,6 +931,8 @@ getcodepoints(int *sizecodepoints)
662 931
 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
663 932
 /* Latin-1 Supplement */
664 933
 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
934
+/* down arrow (U+2186 -- this font doesn't have arrows, this is old roman numeral 50 */
935
+(0x21<<8)|0x86,
665 936
 };
666 937
         if(sizecodepoints!=NULL)
667 938
                 *sizecodepoints=(int) (sizeof(codepoints)/sizeof(codepoints[0]));
... ...
@@ -675,18 +946,21 @@ strptrcmp(void *a,void *b)
675 946
 }
676 947
 
677 948
 int
678
-listing_get(listing_t *listing, char *path, int flag_sort)
949
+listing_get(listing_t *listing, char *pathprefix, char *parampath, int flag_sort)
679 950
 {
680 951
         int l;
681 952
         DIR *d;
682 953
         struct dirent *de;
683 954
         unsigned char dtype;
955
+        char path[1024];
684 956
         if(listing==NULL)
685 957
                 return(-1); /* sanity check failed */
686 958
         listing->usedelems=listing->usedbuf=0;
687
-        if(path==NULL)
959
+        if(pathprefix==NULL && parampath==NULL)
688 960
                 return(-1); /* nothing to fill */
689
-        if((d=opendir(".." SEP "."))==NULL)
961
+        snprintf(path,sizeof(path),"%s%s%s",(pathprefix!=NULL)?pathprefix:"",SEP,(parampath!=NULL)?parampath:"");
962
+        path[sizeof(path)-1]='\0';
963
+        if((d=opendir(path))==NULL)
690 964
                 return(-1); /* dir not found */
691 965
         while((de=readdir(d))!=NULL) {
692 966
                 l=strlen(de->d_name);
... ...
@@ -702,7 +976,7 @@ listing_get(listing_t *listing, char *path, int flag_sort)
702 976
                       :'u';
703 977
 #endif
704 978
                 if(dtype=='u') {
705
-                        char stpath[1024];
979
+                        char stpath[2048];
706 980
                         struct stat st;
707 981
                         mode_t m;
708 982
                         snprintf(stpath,sizeof(stpath),"%s%s%s",path,SEP,de->d_name);
Browse code

Able to list files

Dario Rodriguez authored on 22/02/2025 16:22:20
Showing 1 changed files
... ...
@@ -8,6 +8,7 @@
8 8
  *      20250123 Load font.
9 9
  *      20250213 Support sticky drop-down menus.
10 10
  *      20250216 Modularize menu handling.
11
+ *      20250222 Able to list files.
11 12
  *
12 13
  * Author: Dario Rodriguez dario@darionomono.com
13 14
  * (c) Dario Rodriguez 2025
... ...
@@ -18,6 +19,9 @@
18 19
 #include <stdlib.h>
19 20
 #include <unistd.h>
20 21
 #include <string.h>
22
+#include <sys/types.h>
23
+#include <dirent.h>
24
+#include <sys/stat.h>
21 25
 
22 26
 #include "raylib.h"
23 27
 #include "roboto_regular.c"
... ...
@@ -25,6 +29,14 @@
25 29
 #define DEFAULTWIDTH 1280
26 30
 #define DEFAULTHEIGHT 768
27 31
 
32
+#define LEFTSIZE 720
33
+#define RIGHTELEMHEIGHT 280
34
+
35
+#define SEP "/"
36
+
37
+#define BLOCKLISTINGBUF 2048
38
+#define BLOCKLISTINGELEMS 1024
39
+
28 40
 #ifndef FILLXY
29 41
 #define FILLXY(xywh,valx,valy) (xywh).x=(valx),(xywh).y=(valy)
30 42
 #endif
... ...
@@ -70,9 +82,19 @@ typedef struct menubar_t {
70 82
         menudata_t **menudata;
71 83
 } menubar_t;
72 84
 
85
+typedef struct listing_t {
86
+        int sizeelems;
87
+        int usedelems;
88
+        char **elems; /* first byte in the elem is the type, next is the name, i.e. a directory is "dhome" and a file is "f.bashrc" */
89
+        int sizebuf;
90
+        int usedbuf;
91
+        char *buf;
92
+} listing_t;
93
+
73 94
 typedef struct dirdata_t {
74 95
         int height;
75 96
         char *dirname;
97
+        listing_t listing;
76 98
 } dirdata_t;
77 99
 
78 100
 typedef struct im_t {
... ...
@@ -88,6 +110,7 @@ typedef struct im_t {
88 110
         font_t *font;
89 111
 } im_t;
90 112
 
113
+
91 114
 im_t *im_init(char *menus);
92 115
 void im_free(im_t *im);
93 116
 
... ...
@@ -100,6 +123,9 @@ void im_menubar_free(menubar_t *menubar);
100 123
 int im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail, char **sel_menu, char **sel_submenu);
101 124
 int im_menubar_draw(menubar_t *menubar, font_t *font, int windowwidth, int windowheight);
102 125
 
126
+int listing_get(listing_t *listing, char *path, int flag_sort);
127
+void listing_freedata(listing_t *listing);
128
+
103 129
 int imutil_menu_count(char *menus);
104 130
 char *imutil_menu_get(char *menus, int targetn, int *len);
105 131
 int imutil_submenu_count(char *menus);
... ...
@@ -142,6 +168,39 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
142 168
                 BeginDrawing();
143 169
                 ClearBackground(RAYWHITE);
144 170
                 im_menubar_draw(im->menubar,im->font,im->w,im->h);
171
+#if 1
172
+{
173
+ int i,j;
174
+ Vector2 v2;
175
+ listing_t listing={0};
176
+ if(listing_get(&listing,".." SEP ".",1)==0) {
177
+   i=2;
178
+     v2.x=(float) (im->font->height/2);
179
+     v2.y=(float) ((im->font->height+im->font->height/2)*i+(im->font->height/4));
180
+     DrawTextEx(im->font->font
181
+       ,SEP
182
+       ,v2
183
+       ,im->font->height
184
+       ,0
185
+       ,((Color){ 45, 45, 45, 255 })
186
+     );
187
+   for(j=0;j<listing.usedelems;j++) {
188
+     Color c;
189
+     i++;
190
+     c=((Color){ 45, 45, 45, 255 });
191
+     v2.x=(float) (im->font->height/2);
192
+     v2.y=(float) ((im->font->height+im->font->height/2)*i+(im->font->height/4));
193
+     DrawTextEx(im->font->font
194
+       ,listing.elems[j]
195
+       ,v2
196
+       ,im->font->height
197
+       ,0
198
+       ,c
199
+     );
200
+   }
201
+ }
202
+}
203
+#endif
145 204
                 EndDrawing();
146 205
         }
147 206
         CloseWindow();
... ...
@@ -189,6 +248,7 @@ im_free(im_t *im)
189 248
                                 continue;
190 249
                         if(dirdata->dirname!=NULL)
191 250
                                 free(dirdata->dirname),dirdata->dirname=NULL;
251
+                        listing_freedata(&(dirdata->listing));
192 252
                 }
193 253
                 free(im->dirdata),im->dirdata=NULL,im->sizedirdata=0;
194 254
         }
... ...
@@ -608,3 +668,112 @@ getcodepoints(int *sizecodepoints)
608 668
         return(codepoints);
609 669
 }
610 670
 
671
+static int
672
+strptrcmp(void *a,void *b)
673
+{
674
+        return(strcmp(*((char **)a),*((char **)b)));
675
+}
676
+
677
+int
678
+listing_get(listing_t *listing, char *path, int flag_sort)
679
+{
680
+        int l;
681
+        DIR *d;
682
+        struct dirent *de;
683
+        unsigned char dtype;
684
+        if(listing==NULL)
685
+                return(-1); /* sanity check failed */
686
+        listing->usedelems=listing->usedbuf=0;
687
+        if(path==NULL)
688
+                return(-1); /* nothing to fill */
689
+        if((d=opendir(".." SEP "."))==NULL)
690
+                return(-1); /* dir not found */
691
+        while((de=readdir(d))!=NULL) {
692
+                l=strlen(de->d_name);
693
+                dtype='u';
694
+#ifdef _DIRENT_HAVE_D_TYPE
695
+                dtype=(de->d_type==DT_BLK)?'b'
696
+                      :(de->d_type==DT_CHR)?'c'
697
+                      :(de->d_type==DT_DIR)?'d'
698
+                      :(de->d_type==DT_FIFO)?'p'
699
+                      :(de->d_type==DT_LNK)?'l'
700
+                      :(de->d_type==DT_REG)?'f'
701
+                      :(de->d_type==DT_SOCK)?'s'
702
+                      :'u';
703
+#endif
704
+                if(dtype=='u') {
705
+                        char stpath[1024];
706
+                        struct stat st;
707
+                        mode_t m;
708
+                        snprintf(stpath,sizeof(stpath),"%s%s%s",path,SEP,de->d_name);
709
+                        stpath[sizeof(stpath)-1]='\0';
710
+                        if(stat(stpath,&st)==0 && (m=(st.st_mode&S_IFMT))!=0) {
711
+                                dtype=(m==S_IFBLK)?'b'
712
+                                      :(m==S_IFCHR)?'c'
713
+                                      :(m==S_IFDIR)?'d'
714
+                                      :(m==S_IFIFO)?'p'
715
+#ifdef S_IFLNK
716
+                                      :(m==S_IFLNK)?'l'
717
+#endif
718
+                                      :(m==S_IFREG)?'f'
719
+#ifdef S_IFSOCK
720
+                                      :(m==S_IFSOCK)?'s'
721
+#endif
722
+                                      :'u';
723
+                        }
724
+                }
725
+                /* check for space for this elem (and get space if necessary) */
726
+                if(listing->usedelems==listing->sizeelems) {
727
+                        char **newelems;
728
+                        if((newelems=realloc(listing->elems,sizeof(char *)*(listing->sizeelems+BLOCKLISTINGELEMS)))==NULL) {
729
+                                closedir(d),d=NULL;
730
+                                return(-1); /* insuf. mem. */
731
+                        }
732
+                        listing->elems=newelems;
733
+                        listing->sizeelems+=BLOCKLISTINGELEMS;
734
+                }
735
+                /* check for space for this elem data (and get space if necessary) */
736
+                if((listing->sizebuf+l+2)>listing->sizebuf) {
737
+                        int i;
738
+                        char *newbuf;
739
+                        int newsize;
740
+                        int off;
741
+                        newsize=listing->sizebuf+l+2+BLOCKLISTINGBUF-1;
742
+                        newsize/=BLOCKLISTINGBUF;
743
+                        newsize*=BLOCKLISTINGBUF;
744
+                        if((newbuf=realloc(listing->buf,newsize))==NULL) {
745
+                                closedir(d),d=NULL;
746
+                                return(-1); /* insuf. mem. */
747
+                        }
748
+                        /* the elem data buffer has a new pointer, fix previous entries */
749
+                        for(i=0;i<listing->usedelems;i++) {
750
+                                off=(listing->elems[i])-listing->buf;
751
+                                listing->elems[i]=newbuf+off;
752
+                        }
753
+                        listing->buf=newbuf;
754
+                        listing->sizebuf+=BLOCKLISTINGELEMS;
755
+                }
756
+                /* store the data */
757
+                listing->elems[listing->usedelems++]=listing->buf+listing->usedbuf;
758
+                listing->buf[listing->usedbuf++]=dtype;
759
+                memcpy(listing->buf+listing->usedbuf,de->d_name,l+1);
760
+                listing->usedbuf+=l+1;
761
+        }
762
+        closedir(d),d=NULL;
763
+        if(flag_sort)
764
+                qsort(listing->elems,listing->usedelems,sizeof(char *),(int (*)(const void *, const void *)) strptrcmp);
765
+        return(0);
766
+}
767
+
768
+void
769
+listing_freedata(listing_t *listing)
770
+{
771
+        if(listing==NULL)
772
+                return; /* nothing to do */
773
+        if(listing->elems!=NULL)
774
+                free(listing->elems),listing->elems=NULL,listing->sizeelems=listing->usedelems=0;
775
+        if(listing->buf!=NULL)
776
+                free(listing->buf),listing->buf=NULL,listing->sizebuf=listing->usedbuf=0;
777
+        return;
778
+}
779
+
Browse code

Modularize menu handling

Dario Rodriguez authored on 16/02/2025 18:01:21
Showing 1 changed files
... ...
@@ -7,6 +7,7 @@
7 7
  *      20250119 Creation. Menu bar.
8 8
  *      20250123 Load font.
9 9
  *      20250213 Support sticky drop-down menus.
10
+ *      20250216 Modularize menu handling.
10 11
  *
11 12
  * Author: Dario Rodriguez dario@darionomono.com
12 13
  * (c) Dario Rodriguez 2025
... ...
@@ -47,6 +48,12 @@ typedef struct xywh_t {
47 48
         int h;
48 49
 } xywh_t;
49 50
 
51
+typedef struct font_t {
52
+        Font font;
53
+        int height;
54
+} font_t;
55
+
56
+
50 57
 typedef struct menudata_t {
51 58
         char *title;
52 59
         xywh_t xywh;
... ...
@@ -58,29 +65,40 @@ typedef struct menudata_t {
58 65
         int currentoption;
59 66
 } menudata_t;
60 67
 
68
+typedef struct menubar_t {
69
+        int sizemenudata;
70
+        menudata_t **menudata;
71
+} menubar_t;
72
+
61 73
 typedef struct dirdata_t {
62 74
         int height;
63 75
         char *dirname;
64 76
 } dirdata_t;
65 77
 
66 78
 typedef struct im_t {
79
+        int windowinit;
67 80
         int w;
68 81
         int h;
69
-        int sizemenudata;
70
-        menudata_t **menudata;
71 82
         int sizedirdata;
72 83
         dirdata_t **dirdata;
73 84
         int currentdirdata;
74 85
         int leftscrollpos;
75 86
         int rightscrollpos;
76
-        Font font;
77
-        int font_height;
87
+        menubar_t *menubar;
88
+        font_t *font;
78 89
 } im_t;
79 90
 
80 91
 im_t *im_init(char *menus);
81 92
 void im_free(im_t *im);
82 93
 
83
-int imdraw_menus(im_t *im);
94
+font_t *im_font_init(void);
95
+void im_font_free(font_t *font);
96
+
97
+menubar_t *im_menubar_init(char *menus);
98
+void im_menubar_free(menubar_t *menubar);
99
+
100
+int im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail, char **sel_menu, char **sel_submenu);
101
+int im_menubar_draw(menubar_t *menubar, font_t *font, int windowwidth, int windowheight);
84 102
 
85 103
 int imutil_menu_count(char *menus);
86 104
 char *imutil_menu_get(char *menus, int targetn, int *len);
... ...
@@ -97,9 +115,9 @@ main(int argc, char *argv[])
97 115
         im_t *im;
98 116
         Vector2 mousepos;
99 117
         int flag_ignorelmb;
100
-        int i,j;
101 118
         int lmbpressed,lmbreleased,lmbdown;
102
-        int flag_outsideall;
119
+        int click_avail;
120
+        char *sel_menu,*sel_submenu;
103 121
         if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n"))==NULL) {
104 122
                 return(1);
105 123
         }
... ...
@@ -109,69 +127,21 @@ main(int argc, char *argv[])
109 127
                 lmbpressed=IsMouseButtonPressed(0);
110 128
                 lmbreleased=IsMouseButtonReleased(0);
111 129
                 lmbdown=IsMouseButtonDown(0);
112
-                /* check if we have to open a menu */
113
-                flag_outsideall=1;
114
-                for(i=0;i<im->sizemenudata;i++) {
115
-                        int insidetitle,currentoption;
116
-                        insidetitle=is_imutil_insidexywh(mousepos,&(im->menudata[i]->xywh));
117
-                        currentoption=menudata_pos2option(im->menudata[i],mousepos);
118
-                        flag_outsideall=(currentoption!=-1 || insidetitle)?0:flag_outsideall;
119
-                        if(lmbreleased && insidetitle) {
120
-                                for(j=0;j<im->sizemenudata;j++) {
121
-                                        im->menudata[j]->flag_stickyopen=(j==i)?1:0;
122
-                                        im->menudata[j]->flag_open=0;
123
-                                        im->menudata[j]->currentoption=-1;
124
-                                }
125
-                        } else if((lmbpressed || lmbdown) && insidetitle) {
126
-                                for(j=0;j<im->sizemenudata;j++) {
127
-                                        im->menudata[j]->flag_open=(j==i)?1:0;
128
-                                        im->menudata[j]->flag_stickyopen=0;
129
-                                        im->menudata[j]->currentoption=-1;
130
-                                }
131
-                        } else if((lmbdown || im->menudata[i]->flag_stickyopen) && currentoption!=-1) {
132
-                                for(j=0;j<im->sizemenudata;j++) {
133
-                                        if(lmbreleased==0 || j!=i || im->menudata[i]->flag_stickyopen==0) {
134
-                                                im->menudata[j]->flag_open=(j==i)?im->menudata[i]->flag_open:0;
135
-                                                im->menudata[j]->flag_stickyopen=(j==i)?im->menudata[i]->flag_stickyopen:0;
136
-                                                im->menudata[j]->currentoption=(j==i)?currentoption:-1;
137
-                                        } else {
138
-                                                im->menudata[j]->flag_open=0;
139
-                                                im->menudata[j]->flag_stickyopen=0;
140
-                                                im->menudata[j]->currentoption=-1;
130
+                click_avail=1;
131
+                /* process clicks on menus */
132
+                if(click_avail) {
133
+                        sel_menu=sel_submenu=NULL;
134
+                        im_menubar_mouse(im->menubar, mousepos, lmbpressed, lmbreleased, lmbdown, &click_avail, &sel_menu, &sel_submenu);
135
+                        if(sel_menu!=NULL && sel_submenu!=NULL) {
141 136
 #if 1
142
-fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",im->menudata[i]->title,im->menudata[i]->options[currentoption]);
137
+fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",sel_menu,sel_submenu);
143 138
 #endif
144
-                                        }
145
-                                }
146
-                        } else if(im->menudata[i]->flag_stickyopen && currentoption==-1) {
147
-                                if(lmbreleased) {
148
-                                        im->menudata[i]->flag_open=0;
149
-                                        im->menudata[i]->flag_stickyopen=0;
150
-                                }
151
-                                im->menudata[i]->currentoption=-1;
152
-                        } else if(lmbreleased && currentoption!=-1) {
153
-                                for(j=0;j<im->sizemenudata;j++) {
154
-                                        im->menudata[j]->flag_open=0;
155
-                                        im->menudata[j]->flag_stickyopen=0;
156
-                                        im->menudata[j]->currentoption=-1;
157
-                                }
158
-#if 1
159
-fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",im->menudata[i]->title,im->menudata[i]->options[currentoption]);
160
-#endif
161
-                        } else if(lmbdown==0) {
162
-                                im->menudata[i]->flag_open=0;
163
-                                im->menudata[i]->flag_stickyopen=0;
164
-                                im->menudata[i]->currentoption=-1;
165
-                        }
166
-                }
167
-                if(flag_outsideall) {
168
-                        for(j=0;j<im->sizemenudata;j++) {
169
-                                im->menudata[j]->currentoption=-1;
170 139
                         }
171 140
                 }
141
+                /* draw screen contents */
172 142
                 BeginDrawing();
173 143
                 ClearBackground(RAYWHITE);
174
-                imdraw_menus(im);
144
+                im_menubar_draw(im->menubar,im->font,im->w,im->h);
175 145
                 EndDrawing();
176 146
         }
177 147
         CloseWindow();
... ...
@@ -183,51 +153,118 @@ im_t *
183 153
 im_init(char *menus)
184 154
 {
185 155
         im_t *im;
156
+        if(menus==NULL)
157
+                return(NULL); /* sanity check failed */
158
+        if((im=calloc(1,sizeof(im_t)))==NULL
159
+          || (im->menubar=im_menubar_init(menus))==NULL
160
+        ) {
161
+                im_free(im),im=NULL;
162
+                return(NULL); /* insuf. mem. */
163
+        }
164
+        /* init window */
165
+        SetTraceLogLevel(LOG_ERROR);
166
+        InitWindow((im->w=DEFAULTWIDTH),(im->h=DEFAULTHEIGHT),"Image Mover");
167
+        im->windowinit=1;
168
+        SetTargetFPS(30);
169
+        /* init font */
170
+        if((im->font=im_font_init())==NULL) {
171
+                im_free(im),im=NULL;
172
+                return(NULL); /* insuf. mem. */
173
+        }
174
+        return(im);
175
+}
176
+
177
+void
178
+im_free(im_t *im)
179
+{
180
+        int i;
181
+        if(im==NULL)
182
+                return;
183
+        if(im->menubar!=NULL)
184
+                im_menubar_free(im->menubar),im->menubar=NULL;
185
+        if(im->dirdata!=NULL) {
186
+                dirdata_t *dirdata;
187
+                for(i=0;i<im->sizedirdata;i++) {
188
+                        if((dirdata=im->dirdata[i])==NULL)
189
+                                continue;
190
+                        if(dirdata->dirname!=NULL)
191
+                                free(dirdata->dirname),dirdata->dirname=NULL;
192
+                }
193
+                free(im->dirdata),im->dirdata=NULL,im->sizedirdata=0;
194
+        }
195
+        if(im->font!=NULL)
196
+                im_font_free(im->font),im->font=NULL;
197
+#if 0 /* not working as intended */
198
+        if(im->windowinit)
199
+                CloseWindow(),im->windowinit=0;
200
+#endif
201
+        free(im),im=NULL;
202
+        return;
203
+}
204
+
205
+font_t *
206
+im_font_init(void)
207
+{
208
+        font_t *font;
209
+        int sizecodepoints;
210
+        int *codepoints;
211
+        if((font=calloc(1,sizeof(font_t)))==NULL)
212
+                return(NULL); /* insuf. mem. */
213
+        font->height=18;
214
+        codepoints=getcodepoints(&sizecodepoints);
215
+        font->font=LoadFontFromMemory(".ttf",(const unsigned char *)roboto_regular,sizeof(roboto_regular)-1,font->height,codepoints,sizecodepoints);
216
+        return(font);
217
+}
218
+
219
+void
220
+im_font_free(font_t *font)
221
+{
222
+        if(font==NULL)
223
+                return;
224
+#if 0 /* not working as intended */
225
+        UnloadFont(font->font);
226
+#endif
227
+        free(font),font=NULL;
228
+        return;
229
+}
230
+
231
+menubar_t *
232
+im_menubar_init(char *menus)
233
+{
186 234
         int i,j;
187 235
         char *str,*substr;
188 236
         int len,sublen;
237
+        menubar_t *menubar;
189 238
         menudata_t *menudata;
190 239
         if(menus==NULL)
191 240
                 return(NULL); /* sanity check failed */
192
-        if((im=calloc(1,sizeof(im_t)))==NULL
193
-          || (im->sizemenudata=imutil_menu_count(menus))<=0
194
-          || (im->menudata=calloc(im->sizemenudata,sizeof(menudata_t)))==NULL
241
+        if((menubar=calloc(1,sizeof(menubar_t)))==NULL
242
+          || (menubar->sizemenudata=imutil_menu_count(menus))<=0
243
+          || (menubar->menudata=calloc(menubar->sizemenudata,sizeof(menudata_t)))==NULL
195 244
         ) {
196
-                im_free(im),im=NULL;
245
+                im_menubar_free(menubar),menubar=NULL;
197 246
                 return(NULL); /* insuf. mem. */
198 247
         }
199 248
         /* init menus */
200
-        for(i=0;i<im->sizemenudata;i++) {
201
-                if((menudata=im->menudata[i]=calloc(1,sizeof(menudata_t)))==NULL
249
+        for(i=0;i<menubar->sizemenudata;i++) {
250
+                if((menudata=menubar->menudata[i]=calloc(1,sizeof(menudata_t)))==NULL
202 251
                   || (str=imutil_menu_get(menus,i,&len))==NULL
203 252
                   || (menudata->title=imutil_strduplen(str,len))==NULL
204 253
                   || (menudata->sizeoptions=imutil_submenu_count(str))<=0
205 254
                   || (menudata->options=calloc(menudata->sizeoptions,sizeof(char *)))==NULL
206 255
                 ) {
207
-                        im_free(im),im=NULL;
256
+                        im_menubar_free(menubar),menubar=NULL;
208 257
                         return(NULL); /* insuf. mem. */
209 258
                 }
210 259
                 for(j=0;j<menudata->sizeoptions;j++) {
211 260
                         if((substr=imutil_submenu_get(str,j,&sublen))==NULL
212 261
                           || (menudata->options[j]=imutil_strduplen(substr,sublen))==NULL
213 262
                         ) {
214
-                                im_free(im),im=NULL;
263
+                                im_menubar_free(menubar),menubar=NULL;
215 264
                                 return(NULL); /* insuf. mem. */
216 265
                         }
217 266
                 }
218 267
         }
219
-        /* init window */
220
-        SetTraceLogLevel(LOG_ERROR);
221
-        InitWindow((im->w=DEFAULTWIDTH),(im->h=DEFAULTHEIGHT),"Image Mover");
222
-        SetTargetFPS(30);
223
-        /* init font */
224
-        {
225
-                int sizecodepoints;
226
-                int *codepoints;
227
-                im->font_height=18;
228
-                codepoints=getcodepoints(&sizecodepoints);
229
-                im->font=LoadFontFromMemory(".ttf",(const unsigned char *)roboto_regular,sizeof(roboto_regular)-1,im->font_height,codepoints,sizecodepoints);
230
-        }
231 268
 #if 0
232 269
         /* test imutil_menu_xxx */
233 270
         int n,m,l,ml,len,mlen;
... ...
@@ -248,26 +285,26 @@ im_init(char *menus)
248 285
 #endif
249 286
 #if 0
250 287
         /* test menudata */
251
-        for(i=0;i<im->sizemenudata;i++) {
252
-                fprintf(stderr,"menu[%i]:\"%s\"->",i,im->menudata[i]->title);
253
-                for(j=0;j<im->menudata[i]->sizeoptions;j++)
254
-                        fprintf(stderr,"|\"%s\"",im->menudata[i]->options[j]);
288
+        for(i=0;i<menubar->sizemenudata;i++) {
289
+                fprintf(stderr,"menu[%i]:\"%s\"->",i,menubar->menudata[i]->title);
290
+                for(j=0;j<menubar->menudata[i]->sizeoptions;j++)
291
+                        fprintf(stderr,"|\"%s\"",menubar->menudata[i]->options[j]);
255 292
                 fprintf(stderr,"\n");
256 293
         }
257 294
 #endif
258
-        return(im);
295
+        return(menubar);
259 296
 }
260 297
 
261 298
 void
262
-im_free(im_t *im)
299
+im_menubar_free(menubar_t *menubar)
263 300
 {
264 301
         int i,j;
265
-        if(im==NULL)
302
+        menudata_t *menudata;
303
+        if(menubar==NULL)
266 304
                 return;
267
-        if(im->menudata!=NULL) {
268
-                menudata_t *menudata;
269
-                for(i=0;i<im->sizemenudata;i++) {
270
-                        if((menudata=im->menudata[i])==NULL)
305
+        if(menubar->menudata!=NULL) {
306
+                for(i=0;i<menubar->sizemenudata;i++) {
307
+                        if((menudata=menubar->menudata[i])==NULL)
271 308
                                 continue;
272 309
                         if(menudata->title!=NULL)
273 310
                                 free(menudata->title),menudata->title=NULL;
... ...
@@ -278,41 +315,114 @@ im_free(im_t *im)
278 315
                                 }
279 316
                                 free(menudata->options),menudata->options=NULL,menudata->sizeoptions=0;
280 317
                         }
281
-                        free(im->menudata[i]),im->menudata[i]=NULL,menudata=NULL;
318
+                        free(menubar->menudata[i]),menubar->menudata[i]=NULL,menudata=NULL;
282 319
                 }
283
-                free(im->menudata),im->menudata=NULL,im->sizemenudata=0;
320
+                free(menubar->menudata),menubar->menudata=NULL,menubar->sizemenudata=0;
284 321
         }
285
-        if(im->dirdata!=NULL) {
286
-                dirdata_t *dirdata;
287
-                for(i=0;i<im->sizedirdata;i++) {
288
-                        if((dirdata=im->dirdata[i])==NULL)
289
-                                continue;
290
-                        if(dirdata->dirname!=NULL)
291
-                                free(dirdata->dirname),dirdata->dirname=NULL;
322
+        free(menubar),menubar=NULL;
323
+        return;
324
+}
325
+
326
+int
327
+im_menubar_mouse(menubar_t *menubar, Vector2 mousepos, int lmbpressed, int lmbreleased, int lmbdown, int *click_avail, char **sel_menu, char **sel_submenu)
328
+{
329
+        int flag_outsideall;
330
+        int i,j;
331
+        if(menubar==NULL || click_avail==NULL || sel_menu==NULL || sel_submenu==NULL)
332
+                return(-1);
333
+        *click_avail=1;
334
+        *sel_menu=NULL;
335
+        *sel_submenu=NULL;
336
+        flag_outsideall=1;
337
+        for(i=0;i<menubar->sizemenudata;i++) {
338
+                int insidetitle,currentoption;
339
+                insidetitle=is_imutil_insidexywh(mousepos,&(menubar->menudata[i]->xywh));
340
+                currentoption=menudata_pos2option(menubar->menudata[i],mousepos);
341
+                flag_outsideall=(currentoption!=-1 || insidetitle)?0:flag_outsideall;
342
+                if(lmbreleased && insidetitle) {
343
+                        for(j=0;j<menubar->sizemenudata;j++) {
344
+                                menubar->menudata[j]->flag_stickyopen=(j==i)?1:0;
345
+                                menubar->menudata[j]->flag_open=0;
346
+                                menubar->menudata[j]->currentoption=-1;
347
+                        }
348
+                } else if((lmbpressed || lmbdown) && insidetitle) {
349
+                        for(j=0;j<menubar->sizemenudata;j++) {
350
+                                menubar->menudata[j]->flag_open=(j==i)?1:0;
351
+                                menubar->menudata[j]->flag_stickyopen=0;
352
+                                menubar->menudata[j]->currentoption=-1;
353
+                        }
354
+                } else if((lmbdown || menubar->menudata[i]->flag_stickyopen) && currentoption!=-1) {
355
+                        for(j=0;j<menubar->sizemenudata;j++) {
356
+                                if(lmbreleased==0 || j!=i || menubar->menudata[i]->flag_stickyopen==0) {
357
+                                        menubar->menudata[j]->flag_open=(j==i)?menubar->menudata[i]->flag_open:0;
358
+                                        menubar->menudata[j]->flag_stickyopen=(j==i)?menubar->menudata[i]->flag_stickyopen:0;
359
+                                        menubar->menudata[j]->currentoption=(j==i)?currentoption:-1;
360
+                                } else {
361
+                                        menubar->menudata[j]->flag_open=0;
362
+                                        menubar->menudata[j]->flag_stickyopen=0;
363
+                                        menubar->menudata[j]->currentoption=-1;
364
+                                        /* has selected this submenu */
365
+                                        *click_avail=0;
366
+                                        *sel_menu=menubar->menudata[j]->title;
367
+                                        *sel_submenu=menubar->menudata[j]->options[currentoption];
368
+                                }
369
+                        }
370
+                } else if(menubar->menudata[i]->flag_stickyopen && currentoption==-1) {
371
+                        if(lmbreleased) {
372
+                                menubar->menudata[i]->flag_open=0;
373
+                                menubar->menudata[i]->flag_stickyopen=0;
374
+                        }
375
+                        menubar->menudata[i]->currentoption=-1;
376
+                } else if(lmbreleased && currentoption!=-1) {
377
+                        for(j=0;j<menubar->sizemenudata;j++) {
378
+                                menubar->menudata[j]->flag_open=0;
379
+                                menubar->menudata[j]->flag_stickyopen=0;
380
+                                menubar->menudata[j]->currentoption=-1;
381
+                        }
382
+                        /* has selected this submenu */
383
+                        *click_avail=0;
384
+                        *sel_menu=menubar->menudata[i]->title;
385
+                        *sel_submenu=menubar->menudata[i]->options[currentoption];
386
+                } else if(lmbdown==0) {
387
+                        menubar->menudata[i]->flag_open=0;
388
+                        menubar->menudata[i]->flag_stickyopen=0;
389
+                        menubar->menudata[i]->currentoption=-1;
292 390
                 }
293
-                free(im->dirdata),im->dirdata=NULL,im->sizedirdata=0;
294 391
         }
295
-        free(im),im=NULL;
296
-        return;
392
+        if(flag_outsideall) {
393
+                for(j=0;j<menubar->sizemenudata;j++) {
394
+                        menubar->menudata[j]->currentoption=-1;
395
+                }
396
+        }
397
+        /* update click_avail */
398
+        for(j=0;j<menubar->sizemenudata;j++) {
399
+                if(menubar->menudata[j]->flag_open || menubar->menudata[j]->flag_stickyopen) {
400
+                        *click_avail=0;
401
+                        break;
402
+                }
403
+        }
404
+        return(0);
297 405
 }
298 406
 
299 407
 int
300
-imdraw_menus(im_t *im)
408
+im_menubar_draw(menubar_t *menubar, font_t *font, int windowwidth, int windowheight)
301 409
 {
302 410
         int i,j,k,x;
303 411
         menudata_t *menudata;
304
-        DrawRectangle(0,0,im->w, im->font_height+im->font_height/2, (Color){ 235, 235, 235, 235 } );
305
-        for(i=0,x=0;i<im->sizemenudata;i++) {
412
+        if(menubar==NULL || font==NULL)
413
+                return(-1); /* sanity check failed */
414
+        DrawRectangle(0,0,windowwidth, font->height+font->height/2, (Color){ 235, 235, 235, 235 } );
415
+        for(i=0,x=0;i<menubar->sizemenudata;i++) {
306 416
                 Vector2 v2;
307
-                menudata=im->menudata[i];
308
-                v2=MeasureTextEx(im->font,menudata->title,im->font_height,0);
309
-                FILLXYWH(menudata->xywh,x,0,((int)v2.x)+im->font_height,im->font_height+im->font_height/2);
310
-                v2.x=(float) (menudata->xywh.x+im->font_height/2);
311
-                v2.y=(float) (menudata->xywh.y+im->font_height/4);
312
-                DrawTextEx(im->font
417
+                menudata=menubar->menudata[i];
418
+                v2=MeasureTextEx(font->font,menudata->title,font->height,0);
419
+                FILLXYWH(menudata->xywh,x,0,((int)v2.x)+font->height,font->height+font->height/2);
420
+                v2.x=(float) (menudata->xywh.x+font->height/2);
421
+                v2.y=(float) (menudata->xywh.y+font->height/4);
422
+                DrawTextEx(font->font
313 423
                   ,menudata->title
314 424
                   ,v2
315
-                  ,im->font_height
425
+                  ,font->height
316 426
                   ,0
317 427
                   ,(Color){ 45, 45, 45, 255 }
318 428
                 );
... ...
@@ -321,12 +431,12 @@ imdraw_menus(im_t *im)
321 431
                         int maxw;
322 432
                         DrawRectangle(menudata->xywh.x,menudata->xywh.y+menudata->xywh.h-underline_height,menudata->xywh.w,underline_height, (Color){ 53,132,228,255 } );
323 433
                         for(j=0,maxw=0;j<menudata->sizeoptions;j++) {
324
-                                v2=MeasureTextEx(im->font,menudata->options[j],im->font_height,0);
434
+                                v2=MeasureTextEx(font->font,menudata->options[j],font->height,0);
325 435
                                 maxw=(((int)(v2.x))>maxw)?((int)(v2.x)):maxw;
326 436
                         }
327
-                        maxw=(maxw<(menudata->xywh.w+im->font_height))?(menudata->xywh.w+im->font_height):maxw;
328
-                        maxw+=im->font_height;
329
-                        FILLXYWH(menudata->optionsxywh,menudata->xywh.x+1,menudata->xywh.y+menudata->xywh.h+2,maxw,(im->font_height+im->font_height/2)*menudata->sizeoptions);
437
+                        maxw=(maxw<(menudata->xywh.w+font->height))?(menudata->xywh.w+font->height):maxw;
438
+                        maxw+=font->height;
439
+                        FILLXYWH(menudata->optionsxywh,menudata->xywh.x+1,menudata->xywh.y+menudata->xywh.h+2,maxw,(font->height+font->height/2)*menudata->sizeoptions);
330 440
                         DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y-2,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y-2,(Color){ 255,255,255,255 } );
331 441
                         DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y,menudata->optionsxywh.x-1,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 255,255,255,255 } );
332 442
                         DrawLine(menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 192,192,192,255 } );
... ...
@@ -336,13 +446,13 @@ imdraw_menus(im_t *im)
336 446
                                 Color c;
337 447
                                 c=(k==menudata->currentoption)?((Color){ 255,255,255,255 }):((Color){ 45, 45, 45, 255 });
338 448
                                 if(k==menudata->currentoption)
339
-                                        DrawRectangle(menudata->optionsxywh.x+1,menudata->optionsxywh.y+(im->font_height+(im->font_height/2))*k,menudata->optionsxywh.w-2,im->font_height+im->font_height/2,(Color){ 53,132,228,255 });
340
-                                v2.x=(float) (menudata->optionsxywh.x+im->font_height/2);
341
-                                v2.y=(float) (menudata->optionsxywh.y+(im->font_height/4)+(im->font_height+(im->font_height/2))*k);
342
-                                DrawTextEx(im->font
449
+                                        DrawRectangle(menudata->optionsxywh.x+1,menudata->optionsxywh.y+(font->height+(font->height/2))*k,menudata->optionsxywh.w-2,font->height+font->height/2,(Color){ 53,132,228,255 });
450
+                                v2.x=(float) (menudata->optionsxywh.x+font->height/2);
451
+                                v2.y=(float) (menudata->optionsxywh.y+(font->height/4)+(font->height+(font->height/2))*k);
452
+                                DrawTextEx(font->font
343 453
                                   ,menudata->options[k]
344 454
                                   ,v2
345
-                                  ,im->font_height
455
+                                  ,font->height
346 456
                                   ,0
347 457
                                   ,c
348 458
                                 );
... ...
@@ -352,7 +462,6 @@ imdraw_menus(im_t *im)
352 462
                 }
353 463
                 x=menudata->xywh.x+menudata->xywh.w;
354 464
         }
355
-#warning TODO
356 465
         return(0);
357 466
 }
358 467
 
Browse code

Support sticky drop-down menus

Dario Rodriguez authored on 13/02/2025 20:48:37
Showing 1 changed files
... ...
@@ -6,6 +6,7 @@
6 6
  * History:
7 7
  *      20250119 Creation. Menu bar.
8 8
  *      20250123 Load font.
9
+ *      20250213 Support sticky drop-down menus.
9 10
  *
10 11
  * Author: Dario Rodriguez dario@darionomono.com
11 12
  * (c) Dario Rodriguez 2025
... ...
@@ -114,7 +115,7 @@ main(int argc, char *argv[])
114 115
                         int insidetitle,currentoption;
115 116
                         insidetitle=is_imutil_insidexywh(mousepos,&(im->menudata[i]->xywh));
116 117
                         currentoption=menudata_pos2option(im->menudata[i],mousepos);
117
-                        flag_outsideall=(currentoption!=-1)?0:flag_outsideall;
118
+                        flag_outsideall=(currentoption!=-1 || insidetitle)?0:flag_outsideall;
118 119
                         if(lmbreleased && insidetitle) {
119 120
                                 for(j=0;j<im->sizemenudata;j++) {
120 121
                                         im->menudata[j]->flag_stickyopen=(j==i)?1:0;
... ...
@@ -127,12 +128,27 @@ main(int argc, char *argv[])
127 128
                                         im->menudata[j]->flag_stickyopen=0;
128 129
                                         im->menudata[j]->currentoption=-1;
129 130
                                 }
130
-                        } else if(lmbdown && currentoption!=-1) {
131
+                        } else if((lmbdown || im->menudata[i]->flag_stickyopen) && currentoption!=-1) {
131 132
                                 for(j=0;j<im->sizemenudata;j++) {
132
-                                        im->menudata[j]->flag_open=(j==i)?im->menudata[i]->flag_open:0;
133
-                                        im->menudata[j]->flag_stickyopen=(j==i)?im->menudata[i]->flag_stickyopen:0;
134
-                                        im->menudata[j]->currentoption=(j==i)?currentoption:-1;
133
+                                        if(lmbreleased==0 || j!=i || im->menudata[i]->flag_stickyopen==0) {
134
+                                                im->menudata[j]->flag_open=(j==i)?im->menudata[i]->flag_open:0;
135
+                                                im->menudata[j]->flag_stickyopen=(j==i)?im->menudata[i]->flag_stickyopen:0;
136
+                                                im->menudata[j]->currentoption=(j==i)?currentoption:-1;
137
+                                        } else {
138
+                                                im->menudata[j]->flag_open=0;
139
+                                                im->menudata[j]->flag_stickyopen=0;
140
+                                                im->menudata[j]->currentoption=-1;
141
+#if 1
142
+fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",im->menudata[i]->title,im->menudata[i]->options[currentoption]);
143
+#endif
144
+                                        }
135 145
                                 }
146
+                        } else if(im->menudata[i]->flag_stickyopen && currentoption==-1) {
147
+                                if(lmbreleased) {
148
+                                        im->menudata[i]->flag_open=0;
149
+                                        im->menudata[i]->flag_stickyopen=0;
150
+                                }
151
+                                im->menudata[i]->currentoption=-1;
136 152
                         } else if(lmbreleased && currentoption!=-1) {
137 153
                                 for(j=0;j<im->sizemenudata;j++) {
138 154
                                         im->menudata[j]->flag_open=0;
... ...
@@ -145,7 +161,7 @@ fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",im->menudata[i]->title,im->menudata[
145 161
                         } else if(lmbdown==0) {
146 162
                                 im->menudata[i]->flag_open=0;
147 163
                                 im->menudata[i]->flag_stickyopen=0;
148
-                                im->menudata[i]->flag_open=0;
164
+                                im->menudata[i]->currentoption=-1;
149 165
                         }
150 166
                 }
151 167
                 if(flag_outsideall) {
Browse code

Initial commit

Dario Rodriguez authored on 26/01/2025 11:50:16
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,485 @@
1
+/*
2
+ * imgmover.c
3
+ *
4
+ * Simple C application using raylib to move images between directories.
5
+ *
6
+ * History:
7
+ *      20250119 Creation. Menu bar.
8
+ *      20250123 Load font.
9
+ *
10
+ * Author: Dario Rodriguez dario@darionomono.com
11
+ * (c) Dario Rodriguez 2025
12
+ * This program is licensed under the terms of GNU GPL v2.1+
13
+ */
14
+
15
+#include <stdio.h>
16
+#include <stdlib.h>
17
+#include <unistd.h>
18
+#include <string.h>
19
+
20
+#include "raylib.h"
21
+#include "roboto_regular.c"
22
+
23
+#define DEFAULTWIDTH 1280
24
+#define DEFAULTHEIGHT 768
25
+
26
+#ifndef FILLXY
27
+#define FILLXY(xywh,valx,valy) (xywh).x=(valx),(xywh).y=(valy)
28
+#endif
29
+
30
+#ifndef FILLWH
31
+#define FILLWH(xywh,valw,valh) (xywh).w=(valw),(xywh).h=(valh)
32
+#endif
33
+
34
+#ifndef FILLXYWH
35
+#define FILLXYWH(xywh,valx,valy,valw,valh) (xywh).x=(valx),(xywh).y=(valy),(xywh).w=(valw),(xywh).h=(valh)
36
+#endif
37
+
38
+#ifndef UNROLLXYWH
39
+#define UNROLLXYWH(xywh) (xywh).x,(xywh).y,(xywh).w,(xywh).h
40
+#endif
41
+
42
+typedef struct xywh_t {
43
+        int x;
44
+        int y;
45
+        int w;
46
+        int h;
47
+} xywh_t;
48
+
49
+typedef struct menudata_t {
50
+        char *title;
51
+        xywh_t xywh;
52
+        int sizeoptions;
53
+        char **options;
54
+        xywh_t optionsxywh;
55
+        int flag_open;
56
+        int flag_stickyopen;
57
+        int currentoption;
58
+} menudata_t;
59
+
60
+typedef struct dirdata_t {
61
+        int height;
62
+        char *dirname;
63
+} dirdata_t;
64
+
65
+typedef struct im_t {
66
+        int w;
67
+        int h;
68
+        int sizemenudata;
69
+        menudata_t **menudata;
70
+        int sizedirdata;
71
+        dirdata_t **dirdata;
72
+        int currentdirdata;
73
+        int leftscrollpos;
74
+        int rightscrollpos;
75
+        Font font;
76
+        int font_height;
77
+} im_t;
78
+
79
+im_t *im_init(char *menus);
80
+void im_free(im_t *im);
81
+
82
+int imdraw_menus(im_t *im);
83
+
84
+int imutil_menu_count(char *menus);
85
+char *imutil_menu_get(char *menus, int targetn, int *len);
86
+int imutil_submenu_count(char *menus);
87
+char *imutil_submenu_get(char *menus, int targetn, int *len);
88
+char *imutil_strduplen(char *str, int len);
89
+int is_imutil_insidexywh(Vector2 pos, xywh_t *xywh);
90
+int menudata_pos2option(menudata_t *menudata, Vector2 pos);
91
+int *getcodepoints(int *sizecodepoints);
92
+
93
+int
94
+main(int argc, char *argv[])
95
+{
96
+        im_t *im;
97
+        Vector2 mousepos;
98
+        int flag_ignorelmb;
99
+        int i,j;
100
+        int lmbpressed,lmbreleased,lmbdown;
101
+        int flag_outsideall;
102
+        if((im=im_init("Fichero\nAjustes\nSalir\n\nEditar\nNuevo directorio\n\nAyuda\nInformación sobre el programa\n\n"))==NULL) {
103
+                return(1);
104
+        }
105
+        flag_ignorelmb=0;
106
+        while(!WindowShouldClose()) {
107
+                mousepos=GetMousePosition();
108
+                lmbpressed=IsMouseButtonPressed(0);
109
+                lmbreleased=IsMouseButtonReleased(0);
110
+                lmbdown=IsMouseButtonDown(0);
111
+                /* check if we have to open a menu */
112
+                flag_outsideall=1;
113
+                for(i=0;i<im->sizemenudata;i++) {
114
+                        int insidetitle,currentoption;
115
+                        insidetitle=is_imutil_insidexywh(mousepos,&(im->menudata[i]->xywh));
116
+                        currentoption=menudata_pos2option(im->menudata[i],mousepos);
117
+                        flag_outsideall=(currentoption!=-1)?0:flag_outsideall;
118
+                        if(lmbreleased && insidetitle) {
119
+                                for(j=0;j<im->sizemenudata;j++) {
120
+                                        im->menudata[j]->flag_stickyopen=(j==i)?1:0;
121
+                                        im->menudata[j]->flag_open=0;
122
+                                        im->menudata[j]->currentoption=-1;
123
+                                }
124
+                        } else if((lmbpressed || lmbdown) && insidetitle) {
125
+                                for(j=0;j<im->sizemenudata;j++) {
126
+                                        im->menudata[j]->flag_open=(j==i)?1:0;
127
+                                        im->menudata[j]->flag_stickyopen=0;
128
+                                        im->menudata[j]->currentoption=-1;
129
+                                }
130
+                        } else if(lmbdown && currentoption!=-1) {
131
+                                for(j=0;j<im->sizemenudata;j++) {
132
+                                        im->menudata[j]->flag_open=(j==i)?im->menudata[i]->flag_open:0;
133
+                                        im->menudata[j]->flag_stickyopen=(j==i)?im->menudata[i]->flag_stickyopen:0;
134
+                                        im->menudata[j]->currentoption=(j==i)?currentoption:-1;
135
+                                }
136
+                        } else if(lmbreleased && currentoption!=-1) {
137
+                                for(j=0;j<im->sizemenudata;j++) {
138
+                                        im->menudata[j]->flag_open=0;
139
+                                        im->menudata[j]->flag_stickyopen=0;
140
+                                        im->menudata[j]->currentoption=-1;
141
+                                }
142
+#if 1
143
+fprintf(stderr,"SELECTED: \"%s\"->\"%s\"\n",im->menudata[i]->title,im->menudata[i]->options[currentoption]);
144
+#endif
145
+                        } else if(lmbdown==0) {
146
+                                im->menudata[i]->flag_open=0;
147
+                                im->menudata[i]->flag_stickyopen=0;
148
+                                im->menudata[i]->flag_open=0;
149
+                        }
150
+                }
151
+                if(flag_outsideall) {
152
+                        for(j=0;j<im->sizemenudata;j++) {
153
+                                im->menudata[j]->currentoption=-1;
154
+                        }
155
+                }
156
+                BeginDrawing();
157
+                ClearBackground(RAYWHITE);
158
+                imdraw_menus(im);
159
+                EndDrawing();
160
+        }
161
+        CloseWindow();
162
+        im_free(im),im=NULL;
163
+        return(0);
164
+}
165
+
166
+im_t *
167
+im_init(char *menus)
168
+{
169
+        im_t *im;
170
+        int i,j;
171
+        char *str,*substr;
172
+        int len,sublen;
173
+        menudata_t *menudata;
174
+        if(menus==NULL)
175
+                return(NULL); /* sanity check failed */
176
+        if((im=calloc(1,sizeof(im_t)))==NULL
177
+          || (im->sizemenudata=imutil_menu_count(menus))<=0
178
+          || (im->menudata=calloc(im->sizemenudata,sizeof(menudata_t)))==NULL
179
+        ) {
180
+                im_free(im),im=NULL;
181
+                return(NULL); /* insuf. mem. */
182
+        }
183
+        /* init menus */
184
+        for(i=0;i<im->sizemenudata;i++) {
185
+                if((menudata=im->menudata[i]=calloc(1,sizeof(menudata_t)))==NULL
186
+                  || (str=imutil_menu_get(menus,i,&len))==NULL
187
+                  || (menudata->title=imutil_strduplen(str,len))==NULL
188
+                  || (menudata->sizeoptions=imutil_submenu_count(str))<=0
189
+                  || (menudata->options=calloc(menudata->sizeoptions,sizeof(char *)))==NULL
190
+                ) {
191
+                        im_free(im),im=NULL;
192
+                        return(NULL); /* insuf. mem. */
193
+                }
194
+                for(j=0;j<menudata->sizeoptions;j++) {
195
+                        if((substr=imutil_submenu_get(str,j,&sublen))==NULL
196
+                          || (menudata->options[j]=imutil_strduplen(substr,sublen))==NULL
197
+                        ) {
198
+                                im_free(im),im=NULL;
199
+                                return(NULL); /* insuf. mem. */
200
+                        }
201
+                }
202
+        }
203
+        /* init window */
204
+        SetTraceLogLevel(LOG_ERROR);
205
+        InitWindow((im->w=DEFAULTWIDTH),(im->h=DEFAULTHEIGHT),"Image Mover");
206
+        SetTargetFPS(30);
207
+        /* init font */
208
+        {
209
+                int sizecodepoints;
210
+                int *codepoints;
211
+                im->font_height=18;
212
+                codepoints=getcodepoints(&sizecodepoints);
213
+                im->font=LoadFontFromMemory(".ttf",(const unsigned char *)roboto_regular,sizeof(roboto_regular)-1,im->font_height,codepoints,sizecodepoints);
214
+        }
215
+#if 0
216
+        /* test imutil_menu_xxx */
217
+        int n,m,l,ml,len,mlen;
218
+        char *ptr,*mptr;
219
+        for(n=0,l=imutil_menu_count(menus);n<l;n++) {
220
+                ptr=imutil_menu_get(menus,n,&len);
221
+                fprintf(stderr,"menu[%i]:\"",n);
222
+                fwrite(ptr,1,len,stderr);
223
+                fprintf(stderr,"\"->");
224
+                for(m=0,ml=imutil_submenu_count(ptr);m<ml;m++) {
225
+                        mptr=imutil_submenu_get(ptr,m,&mlen);
226
+                        fprintf(stderr,"|\"");
227
+                        fwrite(mptr,1,mlen,stderr);
228
+                        fprintf(stderr,"\"");
229
+                }
230
+                fprintf(stderr,"\n");
231
+        }
232
+#endif
233
+#if 0
234
+        /* test menudata */
235
+        for(i=0;i<im->sizemenudata;i++) {
236
+                fprintf(stderr,"menu[%i]:\"%s\"->",i,im->menudata[i]->title);
237
+                for(j=0;j<im->menudata[i]->sizeoptions;j++)
238
+                        fprintf(stderr,"|\"%s\"",im->menudata[i]->options[j]);
239
+                fprintf(stderr,"\n");
240
+        }
241
+#endif
242
+        return(im);
243
+}
244
+
245
+void
246
+im_free(im_t *im)
247
+{
248
+        int i,j;
249
+        if(im==NULL)
250
+                return;
251
+        if(im->menudata!=NULL) {
252
+                menudata_t *menudata;
253
+                for(i=0;i<im->sizemenudata;i++) {
254
+                        if((menudata=im->menudata[i])==NULL)
255
+                                continue;
256
+                        if(menudata->title!=NULL)
257
+                                free(menudata->title),menudata->title=NULL;
258
+                        if(menudata->options!=NULL) {
259
+                                for(j=0;j<menudata->sizeoptions;j++) {
260
+                                        if(menudata->options[j]!=NULL)
261
+                                                free(menudata->options[j]),menudata->options[j]=NULL;
262
+                                }
263
+                                free(menudata->options),menudata->options=NULL,menudata->sizeoptions=0;
264
+                        }
265
+                        free(im->menudata[i]),im->menudata[i]=NULL,menudata=NULL;
266
+                }
267
+                free(im->menudata),im->menudata=NULL,im->sizemenudata=0;
268
+        }
269
+        if(im->dirdata!=NULL) {
270
+                dirdata_t *dirdata;
271
+                for(i=0;i<im->sizedirdata;i++) {
272
+                        if((dirdata=im->dirdata[i])==NULL)
273
+                                continue;
274
+                        if(dirdata->dirname!=NULL)
275
+                                free(dirdata->dirname),dirdata->dirname=NULL;
276
+                }
277
+                free(im->dirdata),im->dirdata=NULL,im->sizedirdata=0;
278
+        }
279
+        free(im),im=NULL;
280
+        return;
281
+}
282
+
283
+int
284
+imdraw_menus(im_t *im)
285
+{
286
+        int i,j,k,x;
287
+        menudata_t *menudata;
288
+        DrawRectangle(0,0,im->w, im->font_height+im->font_height/2, (Color){ 235, 235, 235, 235 } );
289
+        for(i=0,x=0;i<im->sizemenudata;i++) {
290
+                Vector2 v2;
291
+                menudata=im->menudata[i];
292
+                v2=MeasureTextEx(im->font,menudata->title,im->font_height,0);
293
+                FILLXYWH(menudata->xywh,x,0,((int)v2.x)+im->font_height,im->font_height+im->font_height/2);
294
+                v2.x=(float) (menudata->xywh.x+im->font_height/2);
295
+                v2.y=(float) (menudata->xywh.y+im->font_height/4);
296
+                DrawTextEx(im->font
297
+                  ,menudata->title
298
+                  ,v2
299
+                  ,im->font_height
300
+                  ,0
301
+                  ,(Color){ 45, 45, 45, 255 }
302
+                );
303
+                if(menudata->flag_open || menudata->flag_stickyopen) {
304
+                        int underline_height=3;
305
+                        int maxw;
306
+                        DrawRectangle(menudata->xywh.x,menudata->xywh.y+menudata->xywh.h-underline_height,menudata->xywh.w,underline_height, (Color){ 53,132,228,255 } );
307
+                        for(j=0,maxw=0;j<menudata->sizeoptions;j++) {
308
+                                v2=MeasureTextEx(im->font,menudata->options[j],im->font_height,0);
309
+                                maxw=(((int)(v2.x))>maxw)?((int)(v2.x)):maxw;
310
+                        }
311
+                        maxw=(maxw<(menudata->xywh.w+im->font_height))?(menudata->xywh.w+im->font_height):maxw;
312
+                        maxw+=im->font_height;
313
+                        FILLXYWH(menudata->optionsxywh,menudata->xywh.x+1,menudata->xywh.y+menudata->xywh.h+2,maxw,(im->font_height+im->font_height/2)*menudata->sizeoptions);
314
+                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y-2,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y-2,(Color){ 255,255,255,255 } );
315
+                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y,menudata->optionsxywh.x-1,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 255,255,255,255 } );
316
+                        DrawLine(menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 192,192,192,255 } );
317
+                        DrawLine(menudata->optionsxywh.x-1,menudata->optionsxywh.y+menudata->optionsxywh.h+1,menudata->optionsxywh.x+menudata->optionsxywh.w+2,menudata->optionsxywh.y+menudata->optionsxywh.h+1,(Color){ 192,192,192,255 } );
318
+                        DrawRectangle(menudata->optionsxywh.x,menudata->optionsxywh.y,menudata->optionsxywh.w,menudata->optionsxywh.h,(Color){ 235, 235, 235, 235 });
319
+                        for(k=0;k<menudata->sizeoptions;k++) {
320
+                                Color c;
321
+                                c=(k==menudata->currentoption)?((Color){ 255,255,255,255 }):((Color){ 45, 45, 45, 255 });
322
+                                if(k==menudata->currentoption)
323
+                                        DrawRectangle(menudata->optionsxywh.x+1,menudata->optionsxywh.y+(im->font_height+(im->font_height/2))*k,menudata->optionsxywh.w-2,im->font_height+im->font_height/2,(Color){ 53,132,228,255 });
324
+                                v2.x=(float) (menudata->optionsxywh.x+im->font_height/2);
325
+                                v2.y=(float) (menudata->optionsxywh.y+(im->font_height/4)+(im->font_height+(im->font_height/2))*k);
326
+                                DrawTextEx(im->font
327
+                                  ,menudata->options[k]
328
+                                  ,v2
329
+                                  ,im->font_height
330
+                                  ,0
331
+                                  ,c
332
+                                );
333
+                        }
334
+                } else {
335
+                        FILLXYWH(menudata->optionsxywh,0,0,0,0);
336
+                }
337
+                x=menudata->xywh.x+menudata->xywh.w;
338
+        }
339
+#warning TODO
340
+        return(0);
341
+}
342
+
343
+int
344
+imutil_menu_count(char *menus)
345
+{
346
+        int n;
347
+        char *ptr,*next;
348
+        if(menus==NULL)
349
+                return(0); /* sanity check error */
350
+        for(ptr=menus,n=0;(next=strchr(ptr,'\n'))!=NULL;ptr=next+1) {
351
+                if(next[1]=='\n') {
352
+                        next++;
353
+                        n++;
354
+                }
355
+        }
356
+        return(n);
357
+}
358
+
359
+char *
360
+imutil_menu_get(char *menus, int targetn, int *len)
361
+{
362
+        int n;
363
+        char *ptr,*next,*end;
364
+        int is_title;
365
+        if(len!=NULL)
366
+                *len=0;
367
+        if(menus==NULL || targetn<0)
368
+                return(NULL); /* sanity check error */
369
+        end=menus+strlen(menus);
370
+        for(ptr=menus,is_title=1,n=0;(next=strchr(ptr,'\n'))!=NULL;ptr=next+1) {
371
+                if(targetn==n && is_title==1) {
372
+                        if(len!=NULL)
373
+                                *len=next-ptr;
374
+                        return(ptr); /* found, return start of menu string */
375
+                }
376
+                is_title=0;
377
+                if(next[1]=='\n') {
378
+                        n++;
379
+                        next++;
380
+                        is_title=1;
381
+                }
382
+        }
383
+        return(end); /* not found, return end of menus */
384
+}
385
+
386
+int
387
+imutil_submenu_count(char *menus)
388
+{
389
+        int subn;
390
+        char *ptr,*next;
391
+        if(menus==NULL)
392
+                return(0); /* sanity check error */
393
+        next=strchr(menus,'\n');
394
+        if(next==NULL)
395
+                return(0); /* no title */
396
+        for(subn=0,ptr=next+1;(next=strchr(ptr,'\n'))!=NULL;ptr=next+1) {
397
+                subn++;
398
+                if(next[1]=='\n')
399
+                        break;
400
+        }
401
+        return(subn);
402
+}
403
+
404
+char *
405
+imutil_submenu_get(char *menus, int targetsubn, int *len)
406
+{
407
+        char *ptr,*next,*end;
408
+        int subn;
409
+        if(len!=NULL)
410
+                *len=0;
411
+        if(menus==NULL || targetsubn<0)
412
+                return(NULL); /* sanity check error */
413
+        end=menus+strlen(menus);
414
+        next=strchr(menus,'\n');
415
+        if(next==NULL)
416
+                return(end); /* no title */
417
+        for(ptr=next+1,subn=0;(next=strchr(ptr,'\n'))!=NULL;ptr=next+1,subn++) {
418
+                if(targetsubn==subn) {
419
+                        if(len!=NULL)
420
+                                *len=next-ptr;
421
+                        return(ptr);
422
+                }
423
+                if(next[1]=='\n')
424
+                        break; /* "\n\n" marks the end of submenus */
425
+        }
426
+        return(end);
427
+}
428
+
429
+char *
430
+imutil_strduplen(char *str, int len)
431
+{
432
+        char *res;
433
+        if(len<0 || (str==NULL && len!=0))
434
+                return(NULL);
435
+        if((res=malloc(len+1))==NULL)
436
+                return(NULL);
437
+        memcpy(res,str,len);
438
+        res[len]='\0';
439
+        return(res);
440
+}
441
+
442
+int
443
+is_imutil_insidexywh(Vector2 pos, xywh_t *xywh)
444
+{
445
+        if(xywh==NULL)
446
+                return(0); /* sanity check error */
447
+        if(pos.x>=(float)(xywh->x)
448
+          && pos.x<=(float)(xywh->x+xywh->w)
449
+          && pos.y>=(float)(xywh->y)
450
+          && pos.y<=(float)(xywh->y+xywh->h)
451
+        ) {
452
+                return(1);
453
+        }
454
+        return(0);
455
+}
456
+
457
+int
458
+menudata_pos2option(menudata_t *menudata, Vector2 pos)
459
+{
460
+        int n,h;
461
+        if(menudata==NULL
462
+          || (menudata->flag_open==0 && menudata->flag_stickyopen==0)
463
+          || is_imutil_insidexywh(pos, &(menudata->optionsxywh))==0
464
+        ) {
465
+                return(-1);
466
+        }
467
+        h=(menudata->sizeoptions==0)?0:menudata->optionsxywh.h/menudata->sizeoptions;
468
+        n=(((int)pos.y)-menudata->optionsxywh.y)/h;
469
+        return(n);
470
+}
471
+
472
+int *
473
+getcodepoints(int *sizecodepoints)
474
+{
475
+        static int codepoints[]={
476
+/* Basic Latin */
477
+32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
478
+/* Latin-1 Supplement */
479
+160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
480
+};
481
+        if(sizecodepoints!=NULL)
482
+                *sizecodepoints=(int) (sizeof(codepoints)/sizeof(codepoints[0]));
483
+        return(codepoints);
484
+}
485
+