Posted on

XML attribute comparing utility

I work with XML a lot, specifically SDXML which is what we use to describe documents in the Silicon Designer online document editing application. I often have to compare the attributes of two elements to check for what has changed. Sometimes, I’m not checking the same document, so the content could be wildly different but there will still be nodes in the XML that have specific attributes of interest. I built a basic tool to open two XML documents side by side and select an element for each file and compare the attributes of the selected nodes.

It doesn’t allow editing or a report of any kind. It doesn’t show the content of the nodes. It doesn’t let you see more than one node at a time. This is all by design for the minimum viable product. Perhaps it will save someone else some debugging time.

http://www.theflexguy.com/tools/xmldiff/

I’ll be updating it over time to streamline the workflow as much as possible.

Posted on

Adding Bookmarks in Flash Builder

A while ago, I wrote this post (Using SourceMate 3.0 to create code bookmarks). While poking around in the Flash Builder preferences, I came across some references to the Bookmarks view. It turns out, this feature has been there all along.

To show the view

Go to Window > Show View > Other… and choose General > Bookmarks. This will show the view in the bottom pane.

To add a bookmark

When on a line of code, go to Edit > Add Bookmark… By default, this does not have a shortcut key.

To add a shortcut key combo

Go to Preferences, General > Keys. Scroll down a little to Add Bookmark. In the Binding input, you can add a key combo that works for you. I’m on a Mac and alt/option+B was available and easy to remember.

It even allows you to name the bookmarks, which is nice.

Posted on

How to create a default date range for google search

Something I have been wanting a LONG time has been the ability to set my google searches to default to Past Year. Since I do a lot of software related searches, results from 5 years ago are usually irrelevant.

I did a search on the structure of google search urls and found this post: http://www.our-picks.com/archives/2007/01/30/google-search-urls-revealed-or-how-to-create-your-own-search-url/

Here’s how to set up Chrome to use the past year as your default search range:

  1. Go to settings.
  2. Under the Search heading, click the Manage Search Engines… button.
  3. Scroll to the bottom of the page, so you see the 3 fields for entering your own search engine.
  4. Put these in the three fields: (view the UPDATE below to simplify the third field)
    1. GoogleYear
    2. search.google.com
    3. {google:baseURL}search?q=%s&as_qdr=y&{google:RLZ}{google:acceptedSuggestion}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}ie={inputEncoding}
  5. Click the “Make default” button that appears at the end of the row you just made.
  6. Click DONE and you’re set. Now your omnibox will always default search results to the past year unless you change it the usual way from the Search Tools at the top of the results page.

For other browsers, you can do something similar with a bookmark to the following: http://www.google.com/search?as_qdr=y or by setting up a custom search engine similarly.

Enjoy!

UPDATE

There is a much simpler url you can use now. Try using this in field 3:

https://www.google.com/search?tbs=qdr:y&q=%s

Replace the y (for year) with d for day, w for week or m for month if you prefer a different range. Thanks Kusa for the comment that pointed this out!

Posted on

Using SourceMate 3.0 to create code bookmarks

Something I’ve been wanting for a while was a slick way to have “bookmarks” in my code to help me jump quickly to certain places in the source files. It’s not uncommon for me to have a long list of files open in Flash Builder. Some files are unnecessarily large, with far more functions than should be there. These problems are something we are all guilty of at one point or another.

I recently installed the trial version of SourceMate 3.0 from Element River. It’s got a ton of productivity enhancements for Flash Builder 4.5+. It doesn’t have a bookmarks feature, but what does it does have is task tags. I really like this feature in general but I found it can be used to create bookmarks.

  1. I created a new tag “BKMK” in the SourceMate tags preferences (Preferences > SourceMate > TaskTags).
    Add “BKMK” task tag

    Now, when I add a comment that starts with BKMK, it will show up in the tasks view.
    // BKMK Place where I go to often

  2. Then, using the menu for the tasks view, I showed a new view and named it Bookmarks.

    Create a new Tasks view
  3. I chose Configure Contents… from the menu and created a new configuration called Bookmarks. For that configuration, I added Text: contains BKMK.

    Create new Bookmarks configuration
  4. Leaving that dialog and returning to the Flash Builder window, I chose Show > Bookmarks for that tasks view and viola, this Bookmarks view will always show the list of BKMK items I’ve placed inline in my code.

    Show Bookmarks configuration in the new view

This requires adding lines to the source code, so unlike breakpoints, it requires modification but can still be a pretty good workaround for the time being.

Posted on

Jenkins, Windows Server 2008 R2 and Git with SSH

The team I’m on have been using Hudson for our builds for quite a while and really like it. A while back, something went terribly wrong and Hudson, well, let’s just say he passed away. We tried and tried to bring him back but after a week of doing all we could, we had to call the time of death.

