Type Khmer Unicode Properly In Illustrator

If you are having problem typing Khmer Unicode in Illustrator,  then this post will help to fix that. The problem I encountered was that the leg doesn’t appear after type ‘j’ and the vowel some time on wrong letter. Well anyway, basically, the problem is when you type it doesn’t turn out as it supposed to be. You need to do below settings. FYI: I’m using Adobe Illustrator CC.

Step 1: Go to Edit > Preferences > Type… Then make sure that “Show Indic Options” is ticked.

screenshot.1

screenshot.2

Step 2: Click on Paragraph link to see the paragraph dialog box then click on the little menu icon on top right of the dialog and make sure that the option “Middle Easter & South Asian Every-line Composer” is ticked.

screenshot.3

With this you are good to go. :) Enjoy typing Khmer in Illustrator. If it doesn’t work please drop a comment and mention your illustrator version.

2015

Happy New Year folks!

2014 has been a bumpy year for me personally and probably generally a very bad year for many people globally.

Let’s take a look at global level. If we play a word association game, the word I instinctively associate with 2014 would be plane, disaster, tragedy. It’s been a very bad year for Malaysia Airline, Malaysia, AirAsia and an even more horrible year for the families of all the victims involved in all the major accidents happened throughout this year.  This event map pretty much clearly describe 2014. It has not been a good year. I hope that things will be better 2015.

Personally, I have my ups and downs, mostly emotionally. I went through quite a number of major changes. From working in fast pace office to working at home, from work overseas to working locally, from taking public transport to learning to ride my own motorbike. The things they say about leaving your comfort zone is not wrong. It’s a major struggle especially emotionally. I’m so used to be independent and to be in control. The changes made me lost that control and independence. I lost confidence. I lack courage. At times, I felt lost. Part of me wanting to go back to old life to my comfort zone, part of me tells me to stay build comfort zone here, part of me asking me to leave a look for else where. Now that I’m about to officially start a new life in a new year and looking back to the things I’ve been through in 2014, I felt glad that I decided to go through with it. I left my stress, pressure, and monotonous life behind and came to explore new possibility at home.

Throughout the journey, I have learnt a lot. Obviously, I’m not making as much money as I used to. Very little in comparison in fact. However, in return, I felt more alive, more at home, peace at heart. I felt more in touch and bonded with people. I guess this is probably what people meant when they choose soul over salary. I’d be a hypocrite if I say I’m contented with my little pay and lower status. It’s just that over time, I have explored that it is not some thing that I value family, heart, and happiness more highly over salary and overseas status. And money and status is some thing that I believe I can work on and earn over time regardless where I am. So I have come to accept my choice, to live with it and move forward regardless of the consequences, I will make the best of it. I do fear of judgmental opinion from peers and friends. But I have also come to strongly believe that those who judge aren’t my real friend, and my real friends do not judge. All in all, things that matter most to me is support and understanding from my family. On top of that, another thing that really open my eyes is the fact that I see many foreigners flooding Cambodia to invest and run business, while the locals are flooding out trying to find work overseas for companies. Only a handful of locals with enough vision and capital able to see the abundance of opportunity at home. Then I asked myself, why do I want to get out when everybody is coming in? Well, I think the obvious answer to most people would give is safety, security and possible higher monetary gain. People always tend to look for safe and secure environment to settle. It’s an animal instinct nature to look for more safe and secure environment to reproduce.

Regardless of their choice, I’m glad for friends who are happy with their choice to settle where they are. I can only feel sorry for friends who chose anything other being where they are happiest and live in the illusion that they are happy because they have more money. Either way, there is no real indicator of happiness. Only you yourself can tell. You can lie to everybody but not yourself. I can say I’m happy to everybody and they may or may not believe it but in my heart I always know the truth. So the good news is if you are not happy you can lie about it to everybody and people will think you are happy. It’s very long and unpredictable journey which you cannot see clearly. I’ve seen people with a good head start tumble and fall behind. I have also seen people with little or no future prospect end up doing so well in life so far. One thing that I believe for sure is that good things will come to people who constantly make decision, make changes, take action to move forward and looking for new opportunity and work hard for it. Blessing is given to people who keep trying and standing back up every time they fall.

