 ; You must not remove this notice, or any other, from this software.
 
 (ns flatgui.focus
-    (:require [flatgui.base :as fg]
-      [flatgui.comlogic :as fgc]
-      [flatgui.inputchannels.awtbase :as inputbase]
-      [flatgui.inputchannels.mouse :as mouse]
-      [flatgui.inputchannels.keyboard :as keyboard])
-  (:import (java.awt.event KeyEvent)))
-
-(def clean-state {:mode :none
-                  :focused-child nil})
-
-(def having-focus-state {:mode :has-focus
-                         :focused-child nil})
-
-(defn temporarily-taken-from-state [permanent-owner-child dir] {:mode :has-focus
-                                                                :focused-child permanent-owner-child
-                                                                :throw-mode dir})
-
-(defn focus-child [child-id]
-  (if (keyword? child-id)
-    {:mode :parent-of-focused
-     :focused-child child-id}
-    (throw (IllegalArgumentException. (str "child-id must be a keyword but is: " child-id)))))
-
-;; For :parent-of-focused and :has-focus the latest focus movent direction (if any) is tracked in :throw-mode
-(defn focus-child-by-direction [child-id dir]
-  (assoc (focus-child child-id) :throw-mode dir))
+  (:require [flatgui.base :as fg]
+            [flatgui.comlogic :as fgc]
+            [flatgui.inputchannels.awtbase :as inputbase]
+            [flatgui.inputchannels.mouse :as mouse]
+            [flatgui.inputchannels.keyboard :as keyboard]
+            [flatgui.util.matrix :as m])
+  (:import (java.awt.event KeyEvent)
+           (java.util Comparator)))
+
 
 (defn accepts-focus? [component]
   (or

    ;; If the component has any child to which it can pass focus
    (some (fn [[_ c]] (accepts-focus? c)) (:children component))))

(defn get-in-cycle
  ([component dir c-id]
    (let [accepting-children (filter accepts-focus? (for [[_ v] (:children component)] v))
          child-count (count accepting-children)
          child-ids (mapv :id accepting-children)
          closed (:closed-focus-root component)
          cycle-keeper (fn [i]
                         (cond

                :first (nth child-ids 0)
                :last (nth child-ids (dec child-count))))))
  ([component dir] (get-in-cycle component dir nil)))

(def clean-state {:mode :none
                  :focused-child nil})

(def having-focus-state {:mode :has-focus
                         :focused-child nil})

(defn temporarily-taken-from-state [permanent-owner-child dir] {:mode :has-focus
                                                                :focused-child permanent-owner-child
                                                                :throw-mode dir})

(defn focus-child [child-id]
  (if (keyword? child-id)
    {:mode :parent-of-focused
     :focused-child child-id}
    (throw (IllegalArgumentException. (str "child-id must be a keyword but is: " child-id)))))

;; For :parent-of-focused and :has-focus the latest focus movent direction (if any) is tracked in :throw-mode
(defn focus-child-by-direction [child-id dir]
  (assoc (focus-child child-id) :throw-mode dir))

(fg/defevolverfn :focus-state
  (let [reason (fg/get-reason)
