Home

Desktop Sidebar stores configuration in sidebar105.settings file usually in C:\Documents and Settings\[your user name]\Application Data\Desktop Sidebar directory. And any panel has ability to store its setting in this file as well.

Simple data

IPanelConfig interface has a few methods which allows panel to store/retrieve simple data. Let's modify our previous example to display number of clicks instead of "Hello World". We will preserve this number of clicks in Desktop Sidebar settings file.

Please add following fields to firstPanel class.

IPanelConfig config;
int counter;

Now we modify Create method to retrieve number of click from settings file.

config=Config;
config.InitSetting("myCounter",0);
config.Load(panelSettings);

counter=System.Convert.ToInt32(config.GetSetting("myCounter"));

textOutput.SetText("Counter:"+counter);

Because we can store any number of parameters we use textual label to identify parameters. In our example we use "myCounter" label to identify our counter. InitSetting sets default value which is used if DS can't find such parameter in settings file.

Then we load our settings, retrieve counter from configuration object and store it in counter field of firstPanel class

Loading code is finished so now we have to work on second side - Save. Pleas modify Save method to such code.

config.SetSetting("myCounter",counter);
config.Save(panelItem);

It passes current value of our counter field to configuration object and then it saves this object in sidebar105.settings file

This is complete source of modified panel

using System;
using DesktopSidebar;

namespace firstPlugin
{
   public class firstPanel: IPanel, IPanelWindow, ITextOutputParent
   {
      Sidebar sidebar;
      IPanelParent parent;
      int cookie;

      ITextOutput textOutput;

      IPanelConfig config;
      int counter;

      public firstPanel()
      {
      }

      // IPlugin Members
      public void Create(
         int hwndParent, 
         Sidebar Sidebar, 
         IPanelParent Parent, 
         IPanelConfig Config, 
         ICanvas canvas, 
         IXmlNode configRoot, 
         IXmlNode panelConfig, 
         IXmlNode settingsRoot, 
         IXmlNode panelSettings, 
         int Cookie)
      {
         sidebar=Sidebar;
         parent=Parent;
         config=Config;
         cookie=Cookie;

         parent.SetCaption(cookie,"First .NET Panel");

         textOutput=Sidebar.GetControlFactory().CreateTextOutput();
         textOutput.Init(Sidebar.GetGlobalSettings(),Sidebar.GetSkinManager(),this,true);
         textOutput.Create(hwndParent,true);

         config.InitSetting("myCounter",0);
         config.Load(panelSettings);

         counter=System.Convert.ToInt32(config.GetSetting("myCounter"));

         textOutput.SetText("Counter:"+counter);

      }

      public void Close()
      {
         textOutput.Close();
      }

      public bool Tick(bool minute)
      {
         return false;
      }

      public void Save(IXmlBuilder panelItem, IXmlBuilder settingsRoot)
      {
         config.SetSetting("myCounter",counter);
         config.Save(panelItem);
      }

      // IPanelWindow Members
      public int GetFitHeight(int width)
      {
         return textOutput.GetFitHeight();
      }

      public System.IntPtr GetHwnd()
      {
         return (System.IntPtr)textOutput.GetHwnd();
      }

      // ITextOutputParent Members
      public void OnDrawBackground(ITextOutput textOutput, IGraphics graphics)
      {
         parent.DrawControlBackground(graphics,cookie,textOutput.GetHwnd());
      }

      public void OnClick(ITextOutput textOutput, bool dbclk)
      {
         counter++;
         textOutput.SetText("Counter:"+counter);
      }

      public void OnMouseLeave(ITextOutput textOutput)
      {
      }

      public void OnShowDetails(ITextOutput textOutput)
      {
      }

      public void OnMouseHover(ITextOutput textOutput)
      {
      }
   }
}

Structural data

Interface described above is sufficient to preserve simple data but what to do if our panel requires complex structural data? Desktop Sidebar stores all settings in XML so using IXmlNode and IXmlBuilder you can store any information there.

Let's modify our example to display a few lines of text and count click for each line separately.

Desktop Sidebar provides better control to display such type of data. This time we use IListOutput control.

Please remove inheritance from ITextOutputParent and add inheritance from IListOutputParent and change field ITextOutput textOutput to IListOutput listOutput

Now we should modify Create method to following code

// IPlugin Members
public void Create(
   int hwndParent, 
   Sidebar Sidebar, 
   IPanelParent Parent, 
   IPanelConfig Config, 
   ICanvas canvas, 
   IXmlNode configRoot, 
   IXmlNode panelConfig, 
   IXmlNode settingsRoot, 
   IXmlNode panelSettings, 
   int Cookie)
{
   sidebar=Sidebar;
   parent=Parent;
   cookie=Cookie;

   parent.SetCaption(cookie,"First .NET Panel");

   listOutput=Sidebar.GetControlFactory().CreateListOutput();
   listOutput.Init(Sidebar.GetGlobalSettings(),Sidebar.GetSkinManager(),this,false);
   listOutput.Create(hwndParent,true);

   if (panelSettings!=null && panelSettings.GetNode("rows")!=null)
   {
      loadRows(panelSettings.GetNode("rows"));
   }
   else if (configRoot.GetNode("rows")!=null)
   {
      loadRows(configRoot.GetNode("rows"));
   }
}

