#132: Return to Icon Flexibility
- Contents
- Proposed by
- Maik Röder
- Proposal type
- User interface
- Assigned to release
- State
- rejected
Definitions
The following code shows the general way, the icon is fetched to construct the CSS in Plone 2.1:
from Products.CMFCore.utils import getToolByName
pt_tool = getToolByName(context, 'portal_types')
for item in pt_tool.objectValues():
icon = item.getIcon()
This method is different from the general way the "getIcon" method is indexed on the content itself:
ti = self.getTypeInfo()
return ti.getIcon()
In a Virtual Hosting scenario, where the Plone site is the root, you would find an icon name like this in the "getIcon" metadata:
newsitem_icon.gif
If you are working with the Plone site under the root, like http://localhost:8080/Plone, the following would be indexed in "getIcon":
Plone/newsitem_icon.gif
Here are three examples, of how AttachmentField maps icons to MIME types:
The audio icon is used to group several content types like WAV and MPEG together:
- audio/mpeg
- audio/x-wav
- audio/x-pn-realaudio
- audio/x-realaudio
- audio/x-mpegurl
The Autocad is a special case that groups all MIME types related to Autocad:
- application/acad
- application/dxf
For HTML the is only one MIME type
- text/html
Motivation
The motivation for this proposal comes from the AttachmentField product, which is used in PloneExFile and PloneArticle to handle attachments.
Depending on the MIME type of the attachment, the icon is changed by AttachmentField, which makes it possible to indicate the type of Attachment already in the folder contents view.

