Skip to content
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

StyleClassedTextArea: clear(), then insertText(), doesn't work consistently #762

Closed
SkyAphid opened this issue Jun 30, 2018 · 9 comments
Closed

Comments

@SkyAphid
Copy link
Contributor

If you call

styleClassedTextArea.clear()
styleClassedTextArea.insertText(0, text)

It won't work, as in, if there is text in the text area, the insert() won't register. If the text area is empty, then the insert() will work. It works in that pattern, so you can probably reproduce it easily. I've been getting around it by using replaceText(), as it doesn't seem to have the problem.

@JordanMartinez
Copy link
Contributor

then the insert() will work

What does it do? Is nothing inserted and the area's text remains the same? I'm not fully understanding the problem. Also, when you open up issues, could you please follow the guidelines I wrote in the Issue template? You should see it every time you open a new issue.

@SkyAphid
Copy link
Contributor Author

SkyAphid commented Jun 30, 2018

Here, I recorded the problem:

https://drive.google.com/open?id=1OP-4h5tU-eBMRymkhNHpI48Io_Xher3R

What's happening:

  • New Project is clicked (and I click a prompt to confirm that doesnt show up in the video)
  • This code is called:
styleClassedTextArea.clear()
styleClassedTextArea.insertText(0, "Default Project")

clear() seems to clear it, but insertText() only seems to work if the StyleClassedTextArea has nothing in it. If you called replaceText() on the StyleClassedTextArea, it works as a stand-in. But I just thought I'd take the time to alert you guys that this is happening.

Again, to further clarify, in that footage, the text area where "Default Project" is should never be empty in this case. StyleClassedTextArea.clear() is being called, but insertText() is not always working (adding Default Project back in). Also: it's not always "Default Project," I'm just using that to help with the example. It'll change between projects (hence the need for clearing it and re-inserting the new text).

It's probably easily reproducible on your end, but if it isn't, I can link you to the code for my project and you can take a look there.

P.S. sorry for not following the rules, I'm a bit burnt out from working on this software and wanted to try and get this patched up. If I open another down the line, I'll re-read it and try again.

@JordanMartinez
Copy link
Contributor

If you are calling area.clear(); area.insertText(0, text), why not just call area.replaceText(text)? The first is two edit operations while the second is one edit operation. So, not only is it faster, but it better describes what you're trying to do: take all of the area's text and replace it with this text.

It's probably easily reproducible on your end, but if it isn't, I can link you to the code for my project and you can take a look there.

P.S. sorry for not following the rules, I'm a bit burnt out from working on this software and wanted to try and get this patched up. If I open another down the line, I'll re-read it and try again.

Yes, it is easily reproducible. However, it also takes up some of my time, and if that keeps happening, I'll start ignoring such requests because you aren't following the guidelines I specified.

Also, if you say "Here's a link to my code that reproduces the problem," I'll ignore that and not count it as a reproducible demo. Why? Because a reproducible demo that uses nothing more than this project proves that the problem is entirely with this project's code. Thus, it is the fault of one of the contributor's and our responsibility to fix it (given the limited amount of resources we have to do so). Your code might have a bug not because of this project but because of misusing it for your purposes. Thus, by linking to your code, you're essentially asking me to learn and debug your code for free.

Finally, by creating a reproducible demo, you are forced to narrow down what causes the issue. Sometimes, by doing that, you discover what you're doing wrong in your code and fix it yourself. When that happens, I don't have to use any of my time and I'm happy. However, if you can provide a reproducible demo, you make yourself happy because I can fix it faster/better because I can reproduce it on my end.

Getting back to the root of the issue (of whether a call of clearText(); insertText(); doesn't work), I tested the problem with this code and could not reproduce the issue:

import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import org.fxmisc.flowless.VirtualizedScrollPane;
import org.fxmisc.richtext.InlineCssTextArea;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class ClearThenInsertText extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        InlineCssTextArea area = new InlineCssTextArea("initial text");

        BorderPane p = new BorderPane();
        p.setCenter(new VirtualizedScrollPane<>(area));

        Button b1 = new Button("clear text");
        b1.setOnAction(e -> area.clear());

        Button b2 = new Button("insert text");
        b2.setOnAction(e -> area.insertText(0, "some text"));

        p.setTop(new HBox(b1, b2));
        final Scene scene = new Scene(p, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
}

@SkyAphid
Copy link
Contributor Author

SkyAphid commented Jul 2, 2018

I ended up doing some testing, and it ended up being because the text listener was catching the clear()/insert(). So when I called clear(), the text listener was updated with a blank newText value, and that in turn caused my code to clear the project name. That rendered the insert() fruitless as a result. TL;DR; totally my bad lol

@SkyAphid SkyAphid closed this as completed Jul 2, 2018
@JordanMartinez
Copy link
Contributor

Lol... It happens, man.

... the text listener...

You're not using EventStreams to handle things?

@SkyAphid
Copy link
Contributor Author

SkyAphid commented Jul 3, 2018

I'm a still a bit new to JavaFX, but my listener works like this:

projectNameField.textProperty().addListener((o, oldText, newText) -> {
	project.setName(newText);
});

@JordanMartinez
Copy link
Contributor

That can be changed to EventStreams.valuesOf(area.textProperty()).feedTo(project.nameProperty());

Your listener works fine since I think the above uses a bit more memory than just your listener. However, for more complicated things, EventStreams would be better because they compose. See ReactFX's EventStream tutorial that starts with the page titled, "EventStream Intro and Basic Usage"

@SkyAphid
Copy link
Contributor Author

SkyAphid commented Jul 3, 2018

Thanks for the tip! I'll check it out. It may come in handy for the actual dialogue editing. If you don't mind me asking, what would you say the key difference is?

@JordanMartinez
Copy link
Contributor

Taken from the page I referenced:

For example, using ChangeListeners, EventHandlers, and everything else the JavaFX API provides, how difficult would it be for a developer to write code that must run only when the following conditions are true:

  • The last letters that were pressed by the user were "a", "b", and "c"
    - The user hovered the mouse over a circle for three seconds
    - After hovering, the user clicks the mouse.
    - A BooleanProperty is true
    - A second BooleanProperty is false

Writing the above code with EventStream objects is not only possible but easy.

I'll take this project as an example. Every time you type a letter into an area, what needs to happen? A large variety of things. We need to

  • update the area's properties (text, length),
  • update the caret's properties (2Dposition, position, paragraphIndex, columnPosition),
  • update the selection's properties (same position things for start and end, selectedText, selectedDocument),
  • update the visual components (re-render a paragraph if it's been changed, update the paragraph's index to something else so that the corresponding LineNumberFactory outputs the correct line number)
  • notify "listeners" that a rich text change has occurred, so they can further respond to it
  • notify "listeners" that a plain text change has occurred, so they can further respond to it
  • handle all of this in a way that makes memory-leaks impossible

The Listener approach is based on the Observable-Observer pattern, which is horrendously flawed (google it if you're curious why) and was replaced in Java 9 with the Publisher-Subscriber pattern. ReactFX (similar to RxJava) aligns more with the latter than the former.

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

No branches or pull requests

2 participants