private static void UpdateHelpStack() { needStackUpdate = false; foreach (Form f in EditorHelper.GetZSortedAppWindows()) { if (!f.Visible) { continue; } if (!new Rectangle(f.Location, f.Size).Contains(Cursor.Position)) { continue; } Point localPos = f.PointToClient(Cursor.Position); hoveredControl = f.GetChildAtPointDeep(localPos, GetChildAtPointSkip.Invisible | GetChildAtPointSkip.Transparent); break; } Control c; HelpInfo help; // Get rid of disposed Controls c = hoveredHelpProvider as Control; if (c == null || c.IsDisposed) { hoveredHelpProvider = null; hoveredHelpCaptured = false; } // An IHelpProvider has captured the mouse: Ask what to do with it. if (hoveredHelpCaptured) { help = hoveredHelpProvider.ProvideHoverHelp(c.PointToClient(Cursor.Position), ref hoveredHelpCaptured); // Update provider's help info stack.UpdateFromProvider(hoveredHelpProvider, help); // If still in charge: Return early. if (hoveredHelpCaptured) { return; } } // No IHelpProvider in charge: Find one that provides help help = null; IHelpProvider lastHelpProvider = hoveredHelpProvider; foreach (IHelpProvider hp in hoveredControl.GetControlAncestors <IHelpProvider>()) { c = hp as Control; help = hp.ProvideHoverHelp(c.PointToClient(Cursor.Position), ref hoveredHelpCaptured); hoveredHelpProvider = hp; if (help != null || hoveredHelpCaptured) { break; } } // Update help system based on the result. if (lastHelpProvider != hoveredHelpProvider) { stack.UpdateFromProvider(lastHelpProvider, hoveredHelpProvider, help); } else if (hoveredHelpProvider != null) { stack.UpdateFromProvider(hoveredHelpProvider, help); } }
HelpInfo IHelpProvider.ProvideHoverHelp(Point localPos, ref bool captured) { // A dropdown is opened. Provide dropdown help. IPopupControlHost dropdownEdit = this.FocusEditor as IPopupControlHost; if (dropdownEdit != null && dropdownEdit.IsDropDownOpened) { EnumPropertyEditor enumEdit = dropdownEdit as EnumPropertyEditor; FlaggedEnumPropertyEditor enumFlagEdit = dropdownEdit as FlaggedEnumPropertyEditor; ObjectSelectorPropertyEditor objectSelectorEdit = dropdownEdit as ObjectSelectorPropertyEditor; // Its able to provide help. Redirect. if (dropdownEdit is IHelpProvider) { captured = true; Point dropdownEditorPos = this.GetEditorLocation(dropdownEdit as PropertyEditor, true); return((dropdownEdit as IHelpProvider).ProvideHoverHelp(new Point(localPos.X - dropdownEditorPos.X, localPos.Y - dropdownEditorPos.Y), ref captured)); } // Special case: Its a known basic dropdown. else if (enumEdit != null) { captured = true; if (enumEdit.DropDownHoveredName != null) { return(HelpInfo.FromMember(enumEdit.EditedType.GetField(enumEdit.DropDownHoveredName, ReflectionHelper.BindAll))); } else { FieldInfo field = enumEdit.EditedType.GetField(enumEdit.DisplayedValue.ToString(), ReflectionHelper.BindAll); if (field != null) { return(HelpInfo.FromMember(field)); } } } else if (enumFlagEdit != null) { captured = true; if (enumFlagEdit.DropDownHoveredItem != null) { return(HelpInfo.FromMember(enumFlagEdit.EditedType.GetField(enumFlagEdit.DropDownHoveredItem.Caption, ReflectionHelper.BindAll))); } else { FieldInfo field = enumFlagEdit.EditedType.GetField(enumFlagEdit.DisplayedValue.ToString(), ReflectionHelper.BindAll); if (field != null) { return(HelpInfo.FromMember(field)); } } } else if (objectSelectorEdit != null) { captured = true; if (objectSelectorEdit.DropDownHoveredObject != null) { return(HelpInfo.FromObject(objectSelectorEdit.DropDownHoveredObject.Value)); } else { return(HelpInfo.FromObject(objectSelectorEdit.DisplayedValue)); } } // No help available. return(null); } captured = false; // Pick an editor and see if it has access to an actual IHelpProvider PropertyEditor pickedEditor = this.PickEditorAt(localPos.X, localPos.Y, true); PropertyEditor helpEditor = pickedEditor; while (helpEditor != null) { Point helpEditorPos = this.GetEditorLocation(helpEditor, true); if (helpEditor is IHelpProvider) { IHelpProvider localProvider = helpEditor as IHelpProvider; HelpInfo localHelp = localProvider.ProvideHoverHelp(new Point(localPos.X - helpEditorPos.X, localPos.Y - helpEditorPos.Y), ref captured); if (localHelp != null) { return(localHelp); } } helpEditor = helpEditor.ParentEditor; } // If not, default to member or type information if (pickedEditor != null) { if (!string.IsNullOrEmpty(pickedEditor.PropertyDesc)) { return(HelpInfo.FromText(pickedEditor.PropertyName, pickedEditor.PropertyDesc)); } else if (pickedEditor.EditedMember != null) { return(HelpInfo.FromMember(pickedEditor.EditedMember)); } else if (pickedEditor.EditedType != null) { return(HelpInfo.FromMember(pickedEditor.EditedType)); } } return(null); }
private static void UpdateHelpStack() { needStackUpdate = false; // Retrieving all windows in a z-sorted way is a "time consuming" (~ 0.05ms) and API-heavy // query, and we don't need to be that accurate. Don't do it every time. Once a second is enough. bool updateGlobalWindows = globalWindows == null || (DateTime.Now - lastGlobalWindowUpdate).TotalMilliseconds > 1000 || globalWindows.Any(f => f.IsDisposed); if (updateGlobalWindows) { lastGlobalWindowUpdate = DateTime.Now; globalWindows = EditorHelper.GetZSortedAppWindows(); } // Iterate through our list of windows to find the one we're hovering foreach (Form form in globalWindows) { if (!form.Visible) { continue; } if (!new Rectangle(form.Location, form.Size).Contains(Cursor.Position)) { continue; } Point localPos = form.PointToClient(Cursor.Position); hoveredControl = form.GetChildAtPointDeep(localPos, GetChildAtPointSkip.Invisible | GetChildAtPointSkip.Transparent); break; } Control c; HelpInfo help; // Get rid of disposed Controls c = hoveredHelpProvider as Control; if (c == null || c.IsDisposed) { hoveredHelpProvider = null; hoveredHelpCaptured = false; } // An IHelpProvider has captured the mouse: Ask what to do with it. if (hoveredHelpCaptured) { help = hoveredHelpProvider.ProvideHoverHelp(c.PointToClient(Cursor.Position), ref hoveredHelpCaptured); // Update provider's help info stack.UpdateFromProvider(hoveredHelpProvider, help); // If still in charge: Return early. if (hoveredHelpCaptured) { return; } } // No IHelpProvider in charge: Find one that provides help help = null; IHelpProvider lastHelpProvider = hoveredHelpProvider; foreach (IHelpProvider hp in hoveredControl.GetControlAncestors <IHelpProvider>()) { c = hp as Control; help = hp.ProvideHoverHelp(c.PointToClient(Cursor.Position), ref hoveredHelpCaptured); hoveredHelpProvider = hp; if (help != null || hoveredHelpCaptured) { break; } } // Update help system based on the result. if (lastHelpProvider != hoveredHelpProvider) { stack.UpdateFromProvider(lastHelpProvider, hoveredHelpProvider, help); } else if (hoveredHelpProvider != null) { stack.UpdateFromProvider(hoveredHelpProvider, help); } }