--- /dev/null
+package SL::Layout::DHTMLMenu;
+
+use strict;
+use parent qw(SL::Layout::Base);
+
+use SL::Presenter::JavascriptMenu qw(render_menu);
+
+sub static_javascripts {
+ qw(dhtmlsuite/menu-for-applications.js),
+}
+
+sub javascripts_inline {
+<<'EOJS',
+ DHTMLSuite.createStandardObjects();
+ DHTMLSuite.configObj.setImagePath('image/dhtmlsuite/');
+ var menu_model = new DHTMLSuite.menuModel();
+ menu_model.addItemsFromMarkup('main_menu_model');
+ menu_model.init();
+ var menu_bar = new DHTMLSuite.menuBar();
+ menu_bar.addMenuItems(menu_model);
+ menu_bar.setTarget('main_menu_div');
+ menu_bar.init();
+EOJS
+}
+
+sub pre_content {
+ render_menu($_[0]->menu),
+}
+
+sub static_stylesheets {
+ qw(
+ dhtmlsuite/menu-item.css
+ dhtmlsuite/menu-bar.css
+ icons16.css
+ menu.css
+ );
+}
+
+1;
use parent qw(SL::Layout::Base);
use SL::Layout::None;
+use SL::Layout::DHTMLMenu;
use SL::Layout::Top;
use SL::Layout::ActionBar;
use SL::Layout::Content;
[
SL::Layout::None->new,
SL::Layout::Top->new,
+ SL::Layout::DHTMLMenu->new,
+ $_[0]->sub_layouts_by_name->{actionbar},
SL::Layout::Content->new,
]
}
-sub javascripts {
- my ($self) = @_;
-
- return uniq grep { $_ } map { $self->_find_javascript($_) }
- map({ $_->javascripts } $self->sub_layouts),
- qw(dhtmlsuite/menu-for-applications.js),
- $_[0]->sub_layouts_by_name->{actionbar}->javascripts,
- $self->use_javascript;
-}
-
-sub javascripts_inline {
- $_[0]->SUPER::javascripts_inline,
-<<'EOJS',
- DHTMLSuite.createStandardObjects();
- DHTMLSuite.configObj.setImagePath('image/dhtmlsuite/');
- var menu_model = new DHTMLSuite.menuModel();
- menu_model.addItemsFromMarkup('main_menu_model');
- menu_model.init();
- var menu_bar = new DHTMLSuite.menuBar();
- menu_bar.addMenuItems(menu_model);
- menu_bar.setTarget('main_menu_div');
- menu_bar.init();
-EOJS
- $_[0]->sub_layouts_by_name->{actionbar}->javascripts_inline,
-}
-
-sub pre_content {
- $_[0]->SUPER::pre_content .
- $_[0]->presenter->render("menu/menunew",
- force_ul_width => 1,
- menu => $_[0]->menu,
- icon_path => sub { my $simg = "image/icons/svg/$_[0].svg"; my $pimg="image/icons/16x16/$_[0].png"; -f $simg ? $simg : ( -f $pimg ? $pimg : ()) },
- max_width => sub { 10 * max map { length $::locale->text($_->{name}) } @{ $_[0]{children} || [] } },
- ) .
- ($_[0]->sub_layouts_by_name->{actionbar}->pre_content // '');
-}
-
-sub stylesheets {
- my ($self) = @_;
- my $css_path = $self->get_stylesheet_for_user;
-
- return
- uniq
- grep { $_ }
- map { $self->_find_stylesheet($_, $css_path) }
- qw(
- dhtmlsuite/menu-item.css
- dhtmlsuite/menu-bar.css
- icons16.css
- menu.css
- ),
- ( map { $_->stylesheets } $_[0]->sub_layouts ),
- $_[0]->sub_layouts_by_name->{actionbar}->stylesheets,
- $_[0]->use_stylesheet;
-}
-
1;
--- /dev/null
+package SL::Presenter::JavascriptMenu;
+
+use strict;
+use SL::Presenter::EscapedText qw(escape is_escaped);
+use SL::Presenter::Tag qw( html_tag link_tag);
+use SL::Locale::String qw(t8);
+use SL::System::ResourceCache;
+
+use List::Util qw(max);
+
+use Exporter qw(import);
+our @EXPORT_OK = qw(render_menu);
+
+sub render_menu {
+ my ($menu) = @_;
+
+ html_tag('div', '', id => 'main_menu_div') .
+ html_tag('ul', render_children($menu, 100, $menu->{tree}),
+ id => "main_menu_model",
+ style => 'display:none',
+ );
+}
+
+sub render_node {
+ my ($menu, $node, $id) = @_;
+ return '' if !$node->{visible};
+
+ my $icon = get_icon($node->{icon});
+ my $link = $menu->href_for_node($node) || '#';
+ my $name = $menu->name_for_node($node);
+
+ html_tag('li',
+ link_tag($link, $name, target => $node->{target})
+ . html_tag('ul', render_children($menu, $id * 100, $node->{children} // []),
+ width => max_width($node)
+ ),
+ id => $id,
+ (itemIcon => $icon)x!!$icon,
+ )
+}
+
+sub render_children {
+ my ($menu, $id, $children) = @_;
+ my $sub_id = 1;
+
+ join '', map {
+ render_node($menu, $_, 100 * $id + $sub_id++)
+ } @$children
+}
+
+sub max_width {
+ 11 * ( max( map { length $::locale->text($_->{name}) } @{ $_[0]{children} || [] } ) // 1 )
+}
+
+sub get_icon {
+ my $name = $_[0];
+
+ return undef if !defined $name;
+
+ my $simg = "image/icons/svg/$name.svg";
+ my $pimg = "image/icons/16x16/$name.png";
+
+ SL::System::ResourceCache->get($simg) ? $simg
+ : SL::System::ResourceCache->get($pimg) ? $pimg
+ : ();
+}
+
+1;
+
+
--- /dev/null
+package SL::System::ResourceCache;
+
+use strict;
+use File::stat;
+use File::Find;
+
+our @paths = qw(image css);
+our $cache;
+
+sub generate_data {
+ return if $cache;
+
+ $cache = {};
+
+ File::Find::find(sub {
+ $cache->{ $File::Find::name =~ s{^\./}{}r } = stat($_);
+ }, @paths);
+}
+
+sub get {
+ my ($class, $file) = @_;
+ no warnings 'once';
+
+ return stat($file) if ($::dispatcher // { interface => 'cgi' })->{interface} eq 'cgi';
+
+ $class->generate_data;
+ $cache->{$file};
+}
+
+1;
+
+
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+SL::System::ResourceCache - provides access to resource files without having to access the filesystem all the time
+
+=head1 SYNOPSIS
+
+ use SL::System::ResourceCache;
+
+ SL::System::ResourceCache->get($filename);
+
+=head1 DESCRIPTION
+
+This will stat() all files in the configured paths at startup once, so that
+subsequent calls can use the cached values. Particularly useful for icons in
+the menu, which would otherwise generate a few hundred file sytem accesses per
+request.
+
+The caching will not happen in CGI and script environments.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item * C<get FILENAME>
+
+If the file exists, returns a L<File::stat> object. If it doesn't exists, returns undef.
+
+=back
+
+=head1 BUGS
+
+None yet :)
+
+=head1 TODO
+
+Make into instance cache and keep it as system wide object
+
+=head1 AUTHOR
+
+Sven Schöling E<lt>sven.schoeling@googlemail.comE<gt>
+
+=cut
+
+++ /dev/null
-[%- USE T8 %]
-[%- USE L %]
-[%- USE HTML %]
-[%- USE LxERP -%]
- <div id="main_menu_div"></div>
- [%- SET main_id = '100' %]
- <ul id="main_menu_model" style='display:none'>
- [%- FOREACH node = menu.tree %]
- [%- NEXT UNLESS node.visible %]
- [%- SET main_id = main_id + 1 %]
- <li id="[% main_id %]"[% IF icon_path(node.icon) %] itemIcon="[% icon_path(node.icon) %]"[% END %]>
- [% L.link(menu.href_for_node(node) || '#', menu.name_for_node(node), target=node.target) %]
- [%- IF node.children %]
- <ul width="[% max_width(node) %]">
- [%- SET sub1_id = main_id * 100 %]
- [%- FOREACH sub1node = node.children %]
- [%- NEXT UNLESS sub1node.visible %]
- [%- SET sub1_id = sub1_id + 1 %]
- <li id="[% sub1_id %]"[% IF icon_path(sub1node.icon) %] itemIcon="[% icon_path(sub1node.icon) %]"[% END %]>
- [% L.link(menu.href_for_node(sub1node) || '#', menu.name_for_node(sub1node), target=sub1node.target) %]
- [%- IF sub1node.children %]
- <ul width="[% max_width(sub1node) %]">
- [%- SET sub2_id = sub1_id * 100 %]
- [%- FOREACH sub2node = sub1node.children %]
- [%- NEXT UNLESS sub2node.visible %]
- [%- SET sub2_id = sub2_id + 1 %]
- <li id="[% sub2_id %]"[% IF icon_path(sub2node.icon) %] itemIcon="[% icon_path(sub2node.icon) %]"[% END %]>
- [% L.link(menu.href_for_node(sub2node) || '#', menu.name_for_node(sub2node), target=sub2node.target) %]
- </li>
- [%- END %]
- </ul>
- [%- END %]
- </li>
- [%- END %]
- </ul>
- [%- END %]
- </li>
- [%- END %]
- </ul>