8000 Add support for drag and drop by jperedadnr · Pull Request #161 · gluonhq/rich-text-area · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add support for drag and drop #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/com/gluonhq/richtextarea/ParagraphTile.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ void mousePressedListener(MouseEvent e) {
} else if (e.getClickCount() == 3) {
viewModel.selectCurrentParagraph();
} else {
richTextAreaSkin.dragStart = globalInsertionIndex;
richTextAreaSkin.mouseDragStart = globalInsertionIndex;
viewModel.clearSelection();
}
} else if (e.isShiftDown() && e.getClickCount() == 1 && !(e.isControlDown() || e.isAltDown() || e.isMetaDown() || e.isShortcutDown())) {
Expand All @@ -253,7 +253,7 @@ void mouseDraggedListener(MouseEvent e) {
HitInfo hitInfo = textFlow.hitTest(new Point2D(e.getX() - textFlowLayoutX, e.getY() - textFlowLayoutY));
if (hitInfo.getInsertionIndex() >= 0) {
int dragEnd = paragraph.getStart() + hitInfo.getInsertionIndex();
viewModel.setSelection(new Selection(richTextAreaSkin.dragStart, dragEnd));
viewModel.setSelection(new Selection(richTextAreaSkin.mouseDragStart, dragEnd));
viewModel.setCaretPosition(dragEnd);
}
e.consume();
Expand Down
23 changes: 20 additions & 3 deletions src/main/java/com/gluonhq/richtextarea/RichListCell.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import javafx.scene.control.ListCell;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.DragEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
Expand Down Expand Up @@ -78,18 +80,33 @@ class RichListCell extends ListCell<Paragraph> {
}
// allow dragging
if (richTextAreaSkin.anchorIndex == -1) {
richTextAreaSkin.dragStart = textLength;
richTextAreaSkin.mouseDragStart = textLength;
}
});
});
addEventHandler(MouseEvent.MOUSE_RELEASED, event -> {
if (richTextAreaSkin.anchorIndex != -1) {
event.consume();
richTextAreaSkin.dragStart = -1;
richTextAreaSkin.mouseDragStart = -1;
richTextAreaSkin.anchorIndex = -1;
}
});

addEventHandler(DragEvent.DRAG_OVER, de -> {
if (richTextAreaSkin.dragAndDropStart != -1) {
getParagraphTile().ifPresent(p -> {
if (!richTextAreaSkin.getSkinnable().isFocused()) {
richTextAreaSkin.getSkinnable().requestFocus();
}
// caret follows dnd movement
p.mousePressedListener(new MouseEvent(de.getSource(), de.getTarget(), MouseEvent.MOUSE_PRESSED,
de.getX(), de.getY(), de.getScreenX(), de.getScreenY(),
MouseButton.PRIMARY, 1,
false, false, false, false,
true, false, false,
false, false, false, null));
});
}
});
}

@Override
Expand Down
52 changes: 51 additions & 1 deletion src/main/java/com/gluonhq/richtextarea/RichTextAreaSkin.java
ED4F
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.gluonhq.richtextarea;

import com.gluonhq.richtextarea.model.Document;
import com.gluonhq.richtextarea.model.ImageDecoration;
import com.gluonhq.richtextarea.model.Paragraph;
import com.gluonhq.richtextarea.model.ParagraphDecoration;
import com.gluonhq.richtextarea.model.PieceTable;
Expand Down Expand Up @@ -37,9 +38,12 @@
import javafx.scene.control.skin.VirtualFlow;
import javafx.scene.image.Image;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.shape.Path;
Expand Down Expand Up @@ -159,7 +163,8 @@ interface ActionBuilder extends Function<KeyEvent, ActionCmd>{}

private final Consumer<TextBuffer.Event> textChangeListener = e -> refreshTextFlow();
int lastValidCaretPosition = -1;
int dragStart = -1;
int mouseDragStart = -1;
int dragAndDropStart = -1;
int anchorIndex = -1;
Paragraph lastParagraph = null;

