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}