1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
|
/*
Crystal Space Windowing System: tree box class
Copyright (C) 2000 by Norman Krmer, based on the listbox code:
Copyright (C) 1998,1999 by Andrew Zabolotny <bit@eltech.ru>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __CSTREE_H__
#define __CSTREE_H__
#include "cscomp.h"
#include "csscrbar.h"
/**
* Tree control - specific messages
*/
enum
{
/**
* Check if a component is indeed a tree item.
* <pre>
* IN: NULL (nothing)
* OUT: CS_TREEITEM_MAGIC if it is a tree item.
* </pre>
*/
cscmdTreeItemCheck = 0x00000e00,
/**
* Toggle the tree item (expand/collapse)
* <pre>
* IN: Action to perform: 0 - collapse, 1 - expand, other - toggle
* OUT: current state (0 - collapsed, 1 - expanded)
* </pre>
*/
cscmdTreeItemToggle,
/**
* Toggle the tree item and all child items in the subtree.
* <pre>
* IN: Action to perform: 0 - collapse, 1 - expand
* </pre>
*/
cscmdTreeItemToggleAll,
/**
* Tree item state change notification. This event is sent to parent
* before the actual change happens; you still have a chance to forbid
* the tree item to change its state. This event is re-sent by tree
* items to their parents, so your dialog will always receive these
* messages, even if they are emmited by deep tree items.
* <pre>
* IN: (csTreeItem *)item;
* OUT: CS_TREEITEM_MAGIC to forbid changing state
* </pre>
*/
cscmdTreeItemToggleNotify,
/**
* Notify parent treebox that the size (notably height) of the item
* has been changed, and all the tree items should be re-positioned.
* <pre>
* IN: (csTreeItem *)item;
* </pre>
*/
cscmdTreeItemSizeChangeNotify,
/**
* This message is sent by a tree to notify its parent that a item
* has been focused.
* <pre>
* IN: (csTreeItem *)Item;
* </pre>
* To find the parent of the item, check Item->parent; this can be
* either another tree item or the tree box. To clarify this, send
* the cscmdTreeItemCheck message to the item in question.
*/
cscmdTreeItemFocused,
/**
* Query what's the previous of a given item.
* The 'previous' notion is defined as follows: if this is the first
* child tree item, return its parent; otherwise if his previous neightbour
* is closed, return it; otherwise return the last child tree item from the
* "last->opened ? last->last : last" chain.
* If there is no previous item (top of the tree), it returns NULL.
* <pre>
* OUT: (csTreeItem *)PrevItem
* </pre>
*/
cscmdTreeItemGetPrev,
/**
* Query what's the next of a given item.
* The 'next' notion is defined as follows: if the item is opened,
* return its first child item; otherwise if it is the last item
* in the subtree, return the item following its parent; otherwise
* return the next item in the branch.
* If there is no next item (bottom of the tree), it returns NULL.
* <pre>
* OUT: (csTreeItem *)NextItem
* </pre>
*/
cscmdTreeItemGetNext,
/**
* Ask the parent for its first tree item.
* <pre>
* OUT: (csTreeItem *)Item
* </pre>
*/
cscmdTreeItemGetFirst,
/**
* Ask the parent for its last tree item.
* <pre>
* OUT: (csTreeItem *)Item
* </pre>
*/
cscmdTreeItemGetLast,
/**
* Sent to parent treebox to notify that a tree item is being deleted.
* <pre>
* IN: (csTreeItem *)item;
* </pre>
*/
cscmdTreeItemDeleteNotify,
/**
* Sent to treebox parent to notify it that a tree item has been clicked
* with the right mouse button.
* <pre>
* IN: (csTreeItem *)item;
* </pre>
*/
cscmdTreeItemRightClick,
/**
* Query the selected tree item.Note that the parent of item
* is not neccessarily the tree box (it can be a level N child).
* <pre>
* OUT: (csTreeItem *)item
* </pre>
*/
cscmdTreeQuerySelected,
/**
* Select first item that exactly matches the text.
* <pre>
* IN: (char *)text
* OUT: (csTreeItem *)item (or NULL if not found)
* </pre>
*/
cscmdTreeSelectItem,
/**
* Set horizontal offset for all tree items (horizontal scrolling)
* <pre>
* IN: (int)deltaX
* </pre>
*/
cscmdTreeSetHorizOffset,
/**
* This message is sent by a tree item to its parent when it receives
* a 'mouse down' event.
* <pre>
* IN: (csTreeItem *)source;
* </pre>
*/
cscmdTreeStartTracking,
/**
* This message is sent by a tree item to its parent when the mouse
* is captured and moved over a unfocused tree item, so that the
* csTreeBox component can check whenever the item in question should
* be highlighted.
* <pre>
* IN: (csTreeItem *)source;
* </pre>
*/
cscmdTreeTrack,
/**
* This command tells to a Tree control object to make given item visible
* (and scroll the view if it is not inside the current viewport).
* <pre>
* IN: (csTreeItem *)item;
* </pre>
*/
cscmdTreeMakeVisible,
/**
* Same as cscmdTreeMakeVisible but tells to make visible the entire
* branch (subtree) rather than just the branch, if possible. If the
* branch is too high, the top margin will placed be at the top of the
* view, and the bottom margin will be clipped.
* <pre>
* IN: (csTreeItem *)item;
* </pre>
*/
cscmdTreeMakeBranchVisible,
/**
* Completely clear a tree.
*/
cscmdTreeClear
};
/// Additional state flag to mark open branches
#define CSS_TREEITEM_OPEN 0x00010000
/// Child tree items should be re-positioned
#define CSS_TREEITEM_PLACEITEMS 0x00020000
/// The magic answer that means that the component is indeed a tree item
#define CS_TREEITEM_MAGIC (void *)0xdeadface
/**
* Tree items are divided into several subtypes which will be
* shown in different colors.
*/
enum csTreeItemStyle
{
/// Normal text
cstisNormal,
/// Emphasized text
cstisEmphasized
};
/**
* This class encapsulates a tree item. The tree item always contains
* an "expand/collapse" button, optionally contains two pixmaps (shown
* depending on the expanded state), and a text string. The button is
* displayed only if tree has child items. Also the tree item can contain
* any number of child (subordinate) tree items. Note that the tree item
* can contain ONLY other csTreeItem's and their derivates; the only
* exception is the button component which is handled specialy. Inserting
* something other than a csTreeItem into another csTreeItem will crash,
* since csTreeItem often does unconditional typecasts to csTreeItem.
*/
class csTreeItem : public csComponent
{
friend class csTreeBox;
/// Tree item style
csTreeItemStyle ItemStyle;
/// Tree item images (for closed(0) and open(1) states)
csPixmap *ItemBitmap [2];
/// Delete bitmap on object deletion?
bool DeleteBitmap;
/// Horizontal offset of child items
int hChildrenOffset;
/// The expand/collapse button
csButton *button;
/// The tree box control
csTreeBox *treebox;
/// Place all child tree items
void PlaceItems ();
/// Return the next item after this one
csTreeItem *NextItem ();
/// Return the item preceeding this one
csTreeItem *PrevItem ();
public:
/// Tree item constructor: text item with optional style
csTreeItem (csComponent *iParent, const char *iText, int iID = 0,
csTreeItemStyle iStyle = cstisNormal);
/// Tree item destructor
virtual ~csTreeItem ();
/// Handle input events
virtual bool HandleEvent (iEvent &Event);
/// Draw the tree item
virtual void Draw ();
/// Handle additional state flags
virtual void SetState (int mask, bool enable);
/// Invalidate ourselves when the focus goes to one of our children
virtual bool SetFocused (csComponent *comp);
/// Tell parent to re-position items
virtual void Insert (csComponent *comp);
/// Tell parent to re-position items
virtual void Delete (csComponent *comp);
/// Report the minimal size of tree item
virtual void SuggestSize (int &w, int &h);
/// Report the minimal size of tree item and total size with children
void SuggestTotalSize (int &w, int &h, int &totw, int &toth);
/// Set tree item image (possibly for open state too)
void SetBitmap (csPixmap *iBitmap, csPixmap *iBitmapOpen = NULL,
bool iDelete = true);
/// Set horizontal offset of child items
void SetChildOffset (int ihOffset)
{ hChildrenOffset = ihOffset; }
/// Toggle the open state of the branch: 0: collapse, 1: expand, other: toggle
int Toggle (int iAction = 2);
/**
* For each subtree item call a function with a optional arg
* Function returns the first child on which func returnes 'true'
* Optionally you can pass an "only for opened branches" flag,
* so that only visible branches will be handled.
*/
csTreeItem *ForEachItem (bool (*func) (csTreeItem *child, void *param),
void *param = NULL, bool iOnlyOpen = false);
/// Force a reset of button size & position
void ResetButton ()
{ button->SetRect (0, 0, -1, -1); parent->SendCommand (cscmdTreeItemSizeChangeNotify, this); }
};
/**
* Tree control styles. These are bit masks which can be ORed
* together to form a final value sent to the csTreeBox constructor.
*/
/// Tree has a horizontal scroll bar
#define CSTS_HSCROLL 0x00000001
/// Tree has a vertical scroll bar
#define CSTS_VSCROLL 0x00000002
/// Automatically hide scrollbars if they are not needed
#define CSTS_AUTOSCROLLBAR 0x00000004
/// Tree items have small expand/collapse buttons
#define CSTS_SMALLBUTTONS 0x00000008
/// default tree control style
#define CSTS_DEFAULTVALUE CSTS_VSCROLL | CSTS_AUTOSCROLLBAR
/// Child tree items should be re-positioned
#define CSS_TREEBOX_PLACEITEMS 0x00010000
/// Temporarily ignore cscmdTreeMakeVisible commands (used internally)
#define CSS_TREEBOX_LOCKVISIBLE 0x00020000
/// Tree control frame styles
enum csTreeFrameStyle
{
/// tree control has no frame
cstfsNone,
/// tree control has a thin 3D rectangular frame
cstfsThinRect,
/// tree control has a thick 3D rectangular frame
cstfsThickRect
};
/**
* The csTreeBox class is a rectangle which contains a number of subrectangles,
* each of which is recursively similar to its parent. In other words, every
* tree item can contain a subtree itself. In very other words, the tree is
* a graph, every vertex of which has one incoming and several outgoing edges.
* The csTreeBox control can hold several trees at once (e.g. it can have
* several "roots"). csTreeBox control ALWAYS contains just one selected
* item at a time; multiple selection mode is not implemented (I don't see
* why this may be useful anyway).
*<p>
* Every csTreeItem that is inserted into the tree is queried for its preferred
* size (in particular its preffered height), and the next item is positioned
* at the bottom of every previous item. Every csTreeItem asks in turn all his
* child nodes (if the tree node is "open") or just returns its own height
* without child nodes.
*<p>
* Example code how to create a tree:
*<code>
* csTreeBox *tree = new csTreeBox (app);
* tree->SetRect (0, 0, 200, 400);
* csTreeItem *item1, *item2, *item3;
* item1 = new csTreeItem (tree, "My Computer");
* item2 = new csTreeItem (item1, "C:\\");
* item3 = new csTreeItem (item2, "Blindows");
* item3 = new csTreeItem (item2, "Suxx");
* item2 = new csTreeItem (item1, "D:\\");
* item3 = new csTreeItem (item2, "My Documents");
* item3 = new csTreeItem (item2, "My Toys");
* item3 = new csTreeItem (item2, "My Mom Told Me - Dont Run Windows");
* item2 = new csTreeItem (item1, "\\\\SAMBA\\RULEZ\\FOREVER\\");
* item3 = new csTreeItem (item2, "Home directory");
* item3 = new csTreeItem (item2, "Public stuff");
*</code>
* Keyboard navigation:
* <dl>
* <dt>Up/Down</dt><dd>Select previous/next tree item</dd>
* <dt>Left/Right</dt><dd>Scroll tree horizontally (if meaningful)</dd>
* <dt>Ctrl+Left/Right</dt><dd>Scroll horizontally in big steps</dd>
* <dt>PgUp/PgDn</dt><dd>Go to the previous/next page of the tree.</dd>
* <dt>Shift+PgUp/PgDn</dt><dd>Show the previous/next page of the tree
* (does not move the caret).</dd>
* <dt>Ctrl+PgUp/PgDn</dd><dd>Go to the first/last tree item</dd>
* <dt>Home/End</dt><dd>Scroll to left/right margin.</dd>
* <dt>Ctrl+Home/End</dt><dd>Scroll to the beginning/end of the tree
* (does not move the caret).</dd>
* <dt>Keypad PLUS/MINUS</dt><dd>Expand/collapse current branch.</dd>
* <dt>Ctrl+Keypad PLUS/MINUS</dt><dd>Expand/collapse all branches
* at once.</dd>
* <dt>Shift+Keypad PLUS/MINUS</dt><dd>Expand/collapse all the items
* contained in the current branch.</dd>
* <dt>Space</dt><dd>Toggle expand/collapse current branch</dd>
* <dt>Any other symbols</dt><dd>Find the next item that starts with
* given character. For example, pressing 'a' will find the first
* item following current which starts with 'A' or 'a'; if there
* is no one until the end of tree, the search is restarted from
* top; if there is no such item at all, the cursor stays still.</dd>
* </dl>
*/
class csTreeBox : public csComponent
{
/**
* A private class used to insert all tree items into.
* This is used since we need to not allow any tree item
* to paint on top of treebox border or scrollbars; thus
* this class. The hierarchy of a treebox looks this way:
* <pre>
* csTreeBox
* +--- csTreeBox::csTreeView
* +--- Item 1
* | +--- Item 1:1
* | +--- Item 1:2
* | +--- ...
* +--- Item 2
* ...
* </pre>
* This component should contain ONLY and EXCLUSIVELY csTreeItem's
* and their derivates; inserting something other will lead to crash
* since csTreeBox often uses unconditional typecasts to csTreeItem.
*/
class csTreeView : public csComponent
{
public:
/// Constructor
csTreeView (csComponent *iParent);
/// Resend all command events to parent (csTreeBox)
virtual bool HandleEvent (iEvent &Event);
/// Set parent's CSS_TREEBOX_PLACEITEMS since a item has been removed
virtual void Delete (csComponent *comp);
} *clipview;
/// Tree style
int TreeStyle;
/// Tree frame style
csTreeFrameStyle FrameStyle;
/// Tree frame width and height
int BorderWidth, BorderHeight;
/// The timer
csComponent *timer;
/// The scroll bars
csScrollBar *hscroll, *vscroll;
/// Status of both scroll bars
csScrollBarStatus hsbstatus, vsbstatus;
/// Horizontal scrolling position & maximum width of all visible tree items
int deltax, maxdeltax;
/// Vertical scrolling position & total height of all the tree items
int deltay, maxdeltay;
/// Active tree item
csTreeItem *active;
/// Return the next item after this one
csTreeItem *NextItem ();
/// Return the item preceeding this one
csTreeItem *PrevItem ();
public:
/// Create input line object
csTreeBox (csComponent *iParent, int iStyle = CSTS_DEFAULTVALUE,
csTreeFrameStyle iFrameStyle = cstfsThickRect);
/// Destroy the tree box
virtual ~csTreeBox ();
/// Handle external events and generate timeouts
virtual bool HandleEvent (iEvent &Event);
/// Draw the tree
virtual void Draw ();
/// Find a place for each tree item, and optionally set scrollbar parameters
void PlaceItems (int sbFlags = CSTS_HSCROLL | CSTS_VSCROLL);
/// Resize child items on parent window resize
virtual bool SetRect (int xmin, int ymin, int xmax, int ymax);
/**
* For each tree item call a function with a optional arg
* Function returns the first child on which func returnes 'true'
*/
csTreeItem *ForEachItem (bool (*func) (csTreeItem *child, void *param),
void *param = NULL, bool iOnlyOpen = false);
/// Override SetState method to toggle scrollbars together with CSS_SELECTED
virtual void SetState (int mask, bool enable);
/// Set fPlaceItems since a item has been inserted
virtual void Insert (csComponent *comp);
/// Expand all items
virtual void ExpandAll ();
/// Collapse all items
virtual void CollapseAll ();
/// Query tree box style
int GetStyle () { return TreeStyle; }
/// Query tree box frame style
csTreeFrameStyle GetFrameStyle () { return FrameStyle; }
/// Change tree box style
void SetStyle (int iStyle, csTreeFrameStyle iFrameStyle);
protected:
friend class csTreeItem;
/// Set the imagess for expand/collapse button
void PrepareButton (csButton *iButton, bool iOpen);
/// Make a tree item visible (the functionality for cscmdTreeMakeVisible)
void MakeItemVisible (csComponent *iItem, bool iChildren = false);
/// Focus a item (and defocus all other items)
void FocusItem (csTreeItem *iItem);
/// Scroll vertically by iDelta pixels, possibly preserving caret's relative Y
void VScroll (int iDelta, bool iMoveCaret);
/// Place scrollbars and the csTreeView.
void PlaceScrollbars ();
};
#endif // __CSTREE_H__
|