Friday, June 26, 2009

WPF: Sorting Sets of Simple Strings

I've been doing a fair bit of WPF coding recently, and it's a compelling experience. The thing is, it isn't easy, and I think that surprises some people. Part of the reason for this is that the documentation still feels incomplete, in that undocumented kind of way. But the other reason is that it forces you to think very abstractly, all the time. If I were to think of a decent analogy, it would be one involving cooking: Coding in most UI toolkits is like cooking with lots of pre-made dishes (pre-cooked noodles, microwave dinners, pasta sauces out of the bottle.) Sure, you can make a decent meal, but the results are pretty predictable and maybe not that satisfying. Coding in WPF is like cooking with real ingredients - it can be challenging, and you can certainly mess up the results, but you can also whip up something fantastic.

That said, I thought I might pass along a tip for something that seems like it should be quite easy, but the documentation makes it unclear. I needed to produce two comboboxes for some UI, both of which contain lists of Strings. For one combobox, I needed a custom sort pattern, and for the second one I needed a straight up sort.
I'm finding that there are a bunch of ways to do this. You can create a List<> object that contains the strings, call Sort() on it, then bind it. However, that might not be an adequate solution since you're re-arranging your internal data and you may want to preserve its original order.
The other way of doing this is to apply a SortDescription to the Items list of your combobox or ListView. A SortDescription is pair consisting of a String which describes the property to sort on, and a sort order (ascending or descending.)
Now here's a little tip I just figured out: Most examples explain how to Sort a list of items that are bound to the control, by specifying the property name of the property to sort the content on.
    new SortDescriptions("Content", ListSortDirection.Ascending));
But what if your items don't have a sub-property? You may have guessed the answer, but I am hear to confirm that if you pass an empty string as the first parameter to the SortDescription, then it will apply the SortDirection to the Items themselves:
    new SortDescriptions("", ListSortDirection.Ascending));
And voila! For the second combo where I needed a custom sort, I simply did my sort on the items themselves beforehand then added them in the right order.


Friday, June 5, 2009

E3: Let's Get Physical

Seems like the latest E3 was full of surprises... or maybe not. With Nintendo's raging success in the video game market due to its unconvential Wii, you'd have to expect that both Microsoft and Sony would have to respond. They are now officially playing catch-up, and introduced their takes on the genre at the electronics tradeshow.
Microsoft gave a rather bold live demo of its newly acquired Project Natal, a smart camera that can motion-capture participants using a single camera device. This may sound like a gimmick, but the demos are surprising and effective. Included in the system are both image and voice recognition systems that are used to recognize the current user and interpret commands, respectively. I think the possibilities just for the social and device browsing features are pretty cool - built in voice and video chat, voice-activated, as well as being able to browse to your favourite downloaded media using hand motions. Kind of makes Minority Report seem a little clunky, actually.
Probably the most impressive demonstration of the technology is the Milo video, featuring Lionhead and Peter Molyneux.
Thanks to Trevor, who pointed out that Penny Arcade has the best take on Natal:
And then there was the PS3, that stayed with the conventional, and yet refined Nintendo's motion controller with one that appears to be much, much more sensitive. I think this is actually a pretty smart move on their part, since they are now working with a refinement on a proven technology. It remains to be seen whether they can get these controllers to the 15 million or so install base that the PS3 currently enjoys.
I found the handwritting demo to be the most effective. I mentioned to a collegue that the token Sony Demo Geek could write better in virtual space than I can on paper.
And finally, there was Nintendo. You'd think that the company that revolutionized and galvanized the gaming industry would want to follow that up with something that would keep them one step ahead of the competition. With that in mind, Nintendo unveiled Vitality, which is basically a heartbeat sensor that attaches to your finger. “...Intends to have you see the information relating to the inner world of your body," is the quote from Satoru Iwata, president of Nintendo. At this rate, you can soon expect an electronic rectal thermometer from the esteemed "gaming" company in the coming years. With force feedback.


Thursday, May 21, 2009

I'm a Doctor, Jim, not a Horse Lord of Rohan!

I was reading an interview with JJ Abrams on and had my mind blown. I knew the guy who played Bones in the fantastic new Star Trek film looked familiar, but I hadn't bothered to look him up.

