JSAutocomplete.cpp 4.8 KB

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