Developing Vista Sidebar Gadgets

Developing Vista Sidebar Gadgets

So those of you who have Vista will be well aware of the sidebar, some may love it, some may not see the point!  Personally I like it; I think from a developer’s perspective it opens some great possibilities to enhance existing applications/services and also just to have some fun with!  From a users perspective it adds some cool functionality to my desktop!

Vista gadgets are basically a collection of HTML, CSS and JS files; with an XML file that is the gadget manifest and contains info about the gadget properties, name, icon and description.
To make it easier to develop gadgets that perform system tasks Microsoft have provided a small framework that exposes certain properties of the host system.

Resources

Gadget Home

Development Overview

MSDN Reference

Sidebar blog

My Gadget

I wanted to develop something simple to get into using the object model and just developing gadgets in general.  So after looking at some of the documentation I decided on a “Drive Info” gadget that will display info of the drives on the host machine.  The object model exposes drive info so it should be too tricky and it wasn’t!  In the settings I am going to give the user the ability to select the drive to view the details for.

cdrive

Setup the file structure

To put a gadget on your sidebar you need to have the right files in the right place.  Vista user gadgets can be put in this location... C:\Users\<>\AppData\Local\Microsoft\Windows Sidebar\Gadgets and then in a directory named <>.gadget so in this case it’s DriveInfo.gadget.  I’ll cover preparing a gadget for deploying later.  I develop with the files in this location so it’s easy to test.

Files required:

Gadget.htm – contains the HTML mark up for the gadget displayed in the sidebar.

Settings.htm – contains the HTML mark up for the settings view.

Gadget.xml – the manifest file.

Note: You can put the JS and CSS inline in the HTML files but I prefer to have separate files referenced from the HTML. 

Here is my file structure:file structure

XML Manifest

You can read a full description of the gadget manifest in the MSDN documentation.  Some of the more important sections are:

·         The element is required and contains a string that defines the gadgets name; this will be displayed in the Gadget Gallery.

·         The element is optional and contains the gadget’s author’s name.  The author tag can contain a element that has the path to your logo!

·         The element is required and contains the host for the gadget.  Although at present the only allowed host is “sitebar”.

HTML

The HTML for this gadget is very simple as the values to display are all retrieved and set in the JavaScript file so the HTML is simply declaring and positioning some tags.  Looks just a like a standard web page!!

       <head>

              <title>Drive Info Gadget</title>

              <script type="text/javascript" src="js/Gadget.js"></script>

              <link type="text/css" rel="stylesheet" href="css/Gadget.css" />

       </head>

       <body onload="PageLoad();">

               <div class="gadget-head">

                   <span id="driveHead"></span>

               </div>

            <div class="gadget-main">

               <span id="UsedTotal"></span>

               <span id="FreeTitle" class="titles">Free: </span>

               <span id="Free"></span>

           </div>

           <div id="used-bar">

               <div id="coverBar"></div>

           </div>

       </body>

</html>

Javascript

 Most of the work is done in the JavaScript.   So straight away you will notice some differences, “onreadystatechanged”, well that is the recommended events to handle instead of onload when developing gadgets.

document.onreadystatechange = function() {

    if(document.readyState == "complete") {

         System.Gadget.settingsUI = "Settings.htm";

         System.Gadget.onSettingsClosed = settingsUpdated;

    }

}

Here is the code required to display the gadget, you can see the use of the Gadget API to get the drive object and use the properties of that object to perform various calulations for the gadget display. 

The settingsUpdated function as runs when the gadget’s settings are changed; as set above.

function PageLoad()

