Skip to content

Paste as plain text functionality#37

Merged
cuikp merged 4 commits intocuikp:mainfrom
voidray:paste-as-plain-text
May 6, 2026
Merged

Paste as plain text functionality#37
cuikp merged 4 commits intocuikp:mainfrom
voidray:paste-as-plain-text

Conversation

@voidray
Copy link
Copy Markdown
Contributor

@voidray voidray commented May 2, 2026

This PR adds the functionality to paste as plain text with shortcut CTRL+SHIFT+V or using the context menu.

If the text where the clipboard-data is inserted at has already formatting, than this formatting will not be applied to the inserted text. This is how for example LibreOffice Writer works, but I'm open to change this.
Update: That's actually not correct. Existing formatting is applied in LibreOffice Writer. Should the changes in commit b7ea0e1 be undone?
I reverted the changes, so it like most users probably expect it to work (use formatting that the current text in the control has). A way to clear formatting could be added in addition.

The addUndo variable and if-clause has been removed, because addUndo is always true. This change can be reverted, if there is a reason to keep it, of course.

@voidray voidray marked this pull request as draft May 2, 2026 08:56
@voidray voidray force-pushed the paste-as-plain-text branch from e6b946b to 9606cb2 Compare May 5, 2026 11:06
@voidray voidray marked this pull request as ready for review May 5, 2026 11:10
@cuikp
Copy link
Copy Markdown
Owner

cuikp commented May 5, 2026

it seems that instead of modifying SetRangeToText() for this purpose, the KeyDown event can just be routed

case Key.V:

if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
PasteTextFromClipboard()
else
PasteFromClipboard();
break;

something like that?
Where PasteTextFromClipboard() only pastes if Text is on the clipboard.

@voidray
Copy link
Copy Markdown
Contributor Author

voidray commented May 5, 2026

What about refactoring all shortcuts like this:


 private readonly record struct KeyCombo(
    Key Key,
    bool Ctrl = false,
    bool Shift = false,
    bool Alt = false
 );

 private Dictionary<KeyCombo, Action>? _keyActions;

 private Dictionary<KeyCombo, Action> KeyActions => _keyActions ??= new()
 {
    // Ctrl shortcuts
    { new(Key.B, Ctrl: true), () => ToggleBold() },
    { new(Key.I, Ctrl: true), () => ToggleItalics() },
    { new(Key.U, Ctrl: true), () => ToggleUnderlining() },

    { new(Key.C, Ctrl: true), () => CopyToClipboard() },
    { new(Key.X, Ctrl: true), () => CutToClipboard() },
    { new(Key.V, Ctrl: true), () => PasteFromClipboard() },
    { new(Key.V, Ctrl: true, Shift: true), () => PasteFromClipboardAsPlainText() },

    ...
   };
   
   private static KeyCombo GetCombo(KeyEventArgs e) =>
      new(
         e.Key,
         Ctrl: e.KeyModifiers.HasFlag(KeyModifiers.Control),
         Shift: e.KeyModifiers.HasFlag(KeyModifiers.Shift),
         Alt: e.KeyModifiers.HasFlag(KeyModifiers.Alt)
      );

   private bool TryHandleKeyAction(KeyEventArgs e)
   {
      if (KeyActions.TryGetValue(GetCombo(e), out var action))
      {
         action();
         e.Handled = true;
         return true;
      }

      return false;
   }

   private void RichTextBox_KeyDown(object? sender, KeyEventArgs e)
   {
      TryHandleKeyAction(e);

      RtbVm.CaretVisible = (RtbVm.FlowDoc.Selection.Length == 0);
      if (client != null)
         UpdatePreeditOverlay();
   }

@voidray voidray force-pushed the paste-as-plain-text branch from 9606cb2 to 2b066a9 Compare May 5, 2026 18:46
@voidray
Copy link
Copy Markdown
Contributor Author

voidray commented May 5, 2026

@cuikp
Copy link
Copy Markdown
Owner

cuikp commented May 6, 2026

The changes to SetRangeToText(...., bool pasteFormatting) are good, yes. Formatting the new text is only necessary when user begins typing within a selection, so it retains the selection's formatting. Not for text-only pasting.

Actually I'm not sure there's a need for separate extra method of:
PasteFromClipboardAsPlainText()
just add true in the key handler for Ctrl-Shift-V:
PasteFromClipboard(true)

Regarding the refactoring of key handling, is there some advantage to those changes? (i.e. Dictionary<KeyCombo, Action> KeyActions => _keyActions...).
I find it harder to read at a glance, as opposed to the current switch/case layout.

I also think RichTextBox will need a switch to enable/disable this action on Ctrl-Shift-V, because developers of the control might not want it or will have other uses for Ctrl-Shift-V. But I'll add that later after merging. Or maybe a switch to enable/disable all hotkeys or just copy/paste related hotkeys, idk.

@voidray
Copy link
Copy Markdown
Contributor Author

voidray commented May 6, 2026

I added the extra method PasteFromClipboardAsPlainText just so that it is easier to understand. With PasteFromClipboard(true) you have to first look to see what 'true' means.

Regarding the shortcut-refactoring: Using this approach avoids the issue which was there earlier, where the combination isn't strict enough (for example CTRL+SHIFT+C also copies text). It makes such cases impossible, because you have to explicitly define which modified-keys are necessary.
It's also easier to add new shortcuts in my opinion, because you don't have to search first, which branch is the correct one for the combination of modifiers.
The list of definitions could also split up in methods if that would make reading it easier.

@cuikp
Copy link
Copy Markdown
Owner

cuikp commented May 6, 2026

Re: shortcut refactoring - makes sense, ok. Just have to get used to looking at that syntax.

Re: interpreting PasteFromClipboard(true), it could be specified as:
PasteFromClipboard(plainTextOnly: true);
in the keyboard handler instead of in the extra PasteFromClipboardAsPlainText() => PasteFromClipboard(plainTextOnly: true); method, should be clear enough?
(just to avoid a separate method)

@voidray
Copy link
Copy Markdown
Contributor Author

voidray commented May 6, 2026

PasteFromClipboard(plainTextOnly: true) is also ok. I will change it.

@cuikp cuikp merged commit 08b6dac into cuikp:main May 6, 2026
@cuikp
Copy link
Copy Markdown
Owner

cuikp commented May 6, 2026

Merged. Looks good, thx.

Later I'm going to add a StyledProperty to RTB to enabled/disable just the editing shortcuts (enabled by default), since some users may not want them at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants