1use std::ptr;
2
3use crate::destination::PdfDestination;
4use crate::document::PdfDocument;
5use crate::error::Result;
6use crate::ffi;
7use crate::handle::ObjectHandle;
8use crate::page::PdfPage;
9use crate::page_overlay_view_provider::PdfPageOverlayViewProviderHandle;
10use crate::selection::PdfSelection;
11use crate::types::{
12 DisplayBox, PdfAreaOfInterest, PdfDisplayDirection, PdfDisplayMode, PdfPoint, PdfSize,
13 PdfViewInfo,
14};
15use crate::util::parse_json;
16use crate::view_delegate::PdfViewDelegateHandle;
17
18#[derive(Debug, Clone)]
20pub struct PdfView {
21 handle: ObjectHandle,
22}
23
24impl PdfView {
25 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
26 Self { handle }
27 }
28
29 pub fn new(size: PdfSize) -> Result<Self> {
31 let mut out_view = ptr::null_mut();
32 let mut out_error = ptr::null_mut();
33 let status =
34 unsafe { ffi::pdf_view_new(size.width, size.height, &mut out_view, &mut out_error) };
35 crate::util::status_result(status, out_error)?;
36 Ok(Self::from_handle(crate::util::required_handle(
37 out_view, "PDFView",
38 )?))
39 }
40
41 pub fn info(&self) -> Result<PdfViewInfo> {
43 parse_json(
44 unsafe { ffi::pdf_view_info_json(self.handle.as_ptr()) },
45 "PDFView",
46 )
47 }
48
49 #[must_use]
51 pub fn document(&self) -> Option<PdfDocument> {
52 let ptr = unsafe { ffi::pdf_view_document(self.handle.as_ptr()) };
53 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfDocument::from_handle)
54 }
55
56 pub fn set_document(&self, document: Option<&PdfDocument>) -> Result<()> {
58 let mut out_error = ptr::null_mut();
59 let status = unsafe {
60 ffi::pdf_view_set_document(
61 self.handle.as_ptr(),
62 document.map_or(ptr::null_mut(), PdfDocument::as_handle_ptr),
63 &mut out_error,
64 )
65 };
66 crate::util::status_result(status, out_error)
67 }
68
69 pub fn set_delegate(&self, delegate: Option<&PdfViewDelegateHandle>) -> Result<()> {
71 let mut out_error = ptr::null_mut();
72 let status = unsafe {
73 ffi::pdf_view_set_delegate(
74 self.handle.as_ptr(),
75 delegate.map_or(ptr::null_mut(), PdfViewDelegateHandle::as_handle_ptr),
76 &mut out_error,
77 )
78 };
79 crate::util::status_result(status, out_error)
80 }
81
82 pub fn set_page_overlay_view_provider(
84 &self,
85 provider: Option<&PdfPageOverlayViewProviderHandle>,
86 ) -> Result<()> {
87 let mut out_error = ptr::null_mut();
88 let status = unsafe {
89 ffi::pdf_view_set_page_overlay_view_provider(
90 self.handle.as_ptr(),
91 provider.map_or(
92 ptr::null_mut(),
93 PdfPageOverlayViewProviderHandle::as_handle_ptr,
94 ),
95 &mut out_error,
96 )
97 };
98 crate::util::status_result(status, out_error)
99 }
100
101 #[must_use]
103 pub fn current_page(&self) -> Option<PdfPage> {
104 let ptr = unsafe { ffi::pdf_view_current_page(self.handle.as_ptr()) };
105 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfPage::from_handle)
106 }
107
108 #[must_use]
110 pub fn current_destination(&self) -> Option<PdfDestination> {
111 let ptr = unsafe { ffi::pdf_view_current_destination(self.handle.as_ptr()) };
112 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfDestination::from_handle)
113 }
114
115 #[must_use]
117 pub fn current_selection(&self) -> Option<PdfSelection> {
118 let ptr = unsafe { ffi::pdf_view_current_selection(self.handle.as_ptr()) };
119 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfSelection::from_handle)
120 }
121
122 pub fn set_current_selection(
124 &self,
125 selection: Option<&PdfSelection>,
126 animate: bool,
127 ) -> Result<()> {
128 let mut out_error = ptr::null_mut();
129 let status = unsafe {
130 ffi::pdf_view_set_current_selection(
131 self.handle.as_ptr(),
132 selection.map_or(ptr::null_mut(), PdfSelection::as_handle_ptr),
133 i32::from(animate),
134 &mut out_error,
135 )
136 };
137 crate::util::status_result(status, out_error)
138 }
139
140 pub fn clear_selection(&self) {
142 unsafe { ffi::pdf_view_clear_selection(self.handle.as_ptr()) };
143 }
144
145 pub fn go_to_page(&self, page: &PdfPage) -> Result<()> {
147 let mut out_error = ptr::null_mut();
148 let status = unsafe {
149 ffi::pdf_view_go_to_page(self.handle.as_ptr(), page.as_handle_ptr(), &mut out_error)
150 };
151 crate::util::status_result(status, out_error)
152 }
153
154 pub fn go_to_destination(&self, destination: &PdfDestination) -> Result<()> {
156 let mut out_error = ptr::null_mut();
157 let status = unsafe {
158 ffi::pdf_view_go_to_destination(
159 self.handle.as_ptr(),
160 destination.as_handle_ptr(),
161 &mut out_error,
162 )
163 };
164 crate::util::status_result(status, out_error)
165 }
166
167 pub fn go_to_selection(&self, selection: &PdfSelection) -> Result<()> {
169 let mut out_error = ptr::null_mut();
170 let status = unsafe {
171 ffi::pdf_view_go_to_selection(
172 self.handle.as_ptr(),
173 selection.as_handle_ptr(),
174 &mut out_error,
175 )
176 };
177 crate::util::status_result(status, out_error)
178 }
179
180 pub fn set_display_mode(&self, mode: PdfDisplayMode) -> Result<()> {
182 let mut out_error = ptr::null_mut();
183 let status = unsafe {
184 ffi::pdf_view_set_display_mode(self.handle.as_ptr(), mode as i32, &mut out_error)
185 };
186 crate::util::status_result(status, out_error)
187 }
188
189 pub fn set_display_direction(&self, direction: PdfDisplayDirection) -> Result<()> {
191 let mut out_error = ptr::null_mut();
192 let status = unsafe {
193 ffi::pdf_view_set_display_direction(
194 self.handle.as_ptr(),
195 direction as i32,
196 &mut out_error,
197 )
198 };
199 crate::util::status_result(status, out_error)
200 }
201
202 pub fn set_display_box(&self, display_box: DisplayBox) -> Result<()> {
204 let mut out_error = ptr::null_mut();
205 let status = unsafe {
206 ffi::pdf_view_set_display_box(
207 self.handle.as_ptr(),
208 display_box.as_raw(),
209 &mut out_error,
210 )
211 };
212 crate::util::status_result(status, out_error)
213 }
214
215 pub fn set_auto_scales(&self, value: bool) {
217 unsafe { ffi::pdf_view_set_auto_scales(self.handle.as_ptr(), i32::from(value)) };
218 }
219
220 pub fn set_scale_factor(&self, value: f64) {
222 unsafe { ffi::pdf_view_set_scale_factor(self.handle.as_ptr(), value) };
223 }
224
225 pub fn set_min_scale_factor(&self, value: f64) {
227 unsafe { ffi::pdf_view_set_min_scale_factor(self.handle.as_ptr(), value) };
228 }
229
230 pub fn set_max_scale_factor(&self, value: f64) {
232 unsafe { ffi::pdf_view_set_max_scale_factor(self.handle.as_ptr(), value) };
233 }
234
235 pub fn layout_document_view(&self) {
237 unsafe { ffi::pdf_view_layout_document_view(self.handle.as_ptr()) };
238 }
239
240 #[must_use]
242 pub fn area_of_interest_for_point(&self, point: PdfPoint) -> PdfAreaOfInterest {
243 PdfAreaOfInterest::from_bits(unsafe {
244 ffi::pdf_view_area_of_interest_for_point(self.handle.as_ptr(), point.x, point.y)
245 })
246 }
247
248 #[must_use]
250 pub fn visible_page_count(&self) -> usize {
251 unsafe { ffi::pdf_view_visible_page_count(self.handle.as_ptr()) as usize }
252 }
253
254 #[must_use]
256 pub fn visible_page(&self, index: usize) -> Option<PdfPage> {
257 let ptr = unsafe { ffi::pdf_view_visible_page_at(self.handle.as_ptr(), index as u64) };
258 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfPage::from_handle)
259 }
260
261 #[must_use]
263 pub fn visible_pages(&self) -> Vec<PdfPage> {
264 (0..self.visible_page_count())
265 .filter_map(|index| self.visible_page(index))
266 .collect()
267 }
268
269 pub(crate) fn as_handle_ptr(&self) -> *mut core::ffi::c_void {
270 self.handle.as_ptr()
271 }
272}