Rotate NSImage in an NSImageView
I didn’t want to half-implement the new tab feature in Slider – I want people to have almost as much control as if they were coding the site by hand.
This has meant I’ve had to rethink Slider’s UI many times, and I’ve had (re: couldn’t face shipping without) to implement many small features that I feel are required, from a usability standpoint.
When I decided that the user may choose to place tabs in 12 different positions, I needed to consider how this would effect the arrows and sliding animations. I came to the conclusion that if the user elects to place the tabs on the top or bottom, the arrows will be on the left and right, with the animation going right/left. If the user chooses to place tabs on the left or right, the arrows will be positioned on the top and bottom, with the animation going up/down.
Pictures make it easier:


As soon as I implemented this I realised how much of a pain it would be to copy out the arrow images, rotate them in an external program, then copy them back in. So I put some buttons next to the arrow image wells that allow the user to rotate the arrows within Slider itself.
Here is the code I used to rotate the images (thanks to Jerry Krinock and Steve Christensen and for posting this solution to the Cocoa-dev list):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #import <Cocoa/Cocoa.h> @interface NSImage (Transform) /*! @brief Rotates an image around its center by a given angle in degrees and returns the new image. @details The width and height of the returned image are, respectively, the height and width of the receiver. I have not yet tested this with a non-square image. authors: Jerry Krinock and Steve Christensen */ - (NSImage*)imageRotatedByDegrees:(CGFloat)degrees ; @end #import "NSImage+Transform.h" @implementation NSImage (Transform) - (NSImage*)imageRotatedByDegrees:(CGFloat)degrees { // calculate the bounds for the rotated image NSRect imageBounds = {NSZeroPoint, [self size]}; NSBezierPath* boundsPath = [NSBezierPath bezierPathWithRect:imageBounds]; NSAffineTransform* transform = [NSAffineTransform transform]; [transform rotateByDegrees:degrees]; [boundsPath transformUsingAffineTransform:transform]; NSRect rotatedBounds = {NSZeroPoint, [boundsPath bounds].size}; NSImage* rotatedImage = [[NSImage alloc] initWithSize:rotatedBounds.size]; // center the image within the rotated bounds imageBounds.origin.x = NSMidX(rotatedBounds) - (NSWidth (imageBounds) / 2); imageBounds.origin.y = NSMidY(rotatedBounds) - (NSHeight (imageBounds) / 2); // set up the rotation transform transform = [NSAffineTransform transform]; [transform translateXBy:+(NSWidth(rotatedBounds) / 2) yBy:+ (NSHeight(rotatedBounds) / 2)]; [transform rotateByDegrees:degrees]; [transform translateXBy:-(NSWidth(rotatedBounds) / 2) yBy:- (NSHeight(rotatedBounds) / 2)]; // draw the original image, rotated, into the new image [rotatedImage lockFocus]; [transform concat]; [self drawInRect:imageBounds fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0] ; [rotatedImage unlockFocus]; return [rotatedImage autorelease]; } @end |
I had to change (from/to):
NSImage* rotatedImage = [[[NSImage alloc] initWithSize:rotatedBounds.size] autorelease];
NSImage* rotatedImage = [[NSImage alloc] initWithSize:rotatedBounds.size];
return rotatedImage;return [rotatedImage autorelease];
[transform set];
[transform concat];
For it to work flawlessly with Slider.
Thanks guys!
Like this post? Move it on along with:
Email |
delicious |
Digg |
Tweet |
Reddit |
Newsvine |
Furl |
Google |
Stumble |
HaoHao
| Trackback: |
Scroll to post title
Tile an NSImage Within an NSBezierPath
Another snippet I had to write during the great Slider rebuild.
I needed to be able to take an NSImage supplied by the user and tile it within an NSBezierPath defined by more user-set values.
The below example uses a rounded rectangle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | NSBitmapImageRep *theImage = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:imageSize.width pixelsHigh:imageSize.height bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:0 bitsPerPixel:0]; [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:theImage]]; //bgImage can be any NSImage NSColor *c = [NSColor colorWithPatternImage:bgImage]; [c set]; [path appendBezierPathWithRoundedRect:NSMakeRect(0, 0, imageSize.width, imageSize.height) xRadius:10.0 yRadius:10.0]; [path fill]; [NSGraphicsContext restoreGraphicsState]; |
Like this post? Move it on along with:
Email |
delicious |
Digg |
Tweet |
Reddit |
Newsvine |
Furl |
Google |
Stumble |
HaoHao
| Trackback: |
Scroll to post title
Fancy Footer Update
I’ve updated the Fancy Footer snippet, now Trackbacks/Pingbacks will be able to find your posts – the previous version’s implementation was … lacking.
The previous snippet used the post permalink as both the permalink and the path – the Trackback/Pingback system didn’t like “http://“ being included in the path attribute.
I was afraid that I wouldn’t be able to find a solution that allowed us to have Trackback/Pingback support and keep our existing comments.
I am glad to say that my fears were unfounded, and I managed to come up with a solution. The snippet now parses out the “http://domain.com” part of the permalink, and uses that for the path attribute for the widgets. Happily, JS-Kit must do a similar thing, as it hasn’t messed up my comments (the path attribute is what JS-Kit uses to determine what page to display which comments).
The snippet may be downloaded here. To learn how to use this snippet, read Fancy Footer – Usage and Tips.
Like this post? Move it on along with:
Email |
delicious |
Digg |
Tweet |
Reddit |
Newsvine |
Furl |
Google |
Stumble |
HaoHao
| Trackback: |
Scroll to post title
JS-Kit Comments + Greybox on Any Page
I’ve been using JS-Kit for comments for a long time, and I’ve been extremely impressed with the quality of their service.
They’ve recently acquired Haloscan, which is great – I dropped Haloscan in favour of JS-Kit some time ago, as I didn’t like the lack of control I felt I had over my comments. I haven’t looked back.
A few weeks ago I was showing my site to a fellow student, when she asked me why people were unable to leave comments on my photo pages. I couldn’t think of a reason, so as soon as I got home I set about fixing this lack.
After thinking about the problem for a short time, I realised that I didn’t want comments to be visible on the page in case one set of photos became wildly popular (yeah, right); which would result in a page of comments with a few photos, instead of a page of photos with maybe one or two comments. For some reason, Greybox popped into my head, and wouldn’t leave. A few hours later, this happened: Hangzhou Day 1.
If you like the effect, read on. Below is a short tutorial explaining how it was accomplished.
1) You must first have Greybox integrated with your site. Jan Erik Moström has written a tutorial explaining how to do this: RapidWeaver – using Greybox in a theme.
When you’re done with that (please make a test page to verify Greybox is working), head over to Code of Interest and download the Friendly Comments snippet.
Friendly Comment Snippet’s User Rating:
2) Open your RW project, select/create the page you wish to add JS-Kit comments to.
3) Open the page inspector, go to the Header > CSS tab. Paste the following CSS:
#comment{
height: 40px;
visibility: hidden;
font-size: 13px;
}
.href{
font-size: 15px;
}
#subtext{
height: 12px;
position: relative;
top: -20px;
visibility: hidden;
font-size: 8px;
font-style: italic;
}
Please note that the CSS may require some editing to ensure the link to the comment page matches the style of your site. Not all of us adore grey links.
The CSS reserves a space for the comments link, which is generated when the page has finished loading.
4) Still in the page inspector, switch to the Javascript tab. Drag the Friendly Comments snippet in. Close the page inspector.
Please note that if you are using a different script on the page that uses the “addLoadEvent†function, you don’t need to add the function again. You will, however, need to make a call to it:
addLoadEvent(friendlyComment);
Create a new HTML page. The following code should be modified, then pasted into this page:
A_TITLE = a title (do this now, it’ll come in handy in the future ;)
PATH_TO_MAIN_PAGE = full URL to the page containing the link to this comment page.
As this page will only be displaying comments, it won’t need much of the styling required for the other pages in your site. The way I accomplished this is possibly not the best, but it worked for me. I copied the CSS from the styles.css file for the theme I use, pasted it between tags, and removed the information from the {…} for each item. It took awhile. I suggest you work through the rest of the tutorial and preview your work to see if you need this step.
Now you should upload the HTML page.
6) On your main page, wherever you wish the link to the comment page to appear, paste* the following:
(Comments will open on top of this page)
You will need to change the following:
***X = Horizontal size of the comment Greybox
***Y = Vertical size of the comment Greybox
LINK_TO_THIS_PAGE = the full URL to the page this code is to be pasted in
LINK_TO_COMMENTS_PAGE = full URL to the comments page
TITLE_OF_COMMENTS = Text you wish to appear at the top of the comment Greybox
This code should go in either the main body of the page or the sidebar. On my photo pages I’ve pasted it into the “header†area of the Rapidflicker plugin.
As an example, this is the exact code I use for my Hangzhou Day 1 photo page:
(Comments will open on top of this page)
*Remember to select the pasted code and either choose “Format > Ignore Formatting†from the RapidWeaver menu, or press “⌘ + .â€
Always do this when pasting code. Always.
If you don’t do this, there is a good chance that the code will break. Always do this!
As an added precaution, open the Page Inspector, go to the “General†tab and choose “Output: Defaultâ€. This will stop RapidWeaver from inadvertently breaking PHP or HTML code.
To learn more JS-Kit tricks, read the following posts:
Fancy Footer
JS-Kit Comments for Each Blog Entry
JS-Kit Comments: Correct Usage of the ‘Permalink’ and ‘Path’ Attributes
Recent Comments PHP Script
Styling JS-Kit Comments
JS-Kit Comments: Correct Usage of the ‘Permalink’ and ‘Path’ Attributes
Like this post? Move it on along with:
Email |
delicious |
Digg |
Tweet |
Reddit |
Newsvine |
Furl |
Google |
Stumble |
HaoHao
| Trackback: |
Scroll to post title
Archive Annihilator Improved Again
The solution for the ’sidebar explosion’ effect that the Archive Annihilator caused occurred to me earlier today. The fix was pretty simple, the fact that I didn’t think of it right away is a little embarrassing.
The update has been uploaded, and is available here.
Like this post? Move it on along with:
Email |
delicious |
Digg |
Tweet |
Reddit |
Newsvine |
Furl |
Google |
Stumble |
HaoHao
| Trackback: |
Scroll to post title





























Recent Comments
Js Kit Comments Correct Usage Of The Permalink And Path Attributes
HTML codes are always confusing but once one gets the hang of it, things will be pretty smooth from there on.
--
technology essays | essay topics
Wed, 03 Feb 2010 09:04:20 +0000
Js Kit Comments Correct Usage Of The Permalink And Path Attributes
不错啊 挺好的 希望大家有空去也去我的小站光临 http://www.8zyu.com/ welcome to http://www.8zyu.com/ for UGG Boots
Tue, 02 Feb 2010 03:12:37 +0000
Js Kit Comments Correct Usage Of The Permalink And Path Attributes
蜡笔小炘の杂货铺 http://vsinger.jimdo.com
Mon, 01 Feb 2010 13:22:31 +0000
The Best Photographer In Shanghai
When we pick them up :( Don't know when that will be yet!
Chose another 49 today
Wed, 13 Jan 2010 14:13:21 +0000
The Best Photographer In Shanghai
When do we get to see them!!!!!
Tue, 12 Jan 2010 19:08:51 +0000
Installing Jdownloader In Ubuntu
Thank You!!!!
It works like a charm!!!!!!!!!!!!
Tue, 05 Jan 2010 13:02:35 +0000