/// <summary> /// Constructor. /// </summary> /// <param name="block">Block for which MBP properties are retrieved.</param> private MbpInfo(TextElement block) { _margin = (Thickness)block.GetValue(Block.MarginProperty); _border = (Thickness)block.GetValue(Block.BorderThicknessProperty); _padding = (Thickness)block.GetValue(Block.PaddingProperty); _borderBrush = (Brush)block.GetValue(Block.BorderBrushProperty); }
internal static void OnContextMenuOpening(object sender, ContextMenuEventArgs e) { TextEditor textEditor = TextEditor._GetTextEditor(sender); if (textEditor == null || textEditor.TextView == null) { return; } Point position = Mouse.GetPosition(textEditor.TextView.RenderScope); ContextMenu contextMenu = null; bool flag = false; if (textEditor.IsReadOnly) { if ((e.CursorLeft != -1.0 && !textEditor.Selection.Contains(position)) || (e.CursorLeft == -1.0 && textEditor.Selection.IsEmpty)) { return; } } else if ((textEditor.Selection.IsEmpty || e.TargetElement is TextElement) && e.TargetElement != null) { contextMenu = (ContextMenu)e.TargetElement.GetValue(FrameworkElement.ContextMenuProperty); } else if (e.CursorLeft == -1.0) { TextPointer textPointer = TextEditorContextMenu.GetContentPosition(textEditor.Selection.Start) as TextPointer; if (textPointer != null) { for (TextElement textElement = textPointer.Parent as TextElement; textElement != null; textElement = (textElement.Parent as TextElement)) { contextMenu = (ContextMenu)textElement.GetValue(FrameworkElement.ContextMenuProperty); if (contextMenu != null) { flag = true; break; } } } } if (e.CursorLeft != -1.0) { if (!TextEditorMouse.IsPointWithinInteractiveArea(textEditor, Mouse.GetPosition(textEditor.UiScope))) { return; } if (contextMenu == null || !(e.TargetElement is UIElement)) { using (textEditor.Selection.DeclareChangeBlock()) { if (!textEditor.Selection.Contains(position)) { TextEditorMouse.SetCaretPositionOnMouseEvent(textEditor, position, MouseButton.Right, 1); } } } } if (contextMenu == null) { if (textEditor.UiScope.ReadLocalValue(FrameworkElement.ContextMenuProperty) == null) { return; } contextMenu = textEditor.UiScope.ContextMenu; } textEditor.IsContextMenuOpen = true; if (contextMenu != null && !flag) { contextMenu.HorizontalOffset = 0.0; contextMenu.VerticalOffset = 0.0; contextMenu.Closed += TextEditorContextMenu.OnContextMenuClosed; return; } textEditor.CompleteComposition(); if (contextMenu == null) { contextMenu = new TextEditorContextMenu.EditorContextMenu(); ((TextEditorContextMenu.EditorContextMenu)contextMenu).AddMenuItems(textEditor, e.UserInitiated); } contextMenu.Placement = PlacementMode.RelativePoint; contextMenu.PlacementTarget = textEditor.UiScope; ITextPointer textPointer2 = null; SpellingError spellingError = (contextMenu is TextEditorContextMenu.EditorContextMenu) ? textEditor.GetSpellingErrorAtSelection() : null; LogicalDirection logicalDirection; if (spellingError != null) { textPointer2 = spellingError.End; logicalDirection = LogicalDirection.Backward; } else if (e.CursorLeft == -1.0) { textPointer2 = textEditor.Selection.Start; logicalDirection = LogicalDirection.Forward; } else { logicalDirection = LogicalDirection.Forward; } if (textPointer2 != null && textPointer2.CreatePointer(logicalDirection).HasValidLayout) { double horizontalOffset; double verticalOffset; TextEditorContextMenu.GetClippedPositionOffsets(textEditor, textPointer2, logicalDirection, out horizontalOffset, out verticalOffset); contextMenu.HorizontalOffset = horizontalOffset; contextMenu.VerticalOffset = verticalOffset; } else { Point position2 = Mouse.GetPosition(textEditor.UiScope); contextMenu.HorizontalOffset = position2.X; contextMenu.VerticalOffset = position2.Y; } contextMenu.Closed += TextEditorContextMenu.OnContextMenuClosed; contextMenu.IsOpen = true; e.Handled = true; }
internal static void OnContextMenuOpening(object sender, ContextMenuEventArgs e) { TextEditor This = TextEditor._GetTextEditor(sender); const double KeyboardInvokedSentinel = -1.0; // e.CursorLeft has this value when the menu is invoked with the keyboard. if (This == null || This.TextView == null) { return; } // Get the mouse position that base on RenderScope which we will set // the caret on the RenderScope. Point renderScopeMouseDownPoint = Mouse.GetPosition(This.TextView.RenderScope); ContextMenu contextMenu = null; bool startPositionCustomElementMenu = false; if (This.IsReadOnly) { // If the TextEditor is ReadOnly, only take action if // 1. The selection is non-empty AND // 2. The user clicked inside the selection. if ((e.CursorLeft != KeyboardInvokedSentinel && !This.Selection.Contains(renderScopeMouseDownPoint)) || (e.CursorLeft == KeyboardInvokedSentinel && This.Selection.IsEmpty)) { return; } } else if ((This.Selection.IsEmpty || e.TargetElement is TextElement) && e.TargetElement != null) { // Targeted element has its own ContextMenu, don't override it. contextMenu = (ContextMenu)e.TargetElement.GetValue(FrameworkElement.ContextMenuProperty); } else if (e.CursorLeft == KeyboardInvokedSentinel) { // If the menu was invoked from the keyboard, walk up the tree // from the selection.Start looking for a custom menu. TextPointer start = GetContentPosition(This.Selection.Start) as TextPointer; if (start != null) { TextElement element = start.Parent as TextElement; while (element != null) { contextMenu = (ContextMenu)element.GetValue(FrameworkElement.ContextMenuProperty); if (contextMenu != null) { startPositionCustomElementMenu = true; break; } element = element.Parent as TextElement; } } } // Update the selection caret. // // A negative offset for e.CursorLeft means the user invoked // the menu with a hotkey (shift-F10). Don't mess with the caret // unless the user right-clicked. if (e.CursorLeft != KeyboardInvokedSentinel) { if (!TextEditorMouse.IsPointWithinInteractiveArea(This, Mouse.GetPosition(This.UiScope))) { // Don't bring up a context menu if the user clicked on non-editable space. return; } // Don't update the selection caret if we're bringing up a custom UIElement // ContextMenu. if (contextMenu == null || !(e.TargetElement is UIElement)) { using (This.Selection.DeclareChangeBlock()) // NB: This raises a PUBLIC EVENT. { // If we're not over the selection, move the caret. if (!This.Selection.Contains(renderScopeMouseDownPoint)) { TextEditorMouse.SetCaretPositionOnMouseEvent(This, renderScopeMouseDownPoint, MouseButton.Right, 1 /* clickCount */); } } } } if (contextMenu == null) { // If someone explicitly set it null -- don't mess with it. if (This.UiScope.ReadLocalValue(FrameworkElement.ContextMenuProperty) == null) { return; } // Grab whatever's set to the UiScope's ContextMenu property. contextMenu = This.UiScope.ContextMenu; } // If we are here, it means that either a custom context menu or our default context menu will be opened. // Setting this flag ensures that we dont loose selection highlight while the context menu is open. This.IsContextMenuOpen = true; // If it's not null, someone's overriding our default -- don't mess with it. if (contextMenu != null && !startPositionCustomElementMenu) { // If the user previously raised the ContextMenu with the keyboard, // we've left h/v offsets non-zero, and they need to be cleared now // for mouse placement to work. contextMenu.HorizontalOffset = 0; contextMenu.VerticalOffset = 0; // Since ContextMenuService doesn't open the menu, it won't fire a ContextMenuClosing event. // We need to listen to the Closed event of the ContextMenu itself so we can clear the // IsContextMenuOpen flag. We also do this for the default menu later in this method. contextMenu.Closed += new RoutedEventHandler(OnContextMenuClosed); return; } // Complete the composition before creating the editor context menu. This.CompleteComposition(); if (contextMenu == null) { // It's a default null, so spin up a temporary ContextMenu now. contextMenu = new EditorContextMenu(); ((EditorContextMenu)contextMenu).AddMenuItems(This, e.UserInitiated); } contextMenu.Placement = PlacementMode.RelativePoint; contextMenu.PlacementTarget = This.UiScope; ITextPointer position = null; LogicalDirection direction; // Position the ContextMenu. SpellingError spellingError = (contextMenu is EditorContextMenu) ? This.GetSpellingErrorAtSelection() : null; if (spellingError != null) { // If we have a matching speller error at the selection // start, position relative to the end of the error. position = spellingError.End; direction = LogicalDirection.Backward; } else if (e.CursorLeft == KeyboardInvokedSentinel) { // A negative offset for e.CursorLeft means the user invoked // the menu with a hotkey (shift-F10). Place the menu // relative to Selection.Start. position = This.Selection.Start; direction = LogicalDirection.Forward; } else { direction = LogicalDirection.Forward; } // Calculate coordinats for the ContextMenu. // They must be set relative to UIScope - as EditorContextMenu constructor assumes. if (position != null && position.CreatePointer(direction).HasValidLayout) { double horizontalOffset; double verticalOffset; GetClippedPositionOffsets(This, position, direction, out horizontalOffset, out verticalOffset); contextMenu.HorizontalOffset = horizontalOffset; contextMenu.VerticalOffset = verticalOffset; } else { Point uiScopeMouseDownPoint = Mouse.GetPosition(This.UiScope); contextMenu.HorizontalOffset = uiScopeMouseDownPoint.X; contextMenu.VerticalOffset = uiScopeMouseDownPoint.Y; } // Since ContextMenuService doesn't open the menu, it won't fire a ContextMenuClosing event. // We need to listen to the Closed event of the ContextMenu itself so we can clear the // IsContextMenuOpen flag. contextMenu.Closed += new RoutedEventHandler(OnContextMenuClosed); // This line raises a public event. contextMenu.IsOpen = true; e.Handled = true; }
// Helper to set property value on element. private static void SetPropertyValue(TextElement element, DependencyProperty property, object currentValue, object newValue) { if (!TextSchema.ValuesAreEqual(newValue, currentValue)) { // first clear and see if it will do element.ClearValue(property); // if still need it, set it if (!TextSchema.ValuesAreEqual(newValue, element.GetValue(property))) { element.SetValue(property, newValue); } } }