/*  Title: Block Repeat Script

    Author: Sola Grantham 
        (with much cribbing of interface code from crowdomatic_0.2 and
        many thanks to its author, the mighty graf salamander (and his
        army of invisible squirrels))

    Date: Oct 2, 2008

    Purpose:  Scriptographer script for replicating existing objects 
              in a block repeat pattern

    Todo later: Make it play nicely with layers. 
                Add ability to base additional 
		    rotation/translation/scale on the i, j index
              

    How to use: run script, chose tiling parameters
                (optional: make a "Tiles" layer, and do "generate Tiles"
                select your objects and click "Assign Shapes"
		Create an output layer and make it active
		run "Replicate"
		(optional, hide original shapes)

    Hints for most regular results: (not that you need to want that!) 
         Place source objects in the bottom left tile.
	 Make the num of columns and the %drop multiply to an integer.
	 Make the num of rows and the %shift multiply to an integer.
	 Leave on of %shift or %drop equal to zero.
	 If using %drop, use even num rows.
	 If using %shift, use even number of columns. 

    Settings:
         num_of_columns 1-10
	 num_of_rows 1-10
	 type_of_pattern: plain, pillar, strip, diaper 
	 type_of_modification: none, h_mirror, v_mirror, rotate 180
	 drop_percent: 0-100%
	 shift_percent: 0-100%
	 
	 max_random_translation: 0-100% (one tile's worth)
	 max_random_rotation: 0-100% 
	 min_random_scale: eg. 50%
	 max_random_scale: eg 250%

 */

scriptName = "patternrepeat 0.2";

// debug output switch
debug=false;

// initial parameter values
num_of_columns = 2;
num_of_rows = 2;
type_of_pattern = 0;
type_of_modification = 0;
drop_percent = 0;
shift_percent = 0;

// Calculated global values
document_width = 0;
document_height = 0;

tile_width = 0;
tile_height = 0;
tile_shift = 0;
tile_drop = 0;

max_random_translation = 0;
max_random_rotation = 0;
min_random_scale = 1;
max_random_scale = 1;

// initialize an array and variable for the objects
obj_array = new Array()
obj = null;

// dialog is not open atm
openDialog = false;
// first open the dialog
optionDialog(); // dialog definition at files bottom


var obj_array = null;
var obj = null;

