1 | Unit Outline2;
|
---|
2 |
|
---|
3 | Interface
|
---|
4 |
|
---|
5 | Uses
|
---|
6 | Classes,
|
---|
7 | Forms,
|
---|
8 | SysUtils,
|
---|
9 | BseDos;
|
---|
10 |
|
---|
11 | {
|
---|
12 | History
|
---|
13 |
|
---|
14 | V1.4.13 20/1/1
|
---|
15 | Standardised border, use DrawSystemBorder.
|
---|
16 | Added smooth scrolling.
|
---|
17 |
|
---|
18 | V1.4.12 16/9/00
|
---|
19 | Added recursive collapse functions. Incl TOutline2.CollapseAll;
|
---|
20 |
|
---|
21 | V1.4.11 9/8/00
|
---|
22 | Small optimisation for adding nodes outside
|
---|
23 | of Update...
|
---|
24 | If the node is collapsed, don't check refresh
|
---|
25 |
|
---|
26 | V1.4.10 9/8/00
|
---|
27 | Added level and parent functions to TNOde
|
---|
28 |
|
---|
29 | V1.4.9 9/8/00
|
---|
30 | Fixed problem with not setting up scroll bars after update.?
|
---|
31 | Draw selected node correctly, with inverted colors.
|
---|
32 |
|
---|
33 | V1.4.8 31/7/00
|
---|
34 | Crap - I damaged the node setting.
|
---|
35 |
|
---|
36 | V1.4.7 30/7/00
|
---|
37 | Improved handling during updates: if the
|
---|
38 | selected node is set during update then the new node is
|
---|
39 | just saved and applied at end update.
|
---|
40 |
|
---|
41 | V1.4.6 30/7/00
|
---|
42 | When clearing a node's children do it last node first
|
---|
43 | for efficiency in list handling.
|
---|
44 |
|
---|
45 | V1.4.5 30/7/00
|
---|
46 | Minor bit of fiddling with child list allocation.
|
---|
47 |
|
---|
48 | V1.4.4 26/4/00
|
---|
49 | Added goto next node up and down
|
---|
50 | (includes non-visible nodes; renamed previous
|
---|
51 | methods to gotonextVISIBLEnodeup/down)
|
---|
52 |
|
---|
53 | V1.4.3 26/4/00
|
---|
54 | Added page up and down
|
---|
55 |
|
---|
56 | V1.4.2 26/4/00
|
---|
57 | Fixed problem clearing corner rect between scrollbars.
|
---|
58 |
|
---|
59 | V1.4.1 26/4/00
|
---|
60 | Added +/- keyboard commands
|
---|
61 | If selected node would be hidden when collapsing then
|
---|
62 | make the collapsing node the selected one.
|
---|
63 |
|
---|
64 | V1.4.0 26/4/00
|
---|
65 | Hmm, did I really do nothing for all that time ?
|
---|
66 | Anyway, now has keyboard support, home/end/cursor up/down
|
---|
67 |
|
---|
68 | V1.3.1 12/4/00
|
---|
69 | Tree lines have a seperate color
|
---|
70 | Limit plus minus size to min 7
|
---|
71 | ScanExtents sets lineheight to textheight if textheight is bigger.
|
---|
72 |
|
---|
73 | V1.3.0 12/4/00
|
---|
74 | Optimised a lot more. Now drawing can be just of a single node
|
---|
75 | which eliminates most flickering. Made the plus/minus buttons
|
---|
76 | show feedback when clicked, exactly like original TOutline.
|
---|
77 |
|
---|
78 | V1.2.0 11/4/00
|
---|
79 | Worked some more on visual aspects:
|
---|
80 | - can now draw 3d or flat plus/minus
|
---|
81 | - optimise background clearing somewhat (draw per node)
|
---|
82 | - can show selected node as whole line or just text
|
---|
83 |
|
---|
84 | THis reduces flicker but, it coudl be better.
|
---|
85 | Main thing to do would be to seperate out the layout:
|
---|
86 |
|
---|
87 | Function Layout:
|
---|
88 | Reads from root to last expanded node. Works out Y position of
|
---|
89 | each node and stores in the node. (?)
|
---|
90 |
|
---|
91 | This would allow node drawing to be done basically independently...
|
---|
92 |
|
---|
93 | V1.1.0 ???
|
---|
94 | Now can set topnode to anything. Will draw
|
---|
95 | correctly.
|
---|
96 | Added ExpandParents method to help
|
---|
97 | }
|
---|
98 |
|
---|
99 | const
|
---|
100 | AllNodes = nil;
|
---|
101 | WM_MOUSEENTER = $041E;
|
---|
102 | WM_MOUSELEAVE = $041F;
|
---|
103 |
|
---|
104 | Type
|
---|
105 |
|
---|
106 | TNodeFindFunction = function( Data: TObject ): boolean;
|
---|
107 |
|
---|
108 | TOutline2 = class;
|
---|
109 |
|
---|
110 | TNode = class
|
---|
111 | protected
|
---|
112 | _Text: ^string;
|
---|
113 | _Data: TObject;
|
---|
114 | _Children: TList;
|
---|
115 | _Parent: TNode; // nil if head
|
---|
116 | _Expanded: boolean; // only applicable if _Children.Count> 0
|
---|
117 | _Outline: TOutline2;
|
---|
118 | Function GetChild( index: longint ): TNode;
|
---|
119 | Function IsVisible: boolean;
|
---|
120 | procedure CheckChangeRefresh;
|
---|
121 | Function GetText: string;
|
---|
122 | procedure SetText( const NewText: string );
|
---|
123 | procedure FreeText;
|
---|
124 | public
|
---|
125 | property Children[ index: longint ]: TNode read GetChild;
|
---|
126 | property Text: string read GetText write SetText;
|
---|
127 | property Data: TObject read _Data write _Data;
|
---|
128 |
|
---|
129 | constructor Create( Parent: TNode );
|
---|
130 |
|
---|
131 | function AddChild( const TheText: string;
|
---|
132 | const TheData: TObject ): TNode;
|
---|
133 | function HasChildren: boolean;
|
---|
134 | function ChildCount: longint;
|
---|
135 |
|
---|
136 | procedure Clear; // clear children
|
---|
137 |
|
---|
138 | destructor Destroy; override;
|
---|
139 |
|
---|
140 | function Level: longint; // 0 is top level.
|
---|
141 | function Parent: TNode; // nil if at top level
|
---|
142 | function FullPath( const Separator: string ): string;
|
---|
143 | function IndexOfChild( Child: TNode ): longint;
|
---|
144 | function IndexInParent: longint;
|
---|
145 | function FindData( DataToFind: TObject ): TNode;
|
---|
146 | function FindByFunction( FindFunction: TNodeFindFunction ): TNode;
|
---|
147 |
|
---|
148 | // Returns true if the given node is a parent of
|
---|
149 | // this node
|
---|
150 | function NodeIsAParent( Node: TNode ): boolean;
|
---|
151 |
|
---|
152 | property Expanded: boolean read _Expanded;
|
---|
153 | procedure Expand;
|
---|
154 | procedure ExpandChildren( Recursive: boolean );
|
---|
155 |
|
---|
156 | // Expand all parents if needed
|
---|
157 | procedure ExpandParents;
|
---|
158 |
|
---|
159 | procedure Collapse;
|
---|
160 | procedure CollapseChildren( Recursive: boolean );
|
---|
161 | end;
|
---|
162 |
|
---|
163 | TNodePart =
|
---|
164 | (
|
---|
165 | npNothing,
|
---|
166 | npPlusMinus,
|
---|
167 | npBitmap, // not yet implemented
|
---|
168 | npText,
|
---|
169 | npOther
|
---|
170 | );
|
---|
171 |
|
---|
172 | TPlusMinusStyle = ( pmFlat, pm3d );
|
---|
173 |
|
---|
174 | TNodeEvent = procedure( Node: TNode ) of object;
|
---|
175 |
|
---|
176 | TOutline2=Class(TControl)
|
---|
177 | Protected
|
---|
178 | _UpdateCount: integer;
|
---|
179 | _NewSelectedNode: TNode; // during update
|
---|
180 |
|
---|
181 | _MouseDownNode: TNode;
|
---|
182 | _MouseDownPart: TNodePart;
|
---|
183 | _MouseDownFeedback: boolean;
|
---|
184 | _LastMouseMoveFeedback: boolean;
|
---|
185 |
|
---|
186 | _LastMouseX: longint;
|
---|
187 | _LastMouseY: longint;
|
---|
188 |
|
---|
189 | _HScrollbar: TScrollbar;
|
---|
190 | _VScrollbar: TScrollbar;
|
---|
191 | _NeedVScroll, _NeedHScroll: boolean;
|
---|
192 |
|
---|
193 | // Scroll information
|
---|
194 | // we use these rather than the scrollbar positions direct,
|
---|
195 | // since those are not updated during tracking
|
---|
196 | FXScroll: longint;
|
---|
197 | FYScroll: longint;
|
---|
198 |
|
---|
199 | FLastXScroll: longint;
|
---|
200 | FLastYScroll: longint;
|
---|
201 |
|
---|
202 | FSmoothScroll: boolean;
|
---|
203 |
|
---|
204 | _Root: TNode;
|
---|
205 |
|
---|
206 | _HoverTimer: TTimer;
|
---|
207 | _HintWindow: THintWindow;
|
---|
208 |
|
---|
209 | // appearance controls
|
---|
210 | _BorderStyle: TBorderStyle;
|
---|
211 | _ScrollbarWidth: longint;
|
---|
212 | _LineHeight: longint;
|
---|
213 | _AutoLineHeight: boolean;
|
---|
214 | _Indent: longint; // X distance between branches
|
---|
215 | _LeftMargin: longint; // X distance to left of first plus/minus col
|
---|
216 | _TextIndent: longint; // pixels between stub end and text
|
---|
217 | _PlusMinusWidth: longint;
|
---|
218 | _PlusMinusHeight: longint;
|
---|
219 | _StubWidth: longint; // additional distance beyond indent to draw lines
|
---|
220 | _PlusMinusStyle: TPlusMinusStyle;
|
---|
221 | _SelectLine: boolean;
|
---|
222 | _TreeLineColor: TColor;
|
---|
223 |
|
---|
224 | _PathSeparator: string;
|
---|
225 |
|
---|
226 | _SelectedNode: TNode;
|
---|
227 |
|
---|
228 | _OnItemDblClick: TNodeEvent;
|
---|
229 | _OnItemFocus: TNodeEvent;
|
---|
230 | _OnItemClick: TNodeEvent;
|
---|
231 | _OnExpand: TNodeEvent;
|
---|
232 | _OnCollapse: TNodeEvent;
|
---|
233 |
|
---|
234 | _DrawNode: TNode; // nil for all
|
---|
235 |
|
---|
236 | Procedure SetupComponent; Override;
|
---|
237 |
|
---|
238 | Procedure ScanExtents;
|
---|
239 | Procedure ScanNodeExtents( Node: TNode;
|
---|
240 | X: longint;
|
---|
241 | Var MaxX: longint;
|
---|
242 | Var MaxY: longint );
|
---|
243 |
|
---|
244 | Function RowIsVisible( Y: longint ): boolean;
|
---|
245 |
|
---|
246 | function GetNodePosition( const Node: TNode;
|
---|
247 | Var NodeTop: longint ): boolean;
|
---|
248 | function NodeGetNodePosition( const NodeToFind: TNode;
|
---|
249 | const NodeToScan: TNode;
|
---|
250 | Var NodeTop: longint ): boolean;
|
---|
251 |
|
---|
252 | procedure DrawNode( Node: TNode );
|
---|
253 |
|
---|
254 | procedure Draw;
|
---|
255 | Procedure DrawBorder;
|
---|
256 | Procedure PaintNode( Node: TNode;
|
---|
257 | X: longint;
|
---|
258 | Var Y: longint );
|
---|
259 |
|
---|
260 | procedure DrawPlusMinus( Rect: TRect;
|
---|
261 | Expanded: boolean;
|
---|
262 | Pressed: boolean );
|
---|
263 |
|
---|
264 | Procedure TestHit( Point: TPoint;
|
---|
265 | Var Node: TNode;
|
---|
266 | Var Part: TNodePart );
|
---|
267 | Procedure TestNodeHit( Node: TNode;
|
---|
268 | Point: TPoint;
|
---|
269 | X: longint;
|
---|
270 | Var Y: longint;
|
---|
271 | Var HitNode: TNode;
|
---|
272 | Var Part: TNodePart );
|
---|
273 | Procedure SetupScrollbars;
|
---|
274 | function GetDrawRect: TRect;
|
---|
275 | function GetTextRect: TRect;
|
---|
276 | function DrawHeight: longint;
|
---|
277 | function GetLineRect( LineBottom: longint ): TRect;
|
---|
278 | Function GetPlusMinusRect( Left, LineBottom: longint ): TRect;
|
---|
279 |
|
---|
280 | Procedure DoHorizontalScroll( NewX: longint );
|
---|
281 | Procedure DoVerticalScroll( NewY: longint );
|
---|
282 |
|
---|
283 | // Property handlers
|
---|
284 | Procedure SetSelectedNode( Node: TNode );
|
---|
285 | Procedure SetTopNode( Node: TNode );
|
---|
286 |
|
---|
287 | Function GetChild( index: longint ): TNode;
|
---|
288 | Function GetChildCount: longint;
|
---|
289 |
|
---|
290 | Procedure SetLineHeight( LineHeight: longint );
|
---|
291 | Procedure SetAutoLineHeight( Value: boolean );
|
---|
292 | Procedure SetIndent( Indent: longint );
|
---|
293 | Procedure SetBorderStyle( BorderStyle: TBorderStyle );
|
---|
294 | Procedure SetScrollbarWidth( ScrollbarWidth: longint );
|
---|
295 | Procedure SetLeftMargin( LeftMargin: longint );
|
---|
296 | Procedure SetTextIndent( TextIndent: longint );
|
---|
297 | Procedure SetPlusMinusWidth( PlusMinusWidth: longint );
|
---|
298 | Procedure SetPlusMinusHeight( PlusMinusHeight: longint );
|
---|
299 | Procedure SetStubWidth( StubWidth: longint );
|
---|
300 | Procedure SetPlusMinusStyle( NewValue: TPlusMinusStyle );
|
---|
301 | Procedure SetSelectLine( NewValue: boolean );
|
---|
302 | Procedure SetTreeLineColor( NewValue: TColor );
|
---|
303 | Public
|
---|
304 | Procedure OnHoverTimeout( Sender: TObject );
|
---|
305 | // PM Events
|
---|
306 | Procedure Redraw( const rec: TRect ); Override;
|
---|
307 | Procedure Resize; override;
|
---|
308 | Procedure MouseDblClick( Button: TMouseButton;
|
---|
309 | ShiftState: TShiftState;
|
---|
310 | X, Y: Longint ); override;
|
---|
311 | Procedure MouseDown( Button: TMouseButton;
|
---|
312 | ShiftState: TShiftState;
|
---|
313 | X, Y: Longint ); override;
|
---|
314 | Procedure MouseUp( Button: TMouseButton;
|
---|
315 | ShiftState: TShiftState;
|
---|
316 | X, Y: Longint ); override;
|
---|
317 | Procedure MouseMove( ShiftState: TShiftState;
|
---|
318 | X, Y: Longint ); override;
|
---|
319 |
|
---|
320 | Procedure Scroll( Sender: TScrollbar;
|
---|
321 | ScrollCode: TScrollCode;
|
---|
322 | Var ScrollPos: Longint ); override;
|
---|
323 |
|
---|
324 | Procedure SetupShow; override;
|
---|
325 |
|
---|
326 | Procedure ScanEvent( Var KeyCode: TKeyCode;
|
---|
327 | RepeatCount: Byte ); override;
|
---|
328 | Procedure CharEvent( Var Key: Char;
|
---|
329 | RepeatCount: Byte ); override;
|
---|
330 | Procedure WMMouseLeave( Var Msg: TMessage ); message WM_MOUSELEAVE;
|
---|
331 |
|
---|
332 | Procedure FontChange; override;
|
---|
333 |
|
---|
334 | Procedure SetFocus; override;
|
---|
335 | Procedure KillFocus; override;
|
---|
336 | published
|
---|
337 | property Align;
|
---|
338 | property Color;
|
---|
339 | property Font;
|
---|
340 | property ParentColor;
|
---|
341 | property ParentFont;
|
---|
342 | property ParentPenColor;
|
---|
343 | property ParentShowHint;
|
---|
344 | property PenColor;
|
---|
345 | property PopupMenu;
|
---|
346 | property ShowHint;
|
---|
347 | Property TabOrder;
|
---|
348 | Property TabStop;
|
---|
349 | property Visible;
|
---|
350 | property ZOrder;
|
---|
351 |
|
---|
352 | property LineHeight: longint read _LineHeight write SetLineHeight;
|
---|
353 | property AutoLineHeight: boolean read _AutoLineHeight write SetAutoLineHeight;
|
---|
354 | property Indent: longint read _Indent write SetIndent;
|
---|
355 | property BorderStyle: TBorderStyle read _BorderStyle write SetBorderStyle;
|
---|
356 | property ScrollbarWidth: longint read _ScrollbarWidth write SetScrollbarWidth;
|
---|
357 | property LeftMargin: longint read _LeftMargin write SetLeftMargin;
|
---|
358 | property TextIndent: longint read _TextIndent write SetTextIndent;
|
---|
359 | property PlusMinusWidth: longint read _PlusMinusWidth write SetPlusMinusWidth;
|
---|
360 | property PlusMinusHeight: longint read _PlusMinusHeight write SetPlusMinusHeight;
|
---|
361 | property StubWidth: longint read _StubWidth write SetStubWidth;
|
---|
362 | property PlusMinusStyle: TPlusMinusStyle read _PlusMinusStyle write SetPlusMinusStyle;
|
---|
363 | property SelectLine: boolean read _SelectLine write SetSelectLine;
|
---|
364 | property TreeLineColor: TColor read _TreeLineColor write SetTreeLineColor;
|
---|
365 |
|
---|
366 | property SmoothScroll: boolean read FSmoothScroll write FSmoothScroll;
|
---|
367 |
|
---|
368 | property PathSeparator:string read _PathSeparator write _PathSeparator;
|
---|
369 |
|
---|
370 | property OnItemDblClick: TNodeEvent read _OnItemDblClick write _OnItemDblClick;
|
---|
371 | property OnItemFocus: TNodeEvent read _OnItemFocus write _OnItemFocus;
|
---|
372 | property OnItemClick: TNodeEvent read _OnItemClick write _OnItemClick;
|
---|
373 | property OnExpand: TNodeEvent read _OnExpand write _OnExpand;
|
---|
374 | property OnCollapse: TNodeEvent read _OnCollapse write _OnCollapse;
|
---|
375 | property OnClick;
|
---|
376 | property OnDblClick;
|
---|
377 | property OnDragOver;
|
---|
378 | property OnDragDrop;
|
---|
379 | property OnEndDrag;
|
---|
380 | Property OnEnter;
|
---|
381 | Property OnExit;
|
---|
382 | Property OnFontChange;
|
---|
383 | Property OnHide;
|
---|
384 | property OnKeyPress;
|
---|
385 | Property OnResize;
|
---|
386 | Property OnScan;
|
---|
387 | Property OnSetupShow;
|
---|
388 | Property OnShow;
|
---|
389 |
|
---|
390 | public
|
---|
391 |
|
---|
392 | procedure Clear;
|
---|
393 |
|
---|
394 | function AddChild( const TheText: string;
|
---|
395 | const TheObject: TObject ): TNode;
|
---|
396 | property Children[ index: longint ]: TNode read GetChild;
|
---|
397 | property ChildCount: longint read GetChildCount;
|
---|
398 |
|
---|
399 | procedure BeginUpdate;
|
---|
400 | procedure EndUpdate;
|
---|
401 |
|
---|
402 | Destructor Destroy; Override;
|
---|
403 |
|
---|
404 | function NextNodeUp( Node: TNode;
|
---|
405 | VisibleOnly: boolean ): TNode;
|
---|
406 | function NextNodeDown( Node: TNode;
|
---|
407 | VisibleOnly: boolean ): TNode;
|
---|
408 | function LastVisibleNode: TNode;
|
---|
409 |
|
---|
410 | Procedure GotoFirstNode;
|
---|
411 | Procedure GotoLastVisibleNode;
|
---|
412 |
|
---|
413 | // The following 4 functions return false if
|
---|
414 | // they could not do the requested movement
|
---|
415 | function GotoNextVisibleNodeUp: boolean;
|
---|
416 | function GotoNextVisibleNodeDown: boolean;
|
---|
417 | function GotoNextNodeUp: boolean;
|
---|
418 | function GotoNextNodeDown: boolean;
|
---|
419 |
|
---|
420 | Procedure PageUp;
|
---|
421 | Procedure PageDown;
|
---|
422 |
|
---|
423 | Procedure ExpandAll;
|
---|
424 | Procedure CollapseAll;
|
---|
425 |
|
---|
426 | // search for a node which starts with the given text
|
---|
427 | // Note: if you use VisibleOnly true, then make sure you
|
---|
428 | // start with a visible node!!
|
---|
429 | Function FindNextNodeByText( StartNode: TNode;
|
---|
430 | const S: string;
|
---|
431 | VisibleOnly: boolean ): TNode;
|
---|
432 |
|
---|
433 | { Procedure ScrollUpLine;
|
---|
434 | Procedure ScrollDownLine;
|
---|
435 | Procedure ScrollUpPage;
|
---|
436 | Procedure ScrollDownPage;
|
---|
437 | }
|
---|
438 | { Procedure ScrollLeftLine;
|
---|
439 | Procedure ScrollRightLine;
|
---|
440 | Procedure ScrollLeftPage;
|
---|
441 | Procedure ScrollRightPage;
|
---|
442 | }
|
---|
443 | property SelectedNode: TNode read _SelectedNode write SetSelectedNode;
|
---|
444 | procedure SetSelectedObject( Data: TObject );
|
---|
445 | function NodeFromObject( Data: TObject ): TNode;
|
---|
446 | function FindByFunction( FindFunction: TNodeFindFunction ): TNode;
|
---|
447 |
|
---|
448 | // property TopNode: TNode read _TopNode write SetTopNode;
|
---|
449 | End;
|
---|
450 |
|
---|
451 | {Define components to export}
|
---|
452 | {You may define a page of the component palette and a component bitmap file}
|
---|
453 | Exports
|
---|
454 | TOutline2,'User','Outline2.bmp';
|
---|
455 |
|
---|
456 | Implementation
|
---|
457 |
|
---|
458 | uses
|
---|
459 | Messages,
|
---|
460 | ControlScrolling,
|
---|
461 | StringUtilsUnit;
|
---|
462 |
|
---|
463 | // ============================================================================
|
---|
464 | // Node implementation
|
---|
465 | // ============================================================================
|
---|
466 |
|
---|
467 | Function TNode.IsVisible: boolean;
|
---|
468 | var
|
---|
469 | Node: TNode;
|
---|
470 | begin
|
---|
471 | Result:= true;
|
---|
472 | Node:= self;
|
---|
473 | while Node._Parent <> nil do
|
---|
474 | begin
|
---|
475 | Node:= Node._Parent;
|
---|
476 | if not Node._Expanded then
|
---|
477 | Result:= false;
|
---|
478 | end;
|
---|
479 | end;
|
---|
480 |
|
---|
481 | // Call when a node changes (add, delete, rename, collapse/expand )
|
---|
482 | procedure TNode.CheckChangeRefresh;
|
---|
483 | begin
|
---|
484 | if _Outline.Handle = 0 then
|
---|
485 | exit;
|
---|
486 |
|
---|
487 | if _Outline._UpdateCount > 0 then
|
---|
488 | exit;
|
---|
489 |
|
---|
490 | if IsVisible then
|
---|
491 | begin
|
---|
492 | _Outline.ScanExtents;
|
---|
493 | _Outline.Refresh;
|
---|
494 | end;
|
---|
495 | end;
|
---|
496 |
|
---|
497 | function TNode.GetText: string;
|
---|
498 | begin
|
---|
499 | Result:= _Text^;
|
---|
500 | end;
|
---|
501 |
|
---|
502 | procedure TNode.FreeText;
|
---|
503 | begin
|
---|
504 | if _Text <> nil then
|
---|
505 | FreeMem( _Text, Length( _Text^ ) + 1 );
|
---|
506 | end;
|
---|
507 |
|
---|
508 | procedure TNode.SetText( const NewText: string );
|
---|
509 | begin
|
---|
510 | FreeText;
|
---|
511 | GetMem( _Text, Length( NewText ) + 1 );
|
---|
512 | _Text^:= NewText;
|
---|
513 | end;
|
---|
514 |
|
---|
515 | function TNode.AddChild( const TheText: string;
|
---|
516 | const TheData: TObject ): TNode;
|
---|
517 | Var
|
---|
518 | NewNode: TNode;
|
---|
519 | Begin
|
---|
520 | NewNode:= TNode.Create( self );
|
---|
521 | NewNode.Text:= TheText;
|
---|
522 | NewNode.Data:= TheData;
|
---|
523 | NewNode._Outline:= _Outline;
|
---|
524 |
|
---|
525 | if _Children.Count = 0 then
|
---|
526 | _Children.Capacity:= 4;
|
---|
527 |
|
---|
528 | _Children.Add( NewNode );
|
---|
529 | Result:= NewNode;
|
---|
530 |
|
---|
531 | if _Expanded
|
---|
532 | or ( _Children.Count = 1 ) // we just added first child; need to display +
|
---|
533 | then
|
---|
534 | CheckChangeRefresh;
|
---|
535 | End;
|
---|
536 |
|
---|
537 | function TNode.IndexOfChild( Child: TNode ): longint;
|
---|
538 | begin
|
---|
539 | Result:= _Children.IndexOf( Child );
|
---|
540 | end;
|
---|
541 |
|
---|
542 | function TNode.NodeIsAParent( Node: TNode ): boolean;
|
---|
543 | begin
|
---|
544 | if _Parent = _Outline._Root then
|
---|
545 | Result:= false
|
---|
546 | else if _Parent = Node then
|
---|
547 | Result:= true
|
---|
548 | else
|
---|
549 | Result:= _Parent.NodeIsAParent( Node );
|
---|
550 | end;
|
---|
551 |
|
---|
552 | function TNode.IndexInParent: longint;
|
---|
553 | begin
|
---|
554 | if _Parent = nil then
|
---|
555 | result:= -1
|
---|
556 | else
|
---|
557 | Result:= _Parent.IndexOfChild( Self );
|
---|
558 | end;
|
---|
559 |
|
---|
560 | procedure TNode.ExpandChildren( Recursive: boolean );
|
---|
561 | Var
|
---|
562 | ChildIndex: longint;
|
---|
563 | Child: TNode;
|
---|
564 | begin
|
---|
565 | _Outline.BeginUpdate;
|
---|
566 | for ChildIndex:= 0 to _Children.Count - 1 do
|
---|
567 | begin
|
---|
568 | Child:= _Children[ ChildIndex ];
|
---|
569 | Child.Expand;
|
---|
570 | if Recursive then
|
---|
571 | Child.ExpandChildren( true );
|
---|
572 | end;
|
---|
573 | _Outline.EndUpdate;
|
---|
574 | end;
|
---|
575 |
|
---|
576 | procedure TNode.CollapseChildren( Recursive: boolean );
|
---|
577 | Var
|
---|
578 | ChildIndex: longint;
|
---|
579 | Child: TNode;
|
---|
580 | begin
|
---|
581 | _Outline.BeginUpdate;
|
---|
582 | for ChildIndex:= 0 to _Children.Count - 1 do
|
---|
583 | begin
|
---|
584 | Child:= _Children[ ChildIndex ];
|
---|
585 | Child.Collapse;
|
---|
586 | if Recursive then
|
---|
587 | Child.CollapseChildren( true );
|
---|
588 | end;
|
---|
589 | _Outline.EndUpdate;
|
---|
590 | end;
|
---|
591 |
|
---|
592 | function TNode.FindData( DataToFind: TObject ): TNode;
|
---|
593 | Var
|
---|
594 | ChildIndex: longint;
|
---|
595 | Child: TNode;
|
---|
596 | begin
|
---|
597 | if _Parent <> nil then
|
---|
598 | // not root...
|
---|
599 | if Data = DataToFind then
|
---|
600 | begin
|
---|
601 | Result:= self;
|
---|
602 | exit;
|
---|
603 | end;
|
---|
604 | for ChildIndex:= 0 to _Children.Count - 1 do
|
---|
605 | begin
|
---|
606 | Child:= _Children[ ChildIndex ];
|
---|
607 | Result:= Child.FindData( DataToFind );
|
---|
608 | if Result <> nil then
|
---|
609 | exit;
|
---|
610 | end;
|
---|
611 | Result:= nil;
|
---|
612 | end;
|
---|
613 |
|
---|
614 | function TNode.FindByFunction( FindFunction: TNodeFindFunction ): TNode;
|
---|
615 | Var
|
---|
616 | ChildIndex: longint;
|
---|
617 | Child: TNode;
|
---|
618 | d: TObject;
|
---|
619 | begin
|
---|
620 | if _Parent <> nil then
|
---|
621 | begin
|
---|
622 | // not root...
|
---|
623 | d:= Data;
|
---|
624 | if FindFunction( Data ) then
|
---|
625 | begin
|
---|
626 | Result:= self;
|
---|
627 | exit;
|
---|
628 | end;
|
---|
629 | end;
|
---|
630 | for ChildIndex:= 0 to _Children.Count - 1 do
|
---|
631 | begin
|
---|
632 | Child:= _Children[ ChildIndex ];
|
---|
633 | Result:= Child.FindByFunction( FindFunction );
|
---|
634 | if Result <> nil then
|
---|
635 | exit;
|
---|
636 | end;
|
---|
637 | Result:= nil;
|
---|
638 | end;
|
---|
639 |
|
---|
640 | constructor TNode.Create( Parent: TNode );
|
---|
641 | Begin
|
---|
642 | _Parent:= Parent;
|
---|
643 | _Children:= TList.Create;
|
---|
644 | _Expanded:= false;
|
---|
645 | _Text:= nil;
|
---|
646 | End;
|
---|
647 |
|
---|
648 | procedure TNode.Clear;
|
---|
649 | begin
|
---|
650 | // Delete children
|
---|
651 | // (They will remove themselves from us)
|
---|
652 | // Remove them from end of list first for efficiency.
|
---|
653 | while _Children.Count > 0 do
|
---|
654 | TNode( _Children[ _Children.Count - 1 ] ).Destroy;
|
---|
655 | end;
|
---|
656 |
|
---|
657 | destructor TNode.Destroy;
|
---|
658 | Begin
|
---|
659 | Clear;
|
---|
660 | _Children.Destroy;
|
---|
661 | // Delete self from parent
|
---|
662 | if _Parent <> nil then
|
---|
663 | _Parent._Children.Remove( self );
|
---|
664 |
|
---|
665 | if _Outline._NewSelectedNode = self then
|
---|
666 | _Outline._NewSelectedNode := nil;
|
---|
667 |
|
---|
668 | if _Outline._SelectedNode = self then
|
---|
669 | _Outline.SetSelectedNode( nil );
|
---|
670 |
|
---|
671 | FreeText;
|
---|
672 | CheckChangeRefresh;
|
---|
673 | End;
|
---|
674 |
|
---|
675 | function TNode.ChildCount: longint;
|
---|
676 | Begin
|
---|
677 | Result:= _Children.Count;
|
---|
678 | End;
|
---|
679 |
|
---|
680 | function TNode.HasChildren: boolean;
|
---|
681 | Begin
|
---|
682 | Result:= _Children.Count > 0;
|
---|
683 | End;
|
---|
684 |
|
---|
685 | Function TNode.GetChild( index: longint ): TNode;
|
---|
686 | Begin
|
---|
687 | Result:= _Children[ index ];
|
---|
688 | End;
|
---|
689 |
|
---|
690 | function TNode.Level: longint;
|
---|
691 | Var
|
---|
692 | NextNode: TNode;
|
---|
693 | Begin
|
---|
694 | Result:= -1; // since root is a special case
|
---|
695 | NextNode:= _Parent;
|
---|
696 | while NextNode <> nil do
|
---|
697 | begin
|
---|
698 | inc( Result );
|
---|
699 | NextNode:= NextNode._Parent;
|
---|
700 | end;
|
---|
701 | End;
|
---|
702 |
|
---|
703 | Function TNode.Parent: TNode;
|
---|
704 | begin
|
---|
705 | if _Parent = nil then
|
---|
706 | Result:= nil
|
---|
707 | else if _Parent._Parent = nil then
|
---|
708 | Result:= nil // parent is really root but we don't want to give access to root
|
---|
709 | else
|
---|
710 | Result:= _Parent;
|
---|
711 | end;
|
---|
712 |
|
---|
713 | Function TNode.FullPath( const Separator: string ): string;
|
---|
714 | Var
|
---|
715 | NextNode: TNode;
|
---|
716 | Begin
|
---|
717 | Result:= Text;
|
---|
718 | NextNode:= _Parent;
|
---|
719 | while NextNode <> nil do
|
---|
720 | begin
|
---|
721 | Result:= NextNode.Text + Separator + Result;
|
---|
722 | NextNode:= NextNode._Parent;
|
---|
723 | end;
|
---|
724 | End;
|
---|
725 |
|
---|
726 | procedure TNode.Expand;
|
---|
727 | begin
|
---|
728 | if _Expanded then
|
---|
729 | exit;
|
---|
730 | _Expanded:= true;
|
---|
731 | if Assigned( _Outline._OnExpand ) then
|
---|
732 | _Outline._OnExpand( self );
|
---|
733 | CheckChangeRefresh;
|
---|
734 | end;
|
---|
735 |
|
---|
736 | procedure TNode.Collapse;
|
---|
737 | begin
|
---|
738 | if not _Expanded then
|
---|
739 | exit;
|
---|
740 | if _Outline.SelectedNode <> nil then
|
---|
741 | if _Outline.SelectedNode.NodeIsAParent( Self ) then
|
---|
742 | // selected node is in collapsed nodes, make ourself the selected one
|
---|
743 | _Outline._SelectedNode:= Self;
|
---|
744 | if Assigned( _Outline._OnCollapse ) then
|
---|
745 | _Outline._OnCollapse( self );
|
---|
746 | _Expanded:= false;
|
---|
747 | CheckChangeRefresh;
|
---|
748 | end;
|
---|
749 |
|
---|
750 | // Returns true if a row starting at Y will be at least partially visible
|
---|
751 | Function TOutline2.RowIsVisible( Y: longint ): boolean;
|
---|
752 | begin
|
---|
753 | Result:= ( Y < Height + _LineHeight ) and ( Y >= 0 );
|
---|
754 | end;
|
---|
755 |
|
---|
756 | // ============================================================================
|
---|
757 | // Outline component implementation
|
---|
758 | // ============================================================================
|
---|
759 |
|
---|
760 | Procedure TOutline2.ScanExtents;
|
---|
761 | Var
|
---|
762 | ChildIndex: longint;
|
---|
763 | MaxWidth, MaxHeight: longint;
|
---|
764 | AvailableHeight: longint;
|
---|
765 | AvailableWidth: longint;
|
---|
766 | TextRect: TRect;
|
---|
767 | TextHeight: longint;
|
---|
768 | Begin
|
---|
769 | if csDesigning in ComponentState then
|
---|
770 | exit;
|
---|
771 | if Handle = 0 then
|
---|
772 | exit;
|
---|
773 |
|
---|
774 | MaxWidth:= 0;
|
---|
775 | MaxHeight:= 0;
|
---|
776 | _NeedVScroll:= false;
|
---|
777 | _NeedHScroll:= false;
|
---|
778 |
|
---|
779 | TextRect:= GetTextRect;
|
---|
780 | AvailableWidth:= TextRect.Right - TextRect.Left;
|
---|
781 | AvailableHeight:= TextRect.Top - TextRect.Bottom;
|
---|
782 |
|
---|
783 | TextHeight:= Canvas.TextHeight( 'H' );
|
---|
784 | if TextHeight > _LineHeight then
|
---|
785 | _LineHeight := TextHeight;
|
---|
786 |
|
---|
787 | // draw children
|
---|
788 | for ChildIndex:= 0 to _Root.ChildCount - 1 do
|
---|
789 | begin
|
---|
790 | ScanNodeExtents( _Root.Children[ ChildIndex ],
|
---|
791 | 0,
|
---|
792 | MaxWidth,
|
---|
793 | MaxHeight );
|
---|
794 | end;
|
---|
795 |
|
---|
796 | if MaxWidth > AvailableWidth then
|
---|
797 | begin
|
---|
798 | // will need horizontal scroll bar...
|
---|
799 | _NeedHScroll:= true;
|
---|
800 | dec( AvailableHeight, _ScrollBarWidth );
|
---|
801 | end;
|
---|
802 |
|
---|
803 | if MaxHeight > AvailableHeight then
|
---|
804 | begin
|
---|
805 | // will need vertical scroll bar
|
---|
806 | _NeedVScroll:= true;
|
---|
807 | dec( AvailableWidth, _ScrollBarWidth );
|
---|
808 | if _NeedHScroll = false then
|
---|
809 | // check if we need one now,
|
---|
810 | if MaxWidth > AvailableWidth then
|
---|
811 | begin
|
---|
812 | // will need horizontal scroll bar after all
|
---|
813 | dec( AvailableHeight, _ScrollBarWidth );
|
---|
814 | _NeedHScroll:= true;
|
---|
815 | end;
|
---|
816 | end;
|
---|
817 |
|
---|
818 | if _NeedVScroll then
|
---|
819 | begin
|
---|
820 | if _VScrollBar.Position > ( MaxHeight - AvailableHeight ) then
|
---|
821 | _VScrollBar.Position:= MaxHeight - AvailableHeight;
|
---|
822 |
|
---|
823 | _VScrollBar.Min:= 0;
|
---|
824 | _VScrollBar.Max:= MaxHeight;
|
---|
825 | _VScrollBar.SliderSize:= AvailableHeight;
|
---|
826 | _VScrollBar.SmallChange:= _LineHeight;
|
---|
827 | _VScrollBar.LargeChange:= AvailableHeight div 2;
|
---|
828 | end
|
---|
829 | else
|
---|
830 | // everything will fit vertically.
|
---|
831 | _VScrollBar.Position:= 0;
|
---|
832 |
|
---|
833 | if _NeedHScroll then
|
---|
834 | begin
|
---|
835 | if _HScrollBar.Position > ( MaxWidth - AvailableWidth ) then
|
---|
836 | _HScrollBar.Position:= MaxWidth - AvailableWidth;
|
---|
837 |
|
---|
838 | _HScrollBar.Min:= 0;
|
---|
839 | _HScrollBar.Max:= MaxWidth;
|
---|
840 | _HScrollBar.SliderSize:= AvailableWidth;
|
---|
841 | _HScrollBar.SmallChange:= _LineHeight;
|
---|
842 | _HScrollBar.LargeChange:= AvailableWidth div 2;
|
---|
843 | end
|
---|
844 | else
|
---|
845 | // everything will fit horizontally
|
---|
846 | _HScrollBar.Position:= 0; // no offset
|
---|
847 |
|
---|
848 | SetupScrollBars;
|
---|
849 | End;
|
---|
850 |
|
---|
851 | Procedure TOutline2.ScanNodeExtents( Node: TNode;
|
---|
852 | X: longint;
|
---|
853 | Var MaxX: longint;
|
---|
854 | Var MaxY: longint );
|
---|
855 | Var
|
---|
856 | ChildIndex: longint;
|
---|
857 | TextW, TextH: longint;
|
---|
858 | TextX: longint;
|
---|
859 |
|
---|
860 | Begin
|
---|
861 | Canvas.GetTextExtent( Node.Text, TextW, TextH );
|
---|
862 | TextX:= X + _PlusMinusWidth + _StubWidth + _TextIndent;
|
---|
863 |
|
---|
864 | if TextX + TextW > MaxX then
|
---|
865 | MaxX:= TextX + TextW;
|
---|
866 |
|
---|
867 | inc( MaxY, _LineHeight );
|
---|
868 |
|
---|
869 | if Node.ChildCount > 0 then
|
---|
870 | if Node._Expanded then
|
---|
871 | // check children
|
---|
872 | for ChildIndex:= 0 to Node.ChildCount-1 do
|
---|
873 | ScanNodeExtents( Node.Children[ ChildIndex ],
|
---|
874 | X + Indent,
|
---|
875 | MaxX,
|
---|
876 | MaxY );
|
---|
877 |
|
---|
878 | End;
|
---|
879 |
|
---|
880 | function TOutline2.GetDrawRect: TRect;
|
---|
881 | begin
|
---|
882 | Result := ClientRect;
|
---|
883 | if _NeedHScroll then
|
---|
884 | inc( Result.Bottom, _ScrollbarWidth );
|
---|
885 | if _NeedVScroll then
|
---|
886 | dec( Result.Right, _ScrollbarWidth );
|
---|
887 | end;
|
---|
888 |
|
---|
889 | function TOutline2.GetTextRect: TRect;
|
---|
890 | begin
|
---|
891 | Result := GetDrawRect;
|
---|
892 | if _BorderStyle <> bsNone then
|
---|
893 | InflateRect( Result, -2, -2 );
|
---|
894 | end;
|
---|
895 |
|
---|
896 | function TOutline2.DrawHeight: longint;
|
---|
897 | begin
|
---|
898 | Result := ClientRect.Top - ClientRect.Bottom;
|
---|
899 | if _NeedHScroll then
|
---|
900 | dec( Result, _ScrollbarWidth );
|
---|
901 |
|
---|
902 | if _BorderStyle <> bsNone then
|
---|
903 | begin
|
---|
904 | dec( Result, 2 ); // top border
|
---|
905 | if not _NeedHScroll then
|
---|
906 | dec( Result, 2 ); // bottom border
|
---|
907 | end;
|
---|
908 | end;
|
---|
909 |
|
---|
910 | Procedure TOutline2.Redraw( const rec: TRect );
|
---|
911 | Var
|
---|
912 | OldClip: TRect;
|
---|
913 | TextRect: TRect;
|
---|
914 | Begin
|
---|
915 | OldClip:= Canvas.ClipRect;
|
---|
916 |
|
---|
917 | if csDesigning in ComponentState then
|
---|
918 | begin
|
---|
919 | _NeedVScroll:= false;
|
---|
920 | _NeedHScroll:= false;
|
---|
921 | DrawBorder;
|
---|
922 | Canvas.FillRect( GetTextRect, Color );
|
---|
923 | exit;
|
---|
924 | end;
|
---|
925 |
|
---|
926 | FYScroll:= _VScrollBar.Position;
|
---|
927 | FLastYScroll:= FYScroll;
|
---|
928 | FXScroll:= _HScrollBar.Position;
|
---|
929 | FLastXScroll:= FXScroll;
|
---|
930 |
|
---|
931 | DrawBorder;
|
---|
932 |
|
---|
933 | TextRect:= GetTextRect;
|
---|
934 | Canvas.ClipRect:= IntersectRect( rec, TextRect );
|
---|
935 |
|
---|
936 | _DrawNode:= AllNodes;
|
---|
937 | Draw;
|
---|
938 |
|
---|
939 | Canvas.ClipRect:= OldClip;
|
---|
940 |
|
---|
941 | end;
|
---|
942 |
|
---|
943 | procedure TOutline2.DrawNode( Node: TNode );
|
---|
944 | var
|
---|
945 | OldClip: TRect;
|
---|
946 | TextRect: TRect;
|
---|
947 | begin
|
---|
948 | if Node = nil then
|
---|
949 | exit;
|
---|
950 | if InDesigner then
|
---|
951 | exit;
|
---|
952 | if Handle = 0 then
|
---|
953 | exit;
|
---|
954 | _DrawNode:= Node;
|
---|
955 |
|
---|
956 | TextRect:= GetTextRect;
|
---|
957 | OldClip:= Canvas.ClipRect;
|
---|
958 | Canvas.ClipRect:= TextRect;
|
---|
959 |
|
---|
960 | Draw;
|
---|
961 |
|
---|
962 | Canvas.ClipRect:= OldClip;
|
---|
963 | end;
|
---|
964 |
|
---|
965 | procedure TOutline2.Draw;
|
---|
966 | var
|
---|
967 | Y: longint;
|
---|
968 | ChildIndex: longint;
|
---|
969 | TextRect: Trect;
|
---|
970 | begin
|
---|
971 | TextRect:= GetTextRect;
|
---|
972 |
|
---|
973 | Y:= TextRect.Top + _VScrollBar.Position + 1;
|
---|
974 |
|
---|
975 | // draw children
|
---|
976 | for ChildIndex:= 0 to _Root.ChildCount - 1 do
|
---|
977 | begin
|
---|
978 | PaintNode( _Root.Children[ ChildIndex ],
|
---|
979 | _LeftMargin - _HScrollBar.Position,
|
---|
980 | Y );
|
---|
981 | if y < 0 then
|
---|
982 | break;
|
---|
983 | end;
|
---|
984 |
|
---|
985 | // clear remainder -
|
---|
986 | if Y>0 then
|
---|
987 | begin
|
---|
988 | TextRect.Top:= Y - 1;
|
---|
989 | Canvas.FillRect( TextRect, Color );
|
---|
990 | end;
|
---|
991 | End;
|
---|
992 |
|
---|
993 | Procedure TOutline2.DrawBorder;
|
---|
994 | var
|
---|
995 | Rect: TRect;
|
---|
996 | CornerRect: TRect;
|
---|
997 | begin
|
---|
998 | Rect:= GetDrawRect;
|
---|
999 | DrawSystemBorder( Self, Rect, _BorderStyle );
|
---|
1000 | if _NeedHScroll and _NeedVScroll then
|
---|
1001 | begin
|
---|
1002 | CornerRect.Left:= Width - _ScrollBarWidth;
|
---|
1003 | CornerRect.Bottom:= 0;
|
---|
1004 | CornerRect.Right:= Width;
|
---|
1005 | CornerRect.Top:= _ScrollBarWidth;
|
---|
1006 | Canvas.ClipRect:= IntersectRect( Canvas.ClipRect, CornerRect );
|
---|
1007 | Canvas.FillRect( CornerRect, Parent.Color );
|
---|
1008 | end;
|
---|
1009 | end;
|
---|
1010 |
|
---|
1011 | Procedure DrawDottedRect( Canvas: TCanvas; Rect: TRect );
|
---|
1012 | var
|
---|
1013 | OldStyle: TPenStyle;
|
---|
1014 | begin
|
---|
1015 | OldStyle:= Canvas.Pen.Style;
|
---|
1016 | Canvas.Pen.Style:= psInsideFrame; // psAlternate for SPCC v2.5+
|
---|
1017 | Canvas.MoveTo( Rect.Left, Rect.Bottom - 1 );
|
---|
1018 | Canvas.LineTo( Rect.Left, Rect.Top );
|
---|
1019 | Canvas.LineTo( Rect.Right, Rect.Top );
|
---|
1020 | Canvas.LineTo( Rect.Right, Rect.Bottom );
|
---|
1021 | Canvas.LineTo( Rect.Left, Rect.Bottom );
|
---|
1022 | Canvas.Pen.Style:= OldStyle;
|
---|
1023 | end;
|
---|
1024 |
|
---|
1025 | procedure TOutline2.DrawPlusMinus( Rect: TRect;
|
---|
1026 | Expanded: boolean;
|
---|
1027 | Pressed: boolean );
|
---|
1028 | var
|
---|
1029 | CentreY: integer;
|
---|
1030 | CentreX: integer;
|
---|
1031 | begin
|
---|
1032 | CentreY:= ( Rect.Top + Rect.Bottom ) div 2;
|
---|
1033 | CentreX:= ( Rect.Left + Rect.Right ) div 2;
|
---|
1034 |
|
---|
1035 | Canvas.Pen.Color:= clBlack;
|
---|
1036 |
|
---|
1037 | case _PlusMinusStyle of
|
---|
1038 | pmFlat:
|
---|
1039 | begin
|
---|
1040 | if Pressed then
|
---|
1041 | Canvas.FillRect( Rect, clHighlight );
|
---|
1042 | DrawDottedRect( Canvas, Rect );
|
---|
1043 | end;
|
---|
1044 |
|
---|
1045 | pm3d:
|
---|
1046 | begin
|
---|
1047 | Canvas.Rectangle( Rect );
|
---|
1048 |
|
---|
1049 | InflateRect( Rect, -1, -1 );
|
---|
1050 | Canvas.FillRect( Rect, clLtGray );
|
---|
1051 | if Pressed then
|
---|
1052 | Canvas.ShadowedBorder( Rect,
|
---|
1053 | clDkGray,
|
---|
1054 | clWhite )
|
---|
1055 | else
|
---|
1056 | Canvas.ShadowedBorder( Rect,
|
---|
1057 | clWhite,
|
---|
1058 | clDkGray );
|
---|
1059 | end;
|
---|
1060 | end;
|
---|
1061 |
|
---|
1062 | // draw minus
|
---|
1063 | Canvas.Line( Rect.Left + 2, CentreY,
|
---|
1064 | Rect.Right - 2, CentreY );
|
---|
1065 |
|
---|
1066 | if not Expanded then
|
---|
1067 | // draw vertical stroke of +
|
---|
1068 | Canvas.Line( CentreX, Rect.Top - 2,
|
---|
1069 | CentreX, Rect.Bottom + 2 );
|
---|
1070 | end;
|
---|
1071 |
|
---|
1072 | Function TOutline2.GetPlusMinusRect( Left, LineBottom: longint ): TRect;
|
---|
1073 | Var
|
---|
1074 | CentreY: longint;
|
---|
1075 | Begin
|
---|
1076 | CentreY:= LineBottom + _LineHeight div 2;
|
---|
1077 |
|
---|
1078 | Result.Left:= Left;
|
---|
1079 | Result.Right:= Left + _PlusMinusWidth - 1;
|
---|
1080 | Result.Bottom:= CentreY - _PlusMinusHeight div 2;
|
---|
1081 | Result.Top:= Result.Bottom + _PlusMinusHeight - 1;
|
---|
1082 | end;
|
---|
1083 |
|
---|
1084 | Function TOutline2.GetLineRect( LineBottom: longint ): TRect;
|
---|
1085 | begin
|
---|
1086 | Result:= GetTextRect;
|
---|
1087 |
|
---|
1088 | Result.Top:= LineBottom + _LineHeight - 1;
|
---|
1089 | Result.Bottom:= LineBottom;
|
---|
1090 | end;
|
---|
1091 |
|
---|
1092 | Procedure TOutline2.PaintNode( Node: TNode;
|
---|
1093 | X: longint;
|
---|
1094 | Var Y: longint );
|
---|
1095 | Var
|
---|
1096 | ChildIndex: longint;
|
---|
1097 | CentrePMX: longint;
|
---|
1098 | CentreY: longint;
|
---|
1099 | ChildCentreY: longint;
|
---|
1100 | TextW, TextH: longint;
|
---|
1101 | PlusMinusRect: TRect;
|
---|
1102 | TextX: longint;
|
---|
1103 | LineRect: TRect;
|
---|
1104 | SelectedRect: TRect;
|
---|
1105 | Begin
|
---|
1106 | dec( Y, _LineHeight );
|
---|
1107 |
|
---|
1108 | PlusMinusRect:= GetPlusMinusRect( X, Y );
|
---|
1109 |
|
---|
1110 | CentrePMX:= X + _PlusMinusWidth div 2;
|
---|
1111 | CentreY:= Y + _LineHeight div 2;
|
---|
1112 |
|
---|
1113 | if ( ( _DrawNode = AllNodes )
|
---|
1114 | or ( Node = _DrawNode ) )
|
---|
1115 | and ( Y + _LineHeight >= Canvas.ClipRect.Bottom ) // line top above bottom
|
---|
1116 | and ( Y <= Canvas.ClipRect.Top ) // line bottom below top
|
---|
1117 | then
|
---|
1118 | begin
|
---|
1119 | Canvas.GetTextExtent( Node.Text, TextW, TextH );
|
---|
1120 | TextX:= PlusMinusRect.Right + _StubWidth + _TextIndent;
|
---|
1121 |
|
---|
1122 | LineRect:= GetLineRect( Y );
|
---|
1123 |
|
---|
1124 | if Node = _SelectedNode then
|
---|
1125 | begin
|
---|
1126 | Canvas.Pen.Color:= clHighlightText;
|
---|
1127 | Canvas.Brush.Color:= clHighlight;
|
---|
1128 | if _SelectLine then
|
---|
1129 | SelectedRect:= LineRect
|
---|
1130 | else
|
---|
1131 | begin
|
---|
1132 | SelectedRect.Left:= TextX - _TextIndent div 2;
|
---|
1133 | SelectedRect.Top:= CentreY + TextH div 2 - 1;
|
---|
1134 | SelectedRect.Right:= TextX + TextW + _TextIndent div 2;
|
---|
1135 | SelectedRect.Bottom:= SelectedRect.Top - TextH + 1;
|
---|
1136 | // clear line
|
---|
1137 | Canvas.FillRect( LineRect, Color );
|
---|
1138 | end;
|
---|
1139 |
|
---|
1140 | // Draw selected background (either whole line, or just text background)
|
---|
1141 | Canvas.FillRect( SelectedRect, clHighLight );
|
---|
1142 |
|
---|
1143 | if HasFocus then
|
---|
1144 | Canvas.DrawFocusRect( SelectedRect );
|
---|
1145 | end
|
---|
1146 | else
|
---|
1147 | begin
|
---|
1148 | // Clear line
|
---|
1149 | Canvas.FillRect( LineRect, Color );
|
---|
1150 | Canvas.Pen.Color:= PenColor;
|
---|
1151 | Canvas.Brush.Color:= Color;
|
---|
1152 | end;
|
---|
1153 |
|
---|
1154 | // Draw text
|
---|
1155 | Canvas.Brush.Mode:= bmTransparent;
|
---|
1156 | Canvas.TextOut( TextX,
|
---|
1157 | CentreY - TextH div 2,
|
---|
1158 | Node.Text );
|
---|
1159 |
|
---|
1160 | if Node.ChildCount > 0 then
|
---|
1161 | begin
|
---|
1162 | // draw plus/minus
|
---|
1163 | DrawPlusMinus( PlusMinusRect,
|
---|
1164 | Node._Expanded,
|
---|
1165 | ( _MouseDownNode = Node )
|
---|
1166 | and ( _MouseDownPart = npPlusMinus )
|
---|
1167 | and ( _MouseDownFeedback ) );
|
---|
1168 | // Draw stub from plus/minus
|
---|
1169 | if _StubWidth > 0 then
|
---|
1170 | begin
|
---|
1171 | Canvas.Pen.Color:= _TreeLineColor;
|
---|
1172 | Canvas.Line( PlusMinusRect.Right + 1,
|
---|
1173 | CentreY,
|
---|
1174 | PlusMinusRect.Right + _StubWidth,
|
---|
1175 | CentreY );
|
---|
1176 | end;
|
---|
1177 |
|
---|
1178 | end
|
---|
1179 | else
|
---|
1180 | begin
|
---|
1181 | // no children
|
---|
1182 | if Node._Parent <> _Root then
|
---|
1183 | begin
|
---|
1184 | Canvas.Pen.Color:= _TreeLineColor;
|
---|
1185 | // draw stub, no Plus minus
|
---|
1186 | Canvas.Line( X,
|
---|
1187 | CentreY,
|
---|
1188 | PlusMinusRect.Right + _StubWidth,
|
---|
1189 | CentreY );
|
---|
1190 | end;
|
---|
1191 | end;
|
---|
1192 | end;
|
---|
1193 |
|
---|
1194 | if ( Node.ChildCount > 0 )
|
---|
1195 | and Node._Expanded then
|
---|
1196 | begin
|
---|
1197 | // draw children
|
---|
1198 | for ChildIndex:= 0 to Node.ChildCount-1 do
|
---|
1199 | begin
|
---|
1200 | // make sure truncation of the half pixel works same as for parent
|
---|
1201 | ChildCentreY:= Y - _LineHeight + _LineHeight div 2;
|
---|
1202 | if y < 0 then
|
---|
1203 | break;
|
---|
1204 | PaintNode( Node.Children[ ChildIndex ],
|
---|
1205 | X + Indent,
|
---|
1206 | Y );
|
---|
1207 | Canvas.Pen.Color:= _TreeLineColor;
|
---|
1208 | Canvas.Line( CentrePMX,
|
---|
1209 | ChildCentreY,
|
---|
1210 | X + _Indent,
|
---|
1211 | ChildCentreY );
|
---|
1212 | end;
|
---|
1213 |
|
---|
1214 | // draw vertical branch line
|
---|
1215 | Canvas.Pen.Color:= _TreeLineColor;
|
---|
1216 | Canvas.Line( CentrePMX,
|
---|
1217 | PlusMinusRect.Bottom - 1,
|
---|
1218 | CentrePMX,
|
---|
1219 | ChildCentreY );
|
---|
1220 | end;
|
---|
1221 |
|
---|
1222 | End;
|
---|
1223 |
|
---|
1224 | // Outline component implementation
|
---|
1225 | Procedure TOutline2.TestHit( Point: TPoint;
|
---|
1226 | Var Node: TNode;
|
---|
1227 | Var Part: TNodePart );
|
---|
1228 | Var
|
---|
1229 | ChildIndex: longint;
|
---|
1230 | Y: longint;
|
---|
1231 | DrawRect: TRect;
|
---|
1232 | Begin
|
---|
1233 | Node:= nil;
|
---|
1234 |
|
---|
1235 | DrawRect:= GetDrawRect;
|
---|
1236 | if ( Point.X < DrawRect.Left )
|
---|
1237 | or ( Point.X > DrawRect.Right )
|
---|
1238 | or ( Point.Y > DrawRect.Top )
|
---|
1239 | or ( Point.Y < DrawRect.Bottom ) then
|
---|
1240 | exit;
|
---|
1241 |
|
---|
1242 | Y:= DrawRect.Top + _VScrollBar.Position;
|
---|
1243 |
|
---|
1244 | // test children
|
---|
1245 | for ChildIndex:= 0 to _Root.ChildCount - 1 do
|
---|
1246 | begin
|
---|
1247 | TestNodeHit( _Root.Children[ ChildIndex ],
|
---|
1248 | Point,
|
---|
1249 | _LeftMargin - _HScrollBar.Position,
|
---|
1250 | Y,
|
---|
1251 | Node,
|
---|
1252 | Part );
|
---|
1253 | if Node <> nil then
|
---|
1254 | break;
|
---|
1255 | if Y < 0 then
|
---|
1256 | break;
|
---|
1257 | end;
|
---|
1258 |
|
---|
1259 | End;
|
---|
1260 |
|
---|
1261 | Procedure TOutline2.TestNodeHit( Node: TNode;
|
---|
1262 | Point: TPoint;
|
---|
1263 | X: longint;
|
---|
1264 | Var Y: longint;
|
---|
1265 | Var HitNode: TNode;
|
---|
1266 | Var Part: TNodePart );
|
---|
1267 | Var
|
---|
1268 | ChildIndex: longint;
|
---|
1269 | TextW, TextH: longint;
|
---|
1270 | TextX: longint;
|
---|
1271 | PlusMinusRect: TRect;
|
---|
1272 | CentreY: longint;
|
---|
1273 | TextRect: TRect;
|
---|
1274 | Begin
|
---|
1275 |
|
---|
1276 | dec( Y, _LineHeight );
|
---|
1277 |
|
---|
1278 | if ( Point.Y >= Y )
|
---|
1279 | and ( Point.Y < Y + _LineHeight ) then
|
---|
1280 | begin
|
---|
1281 | // this node. What part?
|
---|
1282 |
|
---|
1283 | HitNode:= Node;
|
---|
1284 |
|
---|
1285 | CentreY:= Y + _LineHeight div 2;
|
---|
1286 |
|
---|
1287 | PlusMinusRect:= GetPlusMinusRect( X, Y );
|
---|
1288 |
|
---|
1289 | if PointInRect( Point, PlusMinusRect ) then
|
---|
1290 | begin
|
---|
1291 | Part:= npPlusMinus;
|
---|
1292 | exit;
|
---|
1293 | end;
|
---|
1294 |
|
---|
1295 | Canvas.GetTextExtent( Node.Text, TextW, TextH );
|
---|
1296 | TextX:= X + _PlusMinusWidth + _StubWidth + _TextIndent;
|
---|
1297 | TextRect.Left:= TextX;
|
---|
1298 | TextRect.Right:= TextX + TextW;
|
---|
1299 | TextRect.Top:= CentreY + TextH div 2;
|
---|
1300 | TextRect.Bottom:= TextRect.Top + TextH;
|
---|
1301 |
|
---|
1302 | if PointInRect( Point, TextRect ) then
|
---|
1303 | begin
|
---|
1304 | Part:= npText;
|
---|
1305 | exit;
|
---|
1306 | end;
|
---|
1307 |
|
---|
1308 | // bitmap...
|
---|
1309 |
|
---|
1310 | Part:= npOther;
|
---|
1311 | exit;
|
---|
1312 | end;
|
---|
1313 |
|
---|
1314 | if Node.ChildCount > 0 then
|
---|
1315 | if Node._Expanded then
|
---|
1316 | // check children
|
---|
1317 | for ChildIndex:= 0 to Node.ChildCount-1 do
|
---|
1318 | begin
|
---|
1319 | TestNodeHit( Node.Children[ ChildIndex ],
|
---|
1320 | Point,
|
---|
1321 | X + Indent,
|
---|
1322 | Y,
|
---|
1323 | HitNode,
|
---|
1324 | Part );
|
---|
1325 | if HitNode <> nil then
|
---|
1326 | break;
|
---|
1327 | if y < 0 then
|
---|
1328 | break;
|
---|
1329 | end;
|
---|
1330 |
|
---|
1331 | End;
|
---|
1332 |
|
---|
1333 | // Finds the distance from the top of the given node.
|
---|
1334 | function TOutline2.GetNodePosition( const Node: TNode;
|
---|
1335 | Var NodeTop: longint ): boolean;
|
---|
1336 | Var
|
---|
1337 | ChildIndex: longint;
|
---|
1338 | DrawRect: TRect;
|
---|
1339 | Begin
|
---|
1340 | DrawRect:= GetDrawRect;
|
---|
1341 |
|
---|
1342 | NodeTop:= 0;
|
---|
1343 |
|
---|
1344 | // test children
|
---|
1345 | for ChildIndex:= 0 to _Root.ChildCount - 1 do
|
---|
1346 | begin
|
---|
1347 | if NodeGetNodePosition( Node,
|
---|
1348 | _Root.Children[ ChildIndex ],
|
---|
1349 | NodeTop ) then
|
---|
1350 | begin
|
---|
1351 | Result:= true;
|
---|
1352 | NodeTop:= - NodeTop;
|
---|
1353 | exit;
|
---|
1354 | end;
|
---|
1355 | end;
|
---|
1356 | Result:= false;
|
---|
1357 | End;
|
---|
1358 |
|
---|
1359 | function TOutline2.NodeGetNodePosition( const NodeToFind: TNode;
|
---|
1360 | const NodeToScan: TNode;
|
---|
1361 | Var NodeTop: longint ): boolean;
|
---|
1362 | Var
|
---|
1363 | ChildIndex: longint;
|
---|
1364 | Begin
|
---|
1365 | if NodeToFind = NodeToScan then
|
---|
1366 | begin
|
---|
1367 | Result:= true;
|
---|
1368 | exit;
|
---|
1369 | end;
|
---|
1370 |
|
---|
1371 | dec( NodeTop, _LineHeight );
|
---|
1372 |
|
---|
1373 | if NodeToScan.ChildCount > 0 then
|
---|
1374 | if NodeToScan._Expanded then
|
---|
1375 | // check children
|
---|
1376 | for ChildIndex:= 0 to NodeToScan.ChildCount-1 do
|
---|
1377 | begin
|
---|
1378 | if NodeGetNodePosition( NodeToFind,
|
---|
1379 | NodeToScan.Children[ ChildIndex ],
|
---|
1380 | NodeTop ) then
|
---|
1381 | begin
|
---|
1382 | Result:= true;
|
---|
1383 | exit;
|
---|
1384 | end;
|
---|
1385 | end;
|
---|
1386 | Result:= false;
|
---|
1387 | End;
|
---|
1388 |
|
---|
1389 | Procedure TOutline2.SetSelectedNode( Node: TNode );
|
---|
1390 | var
|
---|
1391 | OldSelectedNode: TNode;
|
---|
1392 | NodePosition: longint;
|
---|
1393 | DrawRect: TRect;
|
---|
1394 | DrawHeight: longint;
|
---|
1395 | OldScroll: longint;
|
---|
1396 | begin
|
---|
1397 | if _UpdateCount > 0 then
|
---|
1398 | begin
|
---|
1399 | _NewSelectedNode:= Node;
|
---|
1400 | exit;
|
---|
1401 | end;
|
---|
1402 |
|
---|
1403 | if _SelectedNode = Node then
|
---|
1404 | exit;
|
---|
1405 |
|
---|
1406 | OldSelectedNode:= _SelectedNode;
|
---|
1407 |
|
---|
1408 | _SelectedNode:= Node;
|
---|
1409 |
|
---|
1410 | if Node = nil then
|
---|
1411 | begin
|
---|
1412 | DrawNode( OldSelectedNode ); // clear old
|
---|
1413 | exit;
|
---|
1414 | end;
|
---|
1415 |
|
---|
1416 | if not Node.IsVisible then
|
---|
1417 | _SelectedNode.ExpandParents // this will refresh the whole thing...
|
---|
1418 | else
|
---|
1419 | DrawNode( OldSelectedNode ); // clear old
|
---|
1420 |
|
---|
1421 | DrawRect:= GetDrawRect;
|
---|
1422 | DrawHeight:= DrawRect.Top - DrawRect.Bottom;
|
---|
1423 |
|
---|
1424 | OldScroll:= _VScrollBar.Position;
|
---|
1425 | if GetNodePosition( Node, NodePosition ) then
|
---|
1426 | begin
|
---|
1427 | if NodePosition + _LineHeight > _VScrollBar.Position + DrawHeight then
|
---|
1428 | // Node is below bottom of control - scroll down
|
---|
1429 | _VScrollBar.Position:= NodePosition - DrawHeight + _LineHeight;
|
---|
1430 |
|
---|
1431 | if NodePosition < _VScrollBar.Position then
|
---|
1432 | // Node is aobve top of control - scroll up
|
---|
1433 | _VScrollBar.Position:= NodePosition;
|
---|
1434 | end;
|
---|
1435 |
|
---|
1436 |
|
---|
1437 | // draw new
|
---|
1438 | if OldScroll = _VScrollBar.Position then
|
---|
1439 | DrawNode( _SelectedNode )
|
---|
1440 | else
|
---|
1441 | Refresh;
|
---|
1442 |
|
---|
1443 | if _OnItemFocus <> nil then
|
---|
1444 | _OnItemFocus( Node );
|
---|
1445 |
|
---|
1446 | end;
|
---|
1447 |
|
---|
1448 | Procedure TOutline2.SetTopNode( Node: TNode );
|
---|
1449 | var
|
---|
1450 | NodePosition: longint;
|
---|
1451 | begin
|
---|
1452 | Node.ExpandParents;
|
---|
1453 |
|
---|
1454 | if GetNodePosition( Node, NodePosition ) then
|
---|
1455 | begin
|
---|
1456 | _VScrollBar.Position:= NodePosition;
|
---|
1457 | end;
|
---|
1458 | end;
|
---|
1459 |
|
---|
1460 | Procedure TOutline2.SetAutoLineHeight( Value: boolean );
|
---|
1461 | begin
|
---|
1462 | _AutoLineHeight := Value;
|
---|
1463 | if Value then
|
---|
1464 | FontChange;
|
---|
1465 | end;
|
---|
1466 |
|
---|
1467 | Procedure TOutline2.SetLineHeight( LineHeight: longint );
|
---|
1468 | begin
|
---|
1469 | if LineHeight < _PlusMinusHeight + 1 then
|
---|
1470 | LineHeight := _PlusMinusHeight + 1;
|
---|
1471 | if _LineHeight = LineHeight then
|
---|
1472 | exit;
|
---|
1473 | _LineHeight:= LineHeight;
|
---|
1474 | ScanExtents;
|
---|
1475 | Refresh;
|
---|
1476 | end;
|
---|
1477 |
|
---|
1478 | Procedure TOutline2.SetIndent( Indent: longint );
|
---|
1479 | begin
|
---|
1480 | if _Indent = Indent then
|
---|
1481 | exit;
|
---|
1482 |
|
---|
1483 | _Indent:= Indent;
|
---|
1484 | ScanExtents;
|
---|
1485 | Refresh;
|
---|
1486 | end;
|
---|
1487 |
|
---|
1488 | Procedure TOutline2.SetBorderStyle( BorderStyle: TBorderStyle );
|
---|
1489 | begin
|
---|
1490 | if _BorderStyle = BorderStyle then
|
---|
1491 | exit;
|
---|
1492 | _BorderStyle:= BorderStyle;
|
---|
1493 | ScanExtents;
|
---|
1494 | Refresh;
|
---|
1495 | end;
|
---|
1496 |
|
---|
1497 | Procedure TOutline2.SetScrollbarWidth( ScrollbarWidth: longint );
|
---|
1498 | begin
|
---|
1499 | _ScrollBarWidth:= ScrollBarWidth;
|
---|
1500 | ScanExtents;
|
---|
1501 | Refresh;
|
---|
1502 | end;
|
---|
1503 |
|
---|
1504 | Procedure TOutline2.SetLeftMargin( LeftMargin: longint );
|
---|
1505 | begin
|
---|
1506 | if _LeftMargin = LeftMargin then
|
---|
1507 | exit;
|
---|
1508 | _LeftMargin:= LeftMargin;
|
---|
1509 | ScanExtents;
|
---|
1510 | Refresh;
|
---|
1511 | end;
|
---|
1512 |
|
---|
1513 | Procedure TOutline2.SetTextIndent( TextIndent: longint );
|
---|
1514 | begin
|
---|
1515 | if _TextIndent = TextIndent then
|
---|
1516 | exit;
|
---|
1517 | _TextIndent:= TextIndent;
|
---|
1518 | ScanExtents;
|
---|
1519 | Refresh;
|
---|
1520 | end;
|
---|
1521 |
|
---|
1522 | Procedure TOutline2.SetPlusMinusWidth( PlusMinusWidth: longint );
|
---|
1523 | begin
|
---|
1524 | if _PlusMinusWidth = PlusMinusWidth then
|
---|
1525 | exit;
|
---|
1526 |
|
---|
1527 | if PlusMinusWidth < 7 then
|
---|
1528 | PlusMinusWidth:= 7;
|
---|
1529 |
|
---|
1530 | _PlusMinusWidth:= PlusMinusWidth;
|
---|
1531 | ScanExtents;
|
---|
1532 | Refresh;
|
---|
1533 | end;
|
---|
1534 |
|
---|
1535 | Procedure TOutline2.SetPlusMinusHeight( PlusMinusHeight: longint );
|
---|
1536 | begin
|
---|
1537 | if _PlusMinusHeight = PlusMinusHeight then
|
---|
1538 | exit;
|
---|
1539 | if PlusMinusHeight < 7 then
|
---|
1540 | PlusMinusHeight:= 7;
|
---|
1541 |
|
---|
1542 | _PlusMinusHeight:= PlusMinusHeight;
|
---|
1543 | ScanExtents;
|
---|
1544 | Refresh;
|
---|
1545 | end;
|
---|
1546 |
|
---|
1547 | Procedure TOutline2.SetStubWidth( StubWidth: longint );
|
---|
1548 | begin
|
---|
1549 | if _StubWidth = StubWidth then
|
---|
1550 | exit;
|
---|
1551 | _StubWidth:= StubWidth;
|
---|
1552 | ScanExtents;
|
---|
1553 | Refresh;
|
---|
1554 | end;
|
---|
1555 |
|
---|
1556 | Procedure TOutline2.SetPlusMinusStyle( NewValue: TPlusMinusStyle );
|
---|
1557 | begin
|
---|
1558 | if _PlusMinusStyle = NewValue then
|
---|
1559 | exit;
|
---|
1560 |
|
---|
1561 | _PlusMinusStyle:= NewValue;
|
---|
1562 | Refresh;
|
---|
1563 | end;
|
---|
1564 |
|
---|
1565 | Procedure TOutline2.SetSelectLine( NewValue: boolean );
|
---|
1566 | begin
|
---|
1567 | if _SelectLine = NewValue then
|
---|
1568 | exit;
|
---|
1569 | _SelectLine:= NewValue;
|
---|
1570 | DrawNode( _SelectedNode );
|
---|
1571 | end;
|
---|
1572 |
|
---|
1573 | Procedure TOutline2.SetTreeLineColor( NewValue: TColor );
|
---|
1574 | begin
|
---|
1575 | if _TreeLineColor = NewValue then
|
---|
1576 | exit;
|
---|
1577 | _TreeLineColor:= NewValue;
|
---|
1578 | Refresh;
|
---|
1579 | end;
|
---|
1580 |
|
---|
1581 | procedure TNode.ExpandParents;
|
---|
1582 | var
|
---|
1583 | AParent: TNode;
|
---|
1584 | begin
|
---|
1585 | AParent:= self._Parent;
|
---|
1586 | while AParent._Parent <> nil do
|
---|
1587 | begin
|
---|
1588 | AParent.Expand;
|
---|
1589 | AParent:= AParent._Parent;
|
---|
1590 | end;
|
---|
1591 | end;
|
---|
1592 |
|
---|
1593 | procedure TOutline2.Clear;
|
---|
1594 | begin
|
---|
1595 | BeginUpdate;
|
---|
1596 | _Root.Clear;
|
---|
1597 | EndUpdate;
|
---|
1598 | end;
|
---|
1599 |
|
---|
1600 | Function TOutline2.AddChild( const TheText: string;
|
---|
1601 | const TheObject: TObject ): TNode;
|
---|
1602 | Begin
|
---|
1603 | Result := _Root.AddChild( TheText, TheObject );
|
---|
1604 | End;
|
---|
1605 |
|
---|
1606 | Function TOutline2.GetChild( index: longint ): TNode;
|
---|
1607 | Begin
|
---|
1608 | Result:= _Root.Children[ index ];
|
---|
1609 | End;
|
---|
1610 |
|
---|
1611 | Function TOutline2.GetChildCount: longint;
|
---|
1612 | begin
|
---|
1613 | Result:= _Root.ChildCount;
|
---|
1614 | end;
|
---|
1615 |
|
---|
1616 | Procedure TOutline2.SetupScrollbars;
|
---|
1617 | Begin
|
---|
1618 | _VScrollbar.Visible:= _NeedVScroll;
|
---|
1619 | if _NeedVScroll then
|
---|
1620 | begin
|
---|
1621 | _VScrollbar.Left:= Width - _ScrollbarWidth;
|
---|
1622 | _VScrollbar.Width:= _ScrollbarWidth;
|
---|
1623 |
|
---|
1624 | if _NeedHScroll then
|
---|
1625 | begin
|
---|
1626 | _VScrollbar.Bottom:= _ScrollbarWidth;
|
---|
1627 | _VScrollbar.Height:= Height - _ScrollbarWidth
|
---|
1628 | end
|
---|
1629 | else
|
---|
1630 | begin
|
---|
1631 | _VScrollbar.Bottom:= 0;
|
---|
1632 | _VScrollbar.Height:= Height;
|
---|
1633 | end;
|
---|
1634 | end;
|
---|
1635 |
|
---|
1636 | _HScrollbar.Visible:= _NeedHScroll;
|
---|
1637 | if _NeedHScroll then
|
---|
1638 | begin
|
---|
1639 | _HScrollbar.Left:= 0;
|
---|
1640 | _HScrollbar.Bottom:= 0;
|
---|
1641 | _HScrollbar.Height:= _ScrollbarWidth;
|
---|
1642 |
|
---|
1643 | if _NeedVScroll then
|
---|
1644 | _HScrollbar.Width:= Width - _ScrollBarWidth
|
---|
1645 | else
|
---|
1646 | _HScrollbar.Width:= Width;
|
---|
1647 | end;
|
---|
1648 |
|
---|
1649 | End;
|
---|
1650 |
|
---|
1651 | Procedure TOutline2.Resize;
|
---|
1652 | begin
|
---|
1653 | ScanExtents;
|
---|
1654 | end;
|
---|
1655 |
|
---|
1656 | Procedure TOutline2.SetupComponent;
|
---|
1657 | Begin
|
---|
1658 | Inherited SetupComponent;
|
---|
1659 | Name:= 'Outline2';
|
---|
1660 |
|
---|
1661 | Width:= 100;
|
---|
1662 | Height:= 100;
|
---|
1663 |
|
---|
1664 | _BorderStyle:= bsSingle;
|
---|
1665 | FSmoothScroll := true;
|
---|
1666 |
|
---|
1667 | _StubWidth:= 0;
|
---|
1668 | _Indent:= 11;
|
---|
1669 | _PlusMinusWidth:= 11;
|
---|
1670 | _PlusMinusHeight:= 11;
|
---|
1671 | _AutoLineHeight := true;
|
---|
1672 | _LeftMargin:= 5;
|
---|
1673 | _TextIndent:= 5;
|
---|
1674 | _ScrollbarWidth:= 15;
|
---|
1675 | _PlusMinusStyle:= pm3d;
|
---|
1676 | _SelectLine:= false;
|
---|
1677 | _TreeLineColor:= clGray;
|
---|
1678 |
|
---|
1679 | Color:= clEntryField;
|
---|
1680 | ParentPenColor:= true;
|
---|
1681 | Exclude( ComponentState, csAcceptsControls );
|
---|
1682 |
|
---|
1683 | if not InDesigner then
|
---|
1684 | begin
|
---|
1685 | _Root:= TNode.Create( nil );
|
---|
1686 | _Root.Text:= 'Root';
|
---|
1687 | _Root._Outline:= self;
|
---|
1688 | _Root._Expanded:= true; // by definition
|
---|
1689 | _SelectedNode:= nil;
|
---|
1690 |
|
---|
1691 | _MouseDownNode:= nil;
|
---|
1692 | _MouseDownPart:= npNothing;
|
---|
1693 |
|
---|
1694 | _HScrollbar.Create( self );
|
---|
1695 | _HScrollbar.Kind:= sbHorizontal;
|
---|
1696 | Include( _HScrollbar.ComponentState, csDetail );
|
---|
1697 | _HScrollbar.Parent:= self;
|
---|
1698 |
|
---|
1699 | _VScrollbar.Create( self );
|
---|
1700 | _VScrollbar.Kind:= sbVertical;
|
---|
1701 | Include( _VScrollbar.ComponentState, csDetail );
|
---|
1702 | _VScrollbar.Parent:= self;
|
---|
1703 |
|
---|
1704 | _UpdateCount:= 0;
|
---|
1705 |
|
---|
1706 | _HoverTimer := TTimer.Create( self );
|
---|
1707 | _HoverTimer.Interval := 500;
|
---|
1708 | _HoverTimer.OnTImer := OnHoverTimeout;
|
---|
1709 | _HintWindow:= THintWindow.Create( self );
|
---|
1710 | _HintWindow.CreateWnd;
|
---|
1711 | end;
|
---|
1712 |
|
---|
1713 | End;
|
---|
1714 |
|
---|
1715 | Destructor TOutline2.Destroy;
|
---|
1716 | Begin
|
---|
1717 | if not InDesigner then
|
---|
1718 | begin
|
---|
1719 | _Root.Destroy;
|
---|
1720 | end;
|
---|
1721 | Inherited Destroy;
|
---|
1722 | End;
|
---|
1723 |
|
---|
1724 | Procedure TOutline2.SetupShow;
|
---|
1725 | begin
|
---|
1726 | Inherited SetupShow;
|
---|
1727 | _UpdateCount:= 0;
|
---|
1728 |
|
---|
1729 | if not InDesigner then
|
---|
1730 | ScanExtents;
|
---|
1731 | end;
|
---|
1732 |
|
---|
1733 | Procedure TOutline2.MouseDown( Button: TMouseButton;
|
---|
1734 | ShiftState: TShiftState;
|
---|
1735 | X, Y: Longint );
|
---|
1736 | var
|
---|
1737 | Node: TNode;
|
---|
1738 | Part: TNodePart;
|
---|
1739 | Point: TPoint;
|
---|
1740 | begin
|
---|
1741 | inherited MouseDown( Button, ShiftState, X, Y );
|
---|
1742 |
|
---|
1743 | if InDesigner then
|
---|
1744 | exit;
|
---|
1745 |
|
---|
1746 | Focus;
|
---|
1747 |
|
---|
1748 | MouseCapture:= true;
|
---|
1749 | Point.X:= X;
|
---|
1750 | Point.Y:= Y;
|
---|
1751 | TestHit( Point,
|
---|
1752 | Node,
|
---|
1753 | Part );
|
---|
1754 | if Node <> nil then
|
---|
1755 | begin
|
---|
1756 | _MouseDownNode:= Node;
|
---|
1757 | _MouseDownPart:= Part;
|
---|
1758 |
|
---|
1759 | _MouseDownFeedback:= true;
|
---|
1760 | _LastMouseMoveFeedback:= true;
|
---|
1761 |
|
---|
1762 | DrawNode( _MouseDownNode );
|
---|
1763 | end;
|
---|
1764 | end;
|
---|
1765 |
|
---|
1766 | Procedure TOutline2.MouseMove( ShiftState: TShiftState;
|
---|
1767 | X, Y: Longint );
|
---|
1768 | var
|
---|
1769 | Node: TNode;
|
---|
1770 | Part: TNodePart;
|
---|
1771 | Point: TPoint;
|
---|
1772 | begin
|
---|
1773 | if InDesigner then
|
---|
1774 | exit;
|
---|
1775 |
|
---|
1776 | if not MouseCapture then
|
---|
1777 | begin
|
---|
1778 | _HoverTimer.Stop;
|
---|
1779 | // _HoverTimer.Start;
|
---|
1780 | _LastMouseX := X;
|
---|
1781 | _LastMouseY := Y;
|
---|
1782 | exit;
|
---|
1783 | end;
|
---|
1784 |
|
---|
1785 | Point.X:= X;
|
---|
1786 | Point.Y:= Y;
|
---|
1787 | TestHit( Point,
|
---|
1788 | Node,
|
---|
1789 | Part );
|
---|
1790 |
|
---|
1791 | _MouseDownFeedback:=
|
---|
1792 | ( Node = _MouseDownNode )
|
---|
1793 | and ( Part = _MouseDownPart );
|
---|
1794 |
|
---|
1795 | if _LastMouseMoveFeedback <> _MouseDownFeedback then
|
---|
1796 | DrawNode( _MouseDownNode );
|
---|
1797 |
|
---|
1798 | _LastMouseMoveFeedback:= _MouseDownFeedback;
|
---|
1799 | end;
|
---|
1800 |
|
---|
1801 | Procedure TOutline2.MouseUp( Button: TMouseButton;
|
---|
1802 | ShiftState: TShiftState;
|
---|
1803 | X, Y: Longint );
|
---|
1804 | var
|
---|
1805 | Node: TNode;
|
---|
1806 | Part: TNodePart;
|
---|
1807 | Point: TPoint;
|
---|
1808 | MouseDownNode: TNode;
|
---|
1809 | begin
|
---|
1810 | if InDesigner then
|
---|
1811 | exit;
|
---|
1812 |
|
---|
1813 | if not MouseCapture then
|
---|
1814 | exit;
|
---|
1815 |
|
---|
1816 | MouseDownNode:= _MouseDownNode;
|
---|
1817 | _MouseDownNode:= nil;
|
---|
1818 | MouseCapture:= false;
|
---|
1819 |
|
---|
1820 | Point.X:= X;
|
---|
1821 | Point.Y:= Y;
|
---|
1822 | TestHit( Point,
|
---|
1823 | Node,
|
---|
1824 | Part );
|
---|
1825 |
|
---|
1826 | if ( Node <> nil )
|
---|
1827 | and ( Node = MouseDownNode )
|
---|
1828 | and ( Part = _MouseDownPart )
|
---|
1829 | then
|
---|
1830 | begin
|
---|
1831 | if Part = npPlusMinus then
|
---|
1832 | begin
|
---|
1833 | if Node.Expanded then
|
---|
1834 | Node.Collapse
|
---|
1835 | else
|
---|
1836 | Node.Expand;
|
---|
1837 | end
|
---|
1838 | else
|
---|
1839 | begin
|
---|
1840 | SelectedNode:= Node;
|
---|
1841 |
|
---|
1842 | if Assigned( _OnItemClick ) then
|
---|
1843 | _OnItemClick( Node );
|
---|
1844 | end;
|
---|
1845 |
|
---|
1846 | end
|
---|
1847 | else
|
---|
1848 | begin
|
---|
1849 | DrawNode( MouseDownNode );
|
---|
1850 | end;
|
---|
1851 |
|
---|
1852 | end;
|
---|
1853 |
|
---|
1854 | Procedure TOutline2.MouseDblClick( Button: TMouseButton;
|
---|
1855 | ShiftState: TShiftState;
|
---|
1856 | X, Y: Longint );
|
---|
1857 | var
|
---|
1858 | Node: TNode;
|
---|
1859 | Part: TNodePart;
|
---|
1860 | Point: TPoint;
|
---|
1861 | begin
|
---|
1862 | if InDesigner then
|
---|
1863 | exit;
|
---|
1864 |
|
---|
1865 | Point.X:= X;
|
---|
1866 | Point.Y:= Y;
|
---|
1867 | TestHit( Point,
|
---|
1868 | Node,
|
---|
1869 | Part );
|
---|
1870 | if Node <> nil then
|
---|
1871 | begin
|
---|
1872 | if Part = npPlusMinus then
|
---|
1873 | if Node.Expanded then
|
---|
1874 | Node.Collapse
|
---|
1875 | else
|
---|
1876 | Node.Expand
|
---|
1877 | else
|
---|
1878 | begin
|
---|
1879 | SelectedNode:= Node;
|
---|
1880 | if Assigned( _OnItemDblClick ) then
|
---|
1881 | _OnItemDblClick( Node );
|
---|
1882 | end;
|
---|
1883 |
|
---|
1884 | end;
|
---|
1885 | end;
|
---|
1886 |
|
---|
1887 | procedure TOutline2.BeginUpdate;
|
---|
1888 | begin
|
---|
1889 | if _UpdateCount = 0 then
|
---|
1890 | _NewSelectedNode:= _SelectedNode;
|
---|
1891 |
|
---|
1892 | inc( _UpdateCount );
|
---|
1893 | end;
|
---|
1894 |
|
---|
1895 | procedure TOutline2.EndUpdate;
|
---|
1896 | begin
|
---|
1897 | dec( _UpdateCount );
|
---|
1898 | if _UpdateCount = 0 then
|
---|
1899 | begin
|
---|
1900 | ScanExtents;
|
---|
1901 | Refresh;
|
---|
1902 | SetSelectedNode( _NewSelectedNode );
|
---|
1903 | end
|
---|
1904 | else if _UpdateCount < 0 then
|
---|
1905 | raise Exception.Create( 'Too many EndUpdates in TOutline2!' );
|
---|
1906 | end;
|
---|
1907 |
|
---|
1908 | procedure TOutline2.SetSelectedObject( Data: TObject );
|
---|
1909 | var
|
---|
1910 | Node: TNode;
|
---|
1911 | begin
|
---|
1912 | Node:= _Root.FindData( Data );
|
---|
1913 | SelectedNode:= Node;
|
---|
1914 | end;
|
---|
1915 |
|
---|
1916 | function TOutline2.NodeFromObject( Data: TObject ): TNode;
|
---|
1917 | begin
|
---|
1918 | Result:= _Root.FindData( Data );
|
---|
1919 | end;
|
---|
1920 |
|
---|
1921 | function TOutline2.FindByFunction( FindFunction: TNodeFindFunction ): TNode;
|
---|
1922 | begin
|
---|
1923 | Result:= _Root.FindByFunction( FindFunction );
|
---|
1924 | end;
|
---|
1925 |
|
---|
1926 | Procedure TOutline2.GotoFirstNode;
|
---|
1927 | begin
|
---|
1928 | if ChildCount > 0 then
|
---|
1929 | SelectedNode:= Children[ 0 ];
|
---|
1930 | end;
|
---|
1931 |
|
---|
1932 | Procedure TOutline2.GotoLastVisibleNode;
|
---|
1933 | var
|
---|
1934 | Node: TNode;
|
---|
1935 | begin
|
---|
1936 | Node:= LastVisibleNode;
|
---|
1937 | if Node <> nil then
|
---|
1938 | SelectedNode:= Node;
|
---|
1939 | end;
|
---|
1940 |
|
---|
1941 | function TOutline2.LastVisibleNode: TNode;
|
---|
1942 | begin
|
---|
1943 | Result:= nil;
|
---|
1944 | if ChildCount > 0 then
|
---|
1945 | begin
|
---|
1946 | Result:= _Root;
|
---|
1947 | while Result.HasChildren do
|
---|
1948 | begin
|
---|
1949 | if Result.Expanded then
|
---|
1950 | Result:= Result.Children[ Result.ChildCount - 1 ]
|
---|
1951 | else
|
---|
1952 | break;
|
---|
1953 | end;
|
---|
1954 | end;
|
---|
1955 | end;
|
---|
1956 |
|
---|
1957 | function TOutline2.NextNodeUp( Node: TNode;
|
---|
1958 | VisibleOnly: boolean ): TNode;
|
---|
1959 | var
|
---|
1960 | NodeIndexInParent: longint;
|
---|
1961 | begin
|
---|
1962 | NodeIndexInParent:= Node.IndexInParent;
|
---|
1963 | if NodeIndexInParent = 0 then
|
---|
1964 | begin
|
---|
1965 | if Node._Parent = _Root then
|
---|
1966 | Result:= nil // nothing above this one
|
---|
1967 | else
|
---|
1968 | Result:= Node._Parent
|
---|
1969 | end
|
---|
1970 | else
|
---|
1971 | begin
|
---|
1972 | Result:= Node._Parent.Children[ NodeIndexInParent - 1 ];
|
---|
1973 | while Result.HasChildren
|
---|
1974 | and ( Result.Expanded or ( not VisibleOnly ) ) do
|
---|
1975 | begin
|
---|
1976 | Result:= Result.Children[ Result.ChildCount - 1 ];
|
---|
1977 | end;
|
---|
1978 | end;
|
---|
1979 |
|
---|
1980 | end;
|
---|
1981 |
|
---|
1982 | function TOutline2.NextNodeDown( Node: TNode;
|
---|
1983 | VisibleOnly: boolean ): TNode;
|
---|
1984 | var
|
---|
1985 | NodeIndexInParent: longint;
|
---|
1986 | begin
|
---|
1987 | if Node.HasChildren
|
---|
1988 | and ( Node.Expanded or ( not VisibleOnly ) ) then
|
---|
1989 | Result:= Node.Children[ 0 ]
|
---|
1990 | else
|
---|
1991 | begin
|
---|
1992 | Result:= node;
|
---|
1993 | while Result <> _Root do
|
---|
1994 | begin
|
---|
1995 | NodeIndexInParent:= Result.IndexInParent;
|
---|
1996 | if NodeIndexInParent < Result._Parent.ChildCount - 1 then
|
---|
1997 | begin
|
---|
1998 | Result:= Result._Parent.Children[ NodeIndexInParent + 1 ];
|
---|
1999 | break;
|
---|
2000 | end;
|
---|
2001 | Result:= Result._Parent;
|
---|
2002 | end;
|
---|
2003 | if Result = _Root then
|
---|
2004 | begin
|
---|
2005 | Result:= nil;
|
---|
2006 | // already at bottom
|
---|
2007 | exit;
|
---|
2008 | end;
|
---|
2009 | end;
|
---|
2010 | end;
|
---|
2011 |
|
---|
2012 | function TOutline2.GotoNextVisibleNodeUp: boolean;
|
---|
2013 | var
|
---|
2014 | NextNode: TNode;
|
---|
2015 | begin
|
---|
2016 | Result := true;
|
---|
2017 | if SelectedNode <> nil then
|
---|
2018 | begin
|
---|
2019 | NextNode:= NextNodeUp( SelectedNode, true );
|
---|
2020 | if NextNode <> nil then
|
---|
2021 | SelectedNode:= NextNode
|
---|
2022 | else
|
---|
2023 | Result := false;
|
---|
2024 | end
|
---|
2025 | else
|
---|
2026 | GotoFirstNode;
|
---|
2027 | end;
|
---|
2028 |
|
---|
2029 | function TOutline2.GotoNextVisibleNodeDown: boolean;
|
---|
2030 | var
|
---|
2031 | NextNode: TNode;
|
---|
2032 | begin
|
---|
2033 | Result := true;
|
---|
2034 | if SelectedNode <> nil then
|
---|
2035 | begin
|
---|
2036 | NextNode:= NextNodeDown( SelectedNode, true );
|
---|
2037 | if NextNode <> nil then
|
---|
2038 | SelectedNode:= NextNode
|
---|
2039 | else
|
---|
2040 | Result := false;
|
---|
2041 | end
|
---|
2042 | else
|
---|
2043 | GotoFirstNode;
|
---|
2044 | end;
|
---|
2045 |
|
---|
2046 | function TOutline2.GotoNextNodeUp: boolean;
|
---|
2047 | var
|
---|
2048 | NextNode: TNode;
|
---|
2049 | begin
|
---|
2050 | Result := true;
|
---|
2051 | if SelectedNode <> nil then
|
---|
2052 | begin
|
---|
2053 | NextNode:= NextNodeUp( SelectedNode, false );
|
---|
2054 | if NextNode <> nil then
|
---|
2055 | SelectedNode:= NextNode
|
---|
2056 | else
|
---|
2057 | Result := false;
|
---|
2058 | end
|
---|
2059 | else
|
---|
2060 | GotoFirstNode;
|
---|
2061 | end;
|
---|
2062 |
|
---|
2063 | function TOutline2.GotoNextNodeDown: boolean;
|
---|
2064 | var
|
---|
2065 | NextNode: TNode;
|
---|
2066 | begin
|
---|
2067 | Result := true;
|
---|
2068 | if SelectedNode <> nil then
|
---|
2069 | begin
|
---|
2070 | NextNode:= NextNodeDown( SelectedNode, false );
|
---|
2071 | if NextNode <> nil then
|
---|
2072 | SelectedNode:= NextNode
|
---|
2073 | else
|
---|
2074 | Result := false;
|
---|
2075 | end
|
---|
2076 | else
|
---|
2077 | GotoFirstNode;
|
---|
2078 | end;
|
---|
2079 |
|
---|
2080 | Procedure TOutline2.PageUp;
|
---|
2081 | var
|
---|
2082 | NextNode: TNode;
|
---|
2083 | Y: longint;
|
---|
2084 | begin
|
---|
2085 | if SelectedNode <> nil then
|
---|
2086 | begin
|
---|
2087 | NextNode:= NextNodeUp( SelectedNode, true );
|
---|
2088 | Y:= _LineHeight;
|
---|
2089 | while ( NextNode <> nil )
|
---|
2090 | and ( Y < DrawHeight ) do
|
---|
2091 | begin
|
---|
2092 | inc( Y, _LineHeight );
|
---|
2093 | NextNode:= NextNodeUp( NextNode, true );
|
---|
2094 | end;
|
---|
2095 | if NextNode = nil then
|
---|
2096 | GotoFirstNode
|
---|
2097 | else
|
---|
2098 | SelectedNode:= NextNode;
|
---|
2099 |
|
---|
2100 | end
|
---|
2101 | else
|
---|
2102 | GotoFirstNode;
|
---|
2103 | end;
|
---|
2104 |
|
---|
2105 | Procedure TOutline2.PageDown;
|
---|
2106 | var
|
---|
2107 | NextNode: TNode;
|
---|
2108 | Y: longint;
|
---|
2109 | begin
|
---|
2110 | if SelectedNode <> nil then
|
---|
2111 | begin
|
---|
2112 | NextNode:= NextNodeDown( SelectedNode, true );
|
---|
2113 | Y:= _LineHeight;
|
---|
2114 | while ( NextNode <> nil )
|
---|
2115 | and ( Y < DrawHeight ) do
|
---|
2116 | begin
|
---|
2117 | inc( Y, _LineHeight );
|
---|
2118 | NextNode:= NextNodeDown( NextNode, true );
|
---|
2119 | end;
|
---|
2120 | if NextNode = nil then
|
---|
2121 | GotoLastVisibleNode
|
---|
2122 | else
|
---|
2123 | SelectedNode:= NextNode;
|
---|
2124 |
|
---|
2125 | end
|
---|
2126 | else
|
---|
2127 | GotoFirstNode;
|
---|
2128 | end;
|
---|
2129 |
|
---|
2130 | Procedure TOutline2.CollapseAll;
|
---|
2131 | begin
|
---|
2132 | _Root.CollapseChildren( true );
|
---|
2133 | end;
|
---|
2134 |
|
---|
2135 | Procedure TOutline2.ExpandAll;
|
---|
2136 | begin
|
---|
2137 | _Root.ExpandChildren( true );
|
---|
2138 | end;
|
---|
2139 |
|
---|
2140 | Procedure TOutline2.SetFocus;
|
---|
2141 | begin
|
---|
2142 | inherited SetFocus;
|
---|
2143 | if _SelectedNode <> nil then
|
---|
2144 | DrawNode( _SelectedNode );
|
---|
2145 | end;
|
---|
2146 |
|
---|
2147 | Procedure TOutline2.KillFocus;
|
---|
2148 | begin
|
---|
2149 | inherited KillFocus;
|
---|
2150 | if _SelectedNode <> nil then
|
---|
2151 | DrawNode( _SelectedNode );
|
---|
2152 | end;
|
---|
2153 |
|
---|
2154 | Procedure TOutline2.ScanEvent( Var KeyCode: TKeyCode;
|
---|
2155 | RepeatCount: Byte );
|
---|
2156 | Begin
|
---|
2157 | if InDesigner then
|
---|
2158 | begin
|
---|
2159 | inherited ScanEvent( KeyCode, RepeatCount );
|
---|
2160 | exit;
|
---|
2161 | end;
|
---|
2162 |
|
---|
2163 | Case KeyCode Of
|
---|
2164 | kbHome, kbCtrlHome, kbCtrlPageUp:
|
---|
2165 | GotoFirstNode;
|
---|
2166 |
|
---|
2167 | kbEnd, kbCtrlEnd, kbCtrlPageDown:
|
---|
2168 | GotoLastVisibleNode;
|
---|
2169 |
|
---|
2170 | kbCUp:
|
---|
2171 | begin
|
---|
2172 | GotoNextVisibleNodeUp;
|
---|
2173 | KeyCode := kbNull; // prevent sibyl changing focus
|
---|
2174 | end;
|
---|
2175 |
|
---|
2176 | kbCDown:
|
---|
2177 | begin
|
---|
2178 | GotoNextVisibleNodeDown;
|
---|
2179 | KeyCode := kbNull; // prevent sibyl changing focus
|
---|
2180 | end;
|
---|
2181 |
|
---|
2182 | kbPageUp:
|
---|
2183 | PageUp;
|
---|
2184 |
|
---|
2185 | kbPageDown:
|
---|
2186 | PageDown;
|
---|
2187 |
|
---|
2188 | End;
|
---|
2189 |
|
---|
2190 | inherited ScanEvent( KeyCode, RepeatCount );
|
---|
2191 |
|
---|
2192 | End;
|
---|
2193 |
|
---|
2194 | Function TOutline2.FindNextNodeByText( StartNode: TNode;
|
---|
2195 | const S: string;
|
---|
2196 | VisibleOnly: boolean ): TNode;
|
---|
2197 |
|
---|
2198 | var
|
---|
2199 | Node: TNode;
|
---|
2200 | begin
|
---|
2201 | Result := nil;
|
---|
2202 |
|
---|
2203 | if StartNode = nil then
|
---|
2204 | exit;
|
---|
2205 |
|
---|
2206 | Node := StartNode;
|
---|
2207 |
|
---|
2208 | while true do
|
---|
2209 | begin
|
---|
2210 | Node := NextNodeDown( Node, VisibleOnly );
|
---|
2211 | if Node = nil then
|
---|
2212 | // reached bottom, start from top again.
|
---|
2213 | Node := Children[ 0 ];
|
---|
2214 |
|
---|
2215 | if Node = StartNode then
|
---|
2216 | // searched all nodes, done.
|
---|
2217 | exit;
|
---|
2218 |
|
---|
2219 | if StrStartsWithIgnoringCase(Node.Text, S) then
|
---|
2220 | begin
|
---|
2221 | // found
|
---|
2222 | Result := Node;
|
---|
2223 | exit;
|
---|
2224 | end;
|
---|
2225 | end;
|
---|
2226 | end;
|
---|
2227 |
|
---|
2228 | Procedure TOutline2.CharEvent( Var Key: Char;
|
---|
2229 | RepeatCount: Byte );
|
---|
2230 | var
|
---|
2231 | Node: TNode;
|
---|
2232 | NextNode: TNode;
|
---|
2233 | begin
|
---|
2234 | if InDesigner then
|
---|
2235 | begin
|
---|
2236 | inherited CharEvent( Key, RepeatCount );
|
---|
2237 | exit;
|
---|
2238 | end;
|
---|
2239 |
|
---|
2240 | if SelectedNode <> nil then
|
---|
2241 | begin
|
---|
2242 | case Key of
|
---|
2243 | '+', '=': // = to catch non-shifted + on most keyboards
|
---|
2244 | SelectedNode.Expand;
|
---|
2245 |
|
---|
2246 | '-':
|
---|
2247 | SelectedNode.Collapse;
|
---|
2248 |
|
---|
2249 | ' ': // space toggles expanded/collapsed
|
---|
2250 | if SelectedNode.Expanded then
|
---|
2251 | SelectedNode.Collapse
|
---|
2252 | else
|
---|
2253 | SelectedNode.Expand;
|
---|
2254 |
|
---|
2255 | '*': // Alberto thinks this would be nice to expand the tree...
|
---|
2256 | begin
|
---|
2257 | SelectedNode.Expand;
|
---|
2258 | SelectedNode.ExpandChildren( true );
|
---|
2259 | end;
|
---|
2260 |
|
---|
2261 | else
|
---|
2262 | begin
|
---|
2263 | // search by first letter, in visible nodes.
|
---|
2264 |
|
---|
2265 | if ChildCount = 0 then
|
---|
2266 | // no nodes to search in
|
---|
2267 | exit;
|
---|
2268 |
|
---|
2269 | if SelectedNode = nil then
|
---|
2270 | Node := _Root.Children[ 0 ]
|
---|
2271 | else
|
---|
2272 | Node := SelectedNode;
|
---|
2273 |
|
---|
2274 | NextNode := FindNextNodeByText( Node, key, true ); // visible only
|
---|
2275 | if NextNode <> nil then
|
---|
2276 | SelectedNode := NextNode;
|
---|
2277 |
|
---|
2278 | end;
|
---|
2279 | end;
|
---|
2280 | end;
|
---|
2281 |
|
---|
2282 | inherited CharEvent( Key, RepeatCount );
|
---|
2283 | end;
|
---|
2284 |
|
---|
2285 | Procedure TOutline2.OnHoverTimeout( Sender: TObject );
|
---|
2286 | var
|
---|
2287 | R: TRect;
|
---|
2288 | begin
|
---|
2289 | R.Left := _LastMouseX;
|
---|
2290 | R.Bottom := _LastMouseY;
|
---|
2291 | R.Right := R.Left + 100;
|
---|
2292 | R.Top := R.Bottom + 50;
|
---|
2293 | // show hint
|
---|
2294 | R.LeftBottom := ClientToScreen( R.LeftBottom );
|
---|
2295 | R.RightTop := ClientToScreen( R.RightTop );
|
---|
2296 | _HintWindow.Parent := Parent;
|
---|
2297 | _HintWindow.ActivateHint( R, 'Yees' );
|
---|
2298 | _HoverTimer.Stop;
|
---|
2299 | end;
|
---|
2300 |
|
---|
2301 | Procedure TOutline2.WMMouseLeave( Var Msg: TMessage );
|
---|
2302 | begin
|
---|
2303 | if InDesigner then
|
---|
2304 | exit;
|
---|
2305 | _HoverTimer.Stop;
|
---|
2306 | // _HintWindow.DeactivateHint;
|
---|
2307 | end;
|
---|
2308 |
|
---|
2309 | Procedure TOutline2.FontChange;
|
---|
2310 | begin
|
---|
2311 | inherited FontChange;
|
---|
2312 |
|
---|
2313 | if _AutoLineHeight then
|
---|
2314 | begin
|
---|
2315 | LineHeight := Canvas.TextHeight( 'H' ) + 1;
|
---|
2316 | Refresh; // lineheight change alone may not be enough.
|
---|
2317 | end;
|
---|
2318 | end;
|
---|
2319 |
|
---|
2320 | Procedure TOutline2.DoVerticalScroll( NewY: longint );
|
---|
2321 | var
|
---|
2322 | ScrollDistance: longint;
|
---|
2323 | begin
|
---|
2324 | if not Visible then
|
---|
2325 | exit;
|
---|
2326 |
|
---|
2327 | FYScroll := NewY;
|
---|
2328 | ScrollDistance:= FYScroll - FLastYScroll;
|
---|
2329 |
|
---|
2330 | ScrollControlRect( Self,
|
---|
2331 | GetTextRect,
|
---|
2332 | 0,
|
---|
2333 | ScrollDistance,
|
---|
2334 | Color,
|
---|
2335 | FSmoothScroll );
|
---|
2336 |
|
---|
2337 | FLastYScroll:= FYScroll;
|
---|
2338 | PostMsg( Handle, WM_PAINT, 0, 0 );
|
---|
2339 | end;
|
---|
2340 |
|
---|
2341 | Procedure TOutline2.DoHorizontalScroll( NewX: longint );
|
---|
2342 | var
|
---|
2343 | ScrollDistance: longint;
|
---|
2344 | begin
|
---|
2345 | if not Visible then
|
---|
2346 | exit;
|
---|
2347 |
|
---|
2348 | FXScroll := NewX;
|
---|
2349 | ScrollDistance:= FXScroll - FLastXScroll;
|
---|
2350 |
|
---|
2351 | ScrollControlRect( Self,
|
---|
2352 | GetTextRect,
|
---|
2353 | - ScrollDistance,
|
---|
2354 | 0,
|
---|
2355 | Color,
|
---|
2356 | FSmoothScroll );
|
---|
2357 |
|
---|
2358 | FLastXScroll:= FXScroll;
|
---|
2359 | PostMsg( Handle, WM_PAINT, 0, 0 );
|
---|
2360 | end;
|
---|
2361 |
|
---|
2362 | Procedure TOutline2.Scroll( Sender: TScrollbar;
|
---|
2363 | ScrollCode: TScrollCode;
|
---|
2364 | Var ScrollPos: Longint );
|
---|
2365 |
|
---|
2366 | begin
|
---|
2367 | case ScrollCode of
|
---|
2368 | // scVertEndScroll,
|
---|
2369 | scVertPosition,
|
---|
2370 | scPageUp,
|
---|
2371 | scPageDown,
|
---|
2372 | scVertTrack,
|
---|
2373 | scLineDown,
|
---|
2374 | scLineUp:
|
---|
2375 | begin
|
---|
2376 | DoVerticalScroll( ScrollPos );
|
---|
2377 | end;
|
---|
2378 |
|
---|
2379 | scHorzPosition,
|
---|
2380 | scPageRight,
|
---|
2381 | scPageLeft,
|
---|
2382 | scHorzTrack,
|
---|
2383 | scColumnRight,
|
---|
2384 | scColumnLeft:
|
---|
2385 | begin
|
---|
2386 | DoHorizontalScroll( ScrollPos );
|
---|
2387 | end;
|
---|
2388 | end;
|
---|
2389 | end;
|
---|
2390 |
|
---|
2391 | Initialization
|
---|
2392 | {Register classes}
|
---|
2393 | RegisterClasses([TOutline2]);
|
---|
2394 | End.
|
---|
2395 |
|
---|
2396 |
|
---|