I’m looking forward to another challenging year ahead and hoping for the best while preparing to work my hardest. And wishing all my friends and love ones another safe and healthy year.

Speed Up My Galaxy Note 3 (SM-N9005)

Well, one of the main ways (source URL) to speed up an Android Phone is basically to remove bloatwares. I haven’t got around to do it for the longest time because my phone was still under warranty and removing bloatwares required my phone to be rooted (i.e. voiding the warranty). Finally, my warranty is over and I’m finally doing it.

Phone Details
Device Name: Samsung Galaxy Note 3
Model: SM-N9005
Android version: 4.4.2
Baseband version: N9005DXUGNH1

Actions Taken

  1. Rooting my Note 3
    How-to: Root International Galaxy Note 3 SM-N9005 Runs on 4.4.2 KitKat
    Regardless of your phone model, it’s pretty simple to find root instruction on Google. I just google ‘root sm-n9005′, and got plenty of result. Your only job is just to pick out the most comprehensive instruction.
    .
  2. Install System app remover (ROOT) and Titanium Backup Pro Apps
    Basically these 2 apps helps to be able to Remove or Freeze system application/ bloatware which you are unable to do in your Application Manager. Actually, having Titanium Backup would suffice. I just happened to be using System app remover first to remove bloatware and then stumble upon Titanium Backup afterward. Another thing to note about Titanium back up is that apparently, you would need to purchase the PRO version to be able to freeze app.
    More on How-to Freeze/Remove phone app: here. or here.
    .
  3. Start Removing Those Bloatwares!!
    I know that there are a bunch of defaults apps come with Samsung but I really don’t know that there are just so many of them. So yeah, if you are not aware you would be bombarded with shock and confusion as which app should you remove/freezing. Well, don’t worry, there’s a list. Yes there’s always a list. Before looking at the list. You have to understand something about removing / freezing an app. As far as I know, removing is completely uninstalling the app, which is not so advisable if you’re not really sure what you are doing. Freezing on the other hand is safer because it’s a reversible process. So mostly I freeze the app, and only remove the ones that I’m pretty sure I’m never gonna need it. So yes the list. There quite a few lists that you may want to refer to which I did.
    – List of Bloatwares created and contributed by XDA Developers.
    Another bloatware list from XDA forum.
    Another list I found on AndroidCentral which contains some apps not listed in the ones on XDA.
    – Safely Removable System Apps on Note 3 from Androidviews.
    My Own List after referring to all above and done on my phone.
    .
  4. Stop Using TouchWiz
    If you don’t already know. TouchWiz is notoriously slow. So there are two that I would recommend – Nova Launcher Prime or Google Now Launcher. I’m using Google Now Launcher because it’s free and Nova isn’t. Also it’s simple and straight forward not so many setting and configuration like Nova. So if you like more control and customization, you might want to go for Nova.
    .

After 4 steps, my phone is so smooth and fast now. Regardless of your android device model, you can always do this just that you would probably need to Google the instruction that suites your device model. Cheers!

Opening New Chapter

It’s been a long time since I last blog. Many things have been happening so quickly that I initially found myself having no time to do and eventually just stop it and couldn’t bring myself to start again. Instead spent my free time on other activities. Anyway, 2014 has been a very turbulent year so far. Ups and downs happening so quickly. Becoming a husband, work becoming unbearable, overseas life turning very stressful, moving back home, settling in new environment. I don’t know if I have been handling it well enough or not. Either way, here I am. Back home for good. 2015 is yet another opening of a new chapter. A chapter, where I switch job and working environment. Despite the joy and relief of leaving my current job, I’m looking at a very uncertain career path ahead. Where will I be working? Will I be able to work in a new environment? Will it be better than the old one? How much will I be making? One thing for sure is that I would be making less than what I used to. All in all, I feel it would be another challenging chapter ahead in 2015 at least for the start.

