Tool icons in 2.4.x

Adding the tool icons to 2.4.x

In Sakai 2.4, the side navigation is just plain text links. in Sakai 2.5 however, they are styled with a groovy icon!

This guide is for Sakai 2.4 and will show you how to turn:


(Sakai 2.4 tool list)






into


(Sakai 2.5 style tool list)

How to

There are five steps. The essence of it is that the tool links are simply wrapped with a CSS style, and then the stylesheet tells the browser what image to use. You need to modify a few source files, add in the images, then rebuild the components.

The instructions below are just diffs of the original 2.4.x file with the modified one. If you open the appropriate file you will see where these parts need to be slotted in.

Step 1: modify the portal (part 1)

Edit: $SAKAI-SRC/portal-impl/impl/src/java/org/sakaiproject/portal/charon/SkinnableCharonPortal.java
SkinnableCharonPortal.java
Index: portal-impl/impl/src/java/org/sakaiproject/portal/charon/SkinnableCharonPortal.java
===================================================================
@@ -1415,6 +1415,10 @@
    // check if current user has permission to see page
    // we will draw page button if it have permission to see at least
    List pTools = p.getTools();
+   ToolConfiguration firstTool = null;
+   if ( pTools != null && pTools.size() > 0 ) {
+    firstTool = (ToolConfiguration) pTools.get(0);
+   }
    String toolsOnPage = null;
 
    boolean current = (page != null && p.getId().equals(page.getId()) && !p
@@ -1435,6 +1439,13 @@
     m.put("pageRefUrl", pagerefUrl);
     if (toolsOnPage != null) m.put("toolsOnPage", toolsOnPage);
     if (includeSummary) siteHelper.summarizePage(m, site, p);
+    if ( firstTool != null ) {
+     String menuClass = firstTool.getToolId();
+     menuClass = "icon-"+menuClass.replace('.','-');
+     m.put("menuClass", menuClass);
+    } else {
+     m.put("menuClass", "icon-default-tool" );     
+    }
     l.add(m);
     continue;
    }
@@ -1456,6 +1467,9 @@
     m.put("toolTitle", Web.escapeHtml(placement.getTitle()));
     m.put("jsToolTitle", Web.escapeJavascript(placement.getTitle()));
     m.put("toolrefUrl", toolrefUrl);
+    String menuClass = placement.getToolId();
+    menuClass = "icon-"+menuClass.replace('.', '-');
+    m.put("menuClass", menuClass);
     l.add(m);
    }
 
@@ -1465,6 +1479,9 @@
   String helpUrl = ServerConfigurationService.getHelpUrl(null);
   theMap.put("pageNavShowHelp", Boolean.valueOf(showHelp));
   theMap.put("pageNavHelpUrl", helpUrl);
+  theMap.put("helpMenuClass", "icon-sakai-help");
+  theMap.put("subsiteClass", "icon-sakai-subsite");
+  
 
   // theMap.put("pageNavSitContentshead",
   // Web.escapeHtml(rb.getString("sit_contentshead")));

Step 2: modify the portal (part 2)

Edit: $SAKAI-SRC/portal-impl/impl/src/java/org/sakaiproject/portal/charon/handlers/WorksiteHandler.java
WorksiteHander.java
Index: portal-impl/impl/src/java/org/sakaiproject/portal/charon/handlers/WorksiteHandler.java
===================================================================
@@ -254,7 +254,11 @@
 
     SitePage p = (SitePage) i.next();
     List pTools = p.getTools();
-
+    ToolConfiguration firstTool = null;
+    if ( pTools != null && pTools.size() > 0 ) {
+     firstTool = (ToolConfiguration) pTools.get(0);
+    }
+    
     boolean current = (page != null && p.getId().equals(page.getId()) && !p
       .isPopUp());
     String pagerefUrl = pageUrl + Web.escapeUrl(p.getId());
@@ -277,6 +281,13 @@
      m.put("jsPageId", Web.escapeJavascript(p.getId()));
      m.put("pageRefUrl", pagerefUrl);
      if (includeSummary) siteHelper.summarizePage(m, site, p);
+     if ( firstTool != null ) {
+      String menuClass = firstTool.getToolId();
+      menuClass = "icon-"+menuClass.replace('.','-');
+      m.put("menuClass", menuClass);
+     } else {
+      m.put("menuClass", "icon-default-tool" );     
+     }
      l.add(m);
      continue;
     }
