private Size measureTooltip(TooltipModel tooltip, Font titleFont) { string measuredContentText; if (!string.IsNullOrEmpty(tooltip.Title) && !string.IsNullOrEmpty(tooltip.Text)) { measuredContentText = "\n" + tooltip.Text; } else { measuredContentText = tooltip.Text; } var formatFlags = TextFormatFlags.GlyphOverhangPadding | TextFormatFlags.WordBreak; if (!Runtime.IsMono) { formatFlags |= TextFormatFlags.NoPadding | TextFormatFlags.TextBoxControl; } var graphics = _tooltipTextbox.CreateGraphics(); var baseSize = new Size(400, 300).ByDpi(); Size titleSize; if (string.IsNullOrEmpty(tooltip.Title)) { titleSize = new Size(0, 0); } else { titleSize = graphics.MeasureText( tooltip.Title, titleFont, baseSize, formatFlags); } Size contentSize; if (string.IsNullOrEmpty(measuredContentText)) { contentSize = new Size(0, 0); } else { Graphics g = Runtime.IsMono ? null : graphics; contentSize = g.MeasureText( measuredContentText, _tooltipTextbox.Font, baseSize, formatFlags); } int contentWidth = Math.Max(titleSize.Width, contentSize.Width); // ideographic strings are under-measured Size cjkDelta = tooltip.Text.IsCjk() ? new Size(32, 6).ByDpi() : default; int clickableWidthDelta = Clickable ? titleSize.Width + (int)(_buttonClose.Width * 1.25f) - TextPadding.Horizontal / 2 - contentWidth : 0; var size = new Size( contentWidth + TextPadding.Horizontal + 2 + Math.Max(cjkDelta.Width, clickableWidthDelta), titleSize.Height + contentSize.Height + TextPadding.Vertical + cjkDelta.Height); if (Runtime.IsMono) { size += MonoLineInterval.MultiplyBy(measuredContentText.Count(_ => _ == '\n')); } return(size); }
private Size measureTooltip(TooltipModel tooltip) { string measuredContentText; if (!string.IsNullOrEmpty(tooltip.Title) && !string.IsNullOrEmpty(tooltip.Text)) { measuredContentText = "\n" + tooltip.Text; } else { measuredContentText = tooltip.Text; } const TextFormatFlags formatFlags = TextFormatFlags.GlyphOverhangPadding | TextFormatFlags.NoPadding | TextFormatFlags.TextBoxControl | TextFormatFlags.WordBreak; var graphics = _tooltipTextbox.CreateGraphics(); var baseSize = new Size(400, 300).ByDpi(); Size titleSize; if (string.IsNullOrEmpty(tooltip.Title)) { titleSize = new Size(0, 0); } else { titleSize = graphics.MeasureText( tooltip.Title, new Font(_tooltipTextbox.Font, FontStyle.Bold), baseSize, formatFlags); } Size contentSize; if (string.IsNullOrEmpty(measuredContentText)) { contentSize = new Size(0, 0); } else { contentSize = graphics.MeasureText( measuredContentText, _tooltipTextbox.Font, baseSize, formatFlags); } int contentWidth = Math.Max(titleSize.Width, contentSize.Width); // ideographic strings are under-measured Size cjkDelta = tooltip.Text.IsCjk() ? new Size(32, 6).ByDpi() : default; int clickableWidthDelta = Clickable ? titleSize.Width + (int)(_buttonClose.Width * 1.25f) - TextPadding.Horizontal / 2 - contentWidth : 0; var size = new Size( contentWidth + TextPadding.Horizontal + 2 + Math.Max(cjkDelta.Width, clickableWidthDelta), titleSize.Height + contentSize.Height + TextPadding.Vertical + cjkDelta.Height); return(size); }
public void ShowTooltip(TooltipModel tooltip) { _tooltip = tooltip; Clickable = tooltip.Clickable; _buttonClose.Visible = Clickable; _tooltipTextbox.ResetText(); Font titleFont = new Font(_tooltipTextbox.Font, FontStyle.Bold); if (!string.IsNullOrEmpty(tooltip.Title)) { _tooltipTextbox.AppendText(tooltip.Title); _tooltipTextbox.Select(0, tooltip.Title.Length); _tooltipTextbox.SelectionFont = titleFont; } if (!string.IsNullOrWhiteSpace(tooltip.Text)) { if (_tooltipTextbox.TextLength > 0) { _tooltipTextbox.AppendText("\n\n"); } var titleLength = _tooltipTextbox.TextLength; _tooltipTextbox.AppendText(tooltip.Text); if (tooltip.HighlightRanges != null) { foreach (var range in tooltip.HighlightRanges) { _tooltipTextbox.SelectionStart = titleLength + range.Index; _tooltipTextbox.SelectionLength = range.Length; if (range.IsContext) { _tooltipTextbox.SelectionBackColor = tooltip.HighlightOptions.HighlightContextColor; } else { _tooltipTextbox.SelectionBackColor = tooltip.HighlightOptions.HighlightColor; } } } } _tooltipTextbox.SelectionStart = 0; _tooltipTextbox.SelectionLength = 0; var size = measureTooltip(tooltip, titleFont); var screenBounds = tooltip.Control.RectangleToScreen(tooltip.ObjectBounds); var parentForm = _tooltip.Control.ParentForm(); Rectangle bounds; if (tooltip.UnderMouse) { bounds = new Rectangle(Cursor.Position - size.MultiplyBy(0.5f).Round(), size); } else { var cursor = tooltip.Cursor?.Invoke0(tooltip.Control.PointToScreen); bounds = allocateTooltip( size, screenBounds, cursor, TooltipMargin, parentForm, tooltip.PositionPreference?.Invoke(screenBounds)); } if (tooltip.Clickable) { _tooltipTextbox.Cursor = Cursors.IBeam; } else { _tooltipTextbox.Cursor = Cursors.Arrow; } var parentFormPrev = this.ParentForm(); if (parentForm != parentFormPrev) { parentFormPrev?.Controls.Remove(this); parentForm.Controls.Add(this); } Size = bounds.Size; Location = parentForm.PointToClient(bounds.Location); Visible = true; BringToFront(); }
public void ShowTooltip(TooltipModel tooltip) { _tooltip = tooltip; Clickable = tooltip.Clickable; _buttonClose.Visible = Clickable; var titleFont = new Font(_tooltipTextbox.Font, FontStyle.Bold); _tooltipTextbox.ResetText(); if (!string.IsNullOrEmpty(tooltip.Title)) { _tooltipTextbox.AppendText(tooltip.Title); _tooltipTextbox.Select(0, tooltip.Title.Length); _tooltipTextbox.SelectionFont = titleFont; } if (!string.IsNullOrWhiteSpace(tooltip.Text)) { if (_tooltipTextbox.TextLength > 0) { _tooltipTextbox.AppendText("\n\n"); } var titleLength = _tooltipTextbox.TextLength; _tooltipTextbox.AppendText(tooltip.Text); if (tooltip.HighlightRanges != null) { foreach (var range in tooltip.HighlightRanges) { _tooltipTextbox.SelectionStart = titleLength + range.Index; _tooltipTextbox.SelectionLength = range.Length; if (range.IsContext) { _tooltipTextbox.SelectionBackColor = tooltip.HighlightOptions.HighlightContextColor; } else { _tooltipTextbox.SelectionBackColor = tooltip.HighlightOptions.HighlightColor; } } } } _tooltipTextbox.SelectionStart = 0; _tooltipTextbox.SelectionLength = 0; var size = measureTooltip(tooltip); var screenBounds = tooltip.Control.RectangleToScreen(tooltip.ObjectBounds); var cursor = tooltip.Cursor?.Invoke0(tooltip.Control.PointToScreen); var bounds = allocateTooltip(size, screenBounds, cursor, TooltipMargin, tooltip.PositionPreference?.Invoke(screenBounds)); if (_tooltipTextbox.Focused) { _tooltipFocusTarget.Focus(); } if (tooltip.Clickable) { _tooltipTextbox.Cursor = Cursors.IBeam; } else { _tooltipTextbox.Cursor = Cursors.Arrow; } Size = bounds.Size; Application.DoEvents(); Location = bounds.Location; }
private void mouseMove(object sender, MouseEventArgs e) { var command = _control.GetCommand(e.Location, MouseButtons.None); if (!command.HasValue) { Hide?.Invoke(); return; } var property = _control.Properties[command.Value.ButtonIndex]; if (string.IsNullOrEmpty(property)) { Hide?.Invoke(); return; } var bounds = _control.GetPaintingRectangle(command.Value.ButtonIndex, command.Value.ClickedState); var model = new TooltipModel { Id = "qf." + property, Control = _control, ObjectBounds = bounds, Cursor = bounds.Center(), Text = property, PositionPreference = getPositionPreference }; Show?.Invoke(model); Func <ExtremumFinder <TooltipPosition>, ExtremumFinder <TooltipPosition> > getPositionPreference(Rectangle target) { Func <TooltipPosition, int> verticalDistanceFrom(Rectangle t) => c => { int dy = c.Bounds.CenterY() - t.CenterY(); return(PreferTooltipFromTop ? Math.Abs((-dy).MultiplyIfNegative(1.5f)) : Math.Abs(dy.MultiplyIfNegative(1.5f))); }; Func <TooltipPosition, int> horizontalDistanceFrom(Rectangle t) => c => { int dx = c.Bounds.CenterX() - t.CenterX(); return(PreferTooltipFromLeft ? Math.Abs((-dx).MultiplyIfNegative(1.5f)) : Math.Abs(dx.MultiplyIfNegative(1.5f))); }; if (PreferHorizontalShift) { return(_ => _ .ThenAtMin(verticalDistanceFrom(target)) .ThenAtMin(c => PreferTooltipFromLeft ? c.Bounds.X : -c.Bounds.X)); } else { return(_ => _ .ThenAtMin(horizontalDistanceFrom(target)) .ThenAtMin(c => PreferTooltipFromTop ? c.Bounds.Y : -c.Bounds.Y)); } } }
private Size measureTooltip(TooltipModel tooltip) { string measuredContentText; if (!string.IsNullOrEmpty(tooltip.Title) && !string.IsNullOrEmpty(tooltip.Text)) { measuredContentText = "\n" + tooltip.Text; } else { measuredContentText = tooltip.Text; } const TextFormatFlags formatFlags = TextFormatFlags.GlyphOverhangPadding | TextFormatFlags.NoPadding | TextFormatFlags.Left | TextFormatFlags.TextBoxControl | TextFormatFlags.WordBreak; var graphics = _tooltipTextbox.CreateGraphics(); Size titleSize; if (string.IsNullOrEmpty(tooltip.Title)) { titleSize = new Size(0, 0); } else { titleSize = graphics.MeasureText( tooltip.Title, new Font(_tooltipTextbox.Font, FontStyle.Bold), _tooltipTextbox.Size, formatFlags); } Size contentSize; if (string.IsNullOrEmpty(measuredContentText)) { contentSize = new Size(0, 0); } else { contentSize = graphics.MeasureText( measuredContentText, _tooltipTextbox.Font, _tooltipTextbox.Size, formatFlags); } int contentWidth = Math.Max(titleSize.Width, contentSize.Width); // ideographic strings are under-measured int cjkTermH = tooltip.Text.IsCjk() ? 32 : 0; if (Clickable) { cjkTermH = Math.Max(cjkTermH, titleSize.Width - contentWidth + (int)(_buttonClose.Width * 1.25f) - TextPadding); } int cjkTermV = tooltip.Text.IsCjk() ? 6 : 0; var cjkTermSize = new Size(cjkTermH, cjkTermV).ByDpi(); var size = new Size( contentWidth + _tooltipTextbox.Margin.Horizontal + 2 + cjkTermSize.Width, titleSize.Height + contentSize.Height + _tooltipTextbox.Margin.Vertical + cjkTermSize.Height); return(size); }
private void showFieldTooltip(Point position) { var cursorPosition = _view.PointToClient(position); var hitInfo = _view.CalcHitInfo(cursorPosition); var dataSource = _view.FindRow(hitInfo.RowHandle); if (!hitInfo.AlignButtonDirection.HasValue && (dataSource == null || !hitInfo.FieldBounds.HasValue)) { Hide?.Invoke(); return; } if (hitInfo.IsSortButton) { Show?.Invoke(new TooltipModel { Id = $"{_view.Name}.{hitInfo.RowHandle}.{hitInfo.FieldName}.sort", ObjectBounds = hitInfo.ButtonBounds, Control = _view, Title = "Sort by " + hitInfo.FieldName, Text = "Click to sort by this field.\r\n" + "\r\n" + "Shift+Click to ADD this field to sorting. Currently sorted fields will have higher sort priority.\r\n" + "\r\n" + "Ctrl+Click to REMOVE this field from sorting. Other fields sort order will remain unchanged.\r\n" + "\r\n" + "Repeated click on sort button cycles sort order between Ascending, Descending, None.\r\n" + "\r\n" + "Hold Alt key when hovering to prevent showing this button. Helps selecting text in small fields.", Clickable = false }); } else { if (hitInfo.IsSearchButton) { throw new NotSupportedException(); } if (hitInfo.CustomButtonIndex >= 0) { var tooltip = new TooltipModel { Id = $"{_view.Name}.{hitInfo.RowHandle}.{hitInfo.FieldName}.", ObjectBounds = hitInfo.ButtonBounds, Control = _view, Clickable = false }; if (hitInfo.CustomButtonIndex == DeckListLayout.CustomButtonAdd) { tooltip.Id += "add"; tooltip.Text = "Save this deck"; } else if (hitInfo.CustomButtonIndex == DeckListLayout.CustomButtonRemove) { tooltip.Id += "remove"; tooltip.Title = "Remove this deck"; tooltip.Text = "Removes this deck from the list.\r\n" + "NOTE: be careful, you cannot undo this."; } else if (hitInfo.CustomButtonIndex == DeckListLayout.CustomButtonRename) { tooltip.Id += "rename"; tooltip.Text = "Rename this deck"; } else if (hitInfo.CustomButtonIndex == DeckListLayout.CustomButtonOpen) { tooltip.Id += "open"; tooltip.Title = "Open this deck"; tooltip.Text = "Relaces currently opened deck with this one"; } else { throw new NotSupportedException(); } Show?.Invoke(tooltip); } else if (hitInfo.AlignButtonDirection.HasValue) { Show?.Invoke(new TooltipModel { Id = $"{_view.Name}.{hitInfo.RowHandle}.{hitInfo.FieldName}.align", ObjectBounds = _view.GetAlignButtonBounds(hitInfo), Control = _view, Title = "Viewport alignment", Text = "Aligns viewport by this corner.\r\n" + "\r\n" + "If this corner would be truncated\r\n" + "viewport will shift to fit it into the screen.", Clickable = false }); } else if (hitInfo.FieldName != null) { Show?.Invoke(new TooltipModel { Id = $"{_view.Name}.{hitInfo.RowHandle}.{hitInfo.FieldName}", ObjectBounds = hitInfo.FieldBounds.Value, Control = _view, Title = hitInfo.FieldName, Text = _view.GetText(hitInfo.RowHandle, hitInfo.FieldName), HighlightRanges = _view.GetHighlihgtTextRanges(hitInfo.RowHandle, hitInfo.FieldName), HighlightOptions = _view.ProbeCard.HighlightOptions, Clickable = true }); } } }
private void showFieldTooltip(Point position) { var cursorPosition = _view.PointToClient(position); var hitInfo = _view.CalcHitInfo(cursorPosition); var dataSource = _view.FindRow(hitInfo.RowHandle); if (!hitInfo.AlignButtonDirection.HasValue && (dataSource == null || !hitInfo.FieldBounds.HasValue)) { Hide?.Invoke(); return; } if (hitInfo.IsSortButton) { Show?.Invoke(new TooltipModel { Id = $"{_view.Name}.{hitInfo.RowHandle}.{hitInfo.FieldName}.sort", ObjectBounds = hitInfo.ButtonBounds, Control = _view, Title = "Sort by " + hitInfo.FieldName, Text = "Click to sort by this field.\r\n" + "\r\n" + "Shift+Click to ADD this field to sorting. Currently sorted fields will have higher sort priority.\r\n" + "\r\n" + "Ctrl+Click to REMOVE this field from sorting. Other fields sort order will remain unchanged.\r\n" + "\r\n" + "Repeated click on sort button cycles sort order between Ascending, Descending, None.\r\n" + "\r\n" + "Hold Alt key when hovering to prevent showing this button. Helps selecting text in small fields.", Clickable = false }); } else { if (hitInfo.IsSearchButton) { _log.Error("Search button tooltip is not supported in DeckList layout view"); return; } if (hitInfo.CustomButtonIndex >= 0) { var tooltip = new TooltipModel { Id = $"{_view.Name}.{hitInfo.RowHandle}.{hitInfo.FieldName}.", ObjectBounds = hitInfo.ButtonBounds, Control = _view, Clickable = false }; if (hitInfo.IsAddButton()) { tooltip.Id += "add"; tooltip.Text = "Save this deck"; } else if (hitInfo.IsRemoveButton()) { tooltip.Id += "remove"; tooltip.Title = "Remove this deck"; tooltip.Text = "Removes this deck from the list.\r\n" + "NOTE: be careful, you cannot undo this."; } else if (hitInfo.IsRenameButton()) { tooltip.Id += "rename"; tooltip.Text = "Rename this deck"; } else if (hitInfo.IsOpenButton()) { tooltip.Id += "open"; tooltip.Title = "Open deck"; tooltip.Text = "Open the deck in it's original form as it was edited and saved.\r\n\r\n" + "Left-click to open in this tab, currently opened deck will be replaced.\r\n" + "Middle-click to open in new tab.\r\n\r\n"; } else if (hitInfo.IsOpenTransformedButton()) { tooltip.Id += "open_transformed"; tooltip.Title = "Open transformed deck"; tooltip.Text = "Transformed deck uses cards from your collection and cards with known price whenever possible.\r\n\r\n" + "Left-click to open in this tab, currently opened deck will be replaced.\r\n" + "Middle-click to open in new tab.\r\n\r\n"; } else { return; } Show?.Invoke(tooltip); } else if (hitInfo.AlignButtonDirection.HasValue) { Show?.Invoke(new TooltipModel { Id = $"{_view.Name}.{hitInfo.RowHandle}.{hitInfo.FieldName}.align", ObjectBounds = _view.GetAlignButtonBounds(hitInfo), Control = _view, Title = "Viewport alignment", Text = "Aligns viewport by this corner.\r\n" + "\r\n" + "If this corner would be truncated\r\n" + "viewport will shift to fit it into the screen.", Clickable = false }); } else if (hitInfo.FieldName != null) { Show?.Invoke(new TooltipModel { Id = $"{_view.Name}.{hitInfo.RowHandle}.{hitInfo.FieldName}", ObjectBounds = hitInfo.FieldBounds.Value, Control = _view, Title = hitInfo.FieldName, Text = _view.GetText(hitInfo.RowHandle, hitInfo.FieldName), HighlightRanges = _view.GetHighlightTextRanges(hitInfo.RowHandle, hitInfo.FieldName), HighlightOptions = _view.HighlightOptions, Clickable = true }); } } }