TextResourceEditor.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  2. // Please see LICENSE.md in repository root for license information
  3. // https://github.com/AtomicGameEngine/AtomicGameEngine
  4. #include "AtomicEditor.h"
  5. #include <Atomic/Container/ArrayPtr.h>
  6. #include <Atomic/UI/TBUI.h>
  7. #include <Atomic/IO/Log.h>
  8. #include <Atomic/IO/File.h>
  9. #include <Atomic/IO/FileSystem.h>
  10. #include <Atomic/Resource/ResourceCache.h>
  11. #include <Atomic/Core/CoreEvents.h>
  12. #include "../AEEvents.h"
  13. #include "../UI/UIFindTextWidget.h"
  14. #include "TextResourceEditor.h"
  15. #include <TurboBadger/tb_message_window.h>
  16. #include <TurboBadger/tb_editfield.h>
  17. #include <TurboBadger/tb_style_edit.h>
  18. #include <TurboBadger/tb_style_edit_content.h>
  19. using namespace tb;
  20. namespace AtomicEditor
  21. {
  22. TextResourceEditor ::TextResourceEditor(Context* context, const String &fullpath, TBTabContainer *container) :
  23. ResourceEditor(context, fullpath, container),
  24. styleEdit_(0),
  25. editField_(0),
  26. modified_(false),
  27. currentFindPos_(-1)
  28. {
  29. TBLayout* layout = new TBLayout();
  30. layout->SetLayoutDistribution(LAYOUT_DISTRIBUTION_GRAVITY);
  31. layout->SetSize(container_->GetRect().w, container_->GetRect().h);
  32. layout->SetGravity(WIDGET_GRAVITY_ALL);
  33. TBContainer* c = new TBContainer();
  34. c->SetGravity(WIDGET_GRAVITY_ALL);
  35. TBEditField* text = editField_ = new TBEditField();
  36. text->SetMultiline(true);
  37. text->SetWrapping(true);
  38. text->SetGravity(WIDGET_GRAVITY_ALL);
  39. text->SetStyling(true);
  40. text->SetSkinBg(TBIDC("TextCode"));
  41. TBFontDescription fd;
  42. fd.SetID(TBIDC("Monaco"));
  43. fd.SetSize(12);
  44. text->SetFontDescription(fd);
  45. SharedPtr<File> jsFile(GetSubsystem<ResourceCache>()->GetFile(fullpath));
  46. assert(jsFile);
  47. String source;
  48. jsFile->ReadText(source);
  49. text->SetText(source.CString());
  50. c->AddChild(text);
  51. layout->AddChild(c);
  52. layout->SetSpacing(0);
  53. container_->GetContentRoot()->AddChild(layout);
  54. TBStyleEdit* sedit = text->GetStyleEdit();
  55. sedit->text_change_listener = this;
  56. TBTextTheme* theme = new TBTextTheme();
  57. for (unsigned i = 0; i < TB_MAX_TEXT_THEME_COLORS; i++)
  58. theme->themeColors[i] = TBColor(255, 255, 255);
  59. sedit->SetTextTheme(theme);
  60. styleEdit_ = sedit;
  61. }
  62. TextResourceEditor::~TextResourceEditor()
  63. {
  64. }
  65. bool TextResourceEditor::OnEvent(const TBWidgetEvent &ev)
  66. {
  67. if (ev.type == EVENT_TYPE_KEY_DOWN)
  68. {
  69. if (ev.special_key == TB_KEY_ESC)
  70. {
  71. SendEvent(E_FINDTEXTCLOSE);
  72. }
  73. }
  74. if (ev.type == EVENT_TYPE_SHORTCUT)
  75. {
  76. if (ev.ref_id == TBIDC("close"))
  77. {
  78. if (modified_)
  79. {
  80. TBMessageWindow *msg_win = new TBMessageWindow(container_, TBIDC("unsaved_jsmodifications_dialog"));
  81. TBMessageWindowSettings settings(TB_MSG_OK_CANCEL, TBID(uint32(0)));
  82. settings.dimmer = true;
  83. settings.styling = true;
  84. msg_win->Show("Unsaved Modifications", "There are unsaved modications.\nDo you wish to discard them and close?", &settings, 640, 360);
  85. }
  86. else
  87. {
  88. Close();
  89. }
  90. }
  91. if (ev.ref_id == TBIDC("save") && modified_)
  92. {
  93. TBStr text;
  94. styleEdit_->GetText(text);
  95. File file(context_, fullpath_, FILE_WRITE);
  96. file.Write((void*) text.CStr(), text.Length());
  97. file.Close();
  98. ResourceCache* cache = GetSubsystem<ResourceCache>();
  99. //SharedPtr<File> jsFile (GetSubsystem<ResourceCache>()->GetFile<File>(fullpath_));
  100. //cache->ReloadResource(jsFile);
  101. String filename = GetFileNameAndExtension(fullpath_);
  102. button_->SetText(filename.CString());
  103. modified_ = false;
  104. SendEvent(E_JAVASCRIPTSAVED);
  105. return true;
  106. }
  107. else if (ev.ref_id == TBIDC("find"))
  108. {
  109. using namespace FindTextOpen;
  110. SendEvent(E_FINDTEXTOPEN);
  111. }
  112. else if (ev.ref_id == TBIDC("findnext") || ev.ref_id == TBIDC("findprev"))
  113. {
  114. String text;
  115. FindTextWidget* finder = GetSubsystem<FindTextWidget>();
  116. finder->GetFindText(text);
  117. // TODO: get flags from finder
  118. unsigned flags = FINDTEXT_FLAG_NONE;
  119. if (ev.ref_id == TBIDC("findnext"))
  120. flags |= FINDTEXT_FLAG_NEXT;
  121. else if (ev.ref_id == TBIDC("findprev"))
  122. flags |= FINDTEXT_FLAG_PREV;
  123. flags |= FINDTEXT_FLAG_WRAP;
  124. finder->Find(text, flags);
  125. }
  126. }
  127. if (ev.type == EVENT_TYPE_CLICK)
  128. {
  129. if (ev.target->GetID() == TBIDC("unsaved_jsmodifications_dialog"))
  130. {
  131. if (ev.ref_id == TBIDC("TBMessageWindow.ok"))
  132. {
  133. Close();
  134. }
  135. else
  136. {
  137. SetFocus();
  138. }
  139. return true;
  140. }
  141. }
  142. return false;
  143. }
  144. void TextResourceEditor::FindTextClose()
  145. {
  146. editField_->SetFocus(WIDGET_FOCUS_REASON_UNKNOWN);
  147. styleEdit_->selection.SelectNothing();
  148. }
  149. void TextResourceEditor::OnChange(TBStyleEdit* styleEdit)
  150. {
  151. modified_ = true;
  152. String filename = GetFileNameAndExtension(fullpath_);
  153. filename += "*";
  154. button_->SetText(filename.CString());
  155. }
  156. bool TextResourceEditor::FindText(const String& findText, unsigned flags)
  157. {
  158. // TODO: this should be shared with the JS resource editor
  159. unsigned findLength = findText.Length();
  160. if (!findLength)
  161. return true;
  162. TBStr _source;
  163. styleEdit_->GetText(_source);
  164. String source = _source.CStr();
  165. unsigned pos = String::NPOS;
  166. int startPos = currentFindPos_;
  167. if (currentFindPos_ == -1)
  168. startPos = styleEdit_->caret.GetGlobalOfs();
  169. else
  170. {
  171. if (flags & FINDTEXT_FLAG_NEXT)
  172. startPos += findLength;
  173. }
  174. if (flags & FINDTEXT_FLAG_PREV)
  175. {
  176. String pretext = source.Substring(0, startPos);
  177. pos = pretext.FindLast(findText, String::NPOS, flags & FINDTEXT_FLAG_CASESENSITIVE ? true : false);
  178. }
  179. else
  180. {
  181. pos = source.Find(findText, startPos, flags & FINDTEXT_FLAG_CASESENSITIVE ? true : false);
  182. }
  183. if (pos == String::NPOS)
  184. {
  185. if (flags & FINDTEXT_FLAG_WRAP)
  186. {
  187. if (flags & FINDTEXT_FLAG_PREV)
  188. {
  189. pos = source.FindLast(findText, String::NPOS, flags & FINDTEXT_FLAG_CASESENSITIVE ? true : false);
  190. }
  191. else
  192. {
  193. pos = source.Find(findText, 0, flags & FINDTEXT_FLAG_CASESENSITIVE ? true : false);
  194. }
  195. }
  196. if (pos == String::NPOS)
  197. {
  198. styleEdit_->selection.SelectNothing();
  199. return true;
  200. }
  201. }
  202. currentFindPos_ = pos;
  203. styleEdit_->caret.SetGlobalOfs((int) pos + findLength);
  204. int height = styleEdit_->layout_height;
  205. int newy = styleEdit_->caret.y - height/2;
  206. styleEdit_->SetScrollPos(styleEdit_->scroll_x, newy);
  207. styleEdit_->selection.Select(pos, pos + findLength);
  208. return true;
  209. }
  210. void TextResourceEditor::SetFocus()
  211. {
  212. editField_->SetFocus(WIDGET_FOCUS_REASON_UNKNOWN);
  213. }
  214. bool TextResourceEditor::HasUnsavedModifications()
  215. {
  216. return modified_;
  217. }
  218. }