01_FHEMWEB now uses logical icon names

images/icons can be of gif ico jpg png type
95_FLOORPLAN and stylesheets adjusted to use logical icon names

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@1805 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
borisneubert 2012-08-18 15:20:27 +00:00
parent 4b59a45064
commit c0e0604705
8 changed files with 80 additions and 66 deletions

View File

@ -2,11 +2,6 @@
# $Id$
package main;
#
# #Todo:
# 3) logical icons should contain no extension, initial icon search uses any graphics type of png, gif, jpg
use strict;
use warnings;
use TcpServerUtils;
@ -98,6 +93,12 @@ my $FW_chash; # client fhem hash
my $FW_encoding="UTF-8";
my $ICONEXTENSION = "gif|ico|png|jpg"; # don't forget to amend FW_ServeSpecial if you change this!
# FIXME
# use constant FOO => BAR
# is better but then I cannot use FOO in a regexp. Any ideas how to fix it?
#####################################
sub
FHEMWEB_Initialize($)
@ -306,7 +307,7 @@ FW_ServeSpecial($$$) {
#Debug "We serve $dir/$file.$ext";
open(FH, "$dir/$file.$ext") || return 0;
binmode(FH) if($ext =~ m/gif|png|jpg/); # necessary for Windows
binmode(FH) if($ext =~ m/$ICONEXTENSION/); # necessary for Windows
FW_pO join("", <FH>);
close(FH);
$FW_RETTYPE = "text/plain" if($ext eq "txt");
@ -316,6 +317,7 @@ FW_ServeSpecial($$$) {
$FW_RETTYPE = "image/jpeg" if($ext eq "jpg");
$FW_RETTYPE = "image/png" if($ext eq "png");
$FW_RETTYPE = "image/gif" if($ext eq "gif");
$FW_RETTYPE = "image/x-icon" if($ext eq "ico");
return 1;
}
@ -422,7 +424,7 @@ FW_AnswerCall($)
$cachable = 0;
return 0 if(!$icon);
}
$FW_icons{$icon} =~ m/(.*)\.(gif|jpg|png)/;
$FW_icons{$icon} =~ m/(.*)\.($ICONEXTENSION)/;
my ($file,$ext)= ($1,$2);
if(FW_ServeSpecial($file,$ext,$FW_icondir)) {
@ -536,7 +538,7 @@ FW_AnswerCall($)
# Enable WebApp
if($FW_tp || $FW_ss) {
FW_pO '<link rel="apple-touch-icon-precomposed" href="'.$FW_ME.'/icons/fhemicon.png"/>';
FW_pO '<link rel="apple-touch-icon-precomposed" href="'.$FW_ME.'/icons/fhemicon"/>';
FW_pO '<meta name="apple-mobile-web-app-capable" content="yes"/>';
if($FW_ss) {
FW_pO '<meta name="viewport" content="width=320"/>';
@ -937,9 +939,8 @@ FW_roomOverview($)
if($idx<int(@list1)-1);
} else {
pF "<tr%s>", $l1 eq $FW_room ? " class=\"sel\"" : "";
my $icon = "";
$icon = "<img src=\"$FW_ME/icons/ico${l1}.png\">&nbsp;"
if($FW_icons{"ico${l1}.png"});
# image tag if we have an icon, else empty
my $icon= $FW_icons{"ico${l1}"} ? FW_makeImage("ico${l1}") . "&nbsp;" : "";
if($l2 =~ m/.html$/ || $l2 =~ m/^http/) {
FW_pO "<td><a href=\"$l2\">$icon$l1</a></td>";
@ -1005,6 +1006,9 @@ FW_showRoom()
pF "\n<tr class=\"%s\">", ($row&1)?"odd":"even";
my $devName = AttrVal($d, "alias", $d);
my $icon = AttrVal($d, "icon", "");
if($icon =~ m/^(.*)\.($ICONEXTENSION)$/) {
$icon= $1; # silently remove the extension
}
$icon = FW_makeImage($icon) . "&nbsp;" if($icon);
if($FW_hiddenroom{detail}) {
@ -1172,10 +1176,10 @@ FW_logWrapper($)
} else {
FW_pO "<div id=\"content\">";
FW_pO "<br>";
FW_zoomLink("cmd=$cmd;zoom=-1", "Zoom-in.png", "zoom in");
FW_zoomLink("cmd=$cmd;zoom=1", "Zoom-out.png","zoom out");
FW_zoomLink("cmd=$cmd;off=-1", "Prev.png", "prev");
FW_zoomLink("cmd=$cmd;off=1", "Next.png", "next");
FW_zoomLink("cmd=$cmd;zoom=-1", "Zoom-in", "zoom in");
FW_zoomLink("cmd=$cmd;zoom=1", "Zoom-out","zoom out");
FW_zoomLink("cmd=$cmd;off=-1", "Prev", "prev");
FW_zoomLink("cmd=$cmd;off=1", "Next", "next");
FW_pO "<table><tr><td>";
FW_pO "<td>";
my $logtype = $defs{$d}{TYPE};
@ -1954,10 +1958,10 @@ FW_showWeblink($$$$)
($defs{$d}{WLTYPE} eq "fileplot" || $defs{$d}{WLTYPE} eq "dbplot")&&
!AttrVal($d, "fixedrange", undef)) {
FW_zoomLink("zoom=-1", "Zoom-in.png", "zoom in");
FW_zoomLink("zoom=1", "Zoom-out.png","zoom out");
FW_zoomLink("off=-1", "Prev.png", "prev");
FW_zoomLink("off=1", "Next.png", "next");
FW_zoomLink("zoom=-1", "Zoom-in", "zoom in");
FW_zoomLink("zoom=1", "Zoom-out","zoom out");
FW_zoomLink("off=-1", "Prev", "prev");
FW_zoomLink("off=1", "Next", "next");
$buttons = 0;
FW_pO "<br>";
}
@ -2013,7 +2017,7 @@ FW_Attr(@)
sub
FW_ReadIconsFrom($$) {
# recursively reads .gif .jpg .png files and returns filenames as array
# recursively reads .gif .ico .jpg .png files and returns filenames as array
# recursion starts at $FW_icondir/$dir
# filenames are relative to $FW_icondir
@ -2023,27 +2027,23 @@ FW_ReadIconsFrom($$) {
my (@entries, @filenames);
if(opendir(DH, "${FW_icondir}/${dir}")) {
@entries= sort readdir(DH); # assures order: .gif .jpg .png
@entries= sort readdir(DH); # assures order: .gif .ico .jpg .png
closedir(DH);
}
#Debug "$#entries entries found.";
foreach my $entry (@entries) {
my $filename= "$dir/$entry";
my $iconname= "${prepend}${entry}";
#Debug " entry: \"$entry\", filename= \"$filename\", iconname= \"$iconname\"";
#Debug " entry: \"$entry\", filename= \"$filename\"";
if( -d "${FW_icondir}/${filename}" ) {
# entry is a directory
FW_ReadIconsFrom("${iconname}/", $filename) unless($entry eq "." || $entry eq "..");
FW_ReadIconsFrom("${prepend}${entry}/", $filename) unless($entry eq "." || $entry eq "..");
} elsif( -f "${FW_icondir}/${filename}") {
# entry is a regular file
if($entry =~ m/\.(png|gif|jpg)$/i) {
# extension is .gif .jpg .png
#my $basename= $entry;
#$basename =~ s/\.[^.]+$//; # cut extension
# priority due to sort: .png (highest) to .gif (lowest)
#$FW_icons{"${prepend}${basename}"}= $filenamerel;
# store icon with extension
$FW_icons{"${prepend}${entry}"}= $filename;
if($entry =~ m/^(.*)\.($ICONEXTENSION)$/i) {
my $logicalname= $1;
my $iconname= "${prepend}${logicalname}";
#Debug " icon: \"$iconname\"";
$FW_icons{$iconname}= $filename;
}
}
}
@ -2084,11 +2084,21 @@ FW_GetIcons() {
%FW_icons= split(":", $hash->{fhem}{icons});
}
sub
FW_canonicalizeIcon($) {
my ($name)= @_;
if($name =~ m/^(.*)\.($ICONEXTENSION)$/) {
Log 1, "WARNING: argument of FW_canonicalizeIcon($name) has extension - inform the developers!";
$name= $1;
}
return $name;
}
sub
FW_getIcon($) {
my ($name)= @_;
my $icon= "$name.png"; # FIXME
return $FW_icons{$icon} ? $icon : undef;
$name= FW_canonicalizeIcon($name);
return $FW_icons{$name} ? $name : undef;
}
# returns the physical absolute path relative for the logical path
@ -2097,10 +2107,8 @@ FW_getIcon($) {
# weather/sunny -> $FW_icondir/default/weather/sunny.gif
sub
FW_IconPath($) {
my ($name)= @_;
$name =~ s/\.(png)$//; # FIXME
$name= "${name}.png"; # FIXME
$name= FW_canonicalizeIcon($name);
FW_GetIcons(); # get the icon set for the current instance
my $path= $FW_icons{$name};
return $path ? $FW_icondir. $path : undef;
@ -2112,8 +2120,8 @@ FW_IconPath($) {
# weather/sunny -> /icons/sunny
sub FW_IconURL($) {
my ($name)= @_;
$name =~ s/\.(png)$//; # FIXME
return "$FW_ME/icons/${name}.png"; # FIXME
$name= FW_canonicalizeIcon($name);
return "$FW_ME/icons/${name}";
}

View File

@ -1,5 +1,6 @@
################################################################################
# 95 FLOORPLAN
# $Id $
# Feedback: http://groups.google.com/group/fhem-users
# Define Custom Floorplans
# Released : 26.02.2012
@ -302,7 +303,7 @@ FP_htmlHeader($) {
FW_pO "<title>".$title."</title>";
# Enable WebApp
if($FW_tp || $FW_ss) {
FW_pO "<link rel=\"apple-touch-icon-precomposed\" href=\"$FW_ME/fhemicon.png\"/>";
FW_pO "<link rel=\"apple-touch-icon-precomposed\" href=\"" . FW_IconURL("fhemicon") . "\"/>";
FW_pO "<meta name=\"apple-mobile-web-app-capable\" content=\"yes\"/>";
if($FW_ss) {
FW_pO "<meta name=\"viewport\" content=\"width=320\"/>";
@ -314,13 +315,17 @@ FP_htmlHeader($) {
my $rf = AttrVal($FW_wname, "refresh", "");
FW_pO "<meta http-equiv=\"refresh\" content=\"$rf\">" if($rf); # use refresh-value from Web-Instance
# stylesheet
if ($FP_name) {
my $prf = AttrVal($FP_name, "fp_stylesheetPrefix", "");
FW_pO ("<link href=\"$FW_ME/css/$prf"."floorplanstyle.css\" rel=\"stylesheet\"/>"); #use floorplanstyle.css for floorplans, evtl. with fp_stylesheetPrefix #20120730 0017
} else {
my $css = AttrVal($FW_wname, "stylesheetPrefix", "") . "floorplanstyle.css";
FW_pO "<link href=\"$FW_ME/css/$css\" rel=\"stylesheet\"/>"; #use floorplanstyle.css (incl. FW-stylesheetPrefix) for fp-start-screen #20120730 0017
}
# removed the option to have different styles for FHEMWEB and FLOORPLAN
# if ($FP_name) {
# my $prf = AttrVal($FP_name, "fp_stylesheetPrefix", "");
# FW_pO ("<link href=\"$FW_ME/css/$prf"."floorplanstyle.css\" rel=\"stylesheet\"/>"); #use floorplanstyle.css for floorplans, evtl. with fp_stylesheetPrefix #20120730 0017
# } else {
# my $css = AttrVal($FW_wname, "stylesheetPrefix", "") . "floorplanstyle.css";
# FW_pO "<link href=\"$FW_ME/css/$css\" rel=\"stylesheet\"/>"; #use floorplanstyle.css (incl. FW-stylesheetPrefix) for fp-start-screen #20120730 0017
# }
my $css = AttrVal($FW_wname, "stylesheetPrefix", "") . "floorplanstyle.css";
FW_pO "<link href=\"$FW_ME/css/$css\" rel=\"stylesheet\"/>";
#set sripts
FW_pO "<script type=\"text/javascript\" src=\"$FW_ME/svg.js\"></script>"
if($FW_plotmode eq "SVG");
@ -354,7 +359,7 @@ FP_showStart() {
FW_pO '<div id="startcontent">';
FW_pO "<br><br><br><br>No floorplans have been defined yet. For definition, use<br>";
FW_pO "<ul><code>define &lt;name&gt; FLOORPLAN</code></ul>";
FW_pO 'Also check the <a href="/fhem/commandref.html#FLOORPLAN">commandref</a><br>';
FW_pO 'Also check the <a href="$FW_ME/docs/commandref.html#FLOORPLAN">commandref</a><br>';
FW_pO "</div>";
}
FW_pO "</body>";
@ -369,7 +374,7 @@ FP_show(){
## body
FW_pO "<body id=\"$FP_name-body\">\n";
FW_pO "<div id=\"backimg\" style=\"width: 99%; height: 99%;\">";
FW_pO "<img src=\"$FW_ME/icons/fp_$FP_name.png\">"; # alternative: jpg - how? #20120730 0017
FW_pO FW_makeImage("fp_$FP_name");
FW_pO "</div>\n";
## menus
@ -392,7 +397,7 @@ FP_show(){
foreach my $d (sort keys %defs) { # loop all devices
my $type = $defs{$d}{TYPE};
my $attr = AttrVal("$d","fp_$FP_name", undef);
next if(!$attr || $type eq "weblink"); # skip if device-attribute not set for current floorplan-name
next if(!$attr || $type eq "weblink"); # skip if device-attribute not set for current floorplan-name
my ($top, $left, $style, $text, $text2) = split(/,/ , $attr);
# $top = position in px, top
@ -407,6 +412,7 @@ FP_show(){
FW_pO "<form method=\"get\" action=\"$FW_ME/floorplan/$FP_name/$d\">";
FW_pO " <table class=\"$type fp_$FP_name\" id=\"$d\" align=\"center\">"; # Main table per device
my ($allSets, $cmdlist, $txt) = FW_devState($d, "");
#Debug "txt is \"$txt\"";
$txt = ReadingsVal($d, $text, "Undefined Reading $d-<b>$text</b>") if ($style == 3); # Style3 = DeviceReading given in $text
my $cols = ($cmdlist ? (split(":", $cmdlist)) : 0); # Need command-count for colspan of devicename+state
@ -430,20 +436,20 @@ FP_show(){
########################
# Device-state per device
FW_pO "<tr class=\"devicestate fp_$FP_name\" id=\"$d\">"; # For css: class=devicestate, id=devicename
FW_pO "<tr class=\"devicestate fp_$FP_name\" id=\"$d\">"; # For css: class=devicestate, id=devicename
$txt =~ s/measured-temp: ([\.\d]*) \(Celsius\)/$1/; # format FHT-temperature
### use device-specific icons according to userattr fp_image or fp_<floorplan>.image
my $fp_image = AttrVal("$d", "fp_image", undef); # floorplan-independent icon
### use device-specific icons according to userattr fp_image or fp_<floorplan>.image
my $fp_image = AttrVal("$d", "fp_image", undef); # floorplan-independent icon
my $fp_fpimage = AttrVal("$d","fp_$FP_name".".image", undef); # floorplan-dependent icon
if ($fp_image) {
my $state = ReadingsVal($d, "state", undef);
$fp_image =~ s/\{state\}/$state/; # replace {state} by actual device-status
$txt =~ s/\<img\ src\=\"(.*)\"/\<img\ src\=\"\/fhem\/icons\/$fp_image\"/; # replace icon-link in html
$fp_image =~ s/\{state\}/$state/; # replace {state} by actual device-status
#$txt =~ s/\<img\ src\=\"(.*)\"/\<img\ src\=\"\/fhem\/icons\/$fp_image\"/; # replace icon-link in html
}
if ($fp_fpimage) {
my $state = ReadingsVal($d, "state", undef);
$fp_fpimage =~ s/\{state\}/$state/; # replace {state} by actual device-status
$txt =~ s/\<img\ src\=\"(.*)\"/\<img\ src\=\"\/fhem\/icons\/$fp_fpimage\"/; # replace icon-link in html
#$txt =~ s/\<img\ src\=\"(.*)\"/\<img\ src\=\"\/fhem\/icons\/$fp_fpimage\"/; # replace icon-link in html
}
FW_pO "<td colspan=\"$cols\">$txt";
FW_pO "</td></tr>";

View File

@ -1,8 +1,8 @@
body { background-color: #444444; font-family:Verdana; font-size:9px; background-image:url(darklogo.png); background-repeat:no-repeat; }
body[id~=Media] { background-color: #A5A5A5; font-family:Verdana; font-size:9px; background-image:url(Media.bak.png); background-repeat:no-repeat; }
body { background-color: #444444; font-family:Verdana; font-size:9px; background-image:url(../icons/darklogo); background-repeat:no-repeat; }
body[id~=Media] { background-color: #A5A5A5; font-family:Verdana; font-size:9px; background-image:url(../icons/Media.bak); background-repeat:no-repeat; }
#backimg {position:absolute; top:15px; left:190px;}
#logo { position:absolute; top: 10px; left: 10px; width:180px; height:600px; background-image:url(darklogo.png); visibility:hidden;}
#logo { position:absolute; top: 10px; left: 10px; width:180px; height:600px; background-image:url(../icons/darklogo); visibility:hidden;}
#fpmenu.fp_arrange { position:absolute; bottom:20px; left:30px; min-width:310px; font-size:9px; border:1px solid #CCCCCC; background: #111111; -moz-border-radius:8px; border-radius:8px; border-spacing: 6px; padding: 6px;
box-shadow:5px 5px 5px #000; }

View File

@ -1,5 +1,5 @@
/* Author: Till */
body { background-color: #444444; background-image:url(../icons/darklogo.png); background-repeat:no-repeat; color: #CCCCCC; font-family:Arial, Helvetica, sans-serif; font-size:13px;}
body { background-color: #444444; background-image:url(../icons/darklogo); background-repeat:no-repeat; color: #CCCCCC; font-family:Arial, Helvetica, sans-serif; font-size:13px;}
#logo { position:absolute; top:10px; left:20px; width:140px; visibility:hidden; }
#menu { position:absolute; top:170px;left:20px; width:140px; }
#hdr { position:absolute; top:10px; left:180px; }

View File

@ -1,16 +1,16 @@
body { background-color: #F0F0F0;
font-family:Arial, sans-serif;
font-size:9px; background-image:url(Grundriss.bak.png);
font-size:9px; background-image:url(../icons/Grundriss.bak);
background-repeat:no-repeat; }
body[id~=Media] { background-color: #A5A5A5;
font-family:Arial, sans-serif;
font-size:9px;
background-image:url(Media.bak.png);
background-image:url(../icons/Media.bak);
background-repeat:no-repeat; }
#logo { position:absolute; top: 10px; left: 10px;
width:64px; height:67px; background-image:url(fhem_smallscreen.png); }
width:64px; height:67px; background-image:url(../icons/fhem_smallscreen); }
#backimg {position:absolute; top:15px; left:190px;}
#menu { position:absolute; top:120px; left:20px; min-width:60px; }
#menu.floorplan { position:absolute; top:120px; left:20px; min-width:80px; font-size:14px; line-height:22px; }

View File

@ -5,7 +5,7 @@ input { font-family:Arial, sans-serif; font-size:16px;}
select { font-family:Arial, sans-serif; font-size:16px;}
#back { position:absolute; top: 2px; left:18px; }
#logo { position:absolute; top: 2px; left: 2px;
width:64px; height:67px; background-image:url(../icons/fhemicon.png); }
width:64px; height:67px; background-image:url(../icons/fhemicon); }
#menu { position:absolute; top: 2px; left:65px; }
#hdr { position:absolute; top:40px; left:65px; }
#content { position:absolute; top:85px; left: 0px; right: 0px;}

View File

@ -4,7 +4,7 @@ input { font-family:Arial, sans-serif; font-size:16px; }
select { font-family:Arial, sans-serif; font-size:16px; }
#logo { position:fixed; top:10px; left:20px;
width:100px; height:105px; background-image:url(../icons/fhemicon.png); }
width:100px; height:105px; background-image:url(../icons/fhemicon); }
#menu { position:fixed; top:120px;left:20px; width:140px; }
#hdr { position:absolute; top:10px; left:180px; }
#content { position:absolute; top:50px; left:180px; bottom:20px; right:10px; }

View File

@ -5,7 +5,7 @@ textarea { font-family:Arial, sans-serif; font-size:16px}
input { font-family:Arial, sans-serif; font-size:16px}
select { font-family:Arial, sans-serif; font-size:16px}
#logo { position:absolute; top:10px; left:10px;
width:100px; height:105px; background-image:url(fhem.png); }
width:100px; height:105px; background-image:url(fhem); }
#menu { position:absolute; top:120px;left:10px; width:100px; }
#hdr { position:absolute; top:10px; left:140px; }
#content { position:absolute; top:50px; left:140px; bottom:20px; right:10px; }