Friday, June 29, 2007

Hebrew diacritics and - WPF on XP - טקסט מנוקד ו

Well well well. Do you know how to type עִבְרִית שָׂפָה קָשָׁה? No, really? Don't worry. Press CapsLock, then holding Shift key type T(א) and then, without releasing it 8 (*). What we have how? Hallelujah, we have אָ. You can see almost all options here. Well, now we know to write hebrew diacritics (ניקוד). What's next? Use it in WPF of cause. Well just write small program in XAMLPad to see if it works.

image

Well done. It works. No, you have any problem? Ah, I know, you are using Windows XP. Am I right? Here how it looks like.

image

What's the ... Oh, sorry, I forgot to tell you, that such write method is an anachronism and those are bad characters. We have new shiny font set in Unicode U+FB## range to exchange all this stuff. Just take a look - it works fine (from the left old method, from the right new one)

image

So, that's the difference? See yourself. Try to select following two characters - you'll notice, that you, actually, have three.

אָאָ

So what's the problem? The problem is, that there is no normal input method for those new characters and the worth is that there are no enough characters (combinations) there. Open Character Map application, go the the very end of the page and notice two lines of such characters. Here they are

image

Pretty bad, ah? What the solution?

Before I describe a solution, I want you to understand what's the problem. The problem is, that in XP almost neither of fonts are non-OpenType. WPF in XP do not support left and right character shifting for those fonts in XP. This why you see what you see. The problem is not only related to Hebrew, but also for Chinese, Thai and all other fonts with shifting. WPF just drops support for those fonts in XP. That's definitely bug.

So what the solution? In XP (with Hebrew enabled) we have strange old system font named Lucida Sans Unicode - this is the only system Open Type font, so, if you set FontFamily property explicitly to force rendering and text engine to use this font, Hebrew will displayed properly.

image

Unforchantly, I do not know such fonts neither for Thai, nor for any other language, so if you, my dear readers, will find one (if it is), I'll be happy to update this post with your information.

Happy coding.

Thursday, June 28, 2007

The aphorism of the day...

I'd change the world, but God keeps it's source code.

How process asynchronous calls in Silverlight, by using custom Dispatcher

In current public alpha of Silverlight 1.1 there is no dispatcher. However there are STA and MTA. So, how to process long operations in background threads in MTA and update UI in STA? Well, let's write our own dispatcher. But this is not so simple, but it is possible. Let's start

How, actually works dispatcher? It's pumps system messages by using timer in Single Threaded Apartment. Let's write VeryLongMethod. It will be high precise π (PI) calculation. By passing all math stuff, I just point you to how I run the process

public static class BackgroundPiCalculator  { static Thread worker; public static void RunCalculationAsync(int digits, int delayMs) { P = 2 + (digits + 7) / 8; D = delayMs; worker = new Thread(new ThreadStart(calc)); worker.IsBackground = true; worker.Start(); } 

 





As you can see, I open new thread outside of MTA and run this long calculation. I added a couple of wait methods to be able to see the process. The next step is to create callbacks.




public static event EventHandler DoCalculation; public static event EventHandler<RunCalculationCompletedEventArgs> RunCalculationCompleted; public static event EventHandler<ProgressChangedEventArgs> ProgressChanged; 

 





Well. By now, if we'll subscribe to those events from the right thread (STA), we'll get them in the thread where we subscribed. Right? Let's do it.




