<commit_before>(ns nightcode.file-browser
  (:require [clojure.java.io :as io]
            [nightcode.dialogs :as dialogs]
            [nightcode.shortcuts :as shortcuts]
            [nightcode.ui :as ui]
            [nightcode.utils :as utils]
            [seesaw.core :as s]
            [seesaw.icon :as icon])
  (:import [java.awt Desktop]
           [javax.swing JLabel SwingConstants]))

(declare update-card!)

(def ^:const tile-size 150)
(def edit-mode? (atom false))

(defn go-up!
  [& _]
  (-> @ui/tree-selection
      io/file
      .getParentFile
      .getCanonicalPath
      ui/update-project-tree!))

(defn create-up-button
  []
  (doto (ui/button :id :up
                   :text "^^"
                   :focusable? false
                   :listen [:action go-up!])
    (s/text! (shortcuts/wrap-hint-text "&uarr;"))))

(defn enter-filename!
  [default-filename]
  (some->> (dialogs/show-file-path-dialog! default-filename)
           (io/file @ui/tree-selection)))

(defn new-file!
  [& _]
  (when-let [new-file (enter-filename! "example.clj")]
    (if (.exists new-file)
      (s/alert (utils/get-string :file-exists))
      (do
        (io!
          (.mkdirs (.getParentFile new-file))
          (.createNewFile new-file))
        (ui/update-project-tree! (.getCanonicalPath new-file))))))

(defn edit-files!
  [& _]
  (reset! edit-mode? true)
  (update-card!))

(defn open-in-file-browser!
  [& _]
  (.open (Desktop/getDesktop) (io/file @ui/tree-selection)))

(defn finish-edits!
  [& _]
  (reset! edit-mode? false)
  (update-card!))

