AndrewVos.Com .NET, C#, jQuery etc.

28May/100

jQuery.shrinkTo

A cool little plugin that shrinks and fades any element to a position on the page.

View demo

Get the script here

20Apr/100

jquery.watermark

A simple jQuery plugin that allows you to watermark text inputs. Watermarking is when you show some text in a text input, then hide the text when the user focuses on the textbox.

Check the example here

Download the code here

Peace!

21Jan/100

CodeAnywhere 1.0.0.17

Version 1.0.0.17

  • Now compiles to .NET 3.5 instead of 2.0
  • Added support for updating from the context menu
  • You can now return an object instead of a string, and CodeAnywhere will do a ToString on it before writing it back

Sorry – haven’t been around in a while. Thought I’d stop by and release an awesome piece of software, CodeAnywhere.

Let’s say you have this:

CodeAnywhere1

And then you press CAPS LOCK:

CodeAnywhere2

CodeDOM compiled the code and executed it. (It’s C# code, by the way)

BAM.

I wrote this on the train travelling to work everyday.

Install it here

Things to note:

  • It uses UI Automation to grab the text, so some apps won’t work. Notepad and Wordpad definitely do though.
  • It’s meant to set CAPS LOCK state to off when it starts. Some people have reported that it doesn’t though. Comment below if this is you (state your OS please)
15Jan/090

HtmlBuilder 0.1.33

HtmlBuilder is simple web design software, and this is it’s first release.

HtmlBuilder uses a simple template system, and includes some example templates under Help/Example Projects.

The HtmlBuilder Main Window

On the left we have the Site browser, which lists all files in the site.

HtmlBuilder Main Window

The Color Chooser Window

Favorite colors can be stored on the right hand side.

HtmlBuilder Color Chooser

Requirements

.NET Framework 3.5

Downloads

Version 0.1.33

Changes

Version 0.1.33 (January 15th 2009)

Added some DTD’s to the Insert/DTD Menu.

Version 0.1.3 (January 14th 2009)

First Release.

9Jan/090

Getting music from iTunes to your G1

I wanted to export all my music from iTunes to my G1, but I wanted to maintain the folder structure like this:

Artist\Album\TrackName.mp3

Couldn’t find anything on Google so here’s some C# code to get it done. Remember to add a reference to iTunesLib (Add Reference / COM).

   1: private static class ITunesExporter{
   2:   public static void Export(string playlistName, string path) {
   3:     iTunesAppClass iTunes = new iTunesAppClass();
   4:  
   5:     foreach (IITPlaylist playlist in iTunes.LibrarySource.Playlists) {
   6:       if (playlist.Name == playlistName) {
   7:         foreach (IITTrack track in playlist.Tracks) {
   8:           if (track.Kind == ITTrackKind.ITTrackKindFile) {
   9:             IITFileOrCDTrack file = (IITFileOrCDTrack)track;
  10:             string extension = Path.GetExtension(file.Location);
  11:             string newPath = ITunesExporter.createValidFileName(path, file.Artist, file.Album, file.Name, extension);
  12:             string newDirectoryName = Path.GetDirectoryName(newPath);
  13:             Directory.CreateDirectory(newDirectoryName);
  14:             
  15:             if (File.Exists(newPath) == false) {
  16:               File.Copy(file.Location, newPath);
  17:             }
  18:           }
  19:         }
  20:       }
  21:     }
  22:   }
  23:   private static string createValidFileName(string exportPath, string artist, string album, string track, string extension) {
  24:     artist = ITunesExporter.removeInvalidFileNameCharacters(artist);
  25:     album = ITunesExporter.removeInvalidFileNameCharacters(album);
  26:     track = ITunesExporter.removeInvalidFileNameCharacters(track);
  27:  
  28:     string filePath = exportPath;
  29:     filePath = Path.Combine(filePath, artist);
  30:     filePath = Path.Combine(filePath, album);
  31:     filePath = Path.Combine(filePath, track);
  32:     filePath = Path.ChangeExtension(filePath, extension);
  33:     return filePath;
  34:   }
  35:   private static string removeInvalidFileNameCharacters(string str) {
  36:     char[] chars = Path.GetInvalidFileNameChars();
  37:     foreach (char c in chars) {
  38:       str = str.Replace(c.ToString(), null);
  39:     }
  40:     return str;
  41:   }
  42: }

You can use the code like this:

   1: ITunesExporter.Export("Phone", @"D:\Music");

”Phone” is the playlist name and “D:\Music” is the path that the files will be exported to.

If anyone want’s to recode it to use the iTunes XML file please post the code! (I am to lazy).

7Jan/092

object.Format Extension

EDIT: I've added the string extension found here

I was reading an article on haacked today, called Fun With Named Formats, String Parsing, and Edge Cases and I started thinking what if I made a format extension method for an object which used reflection to get the properties.

The following example:

private static void test() {
  CultureInfo southAfrican = CultureInfo.CreateSpecificCulture("en-ZA");

  var human = new {
    FirstName = "Andrew",
    LastName = "Vos",
    BirthDate = new DateTime(1983, 10, 23),
    MoneyInPocket = 123.34
  };

  string formatted = human.Format(southAfrican,
    "Hello my name is {FirstName}, and my last name is {LastName}.\n" +
    "My birth date is {BirthDate:D}\n" +
    "I have {{MoneyInPocket:C}} in my pocket right now.\n" +
    "Here are some random chars... { { } }{ {} {}{} }{ {} " +
    "\nThis last value fails because there's no corresponding property: {TheLastValue}."
    );
  Console.WriteLine(formatted);
}

 

Would result in the following output:

Hello my name is Andrew, and my last name is Vos.
My birth date is 23 October 1983
I have {R 123.34} in my pocket right now.
Here are some random chars... { { } }{ {} {}{} }{ {}
This last value fails because there's no corresponding property: {TheLastValue}.

 

Here's the code:

internal static class ObjectFormatter {
  /// <summary>Formats the string by replacing format items with the objects properties.</summary>
  /// <param name="obj">The <see cref="T:System.Object"></see> to format.</param>
  /// <param name="format">A <see cref="T:System.String"></see> containing the format items.</param>
  /// <returns>A copy of format where the format items have been replace by the corresponding properties.</returns>
  /// <exception cref="T:System.ArgumentNullException">format or obj is null.</exception>
  internal static string Format(this object obj, string format) {
    return ObjectFormatter.Format(obj, null, format);
  }

  /// <summary>Formats the string by replacing format items with the objects properties.</summary>
  /// <param name="obj">The <see cref="T:System.Object"></see> to format.</param>
  /// <param name="provider">An <see cref="T:System.IFormatProvider"></see> that supplies culture-specific formatting information.</param>
  /// <param name="format">A <see cref="T:System.String"></see> containing the format items.</param>
  /// <returns>A copy of format where the format items have been replace by the corresponding properties.</returns>
  /// <exception cref="T:System.ArgumentNullException">format or obj is null.</exception>
  internal static string Format(this object obj, IFormatProvider provider, string format) {
    if (format == null) throw new ArgumentNullException("format");
    if (obj == null) throw new ArgumentNullException("obj");

    const string propertyPattern = @"\{(?<PropertyName>[a-z,0-9,_]+)\:?(?<PropertyFormat>[^}]+)?\}";
    MatchCollection matches = Regex.Matches(format, propertyPattern,
      RegexOptions.Compiled |
      RegexOptions.CultureInvariant |
      RegexOptions.IgnoreCase);

    foreach (Match match in matches) {
      string propertyName = match.Groups["PropertyName"].Value;
      string propertyFormat = match.Groups["PropertyFormat"].Value;
      PropertyInfo propertyInfo = obj.GetType().GetProperty(propertyName);

      if (propertyInfo != null) {
        object propertyValue = propertyInfo.GetValue(obj, null);
        string propertyString = null;

        if (propertyValue != null) {
          propertyString = string.Format(provider, "{0:" + propertyFormat + "}", propertyValue);
        }
        format = format.Replace(match.Value, propertyString);
      }
    }

    return format;
  }
}
internal static class StringObjectInjector {
  /// <summary>Formats the string by replacing format items with the objects properties.</summary>
  /// <param name="format">A <see cref="T:System.String"></see> containing the format items.</param>
  /// <param name="obj">The <see cref="T:System.Object"></see> to format.</param>
  /// <returns>A copy of format where the format items have been replace by the corresponding properties.</returns>
  /// <exception cref="T:System.ArgumentNullException">format or obj is null.</exception>
  internal static string Inject(this string format, object obj) {
    return obj.Format(format);
  }

  /// <summary>Formats the string by replacing format items with the objects properties.</summary>
  /// <param name="format">A <see cref="T:System.String"></see> containing the format items.</param>
  /// <param name="provider">An <see cref="T:System.IFormatProvider"></see> that supplies culture-specific formatting information.</param>
  /// <param name="obj">The <see cref="T:System.Object"></see> to format.</param>
  /// <returns>A copy of format where the format items have been replace by the corresponding properties.</returns>
  /// <exception cref="T:System.ArgumentNullException">format or obj is null.</exception>
  internal static string Inject(this string format, IFormatProvider provider, object obj) {
    return obj.Format(provider, format);
  }
}
6Jan/0913

ShellContextMenu2

Here's a refactored version of the ShellContextMenu code I released a while back. It has been converted to C# and the code is much better.

A shell context menu is the shortcut menu you see when right clicking on a file in Explorer.

Shell Context Menu

Download the code here

24Sep/080

SettingsManager 0.1

SettingsManager is a library that dynamically generates a form to allow the client to edit settings.

Take for example a class that contains the following property:

private bool someBoolean1 = true;
public bool SomeBoolean1 { get { return this.someBoolean1; } set { this.someBoolean1 = value; } }
 

To allow the client to edit this property we would typically create a Form and put some checkboxes, labels etc. on it.

With SettingsManager, we just inherit from the SettingsBase class, and apply a SettingAttribute to the property:

public class MySettings : SettingsBase {
  private bool someBoolean1 = true;
  [Setting("Demo Category", "Booleans", "Please check this box.", typeof(BooleanEditor))]
  public bool SomeBoolean1 { get { return this.someBoolean1; } set { this.someBoolean1 = value; } }
}

And show a Settings form:

MySettings settings = SettingsBase.Load<MySettings>("C:\\settings.xml");
TabbedSettingsForm settingsForm = new TabbedSettingsForm(settings);
settingsForm.ShowDialog();


And we get this:

SettingsManager

Creating custom editors

You may have noticed that the SettingAttribute constructor takes a Type. This we can use to make custom editors for types. Let's take a look at the source for the DateEditor type.

public class DateEditor : SettingEditorBase {

  DateTimePicker datePicker;

  public DateEditor(string text, object settingValue)
    : base(text, settingValue) {

    this.AddLabel(text);

    this.datePicker = new DateTimePicker();
    this.datePicker.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;

    this.datePicker.Value = (DateTime)settingValue;
    this.datePicker.ValueChanged += new EventHandler(datePicker_ValueChanged);
    this.Controls.Add(datePicker);
  }

  private void datePicker_ValueChanged(object sender, EventArgs e) {
    this.OnSettingChanged(this.datePicker.Value);
  }
}

Notice that we inherit from SettingEditorBase, which is an abstract class. Basically all that is important in this code is that we call OnSettingChanged when the value is changed. This allows the Settings form to enable the Apply button.

Creating custom Settings forms

Creating custom Settings forms is fairly easy. We inherit from SettingsFormBase, and override the InitializeEditors method. All our controls are placed on the contentPanel that is passed in as a parameter.

In InitializeEditors, we loop though this.Categories, and in turn loop through each categories' group. We then add each editor to the form.

The Ok, Cancel and Apply buttons are all taken care of in SettingsFormBase.

public class TabbedSettingsForm : SettingsFormBase {
  TabControl tabControl;
  public TabbedSettingsForm(SettingsBase settings)
    : base(settings) {
    this.Padding = new Padding(10);
  }

  public override void InitializeEditors(Panel contentPanel) {
    this.tabControl = new TabControl();
    this.tabControl.Dock = DockStyle.Fill;
    contentPanel.Controls.Add(this.tabControl);

    foreach (SettingCategory category in this.Categories) {
      TabPage tabPage = new TabPage(category.Name);
      tabPage.AutoSize = true;
      this.tabControl.TabPages.Add(tabPage);

      TableLayoutPanel content = new TableLayoutPanel();
      content.Dock = DockStyle.Fill;
      content.AutoScroll = true;
      tabPage.Controls.Add(content);

      foreach (SettingGroup group in category.Groups) {
        content.Controls.Add(new GroupTitle(group.Name));
        foreach (SettingEditorBase editor in group.Editors) {
          content.Controls.Add(editor);
        }
      }
    }
  }
}
 
Source and a Demo project is available here.
2Jul/081

GoogleSearchButtons

My first Firefox extension, a simple toolbar that shows Google search buttons like the Google Toolbar.

EDIT: Maybe I wasn't clear, these buttons search the current web page text and highlight occurrences of the string.

GoogleSearchButtons

Useful because I've taken to using the main search box included with Firefox, but still wanted those buttons.

Click View/Toolbars/Google Search Buttons to hide or show the toolbar.

Download

26May/084

Drive Icons

Basically a clone of this, but without the timer. Oh, also the memory usage looks better.

Download it here

EDIT: WHOA! I forgot to include a required DLL in the zip file! Sorry! I'm a moron! (It's in there now)

Tagged as: , 4 Comments