示例#1
0
        /// <summary>
        /// Treeview's context menu > Plan "(selection)".
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmAddToPlan_Click(object sender, EventArgs e)
        {
            CertificateLevel cert = treeView.SelectedNode.Tag as CertificateLevel;
            IPlanOperation   operation;

            if (cert != null)
            {
                operation = m_plan.TryPlanTo(cert);
            }
            else
            {
                SkillLevel prereq = (SkillLevel)treeView.SelectedNode.Tag;
                operation = m_plan.TryPlanTo(prereq.Skill, prereq.Level);
            }

            if (operation == null)
            {
                return;
            }

            PlanWindow planWindow = ParentForm as PlanWindow;

            if (planWindow == null)
            {
                return;
            }

            PlanHelper.SelectPerform(new PlanToOperationWindow(operation), planWindow, operation);
        }
示例#2
0
        /// <summary>
        /// Updates the provided label with the training time to the given level.
        /// </summary>
        /// <param name="label">The label.</param>
        /// <param name="level">The level.</param>
        private void UpdateLevelLabel(Control label, int level)
        {
            label.Visible = m_selectedCertificate?.Character != null;

            if (m_selectedCertificate?.Character == null)
            {
                return;
            }

            StringBuilder sb = new StringBuilder();

            // "Level III: "
            sb.Append($"Level {Skill.GetRomanFromInt(level)}: ");

            CertificateLevel certificateLevel = m_selectedCertificate.Certificate.GetCertificateLevel(level);

            // Is it already trained ?
            if (certificateLevel.IsTrained)
            {
                label.Text = sb.Append("Already trained").ToString();
                return;
            }

            // Training time left for level
            sb.Append(certificateLevel.GetTrainingTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas));

            label.Text = sb.ToString();
        }
示例#3
0
        protected void addCl(object sender, DirectEventArgs e)
        {
            CertificateLevel dept = new CertificateLevel();

            dept.name = clId.Text;

            PostRequest <CertificateLevel> depReq = new PostRequest <CertificateLevel>();

            depReq.entity = dept;

            PostResponse <CertificateLevel> response = _employeeService.ChildAddOrUpdate <CertificateLevel>(depReq);

            if (response.Success)
            {
                dept.recordId = response.recordId;
                FillCertificateLevels();
                clId.Select(response.recordId);
            }
            else
            {
                X.MessageBox.ButtonText.Ok = Resources.Common.Ok;
                Common.errorMessage(response);
                return;
            }
        }
示例#4
0
        /// <summary>
        /// Updates the specified node and its children.
        /// </summary>
        /// <param name="node"></param>
        private void UpdateNode(TreeNode node)
        {
            CertificateLevel certLevel = node.Tag as CertificateLevel;

            // The node represents a certificate
            if (certLevel != null)
            {
                if (m_character != null)
                {
                    if (certLevel.IsTrained)
                    {
                        node.ImageIndex = imageList.Images.IndexOfKey(TrainedIcon);
                    }
                    else if (certLevel.IsPartiallyTrained)
                    {
                        node.ImageIndex = imageList.Images.IndexOfKey(TrainableIcon);
                    }
                    else
                    {
                        node.ImageIndex = imageList.Images.IndexOfKey(UntrainableIcon);
                    }
                }
            }
            // The node represents a skill prerequisite
            else
            {
                SkillLevel skillPrereq = (SkillLevel)node.Tag;
                Skill      skill       = m_character?.Skills[skillPrereq.Skill.ID] ?? skillPrereq.Skill;

                if (m_character != null)
                {
                    if (skillPrereq.IsTrained)
                    {
                        node.ImageIndex = imageList.Images.IndexOfKey(TrainedIcon);
                    }
                    else if (m_plan != null && m_plan.IsPlanned(skill, skillPrereq.Level))
                    {
                        node.ImageIndex = imageList.Images.IndexOfKey(PlannedIcon);
                    }
                    else if (skill.IsKnown)
                    {
                        node.ImageIndex = imageList.Images.IndexOfKey(TrainableIcon);
                    }
                    else
                    {
                        node.ImageIndex = imageList.Images.IndexOfKey(UntrainableIcon);
                    }
                }
            }

            // When selected, the image remains the same
            node.SelectedImageIndex = node.ImageIndex;

            // Update the children
            foreach (TreeNode child in node.Nodes)
            {
                UpdateNode(child);
            }
        }
        /// <summary>
        /// Gets the time to elite grade.
        /// </summary>
        /// <param name="certificateClass">The certificate class.</param>
        /// <returns>The time required to finish the final grade</returns>
        private static TimeSpan GetTimeToMaxLevel(CertificateClass certificateClass)
        {
            CertificateLevel levelFive = certificateClass.Certificate.GetCertificateLevel(5);

            return(levelFive.IsTrained
                ? TimeSpan.Zero
                : levelFive.GetTrainingTime);
        }
