native_windows_gui2/resources/
image_list.rs1use crate::{Bitmap, Icon, NwgError};
2use std::ptr;
3use winapi::shared::windef::{HBITMAP, HICON};
4use winapi::um::commctrl::{HIMAGELIST, ImageList_AddMasked};
5
6const NOT_BOUND: &'static str = "ImageList is not yet bound to a winapi object";
7
8pub struct ImageList {
34 pub handle: HIMAGELIST,
35 pub owned: bool,
36}
37
38impl ImageList {
39 pub fn builder() -> ImageListBuilder {
40 ImageListBuilder {
41 size: (32, 32),
42 initial: 5,
43 grow: 5,
44 }
45 }
46
47 pub fn size(&self) -> (i32, i32) {
49 use winapi::um::commctrl::ImageList_GetIconSize;
50
51 if self.handle.is_null() {
52 panic!("{}", NOT_BOUND);
53 }
54
55 let mut size = (0, 0);
56 unsafe {
57 ImageList_GetIconSize(self.handle, &mut size.0, &mut size.1);
58 }
59
60 size
61 }
62
63 pub fn set_size(&self, size: (i32, i32)) {
65 use winapi::um::commctrl::ImageList_SetIconSize;
66
67 if self.handle.is_null() {
68 panic!("{}", NOT_BOUND);
69 }
70
71 let (w, h) = size;
72 unsafe {
73 ImageList_SetIconSize(self.handle, w, h);
74 }
75 }
76
77 pub fn len(&self) -> u32 {
79 use winapi::um::commctrl::ImageList_GetImageCount;
80
81 if self.handle.is_null() {
82 panic!("{}", NOT_BOUND);
83 }
84
85 unsafe { ImageList_GetImageCount(self.handle) as u32 }
86 }
87
88 pub fn add_bitmap(&self, bitmap: &Bitmap) -> i32 {
90 if self.handle.is_null() {
91 panic!("{}", NOT_BOUND);
92 }
93 if bitmap.handle.is_null() {
94 panic!("Bitmap was not initialized");
95 }
96
97 unsafe { ImageList_AddMasked(self.handle, bitmap.handle as HBITMAP, 0) }
98 }
99
100 pub fn add_bitmap_from_filename(&self, filename: &str) -> Result<i32, NwgError> {
105 if self.handle.is_null() {
106 panic!("{}", NOT_BOUND);
107 }
108
109 let (w, h) = self.size();
110 let mut bitmap = Bitmap::default();
111 Bitmap::builder()
112 .source_file(Some(filename))
113 .size(Some((w as u32, h as u32)))
114 .strict(true)
115 .build(&mut bitmap)?;
116
117 unsafe {
118 Ok(ImageList_AddMasked(
119 self.handle,
120 bitmap.handle as HBITMAP,
121 0,
122 ))
123 }
124 }
125
126 pub fn add_icon(&self, icon: &Icon) -> i32 {
128 use winapi::um::wingdi::DeleteObject;
129 use winapi::um::winuser::{GetIconInfo, ICONINFO};
130
131 if self.handle.is_null() {
132 panic!("{}", NOT_BOUND);
133 }
134 if icon.handle.is_null() {
135 panic!("Icon was not initialized");
136 }
137
138 unsafe {
141 let mut info: ICONINFO = ::std::mem::zeroed();
142 GetIconInfo(icon.handle as _, &mut info);
143
144 let i = ImageList_AddMasked(self.handle, info.hbmColor, 0);
145
146 DeleteObject(info.hbmMask as _);
147 DeleteObject(info.hbmColor as _);
148
149 i
150 }
151 }
152
153 pub fn add_icon_from_filename(&self, filename: &str) -> Result<i32, NwgError> {
158 if self.handle.is_null() {
159 panic!("{}", NOT_BOUND);
160 }
161
162 let (w, h) = self.size();
163 let mut icon = Icon::default();
164 Icon::builder()
165 .source_file(Some(filename))
166 .size(Some((w as u32, h as u32)))
167 .strict(true)
168 .build(&mut icon)?;
169
170 Ok(self.add_icon(&icon))
171 }
172
173 pub fn remove(&self, index: i32) {
181 use winapi::um::commctrl::ImageList_Remove;
182
183 if self.handle.is_null() {
184 panic!("{}", NOT_BOUND);
185 }
186
187 unsafe {
188 ImageList_Remove(self.handle, index);
189 }
190 }
191
192 pub fn replace_bitmap(&self, index: i32, bitmap: &Bitmap) {
194 use winapi::um::commctrl::ImageList_Replace;
195
196 if self.handle.is_null() {
197 panic!("{}", NOT_BOUND);
198 }
199 if bitmap.handle.is_null() {
200 panic!("Bitmap was not initialized");
201 }
202
203 unsafe {
204 ImageList_Replace(
205 self.handle,
206 index,
207 bitmap.handle as HBITMAP,
208 ptr::null_mut(),
209 );
210 }
211 }
212
213 pub fn replace_icon(&self, index: i32, icon: &Icon) {
215 use winapi::um::commctrl::ImageList_ReplaceIcon;
216
217 if self.handle.is_null() {
218 panic!("{}", NOT_BOUND);
219 }
220 if icon.handle.is_null() {
221 panic!("Icon was not initialized");
222 }
223
224 unsafe {
225 ImageList_ReplaceIcon(self.handle, index, icon.handle as HICON);
226 }
227 }
228}
229
230impl Drop for ImageList {
231 fn drop(&mut self) {
232 use winapi::um::commctrl::ImageList_Destroy;
233 unsafe {
234 if self.owned && !self.handle.is_null() {
235 ImageList_Destroy(self.handle);
236 }
237 }
238 }
239}
240
241impl Default for ImageList {
242 fn default() -> ImageList {
243 ImageList {
244 handle: ptr::null_mut(),
245 owned: false,
246 }
247 }
248}
249
250impl PartialEq for ImageList {
251 fn eq(&self, other: &Self) -> bool {
252 self.handle == other.handle
253 }
254}
255
256pub struct ImageListBuilder {
257 size: (i32, i32),
258 initial: i32,
259 grow: i32,
260}
261
262impl ImageListBuilder {
263 pub fn size(mut self, size: (i32, i32)) -> ImageListBuilder {
264 self.size = size;
265 self
266 }
267
268 pub fn initial(mut self, initial: i32) -> ImageListBuilder {
269 self.initial = initial;
270 self
271 }
272
273 pub fn grow(mut self, grow: i32) -> ImageListBuilder {
274 self.grow = grow;
275 self
276 }
277
278 pub fn build(self, list: &mut ImageList) -> Result<(), NwgError> {
279 use winapi::um::commctrl::{ILC_COLOR32, ILC_MASK, ImageList_Create};
280
281 unsafe {
282 let (w, h) = self.size;
283 let handle = ImageList_Create(w, h, ILC_COLOR32 | ILC_MASK, self.initial, self.grow);
284 if handle.is_null() {
285 return Err(NwgError::resource_create("Failed to create image list"));
286 }
287
288 list.handle = handle;
289 list.owned = true;
290 }
291
292 Ok(())
293 }
294}