LUAEditorView.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "LUAEditorView.hxx"
  9. #include <AzToolsFramework/UI/UICore/ProgressShield.hxx>
  10. #include <Source/LUA/moc_LUAEditorView.cpp>
  11. #include "LUAEditorContextMessages.h"
  12. #include "LUAEditorContextInterface.h"
  13. #include "LUAEditorViewMessages.h"
  14. #include "LUAEditorMainWindow.hxx"
  15. #include "LUABreakpointTrackerMessages.h"
  16. #include "LUAEditorSyntaxHighlighter.hxx"
  17. #include "LUAEditorStyleMessages.h"
  18. #include <Source/LUA/ui_LUAEditorView.h>
  19. #include <AzToolsFramework/SourceControl/SourceControlAPI.h>
  20. #include <QFileInfo>
  21. #include <QTimer>
  22. #include <QMessageBox>
  23. #include <QMimeData>
  24. namespace LUAEditor
  25. {
  26. struct FindOperationImpl
  27. {
  28. AZ_CLASS_ALLOCATOR(FindOperationImpl, AZ::SystemAllocator);
  29. QTextCursor m_cursor;
  30. QString m_searchString;
  31. bool m_isRegularExpression;
  32. bool m_isCaseSensitiveSearch;
  33. bool m_wholeWord;
  34. bool m_wrap;
  35. bool m_searchDown;
  36. };
  37. LUAViewWidget::FindOperation::FindOperation()
  38. : m_impl(nullptr)
  39. {
  40. }
  41. LUAViewWidget::FindOperation::FindOperation(FindOperation&& other)
  42. {
  43. m_impl = nullptr;
  44. *this = AZStd::move(other);
  45. }
  46. LUAViewWidget::FindOperation::FindOperation(FindOperationImpl* impl)
  47. {
  48. m_impl = impl;
  49. }
  50. LUAViewWidget::FindOperation::~FindOperation()
  51. {
  52. delete m_impl;
  53. }
  54. LUAViewWidget::FindOperation& LUAViewWidget::FindOperation::operator=(FindOperation&& other)
  55. {
  56. if (m_impl)
  57. {
  58. delete m_impl;
  59. }
  60. m_impl = other.m_impl;
  61. other.m_impl = nullptr;
  62. return *this;
  63. }
  64. LUAViewWidget::FindOperation::operator bool()
  65. {
  66. return m_impl && !m_impl->m_cursor.isNull();
  67. }
  68. //////////////////////////////////////////////////////////////////////////
  69. //LUADockWidget
  70. LUADockWidget::LUADockWidget(QWidget* parent, Qt::WindowFlags flags)
  71. : QDockWidget("LUADockWidget", parent, flags)
  72. {
  73. connect(this, &LUADockWidget::dockLocationChanged, this, &LUADockWidget::OnDockLocationChanged);
  74. }
  75. void LUADockWidget::closeEvent(QCloseEvent* event)
  76. {
  77. if (QMainWindow* pQMainWindow = qobject_cast<QMainWindow*>(parentWidget()))
  78. {
  79. if (LUAEditorMainWindow* pLUAEditorMainWindow = qobject_cast<LUAEditorMainWindow*>(pQMainWindow->parentWidget()))
  80. {
  81. pLUAEditorMainWindow->RequestCloseDocument(m_assetId);
  82. event->accept();
  83. }
  84. }
  85. }
  86. void LUADockWidget::OnDockLocationChanged(Qt::DockWidgetArea newArea)
  87. {
  88. (void)newArea;
  89. if (QMainWindow* pQMainWindow = qobject_cast<QMainWindow*>(parentWidget()))
  90. {
  91. if (LUAEditorMainWindow* pLUAEditorMainWindow = qobject_cast<LUAEditorMainWindow*>(pQMainWindow->parentWidget()))
  92. {
  93. pLUAEditorMainWindow->OnDockWidgetLocationChanged(m_assetId);
  94. }
  95. }
  96. }
  97. //////////////////////////////////////////////////////////////////////////
  98. //LUAViewWidget
  99. LUAViewWidget::LUAViewWidget(QWidget* pParent /*=NULL*/)
  100. : QWidget(pParent)
  101. , m_gui(azcreate(Ui::LUAEditorView, ()))
  102. , m_pLUADockWidget(NULL)
  103. , m_pLoadingProgressShield(NULL)
  104. , m_pSavingProgressShield(NULL)
  105. , m_pRequestingEditProgressShield(NULL)
  106. , m_PullRequestQueued(false)
  107. , m_AutoCompletionEnabled(true)
  108. {
  109. m_gui->setupUi(this);
  110. setAcceptDrops(true);
  111. m_gui->m_luaTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  112. m_gui->m_breakpoints->SetTextEdit(m_gui->m_luaTextEdit);
  113. m_gui->m_folding->SetTextEdit(m_gui->m_luaTextEdit);
  114. m_Highlighter = aznew LUASyntaxHighlighter(m_gui->m_luaTextEdit->document());
  115. QTextDocument* doc = m_gui->m_luaTextEdit->document();
  116. QTextOption option = doc->defaultTextOption();
  117. option.setFlags(option.flags() | QTextOption::ShowTabsAndSpaces);
  118. doc->setDefaultTextOption(option);
  119. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::modificationChanged, this, &LUAViewWidget::modificationChanged);
  120. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::cursorPositionChanged, this, &LUAViewWidget::UpdateBraceHighlight);
  121. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::Scrolled, m_gui->m_folding, static_cast<void(FoldingWidget::*)()>(&FoldingWidget::update));
  122. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::blockCountChanged, m_gui->m_breakpoints, &LUAEditorBreakpointWidget::OnBlockCountChange);
  123. connect(m_gui->m_luaTextEdit->document(), &QTextDocument::contentsChange, m_gui->m_breakpoints, &LUAEditorBreakpointWidget::OnCharsRemoved);
  124. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::FocusChanged, this, &LUAViewWidget::OnPlainTextFocusChanged);
  125. connect(m_gui->m_luaTextEdit->document(), &QTextDocument::contentsChange, m_gui->m_folding, &FoldingWidget::OnContentChanged);
  126. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::ZoomIn, this, &LUAViewWidget::OnZoomIn);
  127. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::ZoomOut, this, &LUAViewWidget::OnZoomOut);
  128. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::cursorPositionChanged, m_gui->m_folding, static_cast<void(FoldingWidget::*)()>(&FoldingWidget::update));
  129. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::cursorPositionChanged, m_gui->m_breakpoints, static_cast<void(LUAEditorBreakpointWidget::*)()>(&LUAEditorBreakpointWidget::update));
  130. connect(m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::Scrolled, m_gui->m_breakpoints, static_cast<void(LUAEditorBreakpointWidget::*)()>(&LUAEditorBreakpointWidget::update));
  131. connect(this, &LUAViewWidget::RegainFocus, this, &LUAViewWidget::RegainFocusFinal, Qt::QueuedConnection);
  132. connect(m_gui->m_folding, &FoldingWidget::TextBlockFoldingChanged, m_gui->m_breakpoints, static_cast<void(LUAEditorBreakpointWidget::*)()>(&LUAEditorBreakpointWidget::update));
  133. connect(m_gui->m_folding, &FoldingWidget::TextBlockFoldingChanged, m_gui->m_luaTextEdit, static_cast<void(LUAEditorPlainTextEdit::*)()>(&LUAEditorPlainTextEdit::update));
  134. connect(m_Highlighter, &LUASyntaxHighlighter::LUANamesInScopeChanged, m_gui->m_luaTextEdit, &LUAEditorPlainTextEdit::OnScopeNamesUpdated);
  135. connect(m_gui->m_breakpoints, &LUAEditorBreakpointWidget::toggleBreakpoint, this, &LUAViewWidget::BreakpointToggle);
  136. connect(m_gui->m_breakpoints, &LUAEditorBreakpointWidget::breakpointLineMove, this, &LUAViewWidget::OnBreakpointLineMoved);
  137. connect(m_gui->m_breakpoints, &LUAEditorBreakpointWidget::breakpointDelete, this, &LUAViewWidget::OnBreakpointLineDeleted);
  138. CreateStyleSheet();
  139. this->setMinimumSize(300, 300);
  140. SetReadonly(true);
  141. m_gui->m_luaTextEdit->SetGetLuaName([&](const QTextCursor& cursor) {return m_Highlighter->GetLUAName(cursor); });
  142. UpdateFont();
  143. LUABreakpointTrackerMessages::Handler::BusConnect();
  144. }
  145. void LUAViewWidget::Initialize(const DocumentInfo& initialInfo)
  146. {
  147. m_Info = initialInfo;
  148. if (!m_pLoadingProgressShield)
  149. {
  150. m_pLoadingProgressShield = aznew AzToolsFramework::ProgressShield(this);
  151. }
  152. m_pLoadingProgressShield->setProgress(0, 0, AZStd::string::format("Loading '%s'...", initialInfo.m_displayName.c_str()).c_str());
  153. m_pLoadingProgressShield->show();
  154. }
  155. void LUAViewWidget::CreateStyleSheet()
  156. {
  157. auto colors = AZ::UserSettings::CreateFind<SyntaxStyleSettings>(AZ_CRC_CE("LUA Editor Text Settings"), AZ::UserSettings::CT_GLOBAL);
  158. auto styleSheet = QString(R"(QPlainTextEdit:focus
  159. {
  160. background-color: %1;
  161. selection-background-color: %6;
  162. selection-color: %5;
  163. }
  164. QPlainTextEdit:!focus
  165. {
  166. background-color: %2;
  167. selection-color: %5;
  168. selection-background-color: %6;
  169. }
  170. QPlainTextEdit[readOnly="true"]:focus
  171. {
  172. background-color: %3;
  173. selection-color: %5;
  174. selection-background-color: %6;
  175. }
  176. QPlainTextEdit[readOnly="true"]:!focus
  177. {
  178. background-color: %4;
  179. selection-color: %5;
  180. selection-background-color: %6;
  181. }
  182. )");
  183. styleSheet = styleSheet.arg(colors->GetTextFocusedBackgroundColor().name())
  184. .arg(colors->GetTextUnfocusedBackgroundColor().name())
  185. .arg(colors->GetTextReadOnlyFocusedBackgroundColor().name())
  186. .arg(colors->GetTextReadOnlyUnfocusedBackgroundColor().name())
  187. .arg(colors->GetTextSelectedColor().name())
  188. .arg(colors->GetTextSelectedBackgroundColor().name());
  189. m_gui->m_luaTextEdit->setStyleSheet(styleSheet);
  190. styleSheet = QString(R"(LUAEditor--FoldingWidget:enabled {
  191. background-color: %1;
  192. }
  193. LUAEditor--FoldingWidget:!enabled {
  194. background-color: %2;
  195. }
  196. )");
  197. styleSheet = styleSheet.arg(colors->GetFoldingFocusedBackgroundColor().name())
  198. .arg(colors->GetFoldingUnfocusedBackgroundColor().name());
  199. m_gui->m_folding->setStyleSheet(styleSheet);
  200. }
  201. LUAViewWidget::~LUAViewWidget()
  202. {
  203. m_gui->m_breakpoints->PreDestruction();
  204. delete m_Highlighter;
  205. azdestroy(m_gui);
  206. LUABreakpointTrackerMessages::Handler::BusDisconnect();
  207. }
  208. template<typename Callable>
  209. void LUAViewWidget::UpdateCursor(Callable callable)
  210. {
  211. auto cursor = m_gui->m_luaTextEdit->textCursor();
  212. callable(cursor);
  213. m_gui->m_luaTextEdit->setTextCursor(cursor);
  214. }
  215. void LUAViewWidget::OnDocumentInfoUpdated(const DocumentInfo& newInfo)
  216. {
  217. AZ_Assert(newInfo.m_assetId == m_Info.m_assetId, "Asset ID mismatch.");
  218. //this is the the initial unmodified state
  219. bool modifiedValue = newInfo.m_bIsModified;
  220. //data loading///////////////////////////////////////////////
  221. if ((newInfo.m_bDataIsLoaded) && (!m_Info.m_bDataIsLoaded))
  222. {
  223. // load the data now that its ready!
  224. if (!newInfo.m_bUntitledDocument)
  225. {
  226. const char* buffer = NULL;
  227. AZStd::size_t actualSize = 0;
  228. Context_DocumentManagement::Bus::Broadcast(
  229. &Context_DocumentManagement::Bus::Events::GetDocumentData, newInfo.m_assetId, &buffer, actualSize);
  230. m_gui->m_luaTextEdit->setPlainText(buffer);
  231. LUAViewMessages::Bus::Broadcast(&LUAViewMessages::Bus::Events::OnDataLoadedAndSet, newInfo, this);
  232. }
  233. //remove the loading shield
  234. if (m_pLoadingProgressShield)
  235. {
  236. delete m_pLoadingProgressShield;
  237. m_pLoadingProgressShield = NULL;
  238. UpdateFont(); // Loading over, inner document need the latest font settings
  239. }
  240. // scan the breakpoint store from our context and pre-set the markers to get in sync
  241. const LUAEditor::BreakpointMap* myData = NULL;
  242. LUAEditor::LUABreakpointRequestMessages::Bus::BroadcastResult(
  243. myData, &LUAEditor::LUABreakpointRequestMessages::Bus::Events::RequestBreakpoints);
  244. AZ_Assert(myData, "LUAEditor::LUABreakpointRequestMessages::Bus, RequestBreakpoints failed to return any data.");
  245. BreakpointsUpdate(*myData);
  246. UpdateCurrentEditingLine(newInfo.m_PresetLineAtOpen);
  247. //AZ_TracePrintf("LUA", "Document Loaded Regain\n");
  248. emit RegainFocus();
  249. }
  250. if ((!newInfo.m_bDataIsLoaded) && (m_Info.m_bDataIsLoaded))
  251. {
  252. // wait for new data.
  253. if (!m_pLoadingProgressShield)
  254. {
  255. m_pLoadingProgressShield = aznew AzToolsFramework::ProgressShield(this);
  256. }
  257. m_pLoadingProgressShield->setProgress(0, 0, AZStd::string::format("Loading... ").c_str());
  258. m_pLoadingProgressShield->show();
  259. }
  260. //data saving/////////////////////////////
  261. if ((!newInfo.m_bIsBeingSaved) && (m_Info.m_bIsBeingSaved))
  262. {
  263. //remove the saving shield!
  264. if (m_pSavingProgressShield)
  265. {
  266. delete m_pSavingProgressShield;
  267. m_pSavingProgressShield = NULL;
  268. }
  269. }
  270. if ((newInfo.m_bDataIsWritten) && (!m_Info.m_bDataIsWritten))
  271. {
  272. m_gui->m_luaTextEdit->document()->setModified(false);
  273. }
  274. if ((newInfo.m_bIsBeingSaved) && (!m_Info.m_bIsBeingSaved))
  275. {
  276. // show the saving shield!
  277. if (!m_pSavingProgressShield)
  278. {
  279. m_pSavingProgressShield = aznew AzToolsFramework::ProgressShield(this);
  280. }
  281. m_pSavingProgressShield->setProgress(0, 0, AZStd::string::format("Saving... ").c_str());
  282. m_pSavingProgressShield->show();
  283. }
  284. //requesting edit (checking out)/////////////////////////////
  285. if ((!newInfo.m_bSourceControl_BusyRequestingEdit) && (m_Info.m_bSourceControl_BusyRequestingEdit))
  286. {
  287. //remove the checking out shield
  288. if (m_pRequestingEditProgressShield)
  289. {
  290. delete m_pRequestingEditProgressShield;
  291. m_pRequestingEditProgressShield = NULL;
  292. }
  293. }
  294. if ((newInfo.m_bSourceControl_BusyRequestingEdit) && (!m_Info.m_bSourceControl_BusyRequestingEdit))
  295. {
  296. // wait for edit request.
  297. if (!m_pRequestingEditProgressShield)
  298. {
  299. m_pRequestingEditProgressShield = aznew AzToolsFramework::ProgressShield(this);
  300. }
  301. m_pRequestingEditProgressShield->setProgress(0, 0, AZStd::string::format("Checking Out... ").c_str());
  302. m_pRequestingEditProgressShield->show();
  303. }
  304. //update view properties//////////////////////////////////////////////
  305. if ((newInfo.m_bSourceControl_CanWrite) && (newInfo.m_bDataIsLoaded))
  306. {
  307. if (m_gui->m_luaTextEdit->isReadOnly())
  308. {
  309. SetReadonly(false);
  310. update();
  311. }
  312. }
  313. else
  314. {
  315. // in all other cases we are waiting for more.
  316. if (!m_gui->m_luaTextEdit->isReadOnly())
  317. {
  318. SetReadonly(true);
  319. update();
  320. }
  321. }
  322. QString statusString(tr("P4:"));
  323. {
  324. // this flag goes true when a file's read-only status should be verified
  325. bool checkWriteIsWrong = false;
  326. if (newInfo.m_sourceControlInfo.m_status == AzToolsFramework::SCS_ProviderIsDown)
  327. {
  328. statusString += tr(" Unknown: P4 Down");
  329. }
  330. else if (newInfo.m_sourceControlInfo.m_status == AzToolsFramework::SCS_ProviderError)
  331. {
  332. statusString += tr(" Unknown: P4 Error");
  333. }
  334. else if (newInfo.m_sourceControlInfo.m_status == AzToolsFramework::SCS_CertificateInvalid)
  335. {
  336. statusString += tr(" Unknown: P4 SSL Certificate Invalid");
  337. }
  338. else if (newInfo.m_sourceControlInfo.m_flags & AzToolsFramework::SCF_OpenByUser)
  339. {
  340. if (newInfo.m_sourceControlInfo.m_flags & AzToolsFramework::SCF_PendingAdd)
  341. {
  342. statusString += tr(" Adding");
  343. }
  344. else if (newInfo.m_sourceControlInfo.m_flags & AzToolsFramework::SCF_PendingDelete)
  345. {
  346. statusString += tr(" Deleting");
  347. }
  348. else
  349. {
  350. QString msg = tr(" Checked Out");
  351. msg += QString(tr(" By You"));
  352. // m_StatusUser only has contents if someone other than you has this file checked out, too
  353. if (newInfo.m_sourceControlInfo.m_StatusUser.length())
  354. {
  355. msg += QString(tr(" and Others"));
  356. }
  357. statusString += msg;
  358. }
  359. }
  360. else if (newInfo.m_sourceControlInfo.m_flags & AzToolsFramework::SCF_OtherOpen)
  361. {
  362. QString msg = tr(" Checked Out");
  363. msg += QString(tr(" By ")) + newInfo.m_sourceControlInfo.m_StatusUser.c_str();
  364. statusString += msg;
  365. checkWriteIsWrong = true;
  366. }
  367. else if (!newInfo.m_sourceControlInfo.IsManaged())
  368. {
  369. statusString += tr(" Not Tracked");
  370. }
  371. else
  372. {
  373. statusString += tr(" Not Checked Out");
  374. checkWriteIsWrong = true;
  375. }
  376. if (checkWriteIsWrong)
  377. {
  378. QFileInfo fi(newInfo.m_sourceControlInfo.m_filePath.c_str());
  379. if (fi.exists() && fi.isWritable())
  380. {
  381. statusString += tr(" But Writable?");
  382. }
  383. }
  384. if ((!newInfo.m_bSourceControl_BusyRequestingEdit) && (!m_Info.m_bSourceControl_BusyGettingStats))
  385. {
  386. //remove the checking out shield
  387. if (m_pRequestingEditProgressShield)
  388. {
  389. delete m_pRequestingEditProgressShield;
  390. m_pRequestingEditProgressShield = NULL;
  391. }
  392. }
  393. }
  394. emit sourceControlStatusUpdated(statusString);
  395. //save new state
  396. m_Info = newInfo;
  397. m_gui->m_luaTextEdit->document()->setModified(modifiedValue);
  398. UpdateModifyFlag();
  399. }
  400. void LUAViewWidget::OnPlainTextFocusChanged(bool hasFocus)
  401. {
  402. if (!m_gui->m_folding || !m_gui->m_breakpoints)
  403. {
  404. return;
  405. }
  406. if (hasFocus)
  407. {
  408. m_gui->m_breakpoints->setEnabled(true);
  409. m_gui->m_folding->setEnabled(true);
  410. LUAEditorMainWindowMessages::Bus::Broadcast(&LUAEditorMainWindowMessages::Bus::Events::OnFocusInEvent, m_Info.m_assetId);
  411. }
  412. else
  413. {
  414. m_gui->m_breakpoints->setEnabled(false);
  415. m_gui->m_folding->setEnabled(false);
  416. LUAEditorMainWindowMessages::Bus::Broadcast(&LUAEditorMainWindowMessages::Bus::Events::OnFocusOutEvent, m_Info.m_assetId);
  417. }
  418. }
  419. void LUAViewWidget::RegainFocusFinal()
  420. {
  421. //AZ_TracePrintf("LUA", "RegainFocusFinal\n");
  422. show();
  423. activateWindow();
  424. setFocus(Qt::MouseFocusReason);
  425. }
  426. void LUAViewWidget::OnVisibilityChanged(bool vc)
  427. {
  428. if (vc)
  429. {
  430. if (!m_pLUADockWidget->isFloating())
  431. {
  432. RegainFocusFinal();
  433. }
  434. }
  435. }
  436. void LUAViewWidget::OnBreakpointLineMoved(int fromLineNumber, int toLineNumber)
  437. {
  438. auto breakpoint = m_Breakpoints.find(fromLineNumber);
  439. if (breakpoint != m_Breakpoints.end())
  440. {
  441. Context_DebuggerManagement::Bus::Broadcast(
  442. &Context_DebuggerManagement::Bus::Events::MoveBreakpoint, breakpoint->second.m_editorId, toLineNumber);
  443. }
  444. }
  445. void LUAViewWidget::OnBreakpointLineDeleted(int removedLineNumber)
  446. {
  447. auto breakpoint = m_Breakpoints.find(removedLineNumber);
  448. if (breakpoint != m_Breakpoints.end())
  449. {
  450. Context_DebuggerManagement::Bus::Broadcast(
  451. &Context_DebuggerManagement::Bus::Events::DeleteBreakpoint, breakpoint->second.m_editorId);
  452. }
  453. }
  454. void LUAViewWidget::modificationChanged(bool m)
  455. {
  456. Context_DocumentManagement::Bus::Broadcast(&Context_DocumentManagement::Bus::Events::NotifyDocumentModified, m_Info.m_assetId, m);
  457. UpdateModifyFlag();
  458. }
  459. void LUAViewWidget::UpdateModifyFlag() {
  460. QString displayName = QString::fromUtf8(m_Info.m_displayName.c_str());
  461. if (m_gui->m_luaTextEdit->document()->isModified())
  462. {
  463. displayName += "*";
  464. }
  465. this->luaDockWidget()->setWindowTitle(displayName);
  466. }
  467. void LUAViewWidget::UpdateCurrentExecutingLine(int lineNumber)
  468. {
  469. m_gui->m_breakpoints->SetCurrentlyExecutingLine(lineNumber);
  470. }
  471. void LUAViewWidget::UpdateCurrentEditingLine(int lineNumber)
  472. {
  473. SetCursorPosition(lineNumber, 0);
  474. }
  475. void LUAViewWidget::SyncToBreakpointLine(int line, AZ::Uuid existingID)
  476. {
  477. auto existingBreakPont = AZStd::find_if(m_Breakpoints.begin(), m_Breakpoints.end(), [&](const AZStd::pair<int, BreakpointData>& _data)
  478. {
  479. return _data.second.m_editorId == existingID;
  480. });
  481. if (existingBreakPont != m_Breakpoints.end())
  482. {
  483. m_gui->m_breakpoints->RemoveBreakpoint(existingBreakPont->first);
  484. if (existingBreakPont->first != line)
  485. {
  486. m_Breakpoints.insert(AZStd::make_pair(line, BreakpointData(existingID, line)));
  487. m_gui->m_breakpoints->AddBreakpoint(line);
  488. m_Breakpoints.erase(existingBreakPont);
  489. }
  490. }
  491. else
  492. {
  493. m_Breakpoints.insert(AZStd::make_pair(line, BreakpointData(existingID, line)));
  494. m_gui->m_breakpoints->AddBreakpoint(line);
  495. }
  496. }
  497. //////////////////////////////////////////////////////////////////////////
  498. //Debugger Messages, from the LUAEditor::LUABreakpointTrackerMessages::Bus
  499. void LUAViewWidget::BreakpointsUpdate(const LUAEditor::BreakpointMap& uniqueBreakpoints)
  500. {
  501. (void)uniqueBreakpoints;
  502. if (!m_PullRequestQueued)
  503. {
  504. QTimer::singleShot(1, this, &LUAViewWidget::PullFreshBreakpoints);
  505. m_PullRequestQueued = true;
  506. return;
  507. }
  508. }
  509. void LUAViewWidget::PullFreshBreakpoints()
  510. {
  511. m_PullRequestQueued = false;
  512. m_Breakpoints.clear();
  513. m_gui->m_breakpoints->ClearBreakpoints();
  514. const LUAEditor::BreakpointMap* myData = NULL;
  515. LUAEditor::LUABreakpointRequestMessages::Bus::BroadcastResult(
  516. myData, &LUAEditor::LUABreakpointRequestMessages::Bus::Events::RequestBreakpoints);
  517. AZ_Assert(myData, "Nobody responded to the request breakpoints message.");
  518. // and slam down a new set
  519. for (LUAEditor::BreakpointMap::const_iterator it = myData->begin(); it != myData->end(); ++it)
  520. {
  521. const LUAEditor::Breakpoint& bp = it->second;
  522. if (m_Info.m_assetName == bp.m_assetName)
  523. {
  524. SyncToBreakpointLine(bp.m_documentLine, bp.m_breakpointId);
  525. }
  526. }
  527. }
  528. void LUAViewWidget::BreakpointHit(const LUAEditor::Breakpoint& bp)
  529. {
  530. if (bp.m_assetName == this->m_Info.m_assetName)
  531. {
  532. //AZ_TracePrintf("LUA", "Matching LUAViewWidget::BreakpointHit\n");
  533. SetCursorPosition(bp.m_documentLine, 0);
  534. emit RegainFocus();
  535. }
  536. }
  537. void LUAViewWidget::BreakpointResume()
  538. {
  539. m_gui->m_breakpoints->update();
  540. }
  541. void LUAViewWidget::BreakpointToggle(int line)
  542. {
  543. auto breakpoint = m_Breakpoints.find(line);
  544. if (breakpoint == m_Breakpoints.end())
  545. {
  546. Context_DebuggerManagement::Bus::Broadcast(&Context_DebuggerManagement::Bus::Events::CreateBreakpoint, m_Info.m_assetId, line);
  547. }
  548. else
  549. {
  550. Context_DebuggerManagement::Bus::Broadcast(
  551. &Context_DebuggerManagement::Bus::Events::DeleteBreakpoint, breakpoint->second.m_editorId);
  552. }
  553. }
  554. void LUAViewWidget::keyPressEvent(QKeyEvent* ev)
  555. {
  556. if (m_gui->m_luaTextEdit->isReadOnly())
  557. {
  558. bool isUseful = false;
  559. switch (ev->key())
  560. {
  561. case Qt::Key_Return:
  562. case Qt::Key_Enter:
  563. case Qt::Key_Backspace:
  564. case Qt::Key_Delete:
  565. isUseful = true;
  566. break;
  567. }
  568. bool isModified = false;
  569. if (ev->modifiers() & (Qt::ControlModifier | Qt::AltModifier))
  570. {
  571. // every Ctrl+ key combination is "modified" except for Ctrl+V, which should cause a check-out request
  572. if (((ev->key() != Qt::Key_V) && (ev->modifiers() & Qt::ControlModifier)))
  573. {
  574. isModified = true;
  575. }
  576. }
  577. if ((!isModified) && (isascii(ev->key()) || isUseful))
  578. {
  579. QMessageBox msgBox;
  580. msgBox.setText("Checkout This File To Edit?");
  581. msgBox.setInformativeText(m_Info.m_assetName.c_str());
  582. msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
  583. msgBox.setDefaultButton(QMessageBox::Ok);
  584. msgBox.setIcon(QMessageBox::Warning);
  585. int ret = msgBox.exec();
  586. if (ret == QMessageBox::Ok)
  587. {
  588. LUAEditorMainWindowMessages::Bus::Broadcast(
  589. &LUAEditorMainWindowMessages::Bus::Events::OnRequestCheckOut, m_Info.m_assetId);
  590. }
  591. }
  592. }
  593. ev->accept();
  594. QWidget::keyPressEvent(ev);
  595. }
  596. void LUAViewWidget::dropEvent(QDropEvent* e)
  597. {
  598. if (e->mimeData()->hasUrls())
  599. {
  600. LUADockWidget* ldw = luaDockWidget();
  601. if (ldw)
  602. {
  603. if (QMainWindow* pQMainWindow = qobject_cast<QMainWindow*>(ldw->parentWidget()))
  604. {
  605. if (LUAEditorMainWindow* pLUAEditorMainWindow = qobject_cast<LUAEditorMainWindow*>(pQMainWindow->parentWidget()))
  606. {
  607. e->setDropAction(Qt::CopyAction);
  608. pLUAEditorMainWindow->dropEvent(e);
  609. e->accept();
  610. }
  611. }
  612. }
  613. }
  614. else
  615. {
  616. QWidget::dropEvent(e);
  617. }
  618. }
  619. bool LUAViewWidget::IsReadOnly() const
  620. {
  621. return m_gui->m_luaTextEdit->isReadOnly();
  622. }
  623. bool LUAViewWidget::IsModified() const
  624. {
  625. return m_gui->m_luaTextEdit->document()->isModified();
  626. }
  627. void LUAViewWidget::SelectAll()
  628. {
  629. m_gui->m_luaTextEdit->selectAll();
  630. }
  631. bool LUAViewWidget::HasSelectedText() const
  632. {
  633. return m_gui->m_luaTextEdit->textCursor().hasSelection();
  634. }
  635. void LUAViewWidget::RemoveSelectedText()
  636. {
  637. auto cursor = m_gui->m_luaTextEdit->textCursor();
  638. if (!cursor.isNull() && cursor.hasSelection())
  639. {
  640. cursor.deleteChar();
  641. }
  642. }
  643. void LUAViewWidget::ReplaceSelectedText(const QString& newText)
  644. {
  645. auto cursor = m_gui->m_luaTextEdit->textCursor();
  646. if (!cursor.isNull())
  647. {
  648. cursor.insertText(newText);
  649. }
  650. }
  651. QString LUAViewWidget::GetSelectedText() const
  652. {
  653. return m_gui->m_luaTextEdit->textCursor().selectedText();
  654. }
  655. int LUAViewWidget::CalcDocPosition(int line, int column)
  656. {
  657. // Offset line number by one, because line number starts from 1, not 0.
  658. line = line - 1;
  659. if (line < 0)
  660. {
  661. line = column = 0;
  662. }
  663. int blockCount = m_gui->m_luaTextEdit->document()->blockCount();
  664. if (line > blockCount - 1)
  665. {
  666. line = blockCount - 1;
  667. column = INT_MAX;
  668. }
  669. auto block = m_gui->m_luaTextEdit->document()->findBlockByLineNumber(line);
  670. if (!block.isValid())
  671. {
  672. return m_gui->m_luaTextEdit->document()->characterCount() - 1;
  673. }
  674. column = AZStd::max(column, 0);
  675. column = AZStd::min(column, block.length() - 1);
  676. return block.position() + column;
  677. }
  678. void LUAViewWidget::GetCursorPosition(int& line, int& column) const
  679. {
  680. auto cursor = m_gui->m_luaTextEdit->textCursor();
  681. if (cursor.isNull())
  682. {
  683. line = 0;
  684. column = 0;
  685. }
  686. else
  687. {
  688. line = cursor.blockNumber() + 1; // offset by one because line number start from 1
  689. column = cursor.positionInBlock();
  690. }
  691. }
  692. void LUAViewWidget::SetCursorPosition(int line, int column)
  693. {
  694. UpdateCursor([&](QTextCursor& cursor)
  695. {
  696. cursor.setPosition(CalcDocPosition(line, column));
  697. });
  698. }
  699. void LUAViewWidget::MoveCursor(int relativePosition)
  700. {
  701. UpdateCursor([&](QTextCursor& cursor)
  702. {
  703. cursor.movePosition(relativePosition > 0 ? QTextCursor::MoveOperation::Right : QTextCursor::MoveOperation::Left,
  704. QTextCursor::MoveMode::MoveAnchor, abs(relativePosition));
  705. });
  706. }
  707. LUAViewWidget::FindOperation LUAViewWidget::FindFirst(const QString& searchString, bool isRegularExpression, bool isCaseSensitiveSearch, bool wholeWord, bool wrap, bool searchDown) const
  708. {
  709. FindOperation start(aznew FindOperationImpl);
  710. start.m_impl->m_cursor = m_gui->m_luaTextEdit->textCursor();
  711. start.m_impl->m_searchString = searchString;
  712. start.m_impl->m_isRegularExpression = isRegularExpression;
  713. start.m_impl->m_isCaseSensitiveSearch = isCaseSensitiveSearch;
  714. start.m_impl->m_wholeWord = wholeWord;
  715. start.m_impl->m_wrap = wrap;
  716. start.m_impl->m_searchDown = searchDown;
  717. FindNext(start);
  718. return start;
  719. }
  720. void LUAViewWidget::FindNext(FindOperation& operation) const
  721. {
  722. if (!operation)
  723. {
  724. return;
  725. }
  726. int flags = 0;
  727. if (operation.m_impl->m_wholeWord)
  728. {
  729. flags |= QTextDocument::FindFlag::FindWholeWords;
  730. }
  731. if (operation.m_impl->m_isCaseSensitiveSearch)
  732. {
  733. flags |= QTextDocument::FindFlag::FindCaseSensitively;
  734. }
  735. if (!operation.m_impl->m_searchDown)
  736. {
  737. flags |= QTextDocument::FindFlag::FindBackward;
  738. }
  739. if (operation.m_impl->m_isRegularExpression)
  740. {
  741. QRegExp regEx;
  742. regEx.setCaseSensitivity(operation.m_impl->m_isCaseSensitiveSearch ? Qt::CaseSensitivity::CaseSensitive : Qt::CaseSensitivity::CaseInsensitive);
  743. regEx.setPattern(operation.m_impl->m_searchString);
  744. operation.m_impl->m_cursor = m_gui->m_luaTextEdit->document()->find(regEx, operation.m_impl->m_cursor, static_cast<QTextDocument::FindFlag>(flags));
  745. if (!operation && operation.m_impl->m_wrap)
  746. {
  747. if (operation.m_impl->m_searchDown)
  748. {
  749. operation.m_impl->m_cursor.setPosition(0);
  750. }
  751. else
  752. {
  753. operation.m_impl->m_cursor.setPosition(m_gui->m_luaTextEdit->document()->characterCount() - 1);
  754. }
  755. operation.m_impl->m_cursor = m_gui->m_luaTextEdit->document()->find(regEx, operation.m_impl->m_cursor, static_cast<QTextDocument::FindFlag>(flags));
  756. }
  757. }
  758. else
  759. {
  760. operation.m_impl->m_cursor = m_gui->m_luaTextEdit->document()->find(operation.m_impl->m_searchString, operation.m_impl->m_cursor, static_cast<QTextDocument::FindFlag>(flags));
  761. if (!operation && operation.m_impl->m_wrap)
  762. {
  763. if (operation.m_impl->m_searchDown)
  764. {
  765. operation.m_impl->m_cursor.setPosition(0);
  766. }
  767. else
  768. {
  769. operation.m_impl->m_cursor.setPosition(m_gui->m_luaTextEdit->document()->characterCount() - 1);
  770. }
  771. operation.m_impl->m_cursor = m_gui->m_luaTextEdit->document()->find(operation.m_impl->m_searchString, operation.m_impl->m_cursor, static_cast<QTextDocument::FindFlag>(flags));
  772. }
  773. }
  774. if (operation)
  775. {
  776. m_gui->m_luaTextEdit->setTextCursor(operation.m_impl->m_cursor);
  777. }
  778. }
  779. QString LUAViewWidget::GetLineText(int line) const
  780. {
  781. auto block = m_gui->m_luaTextEdit->document()->findBlockByLineNumber(line);
  782. return block.text();
  783. }
  784. bool LUAViewWidget::GetSelection(int& lineStart, int& columnStart, int& lineEnd, int& columnEnd) const
  785. {
  786. auto doc = m_gui->m_luaTextEdit->document();
  787. auto cursor = m_gui->m_luaTextEdit->textCursor();
  788. if (cursor.isNull())
  789. {
  790. lineStart = columnStart = lineEnd = columnEnd = -1;
  791. return false;
  792. }
  793. auto startPos = cursor.selectionStart();
  794. auto endPos = cursor.selectionEnd();
  795. auto startBlock = doc->findBlock(startPos);
  796. lineStart = startBlock.blockNumber();
  797. columnStart = startPos - startBlock.position();
  798. auto endBlock = doc->findBlock(endPos);
  799. lineEnd = endBlock.blockNumber();
  800. columnEnd = endPos - endBlock.position();
  801. return true;
  802. }
  803. void LUAViewWidget::SetSelection(int lineStart, int columnStart, int lineEnd, int columnEnd)
  804. {
  805. auto startPos = CalcDocPosition(lineStart, columnStart);
  806. auto endPos = CalcDocPosition(lineEnd, columnEnd);
  807. UpdateCursor([&](QTextCursor& cursor)
  808. {
  809. // Go back to front to keep cursor position consistent
  810. cursor.setPosition(endPos);
  811. cursor.setPosition(startPos, QTextCursor::MoveMode::KeepAnchor);
  812. });
  813. }
  814. QString LUAViewWidget::GetText()
  815. {
  816. return m_gui->m_luaTextEdit->toPlainText();
  817. }
  818. void LUAViewWidget::Cut()
  819. {
  820. m_gui->m_luaTextEdit->cut();
  821. }
  822. void LUAViewWidget::Copy()
  823. {
  824. m_gui->m_luaTextEdit->copy();
  825. }
  826. template<typename Callable>
  827. //callabe sig (QString&, QTextBlock&)
  828. QString LUAViewWidget::AcumulateSelectedLines(int& startLine, int& endLine, Callable callable)
  829. {
  830. int startColumn;
  831. int endColumn;
  832. GetSelection(startLine, startColumn, endLine, endColumn);
  833. AZ_Assert(startLine <= endLine, "assume selection is always forward");
  834. auto cursor = m_gui->m_luaTextEdit->textCursor();
  835. QString newText;
  836. for (int i = startLine; i <= endLine; ++i)
  837. {
  838. auto block = m_gui->m_luaTextEdit->document()->findBlockByNumber(i);
  839. if (block.isValid())
  840. {
  841. callable(newText, block);
  842. }
  843. }
  844. return newText;
  845. }
  846. template<typename Callable>
  847. void LUAViewWidget::CommentHelper(Callable callable)
  848. {
  849. int startLine;
  850. int endLine;
  851. auto newText = AcumulateSelectedLines(startLine, endLine, callable);
  852. SetSelection(startLine + 1, 0, endLine + 2, 0);
  853. RemoveSelectedText();
  854. SetCursorPosition(startLine + 1, 0);
  855. ReplaceSelectedText(newText);
  856. SetSelection(startLine + 1, 0, endLine + 1, INT_MAX);
  857. }
  858. void LUAViewWidget::CommentSelectedLines()
  859. {
  860. CommentHelper([&](QString& newText, QTextBlock& block)
  861. {
  862. newText.append("-- ");
  863. newText.append(block.text());
  864. newText.append("\n");
  865. });
  866. }
  867. void LUAViewWidget::UncommentSelectedLines()
  868. {
  869. CommentHelper([&](QString& newText, QTextBlock& block)
  870. {
  871. auto blockText = block.text();
  872. if (blockText.startsWith("--"))
  873. {
  874. int removeCount = 2;
  875. if (blockText.at(2).isSpace())
  876. {
  877. ++removeCount;
  878. }
  879. blockText.remove(0, removeCount);
  880. }
  881. newText.append(blockText);
  882. newText.append("\n");
  883. });
  884. }
  885. void LUAViewWidget::MoveSelectedLinesUp()
  886. {
  887. int startLine;
  888. int endLine;
  889. auto currText = AcumulateSelectedLines(startLine, endLine, [&](QString& newText, QTextBlock& block)
  890. {
  891. newText.append(block.text());
  892. newText.append("\n");
  893. });
  894. currText.remove(currText.count() - 1, 1);
  895. if (startLine == 0)
  896. {
  897. return;
  898. }
  899. auto upText = GetLineText(startLine -1);
  900. SetSelection(startLine, 0, startLine, INT_MAX);
  901. RemoveSelectedText();
  902. SetSelection(startLine + 1, 0, endLine + 1, INT_MAX);
  903. RemoveSelectedText();
  904. SetCursorPosition(startLine , 0);
  905. ReplaceSelectedText(currText);
  906. SetCursorPosition(endLine + 1, 0);
  907. ReplaceSelectedText(upText);
  908. SetSelection(startLine, 0, endLine, INT_MAX);
  909. }
  910. void LUAViewWidget::MoveSelectedLinesDn()
  911. {
  912. int startLine;
  913. int endLine;
  914. auto newText = AcumulateSelectedLines(startLine, endLine, [&](QString& newText, QTextBlock& block)
  915. {
  916. newText.append(block.text());
  917. newText.append("\n");
  918. });
  919. if (endLine == m_gui->m_luaTextEdit->document()->blockCount() - 1)
  920. {
  921. return;
  922. }
  923. //hack if we are going to be the new last line
  924. if (endLine == m_gui->m_luaTextEdit->document()->blockCount() - 2)
  925. {
  926. newText.remove(newText.length() - 1, 1);
  927. newText.prepend("\n");
  928. }
  929. SetSelection(startLine + 1, 0, endLine + 2, 0);
  930. RemoveSelectedText();
  931. SetCursorPosition(startLine + 2, 0);
  932. ReplaceSelectedText(newText);
  933. SetSelection(startLine + 2, 0, endLine + 2, INT_MAX);
  934. }
  935. void LUAViewWidget::SetReadonly(bool readonly)
  936. {
  937. m_gui->m_luaTextEdit->setReadOnly(readonly);
  938. m_gui->m_luaTextEdit->style()->unpolish(m_gui->m_luaTextEdit);
  939. m_gui->m_luaTextEdit->style()->polish(m_gui->m_luaTextEdit);
  940. if (readonly)
  941. {
  942. // For readonly documents we set the TextSelectableByKeyboard to display a solid cursor.
  943. m_gui->m_luaTextEdit->setTextInteractionFlags(m_gui->m_luaTextEdit->textInteractionFlags() | Qt::TextSelectableByKeyboard);
  944. }
  945. }
  946. template<typename Callable>
  947. void LUAViewWidget::FindMatchingBrace(Callable callable)
  948. {
  949. auto doc = m_gui->m_luaTextEdit->document();
  950. auto cursor = m_gui->m_luaTextEdit->textCursor();
  951. int bracePos = cursor.position();
  952. QChar braceChar {
  953. QChar::Null
  954. };
  955. bool openingBrace {
  956. true
  957. };
  958. auto detect = [&]()
  959. {
  960. auto testChar = doc->characterAt(bracePos);
  961. if (testChar == '{' || testChar == '[' || testChar == '(')
  962. {
  963. braceChar = testChar;
  964. openingBrace = true;
  965. }
  966. if (testChar == '}' || testChar == ']' || testChar == ')')
  967. {
  968. braceChar = testChar;
  969. openingBrace = false;
  970. }
  971. };
  972. detect();
  973. if (braceChar == QChar::Null && bracePos > 0) //try previous char too so we can detect on either side of brace
  974. {
  975. --bracePos;
  976. detect();
  977. }
  978. if (braceChar != QChar::Null) //found one
  979. {
  980. int startPos = bracePos;
  981. QChar endChar {
  982. QChar::Null
  983. };
  984. if (braceChar == '{')
  985. {
  986. endChar = '}';
  987. }
  988. if (braceChar == '}')
  989. {
  990. endChar = '{';
  991. }
  992. if (braceChar == '[')
  993. {
  994. endChar = ']';
  995. }
  996. if (braceChar == ']')
  997. {
  998. endChar = '[';
  999. }
  1000. if (braceChar == '(')
  1001. {
  1002. endChar = ')';
  1003. }
  1004. if (braceChar == ')')
  1005. {
  1006. endChar = '(';
  1007. }
  1008. int step {
  1009. openingBrace ? 1 : -1
  1010. };
  1011. int level {
  1012. 0
  1013. };
  1014. bracePos += step;
  1015. auto testChar = doc->characterAt(bracePos);
  1016. while (testChar != QChar::Null)
  1017. {
  1018. if (testChar == braceChar)
  1019. {
  1020. ++level;
  1021. }
  1022. else if (testChar == endChar)
  1023. {
  1024. --level;
  1025. if (level < 0)
  1026. {
  1027. if (step > 0)
  1028. {
  1029. ++bracePos;
  1030. }
  1031. else
  1032. {
  1033. ++startPos;
  1034. }
  1035. callable(startPos, bracePos);
  1036. return;
  1037. }
  1038. }
  1039. bracePos += step;
  1040. testChar = doc->characterAt(bracePos);
  1041. }
  1042. callable(startPos, -1); //had an opening brace, but no matching close brace
  1043. }
  1044. }
  1045. void LUAViewWidget::SelectToMatchingBrace()
  1046. {
  1047. auto cursor = m_gui->m_luaTextEdit->textCursor();
  1048. FindMatchingBrace([&](int startPos, int endPos)
  1049. {
  1050. if (endPos >= 0)
  1051. {
  1052. cursor.setPosition(startPos);
  1053. cursor.setPosition(endPos, QTextCursor::MoveMode::KeepAnchor);
  1054. m_gui->m_luaTextEdit->setTextCursor(cursor);
  1055. }
  1056. });
  1057. }
  1058. void LUAViewWidget::UpdateBraceHighlight()
  1059. {
  1060. m_Highlighter->SetBracketHighlighting(-1, -1);
  1061. FindMatchingBrace([&](int startPos, int endPos)
  1062. {
  1063. if (endPos > 0 && endPos < startPos)
  1064. {
  1065. AZStd::swap(startPos, endPos);
  1066. }
  1067. m_Highlighter->SetBracketHighlighting(startPos, endPos - 1);
  1068. });
  1069. auto cursor = m_gui->m_luaTextEdit->textCursor();
  1070. auto text = m_gui->m_luaTextEdit->document()->toPlainText();
  1071. m_gui->m_luaTextEdit->setExtraSelections(m_Highlighter->HighlightMatchingNames(cursor, text));
  1072. m_gui->m_luaTextEdit->update();
  1073. }
  1074. void LUAViewWidget::focusInEvent(QFocusEvent* pEvent)
  1075. {
  1076. QWidget::focusInEvent(pEvent);
  1077. m_gui->m_luaTextEdit->setFocus();
  1078. }
  1079. void LUAViewWidget::FoldAll()
  1080. {
  1081. m_gui->m_folding->FoldAll();
  1082. }
  1083. void LUAViewWidget::UnfoldAll()
  1084. {
  1085. m_gui->m_folding->UnfoldAll();
  1086. }
  1087. void LUAViewWidget::UpdateFont()
  1088. {
  1089. auto syntaxSettings = AZ::UserSettings::CreateFind<SyntaxStyleSettings>(AZ_CRC_CE("LUA Editor Text Settings"), AZ::UserSettings::CT_GLOBAL);
  1090. syntaxSettings->SetZoomPercent(m_zoomPercent);
  1091. const auto& font = syntaxSettings->GetFont();
  1092. m_gui->m_luaTextEdit->SetTabSize(syntaxSettings->GetTabSize());
  1093. m_gui->m_luaTextEdit->SetUseSpaces(syntaxSettings->UseSpacesInsteadOfTabs());
  1094. m_gui->m_luaTextEdit->UpdateFont(font, syntaxSettings->GetTabSize());
  1095. m_gui->m_breakpoints->SetFont(font);
  1096. m_gui->m_folding->SetFont(font);
  1097. m_gui->m_luaTextEdit->update();
  1098. m_gui->m_breakpoints->update();
  1099. m_gui->m_folding->update();
  1100. m_Highlighter->rehighlight();
  1101. CreateStyleSheet();
  1102. m_gui->m_luaTextEdit->repaint();
  1103. }
  1104. void LUAViewWidget::OnZoomIn()
  1105. {
  1106. m_zoomPercent = AZStd::min(m_zoomPercent + m_zoomPercent / 5, 500);
  1107. UpdateFont();
  1108. }
  1109. void LUAViewWidget::OnZoomOut()
  1110. {
  1111. m_zoomPercent = AZStd::max(m_zoomPercent - m_zoomPercent / 5, 50);
  1112. UpdateFont();
  1113. }
  1114. void LUAViewWidget::ResetZoom()
  1115. {
  1116. m_zoomPercent = 100;
  1117. UpdateFont();
  1118. }
  1119. }