Files correlati : tutti Ricompilazione Demo : [ ] Commento : Migliorata gestione colori dei controlli git-svn-id: svn://10.65.10.50/trunk@17590 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			743 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			743 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <colors.h>
 | 
						|
#include <image.h>
 | 
						|
#include <tree.h>
 | 
						|
#include <urldefid.h>
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Callbacks
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
HIDDEN bool callback_compare_node(TTree& node, void* jolly, word when)
 | 
						|
{
 | 
						|
  const TString& id = *((TString*)jolly);
 | 
						|
  TString cur_id; node.curr_id(cur_id);
 | 
						|
  return id == cur_id;
 | 
						|
}
 | 
						|
 | 
						|
HIDDEN bool callback_expand_node(TTree& node, void* jolly, word when)
 | 
						|
{
 | 
						|
  if (when == SCAN_PRE_ORDER)
 | 
						|
    node.expand();
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
HIDDEN bool callback_find_father(TTree& node, void* jolly, word when)
 | 
						|
{
 | 
						|
  TString_array& father_and_son = *(TString_array*)jolly;
 | 
						|
  TString myself; node.curr_id(myself);
 | 
						|
 | 
						|
  if (when == SCAN_PRE_ORDER)
 | 
						|
  {
 | 
						|
    if (myself == father_and_son.row(1))
 | 
						|
      father_and_son.add(myself, 0);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (father_and_son.objptr(0))
 | 
						|
    {
 | 
						|
      father_and_son.add(myself, 0);
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
HIDDEN bool callback_find_brother(TTree& node, void* jolly, word when)
 | 
						|
{
 | 
						|
  TString_array& brother_and_sister = *(TString_array*)jolly;
 | 
						|
  TString myself; node.curr_id(myself);
 | 
						|
 | 
						|
  if (when == SCAN_PRE_ORDER)
 | 
						|
  {
 | 
						|
    if (myself == brother_and_sister.row(1))
 | 
						|
      brother_and_sister.add(myself, 0);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (brother_and_sister.objptr(0))
 | 
						|
    {
 | 
						|
      brother_and_sister.add(myself, 0);
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
//  TTtree
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
bool TTree::scan_depth_first(NODE_HANDLER nh, void* jolly, word flags)
 | 
						|
{
 | 
						|
  if ((flags & 0x7) == 0)
 | 
						|
    flags |= SCAN_PRE_ORDER;
 | 
						|
 | 
						|
  bool test_myself = true;
 | 
						|
  if ((flags & SCAN_IGNORING_LEAVES) && !has_son())
 | 
						|
    test_myself = false;
 | 
						|
 | 
						|
  TString myself;
 | 
						|
  curr_id(myself);
 | 
						|
 | 
						|
  if (test_myself)
 | 
						|
  {
 | 
						|
    if ((flags & SCAN_PRE_ORDER) && nh(*this, jolly, SCAN_PRE_ORDER))
 | 
						|
      return true;
 | 
						|
 | 
						|
    const bool stop = (flags & SCAN_IGNORING_UNEXPANDED) && !expanded();
 | 
						|
    if (!stop && goto_firstson())
 | 
						|
    {
 | 
						|
      if (scan_depth_first(nh, jolly, flags))
 | 
						|
        return true;
 | 
						|
      goto_node(myself);
 | 
						|
    }
 | 
						|
 | 
						|
    if ((flags & SCAN_IN_ORDER) && nh(*this, jolly, SCAN_IN_ORDER))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (goto_rbrother())
 | 
						|
  {
 | 
						|
    if (scan_depth_first(nh, jolly, flags))
 | 
						|
      return true;
 | 
						|
    goto_node(myself);
 | 
						|
  }
 | 
						|
 | 
						|
  if (test_myself)
 | 
						|
  {
 | 
						|
    if ((flags & SCAN_POST_ORDER) && nh(*this, jolly, SCAN_POST_ORDER))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::scan_breadth_first(NODE_HANDLER nh, void* jolly, word flags)
 | 
						|
{
 | 
						|
  if ((flags & 0x7) == 0)
 | 
						|
    flags |= SCAN_PRE_ORDER;
 | 
						|
 | 
						|
  bool test_myself = true;
 | 
						|
  if ((flags & SCAN_IGNORING_LEAVES) && !has_son())
 | 
						|
    test_myself = false;
 | 
						|
 | 
						|
  if (test_myself)
 | 
						|
  {
 | 
						|
    if ((flags & SCAN_PRE_ORDER) && nh(*this, jolly, SCAN_PRE_ORDER))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  TString myself;
 | 
						|
  curr_id(myself);
 | 
						|
 | 
						|
  if (goto_rbrother())
 | 
						|
  {
 | 
						|
    if (scan_breadth_first(nh, jolly, flags))
 | 
						|
      return true;
 | 
						|
    goto_node(myself);
 | 
						|
  }
 | 
						|
 | 
						|
  if (test_myself)
 | 
						|
  {
 | 
						|
    if ((flags & SCAN_IN_ORDER) && nh(*this, jolly, SCAN_IN_ORDER))
 | 
						|
      return true;
 | 
						|
 | 
						|
    const bool stop = (flags & SCAN_IGNORING_UNEXPANDED) && !expanded();
 | 
						|
    if (!stop && goto_firstson())
 | 
						|
    {
 | 
						|
      if (scan_breadth_first(nh, jolly, flags))
 | 
						|
        return true;
 | 
						|
      goto_node(myself);
 | 
						|
    }
 | 
						|
    if ((flags & SCAN_POST_ORDER) && nh(*this, jolly, SCAN_POST_ORDER))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::has_root() const
 | 
						|
{
 | 
						|
  TString myself; curr_id(myself);
 | 
						|
  bool ok = ((TTree*)this)->goto_root();
 | 
						|
  if (ok)
 | 
						|
    ((TTree*)this)->goto_node(myself);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::has_father() const
 | 
						|
{
 | 
						|
  TString myself; curr_id(myself);
 | 
						|
  bool ok = ((TTree*)this)->goto_father();
 | 
						|
  if (ok)
 | 
						|
    ((TTree*)this)->goto_node(myself);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::goto_father()
 | 
						|
{
 | 
						|
  TString myself; curr_id(myself);
 | 
						|
  bool ok = goto_root();
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    TString_array father_and_son;
 | 
						|
    father_and_son.add(myself, 1);
 | 
						|
    ok = scan_breadth_first(callback_find_father, &father_and_son,
 | 
						|
                            SCAN_PRE_ORDER | SCAN_IN_ORDER);
 | 
						|
  }
 | 
						|
  if (!ok)
 | 
						|
    goto_node(myself);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::has_lbrother() const
 | 
						|
{
 | 
						|
  TString myself; curr_id(myself);
 | 
						|
  bool ok = ((TTree*)this)->goto_lbrother();
 | 
						|
  if (ok)
 | 
						|
    ((TTree*)this)->goto_node(myself);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::goto_lbrother()
 | 
						|
{
 | 
						|
  TString myself; curr_id(myself);
 | 
						|
  bool ok = goto_root();
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    TString_array brother_and_sister;
 | 
						|
    brother_and_sister.add(myself, 1);
 | 
						|
    ok = scan_depth_first(callback_find_brother, &brother_and_sister,
 | 
						|
                          SCAN_PRE_ORDER | SCAN_POST_ORDER);
 | 
						|
  }
 | 
						|
  if (!ok)
 | 
						|
    goto_node(myself);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::has_rbrother() const
 | 
						|
{
 | 
						|
  TString myself; curr_id(myself);
 | 
						|
  bool ok = ((TTree*)this)->goto_rbrother();
 | 
						|
  if (ok)
 | 
						|
    ((TTree*)this)->goto_node(myself);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::has_son() const
 | 
						|
{
 | 
						|
  TString myself; curr_id(myself);
 | 
						|
  bool ok = ((TTree*)this)->goto_firstson();
 | 
						|
  if (ok)
 | 
						|
    ((TTree*)this)->goto_node(myself);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::expanded() const
 | 
						|
{
 | 
						|
  TString str; curr_id(str);
 | 
						|
  bool yes = _expanded.is_key(str);
 | 
						|
  return yes;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::expand()
 | 
						|
{
 | 
						|
  bool ok = enabled() && has_son();
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    TString str; curr_id(str);
 | 
						|
    ok = !_expanded.is_key(str);
 | 
						|
    if (ok)
 | 
						|
      _expanded.add(str);
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::shrink()
 | 
						|
{
 | 
						|
  TString str; curr_id(str);
 | 
						|
  bool ok = _expanded.is_key(str);
 | 
						|
  if (ok)
 | 
						|
    _expanded.remove(str);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::expand_all()
 | 
						|
{
 | 
						|
  bool ok = goto_root();
 | 
						|
  if (ok)
 | 
						|
    scan_breadth_first(callback_expand_node, NULL);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TTree::shrink_all()
 | 
						|
{
 | 
						|
  _expanded.destroy();
 | 
						|
  return goto_root();
 | 
						|
}
 | 
						|
 | 
						|
TImage* TTree::get_res_image(short bmp_id) const
 | 
						|
{
 | 
						|
  TImage* bmp = (TImage*)_image.objptr(bmp_id);
 | 
						|
  if (bmp == NULL)
 | 
						|
  {
 | 
						|
    bmp = new TImage(bmp_id);
 | 
						|
    if (bmp->ok())
 | 
						|
    {
 | 
						|
      bmp->convert_transparent_color(NORMAL_BACK_COLOR);
 | 
						|
      ((TTree*)this)->_image.add(bmp, bmp_id);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      delete bmp;
 | 
						|
      bmp = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return bmp;
 | 
						|
}
 | 
						|
 | 
						|
TImage* TTree::get_res_icon(short icon_id) const
 | 
						|
{
 | 
						|
  const int id = 100000 + icon_id;
 | 
						|
  TImage* bmp = (TImage*)_image.objptr(id);
 | 
						|
  if (bmp == NULL)
 | 
						|
  {
 | 
						|
    TImage ico(icon_id, true);
 | 
						|
    if (ico.ok())
 | 
						|
    {
 | 
						|
      const TImage* def = get_res_image(BMP_FILE);
 | 
						|
      int w = 16, h = 16;
 | 
						|
      if (def != NULL) 
 | 
						|
      {
 | 
						|
        w = def->width();
 | 
						|
        h = def->height();
 | 
						|
      }
 | 
						|
      ico.convert_transparent_color(NORMAL_BACK_COLOR);
 | 
						|
      bmp = new TImage(ico, w, h);
 | 
						|
      ((TTree*)this)->_image.add(bmp, id);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return bmp;
 | 
						|
}
 | 
						|
 | 
						|
TImage* TTree::image(bool selected) const
 | 
						|
{
 | 
						|
  short bmp_id = BMP_FILE;
 | 
						|
  if (has_son())
 | 
						|
    bmp_id = selected ? BMP_DIRDN : BMP_DIR;
 | 
						|
  return get_res_image(bmp_id);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
//  TBidirectional_tree
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
bool TBidirectional_tree::scan_depth_first(NODE_HANDLER nh, void* jolly, word flags)
 | 
						|
{
 | 
						|
  if ((flags & 0x7) == 0)
 | 
						|
    flags |= SCAN_PRE_ORDER;
 | 
						|
 | 
						|
  bool test_myself = true;
 | 
						|
  if ((flags & SCAN_IGNORING_LEAVES) && !has_son())
 | 
						|
    test_myself = false;
 | 
						|
 | 
						|
  if (test_myself)
 | 
						|
  {
 | 
						|
    if ((flags & SCAN_PRE_ORDER) && nh(*this, jolly, SCAN_PRE_ORDER))
 | 
						|
      return true;
 | 
						|
 | 
						|
    const bool stop = (flags & SCAN_IGNORING_UNEXPANDED) && !expanded();
 | 
						|
    if (!stop && goto_firstson())
 | 
						|
    {
 | 
						|
      if (scan_depth_first(nh, jolly, flags))
 | 
						|
        return true;
 | 
						|
      goto_father();
 | 
						|
    }
 | 
						|
 | 
						|
    if ((flags & SCAN_IN_ORDER) && nh(*this, jolly, SCAN_IN_ORDER))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (goto_rbrother())
 | 
						|
  {
 | 
						|
    if (scan_depth_first(nh, jolly, flags))
 | 
						|
      return true;
 | 
						|
    goto_lbrother();
 | 
						|
  }
 | 
						|
 | 
						|
  if (test_myself)
 | 
						|
  {
 | 
						|
    if ((flags & SCAN_POST_ORDER) && nh(*this, jolly, SCAN_POST_ORDER))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool TBidirectional_tree::scan_breadth_first(NODE_HANDLER nh, void* jolly, word flags)
 | 
						|
{
 | 
						|
  if ((flags & 0x7) == 0)
 | 
						|
    flags |= SCAN_PRE_ORDER;
 | 
						|
 | 
						|
  bool test_myself = true;
 | 
						|
  if ((flags & SCAN_IGNORING_LEAVES) && !has_son())
 | 
						|
    test_myself = false;
 | 
						|
 | 
						|
  if (test_myself)
 | 
						|
  {
 | 
						|
    if ((flags & SCAN_PRE_ORDER) && nh(*this, jolly, SCAN_PRE_ORDER))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (goto_rbrother())
 | 
						|
  {
 | 
						|
    if (scan_breadth_first(nh, jolly, flags))
 | 
						|
      return true;
 | 
						|
    goto_lbrother();
 | 
						|
  }
 | 
						|
 | 
						|
  if (test_myself)
 | 
						|
  {
 | 
						|
    if ((flags & SCAN_IN_ORDER) && nh(*this, jolly, SCAN_IN_ORDER))
 | 
						|
      return true;
 | 
						|
    const bool stop = (flags & SCAN_IGNORING_UNEXPANDED) && !expanded();
 | 
						|
    if (!stop && goto_firstson())
 | 
						|
    {
 | 
						|
      if (scan_breadth_first(nh, jolly, flags))
 | 
						|
        return true;
 | 
						|
      goto_father();
 | 
						|
    }
 | 
						|
    if ((flags & SCAN_POST_ORDER) && nh(*this, jolly, SCAN_POST_ORDER))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool TBidirectional_tree::goto_node(const TString &id)
 | 
						|
{
 | 
						|
  bool ok = goto_root();
 | 
						|
  if (ok && id.not_empty())
 | 
						|
    ok = scan_breadth_first(callback_compare_node, (void *)&id);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TObject tree
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
bool TObject_tree::expanded() const
 | 
						|
{
 | 
						|
  bool ok = _current && _current->_expanded;
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::expand()
 | 
						|
{
 | 
						|
  bool ok = _current && _current->_son && !_current->_expanded && enabled();
 | 
						|
  if (ok)
 | 
						|
    _current->_expanded = true;
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::shrink()
 | 
						|
{
 | 
						|
  bool ok = _current && _current->_expanded;
 | 
						|
  if (ok)
 | 
						|
    _current->_expanded = false;
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
void TObject_tree::node2id(const TObject* node, TString& id) const
 | 
						|
{
 | 
						|
  id.format("%p", (const void*)node);
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::goto_node(const TString& node)
 | 
						|
{
 | 
						|
  void* p = NULL;
 | 
						|
  if (node.not_empty())
 | 
						|
  {
 | 
						|
#ifdef DBG_TREE
 | 
						|
    if (!_expanded.is_key(node)) // Usa l'assoc array per testare i nodi validi!
 | 
						|
    {
 | 
						|
      NFCHECK("Invalid node: %s", (const char*)node);
 | 
						|
      return goto_root();
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    sscanf(node, "%p", &p);
 | 
						|
  }
 | 
						|
 | 
						|
  bool ok = true;
 | 
						|
  if (p == NULL)
 | 
						|
    ok = goto_root();
 | 
						|
  else
 | 
						|
    _current = (TTree_node*)p;
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::goto_root()
 | 
						|
{
 | 
						|
  _current = _root;
 | 
						|
  return _root != NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::goto_firstson()
 | 
						|
{
 | 
						|
  TTree_node* n = _current ? _current->_son : NULL;
 | 
						|
  if (n) _current = n;
 | 
						|
  return n != NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::goto_rbrother()
 | 
						|
{
 | 
						|
  TTree_node* n = _current ? _current->_rbrother : NULL;
 | 
						|
  if (n) _current = n;
 | 
						|
  return n != NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::goto_father()
 | 
						|
{
 | 
						|
  TTree_node* n = _current ? _current->_father : NULL;
 | 
						|
  if (n) _current = n;
 | 
						|
  return n != NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::goto_lbrother()
 | 
						|
{
 | 
						|
  TTree_node* n = _current ? _current->_lbrother : NULL;
 | 
						|
  if (n) _current = n;
 | 
						|
  return n != NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::set_object(TObject* obj)
 | 
						|
{
 | 
						|
  if (_current)
 | 
						|
  {
 | 
						|
#ifdef DBG_TREE
 | 
						|
    TString str; curr_id(str);
 | 
						|
    _expanded.add(str); // Usa l'assoc array per memorizzare i nodi validi!
 | 
						|
#endif
 | 
						|
    if (_current->_obj)
 | 
						|
      delete _current->_obj;
 | 
						|
    _current->_obj = obj;
 | 
						|
  }
 | 
						|
  return _current != NULL;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::set_object(const TObject& obj)
 | 
						|
{
 | 
						|
  bool ok = false;
 | 
						|
  if (_current)
 | 
						|
  {
 | 
						|
    TObject* ptr = obj.dup();
 | 
						|
    ok = set_object(ptr);
 | 
						|
    if (!ok)
 | 
						|
      delete ptr;
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::create_root()
 | 
						|
{
 | 
						|
  if (!has_root())
 | 
						|
    _root = _current = new TTree_node;
 | 
						|
  return goto_root();
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::add_son(TObject* obj)
 | 
						|
{
 | 
						|
  bool ok = false;
 | 
						|
  if (_root)
 | 
						|
  {
 | 
						|
    TTree_node*& curson = _current->_son;
 | 
						|
    TTree_node* newson = new TTree_node;
 | 
						|
    newson->_father = _current;
 | 
						|
    if (curson != NULL)
 | 
						|
    {
 | 
						|
      curson->_lbrother = newson;
 | 
						|
      newson->_rbrother = curson;
 | 
						|
    }
 | 
						|
    curson = newson;
 | 
						|
    ok = goto_firstson();
 | 
						|
  }
 | 
						|
  else
 | 
						|
    ok = create_root();
 | 
						|
 | 
						|
  if (ok)
 | 
						|
    ok = set_object(obj);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::add_son(const TObject& obj)
 | 
						|
{
 | 
						|
  TObject* ptr = obj.dup();
 | 
						|
  bool ok = add_son(ptr);
 | 
						|
  if (!ok) delete ptr;
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::add_brother(TObject* obj)
 | 
						|
{
 | 
						|
  bool ok = false;
 | 
						|
  if (goto_father())
 | 
						|
    ok = add_son(obj);
 | 
						|
  else
 | 
						|
    ok = create_root() && set_object(obj);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::add_brother(const TObject& obj)
 | 
						|
{
 | 
						|
  TObject* ptr = obj.dup();
 | 
						|
  bool ok = add_brother(ptr);
 | 
						|
  if (!ok) delete ptr;
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::add_rbrother(TObject* obj)
 | 
						|
{
 | 
						|
  bool ok = false;
 | 
						|
  if (has_father())
 | 
						|
  {
 | 
						|
    TTree_node* newbrother = new TTree_node;
 | 
						|
    newbrother->_father    = _current->_father;
 | 
						|
    newbrother->_lbrother  = _current;
 | 
						|
    newbrother->_rbrother  = _current->_rbrother;
 | 
						|
    _current->_rbrother    = newbrother;
 | 
						|
    ok = goto_rbrother();
 | 
						|
  }
 | 
						|
  else
 | 
						|
    ok = create_root();
 | 
						|
 | 
						|
  if (ok)
 | 
						|
    set_object(obj);
 | 
						|
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::add_rbrother(const TObject& obj)
 | 
						|
{
 | 
						|
  TObject* ptr = obj.dup();
 | 
						|
  bool ok = add_rbrother(ptr);
 | 
						|
  if (!ok) delete ptr;
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::add_lbrother(TObject* obj)
 | 
						|
{
 | 
						|
  bool ok = false;
 | 
						|
  if (has_father())
 | 
						|
  {
 | 
						|
    if (_current->_lbrother == NULL)
 | 
						|
      ok = add_brother(obj);
 | 
						|
    else
 | 
						|
    {
 | 
						|
      TTree_node* newbrother = new TTree_node;
 | 
						|
      newbrother->_father    = _current->_father;
 | 
						|
      newbrother->_rbrother  = _current;
 | 
						|
      newbrother->_lbrother  = _current->_lbrother;
 | 
						|
      _current->_lbrother    = newbrother;
 | 
						|
      ok = goto_lbrother();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
    ok = create_root();
 | 
						|
  if (ok)
 | 
						|
    set_object(obj);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::add_lbrother(const TObject& obj)
 | 
						|
{
 | 
						|
  TObject* ptr = obj.dup();
 | 
						|
  bool ok = add_lbrother(ptr);
 | 
						|
  if (!ok) delete ptr;
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::kill_node()
 | 
						|
{
 | 
						|
  bool ok = false;
 | 
						|
  if (_current)
 | 
						|
  {
 | 
						|
    TTree_node* cur = _current;
 | 
						|
    while (goto_firstson())
 | 
						|
    {
 | 
						|
      kill_node();
 | 
						|
      _current = cur;
 | 
						|
    }
 | 
						|
    if (_current->_lbrother)
 | 
						|
    {
 | 
						|
      _current->_lbrother->_rbrother = _current->_rbrother;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (_current->_father)
 | 
						|
        _current->_father->_son = _current->_rbrother;
 | 
						|
    }
 | 
						|
    if (_current->_rbrother)
 | 
						|
      _current->_rbrother->_lbrother = _current->_lbrother;
 | 
						|
 | 
						|
#ifdef DBG_TREE
 | 
						|
    TString id; curr_id(id);
 | 
						|
    _expanded.remove(id);
 | 
						|
#endif
 | 
						|
 | 
						|
    TTree_node* to_be_killed = _current;
 | 
						|
 | 
						|
    if (_current == _root)
 | 
						|
       _root = NULL;
 | 
						|
 | 
						|
    if (_current->_rbrother)
 | 
						|
      _current = _current->_rbrother;
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (_current->_lbrother)
 | 
						|
        _current = _current->_lbrother;
 | 
						|
      else
 | 
						|
        _current = _current->_father;
 | 
						|
    }
 | 
						|
 | 
						|
    delete to_be_killed;
 | 
						|
 | 
						|
    ok = true;
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TObject_tree::get_description(TString& str) const
 | 
						|
{
 | 
						|
  TObject* obj = curr_node();
 | 
						|
  if (obj)
 | 
						|
    str << *obj;
 | 
						|
  return obj != NULL;
 | 
						|
}
 | 
						|
 | 
						|
TObject_tree::TObject_tree()
 | 
						|
{
 | 
						|
  _root = _current = NULL;
 | 
						|
}
 | 
						|
 | 
						|
TObject_tree::~TObject_tree()
 | 
						|
{
 | 
						|
  if (goto_root())
 | 
						|
    kill_node();
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TString_tree
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
bool TString_tree::get_description(TString& str) const
 | 
						|
{
 | 
						|
  const TString* obj = (const TString*)curr_node();
 | 
						|
  if (obj)
 | 
						|
    str = *obj;
 | 
						|
  else
 | 
						|
    str.cut(0);
 | 
						|
  return obj != NULL;
 | 
						|
}
 | 
						|
 |