Index: openacs-4/packages/xowiki/tcl/category-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/category-procs.tcl,v diff -u -r1.19 -r1.20 --- openacs-4/packages/xowiki/tcl/category-procs.tcl 15 May 2009 07:05:19 -0000 1.19 +++ openacs-4/packages/xowiki/tcl/category-procs.tcl 29 May 2009 13:37:47 -0000 1.20 @@ -1,160 +1,16 @@ -namespace eval ::xowiki { - # - # ::xowiki::CatTree (category tree) - # +::xo::library doc { + XoWiki - category specific code - Class CatTree -superclass ::xo::OrderedComposite -parameter {{name ""}} - # - # Class methods - # - CatTree proc renderer {style} { - set renderer CategoryRenderer=$style - if {![my isclass $renderer]} { - error "No such renderer $renderer (avalialble [info cmd ::xowiki::CategoryRenderer=*]" - } - return $renderer - } + @creation-date 2006-10-10 + @author Gustaf Neumann + @cvs-id $Id$ +} - CatTree proc include_head_entries {{-style mktree}} { - [my renderer $style] include_head_entries - } - +namespace eval ::xowiki::includelet { # - # Instance methods - # - CatTree instproc add_to_category { - -category - -orderby - -itemobj - {-increasing:boolean true} - {-open_item:boolean false} - } { - set items ${category}::items - if {![my isobject $items]} { - ::xo::OrderedComposite create $items - if {[info exists orderby]} { - if {$orderby eq "page_order"} { - $items mixin add ::xo::OrderedComposite::IndexCompare - } - set direction [expr {$increasing ? "increasing" : "decreasing"}] - $items orderby -order $direction $orderby - } - } - $items add $itemobj - if {$open_item} { - $category open_tree - $itemobj set open_item 1 - } - } - CatTree instproc open_tree {} {;} - CatTree instproc render {{-style mktree}} { - set renderer [[self class] renderer $style] - Category instmixin $renderer - set content [$renderer render [self]] - Category instmixin "" - - return $content - } - - # - # ::xowiki::Category - # - - Class Category -superclass ::xo::OrderedComposite -parameter { - package_id level label pos category_id {open_requests 0} count {href ""} - } - #Category instproc destroy {} {my log --; next} - Category instproc open_tree {} { - my set open_requests 1 - if {[my exists __parent]} {[my set __parent] open_tree} - } - - Category instproc some_child_has_items {} { - foreach i [my children] { - if {[my isobject ${i}::items]} {return 1} - if {[$i some_child_has_items]} {return 1} - } - return 0 - } - - Category instproc render {} { - set content "" - if {[my isobject [self]::items]} { - foreach i [[self]::items children] { - $i instvar name title prefix suffix - set entry "$prefix$title$suffix" - append cat_content [my render_item -highlight [$i exists open_item] $entry] - } - foreach c [my children] {append cat_content [$c render] \n} - append content [my render_category -open [expr {[my set open_requests]>0}] $cat_content] - } elseif {[my open_requests]>0 || [my some_child_has_items]} { - set cat_content "" - foreach c [my children] {append cat_content [$c render] \n} - append content [my render_category -open true $cat_content] - - } - return $content - } - - # - # Define a meta class for the category renderers with the common - # behavior. - # - Class create CategoryRenderer -superclass Class - CategoryRenderer instproc include_head_entries {} { - # to be overloaded - } - CategoryRenderer instproc render {cattree} { - set content "" - foreach c [$cattree children] {append content [$c render] \n} - return $content - } - - # - # These are the list-specific rendering functions - # - CategoryRenderer create CategoryRenderer=mktree - CategoryRenderer=mktree proc include_head_entries {} { - ::xo::Page requireCSS "/resources/xowiki/cattree.css" - ::xo::Page requireJS "/resources/acs-templating/mktree.js" - } - CategoryRenderer=mktree proc render {cattree} { - return "" - } - CategoryRenderer=mktree instproc render_item {{-highlight:boolean false} item} { - if {$highlight} { - return "
  • $item
  • \n" - } else { - return "
  • $item
  • \n" - } - } - CategoryRenderer=mktree instproc render_category {{-open:boolean false} cat_content} { - set open_state [expr {[my set open_requests]>0?"class='liOpen'" : "class='liClosed'"}] - set c [expr {[my exists count] ? "([my count])" : ""}] - return "
  • [my label] $c\n \n" - } - - # - # These are the section-specific rendering functions - # - - CategoryRenderer create CategoryRenderer=sections - CategoryRenderer=sections instproc render_item {{-highlight:boolean false} item} { - if {$highlight} { - return "$item
    \n" - } else { - return "$item
    \n" - } - } - CategoryRenderer=sections instproc render_category {{-open:boolean false} cat_content} { - set section [expr {[my level] + 2}] - return "[my label]\n

    \ -

    $cat_content
    \n" - } - - # # Commonly used code for categories # + Class create Category Category proc get_mapped_trees { -object_id {-locale ""} Index: openacs-4/packages/xowiki/tcl/includelet-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/includelet-procs.tcl,v diff -u -r1.113 -r1.114 --- openacs-4/packages/xowiki/tcl/includelet-procs.tcl 15 May 2009 07:05:19 -0000 1.113 +++ openacs-4/packages/xowiki/tcl/includelet-procs.tcl 29 May 2009 13:37:48 -0000 1.114 @@ -101,6 +101,11 @@ string map [list \n \\n \" {\"} ' {\'}] $string } + ::xowiki::Includelet proc html_encode {string} { + return [string map [list & "&" < "<" > ">" \" """ ' "'"] $string] + } + + ::xowiki::Includelet proc html_id {name} { # Construct a valid HTML id or name. # For details, see http://www.w3.org/TR/html4/types.html @@ -623,7 +628,7 @@ } categories instproc include_head_entries {} { - ::xowiki::CatTree include_head_entries -style [my set style] + ::xowiki::Tree include_head_entries -renderer [my set style] } categories instproc category_tree_edit_button {-object_id:integer -locale {-allow_edit false} -tree_id:integer} { @@ -697,10 +702,13 @@ return [my category_tree_missing -name $tree_name -edit_html $edit_html] } + if {![my exists id]} {my set id [::xowiki::Includelet html_id [self]]} + foreach tree $trees { foreach {tree_id my_tree_name ...} $tree {break} - set edit_html [my category_tree_edit_button -object_id $package_id -allow_edit $allow_edit -tree_id $tree_id] + set edit_html [my category_tree_edit_button -object_id $package_id \ + -allow_edit $allow_edit -tree_id $tree_id] #append content "
    $edit_html
    \n" if {!$no_tree_name} { @@ -710,13 +718,14 @@ } set categories [list] set pos 0 - set cattree(0) [::xowiki::CatTree new -volatile -orderby pos -name $my_tree_name] - set category_infos [::xowiki::Category get_category_infos -locale $locale -tree_id $tree_id] + set cattree(0) [::xowiki::Tree new -volatile -orderby pos \ + -id [my id]-$my_tree_name -name $my_tree_name] + set category_infos [::xowiki::Category get_category_infos \ + -locale $locale -tree_id $tree_id] foreach category_info $category_infos { foreach {cid category_label deprecated_p level} $category_info {break} - - set c [::xowiki::Category new -orderby pos -category_id $cid -package_id $package_id \ + set c [::xowiki::TreeNode new -orderby pos \ -level $level -label $category_label -pos [incr pos]] set cattree($level) $c set plevel [expr {$level -1}] @@ -773,7 +782,7 @@ if {$category_ids ne ""} { foreach cid [split $category_ids ,] { append sql " and exists (select * from category_object_map \ - where object_id = ci.item_id and category_id = $cid)" + where object_id = ci.item_id and category_id = $cid)" } } append sql $locale_clause @@ -799,8 +808,8 @@ set prefix "" set suffix "" foreach var {name title prefix suffix page_order} {$itemobj set $var [set $var]} - - $cattree(0) add_to_category \ + $itemobj set href [::$package_id pretty_link $name] + $cattree(0) add_item \ -category $category($category_id) \ -itemobj $itemobj \ -orderby $orderby \ @@ -842,13 +851,14 @@ } categories-recent instproc include_head_entries {} { - ::xowiki::CatTree include_head_entries -style [my set style] + ::xowiki::Tree include_head_entries -renderer [my set style] } categories-recent instproc render {} { my get_parameters - set cattree [::xowiki::CatTree new -volatile -name "categories-recent"] + if {![my exists id]} {my set id [::xowiki::Includelet html_id [self]]} + set cattree [::xowiki::Tree new -volatile -id [my id]] foreach {locale locale_clause} \ [::xowiki::Includelet locale_clause -revisions r -items ci $package_id $locale] break @@ -877,14 +887,14 @@ set prefix "$formatted_date " set suffix "" foreach var {name title prefix suffix} {$itemobj set $var [set $var]} + $itemobj set href [::$package_id pretty_link $name] if {![info exists categories($category_id)]} { - set categories($category_id) [::xowiki::Category new \ - -package_id $package_id \ - -label [category::get_name $category_id $locale]\ + set categories($category_id) [::xowiki::TreeNode new \ + -label [category::get_name $category_id $locale] \ -level 1] $cattree add $categories($category_id) } - $cattree add_to_category -category $categories($category_id) -itemobj $itemobj + $cattree add_item -category $categories($category_id) -itemobj $itemobj } return [$cattree render -style [my set style]] } @@ -1707,7 +1717,7 @@ # includelets based on order # Class create PageReorderSupport - PageReorderSupport instproc page_reorder_check_allow {allow_reorder} { + PageReorderSupport instproc page_reorder_check_allow {{-with_head_entries true} allow_reorder} { if {$allow_reorder ne ""} { my instvar package_id set granted [$package_id check_permissions \ @@ -1716,10 +1726,12 @@ $package_id change-page-order] #my msg "granted=$granted" if {$granted} { - set ajaxhelper 0 - ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "utilities/utilities.js" - ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "selector/selector-min.js" - ::xo::Page requireJS "/resources/xowiki/yui-page-order-region.js" + if {$with_head_entries} { + set ajaxhelper 1 + ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "utilities/utilities.js" + ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "selector/selector-min.js" + ::xo::Page requireJS "/resources/xowiki/yui-page-order-region.js" + } } else { # the user has not enough permissions, so disallow set allow_reorder "" @@ -1872,48 +1884,115 @@ return $displayed_page_order } - toc instproc yui_tree {pages open_page package_id expand_all remove_levels} { - my instvar navigation page_name book_mode + toc instproc build_navigation {pages} { + # + # compute associative arrays open_node and navigation (position + # and current) + # + my get_parameters + my instvar navigation page_name + array set navigation {position 0 current ""} - set js "" - set node() root + # the top node is always open + my set open_node() true set node_cnt 0 - #my log "--book read [llength [$pages children]] pages" - #append js "$node().expand();\n" - foreach o [$pages children] { - $o instvar page_order title name + $o instvar page_order name + incr node_cnt + set page_name($node_cnt) $name + if {![regexp {^(.*)[.]([^.]+)} $page_order _ parent]} {set parent ""} + # + # If we are on the provided $open_page, we remember our position + # for the progress bar. + set on_current_node [expr {$open_page eq $name} ? "true" : "false"] + if {$on_current_node} { + set navigation(position) $node_cnt + set navigation(current) $page_order + } + if {$expand_all} { + my set open_node($page_order) true + } elseif {$on_current_node} { + my set open_node($page_order) true + # make sure to open all nodes to the root + for {set p $parent} {$p ne ""} {} { + my set open_node($p) true + if {![regexp {^(.*)[.]([^.]+)} $p _ p]} {set p ""} + } + } + } + set navigation(count) $node_cnt + #my log OPEN=[lsort [my array names open_node]] + } - set label "[my page_number $page_order $remove_levels] $title" - set id tmpNode[incr node_cnt] - set node($page_order) $id - set jsobj [my js_name].objs\[$node_cnt\] - set href [my href $package_id $book_mode $name] - set expand [expr {[my exists open_node($page_order)]}] + toc instproc render_list {{-full false} pages} { + my get_parameters + my instvar navigation page_name + # + # Build a reduced toc tree based on pure HTML (no javascript or + # ajax involved). If an open_page is specified, produce an as + # small as possible tree and omit all non-visible nodes. + # + if {$open_page ne ""} { + # TODO: can we allow open_page and reorder? + set allow_reorder "" + } else { + set allow_reorder [my page_reorder_check_allow $allow_reorder] + } + my page_reorder_init_vars -allow_reorder $allow_reorder js last_level ID min_level + + set css_class [expr {$min_level == 1 ? "page_order_region" : "page_order_region_no_target"}] +#my log allow_reorder=$allow_reorder,min_level=$min_level,css=$css_class + set html "\n"} + set level $new_level + } + set href [my href $package_id $book_mode $name] + set highlight [if {$open_page eq $name} {set _ "style = 'font-weight:bold;'"} {}] + set item_id [my page_reorder_item_id -ID $ID -prefix_js $prefix_js -page_order $page_order js] + append html \ + "
  • " \ + "$page_number $title\n" + } } - return $js + # close all levels + for {set l 0} {$l <= $level} {incr l} {append html "\n"} + if {$js ne ""} {append html "\n"} + + return $html } - toc instproc ajax_tree {js_tree_cmds} { - return "
    - -
    " +" } - toc instproc non_ajax_tree {js_tree_cmds} { - return "
    - -
    " + toc instproc yui_non_ajax {} { + return " + var [my js_name]; + YAHOO.util.Event.onDOMReady(function() { + [my js_name] = new YAHOO.widget.TreeView('[my id]'); + [my js_name].subscribe('clickEvent',function(oArgs) { + //console.info(oArgs); + var m = /href=\"(\[^\"\]+)\"/.exec(oArgs.node.html); + //console.info(m\[1\]); + //window.location.href = m\[1\]; + return false; + }); + [my js_name].render(); + }); + " } + toc instproc build_tree {{-full false} {-remove_levels 0} {-book_mode false} {-open_page ""} pages} { + my instvar package_id + set tree(-1) [::xowiki::Tree new -destroy_on_cleanup -orderby pos -id [my id]] + set pos 0 + foreach o [$pages children] { + $o instvar page_order title name + if {![regexp {^(.*)[.]([^.]+)} $page_order _ parent]} {set parent ""} + set page_number [my page_number $page_order $remove_levels] - toc instproc include_head_entries_yui_tree {ajax style} { - set ajaxhelper 1 - - ::xo::Page requireCSS "/resources/ajaxhelper/yui/treeview/assets/${style}tree.css" - if {$style eq ""} { - ::xowiki::Includelet require_YUI_CSS -ajaxhelper $ajaxhelper \ - treeview/assets/skins/sam/treeview.css + set level [regsub -all {[.]} [$o set page_order] _ page_order_js] + if {$full || [my exists open_node($parent)] || [my exists open_node($page_order)]} { + set href [my href $package_id $book_mode $name] + set c [::xowiki::TreeNode new -orderby pos -pos [incr pos] -level $level \ + -object $o -owner [self] \ + -label $title -prefix $page_number -href $href \ + -highlight [expr {$open_page eq $name}] \ + -expanded true -open_requests 1] + set tree($level) $c + $tree([expr {$level -1}]) add $c + } } - ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "yahoo/yahoo-min.js" - ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "event/event-min.js" - - if {$ajax} { - ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "dom/dom-min.js" ;# ANIM - ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "connection/connection-min.js" - ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "animation/animation-min.js" ;# ANIM - } - ::xowiki::Includelet require_YUI_JS -ajaxhelper $ajaxhelper "treeview/treeview.js" + return $tree(-1) } - - toc instproc render_yui_tree {pages style} { + toc instproc render_yui_list {{-full false} pages} { + my instvar js my get_parameters + my instvar navigation page_name + # # Render the tree with the yui widget (with or without ajax) # @@ -2087,57 +2165,23 @@ set ajax 0 } my set ajax $ajax - # do the hard work here.... - set js_tree_cmds [my yui_tree $pages $open_page $package_id $expand_all $remove_levels] + if {$ajax} { - return [my ajax_tree $js_tree_cmds] + set js [my yui_ajax] + } else { + set js [my yui_non_ajax] } - return [my non_ajax_tree $js_tree_cmds] - } - toc instproc build_navigation {pages} { - # - # compute associative arrays open_node and navigation (position - # and current) - # - my get_parameters - my instvar navigation page_name - array set navigation {position 0 current ""} + set tree [my build_tree -full $full -remove_levels $remove_levels \ + -book_mode $book_mode -open_page $open_page $pages] - # the top node is always open - my set open_node() true - set node_cnt 0 - foreach o [$pages children] { - $o instvar page_order name - incr node_cnt - set page_name($node_cnt) $name - if {![regexp {^(.*)[.]([^.]+)} $page_order _ parent]} {set parent ""} - # - # If we are on the provided $open_page, we remember our position - # for the progress bar. - set on_current_node [expr {$open_page eq $name} ? "true" : "false"] - if {$on_current_node} { - set navigation(position) $node_cnt - set navigation(current) $page_order - } - if {$expand_all} { - my set open_node($page_order) true - } elseif {$on_current_node} { - my set open_node($page_order) true - # make sure to open all nodes to the top - for {set p $parent} {$p ne ""} {} { - my set open_node($p) true - if {![regexp {^(.*)[.]([^.]+)} $p _ p]} {set p ""} - } - } - } - set navigation(count) $node_cnt - #my log OPEN=[lsort [my array names open_node]] + set HTML [$tree render -style yuitree -js $js] + return $HTML } - toc instproc render_list {pages} { + toc instproc render_list {{-full false} pages} { my get_parameters - my instvar navigation page_name + # # Build a reduced toc tree based on pure HTML (no javascript or # ajax involved). If an open_page is specified, produce an as @@ -2147,68 +2191,46 @@ # TODO: can we allow open_page and reorder? set allow_reorder "" } else { - set allow_reorder [my page_reorder_check_allow $allow_reorder] + set allow_reorder [my page_reorder_check_allow -with_head_entries false $allow_reorder] } + set tree [my build_tree -full $full -remove_levels $remove_levels \ + -book_mode $book_mode -open_page $open_page $pages] + my page_reorder_init_vars -allow_reorder $allow_reorder js last_level ID min_level + set js "\nYAHOO.xo_page_order_region.DDApp.package_url = '[$package_id package_url]';" + set HTML [$tree render -style listdnd -js $js -context {min_level $min_level}] + + return $HTML + } - set css_class [expr {$min_level == 1 ? "page_order_region" : "page_order_region_no_target"}] - set html "\n"} - set level $new_level - } - set href [my href $package_id $book_mode $name] - set highlight [if {$open_page eq $name} {set _ "style = 'font-weight:bold;'"} {}] - set item_id [my page_reorder_item_id -ID $ID -prefix_js $prefix_js -page_order $page_order js] - append html \ - "
  • " \ - "$page_number $title\n" - } - } - # close all levels - for {set l 0} {$l <= $level} {incr l} {append html "\n"} - if {$js ne ""} {append html "\n"} - - return $html + toc instproc include_head_entries {} { + my instvar style renderer + ::xowiki::Tree include_head_entries -renderer $renderer -style $style;# FIXME general } - toc instproc include_head_entries {} { + toc instproc initialize {} { my get_parameters - if {$style ne "list"} { - my include_head_entries_yui_tree $ajax $style + + set list_mode 0 + switch -- $style { + "menu" {set s "menu/"; set renderer yuitree} + "folders" {set s "folders/"; set renderer yuitree} + "list" {set s ""; set list_mode 1; set renderer list} + "default" {set s ""; set renderer yuitree} } + my set renderer $renderer + my set style $s + my set list_mode $list_mode } toc instproc render {} { my get_parameters - set list_mode 0 + if {![my exists id]} {my set id [::xowiki::Includelet html_id [self]]} if {[info exists category_id]} {my set category_id $category_id} - switch -- $style { - "menu" {set s "menu/"} - "folders" {set s "folders/"} - "list" {set s ""; set list_mode 1} - "default" {set s ""} - } # # Collect the pages # @@ -2220,10 +2242,11 @@ # # Call a render on the created structure # - if {$list_mode} { + if {[my set list_mode]} { +my log LIST return [my render_list $pages] } else { - return [my render_yui_tree $pages $s] + return [my render_yui_list -full true $pages] } } @@ -2349,8 +2372,7 @@ set base [$package_id pretty_link [$__including_page name]] #set id ID$item_id #$root setAttribute id $id - set as_att_value [string map [list & "&" < "<" > ">" \" """ ' "'"] $inner_html] - + set as_att_value [::xowiki::Includelet html_encode $inner_html] set save_form [subst {

    Create Form from Content Index: openacs-4/packages/xowiki/tcl/package-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/package-procs.tcl,v diff -u -r1.176 -r1.177 --- openacs-4/packages/xowiki/tcl/package-procs.tcl 14 May 2009 08:56:44 -0000 1.176 +++ openacs-4/packages/xowiki/tcl/package-procs.tcl 29 May 2009 13:37:48 -0000 1.177 @@ -1086,6 +1086,7 @@ db_transaction { foreach {page_id item_id name old_page_order new_page_order} [concat $drop_renames $gap_renames] { #my log "--cpo UPDATE $page_id new_page_order $new_page_order" + $temp_obj item_id $item_id $temp_obj update_attribute_from_slot -revision_id $page_id $slot $new_page_order ::xo::clusterwide ns_cache flush xotcl_object_cache ::$item_id ::xo::clusterwide ns_cache flush xotcl_object_cache ::$page_id Index: openacs-4/packages/xowiki/tcl/tree-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/tree-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/xowiki/tcl/tree-procs.tcl 29 May 2009 13:37:48 -0000 1.1 @@ -0,0 +1,338 @@ +::xo::library doc { + Classes for creating, manageing and rendering trees + + @creation-date 2009-05-29 + @author Gustaf Neumann + @cvs-id $Id: tree-procs.tcl,v 1.1 2009/05/29 13:37:48 gustafn Exp $ +} + +namespace eval ::xowiki { + # + # ::xowiki::Tree + # + # This class manages the creation and rendering of the nodes of the + # tree. It provides a name and id for rending in HTML. + + Class Tree \ + -superclass ::xo::OrderedComposite \ + -parameter { + {name ""} + id + } + + # + # Class methods + # + Tree proc renderer {style} { + set renderer TreeRenderer=$style + if {![my isclass $renderer]} { + error "No such renderer $renderer (avalialble [info commands ::xowiki::TreeRenderer=*]" + } + return $renderer + } + + Tree proc include_head_entries {{-renderer mktree} args} { + eval [my renderer $renderer] include_head_entries $args + } + + # + # Instance methods + # + Tree instproc init {} { + # If there is no id specified, use the name as id. + if {![my exists id]} {my id [my name]} + } + + Tree instproc add_item { + -category + -orderby + -itemobj + {-increasing:boolean true} + {-open_item:boolean false} + } { + set items ${category}::items + if {![my isobject $items]} { + ::xo::OrderedComposite create $items + if {[info exists orderby]} { + if {$orderby eq "page_order"} { + $items mixin add ::xo::OrderedComposite::IndexCompare + } + set direction [expr {$increasing ? "increasing" : "decreasing"}] + $items orderby -order $direction $orderby + } + } + $items add $itemobj + if {$open_item} { + $category open_tree + $itemobj set open_item 1 + } + } + Tree instproc open_tree {} {;} + Tree instproc render {{-style mktree} {-js ""} {-context ""}} { + set renderer [[self class] renderer $style] + $renderer set context $context + $renderer set js $js + TreeNode instmixin $renderer + set content [$renderer render [self]] + TreeNode instmixin "" + if {[$renderer set js] ne ""} { + append content "\n\n" + } + return $content + } + + # + # ::xowiki::TreeNode + # + # The TreeNode represents an n-ary node storing its child nodes in + # an ordered composite. In addition to its children, every node may + # have items associated. For example, a tree of categories can have + # associated categorized items, which can be added via the method + # "add_item". + # + Class TreeNode -superclass ::xo::OrderedComposite -parameter { + level label pos {open_requests 0} count {href ""} + object owner li_id ul_id ul_class + {prefix ""} {expanded true} {highlight false} + } + + TreeNode instproc open_tree {} { + my open_requests 1 + if {[my exists __parent]} {[my set __parent] open_tree} + } + + TreeNode instproc some_child_has_items {} { + foreach i [my children] { + if {[my isobject ${i}::items]} {return 1} + if {[$i some_child_has_items]} {return 1} + } + return 0 + } + + TreeNode instproc render {} { + set content "" + if {[my isobject [self]::items]} { + foreach i [[self]::items children] { + append cat_content [my render_item -highlight [$i exists open_item] $i ] + } + foreach c [my children] {append cat_content [$c render] \n} + append content [my render_node -open [expr {[my open_requests]>0}] $cat_content] + } elseif {[my open_requests]>0 || [my some_child_has_items]} { + set cat_content "" + foreach c [my children] {append cat_content [$c render] \n} + append content [my render_node -open true $cat_content] + + } + return $content + } + + # + # The rendering of trees is performed via rendering classes. All + # renderers are created and configured via the meta-class + # TreeRenderer. This meta-class defines the common attributes and + # behavior of all TreeRenders. + # + # In particular, the TreeRenders are defined to work with xowiki's + # page fragment caching. Via page fragment caching, the result of + # the rendering of includedlets is cached. However, the renderer + # might require additional CSS or JavaScript code, which has to be + # included for the cached HTML fragment as well. Therefore, the + # method "include_head_entries" is provided, which is called + # independently from HTML generation. + # + # + + Class create TreeRenderer -superclass Class \ + -parameter { + {li_expanded_atts ""} + {highlight_atts {"style = 'font-weight:bold;'"}} + } + TreeRenderer instproc include_head_entries {args} { + # to be overloaded + } + TreeRenderer instproc render {tree} { + set content "" + foreach c [$tree children] {append content [$c render] \n} + return $content + } + + # + # The renderers should provide the following methods as procs + # + # - include_head_entries {args} + # - render {tree} + # + # (both are optional) and the following methods as instprocs + # + # - render_node {{-open:boolean false} cat_content} + # - render_item {{-highlight:boolean false} item} + # + # The last two methods are required. + + # Below are the currently defined tree renderers. We use as naming + # convention TreeRenderer=