However, this quote from JJ certainly opened my eyes:
"When Karl Urban came in, quite frankly I felt that it would be unlikely that that guy from BOURNE or the hunk from LORD OF THE RINGS was going to be Bones. I knew he was from New Zealand. I just didn’t see the connection, even though I liked his work very much, but I thought “Well, he doesn’t seem right for this, but I’m a fan.” He came in and blew my mind so fast. It was one of those great things where it’s a great lesson to not be so closed minded, but God he was amazing. He just channeled DeForest Kelley, it was eerie."
The "hunk" from LoTR? Bones?
Holy crap. Eomer from The Two Towers is Bones? What a performance by Karl Urban.


Thursday, May 7, 2009


What's the opposite of a Karma Slap? Good things happen to people who tip well. I took a cab today to pick up my car and left the cabby a $4 tip for a $19 ride, for no particular reason. I'd consider that a decent tip. As I was waiting for my car, the cabbie came back and dropped off a small brown bag I'd forgotten in the backseat. The weird thing is I thought I had checked that I had everything because I was also carrying my camera case and a chequebook. The package (which didn't look like much more than a work snack, honestly) actually contained some naturopathy pills, which I had just paid $50 for. So there you go.

The cabbie was obviously a good guy, but I'm guessing he's not turning the car around if I give him a twenty note on the nineteen dollar fare.


Wednesday, May 6, 2009

Dept. of Holy Shit This Is Awesome


Random Tweets

