Grrr Posted September 9, 2016 Share Posted September 9, 2016 Hi, guys My question may be fairly complex, so I hope someone could answer: Does anyone know what is the programmatical relation between the Group Layer Filters and Layers? - or where I can find it? I've found where are the Group Layer Filters located (using VLAX), but I think the only useful information about them I have at this point are their names. Shouldn't each one of them have a "count" property of the number of layers inside them? Or atleast every layer object to have some connection-info(method or property) with the Group Layer Filter where its located within. In order to find any relation I have dumped: - Layers collection, - Layers collection Extended Dict, - Every item inside of Layers collection Extended Dict, - "ACAD_LAYERFILTERS" collection (located inside Layers Coll Extended Dict), - Every item inside of "ACAD_LAYERFILTERS" collection, - Active Layer, - Active Layer's Extended Dict Heres a sample drawing using (C:ForTest) : Group Layer Filters Test.dwg Here is the (shortened) info I got, using VLIDE's console: ; Helper functions: (defun DT ( o / ) (if (= (type o) 'VLA-OBJECT) (vlax-dump-object o T))) ; Dump True (I'm using it as a shortcut) (defun GetExtDict ( o / ) (if (and (= (type o) 'VLA-OBJECT) (vlax-method-applicable-p o 'GetExtensionDictionary)) (vlax-invoke o 'GetExtensionDictionary))) (defun DTColl ( coll / ) (if (= (type coll) 'VLA-OBJECT) (vlax-for o coll (vlax-dump-object o T)))) ; Dump True (everything inside of a collection) (defun Coll->Lst ( #Collection / Lst ) (vlax-for o #Collection (setq Lst (cons o Lst))) (reverse Lst)); convert Collection into List ; Start digging: (setq AcLay (vla-get-ActiveLayer (vla-get-ActiveDocument (vlax-get-acad-object)))) (setq ExtDictAcLay (GetExtDict AcLay)) (setq LayColl (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object)))) (setq ExtDictCollOfLayersColl (GetExtDict LayColl)) ; (DTColl ExtDictCollOfLayersColl) ; inside of it there are: ACAD_LAYERFILTERS ACAD_LAYERSTATES ACLYDICTIONARY (setq LAYERFILTERS (vla-item ExtDictCollOfLayersColl "ACAD_LAYERFILTERS")) (setq LAYERSTATES (vla-item ExtDictCollOfLayersColl "ACAD_LAYERSTATES")) (setq ACLYDICTIONARY (vla-item ExtDictCollOfLayersColl "ACLYDICTIONARY")) _$ (DTcoll LAYERFILTERS) ; IAcadXRecord: XRecord objects are used to store and manage arbitrary data ; Property values: ; Application (RO) = #<VLA-OBJECT IAcadApplication 00007ff78a999110> ; Document (RO) = #<VLA-OBJECT IAcadDocument 0000002a7ec52b78> ; Handle (RO) = "20C" ; HasExtensionDictionary (RO) = 0 ; Name = "Group1" ; ObjectID (RO) = 42 ; ObjectName (RO) = "AcDbXrecord" ; OwnerID (RO) = 43 ; TranslateIDs = -1 ; Methods supported: ; Delete () ; GetExtensionDictionary () ; GetXData (3) ; GetXRecordData (2) ; SetXData (2) ; SetXRecordData (2) ; IAcadXRecord: XRecord objects are used to store and manage arbitrary data ; Property values: ; Application (RO) = #<VLA-OBJECT IAcadApplication 00007ff78a999110> ; Document (RO) = #<VLA-OBJECT IAcadDocument 0000002a7ec52b78> ; Handle (RO) = "20E" ; HasExtensionDictionary (RO) = 0 ; Name = "Group2" ; ObjectID (RO) = 44 ; ObjectName (RO) = "AcDbXrecord" ; OwnerID (RO) = 43 ; TranslateIDs = -1 ; Methods supported: ; Delete () ; GetExtensionDictionary () ; GetXData (3) ; GetXRecordData (2) ; SetXData (2) ; SetXRecordData (2) ; IAcadXRecord: XRecord objects are used to store and manage arbitrary data ; Property values: ; Application (RO) = #<VLA-OBJECT IAcadApplication 00007ff78a999110> ; Document (RO) = #<VLA-OBJECT IAcadDocument 0000002a7ec52b78> ; Handle (RO) = "210" ; HasExtensionDictionary (RO) = 0 ; Name = "Group3" ; ObjectID (RO) = 45 ; ObjectName (RO) = "AcDbXrecord" ; OwnerID (RO) = 43 ; TranslateIDs = -1 ; Methods supported: ; Delete () ; GetExtensionDictionary () ; GetXData (3) ; GetXRecordData (2) ; SetXData (2) ; SetXRecordData (2) ; IAcadXRecord: XRecord objects are used to store and manage arbitrary data ; Property values: ; Application (RO) = #<VLA-OBJECT IAcadApplication 00007ff78a999110> ; Document (RO) = #<VLA-OBJECT IAcadDocument 0000002a7ec52b78> ; Handle (RO) = "212" ; HasExtensionDictionary (RO) = 0 ; Name = "Group4" ; ObjectID (RO) = 46 ; ObjectName (RO) = "AcDbXrecord" ; OwnerID (RO) = 43 ; TranslateIDs = -1 ; Methods supported: ; Delete () ; GetExtensionDictionary () ; GetXData (3) ; GetXRecordData (2) ; SetXData (2) ; SetXRecordData (2) T _$ You may try yourself the above lines, to "dig" / inspect. If you can't open the dwg, use the following test code to re-create the Group Layer Filters and Layers test dwg: ; To create the test Layers with their LayerGroupFilters: (defun C:ForTest ( / LayGroupNames LayLstGroup1 LayLstGroup2 LayLstGroup3 LayLstGroup4 n) (defun CreateLayer ( #Name / ) (entmake (list (cons 0 "LAYER") (cons 100 "AcDbSymbolTableRecord") (cons 100 "AcDbLayerTableRecord") (cons 2 #Name) (cons 70 0) ) ) ) (setq LayGroupNames '("Group1" "Group2" "Group3" "Group4")) (setq LayLstGroup1 '("Group1-Lay1" "Group1-Lay2" "Group1-Lay3" "Group1-Lay4" "Group1-Lay5" "Group1-Lay6" "Group1-Lay7") LayLstGroup2 '("Group2-Lay1" "Group2-Lay2" "Group2-Lay3" "Group2-Lay4" "Group2-Lay5" "Group2-Lay6" "Group2-Lay7") LayLstGroup3 '("Group3-Lay1" "Group3-Lay2" "Group3-Lay3" "Group3-Lay4" "Group3-Lay5" "Group3-Lay6" "Group3-Lay7") LayLstGroup4 '("Group4-Lay1" "Group4-Lay2" "Group4-Lay3" "Group4-Lay4" "Group4-Lay5" "Group4-Lay6" "Group4-Lay7") ) (setq n 0) (foreach x (list LayLstGroup1 LayLstGroup2 LayLstGroup3 LayLstGroup4) (mapcar 'CreateLayer x) (command "._-layer" "filter" "new" "property" "All" (strcat "NAME==\"" (nth n LayGroupNames) "*\"") (nth n LayGroupNames) "X" nil) (setq n (1+ n)) ) (princ) ); defun C:ForTest The reason is that I was curious about a thread with "a simple request" from AUGI's forum. Where the user asked if its possible to rename a group of particular layers, by adding prefix of the name of the Layer Group Filter they're located in. However thats not my goal. Quote Link to comment Share on other sites More sharing options...
Grrr Posted October 13, 2016 Author Share Posted October 13, 2016 Okay... I did a a small progress today: (defun C:test ( / ld AllLyrNames LayersColl LFtContainer MyLayerFilterNames Lst FtsLst) (while (setq ld (tblnext "LAYER" (not ld))) (setq AllLyrNames (cons (cdr (assoc 2 ld)) AllLyrNames)) ) (setq LayersColl (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object)))) (setq LFtContainer (vla-item (vla-GetExtensionDictionary LayersColl) "ACAD_LAYERFILTERS")) (vlax-map-collection LFtContainer '(lambda (x) (setq MyLayerFilterNames (cons (vla-get-Name x) MyLayerFilterNames)))) ; (if MyLayerFilterNames ; (foreach x (reverse MyLayerFilterNames) ; (print (HowMyLayerFilterIsCreated x)) ; ) ; ) (if MyLayerFilterNames (progn (if (not Lst) (setq Lst (list))) (setq FtsLst (mapcar 'HowMyLayerFilterIsCreated MyLayerFilterNames)) (foreach Ft FtsLst (setq Lst (append Lst (mapcar '(lambda (x) (if (wcmatch x (cadr Ft)) (cons (car Ft) x))) AllLyrNames))) ) (setq Lst (reverse (vl-remove nil Lst))) (foreach x Lst (print x)) ) ); if MyLayerFilterNames (princ) ); defun C:test (defun HowMyLayerFilterIsCreated ( LyrFilterName / LayersColl LFtContainer MyLayerFilter XRecordDataLst MyLayerFilterXRecordDataType MyLayerFilterXRecordData ) (if (and (setq LayersColl (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object)))) (setq LFtContainer (vla-item (vla-GetExtensionDictionary LayersColl) "ACAD_LAYERFILTERS")) (setq MyLayerFilter (vla-item LFtContainer LyrFilterName)) ) (progn (vla-GetXRecordData MyLayerFilter 'MyLayerFilterXRecordDataType 'MyLayerFilterXRecordData) (setq XRecordDataLst (mapcar 'vlax-variant-value (vlax-safearray->list MyLayerFilterXRecordData))) ) ) XRecordDataLst );| defun HowMyLayerFilterIsCreated |; (or (vlax-get-acad-object) (vl-load-com)) The printed result from the above attached .dwg looks like this: Command: TEST ("Group1" . "Group1-Lay1") ("Group1" . "Group1-Lay2") ("Group1" . "Group1-Lay3") ("Group1" . "Group1-Lay4") ("Group1" . "Group1-Lay5") ("Group1" . "Group1-Lay6") ("Group1" . "Group1-Lay7") ("Group2" . "Group2-Lay1") ("Group2" . "Group2-Lay2") ("Group2" . "Group2-Lay3") ("Group2" . "Group2-Lay4") ("Group2" . "Group2-Lay5") ("Group2" . "Group2-Lay6") ("Group2" . "Group2-Lay7") ("Group3" . "Group3-Lay1") ("Group3" . "Group3-Lay2") ("Group3" . "Group3-Lay3") ("Group3" . "Group3-Lay4") ("Group3" . "Group3-Lay5") ("Group3" . "Group3-Lay6") ("Group3" . "Group3-Lay7") ("Group4" . "Group4-Lay1") ("Group4" . "Group4-Lay2") ("Group4" . "Group4-Lay3") ("Group4" . "Group4-Lay4") ("Group4" . "Group4-Lay5") ("Group4" . "Group4-Lay6") ("Group4" . "Group4-Lay7") I only need to figure out how to structure this Lst quote like this: '("Group1" . '("Group1-Lay1" "Group1-Lay2" "Group1-Lay3" "Group1-Lay5" "Group1-Lay6" "Group1-Lay7")) '("Group2" . '("Group2-Lay1" "Group2-Lay2" "Group2-Lay3" "Group2-Lay5" "Group2-Lay6" "Group2-Lay7")) '("Group3" . '("Group3-Lay1" "Group3-Lay2" "Group3-Lay3" "Group3-Lay5" "Group3-Lay6" "Group3-Lay7")) '("Group4" . '("Group4-Lay1" "Group4-Lay2" "Group4-Lay3" "Group4-Lay5" "Group4-Lay6" "Group4-Lay7")) So it would be more readable (atleast for me). Quote Link to comment Share on other sites More sharing options...
BIGAL Posted October 14, 2016 Share Posted October 14, 2016 Maybe do it backwards look at the car = group1 add "Group1-layername" to a temporary "lsttemp" get next if = group1 add "Group1-layername" to "lsttemp" keep going. Once group1 /= group2 make your new layer group1 list ("group1" . '(lsttemp)) replace lsttemp as nil and do agian for group2. hope it makes sense. groupname = "Group1" lsttemp = ("Group1-Lay1" "Group1-Lay2" "Group1-Lay3" "Group1-Lay5" "Group1-Lay6" "Group1-Lay7")) Quote Link to comment Share on other sites More sharing options...
Roy_043 Posted October 14, 2016 Share Posted October 14, 2016 Are the layer filters in the drawing really 'group filters'? I can't be sure since BricsCAD only supports layer property filters, but the filters in the drawing seem to be of that type. Quote Link to comment Share on other sites More sharing options...
Grrr Posted October 14, 2016 Author Share Posted October 14, 2016 Maybe do it backwards look at the car = group1 add "Group1-layername" to a temporary "lsttemp" get next if = group1 add "Group1-layername" to "lsttemp" keep going. Once group1 /= group2 make your new layer group1 list ("group1" . '(lsttemp)) replace lsttemp as nil and do agian for group2. hope it makes sense. groupname = "Group1" lsttemp = ("Group1-Lay1" "Group1-Lay2" "Group1-Lay3" "Group1-Lay5" "Group1-Lay6" "Group1-Lay7")) Yes BIGAL, I was thinking about something similar, but perhaps I could go back even more, and modify the "Lst" creation to suit my previous discovery (from the commented part of the code above): (defun C:test ( / LayersColl LFtContainer MyLayerFilterNames ) (setq LayersColl (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object)))) (setq LFtContainer (vla-item (vla-GetExtensionDictionary LayersColl) "ACAD_LAYERFILTERS")) (vlax-map-collection LFtContainer '(lambda (x) (setq MyLayerFilterNames (cons (vla-get-Name x) MyLayerFilterNames)))) (if MyLayerFilterNames (foreach x (reverse MyLayerFilterNames) (print (HowMyLayerFilterIsCreated x)) ) ) (princ) ); defun C:test (defun HowMyLayerFilterIsCreated ( LyrFilterName / LayersColl LFtContainer MyLayerFilter XRecordDataLst MyLayerFilterXRecordDataType MyLayerFilterXRecordData ) (if (and (setq LayersColl (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object)))) (setq LFtContainer (vla-item (vla-GetExtensionDictionary LayersColl) "ACAD_LAYERFILTERS")) (setq MyLayerFilter (vla-item LFtContainer LyrFilterName)) ) (progn (vla-GetXRecordData MyLayerFilter 'MyLayerFilterXRecordDataType 'MyLayerFilterXRecordData) (setq XRecordDataLst (mapcar 'vlax-variant-value (vlax-safearray->list MyLayerFilterXRecordData))) ) ) XRecordDataLst );| defun HowMyLayerFilterIsCreated |; (or (vlax-get-acad-object) (vl-load-com)) I had this result: Command: TEST ("Group1" "Group1*" "*" "*" 0 "*" "*") ("Group2" "Group2*" "*" "*" 0 "*" "*") ("Group3" "Group3*" "*" "*" 0 "*" "*") ("Group4" "Group4*" "*" "*" 0 "*" "*") Maybe doing some wcmatch for the cadr's with each layer name, and somehow cons with the car's (representing the group names). I think that these lists I have, are related to this line: Are the layer filters in the drawing really 'group filters'? I can't be sure since BricsCAD only supports layer property filters, but the filters in the drawing seem to be of that type. I'm afraid you are correct Roy, as I'm using this line to create these sample property filters: (command "._-layer" "filter" "new" "property" "All" (strcat "NAME==\"" (nth n LayGroupNames) "*\"") (nth n LayGroupNames) "X" nil) I really didn't knew the difference between the two: But now I see that upon double-clicking on the folder with the groupfilter name, the above dialog "Layer Filter Properties" appears only on the created "Property" filters, and not the "Group" ones. Although I'm not sure what infomation I will find for the "GROUP" ones with (HowMyLayerFilterIsCreated). I will experiment further, atleast I now got the "info" I needed... so it became a question of list construction/manipulation. Quote Link to comment Share on other sites More sharing options...
Roy_043 Posted October 15, 2016 Share Posted October 15, 2016 @Grrr: The item method will error out if the item is not in the collection: (vla-item (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))) "DoesNotExist") => Error You can use a "vl-catch-all construction" to solve this: (KGA_Sys_Apply 'vla-item (list (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))) "DoesNotExist")) ;;; ====================================================================== ;;; Lib function: KGA_Sys_Apply ;;; Purpose: Shortcut for standard "vl-catch-all construction". ;;; Arguments: expr - Expression to evaluate. ;;; varLst - List of variables. ;;; Return value: Varies. Note: A nil value can mean two things: there was ;;; an error or the expression returned nil. ;;; Use (KGA_Sys_ApplyAlt) if this is a problem. ;;; Remarks: None. ;;; Examples: ;;; (KGA_Sys_Apply 'strcat '("a" "bb" "ccc" 1)) => nil ;;; (KGA_Sys_Apply 'strcat '("a" "bb" "ccc" "dddd")) => "abbcccdddd" ;;; ====================================================================== (defun KGA_Sys_Apply (expr varLst / ret) (if (not (vl-catch-all-error-p (setq ret (vl-catch-all-apply expr varLst)))) ret ) ) ;;; Similar to (KGA_Sys_Apply) but the return value is T or nil (there was an error). (defun KGA_Sys_ApplyAlt (expr varLst) (not (vl-catch-all-error-p (vl-catch-all-apply expr varLst))) ) Quote Link to comment Share on other sites More sharing options...
Grrr Posted October 15, 2016 Author Share Posted October 15, 2016 Yeah Roy, I forgot to "error-trap" these. I prefer to use this: ; modeT - if is set to true: then the return would be 'T or nil, otherwise the returned value or nil ; Examples: ;;; (ErrCatch nil '/ '(4 2)) -> 2 ;;; (ErrCatch T '/ '(4 2)) -> T ;;; (ErrCatch nil '/ '(4 0)) -> nil ;;; (ErrCatch T '/ '(4 0)) -> nil ;;; (defun ErrCatch ( modeT func varLst / rtn ) (if (not (vl-catch-all-error-p (setq rtn (vl-catch-all-apply func varLst)))) (if modeT 'T rtn)) ) Example: ; No layer filters in this drawing yet: _$ (setq LFtContainer (ErrCatch nil 'vla-item (list (vla-GetExtensionDictionary LayersColl) "ACAD_LAYERFILTERS"))) nil ; After creating the layer filters: _$ (setq LFtContainer (ErrCatch nil 'vla-item (list (vla-GetExtensionDictionary LayersColl) "ACAD_LAYERFILTERS"))) #<VLA-OBJECT IAcadDictionary 0000000abe59ea88> _$ (setq LFtContainer (ErrCatch T 'vla-item (list (vla-GetExtensionDictionary LayersColl) "ACAD_LAYERFILTERS"))) T Thanks! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.