1 module unde.marks; 2 3 import unde.global_state; 4 import unde.lib; 5 import unde.font; 6 import unde.path_mnt; 7 import unde.viewers.image_viewer.lib; 8 import unde.viewers.text_viewer.lib; 9 import unde.slash; 10 11 version (Windows) 12 { 13 import unde.file_manager.find_path; 14 } 15 16 import berkeleydb.all; 17 18 import derelict.sdl2.sdl; 19 import derelict.sdl2.ttf; 20 21 import std.math; 22 import std.stdio; 23 import std..string; 24 import std.conv; 25 26 27 public DRect 28 get_rectsize_for_path(GlobalState gs, PathMnt path, string full_path, 29 DRect apply_rect, SortType sort = SortType.ByName) 30 { 31 bool pmnt; 32 Dbt key, data; 33 if (path in gs.lsblk) 34 { 35 string path0 = path.get_key(gs.lsblk); 36 key = path0; 37 auto res = gs.db_map.get(null, &key, &data); 38 if (res == 0) 39 { 40 RectSize rectsize; 41 rectsize = data.to!(RectSize); 42 apply_rect = rectsize.rect(sort).apply(apply_rect); 43 } 44 else 45 { 46 version(Windows) 47 { 48 if (path.length == 2) 49 { 50 DRect rect = get_drect_of_drives(gs, path); 51 apply_rect = rect.apply(apply_rect); 52 } 53 } 54 55 { 56 // TODO: Created mount point, rescan up path 57 } 58 } 59 60 pmnt = true; 61 } 62 63 try 64 { 65 path.update(gs.lsblk); 66 } 67 catch (Exception e) 68 { 69 return DRect(); 70 } 71 72 string path0 = path.get_key(gs.lsblk); 73 key = path0; 74 //writefln("GET %s", path0.replace("\0", SL)); 75 auto res = gs.db_map.get(null, &key, &data); 76 version(Windows) 77 { 78 if (path == SL) res = 0; 79 } 80 81 if (res == 0) 82 { 83 RectSize rectsize; 84 version(Windows) 85 { 86 if (path == SL) 87 { 88 DRect full_rect = DRect(0, 0, 1024*1024, 1024*1024); 89 rectsize = RectSize(full_rect, full_rect, full_rect); 90 } 91 else 92 rectsize = data.to!(RectSize); 93 } 94 else 95 { 96 rectsize = data.to!(RectSize); 97 } 98 rectsize.rect(sort) = rectsize.rect(sort).apply(apply_rect); 99 100 //writefln("path=%s, full_path=%s", path, full_path); 101 if (path == full_path) 102 { 103 return rectsize.rect(sort); 104 } 105 106 string next; 107 bool found = false; 108 version (Windows) 109 { 110 if (path == SL && full_path[1] == ':') 111 { 112 next = full_path[0..2]; 113 found = true; 114 } 115 } 116 if (!found) 117 { 118 auto after_path = full_path[path.length+1..$]; 119 if (path == SL) after_path = full_path[1..$]; 120 //writefln("after_path=%s", after_path); 121 if (after_path.indexOf(SL) > 0) 122 next = path ~ SL ~ after_path[0..after_path.indexOf(SL)]; 123 else 124 next = path ~ SL ~ after_path; 125 if (path == SL) next = next[1..$]; 126 } 127 //writefln("next=%s", next); 128 129 auto drect = get_rectsize_for_path(gs, path.next(next), full_path, rectsize.rect(sort), rectsize.sort); 130 return drect; 131 } 132 return DRect(); 133 } 134 135 void draw_marks(GlobalState gs, ref CoordinatesPlusScale surf) 136 { 137 //unmark(gs, "L"); 138 foreach(char m; 'A'..('Z'+1)) 139 { 140 Dbt key = m; 141 Dbt data; 142 143 auto res = gs.db_marks.get(null, &key, &data); 144 if (res == 0) 145 { 146 Mark mark = data.to!(Mark); 147 string path = from_char_array(mark.path); 148 string uuid = path[0..path.indexOf("\0")]; 149 150 string full_path = null; 151 foreach(mount_point, lsblk_info; gs.lsblk) 152 { 153 if (lsblk_info.uuid == uuid) 154 { 155 full_path = mount_point ~ path[path.indexOf("\0")..$].replace("\0", SL); 156 if (mount_point == SL) full_path = full_path[1..$]; 157 break; 158 } 159 } 160 161 if (full_path) 162 { 163 auto apply_rect = DRect(0, 0, 1024*1024, 1024*1024); 164 auto drect = get_rectsize_for_path(gs, PathMnt(gs.lsblk, SL), full_path, apply_rect); 165 166 SDL_Rect on_surf = drect.to_screen(surf); 167 SDL_Rect on_screen = drect.to_screen(gs.screen); 168 //writefln("%s: %s", m, full_path); 169 //writefln("SDL_Rect: %s", on_screen); 170 //writefln("Mark screen_rect: %s", mark.screen_rect); 171 172 if (on_screen.w <= mark.screen_rect.w && on_screen.h <= mark.screen_rect.h) 173 { 174 double xrelation = cast(double)(gs.screen.w/2 - mark.screen_rect.x) / (mark.screen_rect.x + mark.screen_rect.w - gs.screen.w/2); 175 double yrelation = cast(double)(gs.screen.h/2 - mark.screen_rect.y) / (mark.screen_rect.y + mark.screen_rect.h - gs.screen.h/2); 176 177 //xrelation = X / (on_screen.w - X); 178 //xrelation*on_screen.w = xrelation*X + X 179 180 int x = cast(int)( on_surf.x + xrelation*on_surf.w/(xrelation+1) ); 181 int y = cast(int)( on_surf.y + yrelation*on_surf.h/(yrelation+1) ); 182 183 //writefln("%dx%d", x, y); 184 185 auto tt1 = gs.text_viewer.font.get_char_from_cache( 186 "⬤", 10, SDL_Color(0x00, 0xFF, 0xFF, 0x80)); 187 auto tt2 = gs.text_viewer.font.get_char_from_cache( 188 "◯", 10, SDL_Color(0x00, 0x00, 0x00, 0xFF)); 189 auto tt3 = gs.text_viewer.font.get_char_from_cache( 190 ""~m, 9, SDL_Color(0x00, 0x00, 0x00, 0xFF)); 191 192 SDL_Rect rect1 = SDL_Rect(x-tt1.w/2, y-tt1.h/2, 193 tt1.w, tt1.h); 194 SDL_Rect rect2 = SDL_Rect(x-tt2.w/2, y-tt2.h/2, 195 tt2.w, tt2.h); 196 SDL_Rect rect3 = SDL_Rect(x-tt3.w/2, y-tt3.h/2, 197 tt3.w, tt3.h); 198 199 auto r = SDL_RenderCopy(gs.renderer, tt1.texture, 200 null, &rect1); 201 if (r < 0) 202 { 203 writefln( "draw_marks(): Error while render copy 1: %s", 204 SDL_GetError().to!string() ); 205 } 206 207 r = SDL_RenderCopy(gs.renderer, tt2.texture, 208 null, &rect2); 209 if (r < 0) 210 { 211 writefln( "draw_marks(): Error while render copy 2: %s", 212 SDL_GetError().to!string() ); 213 } 214 215 r = SDL_RenderCopy(gs.renderer, tt3.texture, 216 null, &rect3); 217 if (r < 0) 218 { 219 writefln( "draw_marks(): Error while render copy 3: %s", SDL_GetError().to!string() ); 220 } 221 } 222 } 223 } 224 } 225 } 226 227 void remark_desktop(GlobalState gs) 228 { 229 static CoordinatesPlusScale old_screen; 230 static State old_state; 231 static string old_path; 232 static long old_offset; 233 234 bool remark = false; 235 if (gs.screen != old_screen || gs.state != old_state) 236 { 237 remark = true; 238 old_screen = gs.screen; 239 old_state = gs.state; 240 } 241 else if (gs.screen == old_screen && gs.state == old_state && 242 (gs.state == State.ImageViewer || gs.state == State.TextViewer)) 243 { 244 string path; 245 long offset; 246 if (gs.state == State.ImageViewer) 247 { 248 path = gs.image_viewer.path.get_key(gs.lsblk); 249 offset = old_offset; 250 } 251 else 252 { 253 path = gs.text_viewer.path.get_key(gs.lsblk); 254 offset = gs.text_viewer.rectsize.offset; 255 } 256 257 if (path != old_path || offset != old_offset) 258 remark = true; 259 260 old_path = path; 261 old_offset = offset; 262 } 263 264 if (remark) 265 mark(gs, gs.desktop, true); 266 } 267 268 void mark(GlobalState gs, string m, bool hide_remark_message = false) 269 { 270 writefln("mark %s", m); 271 Mark mark; 272 mark.state = gs.state; 273 string path; 274 final switch (gs.state) 275 { 276 case State.FileManager: 277 path = gs.current_path; 278 break; 279 case State.ImageViewer: 280 path = gs.image_viewer.path.get_key(gs.lsblk); 281 break; 282 case State.TextViewer: 283 path = gs.text_viewer.path.get_key(gs.lsblk); 284 mark.offset = gs.text_viewer.rectsize.offset; 285 break; 286 } 287 mark.path = to_char_array!MARKS_PATH_MAX(path); 288 289 final switch (gs.state) 290 { 291 case State.FileManager: 292 mark.screen_rect = gs.current_path_rect.to_screen(gs.screen); 293 if (!(m >= "0" && m <= "9")) 294 { 295 mark.screen_rect.x += gs.screen.w/2 - gs.mouse_screen_x; 296 mark.screen_rect.y += gs.screen.h/2 - gs.mouse_screen_y; 297 } 298 break; 299 case State.ImageViewer: 300 goto case; 301 case State.TextViewer: 302 mark.screen_rect = SDL_Rect((gs.screen.w - gs.screen.h)/2, 0, gs.screen.h, gs.screen.h); 303 break; 304 } 305 306 writefln("%s, screen_rect = %s, path = %s", m, mark.screen_rect, path); 307 Dbt key, data; 308 key = m; 309 data = mark; 310 311 auto res = gs.db_marks.put(null, &key, &data); 312 if (res != 0) 313 throw new Exception("Mark info to marks-db not written"); 314 315 else if (!hide_remark_message && m >= "0" && m <= "9") 316 { 317 string msg = format("Desktop %s remarked", m); 318 gs.messages ~= ConsoleMessage( 319 SDL_Color(0xFF, 0xFF, 0xFF, 0xFF), 320 msg, 321 SDL_GetTicks() 322 ); 323 writeln(msg); 324 } 325 } 326 327 void unmark(GlobalState gs, string m) 328 { 329 Dbt key; 330 key = m; 331 332 auto res = gs.db_marks.del(null, &key); 333 if (res != 0) 334 throw new Exception("Mark info from marks-db not deleted"); 335 336 if (m >= "0" && m <= "9") 337 { 338 string msg = format("Desktop %s removed", m); 339 gs.messages ~= ConsoleMessage( 340 SDL_Color(0xFF, 0xFF, 0xFF, 0xFF), 341 msg, 342 SDL_GetTicks() 343 ); 344 writeln(msg); 345 } 346 } 347 348 bool check_mark(GlobalState gs, string m) 349 { 350 Dbt key = m; 351 Dbt data; 352 353 auto res = gs.db_marks.get(null, &key, &data); 354 return (res == 0); 355 } 356 357 void go_mark(GlobalState gs, string m) 358 { 359 Dbt key = m; 360 Dbt data; 361 362 writefln("Go Mark %s", m); 363 auto res = gs.db_marks.get(null, &key, &data); 364 if (res == 0) 365 { 366 Mark mark = data.to!(Mark); 367 string path = from_char_array(mark.path); 368 369 if (path == "") 370 goto create_desktop; 371 372 string uuid = path[0..path.indexOf("\0")]; 373 374 string full_path = null; 375 foreach(mount_point, lsblk_info; gs.lsblk) 376 { 377 if (lsblk_info.uuid == uuid) 378 { 379 full_path = mount_point ~ path[path.indexOf("\0")..$].replace("\0", SL); 380 if (mount_point == SL) full_path = full_path[1..$]; 381 break; 382 } 383 } 384 385 version (Windows) 386 { 387 if (full_path.length == 3 && full_path[1] == ':') 388 { 389 full_path = full_path[0..2]; 390 } 391 } 392 writefln("path=%s, screen_rect=%s", path, mark.screen_rect); 393 394 if (full_path) 395 { 396 auto apply_rect = DRect(0, 0, 1024*1024, 1024*1024); 397 auto drect = get_rectsize_for_path(gs, PathMnt(gs.lsblk, SL), full_path, apply_rect); 398 399 if (!isNaN(drect.w)) 400 { 401 //SDL_Rect on_screen = drect.to_screen(gs.screen); 402 //writefln("Recalculate screen coordinates on %s", full_path); 403 drect.rescale_screen(gs.screen, mark.screen_rect); 404 } 405 else 406 { 407 writefln("Can't calculate DRect for %s", full_path); 408 } 409 410 gs.state = State.FileManager; 411 412 if (mark.state != State.FileManager) 413 { 414 if (mark.state == State.ImageViewer) 415 image_viewer(gs, PathMnt(gs.lsblk, full_path)); 416 else if (mark.state == State.TextViewer) 417 { 418 text_viewer(gs, PathMnt(gs.lsblk, full_path)); 419 gs.text_viewer.rectsize.offset = mark.offset; 420 } 421 } 422 } 423 } 424 425 create_desktop: 426 if (res != 0 && m >= "0" && m <= "9") 427 { 428 gs.initScreenAndSurf(); 429 gs.state = State.FileManager; 430 431 string msg = format("Desktop %s created", m); 432 gs.messages ~= ConsoleMessage( 433 SDL_Color(0xFF, 0xFF, 0xFF, 0xFF), 434 msg, 435 SDL_GetTicks() 436 ); 437 writeln(msg); 438 } 439 440 if (m >= "0" && m <= "9") 441 { 442 gs.desktop = m; 443 444 string current_desktop = "current_desktop"; 445 key = current_desktop; 446 data = m; 447 448 res = gs.db_marks.put(null, &key, &data); 449 if (res != 0) 450 throw new Exception("Can't write current desktop to marks-db"); 451 //writefln("gs.desktop=%s", gs.desktop); 452 } 453 }