///|
priv struct PendingPdf {
window : Int64
view : Int64?
request : Int32
path : String
completion : Completion[Result[Unit, WindowSessionError]]
}
///|
priv struct PdfCompletionStore {
pending : Array[PendingPdf]
}
///|
fn PdfCompletionStore::PdfCompletionStore() -> PdfCompletionStore {
{ pending: [], }
}
///|
fn PendingPdf::fail(self : PendingPdf, detail : String) -> Unit {
self.completion.finish(
Err(
window_operation_failed(
"print PDF to " + self.path,
@native.NativeError::Status(status=-6, message=detail),
),
),
)
}
///|
// None selects all windows; a selected window with no view selects its children
// too. Renderer termination is routed separately to the exact page below.
fn PdfCompletionStore::fail(
self : PdfCompletionStore,
window : Int64?,
view : Int64?,
detail : String,
) -> Unit {
for pending in self.pending {
if (window is None || window == Some(pending.window)) &&
(view is None || view == pending.view) {
pending.fail(detail)
}
}
}
///|
fn PdfCompletionStore::route(
self : PdfCompletionStore,
event : @native.RuntimeEvent,
) -> Bool {
if event.pdf_print_result() is Some(result) {
if event.window_id() is Some(window) {
self.complete(window, event.view_id(), result)
}
// A cancelled waiter has already unregistered; discard its late completion.
return true
}
if event.is_window_closed() || event.is_view_closed() {
if event.window_id() is Some(window) {
self.fail(Some(window), event.view_id(), "page has closed")
}
} else if event.renderer_process_termination() is Some(_) {
for pending in self.pending {
if event.window_id() == Some(pending.window) &&
event.view_id() == pending.view {
pending.fail("renderer process has terminated")
}
}
}
false
}
///|
async fn PdfCompletionStore::wait(
self : PdfCompletionStore,
window : Int64,
view : Int64?,
request : Int32,
path : String,
) -> Unit {
let pending : PendingPdf = {
window,
view,
request,
path,
completion: Completion(),
}
self.pending.push(pending)
defer (for index, candidate in self.pending {
if physical_equal(candidate, pending) {
ignore(self.pending.remove(index))
break
}
})
match pending.completion.wait() {
Ok(_) => ()
Err(error) => raise error
}
}
///|
fn PdfCompletionStore::complete(
self : PdfCompletionStore,
window : Int64,
view : Int64?,
result : @native.NativePdfPrintResult,
) -> Unit {
for pending in self.pending {
if window == pending.window &&
view == pending.view &&
result.request_id == pending.request {
if result.success {
pending.completion.finish(Ok(()))
} else {
pending.fail("CEF could not write the PDF")
}
return
}
}
}