From 6f5a8e42cb76824832e67af20695194df9416543 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Sat, 5 Sep 2015 11:22:19 +0200 Subject: [PATCH] started dub project editor --- lazproj/coedit.lpi | 9 +- lazproj/coedit.lpr | 3 +- src/ce_dubproject.pas | 4 +- src/ce_dubprojeditor.lfm | 79 +++++++++++++++ src/ce_dubprojeditor.pas | 209 +++++++++++++++++++++++++++++++++++++++ src/ce_main.pas | 11 ++- src/ce_projconf.pas | 2 + src/ce_projinspect.pas | 2 + 8 files changed, 314 insertions(+), 5 deletions(-) create mode 100644 src/ce_dubprojeditor.lfm create mode 100644 src/ce_dubprojeditor.pas diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index f9697920..4a164a90 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -135,7 +135,7 @@ - + @@ -349,6 +349,13 @@ + + + + + + + diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr index 40090178..876402f1 100644 --- a/lazproj/coedit.lpr +++ b/lazproj/coedit.lpr @@ -9,7 +9,8 @@ uses Interfaces, Forms, lazcontrols, runtimetypeinfocontrols, ce_sharedres, ce_observer, ce_libman, ce_tools, ce_dcd, ce_main, ce_writableComponent, ce_symstring, ce_staticmacro, ce_inspectors, ce_editoroptions, ce_dockoptions, - ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, ce_dialogs; + ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, ce_dialogs, +ce_dubprojeditor; {$R *.res} diff --git a/src/ce_dubproject.pas b/src/ce_dubproject.pas index e73f0b6a..d76b95d9 100644 --- a/src/ce_dubproject.pas +++ b/src/ce_dubproject.pas @@ -41,6 +41,8 @@ type // function compile: boolean; function run(const runArgs: string = ''): boolean; + // + property json: TJSONObject read fJson; end; implementation @@ -112,7 +114,6 @@ begin loader.LoadFromFile(fFilename); fJSon.Free; parser := TJSONParser.Create(loader); - subjProjChanged(fProjectSubject, self); try fJSon := parser.Parse as TJSONObject; finally @@ -120,6 +121,7 @@ begin end; finally loader.Free; + subjProjChanged(fProjectSubject, self); fModified := false; end; end; diff --git a/src/ce_dubprojeditor.lfm b/src/ce_dubprojeditor.lfm new file mode 100644 index 00000000..aa5a0b67 --- /dev/null +++ b/src/ce_dubprojeditor.lfm @@ -0,0 +1,79 @@ +inherited CEDubProjectEditorWidget: TCEDubProjectEditorWidget + Left = 816 + Height = 417 + Top = 191 + Width = 411 + ClientHeight = 417 + ClientWidth = 411 + inherited Back: TPanel + Height = 417 + Width = 411 + ClientHeight = 417 + ClientWidth = 411 + inherited Content: TPanel + Height = 417 + Width = 411 + ClientHeight = 417 + ClientWidth = 411 + object pnlToolBar: TPanel[0] + Left = 4 + Height = 26 + Top = 2 + Width = 403 + Align = alTop + BorderSpacing.Left = 2 + BorderSpacing.Right = 2 + BorderSpacing.Around = 2 + BevelOuter = bvNone + ClientHeight = 26 + ClientWidth = 403 + TabOrder = 0 + object btnAddProp: TSpeedButton + Left = 0 + Height = 26 + Hint = 'add an empty configuration' + Top = 0 + Width = 28 + Align = alLeft + Layout = blGlyphBottom + ShowCaption = False + end + object btnDelProp: TSpeedButton + Left = 28 + Height = 26 + Hint = 'remove selected configuration' + Top = 0 + Width = 28 + Align = alLeft + Layout = blGlyphBottom + ShowCaption = False + end + end + object propTree: TTreeView[1] + Left = 4 + Height = 284 + Top = 32 + Width = 403 + Align = alClient + BorderSpacing.Around = 4 + DefaultItemHeight = 18 + HideSelection = False + ReadOnly = True + ScrollBars = ssAutoBoth + TabOrder = 1 + OnSelectionChanged = propTreeSelectionChanged + Options = [tvoAutoItemHeight, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw] + end + object edValue: TMemo[2] + Left = 4 + Height = 93 + Top = 320 + Width = 403 + Align = alBottom + BorderSpacing.Around = 4 + ScrollBars = ssAutoVertical + TabOrder = 2 + end + end + end +end diff --git a/src/ce_dubprojeditor.pas b/src/ce_dubprojeditor.pas new file mode 100644 index 00000000..f8bf29b9 --- /dev/null +++ b/src/ce_dubprojeditor.pas @@ -0,0 +1,209 @@ +unit ce_dubprojeditor; + +{$I ce_defines.inc} + +interface + +uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, + Menus, StdCtrls, Buttons, ComCtrls, jsonparser, fpjson, + ce_widget, ce_common, ce_interfaces, ce_observer, ce_dubproject; + +type + + { TCEDubProjectEditorWidget } + + TCEDubProjectEditorWidget = class(TCEWidget, ICEProjectObserver) + btnAddProp: TSpeedButton; + btnDelProp: TSpeedButton; + edValue: TMemo; + pnlToolBar: TPanel; + propTree: TTreeView; + procedure propTreeSelectionChanged(Sender: TObject); + private + fSelectedNode: TTreeNode; + fProj: TCEDubProject; + procedure updateGui; + procedure updateValueEditor; + procedure setJsonValueFromEditor; + // + procedure projNew(aProject: ICECommonProject); + procedure projChanged(aProject: ICECommonProject); + procedure projClosing(aProject: ICECommonProject); + procedure projFocused(aProject: ICECommonProject); + procedure projCompiling(aProject: ICECommonProject); + // + protected + procedure SetVisible(Value: boolean); override; + public + end; + +implementation +{$R *.lfm} + +{$REGION Standard Comp/Obj ----------------------------------------------------} +procedure TCEDubProjectEditorWidget.SetVisible(Value: boolean); +begin + inherited; + if not Value then exit; + // + updateGui; +end; +{$ENDREGION} + +{$REGION ICEProjectObserver ----------------------------------------------------} +procedure TCEDubProjectEditorWidget.projNew(aProject: ICECommonProject); +begin + fProj := nil; + if aProject.getFormat <> pfDub then + exit; + fProj := TCEDubProject(aProject.getProject); + // +end; + +procedure TCEDubProjectEditorWidget.projChanged(aProject: ICECommonProject); +begin + if fProj = nil then + exit; + if aProject.getProject <> fProj then + exit; + // + if Visible then + updateGui; +end; + +procedure TCEDubProjectEditorWidget.projClosing(aProject: ICECommonProject); +begin + if fProj = nil then + exit; + if aProject.getProject <> fProj then + exit; + fProj := nil; + // + updateGui; +end; + +procedure TCEDubProjectEditorWidget.projFocused(aProject: ICECommonProject); +begin + fProj := nil; + if aProject.getFormat <> pfDub then + exit; + fProj := TCEDubProject(aProject.getProject); + // + if Visible then + updateGui; +end; + +procedure TCEDubProjectEditorWidget.projCompiling(aProject: ICECommonProject); +begin +end; +{$ENDREGION} + +{$REGION GUI -------------------------------------------------------------------} +procedure TCEDubProjectEditorWidget.propTreeSelectionChanged(Sender: TObject); +begin + fSelectedNode := nil; + if propTree.Selected = nil then exit; + // + fSelectedNode := propTree.Selected; + updateValueEditor; +end; + +procedure TCEDubProjectEditorWidget.setJsonValueFromEditor; +var + dat: TJSONData; + vFloat: TJSONFloat; + vInt: integer; + vInt64: int64; + vBool: boolean; +begin + if fSelectedNode = nil then exit; + if fSelectedNode.Data = nil then exit; + // + dat := TJSONData(fSelectedNode.Data); + case dat.JSONType of + jtNumber: + case TJSONNumber(dat).NumberType of + ntFloat: + if TryStrToFloat(edValue.Text, vFloat) then + dat.AsFloat := vFloat; + ntInt64: + if TryStrToInt64(edValue.Text, vInt64) then + dat.AsInt64 := vInt64; + ntInteger: + if TryStrToInt(edValue.Text, vInt) then + dat.AsInteger := vInt; + end; + jtBoolean: + if TryStrToBool(edValue.Text, vBool) then + dat.AsBoolean := vBool; + jtString: + dat.AsString := edValue.Text; + end; +end; + +procedure TCEDubProjectEditorWidget.updateValueEditor; +var + dat: TJSONData; +begin + edValue.Clear; + if fSelectedNode = nil then exit; + if fSelectedNode.Data = nil then exit; + // + dat := TJSONData(fSelectedNode.Data); + case dat.JSONType of + jtNumber: + case TJSONNumber(dat).NumberType of + ntFloat: + edValue.Text := FloatToStr(dat.AsFloat); + ntInt64: + edValue.Text := IntToStr(dat.AsInt64); + ntInteger: + edValue.Text := IntToStr(dat.AsInteger); + end; + jtBoolean: + edValue.Text := BoolToStr(dat.AsBoolean); + jtString: + edValue.Text := dat.AsString; + end; +end; + +procedure TCEDubProjectEditorWidget.updateGui; + + procedure addPropsFrom(node: TTreeNode; data: TJSONData); + var + i: integer; + c: TTreeNode; + begin + if data.JSONType = jtObject then for i := 0 to data.Count-1 do + begin + c := node.TreeNodes.AddChildObject(node, TJSONObject(data).Names[i], + TJSONObject(data).Items[i]); + case TJSONObject(data).Items[i].JSONType of + jtObject, jtArray: + addPropsFrom(c, TJSONObject(data).Items[i]); + end; + end else if data.JSONType = jtArray then for i := 0 to data.Count-1 do + begin + c := node.TreeNodes.AddChildObject(node, format('item %d',[i]), + TJSONArray(data).Items[i]); + case TJSONArray(data).Items[i].JSONType of + jtObject, jtArray: + addPropsFrom(c, TJSONArray(data).Items[i]); + end; + end; + end; + +begin + propTree.Items.Clear; + if (fProj = nil) or (fProj.json = nil) then + exit; + // + propTree.BeginUpdate; + addPropsFrom(propTree.Items.Add(nil, 'project'), fProj.json); + propTree.EndUpdate; +end; +{$ENDREGION} + +end. + diff --git a/src/ce_main.pas b/src/ce_main.pas index 10047f86..ff713c62 100644 --- a/src/ce_main.pas +++ b/src/ce_main.pas @@ -12,7 +12,7 @@ uses ce_widget, ce_messages, ce_interfaces, ce_editor, ce_projinspect, ce_projconf, ce_search, ce_miniexplorer, ce_libman, ce_libmaneditor, ce_todolist, ce_observer, ce_toolseditor, ce_procinput, ce_optionseditor, ce_symlist, ce_mru, ce_processes, - ce_infos, ce_dubproject, ce_dialogs; + ce_infos, ce_dubproject, ce_dialogs, ce_dubprojeditor; type @@ -209,8 +209,13 @@ type fOptEdWidg: TCEOptionEditorWidget; fSymlWidg: TCESymbolListWidget; fInfoWidg: TCEInfoWidget; + fDubProjWidg: TCEDubProjectEditorWidget; - //TODO-cDUB: widget to edit and view, select config of, a DUB project + //TODO-cDUB: widget to edit and view, select config of, a DUB project. + // DUB format can't be wrapped as published prop so... + // ...visually: displayed as a tree. node = prop name. + // prop value editor in sync with slected node, + // treeview filter. add node, etc. fInitialized: boolean; fRunnableSw: string; @@ -616,6 +621,7 @@ begin fOptEdWidg:= TCEOptionEditorWidget.create(self); fSymlWidg := TCESymbolListWidget.create(self); fInfoWidg := TCEInfoWidget.create(self); + fDubProjWidg:= TCEDubProjectEditorWidget.create(self); getMessageDisplay(fMsgs); @@ -632,6 +638,7 @@ begin fWidgList.addWidget(@fOptEdWidg); fWidgList.addWidget(@fSymlWidg); fWidgList.addWidget(@fInfoWidg); + fWidgList.addWidget(@fDubProjWidg); fWidgList.sort(@CompareWidgCaption); for widg in fWidgList do diff --git a/src/ce_projconf.pas b/src/ce_projconf.pas index ed014cea..9492146a 100644 --- a/src/ce_projconf.pas +++ b/src/ce_projconf.pas @@ -120,6 +120,7 @@ end; procedure TCEProjectConfigurationWidget.projClosing(aProject: ICECommonProject); begin + if fProj = nil then exit; if fProj <> aProject.getProject then exit; inspector.TIObject := nil; @@ -132,6 +133,7 @@ end; procedure TCEProjectConfigurationWidget.projChanged(aProject: ICECommonProject); begin + if fProj = nil then exit; if fProj <> aProject.getProject then exit; if Visible then updateImperative; diff --git a/src/ce_projinspect.pas b/src/ce_projinspect.pas index 72ea900b..fbdd1e2e 100644 --- a/src/ce_projinspect.pas +++ b/src/ce_projinspect.pas @@ -159,6 +159,7 @@ end; procedure TCEProjectInspectWidget.projClosing(aProject: ICECommonProject); begin + if fProject = nil then exit; if fProject <> aProject.getProject then exit; fProject := nil; @@ -179,6 +180,7 @@ end; procedure TCEProjectInspectWidget.projChanged(aProject: ICECommonProject); begin + if fProject = nil then exit; if fProject <> aProject.getProject then exit; if Visible then beginDelayedUpdate;