use std::ffi::{CStr, CString};
use std::os::raw::c_longlong;
use wxdragon_sys as ffi;
use crate::color::Colour;
use crate::event::{Event, EventType, WxEvtHandler};
use crate::geometry::{Point, Size};
use crate::id::Id;
use crate::window::{WindowHandle, WxWidget};
#[allow(unused_imports)]
use crate::window::Window;
widget_style_enum!(
name: HyperlinkCtrlStyle,
doc: "Style flags for HyperlinkCtrl.",
variants: {
Default: 0x0002, "Default style.",
AlignLeft: 0x0004, "Align the text to the left (default).",
AlignRight: 0x0008, "Align the text to the right.",
AlignCentre: 0x0010, "Center the text.",
NoUnderline: 0x0020, "Don't show the underline below the link."
},
default_variant: Default
);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HyperlinkCtrlEvent {
Clicked,
}
#[derive(Debug)]
pub struct HyperlinkCtrlEventData {
event: Event,
}
impl HyperlinkCtrlEventData {
pub fn new(event: Event) -> Self {
Self { event }
}
pub fn get_id(&self) -> i32 {
self.event.get_id()
}
pub fn get_url(&self) -> Option<String> {
if let Some(window_obj) = self.event.get_event_object() {
let hyperlink = unsafe { HyperlinkCtrl::from_ptr(window_obj.handle_ptr() as *mut ffi::wxd_HyperlinkCtrl_t) };
let url = hyperlink.get_url();
if !url.is_empty() {
return Some(url);
}
}
None
}
}
#[derive(Clone, Copy)]
pub struct HyperlinkCtrl {
handle: WindowHandle,
}
impl HyperlinkCtrl {
pub fn builder(parent: &dyn WxWidget) -> HyperlinkCtrlBuilder<'_> {
HyperlinkCtrlBuilder::new(parent)
}
#[inline]
fn hyperlink_ptr(&self) -> *mut ffi::wxd_HyperlinkCtrl_t {
self.handle
.get_ptr()
.map(|p| p as *mut ffi::wxd_HyperlinkCtrl_t)
.unwrap_or(std::ptr::null_mut())
}
pub fn get_url(&self) -> String {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return String::new();
}
let len = unsafe { ffi::wxd_HyperlinkCtrl_GetURL(ptr, std::ptr::null_mut(), 0) };
if len <= 0 {
return String::new();
}
let mut buf = vec![0; len as usize + 1];
unsafe { ffi::wxd_HyperlinkCtrl_GetURL(ptr, buf.as_mut_ptr(), buf.len()) };
unsafe { CStr::from_ptr(buf.as_ptr()).to_string_lossy().into_owned() }
}
pub fn set_url(&self, url: &str) {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return;
}
let c_url = CString::new(url).expect("CString::new failed for url");
unsafe { ffi::wxd_HyperlinkCtrl_SetURL(ptr, c_url.as_ptr()) }
}
pub fn get_visited(&self) -> bool {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return false;
}
unsafe { ffi::wxd_HyperlinkCtrl_GetVisited(ptr) }
}
pub fn set_visited(&self, visited: bool) {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_HyperlinkCtrl_SetVisited(ptr, visited) }
}
pub fn get_hover_colour(&self) -> Colour {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return Colour::rgb(0, 0, 0);
}
let val = unsafe { ffi::wxd_HyperlinkCtrl_GetHoverColour(ptr) };
Colour::from_u32(val as u32)
}
pub fn set_hover_colour(&self, colour: Colour) {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_HyperlinkCtrl_SetHoverColour(ptr, colour.as_u32() as std::os::raw::c_ulong) }
}
pub fn get_normal_colour(&self) -> Colour {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return Colour::rgb(0, 0, 0);
}
let val = unsafe { ffi::wxd_HyperlinkCtrl_GetNormalColour(ptr) };
Colour::from_u32(val as u32)
}
pub fn set_normal_colour(&self, colour: Colour) {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_HyperlinkCtrl_SetNormalColour(ptr, colour.as_u32() as std::os::raw::c_ulong) }
}
pub fn get_visited_colour(&self) -> Colour {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return Colour::rgb(0, 0, 0);
}
let val = unsafe { ffi::wxd_HyperlinkCtrl_GetVisitedColour(ptr) };
Colour::from_u32(val as u32)
}
pub fn set_visited_colour(&self, colour: Colour) {
let ptr = self.hyperlink_ptr();
if ptr.is_null() {
return;
}
unsafe { ffi::wxd_HyperlinkCtrl_SetVisitedColour(ptr, colour.as_u32() as std::os::raw::c_ulong) }
}
pub(crate) unsafe fn from_ptr(ptr: *mut ffi::wxd_HyperlinkCtrl_t) -> Self {
HyperlinkCtrl {
handle: WindowHandle::new(ptr as *mut ffi::wxd_Window_t),
}
}
pub fn window_handle(&self) -> WindowHandle {
self.handle
}
}
impl WxWidget for HyperlinkCtrl {
fn handle_ptr(&self) -> *mut ffi::wxd_Window_t {
self.handle.get_ptr().unwrap_or(std::ptr::null_mut())
}
fn is_valid(&self) -> bool {
self.handle.is_valid()
}
}
impl WxEvtHandler for HyperlinkCtrl {
unsafe fn get_event_handler_ptr(&self) -> *mut ffi::wxd_EvtHandler_t {
self.handle.get_ptr().unwrap_or(std::ptr::null_mut()) as *mut ffi::wxd_EvtHandler_t
}
}
impl crate::event::WindowEvents for HyperlinkCtrl {}
crate::implement_widget_local_event_handlers!(
HyperlinkCtrl,
HyperlinkCtrlEvent,
HyperlinkCtrlEventData,
Clicked => clicked, EventType::COMMAND_HYPERLINK
);
#[cfg(feature = "xrc")]
impl crate::xrc::XrcSupport for HyperlinkCtrl {
unsafe fn from_xrc_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
HyperlinkCtrl {
handle: WindowHandle::new(ptr),
}
}
}
widget_builder!(
name: HyperlinkCtrl,
parent_type: &'a dyn WxWidget,
style_type: HyperlinkCtrlStyle,
fields: {
label: String = String::new(),
url: String = String::new()
},
build_impl: |slf| {
let c_label = CString::new(&slf.label[..]).expect("CString::new failed for label");
let c_url = CString::new(&slf.url[..]).expect("CString::new failed for url");
let raw_ptr = unsafe {
ffi::wxd_HyperlinkCtrl_Create(
slf.parent.handle_ptr(),
slf.id,
c_label.as_ptr(),
c_url.as_ptr(),
slf.pos.x,
slf.pos.y,
slf.size.width,
slf.size.height,
slf.style.bits() as c_longlong,
)
};
if raw_ptr.is_null() {
panic!("Failed to create wxHyperlinkCtrl");
}
HyperlinkCtrl {
handle: WindowHandle::new(raw_ptr as *mut ffi::wxd_Window_t),
}
}
);
impl crate::window::FromWindowWithClassName for HyperlinkCtrl {
fn class_name() -> &'static str {
"wxHyperlinkCtrl"
}
unsafe fn from_ptr(ptr: *mut ffi::wxd_Window_t) -> Self {
HyperlinkCtrl {
handle: WindowHandle::new(ptr),
}
}
}