JSAutocomplete.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  3. // LICENSE: Atomic Game Engine Editor and Tools EULA
  4. // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
  5. // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
  6. //
  7. #include <Atomic/IO/Log.h>
  8. #include "JSAutocomplete.h"
  9. namespace AtomicEditor
  10. {
  11. JSAutocomplete::JSAutocomplete(TBEditField* editField) :
  12. editField_(editField),
  13. styleEdit_(editField->GetStyleEdit()),
  14. autoList_(0)
  15. {
  16. autoList_ = new TBSelectList();
  17. autoList_->SetSource(&autoSource_);
  18. autoList_->SetSize(150, 100);
  19. autoList_->SetIgnoreInput(true);
  20. editField->AddChild(autoList_);
  21. Hide();
  22. }
  23. bool JSAutocomplete::UpdateCompletions(const String& value)
  24. {
  25. if (value == currentValue_)
  26. return autoSource_.GetNumItems() > 0;
  27. currentValue_ = value;
  28. String lstring(value[0]);
  29. if (!locals_.Contains(lstring))
  30. {
  31. return false;
  32. }
  33. autoSource_.DeleteAllItems();
  34. const List<String>& tokens = locals_[lstring];
  35. for (List<String>::ConstIterator i = tokens.Begin(); i != tokens.End(); ++i)
  36. {
  37. if (*i != value && i->StartsWith(value))
  38. {
  39. autoSource_.AddItem(new TBGenericStringItem(i->CString()));
  40. }
  41. }
  42. autoList_->SetValue(0);
  43. return autoSource_.GetNumItems() > 0;
  44. }
  45. void JSAutocomplete::UpdateLocals()
  46. {
  47. TBBlock *block = styleEdit_->blocks.GetFirst();
  48. while (block)
  49. {
  50. for (TBTextFragment* frag = block->fragments.GetFirst(); frag; frag = frag->GetNext())
  51. {
  52. if (frag->len > 3)
  53. {
  54. String lstring(frag->Str()[0]);
  55. String token(frag->Str(), frag->len);
  56. if (!locals_[lstring].Contains(token))
  57. {
  58. //LOGINFOF("Adding Token %s to locals", token.CString());
  59. locals_[lstring].Push(token);
  60. }
  61. }
  62. }
  63. block = block->GetNext();
  64. }
  65. }
  66. void JSAutocomplete::SetPosition(const TBPoint &pos)
  67. {
  68. autoList_->SetPosition(pos);
  69. }
  70. bool JSAutocomplete::OnEvent(const TBWidgetEvent &ev)
  71. {
  72. if (ev.type == EVENT_TYPE_KEY_DOWN)
  73. {
  74. if (ev.special_key == TB_KEY_UP)
  75. {
  76. int v = autoList_->GetValue() - 1;
  77. if (v < 0)
  78. {
  79. styleEdit_->autocomplete_visible = false;
  80. autoList_->SetVisibilility(WIDGET_VISIBILITY_INVISIBLE);
  81. autoList_->SetValue(0);
  82. return styleEdit_->KeyDown(ev.key, ev.special_key, ev.modifierkeys);
  83. }
  84. else
  85. {
  86. autoList_->SetValue(v);
  87. }
  88. }
  89. else if (ev.special_key == TB_KEY_DOWN)
  90. {
  91. int v = autoList_->GetValue() + 1;
  92. if (v >= autoList_->GetSource()->GetNumItems())
  93. {
  94. styleEdit_->autocomplete_visible = false;
  95. autoList_->SetVisibilility(WIDGET_VISIBILITY_INVISIBLE);
  96. autoList_->SetValue(0);
  97. return styleEdit_->KeyDown(ev.key, ev.special_key, ev.modifierkeys);
  98. }
  99. else
  100. {
  101. autoList_->SetValue(v);
  102. }
  103. }
  104. else if (ev.special_key == TB_KEY_ENTER || ev.special_key == TB_KEY_TAB)
  105. {
  106. TBStr str = autoList_->GetSource()->GetItemString(autoList_->GetValue());
  107. TBTextFragment* fragment = 0;
  108. int ofs = styleEdit_->caret.pos.ofs;
  109. if (ofs >= 0)
  110. {
  111. fragment = styleEdit_->caret.pos.block->FindFragment(ofs, true);
  112. if (fragment)
  113. {
  114. int gofs = fragment->GetGlobalOfs();
  115. styleEdit_->selection.Select(gofs, gofs + fragment->len);
  116. styleEdit_->InsertText(str.CStr(), str.Length());
  117. }
  118. }
  119. styleEdit_->autocomplete_visible = false;
  120. autoList_->SetVisibilility(WIDGET_VISIBILITY_INVISIBLE);
  121. autoList_->SetValue(0);
  122. return true;
  123. }
  124. else if (ev.special_key == TB_KEY_ESC)
  125. {
  126. styleEdit_->autocomplete_visible = false;
  127. autoList_->SetVisibilility(WIDGET_VISIBILITY_INVISIBLE);
  128. autoList_->SetValue(0);
  129. return true;
  130. }
  131. }
  132. return false;
  133. }
  134. JSAutocomplete::~JSAutocomplete()
  135. {
  136. autoList_->SetSource(NULL);
  137. autoSource_.DeleteAllItems();
  138. }
  139. void JSAutocomplete::Show()
  140. {
  141. styleEdit_->autocomplete_visible = true;
  142. autoList_->SetVisibilility(WIDGET_VISIBILITY_VISIBLE);
  143. autoList_->SetValue(0);
  144. }
  145. void JSAutocomplete::Hide()
  146. {
  147. styleEdit_->autocomplete_visible = false;
  148. autoList_->SetVisibilility(WIDGET_VISIBILITY_INVISIBLE);
  149. autoList_->SetValue(0);
  150. }
  151. bool JSAutocomplete::Visible()
  152. {
  153. return autoList_->GetVisibility() == WIDGET_VISIBILITY_VISIBLE;
  154. }
  155. }