{

    var curDrive = System.Shell.drive(driveToView);

       driveHead.innerText = curDrive.driveLetter + ":\\ " + curDrive.driveFormat;

       // Get the used and total space into new Number objects.

       var usedSpace = new Number((curDrive.totalSize - curDrive.freeSpace) / 1012);

       var totalSpace = new Number(curDrive.totalSize / 1012);

       // Set the vars to two decimal places.

       usedSpace = usedSpace.toFixed(2);

       totalSpace = totalSpace.toFixed(2);

       // Get free space

       var freeSpace = new Number(curDrive.totalFreeSpace / 1012);

       freeSpace = freeSpace.toFixed(2);

       // % Free

       var percFree = freeSpace / totalSpace * 100;

       percFree = Math.round(percFree);

       UsedTotal.innerText = usedSpace + " GB of " + totalSpace + " GB";

       Free.innerText = freeSpace + " GB / " + percFree + "%";

       // % bar at the bottom

       coverBar.style.width = (100 - percFree) * 1.15;

}

function settingsUpdated()

{

    driveToView = System.Gadget.Settings.read("DriveToView");

    PageLoad();

}

Settings

In the settings section of the gadget (which you can see by clicking the little spanner on the top left corner of the gadget) the user can change the drive to view.  Rather than simply allowing the user to type in a drive letter I search for all active drives on the machine and give the user the option to select which drive (by drive letter and name) to view.

Settings

HTML

The mark-up for the settings is very simple and uses JavaScript for DHTML display and CSS for styling.

       <head>

              <title>Drive Info Settings</title>

              <script type="text/javascript" src="js/Settings.js"></script>

              <link type="text/css" rel="stylesheet" href="css/Settings.css" />

       </head>

       <body onload="PageLoad()">

           <span id="title">Select Drive Letter:</span>

           <select id="ddlDrives" style="width: 150px;"></select>

       </body>

</html>

JavaScript

Here I setup and array with every letter and iterate through each index checking for valid drives and adding to the drop down box items when I find a valid drive.  Again using the Gadget API.

var Drives = new Array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","X","Y","Z");

var DRIVE_TO_VIEW = "C"; // Default to C - everyone has a C drive; right!?

//

// Exec on page load - add all drive that the user has to the drop down.

//

function PageLoad()

{

    //set the close event handler

    System.Gadget.onSettingsClosing = onClose;

    // Check which drive are in use and add to the array any that are ready....

    for(var i = 0; i <= Drives.length; i++) {

        try {

            if(System.Shell.drive(Drives[i]).isReady) {

                // If drive is found add to the collection

                ddlDrives.options[ddlDrives.options.length] = new Option(Drives[i] + ":\\ " + System.Shell.drive(Drives[i]).volumeLabel, Drives[i], "", false);

            }

        }

        catch(e) {

            // Exception will be thrown if the drive doesnt exists...

            // ....this is a big perf hitter but not sure how else to do it as I cant use FileSystemObject

            continue;

        }

    }

}

function onClose(event)

{

    if(event.closeAction == event.Action.commit) {

        //save settings

        System.Gadget.Settings.write("DriveToView",   

               ddlDrives.options[ddlDrives.selectedIndex].value);

        //indicate success

        event.cancel = false;

    }

}

onClose function is called by the Gadget API when the settings panel is closed.  I then set a settings-variable to the value selected from the drop down box.  This is then used in the Gadget.js file, settingsUpdated() function.

Changed my drive letter to S:\Sdrive

Deployment

Deploying your gadget really could not be easier, simply compress your files then change the extension to .gadget (you will see the icon change), you can now simply double click to install.
Gallery

Conclusion

This is a brief introduction into developing sidebar gadgets for Vista and gives you a glimpse of the new gadget API that you have to help develop cool gadgets.  You can of course develop really cool gadgets consuming feeds from Flick for example.  Nikhilk has recently blogged about developing gadgets with script#, his own compiler that compiles C# into JavaScript, check it out here.

Although gadgets are not mind boggling, I was pleasantly surprised how easy they were to develop and I am now looking to develop one that can be used within Bath Spa University (where I work as a developer) on every desktop – just need a spark of inspiration!!

  Download the source for this article from here