Illustrator Time Saver Tip: Paste Remembers Layers

I always love organizing my Illustrator design with layers and symbols, with the right hierarchy of layering, I can easily move or transform any groups of art.  One thing keeps baffling me is that every time I copy and paste layers of art, Illustrator would flatten all the layers.  This is like removing all the folders and shelves which help neatly partition the papers.

It was not until today I came to realized that Illustrator does provide an option to retain the layers, the option is named “Paste Remembers Layers”.  It can be activated through clicking on the option menu of the Layer panel.

I wonder if Adobe has any reason not turning this option on by default, but in case anyone from Adobe cares, please … this saves time and lives.

 

Update:  There is one major drawback of the “Paste Remembers Layers” option – any paste executed would be pasted as top-level layer.  In other words, if one wishes to paste a set of layers inside another layer, one would have to paste and then move the newly-pasted top-level layers into the desired layer.  Rats.

Image

Greyed out files in Mac OS/X

I have long been baffled by a particular external hard drive of mine which consist a few random files which are greyed out.  I cannot see any abnormality via File Info in Mac or Windows, and most Google search returned solutions that don’t work at all.  Worst of all, if I try to “hack” it by moving the file to another location, I end up losing the file entirely!

Finally, a little digging in “Terminal” using ls -la command, I discovered those greyed out files having an attribute of -rwxrwxrwx@, ah ha, the “@” might be all the culprit.  Eventually I found out that stands for extended properties.  And to view the extended properties, I just need to use xattr -l filename command.  In my case, the greyed out files all have this weird com.apple.FinderInfo attribute.  To remove that attribute, I run xattr -d com.apple.FinderInfo filename, and the file is back to normal!

Infographics and Visualization for people who “give a damn” from Good

Good.is, not to be confused with other “Good”, has collected a lot of good infographics over time. Some of them are interactive with a data backend, but more are pre-drawn visualizations. No matter how they are technically or artistically prepared, lots of inspirations can be drawn from them as they tell a better story than just a pie chart or d3js chart alone.

http://www.good.is/infographics

Robotlegs, Mediator and PopupManager

Recently I have shifted my framework of preference from Cairngorm to Robotlegs. Cairngorm has been my choice of framework mainly because it has a large user-base support, so I can point developers to learn the framework on their own. Cairngorm has its limitation, and the one gives me the most heartburn is singleton model, which makes the code difficult to write unit test for.

Just a few hours of reading this awesome book ActionScript Developer’s guide to Robotlegs, I am sold. Within a short time, I am able to rewire up a Cairngorm-based applications into Robotleg’s fashion. Mediator in Robotlegs is an awesome designer. Without Mediator, my control’s container would have to know how to pass data and events back and forth. It gets cumbersome when there are layers of containers. Mediator mapping relies on listening the control’s ADDED_TO_STAGE event, then maps the control to the mediator class. However, the event listening is done on the context root of the Robotleg’s configuration. In a Flex application, typically the context root is set to the Application itself like the following

<s:Application 
			   xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:context="myapp.context.*">


	<fx:Declarations>
		<context:TabletApplicationContext contextView="{this}" />
	</fx:Declarations>

	...
</s:Application>

This works great in most cases because all the controls are usually added to the display tree of the Application, therefore the context is able to capture the control added event. However, when a control is introduced by PopupManager or Callout component, the control is not added to the application but application’s parent, therefore the event is not captured by the context.

There has been discussions and samples to work around this problem. The solutions most discussed would use “Command” to perform the Popup instead of the component itself. This gives me a heartburn because Command is NOT supposed to interfere with UI implementation.

The Solution
Since the cause of the issue is the context is not able see the popup added simply because the popup is added outside the contextView, my solution is to find out what that “outsider” is. A quick dig around of PopupManager’s implementation I found out it uses application’s systemManager as the place to add the popup control. So I quickly implemented the solution below:

	<context:TabletApplicationContext contextView="{DisplayObjectContainer(this.systemManager)}" />

But it does not work as somehow the context is not instantiated. That’s when the contextView is assigned, the systemManager is not added to the stage and the application is not ready. That’s not too obvious, but we can always delay the contextView assignment until the application’s creationComplete event is fired. So I modify my application as follows:

<s:Application creationComplete="initContext();" 
			   xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:context="myapp.context.*">


	<fx:Declarations>
		<context:TabletApplicationContext id="context" />
	</fx:Declarations>

	<fx:Script>
		<![CDATA[
			
			private function initContext():void
			{
				//Use systemManager as contextView so popups instantiated by PopupManager would be wired up properly
				var contextView:DisplayObjectContainer = systemManager as DisplayObjectContainer;
				context.contextView = contextView;
			}
			
			
		]]>
	</fx:Script>

	...
</s:Application>

Since then, the mediator is happily working with the popup control ever after!

Robotlegs 2
I read in the forum posts that the upcoming Robotlegs 2 is supposed to alleviated this pain. I will follow up with a post once I get RL2 and popup working with my new application.

Vectors in ActionScript 3

Vector class is a strongly-typed array implementation in ActionScript 3.  There are lots of blog posts or Stackoverflow posts related Vector, I am simply aggregating a few I have found useful

1. How to instantiate a Vector type with values?

var vec:Vector.<Number> = new <Number> [1.0, 1.0];

(Credit: Stackoverflow.com)

2. What kind of performance advantage Vector has over Array?
Answer: A lot, and each iteration of Flash Player may have different merits. The latest result shows Vector has more than a 100% speed advantage over Array.
(Credit: ActionScript performance test for Array, Object, Vector literals and Array.push, Vector.push methods)

