fortrangoingonforty/sniffly / 8fa7e4e

Browse files

fix some animation, file collapsing things

Authored by espadonne
SHA
8fa7e4e4d33c3fbefaa03ba3d1420d6f6ff856b3
Parents
fe819bb
Tree
024eb5b

4 changed files

StatusFile+-
M src/core/disk_scanner.f90 1 1
M src/core/progressive_scanner.f90 27 1
M src/core/types.f90 4 0
M src/rendering/treemap_renderer.f90 99 5
src/core/disk_scanner.f90modified
@@ -8,7 +8,7 @@ module disk_scanner
88
   private
99
 
1010
   public :: scan_directory, build_tree, calculate_sizes, dump_tree_debug, set_progress_callback, &
11
-             set_show_hidden_files
11
+             set_show_hidden_files, group_small_files
1212
 
1313
   ! Directories to skip (reduce scan time and avoid issues)
1414
   character(len=*), parameter, dimension(7) :: SKIP_DIRS = &
src/core/progressive_scanner.f90modified
@@ -63,6 +63,16 @@ module progressive_scanner
6363
 
6464
 contains
6565
 
66
+  ! Get current time in milliseconds (for flash timing)
67
+  function get_time_ms() result(time_ms)
68
+    integer(int64) :: time_ms
69
+    integer :: count, count_rate, count_max
70
+
71
+    call system_clock(count, count_rate, count_max)
72
+    ! Convert to milliseconds
73
+    time_ms = int(count * 1000_int64 / count_rate, int64)
74
+  end function get_time_ms
75
+
6676
   ! Register callback to be called after each scan update
6777
   subroutine register_scan_update_callback(callback)
6878
     procedure(scan_update_callback) :: callback
@@ -189,6 +199,10 @@ contains
189199
       if (associated(scan_state%root)) then
190200
         scan_state%root%scan_complete = .true.
191201
         scan_state%root%is_scanning = .false.
202
+
203
+        ! Now that all sizes have been accumulated, group small files
204
+        print *, "Grouping small files after scan completion..."
205
+        call group_small_files_root()
192206
       end if
193207
       ! Call completion callback
194208
       if (associated(complete_callback)) then
@@ -286,7 +300,7 @@ contains
286300
           end if
287301
         end do
288302
 
