diff --git a/docs/img/dub_project_editor.png b/docs/img/dub_project_editor.png index 6f4a6b3e..ccb06a7b 100644 Binary files a/docs/img/dub_project_editor.png and b/docs/img/dub_project_editor.png differ diff --git a/docs/widgets_dub_project_editor.md b/docs/widgets_dub_project_editor.md index 1afc7ad2..358bc30b 100644 --- a/docs/widgets_dub_project_editor.md +++ b/docs/widgets_dub_project_editor.md @@ -14,8 +14,10 @@ DUB projects with the [SDL format](http://code.dlang.org/package-format?lang=sdl A property value can be modified in the field at the bottom. New values always require an extra validation. New properties can be added or removed: -- : Removes the selected property. Note that the effect is not reflected until the project is saved as a file (since Coedit does not communicate directly with DUB). - : Shows a small dialog that allows to add a new value, a new array or a new object. +- : Removes the selected property. Note that the effect is not reflected until the project is saved as a file (since Coedit does not communicate directly with DUB). +- : Duplicates the selected object. Can be used to clone a configuration or a build type. +- : Updates the source files list. ![](img/dub_add_property.png) diff --git a/icons/other/copy.png b/icons/other/copy.png index a9f31a27..8dd48c49 100644 Binary files a/icons/other/copy.png and b/icons/other/copy.png differ diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index 2a6182fb..ed4ac89f 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -525,7 +525,7 @@ - + diff --git a/src/ce_dubprojeditor.lfm b/src/ce_dubprojeditor.lfm index 5138cacd..6237be39 100644 --- a/src/ce_dubprojeditor.lfm +++ b/src/ce_dubprojeditor.lfm @@ -2,25 +2,25 @@ inherited CEDubProjectEditorWidget: TCEDubProjectEditorWidget Left = 771 Height = 424 Top = 245 - Width = 402 + Width = 407 Caption = 'DUB project editor' ClientHeight = 424 - ClientWidth = 402 + ClientWidth = 407 inherited Back: TPanel Height = 424 - Width = 402 + Width = 407 ClientHeight = 424 - ClientWidth = 402 + ClientWidth = 407 inherited Content: TPanel Height = 388 - Width = 402 + Width = 407 ClientHeight = 388 - ClientWidth = 402 + ClientWidth = 407 object propTree: TTreeView[0] Left = 4 Height = 352 Top = 4 - Width = 394 + Width = 399 Align = alClient BorderSpacing.Around = 4 DefaultItemHeight = 16 @@ -38,24 +38,24 @@ inherited CEDubProjectEditorWidget: TCEDubProjectEditorWidget Left = 2 Height = 26 Top = 360 - Width = 398 + Width = 403 Align = alBottom BorderSpacing.Around = 2 BevelOuter = bvNone ClientHeight = 26 - ClientWidth = 398 + ClientWidth = 403 TabOrder = 1 object edProp: TEdit Left = 2 Height = 22 Top = 2 - Width = 366 + Width = 371 Align = alClient BorderSpacing.Around = 2 TabOrder = 0 end object btnAcceptProp: TSpeedButton - Left = 370 + Left = 375 Height = 26 Hint = 'accept property value' Top = 0 @@ -68,9 +68,9 @@ inherited CEDubProjectEditorWidget: TCEDubProjectEditorWidget end end inherited toolbar: TCEToolBar - Width = 394 + Width = 399 object btnUpdate: TCEToolButton[0] - Left = 57 + Left = 85 Hint = 'reload project' Top = 0 Caption = 'btnUpdate' @@ -96,21 +96,12 @@ inherited CEDubProjectEditorWidget: TCEDubProjectEditorWidget resourceName = 'TEXTFIELD_ADD' scaledSeparator = False end - object button3: TCEToolButton[3] - Left = 85 - Height = 28 - Top = 0 - Width = 11 - Caption = 'button3' - Style = tbsDivider - scaledSeparator = False - end - object fltEdit: TTreeFilterEdit[4] - Left = 96 + object fltEdit: TTreeFilterEdit[3] + Left = 128 Height = 26 Hint = 'filter properties' Top = 2 - Width = 296 + Width = 269 ButtonWidth = 23 NumGlyphs = 1 Align = alRight @@ -120,6 +111,24 @@ inherited CEDubProjectEditorWidget: TCEDubProjectEditorWidget TabOrder = 0 FilteredTreeview = propTree end + object btnCloneObject: TCEToolButton[4] + Left = 57 + Hint = 'clone selected object' + Top = 0 + Caption = 'btnCloneObject' + OnClick = btnCloneObjectClick + resourceName = 'COPY' + scaledSeparator = False + end + object button1: TCEToolButton[5] + Left = 113 + Height = 28 + Top = 0 + Width = 15 + Caption = 'button1' + Style = tbsDivider + scaledSeparator = False + end end end inherited contextMenu: TPopupMenu diff --git a/src/ce_dubprojeditor.pas b/src/ce_dubprojeditor.pas index f5ac5336..d584bc6a 100644 --- a/src/ce_dubprojeditor.pas +++ b/src/ce_dubprojeditor.pas @@ -40,6 +40,7 @@ type TCEDubProjectEditorWidget = class(TCEWidget, ICEProjectObserver) btnAcceptProp: TSpeedButton; btnAddProp: TCEToolButton; + btnCloneObject: TCEToolButton; btnDelProp: TCEToolButton; btnUpdate: TCEToolButton; edProp: TEdit; @@ -52,6 +53,7 @@ type procedure btnAddPropClick(Sender: TObject); procedure btnDelPropClick(Sender: TObject); procedure btnRefreshClick(Sender: TObject); + procedure btnCloneObjectClick(Sender: TObject); procedure MenuItem1Click(Sender: TObject); procedure propTreeSelectionChanged(Sender: TObject); private @@ -317,18 +319,23 @@ end; {$REGION Editor ----------------------------------------------------------------} procedure TCEDubProjectEditorWidget.propTreeSelectionChanged(Sender: TObject); +var + tpe: TJSONtype; begin fSelectedNode := nil; btnDelProp.Enabled := false; btnAddProp.Enabled := false; + btnCloneObject.Enabled := false; if propTree.Selected.isNil then exit; fSelectedNode := propTree.Selected; + tpe := TJSONData(fSelectedNode.Data).JSONType; btnDelProp.Enabled := (fSelectedNode.Level > 0) and (fSelectedNode.Text <> 'name') and fSelectedNode.data.isNotNil; + btnAddProp.Enabled := tpe in [jtObject, jtArray]; + btnCloneObject.Enabled := (tpe = jtObject) and (fSelectedNode.Level > 0); updateValueEditor; - btnAddProp.Enabled := TJSONData(fSelectedNode.Data).JSONType in [jtObject, jtArray]; end; procedure TCEDubProjectEditorWidget.btnAcceptPropClick(Sender: TObject); @@ -418,6 +425,52 @@ begin fProj.loadFromFile(fProj.filename); end; +procedure TCEDubProjectEditorWidget.btnCloneObjectClick(Sender: TObject); +var + dat: TJSONData; + prt: TJSONData; + arr: TJSONArray; + obj: TJSONObject; + nme: string = ''; + inm: string; + idx: integer = 0; +begin + if fSelectedNode.isNil or fSelectedNode.Data.isNil or fProj.isNil or + fSelectedNode.Parent.Data.isNil then + exit; + + dat := TJSONData(fSelectedNode.Data); + prt := TJSONData(fSelectedNode.Parent.Data); + + if ((prt.JSONType <> jtArray) and (prt.JSONType <> jtObject)) or + (dat.JSONType <> jtObject) then + exit; + + dat := dat.Clone; + if prt.JSONType = jtArray then + begin + fProj.beginModification; + arr := TJSONArray(prt); + arr.Insert(arr.Count-1, dat); + fProj.endModification; + end + else + begin + if not InputQuery('Clone object', 'name of the clone', nme) then + exit; + fProj.beginModification; + obj := TJSONObject(prt); + inm := nme; + while obj.IndexOfName(inm) <> -1 do + begin + inm := format('%s_%d', [nme, idx]); + idx += 1; + end; + obj.Add(inm, dat); + fProj.endModification; + end; +end; + procedure TCEDubProjectEditorWidget.MenuItem1Click(Sender: TObject); begin if fProj.isNil or not fProj.filename.fileExists then