// Main loop 
function patternrepeat()
{
    dbug('starting patternrepeat function!');
    dbug('======================+++++++===');
    dbug('current values: ');
   
    dbug('  num_of_columns: '+num_of_columns);
    dbug('  num_of_rows num_of_rows: '+num_of_rows);
    dbug('  type_of_pattern type_of_pattern: '+ type_of_pattern);
    dbug('  type_of_modification: ' + type_of_modification);
    dbug('  drop_percent: ' + drop_percent);
    dbug('  shift_percent: ' + shift_percent);

    dbug('  max_random_translation: ' + max_random_translation);
    dbug('  max_random_rotation: ' + max_random_rotation);
    dbug('  min_random_scale: ' + min_random_scale);
    dbug('  max_random_scale: ' +max_random_scale);



    // Try to check the validity of our selected objects. 
    try
	{
	    for(var n=0;i<obj_array.length;n++)
		{
		    var working = obj_array[n].valid;
		    if(working)
			{
			    dbug('the shapes are valid: '+obj_array);
			}else{
			print('::error: shape values are not valid, are they still existent?');
			return;
		    }
		}
	}catch(e){
	print('::error: there are no objects, did you assign objects via dialog?');
	return;
    }
    
    dbug('selected objects are now: '+obj_array);
   

    assign_global_vars();

    // Go through and do the replications
    for (var i = 0; i < num_of_columns; i++)
	{
	    //dbug('Column number ' + i);
	    for (var j =0; j < num_of_rows; j++)
		{
		    //dbug ('Row number ' +j); 
		    for (var n = 0; n < obj_array.length; n++)
			{
			    dbug(i + '-' + j +' object:' + n);
			    //copy the object 
			    obj = obj_array[n];
			    var objcopy = obj.clone();
			    
			    if ((type_of_pattern == 1) && odd(i))
				{
				    modify(objcopy, i, j);
				}
			    
			    if ((type_of_pattern == 2) && odd(j)) {
				modify(objcopy, i, j);
			    }
			    
			    if ((type_of_pattern == 3) && odd(i+j)) {
				modify(objcopy, i, j);
			    }
			    
			    // Shift the copy horizontally and vertically
			    translate_x = 0;
			    translate_y = 0;
			    
			    translate_x = tile_width*i + tile_shift * j;
			    translate_y = tile_height*j - tile_drop * i;
			    
			    var move = new Point(translate_x, translate_y);
			    dbug('   Move by '+ move);
			    objcopy.translate(move);
			    
			    
			    // Random Rotate
			    if (max_random_rotation != 0)
				{
				    var randAngle = 
					(randomBetween(-Math.PI, Math.PI)*max_random_rotation);
				    dbug('    Random rotate by '+randAngle+' radians');
				    // rotate around objects centerpoint
				    var dotCenterPoint = objcopy.bounds.center;
				    objcopy.rotate(randAngle, objcopy.bounds.center); // doit!
				}
			    
			    // Random Scale
			    if ((min_random_scale != 1) || (max_random_scale != 1))
				{
				    
				    var randomScaleFactor = 
					randomBetweenFloat(min_random_scale, 
							   max_random_scale);
				    dbug('    Random scale by '+randomScaleFactor);
				    // Need to scale at the origin, or pass in location
				    var xloc = objcopy.bounds.center.x;
				    var yloc = objcopy.bounds.center.x;
				    objcopy.translate(-xloc, -yloc);
				    objcopy.scale(randomScaleFactor,randomScaleFactor);
				    objcopy.translate(xloc, yloc);
				}
			    // Random Translate
			    if (max_random_translation != 0)
				{
				    var randomTranslateX = 
					randomBetweenFloat(-max_random_translation, 
							   max_random_translation);
				    var randomTranslateY = 
					randomBetweenFloat(-max_random_translation, 
							   max_random_translation);
				    
				    
				    var randtrans = new Point(randomTranslateX*tile_width, 
							      randomTranslateY*tile_height);
				    dbug('    Random translate by '+randtrans);	
			    
				    objcopy.translate(randtrans);
				}

			    
			    //It it has moved off the page, wrap it back on
			    wrap(objcopy);
			    
			    
			    
			    
			}		
		}
	}
}

// Takes the object, translates it to near the origin, modifies it and moves it back
function modify(obj, i, j)
{
    // Don't bother doing the extra math if no modification needed
    if (type_of_modification == 0)
	{
	    return;
	}

    // Calculate the objects relevent position within the first tile
    // This can be done rigorously if either the vertical drop or the
    // horizontal shift is zero, but could result in logical
    // impossibility if both are set. Store the translation values needed.
    var trans = new Point(0,0);
    var orig_pos = obj.bounds.center;
    dbug ('    Original position;'+ orig_pos);

    
    if ((tile_shift == 0) || (abs(tile_shift) < abs(tile_drop)))
	// there may be a vertical drop associated with how far over
	// to the right it is so first do the horizontal shifting
	// which will affect the vertical, then fine-tune the vertical
	{
	    // Determine x adjustment necessary
	    while ((orig_pos.x + trans.x) < 0)
		{
		    // If too far to the left, shift it to the right (making sure to 
		    // note the appropriate drop.)
		    trans.x = trans.x + tile_width;
		    trans.y = trans.y - tile_drop;
		}

	    while ((orig_pos.x +trans.x) > tile_width) 
		{
		    trans.x = trans.x -tile_width;
		    trans.y = trans.y +tile_drop;
		}
	    
	    
	    // Then ...determine y adjustment necessary
	    while ((orig_pos.y + trans.y) < 0)
		{
		    // Check if we overshot
		    trans.y = trans.y + tile_height;
		    trans.x = trans.x +tile_shift; // Ideally, tile_shift is 0!
		}
	    while ((orig_pos.y +trans.y) > tile_height) 
		{
		    trans.y = trans.y -tile_height;
		    trans.x = trans.x +tile_shift; // Ideally, tile_shift is 0!
		}
	}
    else // there is a tile_shift, do math as if there were not a
	 // vertical drop also. (If there is a vert drop, your results
	 // may be somewhat ambiguous).
	{
	    // since there is a tile_shift and no (sic) tile_drop,
	    // first adjust the vertical hold and then fine-tune the
	    // horizontal.

	    // Determine y adjustment necessary
	    while ((orig_pos.y + trans.y) < 0)
		{
		    trans.y = trans.y + tile_height;
		    trans.x = trans.x + tile_shift;
		}
	    while ((orig_pos.y +trans.y) > tile_height) 
		{
		    trans.y = trans.y -tile_height;
		    trans.x = trans.x - tile_shift;
		}
	    
	    // Then.. determine x adjustment necessary
	    while ((orig_pos.x + trans.x) < 0)
		{
		    trans.x = trans.x + tile_width;
		    trans.y = trans.y - tile_drop;
		}

	    while ((orig_pos.x +trans.x) > tile_width) 
		{
		    trans.x = trans.x -tile_width;
		    trans.y = trans.y +tile_drop;
		}
	} //the y might be out of whack again if two non-zero values used... ignore.
    

    // Do the shift to near the origin
    obj.translate(trans);
    dbug('    Shifted by ' + trans + ' to position at '+ obj.bounds.center);     
    

    switch(type_of_modification)
	{
	case 0:
	    break;
	    
	case 1:
	    dbug('    to perform horiz mirroring on ' + i + ', ' + j); 
	    obj.scale(-1,1);
	    obj.translate(tile_width,0);
	    break;

	case 2:
	    dbug('    to perform vert. mirroring on ' + i + ', ' + j); 
	    obj.scale(1,-1);
	    obj.translate(0, tile_height);
	    break;

	case 3:
	    dbug('    to perform 180deg rotation on ' + i + ', ' + j); 
	    obj.rotate(Math.PI, tile_width/2, tile_height/2);
	    break;
	    
	default:
	    dbug ('Bad Modification Type! '+ mod_type_enum);
	    throw error;
	}

    // UNDO the shift to near the origin
    dbug('    Modified position ' + obj.bounds.center);     
    obj.translate(-trans.x, -trans.y);
    dbug('    Unshift by ' + trans + ' to position at '+ obj.bounds.center);     

}