示例#6
0
        /// <summary>
        /// Updates a "plan to" menu.
        /// </summary>
        /// <param name="menu">The menu to update</param>
        /// <param name="certLevel">The level represent by this menu</param>
        /// <param name="lastEligibleCertLevel">The highest eligible certificate after this plan</param>
        private bool UpdatePlanningMenuStatus(ToolStripItem menu, CertificateLevel certLevel, CertificateLevel lastEligibleCertLevel)
        {
            menu.Enabled = certLevel != null && (lastEligibleCertLevel == null || certLevel.Level > lastEligibleCertLevel.Level);

            if (menu.Enabled)
            {
                menu.Tag = m_plan.TryPlanTo(certLevel);
            }

            return(menu.Enabled);
        }
示例#7
0
        /// <summary>
        /// Update the whole tree.
        /// </summary>
        private void UpdateTree()
        {
            CertificateLevel oldSelection = SelectedCertificateLevel;
            TreeNode         newSelection = null;

            treeView.ImageList = Settings.UI.SafeForWork ? m_emptyImageList : imageList;

            treeView.BeginUpdate();
            try
            {
                // Clear the old items
                treeView.Nodes.Clear();

                // No update when not fully initialized
                if (m_class == null)
                {
                    return;
                }

                // Create the nodes when not done, yet
                if (treeView.Nodes.Count == 0)
                {
                    foreach (CertificateLevel certLevel in m_class.Certificate.AllLevel)
                    {
                        TreeNode node = CreateNode(certLevel);
                        treeView.Nodes.Add(node);

                        // Does the old selection still exists ?
                        if (certLevel == oldSelection)
                        {
                            newSelection = node;
                        }
                    }
                }

                // Update the nodes
                foreach (TreeNode node in treeView.Nodes)
                {
                    UpdateNode(node);
                }

                // Is the old selection kept ? Then we select the matching node
                if (newSelection != null)
                {
                    treeView.SelectedNode = newSelection;
                }
            }
            finally
            {
                treeView.EndUpdate();
            }
        }
示例#8
0
        /// <summary>
        /// Context menu opening, we update the menus' statuses.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmListSkills_Opening(object sender, CancelEventArgs e)
        {
            TreeNode         node      = treeView.SelectedNode;
            CertificateLevel certLevel = node?.Tag as CertificateLevel;

            planToLevel.Visible = planToLevelSeparator.Visible = m_plan != null && node != null;

            if (m_plan != null)
            {
                // When a certificate is selected
                if (certLevel != null)
                {
                    // Update "add to" menu
                    planToLevel.Enabled = !m_plan.WillGrantEligibilityFor(certLevel);
                    planToLevel.Text    = $"Plan \"{certLevel}\"";
                }
                // When a skill is selected
                else if (node != null)
                {
                    // Update "add to" menu
                    SkillLevel prereq = (SkillLevel)node.Tag;
                    Skill      skill  = prereq.Skill;
                    planToLevel.Enabled = skill.Level < prereq.Level && !m_plan.IsPlanned(skill, prereq.Level);
                    planToLevel.Text    = $"Plan \"{skill} {Skill.GetRomanFromInt(prereq.Level)}\"";
                }
            }

            // Update "show in" menu
            showInBrowserMenu.Visible           =
                showInExplorerMenu.Visible      =
                    showInMenuSeparator.Visible = node != null && certLevel == null;

            // "Collapse" and "Expand" menus
            tsmCollapseSelected.Visible = node != null && node.GetNodeCount(true) > 0 && node.IsExpanded;
            tsmExpandSelected.Visible   = node != null && node.GetNodeCount(true) > 0 && !node.IsExpanded;

            tsmExpandSelected.Text = node != null && node.GetNodeCount(true) > 0 && !node.IsExpanded
                ? $"Expand \"{node.Text}\""
                : string.Empty;
            tsmCollapseSelected.Text = node != null && node.GetNodeCount(true) > 0 && node.IsExpanded
                ? $"Collapse \"{node.Text}\""
                : string.Empty;

            toggleSeparator.Visible = node != null && node.GetNodeCount(true) > 0;

            // "Expand All" and "Collapse All" menus
            tsmCollapseAll.Enabled = tsmCollapseAll.Visible = m_allExpanded;
            tsmExpandAll.Enabled   = tsmExpandAll.Visible = !tsmCollapseAll.Enabled;
        }