Expand Down Expand Up @@ -189,6 +194,7 @@ protected void invalidated() {

private final ChangeListener<Number> caretChangeListener;
private final InvalidationListener focusListener;
private final EventHandler<DragEvent> dndHandler = this::dndListener;

private class RichVirtualFlow extends VirtualFlow<ListCell<Paragraph>> {

Expand Down Expand Up @@ -363,6 +369,7 @@ public void dispose() {
getSkinnable().setOnKeyTyped(null);
getSkinnable().widthProperty().removeListener(controlPrefWidthListener);
getSkinnable().focusedProperty().removeListener(focusListener);
getSkinnable().removeEventHandler(DragEvent.ANY, dndHandler);
contextMenu.getItems().clear();
editableContextMenuItems = null;
nonEditableContextMenuItems = null;
Expand Down Expand Up @@ -402,6 +409,7 @@ private void setup(Document document) {
getSkinnable().setOnKeyTyped(this::keyTypedListener);
getSkinnable().widthProperty().addListener(controlPrefWidthListener);
getSkinnable().focusedProperty().addListener(focusListener);
getSkinnable().addEventHandler(DragEvent.ANY, dndHandler);
refreshTextFlow();
requestLayout();
editableChangeListener(null); // sets up all related listeners
Expand Down Expand Up @@ -555,4 +563,46 @@ private MenuItem createMenuItem(String text, ActionCmd actionCmd) {
return menuItem;
}

private void dndListener(DragEvent dragEvent) {
if (dragEvent.getEventType() == DragEvent.DRAG_ENTERED) {
dragAndDropStart = 1;
} else if (dragEvent.getEventType() == DragEvent.DRAG_DONE || dragEvent.getEventType() == DragEvent.DRAG_EXITED) {
dragAndDropStart = -1;
} else if (dragEvent.getEventType() == DragEvent.DRAG_OVER) {
Dragboard dragboard = dragEvent.getDragboard();
if (dragboard.hasImage() || dragboard.hasString() || dragboard.hasUrl() | dragboard.hasFiles()) {
dragEvent.acceptTransferModes(TransferMode.ANY);
}
} else if (dragEvent.getEventType() == DragEvent.DRAG_DROPPED) {
Dragboard dragboard = dragEvent.getDragboard();
if (!dragboard.getFiles().isEmpty()) {
dragboard.getFiles().forEach(file -> {
String url = file.toURI().toString();
// validate image before adding it
if (url != null && new Image(url).getException() == null) {
ACTION_CMD_FACTORY.decorateImage(new ImageDecoration(url)).apply(viewModel);
}
});
} else if (dragboard.hasUrl()) {
String url = dragboard.getUrl();
// validate if url is an image before adding it:
if (url != null) {
if (new Image(url).getException() == null) {
ACTION_CMD_FACTORY.decorateImage(new ImageDecoration(url)).apply(viewModel);
} else {
// add text and hyperlink
int caret = viewModel.getCaretPosition();
ACTION_CMD_FACTORY.insertText(url).apply(viewModel);
viewModel.setSelection(new Selection(caret, caret + url.length()));
ACTION_CMD_FACTORY.decorateText(TextDecoration.builder().url(url).build()).apply(viewModel);
}
}
} else if (dragboard.hasString()) {
ACTION_CMD_FACTORY.insertText(dragboard.getString()).apply(viewModel);
}
requestLayout();
dragAndDropStart = -1;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public void apply(RichTextAreaViewModel viewModel) {

@Override
public BooleanBinding getDisabledBinding(RichTextAreaViewModel viewModel) {
return Bindings.createBooleanBinding(() -> !(viewModel.clipboardHasString() || viewModel.clipboardHasImage())
return Bindings.createBooleanBinding(() -> !(viewModel.clipboardHasString() || viewModel.clipboardHasImage() || viewModel.clipboardHasUrl())
|| !viewModel.isEditable(),
viewModel.caretPositionProperty(), viewModel.editableProperty());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,10 @@ boolean clipboardHasString() {
return Clipboard.getSystemClipboard().hasString();
}

boolean clipboardHasUrl() {
return Clipboard.getSystemClipboard().hasUrl();
}

void clipboardPaste() {
if (clipboardHasImage()) {
final Image image = Clipboard.getSystemClipboard().getImage();
Expand All @@ -407,6 +411,16 @@ void clipboardPaste() {
commandManager.execute(new DecorateCmd(new ImageDecoration(url)));
}
}
} else if (clipboardHasUrl()) {
final String url = Clipboard.getSystemClipboard().getUrl();
if (url != null) {
if (!getSelection().isDefined()) {
int caret = getCaretPosition();
commandManager.execute(new InsertTextCmd(url));
setSelection(new Selection(caret, caret + url.length()));
}
commandManager.execute(new DecorateCmd(TextDecoration.builder().url(url).build()));
}
} else if (clipboardHasString()) {
final String text = Clipboard.getSystemClipboard().getString();
if (text != null) {
Expand Down
0