JSAutocomplete.cpp 4.8 KB

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