/// <summary> /// Refreshes the label display - resetting text, width and height /// </summary> private void UpdateLabel(NormalLabel label) { label.Text = ((ExpressionMemberContainer)label.Tag).GetValueDisplay(); if (string.IsNullOrWhiteSpace(label.Text) && label is NormalSelectableLabel) label.Text = "[]"; // display something for clickable empty labels if (label as NormalSelectableLabel != null) (label as NormalSelectableLabel).SpecialMode = !((ExpressionMemberContainer)label.Tag).IsValid; // Special mode means there's an error with the contents label.RequiresLinebreak = ((ExpressionMemberContainer)label.Tag).Member.RequiresLinebreak; label.UpdateSize(); }
/// <summary> /// Label was clicked by mouse or activated by keyboard. Not really subscribed to an event but rather called from OnKeydown and other methods subscribed to event. /// </summary> private void _E_l_Activated(NormalLabel label, bool byMouse = false, ExpressionMemberValueEditorActivationMode mode = ExpressionMemberValueEditorActivationMode.Normal) { Point where; if (byMouse) where = Cursor.Position; else { where = new Point(); where.X += label.Width / 2; where.Y += label.Height / 2; where = label.PointToScreen(where); } ((ExpressionMemberContainer)label.Tag).OnClick(label, where, mode); }
/// <summary> /// Update the expression shown in the flow layout panel. Makes sure to select the same item that was selected before. /// </summary> public void UpdateExpression() { // Part 1: Remember information about what was chosen Control activeControl = null; foreach (Control c in FlowLayoutPanelMain.Controls) if (c.Focused) activeControl = c; ExpressionMemberValueDescription lastFocusedValueDescription = (activeControl != null && activeControl is NormalSelectableLabel && activeControl.Tag is ExpressionMemberContainer) ? ((ExpressionMemberContainer)activeControl.Tag).Member.ValueDescription : null; string lastFocusedValueName = (activeControl != null && activeControl is NormalSelectableLabel && activeControl.Tag is ExpressionMemberContainer) ? ((ExpressionMemberContainer)activeControl.Tag).Member.Name : null; List<NormalLabel> listMatchesValueDescription = new List<NormalLabel>(); List<NormalLabel> listMatchesValueName = new List<NormalLabel>(); // Part 2: Repopulating FlowLayoutPanel TreeNode node = TreeViewStatements.SelectedNode; if (node == null || !(node.Tag is MissionStatement)) return; MissionStatement statement = (MissionStatement)node.Tag; int countActiveLabels = 0; FlowLayoutPanelMain.SuspendLayout(); FlowLayoutPanel_Clear(); //TODO: Update the expression in the flowchart [Forgot what this means] <-- WTF does this mean? // Maybe originally I wanted to update the expression directly in the flow chart without clearing and repopulating it? foreach (ExpressionMemberContainer item in statement.Expression) { if (!item.Member.ValueDescription.IsDisplayed) continue; NormalLabel label; if (item.Member.ValueDescription.IsInteractive) { label = new NormalSelectableLabel(); label.MouseClick += _E_l_MouseClick; label.PreviewKeyDown += _E_l_PreviewKeyDown; label.Number = ++countActiveLabels; } else { label = new NormalLabel(); } label.Tag = item; if (item.Member.RequiresLinebreak) FlowLayoutPanelMain.SetFlowBreak(FlowLayoutPanelMain.Controls[FlowLayoutPanelMain.Controls.Count - 1], true); FlowLayoutPanelMain.Controls.Add(label); UpdateLabel(label); } // Part 3: Selecting label that was selected before update //Find all items that match value name or value description foreach (Control c in FlowLayoutPanelMain.Controls) { if (((ExpressionMemberContainer)((NormalLabel)c).Tag).Member.Name == lastFocusedValueName) listMatchesValueName.Add((NormalLabel)c); if (((ExpressionMemberContainer)((NormalLabel)c).Tag).Member.ValueDescription == lastFocusedValueDescription) listMatchesValueDescription.Add((NormalLabel)c); } switch (listMatchesValueDescription.Count) { case 0: //If none matches description - pick one that matches name if (listMatchesValueName.Count > 0) listMatchesValueName[0].Focus(); break; case 1: //If only one matches the description - pick it listMatchesValueDescription[0].Focus(); break; default: //If more than one matches the description, but none match the name - pick first from description if (listMatchesValueName.Count == 0) listMatchesValueDescription[0].Focus(); //If at least one matches in name ... else { //We need to narrow down... for (int i = listMatchesValueName.Count - 1; i >= 0; i--) { //Remove all that match in name that do not match in description if (!listMatchesValueDescription.Contains(listMatchesValueName[i])) listMatchesValueName.RemoveAt(i); } //If none of those matching in name match in description - pick first from description if (listMatchesValueName.Count == 0) listMatchesValueDescription[0].Focus(); //If only one matches in name and in description - pick it if (listMatchesValueName.Count == 1) listMatchesValueName[0].Focus(); //If more than one matches in name and in description... if (listMatchesValueName.Count > 1) { //We need to narrow down again for (int i = listMatchesValueDescription.Count - 1; i >= 0; i--) { //Remove all that match in description but do not match in name if (!listMatchesValueName.Contains(listMatchesValueDescription[i])) listMatchesValueDescription.RemoveAt(i); } //If at least one matches in description and in name = pick first from description if (listMatchesValueDescription.Count >= 1) listMatchesValueDescription[0].Focus(); else // else pick first from those matching by name listMatchesValueName[0].Focus(); } } break; } FlowLayoutPanelMain.ResumeLayout(); }