Using IProgressEventHandler to Report Progress When Saving a File
📌 Overview
This article explains how to use the new IProgressEventHandler
API to report progress when saving a file in Mako. It also compares this new event-based mechanism with the existing tick-based IProgressTick
approach, described in Progress Monitoring in Mako, which is commonly used for progress reporting in custom transforms.
ℹ️ Key Concepts: IProgressEventHandler vs IProgressTick
Feature | IProgressTick | IProgressEventHandler |
---|---|---|
Reporting Style | Tick-based (integer/float increments) | Event-based (specific operation events) |
Typical Use | Custom transforms | Saving files |
Callback Signature |
|
|
Events Supported | None (just ticks) | Page write start/end, node write start/end |
Integration |
|
|
Granularity | Coarse (progress bar style) | Fine (event-driven, detailed) |
💪 Usage
Use IProgressTick for simple, linear progress reporting (e.g., custom transforms where only a percentage or tick count is needed).
Use IProgressEventHandler for more detailed, event-driven reporting (e.g., when you want to track the start/end of pages or nodes during file save operations).
⌨️ Code Examples
1. Tick-Based Progress Reporting with IProgressTick - extract from ProgressMonitoring.cpp.
class ProgressHandler {
public:
// This section should be customised
explicit ProgressHandler(std::string info = "") : m_info(std::move(info)), m_tickCount(0) {}
void tick(uint32_t currentCount, uint32_t maxCount) {
m_tickCount++;
printf("%s : %d\n", m_info.c_str(), m_tickCount);
fflush(stdout);
}
// Everything below this part can be reused
static std::shared_ptr<ProgressHandler> create(const std::string& info) {
std::shared_ptr<ProgressHandler> progressHandler = std::make_shared<ProgressHandler>(info);
progressHandler->m_progressTick = IProgressTick::create(callbackInt, progressHandler.get());
return progressHandler;
}
protected:
static void callbackInt(void* priv, uint32_t currentCount, uint32_t maxCount) {
ProgressHandler* progressHandler = (ProgressHandler*)priv;
progressHandler->tick(currentCount, maxCount);
}
private:
std::string m_info;
int m_tickCount;
IProgressTickPtr m_progressTick;
};
2. Event-Based Progress Reporting with IProgressEventHandler - extract from ProgressEventHandling.cpp
class ProgressEventHandler {
public:
// This section should be customised
ProgressEventHandler() : m_pageCount(0), m_nodeCount(0), m_nodeDepth(0) {}
void handleEvent(IProgressEventHandler::Event evt) {
int id;
switch (evt) {
case IProgressEventHandler::eEvtPageWriteStart:
m_pageCount++;
m_nodeCount = 0;
m_nodeDepth = 0;
m_nodes.clear();
printf("start of page %d\n", m_pageCount);
break;
case IProgressEventHandler::eEvtPageWriteEnd:
printf("end of page %d, got %d node events\n", m_pageCount, m_nodeCount);
if (m_nodeDepth != 0) printf("mismatch in node write start/end %d\n", m_nodeDepth);
break;
case IProgressEventHandler::eEvtNodeWriteStart:
id = ++m_nodeCount;
m_nodeDepth++;
m_nodes.push_back(id);
if (id % 500 == 0) {
printf("start of node %d\n", id);
}
break;
case IProgressEventHandler::eEvtNodeWriteEnd:
m_nodeDepth--;
if (m_nodes.empty())
printf("mismatch, empty nodes\n");
else {
id = m_nodes.back();
m_nodes.pop_back();
if (id % 500 == 0) {
printf("end of node %d\n", id);
}
}
break;
default:
break;
}
}
// Everything below this part can be reused
static std::shared_ptr<ProgressEventHandler> create() {
std::shared_ptr<ProgressEventHandler> progressEventHandler = std::make_shared<ProgressEventHandler>();
progressEventHandler->m_progressEventHandler = IProgressEventHandler::create(callback, progressEventHandler.get());
return progressEventHandler;
}
int m_pageCount;
int m_nodeCount;
int m_nodeDepth;
std::deque<int> m_nodes;
IProgressEventHandlerPtr m_progressEventHandler;
protected:
static void callback(void* priv, IProgressEventHandler::Event evt) {
ProgressEventHandler* progressEventHandler = (ProgressEventHandler*)priv;
if (progressEventHandler)
progressEventHandler->handleEvent(evt);
}
};
Integration Example: Saving a File with Progress Events
// Create a progress monitor and set the event handler
IProgressMonitorPtr monitor = IProgressMonitor::create(IAbortPtr());
auto handler = ProgressEventHandler::create();
monitor->setProgressEventHandler(handler->m_progressEventHandler);
// Pass the monitor to IOutput::create() when saving a file
IOutputPtr output = IOutput::create(..., monitor, ...);
☑️ Conclusion
The IProgressEventHandler
API provides a more flexible and granular way to report progress when saving files. For legacy or simple scenarios, IProgressTick
remains available. Choose the mechanism that best fits your reporting needs.
📚 Additional Resources
If you need additional help, see our API documentation for detailed information on class/method usage, or raise a support ticket via our customer portal.