CaubleStone Ink

.Net development and other geeky stuff

Tutorial – Google Desktop Sidebar – Hello World Part 4, Loading and Saving our properties

Posted on December 10th, 2006


Requirements

.Net Framework SDK 1.1
Google Desktop SDK

Downloads

The zip file listed here is all inclusive of all four tutorial parts. We broke up the article into four parts for ease of reading. Included in the zip is a Word doc version of all four articles.
Download (231KB)

Purpose

In this article I intend to show you how to extend our simple Google Desktop Sidebar (GDS) component. All the source is in C# 1.1. We assume that all developers looking at this article are familiar with writing code in C# and the .Net framework. For this component we will be doing a simple Hello World type sample. We will show screenshots where appropriate. Otherwise we assume you know your way around.

What it Shows

In this part of our tutorial we will be showing you how to save and load the changes you have made. We do not take it so far as to keep up with the content but it gives you the general idea.

Storing our changes

Ok, as we all know if you make a change to something and you want it to stick we must save it. Well the GDK provides that functionality as well. In order to provide this save / load functionality we must implement the interface IPersistStreamInit. To start with we need to add some basic data to our class. We are going to add the following member variables.

const int dataVersion = 1;
private bool isDirty;

The dataVersion property can probably be replaced to read from your assemblyInfo.cs file but we will leave that to you. We need this property so we can support versioning of our component. It will also help if you happen to have multiple versions running that you get the correct data loaded for your component. You don’t really need this but it does provide a bit of added support for later. The isDirty flag will be set and used so we know when anything has changed so that we know when to save our data.

So, for us to know that something has changed we need to add it to our layout property. Let’s change our code:

public GoogleDesktopDisplayContentItemLayout Layout
{
  get { return this.layout; }
  set { this.layout = value; this.isDirty = true; }
}

All we have done here is add the isDirty flag to our property. Now we also need to initialize it so let’s add some code to our constructor.

this.isDirty = false;

Now we can start looking into the IPersistStreamInit interface. The first thing you will probably notice is that it has an IsDirty property. This is used by the GDK to determine if the Save operation needs to occur. So lets modify the code, note that we need to change a Boolean value into an unsigned integer.

public UInt32 IsDirty()
{
  return (UInt32)(isDirty ? 1 : 0);
}

Now that we can tell if our component needs to be saved letss add the code to save our changes. We will do this by adding code to the Save method.

public void Save(UCOMIStream stm, bool clearDirty)
{
  MemoryStream memStream = new MemoryStream();
  BinaryWriter binWriter = new BinaryWriter(memStream);
  // first our version
  binWriter.Write(dataVersion);
  // then the data.
  binWriter.Write(this.Layout.ToString());
  // cleanup binWriter.Flush();
  // write to actual output stream
  byte[] data = memStream.ToArray();
  stm.Write(data, data.Length, IntPtr.Zero);
  if (clearDirty) isDirty = false;
}

Now again, we assume you know how to use the framework and that includes the IO process. So, what we are doing is setting up a memory stream since the GDK actually handles the file IO. To Write to the stream you should be able to use any type of writer and pass it the memory stream to write to. The first thing we write out is our dataVersion and then we write out the value of our Layout property. You will notice that we are writing the string value representation, this will make it easier to pull back in later. Once we are done we convert the memory stream into an array of bytes so we can pass it to the underlying COM stream that the GDK has provided to us. Last but not least we set the dirty flag only if the stream write was successful.

Once we have saved our data we can now add code to load our data. This works the same way just in reverse. In a more advanced scenario there is no reason why you could not serialize / de-serialize a class into this stream. Let’s add our Load code.

public void Load(UCOMIStream stm)
{
  const int maxDataLen = 1000;
  // read a large enough number of bytes for us.
  byte[] data = new byte[maxDataLen];
  stm.Read(data, data.Length, IntPtr.Zero);
  MemoryStream memStream = new MemoryStream(data);
  BinaryReader binReader = new BinaryReader(memStream);

  int version = binReader.ReadInt32();
  if (version != dataVersion)
  {
    MessageBox.Show("Invalid data version, using default values");
  }
  else
  {
    string value = binReader.ReadString();
    switch (value)
    {
      case "GDD_CONTENT_ITEM_LAYOUT_NEWS":
        this.Layout = GoogleDesktopDisplayContentItemLayout.GDD_CONTENT_ITEM_LAYOUT_NEWS;
        break;
      case "GDD_CONTENT_ITEM_LAYOUT_EMAIL":
        this.Layout = GoogleDesktopDisplayContentItemLayout.GDD_CONTENT_ITEM_LAYOUT_EMAIL;
        break;
      case "GDD_CONTENT_ITEM_LAYOUT_NOWRAP_ITEMS":
        this.Layout = GoogleDesktopDisplayContentItemLayout.GDD_CONTENT_ITEM_LAYOUT_NOWRAP_ITEMS;
        break;
    }
  }
}

In this section of code we are again creating a Memory stream and this time a Reader object. You should create the same type of Reader as you did writer so that it will be compatible. Seeing as how we have only written a small amount we have set an arbitrary size of 1000 bytes to read which is way more than enough to cover getting our info. If you had a large set of data you would need to get the actual size of your data and initialize accordingly. Since we wrote out the first value of our dataVersion we can check it first to make sure we are working with the same file. If we are then we can read the rest of the data and set our Layout property to what we saved the component with last.

Well that should do it so compile your app and you should get the following prompt.

install

If you don’t fix any problems you have and then try again. You are ready to try it out. So open your GDS and then go into the properties and change the value and then exit the GDS and re-open your data should be displayed the same as when you exited the app.

The first time you run your app you will get an error saying that you have an invalid data version. We could wrap this but we will leave this to you the reader as an exercise.

What you have learned

In this last part of our tutorial set you have learned how to load and save your data changes that you make to your plug-in. If you want to make it more extensive we will leave that to you the reader as an exercise.

Conclusion

We hope that you have found these tutorials helpful. In looking through the developer forum we saw that a lot of people had asked for one and hope this meets the needs of what you were looking for.

Enjoy.