示例#9
0
        /// <summary>
        /// Create a node from a prerequisite certificate.
        /// </summary>
        /// <param name="certLevel">The cert level.</param>
        /// <returns></returns>
        private static TreeNode CreateNode(CertificateLevel certLevel)
        {
            TreeNode node = new TreeNode
            {
                Text = certLevel.ToString(),
                Tag  = certLevel
            };

            foreach (SkillLevel prereqSkill in certLevel.PrerequisiteSkills)
            {
                node.Nodes.Add(CreateNode(prereqSkill));
            }

            return(node);
        }
示例#10
0
        /// <summary>
        /// Checks whether, after this plan, the owner will be eligible to the provided certificate
        /// </summary>
        /// <param name="certLevel">The cert level.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">certLevel</exception>
        public bool WillGrantEligibilityFor(CertificateLevel certLevel)
        {
            certLevel.ThrowIfNull(nameof(certLevel));

            if (certLevel.IsTrained)
            {
                return(true);
            }

            // We check every prerequisite is trained
            return(!certLevel.PrerequisiteSkills.Select(
                       skillToTrain => new { skillToTrain, skill = skillToTrain.Skill }).Where(
                       skillToTrain => skillToTrain.skill.Level < skillToTrain.skillToTrain.Level).Where(
                       skillToTrain => !IsPlanned(skillToTrain.skill, skillToTrain.skillToTrain.Level)).Select(
                       skill => skill.skillToTrain).Any());
        }
示例#11
0
        /// <summary>
        /// Updates eligibility label and planning menus.
        /// </summary>
        private void UpdateEligibility()
        {
            foreach (ToolStripItem control in tspControl.Items)
            {
                control.Visible = m_plan != null;
            }

            // Not visible
            if (m_selectedCertificate == null || m_plan == null)
            {
                return;
            }

            // First we search the highest eligible certificate level after this plan
            IList <CertificateLevel> eligibleCertLevel = m_selectedCertificate.Certificate.AllLevel
                                                         .TakeWhile(cert => m_plan.WillGrantEligibilityFor(cert)).ToList();

            CertificateLevel lastEligibleCertLevel = null;

            if (!eligibleCertLevel.Any())
            {
                tslbEligible.Text = @"(none)";
            }
            else
            {
                lastEligibleCertLevel = eligibleCertLevel.Last();
                tslbEligible.Text     = lastEligibleCertLevel.ToString();

                tslbEligible.Text += m_selectedCertificate.HighestTrainedLevel == null
                    ? " (improved from \"none\")"
                    : (int)lastEligibleCertLevel.Level > (int)m_selectedCertificate.HighestTrainedLevel.Level
                        ? $" (improved from \"{m_selectedCertificate.HighestTrainedLevel}\")"
                        : @" (no change)";
            }

            planToLevel.Enabled = false;

            // "Plan to N" menus
            for (int i = 1; i <= 5; i++)
            {
                planToLevel.Enabled |= UpdatePlanningMenuStatus(planToLevel.DropDownItems[i - 1],
                                                                m_selectedCertificate.Certificate.GetCertificateLevel(i), lastEligibleCertLevel);
            }
        }
