Skip to main content

pdfkit/
outline.rs

1use std::ptr;
2
3use crate::action_goto::PdfActionGoTo;
4use crate::action_url::PdfActionUrl;
5use crate::destination::PdfDestination;
6use crate::error::Result;
7use crate::ffi;
8use crate::handle::ObjectHandle;
9use crate::util::{option_c_string, take_string};
10
11#[derive(Debug, Clone)]
12pub struct PdfOutline {
13    handle: ObjectHandle,
14}
15
16impl PdfOutline {
17    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
18        Self { handle }
19    }
20
21    pub fn new() -> Result<Self> {
22        let mut out_outline = ptr::null_mut();
23        let mut out_error = ptr::null_mut();
24        let status = unsafe { ffi::pdf_outline_new(&mut out_outline, &mut out_error) };
25        crate::util::status_result(status, out_error)?;
26        Ok(Self::from_handle(crate::util::required_handle(
27            out_outline,
28            "PDFOutline",
29        )?))
30    }
31
32    #[must_use]
33    pub fn label(&self) -> Option<String> {
34        take_string(unsafe { ffi::pdf_outline_label_string(self.handle.as_ptr()) })
35    }
36
37    pub fn set_label(&self, value: Option<&str>) -> Result<()> {
38        let value = option_c_string(value)?;
39        let mut out_error = ptr::null_mut();
40        let status = unsafe {
41            ffi::pdf_outline_set_label(
42                self.handle.as_ptr(),
43                value.as_ref().map_or(ptr::null(), |value| value.as_ptr()),
44                &mut out_error,
45            )
46        };
47        crate::util::status_result(status, out_error)
48    }
49
50    #[must_use]
51    pub fn child_count(&self) -> usize {
52        unsafe { ffi::pdf_outline_child_count(self.handle.as_ptr()) as usize }
53    }
54
55    #[must_use]
56    pub fn child(&self, index: usize) -> Option<Self> {
57        let ptr = unsafe { ffi::pdf_outline_child_at(self.handle.as_ptr(), index as u64) };
58        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(Self::from_handle)
59    }
60
61    #[must_use]
62    pub fn children(&self) -> Vec<Self> {
63        (0..self.child_count())
64            .filter_map(|index| self.child(index))
65            .collect()
66    }
67
68    pub fn insert_child(&self, child: &Self, index: usize) -> Result<()> {
69        let mut out_error = ptr::null_mut();
70        let status = unsafe {
71            ffi::pdf_outline_insert_child(
72                self.handle.as_ptr(),
73                child.handle.as_ptr(),
74                index as u64,
75                &mut out_error,
76            )
77        };
78        crate::util::status_result(status, out_error)
79    }
80
81    pub fn remove_from_parent(&self) {
82        unsafe { ffi::pdf_outline_remove_from_parent(self.handle.as_ptr()) };
83    }
84
85    #[must_use]
86    pub fn index(&self) -> usize {
87        unsafe { ffi::pdf_outline_index(self.handle.as_ptr()) as usize }
88    }
89
90    #[must_use]
91    pub fn is_open(&self) -> bool {
92        unsafe { ffi::pdf_outline_is_open(self.handle.as_ptr()) != 0 }
93    }
94
95    pub fn set_open(&self, value: bool) {
96        unsafe { ffi::pdf_outline_set_open(self.handle.as_ptr(), i32::from(value)) };
97    }
98
99    #[must_use]
100    pub fn destination(&self) -> Option<PdfDestination> {
101        let ptr = unsafe { ffi::pdf_outline_destination(self.handle.as_ptr()) };
102        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfDestination::from_handle)
103    }
104
105    pub fn set_destination(&self, destination: Option<&PdfDestination>) -> Result<()> {
106        let mut out_error = ptr::null_mut();
107        let status = unsafe {
108            ffi::pdf_outline_set_destination(
109                self.handle.as_ptr(),
110                destination.map_or(ptr::null_mut(), PdfDestination::as_handle_ptr),
111                &mut out_error,
112            )
113        };
114        crate::util::status_result(status, out_error)
115    }
116
117    #[must_use]
118    pub fn action_url(&self) -> Option<PdfActionUrl> {
119        let ptr = unsafe { ffi::pdf_outline_action_url(self.handle.as_ptr()) };
120        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfActionUrl::from_handle)
121    }
122
123    pub fn set_action_url(&self, action: Option<&PdfActionUrl>) -> Result<()> {
124        let mut out_error = ptr::null_mut();
125        let status = unsafe {
126            ffi::pdf_outline_set_action_url(
127                self.handle.as_ptr(),
128                action.map_or(ptr::null_mut(), PdfActionUrl::as_handle_ptr),
129                &mut out_error,
130            )
131        };
132        crate::util::status_result(status, out_error)
133    }
134
135    #[must_use]
136    pub fn action_goto(&self) -> Option<PdfActionGoTo> {
137        let ptr = unsafe { ffi::pdf_outline_action_goto(self.handle.as_ptr()) };
138        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfActionGoTo::from_handle)
139    }
140
141    pub fn set_action_goto(&self, action: Option<&PdfActionGoTo>) -> Result<()> {
142        let mut out_error = ptr::null_mut();
143        let status = unsafe {
144            ffi::pdf_outline_set_action_goto(
145                self.handle.as_ptr(),
146                action.map_or(ptr::null_mut(), PdfActionGoTo::as_handle_ptr),
147                &mut out_error,
148            )
149        };
150        crate::util::status_result(status, out_error)
151    }
152
153    #[must_use]
154    pub fn parent(&self) -> Option<Self> {
155        let ptr = unsafe { ffi::pdf_outline_parent(self.handle.as_ptr()) };
156        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(Self::from_handle)
157    }
158
159    pub(crate) fn as_handle_ptr(&self) -> *mut core::ffi::c_void {
160        self.handle.as_ptr()
161    }
162}