home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d56 / RMCTL.ZIP / rmInspector.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-22  |  38KB  |  1,386 lines

  1. {================================================================================
  2. Copyright (C) 1997-2001 Mills Enterprise
  3.  
  4. Unit     : rmInspector
  5. Purpose  : This control is similar to Delphi's properties inspector.
  6. Date     : 01-18-2001
  7. Author   : Ryan J. Mills
  8. Version  : 1.80
  9. ================================================================================}
  10.  
  11. unit rmInspector;
  12.  
  13. interface
  14.  
  15. {$I CompilerDefines.INC}
  16.  
  17. uses
  18.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  19.   StdCtrls, ExtCtrls, rmTreeNonView;
  20.  
  21. type
  22.   TrmInspector = class;
  23.   TrmCustomInspectorItemClass = class of TrmCustomInspectorItem;
  24.   TmsgEvent = procedure(msg:TMessage) of object;
  25.  
  26.   TrmInspectorIndexChangingEvent = procedure(CurrentNode, NewNode: TrmTreeNonViewNode; var AllowChange: boolean) of object;
  27.  
  28.   TrmCustomInspectorItem = class(TComponent)
  29.   private
  30.     fHint: string;
  31.     fInspector : TrmInspector;
  32.     fNode: TrmTreeNonViewNode;
  33.   protected
  34.     function GetStringValue: string; virtual; abstract;
  35.     procedure SetStringValue(const Value: string); virtual; abstract;
  36.   public
  37.     function EditorClass: TWinControlClass; virtual; abstract;
  38.     procedure GetValueFromEditor(Editor: TWinControl); virtual; abstract;
  39.     procedure SetValueIntoEditor(Editor: TWinControl); virtual; abstract;
  40.     procedure SetupEditor(Inspector: TrmInspector; Editor: TWinControl); virtual; abstract;
  41.     property InspectorControl : TrmInspector read fInspector;
  42.     property PathNode : TrmTreeNonViewNode read fNode;
  43.   published
  44.     property AsString: string read GetStringValue write SetStringValue;
  45.     property Hint: string read fHint write fHint;
  46.   end;
  47.  
  48.   TrmInspector = class(TCustomControl)
  49.   private
  50.     { Private declarations }
  51.     fItems: TrmTreeNonView;
  52.     fTopIndex: integer;
  53.     fEditorFocus: boolean;
  54.     fEditControl: TWinControl;
  55.  
  56.     fShowFocusRect: boolean;
  57.     fShowVScrollBars: boolean;
  58.     fItemHeight: integer;
  59.     FBorderStyle: TBorderStyle;
  60.  
  61.     fIndex: integer;
  62.     fCurrentNode: TrmTreeNonViewNode;
  63.  
  64.     fSplit: integer;
  65.     fSplitMove: boolean;
  66.     fOnIndexChanged: TNotifyEvent;
  67.     fonIndexChanging: TrmInspectorIndexChangingEvent;
  68.     fOnEditorExit: TNotifyEvent;
  69.     fOnEditorCreated: TNotifyEvent;
  70.     fOnEditorEnter: TNotifyEvent;
  71.     fOnEditorKeyUp: TKeyEvent;
  72.     fOnEditorKeyDown: TKeyEvent;
  73.     fOnEditorKeyPress: TKeyPressEvent;
  74.     fToolTip: Boolean;
  75.     fOnkeydown : TKeyEvent;
  76.     fReadonly: boolean;
  77.     fOnComplexEdit: TNotifyEvent;
  78.     fOnWnd: TMsgEvent;
  79.  
  80.     function vLines: integer;
  81.     function ItemHeight: integer;
  82.     function VisibleItemCount: integer;
  83.  
  84.     function IsItemVisible(Item:TrmCustomInspectorItem):Boolean;
  85.     function VisibileItemIndex(Item:TrmCustomInspectorItem):integer;
  86.  
  87.     function IsNodeVisible(Node:TrmTreeNonViewNode):boolean;
  88.     function VisibileNodeIndex(Node:TrmTreeNonViewNode):integer;
  89.  
  90.     procedure UpdateVScrollBar;
  91.     procedure ScrollToVisible;
  92.  
  93.     function GetVScrollPos: integer;
  94.     procedure SetVScrollPos(const Value: integer);
  95.  
  96.     procedure DoNodeTextChanged(Sender:TObject; Node:TrmTreeNonViewNode);
  97.  
  98.     procedure cmFontChanged(var Msg: TMessage); message cm_fontchanged;
  99.     procedure wmSize(var MSG: TWMSize); message wm_size;
  100.     procedure wmEraseBKGrnd(var msg: tmessage); message wm_erasebkgnd;
  101.     procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
  102.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  103.     procedure SetShowFocusRect(const Value: boolean);
  104.     procedure SetShowVScrollBars(const Value: boolean);
  105.     function GetVScrollSize: integer;
  106.     procedure SetBorderStyle(const Value: TBorderStyle);
  107.     procedure setSplit(const Value: integer);
  108.     function GetSepChar: char;
  109.     procedure SetItems(const Value: TrmTreeNonViewNodes);
  110.     procedure SetSepChar(const Value: char);
  111.     function GetItems: TrmTreeNonViewNodes;
  112.     procedure SetItemIndex(const Value: integer);
  113.     function GetCurrentInspectorItem: TrmCustomInspectorItem;
  114.     procedure SetNewHint(Node: TrmTreeNonViewNode; Rect: TRect; Data: Boolean);
  115.     procedure CMCancelMode(var Message: TMessage); message cm_CancelMode;
  116.     procedure CMMouseLeave(var Message: TMessage); message cm_MouseLeave;
  117.     procedure SetReadonly(const Value: boolean);
  118.     function GetCurrentPath: string;
  119.     procedure SetCurrentPath(const Value: string);
  120.     procedure SetCurrentNode(const Value: TrmTreeNonViewNode);
  121.   protected
  122.     procedure paint; override;
  123.     procedure CreateParams(var Params: TCreateParams); override;
  124.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  125.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  126.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  127.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  128.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;
  129.     function GetVisibleItem(VisibilityIndex: integer): TrmTreeNonViewNode;
  130.     function GetVisibleItemRect(VisibilityIndex: integer; Data: Boolean): TRect;
  131.     property ShowVScrollBars: boolean read fShowVScrollBars write SetShowVScrollBars default true;
  132.     property ShowFocusRect: boolean read fShowFocusRect write SetShowFocusRect default true;
  133.     procedure DoExit; override;
  134.     procedure DoNodeDelete(Sender: TObject; Node: TrmTreeNonViewNode); virtual;
  135.     procedure EditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  136.     procedure UpdateEditorSizePos;
  137.   public
  138.     { Public declarations }
  139.     constructor create(aowner: TComponent); override;
  140.     destructor destory;
  141.     procedure DoComplexEdit(Sender:TObject);
  142.     procedure loaded; override;
  143.     procedure AssignItems(Value:TrmInspector);
  144.     function ParentPath(st:string):string;
  145.     function AddInspectorItem(Path: string; Value: string; ClassType: TrmCustomInspectorItemClass): TrmCustomInspectorItem;
  146.     function FindInspectorItem(Path: string): TrmCustomInspectorItem;
  147.     procedure ClearItems;
  148.     Procedure DeleteItem(Path:string);
  149.     procedure WndProc(var Message: TMessage); override;
  150.     property CurrentItemPath:string read GetCurrentPath write SetCurrentPath;
  151.     property CurrentItem: TrmCustomInspectorItem read GetCurrentInspectorItem;
  152.     property CurrentNode:TrmTreeNonViewNode read fCurrentNode write SetCurrentNode;
  153.     property VScrollPos: integer read GetVScrollPos write SetVScrollPos;
  154.     property VScrollSize: integer read GetVScrollSize;
  155.     property Editor: TWinControl read fEditControl;
  156.     property SepChar: char read GetSepChar write SetSepChar;
  157.     property OnWnd : TMsgEvent read fOnWnd write fOnWnd;
  158.   published
  159.     property Align;
  160.     property Font;
  161.     property Readonly: boolean read fReadonly write SetReadonly default false;
  162.     property ToolTip: Boolean read fToolTip write fToolTip default true;
  163.     property TabStop;
  164.     property TabOrder;
  165.     property ItemIndex: integer read fIndex write SetItemIndex default -1;
  166.     property Items: TrmTreeNonViewNodes read GetItems write SetItems;
  167.     property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsNone;
  168.     property SplitPos: integer read fSplit write setSplit;
  169.     property ShowHint;
  170.     property OnItemIndexChanging: TrmInspectorIndexChangingEvent read fonIndexChanging write fOnIndexChanging;
  171.     property OnItemIndexChanged: TNotifyEvent read fOnIndexChanged write fOnIndexChanged;
  172.     property OnComplexEdit: TNotifyEvent read fOnComplexEdit write fOnComplexEdit;
  173.     property OnEditorCreated: TNotifyEvent read fOnEditorCreated write fOnEditorCreated;
  174.     property OnEditorKeyDown: TKeyEvent read fOnEditorKeyDown write fOnEditorKeyDown;
  175.     property OnEditorKeyUp: TKeyEvent read fOnEditorKeyUp write fOnEditorKeyUp;
  176.     property OnEditorKeyPress: TKeyPressEvent read fOnEditorKeyPress write fOnEditorKeyPress;
  177.     property OnEditorExit: TNotifyEvent read fOnEditorExit write fOnEditorExit;
  178.     property OnEditorEnter: TNotifyEvent read fOnEditorEnter write fOnEditorEnter;
  179.   end;
  180.  
  181. implementation
  182.  
  183. uses rmlibrary, rmHint, rmInspectorItems;
  184.  
  185. type
  186.   TWinControlInvasion = class(TWinControl)
  187.   end;
  188.  
  189. var
  190.   fHint: TrmHintWindow;
  191.  
  192. {$R *.RES}
  193.  
  194. { TrmInspector }
  195.  
  196. constructor TrmInspector.create(aowner: TComponent);
  197. begin
  198.   inherited;
  199.  
  200.   ControlStyle := controlstyle + [csopaque];
  201.   height := 200;
  202.   width := 225;
  203.   fItemHeight := -1;
  204.   fIndex := -1;
  205.   fReadonly := false;
  206.   fTopIndex := 0;
  207.   fEditControl := nil;
  208.   fCurrentNode := nil;
  209.   fToolTip := true;
  210.   Canvas.Font.Assign(Font);
  211.   fItems := TrmTreeNonView.Create(nil);
  212.   fItems.OnNodeTextChanged := DoNodeTextChanged;
  213.   fItems.OnDeletion := DoNodeDelete;
  214.   fBorderStyle := bsNone;
  215.   fSplit := 100;
  216.   fShowFocusRect := true;
  217.   fShowVScrollBars := true;
  218.   SepChar := #1;
  219. end;
  220.  
  221. procedure TrmInspector.CreateParams(var Params: TCreateParams);
  222. const
  223.   BorderStyles: array[TBorderStyle] of DWORD = (0, WS_BORDER);
  224. begin
  225.   inherited CreateParams(Params);
  226.   with Params do
  227.   begin
  228.     if fShowVScrollBars then
  229.       Style := Style or WS_VSCROLL;
  230.  
  231.     Style := Style or BorderStyles[FBorderStyle];
  232.     if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then
  233.     begin
  234.       Style := Style and not WS_BORDER;
  235.       ExStyle := ExStyle or WS_EX_CLIENTEDGE;
  236.     end;
  237.     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  238.   end;
  239. end;
  240.  
  241. destructor TrmInspector.destory;
  242. begin
  243.   SetNewHint(nil, rect(0, 0, 0, 0), false);
  244.   fItems.free;
  245.   inherited;
  246. end;
  247.  
  248. function TrmInspector.GetVScrollPos: integer;
  249. var
  250.   wScrollInfo: TScrollInfo;
  251. begin
  252.   if fShowVScrollBars then
  253.   begin
  254.     with wScrollInfo do
  255.     begin
  256.       cbSize := sizeof(TScrollInfo);
  257.       fMask := SIF_POS;
  258.     end;
  259.  
  260.     if GetScrollInfo(Handle, SB_VERT, wScrollInfo) then
  261.       result := wScrollInfo.nPos
  262.     else
  263.       result := 0;
  264.   end
  265.   else
  266.     result := 0;
  267. end;
  268.  
  269. procedure TrmInspector.paint;
  270. var
  271.   lcount, loop: integer;
  272.   wNEdit, wNRect: TRect;
  273.   wObj: TrmCustomInspectorItem;
  274.   wNode: TrmTreeNonViewNode;
  275.   wBmp, wImage: TBitMap;
  276.   wLevel: integer;
  277.   fEditControlAdjusted : boolean;
  278. begin
  279.    wNRect := GetVisibleItemRect(0, false);
  280.    wNEdit := GetVisibleItemRect(0, true);
  281.    wImage := TBitMap.create;
  282.    try
  283.      wImage.Height := clientheight;
  284.      wImage.width := clientwidth;
  285.  
  286.      wImage.Canvas.brush.Color := clBtnFace;
  287.  
  288.      if (csdesigning in componentstate) then
  289.      begin
  290.         wImage.Canvas.pen.Style := psDash;
  291.         try
  292.            wImage.Canvas.pen.color := clBtnText;
  293.            wImage.Canvas.Rectangle(clientrect);
  294.         finally
  295.            wImage.Canvas.pen.Style := psSolid;
  296.         end;
  297.      end
  298.      else
  299.         wImage.Canvas.Fillrect(ClientRect);
  300.  
  301.      wImage.Canvas.Font.assign(Canvas.Font);
  302.  
  303.  
  304.      fEditControlAdjusted := false;
  305.      wBmp := TBitMap.create;
  306.      try
  307.        if fitems.Items.Count > 0 then
  308.        begin
  309.          lcount := vLines;
  310.          if lcount + fTopIndex > VisibleItemCount then
  311.            lcount := VisibleItemCount - fTopIndex;
  312.          loop := fTopIndex;
  313.          while loop < fTopIndex + lcount do
  314.          begin
  315.            wNode := GetVisibleItem(loop);
  316.            if assigned(wNode) then
  317.            begin
  318.              wObj := TrmCustomInspectorItem(wNode.Data);
  319.              wLevel := (wNode.Level * 12);
  320.            end
  321.            else
  322.            begin
  323.              wObj := nil;
  324.              wLevel := 0;
  325.            end;
  326.  
  327.            wImage.Canvas.Brush.Color := clBtnFace;
  328.            wImage.canvas.Font.Color := clBtnText;
  329.            if assigned(wObj) then
  330.            begin
  331.              wImage.Canvas.TextRect(wNRect, 12 + wLevel, wNRect.top, wNode.Text);
  332.  
  333.              if loop = fIndex then
  334.              begin
  335.                wImage.Canvas.Brush.Color := clWindow;
  336.                wImage.canvas.Font.Color := clWindowText;
  337.              end;
  338.              wImage.Canvas.TextRect(wNEdit, wNEdit.Left, wNEdit.top, wObj.AsString);
  339.            end
  340.            else
  341.            begin
  342.              if assigned(wNode) then
  343.              begin
  344.                wImage.Canvas.TextRect(wNRect, 12 + wLevel, wNRect.top, wNode.Text);
  345.                if loop = fIndex then
  346.                begin
  347.                  wImage.Canvas.Brush.Color := clWindow;
  348.                  wImage.canvas.Font.Color := clWindowText;
  349.                end;
  350.                wImage.Canvas.TextRect(wNEdit, wNEdit.Left, wNEdit.top, '<empty value>');
  351.              end
  352.              else
  353.              begin
  354.                wImage.Canvas.TextRect(wNRect, 12, wNRect.top, '<empty node>');
  355.                if loop = fIndex then
  356.                begin
  357.                  Canvas.Brush.Color := clWindow;
  358.                  canvas.Font.Color := clWindowText;
  359.                end;
  360.                wImage.Canvas.TextRect(wNEdit, wNEdit.Left, wNEdit.top, '<empty value>');
  361.              end;
  362.            end;
  363.  
  364.            if assigned(wNode) and wNode.HasChildren then
  365.            begin
  366.              if wNode.Expanded then
  367.                wBmp.LoadFromResourceName(HInstance, 'rminspectorcollapse')
  368.              else
  369.                wBmp.LoadFromResourceName(HInstance, 'rminspectorexpand');
  370.  
  371.              wBmp.TransparentMode := tmAuto;
  372.              wBmp.Transparent := true;
  373.              wImage.Canvas.Draw(wLevel + 1, wNRect.Top + ((ItemHeight div 2) - (wBmp.height div 2)), wbmp);
  374.            end;
  375.  
  376.            if (loop = fIndex) then
  377.            begin
  378.              wImage.Canvas.Pen.Color := clBtnHighLight;
  379.              if not fEditorFocus then
  380.              begin
  381.                self.Setfocus;
  382.                wBmp.LoadFromResourceName(HInstance, 'rminspectorindicator');
  383.                ReplaceColors(wBmp, clBtnFace, clBtnText);
  384.                wBmp.Transparent := true;
  385.                wBMP.TransparentColor := clBtnFace;
  386.                wImage.Canvas.Draw(0, wNRect.Top + ((ItemHeight div 2) - (wBmp.height div 2)), wbmp);
  387.              end;
  388.              if assigned(fEditControl) then
  389.              begin
  390.                 fEditControl.BoundsRect := wNEdit;
  391.                 if TWinControlInvasion(fEditControl).Text <> CurrentItem.AsString then
  392.                    TWinControlInvasion(fEditControl).Text := CurrentItem.AsString;
  393.              end;
  394.              fEditControlAdjusted := true;
  395.            end
  396.            else
  397.              wImage.Canvas.Pen.Color := clBtnShadow;
  398.  
  399.            wImage.Canvas.MoveTo(0, wnrect.Bottom - 1);
  400.            wImage.Canvas.lineto(clientwidth, wnRect.Bottom - 1);
  401.  
  402.            wImage.Canvas.Pen.Color := clBtnFace;
  403.            wImage.Canvas.MoveTo(0, wnrect.Bottom - 2);
  404.            wImage.Canvas.lineto(clientwidth, wnRect.Bottom - 2);
  405.  
  406.            wImage.Canvas.Pen.Color := clBtnShadow;
  407.            wImage.canvas.moveto(fsplit - 1, wnRect.Top - 1);
  408.            wImage.canvas.Lineto(fsplit - 1, wnRect.Bottom);
  409.  
  410.            wImage.Canvas.Pen.Color := clBtnHighlight;
  411.            wImage.canvas.moveto(fsplit, wnRect.Top - 1);
  412.            wImage.canvas.Lineto(fsplit, wnRect.Bottom);
  413.  
  414.            offsetrect(wNRect, 0, ItemHeight);
  415.            offsetrect(wNEdit, 0, ItemHeight);
  416.  
  417.            wImage.Canvas.brush.Color := clBtnFace;
  418.            wImage.Canvas.Font.color := clBtnText;
  419.  
  420.            inc(loop);
  421.          end;
  422.        end;
  423.      finally
  424.        wBmp.free;
  425.      end;
  426.      Canvas.Draw(0, 0, wImage);
  427.      if not fEditControlAdjusted then
  428.      begin
  429.         if assigned(fEditControl) then
  430.            fEditControl.Top := clientheight+1;
  431.      end;
  432.    finally
  433.      wImage.Free;
  434.    end;
  435. end;
  436.  
  437. procedure TrmInspector.ScrollToVisible;
  438. begin
  439.   if (fTopIndex < fIndex) then
  440.   begin
  441.     if (((fTopIndex + vLines) - 2) < fIndex) then
  442.       fTopIndex := (fIndex - (vLines - 2));
  443.   end
  444.   else if fIndex < fTopIndex then
  445.     fTopIndex := fIndex;
  446.  
  447.   if fTopIndex < 0 then
  448.   begin
  449.     fTopIndex := 0;
  450.     ItemIndex := 0;
  451.   end;
  452. end;
  453.  
  454. procedure TrmInspector.SetVScrollPos(const Value: integer);
  455. var
  456.   wScrollInfo: TScrollInfo;
  457. begin
  458.   if fShowVScrollBars then
  459.   begin
  460.     with wScrollInfo do
  461.     begin
  462.       cbSize := sizeof(TScrollInfo);
  463.       fMask := SIF_POS or SIF_DISABLENOSCROLL;
  464.       nMin := 0;
  465.       nMax := 0;
  466.       nPos := Value;
  467.     end;
  468.  
  469.     fTopIndex := SetScrollInfo(Handle, SB_VERT, wScrollInfo, true);
  470.   end
  471.   else
  472.   begin
  473.     fTopIndex := SetInRange(value, 0, VScrollSize);
  474.   end;
  475.   Invalidate;
  476. end;
  477.  
  478. procedure TrmInspector.UpdateVScrollBar;
  479. var
  480.   wScrollInfo: TScrollInfo;
  481. begin
  482.   if csloading in componentstate then exit;
  483.   if csDestroying in ComponentState then exit;
  484.  
  485.   fTopIndex := SetInRange(fTopIndex, 0, VScrollSize);
  486.  
  487.   if fShowVScrollBars then
  488.   begin
  489.     with wScrollInfo do
  490.     begin
  491.       cbSize := sizeof(TScrollInfo);
  492.       fMask := SIF_POS or SIF_RANGE;
  493.       nMin := 0;
  494.       nMax := VScrollSize;
  495.       nPos := fTopIndex;
  496.     end;
  497.  
  498.     SetScrollInfo(Handle, SB_VERT, wScrollInfo, True);
  499.     fTopIndex := VScrollPos;
  500.   end;
  501.  
  502. end;
  503.  
  504. function TrmInspector.vLines: integer;
  505. begin
  506.   result := ClientHeight div ItemHeight;
  507.   if (clientheight mod itemheight > 0) then
  508.      inc(result);
  509. end;
  510.  
  511. procedure TrmInspector.wmEraseBKGrnd(var msg: tmessage);
  512. begin
  513.   msg.result := 1;
  514. end;
  515.  
  516. procedure TrmInspector.wmSize(var MSG: TWMSize);
  517. begin
  518.   UpdatevScrollBar;
  519.   SplitPos := splitPos;
  520.   UpdateEditorSizePos;
  521.   inherited;
  522. end;
  523.  
  524. procedure TrmInspector.WMVScroll(var Msg: TWMVScroll);
  525. begin
  526.   inherited;
  527.   case Msg.ScrollCode of
  528.     SB_BOTTOM: fTopIndex := VisibleItemCount - vLines;
  529.     SB_LINEDOWN: inc(fTopIndex);
  530.     SB_LINEUP: dec(fTopIndex);
  531.     SB_TOP: fTopIndex := 0;
  532.     SB_PAGEDOWN: inc(fTopIndex, vLines);
  533.     SB_PAGEUP: dec(fTopIndex, vLines);
  534.     SB_THUMBPOSITION: fTopIndex := Msg.Pos;
  535.     SB_THUMBTRACK: fTopIndex := Msg.Pos;
  536.   else
  537.     exit;
  538.   end;
  539.  
  540.   UpdateVScrollBar;
  541.   Invalidate;
  542. end;
  543.  
  544. procedure TrmInspector.WMGetDlgCode(var Message: TWMGetDlgCode);
  545. begin
  546.   Message.Result := DLGC_WANTARROWS or DLGC_WANTTAB;
  547. end;
  548.  
  549. procedure TrmInspector.KeyDown(var Key: Word; Shift: TShiftState);
  550. var
  551.   wNode: TrmTreeNonViewNode;
  552. begin
  553.   SetNewHint(nil, rect(0, 0, 0, 0), false);
  554.   if shift = [] then
  555.   begin
  556.     case key of
  557.       vk_tab:
  558.         begin
  559.            if not fReadonly then
  560.            begin
  561.               fEditorFocus := true;
  562.               fEditControl.SetFocus;
  563.            end;
  564.         end;
  565.       vk_DOWN:
  566.         begin
  567.           ItemIndex := ItemIndex + 1;
  568.         end;
  569.       vk_up:
  570.         begin
  571.           if ItemIndex-1 >= 0 then
  572.              ItemIndex := ItemIndex - 1;
  573.         end;
  574.       vk_next:
  575.         begin
  576.           ItemIndex := ItemIndex + (vLines - 1);
  577.         end;
  578.       vk_prior:
  579.         begin
  580.           ItemIndex := ItemIndex - (vLines - 1);
  581.           if ItemIndex < 0 then
  582.              ItemIndex := 0;
  583.         end;
  584.       vk_Left:
  585.         begin
  586.           wNode := GetVisibleItem(findex);
  587.           if assigned(wNode) and wNode.HasChildren then
  588.           begin
  589.             wNode.Expanded := false;
  590.           end;
  591.         end;
  592.       vk_Right:
  593.         begin
  594.           wNode := GetVisibleItem(findex);
  595.           if assigned(wNode) and wNode.HasChildren then
  596.           begin
  597.             wNode.Expanded := true;
  598.           end;
  599.         end;
  600.     else
  601.       inherited;
  602.       exit;
  603.     end;
  604.     key := 0;
  605.     ScrollToVisible;
  606.     UpdateVScrollBar;
  607.     Invalidate;
  608.     exit;
  609.   end
  610.   else
  611.   inherited;
  612. end;
  613.  
  614. procedure TrmInspector.MouseDown(Button: TMouseButton;
  615.   Shift: TShiftState; X, Y: Integer);
  616. var
  617.   wLine: integer;
  618.   wNode: TrmTreeNonViewNode;
  619.   wLevel: integer;
  620. begin
  621.   inherited;
  622.   if Button = mbLeft then
  623.   begin
  624.     SetNewHint(nil, rect(0, 0, 0, 0), false);
  625.     if CanFocus then
  626.       setfocus;
  627.  
  628.     if (x >= fsplit - 1) and (x <= fsplit + 1) then
  629.     begin
  630.       fSplitMove := true;
  631.     end
  632.     else
  633.     begin
  634.       wLine := fTopIndex + (y div ItemHeight);
  635.  
  636.       if wLine < VisibleItemCount then
  637.       begin
  638.         wNode := GetVisibleItem(wLine);
  639.         wLevel := (wNode.Level * 12);
  640.         if (x > wLevel) and (x < 12 + wLevel) then
  641.         begin
  642.           if assigned(wNode) and wNode.HasChildren then
  643.           begin
  644.             wNode.Expanded := not wNode.Expanded;
  645.           end;
  646.         end;
  647.         fEditorFocus := (x > fSplit) and not FReadOnly;
  648.         ItemIndex := wLine;
  649.         ScrollToVisible;
  650.         UpdateVScrollBar;
  651.         invalidate;
  652.       end;
  653.     end;
  654.   end;
  655. end;
  656.  
  657. procedure TrmInspector.MouseMove(Shift: TShiftState; X, Y: Integer);
  658. var
  659.   wLine, wyPos, wxPos, wLevel: integer;
  660.   wnvNode: TrmTreeNonViewNode;
  661.   wRect: TRect;
  662.   wData: boolean;
  663. begin
  664.   inherited;
  665.   wLine := fTopIndex + (y div ItemHeight);
  666.  
  667.   if fSplitMove then
  668.   begin
  669.     if splitpos <> x then
  670.     begin
  671.        splitpos := x;
  672.        UpdateEditorSizePos;
  673.        Repaint;
  674.     end;
  675.   end
  676.   else
  677.   begin
  678.     wnvNode := nil;
  679.     wData := x > SplitPos;
  680.     if wLine < VisibleItemCount then
  681.     begin
  682.       if focused and (Shift = [ssLeft]) then
  683.       begin
  684.         ItemIndex := wLine;
  685.         ScrollToVisible;
  686.         UpdateVScrollBar;
  687.         invalidate;
  688.       end;
  689.       if (Shift = []) and Application.Active then
  690.       begin
  691.         wnvNode := GetVisibleItem(wLine);
  692.         wRect := rect(0, 0, 0, 0);
  693.         if assigned(wnvNode) then
  694.         begin
  695.           wyPos := ((y div itemheight) * itemheight);
  696.           wLevel := ((wnvNode.Level * 12) + 12);
  697.           if wData then
  698.           begin
  699.             if (wnvNode <> fCurrentNode) then
  700.             begin
  701.               wxPos := SplitPos - 1;
  702.               if Canvas.textwidth(TrmCustomInspectorItem(wnvNode.Data).AsString) > (clientwidth - splitpos) then
  703.                 wRect := Rect(wxPos, wyPos, wxPos + Canvas.textwidth(TrmCustomInspectorItem(wnvNode.Data).AsString) + 3, wypos + itemheight)
  704.               else
  705.                 wnvNode := nil;
  706.             end
  707.             else
  708.               wnvNode := nil;
  709.           end
  710.           else
  711.           begin
  712.             wxPos := wLevel - 2;
  713.             if Canvas.textwidth(wnvNode.text) + wLevel > (splitpos) then
  714.               wRect := Rect(wxpos, wypos, wxpos + Canvas.textwidth(wnvNode.text) + 3, wypos + itemheight)
  715.             else
  716.               wnvNode := nil;
  717.           end;
  718.         end;
  719.       end;
  720.     end;
  721.     SetNewHint(wnvNode, wRect, wData);
  722.   end;
  723.   if (x >= fsplit - 1) and (x <= fsplit + 1) then
  724.     Cursor := crHSplit
  725.   else
  726.     Cursor := crDefault;
  727. end;
  728.  
  729. procedure TrmInspector.SetShowFocusRect(const Value: boolean);
  730. begin
  731.   if fShowFocusRect <> Value then
  732.   begin
  733.     fShowFocusRect := Value;
  734.     invalidate;
  735.   end;
  736. end;
  737.  
  738. procedure TrmInspector.SetShowVScrollBars(const Value: boolean);
  739. begin
  740.   if fShowVScrollBars <> Value then
  741.   begin
  742.     fShowVScrollBars := Value;
  743.     recreatewnd;
  744.   end;
  745. end;
  746.  
  747. function TrmInspector.GetVScrollSize: integer;
  748. begin
  749.   if VisibleItemCount - vLines < 0 then
  750.     result := 0
  751.   else
  752.     result := (VisibleItemCount - vLines)+1;
  753. end;
  754.  
  755. procedure TrmInspector.cmFontChanged(var Msg: TMessage);
  756. begin
  757.   inherited;
  758.   Canvas.font.Assign(font);
  759.   fItemHeight := -1;
  760. end;
  761.  
  762. function TrmInspector.DoMouseWheel(Shift: TShiftState;
  763.   WheelDelta: Integer; MousePos: TPoint): Boolean;
  764. var
  765.   wdata: integer;
  766. begin
  767.   inherited DoMouseWheel(Shift, WheelDelta, MousePos);
  768.   result := true;
  769.   wData := (WheelDelta div ItemHeight);
  770.   fTopIndex := SetInRange(vScrollPos + wData, 0, VScrollSize);
  771.   UpdateVScrollBar;
  772.   invalidate;
  773. end;
  774.  
  775. function TrmInspector.ItemHeight: integer;
  776. var
  777.   wTextMetric: TTextMetric;
  778. begin
  779.   if fItemHeight = -1 then
  780.   begin
  781.     GetTextMetrics(canvas.handle, wTextMetric);
  782.     fItemHeight := wTextMetric.tmHeight + 3;
  783.   end;
  784.   result := fItemHeight
  785. end;
  786.  
  787. procedure TrmInspector.SetBorderStyle(const Value: TBorderStyle);
  788. begin
  789.   if FBorderStyle <> Value then
  790.   begin
  791.     FBorderStyle := Value;
  792.     RecreateWnd;
  793.   end;
  794. end;
  795.  
  796. function TrmInspector.VisibleItemCount: integer;
  797. var
  798.   wNode: TrmTreeNonViewNode;
  799. begin
  800.    wNode := fItems.Items.GetFirstNode;
  801.    result := 0;
  802.    while wNode <> nil do
  803.    begin
  804.      inc(result);
  805.      if wNode.Expanded then
  806.        wNode := wNode.GetFirstChild
  807.      else
  808.      begin
  809.        if (wNode.GetNextSibling = nil) then
  810.        begin
  811.          while (wNode <> nil) and (wNode.GetNextSibling = nil) do
  812.            wNode := wNode.Parent;
  813.          if wNode <> nil then
  814.            wNode := wNode.GetNextSibling;
  815.        end
  816.        else
  817.          wNode := wNode.GetNextSibling;
  818.      end;
  819.    end;
  820. end;
  821.  
  822. function TrmInspector.GetVisibleItem(VisibilityIndex: integer): TrmTreeNonViewNode;
  823. var
  824.   loop: integer;
  825.   wNode: TrmTreeNonViewNode;
  826. begin
  827.   wNode := nil;   
  828.   if Visibilityindex <> -1 then
  829.   begin
  830.      loop := 0;
  831.      wNode := fItems.Items.GetFirstNode;
  832.      while (wNode <> nil) and (loop < VisibilityIndex) do
  833.      begin
  834.        inc(loop);
  835.        if wNode.Expanded then
  836.          wNode := wNode.GetFirstChild
  837.        else
  838.        begin
  839.          if (wNode.GetNextSibling = nil) then
  840.          begin
  841.            while (wNode <> nil) and (wNode.GetNextSibling = nil) do
  842.              wNode := wNode.Parent;
  843.            if wNode <> nil then
  844.              wNode := wNode.GetNextSibling;
  845.          end
  846.          else
  847.            wNode := wNode.GetNextSibling;
  848.        end;
  849.      end;
  850.   end;
  851.   result := wNode;
  852. end;
  853.  
  854. procedure TrmInspector.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  855.   Y: Integer);
  856. begin
  857.   inherited;
  858.   if fSplitMove then
  859.     fSplitMove := false;
  860. end;
  861.  
  862. procedure TrmInspector.setSplit(const Value: integer);
  863. begin
  864.   try
  865.      fsplit := SetInRange(value, 15, clientwidth - 15);
  866.   except
  867.      fsplit := 15;
  868.   end;
  869.   invalidate;
  870. end;
  871.  
  872. function TrmInspector.GetSepChar: char;
  873. begin
  874.   result := fItems.SepChar;
  875. end;
  876.  
  877. procedure TrmInspector.SetItems(const Value: TrmTreeNonViewNodes);
  878. begin
  879.   fItems.Items.Assign(Value);
  880.   if csDesigning in Componentstate then
  881.      Paint
  882.   else
  883.      Paint;
  884. end;
  885.  
  886. procedure TrmInspector.SetSepChar(const Value: char);
  887. begin
  888.   if value <> fItems.SepChar then
  889.     fItems.SepChar := value;
  890. end;
  891.  
  892. function TrmInspector.GetItems: TrmTreeNonViewNodes;
  893. begin
  894.   Result := fItems.Items;
  895. end;
  896.  
  897. procedure TrmInspector.SetItemIndex(const Value: integer);
  898. var
  899.   wNode1, wNode2: TrmTreeNonViewNode;
  900.   wObj1, wObj2: TrmCustomInspectorItem;
  901.   wAllowChange: boolean;
  902.   wValue: integer;
  903.   wRect: TRect;
  904. begin
  905.   if fIndex <> value then
  906.   begin
  907.     wNode1 := GetVisibleItem(fIndex);
  908.     wValue := SetInRange(Value, -1, VisibleItemCount - 1);
  909.     wNode2 := GetVisibleItem(wValue);
  910.     if wNode1 <> wNode2 then
  911.     begin
  912.       wAllowChange := true;
  913.       if assigned(fonIndexChanging) then
  914.         fonIndexChanging(wNode1, wNode2, wAllowChange);
  915.       if wAllowChange then
  916.       begin
  917.         fCurrentNode := nil;
  918.         if assigned(wNode1) then
  919.           wObj1 := TrmCustomInspectorItem(wNode1.Data)
  920.         else
  921.           wObj1 := nil;
  922.  
  923.         if assigned(wNode2) then
  924.           wObj2 := TrmCustomInspectorItem(wNode2.Data)
  925.         else
  926.           wObj2 := nil;
  927.  
  928.         if assigned(wObj1) then
  929.         begin
  930.           try
  931.             if not fReadOnly then
  932.                wObj1.GetValueFromEditor(fEditControl);
  933.             FreeAndNil(fEditControl);
  934.           except
  935.             wObj1.SetValueIntoEditor(fEditControl);
  936.             raise;
  937.           end;
  938.         end;
  939.  
  940.         if assigned(wObj2) then
  941.         begin
  942.           fEditControl := wobj2.EditorClass.Create(self);
  943.           fEditControl.parent := self;
  944.           fEditControl.Visible := false;
  945.           if assigned(fOnEditorCreated) then
  946.           try
  947.             fOnEditorCreated(self);
  948.           except
  949.           end;
  950.           fOnkeydown := TWinControlInvasion(fEditControl).OnKeyDown;
  951.           TWinControlInvasion(fEditControl).OnKeyDown := EditorKeyDown;
  952.  
  953.           wObj2.SetupEditor(self, fEditControl);
  954.           wObj2.SetValueIntoEditor(fEditControl);
  955.  
  956.           FCurrentNode := wNode2;
  957.  
  958.           wRect := GetVisibleItemRect(wValue, True);
  959.           dec(wRect.Bottom, 2);
  960.           fEditControl.BoundsRect := wRect;
  961.           if fReadOnly then
  962.           begin
  963.              fEditControl.Visible := false;
  964.              fEditorFocus := false;
  965.           end
  966.           else
  967.              fEditControl.Visible := true;
  968.  
  969.           if fEditorFocus and (fEditControl.CanFocus) then
  970.             fEditControl.SetFocus;
  971.         end;
  972.  
  973.         fIndex := wValue;
  974.  
  975.         if assigned(fOnIndexChanged) then
  976.         try
  977.           fOnIndexChanged(self);
  978.         except
  979.         end;
  980.         invalidate;
  981.       end;
  982.     end;
  983.   end;
  984. end;
  985.  
  986. function TrmInspector.AddInspectorItem(Path: string; Value: string; ClassType: TrmCustomInspectorItemClass): TrmCustomInspectorItem;
  987. var
  988.   wObj: TrmCustomInspectorItem;
  989.   wNode : TrmTreeNonViewNode;
  990. begin
  991.   result := nil;
  992.   wNode := fItems.FindPathNode(path);
  993.   if not assigned(wNode) then
  994.   begin
  995.      wNode := fItems.AddPathNode(nil, Path);
  996.      try
  997.        wObj := ClassType.create(self);
  998.        wObj.fInspector := Self;
  999.        wObj.AsString := Value;
  1000.        wObj.fNode := wNode;
  1001.        wNode.Data := wobj;
  1002.        result := wObj;
  1003.        Invalidate;
  1004.      except
  1005.        on E:Exception do
  1006.        begin
  1007.           wNode.Delete;
  1008.           showmessage(E.messagE);
  1009.        end;
  1010.      end;
  1011.   end
  1012.   else
  1013.   raise EAbort.create('The specified path item already exists');
  1014. end;
  1015.  
  1016. function TrmInspector.FindInspectorItem(Path: string): TrmCustomInspectorItem;
  1017. var
  1018.    wItem : TrmTreeNonViewNode;
  1019. begin
  1020.   wItem := fItems.FindPathNode(Path);
  1021.   if assigned(wItem) then
  1022.      result := TrmCustomInspectorItem(wItem.Data)
  1023.   else
  1024.      result := nil;
  1025. end;
  1026.  
  1027. procedure TrmInspector.DoExit;
  1028. var
  1029.   wNode: TrmTreeNonViewNode;
  1030.   wObj: TrmCustomInspectorItem;
  1031. begin
  1032.   if assigned(fEditControl) and fEditControl.visible then
  1033.   begin
  1034.     wNode := GetVisibleItem(fIndex);
  1035.     if assigned(wNode) and assigned(wNode.Data) then
  1036.     begin
  1037.       wObj := TrmCustomInspectorItem(wNode.Data);
  1038.       try
  1039.         wObj.GetValueFromEditor(fEditControl);
  1040.       except
  1041.         fEditControl.SetFocus;
  1042.         raise;
  1043.       end;
  1044.     end;
  1045.   end;
  1046.   inherited;
  1047.  
  1048. end;
  1049.  
  1050. procedure TrmInspector.loaded;
  1051. begin
  1052.   inherited;
  1053.   UpdatevScrollBar;
  1054.   Invalidate;
  1055. end;
  1056.  
  1057. procedure TrmInspector.EditorKeyDown(Sender: TObject; var Key: Word;
  1058.   Shift: TShiftState);
  1059. begin
  1060.   if Shift = [] then
  1061.   begin
  1062.     case key of
  1063.       vk_tab:
  1064.         begin
  1065.           key := 0;
  1066.           fEditorFocus := false;
  1067.           self.SetFocus;
  1068.           Invalidate;
  1069.         end;
  1070.       vk_up:
  1071.         begin
  1072.           key := 0;
  1073.           if itemindex-1 >= 0 then
  1074.              ItemIndex := itemindex - 1;
  1075.         end;
  1076.       vk_down:
  1077.         begin
  1078.           key := 0;
  1079.           ItemIndex := itemindex + 1;
  1080.         end;
  1081.     end;
  1082.   end;
  1083.  
  1084.   if assigned(fOnKeyDown) then
  1085.      fOnkeydown(Sender, key, shift);
  1086. end;
  1087.  
  1088. function TrmInspector.GetCurrentInspectorItem: TrmCustomInspectorItem;
  1089. begin
  1090.   if assigned(fcurrentNode) then
  1091.      result := TrmCustomInspectorItem(fCurrentNode.Data)
  1092.   else
  1093.      result := nil;
  1094. end;
  1095.  
  1096. procedure TrmInspector.SetNewHint(Node: TrmTreeNonViewNode; Rect: TRect; Data: boolean);
  1097. begin
  1098.   if fToolTip and assigned(Node) then
  1099.   begin
  1100.     if assigned(fHint) then
  1101.     begin
  1102.       if (not Data and (Node.text = fHint.Caption)) or
  1103.         (Data and (TrmCustomInspectorItem(Node.Data).AsString = fHint.Caption)) then
  1104.         exit
  1105.     end
  1106.     else
  1107.     begin
  1108.       fHint.free;
  1109.       fHint := nil;
  1110.     end;
  1111.  
  1112.     if assigned(Node) then
  1113.     begin
  1114.       Rect.TopLeft := Self.ClientToScreen(Rect.TopLeft);
  1115.       Rect.BottomRight := Self.ClientToScreen(Rect.BottomRight);
  1116.  
  1117.       if not assigned(fHint) then
  1118.         fHint := TrmHintWindow.Create(nil);
  1119.       fHint.Color := clInfoBk;
  1120.       fHint.Font.Assign(Canvas.font);
  1121.       if Data then
  1122.         fHint.ActivateHint(Rect, TrmCustomInspectorItem(Node.Data).AsString)
  1123.       else
  1124.         fHint.ActivateHint(Rect, Node.Text);
  1125.     end;
  1126.   end
  1127.   else
  1128.   begin
  1129.     fHint.free;
  1130.     fHint := nil;
  1131.   end;
  1132. end;
  1133.  
  1134. procedure TrmInspector.CMCancelMode(var Message: TMessage);
  1135. begin
  1136.   try
  1137.     SetNewHint(nil, rect(0, 0, 0, 0), false);
  1138.   except
  1139.       //Do Nothing...
  1140.   end;
  1141.   inherited;
  1142. end;
  1143.  
  1144. procedure TrmInspector.CMMouseLeave(var Message: TMessage);
  1145. begin
  1146.   try
  1147.     SetNewHint(nil, rect(0, 0, 0, 0), false);
  1148.   except
  1149.       //Do Nothing...
  1150.   end;
  1151.   inherited;
  1152. end;
  1153.  
  1154. function TrmInspector.GetVisibleItemRect(VisibilityIndex: integer; Data: Boolean): TRect;
  1155. var
  1156.   wRect: TRect;
  1157. begin
  1158.   if Data then
  1159.     wRect := rect(fSplit + 2, 0, clientwidth, itemHeight-1)
  1160.   else
  1161.     wRect := rect(0, 0, fSplit - 2, ItemHeight);
  1162.  
  1163.   offsetRect(wRect, 0, itemheight * visibilityindex);
  1164.   result := wRect;
  1165. end;
  1166.  
  1167. procedure TrmInspector.UpdateEditorSizePos;
  1168. var
  1169.    wRect : TRect;
  1170. begin
  1171.   if assigned(fEditControl) then
  1172.   begin
  1173.      wRect := GetVisibleItemRect(fIndex, true);
  1174.      dec(wRect.Bottom);
  1175.      fEditControl.BoundsRect := wRect;
  1176.   end;
  1177. end;
  1178.  
  1179. procedure TrmInspector.SetReadonly(const Value: boolean);
  1180. begin
  1181.   fReadonly := Value;
  1182.   if assigned(fEditControl) then
  1183.   begin
  1184.      fEditControl.Visible := not fReadOnly;
  1185.      if fReadOnly then
  1186.      begin
  1187.         fEditorFocus := not fReadOnly;
  1188.         Setfocus;
  1189.         invalidate;
  1190.      end
  1191.   end;
  1192. end;
  1193.  
  1194. procedure TrmInspector.AssignItems(Value: TrmInspector);
  1195. begin
  1196.    Items.assign(Value.Items);
  1197.    Invalidate;
  1198. end;
  1199.  
  1200. function TrmInspector.GetCurrentPath: string;
  1201. begin
  1202.    if assigned(fCurrentNode) then
  1203.       result := fCurrentNode.NodePath
  1204.    else
  1205.       result := '';
  1206. end;
  1207.  
  1208. procedure TrmInspector.SetCurrentPath(const Value: string);
  1209. var
  1210.    wNode : TrmTreeNonViewNode;
  1211. begin
  1212.    wNode := fItems.FindPathNode(value);
  1213.    if assigned(wNode) then
  1214.       SetCurrentNode(wNode)
  1215.    else
  1216.       raise exception.create('Unable to find Inspector Item');
  1217. end;
  1218.  
  1219. function TrmInspector.ParentPath(st: string): string;
  1220. var
  1221.    wstr : string;
  1222. begin
  1223.    wstr := '';
  1224.    if pos(sepchar, st) = 1 then
  1225.       delete(st, 1, 1);
  1226.    while pos(SepChar, st) > 0 do
  1227.    begin
  1228.       wstr := wstr + copy(st, 1, pos(SepChar, st)-1);
  1229.       delete(st, 1, pos(sepchar, st));
  1230.    end;
  1231.    result := sepchar+wstr;
  1232. end;
  1233.  
  1234. procedure TrmInspector.ClearItems;
  1235. begin
  1236.    fItems.Items.Clear;
  1237.    fIndex := -1;
  1238.    fTopIndex := 0;
  1239.    Invalidate;  
  1240. end;
  1241.  
  1242. procedure TrmInspector.DeleteItem(Path: string);
  1243. var
  1244.    wNode : TrmTreeNonViewNode;
  1245. begin
  1246.   wNode := fItems.FindPathNode(Path);
  1247.   if assigned(wNode) then
  1248.   begin
  1249.      if Path = CurrentItemPath then
  1250.         fIndex := -1;
  1251.      wNode.Delete;
  1252.      Invalidate;
  1253.   end;
  1254. end;
  1255.  
  1256. procedure TrmInspector.DoNodeDelete(Sender: TObject;
  1257.   Node: TrmTreeNonViewNode);
  1258. var
  1259.    wItem : TrmCustomInspectorItem;
  1260. begin
  1261.    if assigned(Node) and assigned(Node.Data) then
  1262.    begin
  1263.       if Node = fCurrentNode then
  1264.       begin
  1265.          fCurrentNode := nil;
  1266.          if assigned(fOnIndexChanged) then
  1267.          try
  1268.             fOnIndexChanged(self);
  1269.          except
  1270.          end;
  1271.       end;
  1272.          
  1273.       wItem := TrmCustomInspectorItem(Node.Data);
  1274.       Node.Data := nil;
  1275.       wItem.free;
  1276.    end;
  1277. end;
  1278.  
  1279. procedure TrmInspector.DoComplexEdit(Sender: TObject);
  1280. begin
  1281.    if assigned(fOnComplexEdit) then
  1282.       fOnComplexEdit(fEditControl);
  1283. end;
  1284.  
  1285. procedure TrmInspector.SetCurrentNode(const Value: TrmTreeNonViewNode);
  1286. var
  1287.    wstr : string;
  1288.    wNode : TrmTreeNonViewNode;
  1289. begin
  1290.    wstr := fItems.NodePath(Value);
  1291.    if assigned(Value) and (wstr <> '') then
  1292.    begin
  1293.       fCurrentNode := Value;
  1294.       if not IsNodeVisible(fCurrentNode) then
  1295.       begin
  1296.          wNode := fCurrentNode;
  1297.          while wNode <> nil do
  1298.          begin
  1299.             wNode := wNode.parent;
  1300.             if wNode <> nil then
  1301.                wNode.Expanded := true; 
  1302.          end;
  1303.       end;
  1304.       ItemIndex := VisibileNodeIndex(fCurrentNode);
  1305.    end;
  1306. end;
  1307.  
  1308. function TrmInspector.IsItemVisible(Item: TrmCustomInspectorItem): Boolean;
  1309. begin
  1310.    if assigned(Item) and (Item.InspectorControl = self) then
  1311.       result := IsNodeVisible(Item.PathNode)
  1312.    else
  1313.       result := false;
  1314. end;
  1315.  
  1316. function TrmInspector.IsNodeVisible(Node: TrmTreeNonViewNode): boolean;
  1317. begin
  1318.    if assigned(Node) then
  1319.    begin
  1320.       Result := true;
  1321.       while result and (Node <> nil) do
  1322.       begin
  1323.          node := node.parent;
  1324.          if Node <> nil then
  1325.             result := result and node.Expanded;
  1326.       end;
  1327.    end
  1328.    else
  1329.       result := false;
  1330. end;
  1331.  
  1332. function TrmInspector.VisibileItemIndex(Item: TrmCustomInspectorItem): integer;
  1333. begin
  1334.    if assigned(Item) and (Item.InspectorControl = self) then
  1335.       result := VisibileNodeIndex(Item.PathNode)
  1336.    else
  1337.       result := -1;
  1338. end;
  1339.  
  1340. function TrmInspector.VisibileNodeIndex(Node: TrmTreeNonViewNode): integer;
  1341. var
  1342.   wNode: TrmTreeNonViewNode;
  1343. begin
  1344.    result := 0;
  1345.    wNode := fItems.Items.GetFirstNode;
  1346.    while (wNode <> nil) and (wNode <> Node) do
  1347.    begin
  1348.      inc(result);
  1349.      if wNode.Expanded then
  1350.        wNode := wNode.GetFirstChild
  1351.      else
  1352.      begin
  1353.        if (wNode.GetNextSibling = nil) then
  1354.        begin
  1355.          while (wNode <> nil) and (wNode.GetNextSibling = nil) do
  1356.            wNode := wNode.Parent;
  1357.          if wNode <> nil then
  1358.            wNode := wNode.GetNextSibling;
  1359.        end
  1360.        else
  1361.          wNode := wNode.GetNextSibling;
  1362.      end;
  1363.    end;
  1364.    if wNode = nil then
  1365.       result := -1;
  1366. end;
  1367.  
  1368. procedure TrmInspector.DoNodeTextChanged(Sender: TObject;
  1369.   Node: TrmTreeNonViewNode);
  1370. begin
  1371.    Invalidate;
  1372. end;
  1373.  
  1374. procedure TrmInspector.WndProc(var Message: TMessage);
  1375. begin
  1376.   inherited;
  1377.   if assigned(fOnWnd) then
  1378.      fOnWnd(message);
  1379. end;
  1380.  
  1381. initialization
  1382.    RegisterClass(TrmCustomInspectorItem);
  1383.  
  1384. end.
  1385.  
  1386.