@@ -298,6 +309,9 @@
      m.put("toolTitle", Web.escapeHtml(placement.getTitle()));
      m.put("jsToolTitle", Web.escapeJavascript(placement.getTitle()));
      m.put("toolrefUrl", toolrefUrl);
+     String menuClass = placement.getToolId();
+     menuClass = "icon-"+menuClass.replace('.', '-');
+     m.put("menuClass", menuClass);
      l.add(m);
     }
 
@@ -307,7 +321,9 @@
    String helpUrl = ServerConfigurationService.getHelpUrl(null);
    rcontext.put("pageNavShowHelp", Boolean.valueOf(showHelp));
    rcontext.put("pageNavHelpUrl", helpUrl);
-
+   rcontext.put("helpMenuClass", "icon-sakai-help");
+   rcontext.put("subsiteClass", "icon-sakai-subsite");
+   
    // rcontext.put("pageNavSitContentshead",
    // Web.escapeHtml(rb.getString("sit_contentshead")));

Step 3: modify the portal (part 3)

Edit: $SAKAI-SRC/portal-render-engine-impl/pack/src/webapp/vm/defaultskin/macros.vm
macros.vm
Index: portal-render-engine-impl/pack/src/webapp/vm/defaultskin/macros.vm
===================================================================
@@ -383,25 +383,25 @@
 #foreach( $page in $pageNavTools )
   #if (${page.current})
     <li class="selectedTool">
-    <span>${page.pageTitle}</span>
+    <span class="${page.menuClass}" >${page.pageTitle}</span>
     </li>
   #else
    #if (${page.ispopup})
     <li>
-    <a href="javascript:;" onclick="window.open('${page.pagePopupUrl}${page.pageId}','${page.jsPageTitle}','resizable=yes,toolbar=no,scrollbars=yes, width=800,height=600')">
+    <a href="javascript:;" class="${page.menuClass}" onclick="window.open('${page.pagePopupUrl}${page.pageId}','${page.jsPageTitle}','resizable=yes,toolbar=no,scrollbars=yes, width=800,height=600')">
     <span>${page.pageTitle}</span>
     </a>
     </li>
    #else
    <li>
-   <a href="${page.pageRefUrl}" ><span>${page.pageTitle}</span></a>
+   <a href="${page.pageRefUrl}" class="${page.menuClass}"><span>${page.pageTitle}</span></a>
    </li>
    #end
   #end
 #end
 #if (${pageNavShowHelp})
     <li>
-    <a  accesskey="6" href="${pageNavHelpUrl}" target="_blank" 
+    <a  class="${helpMenuClass}" accesskey="6" href="${pageNavHelpUrl}" target="_blank" 
      onclick="openWindow('${pageNavHelpUrl}', 
      'Help', 'resizable=yes,toolbar=no,scrollbars=yes,menubar=yes,width=800,height=600'); 
      return false">

Step 4: put the icons in place

The icons used are the FamFam silk icon set available here http://www.famfamfam.com/lab/icons/silk/
Unzip them directly into $SAKAI-SRC/reference/library/src/webapp/image/silk/

Step 5: modify the stylesheet to add the extra styles

Edit: $SAKAI-SRC/reference/library/src/webapp/skin/default/portal.css
portal.css
/* PART 9 - Tool Icons */

.icon-osp-evaluation {
	background-image: url(../../image/silk/thumb_up.png);
}

.icon-osp-glossary {
	background-image: url(../../image/silk/text_list_bullets.png);
}

.icon-osp-matrix {
	background-image: url(../../image/silk/table.png);
}

.icon-osp-presentation {
	background-image: url(../../image/silk/briefcase.png);
}

.icon-osp-presLayout {
	background-image: url(../../image/silk/layout_content.png);
}

.icon-osp-presTemplate {
	background-image: url(../../image/silk/application_view_tile.png);
}

.icon-osp-style {
	background-image: url(../../image/silk/style.png);
}

.icon-osp-wizard {
	background-image: url(../../image/silk/wand.png);
}

.icon-sakai-announcements {
	background-image: url(../../image/silk/flag_blue.png);
}

.icon-sakai-chat {
	background-image: url(../../image/silk/user_comment.png);
}

.icon-sakai-datapoint {
	background-image: url(../../image/silk/chart_line.png);
}

