{"action":"created","comment":{"url":"https://api.github.com/repos/freeorion/freeorion/pulls/comments/39195356","id":39195356,"diff_hunk":"@@ -0,0 +1,152 @@\n+#include <GG/RichText/ImageBlock.h>\n+\n+#include <GG/Texture.h>\n+#include <GG/RichText/RichText.h>\n+#include <GG/TextControl.h>\n+#include <GG/DrawUtil.h>\n+\n+#include <GG/dialogs/FileDlg.h>\n+\n+#include <boost/filesystem.hpp>\n+#include <algorithm>\n+\n+namespace GG {\n+\n+    const std::string ImageBlock::IMAGE_TAG (\"img\");\n+\n+    ImageBlock::ImageBlock (const std::string& image_path, X x, Y y, X w, GG::Flags< GG::WndFlag > flags) :\n+        BlockControl (x, y, w, flags),\n+        m_graphic (0) {\n+        try {\n+            boost::shared_ptr<Texture> texture = GetTextureManager().GetTexture (image_path);\n+            m_graphic = new StaticGraphic (texture, GRAPHIC_PROPSCALE | GRAPHIC_SHRINKFIT | GRAPHIC_CENTER);\n+            AttachChild (m_graphic);\n+        } catch (GG::Texture::BadFile& errBadFile) {\n+            // No can do inside GiGi.\n+        }\n+    }\n+\n+    Pt ImageBlock::SetMaxWidth (X width) {\n+\n+        if (m_graphic != 0) {\n+            // Give the graphic the set width and give it liberty with the height.\n+            m_graphic->Resize (Pt (width, Y (INT_MAX)));\n+\n+            // Get the actual space the graphic decided to use.\n+            Rect rect = m_graphic->RenderedArea();\n+            Pt size = rect.LowerRight() - rect.UpperLeft();\n+\n+            // Take up the full width to center the image.\n+            size.x = width;\n+\n+            // Don't take the extra vertical space.\n+            m_graphic->Resize (size);\n+\n+            // Update our size to match the graphic we are wrapping.\n+            Resize (size);\n+\n+            // Return the size we decided to be.\n+            return size;\n+        } else {\n+            // We don't have an image. Take a quarter of width to show an X.\n+            Pt size (width, Y (Value (width) / 4));\n+            Resize (size);\n+            return size;\n+        }\n+    }\n+\n+    void ImageBlock::Render() {\n+        if (m_graphic == 0) {\n+            // Error: no image. Draw red x.\n+            Pt ul = UpperLeft();\n+            Pt lr = LowerRight();\n+            Pt size = lr - ul;\n+            ul.x += size.x / 2 - X (Value (size.y)) / 2;\n+            lr.x -= size.x / 2 - X (Value (size.y)) / 2;\n+            FlatX (ul, lr, CLR_RED);\n+        }\n+    }\n+\n+    // A factory for creating image blocks from tags.\n+    class ImageBlockFactory: public RichText::IBlockControlFactory {\n+        public:\n+            ImageBlockFactory() :\n+                m_root_path (\".\")\n+            {}\n+\n+            //! Create a Text block from a plain text tag.\n+            virtual BlockControl* CreateFromTag (const std::string& tag,\n+                                                 const RichText::TAG_PARAMS& params,\n+                                                 const std::string& content,\n+                                                 const boost::shared_ptr<Font>& font,\n+                                                 Clr color,\n+                                                 Flags<TextFormat> format\n+                                                ) {\n+                // Get the path from the parameters.\n+                std::string path = ExtractPath (params);\n+\n+                // Create a new image block, basing the path on the root path.\n+                return new ImageBlock ( (m_root_path / FileDlg::StringToPath(path)).string() , X0, Y0, X1, Flags<WndFlag>());\n+            }\n+\n+            // Sets the root of image search path.\n+            void SetRootPath (const std::string& path) {\n+                m_root_path = FileDlg::StringToPath(path);\n+            }\n+        private:\n+            boost::filesystem::path m_root_path;\n+\n+            // Extracts the path from the given params.\n+            static std::string ExtractPath (const RichText::TAG_PARAMS& params) {\n+\n+                // Find the src.\n+                RichText::TAG_PARAMS::const_iterator src_param = params.find (\"src\");\n+\n+                // If src not found, error out.\n+                if (src_param == params.end()) {\n+                    return std::string (\"ERR:invalid params: missing src.\");\n+                } else {\n+                    // Return the path.\n+                    return src_param->second;\n+                }\n+            }\n+    };\n+\n+    // Register image block as the image tag handler.\n+    static int dummy = RichText::RegisterDefaultBlock (ImageBlock::IMAGE_TAG, new ImageBlockFactory());\n+\n+    //! Set the root path from which to look for images with the factory.\n+    bool ImageBlock::SetImagePath (RichText::IBlockControlFactory* factory, //!< The factory to set the path for. Should be an image block factory.","path":"GG/src/RichText/ImageBlock.cpp","position":119,"original_position":119,"commit_id":"4fa40df03f2b4dcffbb8a372e30ee8a962ab95c8","original_commit_id":"4fa40df03f2b4dcffbb8a372e30ee8a962ab95c8","user":{"login":"geoffthemedio","id":11386908,"avatar_url":"https://avatars.githubusercontent.com/u/11386908?v=3","gravatar_id":"","url":"https://api.github.com/users/geoffthemedio","html_url":"https://github.com/geoffthemedio","followers_url":"https://api.github.com/users/geoffthemedio/followers","following_url":"https://api.github.com/users/geoffthemedio/following{/other_user}","gists_url":"https://api.github.com/users/geoffthemedio/gists{/gist_id}","starred_url":"https://api.github.com/users/geoffthemedio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/geoffthemedio/subscriptions","organizations_url":"https://api.github.com/users/geoffthemedio/orgs","repos_url":"https://api.github.com/users/geoffthemedio/repos","events_url":"https://api.github.com/users/geoffthemedio/events{/privacy}","received_events_url":"https://api.github.com/users/geoffthemedio/received_events","type":"User","site_admin":false},"body":"Perhaps should abandon the string path and root path stuff and just have ImageBlock take a Texture parameter like StaticGraphic does...? I suppose that makes in-GG img tag handling problematic, though?","created_at":"2015-09-10T18:26:36Z","updated_at":"2015-09-10T18:26:36Z","html_url":"https://github.com/freeorion/freeorion/pull/332#discussion_r39195356","pull_request_url":"https://api.github.com/repos/freeorion/freeorion/pulls/332","_links":{"self":{"href":"https://api.github.com/repos/freeorion/freeorion/pulls/comments/39195356"},"html":{"href":"https://github.com/freeorion/freeorion/pull/332#discussion_r39195356"},"pull_request":{"href":"https://api.github.com/repos/freeorion/freeorion/pulls/332"}}},"pull_request":{"url":"https://api.github.com/repos/freeorion/freeorion/pulls/332","id":44471608,"html_url":"https://github.com/freeorion/freeorion/pull/332","diff_url":"https://github.com/freeorion/freeorion/pull/332.diff","patch_url":"https://github.com/freeorion/freeorion/pull/332.patch","issue_url":"https://api.github.com/repos/freeorion/freeorion/issues/332","number":332,"state":"open","locked":false,"title":"Images in the encyclopedia","user":{"login":"Mitten-O","id":8913801,"avatar_url":"https://avatars.githubusercontent.com/u/8913801?v=3","gravatar_id":"","url":"https://api.github.com/users/Mitten-O","html_url":"https://github.com/Mitten-O","followers_url":"https://api.github.com/users/Mitten-O/followers","following_url":"https://api.github.com/users/Mitten-O/following{/other_user}","gists_url":"https://api.github.com/users/Mitten-O/gists{/gist_id}","starred_url":"https://api.github.com/users/Mitten-O/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Mitten-O/subscriptions","organizations_url":"https://api.github.com/users/Mitten-O/orgs","repos_url":"https://api.github.com/users/Mitten-O/repos","events_url":"https://api.github.com/users/Mitten-O/events{/privacy}","received_events_url":"https://api.github.com/users/Mitten-O/received_events","type":"User","site_admin":false},"body":"Adds the capability to embed images into encyclopedia articles.\r\n\r\nIntroduces a new text control, RichText, that parses its contents\r\nfor registered tags and creates control to display them using\r\nfactories provided at tag registration.\r\n\r\nThe tag handler controls must derive from BlockControl.\r\nIt defines the contract between the blocks and th container:\r\nthe container specifies the width and the block determines its height.\r\nThis is the easiest reasonable way to flow text.\r\n\r\nThere are only two registered tags for now, img and RichText::PLAINTEXT_TAG.\r\nImageBlock is registered to handle images and TextBLock is used to handle plain text by default.\r\n\r\nIn the encyclopedia, CUILinkTextBlock is registered as the plain text handler to\r\nenable links.\r\n\r\n![fo_suitability_wheel_image](https://cloud.githubusercontent.com/assets/8913801/9744880/228971f6-5677-11e5-8fe0-58e8665a516c.png)\r\n\r\nOnly centered, native size or automatically smaller images for now.","created_at":"2015-09-08T19:17:32Z","updated_at":"2015-09-10T18:26:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"796db1872613659f7f66b8c611211d1da173d64e","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/freeorion/freeorion/pulls/332/commits","review_comments_url":"https://api.github.com/repos/freeorion/freeorion/pulls/332/comments","review_comment_url":"https://api.github.com/repos/freeorion/freeorion/pulls/comments{/number}","comments_url":"https://api.github.com/repos/freeorion/freeorion/issues/332/comments","statuses_url":"https://api.github.com/repos/freeorion/freeorion/statuses/4fa40df03f2b4dcffbb8a372e30ee8a962ab95c8","head":{"label":"Mitten-O:rich_text_more","ref":"rich_text_more","sha":"4fa40df03f2b4dcffbb8a372e30ee8a962ab95c8","user":{"login":"Mitten-O","id":8913801,"avatar_url":"https://avatars.githubusercontent.com/u/8913801?v=3","gravatar_id":"","url":"https://api.github.com/users/Mitten-O","html_url":"https://github.com/Mitten-O","followers_url":"https://api.github.com/users/Mitten-O/followers","following_url":"https://api.github.com/users/Mitten-O/following{/other_user}","gists_url":"https://api.github.com/users/Mitten-O/gists{/gist_id}","starred_url":"https://api.github.com/users/Mitten-O/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Mitten-O/subscriptions","organizations_url":"https://api.github.com/users/Mitten-O/orgs","repos_url":"https://api.github.com/users/Mitten-O/repos","events_url":"https://api.github.com/users/Mitten-O/events{/privacy}","received_events_url":"https://api.github.com/users/Mitten-O/received_events","type":"User","site_admin":false},"repo":{"id":33953402,"name":"freeorion","full_name":"Mitten-O/freeorion","owner":{"login":"Mitten-O","id":8913801,"avatar_url":"https://avatars.githubusercontent.com/u/8913801?v=3","gravatar_id":"","url":"https://api.github.com/users/Mitten-O","html_url":"https://github.com/Mitten-O","followers_url":"https://api.github.com/users/Mitten-O/followers","following_url":"https://api.github.com/users/Mitten-O/following{/other_user}","gists_url":"https://api.github.com/users/Mitten-O/gists{/gist_id}","starred_url":"https://api.github.com/users/Mitten-O/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Mitten-O/subscriptions","organizations_url":"https://api.github.com/users/Mitten-O/orgs","repos_url":"https://api.github.com/users/Mitten-O/repos","events_url":"https://api.github.com/users/Mitten-O/events{/privacy}","received_events_url":"https://api.github.com/users/Mitten-O/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Mitten-O/freeorion","description":"Source code repository of the FreeOrion project.","fork":true,"url":"https://api.github.com/repos/Mitten-O/freeorion","forks_url":"https://api.github.com/repos/Mitten-O/freeorion/forks","keys_url":"https://api.github.com/repos/Mitten-O/freeorion/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Mitten-O/freeorion/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Mitten-O/freeorion/teams","hooks_url":"https://api.github.com/repos/Mitten-O/freeorion/hooks","issue_events_url":"https://api.github.com/repos/Mitten-O/freeorion/issues/events{/number}","events_url":"https://api.github.com/repos/Mitten-O/freeorion/events","assignees_url":"https://api.github.com/repos/Mitten-O/freeorion/assignees{/user}","branches_url":"https://api.github.com/repos/Mitten-O/freeorion/branches{/branch}","tags_url":"https://api.github.com/repos/Mitten-O/freeorion/tags","blobs_url":"https://api.github.com/repos/Mitten-O/freeorion/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Mitten-O/freeorion/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Mitten-O/freeorion/git/refs{/sha}","trees_url":"https://api.github.com/repos/Mitten-O/freeorion/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Mitten-O/freeorion/statuses/{sha}","languages_url":"https://api.github.com/repos/Mitten-O/freeorion/languages","stargazers_url":"https://api.github.com/repos/Mitten-O/freeorion/stargazers","contributors_url":"https://api.github.com/repos/Mitten-O/freeorion/contributors","subscribers_url":"https://api.github.com/repos/Mitten-O/freeorion/subscribers","subscription_url":"https://api.github.com/repos/Mitten-O/freeorion/subscription","commits_url":"https://api.github.com/repos/Mitten-O/freeorion/commits{/sha}","git_commits_url":"https://api.github.com/repos/Mitten-O/freeorion/git/commits{/sha}","comments_url":"https://api.github.com/repos/Mitten-O/freeorion/comments{/number}","issue_comment_url":"https://api.github.com/repos/Mitten-O/freeorion/issues/comments{/number}","contents_url":"https://api.github.com/repos/Mitten-O/freeorion/contents/{+path}","compare_url":"https://api.github.com/repos/Mitten-O/freeorion/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Mitten-O/freeorion/merges","archive_url":"https://api.github.com/repos/Mitten-O/freeorion/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Mitten-O/freeorion/downloads","issues_url":"https://api.github.com/repos/Mitten-O/freeorion/issues{/number}","pulls_url":"https://api.github.com/repos/Mitten-O/freeorion/pulls{/number}","milestones_url":"https://api.github.com/repos/Mitten-O/freeorion/milestones{/number}","notifications_url":"https://api.github.com/repos/Mitten-O/freeorion/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Mitten-O/freeorion/labels{/name}","releases_url":"https://api.github.com/repos/Mitten-O/freeorion/releases{/id}","created_at":"2015-04-14T19:49:23Z","updated_at":"2015-04-15T18:47:09Z","pushed_at":"2015-09-10T18:16:29Z","git_url":"git://github.com/Mitten-O/freeorion.git","ssh_url":"git@github.com:Mitten-O/freeorion.git","clone_url":"https://github.com/Mitten-O/freeorion.git","svn_url":"https://github.com/Mitten-O/freeorion","homepage":"http://www.freeorion.org/","size":489144,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"freeorion:master","ref":"master","sha":"0868ed4c24030d9b9108f96950d59fde2b0537c4","user":{"login":"freeorion","id":1025550,"avatar_url":"https://avatars.githubusercontent.com/u/1025550?v=3","gravatar_id":"","url":"https://api.github.com/users/freeorion","html_url":"https://github.com/freeorion","followers_url":"https://api.github.com/users/freeorion/followers","following_url":"https://api.github.com/users/freeorion/following{/other_user}","gists_url":"https://api.github.com/users/freeorion/gists{/gist_id}","starred_url":"https://api.github.com/users/freeorion/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/freeorion/subscriptions","organizations_url":"https://api.github.com/users/freeorion/orgs","repos_url":"https://api.github.com/users/freeorion/repos","events_url":"https://api.github.com/users/freeorion/events{/privacy}","received_events_url":"https://api.github.com/users/freeorion/received_events","type":"Organization","site_admin":false},"repo":{"id":33066062,"name":"freeorion","full_name":"freeorion/freeorion","owner":{"login":"freeorion","id":1025550,"avatar_url":"https://avatars.githubusercontent.com/u/1025550?v=3","gravatar_id":"","url":"https://api.github.com/users/freeorion","html_url":"https://github.com/freeorion","followers_url":"https://api.github.com/users/freeorion/followers","following_url":"https://api.github.com/users/freeorion/following{/other_user}","gists_url":"https://api.github.com/users/freeorion/gists{/gist_id}","starred_url":"https://api.github.com/users/freeorion/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/freeorion/subscriptions","organizations_url":"https://api.github.com/users/freeorion/orgs","repos_url":"https://api.github.com/users/freeorion/repos","events_url":"https://api.github.com/users/freeorion/events{/privacy}","received_events_url":"https://api.github.com/users/freeorion/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/freeorion/freeorion","description":"Source code repository of the FreeOrion project.","fork":false,"url":"https://api.github.com/repos/freeorion/freeorion","forks_url":"https://api.github.com/repos/freeorion/freeorion/forks","keys_url":"https://api.github.com/repos/freeorion/freeorion/keys{/key_id}","collaborators_url":"https://api.github.com/repos/freeorion/freeorion/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/freeorion/freeorion/teams","hooks_url":"https://api.github.com/repos/freeorion/freeorion/hooks","issue_events_url":"https://api.github.com/repos/freeorion/freeorion/issues/events{/number}","events_url":"https://api.github.com/repos/freeorion/freeorion/events","assignees_url":"https://api.github.com/repos/freeorion/freeorion/assignees{/user}","branches_url":"https://api.github.com/repos/freeorion/freeorion/branches{/branch}","tags_url":"https://api.github.com/repos/freeorion/freeorion/tags","blobs_url":"https://api.github.com/repos/freeorion/freeorion/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/freeorion/freeorion/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/freeorion/freeorion/git/refs{/sha}","trees_url":"https://api.github.com/repos/freeorion/freeorion/git/trees{/sha}","statuses_url":"https://api.github.com/repos/freeorion/freeorion/statuses/{sha}","languages_url":"https://api.github.com/repos/freeorion/freeorion/languages","stargazers_url":"https://api.github.com/repos/freeorion/freeorion/stargazers","contributors_url":"https://api.github.com/repos/freeorion/freeorion/contributors","subscribers_url":"https://api.github.com/repos/freeorion/freeorion/subscribers","subscription_url":"https://api.github.com/repos/freeorion/freeorion/subscription","commits_url":"https://api.github.com/repos/freeorion/freeorion/commits{/sha}","git_commits_url":"https://api.github.com/repos/freeorion/freeorion/git/commits{/sha}","comments_url":"https://api.github.com/repos/freeorion/freeorion/comments{/number}","issue_comment_url":"https://api.github.com/repos/freeorion/freeorion/issues/comments{/number}","contents_url":"https://api.github.com/repos/freeorion/freeorion/contents/{+path}","compare_url":"https://api.github.com/repos/freeorion/freeorion/compare/{base}...{head}","merges_url":"https://api.github.com/repos/freeorion/freeorion/merges","archive_url":"https://api.github.com/repos/freeorion/freeorion/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/freeorion/freeorion/downloads","issues_url":"https://api.github.com/repos/freeorion/freeorion/issues{/number}","pulls_url":"https://api.github.com/repos/freeorion/freeorion/pulls{/number}","milestones_url":"https://api.github.com/repos/freeorion/freeorion/milestones{/number}","notifications_url":"https://api.github.com/repos/freeorion/freeorion/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/freeorion/freeorion/labels{/name}","releases_url":"https://api.github.com/repos/freeorion/freeorion/releases{/id}","created_at":"2015-03-29T08:22:20Z","updated_at":"2015-09-10T08:52:04Z","pushed_at":"2015-09-10T18:16:30Z","git_url":"git://github.com/freeorion/freeorion.git","ssh_url":"git@github.com:freeorion/freeorion.git","clone_url":"https://github.com/freeorion/freeorion.git","svn_url":"https://github.com/freeorion/freeorion","homepage":"http://www.freeorion.org/","size":503137,"stargazers_count":82,"watchers_count":82,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":37,"mirror_url":null,"open_issues_count":19,"forks":37,"open_issues":19,"watchers":82,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/freeorion/freeorion/pulls/332"},"html":{"href":"https://github.com/freeorion/freeorion/pull/332"},"issue":{"href":"https://api.github.com/repos/freeorion/freeorion/issues/332"},"comments":{"href":"https://api.github.com/repos/freeorion/freeorion/issues/332/comments"},"review_comments":{"href":"https://api.github.com/repos/freeorion/freeorion/pulls/332/comments"},"review_comment":{"href":"https://api.github.com/repos/freeorion/freeorion/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/freeorion/freeorion/pulls/332/commits"},"statuses":{"href":"https://api.github.com/repos/freeorion/freeorion/statuses/4fa40df03f2b4dcffbb8a372e30ee8a962ab95c8"}}}}