289
-        ! Color the tree before showing it
303
+        ! Color the tree before showing it (don't group yet - sizes are still accumulating)
290304
         call color_root_children()
291305
 
292306
         ! Call initial level callback (so UI can start rendering)
@@ -351,6 +365,10 @@ contains
351365
             scan_state%root%children(root_idx)%size = &
352366
               scan_state%root%children(root_idx)%size + file_size
353367
 
368
+            ! Mark node for flash highlighting
369
+            scan_state%root%children(root_idx)%flash_intensity = 1.0d0
370
+            scan_state%root%children(root_idx)%last_update_time = get_time_ms()
371
+
354372
             if (scan_state%dirs_scanned < 5) then
355373
               print *, "  Path-matched: ", trim(file_path), " -> root child ", root_idx, &
356374
                        " (", trim(scan_state%root%children(root_idx)%name), ")"
@@ -512,4 +530,12 @@ contains
512530
     end select
513531
   end subroutine set_color_from_hsv
514532
 
533
+  ! Group small files at root level
534
+  subroutine group_small_files_root()
535
+    use disk_scanner, only: group_small_files
536
+
537
+    if (.not. associated(scan_state%root)) return
538
+    call group_small_files(scan_state%root)
539
+  end subroutine group_small_files_root
540
+
515541
 end module progressive_scanner
src/core/types.f90modified
@@ -51,6 +51,10 @@ module types
5151
     integer(int64) :: estimated_size  ! Estimated total size (grows as scan progresses)
5252
     logical :: is_scanning  ! True if currently being scanned
5353
 
54
+    ! Flash highlight state (for visual feedback during size updates)
55
+    real(real64) :: flash_intensity  ! 0.0 to 1.0, decays over time
56
+    integer(int64) :: last_update_time  ! Timestamp of last size update (milliseconds)
57
+
5458
     ! Tree structure
5559
     type(file_node), dimension(:), allocatable :: children
5660
     integer :: num_children
src/rendering/treemap_renderer.f90modified
@@ -138,6 +138,9 @@ contains
138138
       call update_progress_cb(real(progress, c_double), trim(status_msg))
139139
     end if
140140
 
141
+    ! Decay flash intensities for all visible nodes
142
+    call decay_flash_highlights()
143
+
141144
     ! Invalidate layout to force recalculation with new data
142145
     call invalidate_layout()
143146
 
@@ -530,6 +533,18 @@ contains
530533
     print *, "Restoring sizes before navigation..."
531534
     call recalculate_sizes(root_node)
532535
 
536
+    ! Check if the directory needs to be scanned (progressive scan didn't populate children)
537
+    if (current_view_node%children(index)%num_children == 0 .and. &
538
+        allocated(current_view_node%children(index)%path)) then
539
+      ! This directory was created by progressive scan but never had children populated
540
+      ! We need to scan it now
541
+      print *, "Directory has no children - triggering rescan: ", &
542
+               trim(current_view_node%children(index)%path)
543
+
544
+      call scan_directory(trim(current_view_node%children(index)%path))
545
+      return  ! scan_directory will set current_view_node appropriately
546
+    end if
547
+
533548
     ! Navigate into the directory
534549
     current_view_node => current_view_node%children(index)
535550
 
@@ -901,14 +916,14 @@ contains
901916
     w = real(node%bounds%width, c_double)
902917
     h = real(node%bounds%height, c_double)
903918
 
904
-    ! Draw semi-transparent white overlay (40% opacity)
905
-    call cairo_set_source_rgba(cr, 1.0d0, 1.0d0, 1.0d0, 0.4d0)
919
+    ! Draw semi-transparent yellow overlay (30% opacity) - closer to selection color
920
+    call cairo_set_source_rgba(cr, 1.0d0, 0.9d0, 0.3d0, 0.3d0)
906921
     call cairo_rectangle(cr, x, y, w, h)
907922
     call cairo_fill(cr)
908923
 
909
-    ! Draw thicker highlight border
910
-    call cairo_set_source_rgb(cr, 1.0d0, 1.0d0, 1.0d0)
911
-    call cairo_set_line_width(cr, 3.0d0)
924
+    ! Draw thicker yellow highlight border
925
+    call cairo_set_source_rgb(cr, 1.0d0, 0.9d0, 0.2d0)
926
+    call cairo_set_line_width(cr, 2.5d0)
912927
     call cairo_rectangle(cr, x, y, w, h)
913928
     call cairo_stroke(cr)
914929
   end subroutine render_hover_highlight
@@ -937,6 +952,35 @@ contains
937952
     call cairo_stroke(cr)
938953
   end subroutine render_selection_highlight
939954
 
955
+  ! Render flash highlight overlay (for actively resizing items during scan)
956
+  subroutine render_flash_highlight(cr, node)
957
+    type(c_ptr), intent(in) :: cr
958
+    type(file_node), intent(in) :: node
959
+    real(c_double) :: x, y, w, h
960
+    real(c_double) :: intensity
961
+
962
+    ! Skip if flash intensity is too low
963
+    if (node%flash_intensity < 0.05d0) return
964
+
965
+    x = real(node%bounds%x, c_double)
966
+    y = real(node%bounds%y, c_double)
967
+    w = real(node%bounds%width, c_double)
968
+    h = real(node%bounds%height, c_double)
969
+    intensity = real(node%flash_intensity, c_double)
970
+
971
+    ! Draw bright cyan/white flash overlay (intensity-based opacity)
972
+    ! Cyan gives that "electric" SpaceSniffer feel
973
+    call cairo_set_source_rgba(cr, 0.3d0, 1.0d0, 1.0d0, intensity * 0.6d0)
974
+    call cairo_rectangle(cr, x, y, w, h)
975
+    call cairo_fill(cr)
976
+
977
+    ! Draw bright flash border
978
+    call cairo_set_source_rgba(cr, 0.5d0, 1.0d0, 1.0d0, intensity * 0.9d0)
979
+    call cairo_set_line_width(cr, 2.0d0)
980
+    call cairo_rectangle(cr, x, y, w, h)
981
+    call cairo_stroke(cr)
982
+  end subroutine render_flash_highlight
983
+
940984
   ! Get file extension from filename
941985
   function get_file_extension(filename) result(ext)
942986
     character(len=*), intent(in) :: filename
@@ -1304,6 +1348,11 @@ contains
13041348
     call cairo_rectangle(cr, x, y, w, h)
13051349
     call cairo_stroke(cr)
13061350
 
1351
+    ! Render flash highlight if node is actively being updated
1352
+    if (node%flash_intensity > 0.05d0) then
1353
+      call render_flash_highlight(cr, node)
1354
+    end if
1355
+
13071356
     ! Render text label if rectangle is large enough
13081357
     if (can_show_label) then
13091358
       call render_label(cr, node, x, y, w, h)
@@ -1483,6 +1532,51 @@ contains
14831532
     print *, "Directory cache cleared and deallocated"
14841533
   end subroutine clear_cache
14851534
 
1535
+  ! Decay flash highlights for all visible nodes
1536
+  subroutine decay_flash_highlights()
1537
+    use iso_fortran_env, only: int64, real64
1538
+    integer :: i
1539
+    integer(int64) :: current_time, elapsed_ms
1540
+    real(real64) :: decay_rate
1541
+
1542
+    if (.not. allocated(root_node%children)) return
1543
+
1544
+    ! Get current time
1545
+    current_time = get_current_time_ms()
1546
+
1547
+    ! Decay rate: flash fades out over ~200ms
1548
+    decay_rate = 0.15d0  ! Decay by 15% per update
1549
+
1550
+    ! Decay flash intensity for all root children
1551
+    do i = 1, root_node%num_children
1552
+      if (root_node%children(i)%flash_intensity > 0.01d0) then
1553
+        ! Calculate time-based decay
1554
+        elapsed_ms = current_time - root_node%children(i)%last_update_time
1555
+
1556
+        ! If it's been more than 50ms since last update, start decaying
1557
+        if (elapsed_ms > 50_int64) then
1558
+          root_node%children(i)%flash_intensity = &
1559
+            root_node%children(i)%flash_intensity * (1.0d0 - decay_rate)
1560
+
1561
+          ! Clamp to zero when very small
1562
+          if (root_node%children(i)%flash_intensity < 0.01d0) then
1563
+            root_node%children(i)%flash_intensity = 0.0d0
1564
+          end if
1565
+        end if
1566
+      end if
1567
+    end do
1568
+  end subroutine decay_flash_highlights
1569
+
1570
+  ! Get current time in milliseconds (wrapper for progressive_scanner function)
1571
+  function get_current_time_ms() result(time_ms)
1572
+    use iso_fortran_env, only: int64
1573
+    integer(int64) :: time_ms
1574
+    integer :: count, count_rate, count_max
1575
+
1576
+    call system_clock(count, count_rate, count_max)
1577
+    time_ms = int(count * 1000_int64 / count_rate, int64)
1578
+  end function get_current_time_ms
1579
+
14861580
   ! Recursively deallocate a file tree
14871581
   recursive subroutine deallocate_tree(node)
14881582
     type(file_node), intent(inout) :: node