# Tuesday, 27 July 2010

Tonight, I did a presentation on "Developing a .NET application onMac OS X using MonoMac" at the Alaska .NET Users Group meeting. I hope everyone enjoyed my presentation and learned something from it! I'd appreciate any feedback anyone has to offer!

The download link is at the end of this blog post. If you download the source, you will probably want to review all the posts I've written on MonoMac as well.

Source Code


MovieTimes source code

Tuesday, 27 July 2010 22:53:29 (Alaskan Daylight Time, UTC-08:00)
# Thursday, 08 July 2010

I use and enjoy my Microsoft 4000 keyboard very much. Its the best keyboard I found since the original Microsoft Natural Keyboard. Key placement makes sense, is comfortable to type on, I love the media keys (but honestly, why no love for next and previous track?).

The one thing I don't like however, is how Mac OSX handles PC keyboards. Why does home/end move me to the beginning and end of my document? Everybody knows they are supposed to move the cursor to the beginning and end of the current line. Thankfully, we have Double Command to help fix the issues! If only it could make the page up/down keys function like on the PC...

Thursday, 08 July 2010 18:54:57 (Alaskan Daylight Time, UTC-08:00)
# Tuesday, 06 July 2010

After I finished creating a sample application to test out the capabilities of Mono on the Mac, I figured I should create the same application in Objective-C to have an accurate understanding of what the pain points are in each technology.

The first big pain point I've come across is creating the bindings to call a web service in Objective-C. Apple provides a utility called WSMakeStubs. The utility makes creating the stubs easy and painless, or so it would seem. Out of the box the code doesn't compile.

For reasons unknown to me, WSMakeStubs utility makes duplicate method names. The issues people have with WSMakeStubs are so bad, almost every article I've read, everyone advocates using NSUrlConnection and NSXMLParser and rolling your own service calls.

Its 2010 Apple, how about coming up with a viable solution to making web service calls? Even PHP has a good web services proxy generator.

Tuesday, 06 July 2010 23:15:56 (Alaskan Daylight Time, UTC-08:00)
# Monday, 05 July 2010

I’m working on my presentation for the Alaska .NET Users Group. My goal is to build an app that consumes a web service, and displays the data. After getting the web service piece going, the next step was to display that data in a NSTableView.

I battled for hours and hours trying to figure out how to create a NSTableViewDataSource, and it turns out I was making things way to complicated. I did some searching on the web, but couldn’t really find anything except a post by John Moshakis on the Mono-osx mailing list which gave me some hope that someone had figured it out.

I emailed John, and he was gracious enough to send me some source code to work from. It turns out, I what I had wasn’t far off the mark, I just needed a few pointers.

The DataSource Code

  1. using System;
  2. using System.Collections;
  3. using MonoMac.Foundation;
  4. using MonoMac.AppKit;
  5. using MovieTimes.BusinessLogic;
  6. using System.Collections.Generic;
  7.  
  8. [Register("MyItemDataSource")]
  9. public class MyItemDataSource : NSTableViewDataSource
  10. {
  11.     public List<MyItem> MyItems { get; set; }
  12.  
  13.     static MyItemDataSource () {
  14.     }
  15.  
  16.     [Export("numberOfRowsInTableView:")]
  17.     public int numberOfRowsInTableView (NSTableView aTableView) {
  18.         if (MyItems == null)
  19.             return 0;
  20.         return MyItems.Count;
  21.     }
  22.  
  23.     [Export("tableView:objectValueForTableColumn:row:")]
  24.     public NSObject objectValueForTableColumn (NSTableView aTableView, NSTableColumn aTableColumn, int rowIndex) {
  25.         return new NSString(MyItems[rowIndex].Name);
  26.     }
  27.  
  28.     public void Items(List<MyItem> items) {
  29.         MyItems = items;
  30.     }
  31. }
  32.  
  33. public class MyItemDataSourceDelegate : NSTableViewDelegate {
  34.     public event EventHandler<MyItemChangedEventArgs> MyItemChanged;
  35.  
  36.     public MyItemDataSourceDelegate ():base()  {
  37.     }
  38.  
  39.     public override void SelectionDidChange(NSNotification notification) {
  40.         var table = notification.Object as NSTableView;
  41.            
  42.         var ds = table.DataSource as MyItemDataSource;
  43.            
  44.         var rowNum = table.SelectedRow;
  45.            
  46.         if (rowNum >= 0 && rowNum < ds.MyItems.Count)
  47.             OnMyItemChanged(new MyItemChangedEventArgs(ds.MyItems[rowNum]));
  48.     }
  49.        
  50.     protected void OnMyItemChanged(MyItemChangedEventArgs e) {
  51.         if (MyItemChanged != null)
  52.             MyItemChanged(this, e);
  53.     }
  54. }
  55.    
  56. public class MyItemChangedEventArgs : EventArgs {
  57.     public MyItem MyItem { get; set; }
  58.        
  59.     public MyItemChangedEventArgs(MyItem i) {
  60.         MyItem = i;
  61.     }
  62. }

