/***************************************************************
*                                                              *
*                     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

	println("MAIN")


    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

/****************************************************************
*                                                               *
*           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)

	println("DEUX")

    ;; 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")

	println("TROIS")


  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)

	println("QUATRE")


  when(and(cv equal(cv~>cellViewType "maskLayout"))
    	
	    newcv = dbOpenCellViewByType(cv~>libName
				         symbolToString(gensym(cv~>cellName))
				         "layout"
			   	         "maskLayout" "s"
	   			        )

	 
		layer1Name = "METAL2"
	        layer2Name = "METAL2"
		outLayer = "METAL2"
		size = nil
	   
		    foreach(shape 
		      setof(shp cv~>shapes shp~>objType!="textDisplay")
		      dbCopyFig(shape newcv)
		    )

		level = 2

    
    		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

m1 = setof(x newcv~>shapes x~>lpp=='("METAL2" "drawing"))

layerOp = "dbLayerAnd"
    
    ;; 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))

	foreach(mapcar shape m1 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 
