hover
This commit is contained in:
@@ -46,6 +46,7 @@ var clay_base = {
|
||||
clipped: false,
|
||||
text_break: 'word',
|
||||
text_align: 'left',
|
||||
max_size: null, // {width: null, height: null}
|
||||
};
|
||||
|
||||
var root_item;
|
||||
@@ -287,12 +288,6 @@ clay.draw_commands = function draw_commands(tree_root, pos = {x:0,y:0})
|
||||
var config = node.config
|
||||
var boundingbox = geometry.rect_move(node.boundingbox,point.add(pos,config.offset))
|
||||
var content = geometry.rect_move(node.content,point.add(pos, config.offset))
|
||||
|
||||
// Check if this box should use hover styling
|
||||
if (node.state && node.state.hovered && config.hovered) {
|
||||
config.hovered.__proto__ = config
|
||||
config = config.hovered
|
||||
}
|
||||
|
||||
if (config.background_image)
|
||||
if (config.slice)
|
||||
|
||||
@@ -31,95 +31,45 @@ function should_skip_self(node) {
|
||||
return false
|
||||
}
|
||||
|
||||
clay_input.hit = function hit(tree_root, pos, prev_state = {}) {
|
||||
function find_path(node, path) {
|
||||
if (!pointer_enabled(node)) return null
|
||||
if (!rect_contains(node, pos)) return null
|
||||
function find_path(node, path, pos) {
|
||||
if (!pointer_enabled(node)) return null
|
||||
if (!rect_contains(node, pos)) return null
|
||||
|
||||
var next_path = path.concat(node)
|
||||
var next_path = path.concat(node)
|
||||
|
||||
if (node[clay.CHILDREN] && !should_skip_children(node)) {
|
||||
// Children drawn later should be tested first; reverse if your render order differs
|
||||
for (var i = node[clay.CHILDREN].length - 1; i >= 0; i--) {
|
||||
var child = node[clay.CHILDREN][i]
|
||||
var child_path = find_path(child, next_path)
|
||||
if (child_path) return child_path
|
||||
}
|
||||
if (node[clay.CHILDREN] && !should_skip_children(node)) {
|
||||
// Children drawn later should be tested first; reverse if your render order differs
|
||||
for (var i = node[clay.CHILDREN].length - 1; i >= 0; i--) {
|
||||
var child = node[clay.CHILDREN][i]
|
||||
var child_path = find_path(child, next_path, pos)
|
||||
if (child_path) return child_path
|
||||
}
|
||||
|
||||
if (should_skip_self(node)) return null
|
||||
return next_path
|
||||
}
|
||||
|
||||
var path = find_path(tree_root, []) || []
|
||||
if (should_skip_self(node)) return null
|
||||
return next_path
|
||||
}
|
||||
|
||||
clay_input.deepest = function deepest(tree_root, pos) {
|
||||
var path = find_path(tree_root, [], pos) || []
|
||||
var deepest = path.length ? path[path.length - 1] : null
|
||||
return deepest
|
||||
}
|
||||
|
||||
function nearest_actionable(path) {
|
||||
for (var i = path.length - 1; i >= 0; i--) {
|
||||
var n = path[i]
|
||||
if (n && n.config && typeof n.config.action == 'function') return n
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
var action_target = nearest_actionable(path)
|
||||
|
||||
// Hover bookkeeping: let child hover, and optionally parent hover via hover_includes_children
|
||||
var new_hover_chain = []
|
||||
if (deepest) {
|
||||
if (deepest.config && deepest.config.hovered) {
|
||||
deepest.state = deepest.state || {}
|
||||
deepest.state.hovered = true
|
||||
new_hover_chain.push(deepest)
|
||||
}
|
||||
// Call hovered callback if it exists
|
||||
if (typeof deepest.hovered == 'function') {
|
||||
deepest.hovered(true)
|
||||
}
|
||||
|
||||
for (var i = path.length - 2; i >= 0; i--) {
|
||||
var anc = path[i]
|
||||
if (anc.config && anc.config.hovered) {
|
||||
anc.state = anc.state || {}
|
||||
anc.state.hovered = true
|
||||
new_hover_chain.push(anc)
|
||||
}
|
||||
// Call hovered callback if it exists
|
||||
if (typeof anc.hovered == 'function') {
|
||||
anc.hovered(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear previous hovers not in the new chain
|
||||
if (prev_state.hover_chain) {
|
||||
for (var i = 0; i < prev_state.hover_chain.length; i++) {
|
||||
var n = prev_state.hover_chain[i]
|
||||
if (new_hover_chain.indexOf(n) == -1) {
|
||||
n.state = n.state || {}
|
||||
n.state.hovered = false
|
||||
// Call hovered callback if it exists
|
||||
if (typeof n.hovered == 'function') {
|
||||
n.hovered(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
path: path,
|
||||
deepest: deepest,
|
||||
action_target: action_target,
|
||||
hovered: deepest,
|
||||
hover_chain: new_hover_chain
|
||||
clay_input.bubble = function bubble(deepest, prop) {
|
||||
var current = deepest
|
||||
while (current) {
|
||||
if (current.config && current.config[prop])
|
||||
return current
|
||||
current = current[clay.PARENT]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
clay_input.click = function click(tree_root, mousepos, button = 'left') {
|
||||
var hit_result = clay_input.hit(tree_root, mousepos, {})
|
||||
var target = hit_result.action_target
|
||||
if (target && target.config.action) target.config.action()
|
||||
return target || null
|
||||
var deepest = clay_input.deepest(tree_root, mousepos)
|
||||
var action_target = clay_input.bubble(deepest, 'action')
|
||||
if (action_target && action_target.config.action) action_target.config.action()
|
||||
}
|
||||
|
||||
clay_input.get_actionable = function get_actionable(tree_root) {
|
||||
@@ -133,6 +83,17 @@ clay_input.get_actionable = function get_actionable(tree_root) {
|
||||
return actionable
|
||||
}
|
||||
|
||||
clay_input.filter = function filter(tree_root, predicate) {
|
||||
var results = []
|
||||
function rec(node) {
|
||||
if (predicate(node)) results.push(node)
|
||||
if (node[clay.CHILDREN])
|
||||
for (var child of node[clay.CHILDREN]) rec(child)
|
||||
}
|
||||
rec(tree_root)
|
||||
return results
|
||||
}
|
||||
|
||||
clay_input.find_by_id = function find_by_id(tree_root, id) {
|
||||
function rec(node) {
|
||||
if (node.id == id) return node
|
||||
@@ -146,15 +107,4 @@ clay_input.find_by_id = function find_by_id(tree_root, id) {
|
||||
return rec(tree_root)
|
||||
}
|
||||
|
||||
clay_input.filter = function filter(tree_root, predicate) {
|
||||
var results = []
|
||||
function rec(node) {
|
||||
if (predicate(node)) results.push(node)
|
||||
if (node[clay.CHILDREN])
|
||||
for (var child of node[clay.CHILDREN]) rec(child)
|
||||
}
|
||||
rec(tree_root)
|
||||
return results
|
||||
}
|
||||
|
||||
return clay_input
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
/* dump objects freed by the garbage collector */
|
||||
//#define DUMP_GC_FREE
|
||||
/* dump objects leaking when freeing the runtime */
|
||||
#define DUMP_LEAKS 1
|
||||
//#define DUMP_LEAKS 1
|
||||
/* dump memory usage before running the garbage collector */
|
||||
//#define DUMP_MEM
|
||||
//#define DUMP_OBJECTS /* dump objects in JS_FreeContext */
|
||||
|
||||
Reference in New Issue
Block a user