.icon-sakai-discussion {
	background-image: url(../../image/silk/comments.png);
}

.icon-sakai-dropbox {
	background-image: url(../../image/silk/folder_page.png);
}

.icon-sakai-gmt {
	background-image: url(../../image/silk/award_star_gold_3.png);
}

.icon-sakai-help {
	background-image: url(../../image/silk/help.png);
}

.icon-sakai-iframe {
	background-image: url(../../image/silk/page_world.png);
}

.icon-sakai-iframe-site {
	background-image: url(../../image/silk/house.png);
}

.icon-sakai-mailbox {
	background-image: url(../../image/silk/email.png);
}

.icon-sakai-messages {
	background-image: url(../../image/silk/comment.png );
}

.icon-sakai-metaobj {
	background-image: url(../../image/silk/application_form.png);
}

.icon-sakai-membership {
	background-image: url(../../image/silk/group.png);
}

.icon-sakai-motd {
	background-image: url(../../image/silk/house.png);
}

.icon-sakai-news {
	background-image: url(../../image/silk/rss.png);
}

.icon-sakai-podcasts{
	background-image: url(../../image/silk/ipod_cast.png );
}

.icon-sakai-postem{
	background-image: url(../../image/silk/database_table.png );
}

.icon-sakai-preferences{
	background-image: url(../../image/silk/cog.png );
}

.icon-sakai-rutgers-linktool{
	background-image: url(../../image/silk/application.png);
}

.icon-sakai-sections{
	background-image: url(../../image/silk/group_gear.png );
}

.icon-sakai-singleuser{
	background-image: url(../../image/silk/user.png );
}

.icon-sakai-syllabus{
	background-image: url(../../image/silk/script.png );
}

.icon-blogger{
	background-image: url(../../image/silk/book_edit.png );
}

.icon-sakai-assignment-grades{
	background-image: url(../../image/silk/page_edit.png );
}

.icon-sakai-forums{
	background-image: url(../../image/silk/comments.png );
}

.icon-sakai-gradebook-tool{
	background-image: url(../../image/silk/report.png);
}

.icon-sakai-mailtool {
	background-image: url(../../image/silk/email_go.png );
}

.icon-sakai-poll{
	background-image: url(../../image/silk/chart_bar.png);
}

.icon-sakai-sitestats {
	background-image: url(../../image/silk/chart_bar.png);
}

.icon-sakai-presentation {
	background-image: url(../../image/silk/monitor.png);
}

.icon-sakai-profile {
	background-image: url(../../image/silk/vcard_edit.png);
}

.icon-sakai-reports {
	background-image: url(../../image/silk/report_magnify.png);
}

.icon-sakai-resetpass {
	background-image: url(../../image/silk/key.png);
}

.icon-sakai-resources {
	background-image: url(../../image/silk/folder.png);
}

.icon-sakai-rwiki {
	background-image: url(../../image/silk/page_white_edit.png);
}

.icon-sakai-samigo {
	background-image: url(../../image/silk/pencil.png);
}

.icon-sakai-schedule {
	background-image: url(../../image/silk/calendar.png);
}

.icon-sakai-search {
	background-image: url(../../image/silk/find.png);
}

.icon-sakai-siteinfo {
	background-image: url(../../image/silk/application_lightning.png );
}

.icon-sakai-sitesetup {
	background-image: url(../../image/silk/application_lightning.png );
}

.icon-sakai-site-roster {
	background-image: url(../../image/silk/vcard.png);
}

/*admin tools*/
.icon-sakai-users {
	background-image: url(../../image/silk/folder_user.png);
}
.icon-sakai-aliases {
	background-image: url(../../image/silk/tag_blue.png);
}
.icon-sakai-sites {
	background-image: url(../../image/silk/application_cascade.png);
}
.icon-sakai-realms {
	background-image: url(../../image/silk/sitemap_color.png);
}
.icon-sakai-online {
	background-image: url(../../image/silk/report_user.png);
}
.icon-sakai-memory {
	background-image: url(../../image/silk/server_chart.png);
}
.icon-sakai-archive {
	background-image: url(../../image/silk/page_white_compressed.png);
}
.icon-sakai-scheduler {
	background-image: url(../../image/silk/clock.png);
}
.icon-sakai-su {
	background-image: url(../../image/silk/user_go.png);
}
.icon-sakai-usermembership {
	background-image: url(../../image/silk/drive_user.png);
}

