Posts Tagged ‘corgibytes’

Core Animation Troubles (Update)

Sunday, March 16th, 2008

After doing some research on how to approach solving my problem, I think I may have a direction to follow. And I am pretty sure that I now understand what I was doing wrong.

The problem that I was having was that I was trying to use explicit animations for everything, because I wanted to use CAKeyframeAnimation. After reading a couple of email threads[1][2] on Core Animation, I think I may fully understand what needs to be done.

Okay, so here is the explanation. Explicit animations can only be used for properties that are (1) already defined on the CALayer class and (2) are marked in the documentation as animateable. I was trying to use explicit animation for a property that does not meet either of these conditions. Damn.

Okay, so now on to what I need to do. My main goal is to be able to easily chain animations together, or define when an animation should start. Either will work, because if I know how long it takes for an animation to run, then I know when to tell the next animation to start. So, how do I do this without using explicit animations?

That is what I am going to try and figure out next. I just wanted to make sure that I posted this update before I got any responses.

[1]: http://www.cocoabuilder.com/archive/message/cocoa/2008/1/18/196720
[2]: http://www.cocoabuilder.com/archive/message/cocoa/2008/1/19/196859

Core Animation Troubles

Sunday, March 16th, 2008

I have been struggling with a Core Animation problem for over two weeks. I am going to vent here, because, frankly, I am not sure what else to do.

I have subclassed CALayer to create a layer called LetterLayer. The purpose of this layer is to display a single letter with a given font and text color[1]. I have the text display mostly worked out, but I am having trouble with animating the text color. Here is a quick recap of what I have tried, what has not worked and what I plan to do next.

The LetterLayer subclass adds three properties, letter, foregroundColor and font. I originally wrote accessor and setter methods for each of these properties by hand. I have still not gotten used to the Objective-C 2.0 features, yet.

The LetterLayer class renders its content into the CGContextRef that is passed into -(void)drawInContext:(CGContextRef)context;. At that time it takes the values specified for letter, foregroundColor and font and renders a single letter within the bounds of the clipping rectangle that is set on the given graphics context.

All of that works great. Now on to the animation troubles.

I am animating the bounds of the layers after they are displayed. I have a CAKeyframeAnimation that makes the layers grow from a size [1, 1] to a size of [layer.width, layer.height]. I create the CAKeyframeAnimation instance and set its values property to a 2 element array containing the initial size and the destination sizes for the bounds property. Here is the code that I am using.


  // grow animation
  CAKeyframeAnimation* scaleUpAnimation =
    [CAKeyframeAnimation animationWithKeyPath: @"bounds"];
  scaleUpAnimation.fillMode = kCAFillModeForwards;
  scaleUpAnimation.removedOnCompletion = NO;
  scaleUpAnimation.timeOffset = 3000;
  scaleUpAnimation.speed = 0.1;
  scaleUpAnimation.values = [NSArray arrayWithObjects:
    [NSValue valueWithRect: initialRect],
    [NSValue valueWithRect: destinationRect],
    nil];
  [letterLayer addAnimation: scaleUpAnimation
                            forKey: @"frameSizeAnimation"];

Okay. So that works. The text grows very nicely and slowly, just like I want it to. So, now on to the trouble that I am having.

I cannot for the life of me seem to be able to animate any changes to foregroundColor. Okay. I should correct that statement. I have not been able to explicitly animate foregroundColor. When I assign a new value to foregroundColor, the changes display just fine. And from what I can tell, the change takes place smoothly. I should note that this will not happen if the setter method for foregroundColor does not have a call to -(void)setNeedsDisplay;.

I have tried just about everything that I can think of to make the color change animation take place using a CAKeyframeAnimation. I have also tried a CABasicAnimation, and it does not work either.

Last night, in desperation, I decided to instrument the calls to + (id) defaultValueForKey: (NSString*) keyPath;, -(id<CAAction>)actionForKey: (NSString*) key; and -(CAAnimation*)animationForKey:(NSString*)key;. I basically adding a call to NSLog so that I could see what key path values each of these methods were getting called for. And you know what I discovered? None of these methods were getting called with a key path of "foregroundColor".

