use crate::{Bitmap, Icon, NwgError};
use std::ptr;
use winapi::shared::windef::{HBITMAP, HICON};
use winapi::um::commctrl::{HIMAGELIST, ImageList_AddMasked};
const NOT_BOUND: &'static str = "ImageList is not yet bound to a winapi object";
pub struct ImageList {
pub handle: HIMAGELIST,
pub owned: bool,
}
impl ImageList {
pub fn builder() -> ImageListBuilder {
ImageListBuilder {
size: (32, 32),
initial: 5,
grow: 5,
}
}
pub fn size(&self) -> (i32, i32) {
use winapi::um::commctrl::ImageList_GetIconSize;
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
let mut size = (0, 0);
unsafe {
ImageList_GetIconSize(self.handle, &mut size.0, &mut size.1);
}
size
}
pub fn set_size(&self, size: (i32, i32)) {
use winapi::um::commctrl::ImageList_SetIconSize;
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
let (w, h) = size;
unsafe {
ImageList_SetIconSize(self.handle, w, h);
}
}
pub fn len(&self) -> u32 {
use winapi::um::commctrl::ImageList_GetImageCount;
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
unsafe { ImageList_GetImageCount(self.handle) as u32 }
}
pub fn add_bitmap(&self, bitmap: &Bitmap) -> i32 {
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
if bitmap.handle.is_null() {
panic!("Bitmap was not initialized");
}
unsafe { ImageList_AddMasked(self.handle, bitmap.handle as HBITMAP, 0) }
}
pub fn add_bitmap_from_filename(&self, filename: &str) -> Result<i32, NwgError> {
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
let (w, h) = self.size();
let mut bitmap = Bitmap::default();
Bitmap::builder()
.source_file(Some(filename))
.size(Some((w as u32, h as u32)))
.strict(true)
.build(&mut bitmap)?;
unsafe {
Ok(ImageList_AddMasked(
self.handle,
bitmap.handle as HBITMAP,
0,
))
}
}
pub fn add_icon(&self, icon: &Icon) -> i32 {
use winapi::um::wingdi::DeleteObject;
use winapi::um::winuser::{GetIconInfo, ICONINFO};
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
if icon.handle.is_null() {
panic!("Icon was not initialized");
}
unsafe {
let mut info: ICONINFO = ::std::mem::zeroed();
GetIconInfo(icon.handle as _, &mut info);
let i = ImageList_AddMasked(self.handle, info.hbmColor, 0);
DeleteObject(info.hbmMask as _);
DeleteObject(info.hbmColor as _);
i
}
}
pub fn add_icon_from_filename(&self, filename: &str) -> Result<i32, NwgError> {
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
let (w, h) = self.size();
let mut icon = Icon::default();
Icon::builder()
.source_file(Some(filename))
.size(Some((w as u32, h as u32)))
.strict(true)
.build(&mut icon)?;
Ok(self.add_icon(&icon))
}
pub fn remove(&self, index: i32) {
use winapi::um::commctrl::ImageList_Remove;
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
unsafe {
ImageList_Remove(self.handle, index);
}
}
pub fn replace_bitmap(&self, index: i32, bitmap: &Bitmap) {
use winapi::um::commctrl::ImageList_Replace;
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
if bitmap.handle.is_null() {
panic!("Bitmap was not initialized");
}
unsafe {
ImageList_Replace(
self.handle,
index,
bitmap.handle as HBITMAP,
ptr::null_mut(),
);
}
}
pub fn replace_icon(&self, index: i32, icon: &Icon) {
use winapi::um::commctrl::ImageList_ReplaceIcon;
if self.handle.is_null() {
panic!("{}", NOT_BOUND);
}
if icon.handle.is_null() {
panic!("Icon was not initialized");
}
unsafe {
ImageList_ReplaceIcon(self.handle, index, icon.handle as HICON);
}
}
}
impl Drop for ImageList {
fn drop(&mut self) {
use winapi::um::commctrl::ImageList_Destroy;
unsafe {
if self.owned && !self.handle.is_null() {
ImageList_Destroy(self.handle);
}
}
}
}
impl Default for ImageList {
fn default() -> ImageList {
ImageList {
handle: ptr::null_mut(),
owned: false,
}
}
}
impl PartialEq for ImageList {
fn eq(&self, other: &Self) -> bool {
self.handle == other.handle
}
}
pub struct ImageListBuilder {
size: (i32, i32),
initial: i32,
grow: i32,
}
impl ImageListBuilder {
pub fn size(mut self, size: (i32, i32)) -> ImageListBuilder {
self.size = size;
self
}
pub fn initial(mut self, initial: i32) -> ImageListBuilder {
self.initial = initial;
self
}
pub fn grow(mut self, grow: i32) -> ImageListBuilder {
self.grow = grow;
self
}
pub fn build(self, list: &mut ImageList) -> Result<(), NwgError> {
use winapi::um::commctrl::{ILC_COLOR32, ILC_MASK, ImageList_Create};
unsafe {
let (w, h) = self.size;
let handle = ImageList_Create(w, h, ILC_COLOR32 | ILC_MASK, self.initial, self.grow);
if handle.is_null() {
return Err(NwgError::resource_create("Failed to create image list"));
}
list.handle = handle;
list.owned = true;
}
Ok(())
}
}