tag:blogger.com,1999:blog-359280922024-03-19T05:19:57.420-04:00The Macadamian FilesDiscussing the nuts and bolts of software developmentMatt Villeneuvehttp://www.blogger.com/profile/05412817894881938302noreply@blogger.comBlogger58125tag:blogger.com,1999:blog-35928092.post-2924069233968476482012-04-02T15:45:00.000-04:002012-12-21T16:39:56.855-05:00Real-time face detection with Android<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In this post I will show you how to use the still image FaceDetector class from the Android SDK to achieve (mostly) real-time face detection. The following method was used in the creation of the <a href="https://market.android.com/details?id=com.macadamian.mobile.android.monkeycam" target="_blank">MonkeyCam</a> application.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>
<span style="font-family: 'Trebuchet MS', sans-serif;">Since its first release, the Android SDK has made available the <a href="http://developer.android.com/reference/android/media/FaceDetector.html" target="_blank">FaceDetector</a> class, which “identifies the faces of people in a Bitmap graphic object”. By using the FaceDetector on preview frames from the camera, we approximate the real-time face detection. For example in the MonkeyCam application we achieved a rate of slightly over one second per frame which is in the same range as other solutions found around the Internet using more complex solutions like third party computer vision libraries. Short of using the NDK to do GPU programming for the face detection algorithm this was a very usable compromise.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The <a href="http://developer.android.com/reference/android/hardware/Camera.PreviewCallback.html" target="_blank">Camera.PreviewCallback</a> interface provides the onPreviewFrame callback to deliver copies of the preview frames as they are displayed. The default image format is NV21 and I strongly recommend to stick with it as many cameras don’t support other formats and silently accept a different format from setPreviewFormat() only to return blank frames. </span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>
<span style="font-family: 'Trebuchet MS', sans-serif;">Now that we have the preview frame in the NV21 format we need to convert it to a bitmap format so we can pass it to the FaceDetector. Fortunately, since Android 2.2 we can use the <a href="http://developer.android.com/reference/android/graphics/YuvImage.html" target="_blank">YuvImage</a> class to wrap our NV21 frame and then convert it to RGB_565 using its compressToJpeg method and decode the resulting stream into a Bitmap object using BitmapFactory.decodeStream(). For previous versions of the Android SDK you will have to do the conversion manually.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>
<span style="font-family: 'Trebuchet MS', sans-serif;">At this point all that is left to do is passing the newly created Bitmap frame to FaceDetector.findFaces and remember to re-add the callback buffer to the Camera object so onPreviewFrame gets called again. At this point we now have a real-time face detection mechanism, it’s now time to let the creativity flow and add your own touch to make it into something special.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>
<span style="font-family: 'Trebuchet MS', sans-serif;">Edit [2012-12-21]: The source code for MonkeyCam as been released under Apache License 2.0 and can be found on <a href="https://github.com/Macadamian/MonkeyCam" target="_blank">github</a>.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>Anonymousnoreply@blogger.com413tag:blogger.com,1999:blog-35928092.post-74589485541000828782012-04-02T15:07:00.003-04:002012-04-02T15:33:33.161-04:00Disabling the console switching keys for Android<span style="font-family: 'Trebuchet MS', sans-serif;">Some time ago I was doing development on an Android phone and using a BlueTooth keyboard I came across an intriguing behaviour. Hitting the Alt+Left or Alt+Right key combo, the phone would seemingly stop working and give all the symptoms of a frozen device, no more animated wallpaper and unresponsive touchscreen. This stems from a functionality inherited from Linux for the desktop. In this article I will describe the origin of the issue, how to recover from it and how it can be fixed at the kernel level.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<h2>
<span style="font-family: 'Trebuchet MS', sans-serif;">Background information</span></h2>
<span style="font-family: 'Trebuchet MS', sans-serif;">In Linux there exist some special key combinations that are handled at the kernel level. In this article we'll be looking at the console key combinations, specifically:</span><br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Alt+F1 through F12</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Ctrl+Alt+F1 through F12</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Alt+Left</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Alt+Right</span></li>
</ul>
<span style="font-family: 'Trebuchet MS', sans-serif;">* Alt refers to the left Alt key on the keyboard</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Let's start with Alt+F1 through F12; these allow accessing the tty's. On a typical Linux installation Alt+F1 through F6 allows the user to switch between tty1 through tty6 respectively directly and Alt+F7 (F1 in Fedora) is a special tty in which the graphical interface runs. This can change from distro to distro.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><span style="font-family: 'Trebuchet MS', sans-serif;">These Alt commands work from the tty's, but don't from the graphical interface. That's where the Ctrl+Alt+Fn combinations come in, to let you leave the graphical interface. Now the Alt+Left and Alt+Right commands let you cycle through the tty's to the left or to the right. i.e. using Alt+Right from tty3 will lead you to tty4.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<h2>
<span style="font-family: 'Trebuchet MS', sans-serif;">I don't have these keys on my Android phone...</span></h2>
<span style="font-family: 'Trebuchet MS', sans-serif;">That's right! For the most part these key combinations do not come into play on an Android phone as you can't find them on the touchscreen.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">When users start connecting BlueTooth or USB keyboards to interface with their Android mobile, that's when the surprise comes for the unsuspecting user. On my Galaxy S for example, pressing the Alt+Right combo freezes the display. The live wallpaper stops moving; and the touchscreen becomes unresponsive. This can be fixed by any of these three options:</span><br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Press Alt+Left to revert the original combination</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Press Alt+Right once or twice depending on how many tty's there are to cycle through (in my case i need to do it twice to cycle back to the graphical interface tty)</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Press Alt+F7 to go directly to the graphical interface tty</span></li>
</ul>
<span style="font-family: 'Trebuchet MS', sans-serif;">That gets the user back to the graphical interface tty and make it responsive again.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<h2>
<span style="font-family: 'Trebuchet MS', sans-serif;">Modifying the kernel default key map</span></h2>
<span style="font-family: 'Trebuchet MS', sans-serif;">The Default kernel keymap in the Android source is located in </span><span style="font-family: 'Courier New', Courier, monospace;">kernel/drivers/char/defkeymap.map</span><span style="font-family: 'Trebuchet MS', sans-serif;"> as of Gingerbread (2.3). Entries in this file look like the following:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">keycode 59 = F1 F11 Console_13</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> control keycode 59 = F1</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> alt keycode 59 = Console_1</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> control alt keycode 59 = Console_1</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">[...]</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">keycode 105 = Left</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> alt keycode 105 = Decr_Console</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">keycode 106 = Right</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> alt keycode 106 = Incr_Console</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In our case, we want to disable the combinations associated to Console so in the above entries we simply need to comment the lines that declare these.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">keycode 59 = F1 F11 Console_13</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> control keycode 59 = F1</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"># alt keycode 59 = Console_1</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"># control alt keycode 59 = Console_1</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">[...]</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">keycode 105 = Left</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"># alt keycode 105 = Decr_Console</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">keycode 106 = Right</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"># alt keycode 106 = Incr_Console</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">There are more entries not shown here that declare Console related key combinations. </span><span style="font-family: 'Trebuchet MS', sans-serif;">The instructions at the top of the </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.c_shipped</span><span style="font-family: 'Trebuchet MS', sans-serif;"> file read:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">/* Do not edit this file! It was automatically generated by */</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">/* loadkeys --mktable defkeymap.map > defkeymap.c */</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">When I do run this loadkeys command, the generated file does not match the shipped file provided in the Android source as can be seen by difference in the files size. </span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">$ ll defkeymap.c*</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">-rw-rw-r--. 1 jpl jpl 18433 Oct 19 12:46 defkeymap.c</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">-rw-rw-r--. 1 jpl jpl 11007 Oct 12 19:35 defkeymap.c_shipped</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Running diff also shows that the provided shipped file has not been generated from the accompanying </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.map</span><span style="font-family: 'Trebuchet MS', sans-serif;"> file. Simply generating </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.c</span><span style="font-family: 'Trebuchet MS', sans-serif;"> from our modified </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.map</span><span style="font-family: 'Trebuchet MS', sans-serif;"> won't do either as our new </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.c</span><span style="font-family: 'Trebuchet MS', sans-serif;"> is overwritten with a copy of </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.c_shipped</span><span style="font-family: 'Trebuchet MS', sans-serif;"> during the build.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">What do we do now? The way I worked around this is a bit tedious but will make sure that we don't lose changes that were applied to the shipped file and not reflected in the </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.map</span><span style="font-family: 'Trebuchet MS', sans-serif;">.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Workaround: I generated a </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.c</span><span style="font-family: 'Trebuchet MS', sans-serif;"> file from the original </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.map</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and a </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.c</span><span style="font-family: 'Trebuchet MS', sans-serif;"> from the modified </span><span style="font-family: 'Courier New', Courier, monospace;">defkeymap.map</span><span style="font-family: 'Trebuchet MS', sans-serif;"> to remove the Alt+X combinations. Then I generated the diff of the 2 files and manually applied it to the shipped file.</span>Anonymousnoreply@blogger.com152tag:blogger.com,1999:blog-35928092.post-92128188769882217782012-03-29T16:35:00.004-04:002012-03-30T06:35:31.158-04:00Surviving the transition between SVN and Git<h2>
A guide for the commandline-adverse</h2>
<div class="MsoNormal">
As a Microsoft ‘fanboi’ I was at first rather unhappy when
the people promoting Git kept insisting that “the command-line is
where there power is at” and that “GUIs aren’t good enough”.</div>
<div class="MsoNormal">
They were, in part, right; but there’s a lot you CAN do with
the right GUI. I for one am a fan of TortoiseGit (<a href="http://code.google.com/p/tortoisegit/">http://code.google.com/p/tortoisegit/</a>)</div>
<div class="MsoNormal">
In this blog post I’ll outline a few common operations that
you can do using a combination of Git Bash and Tortoise Git, and a few that are
best done in Bash alone (don’t worry, we’ll try to keep the use of Bash to a
minimum; Note however that that it will probably be helpful if you were already familiar with basic git concepts (branch, commit, rebase, etc)</div>
<h3>
<a name='more'></a>Show Log using TortoiseGit</h3>
<div class="MsoNormal">
Let’s say you’ve already cloned a remote repository; I’ll
use TortoiseGit’s repository as an example, checked out from here <a href="http://code.google.com/p/tortoisegit/source/checkout">http://code.google.com/p/tortoisegit/source/checkout</a> </div>
<div class="MsoNormal">
The first neat thing you can do with Tortoise is have it show
you a nice, easy-to-understand commit graph/history: </div>
<div class="MsoNormal">
Right click your repository and select ‘Git Show log’</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-XqfABH28lUw/T3TCES5gsKI/AAAAAAAAABI/_NS2ts_R84w/s1600/TShowLog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-XqfABH28lUw/T3TCES5gsKI/AAAAAAAAABI/_NS2ts_R84w/s1600/TShowLog.png" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
Make sure you’ve got “All Branches” checked, so you’re not
missing any unrelated branches from your overview.</div>
<div class="MsoNormal">
Now for a short map legend:</div>
<div class="MsoNormal">
- The commit in <b>bold</b> is the commit you currently have
checked out. This is the commit you can currently view/compile/modify; any
commit you make at this point will be based on the commit shown in <b>bold</b></div>
<div class="MsoNormal">
- Tags with an orange-ish background, such as <span style="background: none repeat scroll 0% 0% rgb(255, 204, 0);">origin/master</span> are remote branches: branches
that exist(ed) on the repository the last time you did a clone/pull</div>
<div class="MsoNormal">
- There can be at most one tag with a red background, such
as <span style="background: none repeat scroll 0% 0% red;">master</span>: this is the
branch you currently have checked out (earlier I’ve mentioned that you can
check out a commit: checking out a branch is essentially the same as checking
out its corresponding commit, as far as your working dir is concerned; i.e.
you’ll get the same code changes)</div>
<div class="MsoNormal">
- Tags with a green background (not shown in the above pic,
since we haven’t created any yet) are local branches. While working with git,
branches will be your bread and butter, you’ll be creating a lot of them</div>
<div class="MsoNormal">
<br /></div>
<h3>
Commit using TortoiseGit</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-5T78WT8S5bw/T3TCQojRCpI/AAAAAAAAABQ/Uv9wMpi2BkA/s1600/TortoiseOpenCommit.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-5T78WT8S5bw/T3TCQojRCpI/AAAAAAAAABQ/Uv9wMpi2BkA/s1600/TortoiseOpenCommit.png" /></a></div>
<div class="MsoNormal">
To get to the commit
screen, just right click on your repository clone, and select Git Commit (note
that it will display what branch you’re about do do a commit on, in this case: “<i>master”</i>)</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-1-A78tjgWiA/T3TC0-bhmWI/AAAAAAAAABY/UJGeuO5lf00/s1600/TortoiseCommitOpened.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-1-A78tjgWiA/T3TC0-bhmWI/AAAAAAAAABY/UJGeuO5lf00/s1600/TortoiseCommitOpened.png" /></a></div>
<div class="MsoNormal">
The main difference
between command line Git and TortoiseGit is that Tortoise abstracts away the concept
of “staging”; basically whatever files have a checked checkbox get staged and
committed once you hit OK</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Now, let’s look at that graph again and see what happened</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-j7xSdofOH1c/T3TDEZOQSwI/AAAAAAAAABg/5CSmQvSEimo/s1600/TLogAfter1stCommit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-j7xSdofOH1c/T3TDEZOQSwI/AAAAAAAAABg/5CSmQvSEimo/s1600/TLogAfter1stCommit.png" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
As you can see, my commit got added on top of the
previously-bold (checked-out) commit. </div>
<div class="MsoNormal">
Also, since I committed my changes against the <i>“master”</i>
branch, it also moved up to my new commit.</div>
<div class="MsoNormal">
Now, fortunately this being Git, my changes will not be
visible by anyone but myself; no need to worry about Sven being angry at me for
messing with those txt files.</div>
<h3>
Create Branch using TortoiseGit</h3>
<div class="MsoNormal">
But wait! I “accidentally” did something wrong! I wanted to
keep <i>master</i> and <i>origin/master</i> in-sync, and make my commit on a
new branch (that's because we want to use Gerrit, otherwise it would probably have been ok to commit against the master branch). </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
So let’s see how to fix this</div>
<div class="MsoNormal">
What we want to do is:</div>
<div class="MsoNormal" style="margin-left: .5in; mso-list: l0 level1 lfo1; tab-stops: list .5in; text-indent: -.25in;">
1)<span style="font: 7pt "Times New Roman";">
</span><span dir="LTR">Create a new branch on my new
commit</span></div>
<div class="MsoNormal" style="margin-left: .5in; mso-list: l0 level1 lfo1; tab-stops: list .5in; text-indent: -.25in;">
2)<span style="font: 7pt "Times New Roman";">
</span><span dir="LTR">Restore <i>master</i> to its
original state</span></div>
<div class="MsoNormal">
And we will want to do it in that order, since if we were to
move <i>master</i> ‘down’ one commit on the graph, my new commit would be left
without a branch <b>on or ‘above’ it</b> and Git would delete it, i.e. <b>Git
'deletes' all commits that don’t ‘lead up to’ a branch</b><span style="font-size: x-small;"> (actually, commits lost in this way aren't lost forever, it's just a bit complicated to restore them)</span>. </div>
<div class="MsoNormal">
<br />
Creating a new branch: Right click
on your repository, select Create Branch, give the new branch a name you’ll
remember and hit OK.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-HAe7TgxmkCw/T3TENcnBs0I/AAAAAAAAABo/okuIK8gUXqc/s1600/CreateBranch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-HAe7TgxmkCw/T3TENcnBs0I/AAAAAAAAABo/okuIK8gUXqc/s1600/CreateBranch.png" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Let’s check that Log
again:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-8rLlRvgmtqQ/T3TEZkt4a7I/AAAAAAAAABw/LTM27vBZk1g/s1600/TLogAfterCreateBranch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-8rLlRvgmtqQ/T3TEZkt4a7I/AAAAAAAAABw/LTM27vBZk1g/s1600/TLogAfterCreateBranch.png" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Now that we’ve got a branch to hold our new commit, let’s
take the <i>master</i> branch back down to be in-sync with <i>origin/master.</i>
</div>
<div class="MsoNormal">
<br /></div>
<h3>
Interactive rebase using Git Bash/Extensions</h3>
(AKA: one of your two best friends after doing something silly)<br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
This is the part where we’ll have to use Git Bash, I have
yet to find a way to do an equivalent operation using Tortoise. (I know, the
white-on-black Bash window tends to repel Windows users, just roll a save vs.
Willpower to avoid cringing).</div>
<div class="MsoNormal">
Hint: Git Extensions (<a href="http://code.google.com/p/gitextensions/">http://code.google.com/p/gitextensions/</a>
) will provide a more Windows-friendly editor for interactive rebasing</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Open a git bash window on at your repository, and type in:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><i>git rebase -i HEAD~2</i></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
And hit enter. </div>
<div class="MsoNormal">
Now, it could have been
HEAD~10 or any other number, depending on how many commits you want to be able
to pluck out of your branch.</div>
<div class="MsoNormal">
This is what pops up if you have Git Extensions installed:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-aoWHtLXWsMA/T3TFchNbLRI/AAAAAAAAAB4/8DUJAr_m3Ro/s1600/InteractiveRebase.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Git's interactive rebase (rebase -i) is a very versatile tool, and if you haven't already, I recommend reading more about all the neat things it can do " border="0" src="http://1.bp.blogspot.com/-aoWHtLXWsMA/T3TFchNbLRI/AAAAAAAAAB4/8DUJAr_m3Ro/s1600/InteractiveRebase.png" title="" /></a></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
Do what the nice red font says and you should end up with
the following graph:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-0WRPAP9iMek/T3TGHq6DCcI/AAAAAAAAACA/ItlFmZkli5k/s1600/TLogAfterRebase.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-0WRPAP9iMek/T3TGHq6DCcI/AAAAAAAAACA/ItlFmZkli5k/s1600/TLogAfterRebase.png" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<i>Master</i> is in-synch with <i>origin/master</i> and our
commit is sitting on top of it on our new branch called <i>txtFileChanges</i></div>
<div class="MsoNormal">
<br /></div>
<h3>
Amending a commit in Tortoise</h3>
<div class="MsoNormal">
(the other one of your two best friends after doing
something silly)</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Let’s say I wanted to change a commit: perhaps I wrote an
incorrect commit message, or I left a few files out. Here’s what we need to do:</div>
<br />
<div class="MsoNormal">
1) <span dir="LTR">Checkout (Switch to) the commit we
want to change</span></div>
<div class="MsoNormal">
Checking out a branch is straight-forward: right click on it
in the Log view and choose Switch/Checkout to “<name>”</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
2) <span dir="LTR">Amend the Commit</span></div>
<div class="MsoNormal">
We’re now ready to do amend a commit. Right click the
repository folder, select Commit -> “<i>txtFileChanges</i>”; In the commit
window, check the “Ammend Last Commit” box.</div>
<div class="MsoNormal">
You can now edit your commit message, add new files to be
commited, or remove committed file changes (note: you will lose those changes
permanently)</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
And that’s it for the first part of this guide. The second
part will (hopefully) follow soon and contain instructions on how to use Gerrit</div>Anonymousnoreply@blogger.com253tag:blogger.com,1999:blog-35928092.post-29973916054781948022011-02-25T00:37:00.001-05:002011-02-25T13:38:25.948-05:00Windows Phone 7 Isolated Storage Explorer & Open Source Project<h1 id="internal-source-marker_0.10405877396968544"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 24pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline;"></span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 14pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline;">Simplifying WP7 local data storage development and testing</span></h1><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline;">Written by: Anthony Hooper and Romeo Dumitrescu</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">One of the biggest challenges for developing any advanced Windows Phone 7 applications is </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline;">not</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> using or manipulating the isolated storage, but rather having to continuously set up test and development data over and over again as new features are added or bugs are found and fixed. Although the WP7 development tools Microsoft has provided are arguably the best of class, there currently is no easy way to explore, load, or export local data in a WP7 device or emulator that is developer friendly. Until now.</span><br />
<br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Enter the WP7 Isolated Storage Explorer. Both a stand alone tool (that connects either to an emulator or a tethered device) or a Visual Studio 2010 plug-in that enables developers and QA specialist or testers to explore, save, and even upload data to the isolated storage.</span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Lets first explore why the isolated storage is important for WP7 applications. Relying heavily on loading and storing data from the cloud (web services) results in slow loading and sluggish response time of the application. It’s a best practice to cache some data locally and in many situations much of the data in a mobile application can be stored locally, something many application do not do.</span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">So how does the WP7 isolated storage explorer enter into the development cycle? Simply put, it facilitates iterative development and testability of your WP7 applications by facilitating saving, loading and exploring any isolated storage files associated with your WP7 applications. It will speed up debugging edge cases by enabling developers to load isolated storage cache files to the emulator or device, it will empower QA/Test specialists by enabling them the power to explore local data files to help identify critical bugs. Furthermore, it will speed up testing and feature development by enabling testers and developers the ability to preload their devices/emulators with dev and test data to short cut recreating use cases.</span><br />
<br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">How do you get started?</span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<ul><li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><a href="http://wp7explorercontrib2.codeplex.com/releases/view/61228"><span style="background-color: transparent; color: #000099; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline;">Download and install </span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">the WP7 isolated storage explorer using the release setup file. The installer will install:</span></li>
<ul><li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">A service used to communicate with the WP7 deployed applications</span></li>
<li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">A desktop client ideal for testers or non developers</span></li>
<li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">The Visual Studio integrated client. </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline;">Note: Visual Studio 2010 must be installed first</span></li>
<li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">The explorer library</span></li>
</ul><li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Open your WP7 project and add a reference to “IsolatedStorageExplorer” (visible on the .NET tab in Add Reference dialog or by browsing to INSTALLDIR\Library)</span></li>
<li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Add <span style="font-family: "Courier New",Courier,monospace;">IsolatedStorageExplorer.Explorer.Start("</span><hostname><span style="font-family: "Courier New",Courier,monospace;">");</span> (where </hostname></span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline;">hostname </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">is the host name or IP of the testing or development machine) in the Launching event handler. An example is show bellow:</span></li>
</ul><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">// Code to execute when the application is launching (eg, from Start)</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> // This code will not execute when the application is reactivated</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> private void Application_Launching(object sender, LaunchingEventArgs e)</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> {</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> IsolatedStorageExplorer.Explorer.Start("</span><span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline;">localhost</span><span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">");</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> }</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> // Code to execute when the application is activated (brought to foreground)</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> // This code will not execute when the application is first launched</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> private void Application_Activated(object sender, ActivatedEventArgs e)</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> {</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">// This will restore the state of the explorer and the hostname after</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">// reactivating the application</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Explorer.RestoreFromTombstone();</span><br />
<span style="background-color: transparent; color: black; font-family: Courier New; font-size: 9pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> }</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<ul><li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Start exploring your application’s Isolated Storage!</span></li>
</ul><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">The connected application will show up in the application drop down list in the WP7 Isolated Storage Explorer desktop client. To see the Visual Studio integrated client: In Visual Studio 2010, click on the <i>View </i>> <i>Other Windows</i>, select <i>WP7 Isolated Storage Explorer</i>.</span><br />
<br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Finally, why did we start this project? It started as one of our developer's aggravations with the MS provided SDKs. Not that they weren't fantastic (they were very complete) but local storage was difficult to work with. Furthermore, Macadamian believes in efficient, predicable testability of all applications we build. We felt that this was missing from the SDKs provided by Microsoft and hope that this project/tool can help the WP7 developer community. There is nothing like a little healthy competition on the mobile marketplace! </span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span>Tonyhttp://www.blogger.com/profile/17596211212687907094noreply@blogger.com213tag:blogger.com,1999:blog-35928092.post-5888572113673321512011-02-09T18:24:00.008-05:002011-02-09T19:15:47.508-05:00Nokia and Microsoft to Join Forces? by Martin Larochelle<p>Last week I attended a <a href="http://www.wavefrontac.com/news-events/waveguide-training/WaveGuide_Feb2_2011/seminar-2011-02-02">presentation by Nokia</a> about how to do business with them. I was planning to write a blog about how to develop for their phones and how to publish applications to the Ovi Store.</p><br /><p>I concluded that if one has many C++ developers, the Nokia phone is quite accessible. Most of their presentation was focused around how Qt can now be used to develop for all of their platforms (Symbian, Maemo, MeeGo). This is great for us, because we did a couple of projects with Qt in the past six months. They followed with a walk-through of publishing apps to the Ovi Store. Bottom line, the review process takes 7 to 9 business days and it is rejecting slightly over 30% of the submissions on the fist pass.</p><br /><p>Today, a <a href="http://www.engadget.com/2011/02/08/nokia-ceo-stephen-elop-rallies-troops-in-brutally-honest-burnin/">Nokia internal memo</a> was leaked,the contents of which indicated that things could all change on Friday. The memo revealed that the N9 should be the first Nokia device to ship with MeeGo. "at this rate, by the end of 2011, we might have only one MeeGo product in the market". In their presentation, Nokia had hinted that their CEO would make an announcement at MWC, which most of us assumed to be their anticipated MeeGo Tablet. But given the contents of the memo and the fact that the CEO only expects one MeeGo device to ship this year, it now seems unlikely. </p><br /><p>The memo will fuel the rumour that Nokia would move to WP7 for its phone platform. In insight, we learned how the Nokia Ovi Store could be a great asset to get WP7 off the ground.</p><br /><p>Possibly the biggest asset that Nokia has is the global reach of its platform. Nokia covers 170+ counties with credit card payment and 99 countries with carrier billing. Their store is translated into 30 languages and their application approval process includes a moderation process that takes into account the regional and culture differences of each country published to.</p><br /><p>The most surprising statistic which they've released is that carrier billing has increased app sales by up to 13x in some markets. In comparison, Android has carrier billing in two countries and the other competitors have none. These agreements take time to negotiate, and most carriers want to take 50% of the app price. If Nokia brings that to another ecosystem, it would increase the app sales drastically.</p><br /><p> Instead of WP7 it would be easier for Nokia to go with Android and have their own application market for their phones. But will developers really want to submit their apps on all these application market clones? WP7 seems like the most accessible choice.</p><br /><p>On the other hand, WP7 is struggling. It did not even surpass Windows Mobile in <a href="http://www.computerworld.com/s/article/9207361/Android_tops_smartphones_WP7_trails_others_in_various_Q4_reports">Q4</a>. Although Microsoft shipped 2 million phones, it took almost two months for our biggest WP7 fan to find the one he wanted. What if Nokia moved to WP7 and started distributing massive amounts of WP7 world-wide? It would be a huge gain for Microsoft, having the potential to give them 30% of the World’s smartphone market shares. These potential gains could justify an exclusive deal with Nokia.</p><br /><p>According to their memo, Nokia is "standing on a burning platform", which they plan to evacuate on Friday. Will they save the value they have, partner up with Microsoft, and create an ecosystem that can compete with iPhone and Android?</p>Unknownnoreply@blogger.com110tag:blogger.com,1999:blog-35928092.post-19777239770861564242011-02-01T13:58:00.006-05:002011-02-01T19:27:59.377-05:00Pass Me the Data, by Rob WoodsYou've written the Hello Android app, then created your own simple app. Now you've created a much more complicated app with several <a href="http://developer.android.com/reference/android/app/Activity.html">activities</a>. You may need to be able to pass data between your activities. In this post, I will take you from the basics of passing simple data types between activities, right up to making your own custom objects parcelable so they can also be passed along with the same ease as a simple data type. <br />If you feel that you need a bit more background on this subject matter before reading further, <a href="http://developer.android.com/guide/topics/fundamentals.html">here</a> is a helpful article on Android application development. <br /><br />Before we start passing data around, first you will need to understand how an <a href="http://developer.android.com/reference/android/content/Intent.html">activity</a> is launched. To launch a new activity, you would create an Intent and pass it to the Activity method <a href="http://developer.android.com/reference/android/app/Activity.html#startActivity%28android.content.Intent%29">startActivity()</a>. <br /><br />Illustration:<br />"Intent newIntent = new Intent(Context, Class);<br />startActivity(newIntent);"<br /><br />Now lets say you have a listactivity, and whenever a user taps on an entry in the list, you want to launch a new activity that does something with the data from that list entry. The most basic scenario for passing data is to attach an extra to the intent in the form of <br /><br />"newIntent.putExtra(name,value);" <br /><br />Where name is a String that is used to "tag" your data and value is the actual data object you are passing to the intended activity. Value can be many different types, including String, int, Boolean, etc. You can see the complete list of putextra methods <a href="http://developer.android.com/reference/android/content/Intent.html#pubmethods">here</a>. <br /><br />Here's an example from the callingaActivity.<br />"Intent newIntent = new Intent(this, SomeActivity.class);<br />newIntent.putExtra("MAGIC_NUMBER", 42);<br />startActivity(newIntent);"<br /><br />Now on the called activity side (receiving the Intent), in your activities onCreate() method, you will need to retrieve the extra data from the intent. You can do this by calling getIntent() to get the intent that started the activity, then <a href="http://developer.android.com/reference/android/content/Intent.html#getIntExtra%28java.lang.String,%20int%29">getIntExtra(name, default)</a>. This is if you passed an int value, if you passed a different type, you would use the corresponding method for that type. <br /><br />For example:<br />"int magic_number = getIntent().getIntExtra("MAGIC_NUMBER", 420);"<br /><br />Note that the default value is used if the tag "MAGIC_NUMBER" had no value assigned to it. This is great if you are just passing one piece of data using a basic data type, but if you are passing more data than just a single type, you might want to consider using <a href="http://developer.android.com/reference/android/os/Bundle.html">Bundle</a>. <br /><br />Basically, a Bundle is just a mapping of tag-data pairs grouped together into one passable object. Let's say that you had a contact list and when the user taps a contact, you want to pass the name, id and phone number to the called Activity. You could do so like this:<br /><br />"Intent newIntent = Intent(this, ContactDetails.class);<br />Bundle extras = new Bundle();<br />extras.putString("CONTACT_NAME", name);<br />extras.putInt("CONTACT_ID", id);<br />extras.putString("CONTACT_NUMBER", number);<br />newIntent.putExtras(extras);<br />startActivity(newIntent);:<br /><br />And on the receiving Activity:<br /><br />"Bundle extras = getIntent().getExtras();<br />String name = extras.getString("CONTACT_NAME");<br />int id = extras.getInt("CONTACT_ID");<br />String number = extras.getString("CONTACT_NUMBER");"<br /><br />Now lets say you've created your own data class with several different types of data representing the class:<br /><br />"public class Dog extends Object {<br /> private String mType;<br /> private String mName;<br /> private int mId;<br /> <br /> public Dog(String type, String name, int id) {<br /> mType = type;<br /> mName = name;<br /> mId = id;<br /> } "<br /><br />You could pass each piece of data separately by adding 4 tag-data pairs to a Bundle and passing the Bundle. However, a smarter way of doing this is to implement the <a href="http://developer.android.com/reference/android/os/Parcelable.html">parcelable</a> interface in your Dog class. The parcelable interface has 2 methods which are needed to implement, <a href="http://developer.android.com/reference/android/os/Parcelable.html#describeContents%28%29">describeContents()</a> and <a href="http://developer.android.com/reference/android/os/Parcelable.html#writeToParcel%28android.os.Parcel,%20int%29">writeToParcel(Parcel, int)</a>.<br /><br /> "@Override<br /> public void writeToParcel(Parcel dest, int flags) {<br /> dest.writeString(mType);<br /> dest.writeString(mName);<br /> dest.writeInt(id);<br /> }"<br /><br />Using this method, you must add each of your data types to the Parcel with the correct write method for its data type.<br /><br />If your class has child classes, you can use the describeContents() method to differentiate between child classes so that when you unparcel your parceled object, you can create the correct child object.<br /><br />This is only half of the solution. Now that you have the facilities to write your object to a parcel, you also need to be able to rebuild your object in the called activity. First you will need a new constructor for your class. One that takes a parcel object and can populate it's data members from it;<br /><br /> 'public Dog(Parcel dest) {<br /> mType = dest.readString();<br /> mName = dest.readString();<br /> mId = dest.readInt();<br /> }'<br /><br />Note the order. <br />You must read your data types from your parcel in the same order you wrote them. Essentially you're flattening your data into one data stream, then reading it back on the other side.<br /><br />Finally, you will need to create a parcelable creator in your class that will trigger your new parcelable constructor when needed:<br /><br /> "public static final Parcelable.Creator<LocalContact> CREATOR = new Parcelable.Creator<LocalContact>() {<br /> @Override<br /> public LocalContact createFromParcel(Parcel source) {<br /> return new LocalContact(source);<br /> }<br /><br /> @Override<br /> public LocalContact[] newArray(int size) {<br /> return new LocalContact[size];<br /> }<br /> };"<br /><br />One last thing I'll leave you with is the concept of chaining your parcelable objects. Lets say your Dog class has a custom object as one of its data members. You need to make sure that class also implements the parcelable interface. In order to support parcelizing your custom object inside your Dog class, you will need to change 2 methods. <br />First, Dog's writeToParcel(Parcel, int) method needs to tell your custom object to write itself to the parcel. <br />To do this, we can call writeParcelable(Object, int). This method will invoke your custom classes writeToParcel method:<br /><br /> "@Override<br /> public void writeToParcel(Parcel dest, int flags) {<br /> dest.writeString(mType);<br /> dest.writeString(mName);<br /> dest.writeInt(id);<br /> dest.writeParcelable(dogTag, flags);<br /> }"<br /><br />Here dogTag would be your custom class that could implement say, a phone number and address for where the dog lives. Second Dog's parcel constructor. Here we will call readParcelable(Classloader) to get the custom objects parceled data:<br /><br /> "public Dog(Parcel dest) {<br /> mType = dest.readString();<br /> mName = dest.readString();<br /> mId = dest.readInt();<br /> dogTag = dest.readParcelable(DogTag.class.getClassLoader());<br /> }"<br /><br />This should get you passing your data around to your activities!Unknownnoreply@blogger.com141tag:blogger.com,1999:blog-35928092.post-46504976910363530382010-08-05T18:04:00.007-04:002010-08-05T18:16:51.671-04:00Three Ways to Run Multiple Versions of Internet Explorer and Firefox<p>Recently I worked on a project that had to support six different browsers; three versions of Firefox (1 through 3) and three versions of Internet Explorer (6, 7, 8). Right away this raised a few questions, and one of the more interesting ones was about testing:</p><p>What is the optimal environment for testing two browsers at three versions each?</p><p>This is an interesting issue because browsers are not designed to allow more than one version to be installed at once. This makes sense for users — it would be confusing and insecure for them to use an older version by accident — but it's traditionally a big hassle for web developers. It's important for us to be able to test our changes on multiple browsers because different versions of the same browser may not render the same code the same way, and it's important to catch and fix these bugs.</p><p>To answer this question, our team of myself (a developer) and two quality assurance experts did some brainstorming and each of us actually came up with our own solution. Here are the three options we considered:</p><h2>Multiple VMs</h2><p>This was our senior QA's suggestion. Set up three virtual machines, and on each machine, install a different version of Internet Explorer and Firefox.</p><p>Advantages:</p><ul><li>Tried, tested and true. This is a standard QA practice and has been in use for years.</li><li>Can run all six browsers simultaneously (good if we want to test in parallel)</li></ul><p>Disadvantages:</p><ul><li>There is some overhead involved in setting up and keeping track of three VMs.</li><li>Three VMs will need to run on their own machine, so an extra box or some server space is needed.</li></ul><h2>VM Snapshots</h2><p>This was our other QA's suggestion, which I thought was quite novel. The process goes like this: create a virtual machine and install IE6 and FF1, then take a snapshot (something the VM can revert to upon request). Now, upgrade the browsers to IE7/FF2 and take another snapshot, and perform the final upgrade to IE8/FF3 and take a third snapshot. By toggling between the three snapshots, all six browsers can be tested using only one VM.</p><p>Advantages:</p><ul><li>Only one VM is required, so there is less overhead.</li><li>Since there is only one VM, it's possible to run the VM on a developer or QA's machine in a pinch.</li></ul><p>Disadvantages:</p><ul><li>Can only test one version of each browser at a time.</li><li>There is probably still a need for some shared machine space to host the VM.</li></ul><h2>Hack it Together</h2><p>Predictably, this was the developer's solution (mine). I've used a slightly-unstable beta product called <a href="http://www.my-debugbar.com/wiki/IETester/HomePage">IETester</a> in the past, which allows testing multiple versions of Internet Explorer simultaneously. This meant all I needed was a solution for Firefox, and after some searching I found an outline of <a href="http://www.htmlcenter.com/blog/multiple-firefox-installs/">how to install multiple versions of FF</a>.</p><p>Advantages:</p><ul><li>No virtual machine overhead.</li><li>Everything can be run as needed on the developer's machine.</li></ul><p>Disadvantages:</p><ul><li>Highly technical: Setting up and maintaining this environment is not for the faint of heart.</li><li>Can only run one version of FF at a time (though IE can be done in parallel).</li></ul><p>Given these options, we decided that the best match for our project's needs was to use VM Snapshots on the quality assurance side, and the hacked-together solution on the development side. The low overhead was a big plus, especially for development, and it was important that QA was able to reliably test real versions of each browser. This worked out well for us, and I would definitely use such methods again.</p><p>Have you used these or similar solutions in the past? Are there other solutions out there that we don't know about? Let us know in the comments.</p>Unknownnoreply@blogger.com137tag:blogger.com,1999:blog-35928092.post-82558938859550568362010-03-02T06:50:00.010-05:002010-03-02T07:12:26.648-05:00RIATest: Automating Custom Components<a href="http://www.riatest.com/">RIATest</a> is a GUI test automation tool for <a href="http://www.adobe.com/products/flex/">Adobe Flex</a> applications. RIATest does for your GUI what FlexUnit does for your code, and it is available on Windows and Mac OS X. RIATest has number of useful features which can be very helpful, such as component inspector, script debugger, and synchronization capabilities. You can find the full list of features <a href="http://www.riatest.com/products/features.html">here</a>.<br />
<br />
When you specify actions that must be performed on your application the first thing you specify is what component you want to be located by RIATest so that an action can be performed on it. RIATest has few ways of locating components. One of the ways is locating component by label e.g. button with "Save" label can be located following way:<br />
<br />
<pre class="code">FlexButton("Save")</pre><br />
Component can be located in a same manner using components automatationName. You can also locate component using its automationIndex:<br />
<br />
<pre class="code">FlexButton("index:0")</pre><br />
<blockquote>In most of the cases you are getting every component which you need in the inspector, so you can easily locate those components. In case you derive a custom class from built-in container-type classes you usually do not need to do anything special to make children of your custom component available for automation since this is done by the automation delegate of base class.<br />
<br />
However sometimes you implement a custom component that contains other components but your custom component is not derived from Container built-in class. If that is the case you need to expose components contained in your custom class. You will need to perform some additional steps to access them.</blockquote><br />
Let's discuss one exact example. Here we have a CustomPanel with a button added in its title bar. You will notice that the button which you just added is not visible in the inspector:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7YvP7njXTEIX8-ZOMxtznehnpP56LqjzPT9LBVPj5VWmJMQAV522teyuxd4AyJOSGuO19CjYbZHwP-6Hx236SxLU4kyORSK-CJsGYrWvTXQqwK2CuqKlANIQYRybdHJIIhVu6OQ/s1600-h/noSwitch.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7YvP7njXTEIX8-ZOMxtznehnpP56LqjzPT9LBVPj5VWmJMQAV522teyuxd4AyJOSGuO19CjYbZHwP-6Hx236SxLU4kyORSK-CJsGYrWvTXQqwK2CuqKlANIQYRybdHJIIhVu6OQ/s320/noSwitch.PNG" width="320" /></a></div><br />
So what we can do? We need to implement automation delegate class for our custom component. Exposing child components is done by implementing numAutomationChildren/getAutomationChildAt pair of functions. numAutomationChildren function must return the number of children component for your custom class, getAutomationChildAt must return the child at the specified index. This means we need to implement automatation delegate class for our custom component to make Switch button accessible from RIATest.<br />
<br />
<b>numAutomationChildren</b><br />
<br />
In our case we will need to return the number of children which are implementing IAutomationObject plus Switch button:<br />
<pre class="code">override public function get numAutomationChildren() : int {
var count:int = 0;
for(var i:int=0; i < comp.numChildren; i++) {
if (comp.getChildAt(i) is IAutomationObject)
count++;
}
return ++count;
}</pre><br />
<b>getAutomationChildAt</b><br />
<br />
getAutomationChildAt will need to return the child with a given index in case of index < numChildren and return Switch button in case of index == numChildren<br />
<pre class="code">override public function getAutomationChildAt( index : int ) : IAutomationObject {
if (index >= 0 && index < comp.numChildren )
return comp.getChildAt(index) as IAutomationObject;
if(index == comp.numChildren)
return comp.button;
return null;
}</pre><br />
We will also need to implement init method in order to register our delegate class:<br />
<pre class="code">public static function init( root : DisplayObject ) : void {
Automation.registerDelegateClass( CustomPanel, CustomPanelAutomationImpl);
}</pre><br />
The only thing left to do is to include our delegate into build, include your delegate class using additional compiler arguments:<br />
<br />
<pre class="code">-includes CustomPanelAutomationImpl</pre><br />
As you can see from the screenshot now Switch button is getting displayed in the inspector, so you can easily locate it:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSwH9kw_S4MGxCO-cnHs87EUbVh4lZeekkUtWlE_R238heFfW6ZNF_9MvtzaYlVSg2jcltmqmAl5Y-dt_2jo5Y4WZ5qKPVzOXlK7KkYHzFi2VK5c9-6truVR1e45isz82BiD2Bag/s1600-h/Switch.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSwH9kw_S4MGxCO-cnHs87EUbVh4lZeekkUtWlE_R238heFfW6ZNF_9MvtzaYlVSg2jcltmqmAl5Y-dt_2jo5Y4WZ5qKPVzOXlK7KkYHzFi2VK5c9-6truVR1e45isz82BiD2Bag/s320/Switch.PNG" width="320" /></a></div><pre class="code">FlexPanel("index:0")->FlexButton("Switch")=>click();</pre><br />
You can download source code of this project from <a href="http://vini1987.yolasite.com/resources/TestPanel.zip">here</a>.Sargsyan Tigranhttp://www.blogger.com/profile/17269775074544232074noreply@blogger.com91tag:blogger.com,1999:blog-35928092.post-8387746209730741392009-09-18T10:44:00.005-04:002009-09-18T12:25:34.855-04:00Maven Compiler Tips and Tricks<style> <!-- /* Font Definitions */ @font-face {font-family:"Cambria Math"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0in; margin-right:0in; margin-bottom:10.0pt; margin-left:0in; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} p.MsoFootnoteText, li.MsoFootnoteText, div.MsoFootnoteText {mso-style-noshow:yes; mso-style-priority:99; mso-style-link:"Footnote Text Char"; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} span.MsoFootnoteReference {mso-style-noshow:yes; mso-style-priority:99; vertical-align:super;} p.MsoNoSpacing, li.MsoNoSpacing, div.MsoNoSpacing {mso-style-priority:1; mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} span.FootnoteTextChar {mso-style-name:"Footnote Text Char"; mso-style-noshow:yes; mso-style-priority:99; mso-style-unhide:no; mso-style-locked:yes; mso-style-link:"Footnote Text"; mso-ansi-font-size:10.0pt; mso-bidi-font-size:10.0pt;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} /* Page Definitions */ @page {mso-footnote-separator:url("file:///C:/DOCUME~1/dmenard/LOCALS~1/Temp/msohtmlclip1/01/clip_header.htm") fs; mso-footnote-continuation-separator:url("file:///C:/DOCUME~1/dmenard/LOCALS~1/Temp/msohtmlclip1/01/clip_header.htm") fcs; mso-endnote-separator:url("file:///C:/DOCUME~1/dmenard/LOCALS~1/Temp/msohtmlclip1/01/clip_header.htm") es; mso-endnote-continuation-separator:url("file:///C:/DOCUME~1/dmenard/LOCALS~1/Temp/msohtmlclip1/01/clip_header.htm") ecs;} @page Section1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.Section1 {page:Section1;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin-top:0in; mso-para-margin-right:0in; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0in; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"Times New Roman"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin;} </style> <![endif]--> <p class="MsoNormal">Apache’s <a href="http://maven.apache.org/">Maven</a> is a great tool for managing a build environment: it keeps track of all project dependencies and provides a number of configurable build phases which can add depth to the build process. Building a project from the ground-up with Maven is a sure-fire way to keep it well organized and easy to maintain – but what about adding Maven on to an existing project, or worse, merging a non-Maven project into a project that already relies on Maven?</p> <p class="MsoNormal">What follows is a look at some of the lessons I’ve learned from tweaking compiler plug-ins and digging through search results to debug various Maven-related issues. Hopefully it will be useful to the next developer who happens to hit similar issues, and if you have tips of your own be sure to leave a comment.</p> <p class="MsoNormal"><b style=""><span style="line-height: 115%;font-size:14pt;" >The <i style="">maven-compiler-plugin</i> <include> property<o:p></o:p></span></b></p> <p class="MsoNormal">When overriding the default maven-compiler-plugin, the <include> tag may be used to force the compiler to include extra files into the build. There are a couple of interesting points to note here:</p> <p class="MsoNormal" style="margin-left: 0.5in;"><b style="">It is a filter</b>. Many things in Maven expect a path to a directory, but not the <include> tag. If you have some extra java classes in src/main/java and you pass that to <include> it will fail silently – what you actually want is src/main/java/**/*.java.</p> <p class="MsoNormal" style="margin-left: 0.5in;"><b style="">It is for the compile-phase only</b>. By default, in addition to using the maven-compiler-plugin during the compile phase, Maven will also use it during the test-compile phase. Most properties will apply to both, but <include> is not one of them; the test-compile phase requires a separate property, <testIncludes>, for any includables it requires<a style="" href="http://www.blogger.com/post-edit.do#_ftn1" name="_ftnref1" title=""><span class="MsoFootnoteReference"><span style=""><!--[if !supportFootnotes]--><span class="MsoFootnoteReference"><span style="line-height: 115%;font-family:";font-size:11pt;" >[1]</span></span><!--[endif]--></span></span></a>.</p> <p class="MsoNormal"><b style=""><span style="line-height: 115%;font-size:14pt;" >The generate-sources and generate-resources phases<o:p></o:p></span></b></p> <p class="MsoNormal">These phases are great for adding source (.java) and resource (.class) files to the compiler before the compile phase occurs. The snippet below shows how to use <a href="http://mojo.codehaus.org/build-helper-maven-plugin/usage.html">mojo's build-helper-plugin</a> to add some obscure .class files to the classpath:</p><p class="MsoNormal"></p><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><plugin><br /> <groupId>org.codehaus.mojo</groupId><br /> <artifactId>build-helper-maven-plugin</artifactId><br /> <executions><br /> <execution><br /> <phase>generate-resources</phase><br /> <goals><br /> <goal>add-resource</goal><br /> </goals><br /> <configuration><br /> <resources><br /> <resource><br /> <directory>../obscure/classes</directory><br /> </resource><br /> </configuration><br /> </execution><br /> </executions><br /></plugin><br /></pre><br /><p></p><p class="MsoNormal">Now any .class files in ../obscure/classes (or any subdirectories) will be added to the classpath.</p> <p class="MsoNormal">The same plug-in is used for adding .java files, simply tweak the generate-resources and add-resource values to generate-sources and add-source, and the <resources> and <resource> properties to <sources> and <source>.</p> <p class="MsoNormal"><b style=""><span style="line-height: 115%;font-size:14pt;" >The <i style="">maven-compiler-plugin</i> <compilerArgument> property<o:p></o:p></span></b></p> <p class="MsoNormal">The <complierArgument> tag may be used to pass command-line arguments directly to the java compiler. Two examples:</p> <p class="MsoNormal" style="margin-left: 0.5in;"><b style=""><classpath></b> seems like it would let you add resources to the classpath, but near as I can tell, these aren’t actually used. Maven seems to prefer managing its own classpath, though we can still add/remove entries by overriding the default generate-resources phase (as explained above).</p> <p class="MsoNormal" style="margin-left: 0.5in;"><b style=""><sourcepath></b> is a great way to specify multiple source directories for compilation. It takes a semicolon-delimited list of top-level directories containing java files to compile. Alternately, an override of the generate-sources phase may be used here as well.</p> <p class="MsoNormal">One gotcha with regards to sourcepath: to get this to work, I had to manually set <fork> to true on the maven-compiler-plugin. In fact, this gets even worse: when <fork> is true, Maven will use the %PATH% environment variable to determine which JRE to use, and this will fail with a totally non-descript error if the path to your JRE contains any spaces – very annoying to track down. This is actually a bug in Maven, logged here (http://jira.codehaus.org/browse/MCOMPILER-30).</p> <p class="MsoNormal"><b style=""><span style="line-height: 115%;font-size:14pt;" >The <sourceDirectory> property<o:p></o:p></span></b></p> <p class="MsoNormal">A minor but important tag when playing around with various sources and resources, the <sourceDirectory> tag may be used to set the base directory for including java source files.<span style=""> </span>It defaults to src/main/java, but I found when playing around with a lot of sources spread around various directories, it was easiest to set it to the current directory as follows:</p><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><build><br /> <sourceDirectory>.</sourceDirectory><br /> {...}<br /></build><br /></pre><br /><p class="MsoNormal"><b style=""><span style="line-height: 115%;font-size:14pt;" >Other useful debugging hints<o:p></o:p></span></b></p> <p class="MsoNormal">When running into problems, it’s always good to have a few debug flags around to get a little more information out of Maven, which is generally not great at telling you what might be wrong.</p> <p class="MsoNormal">Specifying the <b style="">-e</b> flag while running Maven will print out any exceptions Maven encounters, with the corresponding stack trace.</p> <p class="MsoNormal">The <b style=""><verbose> </b>tag may be added inside any plug-in’s <configuration> property and when toggled to true (default is false) it will print some extra information, including the sourcepath and classpath being used by Maven’s compiler.</p> <p class="MsoNormal">Specifying the <b style="">-X</b> flag while running Maven will document all kinds of intermediate steps Maven takes during the build – much more than -e and <verbose>.</p> <p class="MsoNormal"><o:p> </o:p></p> <div style=""><!--[if !supportFootnotes]--><br /><hr align="left" size="1" width="33%"> <!--[endif]--> <div style="" id="ftn1"> <p class="MsoFootnoteText"><a style="" href="http://www.blogger.com/post-edit.do#_ftnref1" name="_ftn1" title=""><span class="MsoFootnoteReference"><span style=""><!--[if !supportFootnotes]--><span class="MsoFootnoteReference"><span style="line-height: 115%;font-family:";font-size:10pt;" >[1]</span></span><!--[endif]--></span></span></a> This makes perfect sense, of course: it’s unlikely that you’ll want the same includables for both the normal compiler and the testing compiler. It’s just counter-intuitive compared to the rest of the <configuration> properties.</p> </div> </div>Unknownnoreply@blogger.com13tag:blogger.com,1999:blog-35928092.post-3308403058636024932009-07-17T09:08:00.010-04:002009-07-18T02:39:28.719-04:00Here I am!This application allows you to send URL link with your location through SMS message. Receiver will be able to see your location on the map(Google Maps) by simply clicking on the link. First thing we need to do is to get our location using GPS. Android SDK has set of classes and interfaces which makes dealing with location services quite easy. Another positive thing is that SDK is well documented. We need to get an instance of LocationManager: <br />
<pre style="-moz-background-clip: border; -moz-background-inline-policy: continuous; -moz-background-origin: padding; background: rgb(239, 239, 239) none repeat scroll 0% 0%; border: thin solid rgb(166, 176, 191); color: black; padding: 10px; width: 100%;"><span style="color: black;">LocationManager lm = </span><span style="color: black;">(</span><span style="color: black;">LocationManager</span><span style="color: black;">)</span><span style="color: white;"> </span><span style="color: black;">getSystemService</span><span style="color: black;">(</span><span style="color: black;">Context.LOCATION_SERVICE</span><span style="color: black;">)</span><span style="color: black;">;</span></pre>Now that we have location manager we need to request location updates from it. The location is requested using requestLocationUpdates method, it registers the current activity to be notified periodically by the named provider. In our case provider is GPS. For tracking location changes we are using LocationListener which is for receiving notifications from the LocationManager when the location has changed. <br />
<br />
<pre style="-moz-background-clip: border; -moz-background-inline-policy: continuous; -moz-background-origin: padding; background: rgb(239, 239, 239) none repeat scroll 0% 0%; border: thin solid rgb(166, 176, 191); color: black; padding: 10px; width: 100%;"><span style="color: black;">lm.requestLocationUpdates</span><span style="color: black;">(</span><span style="color: black;">LocationManager.GPS_PROVIDER, </span><span style="color: #990000;">1000</span><span style="color: black;">, </span><span style="color: #990000;">0</span><span style="color: black;">, </span>
<span style="color: white;"> </span><span style="color: #7f0055;"><b>new </b></span><span style="color: black;">LocationListener</span><span style="color: black;">() {</span>
<span style="color: white;"> </span><span style="color: #7f0055;"><b>public </b></span><span style="color: #7f0055;"><b>void </b></span><span style="color: black;">onLocationChanged</span><span style="color: black;">(</span><span style="color: black;">Location location</span><span style="color: black;">) </span>
<span style="color: white;"> </span><span style="color: black;">{</span>
<span style="color: white;"> </span><span style="color: #7f0055;"><b>double </b></span><span style="color: black;">lat = location.getLatitude</span><span style="color: black;">()</span><span style="color: black;">;</span>
<span style="color: white;"> </span><span style="color: #7f0055;"><b>double </b></span><span style="color: black;">lng = location.getLongitude</span><span style="color: black;">()</span><span style="color: black;">;</span><span style="color: white;"> </span>
<span style="color: white;"> </span><span style="color: black;">latitude.setText</span><span style="color: black;">( </span><span style="color: black;">Double.toString</span><span style="color: black;">( </span><span style="color: black;">lat </span><span style="color: black;">) )</span><span style="color: black;">;</span>
<span style="color: white;"> </span><span style="color: black;">longitude.setText</span><span style="color: black;">( </span><span style="color: black;">Double.toString</span><span style="color: black;">( </span><span style="color: black;">lng </span><span style="color: black;">) )</span><span style="color: black;">;</span>
<span style="color: white;"> </span><span style="color: black;">}</span>
<span style="color: white;"> </span><span style="color: #7f0055;"><b>public </b></span><span style="color: #7f0055;"><b>void </b></span><span style="color: black;">onProviderDisabled</span><span style="color: black;">(</span><span style="color: black;">String provider</span><span style="color: black;">){}</span>
<span style="color: white;"> </span><span style="color: #7f0055;"><b>public </b></span><span style="color: #7f0055;"><b>void </b></span><span style="color: black;">onProviderEnabled</span><span style="color: black;">(</span><span style="color: black;">String provider</span><span style="color: black;">){}</span>
<span style="color: white;"> </span><span style="color: #7f0055;"><b>public </b></span><span style="color: #7f0055;"><b>void </b></span><span style="color: black;">onStatusChanged</span><span style="color: black;">(</span><span style="color: black;">String provider, </span><span style="color: #7f0055;"><b>int </b></span><span style="color: black;">status,Bundle extras</span><span style="color: black;">){}</span>
<span style="color: white;"> </span><span style="color: black;">})</span><span style="color: black;">;</span></pre><br />
Just getting last known location... <br />
<pre style="-moz-background-clip: border; -moz-background-inline-policy: continuous; -moz-background-origin: padding; background: rgb(239, 239, 239) none repeat scroll 0% 0%; border: thin solid rgb(166, 176, 191); color: black; padding: 10px; width: 100%;"><span style="color: black;">Location location = lm.getLastKnownLocation</span><span style="color: black;">(</span><span style="color: black;">LocationManager.GPS_PROVIDER</span><span style="color: black;">)</span><span style="color: black;">;</span></pre>Good! We got the location. Now we just need to generate the URL and send SMS. Android offers full access to SMS functionality from within your applications with the SMSManager. We are geeting a reference to the SMS Manager using the static method SmsManger.getDefault. For sending SMS message use sendTextMessage, which allows you to send SMS message by specifying text message and receiver's phone number. <br />
<pre style="-moz-background-clip: border; -moz-background-inline-policy: continuous; -moz-background-origin: padding; background: rgb(239, 239, 239) none repeat scroll 0% 0%; border: thin solid rgb(166, 176, 191); color: black; padding: 10px; width: 100%;"><span style="color: #000099;">final SmsManager sm </span>= SmsManager.getDefault();
<span style="color: #000099;">String phoneNumber </span>= number.getText().toString();
<span style="color: #000099;">String URL </span>= "http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=";
<span style="color: #000099;">URL +</span>= latitude.getText() + "," + longitude.getText();
sm.sendTextMessage(phoneNumber, null, URL, null, null);
</pre>That's it! Just one note - in order to send SMS message and request GPS location application require following two permissions: <br />
<pre style="-moz-background-clip: border; -moz-background-inline-policy: continuous; -moz-background-origin: padding; background: rgb(239, 239, 239) none repeat scroll 0% 0%; border: thin solid rgb(166, 176, 191); color: black; padding: 10px; width: 100%;"><span style="color: black;"><uses-permission android:name=</span><span style="color: #2a00ff;">"android.permission.ACCESS_FINE_LOCATION" </span><span style="color: black;">/></span><span style="color: white;"></span>
<span style="color: black;"><uses-permission android:name=</span><span style="color: #2a00ff;">"android.permission.SEND_SMS"</span><span style="color: black;">/> </span></pre><br />
Thanks to my friend Aaron Olson from <a href="http://www.macadamian.com/">Macadamian</a> for the help in testing this code.<br />
<br />
<a href="http://ucesco.googlepages.com/GPSLocation.zip">Source</a>Sargsyan Tigranhttp://www.blogger.com/profile/17269775074544232074noreply@blogger.com17tag:blogger.com,1999:blog-35928092.post-69562786352832076792009-06-04T10:14:00.002-04:002009-06-04T10:42:33.880-04:00Using Mate to Dispatch Events with a Callback in ActionScript<a href="http://mate.asfusion.com/">Mate</a> is a powerful event framework for Adobe Flex which provides advanced functionality for dispatching, listening for and handling events. The framework is tag-based, so the typical use case is to add tags provided by Mate to your MXML. This works very well in most situations, and Mate's documentation is generally very thorough and great for resolving any questions or issues that come up - until you have to do things without MXML.<br /><br />I ran into a situation not too long ago where I had to dispatch an event with a callback from a service-like class. Since this wasn't a UI component, there was no corresponding MXML. I needed a pure-ActionScript solution, but still wanted to use Mate. In a matter of minutes, I had no problem dispatching my event*:<br /><pre><br />public class TestClass<br />{<br /> public function generateEvent():void<br /> {<br /> var event:TestEvent= new TestEvent();<br /> event.type = TestEvent.TYPE;<br /> <br /> var dispatcher:Dispatcher = new Dispatcher();<br /> dispatcher.generator = TestEvent;<br /> dispatcher.dispatchEvent( event );<br /> }<br />}<br /></pre><br />This was a good start, but I wanted to specify a method within the same service-like class to be called if the event returned successfully. Mate's dispatcher tag makes this very easy, but without any MXML, it was not an option. All the handler for the event does is generate a result or fault using Mate's ServiceResponseAnnouncer, so I needed a way to specify the callback from my dispatcher: just like the MXML tag allows, but using only ActionScript.<br /><br />Looking through the docs didn't get me very far. The section on the <a href="http://mate.asfusion.com/page/documentation/tags/dispatcher">Dispatcher</a> provides information on using a dispatcher in ActionScript, but without a callback, and there is a section on using callbacks, but specific to the MXML implementation. I checked the ResponseHandler classes as well, and poked around a bit on Google without much luck.<br /><br />Knowing that these properties exist, I attempted to piece it together myself (and eventually succeeded). In case anyone else ever runs into the same issue, and because I'd rather not go through all that searching/trial-and-error again, here is a working solution:<br /><pre><br />public class TestClass<br />{<br /> public function generateEvent():void<br /> {<br /> var event:TestEvent= new TestEvent();<br /> event.type = TestEvent.TYPE;<br /> <br /> var handler:ResponseHandler = new ResponseHandler();<br /> handler.type = ResponseEvent.RESULT;<br /> handler.method = myCallback;<br /> <br /> var dispatcher:Dispatcher = new Dispatcher();<br /> dispatcher.generator = TestEvent;<br /> dispatcher.responseHandlers = [handler];<br /> dispatcher.dispatchEvent( event );<br /> }<br /> <br /> private function myCallback(event:ResponseEvent):void<br /> {<br /> trace( "callback reached!" );<br /> }<br />}<br /></pre><br />One of the hardest parts to figure out was what method signature was required for the callback function. I found my answer in a comment in the ResponseHandler class - one more reason why open source frameworks and well commented code are the way to go!<br /><br /><small>*Aside: if a callback is not necessary, there's no need to use Mate. In fact, Mate's <a href="http://mate.asfusion.com/page/documentation/best-practices">best practices</a> specifically encourage using Flex's built-in dispatchEvent() method. Had I not needed a callback here, I could have called dispatchEvent() on the parent application (or any other DisplayObject within the scope of my service class).</small>Unknownnoreply@blogger.com32tag:blogger.com,1999:blog-35928092.post-76022820967443886042009-05-11T22:36:00.001-04:002009-05-11T22:49:26.225-04:00XBAP - Using the Popup Control as a Dialog Box<p>How many people have experienced the modal pop up in desktop applications? They are commonly used across a wide variety of applications, one could say, too commonly used. While not appropriate for all situations, sometimes you need to use a pop up. <p>In XBAP applications the ability to open a pop-up is very limited; in many cases you will use navigation and multiple pages instead of separate windows. In most cases this is sufficient, but sometimes you really need to use a pop-up, and when you do a simple work around is to use the Popup control offered by WPF. <p align="justify">First, you define the Popup in the markup, making sure to set its StaysOpen property to true so it will remain open until you close it. (There’s no point in using the PopupAnimation or AllowsTransparency properties, because they won’t have any effect in a web page.) Include suitable buttons, such as OK and Cancel, and set the Placement property to Center so the popup will appear in the middle of the browser window.</p> <p>Code sample:</p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff"><</span><span style="color: #800000">Popup</span> <span style="color: #ff0000">Name</span><span style="color: #0000ff">="dialogPopUp"</span> <span style="color: #ff0000">StaysOpen</span><span style="color: #0000ff">="True"</span> <span style="color: #ff0000">Placement</span><span style="color: #0000ff">="Center"</span> <span style="color: #ff0000">MaxWidth</span><span style="color: #0000ff">="200"</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">Border</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">Border.Background</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">LinearGradientBrush</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">GradientStop</span> <span style="color: #ff0000">Color</span><span style="color: #0000ff">="AliceBlue"</span> <span style="color: #ff0000">Offset</span><span style="color: #0000ff">="1"</span><span style="color: #0000ff">></</span><span style="color: #800000">GradientStop</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">GradientStop</span> <span style="color: #ff0000">Color</span><span style="color: #0000ff">="LightBlue"</span> <span style="color: #ff0000">Offset</span><span style="color: #0000ff">="0"</span><span style="color: #0000ff">></</span><span style="color: #800000">GradientStop</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"></</span><span style="color: #800000">LinearGradientBrush</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"></</span><span style="color: #800000">Border.Background</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">StackPanel</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="5"</span> <span style="color: #ff0000">Background</span><span style="color: #0000ff">="White"</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">TextBlock</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="10"</span> <span style="color: #ff0000">TextWrapping</span><span style="color: #0000ff">="Wrap"</span><span style="color: #0000ff">></span>Please enter your name.</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"></</span><span style="color: #800000">TextBlock</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">TextBox</span> <span style="color: #ff0000">Name</span><span style="color: #0000ff">="txtName"</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="10"</span><span style="color: #0000ff">></</span><span style="color: #800000">TextBox</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">StackPanel</span> <span style="color: #ff0000">Orientation</span><span style="color: #0000ff">="Horizontal"</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="10"</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">Button</span> <span style="color: #ff0000">Click</span><span style="color: #0000ff">="dialog_boxOK_Click"</span> <span style="color: #ff0000">Padding</span><span style="color: #0000ff">="3"</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="0,0,5,0"</span><span style="color: #0000ff">></span>OK<span style="color: #0000ff"></</span><span style="color: #800000">Button</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"><</span><span style="color: #800000">Button</span> <span style="color: #ff0000">Click</span><span style="color: #0000ff">="dialog_boxCancel_Click"</span> <span style="color: #ff0000">Padding</span><span style="color: #0000ff">="3"</span><span style="color: #0000ff">></span>Cancel<span style="color: #0000ff"></</span><span style="color: #800000">Button</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"></</span><span style="color: #800000">StackPanel</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"></</span><span style="color: #800000">StackPanel</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff"></</span><span style="color: #800000">Border</span><span style="color: #0000ff">></span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff"></</span><span style="color: #800000">Popup</span><span style="color: #0000ff">></span></pre><!--CRLF--></div></div><br /><p align="justify">At the appropriate time (for example, when a button is clicked), disable the rest of your user interface and show the Popup. To disable your user interface, you can set the IsEnabled property of some top-level container, such as a StackPanel or a Grid, to false. (You can also set the Background property of the page to gray, which will draw the user’s attention to Popup.) To show the Popup, simply set its IsVisible property to true. <br><br>Here’s an event handler that shows the previously defined Popup:<br /><div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><br /><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> popupTriggerButton_Click(<span style="color: #0000ff">object</span> sender, RoutedEventArgs e)</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> DisableMainPage();</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> DisableMainPage()</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> mainPage.IsEnabled = <span style="color: #0000ff">false</span>;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.Background = Brushes.LightGray;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> dialogPopUp.IsOpen = <span style="color: #0000ff">true</span>;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div></div><br /><p align="justify">When the user clicks the OK or Cancel button, close the Popup by setting its IsVisible property to false, and re-enable the rest of the user interface:<br /><div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><br /><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> dialog_boxOK_Click(<span style="color: #0000ff">object</span> sender, RoutedEventArgs e)</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #008000">// Copy name from the Popup into the main page.</span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> lblName.Content = <span style="color: #006080">"You entered: "</span> + txtName.Text;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> EnableMainPage();</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">} </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> dialog_boxCancel_Click(<span style="color: #0000ff">object</span> sender, RoutedEventArgs e)</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> EnableMainPage();</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> EnableMainPage()</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> mainPage.IsEnabled = <span style="color: #0000ff">true</span>;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.Background = <span style="color: #0000ff">null</span>;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> dialogPopUp.IsOpen = <span style="color: #0000ff">false</span>;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div></div><br /><p align="justify">Using the Popup control to create this workaround has one significant limitation. To ensure that the Popup control can’t be used to spoof legitimate system dialog boxes, the Popup window is constrained to the size of the browser window. If you have a large Popup window and a small browser window, this could chop off some of your content. One solution is to wrap the full content of the Popup control in a ScrollViewer with the VerticalScrollBarVisibility property set to Auto.<br><br>If a Popup isn’t suitable for you, you can try another more “interesting” approach for showing a dialog box. Using the Windows Form library from .NET 2.0 you can safely create and host any WinForm control in your WPF application. In this case, you can create and show an instance of the System.Windows.Forms.Form class (or any custom form that derives from Form), because it doesn’t require unmanaged code permission. In fact, you can even show the form modelessly, so the page remains responsive. The only drawback is that a security balloon automatically appears superimposed over the form and remains until the user clicks the warning message. You’re also limited in what you can show in the form. Windows Forms controls are acceptable, but WPF content isn’t allowed.</p> Unknownnoreply@blogger.com38tag:blogger.com,1999:blog-35928092.post-9431952831575394822009-04-27T16:26:00.000-04:002009-04-27T16:26:50.627-04:00FlexDockFlexDock is a custom component which allows to have a number of "expandable boxes" placed in horizontal direction. It is not possible to have more than one box expanded at the same. Click on the box expanding the clicked box and shrinking previously expanded box. Shift + Click shrinking the expanded box.<br />
<br />
The component which is actually our "box" is called CanvasBox. For expanding the boxes I prefer to use <a href="http://code.google.com/p/tweener/">Caurina Tweener</a>, it is also possible to use built-in mx.effects.Resize, but I prefer Caurina Tweener's one:<br />
<br />
<pre style="color: #ffffff;background: #444444;overflow: scroll;width: 100%;height: 70px;border: 1px solid #A6B0BF;font-size: 100%;text-align: left;margin: 0;padding: 0;">private var _rollOverTween:Object = {width:200, height:200, time:0.45, transition:"easeOutBack", onComplete:onRollOver};
private var _rollOutTween:Object = {width:90, height:90, time:0.2, transition:"linear", onComplete:onRollOut};
</pre><br />
When the user clicks on the button the Tweener.addTween( this, _rollOverTween); method is called, it is possible to change the content of the box in the click handler, but if you want your UI not to be broken it is better to do those changes in the onComplete handler of the tween.<br />
<br />
Besides the CanvasBox component we also need to have a component which will hold the boxes. It is called BoxHolder and it is template component. It has _content field which is storing the boxes, pay attention at [ArrayElementType("CanvasBox")]:<br />
<br />
<pre style="color: #ffffff;background: #444444;overflow: scroll;width: 100%;height: 110px;border: 1px solid #A6B0BF;font-size: 100%;text-align: left;margin: 0;padding: 0;">// An array which stores the UI components
// of our content
[ArrayElementType("CanvasBox")]
private var _content:Array;
</pre><br />
Every time you click on a box, the closeOthers method is called which is shrinking previously expanded box.<br />
<br />
<pre style="color: #ffffff;background: #444444;overflow: scroll;width: 100%;height: 220px;border: 1px solid #A6B0BF;font-size: 100%;text-align: left;margin: 0;padding: 0;">private function closeOthers(event:MouseEvent):void
{
for each(var component:CanvasBox in _content)
{
if(component != event.currentTarget)
{
component.roolOut();
}
}
}
</pre><br />
<a href="http://ucesco.googlepages.com/mockup5.html">DEMO</a> | <a href="http://ucesco.googlepages.com/ExpandableBoxes.zip">SOURCE</a>Sargsyan Tigranhttp://www.blogger.com/profile/17269775074544232074noreply@blogger.com20tag:blogger.com,1999:blog-35928092.post-79776508322520503312009-03-31T15:16:00.003-04:002009-04-20T09:43:21.566-04:00HTML4 and XHTML<div><span class="Apple-style-span" style="font-family: 'Times New Roman'; "><div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "><div>This one hurts, Jason suggested to me to post this, and since Macadamian is an "egoless" programming shop - that I do adhere to - I do it even though I might be laughed at!<br /><br />More seriously, when dealing with HTML, remember that each version of the specification has specific characteristics. And the application you are using (in my case Atlassian's Confluence), is validating against some version of the specification. Somehow I known this for years, having spent countless hours in the SOAP and WSDL specifications back in my Cognos days. Yet somehow I forgot, its easy to overlook these sorts of things sometimes.<br /><br />Now the problem I encountered was around the closing tags. In XHTML you can do things like this but not in HTML4:<br /><span class="Apple-style-span" style="font-weight: bold; "><br /></span><iframe src=.../><div><br /></div><div>instead, in HTML4 you have to explicitely use the closing tag as shown below:</div><div><br /></div><div><iframe src=...> </iframe></div><div><br /><div>The consequence of this mistake was that all the code following the first form was not rendered by the Browser (I tested this in Firefox and Chrome). I could see the content driven by the iframe though.<br /><br />So the morale of the story, read the manual and remember the specification! :)<br /></div><div><br /></div></div></div></div></span></div>Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-35928092.post-27585401791528041152009-03-09T11:49:00.001-04:002009-03-09T11:51:44.853-04:00Single Instance Applications in WPF<p align="justify">In some design scenarios launching multiple copies of the same WPF application is a problem, especially for document-based applications or server applications. </p> <p align="justify">WPF does not provide a native solution for single instance applications; however there are several workarounds for this issue. </p> <p align="justify">The most commonly used solution is to check whether another instance of the application is already running when the Application.Startup event fires. This is easily done using a system wide mutex (provided by the operating system to allow interprocess communication). While this is easily done, it limits the developer’s options by not providing a way for the new instance to communicate with the already running instance. Mainly this will provide only a simple way of limiting the number of running instances to one, while a separate system will be required to handle the new calls (usually through remoting or Windows Communication Foundation). </p> <p align="justify">The recommended and more useful approach is to use the built-in support that’s provided in Windows Forms and originally intended for Visual Basic applications. This approach handles the messy plumbing behind the scenes. This means using an old style application class as wrapper for the WPF application. The wrapper will handle the instance management and will communicate the request to the already running instance of the WPF application. </p> <p align="justify"><strong>Solution steps</strong>: </p> <p align="left">1) Add a reference to the <strong>Microsoft.VisualBasic.dll</strong> assembly. </p> <p align="left">2) Add a new custom class derived from the <strong>Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase</strong> class. </p> <p align="left">3) The <strong>IsSingleInstance</strong> must be set to true in the constructor. This enables a single instance application. </p> <p align="left">4) Override the <strong>OnStartup()</strong> method to create the WPF application object. (Note: The <strong>OnStartup()</strong> method is triggered when the application starts) </p> <p align="left">5) Overide the <strong>OnStartupNextInstance()</strong> method to handle future instances. (Note: The <strong>OnStartupNextInstance()</strong> method is triggered in when another instance of the application starts up) </p> <p align="left">6) Define a Main entry point for the application and create the wrapper object</p> <p align="left">7) Create the WPF application class </p> <p align="justify"><strong>Sample of the application wrapper</strong>: </p> <style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style> <div align="justify"> <div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"> <div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #0000ff">using</span> System;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">using</span> System.Collections.Generic;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #0000ff">using</span> System.Linq;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">using</span> System.Text;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #0000ff">using</span> Microsoft.VisualBasic.ApplicationServices;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">using</span> System.Windows;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">namespace</span> SingleInstanceApplication</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">{</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #008000">//The Main entry point class</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Startup</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> {</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> [STAThread]</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> {</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> SingleInstanceAppWrapper wrapper = <span style="color: #0000ff">new</span> SingleInstanceAppWrapper();</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> wrapper.Run(args);</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> }</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> }</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #008000">//The old-style application wrapper</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> SingleInstanceAppWrapper : WindowsFormsApplicationBase</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> {</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #0000ff">public</span> SingleInstanceAppWrapper()</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> {</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #008000">// Enable single-instance mode.</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #0000ff">this</span>.IsSingleInstance = <span style="color: #0000ff">true</span>;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> }</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #008000">// Create the WPF application class.</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #0000ff">private</span> WPFApplication _app;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #008000">//Override OnStartup() method to create the WPF application object</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">bool</span> OnStartup(</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> {</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> _app = <span style="color: #0000ff">new</span> WPFApplication();</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> _app.Run();</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span>;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> }</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #008000">// Override OnStartupNextInstance() to handle multiple application instances.</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> OnStartupNextInstance(</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e)</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> {</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #008000">//In case of command line arguments, send them to the WPF application object </span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #0000ff">if</span> (e.CommandLine.Count > 0)</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> {</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> _app.HandleCommandLine(e.CommandLine);</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> }</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> }</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> }</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">}</pre></div></div></div><br /><p align="justify">As you can see, the sample above contains the Main entry point for the application. This is required because the wrapper must be created first. <br>If Visual Studio is used, by default the App.xaml application definition style is used. This will not work with the wrapper because the App.xaml approach already has a Main entry point. <br>Remove App.xaml and App.xaml.cs from the project and create a new class for the entry point.</p><br /><p align="justify">The only thing left to do is to create the WPF application definition:</p><br /><div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"><br /><div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> WPFApplication : System.Windows.Application</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">{</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #008000">//Override the OnStartup() method</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> OnStartup(System.Windows.StartupEventArgs e)</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> {</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #0000ff">base</span>.OnStartup(e);</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #008000">//Load the main window</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> Window _MainWindow = <span style="color: #0000ff">new</span> Window();</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> _MainWindow.Show();</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #008000">//Set the MainWindow property for the WPF application object</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #0000ff">this</span>.MainWindow = _MainWindow;</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> }</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #008000">//Method used to handle command line arguments</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> HandleCommandLine (System.Collections.ObjectModel.ReadOnlyCollection<<span style="color: #0000ff">string</span>> e)</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> {</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> <span style="color: #008000">//Code to handle command line arguments from other instances goes here</span></pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> }</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">}</pre></div></div><br /><p align="justify">Because the wrapper approach does not contain a XAML application definition (App.xaml), if you need to load application level resources, the following code can be placed the OnStartup() of the WPF application definition to load the resources from a resource dictionary:</p><br /><div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"><br /><div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> Application.Current.Resources.MergedDictionaries.Add(</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> Application.LoadComponent(</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #0000ff">new</span> Uri(<span style="color: #006080">"AssemblyName;component/ApplicationResourceDictionary.xaml"</span>,</pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"> UriKind.Relative)) <span style="color: #0000ff">as</span> ResourceDictionary);</pre></div></div><br /><p align="justify">The above code will work for dynamic resource definitions. The static resource lookup process will fail because the source for the application resources dictionary need to be specified. In that case the code to load the resources will be replaced with the following:</p><br /><div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"><br /><div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">Application.Current.Resources.Source = </pre><pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"> <span style="color: #0000ff">new</span> Uri(<span style="color: #006080">"/AssemblyName;component/ApplicationResourceDictionary.xaml"</span>, UriKind.Relative);</pre></div></div><br /><p align="justify">Note: AssemblyName is a placeholder for the actual assembly name. The Uri for the resource dictionary location can be changed as required.</p> Unknownnoreply@blogger.com18tag:blogger.com,1999:blog-35928092.post-78037445941656996292008-11-12T11:25:00.006-05:002008-11-12T11:40:11.875-05:00The Anti-social web - Twitter for the socially ineptTwitter was mentioned during Macadamian's corporate blogging presentation. "Useless! Bah! Humbug!" were the first thoughts to enter my head. Then the speaker pointed out that corporate bloggers should strive to see the positive side of any situation, and I figured making Twitter useful to a neo-Luddite was a good challenge; there must be an itch to scratch here, right?<br /><br />All I knew about Twitter was that people think it's slow, and it's written in Ruby (on Rails.) After exploring a little more, I found out that it can provide private Atom feeds of your messages, and exposes a REST API (ooh, new, shiny!) That was enough to get me coding.<br /><br />To keep things simple I decided to be boring and test out Twitter using Ruby (normally, I plan epic posts with 5 different languages, communicating through at least 2 protocols... and a database for no good reason.) The process I followed was:<br /><ul><li>Install Ruby (one-click installer)</li><li>In the Gems package manager: gem install <a href="http://rest-client.heroku.com/rdoc/">rest-client</a></li><li>Install the <a href="http://rubyeclipse.sourceforge.net/">Ruby Development Tools</a> for Eclipse</li><li>Read the <a href="http://apiwiki.twitter.com/REST+API+Documentation#DirectMessageMethods">Twitter API</a><br /></li></ul><pre>require 'date'<br />require 'rest_client'<br />require 'rexml/document'<br /><br />username = "your_twitter_id_here"<br />password = "your_twitter_password_here"<br /><br />twitter = RestClient::Resource.new 'http://%s:%s@twitter.com' % [ username, password ]<br /><br /># Send a message to twitter<br />result = twitter['statuses/update.xml'].post(<br /> :status => "This is your computer. You have no life as of %s" % DateTime.now()<br />)<br /># print result<br /><br />timelineXML = twitter['statuses/user_timeline.xml'].get({ :count => 5 });<br /><br /># Make the XML usable<br /># (Use XmlSimple for even easier handling)<br />timeline = REXML::Document.new(timelineXML)<br /><br /># Display the text element of every status returned by the service<br /># (print timelineXML to learn more about the structure of the result.)<br />puts "%s's timeline:" % username<br />timeline.elements.each('statuses/status/text') { |message|<br /> puts message.text<br />}<br /></pre><br />As Twitter <a href="http://apiwiki.twitter.com/REST+API+Documentation#RateLimiting">restricts you to 70 calls per hour</a>, it's a good job Ruby (on REST) made this so easy. REST is a nice change from the usual URL gobbledygook that frameworks throw up - I can't wait to try it out in <a href="http://struts.apache.org/2.x/docs/rest-plugin.html">Struts2</a>.<br /><br />So, what can people with no interest in socializing do with Twitter?<br /><ul><li>Free yourself from your desk by monitoring that 45 minute long J2EE build from <a href="http://twitterforiphone.com/">your iPhone</a></li><li>Monitor your computers by receiving disk capacity warnings, CPU performance reports, and IP address changes</li><li>Find out when <a href="http://tech.shantanugoel.com/2008/05/14/keep-tab-on-home-security-with-a-webcam-and-twitter.html">someone is breaking into your home</a></li><li>Know when <a href="http://www.engadget.com/2008/02/25/diy-kit-lets-houseplants-twitter-when-they-need-water/">your plants need to be watered</a></li><li>Search for signs of life in the <a href="http://www.p2pnet.net/story/16101">Mars lander</a></li></ul>One final note, until <a href="http://apiwiki.twitter.com/REST+API+Documentation#Authentication">the authentication framework is more robust</a>, don’t rely on anything you twit staying private.Gord. Phttp://www.blogger.com/profile/10684846302006538110noreply@blogger.com79tag:blogger.com,1999:blog-35928092.post-58786862798574026902008-10-29T00:41:00.006-04:002010-04-01T18:58:09.145-04:00Breadth-First Coding<span style="font-size:130%;"><span style="font-style: italic;">"Look Ma! I'm inventing my own buzzwords!"</span></span><br /><br /><span style="font-weight: bold;font-size:180%;" >The problem</span><br /><br />A little while ago, some of us at <a href="http://www.macadamian.com/">Macadamian</a> held discussions on behaviors we would like to encourage among younger developers. One thing we agreed was that "stubbing" (coming up with methods containing as little code as possible, in order to stabilize the API interactions faster) was becoming a "lost art". And so we resolved to start encouraging "top-down development", as we were used to call it.<br /><br />So far, we've met with little success. Despite our explicit encouragements, it seems hard for people to adopt a "top-down" approach.<br /><br />And lately, I've been wondering: what if we're not communicating right? After all, "top-down" is a pretty generic term. After all, it's even used to describe <a href="http://en.wikipedia.org/wiki/Top_down">an entire programming methodology</a> which predates Object-Oriented Design. So perhaps some of the people in our teams are thinking: "<span style="font-style: italic;">Of cours</span>e I'm going from top to bottom, what are they complaining about!?"<br /><br />That's when I thought of something...<br /><br /><span style="font-weight: bold;font-size:180%;" >Mandatory flashback to the author's younger days</span><br /><br />Back at school, I followed this neat AI course which taught me some general problem-solving heuristics. Overall, it showed two ways to attack a problem by brute force: <span style="font-style: italic;">breadth-first</span> and <span style="font-style: italic;">depth-first</span>.<br /><br />Let's say we're looking for a file within a directory structure. A <span style="font-style: italic;">depth-first</span> approach will recursively explore each solution by first going to the lowest node possible. Only then will it work its way back up, before going down again.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKytIUF1vv2C4EQF5PBAunHrzb6a1M49i1jtLgxATSmaSjA-L1U8jQTctJjqUqpjDPNMGD-y1XGKQLqWxYpbhnKdTRPJBNzlRKpSFU54tMNK8gnoS0azIstWV9QEtdgor9fRhX/s1600/DF-Tree-741467.png"><img style="cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKytIUF1vv2C4EQF5PBAunHrzb6a1M49i1jtLgxATSmaSjA-L1U8jQTctJjqUqpjDPNMGD-y1XGKQLqWxYpbhnKdTRPJBNzlRKpSFU54tMNK8gnoS0azIstWV9QEtdgor9fRhX/s320/DF-Tree-741467.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5455306924969917266" /></a><br /><br />A <span style="font-style: italic;">breadth-first</span> approach, on the other hand, would attempt to fully explore one level of nodes before jumping to the next one.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfxk9z5aaMBQBF17BbSTiGj9wJmdxO_3Jhmi_7SlDNXAf-qvugQ8IEW3dDaL3DFK56oaHensxO82BrDyx4qXzSOx27orve2AcyvZ9e_362AtL7t6EsNVaBdEKzWk51Y1TnPbNC/s1600/BF-Tree-756269.png"><img style="cursor:pointer; cursor:hand;width: 320px; height: 210px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfxk9z5aaMBQBF17BbSTiGj9wJmdxO_3Jhmi_7SlDNXAf-qvugQ8IEW3dDaL3DFK56oaHensxO82BrDyx4qXzSOx27orve2AcyvZ9e_362AtL7t6EsNVaBdEKzWk51Y1TnPbNC/s320/BF-Tree-756269.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5455306625204676386" /></a><br /><br />For additional details, you check out <a href="http://en.wikipedia.org/wiki/Breadth-first_search">breadth-first search</a> and <a href="http://en.wikipedia.org/wiki/Depth-first">depth-first search</a> on Wikipedia (where I borrowed these graphs from).<br /><br /><span style="font-weight: bold;font-size:180%;" >And so...</span><br /><br />I'm beginning to think that younger developers show a natural tendency to code <span style="font-style:italic;">depth-first</span>. They pick a single feature/functionality/API call, then implement it down to the lowest level, at which point they consider to have a "valid iteration". Then they go back up a few levels, and start again. Doing things that way can make you feel good because you've added a lot of code, but it makes things harder to test, and might complicate future integration.<br /><br />We'd like people to try out <span style="font-style:italic;">breadth-first coding</span>, which would mean getting a wider range of partly-implemented methods in the early stages.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/commons/4/46/Animated_BFS.gif"><img style="cursor:pointer; cursor:hand;width: 187px; height: 175px;" src="http://upload.wikimedia.org/wikipedia/commons/4/46/Animated_BFS.gif" border="0" alt="" /></a><br /><br />First, you'd define the APIs of the first layer, providing a "bare-bone" implementation of each method. Then you'd define the second layer, once again with a minimal implementation, at which point you'd be able to properly implement the first layer. Repeat for each layer of implementation.<br /><br />So, as my first step, I'll start using the term "breadth-first" when talking about this approach. I'm hoping that by using this term instead of "top-down", I'll get a few "Huh? WTF?" responses, which may be just what we need in order to break some old habits...Unknownnoreply@blogger.com1010tag:blogger.com,1999:blog-35928092.post-80807233723924357172008-09-12T09:28:00.004-04:002008-09-12T09:59:03.465-04:00Bridge SharePoint - User Profiles and User Profile Properties (part 2 of 2)<p>As we have found out in part 1, SharePoint can manipulate data using the user profile management objects and can accept data from external sources. Using these two features apart we have two limited tools with limited usage, but using them together gives us a powerful, flexible and efficient method of storing and using data from any internal or external resource.<br /><br />It’s time to see this solution to our problems in action. </p> <p><b>Code example of getting/setting the profile property from a C# application</b> </p> <p>The concept is the same for any source of information (web services, web applications, etc.):<br />Get the user’s profile->Get the required profile property->Get/Set profile property value </p> <p><b>Code example</b>: (note that to access profile properties, this code must run with elevated privileges)</p><pre class="code"><span style="color:blue;">string </span>value;<br /><span style="color:blue;">try<br /></span>{<br /> SPSecurity.RunWithElevatedPrivileges(<span style="color:blue;">delegate</span>()<br /> {<br /> <br /> <span style="color:green;">// Change the site address for different deployment environments<br /> // Note: WIN2003STD is a place holder for your environment, usually your server name<br /> </span>SPSite site = <span style="color:blue;">new </span>SPSite(<span style="color: rgb(163, 21, 21);">"http://WIN2003STD/"</span>);<br /> SPWeb web = site.OpenWeb();<br /><br /> <span style="color:green;">// Get the profile manager object for the site<br /> </span>UserProfileManager profileManager = <span style="color:blue;">new </span>UserProfileManager(ServerContext.GetContext(site));<br /><br /> <span style="color:green;">// Use the username from the User Information Item to get the full profile of an user<br /> </span>UserProfile user_profile = profileManager.GetUserProfile(System.Web.HttpContext.Current.User.Identity.Name);<br /><br /> <span style="color:green;">// Get the required profile property value from the profile<br /> </span>value = user_profile[<span style="color: rgb(163, 21, 21);">"MyProperty"</span>].Value.ToString();<br /><br /> <br /> });<br />}<br /><span style="color:blue;">catch </span>(Exception e)<br />{<br /> <span style="color:blue;">return </span><span style="color: rgb(163, 21, 21);">"Error getting user info: " </span>+ e.Message.ToString();<br />}</pre><br /><p>user_profile["MyProperty"].Value gets or sets the profile property value.<br /></p><p>This is a very convenient way of using profile properties to store required information for each user. Properties can be set as read-only or not to appear in the user’s profile, which gives you even more control. </p>System.Web.HttpContext.Current.User.Identity.Name returns the username (the login username) and it is used in the code example above to get the profile of the currently logged-in user.<br /><p><b>Tools You Never Knew You Had… (and what to do with them now that you’ve wised up!)</b> </p>With this simple solution to getting/setting a user’s profile property value, endless opportunities are now at hand. This small code snippet helps developers control, validate and use values stored for each user, without corrupting the database or resorting to other more complex and error-prone solutions.<br />For those not needing to use an external application to get information from the users, a custom SharePoint web application can be developed and deployed on SharePoint. This way all the controls offered by ASP .NET or custom controls can be used to perform required operations on the data before it’s stored.<br /><p>External applications running on the server can access this information the same way, so a bridge between SharePoint and applications like web sites, game servers, messaging apps, etc. can be easily created.<br /></p><p><b>SharePoint Complications, As Usual</b><br /></p><p>Watch out that the profile property might be set as read-only in SharePoint. Even if it’s the case however, the above code should still be able to access the profile because it’s running with elevated privileges. So if there is a situation in which the user is allowed to see the data but only modify it by using a service (like a web application or web service), this is a good way of doing it. </p>Another gotcha is that the code above can only be used on the SharePoint server machine. This is due to the framework that SharePoint uses. To get information or to change data from a network on internet location, a SharePoint custom web service or web application can come in handy. Other ways of passing information will work too, like server-client applications, as long as the part running the above code is on the SharePoint server machine.<br /><p>So we now have a way to store data and manipulate it according to our needs. We can control it, we can validate it and most important of all, we decide how the user interacts with the data. </p>We’re now ready to start doing some serious SharePoint development!Unknownnoreply@blogger.com26tag:blogger.com,1999:blog-35928092.post-34805402783161234832008-09-10T11:51:00.000-04:002008-09-10T13:07:05.673-04:00Bridge SharePoint - User Profiles and User Profile Properties (part 1 of 2)There is a constant need in SharePoint feature development to bridge SharePoint 2007 with other web applications. In order to create such a bridge, a variety of user information must be stored in the SharePoint database.<br /><br /><span style="font-weight: bold;">Warning: Do not tamper with the SharePoint database! No matter how tempting it is!</span><br /><br /> Although this might sound as simple as a small SQL application, tampering with SharePoint’s database could lead to disastrous results and even complete and irreversible server crashes, since many of SharePoint’s recovery features rely on the database being intact. “Feeding” information to SharePoint through its database is unadvisable and sometimes very hard to do, mainly due to the complex structure of the database.<br /><br /> Fortunately there is a built-in solution to this problem that is both simple and efficient: <span style="font-weight: bold;">User Profiles and User Profile Properties.</span><br /><br /> In this post we will see how SharePoint’s user profiles and profile properties can help us do our job fast and easy without worrying about crashing the server or breaking more features than we create.<br /><br /> Let’s start with the storing information problem.<br /> Many developers have already considered using Profile Properties as way to store the required data, but have given up on using them due to their limitations (limited validation, control, variety). Controlling the user’s input and making sure that the values are correct is essential in any bridge, and often auto-generated values based on that data are necessary. SharePoint can only do so much, and this is usually the main reason why developers avoid using the custom profile properties.<br /><br /> <span style="font-weight: bold;">Solution: Manage information using the Microsoft.Office.Server.UserProfiles namespaces.</span><br /><br /> SharePoint Server 2007 stores user profiles in SQL Server, but the information can be imported from other data sources, such as:<br />· Active Directory<br />· Lightweight Directory Access Protocol directories (which is not Active Directory)<br />· Databases<br />· Enterprise applications (such as SAP or PeopleSoft) by defining a Business Data Catalog connection<br />· Web applications<br />· Custom SharePoint web services<br />· Standard .NET applications, etc.<br /> The main classes are found in the Microsoft.Office.Server.UserProfiles namespaces. The assembly is Microsoft.Office.Server.dll found in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI.<br /> The main objects to handle information within the User Profile store are:<br /><span style="font-weight: bold;">UserProfile</span><br />Allows you to access profile properties, the My Site, personalization links, and so on.<br /><br /><span style="font-weight: bold;">UserProfileManager</span><br />Gives access to a collection of UserProfile objects and allows you to create, edit, and retrieve user profile objects and properties from the user profile store.<br /><br /><span style="font-weight: bold;">UserProfileConfigManager</span><br />Manages the user profile configuration.<br /><br /><span style="font-weight: bold;">Note</span>: In order to manage data in a custom user profile property, the property must be first created. You can use the following steps to create a profile property:<br /><br />1. Start > Administrative Tools > SharePoint 3.0 Central Administrator<br />2. In the left panel, under Shared Services Administration, click SharedServices1<br />3. Click User Profiles and Properties<br />4. Under User Profile Properties, click Add Profile Property<br />5. Fill in the required data and click OK<br /><br />Now that we know that SharePoint accepts data from external sources and that it stores individual user values in user profile properties, it’s time to put the two together and find out how to store user data in profile properties from external data sources. This is the topic for part two of this post: Getting/Storing user data from external sources.Unknownnoreply@blogger.com9tag:blogger.com,1999:blog-35928092.post-28926932501997887122008-09-04T15:50:00.002-04:002008-09-04T16:12:49.197-04:00SharePoint says "Unknown Error"<strong>ERROR: Only Content controls are allowed directly in a content page that contains Content controls.</strong><br /><br />By default, SharePoint doesn't seem willing to share some of its internal errors with developers opting instead to use a generic "Unknown Error" page. The informative <em>(and I use the term loosely)</em> error string above wasn't displayed in the browser until the file <u>C:\Inetpub\wwwroot\wss\VirtualDirectories\80\web.config</u> was modified to disable custom error messages.<br /><br />By changing <span style="color:#cc0000;"><SafeMode CallStack="false" ...></span> to <span style="color:#cc0000;"><SafeMode CallStack="true" ...></span> and changing <span style="color:#cc0000;"><customErrors mode="On" /></span> to <span style="color:#cc0000;"><customErrors mode="Off" /></span>, the generic error page is replaced with a more detailed error message and maybe even a callstack.<br /><br />As for the error above? It was caused by a comment that had been added to an .aspx file. For some reasons, comments were not allowed because they didn't qualify as "content controls".Frederic LeBelhttp://www.blogger.com/profile/01870456065216884794noreply@blogger.com9tag:blogger.com,1999:blog-35928092.post-41716782289365636042008-08-03T19:33:00.000-04:002008-08-03T19:33:01.375-04:00Performance reality check for web developersWhen I work on a web application, I usually have the luxury of running everything that I need locally on my developer machine. My browser, Web-server and database all working together without ever having to put a single packet on a real network.<br /><br />With today's web applications growing more complex and making use of asynchronous calls to the web server, this idealistic development environment makes it very difficult for the developer to assess the performance characteristics of the application. This can lead to surprises when the application is deployed to a real environment where users actually access it from remote locations.<br /><br />A good way to bring reality back to this equation is to make use of a proxy server. I like to use <a href="http://donsproxy.sourceforge.net/">Don's Proxy</a>. It is simple Java-based application that takes 1 minute to setup and lets you inject latency, errors and throttle your connection bandwidth. All of this is made in a manner that is independent of your browser or your web server. Most importantly. it does not require any changes to your application's code or setup.<br /><br />To use Don's Proxy, simply download the package, unzip and double-click the jar file. A simple GUI will open (<a href="http://sourceforge.net/project/screenshots.php?group_id=211367">screenshot</a>) that will prompt you for a port for the proxy to listen to and a host/port for the destination of your test web server. In the example screenshot, the test web server is running locally at port 8080 and the proxy is setup to listen on port 9090.<br /><br />Once the proxy is started, you just redirect your browser to the proxy's port and everything should work as before. The difference is that now, you can inject realistic network parameters like latency and bandwidth limitations. Don's Proxy also allows you to capture traffic as it goes through and perform other diagnostics without the use of a packet-sniffer.<br /><br />Hopefully, a more common use of tools like this will help curb developer enthusiasm for flashy Ajax behavior. Your users will thank you.Anonymoushttp://www.blogger.com/profile/11917210826902818268noreply@blogger.com19tag:blogger.com,1999:blog-35928092.post-71831372875628201162008-07-30T16:30:00.005-04:002008-07-31T15:44:11.654-04:00Snake On A Phone<p>For a few years now, my main task at work has been working on the firmware of an IP phone. The phone runs VxWorks on a MIPS32 CPU; the firmware is written in C and C++.<br /><br /></p><p>For slightly less time, I've been dabbling in python on my own time. Freedom from explicit typing was a refreshing change, and python's tendency to Just Work was a nice bonus.<br /><br /></p><p>It was perhaps inevitable that I would one day try to combine phone and language. (why? because they were both there)<br /><br /></p><p>It wasn't obvious that the idea stood a chance. VxWorks is a bit off the OS beaten track, and might not provide all the functionality needed by Python's "core" (not with the same names, anyway). There might be some processor-specific pieces that would rule out MIPS32. And even if I could get something built, would it fit in the 2 or 3 MB of RAM (and even less flash) I could spare?<br /><br /></p><p>As it turns out, there was very little to worry about. Python's code is impressively (if perhaps unsurprisingly) portable, only needing a couple of tweaks to its build system and none at all to its source code. There doesn't seem to be anything CPU-dependant; and in the end, adding python to my firmware only cost me 1MB. It took me only a few evenings of tinkering to get a libpython built, linked into my firmware, and loaded on my phone, to the point that I could run this little experiment at the VxWorks shell:<br /><br /></p><pre><br /> -> Py_Initialize()<br /> value = 42 = 0x2a = '*'<br /> -> PyRun_SimpleString("print 'Hello, World!'\n")<br /> Hello, World!<br /> value = 0 = 0x0<br /></pre><br /><br /><p>(the VxWorks shell being a peculiar animal that allows calling C functions by name, in this case giving me access to Python's C Extension API for a near-REPL experience)<br /><br /><br /></p><p>For my purposes, that's enough; I know it can work, and that's all I wanted. I don't expect to ever go further than this. But as little as it is, publishing how I got there might help someone get started on a real project; so here goes:<br /><br /></p><h2>Porting python in 10 easy* steps</h2><br /><br /><p>*for a suitable definition of easy<br /><br /><ol><br /><li>As far as embedding Python in an existing application (or firmware) is concerned, <a href="http://docs.python.org/api/embedding.html">Python's own documentation</a> should give you most of what you need<br /></li><p></p><li>You'll need a cross-compiling toolchain, i.e. a compiler that can be used on one platform (e.g. x86) and produces executables for use on a different platform (e.g. MIPS32). GCC is your best bet; it's what will make python's build system happiest, and there's lots of resources on getting a GCC cross-compiler working on the web, though it looks a bit daunting to me. I was fortunate in that, since I was already set up to build firmwares, I already had all the needed tools; I would guess that most people engaging on a similar project would be in the same position.<br /><br /></li><p></p><li>In addition to the compiler (and assembler, linker, etc), you'll want to have a Unix-like environment to run Python's configure script and makefiles. If you're on Windows, cygwin will serve nicely.<br /><br /></li><p></p><li>The 'configure' script needs some tweaking: it contains a few uses of AC_TRY_RUN, which will fail when cross-compiling.<br /><ul><li>If you have a working 'autoconf', the simplest is to edit the 'configure.in' file. You can either remove the AC_TRY_RUN tests altogether or replace them by the newer, more cross-compiler-friendly <a href="http://www.gnu.org/software/autoconf/manual/html_node/Runtime.html">AC_RUN_IFELSE</a>. Then run 'autoconf' to regenerate the 'configure' script.<br /></li><li> If you don't (as I didn't), you can brace yourself and go edit the 'configure' script directly. Running the script produces error messages that gives something to search for. The fix is actually simple: just remove the calls to 'exit' to allow the error to get ignored.<br /></li></ul><br /><br /></li><p></p><li>The makefile also needs tweaking: just like 'configure', at some point it tries to compile and run a program. This appears to be in order to autogenerate some source files, which fortunately are already provided in the source distribution; so it's safe to disable this step. The simplest way:<br /><ul><li>open "Makefile.pre.in"<br /></li><li>find the place where "$(PGEN)" shows up AFTER a ':'<br /></li><li>remove "$(PGEN)"<br /></li></ul><br />(this will only prevent the executable from getting built. The makefile will still attempt to run it, but it's written so that the resulting failure is ignored)<br /><br /></li><p></p><li>The configure script and makefile try to guess at the name of tools to use; you can give them a hint with environment variables. In my case I needed to set CC (the C Compiler) and AR (the "archiver", ie. what creates static libraries)<br /><br /></li><p></p><li>If you need to specify special command-line options to the compiler, environment variables can also be used. Annoyingly, 'configure' and the makefiles use different variable; you'll want to set CFLAGS and BASECFLAGS to the same thing.<br /><br /></li><p></p><li>Finally you'll be ready to run the 'configure' script. You need to give it the special options <a href="http://www.gnu.org/software/autoconf/manual/html_node/Specifying-Names.html">--build and --host</a> to tell it you're cross-compiling, something like:<br /><pre><br />$ ./configure --build=win32 --host=vxworks<br /></pre><br /><br />(win32 and vxworks were a wild guess that happened to work for me. I got the impression the specific values didn't particularly matter)<br /><br /></li><p></p><li>You can then run 'make' to compile everything. If, like me, all you need is a static library, this will do it:<br /><pre><br />$ make libpython2.5.a<br /></pre><br /><br /></li><p></p><li>There's a good chance some files under Modules/ will fail to compile (in my case, posixmodule.c). The file Module/Setup specifies (in a rather well-documented way) which Python modules (written in C) should be built into the python library; comment out the failing one, and re-run 'make'. I only had to disable posixmodule and pwdmodule; YMMV.<br /></li></ol><br /><br /><p>And for me, that was it; nothing else needed manual intervention. If you run into more troubles (e.g. trying to build the actual python.exe), I'm afraid you're on your own.<br /><br /></p><p>My next step was to figure out how to integrate the python library into my firmware; you'll have to figure out the corresponding steps for your own firmware/embedded application/whatever. Start with the <a href="http://docs.python.org/api/embedding.html">'embedding' link</a> for how to access python code from your code.<br /><br /></p><p>If you want to be able to load python source files with 'import', pay particular attention to what that page says about PYTHONHOME; as for me, I put a putenv(PYHONHOME=/whatever") before the Py_Initialize call, letting me import /whatever/python2.5/*.py files (and possibly, though I haven't tried, .py files contained in a /whatever/python2.5/libpython2.5.zip)<br /><br /></p><p>Happy cross-compiling!<br /></p>LPGhttp://www.blogger.com/profile/17088475660870758813noreply@blogger.com55tag:blogger.com,1999:blog-35928092.post-38255280102473694512008-07-24T07:00:00.001-04:002008-07-25T14:31:21.824-04:00Outlook Entry IDs Made EasyWhen developing for Outlook you will quickly realize that there's more than one way of doing things. For example, take a look at the number of APIs for interacting with Outlook:<ul><li>Outlook Object Model (OOM)</li><li>MAPI</li><li>CDO</li><li>Office/Outlook COM Add-in (_IDTExtensibility2)</li><li>Exchange Client Extensions</li></ul>That doesn't even include the six libraries included in the Outlook 2003 Integration API or the excellent 3rd-party <a href="http://www.dimastr.com/redemption/">Redemption</a> library. I'm positive there are others. Usually you won't use all these APIs in the same project. However, if you want to do anything significant in Outlook, you'll need to use the OOM and MAPI libraries.<br /><br />It's important to understand the relationship between MAPI and the OOM:<ul><li>The MAPI API dates back to the early Outlook days. It's used for the messaging and storage subsystems in Outlook.</li><li>The Outlook Object Model sits on top of MAPI and wraps a minimal amount of its functionality. It also exposes some of the Outlook UI to the developer.</li></ul>When you work with these APIs, you'll hit on the problem of linking them together. Outlook Entry IDs are a good example. Entry IDs uniquely identify most objects in the OOM and MAPI. Being very flexible, Entry IDs can take many shape or form and can cause headaches when you try to handle them.<br /><br />At its simplest, an Entry ID is a variable length byte buffer, sometimes represented with a simple byte array. In MAPI, most Entry IDs are represented by the ENTRYID structure:<h3>mapidefs.h</h3><pre>typedef struct { <br /> BYTE abFlags[4]; <br /> BYTE ab[MAPI_DIM]; <br />} ENTRYID, FAR *LPENTRYID;</pre>This structure usually comes wrapped in the SBinary structure.<h3>mapidefs.h</h3><pre>typedef struct _SBinary { <br /> ULONG cb; <br /> LPBYTE lpb; <br />} SBinary, FAR *LPSBinary;</pre>In the Outlook Object Model things take a turn for the worst:<ul><li>Most times you see Entry IDs as a BSTR that is hex encoded (i.e. the strings look like this: "000F1329EC29A0382BC...").</li><li><a href="http://blogs.msdn.com/stephen_griffin/archive/2007/07/03/you-mean-you-want-the-oom-to-actually-work.aspx">Sometimes</a> it still uses a BSTR, but it doesn't encode the buffer, instead using the BSTR as a binary blob. Although inconsistent, this is <a href="http://msdn.microsoft.com/en-us/library/ms221105(VS.85).aspx">perfectly valid</a>.</li><li>Sometimes it's useful to represent the Entry ID as a SAFEARRAY of VARIANT VT_UI1 (this is the format VB uses for its byte arrays). For example, I've needed to have a function that can return a property any type from a MAPI object that needs to be called through automation (i.e. VB). For example, the <a href="http://www.dimastr.com/redemption/utils.htm">IMAPIUtils::HrGetOneProp</a> method from the Redemption Library does this.</li></ul>Is your head spinning? Mine was.<br /><br />I solved the problem by creating a class (yet another format!) to facilitate manipulation of all these formats:<pre>class EntryId<br />{<br />public:<br /> EntryId(EntryId const& entryId);<br /><br /> // All explicit so that it's always clear what we are doing.<br /> explicit EntryId(BSTR const* str, bool hexEncoded = true);<br /> explicit EntryId(SBinary const* binary);<br /> explicit EntryId(SAFEARRAY const* array);<br /> explicit EntryId(unsigned long count, unsigned char const* bytes);<br /><br /> // Again, no implicit conversion<br /> CComBSTR toString(bool hexEncoded = true) const;<br /> CComSafeArray<VARIANT> toSafeArray() const;<br /> std::vector<unsigned char> toByteArray() const;<br /> // ... add more as you need them<br /><br /> // TODO: Add more custom helper functions.<br /> bool isLongTermId() const;<br /><br /> // TODO: Add comparison operators for convenience and ordered <br /> // container support (such as std::map keys). When comparing <br /> // Entry Ids, remember you need to use the <br /> // <a href="http://msdn.microsoft.com/en-us/library/ms530706(EXCHG.10).aspx">IMAPISupport::CompareEntryIDs</a> method.<br /> <br />private:<br /> std::vector<unsigned char> m_buffer;<br />}</pre>Now whenever I get an Entry ID in any format, the first thing I do is convert it to an EntryId instance. This adds many convenient functionalities:<ul><li>Standardized interface to all ids.</li><li>Easy comparison of entry ids.</li><li>EntryId is a copyable class and can be passed by value.</li><li>EntryId can be held in a STL container.</li><li>Your other helper classes and methods can use the EntryId as parameter instead of other formats.</li></ul>Unknownnoreply@blogger.com27tag:blogger.com,1999:blog-35928092.post-86962100277502307262008-07-23T12:14:00.003-04:002008-07-23T12:16:38.677-04:00Software Testers - Don't Underestimate Their Worth for SuccessSometimes, testing your application isn’t enough: sometimes your test cases need to be tested! Testing doesn’t always give you what you’d expect. In extreme cases, it can even give you a false sense of confidence in a product that is a complete failure.<br /><br />Recently, I was managing an offshore team developing a component for our client's core enterprise application. We wrote extensive test cases and, because we were concerned about a lack of domain knowledge, we even had architects write some of the test cases. Things were looking good as we approached the end of the development cycle: the product was behaving as it was supposed to; we were passing test cases; we were greenlighted by the QC ‘process’.<br /><br />Our confidence was high, and we were ready to move on to automated testing. Then we found the problem. It turns out that our test cases were written with a single user in mind. The minute we started to use this component with concurrent user access, the system would pretty much lock up. Our confidence evaporated.<br /><br />This was a big mistake. Architects and technical leads both reviewed the test cases. Nobody found the oversight at the time. This was compounded by an ‘if it passes the test cases then it works’ mentality.<br /><br />Unfortunately, a solution to this problem isn’t as easy as ‘follow these three steps’. But if we can take away a lesson learned from this, it is that testing the right way is not only very important to the success of a product, but it also shouldn’t be taken for granted. If you haven’t noticed, QC/QA and testers were not included in the writing of test cases, thus bypassing all kinds of valuable experience that would most likely caught our newbie mistakes.<br /><br />Bottom line - Don’t underestimate the worth of your testers and their experience, it might just come back to bite you in the future.Tonyhttp://www.blogger.com/profile/17596211212687907094noreply@blogger.com27tag:blogger.com,1999:blog-35928092.post-70147890584287826652008-07-17T23:50:00.000-04:002008-07-17T23:50:49.547-04:00Maintenance Nightmares: Commented out codeI was working on an estimate for a prospective customer, and luckily I had the code to examine beforehand to see what it was doing.<br /><br />While examining the code, I noticed code like this:<br /><br /><span style="color: rgb(0, 153, 0);">// Fix for bug 1021892</span><br /><span style="color: rgb(0, 153, 0);">// some code that was commented out.</span><br /><br />There were instances of this throughout the code.<br /><br />When I see this I instinctively cringe, I immediately think that there is no proper source control or defect tracking procedures (or tools) in place. While there may be the odd corner case where commented out code is acceptable, in general it is not and should be avoided.<br /><br />There are many better ways of dealing with this, the first way is to just delete the line of code, and when you commit/check-in the code, make sure you put a meaningful comment in the commit logs that ties it to the defect it was changed for. You can often search the commit logs, and if you put the bug id in the commit log, you will get the change in your search.<br /><br />Another easy way to do this is to delete the line of code, make a patch, and when resolving the bug in your bug tracking software, attach the patch file to that issue. Then you can always see what you changed to fix the bug.<br /><br />Does anyone else having any suggestions for this?Unknownnoreply@blogger.com16