We create IListOutput instead of text and then we load our "rows" with number of click from settings file. But if there is no such data in settings file we read them from our DSPLUGIN file. So please enter following content to firstPlugin.dsplugin.

<?xml version="1.0" encoding="utf-8" ?> 
<plugin progid="firstPlugin.firstPlugin" compatible="85">

   <rows>
      <row value="1" />
      <row value="2" />
      <row value="3" />
      <row value="4" />
   </rows>

</plugin>

In function loadRows we iterate through subnodes of rows node and we add corresponding row to listOutput. It looks like this:

private void loadRows(IXmlNode rowsNode)
{
   for(int i=0;i<rowsNode.GetChildCount();++i)
   {
      IXmlNode node=rowsNode.GetChild(i);
      int counter=Convert.ToInt32(node.GetAttribute("value"));
      
      IListRow row=listOutput.AddRow();
      row.SetText(counter.ToString());
   }
}

Now we should change OnClick event handler to increment corresponding counter when user clicks on particular row.

public void OnClick(IListOutput list, IListRow row, bool dbclk)
{
   int counter=Convert.ToInt32(row.GetText());
   counter++;
   row.SetText(counter.ToString());
}

And last change: Save method.

public void Save(IXmlBuilder panelItem, IXmlBuilder settingsRoot)
{
   IXmlBuilder rowsNode=panelItem.AddChild("rows");
   for(int i=0;i<listOutput.size();++i)
   {
      IListRow row=listOutput.GetRow(i);
      IXmlBuilder node=rowsNode.AddChild("row");
      node.AddAttribute("value",row.GetText());
   }
}

In this method we iterate through rows in IListOutput control, we retrieve text from each row and we store this text in configuration

Complete source

using System;
using DesktopSidebar;

namespace firstPlugin
{
   public class firstPanel: IPanel, IPanelWindow, IListOutputParent 
   {
      Sidebar sidebar;
      IPanelParent parent;
      int cookie;

      IListOutput listOutput;

      public firstPanel()
      {
      }

      // IPlugin Members
      public void Create(
         int hwndParent, 
         Sidebar Sidebar, 
         IPanelParent Parent, 
         IPanelConfig Config, 
         ICanvas canvas, 
         IXmlNode configRoot, 
         IXmlNode panelConfig, 
         IXmlNode settingsRoot, 
         IXmlNode panelSettings, 
         int Cookie)
      {
         sidebar=Sidebar;
         parent=Parent;
         cookie=Cookie;

         parent.SetCaption(cookie,"First .NET Panel");

         listOutput=Sidebar.GetControlFactory().CreateListOutput();
         listOutput.Init(Sidebar.GetGlobalSettings(),Sidebar.GetSkinManager(),this,false);
         listOutput.Create(hwndParent,true);

         if (panelSettings!=null && panelSettings.GetNode("rows")!=null)
         {
            loadRows(panelSettings.GetNode("rows"));
         }
         else if (configRoot.GetNode("rows")!=null)
         {
            loadRows(configRoot.GetNode("rows"));
         }
      }

      private void loadRows(IXmlNode rowsNode)
      {
         for(int i=0;i<rowsNode.GetChildCount();++i)
         {
            IXmlNode node=rowsNode.GetChild(i);
            int counter=Convert.ToInt32(node.GetAttribute("value"));

            IListRow row=listOutput.AddRow();
            row.SetText(counter.ToString());
         }
      }

      public void Close()
      {
         listOutput.Close();
      }

      public bool Tick(bool minute)
      {
         return false;
      }

      public void Save(IXmlBuilder panelItem, IXmlBuilder settingsRoot)
      {
         IXmlBuilder rowsNode=panelItem.AddChild("rows");
         for(int i=0;i<listOutput.size();++i)
         {
            IListRow row=listOutput.GetRow(i);
            IXmlBuilder node=rowsNode.AddChild("row");
            node.AddAttribute("value",row.GetText());
         }
      }

      // IPanelWindow Members
      public int GetFitHeight(int width)
      {
         return listOutput.GetFitHeight(width);
      }

      public System.IntPtr GetHwnd()
      {
         return (System.IntPtr)listOutput.GetHwnd();
      }

      // IListOutputParent Members
      public void OnDrawBackground(IListOutput list, IGraphics graphics)
      {
         parent.DrawControlBackground(graphics,cookie,list.GetHwnd());
      }
      
      public void OnClick(IListOutput list, IListRow row, bool dbclk)
      {
         int counter=Convert.ToInt32(row.GetText());
         counter++;
         row.SetText(counter.ToString());
      }
      
      public void OnLeave(IListOutput list, IListRow row)
      {
      }
      
      public void OnScrolled(IListOutput list)
      {
      }
      
      public void OnHover(IListOutput list, IListRow row)
      {
      }
      
      public void OnShowDetails(IListOutput list, IListRow row)
      {
      }
   }
}

Panel Properties Window

Typically user changes panel settings in Panel Properties Window. Support for Panel Properties is accomplished by implementing the IPanelProperties interface. This interface contains one method, named ShowProperties. This method is called whenever the user selects Panel Properties from context menu and causes the properties dialog box to be displayed. You need to take care of creating the dialog box yourself