So with this discovery in hand, I decided to change the declaration of foregroundColor and the other properties, so that they are defined with the @property attribute. That had an effect. Now +(id)defaultValueForKey:(NSString*)keyPath; and -(id<CAAction>)actionForKey:(NSString*)key; were getting called. But the animation still does not work.

The next thing that I tried was to have -(id<CAAction>) actionForKey:(NSString*)key; return a CAKeyframeAnimation instance. That did not work. And neither did returning a CABasicAnimation instance.

Okay. The next thing that I tried. I had read somewhere, although I cannot remember where, that the CALayer class provides a default implementation for properties that do not have accessor and setter methods. So I commented out the accessor and setter methods that I had written. Well that did have an effect, but not the one that I wanted. Now -(void)setNeedsDisplay; is not called whenever foregroundColor is modified, so the letter only shows with the color that it is created with. Wow. Now I am moving backwards.

At this point, I am not sure what to do next. I seem to have have missed something fundamental, but I am not sure what. I have poured over the documentation in search of my mistake, and I have yet to find anything. I have searched example code. I have trolled blogs about Core Animation. I have checked all of the Core Animation articles at CocoaDev. I have bought and downloaded the new book on Core Animation that is currently in beta. I have tried everything that I can think of. Yet, I am left with nothing.

I have started to wonder if the issue is with CGColorRef properties in general. So, the next thing that I am going to try is to write a simple test CALayer subclass that provides a custom property. I am going to chose a type of something other than CGColorRef, perhaps int and see if I have any better success with that. I am also going to see if I can provide an explicit animation for backgroundColor.

I will post whatever I find out, but if anyone out there reads this and thinks that they might have an answer, then please, please post a comment or send me an email message.

Help me vast interweb! You are my only hope.

[1]: For those of you that may want to point out that I should be using a CATextLayer for this, I say bah! I have already tried that. I need to make sure that the layer size is the exact bounds of the character that is rendered into it. CATextLayer uses Mac OS X’s text rendering engine to ensure that are characters that are rendered into a layer are displayed with all of their baseline’s aligned. CATextLayer also positions characters so that taller characters can be rendered next to short characters without getting clipped. And it also make sure that characters that extend below the baseline are not clipped. This is great when you are trying to render whole words, but it causes a bunch of problems when you are trying to render a single character.

Update: I have provided more information in another post.

WebKit SVG JavaScript Co…

Monday, February 18th, 2008

WebKit SVG JavaScript Core Animation = Very Cool

Core Animation can be one frus…

Monday, February 18th, 2008

Core Animation can be one frustrating API.

AccessibilityFS is really cool…

Wednesday, February 13th, 2008

AccessibilityFS is really cool. It should really come in handy for writting UI test scripts.

Tutorial: Exand an NTFS partition on virtual disk

Tuesday, May 15th, 2007

I recently needed to expand the NTFS partion that I am using in a Virtual PC virtual machine. When I searched the web, I found several half solutions, but no one spelled everything out in detail. The steps below should help you get the job done. Most of these steps will work for any other virtual machine implementation, with the exception of the VhdResize tool that is used. You will need to find another utility that lets you expand the size of a virtual disk.

Preparation work:

  1. Make a copy of the file that contains the virtual disk. (I guess you could skip this step, but if something goes wrong, don’t complain about it. :))
  2. Download the GParted Live CD.
  3. Download VhdResize.

Resize the hard drive:

  1. Shutdown the vitual machine if it is running.
  2. Run VhdResize, and when prompted, open the virual hard disk that you want to resize.
  3. Select a file to save the resized file to. This cannot be the same as the file that you are resizing.
  4. Set the new disk size
  5. Eat a sandwhich and come back when it is done.
  6. Change the virtual machine settings to use the resized virtual disk instead of the original virtual disk.
  7. Boot the virtual machine and make sure that you are able to read and write to the resized disk. Notice that the partition is still the same size. That is because we have not made it any bigger yet. That is the next step.