The code is kind of long, and I’ve removed all the normal guard code you would use for the sake of brevity. But lets dissect the code. The first part, lines 8 – 31 is the actual data source. It simply listens for a few messages (numberOfRowsInTableView and objectValueForTableColumn) and allows items to be added to the data source (line 28). The next part, lines 33 – 54 fire off an event when the selected item has changed in the NSTableView instance.

The Window Code

  1. public override void WindowDidLoad () {
  2.     base.WindowDidLoad ();
  3.  
  4.     var myDel = new MyItemDataSourceDelegate();
  5.     myDel.ItemChanged += ItemChanged;
  6.  
  7.     this.someTable.Delegate = myDel;
  8.     this.someTable.DataSource = new MyItemDataSource();
  9. }

In the window controller, paste the above code to have code run when you window loads. For WinForms people, public override void WindowDidLoad is the equivilent of protected override void OnLoad().

So what does the window controller code do? First off, we create our delegate (note, delegates in Cocoa are not the same thing as in C#), and wire up to the changed event, then we assign the newly created delegate and a data source to our table.

Any questions, thoughts or feedback? Hit me up in the comments, or follow me on twitter.

C# | Mac OS X | Mono | MonoMac
Monday, 05 July 2010 08:00:00 (Alaskan Daylight Time, UTC-08:00)

For the past week or so, I've been developing a couple of sample apps in Mono with Cocoa on my Mac. In that time, I've struggled quite a bit, and learned quite a bit. One of the biggest things I've learned is things are much harder when you try and mix-in paradimes for which things were not designed.

Take for example NSTableView. Because Objective-C is duck typed, you set Delegate property of your table to this (self in Objective-C) and implement the selectionDidChange method and you will get notified when a row is selected.

Because C# is not duck typed, you have to write a whole lot of ceremony code to get notified when a row is selected. And figuring out that ceremony was a huge battle. I wouldn't have won the war without the help of John Moshakis. Another thing thats not supported is Registering a generic type, or setting a generic .NET type the property of a Cocoa widget.

That means the ceremony code has to be duplicated every time, for every different type of object. I actually tried to make a generic version of my Databinding to an NSTableView blog post, but I was thwarted by an "Invalid IL exception." Hopefully this is just a defect, and not a limitation when dealing with Cocoa.

I would file a defect on this issue with the mono project, but Novell requires you to create an account to add a defect to their bug tracker. I can understand why they want you to do this, but its not a very good way to encourage participation from the community. But I guess it is a particularly good way to discourage drive-by defect reports.

.NET | Mac OS X | Mono | MonoMac
Monday, 05 July 2010 01:28:36 (Alaskan Daylight Time, UTC-08:00)
# Sunday, 04 July 2010

It took me quite a bit of battling tonight, and some of it turned out to be an OS caching issue but I managed to set the application icon for my test MonoMac app.

Take your favorite image and convert it to a .icns file, I used the http://iconverticons.com/ website. Drop the output of that into the root of your MonoDevelop project. Next, right click on the file and set the “Build Action” to content.

Double click on “Info.plist” in the root of your project, add a new item and set its key to “Icon File”, and value to “icon” or what ever you named your icon file. Note, you do not need to put the .icns extension in the value field to make things work.

image

Sunday, 04 July 2010 08:00:00 (Alaskan Daylight Time, UTC-08:00)
# Friday, 02 July 2010

When Miguel De Icaza first announced MonoMac back in April I was pretty excited! Its been my goal for the past two years to write a half-decent, native looking, Mac OSX application with .NET. I’ve looked at the various Cocoa binding strategies for Mono and always found them lacking. Some like CocoaSharp haven’t been updated in ages, and the WinForms stuff on Mac looked plain fugly. Like Windows 95 fugly.

I found Michael Hutchinson’s quick-start post on writing a simple .NET app using MonoMac. Because I had previous experience using Interface Builder, I was able to muddle my way through building his simple app. But at the end, I wanted something more. “Hello World” is great to show you the most basic syntax of a language, and maybe how to use the compiler, but it honestly does nothing for me.

So, I set out to write real, although somewhat contrived image viewing application. Having an extensive background writing WinForms, ASP.NET and some WPF apps, the hardest part for me was trying to figure out the Cocoa equivalent to things like PictureBox, and FolderBrowserDialog. But Google as always was my friend.

I’m not going to dive into how to write the app tonight, but I will post a screen shot, and the ImageViewer source!
image

Nits

Yes Cocoa is based on an MVC architecture, and yes I should have put some of the code into a business class, but I didn’t.

.NET | C# | Mac OS X | Mono | MonoMac
Friday, 02 July 2010 07:22:00 (Alaskan Daylight Time, UTC-08:00)
# Thursday, 01 July 2010

When I started blogging 3+ years ago, I found Windows Live Writer and really loved it. Since I’ve started blogging again, I’ve switched from blogging on my PC to my Mac. Mainly because I’m trying to use and understand Mono on the Mac. Unfortunately I’ve been unable to find any decent free blogging software on the Mac.

Switching back and forth to my PC to write blog posts isn’t my idea of fun. So, I decided to fire up my Windows VM, installed WLW, and put VMware into Unity mode. I must say, I’m pretty impressed. I was able to write a blog post in WLW, take a screen capture on my Mac, and paste it into WLW with absolutely no issues. Consider me sold :)