//Absolute value
function abs(numb)
{
    if (numb < 0)
	{
	    return -numb;
	}
    return numb;
}


function assign_global_vars(){
    
    document_width = document.size.x;
    document_height = document.size.y;
    tile_width = document_width / num_of_columns;
    tile_height = document_height /num_of_rows;
    var tile_size = new Point(tile_width, tile_height);

    //todo: take shift and drop amounts mod page size
    tile_shift = tile_width*shift_percent/100;
    tile_drop = tile_height*drop_percent/100;
    var tile_adjust = new Point(tile_shift, tile_drop);

    dbug('document size: '+document.size);
    dbug('tile size: '+ tile_size);
    dbug('shift values: '+ tile_adjust);

}


function show_tiles()
{
    dbug('generating tiles function!');
    dbug('======================+++++++===');
    dbug('current values: ');
    
    dbug('  num_of_columns: '+num_of_columns);
    dbug('  num_of_rows num_of_rows: '+num_of_rows);
    dbug('  drop_percent: ' + drop_percent);
    dbug('  shift_percent: ' + shift_percent);

    assign_global_vars();
    for (var i = 0; i < num_of_columns; i++)
	{
	    for (var j =0; j < num_of_rows; j++)
		{
		    var rect = new Path();
		    with(rect.style){
			fill.color = null;
		    }
		    
		    rect.closed = true;
		    var gr = new Group();
		    gr.appendChild(rect);
		    var seg = rect.segments;
		    
		    var firstx =i*tile_width +j*tile_shift;
		    var firsty =j*tile_height -i*tile_drop;

		    seg.addAll([
				new Segment(firstx, firsty),
				new Segment(firstx + tile_width, firsty),
				new Segment(firstx +tile_width, firsty +tile_height),
				new Segment(firstx, firsty +tile_height)]);
					    
		    wrap(gr);
		    
		}
	}
}	    

function wrap(obj) 
{
    var doc_width = document.size.x;
    var doc_height = document.size.y;
    var xtrans = 0;
    var ytrans = 0;

    while (obj.bounds.center.x + xtrans < 0)
	{
	    xtrans = xtrans + doc_width;
	}

    while (obj.bounds.center.y + ytrans < 0)
	{
	    ytrans = ytrans + doc_height;
	}

    while (obj.bounds.center.x + xtrans > doc_width)
	{
	    xtrans = xtrans - doc_width;
	}

    while (obj.bounds.center.y + ytrans > doc_height)
	{
	    ytrans = ytrans - doc_height;
	}

    // If we need to move, do it and report
    if ((xtrans != 0) || (ytrans != 0))
	{
	    var trans = new Point(xtrans, ytrans);
	    obj.translate(trans);
	    dbug('    wrapping by ' + trans + ' to ' +obj.bounds.center); 
	}
}



