示例#1
0
 /// <summary>
 /// Adds an item to the queue. The new item is added at queueIndex
 /// which is the most recent position to which the user has tracked
 /// (usually the end of the array if no tracking has occurred). If
 /// queueIndex is in the middle of the array, we remove all items
 /// to the right (from queueIndex+1 onwards) in order to define a
 /// new 'head' position. This produces the expected results when tracking
 /// from the new item inserted back to the most recent item.
 /// </summary>
 /// <param name="item">Item to be added</param>
 public void AddToQueue(Address item)
 {
     while (_queueIndex + 1 < _array.Count)
     {
         _array.RemoveAt(_queueIndex + 1);
     }
     if (_array.Count == _maxItems)
     {
         _array.RemoveAt(0);
         --_queueIndex;
     }
     if (_array.Count > 0)
     {
         Address itemAddress = _array[_array.Count - 1];
         if (itemAddress == item)
         {
             return;
         }
     }
     _array.Add(item);
     ++_queueIndex;
 }
示例#2
0
 /// <summary>
 /// Set the specified address by navigating to the folder referenced by
 /// the address.
 /// </summary>
 /// <param name="address">The address to be set</param>
 public void SetAddress(Address address)
 {
     if (SelectAddress(address))
     {
         return;
     }
     if (JoinMissingForum(address))
     {
         return;
     }
     Process.Start(address.SchemeAndQuery);
 }
示例#3
0
 /// <summary>
 /// Display the folder referenced by the given node, passing through the address and options.
 /// </summary>
 public bool SelectViewForFolder(TreeNode node, Address address, FolderOptions options)
 {
     FolderBase folder = (FolderBase)node.Tag;
     return SelectView(folder.ViewForFolder, folder, address, options);
 }
示例#4
0
 /// <summary>
 /// Find the specified folder in the tree and if found, select it. If it is
 /// already selected, invoke the view with the specified address.
 /// </summary>
 /// <param name="folder">The folder to select</param>
 /// <param name="address">The address to pass to the view</param>
 private void SetSelection(FolderBase folder, Address address)
 {
     if (folder != null)
     {
         TreeNode node = NodeForFolder(folder, frmList.Nodes);
         if (node != null && node.IsSelected)
         {
             SelectViewForFolder(node, address, 0);
         }
         else
         {
             _lastAddress = address;
             SelectFolder(node, 0);
         }
     }
 }
示例#5
0
        /// <summary>
        /// Display the selected view with the given folder, passing through the address and options.
        /// </summary>
        /// <param name="requestedView">The ID of the type of the view requested</param>
        /// <param name="folder">The folder to be displayed in the view</param>
        /// <param name="address">The address of the item within the folder to be selected</param>
        /// <param name="options">Options controlling the folder selection</param>
        /// <returns>True if the view was successfully selected, false otherwise</returns>
        private bool SelectView(AppView requestedView, FolderBase folder, Address address, FolderOptions options)
        {
            ViewBaseView newView = _allViews[requestedView];

            if (newView != _currentView)
            {
                if (_currentView != null)
                {
                    _currentView.Visible = false;
                    frmSplitContainer.Panel2.Controls.Remove(_currentView);
                }
                if (newView != null)
                {
                    frmSplitContainer.Panel2.Controls.Add(newView);

                    _currentView = newView;
                    SetSubviewSize();
                    newView.Visible = true;
                    newView.Update();
                }
            }

            ShowSearchBar(SearchBarVisibility.FastHide);

            if (folder != null)
            {
                string placeholder = folder.AllowsScopedSearch
                    ? string.Format(Resources.SearchForTextIn, folder.Name)
                    : Resources.Search;
                MainForm.SetSearchFieldPlaceholder(placeholder);

                SetTopicName(folder.FullName);
            }
            return (_currentView != null) && _currentView.ViewFromFolder(folder, address, options);
        }
示例#6
0
 /// <summary>
 /// Select a folder based on the address of the node.
 /// </summary>
 /// <param name="address">Address of the node</param>
 /// <returns>True if we found and selected the folder, false if it was not found</returns>
 private bool SelectAddress(Address address)
 {
     FolderBase selection = FolderFromAddress(address.SchemeAndQuery);
     if (selection != null)
     {
         SetSelection(selection, address);
     }
     return selection != null;
 }