In this folder contents view, the PDF icon shows directly what is contained in the PloneExFile.
While this flexibility was still available in Plone 2.0, it was lost in Plone 2.1 by showing the
icon based on the portal type, and no more based on the icon
Proposal
Instead of producing this kind of CSS for documents:
.contenttype-document,
.actionMenu .contenttype-document a:hover {
background-image: url(http:\\localhost:8080/ESS/document_icon.gif);
background-repeat: no-repeat;
background-position: 0% 0%;
}
This kind of CSS would be produced:
.icontype-document-icon,
.actionMenu .icontype-document-icon a:hover {
background-image: url(http:\\localhost:8080/ESS/document_icon.gif);
background-repeat: no-repeat;
background-position: 0% 0%;
}
Then, this would allow us to this for the special case of an Excel sheet in PloneExFile:
.icontype-excel_small.gif,
.actionMenu .icontype-excel a:hover {
background-image: url(http://localhost:8080/ESS/excel_small.gif);
background-repeat: no-repeat;
background-position: 0% 0%;
}
In the HTML, the changes are as follows:
Currently, the rendering of the HTML is:
<div class="contenttype-document">
This would change to:
<div class="contenticon-document">
Then, this would allow us to define classes for the purpose of PloneExFile as:
<div class="contenticon-excel">
Implementation
Modification of "generated.css.dtml":
<dtml-in "getPortalTypeList()">
<dtml-let item=sequence-item
type_icon_with_extension="normalizeString(item['icon'])"
type_icon="type_icon_with_extension[:-4]">
.contenticon-&dtml-type_icon;,
.actionMenu .contenticon-&dtml-type_icon; a:hover {
background-image: url(&dtml-portal_url;/&dtml-type_icon;);
background-repeat: no-repeat;
background-position: 0% 0%;
}
/* Holly hack to prevent items from shifting to the left in IE*/
* html .contenticon-&dtml-type_icon; {
height: 1%;
}
#portal-sitemap .contenticon-&dtml-type_icon; a:hover,
#portlet-navigation-tree .contenticon-&dtml-type_icon; a:hover,
#portlet-navigation-tree .contenticon-&dtml-type_icon; a.navTreeCurrentItem {
background-image: url(&dtml-portal_url;/&dtml-type_icon_with_extension;);
background-repeat: no-repeat;
background-position: 0% 3px;
}
#portal-sitemap .contenticon-&dtml-type_id;,
#portlet-navigation-tree .contenticon-&dtml-type_icon; {
background-position: 0% 4px;
}
* html #portal-sitemap .contenttype-&dtml-type_icon; a:hover,
* html #portlet-navigation-tree .contenttype-&dtml-type_icon; a:hover,
* html #portlet-navigation-tree .contenttype-&dtml-type_icon; a.navTreeCurrentItem {
position: relative;
}
.listing .contenticon-&dtml-type_icon; {
display: block;
}
</dtml-let>
</dtml-in>
Modification of "RTL.css.dtml":
<dtml-in "getPortalTypeList()">
<dtml-let type_icon="normalizeString(_['sequence-item']['icon'][:-4])">
.contenticon-&dtml-type_icon;,
#objectMenu .contenticon-&dtml-type_icon; a:hover {
background-position: 100% 0%;
}
#portlet-navigation-tree .contenticon-&dtml-type_icon; a:hover,
#portlet-navigation-tree .contenticon-&dtml-type_icon; a.navTreeCurrentItem {
background-position: 100% 3px; margin-right: -1px; margin-left: 0;
}
#portlet-navigation-tree .contenticon-&dtml-type_icon; {
background-position: 100% 4px;
}
</dtml-let>
</dtml-in>
Modification of "folder_listing.pt", "folder_summary_view.pt", "folder_tabular_view.pt", "folder_factories.pt", "search.pt", "portlet_navigation.pt", "portlet_navtree_macro.pt", "portlet_recent.pt", "portlet_review.pt", "folder_contents.pt", "global_contentmenu.pt" and "recently_modified.pt":
<tal:level define="item_icon_class python: 'contenticon-' + normalizeString(item['getIcon'][:-4]);">
Risks
No impact on Plone
For Plone, the only thing that changes is the class name in the HTML code
<div class="contenttype-document">
becomes
<div class="contenticon-document">
All the standard Plone CSS has to do is to generate classes for "contenticon-document" instead of "contenttype-document".
If a Plone site has been customized using these classes, they would only need to be renamed.
Moderate growth of CSS for the example of AttachmentField
The content type icon part of the Plone CSS from Plone.org is about 1500 lines long. With the current AttachmentField implementation, the CSS would grow by 500 lines. This is a moderate growth, which is due to the fact that icons are grouped. For example, the icon image.gif is used for the following MIME types:
- image/gif
- image/jpeg
- image/jpg
- image/png
- image/xpm
- image/bmp
- image/x-windows-bmp
+1 on intention, -1 on implementing it this way
If all browsers adhered to the spec, and we could do this in a saner way with less markup, it would have been a somewhat good idea. What we ended up with was a suboptimal implementation that did grew the CSS size a lot, and introduced a lot of unnnecessary markup.
The way to do this, is in my opinion:
- Go back to using getIcon to show these icons
- Put the getIcon result in the catalog, so we don't have to wake up the object to read it (it's just a path string!)
This way, content type icons can be infinitely flexible, even down to a per-instance basis (issue trackers with different icons depending on state, anyone?)
I'd hate to see this become more complex than it already is. Sometimes, it's time to admit that the original implementation was better than the new one, and go back. I believe this is the case here.
I only wanted to do it via CSS because of the switch to the catalog-backed listings. Because of some miscommunication, I believed that having the getIcon result in the catalog would be inefficient, and we came up with the CSS approach. I now know that I was wrong in my assumptions.
Let's go back to using getIcon, but let's use the catalog instead of waking up the object. I can't see any compelling use case that the CSS approach would solve, but this would not.
(It kind of has a parallel to the way the logo image is implemented in current Plone - it's very clever, and 98% of people have no idea where the logo comes from. Sometimes Plone is a bit too smart for its own good. ;)
See PLIP 178 for the other way
http://plone.org/products/plone/roadmap/178
+1 on intention, -1 on implementation
1) The way the logo's handled (it's smart, it's hard to grok, and there's a little too much of this in Plone sometimes)
2) Dynamically generated CSS ;)
This PLIP seems to be moving further down this path, and FWIW I think that's Double-Plus Ungood.
We ended up doing it differently than the PLIP states
1) Logo handling is going away (I have said many times, I believe even in my tutorial about theming Plone, that it's trying to be too smart)
2) We're going to reduce the amount of dynamically generated CSS (if you're talking about the DTML for colors etc, that is - the collapsing and compression of CSS/JS is not going away)
+1