{"action":"created","issue":{"url":"https://api.github.com/repos/TomasMikula/RichTextFX/issues/356","repository_url":"https://api.github.com/repos/TomasMikula/RichTextFX","labels_url":"https://api.github.com/repos/TomasMikula/RichTextFX/issues/356/labels{/name}","comments_url":"https://api.github.com/repos/TomasMikula/RichTextFX/issues/356/comments","events_url":"https://api.github.com/repos/TomasMikula/RichTextFX/issues/356/events","html_url":"https://github.com/TomasMikula/RichTextFX/pull/356","id":175986473,"number":356,"title":"Custom object support","user":{"login":"afester","id":2681864,"avatar_url":"https://avatars.githubusercontent.com/u/2681864?v=3","gravatar_id":"","url":"https://api.github.com/users/afester","html_url":"https://github.com/afester","followers_url":"https://api.github.com/users/afester/followers","following_url":"https://api.github.com/users/afester/following{/other_user}","gists_url":"https://api.github.com/users/afester/gists{/gist_id}","starred_url":"https://api.github.com/users/afester/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/afester/subscriptions","organizations_url":"https://api.github.com/users/afester/orgs","repos_url":"https://api.github.com/users/afester/repos","events_url":"https://api.github.com/users/afester/events{/privacy}","received_events_url":"https://api.github.com/users/afester/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":5,"created_at":"2016-09-09T11:21:15Z","updated_at":"2016-09-12T20:11:14Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/TomasMikula/RichTextFX/pulls/356","html_url":"https://github.com/TomasMikula/RichTextFX/pull/356","diff_url":"https://github.com/TomasMikula/RichTextFX/pull/356.diff","patch_url":"https://github.com/TomasMikula/RichTextFX/pull/356.patch"},"body":"This is an enhanced proposal to support custom objects which can be rendered by user specific nodes.\r\n\r\nIn the model layer, all occurrences of `StyledText `have been replaced by the new interface `Segment`. `StyledText `is now just one flavor of segment types. `CustomObject `is an abstract class which implements the `Segment `interface and which provides a base class for user defined objects. Out-of-the-box, RichTextFX would support images to be inserted into the document, but the user can define any other custom objects by registering a factory method for the JavaFX node and a decode method for deserializing the object through a  Codec.  See `CustomObjectDemo `for an example how to register and use custom objects.\r\n\r\nThe code already supports copy&paste (if the selection contains a custom object, it is serialized when copying). Selecting one single custom object by clicking on it is not supported yet.\r\n\r\nAny feedback/comments are welcome - especially registering the decode method is very unclean yet, see the SegmentFactory class. Essentially, decoding must be delegated to the custom object implementation since only the custom object knows how to recreate itself from a DataInputStream, but the method in ReadOnlyStyledDocument which does the decoding is static which makes it difficult to access a delegate. I tried to make those methods non-static, but this looked like a huge bunch of refactoring is necessary then.\r\n"},"comment":{"url":"https://api.github.com/repos/TomasMikula/RichTextFX/issues/comments/246475869","html_url":"https://github.com/TomasMikula/RichTextFX/pull/356#issuecomment-246475869","issue_url":"https://api.github.com/repos/TomasMikula/RichTextFX/issues/356","id":246475869,"user":{"login":"TomasMikula","id":433439,"avatar_url":"https://avatars.githubusercontent.com/u/433439?v=3","gravatar_id":"","url":"https://api.github.com/users/TomasMikula","html_url":"https://github.com/TomasMikula","followers_url":"https://api.github.com/users/TomasMikula/followers","following_url":"https://api.github.com/users/TomasMikula/following{/other_user}","gists_url":"https://api.github.com/users/TomasMikula/gists{/gist_id}","starred_url":"https://api.github.com/users/TomasMikula/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TomasMikula/subscriptions","organizations_url":"https://api.github.com/users/TomasMikula/orgs","repos_url":"https://api.github.com/users/TomasMikula/repos","events_url":"https://api.github.com/users/TomasMikula/events{/privacy}","received_events_url":"https://api.github.com/users/TomasMikula/received_events","type":"User","site_admin":false},"created_at":"2016-09-12T20:11:14Z","updated_at":"2016-09-12T20:11:14Z","body":"What if we abstract over the type of segments in a type parameter:\r\n\r\n```java\r\n/**\r\n * Segment operations on type Seg.\r\n * Notice that each method takes the segment as an argument.\r\n */\r\npublic interface SegmentOps<Seg> {\r\n    int length(Seg segment);\r\n    char charAt(Seg segment, int index);\r\n    /* ... */\r\n}\r\n\r\npublic class StyledTextArea0<PS, Seg, S> {\r\n    public StyledTextArea0(\r\n            PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle, // as before\r\n            S initialTextStyle, // as before\r\n            SegmentOps<Seg> segmentOps,\r\n            Function<Seg, Node> nodeFactory,\r\n            BiFunction<Seg, S, Seg> applyStyle // Given a segment, update its style. The result is a new segment.\r\n    ) {\r\n        /* ... */\r\n    }\r\n}\r\n```\r\n\r\nNote that any type `Foo` can now represent a segment, without having to implement any interface, as long as we provide an implementation of segment operations for that type, i.e. an instance of `SegmentOps<Foo>`. This is similar to how you can create a `TreeSet<E>` for any type `E` whatsoever, given that you [provide a `Comparator<E>`](https://docs.oracle.com/javase/8/docs/api/java/util/TreeSet.html#TreeSet-java.util.Comparator-).\r\n\r\nOur original `StyledTextArea` is then\r\n\r\n```java\r\npublic class StyledTextArea<PS, S> extends StyledTextArea0<PS, StyledText<S>, S> {}\r\n```\r\n\r\nIf one wanted to embed images in addition to `StyledText`, they could define their own\r\n\r\n```java\r\npublic class MyArea<PS, S> extends StyledTextArea0<PS, Either<StyledText<S>, LinkedImage<S>>, S> {}\r\n```\r\n\r\nExtending is not even really necessary, it is just to provide a shorthand for the rather long type `StyledTextArea0<PS, Either<StyledText<S>, LinkedImage<S>>, S>`."}}
{"actor":{"display_login":"TomasMikula"}}