示例#7
0
        /// <summary>
        /// Return the message that corresponds to a given CIX address if possible, or null if
        /// the input does not reference a valid message.
        /// </summary>
        public CIXMessage MessageFromAddress(string addressString)
        {
            Address address = new Address(addressString);
            int messageID;

            if (address.Scheme != null && Int32.TryParse(address.Data, out messageID))
            {
                address = NormaliseAddress(address);

                string[] splitAddress = address.Query.Split(new[] {'/'});
                if (splitAddress.Length == 2)
                {
                    Folder forum = CIX.FolderCollection.Get(-1, splitAddress[0]);
                    Folder topic = CIX.FolderCollection.Get(forum.ID, splitAddress[1]);
                    return topic.Messages.MessageByID(messageID);
                }
            }
            return null;
        }
示例#8
0
 /// <summary>
 /// Display this view with the specified folder and options
 /// </summary>
 public override bool ViewFromFolder(FolderBase folder, Address address, FolderOptions flags)
 {
     if (_welcomePage == null)
     {
         FillCanvas();
     }
     CIX.RefreshOnlineUsers();
     FolderCollection.RefreshInterestingThreads();
     return true;
 }
示例#9
0
 /// <summary>
 /// Removes an item from the tail of the queue as long as the queue is not empty and returns the backtrack data.
 /// </summary>
 /// <param name="item">Ref of the string to be set with the backtrack data</param>
 /// <returns>True if an item was returned, false otherwise</returns>
 public bool PreviousItemAtQueue(ref Address item)
 {
     if (_queueIndex > 0)
     {
         item = _array[--_queueIndex];
         return true;
     }
     return false;
 }
示例#10
0
 /// <summary>
 /// Removes an item from the tail of the queue as long as the queue is not empty and returns the backtrack data.
 /// </summary>
 /// <param name="item">Ref of the string to be set with the backtrack data</param>
 /// <returns>True if an item was returned, false otherwise</returns>
 public bool NextItemAtQueue(ref Address item)
 {
     if (_queueIndex < _array.Count - 1)
     {
         item = _array[++_queueIndex];
         return true;
     }
     return false;
 }
示例#11
0
        /// <summary>
        /// Display the specified topic folder in the thread list.
        /// </summary>
        /// <param name="folder">The folder whose topic is to be displayed</param>
        /// <param name="address"></param>
        /// <param name="options">Folder display flags</param>
        public override bool ViewFromFolder(FolderBase folder, Address address, FolderOptions options)
        {
            if (folder.ViewForFolder == AppView.AppViewTopic)
            {
                if ((_currentFolder != folder) || options.HasFlag(FolderOptions.ClearFilter))
                {
                    _currentFolder = folder;
                    _currentFilterString = null;
                    _isFiltering = false;
                    _isTopicFolder = IsTopicFolder();

                    tsvMessages.SelectedIndices.Clear();
                    ShowMessage(null);

                    if (FoldersTree.MainForm.RunEvent(EventID.FolderSelected,
                        _isTopicFolder ? ((TopicFolder) folder).Folder : null))
                    {
                        if (_isTopicFolder)
                        {
                            // Attempt to make topic switches cleaner by removing the old messages from display
                            // when switching to a new topic will involve a delay caused by loading the messages
                            // from the DB, sorting, etc.
                            if (!((TopicFolder)_currentFolder).Folder.HasMessages && _messages != null && _messages.Count > 0)
                            {
                                _messages = new List<CIXMessage>();
                                InitialiseList();
                                RedrawAllItems();
                            }
                        }
                        SortConversations();
                    }

                    UpdateFromFlags();
                }

                // Load this topic from the server only if we're empty.
                if (_messages != null && _messages.Count == 0)
                {
                    if (address != null && address.Scheme == "cix")
                    {
                        Int32.TryParse(address.Data, out _lastIndex);
                    }
                    folder.Refresh();
                    return false;
                }

                if (options.HasFlag(FolderOptions.ClearFilter))
                {
                    options &= ~FolderOptions.ClearFilter;
                    _currentFilterString = null;
                    _isFiltering = false;
                }

                if (address != null && address.Scheme == "cix")
                {
                    int selectedID;
                    Int32.TryParse(address.Data, out selectedID);
                    if (!GoToMessage(selectedID))
                    {
                        SetInitialSelection();
                    }
                    if (address.Unread)
                    {
                        SelectedMessage.MarkUnread();
                    }
                }
                else if (options == 0)
                {
                    SetInitialSelection();
                }
                else
                {
                    int row = SelectedRow;
                    if (row < 0 || options.HasFlag(FolderOptions.Reset))
                    {
                        row = -1;
                    }
                    else
                    {
                        CIXMessage selectedMessage = SelectedMessage;
                        if (selectedMessage != null && selectedMessage.Unread)
                        {
                            selectedMessage.MarkRead();
                        }
                    }
                    if (!FirstUnreadAfterRow(row, options))
                    {
                        return false;
                    }
                }

                ActiveControl = tsvMessages;
            }
            return true;
        }
