File "hier.il"
Full Path: /home/analogde/www/VirtualKeyboardSample/SKILL/hier.il
File size: 11.21 KB
MIME-type: text/plain
Charset: utf-8
/***************************************************************
* *
* CCShiHierLayerOps() *
* *
* This function builds and displays the hierarchical layer *
* generation operations form. It is really intended to be run *
* from a menu item or a bindkey because the code stores the *
* cellview and techfile on the form. The form is intended to *
* be similar to the existing "Layer Generation" form for easy *
* familiarity for the end-users. *
* *
***************************************************************/
procedure(CCShiHierLayerOps()
let( (cv techId layer1 layer2 outLayer operation level eqLab form)
;; when the cellview is valid and we can get the techfile
when((cv = geGetEditCellView()) &&
(techId = techGetTechFile(cv))
;; for each layer field create a cyclic layer field with
;; the appropriate arguments and values
foreach(fieldName '(layer1 layer2 outLayer)
set(fieldName hiCreateLayerCyclicField(
;; the technology file Id
techId
;; the prompt for the field (not displayed, see below)
strcat(upperCase(substring(fieldName 1 1)) substring(fieldName 2))
;; the callback is empty/unused
""
;; the list of layer choices
leGetValidLayerList(techId) || list(leGetEntryLayer(techId))
;; the default layer setting
leGetEntryLayer(techId)
;; the name of the field
fieldName); hiCreateLayerCyclicField
); set
); foreach
;; create the cyclic field for the layer operation
operation = hiCreateCyclicField(
?name 'operation
?choices list("AND" "AND NOT" "OR" "XOR" "GROW BY")
?defValue "AND"
?prompt "Layer Operation"
?callback "CCSoperationFieldCB()"
); hiCreateCyclicField
;; create the integer field for the hierarchy depth
level = hiCreateIntField(
?name 'level
?prompt "Hierarchy Depth"
?value geGetCellViewWindow(cv)~>stopLevel || 0
?acceptNil nil
?defValue 0
?range list(0 nil)
); hiCreateIntField
;; create the = label
eqLab = hiCreateLabel(
?name 'eqLab
?labelText "="
); hiCreateLabel
;; create the form, the layout is based upon the existing
;; "Layer Generation" form
form = hiCreateAppForm(
?name 'CCShiHierLayerOps
?formTitle "Hierarchical Layer Generation"
?buttonLayout 'OKCancelApply
?fields list( list(layer1 0:0 100:30 0)
list(operation 135:0 100:30 0)
list(layer2 225:0 100:30 0)
list(eqLab 360:0 30:30 0)
list(outLayer 380:0 100:30 0)
list(level 520:0 130:30 100) )
?callback 'CCShiHierLayerOpsCB
); hiCreateAppForm
;; store the layer2 field, the original is removed from the
;; form if the operation is changed to "GROW BY", use this
;; storage to be able to restore it later
form->store = layer2
;; store the current cellview on the form, this is a convenient
;; way of storing and passing the cellview to the callback
form->cellView = cv
;; display the form
hiDisplayForm(form)
); when we can get the techfile for the current cellview
); let
); procedure CCShiHierLayerOps
/*****************************************************************
* *
* CCSoperationFieldCB() *
* *
* This function is called when the operation field is changed. *
* It is used to add an integer field in place of the second *
* layer field when performing a "GROW BY" operation, or to put *
* the second layer field back again if the operation is changed *
* back to something other than this setting. The last operation *
* is stored on the form to keep track of what was just done. *
* *
*****************************************************************/
procedure(CCSoperationFieldCB()
let( (form op)
;; get the current form (should be the one that caused this
;; callback to be called in the first place
form = hiGetCurrentForm()
;; get the value of the operation cyclic field
op = form->operation->value
;; unless the operation is the same as it last was
unless(op == form->lastOp
cond(
;; if the operation is "GROW BY" then delete the layer2
;; field and add a size floating point field in its place
(op == "GROW BY"
hiDeleteField(form form->layer2->hiFieldSym)
hiAddField(form
list(hiCreateFloatField(
?name 'size
?value 1.0
?acceptNil nil
?prompt "Size"
?range list(0 nil)
)
list(225 0) list(100 30) 0)
); hiAddField
)
;; if the last operation was "GROW BY" (and the current
;; operation is not, since that is handled by the condition
;; above) then delete the size field and put the layer2
;; field back
(form->lastOp == "GROW BY"
hiDeleteField(form form->size->hiFieldSym)
hiAddField(form
list(form->store list(225 0) list(100 30) 0)
)
)
); cond
;; store the operation on the form
form->lastOp = op
); unless
); let
); procedure CCSoperationFieldCB
/****************************************************************
* *
* CCSgetLayerPurposePair( r_form s_field ) *
* *
* A function to take the value of the form's layer cyclic field *
* and convert it into a layer-purpose pair list *
* *
****************************************************************/
procedure(CCSgetLayerPurposePair(form field "rs")
let( (lpp)
;; get the value of the form field passed in
lpp = getq(get(form field) value)
;; then get the part that gives the layer and purpose
lpp = parseString(cadddr(lpp))
;; then remove the () from around the purpose and return
lpp = setcdr(lpp parseString(cadr(lpp) "()"))
); let
); procedure CCSgetLayerPurposePair
/*****************************************************************
* *
* CCShiHierLayerOpsCB( r_form ) *
* *
* This procedure is an interface to the CCShierLayerOps function *
* when the form is used to invoke that function. Most values are *
* taken from the field values directly, except for the layer *
* cyclic fields which are processed from the field value to a *
* layer-purpose pair entry, and the cellview is obtained from *
* the value stored on the form *
* *
*****************************************************************/
procedure(CCShiHierLayerOpsCB(form "r")
CCShierLayerOps(
?cv form->cellView
?layer1 CCSgetLayerPurposePair(form 'layer1)
?layer2 unless(form->size CCSgetLayerPurposePair(form 'layer2))
?outLayer CCSgetLayerPurposePair(form 'outLayer)
?op form->operation->value
?size form->size->value
?level form->level->value
); CCShierLayerOps
); procedure CCShiHierLayerOpsCB
/*********************************************************************
* *
* CCShierLayerOps( *
* [?cv geGetEditCellView() | d_cellView] *
* [?layer1 g_layer1] *
* [?layer2 g_layer2] *
* [?outLayer g_outLayer] *
* [?op t_layerOperation] *
* [?size n_size] *
* [?level 0 | x_hierarchyDepth] ) *
* *
* A function to perform layer generation with the option of working *
* hierarchically. The function takes all shapes on the named input *
* layers (flattened in a scratch cellview if working hierarchically) *
* and uses the dbLayer functions to apply the operation to create *
* data on the "outLayer" and then copy these back to the original *
* cellview. If the "size" argument is given it takes precedence *
* over the layer2 argument, this assumes that the operation is *
* "GROW BY" *
* *
*********************************************************************/
procedure(CCShierLayerOps(@key (cv geGetEditCellView())
layer1 layer2 outLayer op size (level 0) "dgggtgx")
let((newcv layer1Name layer2Name layerOp newInst newShapes)
when(and(cv equal(cv~>cellViewType "maskLayout"))
;; create a new scratch cell for intermediate operations
newcv = dbOpenCellViewByType(cv~>libName
symbolToString(gensym(cv~>cellName))
"layout"
"maskLayout" "s"
)
layer1Name = stringp(layer1)&&layer1 || pairp(layer1)&&car(layer1)
layer2Name = stringp(layer2)&&layer2 || pairp(layer2)&&car(layer2)
printf("* %s \n" layer1Name )
printf("* %s \n" layer2Name )
;; copy each shape & instance to the new scratch cell
;; NOTE: "textDisplays" will not be copied using this method
foreach(shape
setof(shp cv~>shapes shp~>objType!="textDisplay")
dbCopyFig(shape newcv)
)
;; when the hierarchy depth is greater than 0, copy the instances,
;; and then flatten each instance by the number of levels desired
;; Only perform the copy and flatten if level is greater than 0
when(level>0
foreach(inst cv~>instances
;; when the instance was copied, flatten the new instance
when(newInst=dbCopyFig(inst newcv)
dbFlattenInst(newInst level t t t)
); when the instance is copied
); foreach
); when the hierarchy depth is > 0
;; create new shapes based on the interaction (AND in this
;; example) of shapes on certain layers ("metal1" and "poly1"
;; in this example) and store the list for the copy back
layerOp = case(op
("AND" 'dbLayerAnd)
("AND NOT" 'dbLayerAndNot)
("OR" 'dbLayerOr)
("XOR" 'dbLayerXor)
("GROW BY" 'dbLayerSize)
)
;; use "apply" to pass all the arguments to the appropraite
;; dbLayer function
newShapes = apply(layerOp list(newcv outLayer
setof(shape newcv~>shapes shape~>layerName == layer1Name)
;; if the size argument is non-nil use this for "grow by"
or(size setof(shape newcv~>shapes shape~>layerName == layer2Name)) )
)
;; copy back each new generated shape to the original layout
newShapes = foreach(mapcar shape newShapes dbCopyFig(shape cv))
;; close the scratch cellview
dbClose(newcv)
;; return the new shape list in the original cellview, this is
;; useful when this function is called directly (not via the UI)
;;newShapes
); when
); let
); procedure CCShierLayerOps