示例#12
0
        public void DeleteRecord(string index)
        {
            try
            {
                //Step 1 Code to delete the object from the database
                CertificateLevel s = new CertificateLevel();
                s.recordId  = index;
                s.reference = "";

                s.name = "";
                PostRequest <CertificateLevel> req = new PostRequest <CertificateLevel>();
                req.entity = s;
                PostResponse <CertificateLevel> r = _employeeService.ChildDelete <CertificateLevel>(req);
                if (!r.Success)
                {
                    X.MessageBox.ButtonText.Ok = Resources.Common.Ok;
                    X.Msg.Alert(Resources.Common.Error, r.Summary).Show();
                    return;
                }
                else
                {
                    //Step 2 :  remove the object from the store
                    Store1.Remove(index);

                    //Step 3 : Showing a notification for the user
                    Notification.Show(new NotificationConfig
                    {
                        Title = Resources.Common.Notification,
                        Icon  = Icon.Information,
                        Html  = Resources.Common.RecordDeletedSucc
                    });
                }
            }
            catch (Exception ex)
            {
                //In case of error, showing a message box to the user
                X.MessageBox.ButtonText.Ok = Resources.Common.Ok;
                X.Msg.Alert(Resources.Common.Error, Resources.Common.ErrorDeletingRecord).Show();
            }
        }
示例#13
0
文件: Plan.cs 项目: Darkfoe703/evemon
        /// <summary>
        /// Adds the provided certificate's prerequisites to the plan.
        /// </summary>
        /// <param name="certificateLevel">The certificate level.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">certificateLevel</exception>
        public IPlanOperation TryPlanTo(CertificateLevel certificateLevel)
        {
            certificateLevel.ThrowIfNull(nameof(certificateLevel));

            List <StaticSkillLevel> skillsToAdd = new List <StaticSkillLevel>();

            foreach (SkillLevel skillLevel in certificateLevel.PrerequisiteSkills)
            {
                int plannedLevel = GetPlannedLevel(skillLevel.Skill);
                if ((skillLevel.Level == plannedLevel) || (skillLevel.Level <= plannedLevel))
                {
                    continue;
                }

                // Get skill levels to add
                for (int i = plannedLevel + 1; i <= skillLevel.Level; i++)
                {
                    skillsToAdd.Add(new StaticSkillLevel(skillLevel.Skill, i));
                }
            }

            return(TryAddSet(skillsToAdd, $"{certificateLevel.Certificate.Name} {certificateLevel}"));
        }
示例#14
0
        /// <summary>
        /// Gets the time to next grade.
        /// </summary>
        /// <param name="certificateClass">The certificate class.</param>
        /// <returns>The time required to finish the next grade</returns>
        private static TimeSpan GetTimeToNextLevel(CertificateClass certificateClass)
        {
            CertificateLevel lowestTrinedLevel = certificateClass.Certificate.LowestUntrainedLevel;

            return(lowestTrinedLevel?.GetTrainingTime ?? TimeSpan.Zero);
        }