 public void Page_Loaded(object o, EventArgs e) { // Required to initialize variables  InitializeComponent(); PICalculator.BackgroundPiCalculator.RunCalculationAsync(10000,100); PICalculator.BackgroundPiCalculator.ProgressChanged += new EventHandler<BackgroundPiCalculator.ProgressChangedEventArgs>(BackgroundPiCalculator_ProgressChanged); PICalculator.BackgroundPiCalculator.RunCalculationCompleted += new EventHandler<BackgroundPiCalculator.RunCalculationCompletedEventArgs>(BackgroundPiCalculator_RunCalculationCompleted); } 



 

void BackgroundPiCalculator_ProgressChanged(object sender, BackgroundPiCalculator.ProgressChangedEventArgs e) { result.Text = e.PreliminaryResult.ToString(); progress.Text = e.ProgressPercentage.ToString() + "%"; }

 








Well, compile and run to get the error "Invalid cross-thread access".



image



Hmmm, it comes from the other thread, but I subscribed to event in my thread, so what's the problem? Ah, the object I'm trying to use was created in other thread. This why I can not access it from my thread. So what to do?



Windows threats such cases by sending block event and moving the object to executing thread. It just pumps messages. Let's do it.



We create two queues - one for result text and the other for progress. Then when the data arrived we'll enqueue the message. Concurrently we'll create timer in STA to pump and dequeue those messages. The only timer can work in UI thread is HtmlTimer. Please notice, that this class is obsolete due to "This is not a high resolution timer and is not suitable for short-interval animations. A new timer type will be available in a future release.". Hey, there a new dispatchers will be available as well in a future release? I believe, that they are. So, let's create a timer, queues and handlers




HtmlTimer t = new HtmlTimer(); t.Interval = 100; t.Tick += new EventHandler(t_Tick); t.Start();




void t_Tick(object sender, EventArgs e) { while (resultMessages.Count > 0) { result.Text = resultMessages.Dequeue(); } while (progressMessages.Count > 0) { progress.Text = progressMessages.Dequeue(); } } 

 






 




Queue<string> resultMessages = new Queue<string>(); Queue<string> progressMessages = new Queue<string>();

 








And enqueue messages upon their arrival.




void BackgroundPiCalculator_ProgressChanged(object sender, BackgroundPiCalculator.ProgressChangedEventArgs e) { resultMessages.Enqueue(e.PreliminaryResult.ToString()); progressMessages.Enqueue(e.ProgressPercentage.ToString() + "%"); } 

 





We done. Now the calculations will be performed asynchronously and we'll get a feedback into our UI.



image



Well done, so what's next? Next, we'll enqueue delegates and invoke them into right thread, but all this in the next post. Have a nice weekend.



Source code for this article.

Wednesday, June 27, 2007

Windows Live Folders

Today started new limited beta service Windows Live Folders as part of Windows Live services. It's media sharing web client with 500MB of space. I expected for such service after Microsoft SharedView, Product Upload and Gallery

 

image

 

 

It nicely integrated with Windows Live Spaces and Windows Live Messenger, so you can share your document and music with your frieds

image

Nice upload interface, powered by Ajax and Flash :( (not Silverlight) bouncing ball

image

So now, you can have your messenger shared folder from every computer and access your document when your hard disk is dead. It knows to send email with folder invitations. Something like this

I was on Windows Live Folders and saw a folder I thought you should check out.

You can look at it here: http://folders.live.com/browse.aspx/Tjns1JLk7sE/Windows%20Share%20Folder/

Windows Live Folders has free online storage so you can get to your stuff anywhere and share it.

This service is subject to the Windows Live terms of use. Please respect the intellectual property rights of others, and do not copy or share unauthorized materials.

But, it has no visible and accessible option just to copy link or send it directly via Messenger.

image

The other interesting feature is to set contributors for your shared folder. Other words, you can get access to your shared folder to your friends.

image

Another yet visible problem is that main navigation bar disappears on some pages. But, "nu shoin", that's beta :)

Dev team has blog with one entry and the very bad news is that by now, this service is limited to some geographic areas and very small number of beta testers, so you are, my Israel friends, can not use it. That is not fare...

 

Thanks to Dan Crevier, that points me to this service.

Monday, June 25, 2007

Cross-domain calls and server side debugging of Silverlight application

Well, in this post, I'll touch two of most major problems with Silverlight development: Cross-Domain remote calls and Server-Side development and debugging. Two of those problem are related, but still happens one without an other. So, let's start with the first one. How to perform denied cross domain class in Silverlight. Probably all of you tried to get Silverlight sample of RSS reader work with external rss feed and got an exception: "Cross domain calls are not supported by BrowserHttpWebRequest." Well, that's security restriction of XmlHttpRequest. But wait, there is special hidden property of XmlHttpRequest, that makes it able to use for cross domain environment (not in IE, indeed). You are right, but, actually, this problem prevented  by Silverlight developers by putting special hidden small test constraint, so if uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped) not equal HtmlPage.DocumentUri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped), Silverlight will not even try to process your request. Bad news, but I heard, they going to enable it somehow. Anyway, not now. And until this type of calls are disabled, we'll you local calls. Let's do it.

 BrowserHttpWebRequest req = new BrowserHttpWebRequest(new Uri(@"http://localhost/MyLocalService/rss.aspx")); IAsyncResult res = req.BeginGetResponse(new AsyncCallback(ParseResponse), req); status.Text = "Acquiring feed information..."; 

 






Bad news - the same error. Why? You are using local calls. This not cross-domains, this is sweet localhost. Well, actually, X:\Documents\Visual Studio Codename Orcas\Projects\CrossDomainTest\CrossDomainTest\TestPage.html, the location of your silverlight project is not actually localhost. More, then this, that's even not http:// uri. What to do?



Here we'll touch the second item, mentioned in the title of this post and move a Silverlight application to work (and, of cause, being debugged) remotely (even with localhost)



For this propose we'll create new Empty Web Project (I do not like all this stuff added by smart templates for Websites, webservices etc., are you?). Now you have two projects - your old Silverlight and new glossy empty website with address like http://localhost:4885/MyGlossyWeb - exactly, what we need. Now we should put our Silverlight project into web one, but we should also be able to debug it without maintaining it twice. Hit right mouse button on your web project. You'll notice, that Visual Studio 2008 (formerly Orcas) beta with Silverlight Tools Alpha has great new menu item named "Link to Silverlight..." - great. Hit it. Put your web project as start one and press F5. Nothing, except error message? That's right, you have not start page for your web project. Silverlight stuff can not be start page, due to fact, that it is not page, so just copy TestPage.html together with Silverlight.js (else silverlight will ne run) into web project. Click TestPage.html and mark it as start page. Wallaby :), you can run your silverlight application from absolute web uri. It also debuggable. To check it put break point in your Silverlight project and run - the application stopped on it.



Now, when we have such cool stuff, that works on localhost, let's make it work cross domain. Add new Web Handler (just add new item and choose web handler type) to your web project. It'll generate new ashx file with two methods. Look into it - it give you all you need for rerouting all requests into external web address. Just a tip in order to make handler know about what you want it to do generate requests from silverlight following way: http://localhost/myhandler.ashx?url=http://externalurl/page.aspx&att1=something&att2=something&method=GET inside web handler translate all necessary information, you already passed into real request and return the external response. If you do not know, what I mean by this sentence, you probably should lean programming a bit :), 'cos web handler makes you able to perform cross domain requests and responses with regular dot net methods.



Are you still need Google Gears? You do not, for real. Danny, you too :)



Shorten steps:




  1. Create Silverlight project


  2. Create Empty Web project


  3. Link Silverlight project to the Web project


  4. Copy TestPage.html and Silverlight.js from Silverlight into Web project


  5. Make Web project to be default project and TestPage.html to be a default page


  6. Create new Web Handler page in Web project


  7. By using System.Net namespace forward all requests by parsing parameters of current request


  8. Return what you got from external domain (don't forget to provide content type


  9. Have a nice day with fluent debugging only one copy of original project and cross-domain calls in Silverlight



We done, folks. Have a nice programming day. A moony and filed by silver light day :)

Saturday, June 16, 2007

That's over, men, that's over

 So, we done. The first stage of MCP exams preparation for WPF 3.5 is over. It was great pleasure to work with this worldwide team of WPF professionals. Next stage is coming soon. So meanwhile I would suggest you to start learning for it, because up to end of this year, the certification will be ready and it will be really hard. Please notice, that "TestKing and Ko" will be unable to help those, who will not work to learn for it :)

Here the team, great thank to you, we were really outstanding crew. (due to MS request all faces and desks are blurred)

 

WPF Cert Exam Team - GrabCut

Sunday, June 10, 2007

Right-To-Left support for Silverlight

Since, in Silverlight (at least not in current version) there is no support for bidirectional text, I was asked to find a way to get over it. My first try was to try to apply TextDirection and Language properties of Run element (well known and used in WPF) in Silverlight. Unfortunately, there are no such properties (even internal) for this, so I start looking for another methods. As well as we have no such property in XAML element, we have no FormattedText object to pass Direction property there. So this "smart" method is also unacceptable. Translations and transformations are not very helpfully as well, so let's look into 90th. Time, when no one knows about BIDI support at all. The well-known method then was character array swapping. You can believe or not, but the same old stuff working well in Silverlight (both in 1.0 and 1.1 versions). How to do it? Really simple.

 

Silverlight 1.1
        char[] text = myText.Text.ToCharArray();
Array.Reverse(text);
myText.Text =
new string(text);

 


 





Silverlight 1.0
        myText.Text = myText.Text.split('').reverse.join('');

 


We done, folks. Have a nice hebrew day.


image

Thursday, June 07, 2007

The first full time WPF training is over

Today, for the first time since Hi-Tech college days about seven years ago, I teaches full day dev session. It was about WPF and covered all information from fundamentals to interop. I can tag this session as "Learn to understand and write WPF in eight ours" (cool name, indeed). Here the list of topics were covered:

  • Fundamentals (30 min)
  • 2D graphics (40 min)
  • Tools (15 min)
  • Styles, Templates and Resources (60 min)
  • Data Binding (60 min)
  • Animation (60 min)
  • Interop (30 min)

It also includes some demos (cannot without it) and 4 hand-on labs. So, pure 8 hours of WPF studying for those who know briefly what WPF is about, but still can not understand what and how to do with it. 

According audience feedback - the session was great, at least, now they know to write WPF well-designed application without putting all stuff should be in XAML to code-behind.

Sunday evening I'm going to teach they designers how to use Blend in 4 hours. So, if I'll count total amount of sessions for near time, I already spoke last 3.5 full days for three clients and going to speak another 1.5 days for two others. My voice is almost over, but I'm happy for all those who attend and now can use WPF for their real development without myself to make them code review and give negative feedbacks about developers' compulsions to write everything in C# (VB/Java) instead of using XAML markup :)

I know, that I have to release next beta versions of Vista Battery Saver, promised for last week. So now, when I have all those sessions done and ready for next a couple of days, I can finally do it. Hallelujah! :)