Resize the partion:
Note: This part of the tutorial assumes that you have only 1 partition on your disk, if you have more than one, then you had better know what you are doing.

  1. Capture the GParted live CD
  2. Reboot the virtual machine
  3. From the boot menu, select the framebuffer option. This will cause X to fail, but since these instructions use the command line, the framebuffer option will give us more text-based screen real estate.
  4. When prompted, select a keyboard layout and a language.
  5. After X fails to launch, you should be prompted with a bash prompt. If X actually started, the Ctrl-Alt-Backspace will kill it.
  6. Execute fdisk /dev/hda. You may have to change the device if you are not changing the size of the primary partition.
  7. Enter d to delete the partion.
  8. When prompted for the partition choose enter 1.
  9. Enter n to create a new partition.
  10. Enter p to create a new primary partition.
  11. Hit the enter key to select the start of the disk as the default partition starting point.
  12. Hit the enter key to select the end of the disk as the default end point.
  13. Enter t to change the partition type.
  14. Enter 1 to select the first partion.
  15. Enter 7 to set the partion type to NTFS.
  16. Enter a to change the partion’s bootable flag.
  17. Enter 1 to select the first partition.
  18. Enter w to write the partion table out to the drive. This is the step that writes the changes out to the disk. You can still back out now.
  19. Enter q to exit fdisk. This will return you to the bash prompt.
  20. Execute ntfsresize -s 20480M -n /dev/hda1. You will need to change the size to the desired amount. This command does not actually do the resize, it just does a test run without making any changes. Once this step passes without any errors, then go on to the next one.
  21. Execute ntfsresize -s 20480M /dev/hda1.
  22. Eject the GParted live cd.
  23. Execute reboot.
  24. When the virtual machine boots, it will run chkdsk to check for errors. Once this is done, make sure that everything still works.

Now you should have succesfully resized your NTFS partion. Congrats!

Named parameters in Objective-C

Monday, February 5th, 2007

Objective-C has a mechanism that lets you name the parameters that a method accepts. It has taken me a while to really start using this capability to it’s potential, but I think that today I finally have. Check out this method definition.


- (void) assert: (PlayArea *) area has: (NSString *) value atX: (int) x Y: (int) y {
}

This lets me write the following method call.


[self assert: area has: @"W" atX: 0 Y: 1];

I really like writing lines of code that tell you exactly what they are doing. Don’t you?

Mono Win Form support on Mac OS X

Saturday, November 11th, 2006

Since Mono 1.2 was released a few days ago, I tried running a very simple test application on my Mac. From a Mac terminal, the application does not run. If you build a application bundle with macpack the application will still not run. What you need to do is launch the application from within an xterm window. While this is not ideal, at least it is possible to start running WinForms applications on my Mac!

Mono Installer for Intel Macs

Thursday, June 22nd, 2006

Sweet! There is now an installer available for getting Mono running on an Intel Mac. You won’t believe the trouble that I went through a few weeks age. I spent hours setting up an environment to build Mono on my MacBook Pro. Well, you might know, since I did write about it in an earlier post. Anyway, I have not installed it yet, but I have downloaded it. I might be able to find some time to try it out.

Getting a working build environment for Mono on an Intel Mac

Tuesday, May 30th, 2006

Thanks a bunch to FireRabbit in #cocoa# on irc.gnome.org for helping me out with this. I thought that this information might help someone else out there so here goes.

I have been trying to build Mono out of the subversion repository for a while now, but I kept running into an error. I have been using fink to grab all of the dependencies that I need, so I made sure that I had the latest of everything. But the problem remained.

For reference, here is the error that I was getting.


checking for pkg-config... /sw/bin/pkg-config
./configure: line 22766: syntax error near unexpected token `BASE_DEPENDENCIES,'
./configure: line 22766: `PKG_CHECK_MODULES(BASE_DEPENDENCIES, glib-2.0 >= $GLIB_REQUIRED_VERSION)'

FireBird claimed to have run into the same problem, and just built his bulid environment from scratch. As in no fink. He stated several times that he is not a fink fan.

So, what follows are the steps that I took to get the environment up and running.