示例#12
0
        /// <summary>
        /// Display the directory for the specified CategoryFolder
        /// </summary>
        public override bool ViewFromFolder(FolderBase folder, Address address, FolderOptions options)
        {
            if (folder != _currentFolder)
            {
                _currentFolder = folder;
                SortConversations();
            }

            // If an address is specified then it refers to a conversation ID that
            // needs to be selected. If it is not found, the first message is selected
            // instead.
            if (address != null && address.Scheme == "cixmailbox")
            {
                int selectedID;

                Int32.TryParse(address.Data, out selectedID);

                int selectedIndex;
                for (selectedIndex = 0; selectedIndex < _conversations.Count; ++selectedIndex)
                {
                    InboxConversation conversation = _conversations[selectedIndex];
                    if (conversation.RemoteID == selectedID)
                        break;
                }
                if (selectedIndex == _conversations.Count)
                {
                    selectedIndex = 0;
                }
                SelectedRow = selectedIndex;
                if (address.Unread)
                {
                    SelectedMessage.MarkUnread();
                }
                return true;
            }

            // If options are specified then search for the next unread
            // in the list otherwise set the initial selection to something
            // useful.
            if (options == 0 && SelectedRow == -1)
            {
                SetInitialSelection();
            }
            else
            {
                int row = inboxConversations.SearchRow;
                if (row < 0 || options.HasFlag(FolderOptions.Reset))
                {
                    row = 0;
                }
                else if (_conversations.Count > 0)
                {
                    InboxConversation conversation = _conversations[row];
                    if (conversation.UnreadCount > 0)
                    {
                        conversation.MarkRead();
                    }
                }
                if (!FirstUnreadAfterRow(row, options))
                {
                    inboxConversations.SearchRow = 0;
                    return false;
                }
            }

            FoldersTree.SetTopicName(_currentFolder.FullName);

            ActiveControl = inboxConversations;
            inboxConversations.Focus();
            return true;
        }
示例#13
0
        /// <summary>
        /// Display the page for the specified forum.
        /// </summary>
        public override bool ViewFromFolder(FolderBase folder, Address address, FolderOptions flags)
        {
            if (folder is TopicFolder)
            {
                _currentFolder = folder as TopicFolder;
                _thisForum = CIX.DirectoryCollection.ForumByName(_currentFolder.Name);

                FoldersTree.SetTopicName(folder.Name);

                CIX.DirectoryCollection.RefreshForum(folder.Name);

                FillCanvas();
            }
            return true;
        }
示例#14
0
 /// <summary>
 /// Display the directory for the specified CategoryFolder
 /// </summary>
 public override bool ViewFromFolder(FolderBase folder, Address address, FolderOptions flags)
 {
     CategoryFolder category = folder as CategoryFolder;
     if (category != null)
     {
         if (flags.HasFlag(FolderOptions.ClearFilter))
         {
             _currentFilterString = null;
         }
         _currentCategory = category;
         _items = ItemsForView();
         SortItems();
     }
     return true;
 }