Now, if only I could figure out how to get the link that WLW opens after making a post to open in Chrome on my Mac instead of Chrome on my VM :)

Thursday, 01 July 2010 08:25:00 (Alaskan Daylight Time, UTC-08:00)
# Saturday, 26 June 2010

This morning I thought I would sit down with my Mac and play with doing .NET development for OS X. I had previously tried, but always found things to be really frustrating. All the Cocoa bindings were out of date, and the WinForms stuff looked terrible, etc. But Miguel wrote a blog post a while back indicating they are getting serious about developing a native solution for OS X.

I downloaded the experimental version of MonoDevelop 2.4 from Michael Hutchinson blog but quickly found out the experimental version of MonoDevelop (based on 2.4 RC 4) was out dated. So I upgraded to MonoDevelop 2.4, opened it, and noticed that MonoMac wasn't an available add-in in the RTM version of MonoDevelop.

So I did what any self respecting geek would do, I started digging around inside the bundle for the experimental version of MonoDevelop from Michael Hutchinson, and found the MonoMac addin hidden inside at the path MonoDevelop.app/Contents/MacOS/lib/monodevelop/Addins/MonoDevelop.MonoMac. I copied the folder to the appropriate place of the RTM version of MonoDevelop 2.4 and everything works as expected!

Download it

Download MonoDevelop, copy it to your Applications folder. then open the contents of MonoDevelop.app, and extract MonoDevelop.MonoMac to Contents/MacOS/lib/monodevelop/Addins/. Restart MonoDevelop, and now you should be able to create a new MonoMac project!

Update

I missed two other files that updated in MonoDevelop.IPhone, download the new MonoDevelop.Addins.zip (490.49 KB) and extract it to the same place.

Saturday, 26 June 2010 15:02:05 (Alaskan Daylight Time, UTC-08:00)
# Sunday, 08 February 2009

A few weeks back, I wrote about Mac blogging software. Since then, I've removed Ecto. It was way to clunky, and not a joy to use at all. I've downloaded Blogo and figured I'd give it a whirl. So far, its pretty good. But none of these are like Windows Live Writer, which is really what I want. Oh well, can't have it all unless you write it yourself.


Sunday, 08 February 2009 12:11:01 (Alaskan Standard Time, UTC-09:00)
# Saturday, 24 January 2009

Background

Call me a control freak, but I like to see all the shared volumes on my Mac. I could open Terminal and cd to the Volumes folder, or I could use Finder and Go -> Go to Folder to see everything that OS X has mounted in my Volumes folder. But thats kind of a pain.

Solution

After a little bit of digging around, I found out about SetFile. SetFile is a command line utility that allows you to set the file attributes on files in an HFS+ directory. After figuring out the parameters for it, I came up with this little ditty to make the Volumes folder show up under "Macintosh HD." Run this in Terminal:

sudo SetFile -a v /Volumes

With this command, you are setting the visibility attribute on the Volumes folder to visible. To reverse the process, change -a v to -a V. Now open up "Macintosh HD" and you should now see all the volumes mounted on your Mac!

