summaryrefslogtreecommitdiff
path: root/apps/X11/VCL/TCustomTreeView.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'apps/X11/VCL/TCustomTreeView.cpp')
-rw-r--r--apps/X11/VCL/TCustomTreeView.cpp1169
1 files changed, 1169 insertions, 0 deletions
diff --git a/apps/X11/VCL/TCustomTreeView.cpp b/apps/X11/VCL/TCustomTreeView.cpp
new file mode 100644
index 0000000..18e4c29
--- /dev/null
+++ b/apps/X11/VCL/TCustomTreeView.cpp
@@ -0,0 +1,1169 @@
+#include <TCustomTreeView.h>
+#include <TTreeNodes.h>
+
+TCustomTreeView::TCustomTreeView(TComponent *AOwner) :
+ TWinControl(AOwner),
+ Items(this, &TCustomTreeView::getItems, &TCustomTreeView::SetTreeNodes),
+ Images(this, &TCustomTreeView::getImages, &TCustomTreeView::SetImages),
+ StateImages(this, &TCustomTreeView::getStateImages, &TCustomTreeView::SetStateImages),
+ Selected(this, &TCustomTreeView::GetSelection, &TCustomTreeView::SetSelection) {
+ init(AOwner);
+}
+
+
+TCustomTreeView::TCustomTreeView(GtkWidget *parent) :
+ TWinControl(parent),
+ Items(this, &TCustomTreeView::getItems, &TCustomTreeView::SetTreeNodes),
+ Images(this, &TCustomTreeView::getImages, &TCustomTreeView::SetImages),
+ StateImages(this, &TCustomTreeView::getStateImages, &TCustomTreeView::SetStateImages),
+ Selected(this, &TCustomTreeView::GetSelection, &TCustomTreeView::SetSelection) {
+ nativeControl = gtk_tree_new();
+/*
+ gtk_widget_ref (nativeControl);
+ gtk_object_set_data_full (GTK_OBJECT (InstallMgrApp), "LocalTree", LocalTree,
+ (GtkDestroyNotify) gtk_widget_unref);
+*/
+ gtk_widget_show (nativeControl);
+ gtk_container_add (GTK_CONTAINER (parent), nativeControl);
+ init(0);
+}
+
+TCustomTreeView::~TCustomTreeView() {
+}
+
+void TCustomTreeView::init(TComponent *AOwner) {
+/*
+ ControlStyle := ControlStyle - [csCaptureMouse] + [csDisplayDragImage, csReflector];
+ Width := 121;
+ Height := 97;
+ TabStop := True;
+ ParentColor := False;
+ FCanvas := TControlCanvas.Create;
+ TControlCanvas(FCanvas).Control := Self;
+*/
+// FTreeNodes := TTreeNodes.Create(Self);
+ FTreeNodes = new TTreeNodes(this);
+/*
+ FBorderStyle := bsSingle;
+ FShowButtons := True;
+ FShowRoot := True;
+ FShowLines := True;
+ FHideSelection := True;
+ FDragImage := TDragImageList.CreateSize(32, 32);
+ FSaveIndent := -1;
+ FChangeTimer := TTimer.Create(Self);
+ FChangeTimer.Enabled := False;
+ FChangeTimer.Interval := 0;
+ FChangeTimer.OnTimer := OnChangeTimer;
+ FToolTips := True;
+ FEditInstance := MakeObjectInstance(EditWndProc);
+ FImageChangeLink := TChangeLink.Create;
+ FImageChangeLink.OnChange := ImageListChange;
+ FStateChangeLink := TChangeLink.Create;
+ FStateChangeLink.OnChange := ImageListChange;
+*/
+}
+
+
+/*
+procedure TCustomTreeView.SetTreeNodes(Value: TTreeNodes);
+begin
+ Items.Assign(Value);
+end;
+*/
+
+void TCustomTreeView::SetTreeNodes(TTreeNodes* Value) {
+// Items->Assign(Value);
+}
+
+/*
+procedure TCustomTreeView.GetSelectedIndex(Node: TTreeNode);
+begin
+ if Assigned(FOnGetSelectedIndex) then FOnGetSelectedIndex(Self, Node);
+end;
+
+TTreeNode *TCustomTreeView::GetSelected() {
+}
+
+*/
+
+/*
+function TCustomTreeView.GetSelection: TTreeNode;
+begin
+ if HandleAllocated then
+ begin
+ if FRightClickSelect and Assigned(FRClickNode) then
+ Result := FRClickNode
+ else
+ Result := Items.GetNode(TreeView_GetSelection(Handle));
+ end
+ else Result := nil;
+end;
+
+procedure TCustomTreeView.SetSelection(Value: TTreeNode);
+begin
+ if Value <> nil then Value.Selected := True
+ else TreeView_SelectItem(Handle, nil);
+end;
+*/
+
+TTreeNode *TCustomTreeView::GetSelection() {
+ GList *selected_nodes = GTK_TREE_SELECTION (nativeControl);
+ selected_nodes = g_list_first(selected_nodes);
+ return (selected_nodes) ? Items->GetNode(GTK_TREE_ITEM(selected_nodes->data)) : 0;
+}
+
+void TCustomTreeView::SetSelection(TTreeNode *node) {
+}
+
+
+/*
+procedure TCustomTreeView.SetImages(Value: TCustomImageList);
+begin
+ if Images <> nil then
+ Images.UnRegisterChanges(FImageChangeLink);
+ FImages := Value;
+ if Images <> nil then
+ begin
+ Images.RegisterChanges(FImageChangeLink);
+ Images.FreeNotification(Self);
+ SetImageList(Images.Handle, TVSIL_NORMAL)
+ end
+ else SetImageList(0, TVSIL_NORMAL);
+end;
+
+procedure TCustomTreeView.SetStateImages(Value: TCustomImageList);
+begin
+ if StateImages <> nil then
+ StateImages.UnRegisterChanges(FStateChangeLink);
+ FStateImages := Value;
+ if StateImages <> nil then
+ begin
+ StateImages.RegisterChanges(FStateChangeLink);
+ StateImages.FreeNotification(Self);
+ SetImageList(StateImages.Handle, TVSIL_STATE)
+ end
+ else SetImageList(0, TVSIL_STATE);
+end;
+*/
+
+void TCustomTreeView::SetImages(TCustomImageList *images) {
+ FImages = images;
+}
+
+void TCustomTreeView::SetStateImages(TCustomImageList *images) {
+ FStateImages = images;
+}
+
+
+/*
+{ TCustomTreeView }
+destructor TCustomTreeView.Destroy;
+begin
+ Items.Free;
+ FChangeTimer.Free;
+ FSaveItems.Free;
+ FDragImage.Free;
+ FMemStream.Free;
+ FreeObjectInstance(FEditInstance);
+ FImageChangeLink.Free;
+ FStateChangeLink.Free;
+ FCanvas.Free;
+ inherited Destroy;
+end;
+
+procedure TCustomTreeView.CreateParams(var Params: TCreateParams);
+const
+ BorderStyles: array[TBorderStyle] of DWORD = (0, WS_BORDER);
+ LineStyles: array[Boolean] of DWORD = (0, TVS_HASLINES);
+ RootStyles: array[Boolean] of DWORD = (0, TVS_LINESATROOT);
+ ButtonStyles: array[Boolean] of DWORD = (0, TVS_HASBUTTONS);
+ EditStyles: array[Boolean] of DWORD = (TVS_EDITLABELS, 0);
+ HideSelections: array[Boolean] of DWORD = (TVS_SHOWSELALWAYS, 0);
+ DragStyles: array[TDragMode] of DWORD = (TVS_DISABLEDRAGDROP, 0);
+ RTLStyles: array[Boolean] of DWORD = (0, TVS_RTLREADING);
+ ToolTipStyles: array[Boolean] of DWORD = (TVS_NOTOOLTIPS, 0);
+ AutoExpandStyles: array[Boolean] of DWORD = (0, TVS_SINGLEEXPAND);
+ HotTrackStyles: array[Boolean] of DWORD = (0, TVS_TRACKSELECT);
+ RowSelectStyles: array[Boolean] of DWORD = (0, TVS_FULLROWSELECT);
+begin
+ InitCommonControl(ICC_TREEVIEW_CLASSES);
+ inherited CreateParams(Params);
+ CreateSubClass(Params, WC_TREEVIEW);
+ with Params do
+ begin
+ Style := Style or LineStyles[FShowLines] or BorderStyles[FBorderStyle] or
+ RootStyles[FShowRoot] or ButtonStyles[FShowButtons] or
+ EditStyles[FReadOnly] or HideSelections[FHideSelection] or
+ DragStyles[DragMode] or RTLStyles[UseRightToLeftReading] or
+ ToolTipStyles[FToolTips] or AutoExpandStyles[FAutoExpand] or
+ HotTrackStyles[FHotTrack] or RowSelectStyles[FRowSelect];
+ if Ctl3D and NewStyleControls and (FBorderStyle = bsSingle) then
+ begin
+ Style := Style and not WS_BORDER;
+ ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
+ end;
+ WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
+ end;
+end;
+
+procedure TCustomTreeView.CreateWnd;
+begin
+ FStateChanging := False;
+ inherited CreateWnd;
+ TreeView_SetBkColor(Handle, ColorToRGB(Color));
+ TreeView_SetTextColor(Handle, ColorToRGB(Font.Color));
+ if FMemStream <> nil then
+ begin
+ Items.ReadData(FMemStream);
+ FMemStream.Destroy;
+ FMemStream := nil;
+ SetTopItem(Items.GetNodeFromIndex(FSaveTopIndex));
+ FSaveTopIndex := 0;
+ SetSelection(Items.GetNodeFromIndex(FSaveIndex));
+ FSaveIndex := 0;
+ end;
+ if FSaveIndent <> -1 then Indent := FSaveIndent;
+ if (Images <> nil) and Images.HandleAllocated then
+ SetImageList(Images.Handle, TVSIL_NORMAL);
+ if (StateImages <> nil) and StateImages.HandleAllocated then
+ SetImageList(StateImages.Handle, TVSIL_STATE);
+end;
+
+procedure TCustomTreeView.DestroyWnd;
+var
+ Node: TTreeNode;
+begin
+ FStateChanging := True;
+ if Items.Count > 0 then
+ begin
+ FMemStream := TMemoryStream.Create;
+ Items.WriteData(FMemStream);
+ FMemStream.Position := 0;
+ Node := GetTopItem;
+ if Node <> nil then FSaveTopIndex := Node.AbsoluteIndex;
+ Node := Selected;
+ if Node <> nil then FSaveIndex := Node.AbsoluteIndex;
+ end;
+ FSaveIndent := Indent;
+ inherited DestroyWnd;
+end;
+
+procedure TCustomTreeView.EditWndProc(var Message: TMessage);
+begin
+ try
+ with Message do
+ begin
+ case Msg of
+ WM_KEYDOWN,
+ WM_SYSKEYDOWN: if DoKeyDown(TWMKey(Message)) then Exit;
+ WM_CHAR: if DoKeyPress(TWMKey(Message)) then Exit;
+ WM_KEYUP,
+ WM_SYSKEYUP: if DoKeyUp(TWMKey(Message)) then Exit;
+ CN_KEYDOWN,
+ CN_CHAR, CN_SYSKEYDOWN,
+ CN_SYSCHAR:
+ begin
+ WndProc(Message);
+ Exit;
+ end;
+ end;
+ Result := CallWindowProc(FDefEditProc, FEditHandle, Msg, WParam, LParam);
+ end;
+ except
+ Application.HandleException(Self);
+ end;
+end;
+
+procedure TCustomTreeView.CMColorChanged(var Message: TMessage);
+begin
+ inherited;
+ RecreateWnd;
+end;
+
+procedure TCustomTreeView.CMCtl3DChanged(var Message: TMessage);
+begin
+ inherited;
+ if FBorderStyle = bsSingle then RecreateWnd;
+end;
+
+procedure TCustomTreeView.CMFontChanged(var Message: TMessage);
+begin
+ inherited;
+ TreeView_SetTextColor(Handle, ColorToRGB(Font.Color));
+end;
+
+procedure TCustomTreeView.CMSysColorChange(var Message: TMessage);
+begin
+ inherited;
+ if not (csLoading in ComponentState) then
+ begin
+ Message.Msg := WM_SYSCOLORCHANGE;
+ DefaultHandler(Message);
+ end;
+end;
+
+function TCustomTreeView.AlphaSort: Boolean;
+var
+ Node: TTreeNode;
+begin
+ if HandleAllocated then
+ begin
+ Result := CustomSort(nil, 0);
+ Node := FTreeNodes.GetFirstNode;
+ while Node <> nil do
+ begin
+ if Node.HasChildren then Node.AlphaSort;
+ Node := Node.GetNext;
+ end;
+ end
+ else
+ Result := False;
+end;
+
+function TCustomTreeView.CustomSort(SortProc: TTVCompare; Data: Longint): Boolean;
+var
+ SortCB: TTVSortCB;
+ Node: TTreeNode;
+begin
+ Result := False;
+ if HandleAllocated then
+ begin
+ with SortCB do
+ begin
+ if not Assigned(SortProc) then lpfnCompare := @DefaultTreeViewSort
+ else lpfnCompare := SortProc;
+ hParent := TVI_ROOT;
+ lParam := Data;
+ Result := TreeView_SortChildrenCB(Handle, SortCB, 0);
+ end;
+ Node := FTreeNodes.GetFirstNode;
+ while Node <> nil do
+ begin
+ if Node.HasChildren then Node.CustomSort(SortProc, Data);
+ Node := Node.GetNext;
+ end;
+ Items.ClearCache;
+ end;
+end;
+
+procedure TCustomTreeView.SetAutoExpand(Value: Boolean);
+begin
+ if FAutoExpand <> Value then
+ begin
+ FAutoExpand := Value;
+ SetComCtlStyle(Self, TVS_SINGLEEXPAND, Value);
+ end;
+end;
+
+procedure TCustomTreeView.SetHotTrack(Value: Boolean);
+begin
+ if FHotTrack <> Value then
+ begin
+ FHotTrack := Value;
+ SetComCtlStyle(Self, TVS_TRACKSELECT, Value);
+ end;
+end;
+
+procedure TCustomTreeView.SetRowSelect(Value: Boolean);
+begin
+ if FRowSelect <> Value then
+ begin
+ FRowSelect := Value;
+ SetComCtlStyle(Self, TVS_FULLROWSELECT, Value);
+ end;
+end;
+
+procedure TCustomTreeView.SetToolTips(Value: Boolean);
+begin
+ if FToolTips <> Value then
+ begin
+ FToolTips := Value;
+ SetComCtlStyle(Self, TVS_NOTOOLTIPS, not Value);
+ end;
+end;
+
+procedure TCustomTreeView.SetSortType(Value: TSortType);
+begin
+ if SortType <> Value then
+ begin
+ FSortType := Value;
+ if ((SortType in [stData, stBoth]) and Assigned(OnCompare)) or
+ (SortType in [stText, stBoth]) then
+ AlphaSort;
+ end;
+end;
+
+procedure TCustomTreeView.SetBorderStyle(Value: TBorderStyle);
+begin
+ if BorderStyle <> Value then
+ begin
+ FBorderStyle := Value;
+ RecreateWnd;
+ end;
+end;
+
+procedure TCustomTreeView.SetDragMode(Value: TDragMode);
+begin
+ if Value <> DragMode then
+ SetComCtlStyle(Self, TVS_DISABLEDRAGDROP, Value = dmManual);
+ inherited;
+end;
+
+procedure TCustomTreeView.SetButtonStyle(Value: Boolean);
+begin
+ if ShowButtons <> Value then
+ begin
+ FShowButtons := Value;
+ SetComCtlStyle(Self, TVS_HASBUTTONS, Value);
+ end;
+end;
+
+procedure TCustomTreeView.SetLineStyle(Value: Boolean);
+begin
+ if ShowLines <> Value then
+ begin
+ FShowLines := Value;
+ SetComCtlStyle(Self, TVS_HASLINES, Value);
+ end;
+end;
+
+procedure TCustomTreeView.SetRootStyle(Value: Boolean);
+begin
+ if ShowRoot <> Value then
+ begin
+ FShowRoot := Value;
+ SetComCtlStyle(Self, TVS_LINESATROOT, Value);
+ end;
+end;
+
+procedure TCustomTreeView.SetReadOnly(Value: Boolean);
+begin
+ if ReadOnly <> Value then
+ begin
+ FReadOnly := Value;
+ SetComCtlStyle(Self, TVS_EDITLABELS, not Value);
+ end;
+end;
+
+procedure TCustomTreeView.SetHideSelection(Value: Boolean);
+begin
+ if HideSelection <> Value then
+ begin
+ FHideSelection := Value;
+ SetComCtlStyle(Self, TVS_SHOWSELALWAYS, not Value);
+ Invalidate;
+ end;
+end;
+
+function TCustomTreeView.GetNodeAt(X, Y: Integer): TTreeNode;
+var
+ HitTest: TTVHitTestInfo;
+begin
+ with HitTest do
+ begin
+ pt.X := X;
+ pt.Y := Y;
+ if TreeView_HitTest(Handle, HitTest) <> nil then
+ Result := Items.GetNode(HitTest.hItem)
+ else Result := nil;
+ end;
+end;
+
+function TCustomTreeView.GetHitTestInfoAt(X, Y: Integer): THitTests;
+var
+ HitTest: TTVHitTestInfo;
+begin
+ Result := [];
+ with HitTest do
+ begin
+ pt.X := X;
+ pt.Y := Y;
+ TreeView_HitTest(Handle, HitTest);
+ if (flags and TVHT_ABOVE) <> 0 then Include(Result, htAbove);
+ if (flags and TVHT_BELOW) <> 0 then Include(Result, htBelow);
+ if (flags and TVHT_NOWHERE) <> 0 then Include(Result, htNowhere);
+ if (flags and TVHT_ONITEM) = TVHT_ONITEM then
+ Include(Result, htOnItem)
+ else
+ begin
+ if (flags and TVHT_ONITEM) <> 0 then Include(Result, htOnItem);
+ if (flags and TVHT_ONITEMICON) <> 0 then Include(Result, htOnIcon);
+ if (flags and TVHT_ONITEMLABEL) <> 0 then Include(Result, htOnLabel);
+ if (flags and TVHT_ONITEMSTATEICON) <> 0 then Include(Result, htOnStateIcon);
+ end;
+ if (flags and TVHT_ONITEMBUTTON) <> 0 then Include(Result, htOnButton);
+ if (flags and TVHT_ONITEMINDENT) <> 0 then Include(Result, htOnIndent);
+ if (flags and TVHT_ONITEMRIGHT) <> 0 then Include(Result, htOnRight);
+ if (flags and TVHT_TOLEFT) <> 0 then Include(Result, htToLeft);
+ if (flags and TVHT_TORIGHT) <> 0 then Include(Result, htToRight);
+ end;
+end;
+
+procedure TCustomTreeView.SetIndent(Value: Integer);
+begin
+ if Value <> Indent then TreeView_SetIndent(Handle, Value);
+end;
+
+function TCustomTreeView.GetIndent: Integer;
+begin
+ Result := TreeView_GetIndent(Handle)
+end;
+
+procedure TCustomTreeView.FullExpand;
+var
+ Node: TTreeNode;
+begin
+ Node := Items.GetFirstNode;
+ while Node <> nil do
+ begin
+ Node.Expand(True);
+ Node := Node.GetNextSibling;
+ end;
+end;
+
+procedure TCustomTreeView.FullCollapse;
+var
+ Node: TTreeNode;
+begin
+ Node := Items.GetFirstNode;
+ while Node <> nil do
+ begin
+ Node.Collapse(True);
+ Node := Node.GetNextSibling;
+ end;
+end;
+
+procedure TCustomTreeView.Loaded;
+begin
+ inherited Loaded;
+ if csDesigning in ComponentState then FullExpand;
+end;
+
+function TCustomTreeView.GetTopItem: TTreeNode;
+begin
+ if HandleAllocated then
+ Result := Items.GetNode(TreeView_GetFirstVisible(Handle))
+ else Result := nil;
+end;
+
+procedure TCustomTreeView.SetTopItem(Value: TTreeNode);
+begin
+ if HandleAllocated and (Value <> nil) then
+ TreeView_SelectSetFirstVisible(Handle, Value.ItemId);
+end;
+
+procedure TCustomTreeView.OnChangeTimer(Sender: TObject);
+begin
+ FChangeTimer.Enabled := False;
+ Change(TTreeNode(FChangeTimer.Tag));
+end;
+
+procedure TCustomTreeView.SetChangeDelay(Value: Integer);
+begin
+ FChangeTimer.Interval := Value;
+end;
+
+function TCustomTreeView.GetChangeDelay: Integer;
+begin
+ Result := FChangeTimer.Interval;
+end;
+
+function TCustomTreeView.GetDropTarget: TTreeNode;
+begin
+ if HandleAllocated then
+ begin
+ Result := Items.GetNode(TreeView_GetDropHilite(Handle));
+ if Result = nil then Result := FLastDropTarget;
+ end
+ else Result := nil;
+end;
+
+procedure TCustomTreeView.SetDropTarget(Value: TTreeNode);
+begin
+ if HandleAllocated then
+ if Value <> nil then Value.DropTarget := True
+ else TreeView_SelectDropTarget(Handle, nil);
+end;
+
+function TCustomTreeView.GetNodeFromItem(const Item: TTVItem): TTreeNode;
+begin
+ with Item do
+ if (state and TVIF_PARAM) <> 0 then Result := Pointer(lParam)
+ else Result := Items.GetNode(hItem);
+end;
+
+function TCustomTreeView.IsEditing: Boolean;
+var
+ ControlHand: HWnd;
+begin
+ ControlHand := TreeView_GetEditControl(Handle);
+ Result := (ControlHand <> 0) and IsWindowVisible(ControlHand);
+end;
+
+procedure TCustomTreeView.CNNotify(var Message: TWMNotify);
+var
+ Node: TTreeNode;
+ MousePos: TPoint;
+ R: TRect;
+ DefaultDraw: Boolean;
+ TmpItem: TTVItem;
+begin
+ with Message do
+ case NMHdr^.code of
+ NM_CUSTOMDRAW:
+ with PNMCustomDraw(NMHdr)^ do
+ begin
+ Result := CDRF_DODEFAULT;
+ if dwDrawStage = CDDS_PREPAINT then
+ begin
+ if IsCustomDrawn(dtControl, cdPrePaint) then
+ begin
+ FCanvas.Handle := hdc;
+ FCanvas.Font := Font;
+ FCanvas.Brush := Brush;
+ R := ClientRect;
+ DefaultDraw := CustomDraw(R, cdPrePaint);
+ FCanvas.Handle := 0;
+ if not DefaultDraw then
+ begin
+ Result := CDRF_SKIPDEFAULT;
+ Exit;
+ end;
+ end;
+ if IsCustomDrawn(dtControl, cdPostPaint) then
+ Result := CDRF_NOTIFYPOSTPAINT;
+ if IsCustomDrawn(dtItem, cdPrePaint) then
+ Result := Result or CDRF_NOTIFYITEMDRAW else
+ Result := Result or CDRF_DODEFAULT;
+ end
+ else if dwDrawStage = CDDS_ITEMPREPAINT then
+ begin
+ FillChar(TmpItem, SizeOf(TmpItem), 0);
+ TmpItem.hItem := HTREEITEM(dwItemSpec);
+ Node := GetNodeFromItem(TmpItem);
+ if Node <> nil then
+ begin
+ FCanvas.Handle := hdc;
+ FCanvas.Font := Font;
+ FCanvas.Brush := Brush;
+ { Unlike the list view, the tree view doesn't override the text
+ foreground and background colors of selected items. }
+ if uItemState and CDIS_SELECTED <> 0 then
+ begin
+ FCanvas.Font.Color := clHighlightText;
+ FCanvas.Brush.Color := clHighlight;
+ end;
+ FCanvas.Font.OnChange := CanvasChanged;
+ FCanvas.Brush.OnChange := CanvasChanged;
+ DefaultDraw := CustomDrawItem(Node,
+ TCustomDrawState(Word(uItemState)), cdPrePaint);
+ if not DefaultDraw then
+ Result := Result or CDRF_SKIPDEFAULT
+ else if FCanvasChanged then
+ begin
+ FCanvasChanged := False;
+ FCanvas.Font.OnChange := nil;
+ FCanvas.Brush.OnChange := nil;
+ with PNMTVCustomDraw(NMHdr)^ do
+ begin
+ clrText := ColorToRGB(FCanvas.Font.Color);
+ clrTextBk := ColorToRGB(FCanvas.Brush.Color);
+ SelectObject(hdc, FCanvas.Font.Handle);
+ Result := Result or CDRF_NEWFONT;
+ end;
+ end;
+ FCanvas.Handle := 0;
+ if IsCustomDrawn(dtItem, cdPostPaint) then
+ Result := Result or CDRF_NOTIFYPOSTPAINT;
+ end;
+ end;
+ end;
+ TVN_BEGINDRAG:
+ begin
+ FDragged := True;
+ with PNMTreeView(NMHdr)^ do
+ FDragNode := GetNodeFromItem(ItemNew);
+ end;
+ TVN_BEGINLABELEDIT:
+ begin
+ with PTVDispInfo(NMHdr)^ do
+ if Dragging or not CanEdit(GetNodeFromItem(item)) then
+ Result := 1;
+ if Result = 0 then
+ begin
+ FEditHandle := TreeView_GetEditControl(Handle);
+ FDefEditProc := Pointer(GetWindowLong(FEditHandle, GWL_WNDPROC));
+ SetWindowLong(FEditHandle, GWL_WNDPROC, LongInt(FEditInstance));
+ end;
+ end;
+ TVN_ENDLABELEDIT: Edit(PTVDispInfo(NMHdr)^.item);
+ TVN_ITEMEXPANDING:
+ if not FManualNotify then
+ begin
+ with PNMTreeView(NMHdr)^ do
+ begin
+ Node := GetNodeFromItem(ItemNew);
+ if (action = TVE_EXPAND) and not CanExpand(Node) then
+ Result := 1
+ else if (action = TVE_COLLAPSE) and
+ not CanCollapse(Node) then Result := 1;
+ end;
+ end;
+ TVN_ITEMEXPANDED:
+ if not FManualNotify then
+ begin
+ with PNMTreeView(NMHdr)^ do
+ begin
+ Node := GetNodeFromItem(itemNew);
+ if (action = TVE_EXPAND) then Expand(Node)
+ else if (action = TVE_COLLAPSE) then Collapse(Node);
+ end;
+ end;
+ TVN_SELCHANGINGA, TVN_SELCHANGINGW:
+ if not CanChange(GetNodeFromItem(PNMTreeView(NMHdr)^.itemNew)) then
+ Result := 1;
+ TVN_SELCHANGEDA, TVN_SELCHANGEDW:
+ with PNMTreeView(NMHdr)^ do
+ if FChangeTimer.Interval > 0 then
+ with FChangeTimer do
+ begin
+ Enabled := False;
+ Tag := Integer(GetNodeFromItem(itemNew));
+ Enabled := True;
+ end
+ else
+ Change(GetNodeFromItem(itemNew));
+ TVN_DELETEITEM:
+ begin
+ Node := GetNodeFromItem(PNMTreeView(NMHdr)^.itemOld);
+ if Node <> nil then
+ begin
+ Node.FItemId := nil;
+ FChangeTimer.Enabled := False;
+ if FStateChanging then Node.Delete
+ else Items.Delete(Node);
+ end;
+ end;
+ TVN_SETDISPINFO:
+ with PTVDispInfo(NMHdr)^ do
+ begin
+ Node := GetNodeFromItem(item);
+ if (Node <> nil) and ((item.mask and TVIF_TEXT) <> 0) then
+ Node.Text := item.pszText;
+ end;
+ TVN_GETDISPINFO:
+ with PTVDispInfo(NMHdr)^ do
+ begin
+ Node := GetNodeFromItem(item);
+ if Node <> nil then
+ begin
+ if (item.mask and TVIF_TEXT) <> 0 then
+ StrLCopy(item.pszText, PChar(Node.Text), item.cchTextMax);
+ if (item.mask and TVIF_IMAGE) <> 0 then
+ begin
+ GetImageIndex(Node);
+ item.iImage := Node.ImageIndex;
+ end;
+ if (item.mask and TVIF_SELECTEDIMAGE) <> 0 then
+ begin
+ GetSelectedIndex(Node);
+ item.iSelectedImage := Node.SelectedIndex;
+ end;
+ end;
+ end;
+ NM_RCLICK:
+ begin
+ if RightClickSelect then
+ begin
+ GetCursorPos(MousePos);
+ with PointToSmallPoint(ScreenToClient(MousePos)) do
+ begin
+ FRClickNode := GetNodeAt(X, Y);
+ Perform(WM_RBUTTONUP, 0, MakeLong(X, Y));
+ end;
+ end
+ else FRClickNode := Pointer(1);
+ end;
+ end;
+end;
+
+function TCustomTreeView.GetDragImages: TDragImageList;
+begin
+ if FDragImage.Count > 0 then
+ Result := FDragImage else
+ Result := nil;
+end;
+
+procedure TCustomTreeView.WndProc(var Message: TMessage);
+begin
+ if not (csDesigning in ComponentState) and ((Message.Msg = WM_LBUTTONDOWN) or
+ (Message.Msg = WM_LBUTTONDBLCLK)) and not Dragging and
+ (DragMode = dmAutomatic) and (DragKind = dkDrag) then
+ begin
+ if not IsControlMouseMsg(TWMMouse(Message)) then
+ begin
+ ControlState := ControlState + [csLButtonDown];
+ Dispatch(Message);
+ end;
+ end
+ else inherited WndProc(Message);
+end;
+
+procedure TCustomTreeView.DoStartDrag(var DragObject: TDragObject);
+var
+ ImageHandle: HImageList;
+ DragNode: TTreeNode;
+ P: TPoint;
+begin
+ inherited DoStartDrag(DragObject);
+ DragNode := FDragNode;
+ FLastDropTarget := nil;
+ FDragNode := nil;
+ if DragNode = nil then
+ begin
+ GetCursorPos(P);
+ with ScreenToClient(P) do DragNode := GetNodeAt(X, Y);
+ end;
+ if DragNode <> nil then
+ begin
+ ImageHandle := TreeView_CreateDragImage(Handle, DragNode.ItemId);
+ if ImageHandle <> 0 then
+ with FDragImage do
+ begin
+ Handle := ImageHandle;
+ SetDragImage(0, 2, 2);
+ end;
+ end;
+end;
+
+procedure TCustomTreeView.DoEndDrag(Target: TObject; X, Y: Integer);
+begin
+ inherited DoEndDrag(Target, X, Y);
+ FLastDropTarget := nil;
+end;
+
+procedure TCustomTreeView.CMDrag(var Message: TCMDrag);
+begin
+ inherited;
+ with Message, DragRec^ do
+ case DragMessage of
+ dmDragMove:
+ with ScreenToClient(Pos) do
+ DoDragOver(Source, X, Y, Message.Result <> 0);
+ dmDragLeave:
+ begin
+ TDragObject(Source).HideDragImage;
+ FLastDropTarget := DropTarget;
+ DropTarget := nil;
+ TDragObject(Source).ShowDragImage;
+ end;
+ dmDragDrop: FLastDropTarget := nil;
+ end;
+end;
+
+procedure TCustomTreeView.DoDragOver(Source: TDragObject; X, Y: Integer; CanDrop: Boolean);
+var
+ Node: TTreeNode;
+begin
+ Node := GetNodeAt(X, Y);
+ if (Node <> nil) and
+ ((Node <> DropTarget) or (Node = FLastDropTarget)) then
+ begin
+ FLastDropTarget := nil;
+ TDragObject(Source).HideDragImage;
+ Node.DropTarget := True;
+ TDragObject(Source).ShowDragImage;
+ end;
+end;
+
+procedure TCustomTreeView.GetImageIndex(Node: TTreeNode);
+begin
+ if Assigned(FOnGetImageIndex) then FOnGetImageIndex(Self, Node);
+end;
+
+function TCustomTreeView.CanChange(Node: TTreeNode): Boolean;
+begin
+ Result := True;
+ if Assigned(FOnChanging) then FOnChanging(Self, Node, Result);
+end;
+
+procedure TCustomTreeView.Change(Node: TTreeNode);
+begin
+ if Assigned(FOnChange) then FOnChange(Self, Node);
+end;
+
+procedure TCustomTreeView.Delete(Node: TTreeNode);
+begin
+ if Assigned(FOnDeletion) then FOnDeletion(Self, Node);
+end;
+
+procedure TCustomTreeView.Expand(Node: TTreeNode);
+begin
+ if Assigned(FOnExpanded) then FOnExpanded(Self, Node);
+end;
+
+function TCustomTreeView.CanExpand(Node: TTreeNode): Boolean;
+begin
+ Result := True;
+ if Assigned(FOnExpanding) then FOnExpanding(Self, Node, Result);
+end;
+
+procedure TCustomTreeView.Collapse(Node: TTreeNode);
+begin
+ if Assigned(FOnCollapsed) then FOnCollapsed(Self, Node);
+end;
+
+function TCustomTreeView.CanCollapse(Node: TTreeNode): Boolean;
+begin
+ Result := True;
+ if Assigned(FOnCollapsing) then FOnCollapsing(Self, Node, Result);
+end;
+
+function TCustomTreeView.CanEdit(Node: TTreeNode): Boolean;
+begin
+ Result := True;
+ if Assigned(FOnEditing) then FOnEditing(Self, Node, Result);
+end;
+
+procedure TCustomTreeView.Edit(const Item: TTVItem);
+var
+ S: string;
+ Node: TTreeNode;
+begin
+ with Item do
+ if pszText <> nil then
+ begin
+ S := pszText;
+ Node := GetNodeFromItem(Item);
+ if Assigned(FOnEdited) then FOnEdited(Self, Node, S);
+ if Node <> nil then Node.Text := S;
+ end;
+end;
+
+function TCustomTreeView.CreateNode: TTreeNode;
+begin
+ Result := TTreeNode.Create(Items);
+end;
+
+procedure TCustomTreeView.SetImageList(Value: HImageList; Flags: Integer);
+begin
+ if HandleAllocated then TreeView_SetImageList(Handle, Value, Flags);
+end;
+
+procedure TCustomTreeView.ImageListChange(Sender: TObject);
+var
+ ImageHandle: HImageList;
+begin
+ if HandleAllocated then
+ begin
+ if TCustomImageList(Sender).HandleAllocated then
+ ImageHandle := TCustomImageList(Sender).Handle
+ else
+ ImageHandle := 0;
+ if Sender = Images then
+ SetImageList(ImageHandle, TVSIL_NORMAL)
+ else if Sender = StateImages then
+ SetImageList(ImageHandle, TVSIL_STATE);
+ end;
+end;
+
+procedure TCustomTreeView.Notification(AComponent: TComponent;
+ Operation: TOperation);
+begin
+ inherited Notification(AComponent, Operation);
+ if Operation = opRemove then
+ begin
+ if AComponent = Images then Images := nil;
+ if AComponent = StateImages then StateImages := nil;
+ end;
+end;
+
+procedure TCustomTreeView.LoadFromFile(const FileName: string);
+var
+ Stream: TStream;
+begin
+ Stream := TFileStream.Create(FileName, fmOpenRead);
+ try
+ LoadFromStream(Stream);
+ finally
+ Stream.Free;
+ end;
+end;
+
+procedure TCustomTreeView.LoadFromStream(Stream: TStream);
+begin
+ with TTreeStrings.Create(Items) do
+ try
+ LoadTreeFromStream(Stream);
+ finally
+ Free;
+ end;
+end;
+
+procedure TCustomTreeView.SaveToFile(const FileName: string);
+var
+ Stream: TStream;
+begin
+ Stream := TFileStream.Create(FileName, fmCreate);
+ try
+ SaveToStream(Stream);
+ finally
+ Stream.Free;
+ end;
+end;
+
+procedure TCustomTreeView.SaveToStream(Stream: TStream);
+begin
+ with TTreeStrings.Create(Items) do
+ try
+ SaveTreeToStream(Stream);
+ finally
+ Free;
+ end;
+end;
+
+procedure TCustomTreeView.WMRButtonDown(var Message: TWMRButtonDown);
+var
+ MousePos: TPoint;
+begin
+ FRClickNode := nil;
+ try
+ if not RightClickSelect then
+ begin
+ inherited;
+ if FRClickNode <> nil then
+ begin
+ GetCursorPos(MousePos);
+ with PointToSmallPoint(ScreenToClient(MousePos)) do
+ Perform(WM_RBUTTONUP, 0, MakeLong(X, Y));
+ end;
+ end
+ else DefaultHandler(Message);
+ finally
+ FRClickNode := nil;
+
+ end;
+end;
+
+procedure TCustomTreeView.WMRButtonUp(var Message: TWMRButtonUp);
+
+ procedure DoMouseDown(var Message: TWMMouse; Button: TMouseButton;
+ Shift: TShiftState);
+ begin
+ if not (csNoStdEvents in ControlStyle) then
+ with Message do
+ MouseDown(Button, KeysToShiftState(Keys) + Shift, XPos, YPos);
+ end;
+
+begin
+ if RightClickSelect then DoMouseDown(Message, mbRight, []);
+ inherited;
+end;
+
+procedure TCustomTreeView.WMLButtonDown(var Message: TWMLButtonDown);
+var
+ Node: TTreeNode;
+ MousePos: TPoint;
+begin
+ FDragged := False;
+ FDragNode := nil;
+ try
+ inherited;
+ if (DragMode = dmAutomatic) and (DragKind = dkDrag) then
+ begin
+ SetFocus;
+ if not FDragged then
+ begin
+ GetCursorPos(MousePos);
+ with PointToSmallPoint(ScreenToClient(MousePos)) do
+ Perform(WM_LBUTTONUP, 0, MakeLong(X, Y));
+ end
+ else begin
+ Node := GetNodeAt(Message.XPos, Message.YPos);
+ if Node <> nil then
+ begin
+ Node.Focused := True;
+ Node.Selected := True;
+ BeginDrag(False);
+ end;
+ end;
+ end;
+ finally
+ FDragNode := nil;
+ end;
+end;
+
+procedure TCustomTreeView.WMNotify(var Message: TWMNotify);
+var
+ Node: TTreeNode;
+ MaxTextLen: Integer;
+ Pt: TPoint;
+begin
+ with Message do
+ if NMHdr^.code = TTN_NEEDTEXTW then
+ begin
+ // Work around NT COMCTL32 problem with tool tips >= 80 characters
+ GetCursorPos(Pt);
+ Pt := ScreenToClient(Pt);
+ Node := GetNodeAt(Pt.X, Pt.Y);
+ if (Node = nil) or (Node.Text = '') or
+ (PToolTipTextW(NMHdr)^.uFlags and TTF_IDISHWND = 0) then Exit;
+ if (GetComCtlVersion >= ComCtlVersionIE4) and (Length(Node.Text) < 80) then
+ begin
+ inherited;
+ Exit;
+ end;
+ FWideText := Node.Text;
+ MaxTextLen := SizeOf(PToolTipTextW(NMHdr)^.szText) div SizeOf(WideChar);
+ if Length(FWideText) >= MaxTextLen then
+ SetLength(FWideText, MaxTextLen - 1);
+ PToolTipTextW(NMHdr)^.lpszText := PWideChar(FWideText);
+ FillChar(PToolTipTextW(NMHdr)^.szText, MaxTextLen, 0);
+ Move(Pointer(FWideText)^, PToolTipTextW(NMHdr)^.szText, Length(FWideText) * SizeOf(WideChar));
+ PToolTipTextW(NMHdr)^.hInst := 0;
+ SetWindowPos(NMHdr^.hwndFrom, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or
+ SWP_NOSIZE or SWP_NOMOVE or SWP_NOOWNERZORDER);
+ Result := 1;
+ end
+ else inherited;
+end;
+
+{ CustomDraw support }
+
+procedure TCustomTreeView.CanvasChanged;
+begin
+ FCanvasChanged := True;
+end;
+
+function TCustomTreeView.IsCustomDrawn(Target: TCustomDrawTarget;
+ Stage: TCustomDrawStage): Boolean;
+begin
+ { Tree view doesn't support erase notifications }
+ if Stage = cdPrePaint then
+ begin
+ if Target = dtItem then
+ Result := Assigned(FOnCustomDrawItem)
+ else if Target = dtControl then
+ Result := Assigned(FOnCustomDraw)
+ else
+ Result := False;
+ end
+ else
+ Result := False;
+end;
+
+function TCustomTreeView.CustomDraw(const ARect: TRect; Stage: TCustomDrawStage): Boolean;
+begin
+ Result := True;
+ if Assigned(FOnCustomDraw) then FOnCustomDraw(Self, ARect, Result);
+end;
+
+function TCustomTreeView.CustomDrawItem(Node: TTreeNode; State: TCustomDrawState;
+ Stage: TCustomDrawStage): Boolean;
+begin
+ Result := True;
+ if Assigned(FOnCustomDrawItem) then FOnCustomDrawItem(Self, Node, State, Result);
+end;
+
+*/