示例#15
0
 /// <summary>
 /// Invoke the Join dialog to join the forum specified by the address.
 /// This only works for cix: addresses. Others are ignored.
 /// </summary>
 /// <param name="address">The forum or forum/topic address</param>
 /// <returns>True if we displayed the Join Forum dialog, false otherwise</returns>
 private static bool JoinMissingForum(Address address)
 {
     if (address.Scheme == "cix")
     {
         string[] splitAddress = address.Query.Split(new[] {'/'});
         if (splitAddress.Length > 0)
         {
             JoinForum joinForum = new JoinForum(splitAddress[0]);
             joinForum.ShowDialog();
             return true;
         }
     }
     return false;
 }
示例#16
0
        /// <summary>
        /// Recursively locate the folder whose address corresponds to the given address
        /// under the specified tree node collection.
        /// </summary>
        /// <param name="address">Address to match</param>
        /// <param name="nodes">Tree nodes to search</param>
        /// <returns>The FolderBase of the folder with the given address, or null if it was not found</returns>
        private FolderBase FolderFromAddress(string address, IEnumerable nodes)
        {
            foreach (TreeNode node in nodes)
            {
                FolderBase folder = node.Tag as FolderBase;
                if (folder != null && folder.Address == address)
                {
                    return folder;
                }
                if (node.Nodes.Count > 0)
                {
                    FolderBase subFolder = FolderFromAddress(address, node.Nodes);
                    if (subFolder != null)
                    {
                        return subFolder;
                    }
                }
            }

            // Not found but possibly hidden if we're filtering by recent so parse off
            // the parent folder and look for that, then unhide the topic.
            Address addr = new Address(address);
            if (addr.Scheme == "cix" && addr.Query != null)
            {
                string[] splitAddress = addr.Query.Split(new[] {'\\'});
                if (splitAddress.Length == 2)
                {
                    Folder forum = CIX.FolderCollection.Get(-1, splitAddress[0]);
                    Folder topic = CIX.FolderCollection.Get(forum.ID, splitAddress[1]);

                    if (topic != null && !topic.IsRecent)
                    {
                        topic.IsRecent = true;
                        FolderBase forumFolder = FolderWithID(forum.ID, _forumsTree.Nodes);
                        ReloadForumTreeFromNode(forumFolder);

                        return FolderWithID(topic.ID, _forumsTree.Nodes);
                    }
                }
            }
            return null;
        }
示例#17
0
 /// <summary>
 /// Refresh the view for the folder at the given node.
 /// </summary>
 /// <param name="node">The node of the folder to refresh</param>
 /// <param name="options">Options to be passed to the view</param>
 private void RefreshFolder(TreeNode node, FolderOptions options)
 {
     if (node != null)
     {
         SelectViewForFolder(node, _lastAddress, options);
         _lastAddress = null;
     }
 }
示例#18
0
 /// <summary>
 /// Display this view with the specified folder and options
 /// </summary>
 public virtual bool ViewFromFolder(FolderBase folder, Address address, FolderOptions flags)
 {
     return true;
 }
示例#19
0
        /// <summary>
        /// Normalise the query in the address so that the full address is specified.
        /// </summary>
        private Address NormaliseAddress(Address address)
        {
            if (address.Scheme != null && address.Scheme == "cix")
            {
                if (string.IsNullOrEmpty(address.Query))
                {
                    string oldAddress = address.Data;
                    TreeNode node = FoldersTree.SelectedNode;
                    if (node != null)
                    {
                        FolderBase folder = (FolderBase)node.Tag;
                        string newAddress = folder.Address;
                        address = new Address(newAddress) { Data = oldAddress };
                    }
                }

                // Special case the cix:/topic convention here because it requires us to
                // know the forum from the selection which is only possible when we have
                // the UI from which to determine the selection.
                else if (address.Query.StartsWith("/", StringComparison.Ordinal))
                {
                    TreeNode node = FoldersTree.SelectedNode;
                    if (node != null)
                    {
                        FolderBase folder = (FolderBase)node.Tag;
                        if (folder is TopicFolder && !((TopicFolder)folder).Folder.IsRootFolder)
                        {
                            Folder forum = ((TopicFolder)folder).Folder.ParentFolder;
                            address.Query = string.Format("{0}{1}", forum.Name, address.Query);
                        }
                    }
                }
            }
            return address;
        }