3. Any drawback of Vector?
Answer: One drawback I see so far is Vector has no AMF equivalent. If you don’t know what AMF is or would not use Vector to transfer data back and forth to server, then you don’t have to worry. Otherwise, a work-around would be translate Vector to Array or ArrayCollection at transport. This little overhead is minimal as it only occurs at transport. I would strongly recommend anyone use Vector as much as possible.

Another drawback of Vector would be that it is a primitive type like Array, therefore it lacks sophisticated events notifying change of a Vector. Though the latest Apache Flex 4.9 has VectorList and VectorCollection implementation, the implementation offers little or adversed performance advantage, and I would not advise using VectorList/VectorCollection just yet.

Prevent SQL Server from Caching Results

SQL Server has an advantage of caching results of executed queries, so when an expensive query is executed, the server only takes the heaviest hit during the first execution, any subsequent execution would take significantly less hit.

Such approach, however, could make SQL tuning job difficult, because it is hard to know if the tuning actually works faster or it is the caching that does the magic. However, with caching is disabled, the tuning may become apparent. This could be achieved with the following snippet:

DBCC DROPCLEANBUFFERS; 
GO

Note that CHECKPOINT could be “harmful” if abused in Production environment, so the above is only recommended in development environment.

Export Outlook Mails into Excel

Once in a blue moon I have a need to analyze emails in my Outlook, I would need to get my emails into structural data so I could run my analysis and statistics. I have come across this article, and thought I would re-post it with abridged steps.

  1. Start Outlook
  2. Hit ALT-F11, and Visual Basic for Applications should show
  3. Choose Insert -> Module
  4. Copy and Paste the following source code into the Edit
  5. Choose Tools -> References, and make sure that Microsoft Excel is part of the reference
  6. Hit F5 and Run, pick the folder you wish to Outlook export the mails from
' The source code is adopted from
' http://www.techrepublic.com/blog/msoffice/quickly-export-outlook-e-mail-items-to-excel/744
Sub ExportToExcel()
    On Error GoTo ErrHandler
    
    Dim appExcel As Excel.Application
    Dim wkb As Excel.Workbook
    Dim wks As Excel.Worksheet
    Dim rng As Excel.Range
    Dim strSheet As String
    Dim strPath As String
    Dim intRowCounter As Integer
    Dim intColumnCounter As Integer
    Dim msg As Outlook.MailItem
    Dim nms As Outlook.NameSpace
    Dim fld As Outlook.MAPIFolder
    Dim itm As Object
    
    strSheet = "OutlookItems.xlsx"
    strPath = "c:\"

    strSheet = strPath &amp; strSheet
    Debug.Print strSheet

    'Select export folder
    Set nms = Application.GetNamespace("MAPI")
    Set fld = nms.PickFolder

    'Handle potential errors with Select Folder dialog box.
    If fld Is Nothing Then
        MsgBox "There are no mail messages to export", vbOKOnly, "Error"
        Exit Sub
    ElseIf fld.DefaultItemType  olMailItem Then
        MsgBox "There are no mail messages to export", vbOKOnly, "Error"
        Exit Sub
    ElseIf fld.Items.Count = 0 Then
        MsgBox "There are no mail messages to export", vbOKOnly, "Error"
        Exit Sub
    End If

    'Open and activate Excel workbook.
    Set appExcel = CreateObject("Excel.Application")
    appExcel.Workbooks.Open (strSheet)
    Set wkb = appExcel.ActiveWorkbook
    Set wks = wkb.Sheets(1)
    wks.Activate
    
    appExcel.Application.Visible = True
    'Copy field items in mail folder.
    For Each itm In fld.Items
        intColumnCounter = 1
        Set msg = itm
        intRowCounter = intRowCounter + 1
        Set rng = wks.Cells(intRowCounter, intColumnCounter)
        rng.Value = msg.To
        intColumnCounter = intColumnCounter + 1
        Set rng = wks.Cells(intRowCounter, intColumnCounter)
        rng.Value = msg.SenderEmailAddress
        intColumnCounter = intColumnCounter + 1
        Set rng = wks.Cells(intRowCounter, intColumnCounter)
        rng.Value = msg.Subject
        intColumnCounter = intColumnCounter + 1
        Set rng = wks.Cells(intRowCounter, intColumnCounter)
        rng.Value = msg.SentOn
        intColumnCounter = intColumnCounter + 1
        Set rng = wks.Cells(intRowCounter, intColumnCounter)
        rng.Value = msg.ReceivedTime
    Next itm
    Set appExcel = Nothing
    Set wkb = Nothing
    Set wks = Nothing
    Set rng = Nothing
    Set msg = Nothing
    Set nms = Nothing
    Set fld = Nothing
    Set itm = Nothing
    
    Exit Sub
ErrHandler:      If Err.Number = 1004 Then
        MsgBox strSheet &amp; " doesn't exist, please create a empty spreadsheet at the location before running this Macro", vbOKOnly, "Error"
    Else
        MsgBox Err.Number &amp; "; Description: ", vbOKOnly, "Error"
    End If
    
    Set appExcel = Nothing
    Set wkb = Nothing
    Set wks = Nothing
    Set rng = Nothing
    Set msg = Nothing
    Set nms = Nothing
    Set fld = Nothing
    Set itm = Nothing
End Sub
Follow

Get every new post delivered to your Inbox.

Join 356 other followers