|
24 | 24 |
|
25 | 25 | #include <fstream> |
26 | 26 | #include <memory> |
| 27 | +#include <algorithm> |
27 | 28 | #include <sstream> |
28 | 29 | #include <iostream> |
29 | 30 | using std::cerr; |
@@ -88,6 +89,7 @@ static std::string s_registerMessage; |
88 | 89 | #include "comm/RunMgmt.H" |
89 | 90 |
|
90 | 91 | #include "wxgui/ewxProgressDialog.H" |
| 92 | +#include <wx/wupdlock.h> |
91 | 93 | #include "wxgui/EcceTool.H" |
92 | 94 | #include "wxgui/ewxWindowUtils.H" |
93 | 95 | #include "wxgui/ewxBitmap.H" |
@@ -409,6 +411,11 @@ bool CalcMgr::Create( wxWindow* parent, wxWindowID id, const wxString& caption, |
409 | 411 | * new <parent url> <type> |
410 | 412 | * File > New with resource type <type> (gromacs_md_study, |
411 | 413 | * gromacs_md_energy) in <parent>, as the New menu makes it |
| 414 | + * counts broker notices, the updates made for them and their |
| 415 | + * batches since the last counts |
| 416 | + * newprompt <parent url> <code> |
| 417 | + * File > New <code> Calculation with the name prompt, |
| 418 | + * answered OK after 1.5 s |
412 | 419 | * contextmenu <url> right-click <url> in the tree; the New submenu's items |
413 | 420 | */ |
414 | 421 | void CalcMgr::runTestCommand(const string& line) |
@@ -646,6 +653,44 @@ void CalcMgr::runTestCommand(const string& line) |
646 | 653 | } else if (command == "tail-close") { |
647 | 654 | if (p_testTail) p_testTail->Close(); |
648 | 655 | outcome = "ok"; |
| 656 | + } else if (command == "counts") { |
| 657 | + // Broker notices received, tree/summary updates made for them, and |
| 658 | + // the batches they came in, since the last "counts". |
| 659 | + outcome = "notices=" + std::to_string(p_testNotices) + |
| 660 | + " applied=" + std::to_string(p_testApplied) + |
| 661 | + " batches=" + std::to_string(p_testBatches); |
| 662 | + p_testNotices = p_testApplied = p_testBatches = 0; |
| 663 | + } else if (command == "newprompt") { |
| 664 | + // "newprompt PARENT-URL CODE": File > New <code> Calculation with the |
| 665 | + // name prompt, as the menu does it (disabler included); the prompt is |
| 666 | + // answered OK after 1.5 s. |
| 667 | + std::istringstream args(calcName); |
| 668 | + string parentUrl, code; |
| 669 | + args >> parentUrl >> code; |
| 670 | + ResourceType *rt = ResourceDescriptor::getResourceDescriptor() |
| 671 | + .getResourceType("virtual_document", "ecceCalculation", code); |
| 672 | + WxResourceTreeItemData *parentNode = findNode(EcceURL(parentUrl), |
| 673 | + true, true); |
| 674 | + if (!rt || !parentNode) { |
| 675 | + outcome = !rt ? "no resource type " + code : "no parent node"; |
| 676 | + } else { |
| 677 | + wxTimer answer; |
| 678 | + answer.Bind(wxEVT_TIMER, [](wxTimerEvent&) { |
| 679 | + for (wxWindowList::compatibility_iterator n = |
| 680 | + wxTopLevelWindows.GetFirst(); n; n = n->GetNext()) { |
| 681 | + wxDialog *d = dynamic_cast<wxDialog*>(n->GetData()); |
| 682 | + if (d && d->IsModal()) d->EndModal(wxID_OK); |
| 683 | + } |
| 684 | + }); |
| 685 | + answer.StartOnce(1500); |
| 686 | + bool ask = GetMenuBar()->IsChecked(wxID_ASKFORNAME); |
| 687 | + GetMenuBar()->Check(wxID_ASKFORNAME, true); |
| 688 | + startDisabler(); |
| 689 | + createResource(rt, parentNode, false); |
| 690 | + stopDisabler(); |
| 691 | + GetMenuBar()->Check(wxID_ASKFORNAME, ask); |
| 692 | + outcome = "ok"; |
| 693 | + } |
649 | 694 | } else if (command == "start") { |
650 | 695 | // "start TOOL [URL]": what a tool button does (startApp), e.g. |
651 | 696 | // "start CalculationEditor <calc url>". |
@@ -5213,7 +5258,18 @@ void CalcMgr::createResource(ResourceType * resType, |
5213 | 5258 | infoStr = invalidMsg + infoStr; |
5214 | 5259 | ewxTextEntryDialog dialog(this, infoStr, "New " + name + " Name", |
5215 | 5260 | name, wxOK | wxCANCEL); |
5216 | | - if (dialog.ShowModal() == wxID_OK) { |
| 5261 | + // The dialog disables the windows itself. Left disabled by |
| 5262 | + // startDisabler(), the Organizer cannot take the activation back when |
| 5263 | + // the dialog closes, and on MSW the window behind it (another |
| 5264 | + // program) comes to the front. |
| 5265 | + const bool paused = p_disabler != 0; |
| 5266 | + if (paused) { |
| 5267 | + delete p_disabler; |
| 5268 | + p_disabler = 0; |
| 5269 | + } |
| 5270 | + const int answer = dialog.ShowModal(); |
| 5271 | + if (paused) p_disabler = new wxWindowDisabler; |
| 5272 | + if (answer == wxID_OK) { |
5217 | 5273 | name = dialog.GetValue(); |
5218 | 5274 | if (resType->isValidResourceName(name)) |
5219 | 5275 | break; |
@@ -5441,6 +5497,44 @@ void CalcMgr::updateUrl(const EcceURL & url) |
5441 | 5497 | } |
5442 | 5498 |
|
5443 | 5499 |
|
| 5500 | +void CalcMgr::queueUpdate(UpdateKind kind, const EcceURL & url) |
| 5501 | +{ |
| 5502 | + p_testNotices++; |
| 5503 | + std::pair<UpdateKind, string> item(kind, url.toString()); |
| 5504 | + // A repeated change notice adds nothing; additions and removals keep |
| 5505 | + // their order, only an immediate repeat is dropped. |
| 5506 | + bool dup = kind == UPDATE_CHANGED |
| 5507 | + ? std::find(p_queuedUpdates.begin(), p_queuedUpdates.end(), item) != |
| 5508 | + p_queuedUpdates.end() |
| 5509 | + : !p_queuedUpdates.empty() && p_queuedUpdates.back() == item; |
| 5510 | + if (!dup) p_queuedUpdates.push_back(item); |
| 5511 | + if (!p_updateTimer) { |
| 5512 | + p_updateTimer = new wxTimer(this); |
| 5513 | + Bind(wxEVT_TIMER, [this](wxTimerEvent&) { applyQueuedUpdates(); }, |
| 5514 | + p_updateTimer->GetId()); |
| 5515 | + } |
| 5516 | + // The notices of one Save arrive within a few ms of each other. |
| 5517 | + if (!p_updateTimer->IsRunning()) p_updateTimer->StartOnce(150); |
| 5518 | +} |
| 5519 | + |
| 5520 | + |
| 5521 | +void CalcMgr::applyQueuedUpdates() |
| 5522 | +{ |
| 5523 | + std::vector<std::pair<UpdateKind, string> > todo; |
| 5524 | + todo.swap(p_queuedUpdates); |
| 5525 | + if (todo.empty()) return; |
| 5526 | + p_testBatches++; |
| 5527 | + wxWindowUpdateLocker freeze(this); |
| 5528 | + for (size_t i = 0; i < todo.size(); i++) { |
| 5529 | + p_testApplied++; |
| 5530 | + EcceURL url(todo[i].second); |
| 5531 | + if (todo[i].first == UPDATE_ADDED) updateAddNode(url); |
| 5532 | + else if (todo[i].first == UPDATE_REMOVED) updateRemoveNode(url); |
| 5533 | + else updateUrl(url); |
| 5534 | + } |
| 5535 | +} |
| 5536 | + |
| 5537 | + |
5444 | 5538 | /** |
5445 | 5539 | * Refresh the context panel and tree ctrl when the resource associated with |
5446 | 5540 | * the URL got added |
|
0 commit comments