void setup_node( dom::element node )
    {
      dom::element on = node.find_first("option[check='on'],options[check='on']");
      dom::element off = node.find_first("option[check='off'],options[check='off']");
      dom::element mixed = node.find_first("options[check='mixed']");

      const wchar_t* _prev = node.get_attribute(CHECK_ATTR);
      std::wstring  prev = _prev?_prev:L"";
      
      if( mixed.is_valid() || (on.is_valid() && off.is_valid()))
      {
        node.set_attribute(CHECK_ATTR,L"mixed");
        if(prev != L"mixed") node.update();
      }
      else if( on.is_valid() )
      {
        node.set_attribute(CHECK_ATTR,L"on");
        if(prev != L"on") node.update();
      }
      else
      {
        node.set_attribute(CHECK_ATTR,L"off");
        if(prev != L"off") node.update();
      }
    }
 void set_state(dom::element item, NODE_STATE st)
 {
     switch( st )
     {
     case NODE_ON: item.set_attribute("check",L"on"); break;
     case NODE_MIXED: item.set_attribute("check",L"mixed"); break;
     case NODE_OFF: item.set_attribute("check",L"off"); break;
     }
 }
Ejemplo n.º 3
0
    // 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;
    }
    //toggles checkmark
    void toggle_checkmark( dom::element select, dom::element item )
    {
      const wchar_t* _old_state = item.get_attribute(CHECK_ATTR);
      std::wstring  old_state = _old_state?_old_state:L"";

      if( streq(item.get_element_type(), "options"))
      {
        // non-terminal node case 
        
        // inner function
        struct child_toggler: dom::callback
        {
          const wchar_t* state;
          child_toggler(const wchar_t* st): state(st) {}
          inline bool on_element(HELEMENT he) 
          { 
            htmlayout::dom::element item = he; 
            item.set_attribute( CHECK_ATTR, state );
            return false;
          }
        };
        
        const wchar_t* new_state;
        NODE_STATE old_state = get_state(item);
        if(old_state == NODE_OFF)
          new_state = L"on";
        else 
          new_state = L"off";

        child_toggler ct( new_state );
        // do it for all children
        item.find_all(&ct, "option,options");
        // and for itself
        item.set_attribute( CHECK_ATTR, new_state );
        item.update();
      }
      else if( streq(item.get_element_type(), "option"))
      {
        // terminal node
        const wchar_t* new_state;
        if(wcseq(item.get_attribute("check"),L"on"))
        {
          new_state = L"off";
        }
        else 
          new_state = L"on";

        item.set_attribute( CHECK_ATTR, new_state );
        item.update();
      }
      
      // as state was changed we need to update parent chain here too.
      dom::element p = item.parent();
      while( p.is_valid() && p != select )
      {
        if( streq(p.get_element_type(),"options" ))
        {
          setup_node(p);
        }
        p = p.parent();
      }

    }