flu_tree_browser.cpp

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

CPP
2,583
字号
void Flu_Tree_Browser :: Node :: print( int spaces ){  for( int s = 0; s < spaces; s++ )    printf( " " );  if( is_leaf() )    printf( "  %s\n", text.c_str() );  else    printf( "[%s]\n", text.c_str() );  for( int i = 0; i < _children.size(); i++ )    _children.child(i)->print( spaces+2 );}void Flu_Tree_Browser :: draw(){  if( rdata.forceResize )    {      resize( x(), y(), w(), h() );      rdata.forceResize = false;    }  // draw the background color  fl_draw_box( FL_FLAT_BOX, _box->x(), _box->y(), _box->w(), _box->h(), _box->color() );  int dx = Fl::box_dx(box()), dy = Fl::box_dy(box());  // set up the recursive data structure  rdata.x = x()+dx; rdata.y = y()+dy;  // account for the positions of the scrollbars  if( scrollH->visible() )    rdata.x -= scrollH->value();  if( scrollV->visible() )    rdata.y -= scrollV->value();  rdata.first = true;  rdata.last = true;  rdata.bgColor = _box->color();  rdata.shadedIndex = 0;  // pick the connector line and selection colors depending on the active state  if( active() )    {      rdata.lineColor = rdata.defLineColor;      rdata.selectionColor = rdata.defSelectionColor;    }  else    {      rdata.lineColor = fl_inactive( rdata.defLineColor );      rdata.selectionColor = fl_inactive( rdata.defSelectionColor );    }  // draw the tree  fl_push_clip( _box->x(), _box->y(), _box->w(), _box->h() );  root.recurse( rdata, Node::DRAW );  // if dragging to move, draw a bar showing where the dragged node will be inserted#ifdef USE_FLU_DND  if( dnd_is_dragging() && rdata.isMoveValid && rdata.dragging )    {      bool drawLine = false;      if( dnd_event_is_text() )	drawLine = true;      else if( dnd_is_data_type( "Flu_Tree_Browser" ) )	{	  if( !rdata.moveOnlySameGroup || ( rdata.grabbed->parent() == rdata.dragNode->parent() ) )	    drawLine = true;	}      else if( dnd_is_data_type( "DND_Object" ) )	drawLine = true;      if( drawLine && rdata.dragWhere != MOVE_INSIDE )	{	  fl_color( FL_RED );	  fl_line_style( FL_SOLID, 2 );	  fl_line( _box->x(), rdata.dragPos, _box->x()+_box->w(), rdata.dragPos );	  fl_line_style( 0 );	}    }#endif  fl_pop_clip();  // draw the kids  draw_child( *scrollBox );  draw_child( *scrollH );  draw_child( *scrollV );  // draw the box last so it's on top  fl_draw_box( _box->box(), _box->x(), _box->y(), _box->w(), _box->h(), _box->color() );}inline void draw_T( int x, int y, int w, int h ){  int w2 = w >> 1;  int h2 = h >> 1;  fl_line( x+w2, y, x+w2, y+h );  fl_line( x+w2, y+h2, x+w, y+h2 );}inline void draw_L( int x, int y, int w, int h ){  int w2 = w >> 1;  int h2 = h >> 1;  fl_line( x+w2, y, x+w2, y+h2 );  fl_line( x+w2, y+h2, x+w, y+h2 );}inline void draw_Lflip( int x, int y, int w, int h ){  int w2 = w >> 1;  int h2 = h >> 1;  fl_line( x+w2, y+h, x+w2, y+h2 );  fl_line( x+w2, y+h2, x, y+h2 );}inline void draw_Ldash( int x, int y, int w, int h ){  w = w >> 1;  h = h >> 1;  fl_line( x, y+h, x+w, y+h );}inline void draw_vert_dash( int x, int y, int w, int h ){  w = w >> 1;  fl_line( x+w, y+(h>>1), x+w, y+h );}inline void draw_Rdash( int x, int y, int w, int h ){  h = h >> 1;  fl_line( x+w, y+h, x+(w>>1), y+h );}void Flu_Tree_Browser :: Node :: draw( RData &rdata, bool measure ){  int which = open(); // i.e. which icon: open or closed?  bool skipCollapser = is_root() && rdata.showRoot && ( CHECK(ALWAYS_OPEN) || rdata.allBranchesAlwaysOpen );  int halfHGap = rdata.hGap >> 1, halfVGap = rdata.vGap >> 1;  bool doDraw = !measure;  int X = rdata.x;  int Y = rdata.y;  Fl_Color bgColor = rdata.shadedColors[rdata.shadedIndex], tColor = textColor, hilightColor = rdata.selectionColor;  // pick the text color depending on the active state  if( !rdata.tree->active() || !CHECK(ACTIVE))    tColor = fl_inactive( tColor );  if( doDraw )    {      // draw the background for the entry using the entry background color      fl_draw_box( FL_FLAT_BOX, rdata.browserX, Y, rdata.browserW, currentH, bgColor );      // if dragging to the inside of a branch, hilight that branch#ifdef USE_FLU_DND      if( tree->dnd_is_dragging() && rdata.isMoveValid && rdata.dragWhere == MOVE_INSIDE && rdata.dragNode == this )	{	  bgColor = FL_RED;	  tColor = fl_contrast( tColor, bgColor );	  hilightColor = rdata.bgColor;	  fl_draw_box( FL_FLAT_BOX, rdata.browserX, Y, rdata.browserW, currentH, bgColor );	}      // if selected, draw a filled selection box and reverse the normal draw colors      else if( CHECK(SELECTED) )#else      if( CHECK(SELECTED) )#endif	{	  bgColor = rdata.selectionColor;	  tColor = fl_contrast( tColor, bgColor );	  hilightColor = rdata.bgColor;	  fl_draw_box( FL_FLAT_BOX, rdata.browserX, Y, rdata.browserW, currentH, bgColor );	}      fl_color( rdata.lineColor );      fl_line_style( rdata.lineStyle, rdata.lineWidth );    }  if( is_leaf() ) // draw leaves one way...    {      // draw the connectors      if( doDraw && rdata.showConnectors && rdata.showBranches )	{	  if( rdata.last )	    draw_L( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );	  else	    draw_T( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );	}      // account for leaf icon spacing      if( rdata.showBranches )	{	  if( lIcon )	    X += rdata.collapseIcons[which]->w() + rdata.hGap;	  else	    X += rdata.collapseIcons[which]->w() + rdata.wGap;	}      else 	X += rdata.wGap;      // draw some more connectors      if( doDraw && rdata.showConnectors && lIcon && rdata.showBranches )	draw_Ldash( X-halfHGap, Y-halfVGap, lIcon->w()+rdata.hGap, currentH+rdata.vGap );      // draw the leaf icon      if( lIcon )	{	  if( doDraw )	    lIcon->draw( X, Y+(currentH>>1)-(lIcon->h()>>1) );	  X += lIcon->w() + rdata.wGap;	}    }  else // ...and branches another    {      // force the root to the left if it has no visible children      if( _parent == 0 && !CHECK(SOME_VISIBLE_CHILDREN) )	{	  skipCollapser = true;	  which = 0;	}      if( !CHECK(SOME_VISIBLE_CHILDREN) && !rdata.showLeaves )	which = 0;      // draw the connectors      if( doDraw && !skipCollapser && rdata.showConnectors && rdata.showBranches )	{	  if( _parent==0 )	    {	      if( CHECK(SOME_VISIBLE_CHILDREN) )		draw_Rdash( X-halfHGap, Y-halfVGap, rdata.collapseIcons[which]->w()+4+rdata.hGap, currentH+rdata.vGap );	    }	  else if( rdata.last )	    draw_L( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );	  else	    draw_T( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );	}      // draw the collapsed icons      if( doDraw && !skipCollapser && !CHECK(ALWAYS_OPEN) && !rdata.allBranchesAlwaysOpen )	{	  if( CHECK(SOME_VISIBLE_CHILDREN) || rdata.showLeaves )	    {	      if( _parent==0 )		cIcon[which]->draw( X, Y+(currentH>>1)-(cIcon[which]->h()>>1) );	      else		cIcon[which]->draw( X+(rdata.branchIconW>>1)-(cIcon[which]->w()>>1), Y+(currentH>>1)-(cIcon[which]->h()>>1) );	    }	}      if( !skipCollapser )	{	  X += cIcon[which]->w();	  if( bIcon[which] )	    X += rdata.hGap;	  else	    X += rdata.wGap;	}      // draw some more connectors      if( doDraw && rdata.showConnectors && rdata.showBranches )	{	  int hGap = rdata.hGap;	  if( bIcon[which] )	    hGap += bIcon[which]->w();	  if( skipCollapser && CHECK(SOME_VISIBLE_CHILDREN) )	    draw_vert_dash( X-halfHGap, Y-halfVGap, hGap, currentH+rdata.vGap );	  else if( !which || !CHECK(SOME_VISIBLE_CHILDREN) )	    draw_Ldash( X-halfHGap, Y-halfVGap, hGap, currentH+rdata.vGap );	  else	    draw_Lflip( X-halfHGap, Y-halfVGap, hGap, currentH+rdata.vGap );	}      // draw the branch icon      if( bIcon[which] )	{	  if( doDraw )	    bIcon[which]->draw( X, Y+(currentH>>1)-(bIcon[which]->h()>>1) );	  X += bIcon[which]->w() + rdata.wGap;	}    }  if( doDraw )    fl_line_style( 0 );  // draw the entry  if( CHECK(SHOW_LABEL) )    {      if( doDraw )	{	  fl_draw_box( FL_FLAT_BOX, X, Y+(currentH>>1)-(textH>>1), textW, textH, bgColor );	  fl_color( tColor );	  fl_font( textFont, textSize );	  fl_draw( text.c_str(), X, Y+(currentH>>1)-(textH>>1), textW, textH, FL_ALIGN_LEFT );	}      X += textW;    }  if( _widget )    {      int widgetW = _widget->w->w();      int widgetH = _widget->w->h();      if( doDraw )	{	  _widget->w->redraw();	  _widget->w->position( X, Y+(currentH>>1)-(widgetH>>1) );	  if( CHECK(EXPAND_TO_WIDTH) )	    _widget->w->size( MAX( _widget->defaultW, rdata.browserW - (X-rdata.browserX) ), _widget->w->h() );	  _widget->w->draw();	}      if( CHECK(EXPAND_TO_WIDTH) )	{	  if( _widget->w->w() == _widget->defaultW )	    X += _widget->defaultW;	}      else	X += widgetW;    }  // if hilighted, draw a box outlining the entry  if( rdata.hilighted == this && doDraw )    {      fl_color( hilightColor );      fl_line_style( FL_DOT, 1 );      fl_rect( rdata.browserX, Y, rdata.browserW, currentH, hilightColor );      fl_line_style( 0 );    }  rdata.totalW = MAX( rdata.totalW, X );}void Flu_Tree_Browser :: Node :: select( bool b ){  if( (CHECK(SELECTED)==b) && (tree->rdata.when != FL_WHEN_NOT_CHANGED) )    return;  SET(SELECTED,b);  tree->redraw();  if( tree->rdata.when == FL_WHEN_RELEASE )    return;  if( b )    do_callback( FLU_SELECTED );  else    do_callback( FLU_UNSELECTED );}void Flu_Tree_Browser :: timerScrollCB(){  bool doRedraw = false;  float val = scrollV->value() + autoScrollY;  if( val < 0.0f )    val = 0.0f;  if( val > scrollV->maximum() )    val = scrollV->maximum();  doRedraw |= ( val != scrollV->value() );  ((Fl_Valuator*)scrollV)->value( val );  val = scrollH->value() + autoScrollX;  if( val < 0.0f )    val = 0.0f;  if( val > scrollH->maximum() )    val = scrollH->maximum();  doRedraw |= ( val != scrollH->value() );  ((Fl_Valuator*)scrollH)->value( val );  Fl::repeat_timeout( 0.02, _timerScrollCB, this );  scrolledTimerOn = true;  if( doRedraw )    redraw();}void Flu_Tree_Browser :: timerRedrawCB(){  if( rdata.animating )    Fl::repeat_timeout( 1.0f/rdata.fps, _timerRedrawCB, this );  redraw();}void Flu_Tree_Browser :: Node :: open( bool b ){  if( is_leaf() )    return;  if( CHECK(ALWAYS_OPEN) || tree->rdata.allBranchesAlwaysOpen )    return;  if( (open() == b) && (tree->rdata.when != FL_WHEN_NOT_CHANGED) )    return;  tree->rdata.justOpenedClosed = true;  SET(COLLAPSED,!b);  if( tree->rdata.animate )    {      // if we aren't yet animating a node, animate it!      if( !tree->rdata.animating && !tree->rdata.animatedNode )	{	  // if we don't know how high all the children are, find out	  // (this only happens once per node, the first time it is opened)	  if( totalChildH == 0 )	    {	      RData r = tree->rdata;	      r.x = r.y = r.totalW = 0;	      recurse( r, Node::MEASURE_THIS_OPEN );	    }	  // set the initial offset based on whether the branch is open or closed	  tree->rdata.animationOffset = b ? -totalChildH : -1;	  // the delta is how much to change the offset each frame	  tree->rdata.animationDelta = totalChildH / ( tree->rdata.collapseTime * tree->rdata.fps );	  tree->rdata.animationDelta = b ? tree->rdata.animationDelta : -tree->rdata.animationDelta;	  tree->rdata.animating = true;	  tree->rdata.animatedNode = this;	  Fl::add_timeout( 1.0f/tree->rdata.fps, _timerRedrawCB, tree );	}      // otherwise reverse the direction of the animation, only if we are animating this node      else if( tree->rdata.animating && tree->rdata.animatedNode==this )	{	  if( b ^ (tree->rdata.animationDelta>0) )	    tree->rdata.animationDelta = -tree->rdata.animationDelta;	}    }  if( open() && (_parent != 0) ) // root node doesn't count as a single open branch    {      if( ( tree->rdata.lastOpenBranch != this ) && tree->rdata.singleBranchOpen )	tree->rdata.lastOpenBranch->close();      tree->rdata.lastOpenBranch = this;    }  tree->rdata.forceResize = true;  tree->rdata.visibilityChanged = true;  if( b )    do_callback( FLU_OPENED );  else    do_callback( FLU_CLOSED );}void Flu_Tree_Browser :: Node :: active( bool b ){  if( CHECK(ACTIVE) == b  &&  tree->rdata.when != FL_WHEN_NOT_CHANGED )    return;  SET( ACTIVE, b );  if( _widget )    {      if( b )	_widget->w->activate();      else	_widget->w->deactivate();    }  if( !CHECK(ACTIVE) )    {      if( tree->rdata.hilighted == this )	tree->set_hilighted( NULL );      select( false );      open( false );    }}void Flu_Tree_Browser :: Node :: unselect_all( Node* except ){  if( this != except )    select( false );  for( int i = 0; i < _children.size(); i++ )    _children.child(i)->unselect_all( except );}void Flu_Tree_Browser :: Node :: select_all(){  select( true );  for( int i = 0; i < _children.size(); i++ )    _children.child(i)->select_all();}bool Flu_Tree_Browser :: Node :: isMoveValid( Node* &n1, int &where, Node* &n2 ){  // if n1 is NULL, then check it as if it were a node being moved from another tree  if( n2 == NULL )    return false;  // check the validity of the move:  // 1) the source and destination nodes can't be the same  // 2) you can't move before the root node  // 3) you can't move an unmovable node or move a branch node such that it would become a descendent of itself  // 4) if moving only within the same group, check that the parents are the same  // 5) if moving into a sorted tree, the destination node MUST be a branch  // 6) a move AFTER an OPEN branch is a move BEFORE its first child  // 7) you can't move a node into a non-droppable branch node  if( n1 == n2 )    return false;  if( where==MOVE_BEFORE && n2->is_root() )    return false;  if( n1 )    {      if( !n1->movable() )	return false;      if( n1->is_branch() )	if( n1->is_descendent( n2 ) )	  return false;    }  bool sameGroup = n2->tree->move_only_same_group();  if( sameGroup && n1 )    {      if( n1->parent() != n2->parent() || where==MOVE_INSIDE )	return false;    }  int iMode = n2->tree->insertion_mode();  if( iMode == FLU_INSERT_SORTED || iMode == FLU_INSERT_SORTED_REVERSE )    {      if( n2->is_branch() )	{	  where = MOVE_INSIDE;

⌨️ 快捷键说明

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