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