Before doing any of the following, make sure that /usr/local/bin is first on your path. The easiest way for me to tell you to do this is to add export PATH=/usr/local/bin:$PATH at the end of your .profile file. After doing this be sure to run source ~/.profile in any open shell windows.

  1. Installing automake
    • Get the latest version of automake.
    • Extract tarball and enter directory.
    • ./configure --prefix=/usr/local
    • make
    • sudo make install
  2. Installing libtool
    • Grab the stable release of libtool.
    • ./configure --prefix=/usr/local
    • make
    • sudo make install
  3. Installing intltool
    • Grab the latest version of intltool.
    • ./configure --prefix=/usr/local
    • make
    • sudo make install
  4. Installing pkg-config
    • Grab the latest version of pkg-config.
    • ./configure --prefix=/usr/local
    • make
    • sudo make install
  5. Installing gettext
    • Grab the latest version of gettext.
    • ./configure --prefix=/usr/local
    • make
    • sudo make install
  6. Installing glib
    • Grab at least version 2.4 of glib.
    • ./configure --prefix=/usr/local
    • make
    • sudo make install

So after I did all of that, I was unable to build mono from subversion. I am not sure what the problem is, but I was not able to fix it. So, instead, I grabbed the latest tarball for mono and it worked. So, my problem is now solved. I have a working mono installation, and I am happy. :)

I hopes this helps some other Intel Mac user out there. I am hoping that the next release of mono will include support for Intel Macs, but until it does, there is always make.

AntiRSI

Sunday, March 19th, 2006

AntiRSI is a great typing break helper application for Mac OS X. It encorages short and long breaks, just like I am used to from using Workrave on Windows and Linux. There are some improvements that I would like to see. I have grabbed the source code, so maybe I will be able to make them myself.

Speeding up the mouse pointer

Sunday, March 19th, 2006

I might be strange, but I like my touchpads, or “TrackPad”s, to be really sensitive. I had cranked the sensitivity for my MacBooks TrackPad up as high as it would go using the System Preferences application, but today I found a way to get better control of this. Edit the “com.apple.trackpad.scaling” after running “open ~/Library/Preferences/.GlobalPreferences.plist”. I have set mine to 6, and it might be too fast for me. I suggest around 3 or 5 if you like a sensitive touchpad. Enjoy!

My first rails application

Tuesday, February 28th, 2006

I just finished working through the Ruby on Rails tutorial that Apple recently released. I have seen many Ruby on Rails demos in the past, but actually writing the code is an altogether different experience. I am very pleased with it, and I look forward to coming up with an excuse to use it. :)

Ruby on Rails

Tuesday, February 28th, 2006

I just noticed that my hosting provider supports Ruby on Rails for development. I am going to tackle a tutorial, and see what I think. I have been considering using Rails for a few web app ideas that I have.

Funny .Net project names

Friday, February 24th, 2006

Many .Net projects have names that start with the letter N. There is NMock, NCover, NUnit, NDepend, and I am sure that there are plenty more. Not that I have any problem with any of these projects, 3 of them I use every day, but I really do think that this naming convention is rather silly.

I was thinking about this yesterday, and I came up with the following list of satire.

  • NSite
  • NToIt
  • NVolved
  • NBetween
  • NSist
  • NGenius
  • NConceivable
  • NSide
  • NDemand
  • NLaws
  • NCompetent
  • NPut
  • NDependent

NConceivable is probably my favorite. So much so, that I am thinking of adding a shirt to my CafePress store with that printed on the front. And speaking of my store. Stop reading this, and go buy some stuff. :)

If you can think of any more add them to the comments section.

Custom Matchers in NMock 2.0

Thursday, February 23rd, 2006

This post covers how to write a custom NMock 2.0 Matcher. Matchers are objects that tell NMock 2.0 when two values match. If you have been using NMock 2.0, then you may have been using matchers without realizing it.

This example shows how to use the implicitly use the default matcher. The default matcher makes sure that the calling value and the expected value are equal to each other. Think Object.Equals().


    Expect.Once.On(list).Method("Add").With(2);