This was a new beginning though, because we could move over to Jenkins and be one of the modern cool kids. Yeah, not quite as plug-and-play as we hoped. We spent many days trying to get it to work. Through the process, we hit about every error it can spit out. I’ll try to detail what we ran into and how we solved it (to the best of my memory) in another post, if I have the time. In this post, I’ll just summarize the final solution in hopes it will help someone else out there.

Our environment

We’re running Windows 2008 R2 Datacenter SP1 on a virtual machine in Amazons Cloud. Our repository is hosted at codesion.com. After looking around the web for solutions to the errors I ran into, I wished we used GitHub since it seems like EVERYONE else out there does. That’s what most of the solutions are for. Luckily, codesion has enough on their site for me to wrap my head around what I needed to do. We have Git Bash installed on the server.

Install Jenkins

Do everything under the same account from now on, as long as you’re getting Jenkins all configured. Let’s say you’ve created a unique account for Jenkins so your team can all log in to the same account when working on Jenkins. That username is jenkinsuser for the examples here. Once that user is all set up, you can install the Jenkins application. This part is pretty straight forward so I won’t go into detail.

Set the HOME environment variable

Make sure the HOME environment variable is set to the jenkinsuser User directory. I’m actually not entirely sure it wasn’t in our case, but I saw some posts that stated it doesn’t do it automatically.

Create SSH Keys

This was the biggest stumbling block for me. We spent forever trying to get it to authenticate correctly. So, to summarize, you start Git Bash and follow the instructions here: https://help.github.com/articles/generating-ssh-keys. Don’t set a passphrase! It will save you time and frustration later.

In that github link, it talks about supplying your public SSH key. In codesion, this is under My Settings > SSH Keys. Then, go to the projects tab and click on the project you’re going to be building with Jenkins. On the right, is a services section where you can expand Git and see the ssh url. Copy this down because you’ll need it for Jenkins. It will probably say something like ssh://git_mydomain@mydomain.git.codesion.com/myproject.git.

Configure Jenkins

In Jenkins, you can now set up your project to connect to your git repo for builds. Under the project configuration, there will be a Source Code Management section. Choose Git and paste the ssh url from earlier into the Repository URL field. In the Build section, I just added a Windows batch command of echo HEY, I’M BUILDING, FINALLY!... That’s just so you can see that it got to that point and all was well. If you’re lucky, you can click SAVE and then build now and it will work. Check the Console of the build to see errors.

I wasn’t lucky. I ran into some other issues. The first, was that when I went to Manage Jenkins > Configure Jenkins, then scrolled down to the Git section, it had git.exe as the path to Git executable. I had to change this to the full path, despite what one blog post cautioned against.

The final one, that may have been what fixed many of the other issues, was to install the Jenkins git plugin instead of the Hudson version it comes with. Not sure why that isn’t default, but whatever. You can go to Manage Jenkins > Manage Plugins and choose the Installed tab. You should see your Git plugin there. Uncheck the check box to disable it. Restart Jenkins so it’s happy. Then, go here: http://updates.jenkins-ci.org/download/plugins/git/ to download the latest git.hpi file.

Go back to Jenkins then and to the Manage Plugins area, to the Advanced tab. There you’ll see where you can upload the file you just downloaded. Once it’s installed, you’ll have to back to that page, to the Installed tab and enable the plugin. Then back to the configure page for your project and enter the ssh url into the Git section again. This fixed it for me.

I hope this helps someone else out there. I’d love to save someone days or weeks of banging their head against a wall.

Posted on

New position, new learnings

Silicon Publishing logoI’ve landed a new job with Silicon Publishing Inc. Silicon Publishing creates custom InDesign solutions for companies. I’ve been working on a web to print designer tool over the last 6+ months that will allow users to create custom photobooks, cards, envelopes, and other custom print products.

It’s been a great learning experience so far. I’ve learned a lot about working with TLF, images, sizing, template information generated from InDesign documents and more. I’ve used far more math than I ever thought I’d use in a lifetime. It’s allowed me to be creative in many new ways.

I’ve had to solve a lot of problems that were quite tough for me at the time until I wrapped my head around it. I suppose that’s how most problems are. Once you get the solution, you think “wow, I can’t believe it took me that long to get to such a simple solution.”

It’s been a little over a year since I blogged last. I’m not a very consistent blogger as you may have noticed. I’d like to start posting things I learn and problems I solve. We’ll see how that goes.

Posted on

More thoughts on caching in Flex