Screenshot
Saturday, 24 January 2009 20:59:00 (Alaskan Standard Time, UTC-09:00)
# Friday, 23 January 2009

Background

When I originally got Mac Mini, Mac OS X 10.5.1 was out. I did a quick google search and found simple steps to follow to get Time Machine to backup to a network volume on my Linux server. Everything worked great!

When Mac OS X 10.5.2 was released a few weeks later, Time Machine would no longer backup to my file server. I did a lot of googling and found I wasn't the only one with the problem, but couldn't find any solutions. I've given it the old collage try a few times since then trying to get it working again, as recently as mid December 2008, but to no avail.

I don't know what possessed me to try and get it working again this time, but I did. And I won! It wasn't an easy battle, nor was it an epic battle. But it was a battle none the less.

Problem

I found the various postings on the net about how to everything working, including Hupio's OSX Timemachine and Samba/Windows share. But nothing really worked. I kept getting the error message "the backup disk image could not be mounted."

I almost gave up again, but decided to google the error message. And came across a few more sites, but they didn't have anything of interest. I don't know why, but I tried to create my sparse bundle on the network share itself, instead of on the Mini and moving it to the network share. That got me the error message "hdiutil: create failed - Operation not supported".

Googling that error message led me to Viraj's post about Time machine + AFP + Ubuntu - Samba. Viraj got everything working by installing the AFP service on his Linux (Ubuntu) server. He linked to How to: Install Netatalk (AFP) on Ubuntu with Encrypted Authentication which was perfect because I happen to be running an Ubuntu server.

Solution

If your using a Linux file server like I am, and want to backup your Mac using Time Machine to your file server, follow these steps:

1. Install AFP on your Linux server

2. Figure out where you are going to store the backups on your file server. I stored mine in /media/backup/TimeMachine. You will need to edit your /etc/netatalk/AppleVolumes.default file and point it to the directory:

sudo echo "/media/backup/TimeMachine \"Time Machines\"" >> /etc/netatalk/AppleVolumes.default

3. Restart netatalk

sudo /etc/init.d/netatalk restart

4. Mount your "Time Machines" volume. Finder -> Go -> Connect to Server and enter afp://IPADDRESS/Time Machines

5. Create a sparse bundle. If your OS volume is case-sensitive like mine, run this in terminal:

hdiutil create -library SPUD -size 50g -fs "Case-sensitive Journaled HFS+" -type SPARSEBUNDLE -volname "TimeMachine for YOURNAME" "YOURMACSNAME_MACADDRESS.sparsebundle"
this will create a 50 GB sparse bundle for Time Machine. If your OS volume is not case-sensitive (the default) use this command:
hdiutil create -library SPUD -size 50g -fs "Journaled HFS+" -type SPARSEBUNDLE -volname "TimeMachine for YOURNAME" "YOURMACSNAME_MACADDRESS.sparsebundle"

I'm not going to go into the details about the command line, the link above goes into greater detail. You will need to read the article so you can plug the correct values in.

6. Move your newly created sparsebundle to your "Time Machines" share:

mv mini_MACADDRESS.sparsebundle /Volumes/Time\ Machines/

7. Configure your Mac to allow backing up to a network share:

defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1

8. Finally, open Time Machine, click "Change Disk" and point to your "Time Machines" volume. In 2 minutes, Time Machine will start to backup your data to your Linux network file system!

A quick note about the conventions used above

all commands blockquote are supposed to be run in Terminal. All commands that start with a sudo (items 2 and 3) are supposed to be run on your Linux server

Friday, 23 January 2009 22:42:58 (Alaskan Standard Time, UTC-09:00)
# Wednesday, 21 January 2009

I'm trying out blog editing software on my Mac Mini. So far, I've used MarsEdit and Ecto. I'm honestly not very impressed with either of them. MarsEdit doesn't support (that I've found) rich text editing from within its editor. It only supports raw HTML editing, but will shell out to other editors to do the rich text editing.

Ecto, took me quite a few tries to find a good link to download it. When I finally got it downloaded, isn't to terrible. The UI isn't very clean IMHO. Its interface for adding links is sub-par, and NOT discoverable. At least it supports a rich text editor out of the box.

I wish Microsoft would make a version of Windows Live Writer for the Mac :)

Technorati Tags:


Wednesday, 21 January 2009 21:48:12 (Alaskan Standard Time, UTC-09:00)