/// <summary>Presents form to edit and then update the currently selected text message within the ListView.</summary>
        /// <returns>True, when changes are committed, false, otherwise.</returns>
        public bool EditTextMessage()
        {
            bool result = false;
            if (SelectedItems.Count > 0) {
                TextMessageListViewItem lvi = SelectedItems[0] as TextMessageListViewItem;
                TextMessage message = lvi.Message;
                string filePath = message.FilePath;
                NewEditMessage form = new NewEditMessage(message);

                if (form.ShowDialog(this) != DialogResult.Cancel) {
                    TextMessageListViewItem lvi2 = new TextMessageListViewItem(form.Message);
                    Items.Insert(lvi.Index, lvi2);
                    lvi.Remove();
                    Sort();
                    result = true;
                    AfterTextMessageItemUpdateEventArgs args = new AfterTextMessageItemUpdateEventArgs(lvi, lvi2);
                    OnAfterTextMessageItemUpdate(args);
                }
            }
            return result;
        }
 /// <summary>Adds relevant textmessages to the list view.</summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.Forms.DragEventArgs"/> instance containing the event data.</param>
 private void lvChildren_DragDrop(object sender, DragEventArgs e)
 {
     string[] fileNames = (string[]) e.Data.GetData(DataFormats.FileDrop);
     Dictionary<string, ListViewItem> messagesInListView = new Dictionary<string, ListViewItem>();
     foreach (ListViewItem item in textMessageListView.Items) {
         messagesInListView.Add(((TextMessage) item.Tag).FilePath, item);
     }
     foreach (string fileName in fileNames) {
         if (messagesInListView.ContainsKey(fileName)) {
             messagesInListView[fileName].Remove();
         }
         TextMessage message = TextMessage.ReadTextMessage(fileName, format);
         ListViewItem item = new TextMessageListViewItem(message);
         item.Checked = true;
         textMessageListView.Items.Add(item);
     }
 }
 /// <summary>Populates the list view with messages.</summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
 private void phone_MessagesRetrieved(object sender, EventArgs e)
 {
     textMessageListView.Items.Clear();
     MobilePhone phone = (MobilePhone) sender;
     List<TextMessage> messages = phone.Messages;
     foreach (TextMessage message in messages) {
         //create listview item's for each new message
         ListViewItem item = new TextMessageListViewItem(message);
         item.Checked = true;
         textMessageListView.Items.Add(item);
     }
 }
        /// <summary>Shows form to edit activated text message item.</summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void lvChildren_ItemActivate(object sender, EventArgs e)
        {
            ListViewItem lvi = textMessageListView.SelectedItems[0];
            TextMessage message = (TextMessage) lvi.Tag;
            string filePath = message.FilePath;
            NewEditMessage form = new NewEditMessage(message);

            if (form.ShowDialog(this) != DialogResult.Cancel) {
                ListViewItem lvi2 = new TextMessageListViewItem(form.Message);
                textMessageListView.Items.Insert(lvi.Index, lvi2);
                lvi.Remove();
                textMessageListView.Sort();
            }
        }
        /// <summary>Presents form to create new text message and adds new text message to lvChildren.</summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnAdd_Click(object sender, System.EventArgs e)
        {
            // as files are numbered from 0, lvChildren.Items.Count will give the next file number
            string fileNumber = lvChildren.Items.Count.ToString();
            MessageFolder messageFolder = (MessageFolder) tvParents.SelectedNode.Tag;
            string filePath = messageFolder.RetrievePath();
            MessageFormat format = messageFolder.RetrieveFormat();

            if (format == MessageFormat.Motorola) {
                fileNumber = fileNumber.PadLeft(4, '0');
            }
            string nextFile = MessageNameFormatAttribute.FileFormat(format).Replace("*", fileNumber);
            filePath += nextFile;
            NewEditMessage form = new NewEditMessage(filePath, format);
            if (form.ShowDialog(this) != DialogResult.Cancel) {
                //TODO: shouldn't(?) do this directly - should add to phone and trigger event to add message!
                ListViewItem lvi = new TextMessageListViewItem(form.Message);
                lvChildren.Items.Add(lvi);
                lvChildren.Sort();

                //add to cache
                string cacheKey = messageFolder.RetrievePath();
                List<ListViewItem> items = new List<ListViewItem>(messageCache[cacheKey]);
                items.Add(lvi);
                messageCache[cacheKey] = items.ToArray();
            }
        }
        /// <summary>Creates and adds ListViewItems for messages receieved and TreeNodes for folders.</summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void MessageFolder_MessagesRetrieved(object sender, EventArgs e)
        {
            MessageFolder folder = (MessageFolder) sender;

            progressBar.Visible = true;
            progressBar.Maximum = folder.Messages.Count + folder.Folders.Count + 1;
            progressBar.Value = 0;
            // 0 = type, 1 = current, 2 = total, 3 = name
            string progressText = "Creating items...{0} [{1}/{2}]: {3}";

            tvParents.BeginUpdate();
            TreeNode currentNode = tvParents.SelectedNode;
            int currentFolder = 0;
            int totalFolders = folder.Folders.Count;
            foreach (MessageFolder subfolder in folder.Folders) {
                //create treeview node
                TreeNode node = currentNode.Nodes.Add(subfolder.Name);
                subfolder.MessagesRetrieved += new EventHandler(MessageFolder_MessagesRetrieved);
                subfolder.MessagesRetrievalProgress += new EventHandler<MessageFolder.MessagesRetrievalProgressEventArgs>(MessageFolder_MessagesRetrievalProgress);
                node.Tag = subfolder;
                progressBar.Value++;
                currentFolder++;
                statusBar.Text = String.Format(progressText, "Folder", currentFolder, totalFolders, subfolder.Name);
            }
            tvParents.EndUpdate();

            //list view items:
            lvChildren.BeginUpdate();
            lvChildren.Items.Clear();
            //messageCache.Remove(nodePath);
            int currentMessage = 0;
            int totalMessages = folder.Messages.Count;
            MessageFormat messageFolderFormat = folder.RetrieveFormat();
            foreach (TextMessage message in folder.Messages) {
                //create listview item's for each new message
                ListViewItem item = new TextMessageListViewItem(message);
                lvChildren.Items.Add(item);
                progressBar.Value++;
                currentMessage++;
                statusBar.Text = String.Format(progressText, "Text Message", currentMessage, totalMessages, message.FileName);
            }
            lvChildren.EndUpdate();

            if (!(folder is MobilePhone)) {
                ListViewItem[] cacheItems = new ListViewItem[lvChildren.Items.Count];
                lvChildren.Items.CopyTo(cacheItems, 0);
                messageCache[CreateNodePath(currentNode)] = cacheItems;
            }

            progressBar.Visible = false;
            SetNodeStatus(currentNode);
        }