CE Editor GUI.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace Edit{
  5. /******************************************************************************/
  6. ColorTheme ThemeLight=
  7. {
  8. Color(255, 255, 255), // NONE
  9. TRANSPARENT, // REMOVE
  10. Color( 0, 0, 0), // OPERATOR
  11. Color( 0, 0, 255), // KEYWORD
  12. Color( 0, 0, 0), // CODE
  13. Color( 0, 128, 0), // COMMENT
  14. Color(163, 21, 21), // TEXT8
  15. Color(163, 21, 21), // TEXT16
  16. Color(163, 21, 21), // CHAR8
  17. Color(163, 21, 21), // CHAR16
  18. Color( 0, 0, 0), // NUMBER
  19. Color( 0, 0, 255), // PREPROC
  20. Color( 0, 0, 255), // MACRO
  21. Color( 0, 0, 255), // ENUM_TYPE
  22. Color( 0, 0, 0), // ENUM_ELM
  23. Color( 0, 0, 0), // FUNC
  24. Color( 51, 153, 255), // SELECT
  25. Color( 0, 0, 0, 96), // LINE_HIGHLIGHT
  26. Color( 64, 128, 255, 60), // SYMBOL_HIGHLIGHT
  27. Color( 64, 128, 255, 40), // BRACE_HIGHLIGHT
  28. Color(128, 128, 128), // PREPROC_DISABLED
  29. Color( 86, 86, 244, 239), // TOKEN_ELM_BACKGROUND
  30. Color(255, 255, 255), // TOKEN_ELM_NAME
  31. Color(220, 220, 220), // TOKEN_LINE_NUM_BACKGROUND
  32. Color(143, 143, 143), // TOKEN_LINE_NUM
  33. }, ThemeBlue=
  34. {
  35. Color( 0, 0, 96), // NONE
  36. TRANSPARENT, // REMOVE
  37. Color(255, 255, 255), // OPERATOR
  38. Color(255, 255, 255), // KEYWORD
  39. Color(255, 255, 0), // CODE
  40. Color(192, 192, 192), // COMMENT
  41. Color( 0, 255, 255), // TEXT8
  42. Color( 0, 255, 255), // TEXT16
  43. Color( 0, 255, 255), // CHAR8
  44. Color( 0, 255, 255), // CHAR16
  45. Color( 0, 255, 255), // NUMBER
  46. Color( 0, 255, 0), // PREPROC
  47. Color(255, 255, 255), // MACRO
  48. Color(255, 255, 255), // ENUM_TYPE
  49. Color(255, 255, 0), // ENUM_ELM
  50. Color(255, 255, 0), // FUNC
  51. Color( 51, 153, 255), // SELECT
  52. Color(255, 255, 0, 128), // LINE_HIGHLIGHT
  53. Color(255, 255, 255, 85), // SYMBOL_HIGHLIGHT
  54. Color(255, 255, 255, 40), // BRACE_HIGHLIGHT
  55. Color(128, 128, 128), // PREPROC_DISABLED
  56. Color( 36, 106, 172, 245), // TOKEN_ELM_BACKGROUND
  57. Color(255, 255, 255), // TOKEN_ELM_NAME
  58. Color( 0, 0, 75), // TOKEN_LINE_NUM_BACKGROUND
  59. Color(128, 128, 128), // TOKEN_LINE_NUM
  60. }, ThemeDark=
  61. {
  62. Color( 30, 30, 30), // NONE
  63. TRANSPARENT, // REMOVE
  64. Color(220, 220, 220), // OPERATOR
  65. Color( 86, 156, 214), // KEYWORD
  66. Color(200, 200, 200), // CODE
  67. Color( 87, 166, 74), // COMMENT
  68. Color(211, 155, 105), // TEXT8
  69. Color(211, 155, 105), // TEXT16
  70. Color(211, 155, 105), // CHAR8
  71. Color(211, 155, 105), // CHAR16
  72. Color(181, 206, 168), // NUMBER
  73. Color(155, 155, 155), // PREPROC
  74. Color( 86, 156, 214), // MACRO
  75. Color( 86, 156, 214), // ENUM_TYPE
  76. Color(161, 193, 225)/*Color(184, 215, 163)/*Color(200, 200, 200)*/, // ENUM_ELM
  77. Color(200, 200, 200), // FUNC
  78. Color( 38, 79, 120), // SELECT
  79. Color(255, 255, 255, 80), // LINE_HIGHLIGHT
  80. Color(255, 255, 255, 45), // SYMBOL_HIGHLIGHT
  81. Color(255, 255, 255, 30), // BRACE_HIGHLIGHT
  82. Color( 90, 90, 90), // PREPROC_DISABLED
  83. Color( 36, 106, 172, 245), // TOKEN_ELM_BACKGROUND
  84. Color(255, 255, 255), // TOKEN_ELM_NAME
  85. Color( 42, 42, 42), // TOKEN_LINE_NUM_BACKGROUND
  86. Color(128, 128, 128), // TOKEN_LINE_NUM
  87. }, ThemeCustom=ThemeDark,
  88. Theme =ThemeDark;
  89. /******************************************************************************/
  90. void ColorTheme::save(TextNode &node)C
  91. {
  92. node.getNode("Background" ).value=S+colors[TOKEN_NONE ].v4;
  93. node.getNode("Operator" ).value=S+colors[TOKEN_OPERATOR ].v4;
  94. node.getNode("Keyword" ).value=S+colors[TOKEN_KEYWORD ].v4;
  95. node.getNode("Code" ).value=S+colors[TOKEN_CODE ].v4;
  96. node.getNode("Comment" ).value=S+colors[TOKEN_COMMENT ].v4;
  97. node.getNode("Text" ).value=S+colors[TOKEN_TEXT8 ].v4;
  98. node.getNode("Character" ).value=S+colors[TOKEN_CHAR8 ].v4;
  99. node.getNode("Number" ).value=S+colors[TOKEN_NUMBER ].v4;
  100. node.getNode("Preprocessor" ).value=S+colors[TOKEN_PREPROC ].v4;
  101. node.getNode("PreprocessorDisabled").value=S+colors[TOKEN_PREPROC_DISABLED ].v4;
  102. node.getNode("Macro" ).value=S+colors[TOKEN_MACRO ].v4;
  103. node.getNode("EnumType" ).value=S+colors[TOKEN_ENUM_TYPE ].v4;
  104. node.getNode("EnumElement" ).value=S+colors[TOKEN_ENUM_ELM ].v4;
  105. node.getNode("Function" ).value=S+colors[TOKEN_FUNC ].v4;
  106. node.getNode("Selection" ).value=S+colors[TOKEN_SELECT ].v4;
  107. node.getNode("LineHighlight" ).value=S+colors[TOKEN_LINE_HIGHLIGHT ].v4;
  108. node.getNode("SymbolHighlight" ).value=S+colors[TOKEN_SYMBOL_HIGHLIGHT ].v4;
  109. node.getNode("BraceHighlight" ).value=S+colors[TOKEN_BRACE_HIGHLIGHT ].v4;
  110. node.getNode("ElementBackground" ).value=S+colors[TOKEN_ELM_BACKGROUND ].v4;
  111. node.getNode("ElementName" ).value=S+colors[TOKEN_ELM_NAME ].v4;
  112. node.getNode("LineNumberBackground").value=S+colors[TOKEN_LINE_NUM_BACKGROUND].v4;
  113. node.getNode("LineNumber" ).value=S+colors[TOKEN_LINE_NUM ].v4;
  114. }
  115. void ColorTheme::load(C TextNode &node)
  116. {
  117. if(C TextNode *p=node.findNode("Background" ))colors[TOKEN_NONE ]=p->asColor();
  118. if(C TextNode *p=node.findNode("Operator" ))colors[TOKEN_OPERATOR ]=p->asColor();
  119. if(C TextNode *p=node.findNode("Keyword" ))colors[TOKEN_KEYWORD ]=p->asColor();
  120. if(C TextNode *p=node.findNode("Code" ))colors[TOKEN_CODE ]=p->asColor();
  121. if(C TextNode *p=node.findNode("Comment" ))colors[TOKEN_COMMENT ]=p->asColor();
  122. if(C TextNode *p=node.findNode("Text" ))colors[TOKEN_TEXT8 ]=colors[TOKEN_TEXT16]=p->asColor();
  123. if(C TextNode *p=node.findNode("Character" ))colors[TOKEN_CHAR8 ]=colors[TOKEN_CHAR16]=p->asColor();
  124. if(C TextNode *p=node.findNode("Number" ))colors[TOKEN_NUMBER ]=p->asColor();
  125. if(C TextNode *p=node.findNode("Preprocessor" ))colors[TOKEN_PREPROC ]=p->asColor();
  126. if(C TextNode *p=node.findNode("PreprocessorDisabled"))colors[TOKEN_PREPROC_DISABLED ]=p->asColor();
  127. if(C TextNode *p=node.findNode("Macro" ))colors[TOKEN_MACRO ]=p->asColor();
  128. if(C TextNode *p=node.findNode("EnumType" ))colors[TOKEN_ENUM_TYPE ]=p->asColor();
  129. if(C TextNode *p=node.findNode("EnumElement" ))colors[TOKEN_ENUM_ELM ]=p->asColor();
  130. if(C TextNode *p=node.findNode("Function" ))colors[TOKEN_FUNC ]=p->asColor();
  131. if(C TextNode *p=node.findNode("Selection" ))colors[TOKEN_SELECT ]=p->asColor();
  132. if(C TextNode *p=node.findNode("LineHighlight" ))colors[TOKEN_LINE_HIGHLIGHT ]=p->asColor();
  133. if(C TextNode *p=node.findNode("SymbolHighlight" ))colors[TOKEN_SYMBOL_HIGHLIGHT ]=p->asColor();
  134. if(C TextNode *p=node.findNode("BraceHighlight" ))colors[TOKEN_BRACE_HIGHLIGHT ]=p->asColor();
  135. if(C TextNode *p=node.findNode("ElementBackground" ))colors[TOKEN_ELM_BACKGROUND ]=p->asColor();
  136. if(C TextNode *p=node.findNode("ElementName" ))colors[TOKEN_ELM_NAME ]=p->asColor();
  137. if(C TextNode *p=node.findNode("LineNumberBackground"))colors[TOKEN_LINE_NUM_BACKGROUND]=p->asColor();
  138. if(C TextNode *p=node.findNode("LineNumber" ))colors[TOKEN_LINE_NUM ]=p->asColor();
  139. }
  140. /******************************************************************************/
  141. void CodeEditor::HideAndFocusCE(GuiObj &go) {go.hide(); CE.cei().kbSet();}
  142. /******************************************************************************/
  143. CodeEditor::MenuBarEx& CodeEditor::MenuBarEx::rect(C Rect &rect)
  144. {
  145. if(T.rect()!=rect)
  146. {
  147. super::rect(rect);
  148. Flt h=T.rect().h();
  149. CE.view_mode.rect(Rect_L ( T .elmsRect().right()+Vec2(0.01f, 0), 0.21f, h*0.84f));
  150. CE.view_what.rect(Rect_LU(CE.view_mode. rect().ru () , CE.view_mode.rect().h()));
  151. CE.b_close .rect(Rect_RU( T .rect().ru (), h , h));
  152. CE.build_progress.rect(Rect_R (CE.b_close.rect().left(), h*4, h*0.6f));
  153. }
  154. return T;
  155. }
  156. void CodeEditor::MenuBarEx::parentClientRectChanged(C Rect *old_client, C Rect *new_client)
  157. {
  158. if(new_client)
  159. {
  160. Rect r=CE.cei().menuRect()&*new_client;
  161. if(CE.menu_on_top)rect(Rect_LU(r.min.x, r.max.y, r.w(), 0.06f));else rect(Rect_LD(r.min.x, r.min.y, r.w(), 0.06f));
  162. }
  163. }
  164. /******************************************************************************/
  165. void CodeEditor::GotoLineWindow::create(CodeEditor &ce)
  166. {
  167. if(ce.parent)
  168. {
  169. T.ce=&ce;
  170. *ce.parent+=super ::create(Rect_C(0, 0, 1, 0.14f), "Go To Line").hide(); button[2].func(HideAndFocusCE, SCAST(GuiObj, T)).show();
  171. T +=textline.create(Rect (0, -clientHeight(), clientWidth(), 0).extend(-0.01f));
  172. }
  173. }
  174. GuiObj& CodeEditor::GotoLineWindow::activate()
  175. {
  176. if(ce && ce->cur() && hidden())
  177. {
  178. setTitle(S+"Go To Line (1.."+Max(1, ce->cur()->lines.elms())+')');
  179. textline.set(S+(ce->cur()->cur.y+1)).selectAll();
  180. }
  181. return super::activate();
  182. }
  183. void CodeEditor::GotoLineWindow::update(C GuiPC &gpc)
  184. {
  185. super::update(gpc);
  186. if(Gui.window()==this)
  187. {
  188. if(Kb.k(KB_ENTER)){if(ce && ce->cur()){ce->markCurPos(); ce->cur()->highlight(TextInt(textline())-1, false);} button[2].push(); Kb.eatKey();}
  189. }
  190. }
  191. /******************************************************************************/
  192. Window& CodeEditor::Options::VSVersions::show()
  193. {
  194. if(visible())return super::show();
  195. // #VisualStudio
  196. versions.del();
  197. Memc<VisualStudioInstallation> installs; GetVisualStudioInstallations(installs); REPA(installs) // list newest first
  198. {
  199. C VisualStudioInstallation &install=installs[i];
  200. T+=versions.New().create(Vec2(clientWidth()/2, -0.07f-versions.elms()*0.08f), install, ce);
  201. }
  202. if(versions.elms())
  203. {
  204. size(Vec2(size().x, barHeight() + -versions.last().rect().min.y+0.07f));
  205. return super::show();
  206. }else
  207. {
  208. hide();
  209. Str msg; CheckVisualStudio(0, &msg); Error(msg);
  210. return T;
  211. }
  212. }
  213. void CodeEditor::Options::VSVersions::create(CodeEditor &ce)
  214. {
  215. T.ce=&ce;
  216. Gui+=super::create(Rect_C(0, 0, 1.0f, 0.44f), "Visual Studio Versions Detected").hide(); button[2].show();
  217. }
  218. /******************************************************************************/
  219. static void ThemeColorChanged(C Property &prop)
  220. {
  221. ThemeCustom.colors[TOKEN_TEXT16]=ThemeCustom.colors[TOKEN_TEXT8];
  222. ThemeCustom.colors[TOKEN_CHAR16]=ThemeCustom.colors[TOKEN_CHAR8];
  223. CE.themeChanged();
  224. }
  225. CodeEditor::Options::ColorThemeEditor& CodeEditor::Options::ColorThemeEditor::create()
  226. {
  227. props.New().create("Background" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_NONE ]))).setColor();
  228. props.New().create("Operator" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_OPERATOR ]))).setColor();
  229. props.New().create("Keyword" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_KEYWORD ]))).setColor();
  230. props.New().create("Code" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_CODE ]))).setColor();
  231. props.New().create("Comment" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_COMMENT ]))).setColor();
  232. props.New().create("Text" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_TEXT8 ]))).setColor();
  233. props.New().create("Character" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_CHAR8 ]))).setColor();
  234. props.New().create("Number" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_NUMBER ]))).setColor();
  235. props.New().create("Preprocessor" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_PREPROC ]))).setColor();
  236. props.New().create("Preprocessor Disabled" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_PREPROC_DISABLED ]))).setColor();
  237. props.New().create("Macro" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_MACRO ]))).setColor();
  238. props.New().create("Enum Type" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_ENUM_TYPE ]))).setColor();
  239. props.New().create("Enum Element" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_ENUM_ELM ]))).setColor();
  240. props.New().create("Function" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_FUNC ]))).setColor();
  241. props.New().create("Line Highlight" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_LINE_HIGHLIGHT ]))).setColor();
  242. props.New().create("Symbol Highlight" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_SYMBOL_HIGHLIGHT ]))).setColor();
  243. props.New().create("Brace Highlight" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_BRACE_HIGHLIGHT ]))).setColor();
  244. props.New().create("Selection" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_SELECT ]))).setColor();
  245. props.New().create("Element Background" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_ELM_BACKGROUND ]))).setColor();
  246. props.New().create("Element Name" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_ELM_NAME ]))).setColor();
  247. props.New().create("Line Number Background", MemberDesc(MEMBER(ColorTheme, colors[TOKEN_LINE_NUM_BACKGROUND]))).setColor();
  248. props.New().create("Line Number" , MemberDesc(MEMBER(ColorTheme, colors[TOKEN_LINE_NUM ]))).setColor();
  249. ts.reset(true).size=0.036f; ts.align.set(1, 0);
  250. Gui+=super::create("Color Theme Editor").hide();
  251. Rect r=AddProperties(props, T, Vec2(0.02f, -0.02f), 0.043f, 0.3f, &ts); r.max+=defaultInnerPaddingSize()+0.04f;
  252. rect(Rect_RD(D.w(), -D.h(), r.w(), r.h()));
  253. REPAO(props).autoData(&ThemeCustom).changed(ThemeColorChanged); button[2].show();
  254. return T;
  255. }
  256. void CodeEditor::Options::ColorThemeEditor::skinChanged()
  257. {
  258. ts.resetColors(true);
  259. }
  260. /******************************************************************************/
  261. CodeEditor::Options::FontData::FontData()
  262. {
  263. size =18;
  264. spacing.set(0.59f, 1.05f);
  265. font ="Lucida Console";
  266. }
  267. CodeEditor::Options::FontParams::FontParams()
  268. {
  269. sample_text="bool Init()\\n{\\n int variable=123;\\n}\\nclass Test\\n{\\n Str member=\"value\";\\n}\\n";
  270. chinese=japanese=korean=false;
  271. }
  272. static CChar8 *Ansi="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()[]<>{}`~_-+=;:,.?/|\\'\" ";
  273. Str CodeEditor::Options::FontData::chars()C
  274. {
  275. Str c;
  276. if(1 )c+=Ansi;
  277. if(1 )c+=Ellipsis;
  278. if(1 )c+=LanguageSpecific(DE);
  279. if(1 )c+=LanguageSpecific(FR);
  280. if(1 )c+=LanguageSpecific(PL);
  281. if(1 )c+=LanguageSpecific(RU);
  282. REPA(langs)c+=LanguageSpecific(langs[i]);
  283. return c+custom_chars;
  284. }
  285. Bool CodeEditor::Options::FontData::make(Font &font, C Str *chars)C
  286. {
  287. Font::Params fp;
  288. fp.system_font =T.font;
  289. fp.characters =(chars ? *chars : T.chars());
  290. fp.size =size;
  291. fp.mode =Font::SUB_PIXEL;
  292. fp.mip_maps =1;
  293. fp.shadow_blur =0;
  294. fp.shadow_diagonal=false;
  295. fp.shadow_opacity =0;
  296. fp.shadow_spread =0;
  297. return font.create(fp);
  298. }
  299. void CodeEditor::Options::FontData::save(TextNode &node)C
  300. {
  301. node.getNode("size" ).value=S+size;
  302. node.getNode("spacing.x" ).value=S+spacing.x;
  303. node.getNode("spacing.y" ).value=S+spacing.y;
  304. node.getNode("font" ).value=font;
  305. node.getNode("custom_chars").value=custom_chars;
  306. Str &l=node.getNode("languages" ).value; l.clear(); FREPA(langs)l.space()+=langs[i];
  307. }
  308. void CodeEditor::Options::FontData::load(C TextNode &node)
  309. {
  310. langs.clear();
  311. if(C TextNode *p=node.findNode("size" ))size =Mid(p->asInt(), 1, 256);
  312. if(C TextNode *p=node.findNode("spacing.x" ))spacing.x =Mid(p->asFlt(), 0.0f, 1.0f);
  313. if(C TextNode *p=node.findNode("spacing.y" ))spacing.y =Mid(p->asFlt(), 0.0f, 2.0f);
  314. if(C TextNode *p=node.findNode("font" ))font =p->value;
  315. if(C TextNode *p=node.findNode("custom_chars"))custom_chars=p->value;
  316. if(C TextNode *p=node.findNode("languages" )){Memt<Str> l; Split(l, p->value, ' '); FREPA(l)if(l[i].is())langs.include((LANG_TYPE)TextInt(l[i]));}
  317. }
  318. void CodeEditor::Options::FontParams::load(C TextNode &node)
  319. {
  320. super::load(node);
  321. chinese =langs.has(CN);
  322. japanese=langs.has(JP);
  323. korean =langs.has(KO);
  324. }
  325. static void ParamsFont (CodeEditor::Options::FontParams &p, C Str &t) { p.font = t ;}
  326. static void ParamsSize (CodeEditor::Options::FontParams &p, C Str &t) { p.size =TextInt (t);}
  327. static void ParamsSpacingX (CodeEditor::Options::FontParams &p, C Str &t) { p.spacing.x =TextFlt (t);}
  328. static void ParamsSpacingY (CodeEditor::Options::FontParams &p, C Str &t) { p.spacing.y =TextFlt (t);}
  329. static void ParamsChinese (CodeEditor::Options::FontParams &p, C Str &t) {if(p.chinese =TextBool(t))p.langs.include(CN);else p.langs.exclude(CN);}
  330. static void ParamsJapanese (CodeEditor::Options::FontParams &p, C Str &t) {if(p.japanese =TextBool(t))p.langs.include(JP);else p.langs.exclude(JP);}
  331. static void ParamsKorean (CodeEditor::Options::FontParams &p, C Str &t) {if(p.korean =TextBool(t))p.langs.include(KO);else p.langs.exclude(KO);}
  332. static void ParamsCustomChar(CodeEditor::Options::FontParams &p, C Str &t) { p.custom_chars= t ;}
  333. static void Preview(Viewport &viewport) {((CodeEditor::Options::FontEditor*)viewport.user)->preview();}
  334. void CodeEditor::Options::FontEditor::preview()
  335. {
  336. SyncLocker locker(lock);
  337. Rect rect=D.viewRect();
  338. TextStyleParams ts; ts.font(&font); ts.color=BLACK; ts.shadow=0; ts.setPerPixelSize(); ts.align.set(1, -1); ts.spacing=SPACING_CONST; ts.space.set(params.spacing.x, AlignRound(params.spacing.y, 1.0f/font.height()));
  339. rect.draw(WHITE);
  340. D.text(ts, rect.extend(-0.01f), Replace(params.sample_text, "\\n", "\n"));
  341. }
  342. static Bool Make(Thread &thread) {return (*(CodeEditor::Options::FontEditor*)thread.user).make();}
  343. Bool CodeEditor::Options::FontEditor::make()
  344. {
  345. if(visible())
  346. {
  347. SyncLockerEx locker(lock); CodeEditor::Options::FontParams params=T.params; locker.off();
  348. ThreadMayUseGPUData();
  349. Font temp; if(params.make(temp, &params.sample_text)){locker.on(); Swap(font, temp); locker.off();}
  350. }
  351. Time.wait(10);
  352. return true;
  353. }
  354. static void Apply(CodeEditor::Options::FontEditor &font_edit)
  355. {
  356. Font temp; if(font_edit.params.make(temp))
  357. {
  358. File f; temp.save(f.writeMem()); f.pos(0); if(SafeOverwrite(f, "Bin/Code Editor.font"))
  359. {
  360. FontPtr font; if(font.find("Bin/Code Editor.font"))Swap(*font, temp);
  361. CE.fontChanged();
  362. }
  363. }
  364. }
  365. CodeEditor::Options::FontEditor& CodeEditor::Options::FontEditor::hide() {if(visible())thread.stop ( ); super::hide(); return T;}
  366. CodeEditor::Options::FontEditor& CodeEditor::Options::FontEditor::show() {if(hidden ())thread.create(Make, this); super::show(); return T;}
  367. CodeEditor::Options::FontEditor& CodeEditor::Options::FontEditor::del()
  368. {
  369. thread.del(); super::del(); return T;
  370. }
  371. CodeEditor::Options::FontEditor& CodeEditor::Options::FontEditor::create()
  372. {
  373. props.New().create("System Font" , MemberDesc(MEMBER(FontParams, font )).setTextToDataFunc(ParamsFont ));
  374. props.New().create("Size" , MemberDesc(MEMBER(FontParams, size )).setTextToDataFunc(ParamsSize )).range(8, 48);
  375. props.New().create("Char Spacing", MemberDesc(MEMBER(FontParams, spacing.x )).setTextToDataFunc(ParamsSpacingX )).range(0.45f, 0.75f).desc("Spacing between characters, default=0.59");
  376. props.New().create("Line Spacing", MemberDesc(MEMBER(FontParams, spacing.y )).setTextToDataFunc(ParamsSpacingY )).range(0.65f, 1.25f).desc("Spacing between lines, default=1.05");
  377. props.New().create("Chinese" , MemberDesc(MEMBER(FontParams, chinese )).setTextToDataFunc(ParamsChinese )).desc("Will include Chinese characters in the font");
  378. props.New().create("Japanese" , MemberDesc(MEMBER(FontParams, japanese )).setTextToDataFunc(ParamsJapanese )).desc("Will include Japanese characters in the font");
  379. props.New().create("Korean" , MemberDesc(MEMBER(FontParams, korean )).setTextToDataFunc(ParamsKorean )).desc("Will include Korean characters in the font");
  380. props.New().create("Custom Chars", MemberDesc(MEMBER(FontParams, custom_chars)).setTextToDataFunc(ParamsCustomChar)).desc("Will include custom characters in the font");
  381. props.New();
  382. props.New().create("Display:");
  383. props.New().create("Text", MemberDesc(MEMBER(FontParams, sample_text)));
  384. ts.reset(true).size=0.036f; ts.align.set(1, 0);
  385. Gui+=super::create("Font Editor").hide();
  386. Rect r=AddProperties(props, T, Vec2(0.02f, -0.02f), 0.043f, 0.3f, &ts);
  387. REPAO(props).autoData(&params); button[2].show();
  388. T+=apply.create(Rect_U(r.down()-Vec2(0, 0.043f), 0.3f, 0.05f), "Apply").func(Apply, T);
  389. T+=viewport.create(Rect_LU(0.56f, -0.02f, 0.72f, -apply.rect().min.y-0.02f), Preview, this);
  390. Vec2 size(viewport.rect().max.x, -apply.rect().min.y); size+=defaultInnerPaddingSize()+0.02f;
  391. rect(Rect_RD(D.w(), -D.h(), size.x, size.y));
  392. return T;
  393. }
  394. void CodeEditor::Options::FontEditor::skinChanged()
  395. {
  396. ts.resetColors(true);
  397. }
  398. /******************************************************************************/
  399. void CodeEditor::Options::skinChanged()
  400. {
  401. ts.resetColors(true);
  402. color_theme_editor.skinChanged();
  403. font_editor.skinChanged();
  404. }
  405. Window& CodeEditor::Options::show()
  406. {
  407. super::show();
  408. if(ce)ce->cei().visibleChangedOptions();
  409. return T;
  410. }
  411. Window& CodeEditor::Options::hide()
  412. {
  413. w_vs_path .hide();
  414. w_netbeans_path .hide();
  415. w_android_sdk .hide();
  416. w_android_ndk .hide();
  417. vs_versions .hide();
  418. color_theme_editor.hide();
  419. font_editor .hide();
  420. super::hide();
  421. if(ce)ce->cei().visibleChangedOptions();
  422. return T;
  423. }
  424. static void VSDownload ( CodeEditor::Options &op) {Explore("https://www.visualstudio.com/downloads/download-visual-studio-vs#d-community");}
  425. static void NBDownload ( CodeEditor::Options &op) {Explore("https://netbeans.org/downloads/start.html?platform=linux&lang=en&option=cpp&bits=x64");}
  426. static void EASDownload ( CodeEditor::Options &op) {Explore("http://www.esenthel.com/?id=store");}
  427. static void ASDownload ( CodeEditor::Options &op) {Explore("https://developer.android.com/studio/#command-tools");}
  428. static void ANDownload ( CodeEditor::Options &op) {Explore("https://developer.android.com/ndk/downloads/");}
  429. static void JDKDownload ( CodeEditor::Options &op) {Explore("https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html");}
  430. static void VSChanged ( CodeEditor::Options &op) {if(op.ce)op.ce->setVSPath (op. vs_path());}
  431. static void NBChanged ( CodeEditor::Options &op) {if(op.ce)op.ce->setNBPath (op.netbeans_path());}
  432. static void ASChanged ( CodeEditor::Options &op) {if(op.ce)op.ce->setASPath (op. android_sdk());}
  433. static void ANChanged ( CodeEditor::Options &op) {if(op.ce)op.ce->setANPath (op. android_ndk());}
  434. static void JDKChanged ( CodeEditor::Options &op) {if(op.ce)op.ce->setJDKPath (op. jdk_path());}
  435. static void CertChangedF ( CodeEditor::Options &op) {if(op.ce)op.ce->setCertPath(op. cert_file());}
  436. static void CertChangedP ( CodeEditor::Options &op) {if(op.ce)op.ce->setCertPass(op. cert_pass());}
  437. static void VSSelect ( CodeEditor::Options &op) {op.w_vs_path .activate();}
  438. static void NBSelect ( CodeEditor::Options &op) {op.w_netbeans_path.activate();}
  439. static void ASSelect ( CodeEditor::Options &op) {op.w_android_sdk .activate();}
  440. static void ANSelect ( CodeEditor::Options &op) {op.w_android_ndk .activate();}
  441. static void JDKSelect ( CodeEditor::Options &op) {op.w_jdk_path .activate();}
  442. static void CertSelect ( CodeEditor::Options &op) {op.w_cert_file .activate();}
  443. static void VSLoad (C Str &path, CodeEditor::Options &op) {if(op.ce)op.ce->setVSPath (path);}
  444. static void NBLoad (C Str &path, CodeEditor::Options &op) {if(op.ce)op.ce->setNBPath (path);}
  445. static void ASLoad (C Str &path, CodeEditor::Options &op) {if(op.ce)op.ce->setASPath (path);}
  446. static void ANLoad (C Str &path, CodeEditor::Options &op) {if(op.ce)op.ce->setANPath (path);}
  447. static void JDKLoad (C Str &path, CodeEditor::Options &op) {if(op.ce)op.ce->setJDKPath (path);}
  448. static void CertLoad (C Str &path, CodeEditor::Options &op) {if(op.ce)op.ce->setCertPath(path);}
  449. static void VSAutodetect ( CodeEditor::Options &op) {op.vs_versions.activate();}
  450. static void ASAutodetect ( CodeEditor::Options &op) {Str p=GetRegStr(RKG_LOCAL_MACHINE, "Software/Android SDK Tools/Path"); if(p.is())ASLoad(p, op);}
  451. static void JDKAutodetect ( CodeEditor::Options &op) {Str p=GetRegStr(RKG_LOCAL_MACHINE, "Software/JavaSoft/Java Development Kit/1.8/JavaHome"); if(p.is())JDKLoad(p, op);}
  452. static void ANAutodetect ( CodeEditor::Options &op)
  453. {
  454. Memc<Str> paths; // list of Android SDK paths
  455. Str p=GetPath(op.android_sdk()); if(p.is())paths.binaryInclude(p, ComparePathCI);
  456. p=GetPath(GetRegStr(RKG_LOCAL_MACHINE, "Software/Android SDK Tools/Path")); if(p.is())paths.binaryInclude(p, ComparePathCI);
  457. FREPA(paths)for(FileFind ff(paths[i]); ff(); )if(FExistSystem(ff.pathName()+("/" PLATFORM("ndk-build.cmd", "ndk-build")))){ANLoad(ff.pathName(), op); return;} // check if in same paths there is NDK found
  458. }
  459. static void CertCreate (CodeEditor::Options &op) {if(op.ce)op.ce->android_certificate.activate();}
  460. static void FontSizeChanged (CodeEditor::Options &op) {if(op.ce)op.ce-> fontChanged();}
  461. static void ThemeChanged (CodeEditor::Options &op) {if(op.ce)op.ce-> themeChanged();}
  462. static void EditCustomTheme (CodeEditor::Options &op) {op.color_theme_editor.visibleToggleActivate();}
  463. static void EditCustomFont (CodeEditor::Options &op) {op. font_editor.visibleToggleActivate();}
  464. static void ScrollChanged (CodeEditor::Options &op) {if(op.ce)op.ce->scrollChanged();}
  465. static void LineNumbersChanged (CodeEditor::Options &op) {if(op.ce && op.ce->cur())op.ce->cur()->setRegionSize();}
  466. static void HideHorizontalSlidebar(CodeEditor::Options &op) {if(op.ce)op.ce->hideSlideBarChanged();}
  467. static void AutoHideMenuBar (CodeEditor::Options &op) {if(op.ce)op.ce->setMenuBarVisibility();}
  468. static void FacebookAndroidKeyHash(CodeEditor::Options &op)
  469. {
  470. #if WINDOWS
  471. if(!CE.jdk_path.is() || !FExistSystem(CE.jdk_path.tailSlash(true)+"bin/keytool.exe")){CE.options.activatePaths(); Gui.msgBox(S, "Path to Java Development Kit was not specified or is invalid."); return;}
  472. #endif
  473. if(!CE.cert_file.is() || !FExistSystem(CE.cert_file)){CE.options.activateCert(); Gui.msgBox(S, "Path to Android Certificate File was not specified or is invalid."); return;}
  474. if(!CE.cert_pass.is() ){CE.options.activateCert(); Gui.msgBox(S, "Android Certificate Password was not specified."); return;}
  475. ConsoleProcess cp;
  476. if(!cp.create(PLATFORM(CE.jdk_path.tailSlash(true)+"bin/keytool.exe", "keytool"), S+"-exportcert -keystore \""+CE.cert_file+"\" -storepass \""+CE.cert_pass+"\" -keypass \""+CE.cert_pass+"\" -alias \"key\"", true, true))
  477. {Gui.msgBox(S, "Failed to start the Java Development Kit Key Tool."); return;}
  478. if(!cp.wait(-1)){Gui.msgBox(S, "Java Development Kit Key Tool timed out."); return;}
  479. Str out=cp.get(); Memt<Byte> data; data.setNum(out.length()); REPAO(data)=out[i];
  480. SHA1::Hash hash=SHA1Mem(data.data(), data.elms());
  481. out=Base64(&hash, SIZE(hash));
  482. ClipSet(out);
  483. Gui.msgBox("Success", S+"Key Hash\n"+out+"\nhas been copied to clipboard.");
  484. }
  485. void CodeEditor::Options::activatePaths() {tabs.set(1); activate();}
  486. void CodeEditor::Options::activateCert () {tabs.set(2); activate();}
  487. static CChar8 *color_theme_t[]=
  488. {
  489. "Light",
  490. "Blue",
  491. "Dark",
  492. "Custom",
  493. };
  494. static CChar8 *path_mode_t[]=
  495. {
  496. "Absolute",
  497. "Relative",
  498. };
  499. void CodeEditor::Options::create(CodeEditor &ce)
  500. {
  501. font_sizes.New().set(12, "12"); // 0
  502. font_sizes.New().set(13, "13"); // 1
  503. font_sizes.New().set(14, "14"); // 2
  504. font_sizes.New().set(15, "15"); // 3
  505. font_sizes.New().set(16, "16"); // 4
  506. font_sizes.New().set(17, "17"); // 5
  507. font_sizes.New().set(18, "18"); // 6
  508. font_sizes.New().set( 0, "Custom"); // 7
  509. ListColumn lc[]=
  510. {
  511. ListColumn(MEMBER(FontSize, text), LCW_MAX_DATA_PARENT, "size"),
  512. };
  513. T.ce=&ce;
  514. Gui+=super::create(Rect_C(0, 0, 1.2f, 0.885f), "Editor Options").hide(); button[2].show();
  515. CChar8 *tabs_t[]={"Code Editor", "Paths", "Certificates", "Importing"};
  516. Flt Y=-0.05f;
  517. T+=tabs.create(Rect_C(clientWidth()/2, Y, 0.8f, 0.05f), 0, tabs_t, Elms(tabs_t), true).valid(true).set(0); Y-=0.10f;
  518. ts.reset(true).align.set(1, 1);
  519. // code editor
  520. {
  521. Tab &tab=tabs.tab(0);
  522. Flt y=Y, s=0.069f, w=0.64f, h=0.055f;
  523. tab+=t_font_size .create(Vec2(0.32f, y), "Font:");
  524. tab+= font_size .create(Rect_R((clientWidth()+w)/2, y, 0.22f, h)).setColumns(lc, Elms(lc)).setData(font_sizes).func(FontSizeChanged, T, true).set(4);
  525. tab+= font_edit .create(Rect_L(font_size.rect().right()+Vec2(0.02f,0), 0.10f, h), "Edit").func(EditCustomFont, T); y-=s;
  526. tab+=t_color_theme .create(Vec2(0.40f, y), "Color Theme:");
  527. tab+= color_theme .create(Rect_R((clientWidth()+w)/2, y, 0.22f, h), color_theme_t, Elms(color_theme_t)).func(ThemeChanged, T).set(2);
  528. tab+= color_theme_edit .create(Rect_L(color_theme.rect().right()+Vec2(0.02f,0), 0.10f, h), "Edit").func(EditCustomTheme, T); y-=s;
  529. tab+= ac_on_enter .create(Rect_C(clientWidth()/2, y, w, h), "Autocomplete on Enter only"); ac_on_enter.mode=BUTTON_TOGGLE; y-=s;
  530. tab+= simple .create(Rect_C(clientWidth()/2, y, w, h), "Simple Edit Mode" ).desc("Editing text will not perform any additional helper operations."); simple.mode=BUTTON_TOGGLE; y-=s;
  531. tab+= imm_scroll .create(Rect_C(clientWidth()/2, y, w, h), "Immediate Scroll" ).func(ScrollChanged, T).desc("Enable immediate mouse-wheel scrolling instead of default smooth."); imm_scroll.mode=BUTTON_TOGGLE; y-=s;
  532. tab+= eol_clip .create(Rect_C(clientWidth()/2, y, w, h), "End of Line Cursor Clip" ).desc("Clip cursor position to end of line when mouse clicking."); eol_clip.mode=BUTTON_TOGGLE; eol_clip.set(true); y-=s;
  533. tab+= line_numbers .create(Rect_C(clientWidth()/2, y, w, h), "Show Line Numbers" ).func(LineNumbersChanged, T); line_numbers.mode=BUTTON_TOGGLE; y-=s;
  534. tab+= hide_horizontal_slidebar.create(Rect_C(clientWidth()/2, y, w, h), "Hide Horizontal SlideBar" ).func(HideHorizontalSlidebar, T); hide_horizontal_slidebar.mode=BUTTON_TOGGLE; y-=s;
  535. tab+= auto_hide_menu .create(Rect_C(clientWidth()/2, y, w, h), "Auto-Hide MenuBar" ).func(AutoHideMenuBar, T); auto_hide_menu.mode=BUTTON_TOGGLE; y-=s;
  536. tab+=t_export_path_mode .create(Vec2(0.475f, y), "Project Export Paths:");
  537. tab+= export_path_mode .create(Rect_R((clientWidth()+w)/2, y, 0.24f, h), path_mode_t, Elms(path_mode_t)).set(0); y-=s;
  538. }
  539. // paths
  540. {
  541. Tab &tab=tabs.tab(1);
  542. Flt y=Y-0.05f, w=1.0f, h=0.05f, s=0.13f;
  543. #if WINDOWS
  544. tab+= vs_path .create(Rect_C (clientWidth()/2, y, w, h), ce.vs_path).func(VSChanged, T); y-=s;
  545. tab+=t_vs_path .create(vs_path.rect().lu(), "Visual Studio Path", &ts);
  546. tab+=b_vs_path .create(Rect_LU(vs_path.rect().ru(), h, h), "...").func(VSSelect, T);
  547. tab+=d_vs .create(Rect_RD(vs_path.rect().ru(), 0.22f, h), "Download").func(VSDownload , T);
  548. tab+= vs_path_auto.create(Rect_RU(d_vs.rect().lu(), 0.26f, h), "Auto-Detect").func(VSAutodetect, T);
  549. #elif LINUX
  550. tab+= netbeans_path .create(Rect_C (clientWidth()/2, y, w, h), ce.netbeans_path).func(NBChanged, T); y-=s;
  551. tab+=t_netbeans_path .create(netbeans_path.rect().lu(), "NetBeans Path", &ts);
  552. tab+=b_netbeans_path .create(Rect_LU(netbeans_path.rect().ru(), h, h), "...").func(NBSelect, T);
  553. tab+=d_netbeans .create(Rect_RD(netbeans_path.rect().ru(), 0.22f, h), "Download").func(NBDownload , T);
  554. //tab+= netbeans_path_auto.create(Rect_RU(d_netbeans.rect().lu(), 0.26f, h), "Auto-Detect").func(NBAutodetect, T);
  555. #endif
  556. tab+= android_sdk.create(Rect_C(clientWidth()/2, y, w, h), ce.android_sdk).func(ASChanged, T); y-=s;
  557. tab+=t_android_sdk.create(android_sdk.rect().lu(), "Android SDK Path", &ts);
  558. tab+=b_android_sdk.create(Rect_LU(android_sdk.rect().ru(), h, h), "...").func(ASSelect, T);
  559. tab+=d_android_sdk.create(Rect_RD(android_sdk.rect().ru(), 0.22f, h), "Download").func(ASDownload, T);
  560. tab+= android_sdk_auto.create(Rect_RU(d_android_sdk.rect().lu(), 0.26f, h), "Auto-Detect").func(ASAutodetect, T);
  561. tab+= android_ndk.create(Rect_C(clientWidth()/2, y, w, h), ce.android_ndk).func(ANChanged, T); y-=s;
  562. tab+=t_android_ndk.create(android_ndk.rect().lu(), "Android NDK Path", &ts);
  563. tab+=b_android_ndk.create(Rect_LU(android_ndk.rect().ru(), h, h), "...").func(ANSelect, T);
  564. tab+=d_android_ndk.create(Rect_RD(android_ndk.rect().ru(), 0.22f, h), "Download").func(ANDownload, T);
  565. tab+= android_ndk_auto.create(Rect_RU(d_android_ndk.rect().lu(), 0.26f, h), "Auto-Detect").func(ANAutodetect, T);
  566. #if WINDOWS
  567. tab+= jdk_path .create(Rect_C (clientWidth()/2, y, w, h), ce.jdk_path).func(JDKChanged, T); y-=s;
  568. tab+=t_jdk_path .create(jdk_path.rect().lu(), "Java Development Kit (JDK) Path", &ts);
  569. tab+=d_jdk .create(Rect_RD(jdk_path.rect().ru(), 0.22f, h), "Download").func(JDKDownload, T);
  570. tab+=b_jdk_path .create(Rect_LU(jdk_path.rect().ru(), h, h), "...").func(JDKSelect, T);
  571. tab+= jdk_path_auto.create(Rect_RU(d_jdk.rect().lu(), 0.26f, h), "Auto-Detect").func(JDKAutodetect, T);
  572. #elif MAC // not needed on Linux
  573. tab+=t_jdk_path .create(Rect_C(clientWidth()/2, y, w, h).lu(), "Java Development Kit (JDK)", &ts);
  574. tab+=d_jdk .create(Rect_RD(Rect_C(clientWidth()/2, y, w, h).ru(), 0.22f, h), "Download").func(JDKDownload, T);
  575. #endif
  576. }
  577. // certificates
  578. {
  579. Tab &tab=tabs.tab(2);
  580. Flt y=Y-0.05f, w=1.0f, h=0.05f, s=0.06f;
  581. tab+= cert_file.create(Rect_C (clientWidth()*0.5f, y, w, h)).func(CertChangedF, T); y-=s;
  582. tab+=t_cert_file.create(cert_file.rect().lu(), "Android Certificate File", &ts); y-=s;
  583. tab+=b_cert_file.create(Rect_LU(cert_file.rect().ru(), h, h), "...").func(CertSelect, T);
  584. tab+=cert_create.create(Rect_RD(cert_file.rect().ru(), 0.22f, h), "Create").func(CertCreate, T);
  585. tab+= cert_pass.create(Rect_C (clientWidth()*0.5f, y, w, h)).func(CertChangedP, T); y-=s;
  586. tab+=t_cert_pass.create(cert_pass.rect().lu(), "Android Certificate Password", &ts); y-=s;
  587. tab+=facebook_android_key_hash.create(Rect_C(clientWidth()*0.5f, y, 0.80f, 0.06f), "Get Android Key Hash for Facebook").func(FacebookAndroidKeyHash, T); y-=s;
  588. y-=s;
  589. tab+=authenticode.create(Rect_C(clientWidth()/2, y, 0.60f, 0.06f), "Use Microsoft Authenticode").desc("If automatically sign the application when publishing for Windows EXE platform.\nWindows signtool.exe must be installed together with your Microsoft Windows Authenticode Digital Signature in the Certificate Store.\nSign tool will be used with the /a option making it to choose the best certificate out of all available."); authenticode.mode=BUTTON_TOGGLE; authenticode.set(false); y-=s;
  590. }
  591. // importing
  592. {
  593. Tab &tab=tabs.tab(3);
  594. Flt y=Y, s=0.069f, w=0.64f, h=0.055f;
  595. tab+=t_import_path_mode.create(Vec2(0.475f, y), "Asset Paths:");
  596. tab+= import_path_mode.create(Rect_R((clientWidth()+w)/2, y, 0.24f, h), path_mode_t, Elms(path_mode_t)).set(0); y-=s;
  597. tab+= import_image_mip_maps.create(Rect_C(clientWidth()/2, y, w, h), "Create Image Mip Maps").desc("This option defines if newly imported images should have mip maps created."); import_image_mip_maps.mode=BUTTON_TOGGLE; import_image_mip_maps.set(true); y-=s;
  598. }
  599. w_vs_path .create().modeDirSelect().io( VSLoad, VSLoad, T);
  600. w_netbeans_path .create().modeDirSelect().io( NBLoad, NBLoad, T);
  601. w_android_sdk .create().modeDirSelect().io( ASLoad, ASLoad, T);
  602. w_android_ndk .create().modeDirSelect().io( ANLoad, ANLoad, T);
  603. w_jdk_path .create().modeDirSelect().io( JDKLoad, JDKLoad, T);
  604. w_cert_file .create() .io(CertLoad, CertLoad, T);
  605. vs_versions.create(ce);
  606. color_theme_editor.create( );
  607. font_editor.create( );
  608. }
  609. /******************************************************************************/
  610. static void CreateCert(CodeEditor::AndroidCertificate &ac)
  611. {
  612. #if WINDOWS
  613. if(!CE.jdk_path.is() || !FExistSystem(CE.jdk_path.tailSlash(true)+"bin/keytool.exe")){CE.options.activatePaths(); Gui.msgBox(S, "Path to Java Development Kit was not specified or is invalid."); return;}
  614. #endif
  615. if(Contains(ac.org_name(), '"')){Gui.msgBox(S, "Developer Name cannot contain quotation marks"); return;}
  616. if(Contains(ac.pass (), '"')){Gui.msgBox(S, "Password cannot contain quotation marks" ); return;}
  617. if(ac.pass().length()<6 ){Gui.msgBox(S, "Password must be at least 6 characters long" ); return;}
  618. ac.win_io.save();
  619. }
  620. static void CreateCert(C Str &name, CodeEditor::AndroidCertificate &ac)
  621. {
  622. FDelFile(name);
  623. ConsoleProcess cp;
  624. if(!cp.create(PLATFORM(CE.jdk_path.tailSlash(true)+"bin/keytool.exe", "keytool"), S+"-genkey -keystore \""+name+"\" -storepass \""+ac.pass()+"\" -keypass \""+ac.pass()+"\" -keyalg RSA -keysize 2048 -validity 10000 -alias \"key\" -dname \"o="+ac.org_name()+"\""))
  625. {Gui.msgBox(S, "Failed to start the Java Development Kit Certificate Generator."); return;}
  626. if(cp.wait(-1))
  627. {
  628. if(!FExistSystem(name)){Gui.msgBox(S, S+"Failed to create certificate:\n"+cp.get()); return;}
  629. Gui.msgBox("Success", "Certificate created successfully");
  630. CE.setCertPath( name );
  631. CE.setCertPass(ac.pass());
  632. }
  633. ac.hide();
  634. }
  635. Window& CodeEditor::AndroidCertificate::hide()
  636. {
  637. win_io.hide();
  638. return super::hide();
  639. }
  640. void CodeEditor::AndroidCertificate::create(CodeEditor &ce)
  641. {
  642. Gui+=super::create(Rect_C(0, 0, 0.7f, 0.42f), "Android Certificate Creator").hide(); button[2].show();
  643. Flt y=-0.05f, h=0.05f, s=0.06f;
  644. T+=torg_name.create(Rect_C(clientWidth()*0.5f, y, 0, 0), "Developer Name"); y-=s*0.8f;
  645. T+= org_name.create(Rect_C(clientWidth()*0.5f, y, clientWidth()*0.9f, h )); y-=s;
  646. T+=tpass .create(Rect_C(clientWidth()*0.5f, y, 0, 0), "Password" ); y-=s*0.8f;
  647. T+= pass .create(Rect_C(clientWidth()*0.5f, y, clientWidth()*0.9f, h )); y-=s*1.4f;
  648. T+= save .create(Rect_C(clientWidth()*0.5f, y, 0.3f, h ), "Create").func(CreateCert, T); y-=s;
  649. win_io.create(S, S, SystemPath(SP_DESKTOP), CreateCert, CreateCert, T);
  650. }
  651. /******************************************************************************/
  652. void CodeEditor::hideAll()
  653. {
  654. options .hide();
  655. android_certificate.hide();
  656. find .hide();
  657. replace .hide();
  658. build_progress .hide();
  659. build_io .hide();
  660. devlog_io .hide();
  661. visibleOutput (false);
  662. visibleAndroidDevLog(false);
  663. }
  664. Bool CodeEditor::visibleOpenedFiles() {return false;}
  665. void CodeEditor::visibleOpenedFiles(Bool on)
  666. {
  667. }
  668. Bool CodeEditor::visibleOutput( ) {return build_region.visible();}
  669. void CodeEditor::visibleOutput(Bool on)
  670. {
  671. if(build_region.visible()!=on)
  672. {
  673. build_region.visible(on);
  674. build_close .visible(on);
  675. build_export.visible(on);
  676. build_copy .visible(on);
  677. resize();
  678. }
  679. cei().visibleChangedOutput();
  680. }
  681. Bool CodeEditor::visibleAndroidDevLog( ) {return devlog_region.visible();}
  682. void CodeEditor::visibleAndroidDevLog(Bool on)
  683. {
  684. if(devlog_region.visible()!=on)
  685. {
  686. devlog_region.visible(on);
  687. devlog_close .visible(on);
  688. devlog_export.visible(on);
  689. devlog_filter.visible(on);
  690. devlog_clear .visible(on);
  691. if(on && !devlog_process.active())
  692. {
  693. adb_path=adbPath();
  694. if(!adb_path.is()){options.activatePaths(); Gui.msgBox(S, "The path to Android SDK has not been specified or is invalid.");}else
  695. {
  696. if(adb_server.create(adb_path, "start-server")) // if we're going to launch the app then make sure that the ADB server is running, or else custom launched ADB processess will never exit
  697. {
  698. if(adb_server.wait(1000/60)) // wait up to 1 frame of 60 fps for it to show up
  699. {
  700. devlog_process.create(adb_path, "logcat -v time");
  701. adb_server.del();
  702. }else
  703. { // let it run and start devlog once it finished
  704. devlog_data.clear();
  705. devlog_data.New().message="Starting Android Debug Bridge..";
  706. devlog_list.setData(devlog_data);
  707. }
  708. }
  709. }
  710. }
  711. resize();
  712. }
  713. cei().visibleChangedAndroidDevLog();
  714. }
  715. /******************************************************************************/
  716. static void RegionRect(Region &region, C Rect &rect)
  717. {
  718. if(region.rect()!=rect)
  719. {
  720. Bool at_end=region.slidebar[1].wantedAtEnd(); region.rect(rect); if(at_end)region.slidebar[1].scrollEnd(true);
  721. }
  722. }
  723. void CodeEditor::resize()
  724. {
  725. ts .setPerPixelSize();
  726. ts_small.setPerPixelSize();
  727. menu.parentClientRectChanged(null, &NoTemp(D.rect()));
  728. Flt menu_h=menu.rect().h();
  729. RegionRect(build_region, Rect(-D.w(), -D.h(), D.w(), -D.h()*0.5f)+Vec2(0, menu_on_top ? 0 : menu_h));
  730. build_list.elmHeight(ts.size.y).textSize(ts.size.y);//.columnHeight(ts.size.y*1.3f);
  731. build_close .rect(Rect_RU(build_region.rect().ru()-Vec2(build_region.slidebarSize(), 0), build_list.columnHeight(), build_list.columnHeight()));
  732. build_export.rect(Rect_RU(build_close .rect().lu(), 0.18f, build_list.columnHeight())).desc("Export to file");
  733. build_copy .rect(Rect_RU(build_export.rect().lu(), 0.16f, build_list.columnHeight())).desc("Copy to System Clipboard");
  734. RegionRect(devlog_region, Rect_LD(build_region.visible() ? build_region.rect().lu() : Vec2(-D.w(), -D.h()+(menu_on_top ? 0 : menu_h)), build_region.rect().w(), D.h()*(build_region.visible() ? 1.2f : 1.5f)));
  735. devlog_list.elmHeight(ts.size.y).textSize(ts.size.y);
  736. devlog_list.columnWidth(0, ts.size.y*3.8f);
  737. devlog_list.columnWidth(1, ts.size.y*7.8f);
  738. devlog_close .rect(Rect_RU(devlog_region.rect().ru()-Vec2(devlog_region.slidebarSize(), 0), devlog_list.columnHeight(), devlog_list.columnHeight()));
  739. devlog_clear .rect(Rect_RU(devlog_close .rect().lu(), 0.17f, devlog_list.columnHeight()));
  740. devlog_export.rect(Rect_RU(devlog_clear .rect().lu(), 0.20f, devlog_list.columnHeight()));
  741. devlog_filter.rect(Rect_RU(devlog_export.rect().lu(), 0.23f, devlog_list.columnHeight()));
  742. find.resize();
  743. if(cur())cur()->resize();
  744. }
  745. void CodeEditor::skinChanged()
  746. {
  747. FontPtr cjk_font=UID(3047797125, 1232117798, 1870176427, 3857765718) /* Extra\Data\Verdana (Small CJK) */; // get reference before resetting 'ts_cjk' in case that would unload it
  748. ts .resetColors(true);
  749. ts_small.resetColors(true);
  750. ts_cjk .reset (true).font(cjk_font);
  751. if(Gui.skin)suggestions_skin=find_result_skin=source_skin=cjk_skin=*Gui.skin;
  752. source_skin.region.normal.clear();
  753. source_skin.region.normal_color.zero();
  754. find_result_skin.list.text_style=&ts_small;
  755. suggestions_skin.list.text_style=&ts;
  756. cjk_skin.list.text_style=&ts_cjk;
  757. REPAO( build_data).setColor();
  758. REPAO(devlog_data).setColor();
  759. options.skinChanged();
  760. ColorPicker::SetTextStyle();
  761. }
  762. /******************************************************************************/
  763. void CodeEditor::zoom(Int zoom)
  764. {
  765. if(InRange(options.font_size(), options.font_sizes)
  766. && options.font_sizes[options.font_size()].size>0)
  767. {
  768. Int new_index=options.font_size()+zoom;
  769. if(InRange(new_index, options.font_sizes)
  770. && options.font_sizes[new_index].size>0)
  771. options.font_size.set(new_index);
  772. }
  773. }
  774. /******************************************************************************/
  775. void CodeEditor::fontChanged()
  776. {
  777. if(InRange(options.font_size(), options.font_sizes))
  778. {
  779. Int size=options.font_sizes[options.font_size()].size;
  780. options.font_edit.visible(size<=0);
  781. ts.font(null);
  782. Vec2 spacing(0.59f, 1.05f);
  783. if(size<=0) // try to load custom font
  784. {
  785. FontPtr font;
  786. if(font.get("Bin/Code Editor.font"))
  787. if(font->is())
  788. {
  789. ts.font(font); size=font->height(); spacing=options.font_editor.params.spacing;
  790. }
  791. }
  792. if(size<=0)size=18;
  793. if(!ts.font())ts.font(S+"Font/Lucida Console "+Mid(size, 11, 18)+".font");
  794. ts.space.set( spacing.x, // ts.space.x=AlignRound(0.58f, 1.0f/ts.font->height());
  795. AlignRound(spacing.y, 1.0f/ts.font()->height()));
  796. ts_small.font(S+"Font/Lucida Console "+Mid(size-2, 11, 18)+".font");
  797. ts_small.space.set(AlignRound(0.55f, 1.0f/ts_small.font()->height()),
  798. AlignRound(0.90f, 1.0f/ts_small.font()->height()));
  799. resize();
  800. }
  801. }
  802. void CodeEditor:: themeChanged() {Theme=(options.color_theme()==0 ? ThemeLight : options.color_theme()==1 ? ThemeBlue : options.color_theme()==2 ? ThemeDark : ThemeCustom); options.color_theme_edit.visible(options.color_theme()==3); REPAO(sources).themeChanged ();}
  803. void CodeEditor:: scrollChanged() { REPAO(sources).setScroll ();}
  804. void CodeEditor:: hideSlideBarChanged() { REPAO(sources).setHideSlideBar();}
  805. void CodeEditor::setMenuBarVisibility()
  806. {
  807. Bool visible=(options.auto_hide_menu() ? menu.contains(Gui.ms()) || view_mode.contains(Gui.ms()) || view_what.contains(Gui.ms()) || b_close.contains(Gui.ms()) || Ms.pos().y<=menu.rect().min.y+EPS : true);
  808. if(menu.visible()!=visible)
  809. {
  810. menu .visible(visible);
  811. view_mode.visible(visible);
  812. view_what.visible(visible);
  813. b_close .visible(visible);
  814. resize();
  815. }
  816. }
  817. /******************************************************************************/
  818. static Bool JumpTo(C Str &file, Int line)
  819. {
  820. Source *old=CE.cur();
  821. if(LineMap *lm=CE.build_line_maps.find(file))
  822. {
  823. SourceLoc src; Int original_index; UID original_id; lm->get(line, src, original_index, original_id);
  824. if(CE.load(src))
  825. {
  826. Int l=CE.cur()->findLine(original_id); if(l>=0)original_index=l;
  827. CE.cur()->highlight(original_index, old!=CE.cur());
  828. return true;
  829. }
  830. }
  831. if(CE.load(file, true, true)) // if failed to load original source, then display cpp/h file version instead
  832. {
  833. CE.cur()->highlight(line, old!=CE.cur());
  834. return true;
  835. }
  836. return false;
  837. }
  838. Bool CodeEditor::BuildResult::jumpTo()
  839. {
  840. if(source_loc.is()) // if source is specified
  841. {
  842. Source *old=CE.cur();
  843. if(CE.load(source_loc))
  844. {
  845. CE.cur()->highlight(CE.cur()->findLine(line), old!=CE.cur());
  846. return true;
  847. }
  848. }else // try to parse the text and detect file paths and lines
  849. {
  850. Str text=T.text;
  851. // Visual Studio - 1>file.cpp(line) : error C2065: '' : undeclared identifier
  852. // MSBuild - file.cpp(23): error C2039: '' : is not a member of..
  853. // Apple/Linux/Android - "C:/path/file.cpp:line:message" or "jni/../path/file.cpp:line:message"
  854. // remove Visual Studio process number
  855. FREPA(text)if(!(CharFlag(text[i])&CHARF_DIG))
  856. {
  857. if(text[i]=='>')text.remove(0, i+1);
  858. break;
  859. }
  860. text=SkipWhiteChars(text);
  861. text=SkipStart (text, "could be '");
  862. text=SkipStart (text, "or '");
  863. text=SkipWhiteChars(text);
  864. // try Visual Studio and MSBuild
  865. Int posa=TextPosI(text, ") : "), // "file.cpp(line) : error/warning"
  866. posb=TextPosI(text, "): " ); // "file.cpp(line): error/warning" (this case can be encountered in VS 2010)
  867. Int pos =posa; if(posb>=0 && (pos<0 || posb<pos))pos=posb; // take whichever is first and valid
  868. if( pos>=0)
  869. {
  870. text.clip(pos);
  871. REPA(text)
  872. {
  873. if(text[i]=='(')
  874. {
  875. Int line=TextInt(text()+i+1)-1;
  876. text.clip(i);
  877. if( Starts (text, ".\\"))text.remove(0, 2); // remove ".\\" in ".\\Source\\file.cpp"
  878. if(!FullPath(text ))text=CE.build_path+text; // "Source\\file.cpp"
  879. if(JumpTo(text, line))return true;
  880. break;
  881. }else
  882. if(!(CharFlag(text[i])&CHARF_DIG) && text[i]!=',')break;
  883. }
  884. }else
  885. {
  886. Int pos =TextPosI(text, ':'); if(pos==1)pos=TextPosIN(text, ':', 1); // if it's ':' from "C:" then get the next ':'
  887. if( pos>=0)
  888. {
  889. Int line =TextInt(text()+pos+1)-1;
  890. if( line>=0)
  891. {
  892. text.clip(pos);
  893. if(FullPath(text) || StartsPath(text, "Source") || StartsPath(text, "jni") || StartsPath(text, ".."))
  894. {
  895. if(!FullPath(text))
  896. {
  897. if(CE.build_exe_type==EXE_APK)text=NormalizePath(CE.build_path+"Android/"+text);
  898. else text=NormalizePath(CE.build_path+ text);
  899. }
  900. if(JumpTo(text, line))return true;
  901. }
  902. }
  903. }
  904. }
  905. }
  906. return false;
  907. }
  908. void CodeEditor::BuildList::update(C GuiPC &gpc)
  909. {
  910. super::update(gpc);
  911. if(Gui.ms()==this && Ms.bp(0))if(BuildResult *br=T())br->jumpTo();
  912. }
  913. void CodeEditor::BuildList::draw(C GuiPC &gpc)
  914. {
  915. if(visible() && gpc.visible && InRange(highlight_line, T))
  916. {
  917. Flt alpha=1-(Time.appTime()-highlight_time);
  918. if( alpha>0)
  919. {
  920. D.clip(gpc.clip);
  921. visToScreenRect(highlight_line).draw(ColorAlpha(CYAN, alpha*0.5f));
  922. }
  923. }
  924. super::draw(gpc);
  925. }
  926. void CodeEditor::buildClear( ) { build_data.clear();}
  927. CodeEditor::BuildResult& CodeEditor::buildNew ( ) {return build_data.New ();}
  928. void CodeEditor::buildNew (Memc<Message> &msgs)
  929. {
  930. Source *last_source=null;
  931. FREPA(msgs)
  932. {
  933. Message &msg=msgs[i];
  934. Source *cur_source=msg.source;
  935. if(last_source!=cur_source){last_source=cur_source; buildNew().set(S+"\""+(cur_source ? cur_source->loc.asText() : S)+"\":", cur_source);}
  936. if(msg.type==Message::ERROR ){if(msg.token)buildNew().set(S+" Error: " +msg.text, msg.token);else buildNew().set(S+" Error: " +msg.text, msg.source);}else
  937. if(msg.type==Message::WARNING){if(msg.token)buildNew().set(S+" Warning: "+msg.text, msg.token);else buildNew().set(S+" Warning: "+msg.text, msg.source);}else
  938. {if(msg.token)buildNew().set( msg.text, msg.token);else buildNew().set( msg.text, msg.source);}
  939. FREPA(msg.children)
  940. {
  941. Message &c=msg.children[i];
  942. if(msg.token)buildNew().set(S+" "+c.text, c.token);else buildNew().set(S+" "+c.text, c.source);
  943. }
  944. }
  945. }
  946. void CodeEditor::buildUpdate(Bool show)
  947. {
  948. build_list.setData(build_data);
  949. if(show)visibleOutput(true);
  950. }
  951. Str CodeEditor::DeviceLog::asText() {return S+"Time("+time+"), App("+app+"): "+message;}
  952. /******************************************************************************/
  953. }}
  954. /******************************************************************************/