//----< button click handler >------------------------------------------------
        private void btnDelRemote_Click(object sender, RoutedEventArgs e)
        {
            if (remoteListView.SelectedItems.Count == 0)
            {
                MessageBox.Show("No file selected!", "Open", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            var item = remoteListView.SelectedItem;

            if (item.GetType() == typeof(FileDirItem))
            {
                FileDirItem fileDirItem = (FileDirItem)item;

                if (fileDirItem.Name == "..")
                {
                    MessageBox.Show("No file selected!", "Open", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }

                String filePath = currentRemoteDir + "\\" + fileDirItem.Name;
                String msg;
                if (fileDirItem.isFolder)
                {
                    msg = "DelDir," + filePath;
                }
                else
                {
                    msg = "DelFile," + filePath;
                }

                shim.PostMessage(msg);
            }
        }
        //----< file item double click handler >-------------------------------------
        private void localListViewItem_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            ListViewItem item = sender as ListViewItem;
            object       obj  = item.Content;

            if (obj.GetType() == typeof(FileDirItem))
            {
                FileDirItem fileDirItem = (FileDirItem)obj;
                if (fileDirItem.isFolder)
                {
                    if (fileDirItem.Name == "..")
                    {
                        DirectoryInfo dirInfo  = new DirectoryInfo(Directory.GetCurrentDirectory());
                        string        nextPath = dirInfo.Parent.FullName;
                        Directory.SetCurrentDirectory(nextPath);
                    }
                    else
                    {
                        string nextPath = Directory.GetCurrentDirectory() + "/" + fileDirItem.Name;
                        Directory.SetCurrentDirectory(nextPath);
                    }

                    refreshLocalListView();
                }
            }
        }
        //----< upload button click handler >-------------------------------------
        private void btnUpload_Click(object sender, RoutedEventArgs e)
        {
            List <string> fileList = new List <string>();

            if (localListView.SelectedItems.Count > 0)
            {
                foreach (var item in localListView.SelectedItems)
                {
                    if (item.GetType() == typeof(FileDirItem))
                    {
                        FileDirItem fileDirItem = (FileDirItem)item;

                        if (fileDirItem.isFolder && fileDirItem.Name != "..")
                        {
                            foreach (string file in recursiveGetFiles(fileDirItem.Name))
                            {
                                fileList.Add(file);
                            }
                        }
                        else if (fileDirItem.Name != "..")
                        {
                            fileList.Add(fileDirItem.Name);
                        }
                    }
                }
            }

            if (fileList.Count == 0)
            {
                MessageBox.Show("No file selected!", "Upload", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            else
            {
                string      msgBoxString = String.Format("Upload {0} files?", fileList.Count);
                InputDialog inputDialog  = new InputDialog(msgBoxString + "\nInput the name to create a new dir? Or leave it blank.");
                if (inputDialog.ShowDialog() == true)
                {
                    sendFiles(ref fileList, inputDialog.Answer);

                    // do publish
                    if (cbxPublish.IsChecked == true)
                    {
                        btnPublish_Click(null, null);
                    }
                    else
                    {
                        // if don't publish, refresh list view
                        Thread.Sleep(100);
                        btnRefreshRemote_Click(null, null);
                    }
                }
            }
        }
        //----< data source for remote list view >--------------------------------
        public void refreshRemoteListView(string[] fileDirs)
        {
            remoteListView.Items.Clear();

            if (currentRemoteDir != ".")
            {
                FileDirItem backItem = new FileDirItem()
                {
                    Name = "..", Icon = "pack://siteoforigin:,,,/Resources/folderclosed.png", isFolder = true
                };
                remoteListView.Items.Add(backItem);
            }

            // add dirs
            foreach (string fileDir in fileDirs)
            {
                if (fileDir != "")
                {
                    string[] fileInfo = fileDir.Split(new char[] { ';' });

                    if (fileInfo[2] == "d")
                    {
                        FileDirItem item = new FileDirItem()
                        {
                            Name = fileInfo[0], LastWriteTime = fileInfo[1], isFolder = true
                        };
                        item.Icon = "pack://siteoforigin:,,,/Resources/folderclosed.png";
                        remoteListView.Items.Add(item);
                    }
                }
            }

            // add files
            foreach (string fileDir in fileDirs)
            {
                if (fileDir != "")
                {
                    string[] fileInfo = fileDir.Split(new char[] { ';' });

                    if (fileInfo[2] == "f")
                    {
                        FileDirItem item = new FileDirItem()
                        {
                            Name = fileInfo[0], LastWriteTime = fileInfo[1], isFolder = false
                        };
                        item.Icon = "pack://siteoforigin:,,,/Resources/file.png";
                        remoteListView.Items.Add(item);
                    }
                }
            }
        }
        //----< data source for local list view >---------------------------------
        public void refreshLocalListView()
        {
            string path = Directory.GetCurrentDirectory();

            // also refresh text box
            tbxLocalFolder.Text = path;

            localListView.Items.Clear();
            string[] files = Directory.GetFiles(path, "*.*").Where(file => file.ToLower().EndsWith(".h") || file.ToLower().EndsWith(".cpp")).ToArray();
            string[] dirs  = Directory.GetDirectories(path);

            // add a link to parent directory
            if (path != Directory.GetDirectoryRoot(path))
            {
                FileDirItem backItem = new FileDirItem()
                {
                    Name = "..", Icon = "pack://siteoforigin:,,,/Resources/folderclosed.png", isFolder = true
                };
                localListView.Items.Add(backItem);
            }

            // add dirs to list view
            for (int i = 0; i < dirs.Length; i++)
            {
                FileInfo    dir  = new FileInfo(dirs[i]);
                FileDirItem item = new FileDirItem()
                {
                    Name = dir.Name, LastWriteTime = dir.LastWriteTime.ToString(), isFolder = true
                };
                item.Icon = "pack://siteoforigin:,,,/Resources/folderclosed.png";
                localListView.Items.Add(item);
            }

            // add files to list view
            for (int i = 0; i < files.Length; i++)
            {
                FileInfo    file = new FileInfo(files[i]);
                FileDirItem item = new FileDirItem()
                {
                    Name = file.Name, LastWriteTime = file.LastWriteTime.ToString(), isFolder = false
                };
                item.Icon = "pack://siteoforigin:,,,/Resources/file.png";
                localListView.Items.Add(item);
            }
        }
        //----< file item double click handler >-------------------------------------
        private void remoteListViewItem_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            ListViewItem item = sender as ListViewItem;
            object       obj  = item.Content;

            if (obj.GetType() == typeof(FileDirItem))
            {
                FileDirItem fileDirItem = (FileDirItem)obj;
                if (fileDirItem.isFolder)
                {
                    if (fileDirItem.Name == ".." && currentRemoteDir != ".")
                    {
                        currentRemoteDir = currentRemoteDir.Substring(0, currentRemoteDir.LastIndexOf('\\'));
                    }
                    else
                    {
                        currentRemoteDir += ("\\" + fileDirItem.Name);
                    }

                    btnRefreshRemote_Click(null, null);
                }
            }
        }