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 + -
显示快捷键?