Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/Overloading+widgets?V=30
QUERY_STRINGV=30
CONTENT_TYPE
DOCUMENT_URI/revision/Overloading+widgets
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
REMOTE_ADDR172.69.6.22
REMOTE_PORT59562
SERVER_PORT8888
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip
HTTP_X_FORWARDED_FOR18.217.71.217
HTTP_CF_RAY886472051d4c609c-ORD
HTTP_X_FORWARDED_PROTOhttp
HTTP_CF_VISITOR{"scheme":"http"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_CF_CONNECTING_IP18.217.71.217
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 {Overloading widgets} \[Richard\ Suchenwirth\]\ 2001-01-19\ -\ \[overload\]ing\ a\ \[widget\]\ means\ writing\ a\ new\ widget\ \[proc\]\ with\ the\ same\ name\ and\ (at\ least)\ same\ functionality,\ so\ when\ \[Tcl/Tk\]\ (e.g.,\ \[pack\])\ calls\ it\ internally,\ it\ reacts\ in\ the\ same\ way.\ \nThis\ is\ the\ lightweight\ way\ of\ creating\ \"mini-megawidgets\"\ in\ pure\ \[Tcl\]\ without\ much\ hassle.\n\n----\n'''Adding\ a\ new\ method\ to\ a\ widget\ (using\ rename\ only)'''\n\nThis\ widget\ is\ based\ on\ the\ text\ widget\ and\ adds\ a\ new\ method\ called\ ''super''.\ This\ method\ \[puts\]\ text\ on\ stdout:\n\n======\n\ proc\ supertext\ \{w\ args\}\ \{\n\ \ \ \ \ \ \ \ eval\ text\ \$w\ \$args\ \;#\ create\ the\ \"base\"\ thing\n\ \ \ \ \ \ \ \ rename\ \$w\ _\$w\ \ \ \ \ \ \;#\ keep\ the\ original\ widget\ command\n\ \ \ \ \ \ \ \ #\ Here\ comes\ the\ overloaded\ widget\ proc:\n\ \ \ \ \ \ \ \ proc\ \$w\ \{cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ self\ \[lindex\ \[info\ level\ 0\]\ 0\]\ \;#\ get\ name\ I\ was\ called\ with\n\ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ super\ \ \ \{puts\ \"super!\ \$args\"\ \;#\ added\ method\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{uplevel\ 1\ _\$self\ \$cmd\ \$args\}\ \ \ \n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ return\ \$w\ \;#\ like\ the\ original\ \"text\"\ command\n\ \}\ \n\ supertext\ .t\ -foreground\ red\n\ pack\ .t\ -fill\ both\ -expand\ 1\n\ .t\ insert\ end\ \"This\ is\ a..\ (see\ stdout)\"\n\ .t\ super\ example\n======\n\nThis\ way,\ a\ supertext\ \"inherits\"\ all\ the\ behavior\ of\ a\ text\ widget,\ but\nin\ addition\ has\ the\ (here\ very\ stupid)\ \"super\"\ method.\ You\ can\ also\noverload\ the\ configure/cget\ \"methods\"\ (see\ below),\ but\ make\ sure\ the\ original\n\"instance\ variables\"\ are\ still\ passed\ through\ to\ the\ original\ widget\nproc.\ Adding\ \"method\ names\"\ like\ above\ is\ the\ easiest.\n\nSee\ also\ \[ANSI\ color\ control\]\ for\ ''ansicolor::text'',\ a\ text\ widget\ where\ the\ ''insert''\ command\ is\ intercepted\ to\ process\ color\ control\ escape\ sequences.\n----\n\[EF\]\ The\ method\ above\ also\ has\ the\ drawback\ to\ \"pollute\"\ the\ main\ namespace\ with\ a\ new\ (renamed)\ command\ that\ refers\ to\ the\ original\ widget\ command.\ So,\ when\ writing\ a\ \[megawidget\]\ through\ a\ namespace\ you\ will\ be\ tempted\ to\ rename\ the\ old\ command\ to\ a\ new\ command\ that\ only\ exists\ in\ \"your\"\ namespace.\ \ However,\ this\ sort\ of\ renaming\ will\ not\ resist\ to\ several\ renaming\ commands\ (if\ you\ decided\ to\ overload\ and\ overloaded\ widget).\ \ One\ way\ to\ solve\ this\ is\ to\ replace\ the\ \ command\ called\ to\ get\ the\ name\ the\ widget\ command\ was\ called\ with\ with\ a\ namespace\ tail\ command.\ \ The\ following\ code\ exemplifies\ this:\n\n======\n\ rename\ ::\$w\ ::supertext::\$w\n\ proc\ ::\$w\ \{\ cmd\ args\ \}\ \[string\ map\ \[list\ @w@\ ::supertext::\$w\]\ \{\n\ \ \ \ \ set\ w\ \[namespace\ tail\ \[lindex\ \[info\ level\ 0\]\ 0\]\]\n\ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ default\ \{eval\ @w@\ \$cmd\ \$args\}\n\ \ \ \ \ \}\n\ \}\]\n======\n\n\n----\n'''Adding\ a\ new\ method\ to\ a\ widget\ (using\ rename\ and\ interp)'''\n\n'''DKF:'''\ you\ can\ do\ even\ better\ for\ yourself\ if\ you\ use\ interpreter\ command\ aliases\ (i.e.\ your\ code\ can\ be\ simpler,\ more\ robust\ and\ less\ heavily\ nested,\ all\ by\ taking\ advantage\ of\ the\ ability\ to\ add\ extra\ arguments\ to\ the\ command\ via\ the\ alias\ -\ \[RS\]:\ which\ in\ functional\ programming\ circles\ is\ called\ \"currying\"\ -\ see\ \[Custom\ curry\].)\ \ Taking\ the\ example\ listed\ above:\n\n======\n\ proc\ supertext\ \{w\ args\}\ \{\n\ \ \ \ eval\ text\ \$w\ \$args\ \;#\ create\ the\ \"base\"\ thing\n\ \ \ \ rename\ \$w\ _\$w\ \ \ \ \ \ \;#\ keep\ the\ original\ widget\ command\n\ \ \ \ #\ Install\ the\ alias...\n\ \ \ \ interp\ alias\ \{\}\ \$w\ \{\}\ supertext_instanceCmd\ \$w\n\ \ \ \ return\ \$w\ \;#\ like\ the\ original\ \"text\"\ command\n\ \}\ \n\ proc\ supertext_instanceCmd\ \{self\ cmd\ args\}\ \{\n\ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ super\ \ \ \{puts\ \"super!\ \$args\"\ \;#\ added\ method\}\n\ \ \ \ \ \ \ default\ \{return\ \[uplevel\ 1\ \[list\ _\$self\ \$cmd\]\ \$args\]\}\n\ \ \ \ \}\n\ \}\n\ supertext\ .t\ -foreground\ red\n\ pack\ .t\ -fill\ both\ -expand\ 1\n\ .t\ insert\ end\ \"This\ is\ a..\ (see\ stdout)\"\n\ .t\ super\ example\n======\n\nThis\ comes\ even\ more\ into\ its\ own\ when\ combined\ with\ namespaces\ and\ multiple\ interpreters.\n\n\[WHD\]:\ But\ note\ that\ this\ method\ can\ get\ you\ into\ trouble\ if\ your\ overloaded\ widget\ command\ is\ overloaded\ a\ second\ time.\ \ I\ forget\ the\ specifics,\ but\ the\ problem\ arises\ if\ the\ overloaded\ widget\ is\ destroyed.\ \ You\ have\ to\ un-overload\ in\ exactly\ the\ reverse\ order,\ and\ it\ doesn't\ quite\ work.\n----\n'''Adding\ a\ new\ method\ to\ a\ widget\ (using\ interp\ only)'''\n\n\[TR\]\ Here\ is\ an\ alternative\ method\ with\ the\ same\ result,\ but\ without\ using\ \[rename\]\ at\ all.\ This\ was\ inspired\ by\ the\ discussion,\ that\ rename\ invalidates\ the\ byte\ compiled\ representation\ of\ core\ commands\ \[http://groups-beta.google.com/group/comp.lang.tcl/browse_frm/thread/3791969747e86489/159d22e0d70a908?hl=en&lr=&rnum=2&prev=/groups%3Fq%3Drename%2Balias%26hl%3Dde%26lr%3D%26group%3Dcomp.lang.tcl.*%26scoring%3Dd%26selm%3D41C083F0.6080000%2540bardo.clearlight.com%26rnum%3D2#159d22e0d70a908\].\ Note:\ Renaming\ widget\ names\ (aka\ commands)\ is\ just\ something\ like\ an\ alias,\ linking\ to\ the\ instance\ in\ C\ code,\ so\ there\ is\ no\ bytecode\ to\ lose\ and\ no\ performance\ loss\ by\ using\ \[rename\]\ in\ this\ way\ (thanks\ to\ \[RS\]\ for\ this\ clarification).\n\n======\n\ proc\ supertext\ \{w\ args\}\ \{\n\ \ \ \ \ \ \ \ #\ create\ the\ \"base\"\ thing:\n\ \ \ \ \ \ \ \ eval\ text\ \$w\ \$args\n\ \ \ \ \ \ \ \ #\ hide\ the\ original\ widget\ command,\ but\ keep\ it:\n\ \ \ \ \ \ \ \ interp\ hide\ \{\}\ \$w\n\ \ \ \ \ \ \ \ #\ Install\ the\ alias:\n\ \ \ \ \ \ \ \ interp\ alias\ \{\}\ \$w\ \{\}\ supertext_instanceCmd\ \$w\n\ \ \ \ \ \ \ \ #\ like\ the\ original\ \"text\"\ command:\n\ \ \ \ \ \ \ \ return\ \$w\n\ \}\n\n\ proc\ supertext_instanceCmd\ \{self\ cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ puts\ \"supertext_instanceCmd\ \$self\ \$cmd\ \$args\"\n\ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ super\ \ \ \{puts\ \"super!\ \$args\"\ \;#\ added\ method\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{return\ \[uplevel\ 1\ \[list\ interp\ invokehidden\ \{\}\ \$self\ \$cmd\]\ \$args\]\}\n\ \ \ \ \ \ \ \ \}\n\ \}\n\n\ supertext\ .t\ -foreground\ red\n\ pack\ .t\ -fill\ both\ -expand\ 1\n\ .t\ insert\ end\ \"This\ is\ a..\ (see\ stdout)\"\n\ .t\ super\ example\n======\n\nThe\ original\ widget\ command\ is\ hidden\ from\ the\ current\ interpreter\ and\ the\ alias\ is\ installed\ like\ in\ the\ previous\ example.\ The\ instanceCmd\ calls\ this\ hidden\ command\ in\ order\ to\ do\ the\ default\ work,\ that\ is\ not\ cusomized.\n----\n'''Adding\ new\ options\ to\ a\ widget'''\n\nYou\ can\ easily\ add\ your\ own\ configure\ options\ to\ your\ new\ widget.\ This\ results\ (of\ course)\ in\ a\ bit\ more\ code,\ but\ the\ logic\ is\ simple.\ You\ need\ to\ intercept\ your\ new\ options\ and\ handle\ them\ separately.\ All\ default\ options\ are\ just\ passed\ to\ the\ original\ widget\ for\ evaluation.\n\nHere\ is\ an\ extended\ supertext\ example.\ It\ is\ a\ bit\ more\ convoluted,\ because\ it\ adds\ a\ \[labelframe\]\ around\ the\ text,\ so\ we\ need\ to\ take\ care\ of\ the\ text\ widget\ as\ a\ subwidget\ here.\ supertext\ has\ two\ new\ options\ here:\ -label\ (for\ the\ text\ on\ the\ labelframe)\ and\ -labelanchor\ (for\ the\ label\ position):\n\n======\n\ \ \ \ \ \ \ \ proc\ supertext\ \{w\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ new\ options\ and\ their\ standard\ values:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ array\ set\ options\ \{-label\ \{\}\ -labelanchor\ nw\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ split\ off\ the\ custom\ options:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ textArgs\ \[list\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ foreach\ \{opt\ val\}\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$opt\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-label\}\ -\ \{-labelanchor\}\ \{set\ options(\$opt)\ \$val\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{lappend\ textArgs\ \$opt\ \$val\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ create\ the\ \"base\"\ \ widget\ for\ the\ new\ megawidget:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ labelframe\ \$w\ -text\ \$options(-label)\ -labelanchor\ \$options(-labelanchor)\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ eval\ text\ \$w.text\ \$textArgs\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ pack\ \$w.text\ -expand\ yes\ -fill\ both\ -padx\ 5\ -pady\ 5\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ hide\ the\ original\ widget\ command\ from\ the\ interpreter:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ interp\ hide\ \{\}\ \$w\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Install\ the\ alias:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ interp\ alias\ \{\}\ \$w\ \{\}\ supertextCmd\ \$w\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ return\ the\ original\ command:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \$w\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ proc\ supertextCmd\ \{self\ cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #puts\ \"-->\ supertextCmd\ \$self\ \$cmd\ \$args\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ super\ \ \ \{puts\ \"super!\ \$args\"\ \;#\ added\ method\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ configure\ \{eval\ supertextConfigure\ \$self\ \$cmd\ \$args\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ cget\ \{eval\ supertextCget\ \$self\ \$args\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{return\ \[eval\ \$self.text\ \$cmd\ \$args\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ proc\ supertextConfigure\ \{self\ cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ differentiate\ between\ 3\ scenarios:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ \$args\ is\ empty\ \ \ \ \ \ \ ->\ return\ all\ options\ with\ their\ values\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ \$args\ is\ one\ element\ ->\ return\ current\ values\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ \$args\ is\ 2+\ elements\ ->\ configure\ the\ options\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ \[llength\ \$args\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ frame\ option:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ result\ \[interp\ invokehidden\ \{\}\ \$self\ cconfigure\ -text\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ default\ options:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ result\ \[\$self.text\ configure\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \$result\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 1\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-label\}\ \{return\ \[interp\ invokehidden\ \{\}\ \$self\ configure\ -text\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-labelanchor\}\ \{return\ \[interp\ invokehidden\ \{\}\ \$self\ configure\ -labelanchor\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{return\ \[\$self.text\ configure\ \$args\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ go\ through\ each\ option:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ foreach\ \{option\ value\}\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$option\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-label\}\ \{interp\ invokehidden\ \{\}\ \$self\ configure\ -text\ \$value\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-labelanchor\}\ \{interp\ invokehidden\ \{\}\ \$self\ configure\ -labelanchor\ \$value\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{\$self.text\ configure\ \$option\ \$value\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \{\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ proc\ supertextCget\ \{self\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ frame\ related\ options\ must\ be\ handled\ separately,\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ the\ rest\ is\ done\ by\ the\ text\ cget\ command\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-label\}\ \{return\ \[interp\ invokehidden\ \{\}\ \$self\ cget\ -text\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-labelanchor\}\ \{return\ \[interp\ invokehidden\ \{\}\ \$self\ cget\ -labelanchor\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{return\ \[\$self.text\ cget\ \$args\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\n\n\n\ \ \ \ \ \ \ \ supertext\ .t\ -foreground\ red\ -background\ white\ -label\ \"A\ super\ text\"\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -labelanchor\ ne\n\ \ \ \ \ \ \ \ pack\ .t\ -fill\ both\ -expand\ 1\n\n\ \ \ \ \ \ \ \ .t\ insert\ end\ \"This\ is\ a..\ (see\ stdout)\"\n\ \ \ \ \ \ \ \ .t\ super\ example\n\n\ \ \ \ \ \ \ \ set\ l\ \"-label\"\n\ \ \ \ \ \ \ \ puts\ \[.t\ cget\ \$l\]\n\ \ \ \ \ \ \ \ puts\ \[.t\ cget\ -foreground\]\n\n\ \ \ \ \ \ \ \ puts\ \[.t\ configure\ -label\]\n\ \ \ \ \ \ \ \ puts\ \[.t\ configure\ -foreground\]\n\n\ \ \ \ \ \ \ \ puts\ \[.t\ configure\ -foreground\ blue\ -label\ \"a\ super\ result\"\]\n======\n\nAs\ you\ can\ see\ from\ the\ 'puts'\ lines,\ you\ can\ use\ the\ widget\ normally\ with\ the\ two\ added\ configure\ options.\n\n\[GWM\]\ shows\ a\ less\ convoluted\ derived\ widget\ in\ \[Another\ Graphing\ Widget\]\ -\ ie\ one\ which\ adds\ \"options\"\ and\ commands\ to\ a\ canvas\ rather\ than\ combining\ 2\ widgets\ into\ a\ super\ widget.\n\n----\n'''Bindings\ on\ overloaded\ widgets\ (and\ how\ to\ get\ them\ working\ again)'''\n\nIf\ you\ try\ to\ make\ a\ standard\ binding\ on\ the\ overloaded\ textwidget\ in\ the\ last\ example\ above,\ like\n\n======\n\ supertext\ .t\n\ pack\ .t\n\ bind\ .t\ <Motion>\ \{puts\ \"Moving\ cursor\ ...\"\}\n======\n\nnothing\ will\ happen.\ This\ is\ because\ we\ changed\ the\ command\ name\ for\ the\ new\ overloaded\ widget\ but\ this\ did\ of\ course\ not\ change\ the\ path\ name.\ So\ while\ ''.t''\ is\ now\ a\ command\ meaning\ the\ text\ widget\ (inside\ the\ frame),\ the\ path\ ''.t''\ used\ in\ the\ binding\ command\ still\ means\ the\ frame\ around\ the\ text\ widget.\ To\ resolve\ this\ problem,\ we\ can\ add\ a\ clever\ bindtags\ command\ to\ the\ procedure\ ''supertext'':\n\n======\n\ bindtags\ \$w.text\ \[lreplace\ \[bindtags\ \$w.text\]\ 0\ 0\ \$w\]\ \n======\n\nThis\ takes\ the\ binding\ tags\ for\ the\ text\ widget\ created\ inside\ the\ ''supertext''\ procedure\ and\ replaces\ the\ first\ element\ with\ the\ frame\ path.\ Originally\ this\ first\ element\ consisted\ of\ the\ path\ name\ of\ this\ particular\ text\ widget.\ After\ the\ replacement,\ this\ text\ widget\ will\ act\ upon\ bindings\ on\ the\ frame,\ so\ if\ a\ user\ makes\ a\ binding\ on\ ''.t''\ (which\ is\ actually\ the\ frame),\ it\ will\ fire\ in\ the\ text\ widget,\ just\ as\ intended.\ All\ other\ bindings\ on\ the\ text\ class,\ the\ toplevel\ and\ ''All''\ are\ still\ intact.\ The\ ''ScrolledWidget''\ example\ below\ uses\ this\ technique\ to\ get\ the\ bindings\ right.\n\n----\n'''Dynamic\ bindings\ on\ overloaded\ widgets'''\n\n\[Duoas\]\ The\ above\ method\ has\ a\ drawback.\ When\ handling\ ''dynamic''\ bindings\ on\ the\ megawidget,\ you\ get\ the\ same\ problem\ as\ before.\ For\ example,\ if\ you\ have\ specific\ behaviours\ bound\ to\ a\ tag\ which\ you\ add\ to\ the\ megawidget's\ list\ of\ bindtags,\ like\n\n======\n\ #\ Bindings\ for\ 'edit\ mode'\ on\ the\ supertext\ megawidget\n\ bind\ SuperEditMode\ <ButtonPress-1>\ \[list\ dosomething\ %x\ %y\]\n\ ...\n\ #\ Activate\ 'edit\ mode'\ on\ the\ supertext\ megawidget\n\ bindtags\ .t\ \[linsert\ \[bindtags\ .t\]\ 0\ SuperEditMode\]\n\ ...\n\ #\ Deactivate\ 'edit\ mode'\ on\ the\ supertext\ megawidget\n\ bindtags\ .t\ \[lsearch\ -inline\ -all\ -exact\ -not\ \[bindtags\ .t\]\ SuperEditMode\]\nnothing\ will\ happen\ (again).\ This\ is\ for\ the\ very\ same\ reason\ as\ before:\ because\ the\ path\ ''.t''\ means\ the\ frame\ around\ the\ text\ widget\ and\ not\ the\ text\ widget\ itself.\n======\n\nThe\ way\ to\ overcome\ this\ is\ surprisingly\ simple:\ add\ an\ execution\ trace\ to\ the\ '''bindtags'''\ command.\ There\ are,\ of\ course,\ many\ ways\ to\ do\ it,\ but\ here\ is\ a\ simple\ proc\ that\ will\ give\ you\ good\ results.\ It\ combines\ the\ bindtags\ for\ both\ the\ frame\ and\ the\ specified\ subwidget,\ and\ removes\ the\ subwidget\ from\ the\ resulting\ list\ of\ tags:\n\n======\n\ proc\ UpdateBindtags\ \{win\ subwin\ args\}\ \{\n\ \ \ \ \ \ \ \ \ if\ \{(\$args\ eq\ \{\})\ ||\ (\$win\ in\ \[lindex\ \$args\ 0\])\}\ \{\n\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ combine\ the\ bindtags\ for\ the\ widget\ and\ subwidget\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ tags\ \[bindtags\ \$win\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ tags\ \{*\}\[bindtags\ \$subwin\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ tags\ \[lsort\ -unique\ \$tags\]\n\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ remove\ the\ subwidget's\ tag\ from\ the\ result\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ bindtags\ \$subwin\ \[lsearch\ -inline\ -all\ -exact\ -not\ \$tags\ \$subwin\]\n\ \ \ \ \ \ \ \ \ \}\n\ \}\n======\n\nNext,\ in\ your\ widget's\ creation/initialization\ code,\ make\ sure\ to\ perform\ the\ proper\ updates:\n\n======\n\ ::UpdateBindtags\ \$w\ \$w.text\n\ trace\ add\ execution\ bindtags\ leave\ \[list\ ::UpdateBindtags\ \$w\ \$w.text\]\n======\n\nAnd\ that's\ all\ there\ is\ to\ it!\n\nAs\ a\ side\ note,\ I'm\ not\ so\ sure\ that\ you\ always\ need\ to\ remove\ the\ subwidget's\ name\ from\ the\ list\ of\ tags.\ That\ is,\ of\ course,\ a\ matter\ to\ consider\ against\ your\ requirements\ and\ needs.\n----\n'''Intercepting\ changes\ to\ a\ widget's\ state'''\n\n\[KBK\]\ 2006-09-22:\ One\ thing\ that\ overloading\ can\ sometimes\ get\ you\ is\ the\ ability\ to\ act\ on\ changes\ to\ a\ widget's\ state.\ \ For\ instance,\ a\ text\ widget's\ characters\ can\ change\ only\ by\ the\ ''insert''\ and\ ''delete''\ widget\ commands\;\ its\ insertion\ cursor\ can\ be\ moved\ only\ by\ the\ ''mark\ set\ insert''\ command,\ and\ so\ on.\ \ These\ provide\ a\ limited\ number\ of\ places\ that\ you\ need\ to\ hook\ to\ attach\ new\ behaviours\ to\ the\ given\ actions.\ \ One\ worked\ example\ shows\ that\ you\ can\ provide\ a\ \[text\ variable\ for\ text\ widget\]s\ that\ function\ as\ multi-line\ entries.\n----\n'''Useful\ examples\ of\ small\ megawidgets''''\n\n''text\ widget\ with\ markup''\n\nA\ more\ meaningful\ example\ was\ triggered\ by\ a\ c.l.t\ post\ from\ \[Bryan\ Oakley\]:\n''it'd\ be\ nice\ to\ create\ text\ like\ \"some\ things\ are\ *bold*\ and\ some\ are\ _underlined_\"\ and\ be\ able\ to\ put\ that\ into\ a\ widget\ with\ a\ single\ call.''\ \nHere's\ a\ quick\ shot:\n\n======\n\ proc\ markuptext\ \{w\ args\}\ \{\n\ \ \ \ eval\ \[list\ text\ \$w\]\ \$args\n\ \ \ \ rename\ ::\$w\ ::_\$w\n\ \ \ \ proc\ ::\$w\ \{cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ set\ w\ \[lindex\ \[info\ level\ 1\]\ 0\]\n\ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ insert\ \ \{eval\ \[list\ markuptext'insert\ \$w\]\ \$args\}\n\ \ \ \ \ \ \ \ \ \ \ \ default\ \{eval\ \[list\ ::_\$w\ \$cmd\]\ \$args\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ set\ w\n\ \}\n\ proc\ markuptext'insert\ \{w\ position\ args\}\ \{\n\ \ \ \ if\ \{\[llength\ \$args\]==1\}\ \{set\ args\ \[lindex\ \$args\ 0\]\}\n\ \ \ \ foreach\ word\ \[split\ \$args\]\ \{\n\ \ \ \ \ \ \ \ \ if\ \{\$word==\"\"\}\ continue\n\ \ \ \ \ \ \ \ set\ tag\ \"\"\n\ \ \ \ \ \ \ \ if\ \{\[regexp\ \{^\\*(.+)\\*\$\}\ \$word\ ->\ word\]\}\ \{set\ tag\ bold\}\n\ \ \ \ \ \ \ \ if\ \{\[regexp\ \{^_(.+)_\$\}\ \ \ \$word\ ->\ word\]\}\ \{set\ tag\ underline\}\n\ \ \ \ \ \ \ \ ::_\$w\ insert\ \$position\ \"\$word\ \"\ \$tag\n\ \ \ \ \}\n\ \}\n\ #-----------------------------\ Test\ and\ demo\ code...\n\ pack\ \[markuptext\ .t\]\n\ .t\ tag\ configure\ bold\ \ \ \ \ \ -font\ \{Arial\ 10\ bold\}\n\ .t\ tag\ configure\ underline\ -font\ \{Arial\ 10\ underline\}\n\ .t\ insert\ end\ \"Test\ for\ *bold*\ and\ _underlined_\ words...\\\n\ \ \ \ \ with\ \\\"quotes\\\"\ and\ \\\{unbalanced\ braces\"\n======\n\n\n\[LV\]\ There\ are\ several\ examples\ for\ markup\ languages.\ \ For\ instance,\ this\ wiki\ uses\ ''''\ to\nmark\ a\ request\ for\ emphasis\ (italics)\ and\ ''''''\ as\ a\ request\ for\ strong\ (bold)\ highlighting.\ \ This\ wiki\ doesn't\ have\ a\ notation\ for\ underlining.\n\nThen\ there's\ '''setext'''\ \[http://www.valdemar.net/~erik/setext/\],\ which\ uses\ similar\ markup\ as\ you've\ implemented.\ \ And\ there\ is\ a\n\[mime\]\ richtext\[http://www.ietf.org/rfc/rfc1341.txt\]\ (not\ the\ same\ as\ the\ \[Microsoft\]\ rich\ text),\ which\ has\ its\ own\nmarkup.\ \ See\ \[A\ wiki-like\ markup\ language\ for\ the\ text\ widget\]\ for\ an\ example.\n\n''a\ scrolled\ widget\ megawidget''\n\nThis\ widget\ can\ be\ used\ to\ produce\ a\ standard\ widget\ with\ scrollbars\ around\ it.\ You\ call\ it\ with\ a\ standard\ widget\ as\ a\ parameter\ and\ specify,\ which\ scrollbars\ you\ want,\ and\ you\ get\ a\ scrolled\ widget\ of\ that\ type\ acting\ just\ like\ the\ standard\ thing.\ It\ just\ comes\ with\ functional\ added\ scrollbars:\n\n======\n\ \ \ \ \ \ \ \ #\ create\ a\ standard\ widget\ with\ scrollbars\ around\n\ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ #\ wigdet\ \ ->\ name\ of\ the\ widget\ to\ be\ created\n\ \ \ \ \ \ \ \ #\ parent\ \ ->\ path\ to\ the\ frame,\ in\ which\ the\ widget\ and\ the\ scrollbars\ should\n\ \ \ \ \ \ \ \ #\ \ \ \ \ \ \ \ \ \ \ \ be\ created\n\ \ \ \ \ \ \ \ #\ scrollx\ ->\ boolean\;\ create\ horizontal\ scrollbar?\n\ \ \ \ \ \ \ \ #\ scrolly\ ->\ boolean\;\ create\ vertical\ scrollbar?\n\ \ \ \ \ \ \ \ #\ args\ \ \ \ ->\ additional\ arguments\ passed\ on\ the\ the\ original\ widget\n\ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ #\ returns:\ the\ path\ to\ the\ created\ widget\ (frame)\n\ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ proc\ ScrolledWidget\ \{widget\ parent\ scrollx\ scrolly\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Create\ widget\ attached\ to\ scrollbars,\ pass\ thru\ \$args\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ frame\ \$parent\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ eval\ \$widget\ \$parent.list\ \$args\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Create\ scrollbars\ attached\ to\ the\ listbox\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$scrollx\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ scrollbar\ \$parent.sx\ -orient\ horizontal\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -command\ \[list\ \$parent.list\ xview\]\ -elementborderwidth\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ \$parent.sx\ \ \ \ \ \ \ \ \ -column\ 0\ -row\ 1\ -sticky\ ew\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$parent.list\ configure\ -xscrollcommand\ \[list\ \$parent.sx\ set\]\n\ \ \ \ \ \ \ \ \\\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$scrolly\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ scrollbar\ \$parent.sy\ -orient\ vertical\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -command\ \[list\ \$parent.list\ yview\]\ -elementborderwidth\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ \$parent.sy\ \ \ \ \ \ \ \ \ -column\ 1\ -row\ 0\ -sticky\ ns\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$parent.list\ configure\ -yscrollcommand\ \[list\ \$parent.sy\ set\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Arrange\ them\ in\ the\ parent\ frame\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ \$parent.list\ \ -column\ 0\ -row\ 0\ -sticky\ ewsn\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ columnconfigure\ \$parent\ 0\ -weight\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ rowconfigure\ \$parent\ 0\ -weight\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ hide\ the\ original\ widget\ command\ from\ the\ interpreter:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ interp\ hide\ \{\}\ \$parent\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Install\ the\ alias:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ interp\ alias\ \{\}\ \$parent\ \{\}\ ScrolledWidgetCmd\ \$parent.list\n\ \ \ \ \ \ \ \ \ \ \ \ #\ fix\ the\ bindtags:\n\ \ \ \ \ \ \ \ \ \ \ \ bindtags\ \$parent.list\ \[lreplace\ \[bindtags\ \$parent.list\]\ 0\ 0\ \$parent\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \$parent\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ proc\ ScrolledWidgetCmd\ \{self\ cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[uplevel\ 1\ \[list\ \$self\ \$cmd\]\ \$args\]\n\ \ \ \ \ \ \ \ \}\n======\n\nTo\ create\ a\ scrolled\ text\ widget\ with\ both\ scrollbars,\ use:\n\n======\n\ \ ScrolledWidget\ text\ .t\ 1\ 1\n\n\n----\nTo\ see\ how\ a\ real\ megawidget\ framework\ does\ this\ work,\ start\ reading\ here:\ \[megawidget\]\n\n<<categories>>Arts\ and\ crafts\ of\ Tcl-Tk\ programming\ |\ GUI\ |\ Widget regexp2} CALL {my render {Overloading widgets} \[Richard\ Suchenwirth\]\ 2001-01-19\ -\ \[overload\]ing\ a\ \[widget\]\ means\ writing\ a\ new\ widget\ \[proc\]\ with\ the\ same\ name\ and\ (at\ least)\ same\ functionality,\ so\ when\ \[Tcl/Tk\]\ (e.g.,\ \[pack\])\ calls\ it\ internally,\ it\ reacts\ in\ the\ same\ way.\ \nThis\ is\ the\ lightweight\ way\ of\ creating\ \"mini-megawidgets\"\ in\ pure\ \[Tcl\]\ without\ much\ hassle.\n\n----\n'''Adding\ a\ new\ method\ to\ a\ widget\ (using\ rename\ only)'''\n\nThis\ widget\ is\ based\ on\ the\ text\ widget\ and\ adds\ a\ new\ method\ called\ ''super''.\ This\ method\ \[puts\]\ text\ on\ stdout:\n\n======\n\ proc\ supertext\ \{w\ args\}\ \{\n\ \ \ \ \ \ \ \ eval\ text\ \$w\ \$args\ \;#\ create\ the\ \"base\"\ thing\n\ \ \ \ \ \ \ \ rename\ \$w\ _\$w\ \ \ \ \ \ \;#\ keep\ the\ original\ widget\ command\n\ \ \ \ \ \ \ \ #\ Here\ comes\ the\ overloaded\ widget\ proc:\n\ \ \ \ \ \ \ \ proc\ \$w\ \{cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ self\ \[lindex\ \[info\ level\ 0\]\ 0\]\ \;#\ get\ name\ I\ was\ called\ with\n\ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ super\ \ \ \{puts\ \"super!\ \$args\"\ \;#\ added\ method\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{uplevel\ 1\ _\$self\ \$cmd\ \$args\}\ \ \ \n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ return\ \$w\ \;#\ like\ the\ original\ \"text\"\ command\n\ \}\ \n\ supertext\ .t\ -foreground\ red\n\ pack\ .t\ -fill\ both\ -expand\ 1\n\ .t\ insert\ end\ \"This\ is\ a..\ (see\ stdout)\"\n\ .t\ super\ example\n======\n\nThis\ way,\ a\ supertext\ \"inherits\"\ all\ the\ behavior\ of\ a\ text\ widget,\ but\nin\ addition\ has\ the\ (here\ very\ stupid)\ \"super\"\ method.\ You\ can\ also\noverload\ the\ configure/cget\ \"methods\"\ (see\ below),\ but\ make\ sure\ the\ original\n\"instance\ variables\"\ are\ still\ passed\ through\ to\ the\ original\ widget\nproc.\ Adding\ \"method\ names\"\ like\ above\ is\ the\ easiest.\n\nSee\ also\ \[ANSI\ color\ control\]\ for\ ''ansicolor::text'',\ a\ text\ widget\ where\ the\ ''insert''\ command\ is\ intercepted\ to\ process\ color\ control\ escape\ sequences.\n----\n\[EF\]\ The\ method\ above\ also\ has\ the\ drawback\ to\ \"pollute\"\ the\ main\ namespace\ with\ a\ new\ (renamed)\ command\ that\ refers\ to\ the\ original\ widget\ command.\ So,\ when\ writing\ a\ \[megawidget\]\ through\ a\ namespace\ you\ will\ be\ tempted\ to\ rename\ the\ old\ command\ to\ a\ new\ command\ that\ only\ exists\ in\ \"your\"\ namespace.\ \ However,\ this\ sort\ of\ renaming\ will\ not\ resist\ to\ several\ renaming\ commands\ (if\ you\ decided\ to\ overload\ and\ overloaded\ widget).\ \ One\ way\ to\ solve\ this\ is\ to\ replace\ the\ \ command\ called\ to\ get\ the\ name\ the\ widget\ command\ was\ called\ with\ with\ a\ namespace\ tail\ command.\ \ The\ following\ code\ exemplifies\ this:\n\n======\n\ rename\ ::\$w\ ::supertext::\$w\n\ proc\ ::\$w\ \{\ cmd\ args\ \}\ \[string\ map\ \[list\ @w@\ ::supertext::\$w\]\ \{\n\ \ \ \ \ set\ w\ \[namespace\ tail\ \[lindex\ \[info\ level\ 0\]\ 0\]\]\n\ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ default\ \{eval\ @w@\ \$cmd\ \$args\}\n\ \ \ \ \ \}\n\ \}\]\n======\n\n\n----\n'''Adding\ a\ new\ method\ to\ a\ widget\ (using\ rename\ and\ interp)'''\n\n'''DKF:'''\ you\ can\ do\ even\ better\ for\ yourself\ if\ you\ use\ interpreter\ command\ aliases\ (i.e.\ your\ code\ can\ be\ simpler,\ more\ robust\ and\ less\ heavily\ nested,\ all\ by\ taking\ advantage\ of\ the\ ability\ to\ add\ extra\ arguments\ to\ the\ command\ via\ the\ alias\ -\ \[RS\]:\ which\ in\ functional\ programming\ circles\ is\ called\ \"currying\"\ -\ see\ \[Custom\ curry\].)\ \ Taking\ the\ example\ listed\ above:\n\n======\n\ proc\ supertext\ \{w\ args\}\ \{\n\ \ \ \ eval\ text\ \$w\ \$args\ \;#\ create\ the\ \"base\"\ thing\n\ \ \ \ rename\ \$w\ _\$w\ \ \ \ \ \ \;#\ keep\ the\ original\ widget\ command\n\ \ \ \ #\ Install\ the\ alias...\n\ \ \ \ interp\ alias\ \{\}\ \$w\ \{\}\ supertext_instanceCmd\ \$w\n\ \ \ \ return\ \$w\ \;#\ like\ the\ original\ \"text\"\ command\n\ \}\ \n\ proc\ supertext_instanceCmd\ \{self\ cmd\ args\}\ \{\n\ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ super\ \ \ \{puts\ \"super!\ \$args\"\ \;#\ added\ method\}\n\ \ \ \ \ \ \ default\ \{return\ \[uplevel\ 1\ \[list\ _\$self\ \$cmd\]\ \$args\]\}\n\ \ \ \ \}\n\ \}\n\ supertext\ .t\ -foreground\ red\n\ pack\ .t\ -fill\ both\ -expand\ 1\n\ .t\ insert\ end\ \"This\ is\ a..\ (see\ stdout)\"\n\ .t\ super\ example\n======\n\nThis\ comes\ even\ more\ into\ its\ own\ when\ combined\ with\ namespaces\ and\ multiple\ interpreters.\n\n\[WHD\]:\ But\ note\ that\ this\ method\ can\ get\ you\ into\ trouble\ if\ your\ overloaded\ widget\ command\ is\ overloaded\ a\ second\ time.\ \ I\ forget\ the\ specifics,\ but\ the\ problem\ arises\ if\ the\ overloaded\ widget\ is\ destroyed.\ \ You\ have\ to\ un-overload\ in\ exactly\ the\ reverse\ order,\ and\ it\ doesn't\ quite\ work.\n----\n'''Adding\ a\ new\ method\ to\ a\ widget\ (using\ interp\ only)'''\n\n\[TR\]\ Here\ is\ an\ alternative\ method\ with\ the\ same\ result,\ but\ without\ using\ \[rename\]\ at\ all.\ This\ was\ inspired\ by\ the\ discussion,\ that\ rename\ invalidates\ the\ byte\ compiled\ representation\ of\ core\ commands\ \[http://groups-beta.google.com/group/comp.lang.tcl/browse_frm/thread/3791969747e86489/159d22e0d70a908?hl=en&lr=&rnum=2&prev=/groups%3Fq%3Drename%2Balias%26hl%3Dde%26lr%3D%26group%3Dcomp.lang.tcl.*%26scoring%3Dd%26selm%3D41C083F0.6080000%2540bardo.clearlight.com%26rnum%3D2#159d22e0d70a908\].\ Note:\ Renaming\ widget\ names\ (aka\ commands)\ is\ just\ something\ like\ an\ alias,\ linking\ to\ the\ instance\ in\ C\ code,\ so\ there\ is\ no\ bytecode\ to\ lose\ and\ no\ performance\ loss\ by\ using\ \[rename\]\ in\ this\ way\ (thanks\ to\ \[RS\]\ for\ this\ clarification).\n\n======\n\ proc\ supertext\ \{w\ args\}\ \{\n\ \ \ \ \ \ \ \ #\ create\ the\ \"base\"\ thing:\n\ \ \ \ \ \ \ \ eval\ text\ \$w\ \$args\n\ \ \ \ \ \ \ \ #\ hide\ the\ original\ widget\ command,\ but\ keep\ it:\n\ \ \ \ \ \ \ \ interp\ hide\ \{\}\ \$w\n\ \ \ \ \ \ \ \ #\ Install\ the\ alias:\n\ \ \ \ \ \ \ \ interp\ alias\ \{\}\ \$w\ \{\}\ supertext_instanceCmd\ \$w\n\ \ \ \ \ \ \ \ #\ like\ the\ original\ \"text\"\ command:\n\ \ \ \ \ \ \ \ return\ \$w\n\ \}\n\n\ proc\ supertext_instanceCmd\ \{self\ cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ puts\ \"supertext_instanceCmd\ \$self\ \$cmd\ \$args\"\n\ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ super\ \ \ \{puts\ \"super!\ \$args\"\ \;#\ added\ method\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{return\ \[uplevel\ 1\ \[list\ interp\ invokehidden\ \{\}\ \$self\ \$cmd\]\ \$args\]\}\n\ \ \ \ \ \ \ \ \}\n\ \}\n\n\ supertext\ .t\ -foreground\ red\n\ pack\ .t\ -fill\ both\ -expand\ 1\n\ .t\ insert\ end\ \"This\ is\ a..\ (see\ stdout)\"\n\ .t\ super\ example\n======\n\nThe\ original\ widget\ command\ is\ hidden\ from\ the\ current\ interpreter\ and\ the\ alias\ is\ installed\ like\ in\ the\ previous\ example.\ The\ instanceCmd\ calls\ this\ hidden\ command\ in\ order\ to\ do\ the\ default\ work,\ that\ is\ not\ cusomized.\n----\n'''Adding\ new\ options\ to\ a\ widget'''\n\nYou\ can\ easily\ add\ your\ own\ configure\ options\ to\ your\ new\ widget.\ This\ results\ (of\ course)\ in\ a\ bit\ more\ code,\ but\ the\ logic\ is\ simple.\ You\ need\ to\ intercept\ your\ new\ options\ and\ handle\ them\ separately.\ All\ default\ options\ are\ just\ passed\ to\ the\ original\ widget\ for\ evaluation.\n\nHere\ is\ an\ extended\ supertext\ example.\ It\ is\ a\ bit\ more\ convoluted,\ because\ it\ adds\ a\ \[labelframe\]\ around\ the\ text,\ so\ we\ need\ to\ take\ care\ of\ the\ text\ widget\ as\ a\ subwidget\ here.\ supertext\ has\ two\ new\ options\ here:\ -label\ (for\ the\ text\ on\ the\ labelframe)\ and\ -labelanchor\ (for\ the\ label\ position):\n\n======\n\ \ \ \ \ \ \ \ proc\ supertext\ \{w\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ new\ options\ and\ their\ standard\ values:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ array\ set\ options\ \{-label\ \{\}\ -labelanchor\ nw\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ split\ off\ the\ custom\ options:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ textArgs\ \[list\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ foreach\ \{opt\ val\}\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$opt\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-label\}\ -\ \{-labelanchor\}\ \{set\ options(\$opt)\ \$val\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{lappend\ textArgs\ \$opt\ \$val\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ create\ the\ \"base\"\ \ widget\ for\ the\ new\ megawidget:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ labelframe\ \$w\ -text\ \$options(-label)\ -labelanchor\ \$options(-labelanchor)\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ eval\ text\ \$w.text\ \$textArgs\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ pack\ \$w.text\ -expand\ yes\ -fill\ both\ -padx\ 5\ -pady\ 5\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ hide\ the\ original\ widget\ command\ from\ the\ interpreter:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ interp\ hide\ \{\}\ \$w\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Install\ the\ alias:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ interp\ alias\ \{\}\ \$w\ \{\}\ supertextCmd\ \$w\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ return\ the\ original\ command:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \$w\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ proc\ supertextCmd\ \{self\ cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #puts\ \"-->\ supertextCmd\ \$self\ \$cmd\ \$args\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ super\ \ \ \{puts\ \"super!\ \$args\"\ \;#\ added\ method\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ configure\ \{eval\ supertextConfigure\ \$self\ \$cmd\ \$args\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ cget\ \{eval\ supertextCget\ \$self\ \$args\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{return\ \[eval\ \$self.text\ \$cmd\ \$args\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ proc\ supertextConfigure\ \{self\ cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ differentiate\ between\ 3\ scenarios:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ \$args\ is\ empty\ \ \ \ \ \ \ ->\ return\ all\ options\ with\ their\ values\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ \$args\ is\ one\ element\ ->\ return\ current\ values\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ \$args\ is\ 2+\ elements\ ->\ configure\ the\ options\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ \[llength\ \$args\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ frame\ option:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ result\ \[interp\ invokehidden\ \{\}\ \$self\ cconfigure\ -text\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ default\ options:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ result\ \[\$self.text\ configure\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \$result\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 1\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-label\}\ \{return\ \[interp\ invokehidden\ \{\}\ \$self\ configure\ -text\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-labelanchor\}\ \{return\ \[interp\ invokehidden\ \{\}\ \$self\ configure\ -labelanchor\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{return\ \[\$self.text\ configure\ \$args\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ go\ through\ each\ option:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ foreach\ \{option\ value\}\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$option\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-label\}\ \{interp\ invokehidden\ \{\}\ \$self\ configure\ -text\ \$value\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-labelanchor\}\ \{interp\ invokehidden\ \{\}\ \$self\ configure\ -labelanchor\ \$value\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{\$self.text\ configure\ \$option\ \$value\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \{\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ proc\ supertextCget\ \{self\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ frame\ related\ options\ must\ be\ handled\ separately,\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ the\ rest\ is\ done\ by\ the\ text\ cget\ command\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ switch\ --\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-label\}\ \{return\ \[interp\ invokehidden\ \{\}\ \$self\ cget\ -text\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{-labelanchor\}\ \{return\ \[interp\ invokehidden\ \{\}\ \$self\ cget\ -labelanchor\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{return\ \[\$self.text\ cget\ \$args\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\n\n\n\ \ \ \ \ \ \ \ supertext\ .t\ -foreground\ red\ -background\ white\ -label\ \"A\ super\ text\"\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -labelanchor\ ne\n\ \ \ \ \ \ \ \ pack\ .t\ -fill\ both\ -expand\ 1\n\n\ \ \ \ \ \ \ \ .t\ insert\ end\ \"This\ is\ a..\ (see\ stdout)\"\n\ \ \ \ \ \ \ \ .t\ super\ example\n\n\ \ \ \ \ \ \ \ set\ l\ \"-label\"\n\ \ \ \ \ \ \ \ puts\ \[.t\ cget\ \$l\]\n\ \ \ \ \ \ \ \ puts\ \[.t\ cget\ -foreground\]\n\n\ \ \ \ \ \ \ \ puts\ \[.t\ configure\ -label\]\n\ \ \ \ \ \ \ \ puts\ \[.t\ configure\ -foreground\]\n\n\ \ \ \ \ \ \ \ puts\ \[.t\ configure\ -foreground\ blue\ -label\ \"a\ super\ result\"\]\n======\n\nAs\ you\ can\ see\ from\ the\ 'puts'\ lines,\ you\ can\ use\ the\ widget\ normally\ with\ the\ two\ added\ configure\ options.\n\n\[GWM\]\ shows\ a\ less\ convoluted\ derived\ widget\ in\ \[Another\ Graphing\ Widget\]\ -\ ie\ one\ which\ adds\ \"options\"\ and\ commands\ to\ a\ canvas\ rather\ than\ combining\ 2\ widgets\ into\ a\ super\ widget.\n\n----\n'''Bindings\ on\ overloaded\ widgets\ (and\ how\ to\ get\ them\ working\ again)'''\n\nIf\ you\ try\ to\ make\ a\ standard\ binding\ on\ the\ overloaded\ textwidget\ in\ the\ last\ example\ above,\ like\n\n======\n\ supertext\ .t\n\ pack\ .t\n\ bind\ .t\ <Motion>\ \{puts\ \"Moving\ cursor\ ...\"\}\n======\n\nnothing\ will\ happen.\ This\ is\ because\ we\ changed\ the\ command\ name\ for\ the\ new\ overloaded\ widget\ but\ this\ did\ of\ course\ not\ change\ the\ path\ name.\ So\ while\ ''.t''\ is\ now\ a\ command\ meaning\ the\ text\ widget\ (inside\ the\ frame),\ the\ path\ ''.t''\ used\ in\ the\ binding\ command\ still\ means\ the\ frame\ around\ the\ text\ widget.\ To\ resolve\ this\ problem,\ we\ can\ add\ a\ clever\ bindtags\ command\ to\ the\ procedure\ ''supertext'':\n\n======\n\ bindtags\ \$w.text\ \[lreplace\ \[bindtags\ \$w.text\]\ 0\ 0\ \$w\]\ \n======\n\nThis\ takes\ the\ binding\ tags\ for\ the\ text\ widget\ created\ inside\ the\ ''supertext''\ procedure\ and\ replaces\ the\ first\ element\ with\ the\ frame\ path.\ Originally\ this\ first\ element\ consisted\ of\ the\ path\ name\ of\ this\ particular\ text\ widget.\ After\ the\ replacement,\ this\ text\ widget\ will\ act\ upon\ bindings\ on\ the\ frame,\ so\ if\ a\ user\ makes\ a\ binding\ on\ ''.t''\ (which\ is\ actually\ the\ frame),\ it\ will\ fire\ in\ the\ text\ widget,\ just\ as\ intended.\ All\ other\ bindings\ on\ the\ text\ class,\ the\ toplevel\ and\ ''All''\ are\ still\ intact.\ The\ ''ScrolledWidget''\ example\ below\ uses\ this\ technique\ to\ get\ the\ bindings\ right.\n\n----\n'''Dynamic\ bindings\ on\ overloaded\ widgets'''\n\n\[Duoas\]\ The\ above\ method\ has\ a\ drawback.\ When\ handling\ ''dynamic''\ bindings\ on\ the\ megawidget,\ you\ get\ the\ same\ problem\ as\ before.\ For\ example,\ if\ you\ have\ specific\ behaviours\ bound\ to\ a\ tag\ which\ you\ add\ to\ the\ megawidget's\ list\ of\ bindtags,\ like\n\n======\n\ #\ Bindings\ for\ 'edit\ mode'\ on\ the\ supertext\ megawidget\n\ bind\ SuperEditMode\ <ButtonPress-1>\ \[list\ dosomething\ %x\ %y\]\n\ ...\n\ #\ Activate\ 'edit\ mode'\ on\ the\ supertext\ megawidget\n\ bindtags\ .t\ \[linsert\ \[bindtags\ .t\]\ 0\ SuperEditMode\]\n\ ...\n\ #\ Deactivate\ 'edit\ mode'\ on\ the\ supertext\ megawidget\n\ bindtags\ .t\ \[lsearch\ -inline\ -all\ -exact\ -not\ \[bindtags\ .t\]\ SuperEditMode\]\nnothing\ will\ happen\ (again).\ This\ is\ for\ the\ very\ same\ reason\ as\ before:\ because\ the\ path\ ''.t''\ means\ the\ frame\ around\ the\ text\ widget\ and\ not\ the\ text\ widget\ itself.\n======\n\nThe\ way\ to\ overcome\ this\ is\ surprisingly\ simple:\ add\ an\ execution\ trace\ to\ the\ '''bindtags'''\ command.\ There\ are,\ of\ course,\ many\ ways\ to\ do\ it,\ but\ here\ is\ a\ simple\ proc\ that\ will\ give\ you\ good\ results.\ It\ combines\ the\ bindtags\ for\ both\ the\ frame\ and\ the\ specified\ subwidget,\ and\ removes\ the\ subwidget\ from\ the\ resulting\ list\ of\ tags:\n\n======\n\ proc\ UpdateBindtags\ \{win\ subwin\ args\}\ \{\n\ \ \ \ \ \ \ \ \ if\ \{(\$args\ eq\ \{\})\ ||\ (\$win\ in\ \[lindex\ \$args\ 0\])\}\ \{\n\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ combine\ the\ bindtags\ for\ the\ widget\ and\ subwidget\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ tags\ \[bindtags\ \$win\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ tags\ \{*\}\[bindtags\ \$subwin\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ tags\ \[lsort\ -unique\ \$tags\]\n\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ remove\ the\ subwidget's\ tag\ from\ the\ result\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ bindtags\ \$subwin\ \[lsearch\ -inline\ -all\ -exact\ -not\ \$tags\ \$subwin\]\n\ \ \ \ \ \ \ \ \ \}\n\ \}\n======\n\nNext,\ in\ your\ widget's\ creation/initialization\ code,\ make\ sure\ to\ perform\ the\ proper\ updates:\n\n======\n\ ::UpdateBindtags\ \$w\ \$w.text\n\ trace\ add\ execution\ bindtags\ leave\ \[list\ ::UpdateBindtags\ \$w\ \$w.text\]\n======\n\nAnd\ that's\ all\ there\ is\ to\ it!\n\nAs\ a\ side\ note,\ I'm\ not\ so\ sure\ that\ you\ always\ need\ to\ remove\ the\ subwidget's\ name\ from\ the\ list\ of\ tags.\ That\ is,\ of\ course,\ a\ matter\ to\ consider\ against\ your\ requirements\ and\ needs.\n----\n'''Intercepting\ changes\ to\ a\ widget's\ state'''\n\n\[KBK\]\ 2006-09-22:\ One\ thing\ that\ overloading\ can\ sometimes\ get\ you\ is\ the\ ability\ to\ act\ on\ changes\ to\ a\ widget's\ state.\ \ For\ instance,\ a\ text\ widget's\ characters\ can\ change\ only\ by\ the\ ''insert''\ and\ ''delete''\ widget\ commands\;\ its\ insertion\ cursor\ can\ be\ moved\ only\ by\ the\ ''mark\ set\ insert''\ command,\ and\ so\ on.\ \ These\ provide\ a\ limited\ number\ of\ places\ that\ you\ need\ to\ hook\ to\ attach\ new\ behaviours\ to\ the\ given\ actions.\ \ One\ worked\ example\ shows\ that\ you\ can\ provide\ a\ \[text\ variable\ for\ text\ widget\]s\ that\ function\ as\ multi-line\ entries.\n----\n'''Useful\ examples\ of\ small\ megawidgets''''\n\n''text\ widget\ with\ markup''\n\nA\ more\ meaningful\ example\ was\ triggered\ by\ a\ c.l.t\ post\ from\ \[Bryan\ Oakley\]:\n''it'd\ be\ nice\ to\ create\ text\ like\ \"some\ things\ are\ *bold*\ and\ some\ are\ _underlined_\"\ and\ be\ able\ to\ put\ that\ into\ a\ widget\ with\ a\ single\ call.''\ \nHere's\ a\ quick\ shot:\n\n======\n\ proc\ markuptext\ \{w\ args\}\ \{\n\ \ \ \ eval\ \[list\ text\ \$w\]\ \$args\n\ \ \ \ rename\ ::\$w\ ::_\$w\n\ \ \ \ proc\ ::\$w\ \{cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ set\ w\ \[lindex\ \[info\ level\ 1\]\ 0\]\n\ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ insert\ \ \{eval\ \[list\ markuptext'insert\ \$w\]\ \$args\}\n\ \ \ \ \ \ \ \ \ \ \ \ default\ \{eval\ \[list\ ::_\$w\ \$cmd\]\ \$args\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ set\ w\n\ \}\n\ proc\ markuptext'insert\ \{w\ position\ args\}\ \{\n\ \ \ \ if\ \{\[llength\ \$args\]==1\}\ \{set\ args\ \[lindex\ \$args\ 0\]\}\n\ \ \ \ foreach\ word\ \[split\ \$args\]\ \{\n\ \ \ \ \ \ \ \ \ if\ \{\$word==\"\"\}\ continue\n\ \ \ \ \ \ \ \ set\ tag\ \"\"\n\ \ \ \ \ \ \ \ if\ \{\[regexp\ \{^\\*(.+)\\*\$\}\ \$word\ ->\ word\]\}\ \{set\ tag\ bold\}\n\ \ \ \ \ \ \ \ if\ \{\[regexp\ \{^_(.+)_\$\}\ \ \ \$word\ ->\ word\]\}\ \{set\ tag\ underline\}\n\ \ \ \ \ \ \ \ ::_\$w\ insert\ \$position\ \"\$word\ \"\ \$tag\n\ \ \ \ \}\n\ \}\n\ #-----------------------------\ Test\ and\ demo\ code...\n\ pack\ \[markuptext\ .t\]\n\ .t\ tag\ configure\ bold\ \ \ \ \ \ -font\ \{Arial\ 10\ bold\}\n\ .t\ tag\ configure\ underline\ -font\ \{Arial\ 10\ underline\}\n\ .t\ insert\ end\ \"Test\ for\ *bold*\ and\ _underlined_\ words...\\\n\ \ \ \ \ with\ \\\"quotes\\\"\ and\ \\\{unbalanced\ braces\"\n======\n\n\n\[LV\]\ There\ are\ several\ examples\ for\ markup\ languages.\ \ For\ instance,\ this\ wiki\ uses\ ''''\ to\nmark\ a\ request\ for\ emphasis\ (italics)\ and\ ''''''\ as\ a\ request\ for\ strong\ (bold)\ highlighting.\ \ This\ wiki\ doesn't\ have\ a\ notation\ for\ underlining.\n\nThen\ there's\ '''setext'''\ \[http://www.valdemar.net/~erik/setext/\],\ which\ uses\ similar\ markup\ as\ you've\ implemented.\ \ And\ there\ is\ a\n\[mime\]\ richtext\[http://www.ietf.org/rfc/rfc1341.txt\]\ (not\ the\ same\ as\ the\ \[Microsoft\]\ rich\ text),\ which\ has\ its\ own\nmarkup.\ \ See\ \[A\ wiki-like\ markup\ language\ for\ the\ text\ widget\]\ for\ an\ example.\n\n''a\ scrolled\ widget\ megawidget''\n\nThis\ widget\ can\ be\ used\ to\ produce\ a\ standard\ widget\ with\ scrollbars\ around\ it.\ You\ call\ it\ with\ a\ standard\ widget\ as\ a\ parameter\ and\ specify,\ which\ scrollbars\ you\ want,\ and\ you\ get\ a\ scrolled\ widget\ of\ that\ type\ acting\ just\ like\ the\ standard\ thing.\ It\ just\ comes\ with\ functional\ added\ scrollbars:\n\n======\n\ \ \ \ \ \ \ \ #\ create\ a\ standard\ widget\ with\ scrollbars\ around\n\ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ #\ wigdet\ \ ->\ name\ of\ the\ widget\ to\ be\ created\n\ \ \ \ \ \ \ \ #\ parent\ \ ->\ path\ to\ the\ frame,\ in\ which\ the\ widget\ and\ the\ scrollbars\ should\n\ \ \ \ \ \ \ \ #\ \ \ \ \ \ \ \ \ \ \ \ be\ created\n\ \ \ \ \ \ \ \ #\ scrollx\ ->\ boolean\;\ create\ horizontal\ scrollbar?\n\ \ \ \ \ \ \ \ #\ scrolly\ ->\ boolean\;\ create\ vertical\ scrollbar?\n\ \ \ \ \ \ \ \ #\ args\ \ \ \ ->\ additional\ arguments\ passed\ on\ the\ the\ original\ widget\n\ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ #\ returns:\ the\ path\ to\ the\ created\ widget\ (frame)\n\ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ proc\ ScrolledWidget\ \{widget\ parent\ scrollx\ scrolly\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Create\ widget\ attached\ to\ scrollbars,\ pass\ thru\ \$args\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ frame\ \$parent\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ eval\ \$widget\ \$parent.list\ \$args\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Create\ scrollbars\ attached\ to\ the\ listbox\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$scrollx\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ scrollbar\ \$parent.sx\ -orient\ horizontal\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -command\ \[list\ \$parent.list\ xview\]\ -elementborderwidth\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ \$parent.sx\ \ \ \ \ \ \ \ \ -column\ 0\ -row\ 1\ -sticky\ ew\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$parent.list\ configure\ -xscrollcommand\ \[list\ \$parent.sx\ set\]\n\ \ \ \ \ \ \ \ \\\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$scrolly\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ scrollbar\ \$parent.sy\ -orient\ vertical\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -command\ \[list\ \$parent.list\ yview\]\ -elementborderwidth\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ \$parent.sy\ \ \ \ \ \ \ \ \ -column\ 1\ -row\ 0\ -sticky\ ns\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$parent.list\ configure\ -yscrollcommand\ \[list\ \$parent.sy\ set\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Arrange\ them\ in\ the\ parent\ frame\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ \$parent.list\ \ -column\ 0\ -row\ 0\ -sticky\ ewsn\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ columnconfigure\ \$parent\ 0\ -weight\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ grid\ rowconfigure\ \$parent\ 0\ -weight\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ hide\ the\ original\ widget\ command\ from\ the\ interpreter:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ interp\ hide\ \{\}\ \$parent\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Install\ the\ alias:\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ interp\ alias\ \{\}\ \$parent\ \{\}\ ScrolledWidgetCmd\ \$parent.list\n\ \ \ \ \ \ \ \ \ \ \ \ #\ fix\ the\ bindtags:\n\ \ \ \ \ \ \ \ \ \ \ \ bindtags\ \$parent.list\ \[lreplace\ \[bindtags\ \$parent.list\]\ 0\ 0\ \$parent\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \$parent\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ proc\ ScrolledWidgetCmd\ \{self\ cmd\ args\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[uplevel\ 1\ \[list\ \$self\ \$cmd\]\ \$args\]\n\ \ \ \ \ \ \ \ \}\n======\n\nTo\ create\ a\ scrolled\ text\ widget\ with\ both\ scrollbars,\ use:\n\n======\n\ \ ScrolledWidget\ text\ .t\ 1\ 1\n\n\n----\nTo\ see\ how\ a\ real\ megawidget\ framework\ does\ this\ work,\ start\ reading\ here:\ \[megawidget\]\n\n<<categories>>Arts\ and\ crafts\ of\ Tcl-Tk\ programming\ |\ GUI\ |\ Widget} CALL {my revision {Overloading widgets}} CALL {::oo::Obj2016165 process revision/Overloading+widgets} CALL {::oo::Obj2016163 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