{"action":"created","comment":{"url":"https://api.github.com/repos/wandernauta/viskell/pulls/comments/33896496","id":33896496,"diff_hunk":"@@ -0,0 +1,248 @@\n+package nl.utwente.group10.ui.components.blocks.function;\n+\n+import java.util.ArrayList;\n+import java.util.HashMap;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.stream.Collectors;\n+\n+import javafx.application.Platform;\n+import javafx.beans.property.SimpleStringProperty;\n+import javafx.beans.property.StringProperty;\n+import javafx.fxml.FXML;\n+import javafx.scene.layout.BorderPane;\n+import javafx.scene.layout.Pane;\n+import javafx.scene.layout.Region;\n+import nl.utwente.group10.haskell.exceptions.HaskellException;\n+import nl.utwente.group10.haskell.exceptions.HaskellTypeError;\n+import nl.utwente.group10.haskell.expr.Apply;\n+import nl.utwente.group10.haskell.expr.Expr;\n+import nl.utwente.group10.haskell.expr.Ident;\n+import nl.utwente.group10.haskell.type.FuncT;\n+import nl.utwente.group10.haskell.type.Type;\n+import nl.utwente.group10.ui.BackendUtils;\n+import nl.utwente.group10.ui.CustomUIPane;\n+import nl.utwente.group10.ui.components.anchors.InputAnchor;\n+import nl.utwente.group10.ui.components.anchors.OutputAnchor;\n+import nl.utwente.group10.ui.components.blocks.Block;\n+import nl.utwente.group10.ui.components.blocks.input.InputBlock;\n+import nl.utwente.group10.ui.components.blocks.output.OutputBlock;\n+import nl.utwente.group10.ui.exceptions.FunctionDefinitionException;\n+import nl.utwente.group10.ui.handlers.ConnectionCreationManager;\n+import javafx.beans.property.BooleanProperty;\n+import javafx.beans.property.SimpleBooleanProperty;\n+import javafx.beans.value.ObservableValue;\n+\n+/**\n+ * Main building block for the visual interface, this class represents a Haskell\n+ * function together with it's arguments and visual representation.\n+ */\n+public class FunctionBlock extends Block implements InputBlock, OutputBlock {\n+    /** The OutputAnchor of this FunctionBlock. */\n+    private OutputAnchor output;\n+\n+    /** The function name. */\n+    private StringProperty name;\n+\n+    /** The space containing the input anchor(s). */\n+    @FXML private Pane inputSpace;\n+\n+    /** The space containing the output anchor. */\n+    @FXML private BorderPane outputSpace;\n+\n+    /** The space containing all the arguments of the function. */\n+    private ArgumentSpace argumentSpace;\n+    \n+    /** The space in which to nest the FunctionBlock's inner parts. */\n+    @FXML private Pane nestSpace;\n+    \n+    /** The space in which the information of the function is displayed. */\n+    @FXML private Pane functionInfo;\n+    \n+    /**\n+     * Method that creates a newInstance of this class along with it's visual\n+     * representation\n+     *\n+     * @param name\n+     *            The name of the function.\n+     * @param type\n+     *            The function's type (usually a FuncT).\n+     * @param pane\n+     *            The parent pane in which this FunctionBlock exists.\n+     */\n+    public FunctionBlock(String name, Type type, CustomUIPane pane) {\n+        super(pane);\n+        this.name = new SimpleStringProperty(name);\n+\n+        this.loadFXML(\"FunctionBlock\");\n+        Expr signature = new Ident(getName());\n+\n+        // Collect argument types\n+        ArrayList<String> args = new ArrayList<>();\n+        Type t = null;\n+        try {\n+            t = signature.getType(pane.getEnvInstance()).prune();\n+        } catch (HaskellException e1) {\n+            throw new FunctionDefinitionException();\n+        }\n+        int inputCount = 0;\n+        while (t instanceof FuncT) {\n+            FuncT ft = (FuncT) t;\n+            args.add(ft.getArgs()[0].toHaskellType());\n+            t = ft.getArgs()[1];\n+            inputCount++;\n+        }\n+        \n+        argumentSpace = new ArgumentSpace(this, inputCount);\n+        argumentSpace.setKnotIndex(getAllInputs().size());\n+        \n+        nestSpace.getChildren().add(argumentSpace);\n+        argumentSpace.knotIndexProperty().addListener(e -> invalidateKnotIndex());\n+        \n+        // Create an anchor for the result\n+        output = new OutputAnchor(this);\n+        outputSpace.setCenter(output);\n+        \n+        // Make sure the prefWidth is correctly updated.\n+        this.prefWidthProperty().bind(functionInfo.widthProperty().add(argumentSpace.prefWidthProperty()));\n+        \n+        \n+        this.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);\n+        this.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);\n+        functionInfo.setMinWidth(Region.USE_PREF_SIZE);\n+        functionInfo.setMaxWidth(Region.USE_PREF_SIZE);\n+        \n+        // Since at this point of the width of the Labels is unknown, we have to ask for another layout pass.\n+        Platform.runLater(this::updateLayout);\n+    }\n+    \n+    /** Updates the layout, if this Pane has a parent. */\n+    public void updateLayout() {\n+        if (this.getParent() != null) {\n+            this.getParent().requestLayout();\n+        }\n+    }\n+    \n+    /** @return the name of this FunctionBlock. */\n+    public final String getName() {\n+        return name.get();\n+    }\n+\n+    /** Sets the name of this FunctionBlock. */\n+    public void setName(String name) {\n+        this.name.set(name);\n+    }\n+    \n+    /** @return the StringProperty for the name of the function. */\n+    public final StringProperty nameProperty() {\n+        return name;\n+    }\n+\n+    /** @return the knot index of this FunctionBlock. */\n+    public final Integer getKnotIndex() {\n+        return argumentSpace.knotIndexProperty().get();\n+    }\n+\n+    /** Sets the new knot index for this FunctionBlock. */\n+    public final void setKnotIndex(int index) {\n+        argumentSpace.setKnotIndex(index);\n+    }\n+\n+    @Override\n+    public final List<InputAnchor> getAllInputs() {\n+        return argumentSpace.getInputArguments().stream().map(a -> a.getInputAnchor()).collect(Collectors.toList());\n+    }\n+\n+    /**\n+     * @return Only the active (as specified by the knot index) inputs.\n+     */\n+    @Override\n+    public List<InputAnchor> getActiveInputs() {\n+        return getAllInputs().subList(0, getKnotIndex());\n+    }\n+\n+    /**\n+     * @return InputAnchor with the given index.\n+     */\n+    public InputAnchor getInput(int index) {\n+        return getAllInputs().get(index);\n+    }\n+\n+    @Override\n+    public OutputAnchor getOutputAnchor() {\n+        return output;\n+    }\n+\n+    /**\n+     * On top of updating the expression, this method also adds a record to the\n+     * CustomUIPane that maps the expr to this block.\n+     */\n+    @Override\n+    public final void updateExpr() {\n+        getPane().removeExprToFunction(expr);\n+        expr = new Ident(getName());\n+        getPane().putExprToFunction(expr, this);\n+        \n+        for (InputAnchor in : getActiveInputs()) {\n+            expr = new Apply(expr, in.getExpr());\n+        }\n+        super.updateExpr();\n+    }\n+    \n+    @Override\n+    public void invalidateVisualState() {\n+        super.invalidateVisualState();\n+        invalidateInputVisuals();\n+        invalidateOutputVisuals();\n+    }\n+    \n+    /**\n+     * If the latest analyze attempt was successful, remove all kept error\n+     * indications.\n+     * \n+     * Since only 1 error can be detected by analyzing, only setting error state\n+     * to false whenever everything goes well makes it possible in some cases to\n+     * show multiple errors.\n+     */\n+    @Override\n+    public void invalidateConnectionState() {\n+        for (InputAnchor input : ((InputBlock) this).getAllInputs()) {\n+            if (!input.isPrimaryConnected() || !getPane().getErrorOccured()) {","path":"Code/src/main/java/nl/utwente/group10/ui/components/blocks/function/FunctionBlock.java","position":210,"original_position":210,"commit_id":"29e7bde4b2d29e6fce76a172c51ee80a5bbca4a8","original_commit_id":"29e7bde4b2d29e6fce76a172c51ee80a5bbca4a8","user":{"login":"wandernauta","id":126832,"avatar_url":"https://avatars.githubusercontent.com/u/126832?v=3","gravatar_id":"","url":"https://api.github.com/users/wandernauta","html_url":"https://github.com/wandernauta","followers_url":"https://api.github.com/users/wandernauta/followers","following_url":"https://api.github.com/users/wandernauta/following{/other_user}","gists_url":"https://api.github.com/users/wandernauta/gists{/gist_id}","starred_url":"https://api.github.com/users/wandernauta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wandernauta/subscriptions","organizations_url":"https://api.github.com/users/wandernauta/orgs","repos_url":"https://api.github.com/users/wandernauta/repos","events_url":"https://api.github.com/users/wandernauta/events{/privacy}","received_events_url":"https://api.github.com/users/wandernauta/received_events","type":"User","site_admin":false},"body":"Could split this into two ifs: clear it if disconnected, clear it if no error.","created_at":"2015-07-05T17:02:32Z","updated_at":"2015-07-05T17:02:32Z","html_url":"https://github.com/wandernauta/viskell/pull/123#discussion_r33896496","pull_request_url":"https://api.github.com/repos/wandernauta/viskell/pulls/123","_links":{"self":{"href":"https://api.github.com/repos/wandernauta/viskell/pulls/comments/33896496"},"html":{"href":"https://github.com/wandernauta/viskell/pull/123#discussion_r33896496"},"pull_request":{"href":"https://api.github.com/repos/wandernauta/viskell/pulls/123"}}},"pull_request":{"url":"https://api.github.com/repos/wandernauta/viskell/pulls/123","id":38990417,"html_url":"https://github.com/wandernauta/viskell/pull/123","diff_url":"https://github.com/wandernauta/viskell/pull/123.diff","patch_url":"https://github.com/wandernauta/viskell/pull/123.patch","issue_url":"https://api.github.com/repos/wandernauta/viskell/issues/123","number":123,"state":"open","locked":false,"title":"UI version 2","user":{"login":"i3anaan","id":2911348,"avatar_url":"https://avatars.githubusercontent.com/u/2911348?v=3","gravatar_id":"","url":"https://api.github.com/users/i3anaan","html_url":"https://github.com/i3anaan","followers_url":"https://api.github.com/users/i3anaan/followers","following_url":"https://api.github.com/users/i3anaan/following{/other_user}","gists_url":"https://api.github.com/users/i3anaan/gists{/gist_id}","starred_url":"https://api.github.com/users/i3anaan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/i3anaan/subscriptions","organizations_url":"https://api.github.com/users/i3anaan/orgs","repos_url":"https://api.github.com/users/i3anaan/repos","events_url":"https://api.github.com/users/i3anaan/events{/privacy}","received_events_url":"https://api.github.com/users/i3anaan/received_events","type":"User","site_admin":false},"body":"- Type system usage overhaul\r\n- Invalidation overhaul\r\n- New error display icon\r\n- Lots of visual glitches are fixed\r\n\r\nCleaning / documenting still needs to happen.\r\n","created_at":"2015-07-01T14:53:51Z","updated_at":"2015-07-05T17:02:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6b98b3d1cc479f28a154507a268122300504c2cf","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/wandernauta/viskell/pulls/123/commits","review_comments_url":"https://api.github.com/repos/wandernauta/viskell/pulls/123/comments","review_comment_url":"https://api.github.com/repos/wandernauta/viskell/pulls/comments{/number}","comments_url":"https://api.github.com/repos/wandernauta/viskell/issues/123/comments","statuses_url":"https://api.github.com/repos/wandernauta/viskell/statuses/29e7bde4b2d29e6fce76a172c51ee80a5bbca4a8","head":{"label":"wandernauta:ui-2","ref":"ui-2","sha":"29e7bde4b2d29e6fce76a172c51ee80a5bbca4a8","user":{"login":"wandernauta","id":126832,"avatar_url":"https://avatars.githubusercontent.com/u/126832?v=3","gravatar_id":"","url":"https://api.github.com/users/wandernauta","html_url":"https://github.com/wandernauta","followers_url":"https://api.github.com/users/wandernauta/followers","following_url":"https://api.github.com/users/wandernauta/following{/other_user}","gists_url":"https://api.github.com/users/wandernauta/gists{/gist_id}","starred_url":"https://api.github.com/users/wandernauta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wandernauta/subscriptions","organizations_url":"https://api.github.com/users/wandernauta/orgs","repos_url":"https://api.github.com/users/wandernauta/repos","events_url":"https://api.github.com/users/wandernauta/events{/privacy}","received_events_url":"https://api.github.com/users/wandernauta/received_events","type":"User","site_admin":false},"repo":{"id":30242992,"name":"viskell","full_name":"wandernauta/viskell","owner":{"login":"wandernauta","id":126832,"avatar_url":"https://avatars.githubusercontent.com/u/126832?v=3","gravatar_id":"","url":"https://api.github.com/users/wandernauta","html_url":"https://github.com/wandernauta","followers_url":"https://api.github.com/users/wandernauta/followers","following_url":"https://api.github.com/users/wandernauta/following{/other_user}","gists_url":"https://api.github.com/users/wandernauta/gists{/gist_id}","starred_url":"https://api.github.com/users/wandernauta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wandernauta/subscriptions","organizations_url":"https://api.github.com/users/wandernauta/orgs","repos_url":"https://api.github.com/users/wandernauta/repos","events_url":"https://api.github.com/users/wandernauta/events{/privacy}","received_events_url":"https://api.github.com/users/wandernauta/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/wandernauta/viskell","description":"Ontwerpproject.","fork":false,"url":"https://api.github.com/repos/wandernauta/viskell","forks_url":"https://api.github.com/repos/wandernauta/viskell/forks","keys_url":"https://api.github.com/repos/wandernauta/viskell/keys{/key_id}","collaborators_url":"https://api.github.com/repos/wandernauta/viskell/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/wandernauta/viskell/teams","hooks_url":"https://api.github.com/repos/wandernauta/viskell/hooks","issue_events_url":"https://api.github.com/repos/wandernauta/viskell/issues/events{/number}","events_url":"https://api.github.com/repos/wandernauta/viskell/events","assignees_url":"https://api.github.com/repos/wandernauta/viskell/assignees{/user}","branches_url":"https://api.github.com/repos/wandernauta/viskell/branches{/branch}","tags_url":"https://api.github.com/repos/wandernauta/viskell/tags","blobs_url":"https://api.github.com/repos/wandernauta/viskell/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/wandernauta/viskell/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/wandernauta/viskell/git/refs{/sha}","trees_url":"https://api.github.com/repos/wandernauta/viskell/git/trees{/sha}","statuses_url":"https://api.github.com/repos/wandernauta/viskell/statuses/{sha}","languages_url":"https://api.github.com/repos/wandernauta/viskell/languages","stargazers_url":"https://api.github.com/repos/wandernauta/viskell/stargazers","contributors_url":"https://api.github.com/repos/wandernauta/viskell/contributors","subscribers_url":"https://api.github.com/repos/wandernauta/viskell/subscribers","subscription_url":"https://api.github.com/repos/wandernauta/viskell/subscription","commits_url":"https://api.github.com/repos/wandernauta/viskell/commits{/sha}","git_commits_url":"https://api.github.com/repos/wandernauta/viskell/git/commits{/sha}","comments_url":"https://api.github.com/repos/wandernauta/viskell/comments{/number}","issue_comment_url":"https://api.github.com/repos/wandernauta/viskell/issues/comments{/number}","contents_url":"https://api.github.com/repos/wandernauta/viskell/contents/{+path}","compare_url":"https://api.github.com/repos/wandernauta/viskell/compare/{base}...{head}","merges_url":"https://api.github.com/repos/wandernauta/viskell/merges","archive_url":"https://api.github.com/repos/wandernauta/viskell/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/wandernauta/viskell/downloads","issues_url":"https://api.github.com/repos/wandernauta/viskell/issues{/number}","pulls_url":"https://api.github.com/repos/wandernauta/viskell/pulls{/number}","milestones_url":"https://api.github.com/repos/wandernauta/viskell/milestones{/number}","notifications_url":"https://api.github.com/repos/wandernauta/viskell/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/wandernauta/viskell/labels{/name}","releases_url":"https://api.github.com/repos/wandernauta/viskell/releases{/id}","created_at":"2015-02-03T13:04:49Z","updated_at":"2015-06-09T07:28:51Z","pushed_at":"2015-07-05T17:00:44Z","git_url":"git://github.com/wandernauta/viskell.git","ssh_url":"git@github.com:wandernauta/viskell.git","clone_url":"https://github.com/wandernauta/viskell.git","svn_url":"https://github.com/wandernauta/viskell","homepage":null,"size":5272,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":11,"forks":0,"open_issues":11,"watchers":0,"default_branch":"master"}},"base":{"label":"wandernauta:master","ref":"master","sha":"b0340309573607ebe144b0367ab3b66dbd38e4c3","user":{"login":"wandernauta","id":126832,"avatar_url":"https://avatars.githubusercontent.com/u/126832?v=3","gravatar_id":"","url":"https://api.github.com/users/wandernauta","html_url":"https://github.com/wandernauta","followers_url":"https://api.github.com/users/wandernauta/followers","following_url":"https://api.github.com/users/wandernauta/following{/other_user}","gists_url":"https://api.github.com/users/wandernauta/gists{/gist_id}","starred_url":"https://api.github.com/users/wandernauta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wandernauta/subscriptions","organizations_url":"https://api.github.com/users/wandernauta/orgs","repos_url":"https://api.github.com/users/wandernauta/repos","events_url":"https://api.github.com/users/wandernauta/events{/privacy}","received_events_url":"https://api.github.com/users/wandernauta/received_events","type":"User","site_admin":false},"repo":{"id":30242992,"name":"viskell","full_name":"wandernauta/viskell","owner":{"login":"wandernauta","id":126832,"avatar_url":"https://avatars.githubusercontent.com/u/126832?v=3","gravatar_id":"","url":"https://api.github.com/users/wandernauta","html_url":"https://github.com/wandernauta","followers_url":"https://api.github.com/users/wandernauta/followers","following_url":"https://api.github.com/users/wandernauta/following{/other_user}","gists_url":"https://api.github.com/users/wandernauta/gists{/gist_id}","starred_url":"https://api.github.com/users/wandernauta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wandernauta/subscriptions","organizations_url":"https://api.github.com/users/wandernauta/orgs","repos_url":"https://api.github.com/users/wandernauta/repos","events_url":"https://api.github.com/users/wandernauta/events{/privacy}","received_events_url":"https://api.github.com/users/wandernauta/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/wandernauta/viskell","description":"Ontwerpproject.","fork":false,"url":"https://api.github.com/repos/wandernauta/viskell","forks_url":"https://api.github.com/repos/wandernauta/viskell/forks","keys_url":"https://api.github.com/repos/wandernauta/viskell/keys{/key_id}","collaborators_url":"https://api.github.com/repos/wandernauta/viskell/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/wandernauta/viskell/teams","hooks_url":"https://api.github.com/repos/wandernauta/viskell/hooks","issue_events_url":"https://api.github.com/repos/wandernauta/viskell/issues/events{/number}","events_url":"https://api.github.com/repos/wandernauta/viskell/events","assignees_url":"https://api.github.com/repos/wandernauta/viskell/assignees{/user}","branches_url":"https://api.github.com/repos/wandernauta/viskell/branches{/branch}","tags_url":"https://api.github.com/repos/wandernauta/viskell/tags","blobs_url":"https://api.github.com/repos/wandernauta/viskell/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/wandernauta/viskell/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/wandernauta/viskell/git/refs{/sha}","trees_url":"https://api.github.com/repos/wandernauta/viskell/git/trees{/sha}","statuses_url":"https://api.github.com/repos/wandernauta/viskell/statuses/{sha}","languages_url":"https://api.github.com/repos/wandernauta/viskell/languages","stargazers_url":"https://api.github.com/repos/wandernauta/viskell/stargazers","contributors_url":"https://api.github.com/repos/wandernauta/viskell/contributors","subscribers_url":"https://api.github.com/repos/wandernauta/viskell/subscribers","subscription_url":"https://api.github.com/repos/wandernauta/viskell/subscription","commits_url":"https://api.github.com/repos/wandernauta/viskell/commits{/sha}","git_commits_url":"https://api.github.com/repos/wandernauta/viskell/git/commits{/sha}","comments_url":"https://api.github.com/repos/wandernauta/viskell/comments{/number}","issue_comment_url":"https://api.github.com/repos/wandernauta/viskell/issues/comments{/number}","contents_url":"https://api.github.com/repos/wandernauta/viskell/contents/{+path}","compare_url":"https://api.github.com/repos/wandernauta/viskell/compare/{base}...{head}","merges_url":"https://api.github.com/repos/wandernauta/viskell/merges","archive_url":"https://api.github.com/repos/wandernauta/viskell/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/wandernauta/viskell/downloads","issues_url":"https://api.github.com/repos/wandernauta/viskell/issues{/number}","pulls_url":"https://api.github.com/repos/wandernauta/viskell/pulls{/number}","milestones_url":"https://api.github.com/repos/wandernauta/viskell/milestones{/number}","notifications_url":"https://api.github.com/repos/wandernauta/viskell/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/wandernauta/viskell/labels{/name}","releases_url":"https://api.github.com/repos/wandernauta/viskell/releases{/id}","created_at":"2015-02-03T13:04:49Z","updated_at":"2015-06-09T07:28:51Z","pushed_at":"2015-07-05T17:00:44Z","git_url":"git://github.com/wandernauta/viskell.git","ssh_url":"git@github.com:wandernauta/viskell.git","clone_url":"https://github.com/wandernauta/viskell.git","svn_url":"https://github.com/wandernauta/viskell","homepage":null,"size":5272,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":11,"forks":0,"open_issues":11,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/wandernauta/viskell/pulls/123"},"html":{"href":"https://github.com/wandernauta/viskell/pull/123"},"issue":{"href":"https://api.github.com/repos/wandernauta/viskell/issues/123"},"comments":{"href":"https://api.github.com/repos/wandernauta/viskell/issues/123/comments"},"review_comments":{"href":"https://api.github.com/repos/wandernauta/viskell/pulls/123/comments"},"review_comment":{"href":"https://api.github.com/repos/wandernauta/viskell/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/wandernauta/viskell/pulls/123/commits"},"statuses":{"href":"https://api.github.com/repos/wandernauta/viskell/statuses/29e7bde4b2d29e6fce76a172c51ee80a5bbca4a8"}}}}