New year is around the corner. What? it’s 2 month away. Well 2 months is a short time. I plan to spend this break to refresh myself mentally and physically, and prepare myself for the challenge ahead. Read books, catch up on news, go to gym, get in shape, and socialize . Basically to spend my time productively. Meanwhile also weighing my options. But obviously things will not go as planned without determination and discipline. I still have a lot distractions. Video games, TV shows, movies, YouTube.. basically entertainment that keeps you procrastinating and being lazy. So well, need to push hard for it.

Honestly, at this point, I’m still not sure what exactly I want to do. I know what I don’t want to do. Like most people I guess. Actually, I have an idea of what I think would be great however it seems not too realistic at least not in a short time. I always picture myself running business with my family members or close trusted friends. They handle sales and I take care of operations. You might think why not? go ahead do it. Or you might not possible not that easy unless you already have a lot of money. To me, those are not the issues. The main thing is I don’t see myself as the business initiator a person to go out there make vision, enforce your vision on people and build partnership. If a business were to happen it, I would be the guy recruited by my friend. I would be willing to try and be very committed to it but it’s just that I don’t see myself the one starting it. In fact I don’t even know what to start. I’m practically a cynic when it comes to business venture. I can see a millions ways that I can go wrong but all the ways that it will go right is pretty much rely on luck some time. Because of that I always dismiss pretty much any idea I had. I just don’t know how to get people together. “Hey, let’s run a business. It’s gonna be awesome.” “Okay let’s do it.” If only it were that simple.

No matter what I will do my best and hope for the best. As I always believe that as long as you work hard, you’ll survive happily. Whether the riches would come or not it’s depend some time on luck to present opportunity and our ability to seize the opportunity which some time not so easy as it sounds. We can’t always stay in comfort zone, can we? Now it’s time for me to step out of mine.

Xamarin Component: ZXing.Net.Mobile Barcode Scanner

If you are looking for a free Xamarin component for Barcode Scanner, ZXing.Net.Mobile is what you are looking for.
Get it from: https://components.xamarin.com/view/zxing.net.mobile

Problem Encountered:
I was having 1 little problem when try using ZXing.Net.Mobile barcode scanner in my code. I got the following error:

Error	1	 cannot find symbol
symbol  : class OnActionExpandListener
location: class android.support.v4.view.MenuItemCompat
		android.support.v4.view.MenuItemCompat.OnActionExpandListener
	D:\Projects\Hybrid Dev\AnacleMobile\AnacleMobile.Droid\obj\Debug\android\src\mono\android\support\v4\view\MenuItemCompat_OnActionExpandListenerImplementor.java	8	41	AnacleMobile.Droid

It turns out the problem was because ZXing.Net.Mobile requires you to reference get and add Xamarin.Android.Support.V4 into reference. And coincidentally, I have added Mono.Android.Support.V4 into reference as well and apparently, you can’t have both Mono.Android.Support.V4 and Xamarin.Android.Support.V4 as in reference. So in this case I just remove Mono.Android.Support.V4 from reference and it compiled fine.

Solution Source: URL.

Xamarin/Android: Use ViewHolder In BaseAdapter Class

I was having a lot problem with Android ListView using Adapters lately. The original implementation was horrible causing the ListView to generate a lot of duplicate item.

Purpose of Code: I had this checklist page where it supposed to load a list of checklist item from server database and populate the item into ListView on the app.

1. Original code.
Problem Description: the display is weird and it’s causing display of duplicate items here and there.

