1 /******************************************************************************** 2 * * 3 * T r e e L i s t W i d g e t * 4 * * 5 ********************************************************************************* 6 * Copyright (C) 1997,2020 by Jeroen van der Zijp. All Rights Reserved. * 7 ********************************************************************************* 8 * This library is free software; you can redistribute it and/or modify * 9 * it under the terms of the GNU Lesser General Public License as published by * 10 * the Free Software Foundation; either version 3 of the License, or * 11 * (at your option) any later version. * 12 * * 13 * This library is distributed in the hope that it will be useful, * 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 16 * GNU Lesser General Public License for more details. * 17 * * 18 * You should have received a copy of the GNU Lesser General Public License * 19 * along with this program. If not, see <http://www.gnu.org/licenses/> * 20 ********************************************************************************/ 21 #ifndef FXTREELIST_H 22 #define FXTREELIST_H 23 24 #ifndef FXSCROLLAREA_H 25 #include "FXScrollArea.h" 26 #endif 27 28 namespace FX { 29 30 31 class FXIcon; 32 class FXFont; 33 class FXTreeList; 34 class FXDirList; 35 36 37 /// Tree list styles 38 enum { 39 TREELIST_EXTENDEDSELECT = 0, /// Extended selection mode allows for drag-selection of ranges of items 40 TREELIST_SINGLESELECT = 0x00100000, /// Single selection mode allows up to one item to be selected 41 TREELIST_BROWSESELECT = 0x00200000, /// Browse selection mode enforces one single item to be selected at all times 42 TREELIST_MULTIPLESELECT = 0x00300000, /// Multiple selection mode is used for selection of individual items 43 TREELIST_AUTOSELECT = 0x00400000, /// Automatically select under cursor 44 TREELIST_SHOWS_LINES = 0x00800000, /// Lines shown 45 TREELIST_SHOWS_BOXES = 0x01000000, /// Boxes to expand shown 46 TREELIST_ROOT_BOXES = 0x02000000, /// Display root boxes also 47 TREELIST_NORMAL = TREELIST_EXTENDEDSELECT 48 }; 49 50 51 /// Tree list Item 52 class FXAPI FXTreeItem : public FXObject { 53 FXDECLARE(FXTreeItem) 54 friend class FXTreeList; 55 friend class FXDirList; 56 protected: 57 FXTreeItem *parent; // Parent item 58 FXTreeItem *prev; // Previous item 59 FXTreeItem *next; // Next item 60 FXTreeItem *first; // First child item 61 FXTreeItem *last; // Last child item 62 FXString label; // Text of item 63 FXIcon *openIcon; // Icon of item 64 FXIcon *closedIcon; // Icon of item 65 FXptr data; // Item user data pointer 66 FXuint state; // Item state flags 67 FXint x,y; 68 private: 69 FXTreeItem(const FXTreeItem&); 70 FXTreeItem& operator=(const FXTreeItem&); 71 protected: FXTreeItem()72 FXTreeItem():parent(NULL),prev(NULL),next(NULL),first(NULL),last(NULL),openIcon(NULL),closedIcon(NULL),data(NULL),state(0),x(0),y(0){} 73 virtual void draw(const FXTreeList* list,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const; 74 virtual FXint hitItem(const FXTreeList* list,FXint x,FXint y) const; 75 public: 76 enum{ 77 SELECTED = 1, /// Selected 78 FOCUS = 2, /// Focus 79 DISABLED = 4, /// Disabled 80 OPENED = 8, /// Opened 81 EXPANDED = 16, /// Expanded 82 HASITEMS = 32, /// Has virtual subitems 83 DRAGGABLE = 64, /// Draggable 84 OPENICONOWNED = 128, /// Open icon owned by item 85 CLOSEDICONOWNED = 256 /// Close icon owned by item 86 }; 87 public: 88 89 /// Constructor parent(NULL)90 FXTreeItem(const FXString& text,FXIcon* oi=NULL,FXIcon* ci=NULL,FXptr ptr=NULL):parent(NULL),prev(NULL),next(NULL),first(NULL),last(NULL),label(text),openIcon(oi),closedIcon(ci),data(ptr),state(0),x(0),y(0){} 91 92 /// Get parent item getParent()93 FXTreeItem* getParent() const { return parent; } 94 95 /// Get next sibling item getNext()96 FXTreeItem* getNext() const { return next; } 97 98 /// Get previous sibling item getPrev()99 FXTreeItem* getPrev() const { return prev; } 100 101 /// Get first child item getFirst()102 FXTreeItem* getFirst() const { return first; } 103 104 /// Get last child item getLast()105 FXTreeItem* getLast() const { return last; } 106 107 /// Get item below this one in list 108 FXTreeItem* getBelow() const; 109 110 /// Get item above this one in list 111 FXTreeItem* getAbove() const; 112 113 /// Get number of children of item 114 FXint getNumChildren() const; 115 116 /// Change item label 117 virtual void setText(const FXString& txt); 118 119 /// Get item label getText()120 const FXString& getText() const { return label; } 121 122 /// Change open icon, deleting the old icon if it was owned 123 virtual void setOpenIcon(FXIcon* icn,FXbool owned=false); 124 125 /// Get open icon getOpenIcon()126 FXIcon* getOpenIcon() const { return openIcon; } 127 128 /// Change closed icon, deleting the old icon if it was owned 129 virtual void setClosedIcon(FXIcon* icn,FXbool owned=false); 130 131 /// Get closed icon getClosedIcon()132 FXIcon* getClosedIcon() const { return closedIcon; } 133 134 /// Change item user data setData(FXptr ptr)135 void setData(FXptr ptr){ data=ptr; } 136 137 /// Get item user data getData()138 FXptr getData() const { return data; } 139 140 /// Make item draw as focused 141 virtual void setFocus(FXbool focus); 142 143 /// Return true if item has focus hasFocus()144 FXbool hasFocus() const { return (state&FOCUS)!=0; } 145 146 /// Select item 147 virtual void setSelected(FXbool selected); 148 149 /// Return true if this item is selected isSelected()150 FXbool isSelected() const { return (state&SELECTED)!=0; } 151 152 /// Make item show as open 153 virtual void setOpened(FXbool opened); 154 155 /// Return true if this item is open isOpened()156 FXbool isOpened() const { return (state&OPENED)!=0; } 157 158 /// Expand or collapse item 159 virtual void setExpanded(FXbool expanded); 160 161 /// Return true if this item is expanded into sub items isExpanded()162 FXbool isExpanded() const { return (state&EXPANDED)!=0; } 163 164 /// Enable or disable item 165 virtual void setEnabled(FXbool enabled); 166 167 /// Return true if this item is enabled isEnabled()168 FXbool isEnabled() const { return (state&DISABLED)==0; } 169 170 /// Make item draggable 171 virtual void setDraggable(FXbool draggable); 172 173 /// Return true if this item is draggable isDraggable()174 FXbool isDraggable() const { return (state&DRAGGABLE)!=0; } 175 176 /// Return true if subitems, real or imagined hasItems()177 FXbool hasItems() const { return (state&HASITEMS)!=0; } 178 179 /// Change has items flag 180 void setHasItems(FXbool flag); 181 182 /// Return true if descendent of parent item 183 FXbool isChildOf(const FXTreeItem* item) const; 184 185 /// Return true if ancestor of child item 186 FXbool isParentOf(const FXTreeItem* item) const; 187 188 /// Return tip text 189 virtual FXString getTipText() const; 190 191 /// Return width of item as drawn in list 192 virtual FXint getWidth(const FXTreeList* list) const; 193 194 /// Return height of item as drawn in list 195 virtual FXint getHeight(const FXTreeList* list) const; 196 197 /// Create server-side resources 198 virtual void create(); 199 200 /// Detach server-side resources 201 virtual void detach(); 202 203 /// Destroy server-side resources 204 virtual void destroy(); 205 206 /// Save to stream 207 virtual void save(FXStream& store) const; 208 209 /// Load from stream 210 virtual void load(FXStream& store); 211 212 /// Destroy item and free icons if owned 213 virtual ~FXTreeItem(); 214 }; 215 216 217 218 /// Tree item collate function 219 typedef FXint (*FXTreeListSortFunc)(const FXTreeItem*,const FXTreeItem*); 220 221 222 223 /** 224 * A Tree List Widget organizes items in a hierarchical, tree-like fashion. 225 * Subtrees can be collapsed or expanded by double-clicking on an item 226 * or by clicking on the optional plus button in front of the item. 227 * Each item may have a text and optional open-icon as well as a closed-icon. 228 * The items may be connected by optional lines to show the hierarchical 229 * relationship. 230 * When an item's selected state changes, the treelist emits a SEL_SELECTED 231 * or SEL_DESELECTED message. If an item is opened or closed, a message 232 * of type SEL_OPENED or SEL_CLOSED is sent. When the subtree under an 233 * item is expanded, a SEL_EXPANDED or SEL_COLLAPSED message is issued. 234 * A change of the current item is signified by the SEL_CHANGED message. 235 * In addition, the tree list sends SEL_COMMAND messages when the user 236 * clicks on an item, and SEL_CLICKED, SEL_DOUBLECLICKED, and SEL_TRIPLECLICKED 237 * when the user clicks once, twice, or thrice, respectively. 238 * When items are added or removed, the tree list sends messages of the 239 * type SEL_INSERTED or SEL_DELETED. 240 * In each of these cases, a pointer to the item, if any, is passed in the 241 * 3rd argument of the message. 242 */ 243 class FXAPI FXTreeList : public FXScrollArea { 244 FXDECLARE(FXTreeList) 245 protected: 246 FXTreeItem *firstitem; // First root item 247 FXTreeItem *lastitem; // Last root item 248 FXTreeItem *anchoritem; // Selection anchor item 249 FXTreeItem *currentitem; // Current item 250 FXTreeItem *extentitem; // Selection extent 251 FXTreeItem *viewableitem; // Visible item 252 FXFont *font; // Font 253 FXTreeListSortFunc sortfunc; // Item sort function 254 FXColor textColor; // Text color 255 FXColor selbackColor; // Selected background color 256 FXColor seltextColor; // Selected text color 257 FXColor lineColor; // Line color 258 FXint treeWidth; // Tree width 259 FXint treeHeight; // Tree height 260 FXint visible; // Number of visible items 261 FXint indent; // Parent to child indentation 262 FXint grabx; // Grab point x 263 FXint graby; // Grab point y 264 FXString lookup; // Lookup string 265 FXString tip; 266 FXString help; // Help string 267 FXbool state; // State of item 268 protected: 269 FXTreeList(); 270 virtual FXTreeItem* createItem(const FXString& text,FXIcon* oi,FXIcon* ci,FXptr ptr); 271 void sort(FXTreeItem*& f1,FXTreeItem*& t1,FXTreeItem*& f2,FXTreeItem*& t2,int n); 272 void recompute(); 273 private: 274 FXTreeList(const FXTreeList&); 275 FXTreeList& operator=(const FXTreeList&); 276 public: 277 long onPaint(FXObject*,FXSelector,void*); 278 long onEnter(FXObject*,FXSelector,void*); 279 long onLeave(FXObject*,FXSelector,void*); 280 long onUngrabbed(FXObject*,FXSelector,void*); 281 long onMotion(FXObject*,FXSelector,void*); 282 long onKeyPress(FXObject*,FXSelector,void*); 283 long onKeyRelease(FXObject*,FXSelector,void*); 284 long onLeftBtnPress(FXObject*,FXSelector,void*); 285 long onLeftBtnRelease(FXObject*,FXSelector,void*); 286 long onRightBtnPress(FXObject*,FXSelector,void*); 287 long onRightBtnRelease(FXObject*,FXSelector,void*); 288 long onQueryTip(FXObject*,FXSelector,void*); 289 long onQueryHelp(FXObject*,FXSelector,void*); 290 long onTipTimer(FXObject*,FXSelector,void*); 291 long onFocusIn(FXObject*,FXSelector,void*); 292 long onFocusOut(FXObject*,FXSelector,void*); 293 long onAutoScroll(FXObject*,FXSelector,void*); 294 long onClicked(FXObject*,FXSelector,void*); 295 long onDoubleClicked(FXObject*,FXSelector,void*); 296 long onTripleClicked(FXObject*,FXSelector,void*); 297 long onCommand(FXObject*,FXSelector,void*); 298 long onLookupTimer(FXObject*,FXSelector,void*); 299 public: 300 static FXint ascending(const FXTreeItem*,const FXTreeItem*); 301 static FXint descending(const FXTreeItem*,const FXTreeItem*); 302 static FXint ascendingCase(const FXTreeItem*,const FXTreeItem*); 303 static FXint descendingCase(const FXTreeItem*,const FXTreeItem*); 304 public: 305 enum { 306 ID_LOOKUPTIMER=FXScrollArea::ID_LAST, 307 ID_LAST 308 }; 309 public: 310 311 /// Construct a new, initially empty tree list 312 FXTreeList(FXComposite *p,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=TREELIST_NORMAL,FXint x=0,FXint y=0,FXint w=0,FXint h=0); 313 314 /// Create server-side resources 315 virtual void create(); 316 317 /// Detach server-side resources 318 virtual void detach(); 319 320 /// Perform layout 321 virtual void layout(); 322 323 /// Return default width 324 virtual FXint getDefaultWidth(); 325 326 /// Return default height 327 virtual FXint getDefaultHeight(); 328 329 /// Compute and return content width 330 virtual FXint getContentWidth(); 331 332 /// Return content height 333 virtual FXint getContentHeight(); 334 335 /// Recalculate layout 336 virtual void recalc(); 337 338 /// Tree list can receive focus 339 virtual FXbool canFocus() const; 340 341 /// Move the focus to this window 342 virtual void setFocus(); 343 344 /// Remove the focus from this window 345 virtual void killFocus(); 346 347 /// Return number of items 348 FXint getNumItems() const; 349 350 /// Return number of visible items getNumVisible()351 FXint getNumVisible() const { return visible; } 352 353 /// Change number of visible items 354 void setNumVisible(FXint nvis); 355 356 /// Return first root item getFirstItem()357 FXTreeItem* getFirstItem() const { return firstitem; } 358 359 /// Return last root item getLastItem()360 FXTreeItem* getLastItem() const { return lastitem; } 361 362 /// Fill tree list by appending items from array of strings 363 FXint fillItems(FXTreeItem* father,const FXchar *const *strings,FXIcon* oi=NULL,FXIcon* ci=NULL,FXptr ptr=NULL,FXbool notify=false); 364 365 /// Fill tree list by appending items from array of strings 366 FXint fillItems(FXTreeItem* father,const FXString* strings,FXIcon* oi=NULL,FXIcon* ci=NULL,FXptr ptr=NULL,FXbool notify=false); 367 368 /// Fill tree list by appending items from newline separated strings 369 FXint fillItems(FXTreeItem* father,const FXString& strings,FXIcon* oi=NULL,FXIcon* ci=NULL,FXptr ptr=NULL,FXbool notify=false); 370 371 /// Replace the original item orig with new [possibly subclassed] item 372 FXTreeItem* setItem(FXTreeItem* orig,FXTreeItem* item,FXbool notify=false); 373 374 /// Insert [possibly subclassed] item under father before other item 375 FXTreeItem* insertItem(FXTreeItem* other,FXTreeItem* father,FXTreeItem* item,FXbool notify=false); 376 377 /// Insert item with given text and optional icons, and user-data pointer under father before other item 378 FXTreeItem* insertItem(FXTreeItem* other,FXTreeItem* father,const FXString& text,FXIcon* oi=NULL,FXIcon* ci=NULL,FXptr ptr=NULL,FXbool notify=false); 379 380 /// Append [possibly subclassed] item as last child of father 381 FXTreeItem* appendItem(FXTreeItem* father,FXTreeItem* item,FXbool notify=false); 382 383 /// Append item with given text and optional icons, and user-data pointer as last child of father 384 FXTreeItem* appendItem(FXTreeItem* father,const FXString& text,FXIcon* oi=NULL,FXIcon* ci=NULL,FXptr ptr=NULL,FXbool notify=false); 385 386 /// Prepend [possibly subclassed] item as first child of father 387 FXTreeItem* prependItem(FXTreeItem* father,FXTreeItem* item,FXbool notify=false); 388 389 /// Prepend item with given text and optional icons, and user-data pointer as first child of father 390 FXTreeItem* prependItem(FXTreeItem* father,const FXString& text,FXIcon* oi=NULL,FXIcon* ci=NULL,FXptr ptr=NULL,FXbool notify=false); 391 392 /// Move item under father before other item 393 FXTreeItem *moveItem(FXTreeItem* other,FXTreeItem* father,FXTreeItem* item); 394 395 /// Extract item 396 FXTreeItem* extractItem(FXTreeItem* item,FXbool notify=false); 397 398 /// Remove item 399 void removeItem(FXTreeItem* item,FXbool notify=false); 400 401 /// Remove items in range [fm, to] inclusively 402 void removeItems(FXTreeItem* fm,FXTreeItem* to,FXbool notify=false); 403 404 /// Remove all items from list 405 void clearItems(FXbool notify=false); 406 407 /// Return item width getItemWidth(const FXTreeItem * item)408 FXint getItemWidth(const FXTreeItem* item) const { return item->getWidth(this); } 409 410 /// Return item height getItemHeight(const FXTreeItem * item)411 FXint getItemHeight(const FXTreeItem* item) const { return item->getHeight(this); } 412 413 /// Get item at x,y, if any 414 virtual FXTreeItem* getItemAt(FXint x,FXint y) const; 415 416 /// Return item hit code: 0 outside, 1 icon, 2 text, 3 box 417 FXint hitItem(const FXTreeItem* item,FXint x,FXint y) const; 418 419 /// Scroll to make item visible 420 virtual void makeItemVisible(FXTreeItem* item); 421 422 /** 423 * Search items by name, beginning from item start. If the start item 424 * is NULL the search will start at the first, top-most item in the list. 425 * Flags may be SEARCH_FORWARD or SEARCH_BACKWARD to control the search 426 * direction; this can be combined with SEARCH_NOWRAP or SEARCH_WRAP 427 * to control whether the search wraps at the start or end of the list. 428 * The option SEARCH_IGNORECASE causes a case-insensitive match. Finally, 429 * passing SEARCH_PREFIX causes searching for a prefix of the item name. 430 * Return NULL if no matching item is found. 431 */ 432 FXTreeItem* findItem(const FXString& name,FXTreeItem* start=NULL,FXuint flags=SEARCH_FORWARD|SEARCH_WRAP) const; 433 434 /** 435 * Search items by associated user data, beginning from item start. If the 436 * start item is NULL the search will start at the first, top-most item 437 * in the list. Flags may be SEARCH_FORWARD or SEARCH_BACKWARD to control 438 * the search direction; this can be combined with SEARCH_NOWRAP or SEARCH_WRAP 439 * to control whether the search wraps at the start or end of the list. 440 */ 441 FXTreeItem* findItemByData(FXptr ptr,FXTreeItem* start=NULL,FXuint flags=SEARCH_FORWARD|SEARCH_WRAP) const; 442 443 /// Change item's text 444 void setItemText(FXTreeItem* item,const FXString& text); 445 446 /// Return item's text 447 FXString getItemText(const FXTreeItem* item) const; 448 449 /// Change item's open icon 450 void setItemOpenIcon(FXTreeItem* item,FXIcon* icon,FXbool owned=false); 451 452 /// Return item's open icon, deleting the old icon if it was owned 453 FXIcon* getItemOpenIcon(const FXTreeItem* item) const; 454 455 /// Chance item's closed icon, deleting the old icon if it was owned 456 void setItemClosedIcon(FXTreeItem* item,FXIcon* icon,FXbool owned=false); 457 458 /// Return item's closed icon 459 FXIcon* getItemClosedIcon(const FXTreeItem* item) const; 460 461 /// Change item user-data pointer 462 void setItemData(FXTreeItem* item,void* ptr) const; 463 464 /// Return item user-data pointer 465 void* getItemData(const FXTreeItem* item) const; 466 467 /// Return true if item is selected 468 FXbool isItemSelected(const FXTreeItem* item) const; 469 470 /// Return true if item is current 471 FXbool isItemCurrent(const FXTreeItem* item) const; 472 473 /// Return true if item is visible 474 FXbool isItemVisible(const FXTreeItem* item) const; 475 476 /// Return true if item opened 477 FXbool isItemOpened(const FXTreeItem* item) const; 478 479 /// Return true if item expanded 480 FXbool isItemExpanded(const FXTreeItem* item) const; 481 482 /// Return true if item is a leaf-item, i.e. has no children 483 FXbool isItemLeaf(const FXTreeItem* item) const; 484 485 /// Return true if item is enabled 486 FXbool isItemEnabled(const FXTreeItem* item) const; 487 488 /// Repaint item 489 void updateItem(FXTreeItem* item) const; 490 491 /// Enable item 492 virtual FXbool enableItem(FXTreeItem* item); 493 494 /// Disable item 495 virtual FXbool disableItem(FXTreeItem* item); 496 497 /// Select item 498 virtual FXbool selectItem(FXTreeItem* item,FXbool notify=false); 499 500 /// Deselect item 501 virtual FXbool deselectItem(FXTreeItem* item,FXbool notify=false); 502 503 /// Toggle item selection 504 virtual FXbool toggleItem(FXTreeItem* item,FXbool notify=false); 505 506 /// Extend selection from anchor item to item 507 virtual FXbool extendSelection(FXTreeItem* item,FXbool notify=false); 508 509 /// Select all items 510 virtual FXbool selectAll(FXbool notify=false); 511 512 /// Deselect all items 513 virtual FXbool killSelection(FXbool notify=false); 514 515 /// Open item 516 virtual FXbool openItem(FXTreeItem* item,FXbool notify=false); 517 518 /// Close item 519 virtual FXbool closeItem(FXTreeItem* item,FXbool notify=false); 520 521 /// Collapse tree 522 virtual FXbool collapseTree(FXTreeItem* tree,FXbool notify=false); 523 524 /// Expand tree 525 virtual FXbool expandTree(FXTreeItem* tree,FXbool notify=false); 526 527 /// Change current item 528 virtual void setCurrentItem(FXTreeItem* item,FXbool notify=false); 529 530 /// Return current item, if any getCurrentItem()531 FXTreeItem* getCurrentItem() const { return currentitem; } 532 533 /// Change anchor item 534 void setAnchorItem(FXTreeItem* item); 535 536 /// Return anchor item, if any getAnchorItem()537 FXTreeItem* getAnchorItem() const { return anchoritem; } 538 539 /// Sort all items recursively 540 void sortItems(); 541 542 /// Sort root items 543 void sortRootItems(); 544 545 /// Sort children of item 546 void sortChildItems(FXTreeItem* item); 547 548 /// Return sort function getSortFunc()549 FXTreeListSortFunc getSortFunc() const { return sortfunc; } 550 551 /// Change sort function setSortFunc(FXTreeListSortFunc func)552 void setSortFunc(FXTreeListSortFunc func){ sortfunc=func; } 553 554 /// Change text font 555 void setFont(FXFont* fnt); 556 557 /// Return text font getFont()558 FXFont* getFont() const { return font; } 559 560 /// Change parent-child indent amount 561 void setIndent(FXint in); 562 563 /// Return parent-child indent amount getIndent()564 FXint getIndent() const { return indent; } 565 566 /// Return normal text color getTextColor()567 FXColor getTextColor() const { return textColor; } 568 569 /// Change normal text color 570 void setTextColor(FXColor clr); 571 572 /// Return selected text background getSelBackColor()573 FXColor getSelBackColor() const { return selbackColor; } 574 575 /// Change selected text background 576 void setSelBackColor(FXColor clr); 577 578 /// Return selected text color getSelTextColor()579 FXColor getSelTextColor() const { return seltextColor; } 580 581 /// Change selected text color 582 void setSelTextColor(FXColor clr); 583 584 /// Return line color getLineColor()585 FXColor getLineColor() const { return lineColor; } 586 587 /// Change line color 588 void setLineColor(FXColor clr); 589 590 /// Return list style 591 FXuint getListStyle() const; 592 593 /// Change list style 594 void setListStyle(FXuint style); 595 596 /// Set the status line help text for this list 597 void setHelpText(const FXString& text); 598 599 /// Get the status line help text for this list getHelpText()600 const FXString& getHelpText() const { return help; } 601 602 /// Save object to a stream 603 virtual void save(FXStream& store) const; 604 605 /// Load object from a stream 606 virtual void load(FXStream& store); 607 608 /// Destructor 609 virtual ~FXTreeList(); 610 }; 611 612 } 613 614 #endif 615