示例#15
0
        /// <summary>
        /// Custom draw for the label.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
        {
            // Prevents a bug that causes every item to be redrawn at the top left corner
            if (e.Bounds.Left <= 10)
            {
                e.DrawDefault = true;
                return;
            }

            string    line2   = "-";
            int       supIcon = -1;
            ImageList il;

            // Is it a certificate level ?
            CertificateLevel certLevel = e.Node.Tag as CertificateLevel;

            if (certLevel != null)
            {
                if (!Settings.UI.SafeForWork)
                {
                    supIcon = (int)certLevel.Level;
                }

                il = imageListCertLevels;

                // When not trained, let's display the training time
                if (!certLevel.IsTrained)
                {
                    TimeSpan time = certLevel.GetTrainingTime;
                    if (time != TimeSpan.Zero)
                    {
                        line2 = time.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);
                    }
                }
            }
            // Or a skill prerequisite ?
            else
            {
                if (!Settings.UI.SafeForWork)
                {
                    supIcon = imageList.Images.IndexOfKey(SkillBookIcon);
                }

                il = imageList;
                SkillLevel skillPrereq = (SkillLevel)e.Node.Tag;

                // When not known to the require level, let's display the training time
                if (!skillPrereq.IsTrained)
                {
                    TimeSpan time = skillPrereq.Skill.GetLeftTrainingTimeToLevel(skillPrereq.Level);
                    if (time != TimeSpan.Zero)
                    {
                        line2 = time.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);
                    }
                }
            }

            // Choose colors according to selection
            bool  isSelected     = (e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected;
            Color backColor      = isSelected ? SystemColors.Highlight : treeView.BackColor;
            Color foreColor      = isSelected ? SystemColors.HighlightText : treeView.ForeColor;
            Color lightForeColor = isSelected ? SystemColors.HighlightText : SystemColors.GrayText;

            // Draws the background
            using (SolidBrush background = new SolidBrush(backColor))
            {
                int width = treeView.ClientSize.Width - e.Bounds.Left;
                e.Graphics.FillRectangle(background, new Rectangle(e.Bounds.Left, e.Bounds.Top, width, e.Bounds.Height));
            }

            // Performs the drawing
            using (SolidBrush foreground = new SolidBrush(foreColor))
            {
                float offset;
                int   left      = e.Bounds.Left + il.ImageSize.Width + 2;
                Size  line1Size = TextRenderer.MeasureText(e.Node.Text, m_boldFont);

                if (!string.IsNullOrEmpty(line2))
                {
                    Size line2Size = TextRenderer.MeasureText(line2, Font);

                    offset = (float)(e.Bounds.Height - line1Size.Height - line2Size.Height) / 2;
                    e.Graphics.DrawString(e.Node.Text, m_boldFont, foreground, new PointF(left, e.Bounds.Top + offset));

                    using (SolidBrush lightForeground = new SolidBrush(lightForeColor))
                    {
                        e.Graphics.DrawString(line2, Font, lightForeground, new PointF(left, e.Bounds.Top + offset + line1Size.Height));
                    }
                }
                else
                {
                    offset = (float)(e.Bounds.Height - line1Size.Height) / 2;
                    e.Graphics.DrawString(e.Node.Text, m_boldFont, foreground, new PointF(left, e.Bounds.Top + offset));
                }
            }

            // Draws the icon for skill/cert on the far right
            if (supIcon == -1)
            {
                return;
            }

            int   imgOfssetX = e.Bounds.Left;
            float imgOffsetY = Math.Max(0.0f, (e.Bounds.Height - il.ImageSize.Height) * 0.5f);

            e.Graphics.DrawImageUnscaled(il.Images[supIcon], imgOfssetX, (int)(e.Bounds.Top + imgOffsetY));
        }
示例#16
0
        protected void SaveNewRecord(object sender, DirectEventArgs e)
        {
            //Getting the id to check if it is an Add or an edit as they are managed within the same form.


            string           obj = e.ExtraParams["values"];
            CertificateLevel b   = JsonConvert.DeserializeObject <CertificateLevel>(obj);

            string id = e.ExtraParams["id"];

            // Define the object to add or edit as null

            if (string.IsNullOrEmpty(id))
            {
                try
                {
                    //New Mode
                    //Step 1 : Fill The object and insert in the store
                    PostRequest <CertificateLevel> request = new PostRequest <CertificateLevel>();

                    request.entity = b;
                    PostResponse <CertificateLevel> r = _employeeService.ChildAddOrUpdate <CertificateLevel>(request);


                    //check if the insert failed
                    if (!r.Success)//it maybe be another condition
                    {
                        //Show an error saving...
                        X.MessageBox.ButtonText.Ok = Resources.Common.Ok;
                        X.Msg.Alert(Resources.Common.Error, r.Summary).Show();
                        return;
                    }
                    else
                    {
                        b.recordId = r.recordId;
                        //Add this record to the store
                        this.Store1.Insert(0, b);

                        //Display successful notification
                        Notification.Show(new NotificationConfig
                        {
                            Title = Resources.Common.Notification,
                            Icon  = Icon.Information,
                            Html  = Resources.Common.RecordSavingSucc
                        });

                        this.EditRecordWindow.Close();
                        RowSelectionModel sm = this.GridPanel1.GetSelectionModel() as RowSelectionModel;
                        sm.DeselectAll();
                        sm.Select(b.recordId.ToString());
                    }
                }
                catch (Exception ex)
                {
                    //Error exception displaying a messsage box
                    X.MessageBox.ButtonText.Ok = Resources.Common.Ok;
                    X.Msg.Alert(Resources.Common.Error, Resources.Common.ErrorSavingRecord).Show();
                }
            }
            else
            {
                //Update Mode

                try
                {
                    //getting the id of the record
                    PostRequest <CertificateLevel> request = new PostRequest <CertificateLevel>();
                    request.entity = b;
                    PostResponse <CertificateLevel> r = _employeeService.ChildAddOrUpdate <CertificateLevel>(request);                      //Step 1 Selecting the object or building up the object for update purpose

                    //Step 2 : saving to store

                    //Step 3 :  Check if request fails
                    if (!r.Success)//it maybe another check
                    {
                        X.MessageBox.ButtonText.Ok = Resources.Common.Ok;
                        X.Msg.Alert(Resources.Common.Error, r.Summary).Show();
                        return;
                    }
                    else
                    {
                        ModelProxy record = this.Store1.GetById(id);
                        BasicInfoTab.UpdateRecord(record);
                        record.Commit();
                        Notification.Show(new NotificationConfig
                        {
                            Title = Resources.Common.Notification,
                            Icon  = Icon.Information,
                            Html  = Resources.Common.RecordUpdatedSucc
                        });
                        this.EditRecordWindow.Close();
                    }
                }
                catch (Exception ex)
                {
                    X.MessageBox.ButtonText.Ok = Resources.Common.Ok;
                    X.Msg.Alert(Resources.Common.Error, Resources.Common.ErrorUpdatingRecord).Show();
                }
            }
        }