//return true if odd
function odd(number) 
{
    if (number%2 !=0)
	{
	    return true;
	}
    else 
	{
	    return false;
	}
}

// return a rounded random number between two given values
// rounded
function randomBetween(min,max)
{
	min = parseFloat(min);
	max = parseFloat(max);
	return Math.round(Math.random() * (max - min) + min);
}

// return a rounded random number between two given values
// not rounded
function randomBetweenFloat(min,max)
{
	min = parseFloat(min);
	max = parseFloat(max);
	return Math.random() * (max - min) + min;
}


// the debug function, writes to console if debug is set to true
function dbug(msg)
{
	if(debug)
		print('::debug: '+msg);
}

// function to get the main items, called from the dialog
function get_objs()
{
	obj_array = null;
	
	var selectedItems = document.selectedItems;
	
	if(selectedItems.length == 0)
	{
		dbug('no objects selected -> nothing will happen...');
		return;
	}
	
	if (selectedItems.length >= 1)
	{
		obj_array = selectedItems;
		dbug('selected objects are: '+obj_array);
	}
}


function set_repeat_type_checkbox(plainCheck, pillarCheck, stripCheck, diaperCheck, repeat_type_enum)
{
    
    plainCheck.setChecked(false)
    pillarCheck.setChecked(false)
    stripCheck.setChecked(false)
    diaperCheck.setChecked(false)

    switch(repeat_type_enum)
	{
	case 0:
	    plainCheck.setChecked(true);
	    type_of_pattern = repeat_type_enum;
	    break;
	    
	case 1:
	    pillarCheck.setChecked(true);
	    type_of_pattern = repeat_type_enum;
	    break;

	case 2:
	    stripCheck.setChecked(true);
	    type_of_pattern = repeat_type_enum;
	    break;

	case 3:
	    diaperCheck.setChecked(true);
	    type_of_pattern = repeat_type_enum;
	    break;
	    
	default:
	    dbug ('Bad Repeat Type! '+ repeat_type_enum);
	    throw error;
	}
}

function set_modification_type_checkbox(noneCheck, hmirrorCheck, vmirrorCheck, rotateCheck, mod_type_enum)
{

    noneCheck.setChecked(false)
    hmirrorCheck.setChecked(false)
    vmirrorCheck.setChecked(false)
    rotateCheck.setChecked(false)

    switch(mod_type_enum)
	{
	case 0:
	    noneCheck.setChecked(true);
	    type_of_modification = mod_type_enum;
	    break;
	    
	case 1:
	    hmirrorCheck.setChecked(true);
	    type_of_modification = mod_type_enum;
	    break;

	case 2:
	    vmirrorCheck.setChecked(true);
	    type_of_modification = mod_type_enum;
	    break;

	case 3:
	    rotateCheck.setChecked(true);
	    type_of_modification = mod_type_enum;
	    break;
	    
	default:
	    dbug ('Bad Modification Type! '+ mod_type_enum);
	    throw error;
	}
}

function update_vert(curVert)
{
    curVert = curVert+20;
    return curVert;
}


// stuff that happens when you check the debug checkbox:
// output basic versioning info and stuff
function startDebug()
{
	version = parseFloat(scriptographer.version);
	revision = parseFloat(scriptographer.revision);

	dbug('basic information:');
	dbug('===================');
	dbug('scriptographer version: ' + version+'.'+revision);
	dbug('illustrator version: ' + app.version+'.'+app.revision);
	dbug('scriptdir: ' + scriptographer.scriptDirectory);
	dbug('script version: '+ scriptName);
}



// function to get the target shapes, called from the dialog
function getShapes()
{
    obj_array = null;
    var selectedItems = document.selectedItems;
    if(selectedItems.length == 0)
	{
	    print('::no-go! no objects selected, please select the shape(s)to be replicated!');
	    return;
	}else{
	obj_array = selectedItems;
	dbug('source-shapes are: '+obj_array);
    }
}


