use ::{_API};
use capi::sctypes::*;
use value::Value;
use capi::screquest::{REQUEST_PARAM, REQUEST_TYPE};
use capi::scdef::RESOURCE_TYPE;
use capi::scbehavior::{CLICK_REASON, BEHAVIOR_EVENTS, BEHAVIOR_EVENT_PARAMS};
use utf::{store_astr, store_wstr, store_bstr};
pub use capi::scdom::{SCDOM_RESULT, HELEMENT, SET_ELEMENT_HTML, ELEMENT_AREAS, ELEMENT_STATE_BITS};
pub use dom::event::{EventHandler, EventReason};
pub type Result<T> = ::std::result::Result<T, SCDOM_RESULT>;
macro_rules! HELEMENT {
() => { ::std::ptr::null_mut() }
}
macro_rules! ok_or {
($rv:expr, $ok:ident) => {
if $ok == SCDOM_RESULT::OK {
Ok($rv)
} else {
Err($ok)
}
};
($rv:expr, $ok:ident, $skip_not_handled:expr) => {
if $ok == SCDOM_RESULT::OK || ($ok == $skip_not_handled) {
Ok($rv)
} else {
Err($ok)
}
};
}
trait ElementVisitor {
fn on_element(&mut self, el: Element) -> bool;
fn result(&self) -> Vec<Element>;
}
#[derive(Default)]
struct FindFirstElement {
all: Vec<Element>,
}
impl ElementVisitor for FindFirstElement {
fn on_element(&mut self, el: Element) -> bool {
self.all.push(el);
return true; }
fn result(&self) -> Vec<Element> {
self.all.clone()
}
}
#[derive(Default)]
struct FindAllElements {
all: Vec<Element>,
}
impl ElementVisitor for FindAllElements {
fn on_element(&mut self, el: Element) -> bool {
self.all.push(el);
return false; }
fn result(&self) -> Vec<Element> {
self.all.clone()
}
}
#[derive(PartialEq)]
pub struct Element {
he: HELEMENT,
}
unsafe impl Send for Element {}
unsafe impl Sync for Element {}
impl From<HELEMENT> for Element {
fn from(he: HELEMENT) -> Self {
Element { he: Element::use_or(he) }
}
}
const DOM_UNWRAP_API_VERSION: u32 = 0x0000_0007;
impl std::convert::TryFrom<Element> for Value {
type Error = SCDOM_RESULT;
fn try_from(e: Element) -> Result<Value> {
let mut v = Value::new();
let ok = if crate::api_version() >= DOM_UNWRAP_API_VERSION {
(_API.SciterElementWrap)(v.as_mut_ptr(), e.as_ptr())
} else {
(_API.SciterGetExpando)(e.as_ptr(), v.as_ptr(), true as BOOL)
};
ok_or!(v, ok)
}
}
impl crate::value::FromValue for Element {
fn from_value(v: &Value) -> Option<Element> {
if crate::api_version() >= DOM_UNWRAP_API_VERSION {
let mut h = std::ptr::null_mut();
let ok = (_API.SciterElementUnwrap)(v.as_cptr(), &mut h);
if ok == SCDOM_RESULT::OK {
Some(Element::from(h))
} else {
None
}
} else {
let mut pv: LPCBYTE = std::ptr::null();
let mut cb: UINT = 0;
let ok = (_API.ValueBinaryData)(v.as_cptr(), &mut pv, &mut cb);
if ok == crate::value::VALUE_RESULT::OK {
Some(Element::from(pv as HELEMENT))
} else {
None
}
}
}
}
impl Element {
pub fn create(tag: &str) -> Result<Element> {
let mut e = Element { he: HELEMENT!() };
let tag = s2u!(tag);
let text = 0 as LPCWSTR;
let ok = (_API.SciterCreateElement)(tag.as_ptr(), text, &mut e.he);
ok_or!(e, ok)
}
pub fn with_parent(tag: &str, parent: &mut Element) -> Result<Element> {
let mut e = Element { he: HELEMENT!() };
let tag = s2u!(tag);
let text = 0 as LPCWSTR;
(_API.SciterCreateElement)(tag.as_ptr(), text, &mut e.he);
let ok = parent.append(&e);
ok.map(|_| e)
}
#[deprecated(since="0.5.0", note="please use `Element::with_parent()` instead.")]
pub fn create_at(tag: &str, parent: &mut Element) -> Result<Element> {
Element::with_parent(tag, parent)
}
pub fn with_text(tag: &str, text: &str) -> Result<Element> {
let mut e = Element { he: HELEMENT!() };
let tag = s2u!(tag);
let text = s2w!(text);
let ok = (_API.SciterCreateElement)(tag.as_ptr(), text.as_ptr(), &mut e.he);
ok_or!(e, ok)
}
pub fn with_type(tag: &str, el_type: &str) -> Result<Element> {
let mut e = Element { he: HELEMENT!() };
let tag = s2u!(tag);
let text = 0 as LPCWSTR;
let ok = (_API.SciterCreateElement)(tag.as_ptr(), text, &mut e.he);
if ok == SCDOM_RESULT::OK {
let r = e.set_attribute("type", el_type);
r.map(|_| e)
} else {
Err(ok)
}
}
fn forbid_null(e: Element) -> Result<Element> {
if e.he.is_null() {
Err(SCDOM_RESULT::OK_NOT_HANDLED)
} else {
Ok(e)
}
}
pub fn from_window(hwnd: HWINDOW) -> Result<Element> {
let mut p = HELEMENT!();
let ok = (_API.SciterGetRootElement)(hwnd, &mut p);
ok_or!(Element::from(p), ok).and_then(Element::forbid_null)
}
pub fn from_focus(hwnd: HWINDOW) -> Result<Element> {
let mut p = HELEMENT!();
let ok = (_API.SciterGetFocusElement)(hwnd, &mut p);
ok_or!(Element::from(p), ok).and_then(Element::forbid_null)
}
pub fn from_highlighted(hwnd: HWINDOW) -> Result<Element> {
let mut p = HELEMENT!();
let ok = (_API.SciterGetHighlightedElement)(hwnd, &mut p);
ok_or!(Element::from(p), ok).and_then(Element::forbid_null)
}
pub fn from_point(hwnd: HWINDOW, pt: POINT) -> Result<Element> {
let mut p = HELEMENT!();
let ok = (_API.SciterFindElement)(hwnd, pt, &mut p);
ok_or!(Element::from(p), ok).and_then(Element::forbid_null)
}
pub fn from_uid(hwnd: HWINDOW, uid: u32) -> Result<Element> {
let mut p = HELEMENT!();
let ok = (_API.SciterGetElementByUID)(hwnd, uid, &mut p);
ok_or!(Element::from(p), ok).and_then(Element::forbid_null)
}
#[doc(hidden)]
fn use_or(he: HELEMENT) -> HELEMENT {
let ok = (_API.Sciter_UseElement)(he);
if ok == SCDOM_RESULT::OK {
he
} else {
HELEMENT!()
}
}
pub fn as_ptr(&self) -> HELEMENT {
self.he
}
pub fn get_uid(&self) -> u32 {
let mut n = 0;
(_API.SciterGetElementUID)(self.he, &mut n);
return n;
}
pub fn get_tag(&self) -> String {
let mut s = String::new();
(_API.SciterGetElementTypeCB)(self.he, store_astr, &mut s as *mut String as LPVOID);
return s;
}
pub fn get_text(&self) -> String {
let mut s = String::new();
(_API.SciterGetElementTextCB)(self.he, store_wstr, &mut s as *mut String as LPVOID);
return s;
}
pub fn set_text(&mut self, text: &str) -> Result<()> {
let (s,n) = s2wn!(text);
let ok = (_API.SciterSetElementText)(self.he, s.as_ptr(), n);
ok_or!((), ok)
}
pub fn get_html(&self, with_outer_html: bool) -> Vec<u8> {
let mut s = Vec::new();
(_API.SciterGetElementHtmlCB)(self.he, with_outer_html as BOOL, store_bstr, &mut s as *mut Vec<u8> as LPVOID);
return s;
}
pub fn set_html(&mut self, html: &[u8], how: Option<SET_ELEMENT_HTML>) -> Result<()> {
if html.is_empty() {
return self.clear();
}
let ok = (_API.SciterSetElementHtml)(self.he, html.as_ptr(), html.len() as UINT, how.unwrap_or(SET_ELEMENT_HTML::SIH_REPLACE_CONTENT) as UINT);
ok_or!((), ok)
}
pub fn get_value(&self) -> Value {
let mut rv = Value::new();
(_API.SciterGetValue)(self.he, rv.as_ptr());
return rv;
}
pub fn set_value<T: Into<Value>>(&mut self, val: T) -> Result<()> {
let ok = (_API.SciterSetValue)(self.he, val.into().as_cptr());
ok_or!((), ok)
}
pub fn get_state(&self) -> ELEMENT_STATE_BITS {
let mut rv = 0u32;
(_API.SciterGetElementState)(self.he, &mut rv as *mut _);
let state = unsafe { ::std::mem::transmute(rv) };
return state;
}
pub fn set_state(&mut self, set: ELEMENT_STATE_BITS, clear: Option<ELEMENT_STATE_BITS>, update: bool) -> Result<()> {
let clear = clear.unwrap_or(ELEMENT_STATE_BITS::STATE_NONE);
let ok = (_API.SciterSetElementState)(self.he, set as UINT, clear as UINT, update as BOOL);
ok_or!((), ok)
}
pub fn get_hwnd(&self, for_root: bool) -> HWINDOW {
let mut hwnd: HWINDOW = ::std::ptr::null_mut();
(_API.SciterGetElementHwnd)(self.he, &mut hwnd as *mut HWINDOW, for_root as BOOL);
return hwnd;
}
pub fn attach_hwnd(&mut self, child: HWINDOW) -> Result<()> {
let ok = (_API.SciterAttachHwndToElement)(self.he, child);
ok_or!((), ok)
}
pub fn detach_hwnd(&mut self) -> Result<()> {
let ok = (_API.SciterAttachHwndToElement)(self.he, 0 as HWINDOW);
ok_or!((), ok)
}
pub fn get_location(&self, kind: u32) -> Result<RECT> {
let mut rc = RECT::default();
let ok = (_API.SciterGetElementLocation)(self.he, &mut rc as *mut _, kind as u32);
ok_or!(rc, ok)
}
pub fn request_data(&self, url: &str, data_type: RESOURCE_TYPE, initiator: Option<HELEMENT>) -> Result<()> {
let url = s2w!(url);
let ok = (_API.SciterRequestElementData)(self.he, url.as_ptr(), data_type as u32, initiator.unwrap_or(HELEMENT!()));
ok_or!((), ok)
}
pub fn request_html(&self, url: &str, initiator: Option<HELEMENT>) -> Result<()> {
self.request_data(url, RESOURCE_TYPE::HTML, initiator)
}
pub fn send_get_request(&self, url: &str) -> Result<()> {
let url = s2w!(url);
let no_params = ::std::ptr::null();
let ok = (_API.SciterHttpRequest)(self.he, url.as_ptr(), RESOURCE_TYPE::HTML as u32, REQUEST_TYPE::AsyncGet as u32, no_params, 0);
ok_or!((), ok)
}
pub fn send_request(&self, url: &str, params: Option<&[(&str, &str)]>, method: Option<REQUEST_TYPE>, data_type: Option<RESOURCE_TYPE>) -> Result<()> {
let url = s2w!(url);
let method = method.unwrap_or(REQUEST_TYPE::AsyncGet) as u32;
let data_type = data_type.unwrap_or(RESOURCE_TYPE::HTML) as u32;
type WSTR = Vec<u16>;
let mut wide_params: Vec<(WSTR, WSTR)> = Vec::new();
let mut call_params: Vec<REQUEST_PARAM> = Vec::new();
if let Some(params) = params {
let count = params.len();
wide_params.reserve_exact(count);
call_params.reserve_exact(count);
for (k,v) in params {
let (kw, vw) = (s2w!(k), s2w!(v));
call_params.push (REQUEST_PARAM {
name: kw.as_ptr(),
value: vw.as_ptr(),
});
wide_params.push((kw, vw));
}
}
let ok = (_API.SciterHttpRequest)(self.he, url.as_ptr(), data_type, method, call_params.as_ptr(), call_params.len() as u32);
ok_or!((), ok)
}
pub fn send_event(&self, code: BEHAVIOR_EVENTS, reason: Option<CLICK_REASON>, source: Option<HELEMENT>) -> Result<bool> {
let mut handled = false as BOOL;
let r = reason.unwrap_or(CLICK_REASON::SYNTHESIZED);
let s = source.unwrap_or(self.he);
let ok = (_API.SciterSendEvent)(self.he, code as u32, s, r as UINT_PTR, &mut handled);
ok_or!(handled != 0, ok)
}
pub fn post_event(&self, code: BEHAVIOR_EVENTS, reason: Option<CLICK_REASON>, source: Option<HELEMENT>) -> Result<()> {
let r = reason.unwrap_or(CLICK_REASON::SYNTHESIZED);
let s = source.unwrap_or(self.he);
let ok = (_API.SciterPostEvent)(self.he, code as u32, s, r as UINT_PTR);
ok_or!((), ok)
}
pub fn fire_event(&self, code: BEHAVIOR_EVENTS, reason: Option<CLICK_REASON>, source: Option<HELEMENT>, post: bool, data: Option<Value>) -> Result<bool> {
let mut handled = false as BOOL;
let mut params = BEHAVIOR_EVENT_PARAMS {
cmd: code as UINT,
reason: reason.unwrap_or(CLICK_REASON::SYNTHESIZED) as UINT_PTR,
he: source.unwrap_or(self.he),
heTarget: self.he,
data: Default::default(),
name: 0 as LPCWSTR,
};
if let Some(data) = data {
data.pack_to(&mut params.data);
}
let ok = (_API.SciterFireEvent)(¶ms, post as BOOL, &mut handled);
ok_or!(handled != 0, ok)
}
pub fn fire_event_params(evt: &BEHAVIOR_EVENT_PARAMS, post: bool) -> Result<bool> {
let mut handled = false as BOOL;
let ok = (_API.SciterFireEvent)(evt, post as BOOL, &mut handled);
ok_or!(handled != 0, ok)
}
pub fn broadcast_event(&self, name: &str, post: bool, data: Option<Value>) -> Result<bool> {
let name = s2w!(name);
let mut params = BEHAVIOR_EVENT_PARAMS {
cmd: BEHAVIOR_EVENTS::CUSTOM as UINT,
heTarget: HELEMENT!(),
reason: 0,
he: self.he,
name: name.as_ptr(),
data: Default::default(),
};
if let Some(data) = data {
data.pack_to(&mut params.data);
}
let mut handled = false as BOOL;
let ok = (_API.SciterFireEvent)(¶ms, post as BOOL, &mut handled);
ok_or!(handled != 0, ok)
}
pub fn eval_script(&self, script: &str) -> Result<Value> {
let mut rv = Value::new();
let (s,n) = s2wn!(script);
let ok = (_API.SciterEvalElementScript)(self.he, s.as_ptr(), n, rv.as_ptr());
return ok_or!(rv, ok, SCDOM_RESULT::OPERATION_FAILED);
}
pub fn call_function(&self, name: &str, args: &[Value]) -> Result<Value> {
let mut rv = Value::new();
let name = s2u!(name);
let argv = Value::pack_args(args);
let ok = (_API.SciterCallScriptingFunction)(self.he, name.as_ptr(), argv.as_ptr(), argv.len() as UINT, rv.as_ptr());
return ok_or!(rv, ok, SCDOM_RESULT::OPERATION_FAILED);
}
pub fn call_method(&self, name: &str, args: &[Value]) -> Result<Value> {
let mut rv = Value::new();
let name = s2u!(name);
let argv = Value::pack_args(args);
let ok = (_API.SciterCallScriptingMethod)(self.he, name.as_ptr(), argv.as_ptr(), argv.len() as UINT, rv.as_ptr());
return ok_or!(rv, ok, SCDOM_RESULT::OPERATION_FAILED);
}
pub fn call_behavior_method(&self, params: event::MethodParams) -> Result<()> {
let call = |p| {
(_API.SciterCallBehaviorMethod)(self.he, p)
};
use capi::scbehavior::{METHOD_PARAMS, VALUE_PARAMS, IS_EMPTY_PARAMS};
use capi::scbehavior::BEHAVIOR_METHOD_IDENTIFIERS::*;
let ok = match params {
event::MethodParams::Click => {
let mut p = METHOD_PARAMS {
method: DO_CLICK as u32,
};
call(&mut p as *mut _)
},
event::MethodParams::SetValue(v) => {
let mut p = VALUE_PARAMS {
method: SET_VALUE as u32,
value: Default::default(),
};
v.pack_to(&mut p.value);
call(&mut p as *mut _ as *mut METHOD_PARAMS)
},
event::MethodParams::GetValue(retv) => {
let mut p = VALUE_PARAMS {
method: SET_VALUE as u32,
value: Default::default(),
};
let ok = call(&mut p as *mut _ as *mut METHOD_PARAMS);
if ok != SCDOM_RESULT::OK {
return Err(ok);
}
*retv = Value::from(&p.value);
ok
},
event::MethodParams::IsEmpty(retv) => {
let mut p = IS_EMPTY_PARAMS {
method: IS_EMPTY as u32,
is_empty: Default::default(),
};
let ok = call(&mut p as *mut _ as *mut METHOD_PARAMS);
if ok != SCDOM_RESULT::OK {
return Err(ok);
}
*retv = p.is_empty != 0;
ok
},
_ => {
SCDOM_RESULT::INVALID_PARAMETER
},
};
ok_or!((), ok)
}
pub fn attribute_count(&self) -> usize {
let mut n = 0u32;
(_API.SciterGetAttributeCount)(self.he, &mut n);
return n as usize;
}
pub fn attribute_name(&self, index: usize) -> String {
let mut s = String::new();
(_API.SciterGetNthAttributeNameCB)(self.he, index as UINT, store_astr, &mut s as *mut String as LPVOID);
return s;
}
pub fn attribute(&self, index: usize) -> String {
let mut s = String::new();
(_API.SciterGetNthAttributeValueCB)(self.he, index as UINT, store_wstr, &mut s as *mut String as LPVOID);
return s;
}
pub fn get_attribute(&self, name: &str) -> Option<String> {
let mut s = String::new();
let name = s2u!(name);
let ok = (_API.SciterGetAttributeByNameCB)(self.he, name.as_ptr(), store_wstr, &mut s as *mut String as LPVOID);
match ok {
SCDOM_RESULT::OK => Some(s),
_ => None,
}
}
pub fn set_attribute(&mut self, name: &str, value: &str) -> Result<()> {
let name = s2u!(name);
let value = s2w!(value);
let ok = (_API.SciterSetAttributeByName)(self.he, name.as_ptr(), value.as_ptr());
ok_or!((), ok)
}
pub fn remove_attribute(&mut self, name: &str) -> Result<()> {
let name = s2u!(name);
let value = ::std::ptr::null();
let ok = (_API.SciterSetAttributeByName)(self.he, name.as_ptr(), value);
ok_or!((), ok)
}
pub fn toggle_attribute(&mut self, name: &str, isset: bool, value: Option<&str>) -> Result<()> {
if isset {
self.set_attribute(name, value.unwrap())
} else {
self.remove_attribute(name)
}
}
pub fn clear_attributes(&mut self) -> Result<()> {
let ok = (_API.SciterClearAttributes)(self.he);
ok_or!((), ok)
}
pub fn get_style_attribute(&self, name: &str) -> String {
let mut s = String::new();
let name = s2u!(name);
(_API.SciterGetStyleAttributeCB)(self.he, name.as_ptr(), store_wstr, &mut s as *mut String as LPVOID);
return s;
}
pub fn set_style_attribute(&mut self, name: &str, value: &str) -> Result<()> {
let name = s2u!(name);
let value = s2w!(value);
let ok = (_API.SciterSetStyleAttribute)(self.he, name.as_ptr(), value.as_ptr());
ok_or!((), ok)
}
pub fn index(&self) -> usize {
let mut n = 0u32;
(_API.SciterGetElementIndex)(self.he, &mut n as *mut UINT);
return n as usize;
}
pub fn root(&self) -> Element {
if let Some(dad) = self.parent() {
dad.root()
} else {
self.clone()
}
}
pub fn parent(&self) -> Option<Element> {
let mut p = HELEMENT!();
(_API.SciterGetParentElement)(self.he, &mut p);
if p.is_null() {
None
} else {
Some(Element::from(p))
}
}
pub fn first_sibling(&self) -> Option<Element> {
if let Some(dad) = self.parent() {
let count = dad.len();
if count > 0 {
return dad.child(0);
}
}
None
}
pub fn last_sibling(&self) -> Option<Element> {
if let Some(dad) = self.parent() {
let count = dad.len();
if count > 0 {
return dad.child(count - 1);
}
}
None
}
pub fn next_sibling(&self) -> Option<Element> {
let idx = self.index() + 1;
if let Some(dad) = self.parent() {
let count = dad.len();
if idx < count {
return dad.child(idx);
}
}
None
}
pub fn prev_sibling(&self) -> Option<Element> {
let idx = self.index();
if let Some(dad) = self.parent() {
let count = dad.len();
if idx > 0 && (idx - 1) < count {
return dad.child(idx - 1);
}
}
None
}
pub fn first_child(&self) -> Option<Element> {
return self.child(0);
}
pub fn last_child(&self) -> Option<Element> {
let count = self.len();
if count > 0 {
return self.child(count - 1);
}
None
}
pub fn get(&self, index: usize) -> Option<Element> {
return self.child(index);
}
pub fn children(&self) -> Children {
Children {
base: self,
index: 0,
count: self.children_count(),
}
}
pub fn child(&self, index: usize) -> Option<Element> {
let mut p = HELEMENT!();
let ok = (_API.SciterGetNthChild)(self.he, index as UINT, &mut p);
match ok {
SCDOM_RESULT::OK => Some(Element::from(p)),
_ => None
}
}
pub fn children_count(&self) -> usize {
let mut n = 0u32;
(_API.SciterGetChildrenCount)(self.he, &mut n as *mut UINT);
return n as usize;
}
pub fn len(&self) -> usize {
return self.children_count();
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn clear(&mut self) -> Result<()> {
let ok = (_API.SciterSetElementText)(self.he, ::std::ptr::null(), 0);
ok_or!((), ok)
}
pub fn clone_element(&self) -> Element {
let mut e = Element { he: HELEMENT!() };
(_API.SciterCloneElement)(self.he, &mut e.he);
return e;
}
pub fn insert(&mut self, index: usize, child: &Element) -> Result<()> {
let ok = (_API.SciterInsertElement)(child.he, self.he, index as UINT);
ok_or!((), ok)
}
pub fn append(&mut self, child: &Element) -> Result<()> {
self.insert(0x7FFF_FFFF, child)
}
#[allow(clippy::needless_pass_by_value)]
pub fn push(&mut self, element: Element) {
self.append(&element).expect("Could not append element.");
}
pub fn pop(&mut self) -> Option<Element> {
let count = self.len();
if count > 0 {
if let Some(mut child) = self.get(count - 1) {
child.detach().expect("Could not detach element.");
return Some(child);
}
}
return None;
}
pub fn detach(&mut self) -> Result<()> {
let ok = (_API.SciterDetachElement)(self.he);
ok_or!((), ok)
}
pub fn destroy(&mut self) -> Result<()> {
let mut p = HELEMENT!();
::std::mem::swap(&mut self.he, &mut p);
let ok = (_API.SciterDeleteElement)(p);
ok_or!((), ok)
}
pub fn swap(&mut self, other: &mut Element) -> Result<()> {
let ok = (_API.SciterSwapElements)(self.he, other.he);
ok_or!((), ok)
}
pub fn test(&self, selector: &str) -> bool {
let mut p = HELEMENT!();
let s = s2u!(selector);
(_API.SciterSelectParent)(self.he, s.as_ptr(), 1, &mut p);
return !p.is_null();
}
fn select_elements<T: ElementVisitor>(&self, selector: &str, callback: T) -> Result<Vec<Element>> {
extern "system" fn inner<T: ElementVisitor>(he: HELEMENT, param: LPVOID) -> BOOL {
let p = param as *mut T;
let obj = unsafe { &mut *p };
let e = Element::from(he);
let stop = obj.on_element(e);
return stop as BOOL;
}
let s = s2u!(selector);
let handler = Box::new(callback);
let param = Box::into_raw(handler);
let ok = (_API.SciterSelectElements)(self.he, s.as_ptr(), inner::<T>, param as LPVOID);
let handler = unsafe { Box::from_raw(param) };
if ok != SCDOM_RESULT::OK {
return Err(ok);
}
return Ok(handler.result());
}
pub fn find_nearest_parent(&self, selector: &str) -> Result<Option<Element>> {
let mut p = HELEMENT!();
let s = s2u!(selector);
let ok = (_API.SciterSelectParent)(self.he, s.as_ptr(), 0, &mut p);
if ok != SCDOM_RESULT::OK {
return Err(ok);
}
if p.is_null() { Ok(None) } else { Ok(Some(Element::from(p))) }
}
pub fn find_first(&self, selector: &str) -> Result<Option<Element>> {
let cb = FindFirstElement::default();
let all = self.select_elements(selector, cb);
all.map(|mut x| { x.pop() })
}
pub fn find_all(&self, selector: &str) -> Result<Option<Vec<Element>>> {
let cb = FindAllElements::default();
let all = self.select_elements(selector, cb);
all.map(Some)
}
pub fn update(&self, render_now: bool) -> Result<()> {
let ok = (_API.SciterUpdateElement)(self.he, render_now as BOOL);
ok_or!((), ok)
}
pub fn refresh(&self) -> Result<()> {
let rect = self.get_location(ELEMENT_AREAS::self_content())?;
let ok = (_API.SciterRefreshElementArea)(self.he, rect);
ok_or!((), ok)
}
pub fn start_timer(&self, period_ms: u32, timer_id: u64) -> Result<()> {
let ok = (_API.SciterSetTimer)(self.he, period_ms as UINT, timer_id as ::capi::sctypes::UINT_PTR);
ok_or!((), ok)
}
pub fn stop_timer(&self, timer_id: u64) -> Result<()> {
if !self.he.is_null() {
let ok = (_API.SciterSetTimer)(self.he, 0, timer_id as ::capi::sctypes::UINT_PTR);
ok_or!((), ok)
} else {
Ok(())
}
}
pub fn attach_handler<Handler: EventHandler>(&mut self, handler: Handler) -> Result<u64> {
let boxed = Box::new(handler);
let ptr = Box::into_raw(boxed); let token = ptr as usize as u64;
let ok = (_API.SciterAttachEventHandler)(self.he, ::eventhandler::_event_handler_proc::<Handler>, ptr as LPVOID);
ok_or!(token, ok)
}
pub fn detach_handler<Handler: EventHandler>(&mut self, token: u64) -> Result<()> {
let ptr = token as usize as *mut Handler;
let ok = (_API.SciterDetachEventHandler)(self.he, ::eventhandler::_event_handler_proc::<Handler>, ptr as LPVOID);
ok_or!((), ok)
}
}
impl Drop for Element {
fn drop(&mut self) {
(_API.Sciter_UnuseElement)(self.he);
self.he = HELEMENT!();
}
}
impl Clone for Element {
fn clone(&self) -> Self {
Element::from(self.he)
}
}
impl ::std::fmt::Display for Element {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
if self.he.is_null() {
return f.write_str("None");
}
let tag = self.get_tag();
f.write_str(&tag)?;
if let Some(i) = self.get_attribute("id") {
write!(f, "#{}", i)?;
}
if let Some(c) = self.get_attribute("class") {
write!(f, ".{}", c)?;
}
if let Some(t) = self.get_attribute("type") {
write!(f, "|{}", t)?;
}
if let Some(n) = self.get_attribute("name") {
write!(f, "({})", n)?;
}
return Ok(());
}
}
impl ::std::fmt::Debug for Element {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
if f.alternate() {
use ::std::mem;
fn state_name(value: &ELEMENT_STATE_BITS) -> &'static str {
match *value {
ELEMENT_STATE_BITS::STATE_LINK => "link",
ELEMENT_STATE_BITS::STATE_HOVER => "hover",
ELEMENT_STATE_BITS::STATE_ACTIVE => "active",
ELEMENT_STATE_BITS::STATE_VISITED => "visited",
ELEMENT_STATE_BITS::STATE_FOCUS => "focus",
ELEMENT_STATE_BITS::STATE_POPUP => "popup",
ELEMENT_STATE_BITS::STATE_CURRENT => "current",
ELEMENT_STATE_BITS::STATE_CHECKED => "checked",
ELEMENT_STATE_BITS::STATE_EXPANDED => "expanded",
ELEMENT_STATE_BITS::STATE_COLLAPSED => "collapsed",
ELEMENT_STATE_BITS::STATE_DISABLED => "disabled",
ELEMENT_STATE_BITS::STATE_INCOMPLETE => "incomplete",
ELEMENT_STATE_BITS::STATE_BUSY => "busy",
ELEMENT_STATE_BITS::STATE_ANIMATING => "animating",
ELEMENT_STATE_BITS::STATE_FOCUSABLE => "",
ELEMENT_STATE_BITS::STATE_READONLY => "readonly",
ELEMENT_STATE_BITS::STATE_EMPTY => "empty",
ELEMENT_STATE_BITS::STATE_ANCHOR => "anchor",
ELEMENT_STATE_BITS::STATE_SYNTHETIC => "synthetic",
ELEMENT_STATE_BITS::STATE_OWNS_POPUP => "owns_popup",
ELEMENT_STATE_BITS::STATE_TABFOCUS => "tabfocus",
ELEMENT_STATE_BITS::STATE_IS_RTL => "is_rtl",
ELEMENT_STATE_BITS::STATE_IS_LTR => "is_ltr",
ELEMENT_STATE_BITS::STATE_DRAG_OVER => "drag_over",
ELEMENT_STATE_BITS::STATE_DROP_TARGET => "drop_target",
ELEMENT_STATE_BITS::STATE_MOVING => "moving",
ELEMENT_STATE_BITS::STATE_COPYING => "copying",
ELEMENT_STATE_BITS::STATE_DRAG_SOURCE => "drag_source",
ELEMENT_STATE_BITS::STATE_DROP_MARKER => "drop_marker",
ELEMENT_STATE_BITS::STATE_READY => "",
ELEMENT_STATE_BITS::STATE_PRESSED => "pressed",
ELEMENT_STATE_BITS::STATE_NONE => "",
}
}
let state = self.get_state() as u32;
write!(f, "{{{}", self)?;
for i in 0..31 {
let bit = state & (1 << i);
if bit != 0 {
let state_bit: ELEMENT_STATE_BITS = unsafe { mem::transmute(bit) };
let name = state_name(&state_bit);
if !name.is_empty() {
write!(f, ":{}", name)?;
}
}
}
write!(f, "}}")
} else {
write!(f, "{{{}:{:?}}}", self, self.he)
}
}
}
pub struct Children<'a> {
base: &'a Element,
index: usize,
count: usize,
}
impl<'a> ::std::iter::Iterator for Children<'a> {
type Item = Element;
fn next(&mut self) -> Option<Element> {
if self.index < self.count {
let pos = self.index;
self.index += 1;
self.base.child(pos)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remain = self.count - self.index;
(remain, Some(remain))
}
fn count(self) -> usize {
self.count
}
}
impl<'a> ::std::iter::DoubleEndedIterator for Children<'a> {
fn next_back(&mut self) -> Option<Element> {
if self.index == self.count || self.count == 0 {
None
} else {
self.count -= 1;
self.base.child(self.count)
}
}
}
impl<'a> ::std::iter::IntoIterator for &'a Element {
type Item = Element;
type IntoIter = Children<'a>;
fn into_iter(self) -> Children<'a> {
self.children()
}
}
pub mod event {
pub use capi::scbehavior::{EVENT_GROUPS, BEHAVIOR_EVENTS, PHASE_MASK};
pub use capi::scbehavior::{CLICK_REASON, EDIT_CHANGED_REASON, DRAW_EVENTS};
use capi::sctypes::*;
use capi::scdom::HELEMENT;
use capi::scgraphics::HGFX;
use value::Value;
pub fn default_events() -> EVENT_GROUPS {
return EVENT_GROUPS::HANDLE_BEHAVIOR_EVENT | EVENT_GROUPS::HANDLE_SCRIPTING_METHOD_CALL | EVENT_GROUPS::HANDLE_METHOD_CALL;
}
#[derive(Debug)]
pub enum EventReason {
General(CLICK_REASON),
EditChanged(EDIT_CHANGED_REASON),
VideoBind(LPVOID),
}
#[derive(Debug)]
pub enum MethodParams<'a> {
Click,
IsEmpty(&'a mut bool),
GetValue(&'a mut Value),
SetValue(Value),
Custom(u32, LPVOID),
}
#[allow(unused_variables)]
pub trait EventHandler {
fn get_subscription(&mut self) -> Option<EVENT_GROUPS> {
return Some(default_events());
}
fn attached(&mut self, root: HELEMENT) {}
fn detached(&mut self, root: HELEMENT) {}
fn document_complete(&mut self, root: HELEMENT, target: HELEMENT) {}
fn document_close(&mut self, root: HELEMENT, target: HELEMENT) {}
fn on_method_call(&mut self, root: HELEMENT, params: MethodParams) -> bool { return false }
fn on_script_call(&mut self, root: HELEMENT, name: &str, args: &[Value]) -> Option<Value> {
return self.dispatch_script_call(root, name, args);
}
#[doc(hidden)]
fn dispatch_script_call(&mut self, root: HELEMENT, name: &str, args: &[Value]) -> Option<Value> {
return None;
}
#[doc(hidden)]
fn get_asset(&mut self) -> Option<&crate::capi::scom::som_asset_t> {
return None;
}
fn on_event(&mut self, root: HELEMENT, source: HELEMENT, target: HELEMENT, code: BEHAVIOR_EVENTS, phase: PHASE_MASK, reason: EventReason) -> bool {
return false;
}
fn on_timer(&mut self, root: HELEMENT, timer_id: u64) -> bool { return false; }
fn on_draw(&mut self, root: HELEMENT, gfx: HGFX, area: &RECT, layer: DRAW_EVENTS) -> bool { return false; }
fn on_size(&mut self, root: HELEMENT) {}
}
}