As I discussed previously, caching can have it’s advantages.  It makes referencing objects and binding much more straight forward.  Unfortunately, it comes at a performance cost.  Since I’ve been using caching, there are some important things to keep in mind when you use caching to make sure your data sticks around and your performance doesn’t suffer any more than it has to. Continue reading More thoughts on caching in Flex

Posted on

ArrayCollection contains() uses your sort!

Here’s another gotcha that took me a while to realize what was wrong.

I was using an ArrayCollection to hold a collection of items. I had a custom sort applied since the items were typed objects that needed to be sorted according to certain, out-of-the-ordinary fields. In the sort method, I was comparing values and returning either -1 or 1.

return itemA > itemB ? -1 : 1;

From the docs for a compareFunction:

The method used to compare items when sorting. If you specify this property, Flex ignores any compareFunction properties that you specify in the ISortField objects that you use in this class.

The compare function must have the following signature:

         function [name](a:Object, b:Object, fields:Array = null):int

This function must return the following value:

  • -1, if the Object a should appear before the Object b in the sorted sequence
  • 0, if the Object a equals the Object b
  • 1, if the Object a should appear after the Object b in the sorted sequence

To return to the internal comparision function, set this value to null.

I decided that instead of returning 0 if they were the same, I would just let it stick it below the item. No big deal.

Later, when checking to see if an item was selected, I used the contains() method to see if an item was in the ArrayCollection. I quickly noticed that it wasn’t finding my item, even when I knew it was in the list.  Stepping through the code, and diving in to the Flex framework classes, I found that the contains() method uses the custom sort compare method to compare the item you’re looking for with the items in the list. It determines it found the item when it gets 0 back from the compare function. Since my custom compare method never returned 0, it never found the item.

Knowing this also helped me optimize the compare method for finding items.  Instead of thinking just in terms of whether one item goes before or after another item (or at the same level), I could also think about the comparisons in terms of checking to see if itemA was itemB.

Posted on

Don’t forget the down state

I have been immersed in Flex 4 lately and had this issue come up.  It seems like it might be fairly easy to run into and isn’t entirely obvious at first so I’ll share.  I had a custom component that included buttons that weren’t registering click events.

Here’s the scenario.  I created a custom component that contained a background rectangle for highlighting, a label to display the name of the item, a toggle button for expanding the item and a button for editing the item.  I won’t get into the specifics of what this component is for, but just stick to the high level concept.

[ [expandBtn:ToggleButton] [labelDisplay:Label] [editBtn:Button] ]

The component had a number of states:

[SkinState("up")]
[SkinState("over")]
[SkinState("down")]
[SkinState("upAndSelected")]
[SkinState("overAndSelected")]
[SkinState("downAndSelected")]

This is similar to the ToggleButton component in the SDK but didn’t need the disabled state.  I created mouseEvent handlers to take the rollOver, rollOut, mouseDown, mouseUp and click events so I could handle them appropriately, setting properties for the getCurrentSkinState() method to use and setting invalidateSkinState() after changing the properties.

In the components up state, I wanted just the label to show and then when the user hovers over the component, the expand and edit buttons show.  Using states, this is simple enough to accomplish in the skin for the component:

<s:states> <s:State name="up" /> <s:State name="over" stateGroups="overStates" /> <s:State name="down" stateGroups="downStates" /> <s:State name="upAndSelected" stateGroups="selectedStates" /> <s:State name="overAndSelected" stateGroups="overStates, selectedStates" /> <s:State name="downAndSelected" stateGroups="downStates, selectedStates" /> </s:states> ...
<s:ToggleButton id="expandBtn" includeIn="overStates" .../>
<s:Label id="labelDisplay" ... />
<s:Button id="editBtn" includeIn="overStates" .../>

The ellipses indicate additional code that is irrelevant.

I added the click handlers for the buttons in the custom component so I could capture the clicks and dispatch my own custom event.

So this starts out looking fine.  The buttons show up when the mouse is hovered.  Great.  I click on the edit button and… nothing.  The click handler is never called.  Do you see why?

Hint: Because events like clicks travel the displayList, the surrounding component will react to the clicks of the buttons inside it too.

Ok, here’s the chain of events:

  1. The user presses the mouse button down over the edit button.
  2. The edit button gets the mouseDown and enters it’s down state (if it has one).
  3. The surrounding component gets the mouseDown and changes it’s skin state to the down state.
  4. The edit button is not included in the down state, so it is removed.
  5. The user releases the mouse button.
  6. The surrounding component gets the mouseUp and returns to the over state.
  7. The edit button is included in the over state so it appears again.

Since the edit button wasn’t included in the down state, it never had a chance to react to a click event.  Click events occur when the user presses and releases the mouse button over a component and the edit button was not around for that whole chain of events.

Solution: Add the buttons into the downStates so they exist during the entire click action.  Problem solved.