Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/A+%27Sketch+On%27+GUI+...+for+drawing+on+an+image+or+colored+background?V=3
QUERY_STRINGV=3
CONTENT_TYPE
DOCUMENT_URI/revision/A+'Sketch+On'+GUI+...+for+drawing+on+an+image+or+colored+background
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.100.233
REMOTE_PORT39036
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR18.117.152.26
HTTP_CF_RAY886e03b10adae251-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_REFERERhttp://wiki.tcl.tk./revision/A+%27Sketch+On%27+GUI+%2E%2E%2E+for+drawing+on+an+image+or+colored+background?V=3
HTTP_CF_CONNECTING_IP18.117.152.26
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: LINE -> END

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit {A 'Sketch On' GUI ... for drawing on an image or colored background} \[uniquename\]\ -\ 2012oct05\n\nIn\ doing\ some\ searches\ on\ this\ wiki\ for\ 'canvas'\ applications,\ I\ ran\nacross\ the\ old\ 2003\ Suchenwirth\ page\ \[A\ minimal\ doodler\ explained\].\n\nI\ pasted\ the\ code\ into\ a\ script\ and\ ran\ it.\ It\ could\ draw\ black\ncurves\ on\ a\ white\ background.\ Nice.\n\nHowever,\ an\ 'artistically\ challenged'\ person\ like\ myself\ could\ use\nsome\ help\ in\ sketching\ ---\ like\ an\ image\ to\ use\ as\ a\ guide\ in\ sketching.\n\nI\ had\ recently\ posted\ a\ script\ here\ that\ loads\ GIF/PNG\ images\ from\nan\ image\ file\ to\ a\ canvas\ ---\ at\ \[GUI\ for\ Editing\ Photo-images\ with\ Functions\].\n\nI\ figured\ that,\ based\ on\ that\ code,\ I\ should\ be\ able\ to\ make\ a\ nice\nsketcher\ utility\ that\ could\ be\ used\ to\ make\ some\ non-trivial\ sketches.\n\nSome\ of\ the\ goals\ that\ I\ had\ for\ this\ utility\ were:\n\n1)\ I\ should\ be\ able\ to\ remove\ the\ image\ from\ the\ canvas\ at\ any\ time\nso\ that\ I\ could\ check\ on\ the\ progress\ of\ the\ sketch.\ Then\ I\ should\nbe\ able\ to\ quickly\ re-apply\ the\ image\ to\ the\ canvas.\n\n2)\ I\ should\ be\ able\ to\ specify\ any\ color\ for\ the\ lines\ being\ sketched\n---\ and\ any\ color\ for\ the\ background\ (the\ canvas).\n\n3)\ I\ should\ be\ able\ to\ change\ to\ a\ different\ line\ width\ at\ any\ntime\ as\ I\ laid\ down\ the\ line\ segments.\n\n4)\ And,\ perhaps\ most\ importantly,\ since\ it\ is\ difficult\ to\ get\ line\nsegments\ just\ the\ way\ you\ want\ them\ (the\ first\ time,\ every\ time),\nI\ needed\ a\ 'robust'\ delete\ capability\ that\ allowed\ me\ to\ quickly\ndelete\ a\ line\ segment\ and\ re-draw\ it.\ (In\ Suchenwirth's\ 'minimal\ndoodler'\ example,\ it\ could\ delete\ ALL\ the\ lines\ drawn,\ but\ not\nindividual\ line\ segments.)\n\nAfter\ a\ couple\ of\ long\ days\ of\ coding\ ---\ and\ reviewing\ and\nreferring\ to\ Chapter\ 37\ 'The\ Canvas\ Widget'\ in\ the\ 4th\ edition\nof\ the\ book\ 'Practical\ Programming\ in\ Tcl\ and\ Tk',\ I\ came\ up\nwith\ the\ GUI\ indicated\ by\ the\ following\ image.\n\n\[sketchONimgGUI_imgOnly_screenshot_638x415.jpg\]\n\nThe\ GUI\ actually\ has\ a\ blank\ canvas\ when\ it\ is\ first\ started\ up.\nThis\ image\ demonstrates\ that\ one\ can\ load\ a\ nice\ image\ onto\ the\ncanvas.\n\nAnd\ the\ following\ image\ shows\ how\ the\ GUI\ may\ look\ after\ sketching\nsome\ lines\ on\ the\ image.\n\n\[sketchONimgGUI_linesANDimg_screenshot_638x415.jpg\]\n\nNote\ that\ if\ you\ are\ having\ a\ hard\ time\ seeing\ the\ lines\ that\ you\nare\ drawing\ on\ the\ image,\ you\ could\ start\ with\ a\ 'faded'\ image.\nFor\ example,\ you\ could\ take\ your\ GIF/PNG\ image\ file\ into\ an\ image\neditor\ (like\ 'mtpaint'\ on\ Linux).\ I\ use\ the\ 'Effects\ >\ Transform\ color\ ...'\noption\ in\ 'mtpaint'\ to\ access\ a\ slider\ bar\ for\ 'Gamma\ correction'.\nBy\ simply\ sliding\ that\ bar\ from\ 100\ to\ about\ 200,\ I\ can\ save\ to\na\ paler\ image,\ and\ then\ use\ that\ image\ on\ which\ to\ sketch.\n\nThe\ following\ image\ shows\ how\ the\ image\ can\ be\ removed\ with\ the\n'RemoveImg'\ button,\ to\ reveal\ the\ progress\ on\ the\ sketch.\n\n\[sketchONimgGUI_linesOnly_screenshot_637x416.jpg\]\n\nThe\ 'Help'\ button\ of\ the\ GUI\ shows\ text\ like\ the\ following,\ which\nindicates\ how\ one\ can\ re-apply\ the\ image\ to\ the\ GUI,\ to\ continue\ndrawing.\ And\ the\ help\ indicates\ how\ one\ can\ quickly\ delete\ line\nsegments\ and\ quickly\ relocate\ the\ image\ on\ the\ canvas.\n\n======\n\n\ To\ DRAW:\n\ Press\ MB1\ (mouse\ button\ 1)\ to\ start\ a\ line\ where\ the\ arrow-cursor\n\ is\ currently\ located\ on\ the\ canvas.\ Continue\ to\ hold\ MB1\ down\ and\n\ move\ the\ mouse\ to\ draw\ the\ current\ line\ segment\ on\ the\ canvas.\n\ Release\ MB1\ to\ terminate\ drawing\ that\ line\ segment.\n\n\ To\ DELETE\ a\ line\ segment,\ press-and-release\ MB3\ (mouse\ button\ 3)\n\ on\ the\ line\ segment\ to\ be\ deleted.\n\n\ Click\ the\ 'RemoveImage'\ button\ to\ see\ how\ your\ drawing\ is\n\ progressing.\ Then\ ...\n\n\ Click\ and\ release\ MB1\ on\ the\ filename\ in\ the\ entry\ field,\ to\n\ RELOAD\ the\ image\ from\ the\ image\ file\ to\ the\ canvas.\ If\ the\n\ reload\ covers\ up\ your\ lines,\ click\ on\ the\ 'RaiseLines'\ button\n\ to\ reveal\ the\ lines\ again.\n\n\ Use\ MB2\ to\ move\ (drag)\ the\ image\ to\ a\ new\ location.\ This\ can\n\ be\ useful\ to\ use\ additional\ images\ to\ help\ sketch\ the\ picture.\n\ Or\ it\ can\ be\ used\ to\ offset\ the\ current\ image\ and\ use\ it\ for\n\ addtional\ sketching.\n\n\ You\ can\ use\ a\ screen/image\ capture\ utility\ to\ capture\ your\n\ drawing\ ---\ with\ or\ without\ an\ underlying\ image\ in\ place.\n\n======\n\nHow\ to\ change\ colors\ is\ not\ mentioned\ in\ this\ help,\ but\ it\ should\nbe\ fairly\ obvious\ that\ those\ capabilities\ are\ available\ (and\ how\ to\nmake\ the\ color\ changes)\ from\ the\ presense\ of\ the\ 'Next\ line\ color'\ and\n'Background\ color'\ buttons\ on\ the\ GUI.\n\nThose\ 2\ color\ buttons\ call\ on\ a\ color-selector-GUI\ script\ to\ set\ those\ colors.\nYou\ can\ make\ that\ color-selector\ script\ by\ cutting-and-pasting\ the\ code\ from\nthe\ page\ \[A\ non-obfuscated\ color\ selector\ GUI\]\ on\ this\ site.\n\n_____________________________________________________________________\n\nBelow\ is\ the\ code\ that\ produced\ this\ GUI.\n\nThere\ are\ comments\ above\ the\ sample\ code,\ in\ a\ section\ titled\n'USING\ THE\ GENERATED\ IMAGE',\ that\ describe\ how\ one\ could\ make\ use\ of\nimages\ produced\ by\ this\ GUI.\n\nI\ follow\ my\ usual\ 'canonical'\ structure\ for\ Tk\ code,\ for\ this\ Tk\ script:\n\n\ \ 0)\ Set\ general\ window\ &\ widget\ parms\ (win-name,\ win-position,\n\ \ \ \ \ win-color-scheme,\ fonts,\ widget-geometry-parms,\ win-size-control).\n\n\ \ 1a)\ Define\ ALL\ frames\ and\ sub-frames.\n\ \ 1b)\ Pack\ \ \ ALL\ frames\ and\ sub-frames.\n\n\ \ 2)\ Define\ &\ pack\ all\ widgets\ in\ the\ frames.\n\n\ \ 3)\ Define\ keyboard\ or\ mouse\ action\ BINDINGS,\ if\ needed.\n\n\ \ 4)\ Define\ PROCS,\ if\ needed.\n\n\ \ 5)\ Additional\ GUI\ initialization\ (typically\ with\ one\ or\ more\ of\n\ \ \ \ \ the\ procs),\ if\ needed.\n\nThis\ makes\ it\ easy\ for\ me\ to\ find\ code\ sections\ ---\ while\ generating\nand\ testing\ this\ script,\ and\ when\ looking\ for\ code\ snippets\ to\ninclude\ in\ other\ scripts.\n\n_________________________________________________________________\n\nAs\ in\ all\ my\ scripts\ that\ use\ the\ 'pack'\ geometry\ manager\ (which\nis\ all\ of\ my\ 100-plus\ Tk\ scripts,\ so\ far),\ I\ provide\ the\ four\ main\npack\ parameters\ ---\ '-side',\ '-anchor',\ '-fill',\ and\ '-expand'\n---\ on\ all\ the\ 'pack'\ commands\ for\ the\ frames\ and\ widgets.\n\nI\ think\ I\ have\ found\ a\ good\ setting\ of\ the\ \n'-side',\ '-anchor',\ '-fill',\ and\ '-expand'\ parameters\ on\nthe\ 'pack'\ commands\ for\ the\ various\ widgets\ of\ this\ GUI.\ In\ particular\ ...\n\nThe\ 'canvas'\ widget\ expands/contracts\ appropriately\ when\ the\ window\nsize\ is\ changed\ ---\ and\ button\ and\ label\ widgets\ stay\ fixed\ in\ size\nand\ relative-location\ as\ the\ window\ size\ is\ changed.\n\nIf\ anyone\ wants\ to\ change\ the\ way\ the\ GUI\ configures\nitself\ as\ the\ main\ window\ size\ is\ changed,\ they\ can\ experiment\nwith\ the\ \ '-side',\ '-anchor',\ '-fill',\ and\ '-expand'\ parameters\non\ the\ 'pack'\ commands\ for\ the\ various\ widgets\ ---\ to\ get\ the\nwidget\ behavior\ that\ they\ want.\ For\ example,\ I\ allow\ the\ scale\ widget\nto\ x-expand\ with\ the\ window.\ You\ may\ want\ the\ scale\ widget\ to\ be\ a\nfixed\ size.\n\nAlso,\ you\ could\ change\ the\ font\ used\ for\ the\ text\ in\ the\ widgets.\nFor\ example,\ you\ could\ change\ '-weight'\ from\ 'bold'\ to\ 'normal'\ ---\nor\ '-slant'\ from\ 'roman'\ to\ 'italic'.\ Or\ change\ font\ families.\n\nFurthermore,\ there\ are\ variables\ used\ to\ set\ geometry\ parameters\nof\ widgets\ ---\ parameters\ such\ as\ border-widths\ and\ padding.\nFeel\ free\ to\ experiment\ with\ those\ parameters\ as\ well.\n\n_____________________________________________________________________\n\nThat\ said,\ here's\ the\ code\ ---\ with\ plenty\ of\ comments\ to\ describe\nwhat\ most\ of\ the\ code-sections\ are\ doing.\n\nI\ modified\ the\ 'doodle'\ procs\ of\ Suchenwirth\ quite\ a\ bit\ ---\ and\ devised\na\ 'doodle_delete'\ proc\ to\ help\ assure\ that\ the\ desired\ object\ is\ deleted\non\ an\ MB3\ click-and-release.\n\nThe\ copious\ comments\ in\ the\ code\ might\ help\ Tcl-Tk\ coding\ 'newbies'\ get\ started\nin\ making\ GUI's\ like\ this.\ Without\ the\ comments\ ---\ especially\ in\ the\ 'doodle_delete'\nproc,\ the\ code\ might\ look\ too\ cryptic\ ---\ and\ potential\ young\ Tcler's\nmight\ be\ tempted\ to\ return\ to\ their\ iPhones\ and\ iPads\ and\ iPods\ ---\ to\ listen\nto\ recently\ released\ music\ ---\ which\ IMHO,\ for\ the\ most\ part,\ cannot\ match\ the\nmusic\ of\ the\ late\ 1960's\ and\ early\ 1970's.\n\n======\n\n#!/usr/bin/wish\ -f\n##+###########################################################################\n##\n##\ SCRIPT:\ sketch_onImgFromFile_utility.tk\n##\n##\ PURPOSE:\ This\ script\ allows\ the\ user\ to\ select\ an\ image\ file\ and\ load\n##\ \ \ \ \ \ \ \ \ \ its\ image\ onto\ a\ Tk\ canvas.\ The\ user\ can\ then\ 'freehand'\n##\ \ \ \ \ \ \ \ \ \ draw\ lines\ (curves)\ of\ varying\ width\ and\ color\ on\ the\ image,\n##\ \ \ \ \ \ \ \ \ \ using\ the\ mouse\ (or\ touchpad\ or\ touch-sensitive-screen\ or\ whatever).\n##\n##\ \ \ \ \ \ \ \ \ \ The\ user\ can\ choose\ from\ over\ 16\ million\ colors\ for\ the\n##\ \ \ \ \ \ \ \ \ \ various\ line\ segments\ drawn.\n##\n##\ \ \ \ \ \ \ \ \ \ The\ image\ files\ that\ can\ be\ loaded\ to\ the\ canvas\ may\ be\ GIF\ files\n##\ \ \ \ \ \ \ \ \ \ ---\ and\ PNG\ eventually,\ by\ using\ 8.6.x\ versions\ of\ the\ 'wish'\n##\ \ \ \ \ \ \ \ \ \ interpreter.\n##\n##\ \ \ \ \ \ \ \ \ \ (I\ used\ a\ utility\ script\ based\ on\ the\ ImageMagick\ 'convert'\n##\ \ \ \ \ \ \ \ \ \ \ command\ to\ convert\ JPEG\ files\ to\ GIF\ files,\ for\ testing.)\ \ \ \ \ \ \ \ \ \ \n##\n##\ \ \ \ \ \ \ \ \ \ The\ user\ has\ the\ option\ of\ removing\ the\ image\ from\ the\ canvas\n##\ \ \ \ \ \ \ \ \ \ (leaving\ the\ 'sketch')\ ---\ or\ the\ image\ can\ be\ left\ in\ place,\n##\ \ \ \ \ \ \ \ \ \ along\ with\ the\ sketch\ lines.\n##\n##\ \ \ \ \ \ \ \ \ \ Then\ the\ user\ can\ capture\ the\ image\ with\ a\ screen/window\ capture\n##\ \ \ \ \ \ \ \ \ \ tool\ and\ save\ the\ image\ as\ a\ PNG\ file\ (or\ whatever\ output\ format\n##\ \ \ \ \ \ \ \ \ \ the\ screen\ capture\ tool\ supports).\n##\n##\ \ \ \ \ \ \ \ \ \ The\ user\ can\ crop\ the\ image\ with\ an\ image\ editor,\ and\ save\ the\n##\ \ \ \ \ \ \ \ \ \ image\ as\ a\ PNG\ or\ JPEG\ or\ GIF\ file,\ say.\ \ Then\ the\ image\ file\n##\ \ \ \ \ \ \ \ \ \ could\ be\ used\ in\ e-mails,\ web\ pages,\ or\ even\ Tk\ GUI's.\n##\n##\ \ \ \ \ \ \ \ \ \ One\ 'application'\ of\ the\ script\ is\ to\ use\ photos\ of\ relatives\ or\n##\ \ \ \ \ \ \ \ \ \ friends\ or\ pets\ or\ favorite\ celebrities\ and\ make\ sketches\n##\ \ \ \ \ \ \ \ \ \ from\ the\ photo.\n##\n##\ \ \ \ \ \ \ \ \ \ Note\ that\ an\ image\ file\ is\ not\ required.\ This\ utility\ can\n##\ \ \ \ \ \ \ \ \ \ be\ used\ to\ sketch\ lines\ of\ various\ thicknesses\ and\ colors\n##\ \ \ \ \ \ \ \ \ \ onto\ a\ colored\ canvas.\n##\n##\ \ \ \ \ \ \ \ \ \ A\ key\ feature\ is\ the\ ability\ to\ quickly\ delete\ mistakes\n##\ \ \ \ \ \ \ \ \ \ (unwanted\ canvas\ objects\ ---\ lines\ or\ 'degenerate\ lines'=points),\n##\ \ \ \ \ \ \ \ \ \ by\ a\ button-3\ click\ on\ a\ botched\ line\ (or\ point).\n##\n##\ GUI\ DESIGN:\n##\n##\ \ \ \ \ \ \ \ \ This\ script\ provides\ a\ Tk\ GUI\ with\ the\ following\ widgets.\n##\n##\ \ \ \ \ \ \ \ \ 0)\ There\ is\ a\ CANVAS\ widget\ on\ which\ to\ load\ the\ 'photo'\ image\n##\ \ \ \ \ \ \ \ \ \ \ \ and\ on\ which\ to\ draw\ 'freehand'\ lines/curves.\n##\n##\ \ \ \ \ \ \ \ \ 1)\ There\ is\ a\ FILENAME-ENTRY\ FIELD\ and\ 'Browse\ ...'\ BUTTON\ with\n##\ \ \ \ \ \ \ \ \ \ \ \ which\ to\ get\ an\ image\ file\ to\ load\ onto\ the\ canvas\ widget\ of\n##\ \ \ \ \ \ \ \ \ \ \ \ this\ GUI.\n##\n##\ \ \ \ \ \ \ \ \ 2)\ There\ is\ a\ set\ of\ BUTTONS\ ---\ 'Exit'\ and\ 'RemoveImage'\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ 'RemoveLines'\ and\ 'RaiseLines'\ and\ a\ couple\ of\ COLOR\ buttons\n##\ \ \ \ \ \ \ \ \ \ \ \ to\ set\ the\ current\ line-drawing\ color\ ---\ and\ to\ set\n##\ \ \ \ \ \ \ \ \ \ \ \ a\ background\ (canvas)\ color.\ \ The\ background\ color\ shows\ if\n##\ \ \ \ \ \ \ \ \ \ \ \ the\ user\ chooses\ to\ remove\ the\ image\ that\ was\ placed\ on\n##\ \ \ \ \ \ \ \ \ \ \ \ the\ canvas.\n##\n##\ \ \ \ \ \ \ \ \ 3)\ There\ is\ a\ SCALE\ widget\ to\ set\ the\ WIDTH\ of\ the\ next\n##\ \ \ \ \ \ \ \ \ \ \ \ line-segments\ to\ be\ drawn.\n##\n##\ \ \ \ \ \ \ \ \ 4)\ Other\ controls\ were\ added:\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ a\ SCALE\ to\ set\ millisecs\ between\ points\ added\ to\ current\ line\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ ---\ to\ let\ the\ user\ control\ the\ 'jitteriness'\ ---\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ the\ straightness\ ---\ of\ the\ line\ being\ drawn.\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ CHECKBUTTON\ to\ set\ line\ style:\ 'smooth'\ (curved)\ ---\ or\ polygonal\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ RADIOBUTTONS\ to\ set\ line\ cap-style:\ round/butt/projecting\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ RADIOBUTTONS\ to\ set\ line\ join-style:\ round/bevel/miter\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ LABELS\ to\ show\ 'Nobj'\ and\ 'NcurPoints',\ where\ \$Nobj\ is\ the\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ number\ of\ objects\ (lines\ and\ points)\ in\ the\ current\ drawing,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ \$NcurPoints\ is\ the\ number\ of\ points\ being\ generated\ in\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ the\ line\ currently\ being\ drawn.\n##\n##+########################\n##\ REFERENCES\ (and\ credits):\n##\n##\ \ The\ image\ file\ loading\ code\ (and\ a\ lot\ of\ the\ other\ code)\ in\ this\ script\n##\ \ is\ based\ on\ my\ script\ 'photoFile_editing_viaFunctions.tk'\ from\ the\n##\ \ http://wiki.tcl.tk/36850\ -\ 'GUI\ for\ Editing\ Photo-images\ with\ Functions'.\n##\n##\ \ The\ code\ for\ the\ 'doodling'\ on\ the\ canvas\ was\ based\ on\ \n##\ \ 'A\ minimal\ doodler\ explained'\ -\ http://wiki.tcl.tk/9625\n##\ \ by\ Richard\ Suchenwirth,\ 2003\ Aug.\n##\n##\ \ Similar\ code\ was\ posted\ by\ 'elfo',\ years\ earlier:\n##\ \ http://wiki.tcl.tk/1155\ \ -\ 'Canvas\ pixel\ painting'\n##\n##\ \ Some\ reading\ of\ Chapter\ 37\ 'The\ Canvas\ Widget'\ in\ the\ 4th\ edition\n##\ \ of\ the\ book\ 'Practical\ Programming\ in\ Tcl\ and\ Tk'\ was\ helpful.\n##\n##+#######################################################################\n##\ 'CANONICAL'\ STRUCTURE\ OF\ THIS\ CODE:\n##\n##\ \ 0)\ Set\ general\ window\ parms\ (win-name,\ win-position,\ win-color-scheme,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ fonts,\ widget-geometry,\ win-size-control).\n##\ \ 1a)\ Define\ ALL\ frames\ and\ sub-frames.\n##\ \ 1b)\ Pack\ \ \ ALL\ frames\ and\ sub-frames.\n##\ \ 2)\ Define\ &\ pack\ all\ widgets\ in\ the\ frames.\n##\n##\ \ 3)\ Define\ key\ and\ mouse/touchpad/touch-sensitive-screen\ action\n##\ \ \ \ \ BINDINGS,\ if\ needed.\n##\ \ 4)\ Define\ PROCS,\ if\ needed.\n##\ \ 5)\ Additional\ GUI\ INITIALIZATION\ (typically\ with\ one\ or\ more\ of\n##\ \ \ \ \ the\ procs),\ if\ needed.\n##\n##+#################################\n##\ Some\ detail\ of\ the\ code\ structure\ of\ this\ particular\ script:\n##\n##\ \ 1a)\ Define\ ALL\ frames:\n##\ \n##\ \ \ Top-level\ :\n##\ \ \ \ \ \ \ 'fRfile'\ \ \ \ \ \ -\ to\ contain\ a\ triplet:\ label-entry-button\ widgets\n##\ \ \ \ \ \ \ 'fRbuttons'\ \ \ -\ to\ contain\ an\ 'Exit'\ button,\ 'Help'\ button,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 'RemoveImg'\ &\ 'RemoveLines'\ &\ 'RaiseLines'\ buttons,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ 2\ color\ selection\ buttons\ (for\ next\ line\ color\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ for\ canvas/background\ color).\n##\ \ \ \ \ \ \ 'fRstatus'\ \ \ \ \ -\ to\ contain\ labels\ showing\ Nobj\ and\ NcurPoints.\n##\ \ \ \ \ \ \ 'fRcontrols1'\ \ -\ to\ contain\ a\ label\ &\ scale\ widget\ pair\ for\ next-line\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ width\ ---\ and\ a\ label\ &\ scale\ widget\ pair\ for\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ setting\ a\ 'milliseconds\ tween\ added\ points'\ variable,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Nmillisecs,\ which\ controls\ line-'jitter'/straightness\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ by\ controlling\ the\ number\ of\ 'control\ points'\ in\ a\ line.\n##\ \ \ \ \ \ \ 'fRcontrols2'\ \ -\ to\ contain\ a\ checkbutton\ to\ set\ the\ 'smooth'\ option\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ of\ 'create\ line'\ on/off.\ Also\ to\ contain\ 2\ sets\ of\ radiobuttons\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ for\ the\ 'capstyle'\ &\ 'joinstyle'\ options\ of\ 'create\ line'.\n##\ \ \ \ \ \ \ 'fRcanvas'\ \ \ \ \ -\ to\ contain\ the\ canvas\ widget.\n##\n##\ \ \ Sub-frames:\ none\n##\n##\ \ 1b)\ Pack\ ALL\ frames.\ (Note:\ We\ may\ change\ the\ packing\ order\ of\ the\ frames\n##\ \ \ \ \ \ as\ we\ experiment\ with\ the\ GUI\ layout.\ In\ fact,\ some\ widgets\ may\ be\n##\ \ \ \ \ \ switched\ from\ one\ frame\ to\ another.)\n##\n##\ \ 2)\ Define\ &\ pack\ all\ widgets\ in\ the\ frames\ --\ basically\ going\ through\n##\ \ \ \ \ frames\ &\ their\ interiors\ in\ top-to-bottom\ and/or\ left-to-right\ order:\n##\n##\ \ 3)\ Define\ bindings:\n##\ \ \ \ \ \ -\ Button1-release\ \ -\ on\ the\ filename\ entry\ field\ -\ to\ put\ img\ on\ canvas\n##\ \ \ \ \ \ -\ Return/Enter\ key\ -\ on\ the\ filename\ entry\ field\ -\ to\ put\ img\ on\ canvas\n##\n##\ \ \ \ \ \ -\ bind\ <ButtonPress-1>\ \ \ -\ on\ the\ canvas\ -\ calls\ proc\ 'doodle_start'\n##\ \ \ \ \ \ -\ bind\ <Button1-Motion>\ \ -\ on\ the\ canvas\ -\ calls\ proc\ 'doodle_continue'\n##\ \ \ \ \ \ -\ bind\ <ButtonRelease-1>\ -\ on\ the\ canvas\ -\ calls\ proc\ 'doodle_end'\n##\n##\ \ \ \ \ \ -\ bind\ <ButtonRelease-3>\ -\ on\ the\ canvas\ -\ calls\ proc\ 'doodle_delete'\n##\n##\ \ \ \ Two\ Button3\ Enter/Leave\ bindings\ could\ be\ added\ to\ change\ the\ color\ of\ a\ line\ (say,\n##\ \ \ \ to\ orange)\ when\ the\ mouse\ is\ over\ a\ line\ ---\ to\ let\ the\ user\ know\ which\ line-object\n##\ \ \ \ has\ been\ detected\ ---\ to\ help\ with\ deleting\ lines/objects\ ---\ so\ that\ the\n##\ \ \ \ wrong\ object\ is\ not\ deleted.\n##\n##\ \ \ \ \ \ -\ bind\ <Control-ButtonPress-1>\ \ \ -\ on\ the\ canvas\ -\ calls\ proc\ 'image_grab'\n##\ \ \ \ \ \ -\ bind\ <Control-Button1-Motion>\ \ -\ on\ the\ canvas\ -\ calls\ proc\ 'image_move'\n##\n##\n##\ \ 4)\ Define\ procs:\n##\ \ \ \ \ -\ 'get_img_filename'\ \ \ \ \ \ -\ to\ get\ the\ image\ filename\n##\ \ \ \ \ -\ 'doodle_start'\ \ \ \ \ \ \ \ \ \ -\ to\ start\ a\ 'doodle'\ line\n##\ \ \ \ \ -\ 'doodle_continue'\ \ \ \ \ \ \ -\ to\ continue\ a\ 'doodle'\ line\n##\ \ \ \ \ -\ 'doodle_end'\ \ \ \ \ \ \ \ \ \ \ \ -\ to\ finish\ a\ 'doodle'\ line\n##\ \ \ \ \ -\ 'doodle_delete'\ \ \ \ \ \ \ \ \ -\ to\ delete\ a\ 'closest'\ doodle\ line\n##\ \ \ \ \ -\ 'image_grab'\ \ \ \ \ \ \ \ \ \ \ \ -\ to\ start\ grab\ the\ image\ (not\ needed?)\n##\ \ \ \ \ -\ 'image_move'\ \ \ \ \ \ \ \ \ \ \ \ -\ to\ move\ the\ image\n##\ \ \ \ \ -\ 'set_line_color1'\ \ \ \ \ \ \ -\ to\ set\ the\ 'fill'\ color\ for\ drawing\ the\ next\ line\n##\ \ \ \ \ -\ 'set_background_color'\ \ -\ to\ set\ the\ background\ (canvas)\ color\n##\ \ \ \ \ -\ 'update_colors_label'\ \ \ -\ to\ set\ a\ COLORS\ label\ to\ current\ color\ vals\n##\ \ \ \ \ -\ 'update_status_labels'\ \ -\ to\ set\ 2\ counts\ labels\ to\ current\ vals\n##\ \ \ \ \ -\ 'remove_all_lines'\ \ \ \ \ \ -\ to\ remove\ all\ lines\ from\ the\ canvas\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ reset\ a\ couple\ of\ counts\n##\ \ \ \ \ -\ 'popup_msg_var'\ \ \ \ \ \ \ \ \ -\ to\ show\ help\ (could\ be\ used\ to\ show\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ other\ msgs,\ as\ needed)\n##\n##\ \ 5)\ Additional\ GUI\ initialization:\ set\ a\ default\ canvas\ color\ ---\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ other\ than\ that,\ the\ canvas\ is\ blank,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ waiting\ for\ the\ user\ to\ select\ an\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ image\ and\ start\ drawing\ lines\ ---\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ or\ simply\ start\ drawing\ lines.\n##\n##+#######################################################################\n##\ DEVELOPED\ WITH:\ Tcl-Tk\ 8.5\ on\ Ubuntu\ 9.10\ (2009-october,\ 'Karmic\ Koala')\n##\n##\ \ \ \$\ wish\n##\ \ \ %\ puts\ \"\$tcl_version\ \$tk_version\"\n##\n##\ showed\n##\ \ \ \ \ 8.5\ 8.5\n##\ but\ this\ script\ should\ work\ in\ most\ previous\ 8.x\ versions,\ and\ probably\n##\ even\ in\ some\ 7.x\ versions\ (if\ font\ handling\ is\ made\ 'old-style').\n##+#######################################################################\n##\ MAINTENANCE\ HISTORY:\n##\ Started\ by:\ Blaise\ Montandon\ 2012sep22\ Started\ development,\ on\ Ubuntu\ 9.10,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ based\ on\ my\ code\ at\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ http://wiki.tcl.tk/36850\ -\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 'GUI\ for\ Editing\ Photo-images\ with\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Functions'\n##\ Changed\ by:\ Blaise\ Montandon\ 2012oct05\ Improve\ the\ 'doodle_delete'\ proc\ to\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ make\ sure\ it\ deletes\ a\ line\ segment\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ not\ the\ image.\ Also\ add\ a\ 'halo'\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ parm\ to\ delete\ the\ intended\ line\ segment.\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Add\ an\ MB2\ binding\ to\ move\ the\ image.\n##\ Changed\ by:\ Blaise\ Montandon\ 2012oct20\ Added\ counters\ Nobj\ &\ NcurPoints\ ---\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ to\ indicate\ to\ the\ user\ how\ many\ lines\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ points\ are\ being\ generated.\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Added\ a\ scale\ to\ 'fRcontrols1'\ to\ set\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ the\ new\ var\ Nmillisecs\ ---\ to\ help\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ draw\ straight\ lines.\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Added\ frames\ 'fRstatus'\ &\ 'fRcontrols2'\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ the\ label\ &\ checkbutton\ &\ radiobutton\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ widgets\ within\ them.\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Added\ button3-enter\ &\ button3-leave\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ bindings\ to\ hilite\ an\ object\ before\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ it\ is\ deleted.\n##+########################################################################\n\n\n##+#######################################################################\n##\ Set\ general\ window\ parms\ (titles,position).\n##+#######################################################################\n\nwm\ title\ \ \ \ .\ \"'Sketch\ On'\ ...\ an\ image\ or\ a\ color\ background\"\nwm\ iconname\ .\ \"SketchOn\"\n\nwm\ geometry\ .\ +15+30\n\n\n##+######################################################\n##\ Set\ the\ color\ scheme\ for\ the\ window\ and\ its\ widgets\ ---\n##\ such\ as\ entry\ field\ background\ color.\n##+######################################################\n\ntk_setPalette\ \"#e0e0e0\"\n\nset\ entryBKGD\ \"#ffffff\"\n#\ set\ listboxBKGD\ \"#ffffff\"\n\n##\ Initialize\ the\ line-drawing\ color\n##\ and\ the\ background\ color\ for\ the\ canvas.\n\nset\ COLOR1r\ 0\nset\ COLOR1g\ 0\nset\ COLOR1b\ 0\n#\ set\ COLOR1r\ 255\n#\ set\ COLOR1g\ 255\n#\ set\ COLOR1b\ 0\nset\ COLOR1hex\ \[format\ \"#%02X%02X%02X\"\ \$COLOR1r\ \$COLOR1g\ \$COLOR1b\]\n\n\n#\ set\ COLORbkGNDr\ 60\n#\ set\ COLORbkGNDg\ 60\n#\ set\ COLORbkGNDb\ 60\nset\ COLORbkGNDr\ 255\nset\ COLORbkGNDg\ 255\nset\ COLORbkGNDb\ 255\nset\ COLORbkGNDhex\ \\\n\ \ \ \ \[format\ \"#%02X%02X%02X\"\ \$COLORbkGNDr\ \$COLORbkGNDg\ \$COLORbkGNDb\]\n\n\nset\ radbuttBKGD\ \"#f0f0f0\"\n\n\n##+########################################################\n##\ We\ use\ a\ VARIABLE-WIDTH\ font\ for\ text\ on\ label\ and\n##\ button\ widgets.\n##\n##\ We\ use\ a\ FIXED-WIDTH\ font\ for\ text\ in\ entry\ &\ listbox\ widgets\n##\ and\ for\ the\ text\ in\ a\ text\ widget,\ such\ as\ help\ text.\n##+########################################################\n\nfont\ create\ fontTEMP_varwidth\ \\\n\ \ \ -family\ \{comic\ sans\ ms\}\ \\\n\ \ \ -size\ -14\ \\\n\ \ \ -weight\ bold\ \\\n\ \ \ -slant\ roman\n\nfont\ create\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -family\ \{comic\ sans\ ms\}\ \\\n\ \ \ -size\ -10\ \\\n\ \ \ -weight\ bold\ \\\n\ \ \ -slant\ roman\n\n##\ Some\ other\ possible\ (similar)\ variable\ width\ fonts:\n##\ \ Arial\n##\ \ Bitstream\ Vera\ Sans\n##\ \ DejaVu\ Sans\n##\ \ Droid\ Sans\n##\ \ FreeSans\n##\ \ Liberation\ Sans\n##\ \ Nimbus\ Sans\ L\n##\ \ Trebuchet\ MS\n##\ \ Verdana\n\nfont\ create\ fontTEMP_fixedwidth\ \ \\\n\ \ \ -family\ \{liberation\ mono\}\ \\\n\ \ \ -size\ -14\ \\\n\ \ \ -weight\ bold\ \\\n\ \ \ -slant\ roman\n\nfont\ create\ fontTEMP_SMALL_fixedwidth\ \ \\\n\ \ \ -family\ \{liberation\ mono\}\ \\\n\ \ \ -size\ -10\ \\\n\ \ \ -weight\ bold\ \\\n\ \ \ -slant\ roman\n\n##\ Some\ other\ possible\ fixed\ width\ fonts\ (esp.\ on\ Linux):\n##\ \ Andale\ Mono\n##\ \ Bitstream\ Vera\ Sans\ Mono\n##\ \ Courier\ 10\ Pitch\n##\ \ DejaVu\ Sans\ Mono\n##\ \ Droid\ Sans\ Mono\n##\ \ FreeMono\n##\ \ Nimbus\ Mono\ L\n##\ \ TlwgMono\n\n\n##+###########################################################\n##\ SET\ GEOM\ VARS\ FOR\ THE\ VARIOUS\ WIDGET\ DEFINITIONS.\n##\ (e.g.\ width\ and\ height\ of\ canvas,\ and\ padding\ for\ Buttons)\n##+###########################################################\n\nset\ initCanWidthPx\ 300\nset\ initCanHeightPx\ 300\n\nset\ minCanWidthPx\ 24\nset\ minCanHeightPx\ 24\n\n#\ set\ BDwidthPx_canvas\ 2\n\ \ set\ BDwidthPx_canvas\ 0\n\n\n##\ BUTTON\ widget\ geom\ settings:\n\nset\ PADXpx_button\ 0\nset\ PADYpx_button\ 0\nset\ BDwidthPx_button\ 2\n\n\n##\ LABEL\ widget\ geom\ settings:\n\nset\ BDwidthPx_label\ 2\n\n\n##\ ENTRY\ widget\ geom\ settings:\n\nset\ BDwidthPx_entry\ 2\nset\ initImgfileEntryWidthChars\ 20\n\n\n##\ SCALE\ geom\ parameters:\n\nset\ BDwidthPx_scale\ 2\nset\ initScaleLengthPx\ 200\n\n\n##\ LISTBOX\ geom\ settings:\n\n#\ set\ BDwidthPx_listbox\ 2\n#\ set\ initListboxWidthChars\ 30\n#\ set\ initListboxHeightChars\ 8\n\n\n##+#######################################################################\n##\ Set\ a\ MINSIZE\ of\ the\ window\ (roughly).\n##\n##\ For\ width,\ allow\ for\ the\ minwidth\ of\ the\ '.fRbuttons'\ frame:\n##\ \ \ \ \ \ \ \ \ \ \ \ about\ 4\ buttons\ (Exit,RemoveImg,Color1,ColorBkgnd),\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ a\ label\ with\ current\ color\ values\ info.\n##\n##\ For\ height,\ allow\ for\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 1\ char\ high\ for\ the\ '.fRfile'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 2\ chars\ high\ for\ the\ widgets\ in\ the\ '.fRbuttons'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 1\ char\ high\ for\ the\ '.fRstatus'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 2\ chars\ high\ for\ the\ '.fRcontrols1'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 2\ chars\ high\ for\ the\ '.fRcontrols2'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ a\ canvas\ at\ least\ 24\ pixels\ high.\n##+#######################################################################\n\nset\ minWinWidthPx\ \[font\ measure\ fontTEMP_varwidth\ \\\n\ \ \ \"Exit\ Remove\ Next\ Line\ Background\ \ Colors:\ Line\ #ff00ff\ Bkgnd:\ #000000\"\]\n\n##\ Add\ some\ pixels\ to\ account\ for\ right-left-side\ window\ decoration\n##\ (about\ 8\ pixels),\ about\ 5\ x\ 8\ pixels/widget\ for\ borders/padding\ for\n##\ 5\ widgets\ ---\ 4\ buttons\ and\ 1\ label.\n\nset\ minWinWidthPx\ \[expr\ \{48\ +\ \$minWinWidthPx\}\]\n\n\n##\ MIN\ HEIGHT\ ---\n##\ for\ the\ 6\ frames\ 'fRfile'\ 'fRstatus'\ 'fRbuttons'\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 'fRcontrols1'\ 'fRcontrols2'\ 'fRcanvas'.\n##\ Allow\n##\ \ \ \ 1\ char\ \ high\ for\ 'fRfile'\n##\ \ \ \ 2\ char\ \ high\ for\ 'fRbuttons'\n##\ \ \ \ 1\ char\ \ high\ for\ 'fRstatus'\n##\ \ \ \ 2\ chars\ high\ for\ 'fRcontrols1'\n##\ \ \ \ 2\ chars\ high\ for\ 'fRcontrols2'\n##\ \ \ 24\ pixels\ high\ for\ 'fRcanvas'\n\nset\ charHeightPx\ \[font\ metrics\ fontTEMP_fixedwidth\ -linespace\]\n\nset\ minWinHeightPx\ \[expr\ \{24\ +\ 8\ *\ \$charHeightPx\}\]\n\n##\ Add\ about\ 28\ pixels\ for\ top-bottom\ window\ decoration,\n##\ about\ 6x6\ pixels\ for\ each\ of\ the\ 6\ stacked\ frames\ and\ their\n##\ widgets\ (their\ borders/padding).\n\nset\ minWinHeightPx\ \[expr\ \{\$minWinHeightPx\ +\ 64\}\]\n\n##\ FOR\ TESTING:\n#\ \ \ puts\ \"minWinWidthPx\ =\ \$minWinWidthPx\"\n#\ \ \ puts\ \"minWinHeightPx\ =\ \$minWinHeightPx\"\n\nwm\ minsize\ .\ \$minWinWidthPx\ \$minWinHeightPx\n\n\n##\ We\ allow\ the\ window\ to\ be\ resizable\ and\ we\ pack\ the\ canvas\ with\n##\ '-fill\ both'\ so\ that\ the\ canvas\ can\ be\ enlarged\ by\ enlarging\ the\n##\ window.\n\n##\ If\ you\ want\ to\ make\ the\ window\ un-resizable,\ \n##\ you\ can\ use\ the\ following\ statement.\n#\ wm\ resizable\ .\ 0\ 0\n\n\n##+################################################################\n##\ DEFINE\ *ALL*\ THE\ FRAMES:\n##\n##\ \ \ Top-level\ :\ '.fRfile'\ '.fRbuttons'\ '.fRstatus'\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '.fRcontrols1'\ '.fRcontrols2'\ '.fRcanvas'\n##\n##\ \ \ Sub-frames:\ none\n##+################################################################\n\n#\ set\ RELIEF_frame\ raised\n#\ set\ BDwidth_frame\ 2\n\n\ \ set\ RELIEF_frame\ flat\n\ \ set\ BDwidth_frame\ 0\n\nframe\ .fRfile\ \ \ \ \ \ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRbuttons\ \ \ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRstatus\ \ \ \ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRcontrols1\ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRcontrols2\ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRcanvas\ \ \ \ -relief\ raised\ \ \ \ \ \ \ \ \ -bd\ 2\n\n\n##+######################################\n##\ PACK\ the\ FRAMES.\ \n##\ NOTE:\ We\ can\ experiment\ with\ the\ order\n##\ in\ which\ the\ frames\ are\ stacked.\n##+######################################\n\npack\ .fRfile\ \\\n\ \ \ -side\ top\ \\\n\ \ \ -anchor\ nw\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 0\n\npack\ .fRbuttons\ \\\n\ \ \ \ \ .fRstatus\ \\\n\ \ \ \ \ .fRcontrols2\ \\\n\ \ \ \ \ .fRcontrols1\ \\\n\ \ \ -side\ top\ \\\n\ \ \ -anchor\ nw\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\npack\ .fRcanvas\ \\\n\ \ \ -side\ top\ \\\n\ \ \ -anchor\ nw\ \\\n\ \ \ -fill\ both\ \\\n\ \ \ -expand\ 1\n\n##\ OK,\ frames\ are\ defined.\ Now\ start\ defining-and-packing\ widgets.\n\n\n##+###############################\n##\ In\ FRAME\ '.fRfile'\ -\n##\ DEFINE-and-PACK\ 3\ widgets\ -\n##\ LABEL,\ ENTRY,\ BUTTON:\n##+###############################\n\nlabel\ .fRfile.labelFILE\ \\\n\ \ \ -text\ \"ImgFilename\ (GIF/PNG):\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ 0\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ ENTRYfilename\ \"\"\n\nentry\ .fRfile.entFILENAME\ \\\n\ \ \ -textvariable\ ENTRYfilename\ \\\n\ \ \ -bg\ \$entryBKGD\ \\\n\ \ \ -font\ fontTEMP_fixedwidth\ \\\n\ \ \ -width\ \$initImgfileEntryWidthChars\ \\\n\ \ \ -relief\ sunken\ \\\n\ \ \ -bd\ \$BDwidthPx_entry\n\nbutton\ .fRfile.buttBROWSE\ \\\n\ \ \ -text\ \"Browse\ ...\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{get_img_filename\}\n\n\n##\ Pack\ the\ '.fRfile'\ widgets.\n\npack\ \ .fRfile.labelFILE\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\npack\ .fRfile.entFILENAME\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 1\n\npack\ \ .fRfile.buttBROWSE\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\n\n##+#########################################\n##\ In\ FRAME\ '.fRbuttons'\ -\n##\ DEFINE-and-PACK\ 7\ 'BUTTON'\ WIDGETS\n##\ ---\ and\ a\ label\ widget.\n##+#########################################\n\nbutton\ .fRbuttons.buttEXIT\ \\\n\ \ \ -text\ \"Exit\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{exit\}\n\nbutton\ .fRbuttons.buttHELP\ \\\n\ \ \ -text\ \"Help\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{popup_msg_var\ \"\$HELPtext\"\}\n\nbutton\ .fRbuttons.buttREMOVEIMG\ \\\n\ \ \ -text\ \"RemoveImg\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{.fRcanvas.can\ delete\ TAGimg\ \;\ image\ delete\ imgID1\}\n\nbutton\ .fRbuttons.buttREMOVELINES\ \\\n\ \ \ -text\ \"RemoveLines\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{remove_all_lines\}\n\nbutton\ .fRbuttons.buttRAISELINES\ \\\n\ \ \ -text\ \"RaiseLines\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{.fRcanvas.can\ raise\ TAGlines\}\n\nbutton\ .fRbuttons.buttCOLOR1\ \\\n\ \ \ -text\ \"\\\nNext\ Line\n\ Color\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \"set_line_color1\"\n\nbutton\ .fRbuttons.buttCOLORbkGND\ \\\n\ \ \ -text\ \"\\\nBackground\nColor\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \"set_background_color\"\n\n\nlabel\ .fRbuttons.labelCOLORS\ \\\n\ \ \ -text\ \"\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\n\n##+##################################################\n##\ Pack\ the\ widgets\ in\ the\ '.fRbuttons'\ frame.\n##+##################################################\n\npack\ .fRbuttons.buttEXIT\ \\\n\ \ \ \ \ .fRbuttons.buttHELP\ \\\n\ \ \ \ \ .fRbuttons.buttREMOVEIMG\ \\\n\ \ \ \ \ .fRbuttons.buttREMOVELINES\ \\\n\ \ \ \ \ .fRbuttons.buttRAISELINES\ \\\n\ \ \ \ \ .fRbuttons.buttCOLOR1\ \\\n\ \ \ \ \ .fRbuttons.buttCOLORbkGND\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\n\npack\ .fRbuttons.labelCOLORS\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 0\n\n\n##+#########################################\n##\ In\ FRAME\ '.fRstatus'\ -\n##\ DEFINE-and-PACK\ \ 1\ CHECKBUTTON\ WIDGET\n##\ and\ 4\ 'LABEL'\ WIDGETS.\n##+#########################################\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ smooth0or1\ 1\n\ncheckbutton\ .fRstatus.chkbuttSMOOTH\ \\\n\ \ \ -text\ \"\\\nMake\ curves\ between\n\ points\ in\ the\ next\ line.\"\ \\\n\ \ \ -font\ \ fontTEMP_varwidth\ \\\n\ \ \ -variable\ smooth0or1\ \\\n\ \ \ -selectcolor\ \"#cccccc\"\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nlabel\ .fRstatus.label4COUNTobj\ \\\n\ \ \ -text\ \"\ \ \ Lines\ (incl.\ single-point\ lines)\ currently\ in\ drawing:\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\nlabel\ .fRstatus.labelCOUNTobj\ \\\n\ \ \ -text\ \"\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\ \\\n\ \ \ -padx\ 20\n\nlabel\ .fRstatus.label4COUNTpoints\ \\\n\ \ \ -text\ \"Points\ in\ last-created\ line:\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\nlabel\ .fRstatus.labelCOUNTpoints\ \\\n\ \ \ -text\ \"\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\ \\\n\ \ \ -padx\ 20\n\n##\ Pack\ the\ widgets\ in\ frame\ '.fRstatus'.\n\npack\ .fRstatus.chkbuttSMOOTH\ \\\n\ \ \ \ \ .fRstatus.label4COUNTobj\ \\\n\ \ \ \ \ .fRstatus.labelCOUNTobj\ \\\n\ \ \ \ \ .fRstatus.label4COUNTpoints\ \\\n\ \ \ \ \ .fRstatus.labelCOUNTpoints\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\n\n##+#########################################\n##\ In\ FRAME\ '.fRcontrols1'\ -\n##\ DEFINE-and-PACK\ 2\ 'SCALE'\ WIDGETS\n##\ ---\ with\ their\ label\ widgets.\n##\ \ \ (One\ scale\ for\ setting\ the\ 'next'\n##\ \ \ \ line-width.\n##\ \ \ \ One\ scale\ for\ setting\ the\n##\ \ \ \ millisecs\ var\ to\ control\ 'jitter'\n##\ \ \ \ or\ straightness\ of\ next\ line.)\n##+########################################\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ lineWIDTHpx\ 2\n\n##\ Define\ a\ label\ widget\ for\ the\ lineWIDTHpx\ scale\ widget.\n\nlabel\ .fRcontrols1.labelLINEWIDTH\ \\\n\ \ \ -text\ \"\\\nWidth\ (pixels)\ for\n\ the\ next\ line:\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\nscale\ .fRcontrols1.scaleLINEWIDTH\ \\\n\ \ \ -orient\ horizontal\ \\\n\ \ \ -resolution\ 1\ \\\n\ \ \ -from\ 1\ -to\ 100\ \\\n\ \ \ -length\ \$initScaleLengthPx\ \\\n\ \ \ -variable\ lineWIDTHpx\n\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ Nmillisecs\ 2\n\n##\ Define\ a\ label\ widget\ for\ the\ Nmillisecs\ scale\ widget.\n\nlabel\ .fRcontrols1.labelMILLISECS\ \\\n\ \ \ -text\ \"\\\nMillisecs\ tween\ adding\n\ points\ to\ next\ line:\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\nscale\ .fRcontrols1.scaleMILLISECS\ \\\n\ \ \ -orient\ horizontal\ \\\n\ \ \ -resolution\ 1\ \\\n\ \ \ -from\ 0\ -to\ 2000\ \\\n\ \ \ -length\ \$initScaleLengthPx\ \\\n\ \ \ -variable\ Nmillisecs\n\n\nlabel\ .fRcontrols1.labelMILLISECShelp\ \\\n\ \ \ -text\ \"\\\nSet\ millisecs\ high\ (>\ 700)\ to\n\ help\ draw\ straight\ lines.\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\n\n##\ PACK\ the\ widgets\ of\ FRAME\ '.fRcontrols1'\ ---\n##\ label,\ scale,\ label,\ scale,\ label.\n##\n##\ We\ use\ '-expand\ 1'\ in\ packing\ the\ scale\ widgets,\n##\ to\ allow\ them\ to\ x-expand\ if\ window\ is\ x-expanded.\n##\ That\ action\ depends\ on\ the\ pack\ parameters\ of\n##\ frame\ '.fRcontrols1'.\n\npack\ .fRcontrols1.labelLINEWIDTH\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\npack\ .fRcontrols1.scaleLINEWIDTH\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 1\n\npack\ .fRcontrols1.labelMILLISECS\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\npack\ .fRcontrols1.scaleMILLISECS\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 1\n\npack\ .fRcontrols1.labelMILLISECShelp\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\n\n##+#########################################\n##\ In\ FRAME\ '.fRcontrols2'\ -\n##\ DEFINE-and-PACK\ 1\ 'CHECKBUTTON'\ WIDGET\n##\ and\ 1\ LABEL\ and\ 3\ RADIOBUTTONS,\n##\ and\ 1\ more\ LABEL\ and\ 3\ more\ RADIOBUTTONS.\n##\ \ \ (One\ checkbutton\ for\ turning\ on/off\n##\ \ \ \ the\ 'smooth'\ option\ of\ 'create\ line'.\n##\ \ \ \ Radiobuttons\ for\ setting\ 'cap'\ and\n##\ \ \ \ 'join'\ styles\ of\ 'create\ line'.)\n##+########################################\n\n\nlabel\ .fRcontrols2.labelCAPSTYLE\ \\\n\ \ \ -text\ \"\\\nCap-style\ of\ line-segs:\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ lineCAPstyle\ \"round\"\n##\ Line\ cap-style\ options:\ round/butt/projecting\n\nradiobutton\ \ .fRcontrols2.radbuttCAPSTYLE1\ \\\n\ \ \ -text\ \"round\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineCAPstyle\ \\\n\ \ \ -value\ \"round\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nradiobutton\ \ .fRcontrols2.radbuttCAPSTYLE2\ \\\n\ \ \ -text\ \"butt\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineCAPstyle\ \\\n\ \ \ -value\ \"butt\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nradiobutton\ \ .fRcontrols2.radbuttCAPSTYLE3\ \\\n\ \ \ -text\ \"projecting\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineCAPstyle\ \\\n\ \ \ -value\ \"projecting\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -padx\ 20\n\n\nlabel\ .fRcontrols2.labelJOINSTYLE\ \\\n\ \ \ -text\ \"\\\nJoin-style\ of\ line-segs:\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\nset\ lineJOINstyle\ \"round\"\n##\ Line\ join-style\ options:\ round/bevel/miter\n\nradiobutton\ \ .fRcontrols2.radbuttJOINSTYLE1\ \\\n\ \ \ -text\ \"round\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineJOINstyle\ \\\n\ \ \ -value\ \"round\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nradiobutton\ \ .fRcontrols2.radbuttJOINSTYLE2\ \\\n\ \ \ -text\ \"bevel\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineJOINstyle\ \\\n\ \ \ -value\ \"bevel\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nradiobutton\ \ .fRcontrols2.radbuttJOINSTYLE3\ \\\n\ \ \ -text\ \"miter\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineJOINstyle\ \\\n\ \ \ -value\ \"miter\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\n##\ PACK\ the\ widgets\ of\ FRAME\ '.fRcontrols2'\ ---\n##\ checkbutton,\ label,\ 3\ radiobuttons,\ label,\ 3\ radiobuttons.\n\npack\ .fRcontrols2.labelCAPSTYLE\ \\\n\ \ \ \ \ .fRcontrols2.radbuttCAPSTYLE1\ \\\n\ \ \ \ \ .fRcontrols2.radbuttCAPSTYLE2\ \\\n\ \ \ \ \ .fRcontrols2.radbuttCAPSTYLE3\ \\\n\ \ \ \ \ .fRcontrols2.labelJOINSTYLE\ \\\n\ \ \ \ \ .fRcontrols2.radbuttJOINSTYLE1\ \\\n\ \ \ \ \ .fRcontrols2.radbuttJOINSTYLE2\ \\\n\ \ \ \ \ .fRcontrols2.radbuttJOINSTYLE3\ \\\n\ \ \ \ \ \ -side\ left\ \\\n\ \ \ \ \ \ -anchor\ w\ \\\n\ \ \ \ \ \ -fill\ none\ \\\n\ \ \ \ \ \ -expand\ 0\n\n\n##+###################################################\n##\ In\ FRAME\ '.fRcanvas'\ -\n##\ DEFINE-and-PACK\ a\ CANVAS\ WIDGET:\n##+###################################################\n##\ We\ set\ '-highlightthickness'\ and\ '-borderwidth'\ to\n##\ zero,\ to\ avoid\ covering\ some\ of\ the\ viewable\ area\n##\ of\ the\ canvas,\ as\ suggested\ on\ page\ 558\ of\ the\ 4th\n##\ edition\ of\ 'Practical\ Programming\ with\ Tcl\ and\ Tk'.\n##+###################################################\n\ncanvas\ .fRcanvas.can\ \\\n\ \ \ -width\ \$initCanWidthPx\ \\\n\ \ \ -height\ \$initCanHeightPx\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -highlightthickness\ 0\ \\\n\ \ \ -borderwidth\ 0\n\npack\ .fRcanvas.can\ \\\n\ \ \ -side\ top\ \\\n\ \ \ -anchor\ nw\ \\\n\ \ \ -fill\ both\ \\\n\ \ \ -expand\ 1\n\n\n##+##################################################\n##\ END\ OF\ DEFINITION\ of\ the\ GUI\ widgets.\n##+##################################################\n##\ Start\ of\ BINDINGS,\ PROCS,\ Added-GUI-INIT\ sections.\n##+##################################################\n\n##+#######################################################################\n##+#######################################################################\n##\ \ BINDINGS\ SECTION:\n##\ \ \ -\ For\ MB1-release\ on\ the\ image-filename\ entry\ field,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ load\ the\ image\ onto\ the\ canvas.\n##\ \ \ -\ For\ Return-key\ press\ with\ text\ cursor\ in\ the\ image-filename\ entry\ field,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ load\ the\ image\ onto\ the\ canvas.\n##\n##\ \ \ -\ <ButtonPress-1>\ \ \ \ on\ canvas\ calls\ proc\ 'doodle_start'\n##\ \ \ -\ <Button1-Motion>\ \ \ on\ canvas\ calls\ proc\ 'doodle_continue'\n##\ \ \ -\ <ButtonRelease-1>\ \ on\ canvas\ calls\ proc\ 'doodle_end'\n##\n##\ \ \ -\ <ButtonRelease-3>\ \ on\ canvas\ calls\ proc\ 'doodle_delete'\n##\n##\ \ \ -\ <Control-ButtonPress-1>\ \ \ \ on\ canvas\ calls\ proc\ 'image_grab'\ (not\ needed?)\n##\ \ \ -\ <Control-Button1-Motion>\ \ \ on\ canvas\ calls\ proc\ 'image_move'\n##+#######################################################################\n\nbind\ .fRfile.entFILENAME\ <ButtonRelease-1>\ \ \{\n\ \ \ #\ image\ delete\ imgID1\ (not\ needed?)\n\ \ \ image\ create\ photo\ imgID1\ -file\ \"\$ENTRYfilename\"\n\ \ \ .fRcanvas.can\ create\ image\ 0\ 0\ -anchor\ nw\ -image\ imgID1\ -tag\ TAGimg\n\}\n\nbind\ .fRfile.entFILENAME\ <Return>\ \ \{\n\ \ \ #\ image\ delete\ imgID1\ (not\ needed?)\n\ \ \ image\ create\ photo\ imgID1\ -file\ \"\$ENTRYfilename\"\n\ \ \ .fRcanvas.can\ create\ image\ 0\ 0\ -anchor\ nw\ -image\ imgID1\ -tag\ TAGimg\n\}\n\nbind\ .fRcanvas.can\ <ButtonPress-1>\ \ \[list\ doodle_start\ %W\ %x\ %y\ \$COLOR1hex\]\n\nbind\ .fRcanvas.can\ <Button1-Motion>\ \{doodle_continue\ %W\ %x\ %y\}\n\nbind\ .fRcanvas.can\ <ButtonRelease-1>\ \{doodle_end\ %W\ %x\ %y\}\n\n##\ FOR\ DELETING\ LINES:\n##\ Suchenwirth\ used\ <Double-3>\ to\ delete\ 'all'\ from\ the\ canvas,\ with:\n##\ \ \ \ \ \ \ bind\ .fRcanvas.can\ <Double-3>\ \{%W\ delete\ all\}\n##\n##\ We\ give\ the\ user\ the\ opportunity\ to\ bail\ out\ of\ the\ delete,\ by\ moving\n##\ the\ mouse\ cursor\ off\ of\ the\ canvas\ before\ releasing\ button3.\n##\ And\ we\ only\ delete\ the\ line\ nearest\ the\ current\ cursor\ location.\n##\ (The\ 'doodle_delete'\ proc\ may\ need\ some\ improvement\ to\ make\ sure\n##\ \ that\ we\ delete\ precisely\ the\ line-segment\ desired.)\n\nbind\ .fRcanvas.can\ <ButtonRelease-3>\ \{doodle_delete\ %W\ %x\ %y\}\n\n\n##\ We\ could\ high-light\ (in\ orange,\ say)\ an\ item,\ to\ help\ the\ user\ when\n##\ they\ want\ to\ delete\ a\ line\ ...\ to\ make\ sure\ they\ delete\ the\ right\ one.\n##\ We\ would\ need\ to\ get\ the\ item's\ current\ color\ and\ restore\ it\ on\n##\ leaving\ the\ item.\n\n#\ .fRcanvas.can\ bind\ TAGlines\ <Button3-Enter>\ \\\n#\ \ \ \"Put\ the\ item's\ current\ color\ in\ \$prevCOLOR,\ then\ do\n#\ \ \ .fRcanvas.can\ itemconfig\ current\ -fill\ #ffaa00\"\n\n#\ .fRcanvas.can\ bind\ TAGlines\ <Button3-Leave>\ \\\n#\ \ \ \ \".fRcanvas.can\ itemconfig\ current\ -fill\ \$prevCOLOR\"\n\n\n##\ Provide\ a\ way\ to\ move\ the\ IMAGE\ on\ the\ canvas.\n\n#\ bind\ .fRcanvas.can\ <ButtonPress-2>\ \ \ \{image_grab\ %W\ %x\ %y\}\ \ \ (not\ needed?)\n\nbind\ .fRcanvas.can\ <Button2-Motion>\ \ \{image_move\ %W\ %x\ %y\}\n\n\n##+#############################################################################\n##+#############################################################################\n##\ DEFINE\ PROCS\ SECTION:\n##\n##\ \ \ \ -\ 'get_img_filename'\ \ \ \ \ \ -\ gets\ the\ filename\ of\ an\ image\ (GIF/PNG)\ file\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ places\ the\ image\ on\ the\ canvas\n##\n##\ \ \ \ -\ 'get_chars_before_last'\ -\ used\ in\ 'get_img_filename'\ to\ set\ curDIR\n##\n##\ \ \ \ -\ 'doodle_start'\ \ \ \ \ \ \ \ \ \ -\ start\ drawing\ a\ freehand\ line\n##\ \ \ \ -\ 'doodle_continue'\ \ \ \ \ \ \ -\ continue\ drawing\ the\ 'current'\ freehand\ line\n##\ \ \ \ -\ 'doodle_end'\ \ \ \ \ \ \ \ \ \ \ \ -\ stop\ drawing\ the\ 'current'\ freehand\ line\n##\ \ \ \ -\ 'doodle_delete'\ \ \ \ \ \ \ \ \ -\ delete\ a\ 'closest'\ line\n##\n##\ \ \ \ -\ 'image_grab'\ \ \ \ \ \ \ \ \ \ \ \ -\ grab\ the\ image\ \ (not\ needed?)\n##\ \ \ \ -\ 'image_move'\ \ \ \ \ \ \ \ \ \ \ \ -\ move\ the\ image\n##\n##\ \ \ \ -\ 'set_line_color1'\ \ \ \ \ \ \ -\ set\ the\ 'fill'\ color\ for\ drawing\ the\ next\ line\n##\ \ \ \ -\ 'set_background_color'\ \ -\ set\ the\ background\ (canvas)\ color\n##\ \ \ \ -\ 'update_colors_label'\ \ \ -\ updates\ the\ colors\ in\ the\ label\ widget\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '.fRbuttons.labelCOLORS'.\n##\ \ \ \ -\ 'remove_all_lines'\ \ \ \ \ \ -\ removes\ all\ lines\ &\ points\ from\ the\ canvas\n##\n##\ \ \ \ -\ 'popup_msg_var'\ \ \ \ \ \ \ \ \ -\ to\ show\ help,\ and\ to\ show\ other\ msgs\ as\ needed\n##+############################################################################\n\n\n##+#########################################################################\n##\ Proc\ 'get_img_filename'\ -\n##\n##\ PURPOSE:\ To\ get\ the\ name\ of\ an\ image\ file\ (GIF/PNG)\ and\ put\ the\n##\ \ \ \ \ \ \ \ \ \ filename\ into\ global\ var\ 'ENTRYfilename'.\n##\ \ \ \ \ \ \ \ \ \ Also,\ go\ ahead\ and\ load\ the\ image\ onto\ the\ canvas.\n##\n##\ USED\ BY:\ the\ '-command'\ option\ of\ the\ 'Browse\ ...'\ button.\n##+#########################################################################\n\n#\ set\ curDIR\ \"\$env(HOME)\"\n\n##\ FOR\ TESTING:\n\ \ set\ curDIR\ \"pwd\"\n\nproc\ get_img_filename\ \{\}\ \{\n\n\ \ \ global\ ENTRYfilename\ env\ curDIR\n\ \ \ #\ global\ imgID1\n\n\ \ \ ##\ Provide\ the\ user\ a\ way\ to\ select\ an\ image\ file.\n\n\ \ \ set\ fName\ \[tk_getOpenFile\ -parent\ .\ -title\ \"Select\ GIF/PNG\ file\ to\ load\"\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ -initialdir\ \"\$curDIR\"\ \]\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ puts\ \"fName\ :\ \$fName\"\n\n\ \ \ ##\ Load\ the\ image\ file\ contents\ onto\ the\ canvas.\n\ \ \ ##\ (Since\ there\ is\ only\ one\ image\ on\ the\ canvas\ at\ any\ time,\ we\ will\n\ \ \ ##\ \ always\ use\ the\ string\ 'imgID1'\ as\ the\ image\ ID\ in\ this\ script.)\n\n\ \ \ if\ \{\[file\ exists\ \$fName\]\}\ \{\n\n\ \ \ \ \ \ set\ ENTRYfilename\ \"\$fName\"\n\ \ \ \ \ \ set\ curDIR\ \[\ get_chars_before_last\ /\ in\ \"\$ENTRYfilename\"\ \]\n\n\ \ \ \ \ \ #\ catch\ \{\ image\ delete\ imgID1\ \}\ (not\ needed?)\n\n\ \ \ \ \ \ image\ create\ photo\ imgID1\ -file\ \"\$ENTRYfilename\"\n\n\ \ \ \ \ \ ##\ Place\ the\ image\ on\ the\ canvas.\n\ \ \ \ \ \ .fRcanvas.can\ create\ image\ 0\ 0\ -anchor\ nw\ -image\ imgID1\ -tag\ TAGimg\n\n\ \ \ \ \ \ ##\ Set\ the\ canvas\ size\ according\ to\ the\ size\ of\ the\ image.\n\ \ \ \ \ \ set\ imgWidthPx\ \ \[image\ width\ \ imgID1\]\n\ \ \ \ \ \ set\ imgHeightPx\ \[image\ height\ imgID1\]\n\ \ \ \ \ \ .fRcanvas.can\ configure\ -width\ \$imgWidthPx\ -height\ \$imgHeightPx\n\n\ \ \ \ \ \ ##\ FOR\ TESTING:\n\ \ \ \ \ \ #\ \ \ puts\ \"get_img_filename\ >\ imgWidthPx:\ \$imgWidthPx\ \ \ imgHeightPx:\ \$imgHeightPx\"\n\n\ \ \ \ \ \ ##\ Force\ the\ resizing\ of\ the\ canvas,\ esp.\ if\ a\ new\ image\ is\n\ \ \ \ \ \ ##\ loaded\ that\ is\ taller\ than\ the\ previous\ image.\n\ \ \ \ \ \ pack\ forget\ .fRcanvas.can\n\ \ \ \ \ \ pack\ .fRcanvas.can\ \\\n\ \ \ \ \ \ \ \ \ -side\ top\ \\\n\ \ \ \ \ \ \ \ \ -anchor\ nw\ \\\n\ \ \ \ \ \ \ \ \ -fill\ both\ \\\n\ \ \ \ \ \ \ \ \ -expand\ 1\n\n\ \ \ \ \ \ ##\ We\ could\ automatically\ raise\ any\ lines\ already\ drawn\n\ \ \ \ \ \ ##\ so\ that\ they\ are\ not\ hidden\ by\ the\ newly\ loaded\ image.\n\n\ \ \ \ \ \ #\ catch\ \{.fRcanvas.can\ raise\ TAGlines\}\n\n\ \ \ \}\n\}\n##\ END\ OF\ proc\ 'get_img_filename'\n\n\n##+######################################################################\n##\ Proc\ 'get_chars_before_last'\ -\n##+######################################################################\n##\ PURPOSE:\ Gets\ the\ chars\ before\ the\ last\ occurrence\ of\ a\ char\ in\ a\ string.\n##\n##\ INPUT:\ \ A\ character\ and\ a\ string.\n##\ \ \ \ \ \ \ \ \ Note:\ The\ \"in\"\ parameter\ is\ there\ only\ for\ clarity.\n##\n##\ OUTPUT:\ Returns\ all\ of\ the\ characters\ in\ the\ string\ \"strng\"\ that\n##\ \ \ \ \ \ \ \ \ are\ BEFORE\ the\ last\ occurence\ of\ the\ characater\ \"char\".\n##\n##\ EXAMPLE\ CALL:\ To\ extract\ the\ directory\ from\ a\ fully\ qualified\ file\ name:\n##\n##\ set\ directory\ \[\ get_chars_before_last\ \"/\"\ in\ \"/home/abc01/junkfile\"\ \]\n##\n##\ \ \ \ \ \ \$directory\ will\ now\ be\ the\ string\ \"/home/abc01\"\n##\n##+######################################################################\n\nproc\ get_chars_before_last\ \{\ char\ in\ strng\ \}\ \{\n\n\ \ \ set\ end\ \[\ expr\ \{\[string\ last\ \$char\ \$strng\ \]\ -\ 1\}\ \]\n\ \ \ #\ set\ start\ 0\n\ \ \ #\ set\ output\ \[\ string\ range\ \$strng\ \$start\ \$end\ \]\n\ \ \ set\ output\ \[\ string\ range\ \$strng\ 0\ \$end\ \]\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ puts\ \"From\ 'get_chars_before_last'\ proc:\"\n\ \ \ #\ puts\ \"STRING:\ \$strng\"\n\ \ \ #\ puts\ \"CHAR:\ \$char\"\n\ \ \ #\ puts\ \"RANGE\ up\ to\ LAST\ CHAR\ -\ start:\ 0\ \ \ end:\ \$end\"\n\n\ \ \ return\ \$output\n\n\}\n##\ END\ OF\ 'get_chars_before_last'\ PROCEDURE\n\n\n##+#########################################################\n##\ proc\ doodle_start\n##+#########################################################\n##\ PURPOSE:\ Start\ a\ line\ using\ the\ 'create\ line'\ command\n##\ \ \ \ \ \ \ \ \ \ on\ the\ canvas.\ Draws\ an\ 'invisible'\ point.\n##\n##\ \ \ \ \ \ \ \ \ \ Also\ increments\ Nobj\ and\ sets\ NcurPoints\ to\ zero\n##\ \ \ \ \ \ \ \ \ \ and\ calls\ proc\ 'update_status_labels'.\n##\n##\ NOTE:\ Provides\ '-fill'\ ,\ '-width'\ ,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '-smooth'\ \ '-splinesteps'\ ,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '-capstyle'\ ,\ '-joinstyle'\ ,\ and\ '-tag'\n##\ \ \ \ \ \ \ option\ to\ 'create\ line'.\n##\n##\ CALLED\ BY:\ bind\ .fRcanvas.can\ <ButtonPress-1>\n##+#########################################################\n##\ We\ store\ the\ line-IDs\ in\ an\ array\ variable,\ aRlineIDs,\n##\ and\ keep\ our\ own\ count\ of\ the\ lines.\ The\ line\ count\n##\ and\ the\ array\ variable\ do\ not\ seem\ to\ be\ necessary\ at\n##\ this\ time,\ but\ they\ may\ be\ useful\ for\ future\ enhancements.\n##+#########################################################\n\nset\ curObjID_CNT\ 1\n\n##\ Initialize\ initX\ and\ initY\ for\ use\ in\ procs\n##\ 'doodle_start'\ and\ 'doodle_end'.\nset\ initX\ -1\nset\ initY\ -1\n\nproc\ doodle_start\ \{w\ x\ y\ color\}\ \{\n\n\ \ \ global\ aRlineIDs\ curObjID_CNT\ COLOR1hex\ lineWIDTHpx\ \\\n\ \ \ \ \ \ \ \ \ smooth0or1\ lineCAPstyle\ lineJOINstyle\ \\\n\ \ \ \ \ \ \ \ \ Nobj\ NcurPoints\ initX\ initY\n\n\ \ \ ##\ Map\ from\ view\ coordinates\ to\ canvas\ coordinates,\ per\n\ \ \ ##\ page\ 559\ of\ 4th\ edition\ of\ 'Practical\ Programming\ in\ Tcl\ &\ Tk'.\n\ \ \ set\ x\ \[\$w\ canvasx\ \$x\]\n\ \ \ set\ y\ \[\$w\ canvasx\ \$y\]\n\n\ \ \ ##\ Initialize\ the\ line\ for\ the\ current\ line-count.\n\ \ \ ##\ (We\ store\ a\ separate\ line-ID\ for\ each\ doodle\n\ \ \ ##\ \ line,\ in\ array\ item\ aRlineIDs(\$curObjID_CNT).\ This\ could\n\ \ \ ##\ \ be\ useful,\ for\ example,\ if\ we\ ever\ want\ to\ click\ a\n\ \ \ ##\ \ button\ on\ the\ GUI\ and\ show\ the\ current\ number\ of\n\ \ \ ##\ \ lines\ in\ the\ sketch.\ We\ would\ to\ keep\ track\ of\n\ \ \ ##\ \ deleted\ lines\ in\ that\ case.\ See\ the\ doodle_delete'\n\ \ \ ##\ \ proc\ below.)\n\ \ \ ##\n\ \ \ ##\ Note:\ The\ start\ and\ end\ point\ of\ the\ line\ is\ the\ same.\n\ \ \ ##\ \ \ \ \ \ \ Under\ certain\ conditions\ (not\ clear\ to\ me\ yet),\n\ \ \ ##\ \ \ \ \ \ \ Tk's\ 'create\ line'\ will\ not\ draw\ a\ point\ on\ the\n\ \ \ ##\ \ \ \ \ \ \ canvas\ unless\ the\ 2nd\ point\ is\ different\ from\n\ \ \ ##\ \ \ \ \ \ \ the\ first\ point.\ So\ this\ initial\ point\ may\ be\n\ \ \ ##\ \ \ \ \ \ \ 'invisible'.\n\ \ \ ##\ \ \ \ \ \ \ See\ the\ 'doodle_end'\ proc.\ There\ we\ could\ make\ the\n\ \ \ ##\ \ \ \ \ \ \ point\ visible,\ if\ only\ the\ initial\ xy\ points\ were\n\ \ \ ##\ \ \ \ \ \ \ in\ this\ 'doodle\ object'.\n\n\ \ \ set\ aRlineIDs(\$curObjID_CNT)\ \[\$w\ create\ line\ \\\n\ \ \ \ \ \ \ \$x\ \$y\ \$x\ \$y\ \\\n\ \ \ \ \ \ \ -fill\ \$COLOR1hex\ -width\ \$lineWIDTHpx\ \\\n\ \ \ \ \ \ \ -smooth\ \$smooth0or1\ \ \\\n\ \ \ \ \ \ \ -capstyle\ \$lineCAPstyle\ -joinstyle\ \$lineJOINstyle\ -tag\ TAGlines\]\n\n\ \ \ ##\ -splinesteps\ 1\n\n\ \ \ set\ initX\ \$x\n\ \ \ set\ initY\ \$y\n\n\ \ \ ##\ capstyles:\ butt,\ projecting,\ round\n\ \ \ ##\ joinstyles:\ bevel,\ miter,\ round\n\ \ \ ##\ Turning\ on\ '-smooth'\ seems\ to\ give\ nicer\ lines.\n\ \ \ ##\ '-splinesteps'\ may\ be\ helpful\ too.\ (best\ value?\ default\ value?\n\ \ \ ##\ hard-code\ it\ OR\ prompt\ for\ it?)\n\n\ \ \ ##\ NOTE1:\ \"If\ the\ smoothing\ method\ is\ 'true'\ (1),\ this\ indicates\ that\ the\n\ \ \ ##\ line\ should\ be\ drawn\ as\ a\ curve,\ rendered\ as\ a\ set\ of\ quadratic\n\ \ \ ##\ splines:\ one\ spline\ is\ drawn\ for\ the\ first\ and\ second\ line\ segments,\n\ \ \ ##\ one\ for\ the\ second\ and\ third,\ and\ so\ on.\"\n\ \ \ ##\ \"If\ a\ boolean\ false\ value\ or\ empty\ string\ is\ given,\ no\ smoothing\ is\n\ \ \ ##\ applied.\"\n\ \ \ ##\ NOTE2:\ \"'-splinesteps'\ specifies\ the\ degree\ of\ smoothness\ desired\n\ \ \ ##\ for\ curves:\ each\ spline\ will\ be\ approximated\ with\ that\ number\ of\n\ \ \ ##\ line\ segments.\"\n\ \ \ ##\ SOURCE\ of\ notes\ 1\ &\ 2:\ Tcl-Tk\ 8.5.5\ documentation.\n\n\ \ \ ##\ Increment\ the\ objects-in-drawing\ count.\n\ \ \ incr\ Nobj\n\n\ \ \ ##\ Reset\ the\ number-of-points-in-current-line\ counter.\n\ \ \ set\ NcurPoints\ 1\n\ \ \ update_status_labels\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ puts\ \"doodle_start\ >\ \ curObjID_CNT:\ \$curObjID_CNT\ \\\n\ \ \ #\ \ \ \ \ \ \ \ \ aRlineIDs(\$curObjID_CNT):\ \$aRlineIDs(\$curObjID_CNT)\"\n\}\n##\ END\ OF\ proc\ doodle_start\n\n\n##+#########################################################\n##\ proc\ doodle_continue\n##+#########################################################\n##\ PURPOSE:\ Adds\ the\ current\ x,y\ point\ to\ the\ currently\n##\ \ \ \ \ \ \ \ \ \ in-process\ line\ ---\ after\ a\ delay\ of\ Nmillisecs.\n##\ \ \ \ \ \ \ \ \ \ Also\ increments\ NcurPoints\ and\ calls\ proc\n##\ \ \ \ \ \ \ \ \ \ 'update_status_labels'.\n##\n##\ CALLED\ BY:\ bind\ .fRcanvas.can\ <Button1-Motion>\n##+#########################################################\n\nproc\ doodle_continue\ \{w\ x\ y\}\ \{\n\n\ \ \ global\ aRlineIDs\ curObjID_CNT\ Nmillisecs\ NcurPoints\n\n\ \ \ ##\ Wait\ Nmillisecs.\ (This\ is\ to\ help\ user\ make\ straight\ lines.\n\ \ \ ##\ It\ can\ reduce\ 'jitter'\ in\ lines,\ by\ reducing\ the\ number\ of\n\ \ \ ##\ 'control\ points'\ in\ the\ line.)\n\ \ \ after\ \$Nmillisecs\n\n\ \ \ ##\ Map\ from\ view\ coordinates\ to\ canvas\ coordinates,\ per\n\ \ \ ##\ page\ 559\ of\ 4th\ edition\ of\ 'Practical\ Programming\ in\ Tcl\ &\ Tk'.\n\ \ \ set\ x\ \[\$w\ canvasx\ \$x\]\n\ \ \ set\ y\ \[\$w\ canvasx\ \$y\]\n\n\ \ \ ##\ Add\ an\ end-point\ to\ the\ line\ for\ the\ current\ line-count.\n\ \ \ ##\ (We\ do\ this\ by\ getting\ the\ xy\ coords\ for\ ALL\ the\ points\ of\n\ \ \ ##\ \ the\ currently-being-drawn-line\ and\ concatenating\ the\n\ \ \ ##\ \ new\ point.\ Then\ use\ 'coords'\ to\ reset\ the\ coordinates.)\n\ \ \ ##\ This\ is\ what\ Suchenwirth\ did\ in\ his\ 'doodle_move'\ proc.\n\n\ \ \ \$w\ coords\ \$aRlineIDs(\$curObjID_CNT)\ \\\n\ \ \ \ \ \ \ \ \ \[concat\ \[\$w\ coords\ \$aRlineIDs(\$curObjID_CNT)\]\ \$x\ \$y\]\n\n\ \ \ ##\ Increment\ the\ number-of-points-in-current-line\ count.\n\ \ \ incr\ NcurPoints\n\ \ \ update_status_labels\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ puts\ \"doodle_continue\ >\ Adding\ point\ \$x\ \$y\"\n\n\}\n##\ END\ OF\ proc\ doodle_continue\n\n\n##+#################################################################\n##\ proc\ doodle_end\n##+#################################################################\n##\ PURPOSE:\ Increments\ var\ curObjID-CN\ that\ we\ are\ using\ to\ hold\n##\ \ \ \ \ \ \ \ \ \ a\ numeric\ ID\ for\ the\ next\ or\ current\ line.\n##\n##\ \ \ \ \ \ \ \ \ \ But\ before\ that\ ID\ is\ incremented,\ we\ test\ to\ see\ if\n##\ \ \ \ \ \ \ \ \ \ we\ are\ ending\ a\ line\ that\ consisted\ of\ just\ one,\n##\ \ \ \ \ \ \ \ \ \ not-drawn\ point.\ It\ that\ is\ the\ case,\ we\ draw\ the\ point.\n##\n##\ CALLED\ BY:\ \ bind\ .fRcanvas.can\ <ButtonRelease-1>\n##+################################################################\n\nproc\ doodle_end\ \{w\ x\ y\}\ \{\n\n\ \ \ global\ curObjID_CNT\ COLOR1hex\ lineWIDTHpx\ \\\n\ \ \ \ \ \ \ \ \ smooth0or1\ lineCAPstyle\ lineJOINstyle\ \\\n\ \ \ \ \ \ \ \ \ Nobj\ NcurPoints\ initX\ initY\n\ \ \ #\ global\ aRlineIDs\n\n\ \ \ ##\ If\ the\ current\ doodle-object\ has\ only\ the\ initial\ xy\n\ \ \ ##\ point\ in\ it\ and\ the\ point\ was\ not\ drawn\ (under\ certain\n\ \ \ ##\ conditions\ not\ yet\ clear\ to\ me),\ then\ we\ could\ test\ for\n\ \ \ ##\ those\ conditions\ and\ draw\ a\ single\ point/blot.\n\n\ \ \ #\ if\ \{\ \$x\ ==\ \$initX\ &&\ \$y\ ==\ \$initY\ &&\ \$NcurPoints\ ==\ 1\ \ &&\ \\\n\ \ \ #\ \ \ \ \ \ ...\ other\ conditions\ go\ here\ ...\ \}\ \{\n\ \ \ #\n\ \ \ #\ \ \ set\ aRlineIDs(\$curObjID_CNT)\ \[\$w\ create\ line\ \\\n\ \ \ #\ \ \ \ \ \ \$x\ \$y\ \[expr\ \{\$x\ +\ 1\}\]\ \$y\ \\\n\ \ \ #\ \ \ \ \ \ -fill\ \$COLOR1hex\ -width\ \$lineWIDTHpx\ \\\n\ \ \ #\ \ \ \ \ \ -smooth\ \$smooth0or1\ \ \ -splinesteps\ 4\ \\\n\ \ \ #\ \ \ \ \ \ -capstyle\ \$lineCAPstyle\ -joinstyle\ \$lineJOINstyle\ -tag\ TAGlines\]\n\ \ \ #\ \}\n\n\ \ \ ##\ Advance\ the\ line\ count\ so\ that\ the\ next\ 'doodle_start'\n\ \ \ ##\ stores\ the\ new\ line-ID\ in\ a\ different\ lineID\ array\ location.\n\ \ \ incr\ curObjID_CNT\n\n\ \ \ set\ initX\ -1\n\ \ \ set\ initY\ -1\n\n\}\n##\ END\ OF\ proc\ doodle_end\n\n\n##+##################################################################\n##\ proc\ doodle_delete\n##+##################################################################\n##\ PURPOSE:\ Deletes\ a\ line\ object\ nearest\ the\ current\ cursor\ position,\n##\ \ \ \ \ \ \ \ \ \ and\ decrements\ Nobj\ and\ sets\ NcurPoints\ to\ 0\ and\n##\ \ \ \ \ \ \ \ \ \ calls\ proc\ 'update_status_labels'.\n##\n##\ CALLED\ BY:\ \ bind\ .fRcanvas.can\ <ButtonRelease-3>\n##+##################################################################\n##\ NOTE:\n##\ We\ need\ a\ good\ delete-segment\ capability,\ because\n##\ it\ is\ hard\ to\ sketch\ the\ line\ segments\n##\ exactly\ where\ we\ want\ them\ with\ the\ mouse\n##\ ---\ for\ every\ segment,\ the\ first\ time,\ every\ time.\n##+#########################################################\n\nset\ pixelTol\ 3\n\nproc\ doodle_delete\ \{w\ x\ y\}\ \{\n\n\ \ \ global\ pixelTol\ Nobj\ NcurPoints\n\n\ \ \ ##\ See\ note\ below\ on\ aRlineIDs\ and\ '-1'.\n\ \ \ #\ global\ aRlineIDs\n\n\ \ \ ##\ Map\ from\ view\ coordinates\ to\ canvas\ coordinates,\ per\n\ \ \ ##\ page\ 559\ of\ 4th\ edition\ of\ 'Practical\ Programming\ in\ Tcl\ &\ Tk'.\n\ \ \ set\ x\ \[\$w\ canvasx\ \$x\]\n\ \ \ set\ y\ \[\$w\ canvasx\ \$y\]\n\n\ \ \ ##\ Find\ canvas\ object\ nearest\ \$x\ \$y.\ This\ returns\ the\ 'last\ one'\n\ \ \ ##\ (uppermost)\ in\ the\ display\ list.\n\n\ \ \ set\ objID\ \[\$w\ find\ closest\ \$x\ \$y\ \$pixelTol\]\n\n\ \ \ ##\ We\ could\ popup\ a\ prompt\ to\ the\ user\ here\ indicating\ the\n\ \ \ ##\ item\ that\ will\ be\ deleted\ and\ ask\ the\ user\ if\ it\ is\ OK\n\ \ \ ##\ to\ do\ the\ delete.\n\n\ \ \ set\ objTAGs\ \[\$w\ gettags\ \$objID\]\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"'doodle_delete'\ >\ \ objID:\ \$objID\ \ \ objTAGs:\ \$objTAGs\"\n\n\ \ \ ##\ If\ objTAGs\ typically\ contains\ 'TAGlines\ current'\ when\ a\ line\ is\n\ \ \ ##\ detected\ by\ 'closest',\ and\ 'TAGimg\ current'\ when\ the\ image\ is\ detected.\n\n\ \ \ ##\ We\ make\ sure\ we\ delete\ a\ line\ and\ NOT\ an\ image\ on\ the\ canvas.\n\ \ \ if\ \{\ \$objTAGs\ ==\ \"TAGlines\ current\"\ ||\ \$objTAGs\ ==\ \"TAGlines\"\ \}\ \{\n\ \ \ \ \ \ \$w\ delete\ \$objID\n\n\ \ \ \ \ \ ##\ Decrement\ the\ number-of-objects-in-drawing\ count.\n\ \ \ \ \ \ incr\ Nobj\ -1\n\n\ \ \ \ \ \ ##\ Reset\ the\ number-of-points-in-current-line\ count.\n\ \ \ \ \ \ set\ NcurPoints\ 0\n\n\ \ \ \ \ \ update_status_labels\n\ \ \ \}\n\n\ \ \ ##\ We\ could\ find\ the\ objectID\ in\ the\ array\ aRlineIDs\n\ \ \ ##\ and,\ for\ that\ array\ index,\ reset\ the\ array\ to\ a\ value,\n\ \ \ ##\ like\ DEL\ or\ -1,\ that\ indicates\ the\ line\ (object)\ is\ deleted.\n\n\ \ \ #\ Search\ the\ array\ to\ find\ the\ index,\ idx,\ of\ the\ deleted\ object.\n\ \ \ #\ set\ aRlineIDs(\$idx)\ \"-1\"\n\n\}\n##\ END\ OF\ proc\ doodle_delete\n\n\n##+#########################################################\n##\ proc\ image_move\n##+#########################################################\n##\ PURPOSE:\ Moves\ the\ image\ on\ the\ canvas.\n##\n##\ CALLED\ BY:\ bind\ .fRcanvas.can\ <Button2-Motion>\n##+#########################################################\n\nproc\ image_move\ \{w\ x\ y\}\ \{\n\n\ \ \ ##\ Map\ from\ view\ coordinates\ to\ canvas\ coordinates,\ per\n\ \ \ ##\ page\ 559\ of\ 4th\ edition\ of\ 'Practical\ Programming\ in\ Tcl\ &\ Tk'.\n\ \ \ set\ x\ \[\$w\ canvasx\ \$x\]\n\ \ \ set\ y\ \[\$w\ canvasx\ \$y\]\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ set\ tempCoords\ \[\$w\ coords\ TAGimg\]\n\ \ \ #\ \ \ puts\ \"'image_move'\ >\ Current\ image\ coords:\ \$tempCoords\"\n\n\ \ \ ##\ Reset\ the\ location\ of\ the\ image\ on\ the\ canvas.\n\n\ \ \ \$w\ coords\ TAGimg\ \$x\ \$y\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"'image_move'\ >\ Moving\ image\ to\ \$x\ \$y\"\n\n\}\n##\ END\ OF\ proc\ image_move\n\n\n\n##+#####################################################################\n##\ proc\ 'set_line_color1'\n##+#####################################################################\ \n##\ PURPOSE:\ \ This\ procedure\ is\ invoked\ to\ get\ an\ RGB\ triplet\n##\ \ \ \ \ \ \ \ \ \ \ via\ 3\ RGB\ slider\ bars\ on\ the\ FE\ Color\ Selector\ GUI.\n##\n##\ \ \ \ \ \ \ \ \ \ \ Uses\ that\ RGB\ value\ to\ set\ a\ 'fill'\ color.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ \ .fRbuttons.buttCOLOR1\ \ button\n##+#####################################################################\n\nproc\ set_line_color1\ \{\}\ \{\n\n\ \ \ global\ COLOR1r\ COLOR1g\ COLOR1b\ COLOR1hex\ COLOR1r\ COLOR1g\ COLOR1b\n\ \ \ #\ global\ feDIR_tkguis\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"COLOR1r:\ \$COLOR1r\"\n\ \ \ #\ \ \ \ puts\ \"COLOR1g:\ \$COLOR1g\"\n\ \ \ #\ \ \ \ puts\ \"COLOR1b:\ \$COLOR1b\"\n\n\ \ \ set\ TEMPrgb\ \[\ exec\ \\\n\ \ \ \ \ \ \ ./sho_colorvals_via_sliders3rgb.tk\ \\\n\ \ \ \ \ \ \ \$COLOR1r\ \$COLOR1g\ \$COLOR1b\]\n\n\ \ \ #\ \ \ \$feDIR_tkguis/sho_colorvals_via_sliders3rgb.tk\ \\\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"TEMPrgb:\ \$TEMPrgb\"\n\n\ \ \ if\ \{\ \"\$TEMPrgb\"\ ==\ \"\"\ \}\ \{\ return\ \}\n\ \n\ \ \ scan\ \$TEMPrgb\ \"%s\ %s\ %s\ %s\"\ r255\ g255\ b255\ hexRGB\n\n\ \ \ set\ COLOR1hex\ \"#\$hexRGB\"\n\ \ \ set\ COLOR1r\ \$r255\n\ \ \ set\ COLOR1g\ \$g255\n\ \ \ set\ COLOR1b\ \$b255\n\n\ \ \ ##\ Update\ the\ colors-label.\n\n\ \ \ update_colors_label\n\n\}\n##\ END\ OF\ proc\ 'set_line_color1'\n\n\n##+#####################################################################\n##\ proc\ 'set_background_color'\n##+#####################################################################\ \n##\ PURPOSE:\ This\ procedure\ is\ invoked\ to\ get\ an\ RGB\ triplet\n##\ \ \ \ \ \ \ \ \ \ via\ 3\ RGB\ slider\ bars\ on\ the\ FE\ Color\ Selector\ GUI.\n##\n##\ \ \ \ \ \ \ \ \ \ Uses\ that\ RGB\ value\ to\ set\ the\ color\ of\ the\ canvas\ ---\n##\ \ \ \ \ \ \ \ \ \ on\ which\ all\ the\ tagged\ items\ (lines)\ lie.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ .fRbuttons.buttCOLORbkGND\ \ button\n##+#####################################################################\n\nproc\ set_background_color\ \{\}\ \{\n\n\ \ \ global\ COLORbkGNDr\ COLORbkGNDg\ COLORbkGNDb\ COLORbkGNDhex\ \\\n\ \ \ \ \ \ \ \ \ \ COLORbkGNDr\ COLORbkGNDg\ COLORbkGNDb\n\ \ \ #\ global\ feDIR_tkguis\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"COLORbkGNDr:\ \$COLORbkGNDr\"\n\ \ \ #\ \ \ \ puts\ \"COLORbkGNDg:\ \$COLORbkGNDb\"\n\ \ \ #\ \ \ \ puts\ \"COLORbkGNDb:\ \$COLORbkGNDb\"\n\n\ \ \ set\ TEMPrgb\ \[\ exec\ \\\n\ \ \ \ \ \ \ ./sho_colorvals_via_sliders3rgb.tk\ \\\n\ \ \ \ \ \ \ \$COLORbkGNDr\ \$COLORbkGNDg\ \$COLORbkGNDb\]\n\n\ \ \ #\ \ \ \$feDIR_tkguis/sho_colorvals_via_sliders3rgb.tk\ \\\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"TEMPrgb:\ \$TEMPrgb\"\n\n\ \ \ if\ \{\ \"\$TEMPrgb\"\ ==\ \"\"\ \}\ \{\ return\ \}\n\ \n\ \ \ scan\ \$TEMPrgb\ \"%s\ %s\ %s\ %s\"\ r255\ g255\ b255\ hexRGB\n\n\ \ \ set\ COLORbkGNDhex\ \"#\$hexRGB\"\n\ \ \ set\ COLORbkGNDr\ \$r255\n\ \ \ set\ COLORbkGNDg\ \$g255\n\ \ \ set\ COLORbkGNDb\ \$b255\n\n\ \ \ ##\ Set\ the\ color\ of\ the\ canvas.\n\n\ \ \ .fRcanvas.can\ config\ -bg\ \$COLORbkGNDhex\n\n\ \ \ ##\ Update\ the\ colors-label.\n\n\ \ \ update_colors_label\n\n\}\n##\ END\ OF\ proc\ 'set_background_color'\n\n\n##+#####################################################################\n##\ proc\ update_colors_label\n##+#####################################################################\ \n##\ PURPOSE:\ \ Updates\ the\ colors\ in\ the\ label\ widget\n##\ \ \ \ \ \ \ \ \ \ \ '.fRbuttons.labelCOLORS'.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ two\ color-setting\ procs\ and\ the\ GUI\ init\ section\ at\n##\ \ \ \ \ \ \ \ \ \ \ \ the\ bottom\ of\ this\ script.\n##+#####################################################################\n\nproc\ update_colors_label\ \{\}\ \{\n\n\ \ \ global\ COLOR1hex\ COLORbkGNDhex\n\n\ \ \ .fRbuttons.labelCOLORS\ configure\ -text\ \"\\\nColor\ for\ the\ next\ line:\ \ \$COLOR1hex\ \n\ Background\ Color:\ \ \$COLORbkGNDhex\"\n\n\}\n##\ END\ OF\ proc\ 'update_colors_label'\n\n\n##+#####################################################################\n##\ proc\ update_status_labels\n##+#####################################################################\ \n##\ PURPOSE:\ \ Updates\ the\ counts\ in\ the\ label\ widgets\n##\ \ \ \ \ \ \ \ \ \ \ '.fRstatus.labelCOUNTobj'\ and\ '.fRstatus.labelCOUNTpoints'.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ 'doodle_end',\ 'doodle_delete'\ procs\ and\ the\n##\ \ \ \ \ \ \ \ \ \ \ \ GUI\ init\ section\ at\ the\ bottom\ of\ this\ script.\n##+#####################################################################\n\nproc\ update_status_labels\ \{\}\ \{\n\n\ \ \ global\ Nobj\ NcurPoints\n\n\ \ \ .fRstatus.labelCOUNTobj\ configure\ -text\ \"\$Nobj\"\n\ \ \ .fRstatus.labelCOUNTpoints\ configure\ -text\ \"\$NcurPoints\"\n\n\}\n##\ END\ OF\ proc\ 'update_status_labels'\n\n\n##+#####################################################################\n##\ proc\ remove_all_lines\n##+#####################################################################\ \n##\ PURPOSE:\ \ Removes\ all\ objects\ (lines,\ 'degenerate\ lines'=points)\n##\ \ \ \ \ \ \ \ \ \ \ from\ the\ canvas\ and\ resets\ some\ counts\ accordingly.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ 'doodle_end',\ 'doodle_delete'\ procs\ and\ the\n##\ \ \ \ \ \ \ \ \ \ \ \ GUI\ init\ section\ at\ the\ bottom\ of\ this\ script.\n##+#####################################################################\n\nproc\ remove_all_lines\ \{\}\ \{\n\n\ \ \ global\ Nobj\ NcurPoints\n\n\ \ \ .fRcanvas.can\ delete\ TAGlines\n\n\ \ \ set\ Nobj\ 0\n\ \ \ set\ NcurPoints\ 0\n\ \ \ update_status_labels\n\n\}\n##\ END\ OF\ proc\ 'remove_all_lines'\n\n\n##+########################################################################\n##\ \ 'popup_msg_var'\ PROCEDURE\ \n##+########################################################################\n##\ PURPOSE:\ Show\ help\ to\ the\ user.\n##\ \ \ \ \ \ \ \ \ (Could\ also\ be\ used\ to\ advise\ user\ of\ error\ conditions.)\n##\n##\ CALLED\ BY:\ '-command'\ option\ of\ the\ Help\ button\n##+########################################################################\n##\ To\ have\ more\ control\ over\ the\ formatting\ of\ the\ message\ (esp.\n##\ max\ length\ of\ lines),\ we\ use\ this\ 'toplevel-text'\ method,\ \n##\ rather\ than\ the\ 'tk_dialog'\ method\ --\ like\ on\ page\ 574\ of\ the\ book\ \n##\ by\ Hattie\ Schroeder\ &\ Mike\ Doyel,'Interactive\ Web\ Applications\n##\ with\ Tcl/Tk',\ Appendix\ A\ \"ED,\ the\ Tcl\ Code\ Editor\".\n##+########################################################################\n\nproc\ popup_msg_var\ \{\ VARtext\ \}\ \{\n\n\ \ \ ##\ global\ env\n\n\ \ \ #\ bell\n\ \ \ #\ bell\n\ \ \n\ \ \ #####################################\n\ \ \ ##\ SETUP\ 'TOP\ LEVEL'\ HELP\ WINDOW.\n\ \ \ #####################################\n\ \ \n\ \ \ set\ w\ .topmsg\n\n\ \ \ catch\ \{destroy\ \$w\}\n\ \ \ toplevel\ \ \$w\n\n\ \ \ wm\ geometry\ \$w\ +100+100\n\n\ \ \ wm\ title\ \ \ \ \ \$w\ \"To\ You\"\n\ \ \ wm\ iconname\ \ \$w\ \"ToYou\"\n\n\ \ \ #####################################\n\ \ \ ##\ DEFINE\ &\ PACK\ TEXT\ WIDGET.\n\ \ \ #####################################\n\n\ \ \ text\ \$w.text\ \\\n\ \ \ \ \ \ -relief\ raised\ \\\n\ \ \ \ \ \ -bd\ 2\ \\\n\ \ \ \ \ \ -font\ fontTEMP_fixedwidth\n\n\ \ \ pack\ \ \$w.text\ \\\n\ \ \ \ \ \ -side\ top\ \\\n\ \ \ \ \ \ -anchor\ center\ \\\n\ \ \ \ \ \ -fill\ both\ \\\n\ \ \ \ \ \ -expand\ 0\n\n\ \ \ #####################################\n\ \ \ ##\ DEFINE\ &\ PACK\ OK\ BUTTON\ WIDGET.\n\ \ \ #####################################\n\n\ \ \ button\ \$w.butt\ -text\ \"OK\"\ \\\n\ \ \ \ \ \ -font\ fontTEMP_fixedwidth\ -command\ \ \"destroy\ \$w\"\n\n\ \ \ pack\ \ \$w.butt\ \\\n\ \ \ \ \ \ -side\ bottom\ \\\n\ \ \ \ \ \ -anchor\ center\ \\\n\ \ \ \ \ \ -fill\ none\ \\\n\ \ \ \ \ \ -expand\ 0\n\n\ \ \ #####################################\n\ \ \ ##\ LOAD\ MSG\ INTO\ TEXT\ WIDGET.\n\ \ \ #####################################\n\n\ \ \ ##\ \ \$w.text\ delete\ 1.0\ end\n\ \n\ \ \ \$w.text\ insert\ end\ \$VARtext\n\ \ \ \n\ \ \ \$w.text\ \ configure\ -state\ disabled\n\n\ \ \ #################################################\n\ \ \ ##\ Set\ VARwidth\ &\ VARheight\ from\ \$VARtext.\n\ \ \ ##\n\ \ \ #################################################\n\ \ \ ##\ To\ get\ VARheight,\n\ \ \ ##\ \ \ \ split\ at\ '\\n'\ (newlines)\ and\ count\ 'lines'.\n\ \ \ #################################################\n\ \n\ \ \ set\ VARlist\ \[\ split\ \$VARtext\ \"\\n\"\ \]\n\n\ \ \ ##\ For\ testing:\n\ \ \ #\ \ puts\ \"VARlist:\ \$VARlist\"\n\n\ \ \ set\ VARheight\ \[\ llength\ \$VARlist\ \]\n\n\ \ \ ##\ For\ testing:\n\ \ \ #\ \ puts\ \"VARheight:\ \$VARheight\"\n\n\ \ \ \$w.text\ configure\ -height\ \$VARheight\n\n\ \ \ #################################################\n\ \ \ ##\ To\ get\ VARwidth,\n\ \ \ ##\ \ \ \ loop\ through\ the\ 'lines'\ getting\ length\n\ \ \ ##\ \ \ \ \ of\ each\;\ save\ max.\n\ \ \ #################################################\n\n\ \ \ set\ maxLINEwidth\ 0\n\n\ \ \ #############################################\n\ \ \ ##\ LOOK\ AT\ EACH\ LINE\ IN\ THE\ LIST.\n\ \ \ #############################################\n\ \ \ foreach\ line\ \$VARlist\ \{\n\n\ \ \ \ \ \ #############################################\n\ \ \ \ \ \ ##\ Get\ the\ length\ of\ the\ line.\n\ \ \ \ \ \ #############################################\n\ \ \ \ \ \ set\ LINEwidth\ \[\ string\ length\ \$line\ \]\n\n\n\ \ \ \ \ \ if\ \{\ \$LINEwidth\ >\ \$maxLINEwidth\ \}\ \{\n\ \ \ \ \ \ \ \ \ set\ maxLINEwidth\ \$LINEwidth\ \n\ \ \ \ \ \ \}\n\n\ \ \ \}\n\ \ \ ##\ END\ OF\ foreach\ line\ \$VARlist\n\n\ \ \ \$w.text\ configure\ -width\ \ \$maxLINEwidth\n\n\ \ \ ##\ For\ testing:\n\ \ \ #\ \ \ puts\ \"maxLINEwidth:\ \$maxLINEwidth\"\n\n\ \ \ ########################################################################\n\ \ \ ##\ NOTE:\ maxLINEwidth\ should\ work\ well\ when\ a\ fixed-width\ font\ used\n\ \ \ ##\ \ \ \ \ \ \ for\ the\ text\ widget\ ...\ BUT\ the\ programmer\ may\ need\ to\ be\n\ \ \ ##\ \ \ \ \ \ \ careful\ that\ the\ contents\ of\ VARtext\ are\ all\ countable\n\ \ \ ##\ \ \ \ \ \ \ characters\ according\ to\ the\ 'string\ length'\ command.\n\ \ \ ########################################################################\n\ \ \n\}\n##\ END\ OF\ 'popup_msg_var'\ PROCEDURE\n\n\n##+########################\n##\ END\ of\ PROC\ definitions.\n##+########################\n\nset\ HELPtext\ \"\\\n\\\ \\\ \\\ \\\ \\\ **HELP\ for\ the\ 'Sketch\ Lines\ on\ an\ Image'\ utility\ **\n\n\ To\ DRAW:\n\ Press\ MB1\ (mouse\ button\ 1)\ to\ start\ a\ line\ where\ the\ arrow-cursor\n\ is\ currently\ located\ on\ the\ canvas.\ Continue\ to\ hold\ MB1\ down\ and\n\ move\ the\ mouse\ to\ draw\ the\ current\ line\ segment\ on\ the\ canvas.\n\ Release\ MB1\ to\ terminate\ drawing\ that\ line\ segment.\n\n\ To\ DELETE\ a\ line\ segment,\ press-and-release\ MB3\ (mouse\ button\ 3)\n\ on\ the\ line\ segment\ (or\ 'degenerate\ line'\ =\ point)\ to\ be\ deleted.\n\n\ Click\ the\ 'RemoveImage'\ button\ to\ see\ how\ your\ drawing\ is\n\ progressing.\ Then\ ...\n\n\ Click\ and\ release\ MB1\ on\ the\ filename\ in\ the\ entry\ field,\ to\n\ RELOAD\ the\ image\ from\ the\ image\ file\ to\ the\ canvas.\ If\ the\n\ reload\ covers\ up\ your\ lines,\ click\ on\ the\ 'RaiseLines'\ button\n\ to\ reveal\ the\ lines\ again.\n\n\ Use\ MB2\ to\ move\ (drag)\ the\ image\ to\ a\ new\ location.\ This\ can\n\ be\ useful\ to\ use\ additional\ images\ to\ help\ sketch\ the\ picture.\n\ Or\ it\ can\ be\ used\ to\ offset\ the\ current\ image\ and\ use\ it\ for\n\ addtional\ sketching.\n\n\ You\ can\ reduce\ the\ number\ of\ points\ being\ captured\ to\ make\ the\n\ curved/polygonal\ line\ by\ increasing\ the\ 'millisecs'\ parameter.\n\n\ Click\ on\ the\ sliderbar\ trough\ for\ fine-grained\ control.\n\n\ You\ can\ use\ a\ screen/image\ capture\ utility\ to\ capture\ your\n\ drawing\ ---\ with\ or\ without\ an\ underlying\ image\ in\ place.\"\n\n\n##+######################################################\n##+######################################################\n##\ Additional\ GUI\ INITIALIZATION:\n##+######################################################\n\n##\ Initialize\ some\ count\ variables\ and\ some\n##\ scale/checkbutton/radiobutton\ widget\ variables\n##\ that\ are\ shown\ on\ the\ GUI\ or\ set\ via\ the\ GUI.\n\nset\ ENTRYfilename\ \"\"\nset\ Nobj\ 0\nset\ NcurPoints\ 0\n#\ set\ lineWIDTHpx\ 2\nset\ lineWIDTHpx\ 15\nset\ Nmillisecs\ 50\nset\ smooth0or1\ 1\nset\ lineCAPstyle\ \"round\"\nset\ lineJOINstyle\ \"round\"\n\n.fRcanvas.can\ configure\ -bg\ \$COLORbkGNDhex\n\nupdate_colors_label\n\nupdate_status_labels\n\n\n\n======\n\nHere\ is\ an\ image\ that\ shows\ that\ you\ do\ not\ have\ to\ use\ an\ image\nto\ do\ your\ sketching.\ You\ can\ simply\ sketch\ on\ the\ canvas\ without\nusing\ the\ 'Browse...'\ button\ to\ locate\ an\ image\ file.\n\n\[sketchOnimgGUI_gimmeSomeTruth_screenshot_501x350.jpg\]\n\nIn\ this\ case,\ I\ used\ the\ 'Background\ color'\ button\ to\ set\ the\ canvas\nbackground\ to\ blue.\ And\ I\ used\ the\ 'Next\ line\ color'\ button\ to,\ at\nvarious\ times,\ set\ the\ line-color\ to\ white,\ black,\ and\ yellow.\n\nI\ also\ used\ the\ 'Width\ of\ next\ line'\ scale\ to\ set\ several\ different\nline\ widths.\n\n____\n\nIn\ summary,\ I\ think\ Tcler's\ (or\ their\ kids)\ can\ have\ some\ fun\ntimes\ with\ this\ 'Sketch\ On'\ utility.\ And\ those\ with\ good\ artistic\ncapabilities\ and/or\ lots\ of\ patience\ can\ generate\ some\ stunning\nimages.\n\n\n======\n\n\[uniquename\]\ 2012oct21\ UPDATE:\n\nTo\ give\ potential\ users\ of\ this\ 'Sketch\ On'\ utility\ some\ ideas\ on\ how\nit\ could\ be\ used\ (the\ range\ of\ its\ capabilities),\ I\ decided\ to\ post\nsome\ images\ here\ that\ might\ trigger\ some\ ideas\ on\ how\ to\ make\ use\ of\n'SketchOn'.\n\nI\ thought\ some\ images\ of\ Roy\ Lichtenstein\ artwork\ (the\ use\ of\ dots\nto\ creat\ shading\ in\ drawings)\ would\ be\ a\ good\ example\ ---\ like\ the\nfollowing\ images.\n\n\[dotsPicture_royLichtenstein_GirlsEyeWithTear_parallel-straightLines_245x350.jpg\]\n\[dotsPicture_royLichtenstein_still-life_dots-straightLine-solidColors_308x340.jpg\]\n\[dotsPicture_blueDotsONwhite_suggestsMountains_100x100.jpg\]\n\nBut\ I\ realized\ that\ the\ first\ 2\ of\ these\ images\ involved\ drawing\ very\ straight\nlines,\ and\ the\ code\ for\ 'SketchOn',\ as\ I\ first\ released\ it,\ was\ not\ well\ suited\nfor\ drawing\ precisely\ straight\ lines.\n\nI\ realized\ that\ I\ could\ add\ a\ 'milliseconds\ delay'\ scale\ to\ the\ GUI\ ---\ to\ spread\nout\ the\ sampling\ of\ points\ that\ make\ up\ the\ curves\ or\ polygons\ being\ drawn.\n\nSo\ I\ have\ enhanced\ the\ GUI,\ and\ replaced\ the\ previous\ code\ with\ new\ code\ above.\n\nAs\ it\ stood,\ the\ would\ handle\ creating\ 'pointillism'\ images\ liek\ the\ following\nclassic\ paintings\ ---\ or\ emulations\ of\ them.\ (The\ first\ image\ is\ someone's\n'dot'\ painting\ emulation\ of\ Van\ Gogh's\ 'Starry\ Night'\ painting,\ which\ was\ originally\nrendered\ in\ short\ 'dashes'\ of\ paint.)\n\n\[pointillism_versionOf_starryNight_by_mysticspirits_deviantart_colorDots_705x599.jpg\]\n\[pointillism_sailboat_signac_shortColorStrokesANDdots_431x358.gif\]\n\[pointillism_vincentVanGogh_selfPortraitWithFeltHat_shortColoredStrokes_330x400.jpg\]\n\nHere\ is\ an\ image\ of\ the\ new\ 'SketchOn'\ GUI,\ with\ an\ image\ that\ I\ spend\ about\ 10\nminutes\ sketching\ out,\ based\ on\ the\ Van\ Gogh\ self-portrait\ above.\ This\ is\ just\nto\ give\ an\ example\ of\ how\ one\ could\ attempt\ a\ 'pointillism'\ type\ sketch.\n\n\[sketchONimgGUI_vanGoghPortrait_crude_881x515.jpg\]\n\nBesides\ color\ drawings,\ one\ could\ simply\ use\ black\ and\ white\ dots\ to\ make\ drawings\n---\ like\ the\ following\ ---\ which\ was\ not\ done\ with\ 'SketchOn'\ ---\ but\ with\ a\ lot\nof\ patience\ and\ some\ artistic\ talent,\ a\ person\ could\ create\ drawings\ like\ this,\nwith\ 'SketchOn'.\n\n\[bw-pointillism_womanFace_PUREblackONwhite_dots_600x770.jpg\]\n\nYou\ can\ make\ dots\ ('degenerate\ lines'\ =\ points)\ with\ 'SketchOn'\ by\ simply\nreleasing\ mouse-button-1\ (MB1)\ immediately\ after\ clicking\ down\ with\ MB1.\n\nIn\ fact,\ by\ using\ lots\ of\ closely\ packed\ dots,\ one\ can\ get\ drawings\ that\ look\nlike\ they\ include\ a\ gray-scale.\ Here\ is\ an\ example.\ It\ looks\ like\ the\ dots\nacross\ the\ nose\ of\ this\ cub\ are\ on\ a\ gray\ background.\n\n\[bw-pointillism_lionCub_PUREblackONwhite_pointsANDlines_600x647.jpg\]\n\nHowever,\ on\ taking\ this\ image\ into\ the\ 'mtpaint'\ image\ editor\ on\ Linux,\nand\ going\ into\ 800%\ zoom\ mode,\ you\ can\ see\ that\ the\ dots\ across\ the\ nose\nare\ pure\ black\ and\ white\ ---\ no\ gray.\n\n\[bw-pointillism_lionCub_PUREblackONwhite_mtpaint800pcntView_781x502.jpg\]\n\nSimilarly,\ newspapers\ use\ 'half-tone'\ procedure\ to\ get\ shaded\ images\ of\nphotos,\ like\ the\ following\ image.\n\n\[halftone_face_161x182.gif\]\n\nIf\ you\ scale\ up\ this\ image\ about\ 4\ times,\ you\ will\ see\ that\ the\ image\ is\ made\nup\ of\ pure\ black\ 'objects'\ ---\ some\ that\ are\ L-shapes\ and\ staircase-shapes\ ---\non\ a\ pure\ white\ background.\n\n\[halftone_face_scaledUp4times_644x728.gif\]\n\nThere\ is\ no\ zoom\ option\ in\ 'SketchOn'\ by\ which\ you\ could\ create\ such\nmicro-detailed\ shapes\ ---\ but\ you\ can\ see\ that\ by\ using\ a\ variety\ of\n'line\ widths',\ you\ can\ make\ points/dots\ of\ various\ sizes\ and\ thus\ get\na\ halftone-like\ drawing\ from\ 'SketchOn'.\n\nIn\ fact,\ you\ could\ use\ COLORED\ dots,\ in\ a\ variety\ of\ sizes,\ to\ get\ images\nlike\ the\ following.\n\n\[dotPicture_butterfly_blueANDpurpleDisks_359x255.jpg\]\n\nFuthermore,\ you\ could\ use\ various\ dashed-line\ and\ hatched-line\ techniques\ ---\nlike\ techniques\ that\ engravers\ use\ ---\ to\ get\ shaded\ image\ drawings\ ---\ such\ as\nthe\ following.\n\n\[engraving_abrahamLincoln_face_dashed-parallel-linesANDhatching_see-eyes-lips-beard_blackONwhite_329x348.jpg\]\n\nIn\ the\ Abraham\ Lincoln\ image\ above,\ take\ note\ of\ the\ techniques\ used\ to\ render\nthe\ eyes,\ lips,\ and\ beard\ ---\ dashed-parallel-lines,\ with\ various\ lengths\ and\nspacings\ in\ the\ dashes.\ And\ hatching\ used\ to\ render\ heavily\ shadowed\ areas.\n\n\[engraving_alexanderHamilton_face_near-parallel-lines-on-face_see-hilite_352x406.jpg\]\n\nThe\ Alexander\ Hamilton\ image\ above\ suggests\ that\ one\ could\ start\ with\ a\ gray\ background\ninstead\ of\ white\ ---\ and\ achieve\ high-lights,\ like\ the\ one\ on\ his\ forehead,\ by\nputting\ a\ blob\ of\ white\ in\ those\ spots.\n\n\[engraving_georgeWashington_face_parallel-linesANDhatching_see-hair-lips_blackONwhite_447x416.jpg\]\n\nThe\ George\ Washington\ image\ above\ gives\ some\ more\ ideas\ on\ how\ to\ render\ hair\ and\ lips.\n\n\[engraving_groverCleveland_faceInOval_lotsOfHatching_see-moustache-hair-coat_blackONwhite_436x490.jpg\]\n\nThe\ Grover\ Cleveland\ image\ above\ is\ a\ good\ example\ of\ rendefing\ moustache,\ hair,\ and\ coat.\n\n\[engraving_johnKennedy_portrait_near-parallel-lines-on-faceANDdot-gridsANDhilites_blackONwhite_561x700.jpg\]\n\nThe\ John\ Kennedy\ image\ above\ shows\ that\ one\ can\ get\ shading\ across\ a\ face\ by\nusing\ parallel\ lines\ of\ various\ widths\ (no\ dashes\ involved).\ And\ dot\ and\ grid\npatterns\ can\ be\ used\ effectively\ in\ some\ places.\ Note\ that\ applying/leaving\ white\nin\ areas\ like\ the\ forehead,\ over\ the\ eyebrows,\ under\ the\ eyes,\ on\ the\ bridge\ of\ the\ nose,\nbetween\ nose\ and\ upper\ lip,\ and\ between\ lower\ lip\ and\ chin\ ---\ one\ can\ get\ very\neffective\ sense\ of\ facial-shape\ along\ with\ lighting\ effects.\n\n\[engraving_ulyssesGrant_face_parallel-linesANDhatching_hairsANDwart_blackONwhite_420x333.jpg\]\n\nThe\ Ulysses\ Grant\ image\ above\ shows\ another\ example\ of\ how\ one\ might\ be\nable\ to\ get\ the\ hair\ effect\ ---\ with\ very\ thin\ white\ and\ black\ lines\ ---\neither\ white\ on\ black\ or\ black\ applied\ to\ white.\ And\ this\ image\ shows\nhow\ you\ could\ render\ a\ wart.\ No\ doubt\ 'SketchOn'\ could\ do\ warts\ and\ all.\n\n\nThe\ following\ image\ suggests\ that\ you\ could\ draw\ ovals\ or\ circles\ on\ntop\ of\ a\ photograph\ and\ leave\ the\ photograph\ in\ place\ ---\ to\ get\na\ quite\ interesting\ effect.\n\n\[photo-pointillism_facePhoto_ovalsSuperimposedOnFace_353x476.jpg\]\n\nOf\ course,\ there\ are\ definite\ limits\ to\ what\ can\ be\ done\ with\ 'SketchOn'.\nIt\ is\ not\ suited\ for\ making\ CAD-like\ drawings\ like\ the\ following.\n\n\[escherStaircase_blueANDyellow_600x450.jpg\]\n\nOn\ the\ other\ hand,\ there\ are\ still\ enhancements\ that\ could\ be\ made.\n\n\[engraving_georgeWashington_portrait_parallel-lines-pinchedEnds_noHatch_610x488.jpg\]\n\nThe\ George\ Washington\ image\ above\ is\ done\ with\ lines\ with\ pinched\ ends.\nThis\ is\ an\ effect\ that\ 'SketchOn'\ cannot\ currently\ do.\ But\ it\ is\ conceivable\nthat\ the\ proc\ that\ adds\ line\ segments\ to\ a\ line\ being\ drawn\ could\ be\ enhanced\nto\ be\ sensitive\ to\ the\ time\ at\ each\ point\ in\ the\ drawing\ of\ a\ line.\ The\ line\nwidth\ could\ be\ automatically\ changed\ according\ to\ the\ speed\ at\ which\ the\ user\nis\ drawing\ the\ line\ ---\ thicker\ at\ slow\ speeds\ and\ thinner\ at\ high\ speeds.\nThen\ a\ line\ could\ be\ tapered\ at\ the\ end\ by\ speeding\ up\ the\ drawing\ stroke\nas\ one\ approached\ the\ time\ to\ release\ the\ mouse\ button.\n\nIn\ any\ case,\ hopefully,\ you\ can\ see\ from\ the\ images\ above\ (other\ than\ the\ last\ 2\ images)\nthat\ there\ is\ a\ wealth\ of\ drawing\ types\ that\ you\ can\ make\ by\ using\ this\ rather\nsimple\ 'SketchOn'\ Tk\ script\ ---\ 'simple'\ compared\ to\ commercial\ drawing\nsoftware\ like\ Adobe\ Freehand\ and\ the\ like\ ---\ simple\ and\ free.\n\n\n\n<<categories>>GUI regexp2} CALL {my render {A 'Sketch On' GUI ... for drawing on an image or colored background} \[uniquename\]\ -\ 2012oct05\n\nIn\ doing\ some\ searches\ on\ this\ wiki\ for\ 'canvas'\ applications,\ I\ ran\nacross\ the\ old\ 2003\ Suchenwirth\ page\ \[A\ minimal\ doodler\ explained\].\n\nI\ pasted\ the\ code\ into\ a\ script\ and\ ran\ it.\ It\ could\ draw\ black\ncurves\ on\ a\ white\ background.\ Nice.\n\nHowever,\ an\ 'artistically\ challenged'\ person\ like\ myself\ could\ use\nsome\ help\ in\ sketching\ ---\ like\ an\ image\ to\ use\ as\ a\ guide\ in\ sketching.\n\nI\ had\ recently\ posted\ a\ script\ here\ that\ loads\ GIF/PNG\ images\ from\nan\ image\ file\ to\ a\ canvas\ ---\ at\ \[GUI\ for\ Editing\ Photo-images\ with\ Functions\].\n\nI\ figured\ that,\ based\ on\ that\ code,\ I\ should\ be\ able\ to\ make\ a\ nice\nsketcher\ utility\ that\ could\ be\ used\ to\ make\ some\ non-trivial\ sketches.\n\nSome\ of\ the\ goals\ that\ I\ had\ for\ this\ utility\ were:\n\n1)\ I\ should\ be\ able\ to\ remove\ the\ image\ from\ the\ canvas\ at\ any\ time\nso\ that\ I\ could\ check\ on\ the\ progress\ of\ the\ sketch.\ Then\ I\ should\nbe\ able\ to\ quickly\ re-apply\ the\ image\ to\ the\ canvas.\n\n2)\ I\ should\ be\ able\ to\ specify\ any\ color\ for\ the\ lines\ being\ sketched\n---\ and\ any\ color\ for\ the\ background\ (the\ canvas).\n\n3)\ I\ should\ be\ able\ to\ change\ to\ a\ different\ line\ width\ at\ any\ntime\ as\ I\ laid\ down\ the\ line\ segments.\n\n4)\ And,\ perhaps\ most\ importantly,\ since\ it\ is\ difficult\ to\ get\ line\nsegments\ just\ the\ way\ you\ want\ them\ (the\ first\ time,\ every\ time),\nI\ needed\ a\ 'robust'\ delete\ capability\ that\ allowed\ me\ to\ quickly\ndelete\ a\ line\ segment\ and\ re-draw\ it.\ (In\ Suchenwirth's\ 'minimal\ndoodler'\ example,\ it\ could\ delete\ ALL\ the\ lines\ drawn,\ but\ not\nindividual\ line\ segments.)\n\nAfter\ a\ couple\ of\ long\ days\ of\ coding\ ---\ and\ reviewing\ and\nreferring\ to\ Chapter\ 37\ 'The\ Canvas\ Widget'\ in\ the\ 4th\ edition\nof\ the\ book\ 'Practical\ Programming\ in\ Tcl\ and\ Tk',\ I\ came\ up\nwith\ the\ GUI\ indicated\ by\ the\ following\ image.\n\n\[sketchONimgGUI_imgOnly_screenshot_638x415.jpg\]\n\nThe\ GUI\ actually\ has\ a\ blank\ canvas\ when\ it\ is\ first\ started\ up.\nThis\ image\ demonstrates\ that\ one\ can\ load\ a\ nice\ image\ onto\ the\ncanvas.\n\nAnd\ the\ following\ image\ shows\ how\ the\ GUI\ may\ look\ after\ sketching\nsome\ lines\ on\ the\ image.\n\n\[sketchONimgGUI_linesANDimg_screenshot_638x415.jpg\]\n\nNote\ that\ if\ you\ are\ having\ a\ hard\ time\ seeing\ the\ lines\ that\ you\nare\ drawing\ on\ the\ image,\ you\ could\ start\ with\ a\ 'faded'\ image.\nFor\ example,\ you\ could\ take\ your\ GIF/PNG\ image\ file\ into\ an\ image\neditor\ (like\ 'mtpaint'\ on\ Linux).\ I\ use\ the\ 'Effects\ >\ Transform\ color\ ...'\noption\ in\ 'mtpaint'\ to\ access\ a\ slider\ bar\ for\ 'Gamma\ correction'.\nBy\ simply\ sliding\ that\ bar\ from\ 100\ to\ about\ 200,\ I\ can\ save\ to\na\ paler\ image,\ and\ then\ use\ that\ image\ on\ which\ to\ sketch.\n\nThe\ following\ image\ shows\ how\ the\ image\ can\ be\ removed\ with\ the\n'RemoveImg'\ button,\ to\ reveal\ the\ progress\ on\ the\ sketch.\n\n\[sketchONimgGUI_linesOnly_screenshot_637x416.jpg\]\n\nThe\ 'Help'\ button\ of\ the\ GUI\ shows\ text\ like\ the\ following,\ which\nindicates\ how\ one\ can\ re-apply\ the\ image\ to\ the\ GUI,\ to\ continue\ndrawing.\ And\ the\ help\ indicates\ how\ one\ can\ quickly\ delete\ line\nsegments\ and\ quickly\ relocate\ the\ image\ on\ the\ canvas.\n\n======\n\n\ To\ DRAW:\n\ Press\ MB1\ (mouse\ button\ 1)\ to\ start\ a\ line\ where\ the\ arrow-cursor\n\ is\ currently\ located\ on\ the\ canvas.\ Continue\ to\ hold\ MB1\ down\ and\n\ move\ the\ mouse\ to\ draw\ the\ current\ line\ segment\ on\ the\ canvas.\n\ Release\ MB1\ to\ terminate\ drawing\ that\ line\ segment.\n\n\ To\ DELETE\ a\ line\ segment,\ press-and-release\ MB3\ (mouse\ button\ 3)\n\ on\ the\ line\ segment\ to\ be\ deleted.\n\n\ Click\ the\ 'RemoveImage'\ button\ to\ see\ how\ your\ drawing\ is\n\ progressing.\ Then\ ...\n\n\ Click\ and\ release\ MB1\ on\ the\ filename\ in\ the\ entry\ field,\ to\n\ RELOAD\ the\ image\ from\ the\ image\ file\ to\ the\ canvas.\ If\ the\n\ reload\ covers\ up\ your\ lines,\ click\ on\ the\ 'RaiseLines'\ button\n\ to\ reveal\ the\ lines\ again.\n\n\ Use\ MB2\ to\ move\ (drag)\ the\ image\ to\ a\ new\ location.\ This\ can\n\ be\ useful\ to\ use\ additional\ images\ to\ help\ sketch\ the\ picture.\n\ Or\ it\ can\ be\ used\ to\ offset\ the\ current\ image\ and\ use\ it\ for\n\ addtional\ sketching.\n\n\ You\ can\ use\ a\ screen/image\ capture\ utility\ to\ capture\ your\n\ drawing\ ---\ with\ or\ without\ an\ underlying\ image\ in\ place.\n\n======\n\nHow\ to\ change\ colors\ is\ not\ mentioned\ in\ this\ help,\ but\ it\ should\nbe\ fairly\ obvious\ that\ those\ capabilities\ are\ available\ (and\ how\ to\nmake\ the\ color\ changes)\ from\ the\ presense\ of\ the\ 'Next\ line\ color'\ and\n'Background\ color'\ buttons\ on\ the\ GUI.\n\nThose\ 2\ color\ buttons\ call\ on\ a\ color-selector-GUI\ script\ to\ set\ those\ colors.\nYou\ can\ make\ that\ color-selector\ script\ by\ cutting-and-pasting\ the\ code\ from\nthe\ page\ \[A\ non-obfuscated\ color\ selector\ GUI\]\ on\ this\ site.\n\n_____________________________________________________________________\n\nBelow\ is\ the\ code\ that\ produced\ this\ GUI.\n\nThere\ are\ comments\ above\ the\ sample\ code,\ in\ a\ section\ titled\n'USING\ THE\ GENERATED\ IMAGE',\ that\ describe\ how\ one\ could\ make\ use\ of\nimages\ produced\ by\ this\ GUI.\n\nI\ follow\ my\ usual\ 'canonical'\ structure\ for\ Tk\ code,\ for\ this\ Tk\ script:\n\n\ \ 0)\ Set\ general\ window\ &\ widget\ parms\ (win-name,\ win-position,\n\ \ \ \ \ win-color-scheme,\ fonts,\ widget-geometry-parms,\ win-size-control).\n\n\ \ 1a)\ Define\ ALL\ frames\ and\ sub-frames.\n\ \ 1b)\ Pack\ \ \ ALL\ frames\ and\ sub-frames.\n\n\ \ 2)\ Define\ &\ pack\ all\ widgets\ in\ the\ frames.\n\n\ \ 3)\ Define\ keyboard\ or\ mouse\ action\ BINDINGS,\ if\ needed.\n\n\ \ 4)\ Define\ PROCS,\ if\ needed.\n\n\ \ 5)\ Additional\ GUI\ initialization\ (typically\ with\ one\ or\ more\ of\n\ \ \ \ \ the\ procs),\ if\ needed.\n\nThis\ makes\ it\ easy\ for\ me\ to\ find\ code\ sections\ ---\ while\ generating\nand\ testing\ this\ script,\ and\ when\ looking\ for\ code\ snippets\ to\ninclude\ in\ other\ scripts.\n\n_________________________________________________________________\n\nAs\ in\ all\ my\ scripts\ that\ use\ the\ 'pack'\ geometry\ manager\ (which\nis\ all\ of\ my\ 100-plus\ Tk\ scripts,\ so\ far),\ I\ provide\ the\ four\ main\npack\ parameters\ ---\ '-side',\ '-anchor',\ '-fill',\ and\ '-expand'\n---\ on\ all\ the\ 'pack'\ commands\ for\ the\ frames\ and\ widgets.\n\nI\ think\ I\ have\ found\ a\ good\ setting\ of\ the\ \n'-side',\ '-anchor',\ '-fill',\ and\ '-expand'\ parameters\ on\nthe\ 'pack'\ commands\ for\ the\ various\ widgets\ of\ this\ GUI.\ In\ particular\ ...\n\nThe\ 'canvas'\ widget\ expands/contracts\ appropriately\ when\ the\ window\nsize\ is\ changed\ ---\ and\ button\ and\ label\ widgets\ stay\ fixed\ in\ size\nand\ relative-location\ as\ the\ window\ size\ is\ changed.\n\nIf\ anyone\ wants\ to\ change\ the\ way\ the\ GUI\ configures\nitself\ as\ the\ main\ window\ size\ is\ changed,\ they\ can\ experiment\nwith\ the\ \ '-side',\ '-anchor',\ '-fill',\ and\ '-expand'\ parameters\non\ the\ 'pack'\ commands\ for\ the\ various\ widgets\ ---\ to\ get\ the\nwidget\ behavior\ that\ they\ want.\ For\ example,\ I\ allow\ the\ scale\ widget\nto\ x-expand\ with\ the\ window.\ You\ may\ want\ the\ scale\ widget\ to\ be\ a\nfixed\ size.\n\nAlso,\ you\ could\ change\ the\ font\ used\ for\ the\ text\ in\ the\ widgets.\nFor\ example,\ you\ could\ change\ '-weight'\ from\ 'bold'\ to\ 'normal'\ ---\nor\ '-slant'\ from\ 'roman'\ to\ 'italic'.\ Or\ change\ font\ families.\n\nFurthermore,\ there\ are\ variables\ used\ to\ set\ geometry\ parameters\nof\ widgets\ ---\ parameters\ such\ as\ border-widths\ and\ padding.\nFeel\ free\ to\ experiment\ with\ those\ parameters\ as\ well.\n\n_____________________________________________________________________\n\nThat\ said,\ here's\ the\ code\ ---\ with\ plenty\ of\ comments\ to\ describe\nwhat\ most\ of\ the\ code-sections\ are\ doing.\n\nI\ modified\ the\ 'doodle'\ procs\ of\ Suchenwirth\ quite\ a\ bit\ ---\ and\ devised\na\ 'doodle_delete'\ proc\ to\ help\ assure\ that\ the\ desired\ object\ is\ deleted\non\ an\ MB3\ click-and-release.\n\nThe\ copious\ comments\ in\ the\ code\ might\ help\ Tcl-Tk\ coding\ 'newbies'\ get\ started\nin\ making\ GUI's\ like\ this.\ Without\ the\ comments\ ---\ especially\ in\ the\ 'doodle_delete'\nproc,\ the\ code\ might\ look\ too\ cryptic\ ---\ and\ potential\ young\ Tcler's\nmight\ be\ tempted\ to\ return\ to\ their\ iPhones\ and\ iPads\ and\ iPods\ ---\ to\ listen\nto\ recently\ released\ music\ ---\ which\ IMHO,\ for\ the\ most\ part,\ cannot\ match\ the\nmusic\ of\ the\ late\ 1960's\ and\ early\ 1970's.\n\n======\n\n#!/usr/bin/wish\ -f\n##+###########################################################################\n##\n##\ SCRIPT:\ sketch_onImgFromFile_utility.tk\n##\n##\ PURPOSE:\ This\ script\ allows\ the\ user\ to\ select\ an\ image\ file\ and\ load\n##\ \ \ \ \ \ \ \ \ \ its\ image\ onto\ a\ Tk\ canvas.\ The\ user\ can\ then\ 'freehand'\n##\ \ \ \ \ \ \ \ \ \ draw\ lines\ (curves)\ of\ varying\ width\ and\ color\ on\ the\ image,\n##\ \ \ \ \ \ \ \ \ \ using\ the\ mouse\ (or\ touchpad\ or\ touch-sensitive-screen\ or\ whatever).\n##\n##\ \ \ \ \ \ \ \ \ \ The\ user\ can\ choose\ from\ over\ 16\ million\ colors\ for\ the\n##\ \ \ \ \ \ \ \ \ \ various\ line\ segments\ drawn.\n##\n##\ \ \ \ \ \ \ \ \ \ The\ image\ files\ that\ can\ be\ loaded\ to\ the\ canvas\ may\ be\ GIF\ files\n##\ \ \ \ \ \ \ \ \ \ ---\ and\ PNG\ eventually,\ by\ using\ 8.6.x\ versions\ of\ the\ 'wish'\n##\ \ \ \ \ \ \ \ \ \ interpreter.\n##\n##\ \ \ \ \ \ \ \ \ \ (I\ used\ a\ utility\ script\ based\ on\ the\ ImageMagick\ 'convert'\n##\ \ \ \ \ \ \ \ \ \ \ command\ to\ convert\ JPEG\ files\ to\ GIF\ files,\ for\ testing.)\ \ \ \ \ \ \ \ \ \ \n##\n##\ \ \ \ \ \ \ \ \ \ The\ user\ has\ the\ option\ of\ removing\ the\ image\ from\ the\ canvas\n##\ \ \ \ \ \ \ \ \ \ (leaving\ the\ 'sketch')\ ---\ or\ the\ image\ can\ be\ left\ in\ place,\n##\ \ \ \ \ \ \ \ \ \ along\ with\ the\ sketch\ lines.\n##\n##\ \ \ \ \ \ \ \ \ \ Then\ the\ user\ can\ capture\ the\ image\ with\ a\ screen/window\ capture\n##\ \ \ \ \ \ \ \ \ \ tool\ and\ save\ the\ image\ as\ a\ PNG\ file\ (or\ whatever\ output\ format\n##\ \ \ \ \ \ \ \ \ \ the\ screen\ capture\ tool\ supports).\n##\n##\ \ \ \ \ \ \ \ \ \ The\ user\ can\ crop\ the\ image\ with\ an\ image\ editor,\ and\ save\ the\n##\ \ \ \ \ \ \ \ \ \ image\ as\ a\ PNG\ or\ JPEG\ or\ GIF\ file,\ say.\ \ Then\ the\ image\ file\n##\ \ \ \ \ \ \ \ \ \ could\ be\ used\ in\ e-mails,\ web\ pages,\ or\ even\ Tk\ GUI's.\n##\n##\ \ \ \ \ \ \ \ \ \ One\ 'application'\ of\ the\ script\ is\ to\ use\ photos\ of\ relatives\ or\n##\ \ \ \ \ \ \ \ \ \ friends\ or\ pets\ or\ favorite\ celebrities\ and\ make\ sketches\n##\ \ \ \ \ \ \ \ \ \ from\ the\ photo.\n##\n##\ \ \ \ \ \ \ \ \ \ Note\ that\ an\ image\ file\ is\ not\ required.\ This\ utility\ can\n##\ \ \ \ \ \ \ \ \ \ be\ used\ to\ sketch\ lines\ of\ various\ thicknesses\ and\ colors\n##\ \ \ \ \ \ \ \ \ \ onto\ a\ colored\ canvas.\n##\n##\ \ \ \ \ \ \ \ \ \ A\ key\ feature\ is\ the\ ability\ to\ quickly\ delete\ mistakes\n##\ \ \ \ \ \ \ \ \ \ (unwanted\ canvas\ objects\ ---\ lines\ or\ 'degenerate\ lines'=points),\n##\ \ \ \ \ \ \ \ \ \ by\ a\ button-3\ click\ on\ a\ botched\ line\ (or\ point).\n##\n##\ GUI\ DESIGN:\n##\n##\ \ \ \ \ \ \ \ \ This\ script\ provides\ a\ Tk\ GUI\ with\ the\ following\ widgets.\n##\n##\ \ \ \ \ \ \ \ \ 0)\ There\ is\ a\ CANVAS\ widget\ on\ which\ to\ load\ the\ 'photo'\ image\n##\ \ \ \ \ \ \ \ \ \ \ \ and\ on\ which\ to\ draw\ 'freehand'\ lines/curves.\n##\n##\ \ \ \ \ \ \ \ \ 1)\ There\ is\ a\ FILENAME-ENTRY\ FIELD\ and\ 'Browse\ ...'\ BUTTON\ with\n##\ \ \ \ \ \ \ \ \ \ \ \ which\ to\ get\ an\ image\ file\ to\ load\ onto\ the\ canvas\ widget\ of\n##\ \ \ \ \ \ \ \ \ \ \ \ this\ GUI.\n##\n##\ \ \ \ \ \ \ \ \ 2)\ There\ is\ a\ set\ of\ BUTTONS\ ---\ 'Exit'\ and\ 'RemoveImage'\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ 'RemoveLines'\ and\ 'RaiseLines'\ and\ a\ couple\ of\ COLOR\ buttons\n##\ \ \ \ \ \ \ \ \ \ \ \ to\ set\ the\ current\ line-drawing\ color\ ---\ and\ to\ set\n##\ \ \ \ \ \ \ \ \ \ \ \ a\ background\ (canvas)\ color.\ \ The\ background\ color\ shows\ if\n##\ \ \ \ \ \ \ \ \ \ \ \ the\ user\ chooses\ to\ remove\ the\ image\ that\ was\ placed\ on\n##\ \ \ \ \ \ \ \ \ \ \ \ the\ canvas.\n##\n##\ \ \ \ \ \ \ \ \ 3)\ There\ is\ a\ SCALE\ widget\ to\ set\ the\ WIDTH\ of\ the\ next\n##\ \ \ \ \ \ \ \ \ \ \ \ line-segments\ to\ be\ drawn.\n##\n##\ \ \ \ \ \ \ \ \ 4)\ Other\ controls\ were\ added:\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ a\ SCALE\ to\ set\ millisecs\ between\ points\ added\ to\ current\ line\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ ---\ to\ let\ the\ user\ control\ the\ 'jitteriness'\ ---\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ the\ straightness\ ---\ of\ the\ line\ being\ drawn.\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ CHECKBUTTON\ to\ set\ line\ style:\ 'smooth'\ (curved)\ ---\ or\ polygonal\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ RADIOBUTTONS\ to\ set\ line\ cap-style:\ round/butt/projecting\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ RADIOBUTTONS\ to\ set\ line\ join-style:\ round/bevel/miter\n##\ \ \ \ \ \ \ \ \ \ \ \ -\ LABELS\ to\ show\ 'Nobj'\ and\ 'NcurPoints',\ where\ \$Nobj\ is\ the\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ number\ of\ objects\ (lines\ and\ points)\ in\ the\ current\ drawing,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ \$NcurPoints\ is\ the\ number\ of\ points\ being\ generated\ in\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ the\ line\ currently\ being\ drawn.\n##\n##+########################\n##\ REFERENCES\ (and\ credits):\n##\n##\ \ The\ image\ file\ loading\ code\ (and\ a\ lot\ of\ the\ other\ code)\ in\ this\ script\n##\ \ is\ based\ on\ my\ script\ 'photoFile_editing_viaFunctions.tk'\ from\ the\n##\ \ http://wiki.tcl.tk/36850\ -\ 'GUI\ for\ Editing\ Photo-images\ with\ Functions'.\n##\n##\ \ The\ code\ for\ the\ 'doodling'\ on\ the\ canvas\ was\ based\ on\ \n##\ \ 'A\ minimal\ doodler\ explained'\ -\ http://wiki.tcl.tk/9625\n##\ \ by\ Richard\ Suchenwirth,\ 2003\ Aug.\n##\n##\ \ Similar\ code\ was\ posted\ by\ 'elfo',\ years\ earlier:\n##\ \ http://wiki.tcl.tk/1155\ \ -\ 'Canvas\ pixel\ painting'\n##\n##\ \ Some\ reading\ of\ Chapter\ 37\ 'The\ Canvas\ Widget'\ in\ the\ 4th\ edition\n##\ \ of\ the\ book\ 'Practical\ Programming\ in\ Tcl\ and\ Tk'\ was\ helpful.\n##\n##+#######################################################################\n##\ 'CANONICAL'\ STRUCTURE\ OF\ THIS\ CODE:\n##\n##\ \ 0)\ Set\ general\ window\ parms\ (win-name,\ win-position,\ win-color-scheme,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ fonts,\ widget-geometry,\ win-size-control).\n##\ \ 1a)\ Define\ ALL\ frames\ and\ sub-frames.\n##\ \ 1b)\ Pack\ \ \ ALL\ frames\ and\ sub-frames.\n##\ \ 2)\ Define\ &\ pack\ all\ widgets\ in\ the\ frames.\n##\n##\ \ 3)\ Define\ key\ and\ mouse/touchpad/touch-sensitive-screen\ action\n##\ \ \ \ \ BINDINGS,\ if\ needed.\n##\ \ 4)\ Define\ PROCS,\ if\ needed.\n##\ \ 5)\ Additional\ GUI\ INITIALIZATION\ (typically\ with\ one\ or\ more\ of\n##\ \ \ \ \ the\ procs),\ if\ needed.\n##\n##+#################################\n##\ Some\ detail\ of\ the\ code\ structure\ of\ this\ particular\ script:\n##\n##\ \ 1a)\ Define\ ALL\ frames:\n##\ \n##\ \ \ Top-level\ :\n##\ \ \ \ \ \ \ 'fRfile'\ \ \ \ \ \ -\ to\ contain\ a\ triplet:\ label-entry-button\ widgets\n##\ \ \ \ \ \ \ 'fRbuttons'\ \ \ -\ to\ contain\ an\ 'Exit'\ button,\ 'Help'\ button,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 'RemoveImg'\ &\ 'RemoveLines'\ &\ 'RaiseLines'\ buttons,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ 2\ color\ selection\ buttons\ (for\ next\ line\ color\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ for\ canvas/background\ color).\n##\ \ \ \ \ \ \ 'fRstatus'\ \ \ \ \ -\ to\ contain\ labels\ showing\ Nobj\ and\ NcurPoints.\n##\ \ \ \ \ \ \ 'fRcontrols1'\ \ -\ to\ contain\ a\ label\ &\ scale\ widget\ pair\ for\ next-line\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ width\ ---\ and\ a\ label\ &\ scale\ widget\ pair\ for\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ setting\ a\ 'milliseconds\ tween\ added\ points'\ variable,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Nmillisecs,\ which\ controls\ line-'jitter'/straightness\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ by\ controlling\ the\ number\ of\ 'control\ points'\ in\ a\ line.\n##\ \ \ \ \ \ \ 'fRcontrols2'\ \ -\ to\ contain\ a\ checkbutton\ to\ set\ the\ 'smooth'\ option\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ of\ 'create\ line'\ on/off.\ Also\ to\ contain\ 2\ sets\ of\ radiobuttons\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ for\ the\ 'capstyle'\ &\ 'joinstyle'\ options\ of\ 'create\ line'.\n##\ \ \ \ \ \ \ 'fRcanvas'\ \ \ \ \ -\ to\ contain\ the\ canvas\ widget.\n##\n##\ \ \ Sub-frames:\ none\n##\n##\ \ 1b)\ Pack\ ALL\ frames.\ (Note:\ We\ may\ change\ the\ packing\ order\ of\ the\ frames\n##\ \ \ \ \ \ as\ we\ experiment\ with\ the\ GUI\ layout.\ In\ fact,\ some\ widgets\ may\ be\n##\ \ \ \ \ \ switched\ from\ one\ frame\ to\ another.)\n##\n##\ \ 2)\ Define\ &\ pack\ all\ widgets\ in\ the\ frames\ --\ basically\ going\ through\n##\ \ \ \ \ frames\ &\ their\ interiors\ in\ top-to-bottom\ and/or\ left-to-right\ order:\n##\n##\ \ 3)\ Define\ bindings:\n##\ \ \ \ \ \ -\ Button1-release\ \ -\ on\ the\ filename\ entry\ field\ -\ to\ put\ img\ on\ canvas\n##\ \ \ \ \ \ -\ Return/Enter\ key\ -\ on\ the\ filename\ entry\ field\ -\ to\ put\ img\ on\ canvas\n##\n##\ \ \ \ \ \ -\ bind\ <ButtonPress-1>\ \ \ -\ on\ the\ canvas\ -\ calls\ proc\ 'doodle_start'\n##\ \ \ \ \ \ -\ bind\ <Button1-Motion>\ \ -\ on\ the\ canvas\ -\ calls\ proc\ 'doodle_continue'\n##\ \ \ \ \ \ -\ bind\ <ButtonRelease-1>\ -\ on\ the\ canvas\ -\ calls\ proc\ 'doodle_end'\n##\n##\ \ \ \ \ \ -\ bind\ <ButtonRelease-3>\ -\ on\ the\ canvas\ -\ calls\ proc\ 'doodle_delete'\n##\n##\ \ \ \ Two\ Button3\ Enter/Leave\ bindings\ could\ be\ added\ to\ change\ the\ color\ of\ a\ line\ (say,\n##\ \ \ \ to\ orange)\ when\ the\ mouse\ is\ over\ a\ line\ ---\ to\ let\ the\ user\ know\ which\ line-object\n##\ \ \ \ has\ been\ detected\ ---\ to\ help\ with\ deleting\ lines/objects\ ---\ so\ that\ the\n##\ \ \ \ wrong\ object\ is\ not\ deleted.\n##\n##\ \ \ \ \ \ -\ bind\ <Control-ButtonPress-1>\ \ \ -\ on\ the\ canvas\ -\ calls\ proc\ 'image_grab'\n##\ \ \ \ \ \ -\ bind\ <Control-Button1-Motion>\ \ -\ on\ the\ canvas\ -\ calls\ proc\ 'image_move'\n##\n##\n##\ \ 4)\ Define\ procs:\n##\ \ \ \ \ -\ 'get_img_filename'\ \ \ \ \ \ -\ to\ get\ the\ image\ filename\n##\ \ \ \ \ -\ 'doodle_start'\ \ \ \ \ \ \ \ \ \ -\ to\ start\ a\ 'doodle'\ line\n##\ \ \ \ \ -\ 'doodle_continue'\ \ \ \ \ \ \ -\ to\ continue\ a\ 'doodle'\ line\n##\ \ \ \ \ -\ 'doodle_end'\ \ \ \ \ \ \ \ \ \ \ \ -\ to\ finish\ a\ 'doodle'\ line\n##\ \ \ \ \ -\ 'doodle_delete'\ \ \ \ \ \ \ \ \ -\ to\ delete\ a\ 'closest'\ doodle\ line\n##\ \ \ \ \ -\ 'image_grab'\ \ \ \ \ \ \ \ \ \ \ \ -\ to\ start\ grab\ the\ image\ (not\ needed?)\n##\ \ \ \ \ -\ 'image_move'\ \ \ \ \ \ \ \ \ \ \ \ -\ to\ move\ the\ image\n##\ \ \ \ \ -\ 'set_line_color1'\ \ \ \ \ \ \ -\ to\ set\ the\ 'fill'\ color\ for\ drawing\ the\ next\ line\n##\ \ \ \ \ -\ 'set_background_color'\ \ -\ to\ set\ the\ background\ (canvas)\ color\n##\ \ \ \ \ -\ 'update_colors_label'\ \ \ -\ to\ set\ a\ COLORS\ label\ to\ current\ color\ vals\n##\ \ \ \ \ -\ 'update_status_labels'\ \ -\ to\ set\ 2\ counts\ labels\ to\ current\ vals\n##\ \ \ \ \ -\ 'remove_all_lines'\ \ \ \ \ \ -\ to\ remove\ all\ lines\ from\ the\ canvas\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ reset\ a\ couple\ of\ counts\n##\ \ \ \ \ -\ 'popup_msg_var'\ \ \ \ \ \ \ \ \ -\ to\ show\ help\ (could\ be\ used\ to\ show\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ other\ msgs,\ as\ needed)\n##\n##\ \ 5)\ Additional\ GUI\ initialization:\ set\ a\ default\ canvas\ color\ ---\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ other\ than\ that,\ the\ canvas\ is\ blank,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ waiting\ for\ the\ user\ to\ select\ an\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ image\ and\ start\ drawing\ lines\ ---\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ or\ simply\ start\ drawing\ lines.\n##\n##+#######################################################################\n##\ DEVELOPED\ WITH:\ Tcl-Tk\ 8.5\ on\ Ubuntu\ 9.10\ (2009-october,\ 'Karmic\ Koala')\n##\n##\ \ \ \$\ wish\n##\ \ \ %\ puts\ \"\$tcl_version\ \$tk_version\"\n##\n##\ showed\n##\ \ \ \ \ 8.5\ 8.5\n##\ but\ this\ script\ should\ work\ in\ most\ previous\ 8.x\ versions,\ and\ probably\n##\ even\ in\ some\ 7.x\ versions\ (if\ font\ handling\ is\ made\ 'old-style').\n##+#######################################################################\n##\ MAINTENANCE\ HISTORY:\n##\ Started\ by:\ Blaise\ Montandon\ 2012sep22\ Started\ development,\ on\ Ubuntu\ 9.10,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ based\ on\ my\ code\ at\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ http://wiki.tcl.tk/36850\ -\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 'GUI\ for\ Editing\ Photo-images\ with\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Functions'\n##\ Changed\ by:\ Blaise\ Montandon\ 2012oct05\ Improve\ the\ 'doodle_delete'\ proc\ to\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ make\ sure\ it\ deletes\ a\ line\ segment\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ not\ the\ image.\ Also\ add\ a\ 'halo'\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ parm\ to\ delete\ the\ intended\ line\ segment.\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Add\ an\ MB2\ binding\ to\ move\ the\ image.\n##\ Changed\ by:\ Blaise\ Montandon\ 2012oct20\ Added\ counters\ Nobj\ &\ NcurPoints\ ---\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ to\ indicate\ to\ the\ user\ how\ many\ lines\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ points\ are\ being\ generated.\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Added\ a\ scale\ to\ 'fRcontrols1'\ to\ set\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ the\ new\ var\ Nmillisecs\ ---\ to\ help\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ draw\ straight\ lines.\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Added\ frames\ 'fRstatus'\ &\ 'fRcontrols2'\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ the\ label\ &\ checkbutton\ &\ radiobutton\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ widgets\ within\ them.\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Added\ button3-enter\ &\ button3-leave\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ bindings\ to\ hilite\ an\ object\ before\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ it\ is\ deleted.\n##+########################################################################\n\n\n##+#######################################################################\n##\ Set\ general\ window\ parms\ (titles,position).\n##+#######################################################################\n\nwm\ title\ \ \ \ .\ \"'Sketch\ On'\ ...\ an\ image\ or\ a\ color\ background\"\nwm\ iconname\ .\ \"SketchOn\"\n\nwm\ geometry\ .\ +15+30\n\n\n##+######################################################\n##\ Set\ the\ color\ scheme\ for\ the\ window\ and\ its\ widgets\ ---\n##\ such\ as\ entry\ field\ background\ color.\n##+######################################################\n\ntk_setPalette\ \"#e0e0e0\"\n\nset\ entryBKGD\ \"#ffffff\"\n#\ set\ listboxBKGD\ \"#ffffff\"\n\n##\ Initialize\ the\ line-drawing\ color\n##\ and\ the\ background\ color\ for\ the\ canvas.\n\nset\ COLOR1r\ 0\nset\ COLOR1g\ 0\nset\ COLOR1b\ 0\n#\ set\ COLOR1r\ 255\n#\ set\ COLOR1g\ 255\n#\ set\ COLOR1b\ 0\nset\ COLOR1hex\ \[format\ \"#%02X%02X%02X\"\ \$COLOR1r\ \$COLOR1g\ \$COLOR1b\]\n\n\n#\ set\ COLORbkGNDr\ 60\n#\ set\ COLORbkGNDg\ 60\n#\ set\ COLORbkGNDb\ 60\nset\ COLORbkGNDr\ 255\nset\ COLORbkGNDg\ 255\nset\ COLORbkGNDb\ 255\nset\ COLORbkGNDhex\ \\\n\ \ \ \ \[format\ \"#%02X%02X%02X\"\ \$COLORbkGNDr\ \$COLORbkGNDg\ \$COLORbkGNDb\]\n\n\nset\ radbuttBKGD\ \"#f0f0f0\"\n\n\n##+########################################################\n##\ We\ use\ a\ VARIABLE-WIDTH\ font\ for\ text\ on\ label\ and\n##\ button\ widgets.\n##\n##\ We\ use\ a\ FIXED-WIDTH\ font\ for\ text\ in\ entry\ &\ listbox\ widgets\n##\ and\ for\ the\ text\ in\ a\ text\ widget,\ such\ as\ help\ text.\n##+########################################################\n\nfont\ create\ fontTEMP_varwidth\ \\\n\ \ \ -family\ \{comic\ sans\ ms\}\ \\\n\ \ \ -size\ -14\ \\\n\ \ \ -weight\ bold\ \\\n\ \ \ -slant\ roman\n\nfont\ create\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -family\ \{comic\ sans\ ms\}\ \\\n\ \ \ -size\ -10\ \\\n\ \ \ -weight\ bold\ \\\n\ \ \ -slant\ roman\n\n##\ Some\ other\ possible\ (similar)\ variable\ width\ fonts:\n##\ \ Arial\n##\ \ Bitstream\ Vera\ Sans\n##\ \ DejaVu\ Sans\n##\ \ Droid\ Sans\n##\ \ FreeSans\n##\ \ Liberation\ Sans\n##\ \ Nimbus\ Sans\ L\n##\ \ Trebuchet\ MS\n##\ \ Verdana\n\nfont\ create\ fontTEMP_fixedwidth\ \ \\\n\ \ \ -family\ \{liberation\ mono\}\ \\\n\ \ \ -size\ -14\ \\\n\ \ \ -weight\ bold\ \\\n\ \ \ -slant\ roman\n\nfont\ create\ fontTEMP_SMALL_fixedwidth\ \ \\\n\ \ \ -family\ \{liberation\ mono\}\ \\\n\ \ \ -size\ -10\ \\\n\ \ \ -weight\ bold\ \\\n\ \ \ -slant\ roman\n\n##\ Some\ other\ possible\ fixed\ width\ fonts\ (esp.\ on\ Linux):\n##\ \ Andale\ Mono\n##\ \ Bitstream\ Vera\ Sans\ Mono\n##\ \ Courier\ 10\ Pitch\n##\ \ DejaVu\ Sans\ Mono\n##\ \ Droid\ Sans\ Mono\n##\ \ FreeMono\n##\ \ Nimbus\ Mono\ L\n##\ \ TlwgMono\n\n\n##+###########################################################\n##\ SET\ GEOM\ VARS\ FOR\ THE\ VARIOUS\ WIDGET\ DEFINITIONS.\n##\ (e.g.\ width\ and\ height\ of\ canvas,\ and\ padding\ for\ Buttons)\n##+###########################################################\n\nset\ initCanWidthPx\ 300\nset\ initCanHeightPx\ 300\n\nset\ minCanWidthPx\ 24\nset\ minCanHeightPx\ 24\n\n#\ set\ BDwidthPx_canvas\ 2\n\ \ set\ BDwidthPx_canvas\ 0\n\n\n##\ BUTTON\ widget\ geom\ settings:\n\nset\ PADXpx_button\ 0\nset\ PADYpx_button\ 0\nset\ BDwidthPx_button\ 2\n\n\n##\ LABEL\ widget\ geom\ settings:\n\nset\ BDwidthPx_label\ 2\n\n\n##\ ENTRY\ widget\ geom\ settings:\n\nset\ BDwidthPx_entry\ 2\nset\ initImgfileEntryWidthChars\ 20\n\n\n##\ SCALE\ geom\ parameters:\n\nset\ BDwidthPx_scale\ 2\nset\ initScaleLengthPx\ 200\n\n\n##\ LISTBOX\ geom\ settings:\n\n#\ set\ BDwidthPx_listbox\ 2\n#\ set\ initListboxWidthChars\ 30\n#\ set\ initListboxHeightChars\ 8\n\n\n##+#######################################################################\n##\ Set\ a\ MINSIZE\ of\ the\ window\ (roughly).\n##\n##\ For\ width,\ allow\ for\ the\ minwidth\ of\ the\ '.fRbuttons'\ frame:\n##\ \ \ \ \ \ \ \ \ \ \ \ about\ 4\ buttons\ (Exit,RemoveImg,Color1,ColorBkgnd),\ and\n##\ \ \ \ \ \ \ \ \ \ \ \ a\ label\ with\ current\ color\ values\ info.\n##\n##\ For\ height,\ allow\ for\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 1\ char\ high\ for\ the\ '.fRfile'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 2\ chars\ high\ for\ the\ widgets\ in\ the\ '.fRbuttons'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 1\ char\ high\ for\ the\ '.fRstatus'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 2\ chars\ high\ for\ the\ '.fRcontrols1'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ 2\ chars\ high\ for\ the\ '.fRcontrols2'\ frame\n##\ \ \ \ \ \ \ \ \ \ \ \ \ a\ canvas\ at\ least\ 24\ pixels\ high.\n##+#######################################################################\n\nset\ minWinWidthPx\ \[font\ measure\ fontTEMP_varwidth\ \\\n\ \ \ \"Exit\ Remove\ Next\ Line\ Background\ \ Colors:\ Line\ #ff00ff\ Bkgnd:\ #000000\"\]\n\n##\ Add\ some\ pixels\ to\ account\ for\ right-left-side\ window\ decoration\n##\ (about\ 8\ pixels),\ about\ 5\ x\ 8\ pixels/widget\ for\ borders/padding\ for\n##\ 5\ widgets\ ---\ 4\ buttons\ and\ 1\ label.\n\nset\ minWinWidthPx\ \[expr\ \{48\ +\ \$minWinWidthPx\}\]\n\n\n##\ MIN\ HEIGHT\ ---\n##\ for\ the\ 6\ frames\ 'fRfile'\ 'fRstatus'\ 'fRbuttons'\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 'fRcontrols1'\ 'fRcontrols2'\ 'fRcanvas'.\n##\ Allow\n##\ \ \ \ 1\ char\ \ high\ for\ 'fRfile'\n##\ \ \ \ 2\ char\ \ high\ for\ 'fRbuttons'\n##\ \ \ \ 1\ char\ \ high\ for\ 'fRstatus'\n##\ \ \ \ 2\ chars\ high\ for\ 'fRcontrols1'\n##\ \ \ \ 2\ chars\ high\ for\ 'fRcontrols2'\n##\ \ \ 24\ pixels\ high\ for\ 'fRcanvas'\n\nset\ charHeightPx\ \[font\ metrics\ fontTEMP_fixedwidth\ -linespace\]\n\nset\ minWinHeightPx\ \[expr\ \{24\ +\ 8\ *\ \$charHeightPx\}\]\n\n##\ Add\ about\ 28\ pixels\ for\ top-bottom\ window\ decoration,\n##\ about\ 6x6\ pixels\ for\ each\ of\ the\ 6\ stacked\ frames\ and\ their\n##\ widgets\ (their\ borders/padding).\n\nset\ minWinHeightPx\ \[expr\ \{\$minWinHeightPx\ +\ 64\}\]\n\n##\ FOR\ TESTING:\n#\ \ \ puts\ \"minWinWidthPx\ =\ \$minWinWidthPx\"\n#\ \ \ puts\ \"minWinHeightPx\ =\ \$minWinHeightPx\"\n\nwm\ minsize\ .\ \$minWinWidthPx\ \$minWinHeightPx\n\n\n##\ We\ allow\ the\ window\ to\ be\ resizable\ and\ we\ pack\ the\ canvas\ with\n##\ '-fill\ both'\ so\ that\ the\ canvas\ can\ be\ enlarged\ by\ enlarging\ the\n##\ window.\n\n##\ If\ you\ want\ to\ make\ the\ window\ un-resizable,\ \n##\ you\ can\ use\ the\ following\ statement.\n#\ wm\ resizable\ .\ 0\ 0\n\n\n##+################################################################\n##\ DEFINE\ *ALL*\ THE\ FRAMES:\n##\n##\ \ \ Top-level\ :\ '.fRfile'\ '.fRbuttons'\ '.fRstatus'\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '.fRcontrols1'\ '.fRcontrols2'\ '.fRcanvas'\n##\n##\ \ \ Sub-frames:\ none\n##+################################################################\n\n#\ set\ RELIEF_frame\ raised\n#\ set\ BDwidth_frame\ 2\n\n\ \ set\ RELIEF_frame\ flat\n\ \ set\ BDwidth_frame\ 0\n\nframe\ .fRfile\ \ \ \ \ \ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRbuttons\ \ \ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRstatus\ \ \ \ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRcontrols1\ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRcontrols2\ -relief\ \$RELIEF_frame\ \ -bd\ \$BDwidth_frame\nframe\ .fRcanvas\ \ \ \ -relief\ raised\ \ \ \ \ \ \ \ \ -bd\ 2\n\n\n##+######################################\n##\ PACK\ the\ FRAMES.\ \n##\ NOTE:\ We\ can\ experiment\ with\ the\ order\n##\ in\ which\ the\ frames\ are\ stacked.\n##+######################################\n\npack\ .fRfile\ \\\n\ \ \ -side\ top\ \\\n\ \ \ -anchor\ nw\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 0\n\npack\ .fRbuttons\ \\\n\ \ \ \ \ .fRstatus\ \\\n\ \ \ \ \ .fRcontrols2\ \\\n\ \ \ \ \ .fRcontrols1\ \\\n\ \ \ -side\ top\ \\\n\ \ \ -anchor\ nw\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\npack\ .fRcanvas\ \\\n\ \ \ -side\ top\ \\\n\ \ \ -anchor\ nw\ \\\n\ \ \ -fill\ both\ \\\n\ \ \ -expand\ 1\n\n##\ OK,\ frames\ are\ defined.\ Now\ start\ defining-and-packing\ widgets.\n\n\n##+###############################\n##\ In\ FRAME\ '.fRfile'\ -\n##\ DEFINE-and-PACK\ 3\ widgets\ -\n##\ LABEL,\ ENTRY,\ BUTTON:\n##+###############################\n\nlabel\ .fRfile.labelFILE\ \\\n\ \ \ -text\ \"ImgFilename\ (GIF/PNG):\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ 0\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ ENTRYfilename\ \"\"\n\nentry\ .fRfile.entFILENAME\ \\\n\ \ \ -textvariable\ ENTRYfilename\ \\\n\ \ \ -bg\ \$entryBKGD\ \\\n\ \ \ -font\ fontTEMP_fixedwidth\ \\\n\ \ \ -width\ \$initImgfileEntryWidthChars\ \\\n\ \ \ -relief\ sunken\ \\\n\ \ \ -bd\ \$BDwidthPx_entry\n\nbutton\ .fRfile.buttBROWSE\ \\\n\ \ \ -text\ \"Browse\ ...\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{get_img_filename\}\n\n\n##\ Pack\ the\ '.fRfile'\ widgets.\n\npack\ \ .fRfile.labelFILE\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\npack\ .fRfile.entFILENAME\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 1\n\npack\ \ .fRfile.buttBROWSE\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\n\n##+#########################################\n##\ In\ FRAME\ '.fRbuttons'\ -\n##\ DEFINE-and-PACK\ 7\ 'BUTTON'\ WIDGETS\n##\ ---\ and\ a\ label\ widget.\n##+#########################################\n\nbutton\ .fRbuttons.buttEXIT\ \\\n\ \ \ -text\ \"Exit\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{exit\}\n\nbutton\ .fRbuttons.buttHELP\ \\\n\ \ \ -text\ \"Help\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{popup_msg_var\ \"\$HELPtext\"\}\n\nbutton\ .fRbuttons.buttREMOVEIMG\ \\\n\ \ \ -text\ \"RemoveImg\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{.fRcanvas.can\ delete\ TAGimg\ \;\ image\ delete\ imgID1\}\n\nbutton\ .fRbuttons.buttREMOVELINES\ \\\n\ \ \ -text\ \"RemoveLines\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{remove_all_lines\}\n\nbutton\ .fRbuttons.buttRAISELINES\ \\\n\ \ \ -text\ \"RaiseLines\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \{.fRcanvas.can\ raise\ TAGlines\}\n\nbutton\ .fRbuttons.buttCOLOR1\ \\\n\ \ \ -text\ \"\\\nNext\ Line\n\ Color\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \"set_line_color1\"\n\nbutton\ .fRbuttons.buttCOLORbkGND\ \\\n\ \ \ -text\ \"\\\nBackground\nColor\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -padx\ \$PADXpx_button\ \\\n\ \ \ -pady\ \$PADYpx_button\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -command\ \"set_background_color\"\n\n\nlabel\ .fRbuttons.labelCOLORS\ \\\n\ \ \ -text\ \"\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\n\n##+##################################################\n##\ Pack\ the\ widgets\ in\ the\ '.fRbuttons'\ frame.\n##+##################################################\n\npack\ .fRbuttons.buttEXIT\ \\\n\ \ \ \ \ .fRbuttons.buttHELP\ \\\n\ \ \ \ \ .fRbuttons.buttREMOVEIMG\ \\\n\ \ \ \ \ .fRbuttons.buttREMOVELINES\ \\\n\ \ \ \ \ .fRbuttons.buttRAISELINES\ \\\n\ \ \ \ \ .fRbuttons.buttCOLOR1\ \\\n\ \ \ \ \ .fRbuttons.buttCOLORbkGND\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\n\npack\ .fRbuttons.labelCOLORS\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 0\n\n\n##+#########################################\n##\ In\ FRAME\ '.fRstatus'\ -\n##\ DEFINE-and-PACK\ \ 1\ CHECKBUTTON\ WIDGET\n##\ and\ 4\ 'LABEL'\ WIDGETS.\n##+#########################################\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ smooth0or1\ 1\n\ncheckbutton\ .fRstatus.chkbuttSMOOTH\ \\\n\ \ \ -text\ \"\\\nMake\ curves\ between\n\ points\ in\ the\ next\ line.\"\ \\\n\ \ \ -font\ \ fontTEMP_varwidth\ \\\n\ \ \ -variable\ smooth0or1\ \\\n\ \ \ -selectcolor\ \"#cccccc\"\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nlabel\ .fRstatus.label4COUNTobj\ \\\n\ \ \ -text\ \"\ \ \ Lines\ (incl.\ single-point\ lines)\ currently\ in\ drawing:\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\nlabel\ .fRstatus.labelCOUNTobj\ \\\n\ \ \ -text\ \"\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\ \\\n\ \ \ -padx\ 20\n\nlabel\ .fRstatus.label4COUNTpoints\ \\\n\ \ \ -text\ \"Points\ in\ last-created\ line:\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\nlabel\ .fRstatus.labelCOUNTpoints\ \\\n\ \ \ -text\ \"\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\ \\\n\ \ \ -padx\ 20\n\n##\ Pack\ the\ widgets\ in\ frame\ '.fRstatus'.\n\npack\ .fRstatus.chkbuttSMOOTH\ \\\n\ \ \ \ \ .fRstatus.label4COUNTobj\ \\\n\ \ \ \ \ .fRstatus.labelCOUNTobj\ \\\n\ \ \ \ \ .fRstatus.label4COUNTpoints\ \\\n\ \ \ \ \ .fRstatus.labelCOUNTpoints\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\n\n##+#########################################\n##\ In\ FRAME\ '.fRcontrols1'\ -\n##\ DEFINE-and-PACK\ 2\ 'SCALE'\ WIDGETS\n##\ ---\ with\ their\ label\ widgets.\n##\ \ \ (One\ scale\ for\ setting\ the\ 'next'\n##\ \ \ \ line-width.\n##\ \ \ \ One\ scale\ for\ setting\ the\n##\ \ \ \ millisecs\ var\ to\ control\ 'jitter'\n##\ \ \ \ or\ straightness\ of\ next\ line.)\n##+########################################\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ lineWIDTHpx\ 2\n\n##\ Define\ a\ label\ widget\ for\ the\ lineWIDTHpx\ scale\ widget.\n\nlabel\ .fRcontrols1.labelLINEWIDTH\ \\\n\ \ \ -text\ \"\\\nWidth\ (pixels)\ for\n\ the\ next\ line:\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\nscale\ .fRcontrols1.scaleLINEWIDTH\ \\\n\ \ \ -orient\ horizontal\ \\\n\ \ \ -resolution\ 1\ \\\n\ \ \ -from\ 1\ -to\ 100\ \\\n\ \ \ -length\ \$initScaleLengthPx\ \\\n\ \ \ -variable\ lineWIDTHpx\n\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ Nmillisecs\ 2\n\n##\ Define\ a\ label\ widget\ for\ the\ Nmillisecs\ scale\ widget.\n\nlabel\ .fRcontrols1.labelMILLISECS\ \\\n\ \ \ -text\ \"\\\nMillisecs\ tween\ adding\n\ points\ to\ next\ line:\"\ \\\n\ \ \ -font\ fontTEMP_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\nscale\ .fRcontrols1.scaleMILLISECS\ \\\n\ \ \ -orient\ horizontal\ \\\n\ \ \ -resolution\ 1\ \\\n\ \ \ -from\ 0\ -to\ 2000\ \\\n\ \ \ -length\ \$initScaleLengthPx\ \\\n\ \ \ -variable\ Nmillisecs\n\n\nlabel\ .fRcontrols1.labelMILLISECShelp\ \\\n\ \ \ -text\ \"\\\nSet\ millisecs\ high\ (>\ 700)\ to\n\ help\ draw\ straight\ lines.\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\n\n##\ PACK\ the\ widgets\ of\ FRAME\ '.fRcontrols1'\ ---\n##\ label,\ scale,\ label,\ scale,\ label.\n##\n##\ We\ use\ '-expand\ 1'\ in\ packing\ the\ scale\ widgets,\n##\ to\ allow\ them\ to\ x-expand\ if\ window\ is\ x-expanded.\n##\ That\ action\ depends\ on\ the\ pack\ parameters\ of\n##\ frame\ '.fRcontrols1'.\n\npack\ .fRcontrols1.labelLINEWIDTH\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\npack\ .fRcontrols1.scaleLINEWIDTH\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 1\n\npack\ .fRcontrols1.labelMILLISECS\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\npack\ .fRcontrols1.scaleMILLISECS\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ x\ \\\n\ \ \ -expand\ 1\n\npack\ .fRcontrols1.labelMILLISECShelp\ \\\n\ \ \ -side\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -fill\ none\ \\\n\ \ \ -expand\ 0\n\n\n##+#########################################\n##\ In\ FRAME\ '.fRcontrols2'\ -\n##\ DEFINE-and-PACK\ 1\ 'CHECKBUTTON'\ WIDGET\n##\ and\ 1\ LABEL\ and\ 3\ RADIOBUTTONS,\n##\ and\ 1\ more\ LABEL\ and\ 3\ more\ RADIOBUTTONS.\n##\ \ \ (One\ checkbutton\ for\ turning\ on/off\n##\ \ \ \ the\ 'smooth'\ option\ of\ 'create\ line'.\n##\ \ \ \ Radiobuttons\ for\ setting\ 'cap'\ and\n##\ \ \ \ 'join'\ styles\ of\ 'create\ line'.)\n##+########################################\n\n\nlabel\ .fRcontrols2.labelCAPSTYLE\ \\\n\ \ \ -text\ \"\\\nCap-style\ of\ line-segs:\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\n#\ set\ lineCAPstyle\ \"round\"\n##\ Line\ cap-style\ options:\ round/butt/projecting\n\nradiobutton\ \ .fRcontrols2.radbuttCAPSTYLE1\ \\\n\ \ \ -text\ \"round\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineCAPstyle\ \\\n\ \ \ -value\ \"round\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nradiobutton\ \ .fRcontrols2.radbuttCAPSTYLE2\ \\\n\ \ \ -text\ \"butt\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineCAPstyle\ \\\n\ \ \ -value\ \"butt\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nradiobutton\ \ .fRcontrols2.radbuttCAPSTYLE3\ \\\n\ \ \ -text\ \"projecting\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineCAPstyle\ \\\n\ \ \ -value\ \"projecting\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\ \\\n\ \ \ -padx\ 20\n\n\nlabel\ .fRcontrols2.labelJOINSTYLE\ \\\n\ \ \ -text\ \"\\\nJoin-style\ of\ line-segs:\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -justify\ left\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -bd\ \$BDwidthPx_label\n\n##\ We\ initialize\ this\ widget\ var\ (and\ others)\n##\ in\ the\ GUI\ initialization\ section\ at\ the\n##\ bottom\ of\ this\ script.\nset\ lineJOINstyle\ \"round\"\n##\ Line\ join-style\ options:\ round/bevel/miter\n\nradiobutton\ \ .fRcontrols2.radbuttJOINSTYLE1\ \\\n\ \ \ -text\ \"round\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineJOINstyle\ \\\n\ \ \ -value\ \"round\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nradiobutton\ \ .fRcontrols2.radbuttJOINSTYLE2\ \\\n\ \ \ -text\ \"bevel\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineJOINstyle\ \\\n\ \ \ -value\ \"bevel\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\nradiobutton\ \ .fRcontrols2.radbuttJOINSTYLE3\ \\\n\ \ \ -text\ \"miter\"\ \\\n\ \ \ -font\ fontTEMP_SMALL_varwidth\ \\\n\ \ \ -anchor\ w\ \\\n\ \ \ -variable\ lineJOINstyle\ \\\n\ \ \ -value\ \"miter\"\ \\\n\ \ \ -selectcolor\ \"\$radbuttBKGD\"\ \\\n\ \ \ -relief\ flat\ \\\n\ \ \ -bd\ \$BDwidthPx_button\n\n##\ PACK\ the\ widgets\ of\ FRAME\ '.fRcontrols2'\ ---\n##\ checkbutton,\ label,\ 3\ radiobuttons,\ label,\ 3\ radiobuttons.\n\npack\ .fRcontrols2.labelCAPSTYLE\ \\\n\ \ \ \ \ .fRcontrols2.radbuttCAPSTYLE1\ \\\n\ \ \ \ \ .fRcontrols2.radbuttCAPSTYLE2\ \\\n\ \ \ \ \ .fRcontrols2.radbuttCAPSTYLE3\ \\\n\ \ \ \ \ .fRcontrols2.labelJOINSTYLE\ \\\n\ \ \ \ \ .fRcontrols2.radbuttJOINSTYLE1\ \\\n\ \ \ \ \ .fRcontrols2.radbuttJOINSTYLE2\ \\\n\ \ \ \ \ .fRcontrols2.radbuttJOINSTYLE3\ \\\n\ \ \ \ \ \ -side\ left\ \\\n\ \ \ \ \ \ -anchor\ w\ \\\n\ \ \ \ \ \ -fill\ none\ \\\n\ \ \ \ \ \ -expand\ 0\n\n\n##+###################################################\n##\ In\ FRAME\ '.fRcanvas'\ -\n##\ DEFINE-and-PACK\ a\ CANVAS\ WIDGET:\n##+###################################################\n##\ We\ set\ '-highlightthickness'\ and\ '-borderwidth'\ to\n##\ zero,\ to\ avoid\ covering\ some\ of\ the\ viewable\ area\n##\ of\ the\ canvas,\ as\ suggested\ on\ page\ 558\ of\ the\ 4th\n##\ edition\ of\ 'Practical\ Programming\ with\ Tcl\ and\ Tk'.\n##+###################################################\n\ncanvas\ .fRcanvas.can\ \\\n\ \ \ -width\ \$initCanWidthPx\ \\\n\ \ \ -height\ \$initCanHeightPx\ \\\n\ \ \ -relief\ raised\ \\\n\ \ \ -highlightthickness\ 0\ \\\n\ \ \ -borderwidth\ 0\n\npack\ .fRcanvas.can\ \\\n\ \ \ -side\ top\ \\\n\ \ \ -anchor\ nw\ \\\n\ \ \ -fill\ both\ \\\n\ \ \ -expand\ 1\n\n\n##+##################################################\n##\ END\ OF\ DEFINITION\ of\ the\ GUI\ widgets.\n##+##################################################\n##\ Start\ of\ BINDINGS,\ PROCS,\ Added-GUI-INIT\ sections.\n##+##################################################\n\n##+#######################################################################\n##+#######################################################################\n##\ \ BINDINGS\ SECTION:\n##\ \ \ -\ For\ MB1-release\ on\ the\ image-filename\ entry\ field,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ load\ the\ image\ onto\ the\ canvas.\n##\ \ \ -\ For\ Return-key\ press\ with\ text\ cursor\ in\ the\ image-filename\ entry\ field,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ load\ the\ image\ onto\ the\ canvas.\n##\n##\ \ \ -\ <ButtonPress-1>\ \ \ \ on\ canvas\ calls\ proc\ 'doodle_start'\n##\ \ \ -\ <Button1-Motion>\ \ \ on\ canvas\ calls\ proc\ 'doodle_continue'\n##\ \ \ -\ <ButtonRelease-1>\ \ on\ canvas\ calls\ proc\ 'doodle_end'\n##\n##\ \ \ -\ <ButtonRelease-3>\ \ on\ canvas\ calls\ proc\ 'doodle_delete'\n##\n##\ \ \ -\ <Control-ButtonPress-1>\ \ \ \ on\ canvas\ calls\ proc\ 'image_grab'\ (not\ needed?)\n##\ \ \ -\ <Control-Button1-Motion>\ \ \ on\ canvas\ calls\ proc\ 'image_move'\n##+#######################################################################\n\nbind\ .fRfile.entFILENAME\ <ButtonRelease-1>\ \ \{\n\ \ \ #\ image\ delete\ imgID1\ (not\ needed?)\n\ \ \ image\ create\ photo\ imgID1\ -file\ \"\$ENTRYfilename\"\n\ \ \ .fRcanvas.can\ create\ image\ 0\ 0\ -anchor\ nw\ -image\ imgID1\ -tag\ TAGimg\n\}\n\nbind\ .fRfile.entFILENAME\ <Return>\ \ \{\n\ \ \ #\ image\ delete\ imgID1\ (not\ needed?)\n\ \ \ image\ create\ photo\ imgID1\ -file\ \"\$ENTRYfilename\"\n\ \ \ .fRcanvas.can\ create\ image\ 0\ 0\ -anchor\ nw\ -image\ imgID1\ -tag\ TAGimg\n\}\n\nbind\ .fRcanvas.can\ <ButtonPress-1>\ \ \[list\ doodle_start\ %W\ %x\ %y\ \$COLOR1hex\]\n\nbind\ .fRcanvas.can\ <Button1-Motion>\ \{doodle_continue\ %W\ %x\ %y\}\n\nbind\ .fRcanvas.can\ <ButtonRelease-1>\ \{doodle_end\ %W\ %x\ %y\}\n\n##\ FOR\ DELETING\ LINES:\n##\ Suchenwirth\ used\ <Double-3>\ to\ delete\ 'all'\ from\ the\ canvas,\ with:\n##\ \ \ \ \ \ \ bind\ .fRcanvas.can\ <Double-3>\ \{%W\ delete\ all\}\n##\n##\ We\ give\ the\ user\ the\ opportunity\ to\ bail\ out\ of\ the\ delete,\ by\ moving\n##\ the\ mouse\ cursor\ off\ of\ the\ canvas\ before\ releasing\ button3.\n##\ And\ we\ only\ delete\ the\ line\ nearest\ the\ current\ cursor\ location.\n##\ (The\ 'doodle_delete'\ proc\ may\ need\ some\ improvement\ to\ make\ sure\n##\ \ that\ we\ delete\ precisely\ the\ line-segment\ desired.)\n\nbind\ .fRcanvas.can\ <ButtonRelease-3>\ \{doodle_delete\ %W\ %x\ %y\}\n\n\n##\ We\ could\ high-light\ (in\ orange,\ say)\ an\ item,\ to\ help\ the\ user\ when\n##\ they\ want\ to\ delete\ a\ line\ ...\ to\ make\ sure\ they\ delete\ the\ right\ one.\n##\ We\ would\ need\ to\ get\ the\ item's\ current\ color\ and\ restore\ it\ on\n##\ leaving\ the\ item.\n\n#\ .fRcanvas.can\ bind\ TAGlines\ <Button3-Enter>\ \\\n#\ \ \ \"Put\ the\ item's\ current\ color\ in\ \$prevCOLOR,\ then\ do\n#\ \ \ .fRcanvas.can\ itemconfig\ current\ -fill\ #ffaa00\"\n\n#\ .fRcanvas.can\ bind\ TAGlines\ <Button3-Leave>\ \\\n#\ \ \ \ \".fRcanvas.can\ itemconfig\ current\ -fill\ \$prevCOLOR\"\n\n\n##\ Provide\ a\ way\ to\ move\ the\ IMAGE\ on\ the\ canvas.\n\n#\ bind\ .fRcanvas.can\ <ButtonPress-2>\ \ \ \{image_grab\ %W\ %x\ %y\}\ \ \ (not\ needed?)\n\nbind\ .fRcanvas.can\ <Button2-Motion>\ \ \{image_move\ %W\ %x\ %y\}\n\n\n##+#############################################################################\n##+#############################################################################\n##\ DEFINE\ PROCS\ SECTION:\n##\n##\ \ \ \ -\ 'get_img_filename'\ \ \ \ \ \ -\ gets\ the\ filename\ of\ an\ image\ (GIF/PNG)\ file\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ and\ places\ the\ image\ on\ the\ canvas\n##\n##\ \ \ \ -\ 'get_chars_before_last'\ -\ used\ in\ 'get_img_filename'\ to\ set\ curDIR\n##\n##\ \ \ \ -\ 'doodle_start'\ \ \ \ \ \ \ \ \ \ -\ start\ drawing\ a\ freehand\ line\n##\ \ \ \ -\ 'doodle_continue'\ \ \ \ \ \ \ -\ continue\ drawing\ the\ 'current'\ freehand\ line\n##\ \ \ \ -\ 'doodle_end'\ \ \ \ \ \ \ \ \ \ \ \ -\ stop\ drawing\ the\ 'current'\ freehand\ line\n##\ \ \ \ -\ 'doodle_delete'\ \ \ \ \ \ \ \ \ -\ delete\ a\ 'closest'\ line\n##\n##\ \ \ \ -\ 'image_grab'\ \ \ \ \ \ \ \ \ \ \ \ -\ grab\ the\ image\ \ (not\ needed?)\n##\ \ \ \ -\ 'image_move'\ \ \ \ \ \ \ \ \ \ \ \ -\ move\ the\ image\n##\n##\ \ \ \ -\ 'set_line_color1'\ \ \ \ \ \ \ -\ set\ the\ 'fill'\ color\ for\ drawing\ the\ next\ line\n##\ \ \ \ -\ 'set_background_color'\ \ -\ set\ the\ background\ (canvas)\ color\n##\ \ \ \ -\ 'update_colors_label'\ \ \ -\ updates\ the\ colors\ in\ the\ label\ widget\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '.fRbuttons.labelCOLORS'.\n##\ \ \ \ -\ 'remove_all_lines'\ \ \ \ \ \ -\ removes\ all\ lines\ &\ points\ from\ the\ canvas\n##\n##\ \ \ \ -\ 'popup_msg_var'\ \ \ \ \ \ \ \ \ -\ to\ show\ help,\ and\ to\ show\ other\ msgs\ as\ needed\n##+############################################################################\n\n\n##+#########################################################################\n##\ Proc\ 'get_img_filename'\ -\n##\n##\ PURPOSE:\ To\ get\ the\ name\ of\ an\ image\ file\ (GIF/PNG)\ and\ put\ the\n##\ \ \ \ \ \ \ \ \ \ filename\ into\ global\ var\ 'ENTRYfilename'.\n##\ \ \ \ \ \ \ \ \ \ Also,\ go\ ahead\ and\ load\ the\ image\ onto\ the\ canvas.\n##\n##\ USED\ BY:\ the\ '-command'\ option\ of\ the\ 'Browse\ ...'\ button.\n##+#########################################################################\n\n#\ set\ curDIR\ \"\$env(HOME)\"\n\n##\ FOR\ TESTING:\n\ \ set\ curDIR\ \"pwd\"\n\nproc\ get_img_filename\ \{\}\ \{\n\n\ \ \ global\ ENTRYfilename\ env\ curDIR\n\ \ \ #\ global\ imgID1\n\n\ \ \ ##\ Provide\ the\ user\ a\ way\ to\ select\ an\ image\ file.\n\n\ \ \ set\ fName\ \[tk_getOpenFile\ -parent\ .\ -title\ \"Select\ GIF/PNG\ file\ to\ load\"\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ -initialdir\ \"\$curDIR\"\ \]\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ puts\ \"fName\ :\ \$fName\"\n\n\ \ \ ##\ Load\ the\ image\ file\ contents\ onto\ the\ canvas.\n\ \ \ ##\ (Since\ there\ is\ only\ one\ image\ on\ the\ canvas\ at\ any\ time,\ we\ will\n\ \ \ ##\ \ always\ use\ the\ string\ 'imgID1'\ as\ the\ image\ ID\ in\ this\ script.)\n\n\ \ \ if\ \{\[file\ exists\ \$fName\]\}\ \{\n\n\ \ \ \ \ \ set\ ENTRYfilename\ \"\$fName\"\n\ \ \ \ \ \ set\ curDIR\ \[\ get_chars_before_last\ /\ in\ \"\$ENTRYfilename\"\ \]\n\n\ \ \ \ \ \ #\ catch\ \{\ image\ delete\ imgID1\ \}\ (not\ needed?)\n\n\ \ \ \ \ \ image\ create\ photo\ imgID1\ -file\ \"\$ENTRYfilename\"\n\n\ \ \ \ \ \ ##\ Place\ the\ image\ on\ the\ canvas.\n\ \ \ \ \ \ .fRcanvas.can\ create\ image\ 0\ 0\ -anchor\ nw\ -image\ imgID1\ -tag\ TAGimg\n\n\ \ \ \ \ \ ##\ Set\ the\ canvas\ size\ according\ to\ the\ size\ of\ the\ image.\n\ \ \ \ \ \ set\ imgWidthPx\ \ \[image\ width\ \ imgID1\]\n\ \ \ \ \ \ set\ imgHeightPx\ \[image\ height\ imgID1\]\n\ \ \ \ \ \ .fRcanvas.can\ configure\ -width\ \$imgWidthPx\ -height\ \$imgHeightPx\n\n\ \ \ \ \ \ ##\ FOR\ TESTING:\n\ \ \ \ \ \ #\ \ \ puts\ \"get_img_filename\ >\ imgWidthPx:\ \$imgWidthPx\ \ \ imgHeightPx:\ \$imgHeightPx\"\n\n\ \ \ \ \ \ ##\ Force\ the\ resizing\ of\ the\ canvas,\ esp.\ if\ a\ new\ image\ is\n\ \ \ \ \ \ ##\ loaded\ that\ is\ taller\ than\ the\ previous\ image.\n\ \ \ \ \ \ pack\ forget\ .fRcanvas.can\n\ \ \ \ \ \ pack\ .fRcanvas.can\ \\\n\ \ \ \ \ \ \ \ \ -side\ top\ \\\n\ \ \ \ \ \ \ \ \ -anchor\ nw\ \\\n\ \ \ \ \ \ \ \ \ -fill\ both\ \\\n\ \ \ \ \ \ \ \ \ -expand\ 1\n\n\ \ \ \ \ \ ##\ We\ could\ automatically\ raise\ any\ lines\ already\ drawn\n\ \ \ \ \ \ ##\ so\ that\ they\ are\ not\ hidden\ by\ the\ newly\ loaded\ image.\n\n\ \ \ \ \ \ #\ catch\ \{.fRcanvas.can\ raise\ TAGlines\}\n\n\ \ \ \}\n\}\n##\ END\ OF\ proc\ 'get_img_filename'\n\n\n##+######################################################################\n##\ Proc\ 'get_chars_before_last'\ -\n##+######################################################################\n##\ PURPOSE:\ Gets\ the\ chars\ before\ the\ last\ occurrence\ of\ a\ char\ in\ a\ string.\n##\n##\ INPUT:\ \ A\ character\ and\ a\ string.\n##\ \ \ \ \ \ \ \ \ Note:\ The\ \"in\"\ parameter\ is\ there\ only\ for\ clarity.\n##\n##\ OUTPUT:\ Returns\ all\ of\ the\ characters\ in\ the\ string\ \"strng\"\ that\n##\ \ \ \ \ \ \ \ \ are\ BEFORE\ the\ last\ occurence\ of\ the\ characater\ \"char\".\n##\n##\ EXAMPLE\ CALL:\ To\ extract\ the\ directory\ from\ a\ fully\ qualified\ file\ name:\n##\n##\ set\ directory\ \[\ get_chars_before_last\ \"/\"\ in\ \"/home/abc01/junkfile\"\ \]\n##\n##\ \ \ \ \ \ \$directory\ will\ now\ be\ the\ string\ \"/home/abc01\"\n##\n##+######################################################################\n\nproc\ get_chars_before_last\ \{\ char\ in\ strng\ \}\ \{\n\n\ \ \ set\ end\ \[\ expr\ \{\[string\ last\ \$char\ \$strng\ \]\ -\ 1\}\ \]\n\ \ \ #\ set\ start\ 0\n\ \ \ #\ set\ output\ \[\ string\ range\ \$strng\ \$start\ \$end\ \]\n\ \ \ set\ output\ \[\ string\ range\ \$strng\ 0\ \$end\ \]\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ puts\ \"From\ 'get_chars_before_last'\ proc:\"\n\ \ \ #\ puts\ \"STRING:\ \$strng\"\n\ \ \ #\ puts\ \"CHAR:\ \$char\"\n\ \ \ #\ puts\ \"RANGE\ up\ to\ LAST\ CHAR\ -\ start:\ 0\ \ \ end:\ \$end\"\n\n\ \ \ return\ \$output\n\n\}\n##\ END\ OF\ 'get_chars_before_last'\ PROCEDURE\n\n\n##+#########################################################\n##\ proc\ doodle_start\n##+#########################################################\n##\ PURPOSE:\ Start\ a\ line\ using\ the\ 'create\ line'\ command\n##\ \ \ \ \ \ \ \ \ \ on\ the\ canvas.\ Draws\ an\ 'invisible'\ point.\n##\n##\ \ \ \ \ \ \ \ \ \ Also\ increments\ Nobj\ and\ sets\ NcurPoints\ to\ zero\n##\ \ \ \ \ \ \ \ \ \ and\ calls\ proc\ 'update_status_labels'.\n##\n##\ NOTE:\ Provides\ '-fill'\ ,\ '-width'\ ,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '-smooth'\ \ '-splinesteps'\ ,\n##\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '-capstyle'\ ,\ '-joinstyle'\ ,\ and\ '-tag'\n##\ \ \ \ \ \ \ option\ to\ 'create\ line'.\n##\n##\ CALLED\ BY:\ bind\ .fRcanvas.can\ <ButtonPress-1>\n##+#########################################################\n##\ We\ store\ the\ line-IDs\ in\ an\ array\ variable,\ aRlineIDs,\n##\ and\ keep\ our\ own\ count\ of\ the\ lines.\ The\ line\ count\n##\ and\ the\ array\ variable\ do\ not\ seem\ to\ be\ necessary\ at\n##\ this\ time,\ but\ they\ may\ be\ useful\ for\ future\ enhancements.\n##+#########################################################\n\nset\ curObjID_CNT\ 1\n\n##\ Initialize\ initX\ and\ initY\ for\ use\ in\ procs\n##\ 'doodle_start'\ and\ 'doodle_end'.\nset\ initX\ -1\nset\ initY\ -1\n\nproc\ doodle_start\ \{w\ x\ y\ color\}\ \{\n\n\ \ \ global\ aRlineIDs\ curObjID_CNT\ COLOR1hex\ lineWIDTHpx\ \\\n\ \ \ \ \ \ \ \ \ smooth0or1\ lineCAPstyle\ lineJOINstyle\ \\\n\ \ \ \ \ \ \ \ \ Nobj\ NcurPoints\ initX\ initY\n\n\ \ \ ##\ Map\ from\ view\ coordinates\ to\ canvas\ coordinates,\ per\n\ \ \ ##\ page\ 559\ of\ 4th\ edition\ of\ 'Practical\ Programming\ in\ Tcl\ &\ Tk'.\n\ \ \ set\ x\ \[\$w\ canvasx\ \$x\]\n\ \ \ set\ y\ \[\$w\ canvasx\ \$y\]\n\n\ \ \ ##\ Initialize\ the\ line\ for\ the\ current\ line-count.\n\ \ \ ##\ (We\ store\ a\ separate\ line-ID\ for\ each\ doodle\n\ \ \ ##\ \ line,\ in\ array\ item\ aRlineIDs(\$curObjID_CNT).\ This\ could\n\ \ \ ##\ \ be\ useful,\ for\ example,\ if\ we\ ever\ want\ to\ click\ a\n\ \ \ ##\ \ button\ on\ the\ GUI\ and\ show\ the\ current\ number\ of\n\ \ \ ##\ \ lines\ in\ the\ sketch.\ We\ would\ to\ keep\ track\ of\n\ \ \ ##\ \ deleted\ lines\ in\ that\ case.\ See\ the\ doodle_delete'\n\ \ \ ##\ \ proc\ below.)\n\ \ \ ##\n\ \ \ ##\ Note:\ The\ start\ and\ end\ point\ of\ the\ line\ is\ the\ same.\n\ \ \ ##\ \ \ \ \ \ \ Under\ certain\ conditions\ (not\ clear\ to\ me\ yet),\n\ \ \ ##\ \ \ \ \ \ \ Tk's\ 'create\ line'\ will\ not\ draw\ a\ point\ on\ the\n\ \ \ ##\ \ \ \ \ \ \ canvas\ unless\ the\ 2nd\ point\ is\ different\ from\n\ \ \ ##\ \ \ \ \ \ \ the\ first\ point.\ So\ this\ initial\ point\ may\ be\n\ \ \ ##\ \ \ \ \ \ \ 'invisible'.\n\ \ \ ##\ \ \ \ \ \ \ See\ the\ 'doodle_end'\ proc.\ There\ we\ could\ make\ the\n\ \ \ ##\ \ \ \ \ \ \ point\ visible,\ if\ only\ the\ initial\ xy\ points\ were\n\ \ \ ##\ \ \ \ \ \ \ in\ this\ 'doodle\ object'.\n\n\ \ \ set\ aRlineIDs(\$curObjID_CNT)\ \[\$w\ create\ line\ \\\n\ \ \ \ \ \ \ \$x\ \$y\ \$x\ \$y\ \\\n\ \ \ \ \ \ \ -fill\ \$COLOR1hex\ -width\ \$lineWIDTHpx\ \\\n\ \ \ \ \ \ \ -smooth\ \$smooth0or1\ \ \\\n\ \ \ \ \ \ \ -capstyle\ \$lineCAPstyle\ -joinstyle\ \$lineJOINstyle\ -tag\ TAGlines\]\n\n\ \ \ ##\ -splinesteps\ 1\n\n\ \ \ set\ initX\ \$x\n\ \ \ set\ initY\ \$y\n\n\ \ \ ##\ capstyles:\ butt,\ projecting,\ round\n\ \ \ ##\ joinstyles:\ bevel,\ miter,\ round\n\ \ \ ##\ Turning\ on\ '-smooth'\ seems\ to\ give\ nicer\ lines.\n\ \ \ ##\ '-splinesteps'\ may\ be\ helpful\ too.\ (best\ value?\ default\ value?\n\ \ \ ##\ hard-code\ it\ OR\ prompt\ for\ it?)\n\n\ \ \ ##\ NOTE1:\ \"If\ the\ smoothing\ method\ is\ 'true'\ (1),\ this\ indicates\ that\ the\n\ \ \ ##\ line\ should\ be\ drawn\ as\ a\ curve,\ rendered\ as\ a\ set\ of\ quadratic\n\ \ \ ##\ splines:\ one\ spline\ is\ drawn\ for\ the\ first\ and\ second\ line\ segments,\n\ \ \ ##\ one\ for\ the\ second\ and\ third,\ and\ so\ on.\"\n\ \ \ ##\ \"If\ a\ boolean\ false\ value\ or\ empty\ string\ is\ given,\ no\ smoothing\ is\n\ \ \ ##\ applied.\"\n\ \ \ ##\ NOTE2:\ \"'-splinesteps'\ specifies\ the\ degree\ of\ smoothness\ desired\n\ \ \ ##\ for\ curves:\ each\ spline\ will\ be\ approximated\ with\ that\ number\ of\n\ \ \ ##\ line\ segments.\"\n\ \ \ ##\ SOURCE\ of\ notes\ 1\ &\ 2:\ Tcl-Tk\ 8.5.5\ documentation.\n\n\ \ \ ##\ Increment\ the\ objects-in-drawing\ count.\n\ \ \ incr\ Nobj\n\n\ \ \ ##\ Reset\ the\ number-of-points-in-current-line\ counter.\n\ \ \ set\ NcurPoints\ 1\n\ \ \ update_status_labels\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ puts\ \"doodle_start\ >\ \ curObjID_CNT:\ \$curObjID_CNT\ \\\n\ \ \ #\ \ \ \ \ \ \ \ \ aRlineIDs(\$curObjID_CNT):\ \$aRlineIDs(\$curObjID_CNT)\"\n\}\n##\ END\ OF\ proc\ doodle_start\n\n\n##+#########################################################\n##\ proc\ doodle_continue\n##+#########################################################\n##\ PURPOSE:\ Adds\ the\ current\ x,y\ point\ to\ the\ currently\n##\ \ \ \ \ \ \ \ \ \ in-process\ line\ ---\ after\ a\ delay\ of\ Nmillisecs.\n##\ \ \ \ \ \ \ \ \ \ Also\ increments\ NcurPoints\ and\ calls\ proc\n##\ \ \ \ \ \ \ \ \ \ 'update_status_labels'.\n##\n##\ CALLED\ BY:\ bind\ .fRcanvas.can\ <Button1-Motion>\n##+#########################################################\n\nproc\ doodle_continue\ \{w\ x\ y\}\ \{\n\n\ \ \ global\ aRlineIDs\ curObjID_CNT\ Nmillisecs\ NcurPoints\n\n\ \ \ ##\ Wait\ Nmillisecs.\ (This\ is\ to\ help\ user\ make\ straight\ lines.\n\ \ \ ##\ It\ can\ reduce\ 'jitter'\ in\ lines,\ by\ reducing\ the\ number\ of\n\ \ \ ##\ 'control\ points'\ in\ the\ line.)\n\ \ \ after\ \$Nmillisecs\n\n\ \ \ ##\ Map\ from\ view\ coordinates\ to\ canvas\ coordinates,\ per\n\ \ \ ##\ page\ 559\ of\ 4th\ edition\ of\ 'Practical\ Programming\ in\ Tcl\ &\ Tk'.\n\ \ \ set\ x\ \[\$w\ canvasx\ \$x\]\n\ \ \ set\ y\ \[\$w\ canvasx\ \$y\]\n\n\ \ \ ##\ Add\ an\ end-point\ to\ the\ line\ for\ the\ current\ line-count.\n\ \ \ ##\ (We\ do\ this\ by\ getting\ the\ xy\ coords\ for\ ALL\ the\ points\ of\n\ \ \ ##\ \ the\ currently-being-drawn-line\ and\ concatenating\ the\n\ \ \ ##\ \ new\ point.\ Then\ use\ 'coords'\ to\ reset\ the\ coordinates.)\n\ \ \ ##\ This\ is\ what\ Suchenwirth\ did\ in\ his\ 'doodle_move'\ proc.\n\n\ \ \ \$w\ coords\ \$aRlineIDs(\$curObjID_CNT)\ \\\n\ \ \ \ \ \ \ \ \ \[concat\ \[\$w\ coords\ \$aRlineIDs(\$curObjID_CNT)\]\ \$x\ \$y\]\n\n\ \ \ ##\ Increment\ the\ number-of-points-in-current-line\ count.\n\ \ \ incr\ NcurPoints\n\ \ \ update_status_labels\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ puts\ \"doodle_continue\ >\ Adding\ point\ \$x\ \$y\"\n\n\}\n##\ END\ OF\ proc\ doodle_continue\n\n\n##+#################################################################\n##\ proc\ doodle_end\n##+#################################################################\n##\ PURPOSE:\ Increments\ var\ curObjID-CN\ that\ we\ are\ using\ to\ hold\n##\ \ \ \ \ \ \ \ \ \ a\ numeric\ ID\ for\ the\ next\ or\ current\ line.\n##\n##\ \ \ \ \ \ \ \ \ \ But\ before\ that\ ID\ is\ incremented,\ we\ test\ to\ see\ if\n##\ \ \ \ \ \ \ \ \ \ we\ are\ ending\ a\ line\ that\ consisted\ of\ just\ one,\n##\ \ \ \ \ \ \ \ \ \ not-drawn\ point.\ It\ that\ is\ the\ case,\ we\ draw\ the\ point.\n##\n##\ CALLED\ BY:\ \ bind\ .fRcanvas.can\ <ButtonRelease-1>\n##+################################################################\n\nproc\ doodle_end\ \{w\ x\ y\}\ \{\n\n\ \ \ global\ curObjID_CNT\ COLOR1hex\ lineWIDTHpx\ \\\n\ \ \ \ \ \ \ \ \ smooth0or1\ lineCAPstyle\ lineJOINstyle\ \\\n\ \ \ \ \ \ \ \ \ Nobj\ NcurPoints\ initX\ initY\n\ \ \ #\ global\ aRlineIDs\n\n\ \ \ ##\ If\ the\ current\ doodle-object\ has\ only\ the\ initial\ xy\n\ \ \ ##\ point\ in\ it\ and\ the\ point\ was\ not\ drawn\ (under\ certain\n\ \ \ ##\ conditions\ not\ yet\ clear\ to\ me),\ then\ we\ could\ test\ for\n\ \ \ ##\ those\ conditions\ and\ draw\ a\ single\ point/blot.\n\n\ \ \ #\ if\ \{\ \$x\ ==\ \$initX\ &&\ \$y\ ==\ \$initY\ &&\ \$NcurPoints\ ==\ 1\ \ &&\ \\\n\ \ \ #\ \ \ \ \ \ ...\ other\ conditions\ go\ here\ ...\ \}\ \{\n\ \ \ #\n\ \ \ #\ \ \ set\ aRlineIDs(\$curObjID_CNT)\ \[\$w\ create\ line\ \\\n\ \ \ #\ \ \ \ \ \ \$x\ \$y\ \[expr\ \{\$x\ +\ 1\}\]\ \$y\ \\\n\ \ \ #\ \ \ \ \ \ -fill\ \$COLOR1hex\ -width\ \$lineWIDTHpx\ \\\n\ \ \ #\ \ \ \ \ \ -smooth\ \$smooth0or1\ \ \ -splinesteps\ 4\ \\\n\ \ \ #\ \ \ \ \ \ -capstyle\ \$lineCAPstyle\ -joinstyle\ \$lineJOINstyle\ -tag\ TAGlines\]\n\ \ \ #\ \}\n\n\ \ \ ##\ Advance\ the\ line\ count\ so\ that\ the\ next\ 'doodle_start'\n\ \ \ ##\ stores\ the\ new\ line-ID\ in\ a\ different\ lineID\ array\ location.\n\ \ \ incr\ curObjID_CNT\n\n\ \ \ set\ initX\ -1\n\ \ \ set\ initY\ -1\n\n\}\n##\ END\ OF\ proc\ doodle_end\n\n\n##+##################################################################\n##\ proc\ doodle_delete\n##+##################################################################\n##\ PURPOSE:\ Deletes\ a\ line\ object\ nearest\ the\ current\ cursor\ position,\n##\ \ \ \ \ \ \ \ \ \ and\ decrements\ Nobj\ and\ sets\ NcurPoints\ to\ 0\ and\n##\ \ \ \ \ \ \ \ \ \ calls\ proc\ 'update_status_labels'.\n##\n##\ CALLED\ BY:\ \ bind\ .fRcanvas.can\ <ButtonRelease-3>\n##+##################################################################\n##\ NOTE:\n##\ We\ need\ a\ good\ delete-segment\ capability,\ because\n##\ it\ is\ hard\ to\ sketch\ the\ line\ segments\n##\ exactly\ where\ we\ want\ them\ with\ the\ mouse\n##\ ---\ for\ every\ segment,\ the\ first\ time,\ every\ time.\n##+#########################################################\n\nset\ pixelTol\ 3\n\nproc\ doodle_delete\ \{w\ x\ y\}\ \{\n\n\ \ \ global\ pixelTol\ Nobj\ NcurPoints\n\n\ \ \ ##\ See\ note\ below\ on\ aRlineIDs\ and\ '-1'.\n\ \ \ #\ global\ aRlineIDs\n\n\ \ \ ##\ Map\ from\ view\ coordinates\ to\ canvas\ coordinates,\ per\n\ \ \ ##\ page\ 559\ of\ 4th\ edition\ of\ 'Practical\ Programming\ in\ Tcl\ &\ Tk'.\n\ \ \ set\ x\ \[\$w\ canvasx\ \$x\]\n\ \ \ set\ y\ \[\$w\ canvasx\ \$y\]\n\n\ \ \ ##\ Find\ canvas\ object\ nearest\ \$x\ \$y.\ This\ returns\ the\ 'last\ one'\n\ \ \ ##\ (uppermost)\ in\ the\ display\ list.\n\n\ \ \ set\ objID\ \[\$w\ find\ closest\ \$x\ \$y\ \$pixelTol\]\n\n\ \ \ ##\ We\ could\ popup\ a\ prompt\ to\ the\ user\ here\ indicating\ the\n\ \ \ ##\ item\ that\ will\ be\ deleted\ and\ ask\ the\ user\ if\ it\ is\ OK\n\ \ \ ##\ to\ do\ the\ delete.\n\n\ \ \ set\ objTAGs\ \[\$w\ gettags\ \$objID\]\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"'doodle_delete'\ >\ \ objID:\ \$objID\ \ \ objTAGs:\ \$objTAGs\"\n\n\ \ \ ##\ If\ objTAGs\ typically\ contains\ 'TAGlines\ current'\ when\ a\ line\ is\n\ \ \ ##\ detected\ by\ 'closest',\ and\ 'TAGimg\ current'\ when\ the\ image\ is\ detected.\n\n\ \ \ ##\ We\ make\ sure\ we\ delete\ a\ line\ and\ NOT\ an\ image\ on\ the\ canvas.\n\ \ \ if\ \{\ \$objTAGs\ ==\ \"TAGlines\ current\"\ ||\ \$objTAGs\ ==\ \"TAGlines\"\ \}\ \{\n\ \ \ \ \ \ \$w\ delete\ \$objID\n\n\ \ \ \ \ \ ##\ Decrement\ the\ number-of-objects-in-drawing\ count.\n\ \ \ \ \ \ incr\ Nobj\ -1\n\n\ \ \ \ \ \ ##\ Reset\ the\ number-of-points-in-current-line\ count.\n\ \ \ \ \ \ set\ NcurPoints\ 0\n\n\ \ \ \ \ \ update_status_labels\n\ \ \ \}\n\n\ \ \ ##\ We\ could\ find\ the\ objectID\ in\ the\ array\ aRlineIDs\n\ \ \ ##\ and,\ for\ that\ array\ index,\ reset\ the\ array\ to\ a\ value,\n\ \ \ ##\ like\ DEL\ or\ -1,\ that\ indicates\ the\ line\ (object)\ is\ deleted.\n\n\ \ \ #\ Search\ the\ array\ to\ find\ the\ index,\ idx,\ of\ the\ deleted\ object.\n\ \ \ #\ set\ aRlineIDs(\$idx)\ \"-1\"\n\n\}\n##\ END\ OF\ proc\ doodle_delete\n\n\n##+#########################################################\n##\ proc\ image_move\n##+#########################################################\n##\ PURPOSE:\ Moves\ the\ image\ on\ the\ canvas.\n##\n##\ CALLED\ BY:\ bind\ .fRcanvas.can\ <Button2-Motion>\n##+#########################################################\n\nproc\ image_move\ \{w\ x\ y\}\ \{\n\n\ \ \ ##\ Map\ from\ view\ coordinates\ to\ canvas\ coordinates,\ per\n\ \ \ ##\ page\ 559\ of\ 4th\ edition\ of\ 'Practical\ Programming\ in\ Tcl\ &\ Tk'.\n\ \ \ set\ x\ \[\$w\ canvasx\ \$x\]\n\ \ \ set\ y\ \[\$w\ canvasx\ \$y\]\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ set\ tempCoords\ \[\$w\ coords\ TAGimg\]\n\ \ \ #\ \ \ puts\ \"'image_move'\ >\ Current\ image\ coords:\ \$tempCoords\"\n\n\ \ \ ##\ Reset\ the\ location\ of\ the\ image\ on\ the\ canvas.\n\n\ \ \ \$w\ coords\ TAGimg\ \$x\ \$y\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"'image_move'\ >\ Moving\ image\ to\ \$x\ \$y\"\n\n\}\n##\ END\ OF\ proc\ image_move\n\n\n\n##+#####################################################################\n##\ proc\ 'set_line_color1'\n##+#####################################################################\ \n##\ PURPOSE:\ \ This\ procedure\ is\ invoked\ to\ get\ an\ RGB\ triplet\n##\ \ \ \ \ \ \ \ \ \ \ via\ 3\ RGB\ slider\ bars\ on\ the\ FE\ Color\ Selector\ GUI.\n##\n##\ \ \ \ \ \ \ \ \ \ \ Uses\ that\ RGB\ value\ to\ set\ a\ 'fill'\ color.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ \ .fRbuttons.buttCOLOR1\ \ button\n##+#####################################################################\n\nproc\ set_line_color1\ \{\}\ \{\n\n\ \ \ global\ COLOR1r\ COLOR1g\ COLOR1b\ COLOR1hex\ COLOR1r\ COLOR1g\ COLOR1b\n\ \ \ #\ global\ feDIR_tkguis\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"COLOR1r:\ \$COLOR1r\"\n\ \ \ #\ \ \ \ puts\ \"COLOR1g:\ \$COLOR1g\"\n\ \ \ #\ \ \ \ puts\ \"COLOR1b:\ \$COLOR1b\"\n\n\ \ \ set\ TEMPrgb\ \[\ exec\ \\\n\ \ \ \ \ \ \ ./sho_colorvals_via_sliders3rgb.tk\ \\\n\ \ \ \ \ \ \ \$COLOR1r\ \$COLOR1g\ \$COLOR1b\]\n\n\ \ \ #\ \ \ \$feDIR_tkguis/sho_colorvals_via_sliders3rgb.tk\ \\\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"TEMPrgb:\ \$TEMPrgb\"\n\n\ \ \ if\ \{\ \"\$TEMPrgb\"\ ==\ \"\"\ \}\ \{\ return\ \}\n\ \n\ \ \ scan\ \$TEMPrgb\ \"%s\ %s\ %s\ %s\"\ r255\ g255\ b255\ hexRGB\n\n\ \ \ set\ COLOR1hex\ \"#\$hexRGB\"\n\ \ \ set\ COLOR1r\ \$r255\n\ \ \ set\ COLOR1g\ \$g255\n\ \ \ set\ COLOR1b\ \$b255\n\n\ \ \ ##\ Update\ the\ colors-label.\n\n\ \ \ update_colors_label\n\n\}\n##\ END\ OF\ proc\ 'set_line_color1'\n\n\n##+#####################################################################\n##\ proc\ 'set_background_color'\n##+#####################################################################\ \n##\ PURPOSE:\ This\ procedure\ is\ invoked\ to\ get\ an\ RGB\ triplet\n##\ \ \ \ \ \ \ \ \ \ via\ 3\ RGB\ slider\ bars\ on\ the\ FE\ Color\ Selector\ GUI.\n##\n##\ \ \ \ \ \ \ \ \ \ Uses\ that\ RGB\ value\ to\ set\ the\ color\ of\ the\ canvas\ ---\n##\ \ \ \ \ \ \ \ \ \ on\ which\ all\ the\ tagged\ items\ (lines)\ lie.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ .fRbuttons.buttCOLORbkGND\ \ button\n##+#####################################################################\n\nproc\ set_background_color\ \{\}\ \{\n\n\ \ \ global\ COLORbkGNDr\ COLORbkGNDg\ COLORbkGNDb\ COLORbkGNDhex\ \\\n\ \ \ \ \ \ \ \ \ \ COLORbkGNDr\ COLORbkGNDg\ COLORbkGNDb\n\ \ \ #\ global\ feDIR_tkguis\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"COLORbkGNDr:\ \$COLORbkGNDr\"\n\ \ \ #\ \ \ \ puts\ \"COLORbkGNDg:\ \$COLORbkGNDb\"\n\ \ \ #\ \ \ \ puts\ \"COLORbkGNDb:\ \$COLORbkGNDb\"\n\n\ \ \ set\ TEMPrgb\ \[\ exec\ \\\n\ \ \ \ \ \ \ ./sho_colorvals_via_sliders3rgb.tk\ \\\n\ \ \ \ \ \ \ \$COLORbkGNDr\ \$COLORbkGNDg\ \$COLORbkGNDb\]\n\n\ \ \ #\ \ \ \$feDIR_tkguis/sho_colorvals_via_sliders3rgb.tk\ \\\n\n\ \ \ ##\ FOR\ TESTING:\n\ \ \ #\ \ \ \ puts\ \"TEMPrgb:\ \$TEMPrgb\"\n\n\ \ \ if\ \{\ \"\$TEMPrgb\"\ ==\ \"\"\ \}\ \{\ return\ \}\n\ \n\ \ \ scan\ \$TEMPrgb\ \"%s\ %s\ %s\ %s\"\ r255\ g255\ b255\ hexRGB\n\n\ \ \ set\ COLORbkGNDhex\ \"#\$hexRGB\"\n\ \ \ set\ COLORbkGNDr\ \$r255\n\ \ \ set\ COLORbkGNDg\ \$g255\n\ \ \ set\ COLORbkGNDb\ \$b255\n\n\ \ \ ##\ Set\ the\ color\ of\ the\ canvas.\n\n\ \ \ .fRcanvas.can\ config\ -bg\ \$COLORbkGNDhex\n\n\ \ \ ##\ Update\ the\ colors-label.\n\n\ \ \ update_colors_label\n\n\}\n##\ END\ OF\ proc\ 'set_background_color'\n\n\n##+#####################################################################\n##\ proc\ update_colors_label\n##+#####################################################################\ \n##\ PURPOSE:\ \ Updates\ the\ colors\ in\ the\ label\ widget\n##\ \ \ \ \ \ \ \ \ \ \ '.fRbuttons.labelCOLORS'.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ two\ color-setting\ procs\ and\ the\ GUI\ init\ section\ at\n##\ \ \ \ \ \ \ \ \ \ \ \ the\ bottom\ of\ this\ script.\n##+#####################################################################\n\nproc\ update_colors_label\ \{\}\ \{\n\n\ \ \ global\ COLOR1hex\ COLORbkGNDhex\n\n\ \ \ .fRbuttons.labelCOLORS\ configure\ -text\ \"\\\nColor\ for\ the\ next\ line:\ \ \$COLOR1hex\ \n\ Background\ Color:\ \ \$COLORbkGNDhex\"\n\n\}\n##\ END\ OF\ proc\ 'update_colors_label'\n\n\n##+#####################################################################\n##\ proc\ update_status_labels\n##+#####################################################################\ \n##\ PURPOSE:\ \ Updates\ the\ counts\ in\ the\ label\ widgets\n##\ \ \ \ \ \ \ \ \ \ \ '.fRstatus.labelCOUNTobj'\ and\ '.fRstatus.labelCOUNTpoints'.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ 'doodle_end',\ 'doodle_delete'\ procs\ and\ the\n##\ \ \ \ \ \ \ \ \ \ \ \ GUI\ init\ section\ at\ the\ bottom\ of\ this\ script.\n##+#####################################################################\n\nproc\ update_status_labels\ \{\}\ \{\n\n\ \ \ global\ Nobj\ NcurPoints\n\n\ \ \ .fRstatus.labelCOUNTobj\ configure\ -text\ \"\$Nobj\"\n\ \ \ .fRstatus.labelCOUNTpoints\ configure\ -text\ \"\$NcurPoints\"\n\n\}\n##\ END\ OF\ proc\ 'update_status_labels'\n\n\n##+#####################################################################\n##\ proc\ remove_all_lines\n##+#####################################################################\ \n##\ PURPOSE:\ \ Removes\ all\ objects\ (lines,\ 'degenerate\ lines'=points)\n##\ \ \ \ \ \ \ \ \ \ \ from\ the\ canvas\ and\ resets\ some\ counts\ accordingly.\n##\n##\ ARGUMENTS:\ none\n##\n##\ CALLED\ BY:\ 'doodle_end',\ 'doodle_delete'\ procs\ and\ the\n##\ \ \ \ \ \ \ \ \ \ \ \ GUI\ init\ section\ at\ the\ bottom\ of\ this\ script.\n##+#####################################################################\n\nproc\ remove_all_lines\ \{\}\ \{\n\n\ \ \ global\ Nobj\ NcurPoints\n\n\ \ \ .fRcanvas.can\ delete\ TAGlines\n\n\ \ \ set\ Nobj\ 0\n\ \ \ set\ NcurPoints\ 0\n\ \ \ update_status_labels\n\n\}\n##\ END\ OF\ proc\ 'remove_all_lines'\n\n\n##+########################################################################\n##\ \ 'popup_msg_var'\ PROCEDURE\ \n##+########################################################################\n##\ PURPOSE:\ Show\ help\ to\ the\ user.\n##\ \ \ \ \ \ \ \ \ (Could\ also\ be\ used\ to\ advise\ user\ of\ error\ conditions.)\n##\n##\ CALLED\ BY:\ '-command'\ option\ of\ the\ Help\ button\n##+########################################################################\n##\ To\ have\ more\ control\ over\ the\ formatting\ of\ the\ message\ (esp.\n##\ max\ length\ of\ lines),\ we\ use\ this\ 'toplevel-text'\ method,\ \n##\ rather\ than\ the\ 'tk_dialog'\ method\ --\ like\ on\ page\ 574\ of\ the\ book\ \n##\ by\ Hattie\ Schroeder\ &\ Mike\ Doyel,'Interactive\ Web\ Applications\n##\ with\ Tcl/Tk',\ Appendix\ A\ \"ED,\ the\ Tcl\ Code\ Editor\".\n##+########################################################################\n\nproc\ popup_msg_var\ \{\ VARtext\ \}\ \{\n\n\ \ \ ##\ global\ env\n\n\ \ \ #\ bell\n\ \ \ #\ bell\n\ \ \n\ \ \ #####################################\n\ \ \ ##\ SETUP\ 'TOP\ LEVEL'\ HELP\ WINDOW.\n\ \ \ #####################################\n\ \ \n\ \ \ set\ w\ .topmsg\n\n\ \ \ catch\ \{destroy\ \$w\}\n\ \ \ toplevel\ \ \$w\n\n\ \ \ wm\ geometry\ \$w\ +100+100\n\n\ \ \ wm\ title\ \ \ \ \ \$w\ \"To\ You\"\n\ \ \ wm\ iconname\ \ \$w\ \"ToYou\"\n\n\ \ \ #####################################\n\ \ \ ##\ DEFINE\ &\ PACK\ TEXT\ WIDGET.\n\ \ \ #####################################\n\n\ \ \ text\ \$w.text\ \\\n\ \ \ \ \ \ -relief\ raised\ \\\n\ \ \ \ \ \ -bd\ 2\ \\\n\ \ \ \ \ \ -font\ fontTEMP_fixedwidth\n\n\ \ \ pack\ \ \$w.text\ \\\n\ \ \ \ \ \ -side\ top\ \\\n\ \ \ \ \ \ -anchor\ center\ \\\n\ \ \ \ \ \ -fill\ both\ \\\n\ \ \ \ \ \ -expand\ 0\n\n\ \ \ #####################################\n\ \ \ ##\ DEFINE\ &\ PACK\ OK\ BUTTON\ WIDGET.\n\ \ \ #####################################\n\n\ \ \ button\ \$w.butt\ -text\ \"OK\"\ \\\n\ \ \ \ \ \ -font\ fontTEMP_fixedwidth\ -command\ \ \"destroy\ \$w\"\n\n\ \ \ pack\ \ \$w.butt\ \\\n\ \ \ \ \ \ -side\ bottom\ \\\n\ \ \ \ \ \ -anchor\ center\ \\\n\ \ \ \ \ \ -fill\ none\ \\\n\ \ \ \ \ \ -expand\ 0\n\n\ \ \ #####################################\n\ \ \ ##\ LOAD\ MSG\ INTO\ TEXT\ WIDGET.\n\ \ \ #####################################\n\n\ \ \ ##\ \ \$w.text\ delete\ 1.0\ end\n\ \n\ \ \ \$w.text\ insert\ end\ \$VARtext\n\ \ \ \n\ \ \ \$w.text\ \ configure\ -state\ disabled\n\n\ \ \ #################################################\n\ \ \ ##\ Set\ VARwidth\ &\ VARheight\ from\ \$VARtext.\n\ \ \ ##\n\ \ \ #################################################\n\ \ \ ##\ To\ get\ VARheight,\n\ \ \ ##\ \ \ \ split\ at\ '\\n'\ (newlines)\ and\ count\ 'lines'.\n\ \ \ #################################################\n\ \n\ \ \ set\ VARlist\ \[\ split\ \$VARtext\ \"\\n\"\ \]\n\n\ \ \ ##\ For\ testing:\n\ \ \ #\ \ puts\ \"VARlist:\ \$VARlist\"\n\n\ \ \ set\ VARheight\ \[\ llength\ \$VARlist\ \]\n\n\ \ \ ##\ For\ testing:\n\ \ \ #\ \ puts\ \"VARheight:\ \$VARheight\"\n\n\ \ \ \$w.text\ configure\ -height\ \$VARheight\n\n\ \ \ #################################################\n\ \ \ ##\ To\ get\ VARwidth,\n\ \ \ ##\ \ \ \ loop\ through\ the\ 'lines'\ getting\ length\n\ \ \ ##\ \ \ \ \ of\ each\;\ save\ max.\n\ \ \ #################################################\n\n\ \ \ set\ maxLINEwidth\ 0\n\n\ \ \ #############################################\n\ \ \ ##\ LOOK\ AT\ EACH\ LINE\ IN\ THE\ LIST.\n\ \ \ #############################################\n\ \ \ foreach\ line\ \$VARlist\ \{\n\n\ \ \ \ \ \ #############################################\n\ \ \ \ \ \ ##\ Get\ the\ length\ of\ the\ line.\n\ \ \ \ \ \ #############################################\n\ \ \ \ \ \ set\ LINEwidth\ \[\ string\ length\ \$line\ \]\n\n\n\ \ \ \ \ \ if\ \{\ \$LINEwidth\ >\ \$maxLINEwidth\ \}\ \{\n\ \ \ \ \ \ \ \ \ set\ maxLINEwidth\ \$LINEwidth\ \n\ \ \ \ \ \ \}\n\n\ \ \ \}\n\ \ \ ##\ END\ OF\ foreach\ line\ \$VARlist\n\n\ \ \ \$w.text\ configure\ -width\ \ \$maxLINEwidth\n\n\ \ \ ##\ For\ testing:\n\ \ \ #\ \ \ puts\ \"maxLINEwidth:\ \$maxLINEwidth\"\n\n\ \ \ ########################################################################\n\ \ \ ##\ NOTE:\ maxLINEwidth\ should\ work\ well\ when\ a\ fixed-width\ font\ used\n\ \ \ ##\ \ \ \ \ \ \ for\ the\ text\ widget\ ...\ BUT\ the\ programmer\ may\ need\ to\ be\n\ \ \ ##\ \ \ \ \ \ \ careful\ that\ the\ contents\ of\ VARtext\ are\ all\ countable\n\ \ \ ##\ \ \ \ \ \ \ characters\ according\ to\ the\ 'string\ length'\ command.\n\ \ \ ########################################################################\n\ \ \n\}\n##\ END\ OF\ 'popup_msg_var'\ PROCEDURE\n\n\n##+########################\n##\ END\ of\ PROC\ definitions.\n##+########################\n\nset\ HELPtext\ \"\\\n\\\ \\\ \\\ \\\ \\\ **HELP\ for\ the\ 'Sketch\ Lines\ on\ an\ Image'\ utility\ **\n\n\ To\ DRAW:\n\ Press\ MB1\ (mouse\ button\ 1)\ to\ start\ a\ line\ where\ the\ arrow-cursor\n\ is\ currently\ located\ on\ the\ canvas.\ Continue\ to\ hold\ MB1\ down\ and\n\ move\ the\ mouse\ to\ draw\ the\ current\ line\ segment\ on\ the\ canvas.\n\ Release\ MB1\ to\ terminate\ drawing\ that\ line\ segment.\n\n\ To\ DELETE\ a\ line\ segment,\ press-and-release\ MB3\ (mouse\ button\ 3)\n\ on\ the\ line\ segment\ (or\ 'degenerate\ line'\ =\ point)\ to\ be\ deleted.\n\n\ Click\ the\ 'RemoveImage'\ button\ to\ see\ how\ your\ drawing\ is\n\ progressing.\ Then\ ...\n\n\ Click\ and\ release\ MB1\ on\ the\ filename\ in\ the\ entry\ field,\ to\n\ RELOAD\ the\ image\ from\ the\ image\ file\ to\ the\ canvas.\ If\ the\n\ reload\ covers\ up\ your\ lines,\ click\ on\ the\ 'RaiseLines'\ button\n\ to\ reveal\ the\ lines\ again.\n\n\ Use\ MB2\ to\ move\ (drag)\ the\ image\ to\ a\ new\ location.\ This\ can\n\ be\ useful\ to\ use\ additional\ images\ to\ help\ sketch\ the\ picture.\n\ Or\ it\ can\ be\ used\ to\ offset\ the\ current\ image\ and\ use\ it\ for\n\ addtional\ sketching.\n\n\ You\ can\ reduce\ the\ number\ of\ points\ being\ captured\ to\ make\ the\n\ curved/polygonal\ line\ by\ increasing\ the\ 'millisecs'\ parameter.\n\n\ Click\ on\ the\ sliderbar\ trough\ for\ fine-grained\ control.\n\n\ You\ can\ use\ a\ screen/image\ capture\ utility\ to\ capture\ your\n\ drawing\ ---\ with\ or\ without\ an\ underlying\ image\ in\ place.\"\n\n\n##+######################################################\n##+######################################################\n##\ Additional\ GUI\ INITIALIZATION:\n##+######################################################\n\n##\ Initialize\ some\ count\ variables\ and\ some\n##\ scale/checkbutton/radiobutton\ widget\ variables\n##\ that\ are\ shown\ on\ the\ GUI\ or\ set\ via\ the\ GUI.\n\nset\ ENTRYfilename\ \"\"\nset\ Nobj\ 0\nset\ NcurPoints\ 0\n#\ set\ lineWIDTHpx\ 2\nset\ lineWIDTHpx\ 15\nset\ Nmillisecs\ 50\nset\ smooth0or1\ 1\nset\ lineCAPstyle\ \"round\"\nset\ lineJOINstyle\ \"round\"\n\n.fRcanvas.can\ configure\ -bg\ \$COLORbkGNDhex\n\nupdate_colors_label\n\nupdate_status_labels\n\n\n\n======\n\nHere\ is\ an\ image\ that\ shows\ that\ you\ do\ not\ have\ to\ use\ an\ image\nto\ do\ your\ sketching.\ You\ can\ simply\ sketch\ on\ the\ canvas\ without\nusing\ the\ 'Browse...'\ button\ to\ locate\ an\ image\ file.\n\n\[sketchOnimgGUI_gimmeSomeTruth_screenshot_501x350.jpg\]\n\nIn\ this\ case,\ I\ used\ the\ 'Background\ color'\ button\ to\ set\ the\ canvas\nbackground\ to\ blue.\ And\ I\ used\ the\ 'Next\ line\ color'\ button\ to,\ at\nvarious\ times,\ set\ the\ line-color\ to\ white,\ black,\ and\ yellow.\n\nI\ also\ used\ the\ 'Width\ of\ next\ line'\ scale\ to\ set\ several\ different\nline\ widths.\n\n____\n\nIn\ summary,\ I\ think\ Tcler's\ (or\ their\ kids)\ can\ have\ some\ fun\ntimes\ with\ this\ 'Sketch\ On'\ utility.\ And\ those\ with\ good\ artistic\ncapabilities\ and/or\ lots\ of\ patience\ can\ generate\ some\ stunning\nimages.\n\n\n======\n\n\[uniquename\]\ 2012oct21\ UPDATE:\n\nTo\ give\ potential\ users\ of\ this\ 'Sketch\ On'\ utility\ some\ ideas\ on\ how\nit\ could\ be\ used\ (the\ range\ of\ its\ capabilities),\ I\ decided\ to\ post\nsome\ images\ here\ that\ might\ trigger\ some\ ideas\ on\ how\ to\ make\ use\ of\n'SketchOn'.\n\nI\ thought\ some\ images\ of\ Roy\ Lichtenstein\ artwork\ (the\ use\ of\ dots\nto\ creat\ shading\ in\ drawings)\ would\ be\ a\ good\ example\ ---\ like\ the\nfollowing\ images.\n\n\[dotsPicture_royLichtenstein_GirlsEyeWithTear_parallel-straightLines_245x350.jpg\]\n\[dotsPicture_royLichtenstein_still-life_dots-straightLine-solidColors_308x340.jpg\]\n\[dotsPicture_blueDotsONwhite_suggestsMountains_100x100.jpg\]\n\nBut\ I\ realized\ that\ the\ first\ 2\ of\ these\ images\ involved\ drawing\ very\ straight\nlines,\ and\ the\ code\ for\ 'SketchOn',\ as\ I\ first\ released\ it,\ was\ not\ well\ suited\nfor\ drawing\ precisely\ straight\ lines.\n\nI\ realized\ that\ I\ could\ add\ a\ 'milliseconds\ delay'\ scale\ to\ the\ GUI\ ---\ to\ spread\nout\ the\ sampling\ of\ points\ that\ make\ up\ the\ curves\ or\ polygons\ being\ drawn.\n\nSo\ I\ have\ enhanced\ the\ GUI,\ and\ replaced\ the\ previous\ code\ with\ new\ code\ above.\n\nAs\ it\ stood,\ the\ would\ handle\ creating\ 'pointillism'\ images\ liek\ the\ following\nclassic\ paintings\ ---\ or\ emulations\ of\ them.\ (The\ first\ image\ is\ someone's\n'dot'\ painting\ emulation\ of\ Van\ Gogh's\ 'Starry\ Night'\ painting,\ which\ was\ originally\nrendered\ in\ short\ 'dashes'\ of\ paint.)\n\n\[pointillism_versionOf_starryNight_by_mysticspirits_deviantart_colorDots_705x599.jpg\]\n\[pointillism_sailboat_signac_shortColorStrokesANDdots_431x358.gif\]\n\[pointillism_vincentVanGogh_selfPortraitWithFeltHat_shortColoredStrokes_330x400.jpg\]\n\nHere\ is\ an\ image\ of\ the\ new\ 'SketchOn'\ GUI,\ with\ an\ image\ that\ I\ spend\ about\ 10\nminutes\ sketching\ out,\ based\ on\ the\ Van\ Gogh\ self-portrait\ above.\ This\ is\ just\nto\ give\ an\ example\ of\ how\ one\ could\ attempt\ a\ 'pointillism'\ type\ sketch.\n\n\[sketchONimgGUI_vanGoghPortrait_crude_881x515.jpg\]\n\nBesides\ color\ drawings,\ one\ could\ simply\ use\ black\ and\ white\ dots\ to\ make\ drawings\n---\ like\ the\ following\ ---\ which\ was\ not\ done\ with\ 'SketchOn'\ ---\ but\ with\ a\ lot\nof\ patience\ and\ some\ artistic\ talent,\ a\ person\ could\ create\ drawings\ like\ this,\nwith\ 'SketchOn'.\n\n\[bw-pointillism_womanFace_PUREblackONwhite_dots_600x770.jpg\]\n\nYou\ can\ make\ dots\ ('degenerate\ lines'\ =\ points)\ with\ 'SketchOn'\ by\ simply\nreleasing\ mouse-button-1\ (MB1)\ immediately\ after\ clicking\ down\ with\ MB1.\n\nIn\ fact,\ by\ using\ lots\ of\ closely\ packed\ dots,\ one\ can\ get\ drawings\ that\ look\nlike\ they\ include\ a\ gray-scale.\ Here\ is\ an\ example.\ It\ looks\ like\ the\ dots\nacross\ the\ nose\ of\ this\ cub\ are\ on\ a\ gray\ background.\n\n\[bw-pointillism_lionCub_PUREblackONwhite_pointsANDlines_600x647.jpg\]\n\nHowever,\ on\ taking\ this\ image\ into\ the\ 'mtpaint'\ image\ editor\ on\ Linux,\nand\ going\ into\ 800%\ zoom\ mode,\ you\ can\ see\ that\ the\ dots\ across\ the\ nose\nare\ pure\ black\ and\ white\ ---\ no\ gray.\n\n\[bw-pointillism_lionCub_PUREblackONwhite_mtpaint800pcntView_781x502.jpg\]\n\nSimilarly,\ newspapers\ use\ 'half-tone'\ procedure\ to\ get\ shaded\ images\ of\nphotos,\ like\ the\ following\ image.\n\n\[halftone_face_161x182.gif\]\n\nIf\ you\ scale\ up\ this\ image\ about\ 4\ times,\ you\ will\ see\ that\ the\ image\ is\ made\nup\ of\ pure\ black\ 'objects'\ ---\ some\ that\ are\ L-shapes\ and\ staircase-shapes\ ---\non\ a\ pure\ white\ background.\n\n\[halftone_face_scaledUp4times_644x728.gif\]\n\nThere\ is\ no\ zoom\ option\ in\ 'SketchOn'\ by\ which\ you\ could\ create\ such\nmicro-detailed\ shapes\ ---\ but\ you\ can\ see\ that\ by\ using\ a\ variety\ of\n'line\ widths',\ you\ can\ make\ points/dots\ of\ various\ sizes\ and\ thus\ get\na\ halftone-like\ drawing\ from\ 'SketchOn'.\n\nIn\ fact,\ you\ could\ use\ COLORED\ dots,\ in\ a\ variety\ of\ sizes,\ to\ get\ images\nlike\ the\ following.\n\n\[dotPicture_butterfly_blueANDpurpleDisks_359x255.jpg\]\n\nFuthermore,\ you\ could\ use\ various\ dashed-line\ and\ hatched-line\ techniques\ ---\nlike\ techniques\ that\ engravers\ use\ ---\ to\ get\ shaded\ image\ drawings\ ---\ such\ as\nthe\ following.\n\n\[engraving_abrahamLincoln_face_dashed-parallel-linesANDhatching_see-eyes-lips-beard_blackONwhite_329x348.jpg\]\n\nIn\ the\ Abraham\ Lincoln\ image\ above,\ take\ note\ of\ the\ techniques\ used\ to\ render\nthe\ eyes,\ lips,\ and\ beard\ ---\ dashed-parallel-lines,\ with\ various\ lengths\ and\nspacings\ in\ the\ dashes.\ And\ hatching\ used\ to\ render\ heavily\ shadowed\ areas.\n\n\[engraving_alexanderHamilton_face_near-parallel-lines-on-face_see-hilite_352x406.jpg\]\n\nThe\ Alexander\ Hamilton\ image\ above\ suggests\ that\ one\ could\ start\ with\ a\ gray\ background\ninstead\ of\ white\ ---\ and\ achieve\ high-lights,\ like\ the\ one\ on\ his\ forehead,\ by\nputting\ a\ blob\ of\ white\ in\ those\ spots.\n\n\[engraving_georgeWashington_face_parallel-linesANDhatching_see-hair-lips_blackONwhite_447x416.jpg\]\n\nThe\ George\ Washington\ image\ above\ gives\ some\ more\ ideas\ on\ how\ to\ render\ hair\ and\ lips.\n\n\[engraving_groverCleveland_faceInOval_lotsOfHatching_see-moustache-hair-coat_blackONwhite_436x490.jpg\]\n\nThe\ Grover\ Cleveland\ image\ above\ is\ a\ good\ example\ of\ rendefing\ moustache,\ hair,\ and\ coat.\n\n\[engraving_johnKennedy_portrait_near-parallel-lines-on-faceANDdot-gridsANDhilites_blackONwhite_561x700.jpg\]\n\nThe\ John\ Kennedy\ image\ above\ shows\ that\ one\ can\ get\ shading\ across\ a\ face\ by\nusing\ parallel\ lines\ of\ various\ widths\ (no\ dashes\ involved).\ And\ dot\ and\ grid\npatterns\ can\ be\ used\ effectively\ in\ some\ places.\ Note\ that\ applying/leaving\ white\nin\ areas\ like\ the\ forehead,\ over\ the\ eyebrows,\ under\ the\ eyes,\ on\ the\ bridge\ of\ the\ nose,\nbetween\ nose\ and\ upper\ lip,\ and\ between\ lower\ lip\ and\ chin\ ---\ one\ can\ get\ very\neffective\ sense\ of\ facial-shape\ along\ with\ lighting\ effects.\n\n\[engraving_ulyssesGrant_face_parallel-linesANDhatching_hairsANDwart_blackONwhite_420x333.jpg\]\n\nThe\ Ulysses\ Grant\ image\ above\ shows\ another\ example\ of\ how\ one\ might\ be\nable\ to\ get\ the\ hair\ effect\ ---\ with\ very\ thin\ white\ and\ black\ lines\ ---\neither\ white\ on\ black\ or\ black\ applied\ to\ white.\ And\ this\ image\ shows\nhow\ you\ could\ render\ a\ wart.\ No\ doubt\ 'SketchOn'\ could\ do\ warts\ and\ all.\n\n\nThe\ following\ image\ suggests\ that\ you\ could\ draw\ ovals\ or\ circles\ on\ntop\ of\ a\ photograph\ and\ leave\ the\ photograph\ in\ place\ ---\ to\ get\na\ quite\ interesting\ effect.\n\n\[photo-pointillism_facePhoto_ovalsSuperimposedOnFace_353x476.jpg\]\n\nOf\ course,\ there\ are\ definite\ limits\ to\ what\ can\ be\ done\ with\ 'SketchOn'.\nIt\ is\ not\ suited\ for\ making\ CAD-like\ drawings\ like\ the\ following.\n\n\[escherStaircase_blueANDyellow_600x450.jpg\]\n\nOn\ the\ other\ hand,\ there\ are\ still\ enhancements\ that\ could\ be\ made.\n\n\[engraving_georgeWashington_portrait_parallel-lines-pinchedEnds_noHatch_610x488.jpg\]\n\nThe\ George\ Washington\ image\ above\ is\ done\ with\ lines\ with\ pinched\ ends.\nThis\ is\ an\ effect\ that\ 'SketchOn'\ cannot\ currently\ do.\ But\ it\ is\ conceivable\nthat\ the\ proc\ that\ adds\ line\ segments\ to\ a\ line\ being\ drawn\ could\ be\ enhanced\nto\ be\ sensitive\ to\ the\ time\ at\ each\ point\ in\ the\ drawing\ of\ a\ line.\ The\ line\nwidth\ could\ be\ automatically\ changed\ according\ to\ the\ speed\ at\ which\ the\ user\nis\ drawing\ the\ line\ ---\ thicker\ at\ slow\ speeds\ and\ thinner\ at\ high\ speeds.\nThen\ a\ line\ could\ be\ tapered\ at\ the\ end\ by\ speeding\ up\ the\ drawing\ stroke\nas\ one\ approached\ the\ time\ to\ release\ the\ mouse\ button.\n\nIn\ any\ case,\ hopefully,\ you\ can\ see\ from\ the\ images\ above\ (other\ than\ the\ last\ 2\ images)\nthat\ there\ is\ a\ wealth\ of\ drawing\ types\ that\ you\ can\ make\ by\ using\ this\ rather\nsimple\ 'SketchOn'\ Tk\ script\ ---\ 'simple'\ compared\ to\ commercial\ drawing\nsoftware\ like\ Adobe\ Freehand\ and\ the\ like\ ---\ simple\ and\ free.\n\n\n\n<<categories>>GUI} CALL {my revision {A 'Sketch On' GUI ... for drawing on an image or colored background}} CALL {::oo::Obj334666 process revision/A+%27Sketch+On%27+GUI+...+for+drawing+on+an+image+or+colored+background} CALL {::oo::Obj334664 process}

-errorcode

NONE

-errorinfo

Unknow state transition: LINE -> END
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4