...
public override View GetView(int position, View view, ViewGroup parent)
{
    GetChecklistItem cli = checklistItems[position];

    if (view != null)
        return view;
    if (view == null)
    {
        view = context.LayoutInflater.Inflate(AnacleAndroid.Resource.Layout.ChecklistRow, null);
    }

    TextView objectName = (TextView)view.FindViewById(AndroidApp.Resource.Id.lblObjectName);
    EditText remarks = (EditText)view.FindViewById(AndroidApp.Resource.Id.checklistRemarks);
    RadioGroup radio = (RadioGroup)view.FindViewById(AndroidApp.Resource.Id.radioGroup);
    objectName.Text = cli.ObjectName;
    if (cli.ChecklistType.HasValue)
    {
        if (cli.HasSingleTextboxField == 1 || cli.ChecklistType == ChecklistItemType.Remarks || cli.ChecklistType == ChecklistItemType.SingleLineFreeText)
        {
            remarks.Visibility = ViewStates.Visible;
            remarks.Text = cli.Remarks;
            remarks.TextChanged += delegate(object sender, Android.Text.TextChangedEventArgs e)
            {
                editChecklist.RemarksTextChangedClick(sender, e, cli);
            };
        }
        else
        {
            // otherwise hide the remark control
            remarks.Visibility = ViewStates.Gone;
        }
        if (cli.ChecklistType == ChecklistItemType.Choice)
        {
            // If checklist type is a choice. Split the ResponseName string and create radio button for each response for user to select
            //radio.
            string[] noOfRb = cli.ResponseName.Split(',');
            foreach (string tempRb in noOfRb)
            {
                RadioButton newRb = new RadioButton(this.context);
                newRb.Text = tempRb;
                newRb.TextSize = 16;
                newRb.Checked = (cli.SelectedResponse != null && cli.SelectedResponse.Equals(tempRb.Trim()));
                newRb.Click += delegate(object sender, EventArgs e)
                {
                    editChecklist.RadioButtonClick(sender, e, cli);
                };
                radio.AddView(newRb, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent));
            }
        }
        else
        {
            // Otherwise hide the RadioGroup control
            radio.Visibility = ViewStates.Gone;
        }
    }
    return view;
}
...

After Googling around, I found some answers. It has something to the Android always repainting the ListView. So I have to have a a way to store the control without the android having to look up for control every time it trigger the GetView(…). And the answer is ViewHolder. For more details please refer to this URL.

2. Fix 1 Using ViewHolder
Problem Description: 
The dynamic radio button keep duplicating like crazy every time user scroll up or down.

// ViewHolder Class
private class ViewHolderItem : Java.Lang.Object
{
	public TextView ObjectName;
	public EditText Remarks;
	public RadioGroup Options;
}
...
public override View GetView(int position, View view, ViewGroup parent)
{
	ViewHolderItem viewHolder;
	
	if (view == null)
	{
		view = context.LayoutInflater.Inflate(AnacleAndroid.Resource.Layout.ChecklistRow, null);
		viewHolder = new ViewHolderItem();
		viewHolder.ObjectName = (TextView)view.FindViewById(AnacleAndroid.Resource.Id.lblObjectName);
		viewHolder.Remarks = (EditText)view.FindViewById(AnacleAndroid.Resource.Id.checklistRemarks);
		viewHolder.Options = (RadioGroup)view.FindViewById(AnacleAndroid.Resource.Id.radioGroup);

		view.Tag = viewHolder;
	}
	else
	{
		viewHolder = (ViewHolderItem)view.Tag;
	}
	
	GetChecklistItem cli = checklistItems[position];
	
	if (cli != null)
	{
		viewHolder.ObjectName.Text = cli.ObjectName;
		viewHolder.ObjectName.Tag = cli.ObjectID;
		viewHolder.Remarks.Visibility = ViewStates.Visible;
		viewHolder.Options.Visibility = ViewStates.Visible;

		if (cli.ChecklistType.HasValue)
		{
			if (cli.HasSingleTextboxField == 1 || cli.ChecklistType == ChecklistItemType.Remarks || cli.ChecklistType == ChecklistItemType.SingleLineFreeText)
			{
				viewHolder.Remarks.Visibility = ViewStates.Visible;
				viewHolder.Remarks.Text = cli.Remarks;
				viewHolder.Remarks.TextChanged += delegate(object sender, Android.Text.TextChangedEventArgs e)
				{
					editChecklist.RemarksTextChangedClick(sender, e, cli);
				};
			}
			else
				viewHolder.Remarks.Visibility = ViewStates.Gone;
		}

		if (cli.ChecklistType == ChecklistItemType.Choice)
		{
			//radio.
			string[] noOfRb = cli.ResponseName.Split(',');

			foreach (string tempRb in noOfRb)
			{
				RadioButton newRb = new RadioButton(this.context);
				newRb.Text = tempRb;
				newRb.TextSize = 16;
				newRb.Checked = (cli.SelectedResponse != null && cli.SelectedResponse.Equals(tempRb.Trim()));
				newRb.Click += delegate(object sender, EventArgs e)
				{
					editChecklist.RadioButtonClick(sender, e, cli);
				};
				viewHolder.Options.AddView(newRb, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent));
			}
		}
		else
			viewHolder.Options.Visibility = ViewStates.Gone;
	}
	
	return view;
}
...

