/* File: ..//src//illustrator//triangleBySides.jsx Date: Sat Dec 27 15:17:32 MYT 2008 Author: David Van Brink This script is part of the omino adobe script suite. The latest version can be found at http://omino.com/pixelblog/. I write these because I like to. Please enjoy as you see fit. Questions to poly@omino.com, subject line should start with "plugins" so my spam filter lets it in. This file has been preprocessed to be standalone. I develop them against some reusable libraries -- such as for dialog layout -- but for distribution it's nicer to have just one file. dvb 2007. */ /* * triangleBySides.jsx * Description: Draw a triangle given the length of its three sides. Simple! :: * dvb2008 */ // ----------------------------------------- // #include "../shared/ominoDialogMaker.jsx" // ----------------------------------------- { var D_MARGIN = 6; var D_CONTROLHEIGHT = 20; var D_BUTTONWIDTH = 100; var D_CONTROLLABELWIDTH = 160; var D_CONTROLWIDTH = 150; var D_DIALOG_WIDTH = 400; var S2 = 1.41421356237309504880; // create a rectangle for a new control, walking downwards. function _odControlShared(label,name) { dialog = this; var y = dialog.curYPos; var itemHeight = D_CONTROLHEIGHT; var itemBump = itemHeight + D_MARGIN; if(label != "") label += ":"; var labelCtl = dialog.add('statictext',[20,y,20 + D_CONTROLLABELWIDTH,y+itemHeight],label); labelCtl.justify = "right"; var controlBox = new Object(); controlBox.left = 20 + D_CONTROLLABELWIDTH + 10; controlBox.top = y; controlBox.right = controlBox.left + D_CONTROLWIDTH; controlBox.bottom = controlBox.top + itemHeight; dialog.curYPos = controlBox.bottom + D_MARGIN; return controlBox; } function _odControlSharedFinish(control,name,valueFieldName) { oD = this; oD.items[name] = control; oD.itemValueFieldNames[name] = valueFieldName; oD.itemNames[oD.itemNames.length] = name; } function _odNumber(label,name,value) { oD = this; var controlBox = oD._odControlShared(label,name); var control = oD.add('edittext',controlBox,value); control.value = value; control.onChange = function(){this.value = (this.text) * 1.0; this.text = this.value;}; // make them all .value accessible oD._odControlSharedFinish(control,name,"text"); return control; } function _odText(label,name,value) { oD = this; var controlBox = oD._odControlShared(label,name); var control = oD.add('edittext',controlBox,value); control.value = value; control.onChange = function(){this.value = this.text; }; // make them all .value accessible oD._odControlSharedFinish(control,name,"text"); return control; } function _setColorFromButton(victim,button) { var g = victim.graphics; var n = button.value; var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, n); g.backgroundColor = myBrush; } /* color values are array of three floats, 0.0 .. 1.0. */ function _odColor(label,name,color) { oD = this; var controlBox = oD._odControlShared(label,name); var swatchBox = [controlBox.left + 40,controlBox.top,controlBox.right,controlBox.bottom]; var buttonBox = [controlBox.left,controlBox.top,controlBox.left + 30,controlBox.bottom]; var swatch = oD.add('group',swatchBox); var button = oD.add('button',buttonBox); button.swatch = swatch; button.value = color; button.onClick = function(){ var n = doColorPicker(this.value); this.value = n; _setColorFromButton(swatch,this); }; _setColorFromButton(swatch,button); oD._odControlSharedFinish(button,name,"value"); return button; } /* Add a button and static text to the dialog; the button refers to the text "nameCtl", and has .filePrompt and .fileExtension. */ function _odFileCommon(label,name,path,prompt,extension) { var controlBox = oD._odControlShared(label,name); var buttonWidth = 80; var buttonBox = [controlBox.left,controlBox.top,controlBox.left + buttonWidth,controlBox.bottom]; var nameBox = [controlBox.left + buttonWidth + 10,controlBox.top,D_DIALOG_WIDTH,controlBox.bottom]; var f = new File(path); var nameCtl = oD.add('statictext',nameBox); var button = oD.add('button',buttonBox,'...'); button.nameCtl = nameCtl; nameCtl.text = f.name; button.value = f.fsName; button.file = f; button.filePrompt = prompt; button.fileExtension = extension; oD._odControlSharedFinish(button,name,"value"); return button; } function _odOpenFile(label,name,path,prompt,extension) { oD = this; var buttonCtl = _odFileCommon(label,name,path,prompt,extension); buttonCtl.onClick = function(){ var f = this.file.openDlg(this.filePrompt); if(f) { this.file = f; this.value = f.fsName; this.nameCtl.text = f.name; } }; return buttonCtl; } function _odSaveFile(label,name,path,prompt,extension) { oD = this; var buttonCtl = _odFileCommon(label,name,path,prompt,extension); buttonCtl.onClick = function(){ var f = this.file.saveDlg(this.filePrompt); if(f) { this.file = f; this.value = f.fsName; this.nameCtl.text = f.name; } }; return buttonCtl; } function _odSelectFolder(label,name,path,prompt,extension) { oD = this; var buttonCtl = _odFileCommon(label,name,path,prompt,extension); buttonCtl.folder = new Folder(path); // folder, pls, not file buttonCtl.nameCtl.text += "/"; buttonCtl.onClick = function(){ var f = this.folder.selectDlg(this.filePrompt); if(f) { this.folder = f; this.value = f.fsName; this.nameCtl.text = f.name + "/"; } }; return buttonCtl; } function _odCheckbox(label,name,value,checkboxText) { oD = this; var controlBox = oD._odControlShared(label,name); var control = oD.add('checkbox',controlBox,checkboxText); control.value = value; //control.onChange = function(){this.value = this.text;}; oD._odControlSharedFinish(control,name,"value"); return control; } function _odRadioButtons(label,name,value,radioChoices) { var oD = this; controlBox = oD ._odControlShared(label,name); var itemHeight = controlBox.bottom - controlBox.top; result = oD.add('edittext',controlBox,value); // hidden text field to control it... result.onChange = function(){ var i; this.value = this.text; for(i = 0; i < this.buttons.length; i++) { var button = this.buttons[i]; button.value = (button.theChoice == this.text); } } result.hide(); result.value = value; result.buttons = new Array(); var i; for(i = 0; i < radioChoices.length; i++) { var choice = radioChoices[i]; if(i > 0) { var bump = itemHeight + D_MARGIN; controlBox.top += bump; controlBox.bottom += bump; oD.curYPos += bump; } // each radiobutton object pokes its choice into the ersatz control, // so it looks like a simple value. // ("Grouping" appears to be by adjacent additions only. Nice!) var rb = oD .add('radiobutton',controlBox,choice); rb.value = choice == value; rb.theChoice = choice; rb.theGroupErsatzControl = result; rb.onClick = function(){this.theGroupErsatzControl.value = this.theChoice;}; result.buttons[result.buttons.length] = rb; } oD._odControlSharedFinish(result,name,"text"); return result; } function _odMenu(label,name,value,menuChoices) { var oD = this; controlBox = oD ._odControlShared(label,name); var itemHeight = controlBox.bottom - controlBox.top; var control = oD.add('dropdownlist',controlBox,menuChoices); // I couldnt discern how to get this from the "items" array, so I stash menuChoice for later. dvb08. control.menuChoices = menuChoices; control.value = value; // set the initial selection index var index = 0; for(var i = 0; i < menuChoices.length; i++) { if(value == menuChoices[i]) index = i; } control.selection = index; control.onChange = function() { this.value = this.selection.text; } // make them all .value accessible oD._odControlSharedFinish(control,name,"value"); } function _odSectionLabel(label) { var oD = this; var b2 = new Object(); b2.left = D_MARGIN; b2.top = oD.curYPos; b2.right = b2.left + D_DIALOG_WIDTH; b2.bottom = b2.top + D_CONTROLHEIGHT; oD.curYPos += D_CONTROLHEIGHT + D_MARGIN; oD.add('statictext',b2,label + ':',{multiline:true}); } function _odBoxedText(lines,text) { var oD = this; var width = D_DIALOG_WIDTH; var height = lines * 16; var b2 = new Object(); var b = new Object(); b.top = oD.curYPos; b.bottom = b.top + height + 2 * D_MARGIN; b.left = D_MARGIN; b.right = b.left + width; oD.curYPos = b.bottom + D_MARGIN; var panel = oD.add('panel',b); b2.left = D_MARGIN; b2.top = D_MARGIN; b2.right = b2.left + width - 2 * D_MARGIN; b2.bottom = b2.top + height; panel.add('statictext',b2,text,{multiline:true}); } function _odSeparator() { var oD = this; var height = oD.groupGap; var barWidth = oD.ominoDialogWidth; if(barWidth) { var b = new Object(); b.top = oD.curYPos + height / 2; b.bottom = b.top; b.left = D_MARGIN; b.right = b.left + barWidth; var barHeight = 2; b.top -= barHeight / 2; b.bottom = b.top + barHeight; oD.add('panel',b); } oD.curYPos += height; } function _odAppendGap() { oD = this; oD.curYPos += oD.groupGap; } function appendOKCancel(dialog) { var y = dialog.curYPos; var cancelRect = new Object(); var okRect = new Object(); cancelRect.left = D_MARGIN cancelRect.top = y; cancelRect.right = cancelRect.left + D_BUTTONWIDTH; cancelRect.bottom = cancelRect.top + D_CONTROLHEIGHT; okRect.left = cancelRect.right + D_MARGIN + D_MARGIN; okRect.top = y; okRect.right = okRect.left + D_BUTTONWIDTH; okRect.bottom = okRect.top + D_CONTROLHEIGHT; var cancelBtn = dialog.add('button',cancelRect,'Cancel',{name:'cancel'}); var okBtn = dialog.add('button',okRect,'OK',{name:'ok'}); cancelBtn.theDialog = dialog; cancelBtn.onClick = function(){this.theDialog.close(0);}; // 0 on cancel okBtn.theDialog = dialog; okBtn.onClick = function(){this.theDialog.close(1);}; // 1 on ok dialog.curYPos = okRect.bottom + D_MARGIN; } function trimDialogBounds(dialog) { var xMax = 20; var yMax = 20; var n = dialog.children.length; var i; for(i = 0; i < n; i++) { var aChild= dialog.children[i]; var aChildBounds = aChild.bounds; if(aChildBounds.right > xMax) xMax = aChildBounds.right; if(aChildBounds.bottom > yMax) yMax = aChildBounds.bottom; } dialog.bounds.right = dialog.bounds.left + xMax + D_MARGIN; dialog.bounds.bottom = dialog.bounds.top + yMax + D_MARGIN; // actually... allow bottom gaps. dialog.bounds.bottom = dialog.curYPos + dialog.bounds.top; } function newOminoDialog(name) { var oD = new Window('dialog',name,[100,100,500,500]); oD.curYPos = 20; oD.groupGap = 12; oD.itemNames = new Array(); oD.item oD.items = new Array(); oD.itemValueFieldNames = new Object(); // to poke a value into the dialog, each control's appropriate field, like "text" or "value" oD.ominoDialogWidth = D_DIALOG_WIDTH; oD.gap = _odAppendGap; oD.number = _odNumber; oD.string = _odText; oD.radioButtons = _odRadioButtons; oD.checkbox = _odCheckbox; oD.sectionLabel = _odSectionLabel; oD.separator = _odSeparator; oD.boxedText = _odBoxedText; oD.color = _odColor; oD.openFile = _odOpenFile; oD.selectFolder = _odSelectFolder; oD.saveFile = _odSaveFile; oD.menu = _odMenu; oD.set = _odSet; oD.run = _odRun; oD.get = _odGet; oD._odControlShared = _odControlShared; oD._odControlSharedFinish = _odControlSharedFinish; return oD; } function _odGet() { var values = new Object(); var name; for(name in this.items) { var value = this.items[name].value; values[name] = value; } return values; } function _odSet(values) { var oD = this; if(!values) return; for(var p in values) { var value = values[p]; var item = oD.items[p]; if(!item) continue; var itemValueFieldName = oD.itemValueFieldNames[p]; if(!itemValueFieldName) continue; item[itemValueFieldName] = value; item.notify('onChange'); // to get the refresh } } function _odRun() { var oD = this; if(!oD.finishingTouches) { oD.separator(oD); oD.gap(); appendOKCancel(oD); oD.gap(); trimDialogBounds(oD); oD.finishingTouches = true; } var resultCode = oD.show(); if(resultCode != 1) // cancel return null; var result = oD.get(); return result; } function example() { var host = app; var d = newOminoDialog("Omino Example Dialog: " + host.name); d.curYPos = 20; d.boxedText(4, "This is an example of a dialog built with ominoDialogMaker.jsx\n" + "host: " + host.name + " " + host.version + "\n" + "\n" + "©2007 poly@omino.com", D_DIALOG_WIDTH,80); d.separator(); d.sectionLabel("Kinds of Controls"); d.number("Number H","h",11.23); d.checkbox("Checkbox X","x",true,"check this"); d.string("Text","t","type here"); d.radioButtons("Choose One","r","red",["red","maroon","scarlet","crimson"]); var result; do { d.set(result); result = d.run(); if(result !=null) { var s = "Result Values\n"; var i; for(name in result) s += name + " = " + result[name] + "\n"; alert(s); } } while(result); } /* Easy to use progress bar for ExtendScript. Written by poly@omino.com, 2007 Enjoy, but this credit must remain intact. usage: var pb = progressBar("main title","subtitle"); pb.setValue(valueFrom0to1); pb.setTitle2("new subtitle display!") if(!pb.isRunning()) pb.close(); // they clicked cancel */ function progressBar(title1,title2) { var result = new Object(); result.running = true; result.p = new Window("palette"); result.p.orientation = "column"; result.p.alignChildren = "left"; result.t1 = result.p.add("statictext",undefined,title1); result.t2 = result.p.add("statictext",undefined,title2); result.b = result.p.add("progressbar"); result.c = result.p.add("button",undefined,"Cancel"); result.c.onClick = function() { result.running = false; } result.isRunning = function() { return this.running; } result.setValue = function(x) { this.b.value = x * 100; } result.setTitle1 = function(t1) { this.t1.text = t1; } result.setTitle2 = function(t2) { this.t2.text = t2; } result.close = function() { this.p.close(); } result.p.show(); return result; } /* a foolish little routine to show all the insides of an object in al Alert. You know, for debugging. */ function alertObj(o,title) { if(!title) title = ""; var s = title + "\n"; var k; if(!o) s += "(null object)"; else for(k in o) { s += k + " = " + o[k] + "\n"; } alert(s); } //example(); "ok"; } // end of file // thus ends ../shared/ominoDialogMaker.jsx // ----------------------------------------- // this variable goes outside the main brackets to keep the // most recent dialog values. var gLastSettings; { var docCount = documents.length; if (docCount == 0) { documents.add(); } function layerByName(layers,name) { var i; for(i = 0; i < layers.length; i++) { var layer = layers[i]; if(layer.name == name) return layer; } return null; } function newLayer(doc,baseName) { var n = 0; var result = null; while(result == null) { n++; var aName = "" + baseName + n; var existingLayer = layerByName(doc.layers,aName); if(existingLayer == null) { result = doc.layers.add(); result.name = aName; } } return result; } function addP(points,x,y) { var p = points.add(); p.anchor = [x,y]; p.leftDirection = p.anchor; p.rightDirection = p.anchor; } function main() { var docRef = documents[0]; var docHeight = docRef.height; var docWidth = docRef.width; // default values var cx = docWidth / 2; var cy = docHeight / 2; var omd = newOminoDialog("Triangle By Sides"); omd.boxedText(5,"This Illustrator script draws a triangle, given the lengths of 3 sides."); omd.separator(); omd.number("Center X","cx",cx); omd.number("Y","cy",cy); omd.gap(); omd.number("Base (a)","a",100); omd.number("Left (b)","b",100); omd.number("Right (c)","c",100); omd.set(gLastSettings); var result = omd.run(); if(result) gLastSettings = result; if(!result) return; // canceled cx = result.cx; cy = result.cy; a = result.a; b = result.b; c = result.c; var x = (a * a + b * b - c * c) / (2 * a); var y = Math.sqrt(b * b - x * x); x += cx; y += cy; var layer = newLayer(app.documents[0],"triangle_"); var pathItem = layer.pathItems.add(); var points = pathItem.pathPoints; // brand new, empty addP(points,cx,cy); addP(points,x,y); addP(points,cx + a,cy); pathItem.closed = true; pathItem.name = "triangle (" + a + "," + b + "," + c + ")"; } main(); }