Did you see where the matcher is used. Here is the same example, but this time it calls the matcher explicitly.


    Expect.Once.On(list).Method("Add").With(Is.EqualTo(2));

Did you see it that time? A matcher object is returned by the Is.EqualTo() method. Because this is the most common behavior that is desired when writing expectations, the with method is overloaded so that it saves users some typing.

The other matchers that come with NMock 2.0 can be found in the Is class. These are listed below.

  • Is.Anything – returns a matcher that will allow any value to be accepted
  • Is.AtLeast – returns a matcher that will only allow values that are greater than or equal to the specified value
  • Is.AtMost – returns a matcher that will only allow values that are less than or equal to the specified value
  • Is.EqualTo – returns a matcher that will only allow values that are equal to the specified value
  • Is.GreaterThan – returns a matcher that will only allow values that are greater than the specified value
  • Is.LessThan – returns a matcher that will only allow values that are less than the specified value
  • Is.Nothing – returns a matcher that will not allow any value to be accepted
  • Is.NotNull – return a matcher that will accept any value that is not null
  • Is.Null – returns a matcher that will only accept null values
  • Is.Out – returns a matcher that will only accept out values
  • Is.Same – returns a matcher that will only accept the same object that is specified
  • Is.StringContaining – returns a matcher that will only accept things that contain the specified text

Even though there are many matchers that are provided by NMock 2.0, it is very conceivable that these matchers will not always meet your needs. What if you wanted a matcher that accepted a string that matched a regular expression? Or what if you wanted a matcher that only accepted values that were part of specified a collection? What if you wanted a matcher that gave you a reference to the value it received?

There are many more matchers you may need to write while using NMock 2.0. The fact that you can write your own matchers demonstrates just how extensible NMock 2.0 is. This kind of extensibility will help enusure that as your testing needs change, you will be able to extend NMock 2.0 to meet those needs.

For example, NMock 1.0 had a CollectingConstraint class that would accept any parameter, and make it available later in the test. This was useful in cases when complex logic was needed to make sure that the correct value was passed in. I used CollectingConstraint in several tests, and as I was converting I realized that there was no comparable functionality in NMock2. So to bridge this gap, I wrote CollectingMatcher. It provides the same functionality.

Ideally, I should go back and replace the use the CollectingMatcher with a custom Matcher that implements the complex logic in question. But using this matcher works well for migrating from NMock 1.0 to NMock 2.0.

I will show you an example using it, but first, familiarize yourself with the code.


  public class CollectingMatcher: NMock2.Matcher
  {
    private object collected;
    private string name;

    public CollectingMatcher(): this(null)
    {
    }

    public CollectingMatcher(string name)
    {
      this.name = name;
    }

    public override bool Matches(object o)
    {
      this.collected = o;
      return true;
    }

    public override void DescribeTo(System.IO.TextWriter writer)
    {
      if (name != null)
      {
        writer.Write(name);
      }
      else
      {
        writer.Write("< ");
        writer.Write(this.GetType().Name);
        writer.Write(">");
      }
    }

    public object Value
    {
      get
      {
        return collected;
      }
    }
  }

The important thing to note is that the matcher derives from the abstract NMock 2.0 class Matcher, and override the Matches and the DescribeTo methods.

The Matches method is where you put the logic that determines if the value that is passed in matches what the matcher is expecting. In this example, we want to accept every value that is passed in but keep the last one around in the Value property.

The DescribeTo method is used when NMock 2.0 lists the expectations that have not been met. When writing your own matcher you will want to make sure that you put enough information in the DescribeTo method, so that you can debug an unmet expectations.

Now that you have had a chance to dive into the code, lets take a look at an example. This is somewhat of a toy example, because a more meaningful one, would be a little long.

Here is the interface that we are going to use in the example.


  public interface IntegerList {
    void Add(int value);
  }

And here is the example.


  [Test]
  public void TestAdd() {
    Mockery mock = new Mockery();
    IntegerList list = (IntegerList) mock.NewMock(typeof(IntegerList));

    CollectingMatcher matcher = new CollectingMatcher();
    Expect.Once.On(list).Method("Add").With(matcher);

    Collector collector = new Collector(list);
    collector.collect(4);

    Assert.AreEqual(4, matcher.Value);
  }

