editor_help.cpp 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663
  1. /*************************************************************************/
  2. /* editor_help.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "editor_help.h"
  31. #include "doc_data_compressed.gen.h"
  32. #include "editor/plugins/script_editor_plugin.h"
  33. #include "editor_node.h"
  34. #include "editor_settings.h"
  35. #include "os/keyboard.h"
  36. #include "os/keyboard.h"
  37. void EditorHelpSearch::popup() {
  38. popup_centered_ratio(0.6);
  39. if (search_box->get_text() != "") {
  40. search_box->select_all();
  41. _update_search();
  42. }
  43. search_box->grab_focus();
  44. }
  45. void EditorHelpSearch::popup(const String &p_term) {
  46. popup_centered_ratio(0.6);
  47. if (p_term != "") {
  48. search_box->set_text(p_term);
  49. search_box->select_all();
  50. _update_search();
  51. } else
  52. search_box->clear();
  53. search_box->grab_focus();
  54. }
  55. void EditorHelpSearch::_text_changed(const String &p_newtext) {
  56. _update_search();
  57. }
  58. void EditorHelpSearch::_sbox_input(const InputEvent &p_ie) {
  59. if (p_ie.type == InputEvent::KEY && (p_ie.key.scancode == KEY_UP ||
  60. p_ie.key.scancode == KEY_DOWN ||
  61. p_ie.key.scancode == KEY_PAGEUP ||
  62. p_ie.key.scancode == KEY_PAGEDOWN)) {
  63. search_options->call("_input_event", p_ie);
  64. search_box->accept_event();
  65. }
  66. }
  67. void EditorHelpSearch::_update_search() {
  68. search_options->clear();
  69. search_options->set_hide_root(true);
  70. /*
  71. TreeItem *root = search_options->create_item();
  72. _parse_fs(EditorFileSystem::get_singleton()->get_filesystem());
  73. */
  74. List<StringName> type_list;
  75. ObjectTypeDB::get_type_list(&type_list);
  76. DocData *doc = EditorHelp::get_doc_data();
  77. String term = search_box->get_text();
  78. if (term.length() < 2)
  79. return;
  80. TreeItem *root = search_options->create_item();
  81. Ref<Texture> def_icon = get_icon("Node", "EditorIcons");
  82. //classes first
  83. for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) {
  84. if (E->key().findn(term) != -1) {
  85. TreeItem *item = search_options->create_item(root);
  86. item->set_metadata(0, "class_name:" + E->key());
  87. item->set_text(0, E->key() + " (Class)");
  88. if (has_icon(E->key(), "EditorIcons"))
  89. item->set_icon(0, get_icon(E->key(), "EditorIcons"));
  90. else
  91. item->set_icon(0, def_icon);
  92. }
  93. }
  94. //class methods, etc second
  95. for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) {
  96. DocData::ClassDoc &c = E->get();
  97. Ref<Texture> cicon;
  98. if (has_icon(E->key(), "EditorIcons"))
  99. cicon = get_icon(E->key(), "EditorIcons");
  100. else
  101. cicon = def_icon;
  102. for (int i = 0; i < c.methods.size(); i++) {
  103. if ((term.begins_with(".") && c.methods[i].name.begins_with(term.right(1))) || (term.ends_with("(") && c.methods[i].name.ends_with(term.left(term.length() - 1).strip_edges())) || (term.begins_with(".") && term.ends_with("(") && c.methods[i].name == term.substr(1, term.length() - 2).strip_edges()) || c.methods[i].name.findn(term) != -1) {
  104. TreeItem *item = search_options->create_item(root);
  105. item->set_metadata(0, "class_method:" + E->key() + ":" + c.methods[i].name);
  106. item->set_text(0, E->key() + "." + c.methods[i].name + " (Method)");
  107. item->set_icon(0, cicon);
  108. }
  109. }
  110. for (int i = 0; i < c.signals.size(); i++) {
  111. if (c.signals[i].name.findn(term) != -1) {
  112. TreeItem *item = search_options->create_item(root);
  113. item->set_metadata(0, "class_signal:" + E->key() + ":" + c.signals[i].name);
  114. item->set_text(0, E->key() + "." + c.signals[i].name + " (Signal)");
  115. item->set_icon(0, cicon);
  116. }
  117. }
  118. for (int i = 0; i < c.constants.size(); i++) {
  119. if (c.constants[i].name.findn(term) != -1) {
  120. TreeItem *item = search_options->create_item(root);
  121. item->set_metadata(0, "class_constant:" + E->key() + ":" + c.constants[i].name);
  122. item->set_text(0, E->key() + "." + c.constants[i].name + " (Constant)");
  123. item->set_icon(0, cicon);
  124. }
  125. }
  126. for (int i = 0; i < c.properties.size(); i++) {
  127. if (c.properties[i].name.findn(term) != -1) {
  128. TreeItem *item = search_options->create_item(root);
  129. item->set_metadata(0, "class_property:" + E->key() + ":" + c.properties[i].name);
  130. item->set_text(0, E->key() + "." + c.properties[i].name + " (Property)");
  131. item->set_icon(0, cicon);
  132. }
  133. }
  134. for (int i = 0; i < c.theme_properties.size(); i++) {
  135. if (c.theme_properties[i].name.findn(term) != -1) {
  136. TreeItem *item = search_options->create_item(root);
  137. item->set_metadata(0, "class_theme_item:" + E->key() + ":" + c.theme_properties[i].name);
  138. item->set_text(0, E->key() + "." + c.theme_properties[i].name + " (Theme Item)");
  139. item->set_icon(0, cicon);
  140. }
  141. }
  142. }
  143. //same but descriptions
  144. for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) {
  145. DocData::ClassDoc &c = E->get();
  146. Ref<Texture> cicon;
  147. if (has_icon(E->key(), "EditorIcons"))
  148. cicon = get_icon(E->key(), "EditorIcons");
  149. else
  150. cicon = def_icon;
  151. if (c.description.findn(term) != -1) {
  152. TreeItem *item = search_options->create_item(root);
  153. item->set_metadata(0, "class_desc:" + E->key());
  154. item->set_text(0, E->key() + " (Class Description)");
  155. item->set_icon(0, cicon);
  156. }
  157. for (int i = 0; i < c.methods.size(); i++) {
  158. if (c.methods[i].description.findn(term) != -1) {
  159. TreeItem *item = search_options->create_item(root);
  160. item->set_metadata(0, "class_method_desc:" + E->key() + ":" + c.methods[i].name);
  161. item->set_text(0, E->key() + "." + c.methods[i].name + " (Method Description)");
  162. item->set_icon(0, cicon);
  163. }
  164. }
  165. for (int i = 0; i < c.signals.size(); i++) {
  166. if (c.signals[i].description.findn(term) != -1) {
  167. TreeItem *item = search_options->create_item(root);
  168. item->set_metadata(0, "class_signal:" + E->key() + ":" + c.signals[i].name);
  169. item->set_text(0, E->key() + "." + c.signals[i].name + " (Signal Description)");
  170. item->set_icon(0, cicon);
  171. }
  172. }
  173. for (int i = 0; i < c.constants.size(); i++) {
  174. if (c.constants[i].description.findn(term) != -1) {
  175. TreeItem *item = search_options->create_item(root);
  176. item->set_metadata(0, "class_constant:" + E->key() + ":" + c.constants[i].name);
  177. item->set_text(0, E->key() + "." + c.constants[i].name + " (Constant Description)");
  178. item->set_icon(0, cicon);
  179. }
  180. }
  181. for (int i = 0; i < c.properties.size(); i++) {
  182. if (c.properties[i].description.findn(term) != -1) {
  183. TreeItem *item = search_options->create_item(root);
  184. item->set_metadata(0, "class_property_desc:" + E->key() + ":" + c.properties[i].name);
  185. item->set_text(0, E->key() + "." + c.properties[i].name + " (Property Description)");
  186. item->set_icon(0, cicon);
  187. }
  188. }
  189. }
  190. get_ok()->set_disabled(root->get_children() == NULL);
  191. }
  192. void EditorHelpSearch::_confirmed() {
  193. TreeItem *ti = search_options->get_selected();
  194. if (!ti)
  195. return;
  196. String mdata = ti->get_metadata(0);
  197. emit_signal("go_to_help", mdata);
  198. editor->call("_editor_select", EditorNode::EDITOR_SCRIPT); // in case EditorHelpSearch beeen invoked on top of other editor window
  199. // go to that
  200. hide();
  201. }
  202. void EditorHelpSearch::_notification(int p_what) {
  203. if (p_what == NOTIFICATION_ENTER_TREE) {
  204. connect("confirmed", this, "_confirmed");
  205. _update_search();
  206. }
  207. if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
  208. if (is_visible()) {
  209. search_box->call_deferred("grab_focus"); // still not visible
  210. search_box->select_all();
  211. }
  212. }
  213. }
  214. void EditorHelpSearch::_bind_methods() {
  215. ObjectTypeDB::bind_method(_MD("_text_changed"), &EditorHelpSearch::_text_changed);
  216. ObjectTypeDB::bind_method(_MD("_confirmed"), &EditorHelpSearch::_confirmed);
  217. ObjectTypeDB::bind_method(_MD("_sbox_input"), &EditorHelpSearch::_sbox_input);
  218. ObjectTypeDB::bind_method(_MD("_update_search"), &EditorHelpSearch::_update_search);
  219. ADD_SIGNAL(MethodInfo("go_to_help"));
  220. }
  221. EditorHelpSearch::EditorHelpSearch() {
  222. editor = EditorNode::get_singleton();
  223. VBoxContainer *vbc = memnew(VBoxContainer);
  224. add_child(vbc);
  225. set_child_rect(vbc);
  226. HBoxContainer *sb_hb = memnew(HBoxContainer);
  227. search_box = memnew(LineEdit);
  228. sb_hb->add_child(search_box);
  229. search_box->set_h_size_flags(SIZE_EXPAND_FILL);
  230. Button *sb = memnew(Button(TTR("Search")));
  231. sb->connect("pressed", this, "_update_search");
  232. sb_hb->add_child(sb);
  233. vbc->add_margin_child(TTR("Search:"), sb_hb);
  234. search_box->connect("text_changed", this, "_text_changed");
  235. search_box->connect("input_event", this, "_sbox_input");
  236. search_options = memnew(Tree);
  237. vbc->add_margin_child(TTR("Matches:"), search_options, true);
  238. get_ok()->set_text(TTR("Open"));
  239. get_ok()->set_disabled(true);
  240. register_text_enter(search_box);
  241. set_hide_on_ok(false);
  242. search_options->connect("item_activated", this, "_confirmed");
  243. set_title(TTR("Search Help"));
  244. // search_options->set_hide_root(true);
  245. }
  246. /////////////////////////////////
  247. ////////////////////////////////////
  248. /// /////////////////////////////////
  249. void EditorHelpIndex::add_type(const String &p_type, HashMap<String, TreeItem *> &p_types, TreeItem *p_root) {
  250. if (p_types.has(p_type))
  251. return;
  252. // if (!ObjectTypeDB::is_type(p_type,base) || p_type==base)
  253. // return;
  254. String inherits = EditorHelp::get_doc_data()->class_list[p_type].inherits;
  255. TreeItem *parent = p_root;
  256. if (inherits.length()) {
  257. if (!p_types.has(inherits)) {
  258. add_type(inherits, p_types, p_root);
  259. }
  260. if (p_types.has(inherits))
  261. parent = p_types[inherits];
  262. }
  263. TreeItem *item = class_list->create_item(parent);
  264. item->set_metadata(0, p_type);
  265. item->set_tooltip(0, EditorHelp::get_doc_data()->class_list[p_type].brief_description);
  266. item->set_text(0, p_type);
  267. if (has_icon(p_type, "EditorIcons")) {
  268. item->set_icon(0, get_icon(p_type, "EditorIcons"));
  269. }
  270. p_types[p_type] = item;
  271. }
  272. void EditorHelpIndex::_tree_item_selected() {
  273. TreeItem *s = class_list->get_selected();
  274. if (!s)
  275. return;
  276. emit_signal("open_class", s->get_text(0));
  277. hide();
  278. //_goto_desc(s->get_text(0));
  279. }
  280. void EditorHelpIndex::select_class(const String &p_class) {
  281. if (!tree_item_map.has(p_class))
  282. return;
  283. tree_item_map[p_class]->select(0);
  284. class_list->ensure_cursor_is_visible();
  285. }
  286. void EditorHelpIndex::popup() {
  287. popup_centered_ratio(0.6);
  288. search_box->set_text("");
  289. _update_class_list();
  290. }
  291. void EditorHelpIndex::_notification(int p_what) {
  292. if (p_what == NOTIFICATION_ENTER_TREE) {
  293. _update_class_list();
  294. connect("confirmed", this, "_tree_item_selected");
  295. } else if (p_what == NOTIFICATION_POST_POPUP) {
  296. search_box->call_deferred("grab_focus");
  297. }
  298. }
  299. void EditorHelpIndex::_text_changed(const String &p_text) {
  300. _update_class_list();
  301. }
  302. void EditorHelpIndex::_update_class_list() {
  303. class_list->clear();
  304. tree_item_map.clear();
  305. TreeItem *root = class_list->create_item();
  306. class_list->set_hide_root(true);
  307. String filter = search_box->get_text().strip_edges();
  308. String to_select = "";
  309. for (Map<String, DocData::ClassDoc>::Element *E = EditorHelp::get_doc_data()->class_list.front(); E; E = E->next()) {
  310. if (filter == "") {
  311. add_type(E->key(), tree_item_map, root);
  312. } else {
  313. bool found = false;
  314. String type = E->key();
  315. while (type != "") {
  316. if (filter.is_subsequence_ofi(type)) {
  317. if (to_select.empty()) {
  318. to_select = type;
  319. }
  320. found = true;
  321. break;
  322. }
  323. type = EditorHelp::get_doc_data()->class_list[type].inherits;
  324. }
  325. if (found) {
  326. add_type(E->key(), tree_item_map, root);
  327. }
  328. }
  329. }
  330. if (tree_item_map.has(filter)) {
  331. select_class(filter);
  332. } else if (to_select != "") {
  333. select_class(to_select);
  334. }
  335. }
  336. void EditorHelpIndex::_sbox_input(const InputEvent &p_ie) {
  337. if (p_ie.type == InputEvent::KEY && (p_ie.key.scancode == KEY_UP ||
  338. p_ie.key.scancode == KEY_DOWN ||
  339. p_ie.key.scancode == KEY_PAGEUP ||
  340. p_ie.key.scancode == KEY_PAGEDOWN)) {
  341. class_list->call("_input_event", p_ie);
  342. search_box->accept_event();
  343. }
  344. }
  345. void EditorHelpIndex::_bind_methods() {
  346. ObjectTypeDB::bind_method("_tree_item_selected", &EditorHelpIndex::_tree_item_selected);
  347. ObjectTypeDB::bind_method("_text_changed", &EditorHelpIndex::_text_changed);
  348. ObjectTypeDB::bind_method("_sbox_input", &EditorHelpIndex::_sbox_input);
  349. ObjectTypeDB::bind_method("select_class", &EditorHelpIndex::select_class);
  350. ADD_SIGNAL(MethodInfo("open_class"));
  351. }
  352. EditorHelpIndex::EditorHelpIndex() {
  353. VBoxContainer *vbc = memnew(VBoxContainer);
  354. add_child(vbc);
  355. set_child_rect(vbc);
  356. search_box = memnew(LineEdit);
  357. vbc->add_margin_child(TTR("Search:"), search_box);
  358. search_box->set_h_size_flags(SIZE_EXPAND_FILL);
  359. register_text_enter(search_box);
  360. search_box->connect("text_changed", this, "_text_changed");
  361. search_box->connect("input_event", this, "_sbox_input");
  362. class_list = memnew(Tree);
  363. vbc->add_margin_child(TTR("Class List:") + " ", class_list, true);
  364. class_list->set_v_size_flags(SIZE_EXPAND_FILL);
  365. class_list->connect("item_activated", this, "_tree_item_selected");
  366. get_ok()->set_text(TTR("Open"));
  367. set_title(TTR("Search Classes"));
  368. }
  369. /////////////////////////////////
  370. ////////////////////////////////////
  371. /// /////////////////////////////////
  372. DocData *EditorHelp::doc = NULL;
  373. void EditorHelp::_unhandled_key_input(const InputEvent &p_ev) {
  374. if (!is_visible())
  375. return;
  376. if (p_ev.key.mod.control && p_ev.key.scancode == KEY_F) {
  377. search->grab_focus();
  378. search->select_all();
  379. }
  380. }
  381. void EditorHelp::_search(const String &) {
  382. if (search->get_text() == "")
  383. return;
  384. String stext = search->get_text();
  385. bool keep = prev_search == stext;
  386. bool ret = class_desc->search(stext, keep);
  387. if (!ret) {
  388. class_desc->search(stext, false);
  389. }
  390. prev_search = stext;
  391. }
  392. #if 0
  393. void EditorHelp::_button_pressed(int p_idx) {
  394. if (p_idx==PAGE_CLASS_LIST) {
  395. // edited_class->set_pressed(false);
  396. // class_list_button->set_pressed(true);
  397. // tabs->set_current_tab(PAGE_CLASS_LIST);
  398. } else if (p_idx==PAGE_CLASS_DESC) {
  399. // edited_class->set_pressed(true);
  400. // class_list_button->set_pressed(false);
  401. // tabs->set_current_tab(PAGE_CLASS_DESC);
  402. } else if (p_idx==PAGE_CLASS_PREV) {
  403. if (history_pos<2)
  404. return;
  405. history_pos--;
  406. ERR_FAIL_INDEX(history_pos-1,history.size());
  407. _goto_desc(history[history_pos-1].c,false,history[history_pos-1].scroll);
  408. _update_history_buttons();
  409. } else if (p_idx==PAGE_CLASS_NEXT) {
  410. if (history_pos>=history.size())
  411. return;
  412. history_pos++;
  413. ERR_FAIL_INDEX(history_pos-1,history.size());
  414. _goto_desc(history[history_pos-1].c,false,history[history_pos-1].scroll);
  415. _update_history_buttons();
  416. } else if (p_idx==PAGE_SEARCH) {
  417. _search("");
  418. }
  419. }
  420. #endif
  421. void EditorHelp::_class_list_select(const String &p_select) {
  422. _goto_desc(p_select);
  423. }
  424. void EditorHelp::_class_desc_select(const String &p_select) {
  425. // print_line("LINK: "+p_select);
  426. if (p_select.begins_with("#")) {
  427. //_goto_desc(p_select.substr(1,p_select.length()));
  428. emit_signal("go_to_help", "class_name:" + p_select.substr(1, p_select.length()));
  429. return;
  430. } else if (p_select.begins_with("@")) {
  431. String m = p_select.substr(1, p_select.length());
  432. if (m.find(".") != -1) {
  433. //must go somewhere else
  434. emit_signal("go_to_help", "class_method:" + m.get_slice(".", 0) + ":" + m.get_slice(".", 0));
  435. } else {
  436. if (!method_line.has(m))
  437. return;
  438. class_desc->scroll_to_line(method_line[m]);
  439. }
  440. }
  441. }
  442. void EditorHelp::_class_desc_input(const InputEvent &p_input) {
  443. if (p_input.type == InputEvent::MOUSE_BUTTON && p_input.mouse_button.pressed && p_input.mouse_button.button_index == 1) {
  444. class_desc->set_selection_enabled(false);
  445. class_desc->set_selection_enabled(true);
  446. }
  447. set_focused();
  448. }
  449. void EditorHelp::_add_type(const String &p_type) {
  450. String t = p_type;
  451. if (t == "")
  452. t = "void";
  453. bool can_ref = (t != "int" && t != "real" && t != "bool" && t != "void");
  454. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/base_type_color"));
  455. if (can_ref)
  456. class_desc->push_meta("#" + t); //class
  457. class_desc->add_text(t);
  458. if (can_ref)
  459. class_desc->pop();
  460. class_desc->pop();
  461. }
  462. void EditorHelp::_scroll_changed(double p_scroll) {
  463. if (scroll_locked)
  464. return;
  465. if (class_desc->get_v_scroll()->is_hidden())
  466. p_scroll = 0;
  467. //history[p].scroll=p_scroll;
  468. }
  469. Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
  470. //ERR_FAIL_COND(!doc->class_list.has(p_class));
  471. if (!doc->class_list.has(p_class))
  472. return ERR_DOES_NOT_EXIST;
  473. //if (tree_item_map.has(p_class)) {
  474. select_locked = true;
  475. //}
  476. class_desc->show();
  477. //tabs->set_current_tab(PAGE_CLASS_DESC);
  478. description_line = 0;
  479. if (p_class == edited_class)
  480. return OK; //already there
  481. scroll_locked = true;
  482. class_desc->clear();
  483. method_line.clear();
  484. edited_class = p_class;
  485. //edited_class->show();
  486. DocData::ClassDoc cd = doc->class_list[p_class]; //make a copy, so we can sort without worrying
  487. Color h_color;
  488. Ref<Font> doc_font = get_font("doc", "EditorFonts");
  489. Ref<Font> doc_title_font = get_font("doc_title", "EditorFonts");
  490. Ref<Font> doc_code_font = get_font("doc_source", "EditorFonts");
  491. h_color = Color(1, 1, 1, 1);
  492. class_desc->push_font(doc_title_font);
  493. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  494. class_desc->add_text(TTR("Class:") + " ");
  495. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/base_type_color"));
  496. _add_text(p_class);
  497. class_desc->pop();
  498. class_desc->pop();
  499. class_desc->pop();
  500. class_desc->add_newline();
  501. if (cd.inherits != "") {
  502. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  503. class_desc->push_font(doc_title_font);
  504. class_desc->add_text(TTR("Inherits:") + " ");
  505. class_desc->pop();
  506. class_desc->pop();
  507. String inherits = cd.inherits;
  508. class_desc->push_font(doc_font);
  509. while (inherits != "") {
  510. _add_type(inherits);
  511. inherits = doc->class_list[inherits].inherits;
  512. if (inherits != "") {
  513. class_desc->add_text(" , ");
  514. }
  515. }
  516. class_desc->pop();
  517. class_desc->add_newline();
  518. }
  519. if (ObjectTypeDB::type_exists(cd.name)) {
  520. bool found = false;
  521. bool prev = false;
  522. for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) {
  523. if (E->get().inherits == cd.name) {
  524. if (!found) {
  525. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  526. class_desc->push_font(doc_title_font);
  527. class_desc->add_text(TTR("Inherited by:") + " ");
  528. class_desc->pop();
  529. class_desc->pop();
  530. found = true;
  531. class_desc->push_font(doc_font);
  532. }
  533. if (prev) {
  534. class_desc->add_text(" , ");
  535. prev = false;
  536. }
  537. _add_type(E->get().name);
  538. prev = true;
  539. }
  540. }
  541. if (found)
  542. class_desc->pop();
  543. class_desc->add_newline();
  544. }
  545. class_desc->add_newline();
  546. if (cd.brief_description != "") {
  547. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  548. class_desc->push_font(doc_title_font);
  549. class_desc->add_text(TTR("Brief Description:"));
  550. class_desc->pop();
  551. class_desc->pop();
  552. //class_desc->add_newline();
  553. class_desc->add_newline();
  554. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  555. class_desc->push_font(doc_font);
  556. class_desc->push_indent(1);
  557. _add_text(cd.brief_description);
  558. class_desc->pop();
  559. class_desc->pop();
  560. class_desc->pop();
  561. class_desc->add_newline();
  562. class_desc->add_newline();
  563. }
  564. bool method_descr = false;
  565. bool sort_methods = EditorSettings::get_singleton()->get("help/sort_functions_alphabetically");
  566. if (cd.methods.size()) {
  567. if (sort_methods)
  568. cd.methods.sort();
  569. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  570. class_desc->push_font(doc_title_font);
  571. class_desc->add_text(TTR("Public Methods:"));
  572. class_desc->pop();
  573. class_desc->pop();
  574. //class_desc->add_newline();
  575. // class_desc->add_newline();
  576. class_desc->push_indent(1);
  577. class_desc->push_table(2);
  578. class_desc->set_table_column_expand(1, 1);
  579. for (int i = 0; i < cd.methods.size(); i++) {
  580. class_desc->push_cell();
  581. method_line[cd.methods[i].name] = class_desc->get_line_count() - 2; //gets overriden if description
  582. class_desc->push_align(RichTextLabel::ALIGN_RIGHT);
  583. class_desc->push_font(doc_code_font);
  584. _add_type(cd.methods[i].return_type);
  585. //class_desc->add_text(" ");
  586. class_desc->pop(); //align
  587. class_desc->pop(); //font
  588. class_desc->pop(); //cell
  589. class_desc->push_cell();
  590. class_desc->push_font(doc_code_font);
  591. if (cd.methods[i].description != "") {
  592. method_descr = true;
  593. class_desc->push_meta("@" + cd.methods[i].name);
  594. }
  595. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  596. _add_text(cd.methods[i].name);
  597. class_desc->pop();
  598. if (cd.methods[i].description != "")
  599. class_desc->pop();
  600. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  601. class_desc->add_text(cd.methods[i].arguments.size() ? "( " : "(");
  602. class_desc->pop();
  603. for (int j = 0; j < cd.methods[i].arguments.size(); j++) {
  604. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  605. if (j > 0)
  606. class_desc->add_text(", ");
  607. _add_type(cd.methods[i].arguments[j].type);
  608. class_desc->add_text(" ");
  609. _add_text(cd.methods[i].arguments[j].name);
  610. if (cd.methods[i].arguments[j].default_value != "") {
  611. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  612. class_desc->add_text("=");
  613. class_desc->pop();
  614. _add_text(cd.methods[i].arguments[j].default_value);
  615. }
  616. class_desc->pop();
  617. }
  618. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  619. class_desc->add_text(cd.methods[i].arguments.size() ? " )" : ")");
  620. class_desc->pop();
  621. if (cd.methods[i].qualifiers != "") {
  622. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  623. class_desc->add_text(" ");
  624. _add_text(cd.methods[i].qualifiers);
  625. class_desc->pop();
  626. }
  627. class_desc->pop(); //monofont
  628. // class_desc->add_newline();
  629. class_desc->pop(); //cell
  630. }
  631. class_desc->pop(); //table
  632. class_desc->pop();
  633. class_desc->add_newline();
  634. class_desc->add_newline();
  635. }
  636. if (cd.properties.size()) {
  637. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  638. class_desc->push_font(doc_title_font);
  639. class_desc->add_text(TTR("Members:"));
  640. class_desc->pop();
  641. class_desc->pop();
  642. class_desc->add_newline();
  643. class_desc->push_indent(1);
  644. //class_desc->add_newline();
  645. for (int i = 0; i < cd.properties.size(); i++) {
  646. property_line[cd.properties[i].name] = class_desc->get_line_count() - 2; //gets overriden if description
  647. class_desc->push_font(doc_code_font);
  648. _add_type(cd.properties[i].type);
  649. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  650. class_desc->add_text(" ");
  651. _add_text(cd.properties[i].name);
  652. class_desc->pop();
  653. class_desc->pop();
  654. if (cd.properties[i].description != "") {
  655. class_desc->push_font(doc_font);
  656. class_desc->add_text(" ");
  657. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/comment_color"));
  658. _add_text(cd.properties[i].description);
  659. class_desc->pop();
  660. class_desc->pop();
  661. }
  662. class_desc->add_newline();
  663. }
  664. class_desc->pop();
  665. class_desc->add_newline();
  666. }
  667. if (cd.theme_properties.size()) {
  668. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  669. class_desc->push_font(doc_title_font);
  670. class_desc->add_text(TTR("GUI Theme Items:"));
  671. class_desc->pop();
  672. class_desc->pop();
  673. class_desc->add_newline();
  674. class_desc->push_indent(1);
  675. //class_desc->add_newline();
  676. for (int i = 0; i < cd.theme_properties.size(); i++) {
  677. theme_property_line[cd.theme_properties[i].name] = class_desc->get_line_count() - 2; //gets overriden if description
  678. class_desc->push_font(doc_code_font);
  679. _add_type(cd.theme_properties[i].type);
  680. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  681. class_desc->add_text(" ");
  682. _add_text(cd.theme_properties[i].name);
  683. class_desc->pop();
  684. class_desc->pop();
  685. if (cd.theme_properties[i].description != "") {
  686. class_desc->push_font(doc_font);
  687. class_desc->add_text(" ");
  688. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/comment_color"));
  689. _add_text(cd.theme_properties[i].description);
  690. class_desc->pop();
  691. class_desc->pop();
  692. }
  693. class_desc->add_newline();
  694. }
  695. class_desc->pop();
  696. class_desc->add_newline();
  697. }
  698. if (cd.signals.size()) {
  699. if (sort_methods) {
  700. cd.signals.sort();
  701. }
  702. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  703. class_desc->push_font(doc_title_font);
  704. class_desc->add_text(TTR("Signals:"));
  705. class_desc->pop();
  706. class_desc->pop();
  707. class_desc->add_newline();
  708. //class_desc->add_newline();
  709. class_desc->push_indent(1);
  710. for (int i = 0; i < cd.signals.size(); i++) {
  711. signal_line[cd.signals[i].name] = class_desc->get_line_count() - 2; //gets overriden if description
  712. class_desc->push_font(doc_code_font); // monofont
  713. //_add_type("void");
  714. //class_desc->add_text(" ");
  715. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  716. _add_text(cd.signals[i].name);
  717. class_desc->pop();
  718. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  719. class_desc->add_text(cd.signals[i].arguments.size() ? "( " : "(");
  720. class_desc->pop();
  721. for (int j = 0; j < cd.signals[i].arguments.size(); j++) {
  722. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  723. if (j > 0)
  724. class_desc->add_text(", ");
  725. _add_type(cd.signals[i].arguments[j].type);
  726. class_desc->add_text(" ");
  727. _add_text(cd.signals[i].arguments[j].name);
  728. if (cd.signals[i].arguments[j].default_value != "") {
  729. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  730. class_desc->add_text("=");
  731. class_desc->pop();
  732. _add_text(cd.signals[i].arguments[j].default_value);
  733. }
  734. class_desc->pop();
  735. }
  736. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  737. class_desc->add_text(cd.signals[i].arguments.size() ? " )" : ")");
  738. class_desc->pop();
  739. class_desc->pop(); // end monofont
  740. if (cd.signals[i].description != "") {
  741. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/comment_color"));
  742. class_desc->add_text(" ");
  743. _add_text(cd.signals[i].description);
  744. class_desc->pop();
  745. }
  746. class_desc->add_newline();
  747. }
  748. class_desc->pop();
  749. class_desc->add_newline();
  750. }
  751. if (cd.constants.size()) {
  752. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  753. class_desc->push_font(doc_title_font);
  754. class_desc->add_text(TTR("Constants:"));
  755. class_desc->pop();
  756. class_desc->pop();
  757. class_desc->push_indent(1);
  758. class_desc->add_newline();
  759. //class_desc->add_newline();
  760. for (int i = 0; i < cd.constants.size(); i++) {
  761. constant_line[cd.constants[i].name] = class_desc->get_line_count() - 2;
  762. class_desc->push_font(doc_code_font);
  763. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/base_type_color"));
  764. _add_text(cd.constants[i].name);
  765. class_desc->pop();
  766. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  767. class_desc->add_text(" = ");
  768. class_desc->pop();
  769. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  770. _add_text(cd.constants[i].value);
  771. class_desc->pop();
  772. class_desc->pop();
  773. if (cd.constants[i].description != "") {
  774. class_desc->push_font(doc_font);
  775. class_desc->add_text(" ");
  776. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/comment_color"));
  777. _add_text(cd.constants[i].description);
  778. class_desc->pop();
  779. class_desc->pop();
  780. }
  781. class_desc->add_newline();
  782. }
  783. class_desc->pop();
  784. class_desc->add_newline();
  785. }
  786. if (cd.description != "") {
  787. description_line = class_desc->get_line_count() - 2;
  788. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  789. class_desc->push_font(doc_title_font);
  790. class_desc->add_text(TTR("Description:"));
  791. class_desc->pop();
  792. class_desc->pop();
  793. class_desc->add_newline();
  794. class_desc->add_newline();
  795. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  796. class_desc->push_font(doc_font);
  797. class_desc->push_indent(1);
  798. _add_text(cd.description);
  799. class_desc->pop();
  800. class_desc->pop();
  801. class_desc->pop();
  802. class_desc->add_newline();
  803. class_desc->add_newline();
  804. }
  805. if (method_descr) {
  806. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  807. class_desc->push_font(doc_title_font);
  808. class_desc->add_text(TTR("Method Description:"));
  809. class_desc->pop();
  810. class_desc->pop();
  811. class_desc->add_newline();
  812. class_desc->add_newline();
  813. for (int i = 0; i < cd.methods.size(); i++) {
  814. method_line[cd.methods[i].name] = class_desc->get_line_count() - 2;
  815. class_desc->push_font(doc_code_font);
  816. _add_type(cd.methods[i].return_type);
  817. class_desc->add_text(" ");
  818. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  819. _add_text(cd.methods[i].name);
  820. class_desc->pop();
  821. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  822. class_desc->add_text(cd.methods[i].arguments.size() ? "( " : "(");
  823. class_desc->pop();
  824. for (int j = 0; j < cd.methods[i].arguments.size(); j++) {
  825. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  826. if (j > 0)
  827. class_desc->add_text(", ");
  828. _add_type(cd.methods[i].arguments[j].type);
  829. class_desc->add_text(" ");
  830. _add_text(cd.methods[i].arguments[j].name);
  831. if (cd.methods[i].arguments[j].default_value != "") {
  832. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  833. class_desc->add_text("=");
  834. class_desc->pop();
  835. _add_text(cd.methods[i].arguments[j].default_value);
  836. }
  837. class_desc->pop();
  838. }
  839. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color"));
  840. class_desc->add_text(cd.methods[i].arguments.size() ? " )" : ")");
  841. class_desc->pop();
  842. if (cd.methods[i].qualifiers != "") {
  843. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  844. class_desc->add_text(" ");
  845. _add_text(cd.methods[i].qualifiers);
  846. class_desc->pop();
  847. }
  848. class_desc->pop();
  849. class_desc->add_newline();
  850. class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  851. class_desc->push_font(doc_font);
  852. class_desc->push_indent(1);
  853. _add_text(cd.methods[i].description);
  854. class_desc->pop();
  855. class_desc->pop();
  856. class_desc->pop();
  857. class_desc->add_newline();
  858. class_desc->add_newline();
  859. class_desc->add_newline();
  860. }
  861. }
  862. scroll_locked = false;
  863. return OK;
  864. }
  865. void EditorHelp::_request_help(const String &p_string) {
  866. Error err = _goto_desc(p_string);
  867. if (err == OK) {
  868. editor->call("_editor_select", EditorNode::EDITOR_SCRIPT);
  869. }
  870. //100 palabras
  871. }
  872. void EditorHelp::_help_callback(const String &p_topic) {
  873. String what = p_topic.get_slice(":", 0);
  874. String clss = p_topic.get_slice(":", 1);
  875. String name;
  876. if (p_topic.get_slice_count(":") == 3)
  877. name = p_topic.get_slice(":", 2);
  878. _request_help(clss); //first go to class
  879. int line = 0;
  880. if (what == "class_desc") {
  881. line = description_line;
  882. } else if (what == "class_signal") {
  883. if (signal_line.has(name))
  884. line = signal_line[name];
  885. } else if (what == "class_method" || what == "class_method_desc") {
  886. if (method_line.has(name))
  887. line = method_line[name];
  888. } else if (what == "class_property") {
  889. if (property_line.has(name))
  890. line = property_line[name];
  891. } else if (what == "class_theme_item") {
  892. if (theme_property_line.has(name))
  893. line = theme_property_line[name];
  894. } else if (what == "class_constant") {
  895. if (constant_line.has(name))
  896. line = constant_line[name];
  897. }
  898. class_desc->call_deferred("scroll_to_line", line);
  899. }
  900. static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
  901. DocData *doc = EditorHelp::get_doc_data();
  902. String base_path;
  903. /*p_rt->push_color(EditorSettings::get_singleton()->get("text_editor/text_color"));
  904. p_rt->push_font( get_font("normal","Fonts") );
  905. p_rt->push_indent(1);*/
  906. int pos = 0;
  907. Ref<Font> doc_font = p_rt->get_font("doc", "EditorFonts");
  908. Ref<Font> doc_code_font = p_rt->get_font("doc_source", "EditorFonts");
  909. String bbcode = p_bbcode.replace("\t", " ").replace("\r", " ").strip_edges();
  910. //change newlines for double newlines
  911. for (int i = 0; i < bbcode.length(); i++) {
  912. //find valid newlines (double)
  913. if (bbcode[i] == '\n') {
  914. bool dnl = false;
  915. int j = i + 1;
  916. for (; j < p_bbcode.length(); j++) {
  917. if (bbcode[j] == ' ')
  918. continue;
  919. if (bbcode[j] == '\n') {
  920. dnl = true;
  921. break;
  922. }
  923. break;
  924. }
  925. if (dnl) {
  926. bbcode[i] = 0xFFFF;
  927. //keep
  928. i = j;
  929. } else {
  930. bbcode = bbcode.insert(i, "\n");
  931. i++;
  932. //bbcode[i]=' ';
  933. //i=j-1;
  934. }
  935. }
  936. }
  937. //remove double spaces or spaces after newlines
  938. for (int i = 0; i < bbcode.length(); i++) {
  939. if (bbcode[i] == ' ' || bbcode[i] == '\n' || bbcode[i] == 0xFFFF) {
  940. for (int j = i + 1; j < p_bbcode.length(); j++) {
  941. if (bbcode[j] == ' ') {
  942. bbcode.remove(j);
  943. j--;
  944. continue;
  945. } else {
  946. break;
  947. }
  948. }
  949. }
  950. }
  951. //change newlines to double newlines
  952. CharType dnls[2] = { 0xFFFF, 0 };
  953. bbcode = bbcode.replace(dnls, "\n");
  954. List<String> tag_stack;
  955. while (pos < bbcode.length()) {
  956. int brk_pos = bbcode.find("[", pos);
  957. if (brk_pos < 0)
  958. brk_pos = bbcode.length();
  959. if (brk_pos > pos) {
  960. p_rt->add_text(bbcode.substr(pos, brk_pos - pos));
  961. }
  962. if (brk_pos == bbcode.length())
  963. break; //nothing else o add
  964. int brk_end = bbcode.find("]", brk_pos + 1);
  965. if (brk_end == -1) {
  966. //no close, add the rest
  967. p_rt->add_text(bbcode.substr(brk_pos, bbcode.length() - brk_pos));
  968. break;
  969. }
  970. String tag = bbcode.substr(brk_pos + 1, brk_end - brk_pos - 1);
  971. if (tag.begins_with("/")) {
  972. bool tag_ok = tag_stack.size() && tag_stack.front()->get() == tag.substr(1, tag.length());
  973. if (tag_stack.size()) {
  974. }
  975. if (!tag_ok) {
  976. p_rt->add_text("[");
  977. pos++;
  978. continue;
  979. }
  980. tag_stack.pop_front();
  981. pos = brk_end + 1;
  982. if (tag != "/img")
  983. p_rt->pop();
  984. } else if (tag.begins_with("method ")) {
  985. String m = tag.substr(7, tag.length());
  986. p_rt->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  987. p_rt->push_meta("@" + m);
  988. p_rt->add_text(m + "()");
  989. p_rt->pop();
  990. p_rt->pop();
  991. pos = brk_end + 1;
  992. } else if (doc->class_list.has(tag)) {
  993. p_rt->push_color(EditorSettings::get_singleton()->get("text_editor/keyword_color"));
  994. p_rt->push_meta("#" + tag);
  995. p_rt->add_text(tag);
  996. p_rt->pop();
  997. p_rt->pop();
  998. pos = brk_end + 1;
  999. } else if (tag == "b") {
  1000. //use bold font
  1001. p_rt->push_font(doc_code_font);
  1002. pos = brk_end + 1;
  1003. tag_stack.push_front(tag);
  1004. } else if (tag == "i") {
  1005. //use italics font
  1006. Color text_color = EditorSettings::get_singleton()->get("text_editor/text_color");
  1007. //no italics so emphasize with color
  1008. text_color.r *= 1.1;
  1009. text_color.g *= 1.1;
  1010. text_color.b *= 1.1;
  1011. p_rt->push_color(text_color);
  1012. //p_rt->push_font(get_font("italic","Fonts"));
  1013. pos = brk_end + 1;
  1014. tag_stack.push_front(tag);
  1015. } else if (tag == "code" || tag == "codeblock") {
  1016. //use monospace font
  1017. p_rt->push_font(doc_code_font);
  1018. pos = brk_end + 1;
  1019. tag_stack.push_front(tag);
  1020. } else if (tag == "center") {
  1021. //use monospace font
  1022. p_rt->push_align(RichTextLabel::ALIGN_CENTER);
  1023. pos = brk_end + 1;
  1024. tag_stack.push_front(tag);
  1025. } else if (tag == "br") {
  1026. //use monospace font
  1027. p_rt->add_newline();
  1028. pos = brk_end + 1;
  1029. } else if (tag == "u") {
  1030. //use underline
  1031. p_rt->push_underline();
  1032. pos = brk_end + 1;
  1033. tag_stack.push_front(tag);
  1034. } else if (tag == "s") {
  1035. //use strikethrough (not supported underline instead)
  1036. p_rt->push_underline();
  1037. pos = brk_end + 1;
  1038. tag_stack.push_front(tag);
  1039. } else if (tag == "url") {
  1040. //use strikethrough (not supported underline instead)
  1041. int end = bbcode.find("[", brk_end);
  1042. if (end == -1)
  1043. end = bbcode.length();
  1044. String url = bbcode.substr(brk_end + 1, end - brk_end - 1);
  1045. p_rt->push_meta(url);
  1046. pos = brk_end + 1;
  1047. tag_stack.push_front(tag);
  1048. } else if (tag.begins_with("url=")) {
  1049. String url = tag.substr(4, tag.length());
  1050. p_rt->push_meta(url);
  1051. pos = brk_end + 1;
  1052. tag_stack.push_front("url");
  1053. } else if (tag == "img") {
  1054. //use strikethrough (not supported underline instead)
  1055. int end = bbcode.find("[", brk_end);
  1056. if (end == -1)
  1057. end = bbcode.length();
  1058. String image = bbcode.substr(brk_end + 1, end - brk_end - 1);
  1059. Ref<Texture> texture = ResourceLoader::load(base_path + "/" + image, "Texture");
  1060. if (texture.is_valid())
  1061. p_rt->add_image(texture);
  1062. pos = end;
  1063. tag_stack.push_front(tag);
  1064. } else if (tag.begins_with("color=")) {
  1065. String col = tag.substr(6, tag.length());
  1066. Color color;
  1067. if (col.begins_with("#"))
  1068. color = Color::html(col);
  1069. else if (col == "aqua")
  1070. color = Color::html("#00FFFF");
  1071. else if (col == "black")
  1072. color = Color::html("#000000");
  1073. else if (col == "blue")
  1074. color = Color::html("#0000FF");
  1075. else if (col == "fuchsia")
  1076. color = Color::html("#FF00FF");
  1077. else if (col == "gray" || col == "grey")
  1078. color = Color::html("#808080");
  1079. else if (col == "green")
  1080. color = Color::html("#008000");
  1081. else if (col == "lime")
  1082. color = Color::html("#00FF00");
  1083. else if (col == "maroon")
  1084. color = Color::html("#800000");
  1085. else if (col == "navy")
  1086. color = Color::html("#000080");
  1087. else if (col == "olive")
  1088. color = Color::html("#808000");
  1089. else if (col == "purple")
  1090. color = Color::html("#800080");
  1091. else if (col == "red")
  1092. color = Color::html("#FF0000");
  1093. else if (col == "silver")
  1094. color = Color::html("#C0C0C0");
  1095. else if (col == "teal")
  1096. color = Color::html("#008008");
  1097. else if (col == "white")
  1098. color = Color::html("#FFFFFF");
  1099. else if (col == "yellow")
  1100. color = Color::html("#FFFF00");
  1101. else
  1102. color = Color(0, 0, 0, 1); //base_color;
  1103. p_rt->push_color(color);
  1104. pos = brk_end + 1;
  1105. tag_stack.push_front("color");
  1106. } else if (tag.begins_with("font=")) {
  1107. String fnt = tag.substr(5, tag.length());
  1108. Ref<Font> font = ResourceLoader::load(base_path + "/" + fnt, "Font");
  1109. if (font.is_valid())
  1110. p_rt->push_font(font);
  1111. else {
  1112. p_rt->push_font(doc_font);
  1113. }
  1114. pos = brk_end + 1;
  1115. tag_stack.push_front("font");
  1116. } else {
  1117. p_rt->add_text("["); //ignore
  1118. pos = brk_pos + 1;
  1119. }
  1120. }
  1121. /*p_rt->pop();
  1122. p_rt->pop();
  1123. p_rt->pop();*/
  1124. }
  1125. void EditorHelp::_add_text(const String &p_bbcode) {
  1126. _add_text_to_rt(p_bbcode, class_desc);
  1127. }
  1128. void EditorHelp::_update_doc() {
  1129. }
  1130. void EditorHelp::generate_doc() {
  1131. doc = memnew(DocData);
  1132. doc->generate(true);
  1133. DocData compdoc;
  1134. compdoc.load_compressed(_doc_data_compressed, _doc_data_compressed_size, _doc_data_uncompressed_size);
  1135. doc->merge_from(compdoc); //ensure all is up to date
  1136. }
  1137. void EditorHelp::_notification(int p_what) {
  1138. switch (p_what) {
  1139. case NOTIFICATION_READY: {
  1140. // forward->set_icon(get_icon("Forward","EditorIcons"));
  1141. // back->set_icon(get_icon("Back","EditorIcons"));
  1142. _update_doc();
  1143. } break;
  1144. }
  1145. }
  1146. void EditorHelp::go_to_help(const String &p_help) {
  1147. _help_callback(p_help);
  1148. }
  1149. void EditorHelp::go_to_class(const String &p_class, int p_scroll) {
  1150. _goto_desc(p_class, p_scroll);
  1151. }
  1152. void EditorHelp::popup_search() {
  1153. search_dialog->popup_centered(Size2(250, 80));
  1154. search->grab_focus();
  1155. }
  1156. void EditorHelp::_search_cbk() {
  1157. _search(search->get_text());
  1158. }
  1159. String EditorHelp::get_class_name() {
  1160. return edited_class;
  1161. }
  1162. void EditorHelp::search_again() {
  1163. _search(prev_search);
  1164. }
  1165. int EditorHelp::get_scroll() const {
  1166. return class_desc->get_v_scroll()->get_val();
  1167. }
  1168. void EditorHelp::set_scroll(int p_scroll) {
  1169. class_desc->get_v_scroll()->set_val(p_scroll);
  1170. }
  1171. void EditorHelp::_bind_methods() {
  1172. ObjectTypeDB::bind_method("_class_list_select", &EditorHelp::_class_list_select);
  1173. ObjectTypeDB::bind_method("_class_desc_select", &EditorHelp::_class_desc_select);
  1174. ObjectTypeDB::bind_method("_class_desc_input", &EditorHelp::_class_desc_input);
  1175. // ObjectTypeDB::bind_method("_button_pressed",&EditorHelp::_button_pressed);
  1176. ObjectTypeDB::bind_method("_scroll_changed", &EditorHelp::_scroll_changed);
  1177. ObjectTypeDB::bind_method("_request_help", &EditorHelp::_request_help);
  1178. ObjectTypeDB::bind_method("_unhandled_key_input", &EditorHelp::_unhandled_key_input);
  1179. ObjectTypeDB::bind_method("_search", &EditorHelp::_search);
  1180. ObjectTypeDB::bind_method("_search_cbk", &EditorHelp::_search_cbk);
  1181. ObjectTypeDB::bind_method("_help_callback", &EditorHelp::_help_callback);
  1182. ADD_SIGNAL(MethodInfo("go_to_help"));
  1183. }
  1184. EditorHelp::EditorHelp() {
  1185. editor = EditorNode::get_singleton();
  1186. VBoxContainer *vbc = this;
  1187. EDITOR_DEF("help/sort_functions_alphabetically", true);
  1188. //class_list->connect("meta_clicked",this,"_class_list_select");
  1189. //class_list->set_selection_enabled(true);
  1190. {
  1191. Panel *pc = memnew(Panel);
  1192. Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
  1193. style->set_bg_color(EditorSettings::get_singleton()->get("text_editor/background_color"));
  1194. pc->set_v_size_flags(SIZE_EXPAND_FILL);
  1195. pc->add_style_override("panel", style); //get_stylebox("normal","TextEdit"));
  1196. vbc->add_child(pc);
  1197. class_desc = memnew(RichTextLabel);
  1198. pc->add_child(class_desc);
  1199. class_desc->set_area_as_parent_rect(8);
  1200. class_desc->connect("meta_clicked", this, "_class_desc_select");
  1201. class_desc->connect("input_event", this, "_class_desc_input");
  1202. }
  1203. class_desc->get_v_scroll()->connect("value_changed", this, "_scroll_changed");
  1204. class_desc->set_selection_enabled(true);
  1205. scroll_locked = false;
  1206. select_locked = false;
  1207. set_process_unhandled_key_input(true);
  1208. class_desc->hide();
  1209. search_dialog = memnew(ConfirmationDialog);
  1210. add_child(search_dialog);
  1211. VBoxContainer *search_vb = memnew(VBoxContainer);
  1212. search_dialog->add_child(search_vb);
  1213. search_dialog->set_child_rect(search_vb);
  1214. search = memnew(LineEdit);
  1215. search_dialog->register_text_enter(search);
  1216. search_vb->add_margin_child(TTR("Search Text"), search);
  1217. search_dialog->get_ok()->set_text(TTR("Find"));
  1218. search_dialog->connect("confirmed", this, "_search_cbk");
  1219. search_dialog->set_hide_on_ok(false);
  1220. search_dialog->set_self_opacity(0.8);
  1221. /*class_search = memnew( EditorHelpSearch(editor) );
  1222. editor->get_gui_base()->add_child(class_search);
  1223. class_search->connect("go_to_help",this,"_help_callback");*/
  1224. // prev_search_page=-1;
  1225. }
  1226. EditorHelp::~EditorHelp() {
  1227. }
  1228. /////////////
  1229. void EditorHelpBit::_go_to_help(String p_what) {
  1230. EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
  1231. ScriptEditor::get_singleton()->goto_help(p_what);
  1232. emit_signal("request_hide");
  1233. }
  1234. void EditorHelpBit::_meta_clicked(String p_select) {
  1235. // print_line("LINK: "+p_select);
  1236. if (p_select.begins_with("#")) {
  1237. //_goto_desc(p_select.substr(1,p_select.length()));
  1238. _go_to_help("class_name:" + p_select.substr(1, p_select.length()));
  1239. return;
  1240. } else if (p_select.begins_with("@")) {
  1241. String m = p_select.substr(1, p_select.length());
  1242. if (m.find(".") != -1) {
  1243. //must go somewhere else
  1244. _go_to_help("class_method:" + m.get_slice(".", 0) + ":" + m.get_slice(".", 0));
  1245. } else {
  1246. //
  1247. // if (!method_line.has(m))
  1248. // return;
  1249. //class_desc->scroll_to_line(method_line[m]);
  1250. }
  1251. }
  1252. }
  1253. void EditorHelpBit::_bind_methods() {
  1254. ObjectTypeDB::bind_method("_meta_clicked", &EditorHelpBit::_meta_clicked);
  1255. ADD_SIGNAL(MethodInfo("request_hide"));
  1256. }
  1257. void EditorHelpBit::_notification(int p_what) {
  1258. if (p_what == NOTIFICATION_ENTER_TREE) {
  1259. add_style_override("panel", get_stylebox("normal", "TextEdit"));
  1260. }
  1261. }
  1262. void EditorHelpBit::set_text(const String &p_text) {
  1263. rich_text->clear();
  1264. _add_text_to_rt(p_text, rich_text);
  1265. }
  1266. EditorHelpBit::EditorHelpBit() {
  1267. rich_text = memnew(RichTextLabel);
  1268. add_child(rich_text);
  1269. rich_text->set_area_as_parent_rect(8 * EDSCALE);
  1270. rich_text->connect("meta_clicked", this, "_meta_clicked");
  1271. set_custom_minimum_size(Size2(0, 70 * EDSCALE));
  1272. }