| File: System\Windows\Forms\Design\ToolStripEditorManager.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms.Design\src\System.Windows.Forms.Design.csproj (System.Windows.Forms.Design) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable using System.ComponentModel; using System.ComponentModel.Design; using System.Drawing; using System.Windows.Forms.Design.Behavior; namespace System.Windows.Forms.Design; /// <summary> /// This internal Class is used by all TOPLEVEL ToolStripItems to show the InSitu Editor. When the ToolStripItem /// receives the MouseDown on its Glyph it calls the "ActivateEditor" Function on this EditorManager. The /// ActivateEditor Function checks for any existing "EDITOR" active, closes that down and now opens the new /// editor on the "AdornerWindow". This class is also responsible for "hookingup" to the F2 Command on VS. /// </summary> internal class ToolStripEditorManager { // Local copy of BehaviorService so that we can add the InSitu Editor to the AdornerWindow. private readonly BehaviorService _behaviorService; // Component for this InSitu Editor... (this is a ToolStripItem) that wants to go into InSitu private readonly IDesignerHost _designerHost; // The current Bounds of the InSitu Editor on Adorner Window.. These are required for invalidation. private Rectangle _lastKnownEditorBounds = Rectangle.Empty; // The encapsulated Editor. private ToolStripEditorControl _editor; // Actual ToolStripEditor for the current ToolStripItem. private ToolStripTemplateNode _editorUI; // The Current ToolStripItem that needs to go into the InSitu Mode. // We keep a local copy so that when a new item comes in, we can "ROLLBACK" the existing edit. private ToolStripItem _currentItem; // The designer for current ToolStripItem. private ToolStripItemDesigner _itemDesigner; public ToolStripEditorManager(IComponent comp) { _behaviorService = (BehaviorService)comp.Site.GetService(typeof(BehaviorService)); _designerHost = (IDesignerHost)comp.Site.GetService(typeof(IDesignerHost)); } /// <summary> /// Activates the editor for the given item.If there's still an editor around for the previous-edited item, it is /// deactivated. Pass in 'null' to deactivate and remove the current editor, if any. /// </summary> internal void ActivateEditor(ToolStripItem item) { if (item == _currentItem) { return; } // Remove old editor if (_editor is not null) { _behaviorService.AdornerWindowControl.Controls.Remove(_editor); _behaviorService.Invalidate(_editor.Bounds); _editorUI = null; _editor = null; _currentItem = null; _itemDesigner.IsEditorActive = false; // Show the previously edited glyph if (_currentItem is not null) { _currentItem = null; } } if (item is not null) { // Add new editor from the item... _currentItem = item; if (_designerHost is not null) { _itemDesigner = (ToolStripItemDesigner)_designerHost.GetDesigner(_currentItem); } _editorUI = _itemDesigner.Editor; // If we got an editor, position and focus it. if (_editorUI is not null) { // Hide this glyph while it's being edited _itemDesigner.IsEditorActive = true; _editor = new ToolStripEditorControl(_editorUI.EditorToolStrip, _editorUI.Bounds); _behaviorService.AdornerWindowControl.Controls.Add(_editor); _lastKnownEditorBounds = _editor.Bounds; _editor.BringToFront(); // this is important since the ToolStripEditorControl listens to textChanged messages from TextBox. _editorUI._ignoreFirstKeyUp = true; // Select the Editor... Put Text and Select it ... _editorUI.FocusEditor(_currentItem); } } } /// <summary> /// This will remove the Command for F2. /// </summary> internal static void CloseManager() { } /// <summary> /// This LISTENs to the Editor Resize for resizing the InSitu edit on the Adorner Window ... CURRENTLY DISABLED. /// </summary> private void OnEditorResize(object sender, EventArgs e) { // THIS IS CURRENTLY DISABLE !!!!! TO DO !! SHOULD WE SUPPORT AUTOSIZED INSITU ????? _behaviorService.Invalidate(_lastKnownEditorBounds); if (_editor is not null) { _lastKnownEditorBounds = _editor.Bounds; } } // Private Class Implemented for InSitu Editor. This class just Wraps the ToolStripEditor from the TemplateNode // and puts it in a Panel. private class ToolStripEditorControl : Panel { private readonly Control _wrappedEditor; private Rectangle _bounds; public ToolStripEditorControl(Control editorToolStrip, Rectangle bounds) { _wrappedEditor = editorToolStrip; Bounds1 = bounds; _wrappedEditor.Resize += OnWrappedEditorResize; Controls.Add(editorToolStrip); Location = new Point(bounds.X, bounds.Y); Text = "InSituEditorWrapper"; UpdateSize(); } public Rectangle Bounds1 { get => _bounds; set => _bounds = value; } private void OnWrappedEditorResize(object sender, EventArgs e) { } private void UpdateSize() => Size = new Size(_wrappedEditor.Size.Width, _wrappedEditor.Size.Height); } }