You also need to replace the existing PART 5 in the portal.css with this one. If you have any customisations in this section like margins/colours, just take from this what you need:

portal.css
/*PART 5 - SITE TOOL LINKS  - children of #toolMenuWrap	*/
/*wrapper for ul that lists the links to tools*/
#toolMenu{
	width: 9.6em;
	padding: 0;
	margin: 1em 0 0 0;
	color: #000;
	background: inherit;
}

#toolMenu ul{
	width:auto;
	list-style: none;
	margin: 0;
	padding-right: 0;
	padding-left: 0;
}

#toolMenu li{

	margin: 0;
	width: auto;
	padding-top: 4px;
	border: 1px solid #fff;
	text-align: right;
}

/*span shim for fine grained manipulation of link display (decorative)
also hide if are going to be using icon links (as background of <a> nad <li>
*/

#toolMenu li.selectedTool span{
	display: block;
	text-decoration: none;
	padding-bottom : 2px;
    padding-right : 23px !important;
    padding-top : 2px;
    margin-bottom : 0px;
    margin-left : 0px;
    margin-right : 0px;
    margin-top : 0px;
    background-position : center right !important;
    background-repeat : no-repeat !important;
	filter:alpha(opacity=50);
	opacity: 0.50;
	-moz-opacity: 0.50;
}

#toolMenu li span{
}


#toolMenu li a:link,#toolMenu li a{
	display: block;
	text-decoration: none;
	color: #00664B;
	padding-bottom : 2px;
    padding-right : 23px !important;
    padding-top : 2px;
    margin-bottom : 0px;
    margin-left : 0px;
    margin-right : 0px;
    margin-top : 0px;
    background-position : center right !important;
    background-repeat : no-repeat !important;
}

#toolMenu li a:hover{
	text-decoration: none;
	color: #003123;
}

#toolMenu li a.selected{
	text-decoration: none;
	color: #000;
	cursor: text;
}

#toolMenu li a.selected:hover{
	text-decoration: none;
	color: #000;
	cursor: text;
}

/*
.selectedTool {
font-weight: bold;
}
*/

Now, rebuild both the portal and reference components via 'maven sakai' in those directories, restart Tomcat for good measure (not required for the skin changes, but may be required for the portal changes) and you're done.

Going a step further

Making a few more simple changes to macros.vm and your portal.css, you can add icons to the Login/Logout links, and even add custom links in the top right hand corner, like this:

and

To do this, see the following block of code that needs to be modified in macros.vm

macros.vm
<div id="loginLinks">
<a href="${loginLogInOutUrl}" title="${loginMessage}" id="loginLink1">
#if (${loginHasImage1}) 
<img src="${loginImage1}" alt="${loginMessage}"/>
#else
${loginMessage}
#end
</a>

<a href="https://my.une.edu.au" title="To myUNE" id="myUneLink1" >To myUNE</a>

#if (${loginHasLogInOutUrl2})
<a href="${loginLogInOutUrl2}" title="${loginMessage2}" id="loginLink2">
#if (${loginHasImage2}) 
<img src="${loginImage2}" alt="${loginMessage2}"/>
#${loginMessage2}
#end
</a>
#end
</div>

Note the extra id's in the <a> tags, as well as the extra link.

And the corresponding styles in portal.css

portal.css
/*main CAS link*/
#loginLink1{
	display: block;
	font-size: normal;
	margin-bottom: 5px;
	padding-right: 20px;
	background-repeat: no-repeat;
	background-position: center right;
	background-image: url(images/lock_16.png) !important; 
}

/*secondary login link*/
#loginLink2{
	display:block;
	font-size: x-small;
}

/* myUNE link */
#myUneLink1{
	margin: 1em 0 2em 0;
	display: block;
	font-size: normal;
	padding-right: 20px;
	background-repeat: no-repeat;
	background-position: center right;
	background-image: url(images/home2_16.png) !important; 
}

Make sure the images you have are in the right spot, rebuild the reference component by running 'maven sakai' in $SAKAI-SRC/reference, and you are done!

Acknowledgements

It would not have been possible for me to do this without the assistance from the following people:

  • Chris Dunstall, CSU
  • Shikh Qurishi, portfolio4u
  • Ian Boston, CARET

Thanks to all of you!

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.