As you can see, writting Matchers is pretty easy, and a really powerfull way to extend the functionality that is built into NMock 2.0. I hope that you have enjoyed this article. I am working on a second one that covers NMock 2.0 actions.

AutoHotKey

Thursday, February 9th, 2006

I have been working on a macro to drive a GUI only application that I need to use to export some data from an extremely old database application. To assist me with this task, I have started using AutoHotKey. It is an open-source application that allows you to write macros that take over the keyboard and mouse. It also has support for reading data from some Win32 controls, but what is doesn’t support directly, you can get around with direct Win32 SendMessage or PostMessage calls. The scripting language also has support for calling Windows DLLs if there. As if that was not enough, there is an option that lets you compile your script down into a compiled executable, so that you do not have to distribute the full interpreter.

In case you cannot tell, I am very pleased with this little application.

Funeral Service for a Tablet

Friday, January 27th, 2006

Rory Blyth – Neopoleon.com

I really wish I had done something like this for my PowerBook. It would have liked it. <sniffle/>

Michael Feathers: Programming On Your Own

Tuesday, January 24th, 2006

ArticleS.MichaelFeathers.ProgrammingOnYourOwn

I found these comments by Michael Feathers very enlightening. I often forget that programming is hard. I really have a lot of fun with it, so it is easy to overlook the hard parts. Or maybe it is really the hard parts that I like so much.

Of course, there is also the personal satisfaction that comes when you know that you have made someone’s life a little easier. Programmers have the power to turn “I wish there was a program that …” ideas into realities.

The danger is that in solving some problems, we inadvertently create new ones. This is something that many programmers often overlook. Sure the problem is solved, but how miserable is the user going to be when they use it? This is something that I try to be conscious of all the time.

So, to get back on topic, I agree with Michael Feather’s assertion that programming is something that has to be learned on your own. While that may sound like a negative, it is really a positive.

In many trades, it is very hard to start learning, mainly because there are so many barriers to entry.

With programming, you really only need the following.

  • A problem to solve – this can be as simple as an example from a book or a website or as complex as building a better email client
  • A good source of educational information – A website with some helpful hints is a good source. Some books are better, but they cost money. You can learn a lot with a good search engine at your side. A friend or friends to point you in the right direction is probably best.
  • The tools of the trade – you need the compiler or interpreter for the language that you are trying to learn. A decent text editor is also a must. One that is tailored for the language that you are using is better. Many of these tools are freely available.

There are very few trades out there where all of the educational materials and tools to get the job done are free. It kind of surprises me that there are not more programmers in the world.

Apple launches Intel based Macs

Tuesday, January 10th, 2006

During his MacWorld keynote, Steve Jobs announced Apple’s new Intel based Macs. We have new iMacs, and a PowerBook replacement, the 15 inch Mac Book Pro.

I am both excited and disappointed by this news. The new Mac Book Pro looks great. But my hands really prefer the keyboards on the iBooks, so I was hoping for the announcement of a new iBook today. I am currently saving up for an Apple laptop, and if I want an Intel based one, I will have to save up twice as much to get a Mac Book Pro. Maybe by the time that I have the money the new iBooks will be out.

Although, the new Mac Book Pro does have a lot of features that make me want it in spite of the high price and the keyboard.

The power cable is now secured in place magnetically. This is to help prevent someone, in my case most likely a dog, from tripping over the power cable, sending the laptop to the floor. If that happens with this connector, the cable just comes off instead. I only hope that the magnet is strong enough that it does not lose it’s magnetism after 4 years. That would suck!

The new Mac Book Pro also comes with a built-in iSight camera for video conferencing, and Apple’s new media viewing application, Front Row. To make Front Row more fun, it also comes with an elegant six button remote.

All this comes on a platform that, based on the metrics on Apple’s site, is four times faster than the existing G4 PowerBooks.

So, yeah, if the iBooks are not out by the time that I save up $2000, I am going to buy me a new Mac Book Pro.