So then I tried moving the value and assignment and radio button creation into the view building if section.

3. Fix 2 Using ViewHolder
Problem Description: Yay! the radio button duplication problem disappears. However, another problem pops out right away. It turns out this fix causes the listview to display not in order of the item list stored. And the order keeps getting messed up every time I scroll up or down.

// ViewHolder Class
private class ViewHolderItem : Java.Lang.Object
{
	public TextView ObjectName;
	public EditText Remarks;
	public RadioGroup Options;
}
...
public override View GetView(int position, View view, ViewGroup parent)
{
	ViewHolderItem viewHolder;
	GetChecklistItem cli = checklistItems[position];
	if (view == null)
	{
		view = context.LayoutInflater.Inflate(AnacleAndroid.Resource.Layout.ChecklistRow, null);
		viewHolder = new ViewHolderItem();
		viewHolder.ObjectName = (TextView)view.FindViewById(AnacleAndroid.Resource.Id.lblObjectName);
		viewHolder.Remarks = (EditText)view.FindViewById(AnacleAndroid.Resource.Id.checklistRemarks);
		viewHolder.Options = (RadioGroup)view.FindViewById(AnacleAndroid.Resource.Id.radioGroup);
		
		if (cli != null)
		{
			viewHolder.ObjectName.Text = cli.ObjectName;
			viewHolder.ObjectName.Tag = cli.ObjectID;
			viewHolder.Remarks.Visibility = ViewStates.Visible;
			viewHolder.Options.Visibility = ViewStates.Visible;

			if (cli.ChecklistType.HasValue)
			{
				if (cli.HasSingleTextboxField == 1 || cli.ChecklistType == ChecklistItemType.Remarks || cli.ChecklistType == ChecklistItemType.SingleLineFreeText)
				{
					viewHolder.Remarks.Visibility = ViewStates.Visible;
					viewHolder.Remarks.Text = cli.Remarks;
					viewHolder.Remarks.TextChanged += delegate(object sender, Android.Text.TextChangedEventArgs e)
					{
						editChecklist.RemarksTextChangedClick(sender, e, cli);
					};
				}
				else
					viewHolder.Remarks.Visibility = ViewStates.Gone;
			}

			if (cli.ChecklistType == ChecklistItemType.Choice)
			{
				//radio.
				string[] noOfRb = cli.ResponseName.Split(',');

				foreach (string tempRb in noOfRb)
				{
					RadioButton newRb = new RadioButton(this.context);
					newRb.Text = tempRb;
					newRb.TextSize = 16;
					newRb.Checked = (cli.SelectedResponse != null && cli.SelectedResponse.Equals(tempRb.Trim()));
					newRb.Click += delegate(object sender, EventArgs e)
					{
						editChecklist.RadioButtonClick(sender, e, cli);
					};
					viewHolder.Options.AddView(newRb, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent));
				}
			}
			else
				viewHolder.Options.Visibility = ViewStates.Gone;
		}

		view.Tag = viewHolder;
	}
	else
	{
		viewHolder = (ViewHolderItem)view.Tag;
	}
	
	return view;
}
...

Solution Description: The problem again turns out to have something to do with the repainting of the android ListView during scrolling. The value setting and building of radio buttons has to be after the view initialization if-else. So then I figured it out! Since the view is stored means the radio button created dynamically added into the RadioGroup will also be stored. Then if the scrolling causing the repainting calling the GetView again it will trigger another another radio button creation and add into RadioGroup without removing the previous Radio button. So the magic was just to clear all child view in the Options RadioGroup before adding the Radio Button.

4. Final Fix Using ViewHolder. (Full Code)

public class ChecklistAdapter : BaseAdapter<GetChecklistItem>
{
    private class ViewHolderItem : Java.Lang.Object
    {
        public TextView ObjectName;
        public EditText Remarks;
        public RadioGroup Options;
    }

