bool belongs_to( dom::element parent, dom::element child ) { if( !child.is_valid()) return false; if( parent == child ) return true; return belongs_to( parent, child.parent() ); }
// select bool select_tab( dom::element& tabs_el, dom::element& tab_el ) { if(tab_el.get_state(STATE_CURRENT)) // already selected, nothing to do... return true; // but we've handled it. //find currently selected element (tab and panel) and remove "selected" from them dom::element prev_panel_el = tabs_el.find_first(":root>[name]:expanded"); dom::element prev_tab_el = tabs_el.find_first(":root>.strip>[panel]:current"); // find new tab and panel const wchar_t* pname = tab_el.get_attribute("panel"); dom::element panel_el = tabs_el.find_first(":root>[name=\"%S\"]", pname); if( !panel_el.is_valid() || !tab_el.is_valid() ) { assert(false); // panel="somename" without matching name="somename" return true; } if( prev_panel_el.is_valid() ) { prev_panel_el.set_attribute("selected", 0); // remove selected attribute - just in case somone is using attribute selectors prev_panel_el.set_state(STATE_COLLAPSED,0); // set collapsed in case of someone use it for styling } if( prev_tab_el.is_valid() ) { prev_tab_el.set_attribute("selected", 0); // remove selected attribute prev_tab_el.set_state(0,STATE_CURRENT); // reset also state flag, :current } panel_el.set_attribute("selected", L""); // set selected attribute (empty) panel_el.set_state(STATE_EXPANDED,0); // expand it tab_el.set_attribute("selected", L""); // set selected attribute (empty) tab_el.set_state(STATE_CURRENT,0); // set also state flag, :current // notify all parties involved if (prev_tab_el.is_valid()) { prev_tab_el.post_event(ELEMENT_COLLAPSED,0, prev_tab_el); // source here is old collapsed tab itself } tab_el.post_event(ELEMENT_EXPANDED,0, tab_el); // source here is new expanded tab itself // NOTE #1: these event will bubble from panel elements up to the root so panel itself, tabs ctl, its parent, etc. // will receive these notifications. Handle them if you need to change UI dependent from current tab. // NOTE #2: while handling this event in: // virtual BOOL on_event (HELEMENT he, HELEMENT target, BEHAVIOR_EVENTS type, UINT reason ), // HELEMENT target is the panel element being collapsed/expanded return true; }
dom::element target_item(const dom::element& ctl, dom::element target) { if( target == ctl ) return dom::element(); if( !target.is_valid() ) return target; dom::element target_parent = target.parent(); if( !target_parent.is_valid() ) return target; if( target.test("li > .caption") ) return target_parent; // only if click on "caption" element of <li>. Returns that <li> element. return target_item( ctl, target.parent() ); }
virtual BOOL on_event (HELEMENT he, HELEMENT target, BEHAVIOR_EVENTS type, UINT_PTR reason ) { if( type != UI_STATE_CHANGED ) return FALSE; // we handle only UI_STATE_CHANGED here. assert(objects_bar.is_valid()); // call of getCurrentObjects method json::value stack = dom::element(he).xcall("getCurrentObjects"); assert(stack.is_array()); objects_bar.clear(); int n = stack.length(); for( int i = 0; i < n; ++i ) { dom::element li = dom::element::create("li", stack.nth(i).to_string()); objects_bar.append(li); } objects_bar.update(); return FALSE; /*mark it as not handled because some other behaviors in the chain may want to handle it */ }
dom::element target_row(const dom::element& table, const dom::element& target) { if( !target.is_valid() || target.parent() == table) return target; return target_row(table,target.parent()); }
dom::element target_header(const dom::element& header_row, const dom::element& target) { if( !target.is_valid() || target.parent() == header_row) return target; return target_header(header_row,target.parent()); }