示例#17
0
        /// <summary>
        /// Context menu opening, we update the menus' statuses.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmListSkills_Opening(object sender, CancelEventArgs e)
        {
            TreeNode         node         = treeView.SelectedNode;
            Mastery          masteryLevel = node?.Tag as Mastery;
            CertificateLevel certLevel    = node?.Tag as CertificateLevel;

            planToLevel.Visible = planToLevelSeparator.Visible = m_plan != null && node != null;

            if (m_plan != null)
            {
                if (masteryLevel != null)
                {
                    // Update "add to" menu
                    planToLevel.Enabled = !m_plan.WillGrantEligibilityFor(masteryLevel);
                    planToLevel.Text    = $"Plan \"{masteryLevel}\"";
                }
                // When a certificate is selected
                else if (certLevel != null)
                {
                    // Update "add to" menu
                    planToLevel.Enabled = !m_plan.WillGrantEligibilityFor(certLevel);
                    planToLevel.Text    = $"Plan \"{certLevel.Certificate.Name}\"";
                }
                // When a skill is selected
                else if (node != null)
                {
                    // Update "add to" menu
                    var prereq = node.Tag as SkillLevel;
                    if (prereq != null)
                    {
                        Skill skill = prereq.Skill;
                        planToLevel.Enabled = skill.Level < prereq.Level && !m_plan.
                                              IsPlanned(skill, prereq.Level);
                        planToLevel.Text = $"Plan \"{skill} {Skill.GetRomanFromInt(prereq.Level)}\"";
                    }
                }
            }
            // Update "show in skill browser" text
            showInBrowserMenu.Text = certLevel != null ? "Show in Certificate Browser" :
                                     "Show in Skill Browser";

            // Update "show in skill browser" menu
            showInBrowserMenu.Visible = (node != null && masteryLevel == null);

            // Update "show in skill explorer" menu
            showInExplorerMenu.Visible = (node != null && masteryLevel == null && certLevel == null);

            // Update "show in" menu
            showInMenuSeparator.Visible = (node != null && masteryLevel == null);

            // "Collapse" and "Expand" menus
            int subNodeCount = node?.GetNodeCount(true) ?? 0;

            tsmCollapseSelected.Visible = subNodeCount > 0 && node.IsExpanded;
            tsmExpandSelected.Visible   = subNodeCount > 0 && !node.IsExpanded;

            tsmExpandSelected.Text = (subNodeCount > 0 && !node.IsExpanded) ?
                                     $"Expand \"{node.Text}\"" : string.Empty;
            tsmCollapseSelected.Text = (subNodeCount > 0 && node.IsExpanded) ?
                                       $"Collapse \"{node.Text}\"" : string.Empty;

            toggleSeparator.Visible = subNodeCount > 0;

            // "Expand All" and "Collapse All" menus
            tsmCollapseAll.Enabled = tsmCollapseAll.Visible = m_allExpanded;
            tsmExpandAll.Enabled   = tsmExpandAll.Visible = !tsmCollapseAll.Enabled;
        }