A few tweetbits from my twitter feeds this morning:
An impressive demonstration of the new Wolfram Alpha Computational Knowledge Engine. CNET News reporter Stephen Shankland runs through some sample (and sometimes amusing) searches.
Also, the announcement of the Kindle DX, the long-awaited electronic book solution from Amazon. Its main advantages seem to be the viewing size (large enough that they claim that you won't need to zoom in to any part of a document), its slimness, which would be good for students who want to avoid lugging heavy (computer science) textbooks around with them all day, and its battery life. It can apparently run for days on one charge.
Disadvantages? The price is around 500USD, and... it's in shades of grey. I'm old enough to remember when computers used grey-scale displays. The old Hercules 256-shades-of-grey displays were pretty impressive back when EGA 16 colours was tops (pre-VGA) and the standard was 4-colour CGA for PCs. What was impressive about the Hercules display was the fidelity of the images it produced - like a black-and-white photo, your mind could fill in the missing colours while your eyes bulged at the intricate detail you were seeing on-screen. This would have been in the early 90s, so the display would have been probably twice as crisp as a regular TV at the time.
However, fast-forward 20 years, and I'm not sure how many people are going to want to drop $500 on a device that might be made obsolete by the magical colour Kindle that is likely to come out next year. So I think the device's major disadvantage is the price point vs. the display. If it was $200, then it might be worth it. But at that price, I'll wait for the colour version, thank you very much.
But what's this? Is The Book making a comeback? Don't call it a comeback! Just as the world's forests were heaving a sigh of relief from the downfall of newspapers and books in general, along comes the insta-book ATM, dubbed The Espresso Book Maker. It is billed as the invention that could level the playing field for smaller bookstores that can't afford the space or money to stock the same quantity of books that larger stores can hold. As appealing as that sounds, I have to Call Bullshit on that piece of PR nonsense. If anything, it's another signpost on the long road that leads to Demise, the place where bookstores are heading. Why would I want to lift my fat ass from the couch when I could just as easily order the print online and have it delivered to my door for free? And anyway, leveling the playing field is not a good thing for small stores, because it takes away whatever niche market they had working for them. Want that rare copy of a particular edition of your favourite arcane novel? Why not head over to Chapters and print it up on one of their twenty printers. Beats searching all those old second-hand bookshops for it!


Wednesday, April 29, 2009

Less Briefly, in 3D

I'm astounded that entertainment media has found a valid, artistic reason for presenting movies in 3D. Apparently the movie industry is going to cut costs by attempting to produce movies that don't require barf bags.
Hollywood in general should take note. At one point this industry shifted gears and became hyper-capitalized, like the publicly-owned companies, and producers couldn't judge a film beyond the merits of its opening weekend take. The Watchmen is being painted as a box office bust, but I'd wait for the DVD sales before drawing any conclusions. Though the reviews have been mixed, I'm starting to feel that the movies that receive love-it-or-hate-it reviews are the only ones really worth seeing. If too many people have the same opinion, then it's probably worth a skip.
Blade Runner was a bust in the theatres as well, but it has since been hailed as one of the best movies of all time, and one of the most visionary. Not bad for a film that cost $30 million to make; they'll be re-issuing that one for years to come.


Monday, April 20, 2009

Follow the Moose!

So for all you peeps who have Google accounts - GMail included - you should check out Google Reader. Why? Well for one, it's a pretty neat universal feed aggregator that lets you follow a variety of frequently updated sites. And two, it's an easy way to follow this blog!

For those of you who are a little sick of the suck on the Internet - otherwise known as Facebook ennuie - and are looking to follow publications that provide a little insight, then this can be a very useful tool. And hey, if you think this blog doesn't suck, then feel free to try it out by Following my blog. Just click on the button in the Follow the Moose panel to your left, and this fine publication will be added to your Reader reading list. Go ahead and try it. Do it. DO IT. Or you know, subscribe to the RSS feed. I guess you could do that too.


Wednesday, April 15, 2009

Jing Screen Captures

Just wanted to give a shout-out to a really nifty WPF program called Jing, from the folks at TechSmith. This screencapture tool is extremely streamlined, allows you capture images and videos seamlessly, and you can post them online at the click of a button. The free version uploads them to the TechSmith hosting site,, while the very cheap Pro version lets you upload straight to YouTube. It also supplies an MPEG 4 codec that produces better, smaller video files. And there's a Mac version too!

Other than being a great program, Jing is also a great example of what can be done with WPF. I found out about the program while browsing this very useful WPF resource, Jerry Lin's WPF WTFs, a blog that accumulates WPF knowledge gathered while creating Jing. Check it out!


Tuesday, April 14, 2009

iNIN: You Were Poked with a Nine Inch Nail

More Trent Reznor opinions on the music industry and how it should promote itself, as well as a description of the new Nine Inch Nails iPhone app, another experiment in social networking.
The article also describes the dynamics of the App Store, and how, with its low initial entry cost, it is spurring on development of small-scale applications similar to the ones developed in the late eighties and early nineties. John Carmack has even gotten into the act, porting Wolfenstein 3D, the game that put Id Software on the map, to the iPhone.
In fact, he is using an open-source version of his own source code that was originally modified to use OpenGL, and has re-ported that back on to the iPhone. Apparently the project took him 5 days and will make him a bazillion dollars. Check out his blog item on the subject - Carmack is a good writer and his perspective on the gaming industry, not to mention the software industry in general, is fascinating. Wolfenstein, other than being a brilliant money-maker, is also an experiment in usability design - Carmack wants to figure out how to put the FPS on a multi-touch device, and this is his first crack at it. I wouldn't be surprised if he figures it out by the time he releases DOOM.


Wednesday, April 8, 2009

Trent Reznor Interview is hosting this excellent interview with Trent Reznor, headman of Nine Inch Nails. It's really interesting to see him discuss the business side of music and how he perceives the reality of the music industry these days. He has been ahead of the curve in terms of mainstream bands and how they distribute their music. He no longer has a label, but rather self releases now, and he discusses the success of their latest album The Slip, which emulated the release strategy of In Rainbows (which, for some reason, is no longer available for download) except they were more honest about the release and took a price-point strategy. Basically, the music is free, but if you want the album, DVD, limited edition stuff that fans might be interested in, then they are available at a modest price. This lowers manufacturing costs, since they know exactly how many units to produce.


Wednesday, April 1, 2009

Movies: I Love You, Nick Cage!

I saw a couple of movies that I thought were surprisingly good. Yesterday my girlfriend and I caught Knowing on $5 night at the Paramount. This was actually exactly the kind of movie I like seeing for $5... somewhat plausible and a few holy shit movies that were genuinely surprising. And there's the magic of Nick Cage - you could tell he was on the verge of mailing this one in, and then he got a little hunch that maybe this movie wouldn't suck if he just put in enough effort to make it to the end. There are some pretty awful scenes at the beginning of the movie, but things really pick up at about the 30 minute mark. Again, for $5, it was a great popcorn flick. Plus, this movie will probably make enough movie that it will continue the Nick Cage leading man phenomenon for another five years. (As an extra, I just read that Knowing was directed by Alex Proyas, who did Dark City. And that explains why this movie didn't suck at all.)

And then there's I Love You, Man! This is old-school comedy done right, by a couple of genius actors. The movie is understated, but consistently funny and believable. It's also got the right mix of comic red herrings mixed in with feel-good conventions... it plays with the romantic comedy structure a bit and adapts it for the platonic relationship, but it doesn't stray so far away that the movie isn't entertaining. Honestly, it just feels like they nailed it with this one. Rudd plays a straight-man perfectly, and he does it by not being boring. Apparently Apatow wasn't involved, but he might as well have been, so I'll chalk it up there with 40 Year-Old, Superbad, Forgetting Sarah, and Knocked Up as a another success for the crew.
And finally, I caught The Incredible Hulk on "DVD", as we like to call our internet connection, and I gotta say - WTF? Why was this film necessary? I'm not a comic-book movie hater by any means, but this film was particularly vapid and meaningless, especially since it was effectively a repeat of the surprisingly superior Hulk from five years ago. I mean, Hulk wasn't a great movie, but at least you had a director in Lee who was willing to take some chances and add a little direction to the film. This movie was by the numbers shitty - Liv Tyler reprising her husky Arwen-esque voice is not an upgrade over Jennifer Connelly, nor is Ed Norton an obvious improvement over Eric Bana. People may have had issues with the first movie, but I kind of liked the fact that when Bana as Banner got mad, he looked like he was losing his shit. Norton looked like he was experiencing Nerd Rage, to borrow the term from Fallout 3.
And wasn't this supposed to be the Hulk movie where they fixed the Hulk? If anything, Hulk looked worse in this film - like a Playdough version of Peter Jackson's King Kong. Guys, turn down the reflectivity on the CGI models, please. Crank that spinner down, boy. Environment maps are no longer impressive, and they don't look real. Skin does not reflect, it diffuses. Jesus, I'm getting angry.
And why the heck does every superhero have to fight his evil twin? Iron Man fights Evil Iron Man, Spiderman fights Venom, Hulk fights an abomination, Wolverine is going to fight Sabertooth, Superman fights evil Superman over and over again, and on, and on, ad nauseum, et cetera. At least the first film had Hulk fighting his father who ended up being nothing like him - the fight was incomprehensible (Hulk beat the shit out of a cloud, if you'll remember) but at least Ang Lee was willing to give us something with artistry (even if it failed) instead of the steaming green turd we were handed at the end of the most recent film. I respect the former film, even if I didn't like it much, but the latest movie was just a waste of everyone's time.


Wednesday, March 25, 2009

Podcast Review: Adam Carolla

I'm not a big podcast guy, but I do have a few regulars. I'm a fan of Bill Simmons, the ESPN Sports Guy and probably the most read sports columnist in the US, and I love the CBC Radio: Search Engine podcast, but lately I've found myself regularly tuning in to the digital musings of Adam Carolla.
It seems to me like Hollywood works in posses. I'm not sure if this is a certifiable trend, but the Judd Apatow phenomenon is not unique to Seth Rogan and Co. In fact, this phenomenon might be another instance of viral marketing - or maybe "marketing through networking" is a better term. With Apatow films (and some mimickers, like Zach and Miri Make a Porno,) the same cast of actors each take turns starring and guest starring and making cameos in each other's movies. Even Kevin Smith, with Porno, got an honourary pass into the Apatow guild when he got Rogan and Elizabeth Banks to star in his film. Hollywood loves this because it garantees a certain minimal box office and makes marketing easier for them.
The same could be said for the Jimmy Kimmel crew. Kimmel and Carolla started off in radio, but they eventually hosted The Man Show together. Kimmel has gone on to great success on ABC, while Carolla went back to early-morning talk radio on CBS. Carolla's show was #1 in many parts of the US, but CBS pulled it recently when they shut down their radio operations (or at least the station that was producing Carolla's show - I'm not sure of the details and it's not really that important.) I only caught the last couple of days before the show went off the air, but it was consistently funny and surprisingly touching at the end. Carolla plays the persona of a a-hole with a heart of gold down to a tee. Carolla, Simmons, Kimmel, Sarah Silverman (who dates Kimmel) and others, including Dave Dameshek, have all worked together, hang out together (we hear and read about the Sunday afternoon football games at Kimmel's house from multiple sources) and give each other props by supporting each other's projects.
The day of the announcement, Carolla was on Bill Simmons' podcast (see how that works?), who coincidently worked with Kimmel on his show in the early days before returning to his post as a fulltime columnist at ESPN. Carolla announced that he was fine with the layoff, since CBS will pay him out for 2009, so instead he's going to do a podcast for free and have some fun with that.
Which brings us full circle. Carolla is now pulling in the biggest numbers of any podcast available via iTunes, ever, and he's almost done it by accident. However, this is not really surprising - he's getting plugs from Simmons (who has a several million per column readership) and Kimmel. He's also gotten some very good guests. And finally, since he's doing this all on his own, he's producing a semi-professional show with professional entertainers that has no limits to the conversation - anything goes. No FCC, no sponsors, no nothing. The result is a surprisingly intimate (if you want to call it that) experience. You get the feeling that you're sitting in a room with these guys, just shooting the shit. But the guys are real stars - some of them are the best at what they do.
What's also intriguing is that you're getting that feeling with some recognizable personalities: Kimmel, Simmons, Andy Dick, Seth McFarlane, Tom Arnold, Dave Dameshek, Aisha Tyler... these are pretty big names. And what's more interesting is what they talk about - Andy Dick goes into his substance absuse issues, Tom Arnold discusses his relationship with Roseanne Barr and why he hates Jason Alexander, Seth McFarlane explains the origins of Stewie from the Family Guy (my girlfriend was thrilled to find out that he based him on Henry Higgins from My Fair Lady), and so on and so forth. And throughout, Carolla uses his radio host experience to draw out interesting tidbits from his guests, while chipping in some hilarious stories of his own.
But the best part is the regularity - I think one of the most underrated reasons why podcasting isn't the new radio is consistent scheduling. I'm a creature of habit, and I like the idea that every morning I can wake up, and before I step out the door to head to work I can grab the latest Carolla podcast from iTunes. He's managed to do this on a daily basis during the week - and has a bonafide guest to boot. If you have the discipline to produce content that regularly, you'll beat out everyone who only drop a podcast whenever it's convenient for them.


WPF: Great Resource

I recently had a severe memory leak issue relating some latent WPF animations - a very innocuous animation in a third-party toolkit was causing a complete memory leak of my user control within my application. What's worse is that our workflow called for us to destroy and re-create the control, and as a result the control was leaking several times over.

I found the solution to this problem on Ramon's weblog. I searched quite a long time for this issue and his blog was the only place where I found the information I needed (including MSDN, of course.) So I wanted to give him a shout-out over here. He lists a few interesting and nasty WPF-related memory leaks that are being worked on by Microsoft.
I'll explain the particular issue I was facing in a future post.


Tuesday, March 24, 2009

WPF: Generalizing using generic.xaml

In my previous post, I went on (and on) about a mechanism for loading generic styles and data templates using a Uri load component scheme. This would load your styles and apply them to the control or window that does the loading.

Since then, I've discovered the somewhat magical and better solution to all this, which is to define a file called \Themes\Generic.xaml in your project root. This apparently tells WPF to tap into its uber styling code and plug in your styles defined here.
I had to dig deeper here, because my templated code was working for my main component, but as soon as I added it to the definition of a floating frame outside of the control (which is a third-party component that I don't have control of) it failed to read the template. Adding the Data template definition to \Themes\Generic.xaml did the trick.


Saturday, March 21, 2009

WPF: Loading Generalized DataTemplates in Code

I've been working WPF quite a bit recently and am discovering the ins and outs of this beast. It's nothing if not ambitious.

I personally like it. A lot. I worked with .NET Forms previously and Win32, and Java Swing before that, and this is far and away the most sophisticated UI framework I have ever seen. However, it's still relatively new and documentation (as well as good examples) can be scarce.
One thing that I've noticed when browsing examples online is that most people present ideas through trivial examples - in fact, they repeat the same information through repeated trivial exercises that can be found on other sites. I'll try to avoid doing that, but that also means that I'm going to assume that you know what you're doing. I'm not going to post tutorials or explain basic WPF concepts that are covered in the all the main WPF resources (see another post in the future.) I'm going to post annoying factoids that have halted progress for me personally at work, and hopefully this will help someone out there.
Let's jump in and take a look at generalized DataTemplates in WPF. By generalized, I'm talking about the DataTemplates that set their type via the DataType property. Sampled from MSDN:
  DataType="{x:Type c:GreekGod}">
   <TextBlock Text="{Binding Path=Name}" Foreground="Gold"/>
Like the Style element, DataTemplate uses the DataType property as a way of hooking itself into the general scope of your application. Style's version of this is TargetType.
Now, here's the problem: Where do you specify this DataTemplate? Where does it go in the project? No one seems to make this clear, or provides a satisfactory answer. The real answer is that this DataTemplate needs to exist in a loaded Resources dictionary somewhere up the logical chain of elements where you expect it to be used.
Everyone assumes a trivial layout for a project. "If you need to create a DataTemplate, then just add it to the Window.Resources element, dumbass." However, this is not very helpful, for anyone who is working outside the standard layout conventions (for instance if you're developing WPF controls for a mixed managed application, and blending them into a Win32 frame.) Sometimes, you don't have the benefit of simply adding the template to a higher level component because, wait for it, the XAML might actually be dynamic. Maybe your application reads in XAML to construct a class at runtime. Maybe popping in a DataTemplate definition here is not such a good idea.
So now I'm scratching my head and going back to the root of the problem - how does WPF know about this template in the first place? If I put it in a loose XAML file in my project, and have it compiled, shouldn't the template be properly registered at runtime? Turns out that that isn't the case. Loose XAML does not a loaded component make, which I thought was interesting, and actually makes a lot of sense. This is something that may not be clear from MSDN: Just because you put a DataType property on a DataTemplate in a ResourceDictionary element without a x:Key in a XAML file that is compiled into your project, doesn't mean that it's actually registered with WPF at runtime. It needs to be loaded into the logical chain somewhere.
XAML is cool, but it's still a static definition of components. If you're going to need to sew anything in, you're best bet is to go back to code.
In my case, the answer lay in dynamically loading the XAML and adding it to my root control's MergedDictionaries set (no handy top-level Window, sorry), in the root control's constructor.
To do this, you create a Uri object that points to your project XAML resource (compiled BAML, actually), and use the Application.LoadComponent() static method to load and create the root node of the XAML. If you store your DataTemplate in a ResourceDictionary, the code might look something like this:
public RootControl() {
 Uri uri = new Uri("MyAssembly;component/Templates.xaml", System.UriKind.Relative);
 Resources.MergedDictionaries.Add((ResourceDictionary) Application.LoadComponent(uri);
 // ... continue initialization
Take a look at the MSDN Uri class definition for details as to why this syntax works. The above code is written for an assembly called "MyAssembly.dll", and with a XAML file called Templates.xaml in the root of the project. If you place your loose XAML files in subfolders, add the path after "component" in the Uri. "component" is really just the root of your project.
MergedDictionaries is a handy way of importing and aggregating resources from different definitions into a single Resources object. By loading the XAML into the root component's merged dictionary, you are indirectly registering the DataTemplate into the current logical scope, meaning it will be applied to your instantiated data.
A note concerning Merged Dictionaries and performance. If you have many resources and they are merged into a control that instantiated many times over, be aware that each Merged Dictionary is created once per component - you may want to look into ways of statically organizing your resources. I'll probably be looking at this on my side and will share any advice concerning this in future posts.
Of course, if your root class has a XAML definition, then go ahead and use this simpler notation:
<RootControl x:Class="UserControl"
 xmlns:x="..." >
       <ResourceDictionary Source="Templates.xaml"/>
And that's that. Hopefully this post manages not only to convey how to load templates via code, but also provides a bit of insight into how WPF does things under the hood.


A Note About This Page

I have a reasonably wide variety of interests, among them music, movies, politics, photography, tango, and sports (mostly hockey.) I might use this space to talk about any of those things, but my profession is software design and programming. I was trained as a Software Engineer at Concordia University at the turn of the millennium, and have been working at Autodesk Canada for the past five years in Montreal, Canada. It would be fantastic if people other than programmers read these humble words, but I'm guessing that if anyone stumbles on this page, it'll be a programmer googling some inane or arcane detail concerning WPF or .NET or something (what I currently work with at my job.) Hopefully some of those programmers will have other interests and will stick around for the other things I have to say.

So here goes...


  © Blogger templates The Professional Template by 2008

Back to TOP