 (def ^{:private true} keyword-mapping
   (atom
    ;; UI widgets
-   {:button {:classname android.widget.Button
-             :traits [:layout-params :on-click :def]
+   {:view {:traits [:def :layout-params :on-click :text]}
+    :button {:classname android.widget.Button
+             :inherits :view
              :attributes {:text "Default button"}}
     :linear-layout {:classname android.widget.LinearLayout
-                    :traits [:layout-params :def]}
+                    :inherits :view}
     :edit {:classname android.widget.EditText
-           :traits [:layout-params :def]}
+           :inherits :view}
     :text-view {:classname android.widget.TextView
-                :traits [:layout-params :def]}
+                :inherits :view}
     :list-view {:classname android.widget.ListView
-                :traits [:layout-params :def]}
+                :inherits :view}
 
     ;; Other
     :layout-params {:classname ViewGroup$LayoutParams

  "Returns the list of all unique traits for `kw`. The list is built
  recursively."
  [kw]
  (let [first-level-traits (get-in @keyword-mapping [kw :traits])]
    (->> first-level-traits
         (mapcat all-traits)
         (concat first-level-traits)
         distinct)))

(defn set-value!
  "Associate the value keyword with the provided value for the given

         update-in [element-kw :attributes attribute-kw] value))

(defn default-attributes [element-kw]
  "Returns a map of default attributes for the given element keyword
  and all its parents."
  [element-kw]
  (merge (when element-kw
           (default-attributes (get-in @keyword-mapping
                                       [element-kw :inherits])))
         (get-in @keyword-mapping [element-kw :attributes])))

(defn defelement
  "Defines the element of the given class with the provided name to
  use in the UI construction. Takes the element's classname, a parent
  it inherits, a list of traits and a map of specific values as
  optional arguments.

  Optional arguments
  - :classname, :inherits, :traits, :values, :attributes. "
  [kw-name & args]
  (swap! keyword-mapping assoc kw-name (apply hash-map args)))
