flu_tree_browser.cpp

来自「ncbi源码」· C++ 代码 · 共 2,583 行 · 第 1/5 页

CPP
2,583
字号
    return -1;  int index;  if( search( n, index ) )    {      // move all the others down one spot to remove the node      for( int i = index; i < _nNodes-1; i++ )	_nodes[i] = _nodes[i+1];      _nNodes--;      return index;    }  return -1;}void Flu_Tree_Browser :: NodeList :: erase( int n ){  // make sure n is in range  if( ( n < 0 ) || ( n >= _nNodes ) )    return;  // move all the others down one spot to remove the node  for( int i = n; i < _nNodes-1; i++ )    _nodes[i] = _nodes[i+1];  _nNodes--;}void Flu_Tree_Browser :: NodeList :: clear(){  if( _nodes )    {      //if( _nNodes )      //if( _nodes[0] )      //  _nodes[0]->tree->rdata.cbNode = NULL;      delete[] _nodes;    }  _nodes = NULL;  _nNodes = _size = 0;}int Flu_Tree_Browser :: NodeList :: findNum( const char *n ){  if( ( _nNodes == 0 ) || ( n == 0 ) )    return 0;  // see if there is a first node equal to "n"  int index, last;  if( !search( n, index ) )    return 0;  // now search forward until we hit a node not equal to "n"  for( last = index; last < _nNodes-1; last++ )    if( strcmp( n, _nodes[last+1]->label() ) != 0 )      break;  return last - index + 1;}Flu_Tree_Browser::Node* Flu_Tree_Browser :: NodeList :: find( const char* n, int which ){  if( ( _nNodes == 0 ) || ( n == 0 ) || ( which == 0 ) )    return NULL;  // see if there is a first node equal to "n"  int index, first;  if( !search( n, first ) )    return NULL;  // now search forward and try to find the which'th node named "n"  int total = 0;  for( index = first; index < _nNodes; index++ )    {      if( strcmp( n, _nodes[index]->label() ) == 0 )	{	  total++;	  if( total == which )	    break;	}      else	break;    }  if( total != which )    return NULL;  return _nodes[index];}#define SCROLL_SIZE 15Flu_Tree_Browser :: Flu_Tree_Browser( int x, int y, int w, int h, const char *l )  : Fl_Group( x, y, w, h )#ifdef USE_FLU_DND  , Flu_DND( "Flu_Tree_Browser" )#endif{  lastEvent = -1;  autoScrollX = autoScrollY = 0.0f;#ifdef USE_FLU_DND  dnd_allow_type( "Flu_Tree_Browser" );  dnd_allow_type( "DND_Object" );  dnd_allow_text( true );#endif  // add some widgets  _box = new Fl_Group( x, y, w-SCROLL_SIZE, h-SCROLL_SIZE );  _box->resizable( NULL );  _box->end();  scrollV = new Fl_Scrollbar( x+w-SCROLL_SIZE, y, SCROLL_SIZE, h-SCROLL_SIZE );  scrollV->type( FL_VERTICAL );  scrollV->callback( _scrollCB, this );  scrollV->value( 0, 1, 0, 0 );  scrollH = new Fl_Scrollbar( x, y+h-SCROLL_SIZE, w-SCROLL_SIZE, SCROLL_SIZE );  scrollH->type( FL_HORIZONTAL );  scrollH->callback( _scrollCB, this );  scrollH->value( 0, 1, 0, 0 );  scrollBox = new Fl_Group( x+w-SCROLL_SIZE, y+h-SCROLL_SIZE, SCROLL_SIZE, SCROLL_SIZE );  scrollBox->box( FL_UP_BOX );  scrollBox->end();  resizable( _box );  // set up the recursive data structure  memset( &rdata, 0, sizeof(rdata) );  rdata.root = &root;  root.tree = this;  rdata.tree = this;  rdata.dragging = false;  rdata.forceResize = true;  rdata.shiftSelect = false;  rdata.shiftSelectAll = false;  rdata.nextId = 1;  rdata.searchIndex = 1;  rdata.defaultCollapseIcons[0] = new Fl_Pixmap( (char*const*)plus_xpm );  rdata.defaultCollapseIcons[1] = new Fl_Pixmap( (char*const*)minus_xpm );  rdata.defaultBranchIcons[0] = new Fl_Pixmap( (char*const*)folder_closed_xpm );  rdata.defaultBranchIcons[1] = new Fl_Pixmap( (char*const*)folder_open_xpm );  end();  // set the default values for the tree  auto_branches( false );  animate( false );  collapse_time( 0.1f );  double_click_opens( true );  move_only_same_group( false );  frame_rate( 100.0f );  allow_leaf_duplication( true );  shaded_entry_colors( FL_WHITE, FL_WHITE );  collapse_icons( NULL, NULL );  //branch_icons( NULL, NULL );  rdata.branchIcons[0] = rdata.defaultBranchIcons[0];  rdata.branchIcons[1] = rdata.defaultBranchIcons[1];  leaf_icon( NULL );  branch_text( FL_BLACK, FL_HELVETICA_BOLD, 12 );  leaf_text( FL_BLACK, FL_HELVETICA, 12 );  callback( NULL );  when( FL_WHEN_CHANGED );  color( FL_WHITE );  selection_color( FL_SELECTION_COLOR );  box( FL_NO_BOX );  connector_style( FL_DARK2, FL_DOT );  selection_mode( FLU_MULTI_SELECT );  selection_drag_mode( FLU_DRAG_TO_SELECT );  insertion_mode( FLU_INSERT_SORTED );  show_connectors( true );  show_root( true );  show_leaves( true );  show_branches( true );  open_on_select( false );  //root_always_open( false );  horizontal_gap( 2 );  vertical_gap( 0 );  widget_gap( 2 );  set_root( l );}Flu_Tree_Browser :: ~Flu_Tree_Browser(){  Fl::remove_timeout( _timerRedrawCB, this );  Fl::remove_timeout( _timerScrollCB, this );  delete rdata.defaultCollapseIcons[0];  delete rdata.defaultCollapseIcons[1];  delete rdata.defaultBranchIcons[0];  delete rdata.defaultBranchIcons[1];}void Flu_Tree_Browser :: auto_branches( bool b ){  rdata.autoBranches = b;}void Flu_Tree_Browser :: collapse_icons( Fl_Image *closed, Fl_Image *open ){  if( closed )    rdata.collapseIcons[0] = closed;  else    rdata.collapseIcons[0] = rdata.defaultCollapseIcons[0];  if( open )    rdata.collapseIcons[1] = open;  else    rdata.collapseIcons[1] = rdata.defaultCollapseIcons[1];}void Flu_Tree_Browser :: branch_icons( Fl_Image *closed, Fl_Image *open ){  if( closed )    rdata.branchIcons[0] = closed;  //else  //rdata.branchIcons[0] = rdata.defaultBranchIcons[0];  if( open )    rdata.branchIcons[1] = open;  //else  //rdata.branchIcons[1] = rdata.defaultBranchIcons[1];}void Flu_Tree_Browser :: leaf_icon( Fl_Image *icon ){  rdata.leafIcon = icon;}void Flu_Tree_Browser :: resize( int X, int Y, int W, int H ){  Fl_Group::resize( X, Y, W, H );  int dx = Fl::box_dx(box()), dy = Fl::box_dy(box()), dw = Fl::box_dw(box()), dh = Fl::box_dh(box());  rdata.x = X+dx; rdata.y = Y+dy; rdata.totalW = rdata.x;  root.recurse( rdata, Node::MEASURE );  rdata.totalW -= X-dx;  rdata.totalH = rdata.y - Y-dy;  // if the size of the tree is bigger than the window, turn on the scrollbars  bool hOn = false, vOn = false;  if( rdata.totalW > W-dw )    hOn = true;  if( rdata.totalH > H-dh )    vOn = true;  // check if turning on one scrollbar actually forces the other to turn on  if( hOn && ( rdata.totalH > H-SCROLL_SIZE ) )    vOn = true;  if( vOn && ( rdata.totalW > W-SCROLL_SIZE ) )    hOn = true;  // now resize the other kids depending on the state of the scrollbars  _box->resize( X, Y, W, H );  if( hOn && vOn )  // both scrollbars on    {      scrollH->resize( X+dx, Y+H-SCROLL_SIZE-dy, W-SCROLL_SIZE-dw, SCROLL_SIZE );      scrollH->show();      scrollV->resize( X+W-SCROLL_SIZE-dx, Y+dy, SCROLL_SIZE, H-SCROLL_SIZE-dh );      scrollV->show();      scrollBox->resize( X+W-SCROLL_SIZE-dx, Y+H-SCROLL_SIZE-dy, SCROLL_SIZE, SCROLL_SIZE );      scrollBox->show();      // set the scrollbar sizes and values      int hDelta = rdata.totalW - W+dw + SCROLL_SIZE, scrollHW = scrollH->w()-SCROLL_SIZE-SCROLL_SIZE;      hDelta = MAX( hDelta, 0 );      scrollH->value( MIN( scrollH->value(), hDelta ), 1, 0, hDelta );      scrollH->slider_size( MAX( (float)SCROLL_SIZE/float(scrollHW), float(scrollHW-hDelta)/float(scrollHW) ) );      int vDelta = rdata.totalH - H+dh + SCROLL_SIZE, scrollVH = scrollV->h()-SCROLL_SIZE-SCROLL_SIZE;      vDelta = MAX( vDelta, 0 );      scrollV->value( MIN( scrollV->value(), vDelta ), 1, 0, vDelta );      scrollV->slider_size( MAX( (float)SCROLL_SIZE/float(scrollVH), float(scrollVH-vDelta)/float(scrollVH) ) );    }  else if( !hOn && !vOn )  // neither on    {      scrollH->hide();      scrollV->hide();      scrollBox->hide();    }  else if( hOn )  // just horizontal on    {      scrollH->resize( X+dx, Y+H-SCROLL_SIZE-dy, W-dw, SCROLL_SIZE );      scrollH->show();      scrollV->hide();      scrollBox->hide();      // set the scrollbar size and value      int hDelta = rdata.totalW - W+dw, scrollHW = scrollH->w()-SCROLL_SIZE-SCROLL_SIZE;      hDelta = MAX( hDelta, 0 );      scrollH->value( MIN( scrollH->value(), hDelta ), 1, 0, hDelta );      scrollH->slider_size( MAX( (float)SCROLL_SIZE/float(scrollHW), float(scrollHW-hDelta)/float(scrollHW) ) );    }  else if( vOn )  // just vertical on    {      scrollH->hide();      scrollV->resize( X+W-SCROLL_SIZE-dx, Y+dy, SCROLL_SIZE, H-dh );      scrollV->show();      scrollBox->hide();      // set the scrollbar size and value      int vDelta = rdata.totalH - H+dh, scrollVH = scrollV->h()-SCROLL_SIZE-SCROLL_SIZE;      vDelta = MAX( vDelta, 0 );      scrollV->value( MIN( scrollV->value(), vDelta ), 1, 0, vDelta );      scrollV->slider_size( MAX( (float)SCROLL_SIZE/float(scrollVH), float(scrollVH-vDelta)/float(scrollVH) ) );    }  rdata.browserX = _box->x() + dx;  rdata.browserY = _box->y() + dy;  rdata.browserW = _box->w() - dw;  rdata.browserH = _box->h() - dh;  redraw();  rdata.forceResize = true;  // weird hack to get the scrollbars to turn on right the first time}void Flu_Tree_Browser :: on_dnd_leave(){#ifdef USE_FLU_DND  rdata.isMoveValid = false;  redraw();  // X  if( scrollH->visible() )    {      float max = 0.01f * (scrollH->maximum() - scrollH->minimum());      if( max < 10.0f ) max = 10.0f;      if( autoScrollX > 0.0f )	autoScrollX = max;      else	autoScrollX = -max;    }  // Y  if( scrollV->visible() )    {      float max = 0.01f * (scrollV->maximum() - scrollV->minimum());      if( max < 10.0f ) max = 10.0f;      if( autoScrollY > 0.0f )	autoScrollY = max;      else	autoScrollY = -max;    }#endif}bool Flu_Tree_Browser :: on_dnd_drag( int X, int Y ){#ifdef USE_FLU_DND  rdata.dragging = true;  autoScrollX = autoScrollY = 0.0f;  if( scrollH->visible() )    {      // auto-scroll the horizontal scrollbars based on how close to the left or right of the browser the mouse is      float min = 1.0f, max = 0.01f * (scrollH->maximum() - scrollH->minimum());      if( max < 10.0f ) max = 10.0f;      if( X < (x()+30) ) // left	{	  float t = float((x()+30) - X) / 30.0f;	  autoScrollX = -LERP( t*t, min, max );	  if( !scrolledTimerOn )	    Fl::add_timeout( 0.0, _timerScrollCB, this );	}      else if( X > (x()+w()-30) ) // right	{	  float t = float(X - (x()+w()-30)) / 30.0f;	  autoScrollX = LERP( t*t, min, max );	  if( !scrolledTimerOn )	    Fl::add_timeout( 0.0, _timerScrollCB, this );	}    }  if( scrollV->visible() )    {      // auto-scroll the vertical scrollbars based on how close to the top or bottom of the browser the mouse is      float min = 1.0f, max = 0.01f * (scrollV->maximum() - scrollV->minimum());      if( max < 10.0f ) max = 10.0f;      if( Y < (y()+30) ) // top	{	  float t = float((y()+30) - Y) / 30.0f;	  autoScrollY = -LERP( t*t, min, max );	  if( !scrolledTimerOn )	    Fl::add_timeout( 0.0, _timerScrollCB, this );	}      else if( Y > (y()+h()-30) ) // bottom	{	  float t = float(Y - (y()+h()-30)) / 30.0f;	  autoScrollY = LERP( t*t, min, max );	  if( !scrolledTimerOn )	    Fl::add_timeout( 0.0, _timerScrollCB, this );	}    }  if( autoScrollX == 0.0f && autoScrollY == 0.0f )    {      Fl::remove_timeout( _timerScrollCB, this );      scrolledTimerOn = false;    }  int dx = Fl::box_dx(box()), dy = Fl::box_dy(box());  rdata.x = x()+dx; rdata.y = y()+dy;  if( scrollH->visible() )    rdata.x -= scrollH->value();  if( scrollV->visible() )    rdata.y -= scrollV->value();  rdata.delta = 0;  root.recurse( rdata, Node::HANDLE, FL_DND_DRAG );  rdata.isMoveValid = Fl::event_inside( this ) && Node::isMoveValid( rdata.grabbed, rdata.dragWhere, rdata.dragNode );  redraw();  Fl::flush();  if( rdata.isMoveValid )    return true;  else#endif    return false;}void Flu_Tree_Browser :: on_dnd_release(){#ifdef USE_FLU_DND  Fl::remove_timeout( _timerScrollCB, this );  scrolledTimerOn = false;  redraw();  Fl::flush();#endif}void Flu_Tree_Browser :: on_dnd_drop( const Flu_DND_Event *e ){#ifdef USE_FLU_DND  bool newNode = false;  if( !rdata.isMoveValid )    rdata.grabbed = 0;  else if( e->event_is_text() && rdata.dnd )    {      // create a new node with the text as the name and make it the grabbed node      rdata.grabbed = new Node( true, e->text(), NULL, rdata, NULL, true );      if( rdata.grabbed )	newNode = true;    }  else    {      if( e->is_data_type( "Flu_Tree_Browser" ) )	{	  if( rdata.moveOnlySameGroup && ( rdata.grabbed->parent() != rdata.dragNode->parent() ) )	    rdata.grabbed = NULL;	}      else if( e->is_data_type( "DND_Object" ) && rdata.dnd )	{	  // create a new node with the text as the name and make it the grabbed node	  DND_Object *o = (DND_Object*)e->data();	  rdata.grabbed = new Node( true, o->name(), NULL, rdata, NULL, true );	  if( rdata.grabbed )	    {	      rdata.grabbed->user_data( e->data() );	      newNode = true;	    }	}      else	rdata.grabbed = NULL;    }  // select only the new/moved node  root.unselect_all( rdata.grabbed );  set_hilighted( rdata.grabbed );  if( rdata.grabbed )    {      rdata.grabbed->select( true );        // move the node      if( NodeList::move( rdata.grabbed, rdata.dragWhere, rdata.dragNode ) )	{	  if( newNode )	    rdata.grabbed->do_callback( FLU_NEW_NODE );	  else	    rdata.grabbed->do_callback( FLU_MOVED_NODE );	}      rdata.forceResize = true;    }  Fl::focus(this);  rdata.dragging = false;  rdata.grabbed = 0;  rdata.dragNode = 0;  Fl::remove_timeout( _timerScrollCB, this );  scrolledTimerOn = false;  redraw();#endif}int Flu_Tree_Browser :: handle( int event ){#ifdef USE_FLU_DND  if( dnd_handle( event ) )    return 1;#endif  //if( event == FL_NO_EVENT || event == FL_MOVE )  //return 0;  if( event == FL_FOCUS && rdata.lastHilighted )    {      set_hilighted( rdata.lastHilighted );      lastEvent = event;      Fl_Group::handle( event );      redraw();      return 1;    }  if( event == FL_UNFOCUS )    {      if( lastEvent != FL_LEAVE )

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?