/** set current row **/
    void set_current_row( dom::element& table, dom::element& row, UINT keyboardStates, bool dblClick = false, bool smooth = false )
    {
      // get previously selected row:
      dom::element prev = get_current_row( table );

      uint new_row_checked = STATE_CHECKED;
      uint old_row_checked = STATE_CHECKED;

      if(is_multiple(table))
      {
         if (keyboardStates & SHIFT_KEY_PRESSED)
         {
            checkall(table, false);
            check_range(table,row.index(),TRUE); // from current to new
         } 
         else 
         {      
           if (keyboardStates & CONTROL_KEY_PRESSED)
           {
             set_checked_row (table,row, true); // toggle
             new_row_checked = 0;
           }
           else
             checkall(table, false);
           set_anchor(table,row.index ());
         }
         old_row_checked = 0;
      }
      
      if( prev.is_valid() )
      {
        if( prev != row ) 
          prev.set_state(0,STATE_CURRENT | old_row_checked); // drop state flags
      }
      row.set_state(STATE_CURRENT | new_row_checked); // set state flags
      row.scroll_to_view(false,smooth);
      //::UpdateWindow(row.get_element_hwnd(false));
      table.post_event( dblClick? TABLE_ROW_DBL_CLICK:TABLE_ROW_CLICK, row.index(), row); 
      table.post_event(WY_GRID_VERTICAL_SCROLL, 0);
    }
    virtual BOOL on_key(HELEMENT he, HELEMENT target, UINT event_type, UINT code, UINT keyboardStates ) 
    { 
      if( event_type == KEY_DOWN )
      {
        dom::element table = he;
        switch( code )
        {
          case VK_DOWN: 
            {
               dom::element c = get_current_row( table );
               int idx = c.is_valid()? (c.index() + 1):fixed_rows(table);
               while( idx < (int)table.children_count() )
               {
                   dom::element row = table.child(idx);
                   if( wcseq(row.get_style_attribute("display"),L"none" ))
                   {
                     ++idx;
                     continue;
                   }
                   set_current_row(table, row, keyboardStates); 
                   break;
               }
            }
            return TRUE;
          case VK_UP:             
            {
               dom::element c = get_current_row( table );
               int idx = c.is_valid()? (c.index() - 1):(table.children_count() - 1);
               while( idx >= fixed_rows(table) )
               {
                   dom::element row = table.child(idx);
                   if( wcseq(row.get_style_attribute("display"),L"none" ))
                   {
                     --idx;
                     continue;
                   }
                   set_current_row(table, row, keyboardStates); 
                   break;
               }
            }
            return TRUE;
          case VK_PRIOR:
            {
               RECT trc = table.get_location(ROOT_RELATIVE | SCROLLABLE_AREA);
               int y = trc.top - (trc.bottom - trc.top);
               int first = fixed_rows(table);
               dom::element r;
               for( int i = table.children_count() - 1; i >= first; --i )
               {
                   dom::element nr = table.child(i);
                   if( wcseq(nr.get_style_attribute("display"),L"none" ))
                     continue;
                   dom::element pr = r;
                   r = nr;
                   if( r.get_location(ROOT_RELATIVE | BORDER_BOX).top < y )
                   {
                      // row found
                      if(pr.is_valid()) r = pr; // to last fully visible
                      break;
                   }
               }
               set_current_row(table, r, keyboardStates); 
            }
            return TRUE;

          case VK_NEXT:
            {
               RECT trc = table.get_location(ROOT_RELATIVE | SCROLLABLE_AREA);
               int y = trc.bottom + (trc.bottom - trc.top);
               int last = table.children_count() - 1;
               dom::element r; 
               for( int i = fixed_rows(table); i <= last; ++i )
               {
                   dom::element nr = table.child(i);
                   if( wcseq(nr.get_style_attribute("display"),L"none" ))
                     continue;
                   dom::element pr = r;
                   r = nr;
                   if( r.get_location(ROOT_RELATIVE | BORDER_BOX).bottom > y )
                   {
                      // row found
                      if(pr.is_valid()) r = pr; // to last fully visible
                      break;
                   }
               }
               set_current_row(table, r, keyboardStates); 
            }
            return TRUE;

          case VK_HOME:
            {
               int idx = fixed_rows(table);
               while( (int)idx < (int)table.children_count() )
               {
                   dom::element row = table.child(idx);
                   if( wcseq(row.get_style_attribute("display"),L"none" ))
                   {
                     ++idx;
                     continue;
                   }
                   set_current_row(table, row, keyboardStates); 
                   break;
               }
            }
            return TRUE;

          case VK_END:
            {
               int idx = table.children_count() - 1;
               while( idx >= fixed_rows(table) )
               {
                   dom::element row = table.child(idx);
                   if( wcseq(row.get_style_attribute("display"),L"none" ))
                   {
                     --idx;
                     continue;
                   }
                   set_current_row(table, row, keyboardStates); 
                   break;
               }
            }
            return TRUE;
          case 'A':
            if( is_multiple(table) && (keyboardStates & CONTROL_KEY_PRESSED) != 0 )
            {
              checkall(table, true);
              return TRUE;
            }
            return FALSE;
        }
      }
      return FALSE; 
    }