unit spkte_EditWindow; {$MODE Delphi} interface uses LCLIntf, LCLType, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, {DesignIntf, DesignEditors,} StdCtrls, ImgList, ComCtrls, ActnList, Menus, ComponentEditors, PropEdits, SpkToolbar, spkt_Tab, spkt_Pane, spkt_BaseItem, spkt_Buttons, spkt_Types, spkt_Checkboxes; type TCreateItemFunc = function(Pane : TSpkPane) : TSpkBaseItem; type { TfrmEditWindow } TfrmEditWindow = class(TForm) aAddCheckbox: TAction; aAddRadioButton: TAction; ilTreeImages_150: TImageList; ilActionImages_150: TImageList; ilActionImages_200: TImageList; ilTreeImages_200: TImageList; MenuItem1: TMenuItem; MenuItem2: TMenuItem; MenuItem3: TMenuItem; MenuItem4: TMenuItem; tvStructure: TTreeView; ilTreeImages: TImageList; tbToolBar: TToolBar; tbAddTab: TToolButton; ilActionImages: TImageList; tbRemoveTab: TToolButton; ToolButton3: TToolButton; tbAddPane: TToolButton; tbRemovePane: TToolButton; ActionList: TActionList; aAddTab: TAction; aRemoveTab: TAction; aAddPane: TAction; aRemovePane: TAction; ToolButton6: TToolButton; aMoveUp: TAction; aMoveDown: TAction; tbMoveUp: TToolButton; tbMoveDown: TToolButton; ToolButton9: TToolButton; tbAddItem: TToolButton; tbRemoveItem: TToolButton; pmAddItem: TPopupMenu; SpkLargeButton1: TMenuItem; aAddLargeButton: TAction; aRemoveItem: TAction; aAddSmallButton: TAction; SpkSmallButton1: TMenuItem; pmStructure: TPopupMenu; Addtab1: TMenuItem; Removetab1: TMenuItem; N1: TMenuItem; Addpane1: TMenuItem; Removepane1: TMenuItem; N2: TMenuItem; Additem1: TMenuItem; SpkLargeButton2: TMenuItem; SpkSmallButton2: TMenuItem; Removeitem1: TMenuItem; N3: TMenuItem; Moveup1: TMenuItem; Movedown1: TMenuItem; procedure tvStructureChange(Sender: TObject; Node: TTreeNode); procedure aAddTabExecute(Sender: TObject); procedure aRemoveTabExecute(Sender: TObject); procedure aAddPaneExecute(Sender: TObject); procedure aRemovePaneExecute(Sender: TObject); procedure aMoveUpExecute(Sender: TObject); procedure aMoveDownExecute(Sender: TObject); procedure FormShow(Sender: TObject); procedure aAddLargeButtonExecute(Sender: TObject); procedure aRemoveItemExecute(Sender: TObject); procedure aAddSmallButtonExecute(Sender: TObject); procedure aAddCheckboxExecute(Sender: TObject); procedure aAddRadioButtonExecute(Sender: TObject); procedure tvStructureDeletion(Sender:TObject; Node:TTreeNode); procedure tvStructureEdited(Sender: TObject; Node: TTreeNode; var S: string); procedure tvStructureKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState); procedure FormActivate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } protected FToolbar: TSpkToolbar; FDesigner: TComponentEditorDesigner; procedure CheckActionsAvailability; procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure AddItem(ItemClass: TSpkBaseItemClass); function GetItemCaption(Item: TSpkBaseItem): string; procedure SetItemCaption(Item: TSpkBaseItem; const Value: String); procedure DoRemoveTab; procedure DoRemovePane; procedure DoRemoveItem; function CheckValidTabNode(Node: TTreeNode): boolean; function CheckValidPaneNode(Node: TTreeNode): boolean; function CheckValidItemNode(Node: TTreeNode): boolean; procedure UpdatePPI; public { Public declarations } function ValidateTreeData: boolean; procedure BuildTreeData; procedure RefreshNames; procedure SetData(AToolbar: TSpkToolbar; ADesigner: TComponentEditorDesigner); property Toolbar: TSpkToolbar read FToolbar; end; var frmEditWindow: TfrmEditWindow; implementation {$R *.lfm} resourcestring RSCannotMoveAboveFirstElement = 'You can not move above the top of the first element!'; RSCannotMoveBeyondLastElement = 'You can not move beyond the last element!'; RSDamagedTreeStructure = 'Damaged tree structure!'; RSIncorrectFieldData = 'Incorrect data in the field!'; RSIncorrectObjectInTree = 'Incorrect object attached to the tree!'; RSNoObjectSelected = 'No object selected!'; RSNoObjectSelectedToMove = 'No object selected to move!'; { TfrmEditWindow } procedure TfrmEditWindow.aAddPaneExecute(Sender: TObject); var Obj: TObject; Node: TTreeNode; NewNode: TTreeNode; Tab: TSpkTab; Pane: TSpkPane; begin if (FToolbar = nil) or (FDesigner = nil) then exit; if FDesigner.PropertyEditorHook = nil then exit; Node := tvStructure.Selected; if Node = nil then raise Exception.Create('TfrmEditWindow.aAddPaneExecute: ' + RSNoObjectSelected); if Node.Data = nil then raise Exception.Create('TfrmEditWindow.aAddPaneExecute: ' + RSDamagedTreeStructure); Obj := TObject(Node.Data); if Obj is TSpkTab then begin Tab := TSpkTab(Obj); Pane := TSpkPane.Create(FToolbar.Owner); Pane.Parent := FToolbar; Pane.Name := FDesigner.CreateUniqueComponentName(Pane.ClassName); Tab.Panes.AddItem(Pane); NewNode := tvStructure.Items.AddChild(Node, Pane.Caption); NewNode.Data := Pane; NewNode.ImageIndex := 1; NewNode.SelectedIndex := 1; NewNode.Selected := true; CheckActionsAvailability; end else if Obj is TSpkPane then begin if not(CheckValidPaneNode(Node)) then raise Exception.Create('TfrmEditWindow.aAddPaneExecute: ' + RSDamagedTreeStructure); Tab := TSpkTab(Node.Parent.Data); Pane := TSpkPane.Create(FToolbar.Owner); Pane.Parent := FToolbar; Pane.Name := FDesigner.CreateUniqueComponentName(Pane.ClassName); Tab.Panes.AddItem(Pane); NewNode := tvStructure.Items.AddChild(Node.Parent, Pane.Caption); NewNode.Data := Pane; NewNode.ImageIndex := 1; NewNode.SelectedIndex := 1; NewNode.Selected := true; CheckActionsAvailability; end else if Obj is TSpkBaseItem then begin if not(CheckValidItemNode(Node)) then raise Exception.Create('TfrmEditWindow.aAddPaneExecute: ' + RSDamagedTreeStructure); Tab := TSpkTab(Node.Parent.Parent.Data); Pane := TSpkPane.Create(FToolbar.Owner); Pane.Parent := FToolbar; Pane.Name := FDesigner.CreateUniqueComponentName(Pane.ClassName); Tab.Panes.AddItem(Pane); NewNode := tvStructure.Items.AddChild(Node.Parent.Parent, Pane.Caption); NewNode.Data := Pane; NewNode.ImageIndex := 1; NewNode.SelectedIndex := 1; NewNode.Selected := true; CheckActionsAvailability; end else raise Exception.Create('TfrmEditWindow.aAddPaneExecute: ' + RSIncorrectObjectInTree); FDesigner.PropertyEditorHook.PersistentAdded(Pane,True); FDesigner.Modified; end; procedure TfrmEditWindow.aAddSmallButtonExecute(Sender: TObject); begin AddItem(TSpkSmallButton); end; procedure TfrmEditWindow.aAddLargeButtonExecute(Sender: TObject); begin AddItem(TSpkLargeButton); end; procedure TfrmEditWindow.aAddCheckboxExecute(Sender: TObject); begin AddItem(TSpkCheckbox); end; procedure TfrmEditWindow.aAddRadioButtonExecute(Sender: TObject); begin AddItem(TSpkRadioButton); end; procedure TfrmEditWindow.aAddTabExecute(Sender: TObject); var Node: TTreeNode; Tab: TSpkTab; begin if (FToolbar = nil) or (FDesigner = nil) then exit; if FDesigner.PropertyEditorHook = nil then exit; Tab := TSpkTab.Create(FToolbar.Owner); Tab.Parent := FToolbar; FToolbar.Tabs.AddItem(Tab); Tab.Name := FDesigner.CreateUniqueComponentName(Tab.ClassName); Node := tvStructure.Items.AddChild(nil, Tab.Caption); Node.Data := Tab; Node.ImageIndex := 0; Node.SelectedIndex := 0; Node.Selected := true; CheckActionsAvailability; FDesigner.PropertyEditorHook.PersistentAdded(Tab,True); FDesigner.Modified; end; procedure TfrmEditWindow.AddItem(ItemClass: TSpkBaseItemClass); var Node: TTreeNode; Obj: TObject; Pane: TSpkPane; Item: TSpkBaseItem; NewNode: TTreeNode; s: string; begin if (FToolbar = nil) or (FDesigner = nil) then exit; if FDesigner.PropertyEditorHook = nil then exit; Node := tvStructure.Selected; if Node = nil then raise Exception.Create('TfrmEditWindow.AddItem: ' + RSNoObjectSelected); if Node.Data = nil then raise Exception.Create('TfrmEditWindow.AddItem: ' + RSDamagedTreeStructure); Obj := TObject(Node.Data); if Obj is TSpkPane then begin Pane := TSpkPane(Obj); Item := ItemClass.Create(FToolbar.Owner); Item.Parent := FToolbar; Pane.Items.AddItem(Item); Item.Name := FDesigner.CreateUniqueComponentName(Item.ClassName); s := GetItemCaption(Item); NewNode := tvStructure.Items.AddChild(Node, s); NewNode.Data := Item; NewNode.Selected := true; CheckActionsAvailability; end else if Obj is TSpkBaseItem then begin if not CheckValidItemNode(Node) then raise Exception.Create('TfrmEditWindow.AddItem: ' + RSDamagedTreeStructure); Pane := TSpkPane(Node.Parent.Data); Item := ItemClass.Create(FToolbar.Owner); Item.Parent := FToolbar; Pane.Items.AddItem(Item); Item.Name := FDesigner.CreateUniqueComponentName(Item.ClassName); s := GetItemCaption(Item); NewNode := tvStructure.Items.AddChild(Node.Parent, s); NewNode.Data := Item; NewNode.Selected := true; CheckActionsAvailability; end else raise Exception.Create('TfrmEditWindow.AddItem: ' + RSIncorrectObjectInTree); if ItemClass = TSpkLargeButton then NewNode.ImageIndex := 2 else if ItemClass = TSpkSmallButton then NewNode.ImageIndex := 3 else if ItemClass = TSpkCheckbox then NewNode.ImageIndex := 4 else if ItemClass = TSpkRadioButton then NewNode.ImageIndex := 5 else raise Exception.Create('Item class not supported'); NewNode.SelectedIndex := NewNode.ImageIndex; FDesigner.PropertyEditorHook.PersistentAdded(Item,True); FDesigner.Modified; end; procedure TfrmEditWindow.aMoveDownExecute(Sender: TObject); var Node: TTreeNode; Tab: TSpkTab; Pane: TSpkPane; Obj: TObject; index: Integer; Item: TSpkBaseItem; begin if (FToolbar = nil) or (FDesigner = nil) then exit; Node := tvStructure.Selected; if Node = nil then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSNoObjectSelectedToMove); if Node.Data = nil then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSDamagedTreeStructure); Obj := TObject(Node.Data); if Obj is TSpkTab then begin if not CheckValidTabNode(Node) then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSDamagedTreeStructure); Tab := TSpkTab(Node.Data); index := FToolbar.Tabs.IndexOf(Tab); if (index = -1) then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSDamagedTreeStructure); if (index = FToolbar.Tabs.Count - 1) then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSCannotMoveBeyondLastElement); FToolbar.Tabs.Exchange(index, index+1); FToolbar.TabIndex := index+1; Node.GetNextSibling.MoveTo(Node, naInsert); Node.Selected := true; CheckActionsAvailability; end else if Obj is TSpkPane then begin if not CheckValidPaneNode(Node) then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSDamagedTreeStructure); Pane := TSpkPane(Node.Data); Tab := TSpkTab(Node.Parent.Data); index := Tab.Panes.IndexOf(Pane); if (index = -1) then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSDamagedTreeStructure); if (index = Tab.Panes.Count - 1) then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSCannotMoveBeyondLastElement); Tab.Panes.Exchange(index, index+1); Node.GetNextSibling.MoveTo(Node, naInsert); Node.Selected := true; CheckActionsAvailability; end else if Obj is TSpkBaseItem then begin if not CheckValidItemNode(Node) then raise Exception.Create('TfrmEditWindow.aMoveDown.Execute: ' + RSDamagedTreeStructure); Item := TSpkBaseItem(Node.Data); Pane := TSpkPane(Node.Parent.Data); index := Pane.Items.IndexOf(Item); if (index = -1) then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSDamagedTreeStructure); if (index = Pane.Items.Count - 1) then raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSCannotMoveBeyondLastElement); Pane.Items.Exchange(index, index+1); Node.GetNextSibling.MoveTo(Node, naInsert); Node.Selected := true; CheckActionsAvailability; end else raise Exception.Create('TfrmEditWindow.aMoveDownExecute: ' + RSIncorrectObjectInTree); end; procedure TfrmEditWindow.aMoveUpExecute(Sender: TObject); var Node: TTreeNode; Tab: TSpkTab; Pane: TSpkPane; Obj: TObject; index: Integer; Item: TSpkBaseItem; begin if (FToolbar = nil) or (FDesigner = nil) then exit; Node := tvStructure.Selected; if Node = nil then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: '+ RSNoObjectSelectedToMove); if Node.Data = nil then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSDamagedTreeStructure); Obj := TObject(Node.Data); if Obj is TSpkTab then begin if not CheckValidTabNode(Node) then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSDamagedTreeStructure); Tab := TSpkTab(Node.Data); index := FToolbar.Tabs.IndexOf(Tab); if (index = -1) then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSDamagedTreeStructure); if (index = 0) then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSCannotMoveAboveFirstElement); FToolbar.Tabs.Exchange(index, index-1); FToolbar.TabIndex := index-1; Node.MoveTo(Node.getPrevSibling, naInsert); Node.Selected := true; CheckActionsAvailability; end else if Obj is TSpkPane then begin if not CheckValidPaneNode(Node) then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSDamagedTreeStructure); Pane := TSpkPane(Node.Data); Tab := TSpkTab(Node.Parent.Data); index := Tab.Panes.IndexOf(Pane); if (index = -1) then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSDamagedTreeStructure); if (index = 0) then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSCannotMoveAboveFirstElement); Tab.Panes.Exchange(index, index-1); Node.MoveTo(Node.GetPrevSibling, naInsert); Node.Selected := true; CheckActionsAvailability; end else if Obj is TSpkBaseItem then begin if not CheckValidItemNode(Node) then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSDamagedTreeStructure); Item := TSpkBaseItem(Node.Data); Pane := TSpkPane(Node.Parent.Data); index := Pane.Items.IndexOf(Item); if (index = -1) then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSDamagedTreeStructure); if (index = 0) then raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSCannotMoveAboveFirstElement); Pane.Items.Exchange(index, index-1); Node.MoveTo(Node.GetPrevSibling, naInsert); Node.Selected := true; CheckActionsAvailability; end else raise Exception.Create('TfrmEditWindow.aMoveUpExecute: ' + RSIncorrectObjectInTree); end; procedure TfrmEditWindow.aRemoveItemExecute(Sender: TObject); begin if (FToolbar = nil) or (FDesigner = nil) then exit; DoRemoveItem; end; procedure TfrmEditWindow.aRemovePaneExecute(Sender: TObject); begin if (FToolbar = nil) or (FDesigner = nil) then exit; DoRemovePane; end; procedure TfrmEditWindow.aRemoveTabExecute(Sender: TObject); begin if (FToolbar = nil) or (FDesigner = nil) then exit; DoRemoveTab; end; procedure TfrmEditWindow.CheckActionsAvailability; var Node: TTreeNode; Obj: TObject; Tab: TSpkTab; Pane: TSpkPane; index: integer; Item: TSpkBaseItem; begin if (FToolbar = nil) or (FDesigner = nil) then begin // Brak toolbara lub designera aAddTab.Enabled := false; aRemoveTab.Enabled := false; aAddPane.Enabled := false; aRemovePane.Enabled := false; aAddLargeButton.Enabled := false; aAddSmallButton.Enabled := false; aAddCheckbox.Enabled := false; aAddRadioButton.Enabled := false; aRemoveItem.Enabled := false; aMoveUp.Enabled := false; aMoveDown.Enabled := false; end else begin Node := tvStructure.Selected; if Node = nil then begin // Pusty toolbar aAddTab.Enabled := true; aRemoveTab.Enabled := false; aAddPane.Enabled := false; aRemovePane.Enabled := false; aAddLargeButton.Enabled := false; aAddSmallButton.Enabled := false; aAddCheckbox.Enabled := false; aAddRadioButton.Enabled := false; aRemoveItem.Enabled := false; aMoveUp.Enabled := false; aMoveDown.Enabled := false; end else begin Obj := TObject(Node.Data); if Obj = nil then raise Exception.Create('TfrmEditWindow.CheckActionsAvailability: ' + RSIncorrectFieldData); if Obj is TSpkTab then begin Tab := Obj as TSpkTab; if not CheckValidTabNode(Node) then raise Exception.Create('TfrmEditWindow.CheckActionsAvailability: ' + RSDamagedTreeStructure); aAddTab.Enabled := true; aRemoveTab.Enabled := true; aAddPane.Enabled := true; aRemovePane.Enabled := false; aAddLargeButton.Enabled := false; aAddSmallButton.Enabled := false; aAddCheckbox.Enabled := false; aAddRadioButton.Enabled := false; aRemoveItem.Enabled := false; index := FToolbar.Tabs.IndexOf(Tab); if index = -1 then raise Exception.Create('TfrmEditWindow.CheckActionsAvailability: ' + RSDamagedTreeStructure); aMoveUp.Enabled := (index > 0); aMoveDown.enabled := (index < FToolbar.Tabs.Count-1); end else if Obj is TSpkPane then begin Pane := TSpkPane(Obj); if not(CheckValidPaneNode(Node)) then raise Exception.Create('TfrmEditWindow.CheckActionsAvailability: ' + RSDamagedTreeStructure); Tab := TSpkTab(Node.Parent.Data); aAddTab.Enabled := true; aRemoveTab.Enabled := false; aAddPane.Enabled := true; aRemovePane.Enabled := true; aAddLargeButton.Enabled := true; aAddSmallButton.Enabled := true; aAddCheckbox.Enabled := true; aAddRadiobutton.Enabled := true; aRemoveItem.Enabled := false; index := Tab.Panes.IndexOf(Pane); if index = -1 then raise Exception.Create('TfrmEditWindow.CheckActionsAvailability: ' + RSDamagedTreeStructure); aMoveUp.Enabled := (index > 0); aMoveDown.Enabled := (index < Tab.Panes.Count-1); end else if Obj is TSpkBaseItem then begin Item := TSpkBaseItem(Obj); if not CheckValidItemNode(Node) then raise Exception.Create('TfrmEditWindow.CheckActionsAvailability: ' + RSDamagedTreeStructure); Pane := TSpkPane(Node.Parent.Data); aAddTab.Enabled := true; aRemoveTab.Enabled := false; aAddPane.Enabled := true; aRemovePane.Enabled := false; aAddLargeButton.Enabled := true; aAddSmallButton.Enabled := true; aAddCheckbox.Enabled := true; aAddRadioButton.Enabled := true; aRemoveItem.Enabled := true; index := Pane.Items.IndexOf(Item); if index = -1 then raise Exception.Create('TfrmEditWindow.CheckActionsAvailability: ' + RSDamagedTreeStructure); aMoveUp.Enabled := (index > 0); aMoveDown.Enabled := (index < Pane.Items.Count - 1); end else raise Exception.Create('TfrmEditWindow.CheckActionsAvailability: ' + RSIncorrectObjectInTree); end; end; end; function TfrmEditWindow.CheckValidItemNode(Node: TTreeNode): boolean; begin Result := false; if (FToolbar = nil) or (FDesigner = nil) then exit; {$B-} Result:=(Node <> nil) and (Node.Data <> nil) and (TObject(Node.Data) is TSpkBaseItem) and CheckValidPaneNode(Node.Parent); end; function TfrmEditWindow.CheckValidPaneNode(Node: TTreeNode): boolean; begin Result := false; if (FToolbar = nil) or (FDesigner = nil) then exit; {$B-} Result := (Node <> nil) and (Node.Data <> nil) and (TObject(Node.Data) is TSpkPane) and CheckValidTabNode(Node.Parent); end; function TfrmEditWindow.CheckValidTabNode(Node: TTreeNode): boolean; begin Result := false; if (FToolbar = nil) or (FDesigner = nil) then exit; {$B-} result := (Node <> nil) and (Node.Data <> nil) and (TObject(Node.Data) is TSpkTab); end; procedure TfrmEditWindow.FormActivate(Sender: TObject); begin if (FToolbar = nil) or (FDesigner = nil) then exit; UpdatePPI; if not ValidateTreeData then BuildTreeData; end; procedure TfrmEditWindow.FormDestroy(Sender: TObject); begin if FToolbar <> nil then FToolbar.RemoveFreeNotification(self); end; procedure TfrmEditWindow.FormShow(Sender: TObject); begin if (FToolbar = nil) or (FDesigner = nil) then exit; BuildTreeData; end; function TfrmEditWindow.GetItemCaption(Item: TSpkBaseItem): string; begin if (FToolbar = nil) or (FDesigner = nil) then exit; if Item is TSpkBaseButton then Result := TSpkBaseButton(Item).Caption else Result := ''; end; procedure TfrmEditWindow.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; if (AComponent = FToolbar) and (Operation = opRemove) then begin // The toolbar is currently released, whose content is displayed in the // editor window. Need to clean up the content - otherwise the window will // have references to the already removed toolbars, which will end in AVs ... SetData(nil, nil); end; end; procedure TfrmEditWindow.SetItemCaption(Item: TSpkBaseItem; const Value : string); begin if (FToolbar = nil) or (FDesigner = nil) then exit; if Item is TSpkBaseButton then TSpkBaseButton(Item).Caption := Value; end; procedure TfrmEditWindow.SetData(AToolbar: TSpkToolbar; ADesigner: TComponentEditorDesigner); begin if FToolbar <> nil then FToolbar.RemoveFreeNotification(self); FToolbar := AToolbar; FDesigner := ADesigner; if FToolbar <> nil then FToolbar.FreeNotification(self); BuildTreeData; end; procedure TfrmEditWindow.DoRemoveItem; var Item: TSpkBaseItem; index: Integer; Node: TTreeNode; Pane: TSpkPane; NextNode: TTreeNode; begin if (FToolbar = nil) or (FDesigner = nil) then exit; Node := tvStructure.Selected; if not (CheckValidItemNode(Node)) then raise Exception.Create('TfrmEditWindow.aRemoveItemExecute: ' + RSDamagedTreeStructure); Item := TSpkBaseItem(Node.Data); Pane := TSpkPane(Node.Parent.Data); index := Pane.Items.IndexOf(Item); if index = -1 then raise Exception.Create('TfrmEditWindow.aRemoveItemExecute: ' + RSDamagedTreeStructure); if Node.getPrevSibling <> nil then NextNode := Node.getPrevSibling else if Node.GetNextSibling <> nil then NextNode := Node.getNextSibling else NextNode := Node.Parent; Pane.Items.Delete(index); tvStructure.Items.delete(node); NextNode.Selected := true; CheckActionsAvailability; end; procedure TfrmEditWindow.DoRemovePane; var Pane: TSpkPane; NextNode: TTreeNode; index: Integer; Node: TTreeNode; Tab: TSpkTab; begin if (FToolbar = nil) or (FDesigner = nil) then exit; Node := tvStructure.Selected; if not (CheckValidPaneNode(Node)) then raise Exception.Create('TfrmEditWindow.aRemovePaneExecute: ' + RSDamagedTreeStructure); Pane := TSpkPane(Node.Data); Tab := TSpkTab(Node.Parent.Data); index := Tab.Panes.IndexOf(Pane); if index = -1 then raise Exception.Create('TfrmEditWindow.aRemovePaneExecute: ' + RSDamagedTreeStructure); if Node.GetPrevSibling <> nil then NextNode := Node.GetPrevSibling else if Node.GetNextSibling <> nil then NextNode := Node.GetNextSibling else NextNode := Node.Parent; Tab.Panes.Delete(index); tvStructure.Items.Delete(Node); NextNode.Selected := true; CheckActionsAvailability; end; procedure TfrmEditWindow.DoRemoveTab; var Node: TTreeNode; Tab: TSpkTab; index: Integer; NextNode: TTreeNode; begin if (FToolbar = nil) or (FDesigner = nil) then exit; Node := tvStructure.Selected; if not (CheckValidTabNode(Node)) then raise Exception.Create('TfrmEditWindow.aRemoveTabExecute: ' + RSDamagedTreeStructure); Tab := TSpkTab(Node.Data); index := FToolbar.Tabs.IndexOf(Tab); if index = -1 then raise Exception.Create('TfrmEditWindow.aRemoveTabExecute: ' + RSDamagedTreeStructure); if Node.GetPrevSibling <> nil then NextNode := Node.GetPrevSibling else if Node.GetNextSibling <> nil then NextNode := Node.GetNextSibling else NextNode := nil; FToolbar.Tabs.Delete(index); tvStructure.Items.Delete(Node); if Assigned(NextNode) then begin // The OnChange event will trigger an update of the selected object in // the Object Inspector NextNode.Selected := true; CheckActionsAvailability; end else begin // There are no more objects in the list, but something has to be displayed // in the Object Inspector - so we will display the toolbars itself // (otherwise the IDE will attempt to display the object's properties in // the Object Inspector, which will end, say, not very nice) //DesignObj := PersistentToDesignObject(FToolbar); FDesigner.SelectOnlyThisComponent(FToolbar); CheckActionsAvailability; end; end; procedure TfrmEditWindow.BuildTreeData; var i: Integer; panenode: TTreeNode; j: Integer; tabnode: TTreeNode; k : Integer; itemnode: TTreeNode; Obj: TSpkBaseItem; s: string; node: TTreeNode; begin Caption:='Editing TSpkToolbar contents'; // Clear tree, but don't remove existing toolbar children from the form tvStructure.OnDeletion := nil; tvStructure.Items.Clear; tvStructure.OnDeletion := tvStructureDeletion; if (FToolbar <> nil) and (FDesigner <> nil) then begin for i := 0 to FToolbar.Tabs.Count - 1 do begin tabnode := tvStructure.Items.AddChild(nil, FToolbar.Tabs[i].Caption); tabnode.ImageIndex := 0; tabnode.SelectedIndex := 0; tabnode.Data := FToolbar.Tabs[i]; for j := 0 to FToolbar.Tabs.Items[i].Panes.Count - 1 do begin panenode := tvStructure.Items.AddChild(tabnode, FToolbar.Tabs[i].Panes[j].Caption); panenode.ImageIndex := 1; panenode.SelectedIndex := 1; panenode.Data := FToolbar.Tabs[i].Panes[j]; for k := 0 to FToolbar.Tabs[i].Panes[j].Items.Count - 1 do begin Obj := FToolbar.Tabs[i].Panes[j].Items[k]; s := GetItemCaption(Obj); itemnode := tvStructure.Items.AddChild(panenode,s); itemnode.Imageindex := 2; itemnode.Selectedindex := 2; itemnode.Data := Obj; end; end; end; end; if (tvStructure.Items.Count > 0) and (FToolbar.TabIndex > -1) then begin node := tvStructure.Items[0]; while (node <> nil) do begin if TSpkTab(node.Data) = FToolbar.Tabs[FToolbar.TabIndex] then break; node := node.GetNextSibling; end; if (node <> nil) then begin node.Selected := true; node.Expand(true); end; end; CheckActionsAvailability; end; procedure TfrmEditWindow.RefreshNames; var tabnode, panenode, itemnode: TTreeNode; Obj: TSpkBaseItem; s: string; begin if (FToolbar = nil) or (FDesigner = nil) then exit; tabnode := tvStructure.Items.GetFirstNode; while tabnode<>nil do begin if not CheckValidTabNode(tabnode) then raise Exception.Create('TfrmEditWindow.RefreshNames: ' + RSDamagedTreeStructure); tabnode.Text := TSpkTab(tabnode.Data).Caption; panenode := tabnode.getFirstChild; while panenode <> nil do begin if not CheckValidPaneNode(panenode) then raise Exception.Create('TfrmEditWindow.RefreshNames: ' + RSDamagedTreeStructure); panenode.Text := TSpkPane(panenode.Data).Caption; itemnode := panenode.getFirstChild; while itemnode <> nil do begin if not CheckValidItemNode(itemnode) then raise Exception.Create('TfrmEditWindow.RefreshNames: ' + RSDamagedTreeStructure); Obj := TSpkBaseItem(itemnode.Data); s := GetItemCaption(Obj); itemnode.Text := s; itemnode := itemnode.getNextSibling; end; panenode := panenode.getNextSibling; end; tabnode := tabnode.getNextSibling; end; end; procedure TfrmEditWindow.tvStructureChange(Sender: TObject; Node: TTreeNode); var Obj: TObject; Tab: TSpkTab; Pane: TSpkPane; Item: TSpkBaseItem; index: integer; begin if (FToolbar = nil) or (FDesigner = nil) then exit; if Assigned(Node) then begin Obj := TObject(Node.Data); if Obj = nil then raise Exception.Create('TfrmEditWindow.tvStructureChange: ' + RSIncorrectFieldData); if Obj is TSpkTab then begin Tab := TSpkTab(Obj); FDesigner.SelectOnlyThisComponent(Tab); index := FToolbar.Tabs.IndexOf(Tab); if index=-1 then raise Exception.Create('TfrmEditWindow.tvStructureChange: ' + RSDamagedTreeStructure); FToolbar.TabIndex := index; end else if Obj is TSpkPane then begin Pane := TSpkPane(Obj); FDesigner.SelectOnlyThisComponent(Pane); if not(CheckValidPaneNode(Node)) then raise Exception.Create('TfrmEditWindow.tvStructureChange: ' + RSDamagedTreeStructure); Tab := TSpkTab(Node.Parent.Data); index := FToolbar.Tabs.IndexOf(Tab); if index = -1 then raise Exception.Create('TfrmEditWindow.tvStructureChange: ' + RSDamagedTreeStructure); FToolbar.TabIndex := index; end else if Obj is TSpkBaseItem then begin Item := TSpkBaseItem(Obj); FDesigner.SelectOnlyThisComponent(Item); if not CheckValidItemNode(Node) then raise Exception.Create('TfrmEditWindow.tvStructureChange: ' + RSDamagedTreeStructure); Tab := TSpkTab(Node.Parent.Parent.Data); index := FToolbar.Tabs.IndexOf(Tab); if index = -1 then raise Exception.Create('TfrmEditWindow.tvStructureChange: ' + RSDamagedTreeStructure); FToolbar.TabIndex := index; end else raise Exception.Create('TfrmEditWindow.tvStructureChange: ' + RSIncorrectObjectInTree); end else FDesigner.SelectOnlyThisComponent(FToolbar); CheckActionsAvailability; end; procedure TfrmEditWindow.tvStructureDeletion(Sender:TObject; Node:TTreeNode); var RunNode: TTreeNode; begin if Node = nil then exit; // Recursively delete children and destroy their data RunNode := Node.GetFirstChild; while RunNode <> nil do begin RunNode.Delete; RunNode := RunNode.GetNextSibling; end; // Destroy node's data TSpkComponent(Node.Data).Free; end; procedure TfrmEditWindow.tvStructureEdited(Sender: TObject; Node: TTreeNode; var S: string); var Tab: TSpkTab; Pane: TSpkPane; Item: TSpkBaseItem; begin if (FToolbar = nil) or (FDesigner = nil) then exit; if Node.Data = nil then raise Exception.Create('TfrmEditWindow.tvStructureEdited: ' + RSDamagedTreeStructure); if TObject(Node.Data) is TSpkTab then begin Tab := TSpkTab(Node.Data); Tab.Caption := S; FDesigner.Modified; end else if TObject(Node.Data) is TSpkPane then begin Pane := TSpkPane(Node.Data); Pane.Caption := S; FDesigner.Modified; end else if TObject(Node.Data) is TSpkBaseItem then begin Item := TSpkBaseItem(Node.Data); SetItemCaption(Item, S); FDesigner.Modified; end else raise Exception.Create('TfrmEditWindow.tvStructureEdited: ' + RSDamagedTreeStructure); end; procedure TfrmEditWindow.tvStructureKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (FToolbar = nil) or (FDesigner = nil) then exit; if Key = VK_DELETE then begin if tvStructure.Selected <> nil then begin // We check what kind of object is selected - just test the type of the object if TObject(tvStructure.Selected.Data) is TSpkTab then DoRemoveTab else if TObject(tvStructure.Selected.Data) is TSpkPane then DoRemovePane else if TObject(tvStructure.Selected.Data) is TSpkBaseItem then DoRemoveItem else raise Exception.Create('TfrmEditWindow.tvStructureKeyDown: ' + RSDamagedTreeStructure); end; end; end; function TfrmEditWindow.ValidateTreeData: boolean; var i: Integer; TabsValid: Boolean; TabNode: TTreeNode; j: Integer; PanesValid: Boolean; PaneNode: TTreeNode; k: Integer; ItemsValid: Boolean; ItemNode: TTreeNode; begin Result := false; if (FToolbar = nil) or (FDesigner = nil) then exit; i := 0; TabsValid := true; TabNode := tvStructure.Items.GetFirstNode; while (i < FToolbar.Tabs.Count) and TabsValid do begin TabsValid := TabsValid and (TabNode <> nil); if TabsValid then TabsValid := TabsValid and (TabNode.Data = FToolbar.Tabs[i]); if TabsValid then begin j := 0; PanesValid := true; PaneNode := TabNode.GetFirstChild; while (j < FToolbar.Tabs[i].Panes.Count) and PanesValid do begin PanesValid := PanesValid and (PaneNode <> nil); if PanesValid then PanesValid := PanesValid and (PaneNode.Data = FToolbar.Tabs[i].Panes[j]); if PanesValid then begin k := 0; ItemsValid := true; ItemNode := PaneNode.GetFirstChild; while (k < FToolbar.Tabs[i].Panes[j].Items.Count) and ItemsValid do begin ItemsValid := ItemsValid and (ItemNode <> nil); if ItemsValid then ItemsValid := ItemsValid and (ItemNode.Data = FToolbar.Tabs[i].Panes[j].Items[k]); if ItemsValid then begin inc(k); ItemNode := ItemNode.GetNextSibling; end; end; // Important! You need to make sure that there are no extra items in the tree! ItemsValid := ItemsValid and (ItemNode = nil); PanesValid := PanesValid and ItemsValid; end; if PanesValid then begin inc(j); PaneNode := PaneNode.GetNextSibling; end; end; // Important! You need to make sure that there are no extra items in the tree! PanesValid := PanesValid and (PaneNode = nil); TabsValid := TabsValid and PanesValid; end; if TabsValid then begin inc(i); TabNode := TabNode.GetNextSibling; end; end; // Important! You need to make sure that there are no extra items in the tree! TabsValid := TabsValid and (TabNode = nil); Result := TabsValid; end; procedure TfrmEditWindow.UpdatePPI; begin tbToolbar.Images := nil; if ScreenInfo.PixelsPerInchY >= 180 then begin ActionList.Images := ilActionImages_200; tbToolbar.Images := ilActionImages_200; tvStructure.Images := ilTreeImages_200; pmAddItem.Images := ilActionImages_200; pmStructure.Images := ilActionImages_200; end else if ScreenInfo.PixelsPerInchY >= 135 then begin ActionList.Images := ilActionImages_150; tbToolbar.Images := ilActionImages_150; tvStructure.Images := ilTreeImages_150; pmAddItem.Images := ilActionImages_150; pmStructure.Images := ilActionImages_150; end else begin ActionList.Images := ilActionImages; tbToolbar.Images := ilActionImages; tvStructure.Images := ilTreeImages; pmAddItem.Images := ilActionImages; pmStructure.Images := ilActionImages; end; tbToolbar.ButtonHeight := tbToolbar.Images.Height + 8; end; end.