123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- unit ProjectTree;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, ComCtrls, CommCtrl, ExtCtrls, ImgList, Menus, JvComponent,
- JvDockControlForm, JvExComCtrls, JvComCtrls, JvDotNetControls, Main,
- VirtualTrees;
- type
- PProjectTreeData = ^TProjectTreeData;
- TProjectTreeData = record
- pLuaUnit: TLuaUnit;
- pLuaPrj: TLuaProject;
- ActiveProject: Boolean;
- ToKeep: Boolean;
- Deleting: Boolean;
- end;
- TfrmProjectTree = class(TForm)
- Panel1: TPanel;
- imlProjectTree: TImageList;
- ppmProjectTree: TPopupMenu;
- ActivateSelectedProject1: TMenuItem;
- N1: TMenuItem;
- UnloadFileProject1: TMenuItem;
- JvDockClient1: TJvDockClient;
- N2: TMenuItem;
- AddUnittoProject1: TMenuItem;
- RemoveUnitFromProject1: TMenuItem;
- Options1: TMenuItem;
- vstProjectTree: TVirtualStringTree;
- procedure UnloadFileProject1Click(Sender: TObject);
- procedure ppmProjectTreePopup(Sender: TObject);
- procedure vstProjectTreeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
- procedure vstProjectTreeGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
- procedure vstProjectTreeGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
- procedure vstProjectTreePaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
- procedure vstProjectTreeDblClick(Sender: TObject);
- procedure vstProjectTreeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- procedure vstProjectTreeAfterItemPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; ItemRect: TRect);
- function GetNodeInTree(sFileName, sProjectName: String): PVirtualNode;
- private
- { Private declarations }
- public
- { Public declarations }
- procedure BuildProjectTree(HandleNotifier: Boolean = True);
- end;
- var
- frmProjectTree: TfrmProjectTree;
- implementation
- {$R *.dfm}
- procedure TfrmProjectTree.vstProjectTreeDblClick(Sender: TObject);
- var
- pNode: PVirtualNode;
- pData: PProjectTreeData;
- pLuaUnit: TLuaUnit;
- begin
- pNode := vstProjectTree.GetFirstSelected;
- if Assigned(pNode) then
- begin
- pData := vstProjectTree.GetNodeData(pNode);
- if Assigned(pData.pLuaUnit) then
- begin
- pLuaUnit := pData.pLuaUnit;
- if pLuaUnit.IsLoaded then
- begin
- if LuaOpenedUnits.IndexOf(pLuaUnit) = -1 then
- begin
- // Insert new tab in the page control to view the requested unit
- frmMain.AddFileInTab(pLuaUnit);
- end
- else
- begin
- // Activate the tab associated to the requested unit
- frmMain.jvUnitBar.SelectedTab := frmMain.GetAssociatedTab(pLuaUnit);
- if pLuaUnit.HasChanged then
- frmMain.stbMain.Panels[2].Text := 'Modified'
- else
- frmMain.stbMain.Panels[2].Text := '';
- frmMain.synEditClick(pLuaUnit.synUnit);
- end;
- end;
- end;
- end;
- frmMain.CheckButtons;
- end;
- function TfrmProjectTree.GetNodeInTree(sFileName, sProjectName: String): PVirtualNode;
- var
- pNode: PVirtualNode;
- pData: PProjectTreeData;
- begin
- Result := nil;
- pNode := vstProjectTree.GetFirst;
- while Assigned(pNode) do
- begin
- pData := vstProjectTree.GetNodeData(pNode);
- if sProjectName <> '' then
- begin
- if (Assigned(pData.pLuaUnit) and (not pData.Deleting)) then
- begin
- if ((pData.pLuaUnit.pPrjOwner.sPrjName = sProjectName) or (sProjectName = '[@@SingleUnits@@]')) then
- begin
- if pData.pLuaUnit.sName = sFileName then
- begin
- Result := pNode;
- Break;
- end;
- end;
- end;
- end
- else
- begin
- if Assigned(pData.pLuaPrj) then
- begin
- if pData.pLuaPrj.sPrjName = sFileName then
- begin
- Result := pNode;
- Break;
- end;
- end;
- end;
- pNode := vstProjectTree.GetNext(pNode);
- end;
- end;
- procedure TfrmProjectTree.BuildProjectTree(HandleNotifier: Boolean);
- var
- pTempPrj: TLuaProject;
- pPrjNode, pUnitNode, pSingleUnitLastNode: PVirtualNode;
- pData: PProjectTreeData;
- x, y: Integer;
- // Go through all nodes of the tree and set their ToKeep flag to false
- procedure UnflagAllExpanded(pTree: TVirtualStringTree);
- var
- pNode: PVirtualNode;
- pData: PProjectTreeData;
- begin
- pNode := pTree.GetFirst;
- while Assigned(pNode) do
- begin
- pData := pTree.GetNodeData(pNode);
- pData.ToKeep := False;
- pNode := pTree.GetNext(pNode);
- end;
- end;
- // Deletes all nodes for wich their ToKeep flag is still on false
- procedure CleanTree(pTree: TVirtualStringTree);
- var
- pNode, pPrevious: PVirtualNode;
- pData: PProjectTreeData;
- begin
- pNode := pTree.GetFirst;
- while Assigned(pNode) do
- begin
- pData := pTree.GetNodeData(pNode);
-
- if not pData.ToKeep then
- begin
- pPrevious := pTree.GetPrevious(pNode);
- pTree.DeleteNode(pNode);
- pNode := pPrevious;
- end;
-
- pNode := pTree.GetNext(pNode);
- end;
- end;
-
- begin
- // Initialize stuff
- pPrjNode := nil;
- pUnitNode := nil;
- pSingleUnitLastNode := nil;
- // If the changes notifier is handled, we stop it while building the tree
- if HandleNotifier then
- begin
- frmMain.jvchnNotifier.Active := False;
- frmMain.jvchnNotifier.Notifications.Clear;
- end;
- vstProjectTree.BeginUpdate;
- UnflagAllExpanded(vstProjectTree);
- for x := 0 to LuaProjects.Count - 1 do
- begin
- pTempPrj := TLuaProject(LuaProjects.Items[x]);
- pPrjNode := GetNodeInTree(pTempPrj.sPrjName, '');
- if not Assigned(pPrjNode) then
- begin
- if pTempPrj.sPrjName <> '[@@SingleUnits@@]' then
- begin
- // Create the node
- pPrjNode := vstProjectTree.AddChild(vstProjectTree.RootNode);
- pData := vstProjectTree.GetNodeData(pPrjNode);
- pData.pLuaUnit := nil;
- pData.pLuaPrj := pTempPrj;
- pData.ActiveProject := (pTempPrj = ActiveProject);
- pData.ToKeep := True;
- pData.Deleting := False;
- // Adding project root to change notifier...
- if ((not pTempPrj.IsNew) and HandleNotifier) then
- frmMain.AddToNotifier(ExtractFileDir(pTempPrj.sPrjPath));
- end
- else
- pPrjNode := pSingleUnitLastNode;
- end
- else
- begin
- // Update the node's data
- pData := vstProjectTree.GetNodeData(pPrjNode);
- pData.pLuaUnit := nil;
- pData.pLuaPrj := pTempPrj;
- pData.ActiveProject := (pTempPrj = ActiveProject);
- pData.ToKeep := True;
- pData.Deleting := False;
- // Adding project root to change notifier...
- if ((not pTempPrj.IsNew) and HandleNotifier) then
- frmMain.AddToNotifier(ExtractFileDir(pTempPrj.sPrjPath));
- end;
- for y := 0 to pTempPrj.lstUnits.Count - 1 do
- begin
- pUnitNode := GetNodeInTree(TLuaUnit(pTempPrj.lstUnits.Items[y]).sName, pTempPrj.sPrjName);
- if not Assigned(pUnitNode) then
- begin
- // Adding single unit (projectless) to the tree
- if pTempPrj.sPrjName = '[@@SingleUnits@@]' then
- begin
- if not Assigned(pPrjNode) then
- pUnitNode := vstProjectTree.InsertNode(vstProjectTree.RootNode, amInsertBefore)
- else
- pUnitNode := vstProjectTree.InsertNode(pPrjNode, amInsertAfter);
- // Update last single unit node
- pSingleUnitLastNode := pUnitNode;
- end
- else
- pUnitNode := vstProjectTree.AddChild(pPrjNode);
- // Create the node
- pData := vstProjectTree.GetNodeData(pUnitNode);
- pData.pLuaUnit := TLuaUnit(pTempPrj.lstUnits.Items[y]);
- pData.pLuaPrj := nil;
- pData.ActiveProject := False;
- pData.ToKeep := True;
- pData.Deleting := False;
- // Adding unit root to change notifier...
- if ((not TLuaUnit(pTempPrj.lstUnits.Items[y]).IsNew) and HandleNotifier) then
- frmMain.AddToNotifier(ExtractFileDir(TLuaUnit(pTempPrj.lstUnits.Items[y]).sUnitPath));
- end
- else
- begin
- // Update the node's data
- pData := vstProjectTree.GetNodeData(pUnitNode);
- pData.pLuaUnit := TLuaUnit(pTempPrj.lstUnits.Items[y]);
- pData.pLuaPrj := nil;
- pData.ActiveProject := False;
- pData.ToKeep := True;
- pData.Deleting := False;
- // Adding unit root to change notifier...
- if ((not TLuaUnit(pTempPrj.lstUnits.Items[y]).IsNew) and HandleNotifier) then
- frmMain.AddToNotifier(ExtractFileDir(TLuaUnit(pTempPrj.lstUnits.Items[y]).sUnitPath));
- end;
- end;
- end;
- CleanTree(vstProjectTree);
- vstProjectTree.EndUpdate;
- // Set back on the changes notifier if required
- if ((frmMain.jvchnNotifier.Notifications.Count > 0) and HandleNotifier) then
- frmMain.jvchnNotifier.Active := True;
- end;
- procedure TfrmProjectTree.UnloadFileProject1Click(Sender: TObject);
- var
- pLuaPrj: TLuaProject;
- pLuaUnit: TLuaUnit;
- Answer, x: Integer;
- UnitsToDelete: TList;
- pNode: PVirtualNode;
- pData: PProjectTreeData;
- begin
- pNode := vstProjectTree.GetFirstSelected;
- if Assigned(pNode) then
- begin
- pData := vstProjectTree.GetNodeData(pNode);
- UnitsToDelete := TList.Create;
- // Case where the selected file was a project
- if Assigned(pData.pLuaPrj) then
- begin
- pLuaPrj := pData.pLuaPrj;
- // Ssaving any new or modified project's files
- for x := 0 to pLuaPrj.lstUnits.Count - 1 do
- begin
- pLuaUnit := TLuaUnit(pLuaPrj.lstUnits.Items[x]);
-
- if ((pLuaUnit.HasChanged) or (pLuaUnit.IsNew)) then
- begin
- Answer := Application.MessageBox(PChar('Save changes to unit "'+pLuaUnit.sName+'"?'), 'LuaEdit', MB_YESNOCANCEL+MB_ICONQUESTION);
- if Answer = IDYES then
- begin
- if SaveUnitsInc then
- pLuaUnit.SaveUnitInc(pLuaUnit.sUnitPath)
- else
- pLuaUnit.SaveUnit(pLuaUnit.sUnitPath);
- end
- else if Answer = IDCANCEL then
- begin
- UnitsToDelete.Free;
- Exit;
- end;
- end;
- UnitsToDelete.Add(pLuaUnit);
- end;
- // saving any new or modified project
- if ((pLuaPrj.HasChanged) or (pLuaPrj.IsNew)) then
- begin
- Answer := Application.MessageBox(PChar('Save changes to project "'+pLuaPrj.sPrjName+'"?'), 'LuaEdit', MB_YESNOCANCEL+MB_ICONQUESTION);
- if Answer = IDYES then
- begin
- if SaveProjectsInc then
- pLuaPrj.SaveProjectInc(pLuaPrj.sPrjPath)
- else
- pLuaPrj.SaveProject(pLuaPrj.sPrjPath);
- end
- else if Answer = IDCANCEL then
- begin
- UnitsToDelete.Free;
- Exit;
- end;
- end;
- end
- else if Assigned(pData.pLuaUnit) then
- begin
- pLuaUnit := pData.pLuaUnit;
- if pLuaUnit.pPrjOwner.sPrjName = '[@@SingleUnits@@]' then
- begin
- if ((pLuaUnit.HasChanged) or (pLuaUnit.IsNew)) then
- begin
- Answer := Application.MessageBox(PChar('Save changes to unit "'+pLuaUnit.sName+'"?'), 'LuaEdit', MB_YESNOCANCEL+MB_ICONQUESTION);
- if Answer = IDYES then
- begin
- if SaveUnitsInc then
- pLuaUnit.SaveUnitInc(pLuaUnit.sUnitPath)
- else
- pLuaUnit.SaveUnit(pLuaUnit.sUnitPath);
- end
- else if Answer = IDCANCEL then
- begin
- UnitsToDelete.Free;
- Exit;
- end;
- end;
- UnitsToDelete.Add(pLuaUnit);
- end;
- end;
-
- // Free and close units and project
- for x := UnitsToDelete.Count - 1 downto 0 do
- begin
- pLuaUnit := TLuaUnit(UnitsToDelete.Items[x]);
- if frmMain.GetAssociatedTab(pLuaUnit) <> nil then
- begin
- frmMain.jvUnitBar.Tabs.Delete(frmMain.GetAssociatedTab(pLuaUnit).Index);
- LuaOpenedUnits.Remove(pLuaUnit);
- end;
- pData.Deleting := True;
- pLuaUnit.pPrjOwner.lstUnits.Remove(pLuaUnit);
- pLuaUnit.Free;
- end;
- if Assigned(pLuaPrj) then
- LuaProjects.Remove(pLuaPrj);
- if pLuaPrj = ActiveProject then
- begin
- // Try to find another project to automatically set to the active one
- if LuaProjects.Count > 1 then
- ActiveProject := LuaProjects.Items[LuaProjects.Count - 1]
- else
- ActiveProject := nil;
- end;
- // Reset LuaEdit main form caption to its initial value
- if not Assigned(ActiveProject) then
- frmMain.Caption := 'LuaEdit';
- // Initialize stuff...
- UnitsToDelete.Free;
- BuildProjectTree;
- frmMain.CheckButtons;
- end;
- end;
- procedure TfrmProjectTree.ppmProjectTreePopup(Sender: TObject);
- begin
- frmMain.DoMainMenuProjectExecute;
- end;
- procedure TfrmProjectTree.vstProjectTreeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
- var
- pData: PProjectTreeData;
- begin
- // Set text to display for all nodes
- if TextType = ttNormal then
- begin
- case Column of
- 0:
- begin
- pData := Sender.GetNodeData(Node);
- pData.ToKeep := True;
- if Assigned(pData.pLuaPrj) then
- CellText := pData.pLuaPrj.sPrjName
- else
- CellText := pData.pLuaUnit.sName;
- end;
- 1:
- begin
- pData := Sender.GetNodeData(Node);
- pData.ToKeep := True;
-
- if Assigned(pData.pLuaPrj) then
- CellText := pData.pLuaPrj.sPrjPath
- else
- CellText := pData.pLuaUnit.sUnitPath;
- end;
- end;
- end;
- end;
- procedure TfrmProjectTree.vstProjectTreePaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
- var
- pData: PProjectTreeData;
- begin
- pData := Sender.GetNodeData(Node);
- if Assigned(pData.pLuaPrj) then
- begin
- // Set bold style on the active project node
- if pData.ActiveProject then
- begin
- TargetCanvas.Font.Style := [fsBold];
- frmMain.Caption := 'LuaEdit - ' + TLuaProject(pData.pLuaPrj).sPrjName;
- end;
- end
- else
- begin
- // Set disabled color for non-loaded units
- if not pData.pLuaUnit.IsLoaded then
- begin
- TargetCanvas.Font.Color := clInactiveCaption;
- TargetCanvas.Pen.Color := clInactiveCaption;
- end;
- end;
- end;
- procedure TfrmProjectTree.vstProjectTreeGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
- var
- pData: PProjectTreeData;
- begin
- // Set image index for all nodes
- if Column = 0 then
- begin
- pData := Sender.GetNodeData(Node);
- if Assigned(pData.pLuaPrj) then
- begin
- ImageIndex := 0;
- end
- else
- begin
- if pData.pLuaUnit.IsLoaded then
- ImageIndex := 1
- else
- ImageIndex := 2;
- end;
- end;
- end;
- procedure TfrmProjectTree.vstProjectTreeGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
- begin
- NodeDataSize := SizeOf(TProjectTreeData);
- end;
- procedure TfrmProjectTree.vstProjectTreeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- frmMain.CheckButtons;
- end;
- procedure TfrmProjectTree.vstProjectTreeAfterItemPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; ItemRect: TRect);
- var
- pRect: TRect;
- begin
- pRect := ItemRect;
- InflateRect(pRect, 0, 1);
- pRect.Right := pRect.Left + 22;
- TargetCanvas.Brush.Color := clWhite;
- TargetCanvas.FillRect(pRect);
- // Draw node button since the noda has some child
- if ((Node.Parent = Sender.RootNode) and (Node.ChildCount <> 0)) then
- begin
- // Draw the frame around the button
- TargetCanvas.Pen.Color := clBtnShadow;
- TargetCanvas.Rectangle(5, 4, 14, 13);
- TargetCanvas.MoveTo(14, 8);
- TargetCanvas.LineTo(20, 8);
- TargetCanvas.Pen.Color := clBlack;
- if not (vsExpanded in Node.States) then
- begin
- // Draw expandable node button (plus sign)
- TargetCanvas.MoveTo(7, 8);
- TargetCanvas.LineTo(12, 8);
- TargetCanvas.MoveTo(9, 6);
- TargetCanvas.LineTo(9, 11);
- end
- else
- begin
- // Draw non-expandable node button (minus sign)
- TargetCanvas.MoveTo(7, 8);
- TargetCanvas.LineTo(12, 8);
- end;
- end;
- end;
- end.
|