    List<GetChecklistItem> checklistItems;
    Activity context;
    EditChecklist editChecklist;
    
    public ChecklistAdapter(Activity context, List<GetChecklistItem> newList) : base()
    {
        this.context = context;
        this.checklistItems = newList;
        editChecklist = (EditChecklist)context;
    }
    public override long GetItemId(int position)
    {
        return position;
    }
    public override GetChecklistItem this[int position]
    {
        get { return checklistItems[position]; }
    }
    public override int Count
    {
        get { return checklistItems.Count; }
    }

    public override View GetView(int position, View view, ViewGroup parent)
    {
        ViewHolderItem viewHolder;

        if (view == null)
        {
            view = context.LayoutInflater.Inflate(AnacleAndroid.Resource.Layout.ChecklistRow, null);
            viewHolder = new ViewHolderItem();
            viewHolder.ObjectName = (TextView)view.FindViewById(AndroidApp.Resource.Id.lblObjectName);
            viewHolder.Remarks = (EditText)view.FindViewById(AndroidApp.Resource.Id.checklistRemarks);
            viewHolder.Options = (RadioGroup)view.FindViewById(AndroidApp.Resource.Id.radioGroup);

            view.Tag = viewHolder;
        }
        else
        {
            viewHolder = (ViewHolderItem)view.Tag;
        }

        GetChecklistItem cli = checklistItems[position];

        if (cli != null)
        {
            viewHolder.ObjectName.Text = cli.ObjectName;
            viewHolder.ObjectName.Tag = cli.ObjectID;
            viewHolder.Remarks.Visibility = ViewStates.Visible;
            viewHolder.Options.Visibility = ViewStates.Visible;

            if (cli.ChecklistType.HasValue)
            {
                if (cli.HasSingleTextboxField == 1 || cli.ChecklistType == ChecklistItemType.Remarks || cli.ChecklistType == ChecklistItemType.SingleLineFreeText)
                {
                    viewHolder.Remarks.Visibility = ViewStates.Visible;
                    viewHolder.Remarks.Text = cli.Remarks;
                    viewHolder.Remarks.TextChanged += delegate(object sender, Android.Text.TextChangedEventArgs e)
                    {
                        editChecklist.RemarksTextChangedClick(sender, e, cli);
                    };
                }
                else
                    viewHolder.Remarks.Visibility = ViewStates.Gone;
            }

            if (cli.ChecklistType == ChecklistItemType.Choice)
            {
                //radio.
                string[] noOfRb = cli.ResponseName.Split(',');
				
				// important to remove all vew under the view group before repopulating it
                if (viewHolder.Options != null && viewHolder.Options.ChildCount > 0)
                    viewHolder.Options.RemoveAllViews();

                foreach (string tempRb in noOfRb)
                {
                    RadioButton newRb = new RadioButton(this.context);
                    newRb.Text = tempRb;
                    newRb.TextSize = 16;
                    newRb.Checked = (cli.SelectedResponse != null && cli.SelectedResponse.Equals(tempRb.Trim()));
                    newRb.Click += delegate(object sender, EventArgs e)
                    {
                        editChecklist.RadioButtonClick(sender, e, cli);
                    };
                    viewHolder.Options.AddView(newRb, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent));
                }
            }
            else
                viewHolder.Options.Visibility = ViewStates.Gone;
        }
        
        return view;
    }

    public override void NotifyDataSetChanged()
    {
        base.NotifyDataSetChanged();
    }
}

CSS: Full Browser’s Width Bar

Source: http://css-tricks.com/full-browser-width-bars/

Below are pretty much the main CSS code. For more details, please refer to the source.
To change original color. You can just update the background.

h2 {
  position: relative;
  background: black; 
}
h2:before, h2:after {
  content: "";
  position: absolute;
  background: black;  /* Match the background */
  top: 0;
  bottom: 0;
  width: 9999px;   /* some huge width */
} 
h2:before {
  right: 100%; 
}
h2:after {
  left: 100%;
}

html, body {
    overflow-x: hidden;
}