//****function which creates the option dialog****
function optionDialog() 
{
    //////////////////////CONFIG//////////////////////////
    // dialog config stuff
    var dialogSize = new Size(170,565);
    var curVert = 5;
    
    var dialogTitle = scriptName;
    
    openDialog = true; // set dialog status to true/open
    
    // create dialog
    dialog = new FloatingDialog(FloatingDialog.OPTION_TABBED);
    dialog.setTitle(dialogTitle);
    dialog.setSize(dialogSize);
    
    
    // ***** start size settings ***********************************
    // *start columns value
    var columnsEdit = new SpinEdit(dialog);
    columnsEdit.setVisible(true);
    columnsEdit.enabled = true;
    columnsEdit.setPosition(100, curVert = update_vert(curVert));
    columnsEdit.setSize(50, 20);
    columnsEdit.value = num_of_columns;
    columnsEdit.setUnits(0);
    
    var columnsText = new Static(dialog);
    columnsText.setText("Num of Columns:");
    columnsText.setSize(columnsText.bestSize);
    columnsText.setPosition(20, curVert);
    //------
    
    // *start rows value
    var rowsEdit = new SpinEdit(dialog);
    rowsEdit.setVisible(true);
    rowsEdit.enabled = true;
    rowsEdit.setPosition(100, curVert = update_vert(curVert));
    rowsEdit.setSize(50, 20);
    rowsEdit.value = num_of_rows;
    rowsEdit.setUnits(0);
    
    var rowsText = new Static(dialog);
    rowsText.setText("Num of Rows:");
    rowsText.setSize(rowsText.bestSize);
    rowsText.setPosition(20, curVert);
    //------
    
    // *start Frame
    var sizeFrame = new Frame(dialog);
    sizeFrame.setText("Size of matrix:");
    sizeFrame.setFont(6);
    sizeFrame.setSize(160,65);
    sizeFrame.setPosition(5, curVert - 40);
    curVert = update_vert(curVert) +5;
    //---------
    
    
    
    
    // ***** start of Shifting checkboxes *************************
    
    // *start drop_percent value
    var drop_percentEdit = new SpinEdit(dialog);
    drop_percentEdit.setVisible(true);
    drop_percentEdit.enabled = true;
    drop_percentEdit.setPosition(100, curVert = update_vert(curVert));
    drop_percentEdit.setSize(50, 20);
    drop_percentEdit.value = drop_percent;
    drop_percentEdit.setUnits(0);
    
    var drop_percentText = new Static(dialog);
    drop_percentText.setText("drop shift in %:");
    drop_percentText.setSize(drop_percentText.bestSize);
    drop_percentText.setPosition(20, curVert);
    //------
    
    
    // *start shift_percent value
    var shift_percentEdit = new SpinEdit(dialog);
    shift_percentEdit.setVisible(true);
    shift_percentEdit.enabled = true;
    shift_percentEdit.setPosition(100, curVert = update_vert(curVert));
    shift_percentEdit.setSize(50, 20);
    shift_percentEdit.value = shift_percent;
    shift_percentEdit.setUnits(0);
    
    var shift_percentText = new Static(dialog);
    shift_percentText.setText("brick shift in %:");
    shift_percentText.setSize(shift_percentText.bestSize);
    shift_percentText.setPosition(20, curVert);
    //------
    
    
    // *start shiftFrame 
    var shiftFrame = new Frame(dialog);
    shiftFrame.setText("Progressive offset:");
    shiftFrame.setFont(6);
    shiftFrame.setSize(160,65);
    shiftFrame.setPosition(5, curVert -40);
    curVert = update_vert(curVert)+5;
    //---------
    
    
    
    
    
    // *start testButton
    var testtilesButton = new Button(dialog);
    testtilesButton.setText("(Optional) Generate Tiles");
    testtilesButton.setSize(160,20);
    testtilesButton.setPosition(5, curVert);
    curVert = update_vert(curVert)+5;
    testtilesButton.onClick = function(){ // set all option on click
	
	num_of_columns = columnsEdit.value;
	num_of_rows = rowsEdit.value;
	
	drop_percent = drop_percentEdit.value;
	shift_percent = shift_percentEdit.value;
	
	max_random_translation =  tranlationmaxEdit.value/100.0;
	max_random_rotation = rotation_maxEdit.value/100.0;
	min_random_scale = scaleminEdit.value/100.0;
	max_random_scale = scalemaxEdit.value/100.0;
	
	show_tiles();
    }
    //-------
    
    
    // ***** start type_of_pattern checkboxes *************************
    
    
    // ***** start repeatPlain checkbox *****
    var repeatPlainCheck = new CheckBox(dialog);
    repeatPlainCheck.setPosition(100, curVert = update_vert(curVert));
    repeatPlainCheck.setSize(20, 15);
    repeatPlainCheck.setVisible(true);
    repeatPlainCheck.onClick = function(){
	dbug('plain repeat mode selected');
	set_repeat_type_checkbox(repeatPlainCheck,repeatPillarCheck, 
				 repeatStripCheck, repeatDiaperCheck,
				 0);
    }
    var repeatPlainText = new Static(dialog);
    repeatPlainText.setText("Plain");
    repeatPlainText.setSize(repeatPlainText.bestSize);
    repeatPlainText.setPosition(25, curVert);
    // ----- end repeatPlain checkbox -----
    
    
    // ***** start repeatPillar checkbox *****
    var repeatPillarCheck = new CheckBox(dialog);
    repeatPillarCheck.setPosition(100, curVert = update_vert(curVert));
    repeatPillarCheck.setSize(20, 15);
    repeatPillarCheck.setVisible(true);
    repeatPillarCheck.onClick = function(){
	dbug('pillar repeat mode selected');
	set_repeat_type_checkbox(repeatPlainCheck,repeatPillarCheck, 
				 repeatStripCheck, repeatDiaperCheck,
				 1);
    }
    var repeatPillarText = new Static(dialog);
    repeatPillarText.setText("Pillar");
    repeatPillarText.setSize(repeatPillarText.bestSize);
    repeatPillarText.setPosition(25, curVert);
    // ----- end repeatPillar checkbox -----
    
    
    // ***** start repeatStrip checkbox *****
    var repeatStripCheck = new CheckBox(dialog);
    repeatStripCheck.setPosition(100, curVert = update_vert(curVert));
    repeatStripCheck.setSize(20, 15);
    repeatStripCheck.setVisible(true);
    repeatStripCheck.onClick = function(){
	dbug('strip repeat mode selected');
	set_repeat_type_checkbox(repeatPlainCheck,repeatPillarCheck, 
				 repeatStripCheck, repeatDiaperCheck,
				 2);
    }
    var repeatStripText = new Static(dialog);
    repeatStripText.setText("Strip");
    repeatStripText.setSize(repeatStripText.bestSize);
    repeatStripText.setPosition(25, curVert);
    // ----- end repeatStrip checkbox -----
    
    
    // ***** start repeatDiaper checkbox *****
    var repeatDiaperCheck = new CheckBox(dialog);
    repeatDiaperCheck.setPosition(100, curVert = update_vert(curVert));
    repeatDiaperCheck.setSize(20, 15);
    repeatDiaperCheck.setVisible(true);
    repeatDiaperCheck.onClick = function(){
	dbug('diaper repeat mode selected');
	set_repeat_type_checkbox(repeatPlainCheck,repeatPillarCheck, 
				 repeatStripCheck, repeatDiaperCheck,
				 3);
    }
    var repeatDiaperText = new Static(dialog);
    repeatDiaperText.setText("Diaper");
    repeatDiaperText.setSize(repeatDiaperText.bestSize);
    repeatDiaperText.setPosition(25, curVert);
    // ----- end repeatDiaper checkbox -----
    
    
    set_repeat_type_checkbox(repeatPlainCheck,repeatPillarCheck, 
			     repeatStripCheck, repeatDiaperCheck,
			     type_of_pattern);		    
    
    // *start repeatTypeFrame 
    var repeatTypeFrame = new Frame(dialog);
    repeatTypeFrame.setText("Type of repeat pattern:");
    repeatTypeFrame.setFont(6);
    repeatTypeFrame.setSize(160,105);
    repeatTypeFrame.setPosition(5,curVert - 80);
    curVert = update_vert(curVert) +5;
    //---------
    
    
    
    // ***** start type_of_modification checkboxes *********************
    
    // ***** start modNone checkbox *****
    var modNoneCheck = new CheckBox(dialog);
    modNoneCheck.setPosition(100, curVert = update_vert(curVert));
    modNoneCheck.setSize(20, 15);
    modNoneCheck.setVisible(true);
    
    modNoneCheck.onClick = function(){
	dbug('no modifications mode selected');
	set_modification_type_checkbox(modNoneCheck, modHMirrorCheck, 
				       modVMirrorCheck, modRotateCheck, 
				       0);
    }
    var modNoneText = new Static(dialog);
    modNoneText.setText("None");
    modNoneText.setSize(modNoneText.bestSize);
    modNoneText.setPosition(25, curVert);
    // ----- end modNone checkbox -----
    
    
    // ***** start modHMirror checkbox *****
    var modHMirrorCheck = new CheckBox(dialog);
    modHMirrorCheck.setPosition(100, curVert = update_vert(curVert));
    modHMirrorCheck.setSize(20, 15);
    modHMirrorCheck.setVisible(true);
    modHMirrorCheck.onClick = function(){
	dbug('horizontal mirror modifications mode selected');
	set_modification_type_checkbox(modNoneCheck, modHMirrorCheck, 
				       modVMirrorCheck, modRotateCheck, 
				       1);
    }
    var modHMirrorText = new Static(dialog);
    modHMirrorText.setText("Horiz. Mirror");
    modHMirrorText.setSize(modHMirrorText.bestSize);
    modHMirrorText.setPosition(25, curVert);
    // ----- end modHMirror checkbox -----
    
    
    // ***** start modVMirror checkbox *****
    var modVMirrorCheck = new CheckBox(dialog);
    modVMirrorCheck.setPosition(100, curVert = update_vert(curVert));
    modVMirrorCheck.setSize(20, 15);
    modVMirrorCheck.setVisible(true);
    modVMirrorCheck.onClick = function(){
	dbug('vertical mirror modifications mode selected');
	set_modification_type_checkbox(modNoneCheck, modHMirrorCheck, 
				       modVMirrorCheck, modRotateCheck, 
				       2);
    }
    var modVMirrorText = new Static(dialog);
    modVMirrorText.setText("Vertical Mirror");
    modVMirrorText.setSize(modVMirrorText.bestSize);
    modVMirrorText.setPosition(25, curVert);
    // ----- end modVMirror checkbox -----
    
    
    // ***** start modRotate checkbox *****
    var modRotateCheck = new CheckBox(dialog);
    modRotateCheck.setPosition(100, curVert = update_vert(curVert));
    modRotateCheck.setSize(20, 15);
    modRotateCheck.setVisible(true);
    modRotateCheck.onClick = function(){
	dbug('180 rotataion modifications mode selected');
	set_modification_type_checkbox(modNoneCheck, modHMirrorCheck, 
				       modVMirrorCheck, modRotateCheck, 
				       3);
    }
    var modRotateText = new Static(dialog);
    modRotateText.setText("180 Rotation");
    modRotateText.setSize(modRotateText.bestSize);
    modRotateText.setPosition(25, curVert);
    // ----- end modRotate checkbox -----
    
    
    
    set_modification_type_checkbox(modNoneCheck, modHMirrorCheck, 
				   modVMirrorCheck, modRotateCheck, 
				   type_of_modification);		    
    
    
    // *start modificationTypeFrame 
    var modificationTypeFrame = new Frame(dialog);
    modificationTypeFrame.setText("Type of modification:");
    modificationTypeFrame.setFont(6);
    modificationTypeFrame.setSize(160,105);
    modificationTypeFrame.setPosition(5,curVert -80);
    curVert = update_vert(curVert)+5;
    
    
    
    
    


    // ***** start of Random checkboxes *************************
    
    // *start tranlationmax value
    var tranlationmaxEdit = new SpinEdit(dialog);
    tranlationmaxEdit.setVisible(true);
    tranlationmaxEdit.enabled = true;
    tranlationmaxEdit.setPosition(100, curVert = update_vert(curVert));
    tranlationmaxEdit.setSize(50, 20);
    tranlationmaxEdit.value = max_random_translation *100;
    tranlationmaxEdit.setUnits(0);
    
    var tranlationmaxText = new Static(dialog);
    tranlationmaxText.setText("trans. max(%):");
    tranlationmaxText.setSize(tranlationmaxText.bestSize);
    tranlationmaxText.setPosition(20, curVert);
    //------
    
    
    
    // *start rotation_max value
    var rotation_maxEdit = new SpinEdit(dialog);
    rotation_maxEdit.setVisible(true);
    rotation_maxEdit.enabled = true;
    rotation_maxEdit.setPosition(100, curVert = update_vert(curVert));
    rotation_maxEdit.setSize(50, 20);
    rotation_maxEdit.value = max_random_rotation *100;
    rotation_maxEdit.setUnits(0);
    
    var rotation_maxText = new Static(dialog);
    rotation_maxText.setText("rot. max(%)");
    rotation_maxText.setSize(rotation_maxText.bestSize);
    rotation_maxText.setPosition(20, curVert);
    //------
    
    
    // *start scalemin value
    var scaleminEdit = new SpinEdit(dialog);
    scaleminEdit.setVisible(true);
    scaleminEdit.enabled = true;
    scaleminEdit.setPosition(100, curVert = update_vert(curVert));
    scaleminEdit.setSize(50, 20);
    scaleminEdit.value = min_random_scale *100;
    scaleminEdit.setUnits(0);
    
    var scaleminText = new Static(dialog);
    scaleminText.setText("scale min in %:");
    scaleminText.setSize(scaleminText.bestSize);
    scaleminText.setPosition(20, curVert);
    //------
    
    // *start scalemax value
    var scalemaxEdit = new SpinEdit(dialog);
    scalemaxEdit.setVisible(true);
    scalemaxEdit.enabled = true;
    scalemaxEdit.setPosition(100, curVert = update_vert(curVert));
    scalemaxEdit.setSize(50, 20);
    scalemaxEdit.value = max_random_scale *100;
    scalemaxEdit.setUnits(0);
    
    var scalemaxText = new Static(dialog);
    scalemaxText.setText("scale max in %:");
    scalemaxText.setSize(scalemaxText.bestSize);
    scalemaxText.setPosition(20, curVert);
    //------
    
    
    // *start randomFrame 
    var randomFrame = new Frame(dialog);
    randomFrame.setText("Random perturbations:");
    randomFrame.setFont(6);
    randomFrame.setSize(160,105);
    randomFrame.setPosition(5, curVert-80);
    curVert = update_vert(curVert)+5;
    //---------
    
    
    
    // ***** start debug checkbox *******************************
    var debugCheck = new CheckBox(dialog);
    debugCheck.setPosition(100, curVert);
    debugCheck.setSize(20, 15);
    debugCheck.setVisible(true);
    debugCheck.setChecked(debug);
    debugCheck.onClick = function(){
	debug = debugCheck.isChecked();
	dbug('wise choice!!');
	if(debug)
	    {
		startDebug();
	    }
    }
    var debugText = new Static(dialog);
    debugText.setText("debug:");
    debugText.setSize(debugText.bestSize);
    debugText.setPosition(20, curVert);
    // ----- end debug checkbox -----
    
    
    


    // *start get items button
    var shapesButton = new Button(dialog);
    shapesButton.setText("Assign shape(s)");
    shapesButton.setSize(160,20);
    shapesButton.setPosition(5, curVert = update_vert(curVert));
    shapesButton.onClick = function(){ // set all option on click
	getShapes();
    }
    
    
    //* Reminder about layers
    var layerText = new Static(dialog);
    layerText.setText("Remember to set destination layer.");
    layerText.setSize(layerText.bestSize);
    layerText.setPosition(10, curVert= update_vert(curVert));
    
    
    // *start goButton
    var submitButton = new Button(dialog);
    submitButton.setText("Replicate!");
    submitButton.setSize(160,20);
    submitButton.setPosition(5, curVert = update_vert(curVert));
    submitButton.onClick = function(){ // set all option on click
	
	num_of_columns = columnsEdit.value;
	num_of_rows = rowsEdit.value;
	
	drop_percent = drop_percentEdit.value;
	shift_percent = shift_percentEdit.value;
	
	max_random_translation =  tranlationmaxEdit.value/100.0;
	max_random_rotation = rotation_maxEdit.value/100.0;
	min_random_scale = scaleminEdit.value/100.0;
	max_random_scale = scalemaxEdit.value/100.0;
	
	/// go for it!!!
	patternrepeat();
    }
    //-------
    
    // finalize the dialog
    dialog.setVisible(true);
    dialog.onClose = function() {
	dialog.destroy();
	openDialog = false;
    }
    //**********************************
}