(defn save-edits!
  [& _]
  (doseq [tile (s/select @ui/root [:#file-grid :.edit])]
    (let [path (.getName tile)
          f (io/file path)
          fname (some-> (s/select tile [:.name]) first s/text)]
      (cond
        ; delete
        (some-> (s/select tile [:.delete]) first (s/config :selected?))
        (utils/delete-file-recursively! @ui/tree-projects path)
        ; rename
        (not= (.getName f) fname)
        (io! (.renameTo f (io/file (.getParentFile f) fname))))))
  (ui/update-project-tree!)
  (finish-edits!))

(def ^:dynamic *widgets* [:up :new-file :edit :open-in-browser :save :cancel])

(defn create-actions
  []
  {:up go-up!
   :new-file new-file!
   :edit edit-files!
   :open-in-browser open-in-file-browser!
   :save save-edits!
   :cancel finish-edits!})

(defn create-widgets
  [actions]
  {:up (create-up-button)
   :new-file (ui/button :id :new-file
                        :text (utils/get-string :new-file)
                        :listen [:action (:new-file actions)]
                        :focusable? false)
   :edit (ui/button :id :edit
                    :text (utils/get-string :edit)
                    :listen [:action (:edit actions)]
                    :focusable? false)
   :open-in-browser (ui/button :id :open-in-browser
                               :text (utils/get-string :open-in-file-browser)
                               :listen [:action (:open-in-browser actions)]
                               :focusable? false)
   :save (ui/button :id :save
                    :text (utils/get-string :save)
                    :listen [:action (:save actions)]
                    :focusable? false)
   :cancel (ui/button :id :cancel
                      :text (utils/get-string :cancel)
                      :listen [:action (:cancel actions)]
                      :focusable? false)})

(defn toggle-visible!
  [view path]
  (let [edit? @edit-mode?
        buttons {:#up (and (not edit?)
                           (not (contains? @ui/tree-projects path)))
                 :#new-file (not edit?)
                 :#edit (and (not edit?)
                             (->> (io/file path)
                                  .listFiles
                                  (filter #(.isFile %))
                                  seq))
                 :#open (and (not edit?)
                             (Desktop/isDesktopSupported))
                 :#save edit?
                 :#cancel edit?}]
    (doseq [[id should-show?] buttons]
      (ui/config! view id :visible? should-show?))))

(defn get-icon-path
  [f]
  (when-not (.isDirectory f)
    (case (utils/get-extension (.getName f))
      "clj" "file-clojure.png"
      "cljs" "file-clojure.png"
      "java" "file-java.png"
      "file.png")))

(defn protect-file?
  [path]
  false)

(defn create-tile
  [f]
  (when-not (.isHidden f)
    (if (and @edit-mode?
             (.isFile f)
             (not (protect-file? (.getCanonicalPath f))))
      (doto (s/border-panel :class :edit
                            :north (s/checkbox :class :delete
                                               :text (utils/get-string :delete)
                                               :halign :center
                                               :focusable? false)
                            :center (some-> (get-icon-path f) icon/icon JLabel.)
                            :south (s/text :class :name
                                           :text (.getName f)
                                           :editable? true)
                            :size [tile-size :by tile-size])
        (.setName (.getCanonicalPath f)))
      (doto (s/button :icon (some-> (get-icon-path f) icon/icon)
                      :text (.getName f)
                      :size [tile-size :by tile-size]
                      :listen [:action (->> (.getCanonicalPath f)
                                            ui/update-project-tree!
                                            (fn [_]))]
                      :focusable? false
                      :enabled? (and (or (.isDirectory f)
                                         (utils/valid-file? f))
                                     (not @edit-mode?)))
        (.setVerticalTextPosition SwingConstants/BOTTOM)
        (.setHorizontalTextPosition SwingConstants/CENTER)))))

(defn create-card
  []
  (let [actions (create-actions)
        widgets (create-widgets actions)
        widget-bar (ui/wrap-panel :items (map #(get widgets % %) *widgets*))]
    (doto (s/border-panel :id :file-browser
                          :north widget-bar<commit_msg>Improve button refreshing in file browser<commit_after>(ns nightcode.file-browser
  (:require [clojure.java.io :as io]
            [nightcode.dialogs :as dialogs]
            [nightcode.shortcuts :as shortcuts]
            [nightcode.ui :as ui]
            [nightcode.utils :as utils]
            [seesaw.core :as s]
            [seesaw.icon :as icon])
  (:import [java.awt Desktop]
           [javax.swing JLabel SwingConstants]))

(declare update-card!)

(def ^:const tile-size 150)
(def edit-mode? (atom false))

(defn go-up!
  [& _]
  (-> @ui/tree-selection
      io/file
      .getParentFile
      .getCanonicalPath
      ui/update-project-tree!))

(defn create-up-button
  []
  (doto (ui/button :id :up
                   :text "^^"
                   :focusable? false
                   :listen [:action go-up!])
    (s/text! (shortcuts/wrap-hint-text "&uarr;"))))

(defn enter-filename!
  [default-filename]
  (some->> (dialogs/show-file-path-dialog! default-filename)
           (io/file @ui/tree-selection)))

(defn new-file!
  [& _]
  (when-let [new-file (enter-filename! "example.clj")]
    (if (.exists new-file)
      (s/alert (utils/get-string :file-exists))
      (do
        (io!
          (.mkdirs (.getParentFile new-file))
          (.createNewFile new-file))
        (ui/update-project-tree! (.getCanonicalPath new-file))))))

(defn edit-files!
  [& _]
  (reset! edit-mode? true)
  (update-card!))

(defn open-in-file-browser!
  [& _]
  (.open (Desktop/getDesktop) (io/file @ui/tree-selection)))

(defn finish-edits!
  [& _]
  (reset! edit-mode? false)
  (update-card!))

(defn save-edits!
  [& _]
  (doseq [tile (s/select @ui/root [:#file-grid :.edit])]
    (let [path (.getName tile)
          f (io/file path)
          fname (some-> (s/select tile [:.name]) first s/text)]
      (cond
        ; delete
        (some-> (s/select tile [:.delete]) first (s/config :selected?))
        (utils/delete-file-recursively! @ui/tree-projects path)
        ; rename
        (not= (.getName f) fname)
        (io! (.renameTo f (io/file (.getParentFile f) fname))))))
  (ui/update-project-tree!)
  (finish-edits!))

(def ^:dynamic *widgets* [:up :new-file :edit :open-in-browser :save :cancel])

(defn create-actions
  []
  {:up go-up!
   :new-file new-file!
   :edit edit-files!
   :open-in-browser open-in-file-browser!
   :save save-edits!
   :cancel finish-edits!})

(defn create-widgets
  [actions]
  {:up (create-up-button)
   :new-file (ui/button :id :new-file
                        :text (utils/get-string :new-file)
                        :listen [:action (:new-file actions)]
                        :focusable? false)
   :edit (ui/button :id :edit
                    :text (utils/get-string :edit)
                    :listen [:action (:edit actions)]
                    :focusable? false)
   :open-in-browser (ui/button :id :open-in-browser
                               :text (utils/get-string :open-in-file-browser)
                               :listen [:action (:open-in-browser actions)]
                               :focusable? false)
   :save (ui/button :id :save
                    :text (utils/get-string :save)
                    :listen [:action (:save actions)]
                    :focusable? false)
   :cancel (ui/button :id :cancel
                      :text (utils/get-string :cancel)
                      :listen [:action (:cancel actions)]
                      :focusable? false)})

(defn toggle-visible!
  [view path]
  (let [edit? @edit-mode?
        buttons {:up (and (not edit?)
                          (not (contains? @ui/tree-projects path)))
                 :new-file (not edit?)
                 :edit (and (not edit?)
                            (->> (io/file path)
                                 .listFiles
                                 (filter #(.isFile %))
                                 seq))
                 :open-in-browser (and (not edit?)
                                       (Desktop/isDesktopSupported))
                 :save edit?
                 :cancel edit?}]
    (doseq [btn (s/select view [:#widgets :<javax.swing.JComponent>])]
      (s/config! btn :visible? (get buttons (s/id-of btn) (not edit?))))))

(defn get-icon-path
  [f]
  (when-not (.isDirectory f)
    (case (utils/get-extension (.getName f))
      "clj" "file-clojure.png"
      "cljs" "file-clojure.png"
      "java" "file-java.png"
      "file.png")))

(defn protect-file?
  [path]
  false)

(defn create-tile
  [f]
  (when-not (.isHidden f)
    (if (and @edit-mode?
             (.isFile f)
             (not (protect-file? (.getCanonicalPath f))))
      (doto (s/border-panel :class :edit
                            :north (s/checkbox :class :delete
                                               :text (utils/get-string :delete)
                                               :halign :center
                                               :focusable? false)
                            :center (some-> (get-icon-path f) icon/icon JLabel.)
                            :south (s/text :class :name
                                           :text (.getName f)
                                           :editable? true)
                            :size [tile-size :by tile-size])
        (.setName (.getCanonicalPath f)))
      (doto (s/button :icon (some-> (get-icon-path f) icon/icon)
                      :text (.getName f)
                      :size [tile-size :by tile-size]
                      :listen [:action (->> (.getCanonicalPath f)
                                            ui/update-project-tree!
                                            (fn [_]))]
                      :focusable? false
                      :enabled? (and (or (.isDirectory f)
                                         (utils/valid-file? f))
                                     (not @edit-mode?)))
        (.setVerticalTextPosition SwingConstants/BOTTOM)
        (.setHorizontalTextPosition SwingConstants/CENTER)))))

(defn create-card
  []
  (let [actions (create-actions)
        widgets (create-widgets actions)
        widget-bar (ui/wrap-panel :items (map #(get widgets % %) *widgets*)
                                  :id :widgets)]
    (doto (s/border-panel :id :file-browser
                          :north widget-bar
{'fraction_non_alphanumeric': 0.1429720814224797, 'fraction_numerical': 0.0004827419744146754, 'mean_word_length': 1.4468503937007875, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 44, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3938612', 'n_tokens_mistral': 3888, 'n_tokens_neox': 3709, 'n_words': 866}