''Questions? Suggestions? Errors?'' \n\n|Name|AT |DOT|\n|dae |douglasedmunds |com|\n\n''About''\n\nThis wiki is based on [[TiddlyWiki |http://tiddlywiki.com]]. The boxes of info are called tiddlers. This site is very hypertext-linked. You can click any bold blue item or use one of the menu choices above for links to other tiddlers. The search box at the right is also very handy. \n\nI am using a slightly modified version available at [[MonkeyPirateTiddlyWiki|http://mptw.tiddlyspot.com]]. \nThe site in not writeable (This is not a public wiki like Wikipedia). You may occasionally get a message about\nsaving changes. Disregard them.\n\n----\n''I want a local copy!'' \nBear in mind that this file is being updated hourly, daily, weekly, regularly, now and then, and occasionally.\nTo download a copy of the most recent version, [[right-click here |http://erl.dougedmunds.com/index.html]], and save the file to disk. Everything is in that one file.\n\n\nAuthor: @@Doug Edmunds@@\n
<<option chkGenerateAnRssFeed>> GenerateAnRssFeed\n<<option chkOpenInNewWindow>> OpenLinksInNewWindow\n<<option chkSaveEmptyTemplate>> SaveEmptyTemplate\n<<option chkToggleLinks>> Clicking on links to tiddlers that are already open causes them to close\n^^(override with Control or other modifier key)^^\n<<option chkHttpReadOnly>> HideEditingFeatures when viewed over HTTP\n<<option chkForceMinorUpdate>> Treat edits as MinorChanges by preserving date and time\n^^(override with Shift key when clicking 'done' or by pressing Ctrl-Shift-Enter^^\n<<option chkConfirmDelete>> ConfirmBeforeDeleting\nMaximum number of lines in a tiddler edit box: <<option txtMaxEditRows>>\nFolder name for backup files: <<option txtBackupFolder>>\n<<option chkInsertTabs>> Use tab key to insert tab characters instead of jumping to next field
/***\n| Name|CloseOnCancelPlugin|\n| Description|Closes the tiddler if you click new tiddler then cancel. Default behaviour is to leave it open|\n| Version|3.0 ($Rev: 1845 $)|\n| Date|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $|\n| Source|http://mptw.tiddlyspot.com/#CloseOnCancelPlugin|\n| Author|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\n***/\n//{{{\nmerge(config.commands.cancelTiddler,{\n\n handler_orig_closeUnsaved: config.commands.cancelTiddler.handler,\n\n handler: function(event,src,title) {\n this.handler_orig_closeUnsaved(event,src,title);\n if (!store.tiddlerExists(title) && !store.isShadowTiddler(title))\n story.closeTiddler(title,true);\n return false;\n }\n\n});\n\n//}}}\n\n
Code is from the examples in the GS Users Guide that comes with the release. \n\nI have added notes in front of the code. I have made\nno changes to the code, except as noted.\n
//{{{\nconfig.options.chkHttpReadOnly = false; // means web visitors can experiment with your site by clicking edit\nconfig.options.chkInsertTabs = true; // tab inserts a tab when editing a tiddler\nconfig.views.wikified.defaultText = ""; // don't need message when a tiddler doesn't exist\nconfig.views.editor.defaultText = ""; // don't need message when creating a new tiddler \n//}}}\n
There are 8 containers (the parents on the right below).\nThe parent container must be created before the child object is created.\nIt is probably best to learn the containers before the children.\n\nThis chart is from the gs User's Guide:\n|Objects |Valid Parents |\n|[[window]] |[[window]], [[gs]] |\n|[[button]], [[radiobutton]], [[checkbutton]], [[canvas]], [[editor]], [[entry]], [[frame]], [[grid]], [[label]], [[listbox]], [[menubar]], [[scale]] |[[frame]], [[window]] |\n|[[menubutton]] |[[menubar]], [[window]], [[frame]] |\n|[[gridline]] |[[grid]] |\n|[[menuitem]] |[[menu]] |\n|[[menu]] |[[menubutton]], [[menuitem]] (with {itemtype, cascade }), [[window]], [[frame]] (the last two are for popup menus) |\n|[[arc]], [[image]], [[line]], [[oval]], [[polygon]], [[rectangle]], [[text]] |[[canvas]] |\n\n\n
{{{\n3.5 Data Types\n\nAs previously stated, each object is described in terms of its options. This section defines the data types for options.\n\nAnchor|Align.\n n|w|s|e|nw|se|ne|sw|center \n\nAtom.\n An Erlang atom such as myWay. \n\nBool.\n true or false \n\nColor.\n {R,G,B}, or a the predefined name red,green, blue, white, black, grey, or yellow. For example {0,0,0} is black and {255,255,255} is white. \n\nCursor.\n A mouse cursor, or any of the following: arrow, busy, cross, hand, help, resize, text, or parent. parent has a special meaning, namely that this object will have the same cursor as its parent. \n\nFileName.\n FileName is a string. The file name may include a directory path and should point out a file of a suitable type. The path can be either absolute or relative to the directory from where Erlang was started. \n\nFloat.\n Any float, for example 3.1415. \n\nFont.\n A Font is represented as a two or three tuple: {Family, Size} or {Family, Style, Size}, where Style is bold, italic, or a combination of those in a list. Size is an arbitrary integer. Family is a typeface of type times, courier, helvetica, symbol, new_century_schoolbook, or screen (which is a suitable screen font). \n\nInt.\n Any integer number, for example 42. \n\nLabel.\n A label can either be a plain text label {text, String}, or an image {image, ~FileName} where ~FileName should point out a bitmap. \n\nString.\n An Erlang list of ASCII bytes. For example, "Hi there"=[72,105,32,116,104,101,114,101] \n\nTerm.\n Any Erlang term. \n\nCatchall\n In cases where the type is self-explanatory, the name of the parameter is used. For example, {move, {Dx,Dy}}.\n\n(That is pathetic as an explanation. Dx,Dy is self-explanatory? What is the type of Dx or Dy? Presumably an integer, but why not just say that then?)\n}}}
The source of this code is: gs_widgets.erl in the gs src directory\nSome of the objects are not documented. See [[Undocumented objects]] for a list.\n \n{{{\ndefault_options(arc) -> [{coords, [{0,0}, {0,0}]}];\n\ndefault_options(button) -> [{click,true}, {height,30}, {width,100}, {x,0},\n {y,0}];\n\ndefault_options(canvas) -> [{height,200}, {scrollregion,{0,0,300,200}},\n {width,300}, {x,0}, {y,0}];\n\ndefault_options(checkbutton) -> [{click,true}, {height,30}, {width,100}, {x,0},\n {y,0}];\n\ndefault_options(editor) -> [{height,200}, {width,300}, {x,0}, {y,0}];\n\ndefault_options(entry) -> [{height,30}, {width,100}, {x,0}, {y,0}];\n\ndefault_options(frame) -> [{height,100}, {width,150}, {x,0}, {y,0}];\n\ndefault_options(grid) -> [{bg,grey}, {cellheight,20},\n {columnwidths, [80,80,80,80]},\n {fg,black}, {font,{screen, 12}},\n {height,100},\n {hscroll,bottom},\n {rows,{1,10}},\n {vscroll,right},\n {width,300},\n {x,0}, {y,0}];\n\ndefault_options(gridline) -> [{click,true}, {doubleclick,false}, {row,undefined}];\n\ndefault_options(gs) -> [{kernel,false},\n {{default,all,font}, {screen,12}}];\n\ndefault_options(image) -> [{anchor,nw}, {coords,[{0,0}]}];\n\ndefault_options(label) -> [{height,30}, {width,100}, {x,0}, {y,0}];\n\ndefault_options(line) -> [{coords, [{-1,-1},{-1,-1}]}];\n\ndefault_options(listbox) -> [{height,130}, {hscroll,true},\n {selectmode,single}, {vscroll,true},\n {width,125}, {x,0}, {y,0}];\n\ndefault_options(menu) -> [];\n \ndefault_options(menubar) -> [{bw,2}, {height,25}, {highlightbw,0},\n {relief,raised}];\n\ndefault_options(menubutton) -> [{anchor,nw}, {side,left}];\n\ndefault_options(menuitem) -> [{click,true}, {index,last}, {itemtype,normal}];\n\ndefault_options(message) -> [{height,75}, {width,100}];\n\ndefault_options(oval) -> [{coords, [{0,0},{0,0}]}];\n\ndefault_options(polygon) -> [{coords, [{0,0},{0,0}]}, {fg,black}, {fill,none}];\n\ndefault_options(prompter) -> [{height,200}, {prompt,[]}, {width,300}];\n\ndefault_options(radiobutton) -> [{click,true}, {height,30}, {width,100},\n {x,0}, {y,0}];\n\ndefault_options(rectangle) -> [{coords, [{0,0},{0,0}]}];\n\ndefault_options(scale) -> [{click,true}, {height,50}, {width,100},\n {x,0}, {y,0}];\n \ndefault_options(scrollbar) -> [];\n\ndefault_options(text) -> [{anchor,nw}, {coords,[{0,0}]}, {justify,left}];\n\ndefault_options(window) -> [{configure,false}, {cursor,arrow}, {destroy,true},\n {height,200}, {map,false}, {width,300}];\n}}}
[[GS Objects]]\n[[Introduction]]\n
[[MptwEditTemplate]]\n
/***\n| Name:|ExtentTagButtonPlugin|\n| Description:|Adds a New tiddler button in the tag drop down|\n| Version:|3.0 ($Rev: 1845 $)|\n| Date:|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $|\n| Source:|http://mptw.tiddlyspot.com/#ExtendTagButtonPlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\n***/\n//{{{\n\n// can't hijack a click handler. must redefine this entirely.\n// would be good to refactor in the core...\n// this version copied from 2.1.3 core\n\n// Event handler for clicking on a tiddler tag\nfunction onClickTag(e)\n{\n if (!e) var e = window.event;\n var theTarget = resolveTarget(e);\n var popup = Popup.create(this);\n var tag = this.getAttribute("tag");\n var title = this.getAttribute("tiddler");\n if(popup && tag)\n {\n var tagged = store.getTaggedTiddlers(tag);\n var titles = [];\n var li,r;\n for(r=0;r<tagged.length;r++)\n if(tagged[r].title != title)\n titles.push(tagged[r].title);\n var lingo = config.views.wikified.tag;\n\n wikify("<<newTiddler label:'New tiddler' tag:"+tag+">>",createTiddlyElement(popup,"li")); // <---- the only modification\n\n if(titles.length > 0)\n {\n var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);\n openAll.setAttribute("tag",tag);\n createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");\n for(r=0; r<titles.length; r++)\n {\n createTiddlyLink(createTiddlyElement(popup,"li"),titles[r],true);\n }\n }\n else\n createTiddlyText(createTiddlyElement(popup,"li",null,"disabled"),lingo.popupNone.format([tag]));\n createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");\n var h = createTiddlyLink(createTiddlyElement(popup,"li"),tag,false);\n createTiddlyText(h,lingo.openTag.format([tag]));\n }\n Popup.show(popup,false);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n}\n\n//}}}\n\n
''All the GS Event options'' \nconfigure, buttonpress, buttonrelease, enter, leave, focus, keypress, keyrelease, motion, click, doubleclick, destroy\n\n''An events analogy'' \nThe event is 'ring'. The objects are cellphone and toothpick\n1. Cellphones can ring, toothpicks can't ring. \n2. A cellphone doesn't ring unless it is on. \n3. Someone has to hear it ring.\n\nThink object first, event second, message third\n* @@Can@@ this type of object recognize this type of event? \nFor example, a [[window]] recognizes buttonpress, but not click. \n*If so, @@Make the object recognize the event@@ \n** Activate it in the process of creating the object. \n*Finally, @@do something@@ with it.\n**See [[GS Messages]]\n\nDefault activation status of certain events. \n|{Option,Value} |Default|\n|{buttonpress, Bool} |false|\n|{buttonrelease, Bool} |false|\n|{enter, Bool} |false|\n|{leave, Bool} |false|\n|{keypress, Bool} |false|\n|{motion, Bool} |false|\n\n\n\nIf the default setting is false, then the sending object must be configured, for example: \n{{{\n gs:config(Win,[{configure,true},{keypress,true}]),\n gs:config(Win,[{buttonpress,true},{buttonrelease,true}]),\n}}}\n\n\n\nSee [[GS Messages]] for format and usage of options in message passing.\n\n
Exported functions
Each object/option combination can have a unique message, consisting\nof two fields: Data (anything) and Arg (a list). \nYou decide what is held in the Data field, when you create/configure the object.\nThe option (third element in the tuple) controls what is sent in the Arg field. \n\nAs each Arg is a list, the last item extracted will alway be the 'head of the tail', \nand the tail will be discarded. E.g., [Something, Head | _ ]. \n\n''configure'' \n*{gs,ObjectID,configure,Data,[W,H | Rest]}\n**W = width\n**H = height \n***Applies to many objects, not just window (put configure in the search box to see where)\n***Tracks size change\n \n''buttonpress''\n* {gs,ObjectId,buttonpress,Data,[MouseButton,X,Y|_]}\n**MouseButton = 1, 2 or 3\n**X = coordinate (left-right) of mouse when pressed\n**Y = coordinate (up-down) of mouse when pressed \n**_ = unknown tail content, ignored.\n\n''buttonrelease''\n* {gs,ObjectId,buttonrelease,Data,[MouseButton,X,Y|_]}\n**MouseButton = 1, 2 or 3\n***1 = left \n***2 = right\n***3 = middle\n**X = coordinate (left-right) of mouse when pressed\n**Y = coordinate (up-down) of mouse when pressed \n\n''enter''\n* {gs,ObjectId,enter, Data,[]}\n**Applied to the mouse pointer. \n**The event can be trapped, but there is no additional info provided\n \n''leave'' \n* {gs,ObjectId,leave, Data,[]}\n**Applied to the mouse pointer. \n**The event can be trapped, but there is no additional info provided\n\n''focus'' \n* {gs,ObjectId,focus, Data,[FocusFlag|_]}\n**FocusFlag = 1 or 0\n***1 = object has gained keyboard focus.\n***0 = object has lost keyboard focus.\n****Not sure if tab/return automatically cause keyboard focus change\n\n''keypress''\n* {gs,ObjectId,keypress,Data,[Keysym,Keycode,Shift,Control|_]}\n**Keysym = examples: a,b,c.., 1,2,3..., 'Return', 'Delete', 'Insert', 'Home', 'BackSpace', 'End'. (single quotes required)\n**Keycode = keycode number for the key that was pressed\n**Shift = 1 or 0 \n***1 = held down when other key pressed\n***0 = not held down when other key pressed\n**Control = 1 or 0 \n***1 = held down when other key pressed\n***0 = not held down when other key pressed\n\n''keyrelease'' \n*not documented\n\n''motion'' \n*{gs,ObjectId,motion,Data,[X,Y|_]}\n**X = position (left-right) of mouse pointer\n**Y = position (up-down) of mouse pointer\n*** Run the code in [[ex07]] to see how erlang responds to motion. Try very fast motion.\n\n''click'' \n*User guide says Arg is 'object-specific'. \nclick - button examples\n* {gs,Any_Rb,click,Data,[Text, Grp, a | Rest]} \n* {gs,rb3,click,Data,[Text, Grp, b | Rest]} \n\n''doubleclick''\n*User guide says Arg is 'object-specific'. \n\nclick and doubleclick - listbox \n*{gs, ListBox, click, Data, [Index, Text,Bool | _]}\n*{gs, ListBox, doubleclick, Data, [Index, Text,Bool | _]}\n**Bool = true or false \n***true = object is selected\n***false = object is de-selected.\nSee [[ex10]]\nclick and doubleclick are two discrete events\n\nclick and doubleclick - gridline \n*{gs, GridLineId, click, Data, [Col, Row, Text | _]}\n*{gs, GridLineId, doubleclick, Data, [Col, Row, Text | _]}\n**Col = column\n**Row = row\n**Text = text\n\n \n''destroy''\n*{gs,ObjectID,destroy,_,_} \n**Applies to many objects, not just window\n**Be sure to capture the destroy message from window, otherwise erlang may hang.\n**Does not cause gs to stop. \n \n----\n\n''Physical event descriptions'' \n\nArgs are the last element of the gs message: {gs, IdOrName, EventType, Data, Args}. All are lists.\n\n|Event |Args |Description of event|\n|buttonpress |[ButtonNo,X,Y&#124;_] |A mouse button was pressed over the object.|\n|buttonrelease |[ButtonNo,X,Y&#124;_] |A mouse button was released over the object.|\n|enter |[] |Delivered when the mouse pointer enters the objects area.|\n|focus |[Int&#124;_] |Keyboard focus has changed. 0 means lost focus. 1 means gained focus.|\n|keypress |[KeySym,Keycode, Shift, Control&#124;_] |A key has been pressed.|\n|leave |[] |Mouse pointer leaves the object.|\n|motion |[X,Y&#124;_] |The mouse pointer is moving in the object. Used when tracking the mouse in a window.|\n|click |<object specific> |Pressing a button or operating on a object in some predefined way.|\n|doubleclick |<object specific> |Pressing the mouse button twice quickly. Useful with list boxes.|\n\nkeyrelease (letting go of the key) no documentation of the Args.\nconfigure (resizing of an object) -- see above.\n----\n\nEvents aren't much use unless they provide information. The information is sent\nin a message when the event occurs. That message is handled like any\nother message, typically, by a receive block inside a loop function.\n\nIt is very likely that the receive block will be handling messages from\nseveral different objects in the window. The trick is to pattern match correctly, \nso that the event eventually triggers the result you want. This site\ndoes not get into pattern matching. If you don't understand pattern matching,\ngo read the official docs, then come back here later. \n\nEvents are sent in gs messages (5-tuple). \n@@{gs, IdOrName, EventType, Data, Args}@@\n* gs is a tag which says it is an event from the gs graphics server.\n* IdOrName contains the object identifier or the name of the object in which the event occurred.\n* EventType contains the type of event which has occurred. In the example shown, it is either click or enter.\n* Data is a field which the user can set to any Erlang term. It is very useful to have the object store arbitrary data which is delivered with the event.\n* Args is a list which contains event specific information. In a motion event, the Args argument would contain the x and y coordinates.\n\nHere is an example. \nA click event is received from an object named button1:\n{{{\nreceive \n{gs,button1,click,Data,Arg} -> do something, using Data and Arg\nend\n}}}\nIf Data wasn't important you could code it like this:\n{{{\nreceive \n{gs,button1,click,_Data,Arg} -> do something, using Arg\nend\n}}}\n\n
[[Undocumented objects]]\n[[Containers]] : Parent child relationship of objects \n\nItems below are all the GS objects. Click one.\n
Material here comes from several sources. \n*@@comments@@ found in the gs src files. \n*'defaults' written as @@code@@ in gs_widgets.erl.\n\nAlways test out code that uses gs. \n''Erlang does not check whether options are valid.''\nIf you type {widht, 10} instead of {width,10} Erlang will compile fine\nbut tcl/tk will either not display the object or crash when you run it. \n\nTo find all the options for an object:\n* Find the object here (i.e., [[frame]]). Start with [[GS Objects]]. \n* Look at [[Generic options]] which apply to lots of objects.\n* Look at [[Default options]] (this info also appears on each object's page).\n* What many event options do is covered on [[GS Events]].
@@Code notes@@\nThis template is a starting point. If you have suggestions, email me.\nI have tried to make this template tie in with the format of the tcl\ncode generated by Visual Tcl, using ''place manager'' geometry,\nso you can most easily copy over the values. By using a process for\nthe window, if the loop ends, the process dies, removing the window.\n\n{{{\n\n-module(gui).\n-export([start/0, init/0]).\n\nstart() -> spawn (gui,init,[]).\n\ninit() -> \n S = gs:start(),\n create_window(S),\n create_objs(),\n config_objs(),\n loop().\n\n%% look at vtcl section # CREATING WIDGETS for "wm geometry" line \n%% There are TWO. Use the second one\n%% which has your window title in the 'wm title' \n%% wm geometry $top 381x360+423+117; update\n%% use first two numbers: width = 381 height = 360\n\ncreate_window(S) ->\n gs:create(window,window1,S,\n [{title, "Title of Window here"},{width,381},{height,360}]).\n\n%% Just below the last "wm" line, you will see 'object' lines \n%% such as button, label, entry etc.\n%% Pick out these aspects 1. object name (like 'button1')\n%% and anything that starts with a '-' \n%% (like -text {add me}, -background white)\n%% Include them in the gs:create entry, using tuples\n%% You need to use the correct option identifiers: bg, not background\n\ncreate_objs() ->\n gs:create(label,label1,window1,[{label,{text,"Put label1 text here"}}]),\n gs:create(button,button1,window1,[{label, {text,"add me"}}]),\n gs:create(button,button2,window1,[{label, {text,"exit"}}]),\n gs:create(entry,entry1,window1,[{bg,white}]),\n \n %%for text with scrollbars, use an editor object with vscroll, hscroll\n gs:create(editor,editor1,window1, \n [{bg, white},{vscroll, right}]),\n\n true. %%this avoids missing comma issues\n\n%% Look at the vtcl section # SETTING GEOMETRY\n%% Each object starts with a 'place' line\n%% Match up the line with the right object (lab, ent, but) and\n%% put the x, y, width, height info into the template, as well as \n%% anything else that shows up there.\n\nconfig_objs() -> \n gs:config(label1, [{x, 90}, {y, 20}, {width, 138}, {height, 29}]),\n gs:config(button1,[{x, 90}, {y, 275}, {width, 62}, {height, 36}]),\n gs:config(button2,[{x, 225}, {y, 275}, {width, 60}, {height, 36}]),\n gs:config(entry1, [{x, 46}, {y, 65}, {width, 246}, {height, 44}]),\n %% if you are using scroll bars add about 14 pixels to width and/or height (296 ->310) \n gs:config(editor1, [{x, 45}, {y, 140}, {width, 310}, {height, 103}]),\n\n %% Optional: Mask highlightfg with window bg color. Example:\n %% Hide_focus = gs:read(window1,bg),\n %% gs:config(entry1,[{highlightfg, Hide_focus}]),\n \n gs:config(window1, {map,true}). %%display\n\nloop() ->\n receive\n %% format for button click, copy as needed, then modify\n {gs,button1,click,_,_} -> % button 1 pressed\n io:format("Button 1 pressed!~n",[]),\n loop();\n {gs,button2,click,_,_} -> \n io:format("Button 2 pressed, closing window ~n",[]); %process dies \n {gs,_,destroy,_,_} -> true; % called when window is closed. \n {end_without_semicolon_message} -> true % \n end.\n\n}}}
This page is too long right now. I will break it up later.\n\nConceptually, gs is built around objects, not options. If you look at the source\ncode you will see, for example, gstk_frame.erl, gstk_button.ert. Options, on the other \nhand are built into the code of the particular object. If you look at the code for\n[[button]] and try to find the definition of the option "disabledfg", you'll find this: \n\n\n00162: case Option of\n00163: {bitmap, Bitmap} -> {s, [" -bi @", Bitmap]};\n00164: {disabledfg, Color} -> {s, [" -disabledf ", gstk:to_color(Color)]};\n00165: {underline, Int} -> {s, [" -un ", gstk:to_ascii(Int)]};\n00166: {wraplength, Int} -> {s, [" -wr ", gstk:to_ascii(Int)]};\n \n00183: read_option(Option,Gstkid, TkW,DB,_) ->\n00184: case Option of\n00185: disabledfg -> tcl2erl:ret_color([TkW, " cg -disabledf"]);\n00186: underline -> tcl2erl:ret_int([TkW, " cg -un"]);\n00187: wraplength -> tcl2erl:ret_int([TkW, " cg -wr"]);\n \n\nIn other words, internal muck. If you really understand tcl/tk, you might have some sense\nof what is going on. But that's beyond me. \n\n----\n\n\n@@label and text@@\n\nThe atoms 'label' and 'text' are used both as objects and as options\n(if this stuff wasn't hard enough already).\n\nLook at this example, until you understand it.\n(click around this website for help).\n{{{\ngs:create(button,b1,win1,[{label, {text,"Press Me"}}]),\n}}}\nThe 'object' is button.\nThe 4th argument of create/4 is a list of options.\nThe button has one option set: label.\nThe way you set an option is to name the option (the key)\nand provide a value: \nkey: label\nvalue: {text,"Press me"}.\n\nWhy like that? Look at the syntax of the label option.\nYou can find it if you click [[button]]. There are two alternatives:\ntext and image. \n{{{\n%% label {text, String} | {image, BitmapFile} \n}}}\n \n----\nFrom Official Docs\nConfusion runs supreme. Whole lists, not partial lists, please!\n----\n3.3 Config-Only Options\n\nMost options are read/write key-value tuples such as {select,true|false} and {map,true|false, but some options are by nature write-only, or read-only. For example, buttons can flash for a short time and canvas objects can be moved dx, dy. The following table exemplifies @@some@@ config-only options:\n\nConfig-Only Options \n|Config-Only |Description|\n|flash |Causes the object to flash for 2 seconds.|\n|raise |Raises the object on top of other overlapping objects.|\n|{move, {Dx, Dy}} |Moves the object relative to its current position.|\n\n{{{\ngs:config(Button,[flash])\n}}}\n\ncauses the button to flash.\nNote: do not use {}'s around flash or raise (requirement???)\n\n----\n\n3.4 Read-Only Options\n\nThe opposite of config-only options are read-only options. The following table exemplifies @@some@@ read-only options:\n\nRead-Only Options \n|Read-Only |Return |Description|\n|size |Int |The number of items (entries).|\n|{get, Index} |String |The entry at index Index.|\n\n{{{\nEntryString = gs:read(Listbox,{get, Index}), \n}}}\nis an example.\nNote: do not use {}'s around size.\n\n
@@Generic Options@@\n|{Option,Value} |Default |Description |\n|beep |<unspec> |A beep will sound. Applies to all objects. |\n|{bg, Color} |<unspec> |Background color. Applies to objects which have a background color. |\n|{data, Term} |[] |Always delivered with the event in the data field. Applies to all objects. |\n|{default,Objecttype,{Key,Value}} |<unspec> |Applies to all container objects. Specifies the default value for an option for children of type Objecttype.|\n|{enable, Bool} |true |Objects can be enabled or disabled. A disabled object cannot be clicked on, and text cannot be entered. Applies to buttons, menuitem, entry, editor, scale. |\n|{font, Font} |<unspec> |Applies to all text related objects and the grid. |\n|{fg, Color} |<unspec> |Foreground color. Applies to objects which have a foreground color. |\n|flush |<unspec> |Ensures that front-end and back-end are synchronized. Applies to all objects. |\n|{setfocus, Bool} |<unspec> |Set or remove keyboard focus to this object. Applies to objects which can receive keyboard events.|\n\n----\n\nThe following options apply to objects which @@can have a [[frame]] as parent@@. Also see [[Containers]]. \nCoordinates are relative to the parent.\n\n@@Generic Options (Frame as Parent)@@\n|{Option,Value}|Default|Description|\n|{cursor, Cursor}|parent|The appearance of the mouse cursor.|\n|{height, Int}|<unspec>|The height in pixels.|\n|{pack_x, Column|{StartColumn,EndColumn}}|<unspec>|Packing position. See The Packer section.|\n|{pack_y, row|{Startrow,Endrow}}|<unspec>|Packing position. See The Packer section.|\n|{pack_xy, {Column,row}}|<unspec>|Packing position. See The Packer section.|\n|{width, Int}|<unspec>|The width in pixels.|\n|{x, Int}|<unspec>|The x coordinate within the parent objects frame in pixels. 0 is to the left.|\n|{y, Int}|<unspec>|The y coordinate in pixels. 0 is at the top.|\n\n----\n\n@@Generic Config-Only Options@@ \n|Config-Only |Description|\n|lower |Lowers this object to the bottom in the visual hierarchy.|\n|raise |Lowers this object in the visual hierarchy.|\n\n----\nThe following table lists generic Read-Only options:\n\n@@Generic Read-Only Options@@ \n|Read-Only |Return |Description|\n|children |[ObjectId1, ..., ObjectIdN] |All children|\n|{choose_font,Font}|Font|Return the font that is actually used if a particular font is given.|\n|id |ObjectId |Return the object id for this object. Useful if the object is a named object.|\n|{font_wh,{Font,Text}} |{Width,Height} |Return the size of a text in a specified font. It returns the size of the font that is actually chosen by the back-end.|\n|type |Atom |The type of this object.|\n|parent |ObjectId |The parent of this object.|\n\n----\n\n@@Generic Event Options@@ \n|{Option,Value} |Default|\n|{buttonpress, Bool} |false|\n|{buttonrelease, Bool} |false|\n|{enter, Bool} |false|\n|{leave, Bool} |false|\n|{keypress, Bool} |false|\n|{motion, Bool} |false|\n
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:\n* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)\n* MainMenu: The menu (usually on the left)\n* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened\nYou'll also need to enter your username for signing your edits: <<option txtUserName>>\n\nSee also MonkeyPirateTiddlyWiki.\n
config.options.chkHttpReadOnly = true;
/***\n| Name|HideWhenPlugin|\n| Description|Allows conditional inclusion/exclusion in templates|\n| Version|3.0 ($Rev: 1845 $)|\n| Date|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $|\n| Source|http://mptw.tiddlyspot.com/#HideWhenPlugin|\n| Author|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\nFor use in ViewTemplate and EditTemplate. Example usage:\n{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}\n{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}\n***/\n//{{{\n\nwindow.removeElementWhen = function(test,place) {\n if (test) {\n removeChildren(place);\n place.parentNode.removeChild(place);\n }\n};\n\nmerge(config.macros,{\n\n hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( eval(paramString), place);\n }},\n\n showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( !eval(paramString), place);\n }},\n\n hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( tiddler.tags.containsAll(params), place);\n }},\n\n showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( !tiddler.tags.containsAll(params), place);\n }},\n\n hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( tiddler.tags.containsAny(params), place);\n }},\n\n showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( !tiddler.tags.containsAny(params), place);\n }},\n\n hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( tiddler.tags.containsAll(params), place);\n }},\n\n showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( !tiddler.tags.containsAll(params), place);\n }},\n\n hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);\n }},\n\n showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);\n }}\n\n});\n\n//}}}\n\n
This website focuses on Erlang's Graphic System (gs). \nIf you've not been here before, start with [[GS Objects]].\nDo you wish there was a GUI Builder? Click [[Using Visual Tcl]]. \n\nPlease [[send me an email |About]] if you see an error. \n-- Doug Edmunds\n
* [[Erlang.org| http://erlang.org]] Get a copy of Erlang\n* [[TrapExit.org | http://trapexit.org]] Tutorials, forums, help\n* Like this program? Visit [[MonkeyPirateTiddlyWiki|http://mptw.tiddlyspot.com]]\n* [[ets and dets |http://dougedmunds.com/z_erlang_wiki]] Explorations on those modules (dokuwiki format).\n* [[About]] me and this site.\n
[[GS Objects]]\n[[GS Options]]\n[[Containers]]\n[[GS Events]]\n[[GS Messages]]\n[[Code |Code from GS User's Guide]]\n[[GS Functions]]\n[[Visual Tcl |Using Visual Tcl]]\n[[Links]]\nGettingStarted\nToDoList
[[MonkeyPirateTiddlyWiki|http://mptw.tiddlyspot.com]] is a distribution of [[TiddlyWiki|http://www.tiddlywiki.com/]] created by Simon Baird. See [[the web site|http://mptw.tiddlyspot.com/]] for more information.\n!!Upgrading ~MonkeyPirateTiddlyWiki\nThis "empty" ~MonkeyPirateTiddlyWiki file comes pre-installed with the core ~MonkeyPirateTiddlyWiki plugins. You can upgrade these core plugins to the latest version by doing the following:\n* Click ImportTiddlers\n* Click "Choose..." and select "~MptwUpgradeURL"\n* Click "fetch"\n* Click the checkbox in the first column heading to select all tiddlers\n* Click "More actions..." and select "Import these tiddlers"\n* Click "OK" to confirm you want to overwrite the tiddlers\n* Save and reload\n
/***\n| Name|MptwLayoutPlugin|\n| Description|A package containing templates and css for the MonkeyPirateTiddlyWiki layout|\n| Version|3.0 ($Rev: 1845 $)|\n| Source|http://mptw.tiddlyspot.com/#MptwLayoutPlugin|\n| Author|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\n!Notes\nPresumes you have TagglyTaggingPlugin installed. To enable this you should have a PageTemplate containing {{{[[MptwPageTemplate]]}}} and similar for ViewTemplate and EditTemplate.\n***/\n//{{{\n// used in MptwViewTemplate\n//config.mptwDateFormat = 'DD/MM/YY';\nconfig.mptwJournalFormat = 'Journal DD/MM/YY';\n//config.mptwDateFormat = 'MM/0DD/YY';\nconfig.mptwDateFormat = 'YYYY/0MM/0DD';\n//config.mptwJournalFormat = 'Journal MM/0DD/YY';\n\nconfig.shadowTiddlers.GettingStarted += "\sn\snSee also MonkeyPirateTiddlyWiki.";\n\n//}}}\n\n//{{{\nmerge(config.shadowTiddlers,{\n\n'MptwEditTemplate':[\n "<!--{{{-->",\n "<!--- http://mptw.tiddlyspot.com/#MptwEditTemplate ($Rev: 1829 $) --->",\n "<div class=\s"toolbar\s" macro=\s"toolbar +saveTiddler saveCloseTiddler closeOthers -cancelTiddler cancelCloseTiddler deleteTiddler\s"></div>",\n "<div class=\s"title\s" macro=\s"view title\s"></div>",\n "<div class=\s"editLabel\s">Title</div><div class=\s"editor\s" macro=\s"edit title\s"></div>",\n "<div class=\s"editLabel\s">Tags</div><div class=\s"editor\s" macro=\s"edit tags\s"></div>",\n "<div class=\s"editorFooter\s"><span macro=\s"message views.editor.tagPrompt\s"></span><span macro=\s"tagChooser\s"></span></div>",\n "<div macro=\s"showWhenExists EditPanelTemplate\s">[[EditPanelTemplate]]</div>",\n "<div class=\s"editor\s" macro=\s"edit text\s"></div>",\n "<!--}}}-->"\n].join("\sn"),\n\n'MptwPageTemplate':[\n "<!--{{{-->",\n "<!-- http://mptw.tiddlyspot.com/#MptwPageTemplate ($Rev: 1829 $) -->",\n "<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>",\n " <div class='headerShadow'>",\n " <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;",\n " <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>",\n " </div>",\n " <div class='headerForeground'>",\n " <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;",\n " <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>",\n " </div>",\n "</div>",\n "<!-- horizontal MainMenu -->",\n "<div id='topMenu' refresh='content' tiddler='MainMenu'></div>",\n "<!-- original MainMenu menu -->",\n "<!-- <div id='mainMenu' refresh='content' tiddler='MainMenu'></div> -->",\n "<div id='sidebar'>",\n " <div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>",\n " <div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>",\n "</div>",\n "<div id='displayArea'>",\n " <div id='messageArea'></div>",\n " <div id='tiddlerDisplay'></div>",\n "</div>",\n "<!--}}}-->"\n].join("\sn"),\n\n'MptwStyleSheet':[\n "/*{{{*/",\n "/* http://mptw.tiddlyspot.com/#MptwStyleSheet ($Rev: 1860 $) */",\n "",\n "/* a contrasting background so I can see where one tiddler ends and the other begins */",\n "body {",\n " background: [[ColorPalette::TertiaryLight]];",\n "}",\n "",\n "/* sexy colours and font for the header */",\n ".headerForeground {",\n " color: [[ColorPalette::PrimaryPale]];",\n "}",\n ".headerShadow, .headerShadow a {",\n " color: [[ColorPalette::PrimaryMid]];",\n "}",\n "",\n "/* separate the top menu parts */",\n ".headerForeground, .headerShadow {",\n " padding: 1em 1em 0;",\n "}",\n "",\n ".headerForeground, .headerShadow {",\n " font-family: 'Trebuchet MS' sans-serif;",\n " font-weight:bold;",\n "}",\n ".headerForeground .siteSubtitle {",\n " color: [[ColorPalette::PrimaryLight]];",\n "}",\n ".headerShadow .siteSubtitle {",\n " color: [[ColorPalette::PrimaryMid]];",\n "}",\n "",\n "/* make shadow go and down right instead of up and left */",\n ".headerShadow {",\n " left: 1px;",\n " top: 1px;",\n "}",\n "",\n "/* prefer monospace for editing */",\n ".editor textarea {",\n " font-family: 'Consolas' monospace;",\n "}",\n "",\n "/* sexy tiddler titles */",\n ".title {",\n " font-size: 250%;",\n " color: [[ColorPalette::PrimaryLight]];",\n " font-family: 'Trebuchet MS' sans-serif;",\n "}",\n "",\n "/* more subtle tiddler subtitle */",\n ".subtitle {",\n " padding:0px;",\n " margin:0px;",\n " padding-left:0.5em;",\n " font-size: 90%;",\n " color: [[ColorPalette::TertiaryMid]];",\n "}",\n ".subtitle .tiddlyLink {",\n " color: [[ColorPalette::TertiaryMid]];",\n "}",\n "",\n "/* a little bit of extra whitespace */",\n ".viewer {",\n " padding-bottom:3px;",\n "}",\n "",\n "/* don't want any background color for headings */",\n "h1,h2,h3,h4,h5,h6 {",\n " background: [[ColorPalette::Background]];",\n " color: [[ColorPalette::Foreground]];",\n "}",\n "",\n "/* give tiddlers 3d style border and explicit background */",\n ".tiddler {",\n " background: [[ColorPalette::Background]];",\n " border-right: 2px [[ColorPalette::TertiaryMid]] solid;",\n " border-bottom: 2px [[ColorPalette::TertiaryMid]] solid;",\n " margin-bottom: 1em;",\n " padding-bottom: 2em;",\n "}",\n "",\n "/* make options slider look nicer */",\n "#sidebarOptions .sliderPanel {",\n " border:solid 1px [[ColorPalette::PrimaryLight]];",\n "}",\n "",\n "/* the borders look wrong with the body background */",\n "#sidebar .button {",\n " border-style: none;",\n "}",\n "",\n "/* this means you can put line breaks in SidebarOptions for readability */",\n "#sidebarOptions br {",\n " display:none;",\n "}",\n "/* undo the above in OptionsPanel */",\n "#sidebarOptions .sliderPanel br {",\n " display:inline;",\n "}",\n "",\n "/* horizontal main menu stuff */",\n "#displayArea {",\n " margin: 1em 15.7em 0em 1em; /* use the freed up space */",\n "}",\n "#topMenu br {",\n " display: none;",\n "}",\n "#topMenu {",\n " background: [[ColorPalette::PrimaryMid]];",\n " color:[[ColorPalette::PrimaryPale]];",\n "}",\n "#topMenu {",\n " padding:2px;",\n "}",\n "#topMenu .button, #topMenu .tiddlyLink, #topMenu a {",\n " margin-left: 0.5em;",\n " margin-right: 0.5em;",\n " padding-left: 3px;",\n " padding-right: 3px;",\n " color: [[ColorPalette::PrimaryPale]];",\n " font-size: 115%;",\n "}",\n "#topMenu .button:hover, #topMenu .tiddlyLink:hover {",\n " background: [[ColorPalette::PrimaryDark]];",\n "}",\n "",\n "/* for Tagger Plugin, thanks sb56637 */",\n ".popup li a {",\n " display:inline;",\n "}",\n "",\n "/* make it print a little cleaner */",\n "@media print {",\n " #topMenu {",\n " display: none ! important;",\n " }",\n " /* not sure if we need all the importants */",\n " .tiddler {",\n " border-style: none ! important;",\n " margin:0px ! important;",\n " padding:0px ! important;",\n " padding-bottom:2em ! important;",\n " }",\n " .tagglyTagging .button, .tagglyTagging .hidebutton {",\n " display: none ! important;",\n " }",\n " .headerShadow {",\n " visibility: hidden ! important;",\n " }",\n " .tagglyTagged .quickopentag, .tagged .quickopentag {",\n " border-style: none ! important;",\n " }",\n " .quickopentag a.button, .miniTag {",\n " display: none ! important;",\n " }",\n "}",\n "/*}}}*/"\n].join("\sn"),\n\n'MptwViewTemplate':[\n "<!--{{{-->",\n "<!--- http://mptw.tiddlyspot.com/#MptwViewTemplate ($Rev: 1830 $) --->",\n "",\n "<div class='toolbar'>",\n " <span macro=\s"showWhenTagged systemConfig\s">",\n " <span macro=\s"toggleTag systemConfigDisable . '[[disable|systemConfigDisable]]'\s"></span>",\n " </span>",\n " <span style=\s"padding:1em;\s"></span>",\n " <span macro='toolbar closeTiddler closeOthers deleteTiddler +editTiddler undoChanges permalink references jump'></span>",\n " <span macro='newHere label:\s"new here\s"'></span>",\n " <span macro='newJournalHere {{config.mptwJournalFormat?config.mptwJournalFormat:\s"MM/0DD/YY\s"}}'></span>",\n "</div>",\n "",\n "<div class=\s"tagglyTagged\s" macro=\s"tags\s"></div>",\n "",\n "<div class='titleContainer'>",\n " <span class='title' macro='view title'></span>",\n " <span macro=\s"miniTag\s"></span>",\n "</div>",\n "",\n "<div class='subtitle'>",\n " <span macro='view modifier link'></span>,",\n " <span macro='view modified date {{config.mptwDateFormat?config.mptwDateFormat:\s"MM/0DD/YY\s"}}'></span>",\n " (<span macro='message views.wikified.createdPrompt'></span>",\n " <span macro='view created date {{config.mptwDateFormat?config.mptwDateFormat:\s"MM/0DD/YY\s"}}'></span>)",\n "</div>",\n "",\n "<div macro=\s"showWhenExists ViewPanelTemplate\s">[[ViewPanelTemplate]]</div>",\n "",\n "<div macro=\s"hideWhen tiddler.tags.containsAny(['css','html','pre','systemConfig']) && !tiddler.text.match('{{'+'{')\s">",\n " <div class='viewer' macro='view text wikified'></div>",\n "</div>",\n "<div macro=\s"showWhen tiddler.tags.containsAny(['css','html','pre','systemConfig']) && !tiddler.text.match('{{'+'{')\s">",\n " <div class='viewer'><pre macro='view text'></pre></div>",\n "</div>",\n "",\n "<div macro=\s"showWhenExists ViewDashboardTemplate\s">[[ViewDashboardTemplate]]</div>",\n "",\n "<div class=\s"tagglyTagging\s" macro=\s"tagglyTagging\s"></div>",\n "",\n "<!--}}}-->"\n].join("\sn")\n\n});\n//}}}\n
For upgrading directly from tiddlyspot. See [[ImportTiddlers]].\nURL: /proxy/mptw.tiddlyspot.com/upgrade.html\n
For upgrading. See [[ImportTiddlers]].\nURL: http://mptw.tiddlyspot.com/upgrade.html\n
/***\n| Name:|NewHerePlugin|\n| Description:|Creates the new here and new journal macros|\n| Version:|3.0 ($Rev: 1845 $)|\n| Date:|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $|\n| Source:|http://mptw.tiddlyspot.com/#NewHerePlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\n***/\n//{{{\nmerge(config.macros, {\n newHere: {\n handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n wikify("<<newTiddler "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);\n }\n },\n newJournalHere: {\n handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n wikify("<<newJournal "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);\n }\n }\n});\n\n//}}}\n\n
@@~ObjType(Parent)@@\n@@~ObjType(Parent, Options)@@\n@@~ObjType(Name, Parent, Options)@@\n\nThese functions are shorthand equivalents of create/2, create/3, \nand create/4, respectively. [[create/2/3/4]]
[[MptwPageTemplate]]\n
/***\n| Name|QuickOpenTagPlugin|\n| Description|Changes tag links to make it easier to open tags as tiddlers|\n| Version|3.0 ($Rev: 1845 $)|\n| Date|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $|\n| Source|http://mptw.tiddlyspot.com/#QuickOpenTagPlugin|\n| Author|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\n***/\n//{{{\nconfig.quickOpenTag = {\n\n dropdownChar: (document.all ? "\su25bc" : "\su25be"), // the little one doesn't work in IE?\n\n createTagButton: function(place,tag,excludeTiddler) {\n // little hack so we can to <<tag PrettyTagName|RealTagName>>\n var splitTag = tag.split("|");\n var pretty = tag;\n if (splitTag.length == 2) {\n tag = splitTag[1];\n pretty = splitTag[0];\n }\n \n var sp = createTiddlyElement(place,"span",null,"quickopentag");\n createTiddlyText(createTiddlyLink(sp,tag,false),pretty);\n \n var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar,\n config.views.wikified.tag.tooltip.format([tag]),onClickTag);\n theTag.setAttribute("tag",tag);\n if (excludeTiddler)\n theTag.setAttribute("tiddler",excludeTiddler);\n return(theTag);\n },\n\n miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) {\n var tagged = store.getTaggedTiddlers(tiddler.title);\n if (tagged.length > 0) {\n var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar,\n config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag);\n theTag.setAttribute("tag",tiddler.title);\n theTag.className = "miniTag";\n }\n },\n\n allTagsHandler: function(place,macroName,params) {\n var tags = store.getTags();\n var theDateList = createTiddlyElement(place,"ul");\n if(tags.length == 0)\n createTiddlyElement(theDateList,"li",null,"listTitle",this.noTags);\n for (var t=0; t<tags.length; t++) {\n var theListItem = createTiddlyElement(theDateList,"li");\n var theLink = createTiddlyLink(theListItem,tags[t][0],true);\n var theCount = " (" + tags[t][1] + ")";\n theLink.appendChild(document.createTextNode(theCount));\n var theDropDownBtn = createTiddlyButton(theListItem," " +\n config.quickOpenTag.dropdownChar,this.tooltip.format([tags[t][0]]),onClickTag);\n theDropDownBtn.setAttribute("tag",tags[t][0]);\n }\n },\n\n // todo fix these up a bit\n styles: [\n"/*{{{*/",\n"/* created by QuickOpenTagPlugin */",\n".tagglyTagged .quickopentag, .tagged .quickopentag ",\n" { margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }",\n".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }",\n".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}",\n"/* extra specificity to make it work right */",\n"#displayArea .viewer .quickopentag a.button, ",\n"#displayArea .viewer .quickopentag a.tiddyLink, ",\n"#mainMenu .quickopentag a.tiddyLink, ",\n"#mainMenu .quickopentag a.tiddyLink ",\n" { border:0px solid black; }",\n"#displayArea .viewer .quickopentag a.button, ",\n"#mainMenu .quickopentag a.button ",\n" { margin-left:0px; padding-left:2px; }",\n"#displayArea .viewer .quickopentag a.tiddlyLink, ",\n"#mainMenu .quickopentag a.tiddlyLink ",\n" { margin-right:0px; padding-right:0px; padding-left:0px; margin-left:0px; }",\n"a.miniTag {font-size:150%;} ",\n"#mainMenu .quickopentag a.button ",\n" /* looks better in right justified main menus */",\n" { margin-left:0px; padding-left:2px; margin-right:0px; padding-right:0px; }", \n"#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }",\n"#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }",\n"#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }",\n"/*}}}*/",\n ""].join("\sn"),\n\n init: function() {\n // we fully replace these builtins. can't hijack them easily\n window.createTagButton = this.createTagButton;\n config.macros.allTags.handler = this.allTagsHandler;\n config.macros.miniTag = { handler: this.miniTagHandler };\n config.shadowTiddlers["QuickOpenTagStyles"] = this.styles;\n store.addNotification("QuickOpenTagStyles",refreshStyles);\n }\n}\n\nconfig.quickOpenTag.init();\n\n//}}}\n
/***\n| Name:|RenameTagsPlugin|\n| Description:|Allows you to easily rename or delete tags across multiple tiddlers|\n| Version:|3.0 ($Rev: 1845 $)|\n| Date:|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $|\n| Source:|http://mptw.tiddlyspot.com/#RenameTagsPlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\nRename a tag and you will be prompted to rename it in all its tagged tiddlers.\n***/\n//{{{\nconfig.renameTags = {\n\n prompts: {\n rename: "Rename the tag '%0' to '%1' in %2 tidder%3?",\n remove: "Remove the tag '%0' from %1 tidder%2?"\n },\n\n removeTag: function(tag,tiddlers) {\n store.suspendNotifications();\n for (var i=0;i<tiddlers.length;i++) {\n store.setTiddlerTag(tiddlers[i].title,false,tag);\n }\n store.resumeNotifications();\n store.notifyAll();\n },\n\n renameTag: function(oldTag,newTag,tiddlers) {\n store.suspendNotifications();\n for (var i=0;i<tiddlers.length;i++) {\n store.setTiddlerTag(tiddlers[i].title,false,oldTag); // remove old\n store.setTiddlerTag(tiddlers[i].title,true,newTag); // add new\n }\n store.resumeNotifications();\n store.notifyAll();\n },\n\n storeMethods: {\n\n saveTiddler_orig_renameTags: TiddlyWiki.prototype.saveTiddler,\n\n saveTiddler: function(title,newTitle,newBody,modifier,modified,tags,fields) {\n if (title != newTitle) {\n var tagged = this.getTaggedTiddlers(title);\n if (tagged.length > 0) {\n // then we are renaming a tag\n if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""])))\n config.renameTags.renameTag(title,newTitle,tagged);\n\n if (!this.tiddlerExists(title) && newBody == "")\n // dont create unwanted tiddler\n return null;\n }\n }\n return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields);\n },\n\n removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler,\n\n removeTiddler: function(title) {\n var tagged = this.getTaggedTiddlers(title);\n if (tagged.length > 0)\n if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""])))\n config.renameTags.removeTag(title,tagged);\n return this.removeTiddler_orig_renameTags(title);\n }\n\n },\n\n init: function() {\n merge(TiddlyWiki.prototype,this.storeMethods);\n }\n}\n\nconfig.renameTags.init();\n\n//}}}\n\n
/***\n| Name|SaveCloseTiddlerPlugin|\n| Description|Provides two extra toolbar commands, saveCloseTiddler and cancelCloseTiddler|\n| Version|3.0 ($Rev: 2134 $)|\n| Date|$Date: 2007-04-30 16:11:12 +1000 (Mon, 30 Apr 2007) $|\n| Source|http://mptw.tiddlyspot.com/#SaveCloseTiddlerPlugin|\n| Author|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\nTo use these you must add them to the tool bar in your EditTemplate\n***/\n//{{{\nmerge(config.commands,{\n\n saveCloseTiddler: {\n text: 'done/close',\n tooltip: 'Save changes to this tiddler and close it',\n handler: function(e,src,title) {\n config.commands.saveTiddler.handler(e,src,title);\n config.commands.closeTiddler.handler(e,src,title);\n return false;\n }\n },\n\n cancelCloseTiddler: {\n text: 'cancel/close',\n tooltip: 'Undo changes to this tiddler and close it',\n handler: function(e,src,title) {\n config.commands.cancelTiddler.handler(e,src,title);\n config.commands.closeTiddler.handler(e,src,title);\n return false;\n }\n }\n\n});\n\n//}}}\n\n
Organized by Doug Edmunds
Erlang GS Explorations
http://erl.dougedmunds.com
[[MptwStyleSheet]]\n
/***\n| Name|TagglyTaggingPlugin|\n| Description|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|\n| Version|3.0 ($Rev: 2101 $)|\n| Date|$Date: 2007-04-20 00:24:20 +1000 (Fri, 20 Apr 2007) $|\n| Source|http://mptw.tiddlyspot.com/#TagglyTaggingPlugin|\n| Author|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\n!Notes\nSee http://mptw.tiddlyspot.com/#TagglyTagging\n***/\n//{{{\nconfig.taggly = {\n\n // for translations\n lingo: {\n labels: {\n asc: "\su2191", // down arrow\n desc: "\su2193", // up arrow\n title: "title",\n modified: "modified",\n created: "created",\n show: "+",\n hide: "-",\n normal: "normal",\n group: "group",\n commas: "commas",\n sitemap: "sitemap",\n numCols: "cols\su00b1", // plus minus sign\n label: "Tagged as '%0':",\n excerpts: "excerpts",\n noexcerpts: "no excerpts"\n },\n\n tooltips: {\n title: "Click to sort by title",\n modified: "Click to sort by modified date",\n created: "Click to sort by created date",\n show: "Click to show tagging list",\n hide: "Click to hide tagging list",\n normal: "Click to show a normal ungrouped list",\n group: "Click to show list grouped by tag",\n sitemap: "Click to show a sitemap style list",\n commas: "Click to show a comma separated list",\n numCols: "Click to change number of columns"\n }\n },\n\n config: {\n showTaggingCounts: true,\n listOpts: {\n // the first one will be the default\n sortBy: ["title","modified","created"],\n sortOrder: ["asc","desc"],\n hideState: ["show","hide"],\n listMode: ["normal","group","sitemap","commas"],\n numCols: ["1","2","3","4","5","6"],\n excerpts: ["noexcerpts","excerpts"]\n },\n valuePrefix: "taggly.",\n excludeTags: ["excludeLists","excludeTagging"],\n excerptSize: 50,\n excerptMarker: "/%"+"%/"\n },\n\n getTagglyOpt: function(title,opt) {\n var val = store.getValue(title,this.config.valuePrefix+opt);\n return val ? val : this.config.listOpts[opt][0];\n },\n\n setTagglyOpt: function(title,opt,value) {\n if (!store.tiddlerExists(title))\n // create it silently\n store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),null);\n // if value is default then remove it to save space\n return store.setValue(title,\n this.config.valuePrefix+opt,\n value == this.config.listOpts[opt][0] ? null : value);\n },\n\n getNextValue: function(title,opt) {\n var current = this.getTagglyOpt(title,opt);\n var pos = this.config.listOpts[opt].indexOf(current);\n // a little usability enhancement. actually it doesn't work right for grouped or sitemap\n var limit = (opt == "numCols" ? store.getTaggedTiddlers(title).length : this.config.listOpts[opt].length);\n var newPos = (pos + 1) % limit;\n return this.config.listOpts[opt][newPos];\n },\n\n toggleTagglyOpt: function(title,opt) {\n var newVal = this.getNextValue(title,opt);\n this.setTagglyOpt(title,opt,newVal);\n }, \n\n createListControl: function(place,title,type) {\n var lingo = config.taggly.lingo;\n var label;\n var tooltip;\n var onclick;\n\n if ((type == "title" || type == "modified" || type == "created")) {\n // "special" controls. a little tricky. derived from sortOrder and sortBy\n label = lingo.labels[type];\n tooltip = lingo.tooltips[type];\n\n if (this.getTagglyOpt(title,"sortBy") == type) {\n label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];\n onclick = function() {\n config.taggly.toggleTagglyOpt(title,"sortOrder");\n return false;\n }\n }\n else {\n onclick = function() {\n config.taggly.setTagglyOpt(title,"sortBy",type);\n config.taggly.setTagglyOpt(title,"sortOrder",config.taggly.config.listOpts.sortOrder[0]);\n return false;\n }\n }\n }\n else {\n // "regular" controls, nice and simple\n label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];\n tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];\n onclick = function() {\n config.taggly.toggleTagglyOpt(title,type);\n return false;\n }\n }\n\n // hide button because commas don't have columns\n if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))\n createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");\n },\n\n makeColumns: function(orig,numCols) {\n var listSize = orig.length;\n var colSize = listSize/numCols;\n var remainder = listSize % numCols;\n\n var upperColsize = colSize;\n var lowerColsize = colSize;\n\n if (colSize != Math.floor(colSize)) {\n // it's not an exact fit so..\n upperColsize = Math.floor(colSize) + 1;\n lowerColsize = Math.floor(colSize);\n }\n\n var output = [];\n var c = 0;\n for (var j=0;j<numCols;j++) {\n var singleCol = [];\n var thisSize = j < remainder ? upperColsize : lowerColsize;\n for (var i=0;i<thisSize;i++) \n singleCol.push(orig[c++]);\n output.push(singleCol);\n }\n\n return output;\n },\n\n drawTable: function(place,columns,theClass) {\n var newTable = createTiddlyElement(place,"table",null,theClass);\n var newTbody = createTiddlyElement(newTable,"tbody");\n var newTr = createTiddlyElement(newTbody,"tr");\n for (var j=0;j<columns.length;j++) {\n var colOutput = "";\n for (var i=0;i<columns[j].length;i++) \n colOutput += columns[j][i];\n var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class\n wikify(colOutput,newTd);\n }\n return newTable;\n },\n\n createTagglyList: function(place,title) {\n switch(this.getTagglyOpt(title,"listMode")) {\n case "group": return this.createTagglyListGrouped(place,title); break;\n case "normal": return this.createTagglyListNormal(place,title,false); break;\n case "commas": return this.createTagglyListNormal(place,title,true); break;\n case "sitemap":return this.createTagglyListSiteMap(place,title); break;\n }\n },\n\n getTaggingCount: function(title) {\n // thanks to Doug Edmunds\n if (this.config.showTaggingCounts) {\n var tagCount = store.getTaggedTiddlers(title).length;\n if (tagCount > 0)\n return " ("+tagCount+")";\n }\n return "";\n },\n\n getExcerpt: function(inTiddlerTitle,title) {\n if (this.getTagglyOpt(inTiddlerTitle,"excerpts") == "excerpts") {\n var t = store.getTiddler(title);\n if (t) {\n var text = t.text.replace(/\sn/," ");\n var marker = text.indexOf(this.config.excerptMarker);\n if (marker != -1) {\n return " {{excerpt{<nowiki>" + text.substr(0,marker) + "</nowiki>}}}";\n }\n else if (text.length < this.config.excerptSize) {\n return " {{excerpt{<nowiki>" + t.text + "</nowiki>}}}";\n }\n else {\n return " {{excerpt{<nowiki>" + t.text.substr(0,this.config.excerptSize) + "..." + "</nowiki>}}}";\n }\n }\n }\n return "";\n },\n\n notHidden: function(t,inTiddler) {\n if (typeof t == "string") \n t = store.getTiddler(t);\n return (!t || !t.tags.containsAny(this.config.excludeTags) ||\n (inTiddler && this.config.excludeTags.contains(inTiddler)));\n },\n\n // this is for normal and commas mode\n createTagglyListNormal: function(place,title,useCommas) {\n\n var list = store.getTaggedTiddlers(title,this.getTagglyOpt(title,"sortBy"));\n\n if (this.getTagglyOpt(title,"sortOrder") == "desc")\n list = list.reverse();\n\n var output = [];\n var first = true;\n for (var i=0;i<list.length;i++) {\n if (this.notHidden(list[i],title)) {\n var countString = this.getTaggingCount(list[i].title);\n var excerpt = this.getExcerpt(title,list[i].title);\n if (useCommas)\n output.push((first ? "" : ", ") + "[[" + list[i].title + "]]" + countString + excerpt);\n else\n output.push("*[[" + list[i].title + "]]" + countString + excerpt + "\sn");\n\n first = false;\n }\n }\n\n return this.drawTable(place,\n this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),\n useCommas ? "commas" : "normal");\n },\n\n // this is for the "grouped" mode\n createTagglyListGrouped: function(place,title) {\n var sortBy = this.getTagglyOpt(title,"sortBy");\n var sortOrder = this.getTagglyOpt(title,"sortOrder");\n\n var list = store.getTaggedTiddlers(title,sortBy);\n\n if (sortOrder == "desc")\n list = list.reverse();\n\n var leftOvers = []\n for (var i=0;i<list.length;i++)\n leftOvers.push(list[i].title);\n\n var allTagsHolder = {};\n for (var i=0;i<list.length;i++) {\n for (var j=0;j<list[i].tags.length;j++) {\n\n if (list[i].tags[j] != title) { // not this tiddler\n\n if (this.notHidden(list[i].tags[j],title)) {\n\n if (!allTagsHolder[list[i].tags[j]])\n allTagsHolder[list[i].tags[j]] = "";\n\n if (this.notHidden(list[i],title)) {\n allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"\n + this.getTaggingCount(list[i].title) + this.getExcerpt(title,list[i].title) + "\sn";\n\n leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers\n\n }\n }\n }\n }\n }\n\n var allTags = [];\n for (var t in allTagsHolder)\n allTags.push(t);\n\n var sortHelper = function(a,b) {\n if (a == b) return 0;\n if (a < b) return -1;\n return 1;\n };\n\n allTags.sort(function(a,b) {\n var tidA = store.getTiddler(a);\n var tidB = store.getTiddler(b);\n if (sortBy == "title") return sortHelper(a,b);\n else if (!tidA && !tidB) return 0;\n else if (!tidA) return -1;\n else if (!tidB) return +1;\n else return sortHelper(tidA[sortBy],tidB[sortBy]);\n });\n\n var leftOverOutput = "";\n for (var i=0;i<leftOvers.length;i++)\n if (this.notHidden(leftOvers[i],title))\n leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + this.getExcerpt(title,leftOvers[i]) + "\sn";\n\n var output = [];\n\n if (sortOrder == "desc")\n allTags.reverse();\n else if (leftOverOutput != "")\n // leftovers first...\n output.push(leftOverOutput);\n\n for (var i=0;i<allTags.length;i++)\n if (allTagsHolder[allTags[i]] != "")\n output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(allTags[i]) + this.getExcerpt(title,allTags[i]) + "\sn" + allTagsHolder[allTags[i]]);\n\n if (sortOrder == "desc" && leftOverOutput != "")\n // leftovers last...\n output.push(leftOverOutput);\n\n return this.drawTable(place,\n this.makeColumns(output,parseInt(this.getTagglyOpt(title,"numCols"))),\n "grouped");\n\n },\n\n // used to build site map\n treeTraverse: function(title,depth,sortBy,sortOrder) {\n\n var list = store.getTaggedTiddlers(title,sortBy);\n if (sortOrder == "desc")\n list.reverse();\n\n var indent = "";\n for (var j=0;j<depth;j++)\n indent += "*"\n\n var childOutput = "";\n for (var i=0;i<list.length;i++)\n if (list[i].title != title)\n if (this.notHidden(list[i].title,this.config.inTiddler))\n childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder);\n\n if (depth == 0)\n return childOutput;\n else\n return indent + "[["+title+"]]" + this.getTaggingCount(title) + this.getExcerpt(this.config.inTiddler,title) + "\sn" + childOutput;\n },\n\n // this if for the site map mode\n createTagglyListSiteMap: function(place,title) {\n this.config.inTiddler = title; // nasty. should pass it in to traverse probably\n var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"));\n return this.drawTable(place,\n this.makeColumns(output.split(/(?=^\s*\s[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic\n "sitemap"\n );\n },\n\n macros: {\n tagglyTagging: {\n handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n var refreshContainer = createTiddlyElement(place,"div");\n // do some refresh magic to make it keep the list fresh - thanks Saq\n refreshContainer.setAttribute("refresh","macro");\n refreshContainer.setAttribute("macroName",macroName);\n refreshContainer.setAttribute("title",tiddler.title);\n this.refresh(refreshContainer);\n },\n\n refresh: function(place) {\n var title = place.getAttribute("title");\n removeChildren(place);\n if (store.getTaggedTiddlers(title).length > 0) {\n var lingo = config.taggly.lingo;\n config.taggly.createListControl(place,title,"hideState");\n if (config.taggly.getTagglyOpt(title,"hideState") == "show") {\n createTiddlyElement(place,"span",null,"tagglyLabel",lingo.labels.label.format([title]));\n config.taggly.createListControl(place,title,"title");\n config.taggly.createListControl(place,title,"modified");\n config.taggly.createListControl(place,title,"created");\n config.taggly.createListControl(place,title,"listMode");\n config.taggly.createListControl(place,title,"excerpts");\n config.taggly.createListControl(place,title,"numCols");\n config.taggly.createTagglyList(place,title);\n }\n }\n }\n }\n },\n\n // todo fix these up a bit\n styles: [\n"/*{{{*/",\n"/* created by TagglyTaggingPlugin */",\n".tagglyTagging { padding-top:0.5em; }",\n".tagglyTagging li.listTitle { display:none; }",\n".tagglyTagging ul {",\n" margin-top:0px; padding-top:0.5em; padding-left:2em;",\n" margin-bottom:0px; padding-bottom:0px;",\n"}",\n".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }",\n".tagglyTagging table { margin:0px; padding:0px; }",\n".tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }",\n".tagglyTagging .button, .tagglyTagging .hidebutton {",\n" color:[[ColorPalette::TertiaryLight]]; font-size:90%;",\n" border:0px; padding-left:0.3em;padding-right:0.3em;",\n"}",\n".tagglyTagging .button:hover, .hidebutton:hover, ",\n".tagglyTagging .button:active, .hidebutton:active {",\n" border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];",\n"}",\n".selected .tagglyTagging .button { visibility:visible; }",\n".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }",\n".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }",\n".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }",\n".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }",\n".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}",\n".tagglyTagging ul ul li {margin-left:0.5em; }",\n".editLabel { font-size:90%; padding-top:0.5em; }",\n".tagglyTagging .commas { padding-left:1.8em; }",\n"/* not technically tagglytagging but will put them here anyway */",\n".tagglyTagged li.listTitle { display:none; }",\n".tagglyTagged li { display: inline; font-size:90%; }",\n".tagglyTagged ul { margin:0px; padding:0px; }",\n".excerpt { color:[[ColorPalette::TertiaryMid]]; }",\n"div.tagglyTagging table,",\n"div.tagglyTagging table tr,",\n"td.tagglyTagging",\n" {border-style:none!important; }",\n"/*}}}*/",\n ""].join("\sn"),\n\n init: function() {\n merge(config.macros,this.macros);\n config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;\n store.addNotification("TagglyTaggingStyles",refreshStyles);\n }\n};\n\nconfig.taggly.init();\n\n//}}}\n\n
Fix the templates, to include text with scroll bars\nThe location of code is confusing. Widgets group appears twice.\n\nCode in [[ex12]] needs commentary.\n\nput this somewhere:\ngs uses tcl/tk to generate windows. The gs code you write gets converted into \ntcl/tk code by the gs system. So, if you write something that gs allows, \nyou may still crash in the tcl/tk engine. \n\n\nput this somewhere:\n\nAlways include a 'destroy' tuple in the receive loop. \nOtherwise, Erlang will hang when you close the graphics window. \nexample: {gs,_Id,destroy,_Data,_Arg} -> bye\n\nput this somewhere:\n\nAlways create objects in parent-first order. You can config them in any order.\n\nThis page is too long: [[General info about options]]\n\n\n
/***\n| Name|ToggleTagPlugin|\n| Description|Makes a checkbox which toggles a tag in a tiddler|\n| Version|3.0 ($Rev: 1845 $)|\n| Date|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $|\n| Source|http://tiddlyspot.com/mptw/#ToggleTagMacro|\n| Author|Simon Baird <simon.baird@gmail.com>|\n| License|http://mptw.tiddlyspot.com/#TheBSDLicense|\n!Usage\n{{{<<toggleTag }}}//{{{TagName TiddlerName LabelText}}}//{{{>>}}}\n* TagName - the tag to be toggled, default value "checked"\n* TiddlerName - the tiddler to toggle the tag in, default value the current tiddler\n* LabelText - the text (gets wikified) to put next to the check box, default value is '{{{[[TagName]]}}}' or '{{{[[TagName]] [[TiddlerName]]}}}'\n(If a parameter is '.' then the default will be used)\n\nExamples:\n\n|Code|Description|Example|h\n|{{{<<toggleTag>>}}}|Toggles the default tag (checked) in this tiddler|<<toggleTag>>|\n|{{{<<toggleTag TagName>>}}}|Toggles the TagName tag in this tiddler|<<toggleTag TagName>>|\n|{{{<<toggleTag TagName TiddlerName>>}}}|Toggles the TagName tag in the TiddlerName tiddler|<<toggleTag TagName TiddlerName>>|\n|{{{<<toggleTag TagName TiddlerName 'click me'>>}}}|Same but with custom label|<<toggleTag TagName TiddlerName 'click me'>>|\n|{{{<<toggleTag . . 'click me'>>}}}|dot means use default value|<<toggleTag . . 'click me'>>|\nNotes:\n* If TiddlerName doesn't exist it will be silently created\n* Set label to '-' to specify no label\n* See also http://mgtd-alpha.tiddlyspot.com/#ToggleTag2\n\n!Known issues\n* Doesn't smoothly handle the case where you toggle a tag in a tiddler that is current open for editing\n\n***/\n//{{{\n\nmerge(config.macros,{\n\n toggleTag: {\n\n doRefreshAll: true,\n createIfRequired: true,\n shortLabel: "[[%0]]",\n longLabel: "[[%0]] [[%1]]",\n\n handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n var tag = (params[0] && params[0] != '.') ? params[0] : "checked";\n var title = (params[1] && params[1] != '.') ? params[1] : tiddler.title;\n var defaultLabel = (title == tiddler.title ? this.shortLabel : this.longLabel);\n var label = (params[2] && params[2] != '.') ? params[2] : defaultLabel;\n label = (label == '-' ? '' : label);\n var theTiddler = title == tiddler.title ? tiddler : store.getTiddler(title);\n var cb = createTiddlyCheckbox(place, label.format([tag,title]), theTiddler && theTiddler.isTagged(tag), function(e) {\n if (!store.tiddlerExists(title)) {\n if (config.macros.toggleTag.createIfRequired) {\n var content = store.getTiddlerText(title); // just in case it's a shadow\n store.saveTiddler(title,title,content?content:"",config.options.txtUserName,new Date(),null);\n }\n else \n return false;\n }\n store.setTiddlerTag(title,this.checked,tag);\n return true;\n });\n }\n }\n});\n\n//}}}\n\n
Three objects has default settings but are not documented.\nSee gstk_widgets.erl
Visual Tcl is the next best thing to a GUI builder for Erlang GS.\nYou put objects where you want to see them. VTCL gives you the numbers \nyou need to correctly size and place your objects in an Erlang GS window. \nYou can either work right off the screen or from the file it generates.\nI have written a [[GUI Template]] that ties in with Visual Tcl.\n \nGet Visual Tcl at [[SourceForge |http://vtcl.sourceforge.net/]]. It's a tcl file itself,\nso it will on several operating systems.\n\nIt requires a Tcl/tk 'wish' file. There is one in the Erlang distribution.\n <erlang root>\slib\sgs-1.5.7\spriv\stcl\sbin\swish84s.exe\nThe easiest way to run it in Windows is to associate .tcl files to your 'wish' file.\n\n''Working with the GUI Template''\n*Open Visual Tcl.\n*Set it to use 'place manager'. \n*Make a simple window (a label, an entry, a couple of buttons).\n**@@Note@@: vtcl has more 'object' choices than Erlang GS. Only use those which have Erlang counterparts.\n**A tip: vtcl adds objects to the tcl file in the order you add them to the screen. Putting all of the same kind of objects on the screen (all the buttons, all the labels) groups them that way in the file. I find it easier to copy info to the erl file if I do them by groups (gs:config(button1..., gs:config(button2...). \n**Another tip: when adding labels, resize them (drag the edges) to force vtcl to store the height and width. Otherwise it will just store the x and y coordinates. \n*Save the vtcl file. Close vtcl.\n*Open the tcl and the [[GUI Template]] in a text editor. \n*Using the data from the vtcl file, fill in the blanks in the GUI template. \n**At this stage you are building the GUI, so don't bother writing any code in the loop.\n \nIf you fill it in correctly, your Erlang-generated window will look exactly like the vtcl-generated window.\n*Well, almost exactly. Here are [[some differences |vtcl differences]] noted so far.\n''WoW!!!!''\n\n\n
[[MptwViewTemplate]]
@@Code notes@@\nWhat is so absolutely great about a Visual Tcl file is that \n''you don't have to write it!''\nYou paint the screen, then save the file. That's it.\nThen you take the numbers off it, plug them into the \n[[GUI Template]], and you can go back to the good stuff. \n\nLook at the [[GUI Template]] while looking at this file.\nAuto-generated by Visual Tcl:\n{{{\n#!/bin/sh\n# the next line restarts using wish\s\nexec wish "$0" "$@" \n\nif {![info exists vTcl(sourcing)]} {\n\n package require Tk\n switch $tcl_platform(platform) {\n windows {\n option add *Button.padY 0\n }\n default {\n option add *Scrollbar.width 10\n option add *Scrollbar.highlightThickness 0\n option add *Scrollbar.elementBorderWidth 2\n option add *Scrollbar.borderWidth 2\n }\n }\n \n}\n\n#############################################################################\n# Visual Tcl v1.60 Project\n#\n\n\n#################################\n# VTCL LIBRARY PROCEDURES\n#\n\nif {![info exists vTcl(sourcing)]} {\n#############################################################################\n## Library Procedure: Window\n\nproc ::Window {args} {\n ## This procedure may be used free of restrictions.\n ## Exception added by Christian Gavin on 08/08/02.\n ## Other packages and widget toolkits have different licensing requirements.\n ## Please read their license agreements for details.\n\n global vTcl\n foreach {cmd name newname} [lrange $args 0 2] {}\n set rest [lrange $args 3 end]\n if {$name == "" || $cmd == ""} { return }\n if {$newname == ""} { set newname $name }\n if {$name == "."} { wm withdraw $name; return }\n set exists [winfo exists $newname]\n switch $cmd {\n show {\n if {$exists} {\n wm deiconify $newname\n } elseif {[info procs vTclWindow$name] != ""} {\n eval "vTclWindow$name $newname $rest"\n }\n if {[winfo exists $newname] && [wm state $newname] == "normal"} {\n vTcl:FireEvent $newname <<Show>>\n }\n }\n hide {\n if {$exists} {\n wm withdraw $newname\n vTcl:FireEvent $newname <<Hide>>\n return}\n }\n iconify { if $exists {wm iconify $newname; return} }\n destroy { if $exists {destroy $newname; return} }\n }\n}\n#############################################################################\n## Library Procedure: vTcl:DefineAlias\n\nproc ::vTcl:DefineAlias {target alias widgetProc top_or_alias cmdalias} {\n ## This procedure may be used free of restrictions.\n ## Exception added by Christian Gavin on 08/08/02.\n ## Other packages and widget toolkits have different licensing requirements.\n ## Please read their license agreements for details.\n\n global widget\n set widget($alias) $target\n set widget(rev,$target) $alias\n if {$cmdalias} {\n interp alias {} $alias {} $widgetProc $target\n }\n if {$top_or_alias != ""} {\n set widget($top_or_alias,$alias) $target\n if {$cmdalias} {\n interp alias {} $top_or_alias.$alias {} $widgetProc $target\n }\n }\n}\n#############################################################################\n## Library Procedure: vTcl:DoCmdOption\n\nproc ::vTcl:DoCmdOption {target cmd} {\n ## This procedure may be used free of restrictions.\n ## Exception added by Christian Gavin on 08/08/02.\n ## Other packages and widget toolkits have different licensing requirements.\n ## Please read their license agreements for details.\n\n ## menus are considered toplevel windows\n set parent $target\n while {[winfo class $parent] == "Menu"} {\n set parent [winfo parent $parent]\n }\n\n regsub -all {\s%widget} $cmd $target cmd\n regsub -all {\s%top} $cmd [winfo toplevel $parent] cmd\n\n uplevel #0 [list eval $cmd]\n}\n#############################################################################\n## Library Procedure: vTcl:FireEvent\n\nproc ::vTcl:FireEvent {target event {params {}}} {\n ## This procedure may be used free of restrictions.\n ## Exception added by Christian Gavin on 08/08/02.\n ## Other packages and widget toolkits have different licensing requirements.\n ## Please read their license agreements for details.\n\n ## The window may have disappeared\n if {![winfo exists $target]} return\n ## Process each binding tag, looking for the event\n foreach bindtag [bindtags $target] {\n set tag_events [bind $bindtag]\n set stop_processing 0\n foreach tag_event $tag_events {\n if {$tag_event == $event} {\n set bind_code [bind $bindtag $tag_event]\n foreach rep "\s{%W $target\s} $params" {\n regsub -all [lindex $rep 0] $bind_code [lindex $rep 1] bind_code\n }\n set result [catch {uplevel #0 $bind_code} errortext]\n if {$result == 3} {\n ## break exception, stop processing\n set stop_processing 1\n } elseif {$result != 0} {\n bgerror $errortext\n }\n break\n }\n }\n if {$stop_processing} {break}\n }\n}\n#############################################################################\n## Library Procedure: vTcl:Toplevel:WidgetProc\n\nproc ::vTcl:Toplevel:WidgetProc {w args} {\n ## This procedure may be used free of restrictions.\n ## Exception added by Christian Gavin on 08/08/02.\n ## Other packages and widget toolkits have different licensing requirements.\n ## Please read their license agreements for details.\n\n if {[llength $args] == 0} {\n ## If no arguments, returns the path the alias points to\n return $w\n }\n set command [lindex $args 0]\n set args [lrange $args 1 end]\n switch -- [string tolower $command] {\n "setvar" {\n foreach {varname value} $args {}\n if {$value == ""} {\n return [set ::${w}::${varname}]\n } else {\n return [set ::${w}::${varname} $value]\n }\n }\n "hide" - "show" {\n Window [string tolower $command] $w\n }\n "showmodal" {\n ## modal dialog ends when window is destroyed\n Window show $w; raise $w\n grab $w; tkwait window $w; grab release $w\n }\n "startmodal" {\n ## ends when endmodal called\n Window show $w; raise $w\n set ::${w}::_modal 1\n grab $w; tkwait variable ::${w}::_modal; grab release $w\n }\n "endmodal" {\n ## ends modal dialog started with startmodal, argument is var name\n set ::${w}::_modal 0\n Window hide $w\n }\n default {\n uplevel $w $command $args\n }\n }\n}\n#############################################################################\n## Library Procedure: vTcl:WidgetProc\n\nproc ::vTcl:WidgetProc {w args} {\n ## This procedure may be used free of restrictions.\n ## Exception added by Christian Gavin on 08/08/02.\n ## Other packages and widget toolkits have different licensing requirements.\n ## Please read their license agreements for details.\n\n if {[llength $args] == 0} {\n ## If no arguments, returns the path the alias points to\n return $w\n }\n\n set command [lindex $args 0]\n set args [lrange $args 1 end]\n uplevel $w $command $args\n}\n#############################################################################\n## Library Procedure: vTcl:toplevel\n\nproc ::vTcl:toplevel {args} {\n ## This procedure may be used free of restrictions.\n ## Exception added by Christian Gavin on 08/08/02.\n ## Other packages and widget toolkits have different licensing requirements.\n ## Please read their license agreements for details.\n\n uplevel #0 eval toplevel $args\n set target [lindex $args 0]\n namespace eval ::$target {set _modal 0}\n}\n}\n\n\nif {[info exists vTcl(sourcing)]} {\n\nproc vTcl:project:info {} {\n set base .top27\n namespace eval ::widgets::$base {\n set set,origin 1\n set set,size 1\n set runvisible 1\n }\n namespace eval ::widgets::$base.lab29 {\n array set save {-text 1}\n }\n namespace eval ::widgets::$base.but30 {\n array set save {-pady 1 -text 1}\n }\n namespace eval ::widgets::$base.but31 {\n array set save {-pady 1 -text 1}\n }\n namespace eval ::widgets::$base.ent33 {\n array set save {-background 1 -textvariable 1}\n }\n namespace eval ::widgets::$base.tex27 {\n array set save {-background 1 -yscrollcommand 1}\n }\n namespace eval ::widgets::$base.scr29 {\n array set save {-command 1}\n }\n namespace eval ::widgets_bindings {\n set tagslist _TopLevel\n }\n namespace eval ::vTcl::modules::main {\n set procs {\n init\n main\n }\n set compounds {\n }\n set projectType single\n }\n}\n}\n\n#################################\n# USER DEFINED PROCEDURES\n#\n#############################################################################\n## Procedure: main\n\nproc ::main {argc argv} {}\n\n#############################################################################\n## Initialization Procedure: init\n\nproc ::init {argc argv} {}\n\ninit $argc $argv\n\n#################################\n# VTCL GENERATED GUI PROCEDURES\n#\n\nproc vTclWindow. {base} {\n if {$base == ""} {\n set base .\n }\n ###################\n # CREATING WIDGETS\n ###################\n wm focusmodel $top passive\n wm geometry $top 200x200+88+116; update\n wm maxsize $top 1284 778\n wm minsize $top 115 1\n wm overrideredirect $top 0\n wm resizable $top 1 1\n wm withdraw $top\n wm title $top "vtcl"\n bindtags $top "$top Vtcl all"\n vTcl:FireEvent $top <<Create>>\n wm protocol $top WM_DELETE_WINDOW "vTcl:FireEvent $top <<DeleteWindow>>"\n\n ###################\n # SETTING GEOMETRY\n ###################\n\n vTcl:FireEvent $base <<Ready>>\n}\n\nproc vTclWindow.top27 {base} {\n if {$base == ""} {\n set base .top27\n }\n if {[winfo exists $base]} {\n wm deiconify $base; return\n }\n set top $base\n ###################\n # CREATING WIDGETS\n ###################\n vTcl:toplevel $top -class Toplevel\n wm focusmodel $top passive\n wm geometry $top 381x360+423+117; update\n wm maxsize $top 1284 778\n wm minsize $top 115 1\n wm overrideredirect $top 0\n wm resizable $top 1 1\n wm deiconify $top\n wm title $top "Title of Window here"\n vTcl:DefineAlias "$top" "window1" vTcl:Toplevel:WidgetProc "" 1\n bindtags $top "$top Toplevel all _TopLevel"\n vTcl:FireEvent $top <<Create>>\n wm protocol $top WM_DELETE_WINDOW "vTcl:FireEvent $top <<DeleteWindow>>"\n\n label $top.lab29 \s\n -text {Put label1 text there} \n vTcl:DefineAlias "$top.lab29" "label1" vTcl:WidgetProc "window1" 1\n button $top.but30 \s\n -pady 0 -text {add me} \n vTcl:DefineAlias "$top.but30" "button1" vTcl:WidgetProc "window1" 1\n button $top.but31 \s\n -pady 0 -text exit \n vTcl:DefineAlias "$top.but31" "button2" vTcl:WidgetProc "window1" 1\n entry $top.ent33 \s\n -background white -textvariable "$top\s::ent33" \n vTcl:DefineAlias "$top.ent33" "entry2" vTcl:WidgetProc "window1" 1\n text $top.tex27 \s\n -background white -yscrollcommand {scrollbar2 set} \n vTcl:DefineAlias "$top.tex27" "text1" vTcl:WidgetProc "window1" 1\n scrollbar $top.scr29 \s\n -command {text1 yview} \n vTcl:DefineAlias "$top.scr29" "scrollbar2" vTcl:WidgetProc "window1" 1\n ###################\n # SETTING GEOMETRY\n ###################\n place $top.lab29 \s\n -in $top -x 90 -y 20 -width 138 -height 29 -anchor nw \s\n -bordermode ignore \n place $top.but30 \s\n -in $top -x 90 -y 275 -width 62 -height 36 -anchor nw \s\n -bordermode ignore \n place $top.but31 \s\n -in $top -x 225 -y 275 -width 60 -height 36 -anchor nw \s\n -bordermode ignore \n place $top.ent33 \s\n -in $top -x 46 -y 65 -width 246 -height 44 -anchor nw \s\n -bordermode ignore \n place $top.tex27 \s\n -in $top -x 45 -y 140 -width 296 -height 103 -anchor nw \s\n -bordermode ignore \n place $top.scr29 \s\n -in $top -x 340 -y 140 -width 17 -height 103 -anchor nw \s\n -bordermode ignore \n\n vTcl:FireEvent $base <<Ready>>\n}\n\n#############################################################################\n## Binding tag: _TopLevel\n\nbind "_TopLevel" <<Create>> {\n if {![info exists _topcount]} {set _topcount 0}; incr _topcount\n}\nbind "_TopLevel" <<DeleteWindow>> {\n if {[set ::%W::_modal]} {\n vTcl:Toplevel:WidgetProc %W endmodal\n } else {\n destroy %W; if {$_topcount == 0} {exit}\n }\n}\nbind "_TopLevel" <Destroy> {\n if {[winfo toplevel %W] == "%W"} {incr _topcount -1}\n}\n\nWindow show .\nWindow show .top27\n\nmain $argc $argv\n\n}}}
Super!\nGreat!\nFantastic!\nWhat a topper!\nOut of sight!\nDyne-o-mite!\nHot Stuff!
Parents\n*[[canvas]]\nChildren\n* none\n{{{\ndefault_options(arc) -> [{coords, [{0,0}, {0,0}]}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% ARC OPTIONS\n%%\n%% Attributes:\n%% bw Int\n%% coords [{X1,Y1}, {X2,Y2}]\n%% data Data\n%% extent Degrees\n%% fg Color\n%% fill Color\n%% start Degrees\n%% stipple Bool\n%% style pieslice, chord, arc\n%%\n%% Commands:\n%% lower\n%% move {Dx, Dy}\n%% raise\n%% scale {Xo, Yo, Sx, Sy}\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n}}}
also see [[radiobutton]] and [[checkbutton]]\nParents\n* [[frame]]\n* [[window]]\nChildren\n* none\n{{{\ndefault_options(button) -> [{click,true}, {height,30}, {width,100}, {x,0},\n {y,0}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% BUTTON OPTIONS\n%%\n%% Attributes:\n%% activebg Color\n%% activefg Color\n%% align n,w,s,e,nw,se,ne,sw,center\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bg Color\n%% bw Int\n%% data Data\n%% disabledfg Color\n%% fg Color\n%% font Font\n%% height Int\n%% highlightbg Color\n%% highlightbw Int\n%% highlightfg Color\n%% justify left|right|center\n%% label {text, String} | {image, BitmapFile}\n%% padx Int (Pixels)\n%% pady Int (Pixels)\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%% underline Int\n%% width Int\n%% wraplength Int\n%% x Int\n%% y Int\n%%\n%% Commands:\n%% enable Bool\n%% flash \n%% invoke \n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% click [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% cursor ??????\n%% font ??????\n%%\n}}}\n\n
Parents\n* [[frame]]\n* [[window]]\nChildren\n* [[arc]], \n* [[image]], \n* [[line]], \n* [[oval]], \n* [[polygon]], \n* [[rectangle]], \n* [[text]]\n{{{\ndefault_options(canvas) -> [{height,200}, {scrollregion,{0,0,300,200}},\n {width,300}, {x,0}, {y,0}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% CANVAS OPTIONS\n%%\n%% Attributes:\n%% activebg Color\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bc Color\n%% bg Color\n%% bw Wth\n%% data Data\n%% height Int\n%% highlightbg Color\n%% highlightbw Wth\n%% highlightfg Color\n%% hscroll Bool | top | bottom\n%% relief Relief\n%% scrollbg Color\n%% scrollfg Color\n%% scrollregion {X1, Y1, X2, Y2}\n%% selectbg Color\n%% selectbw Width\n%% selectfg Color\n%% vscroll Bool | left | right\n%% width Int\n%% x Int\n%% y Int\n%%\n%%\n%% Commands:\n%% find {X, Y} => Item at pos X,Y or false\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% fg Color\n%%\n}}}
Parents\n* [[frame]]\n* [[window]]\nChildren\n* none\n{{{\ndefault_options(checkbutton) -> [{click,true}, {height,30}, {width,100}, {x,0},\n {y,0}];\n}}}\n{{{\n%%------------------------------------------------------------------------------\n%% CHECKBUTTON OPTIONS\n%%\n%% Attributes:\n%% activebg Color\n%% activefg Color\n%% align n,w,s,e,nw,se,ne,sw,center\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bg Color\n%% bw Int\n%% data Data\n%% disabledfg Color\n%% fg Color\n%% group Atom\n%% groupid Groupid\n%% height Int\n%% highlightbg Color\n%% highlightbw Int\n%% highlightfg Color\n%% justify left|right|center\n%% label {text, String} | {image, BitmapFile}\n%% padx Int (Pixels)\n%% pady Int (Pixels)\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%% select Bool\n%% selectbg Color\n%% underline Int\n%% width Int\n%% wraplength Int\n%% x Int\n%% y Int\n%%\n%% Commands:\n%% enable Bool\n%% flash\n%% invoke \n%% setfocus Bool\n%% toggle \n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% click [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% cursor ??????\n%% focus ?????? (-takefocus)\n%% font ??????\n%%\n}}}
@@config(~GSObj, Options) -> ok@@\n\nTypes:\n\n~GSOBj = gsobj()\nOptions = [Option] | Option\n๏ฟฝOption = {Key,Value}\n\nConfigures a graphical object according to the specified options.
@@create(~ObjType, Parent) -> ~ObjId@@\n@@create(~ObjType, Parent, Options) -> ~ObjId@@ \n@@create(~ObjType, Name, Parent, Options) -> ~ObjId@@ \n\nSee also [[ObjType/1/2/3]] for aliases.\n\nTypes:\n\n~ObjType = atom()\nParent = gsobj()\nName = atom()\nOptions = [Option] | Option\n๏ฟฝOption = {Key,Value}\n\nCreates a new graphical object of the specified type \nas a child to the specified parent object. The object \nis configured according to the options and its \nidentifier is returned. If no options are provided, \ndefault option values are used.\n\nIf a name is provided, this name can be used to \nreference the object instead of the object identifier. \nThe name is local to the process which creates the object.\n\nThe following object types exist: \nwindow | button | radiobutton | checkbutton | label | \nframe | entry | listbox | canvas | arc | image | line \n| oval | polygon | rectangle | text | menubar | menubutton \n| menu | menuitem | grid | gridline | editor | scale\n\n
@@create_tree(Parent, Tree) -> ok@@ \n\nTypes:\n\nParent = gsobj()\nTree = [Object]\n๏ฟฝObject = {~ObjType,Options} | {~ObjType,Options,Tree} | {~ObjType,Name,Options,Tree}\n
@@ destroy(~GSObj) -> void() @@\n\nTypes:\n\n~GSObj = gsobj()\n\nDestroys a graphical object and all its children.\n\n
Parents\n* [[frame]]\n* [[window]]\nChildren \n* none\n{{{\ndefault_options(editor) -> [{height,200}, {width,300}, {x,0}, {y,0}];\n}}}\n\nThere is a bug in the gs code related to highlightfg. Attempting to change it has no effect.\n\n{{{\n%%------------------------------------------------------------------------------\n%% EDITOR OPTIONS (says canvas in the src file)\n%%\n%% Attributes:\n%% activebg Color\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bc Color\n%% bg Color\n%% bw Wth\n%% data Data\n%% fg Color\n%% font Font\n%% height Int\n%% highlightbg Color\n%% highlightbw Wth\n%% highlightfg Color\n%% hscroll Bool | top | bottom\n%% insertbg Color\n%% insertbw Wth\n%% insertpos {Row,Col}|'end' (Row: 1..Max, Col: 0..Max)\n%% justify left|right|center\n%% padx Int (Pixels)\n%% pady Int (Pixels)\n%% relief Relief\n%% scrollbg Color\n%% scrollfg Color\n%% selectbg Color\n%% selectbw Width\n%% selectfg Color\n%% vscroll Bool | left | right\n%% width Int\n%% wrap none | char | word\n%% x Int\n%% y Int\n%%\n%%\n%% Commands:\n%% clear\n%% del {FromIdx, ToIdx} \n%% enable Bool\n%% file String\n%% get {FromIdx, ToIdx} => Text\n%% insert {Index, Text}Index = [insert,{Row,lineend},end,{Row,Col}]\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n}}}\n\nHere is some additional info from official User Guide. \n{{{\nAttributes:\n\n{Option,Value} Default Description\n{hscroll, Bool | top | bottom} false Horizontal scroll bar.\n{insertpos,{row,Col}} <unspec> The position of the cursor.\n{insertpos,'end'} <unspec> The position of the cursor.\n{justify, left| right| center} left Text justification.\n{scrollbg, Color} <unspec> Background color of scroll bar.\n{scrollfg, Color} <unspec> Foreground color of scroll bar.\n{selection, {FromIndex,ToIndex}} <unspec> The text range that is currently selected.\n{vscroll, Bool | left | right} false Vertical scroll bar.\n{vscrollpos, row} <unspec> The top most visible row in the editor.\n{wrap, none|char | word} none How to wrap text when the line is full.\n\nEditor Config-Only Options \nConfig-Only Description\nclear Clears the editor.\n{del, {FromIndex, ToIndex}}} Deletes text.\n{fg, {{FromIndex,ToIndex},Color}} Sets the foreground color of a range of text.\n{load, FileName} Read FileName into the editor.\n{insert, {Index, Text}} Inserts new text.\n{overwrite, {Index, Text}} Writes new text at index.\n{save, FileName} Writes editor contents to file.\n\n\nEditor Read-Only Options \nRead-Only Return Description\nchar_height Int The height of the editor window measured in characters.\nchar_width Int The width of the editor window measured in characters.\n{fg,Index} Int The foreground color of the text at Index.\n{get,{FromIndex, ToIndex}} Text The text between the indices.\nsize Int The number of rows in the editor.\n}}}\n
Parents\n* [[frame]]\n* [[window]]\nChildren \n* none\n{{{\ndefault_options(entry) -> [{height,30}, {width,100}, {x,0}, {y,0}];\n}}}\n{{{\n%%------------------------------------------------------------------------------\n%% ENTRY OPTIONS\n%%\n%% Attributes:\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bg Color\n%% bw Int\n%% data Data\n%% fg Color\n%% font Font\n%% height Int\n%% highlightbg Color\n%% highlightbw Int (Pixels)\n%% highlightfg Color\n%% insertbg Color\n%% insertbw Int (0 or 1 Pixels ???)\n%% justify left|right|center\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%% selectbg Color\n%% selectbw Int (Pixels)\n%% selectfg Color\n%% text String\n%% width Int\n%% x Int\n%% xselection Bool\n%% y Int\n%%\n%% Commands:\n%% delete Index | {From, To}\n%% enable Bool\n%% insert {index,String}\n%% select {From, To} | clear\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read options:\n%% children\n%% id\n%% index Index => Int\n%% parent\n%% type\n%%\n%%\n%% Not Implemented:\n%% cursor ??????\n%% focus ?????? (-takefocus)\n%% font ??????\n%% hscroll ??????\n%% show ??????\n%% state ??????\n%%\n}}}
@@Code notes@@\nUsing variables (S, Win, Butt). See also [[ex02]].\n{{{\n-module(ex1).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([init/0]).\n\ninit() -> \n S = gs:start(),\n %% the parent of a top-level window is the gs server\n Win = gs:create(window,S,[{width,200},{height,100}]),\n Butt = gs:create(button,Win,[{label, {text,"Press Me"}}]),\n gs:config(Win, {map,true}),\n loop(Butt). \n\nloop(Butt) ->\n receive\n {gs, Butt, click, Data, Args} ->\n io:format("Hello There~n",[]),\n loop(Butt)\n end.\n}}}
Using names instead of variables (see [[ex01]]), except for S = gs:start().\n\n{{{\n-module(ex2).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([init/0]).\n\ninit() -> \n S = gs:start(),\n gs:create(window,win1,S,[{width,200},{height,100}]),\n gs:create(button,b1,win1,[{label, {text,"Press Me"}}]),\n gs:config(win1, {map,true}),\n loop(). \n\nloop() ->\n receive\n {gs, b1, click, Data, Args} ->\n io:format("Hello World!~n",[]),\n loop()\n end.\n}}}
@@Code notes@@\nloop/2 handles 2 buttons.\nThe click event is recognized in the receive block.\nCompare this to [[ex04]], which has no args in the loop.\n\nI have modified this code to use the standard start/0\nfunction. Also, I have added a destroy event message to\nkeep Erlang from hanging on exit.\n\n{{{\n-module(ex3).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0, init/0]).\n\nstart()-> init().\n\ninit() ->\n S = gs:start(),\n W = gs:create(window,S,[{width,300},{height,200}]),\n B1 = gs:create(button,W,[{label, {text,"Button1"}},{y,0}]),\n B2 = gs:create(button,W,[{label, {text,"Button2"}},{y,40}]),\n gs:config(W, {map,true}),\n loop(B1,B2).\n\nloop(B1,B2) ->\n receive\n {gs,B1,click,_Data,_Arg} -> % button 1 pressed\n io:format("Button 1 pressed!~n",[]),\n loop(B1,B2);\n {gs,B2,click,_Data,_Arg} -> % button 2 pressed\n io:format("Button 2 pressed!~n",[]),\n loop(B1,B2);\n %%added next msg pattern\n {gs,_, destroy, _,_} -> true\n\n end.\n}}}
@@Code notes\n*No args to the loop() function.\n**Compare this to [[ex03]]\n*Clean looking init code\n*Modified to include a standard start/0 function\n{{{\n-module(ex4).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0,init/0]).\n\n%%start/0 added\nstart() -> init().\n\ninit() ->\n S = gs:start(),\n gs:create(window,win1,S,[{width,300},{height,200}]),\n gs:create(button,b1,win1,[{label, {text,"Button1"}},{y,0}]),\n gs:create(button,b2,win1,[{label, {text,"Button2"}},{y,40}]),\n gs:config(win1, {map,true}),\n loop(). %% look, no args!\n\nloop() ->\n receive\n {gs,b1,click,_,_} -> % button 1 pressed\n io:format("Button 1 pressed!~n",[]),\n loop();\n {gs,b2,click,_,_} -> % button 2 pressed\n io:format("Button 2 pressed!~n",[]),\n loop()\n end.\n}}}
@@Code notes@@\nUsing apply/3 to simplify loop/0.\nTo work, the MFA info must be stored with the button when created.\nM = module F = function A = argument list\nFor example, {data,{ex5,b1,[]}} \n\nThe 'data' is sent along in the message.\n\n{gs, IdOrName, EventType, Data, Args}\n* gs is a tag which says it is an event from the gs graphics server.\n* IdOrName contains the object identifier or the name of the object in which the event occurred.\n* EventType contains the type of event which has occurred. In the example shown, it is either click or enter.\n* Data is a field which the user can set to any Erlang term. It is very useful to have the object store arbitrary data which is delivered with the event.\n* Args is a list which contains event specific information. In a motion event, the Args argument would contain the x and y coordinates.\n\nIn this code example, {gs,_,click,{M,F,A},_} is sent. This basically means, if you get a click message from any object, store the data into M,F, and A. IdOrName and Args are not used. If it is not 'click', disregard it.\n\n@@Layout@@\nThe buttons have a 'y' option {y, 0} and {y, 40}. This places the second button below the first.\nSee [[button]] for info about the unstated defaults that are used.\n\nA question: does 'click' also apply to the window object too? \nAccording to the comments in the source code, there is no 'click' event for a [[window]].\n\n{{{\n-module(ex5).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0, init/0, b1/0, b2/0]).\n\nstart() ->\n spawn(ex5, init, []).\n\ninit() ->\n S = gs:start(),\n W = gs:create(window,S,[{map,true}]), \n gs:create(button,W,[{label,{text,"Button1"}},{data,{ex5,b1,[]}},{y,0}]),\n gs:create(button,W,[{label,{text,"Button2"}},{data,{ex5,b2,[]}},{y,40}]),\n loop().\n\nloop()->\n receive\n {gs,_,click,{M,F,A},_} -> % any button pressed\n apply(M,F,A),\n loop()\n end.\n\nb1() ->\n io:format("Button 1 pressed!~n",[]).\nb2() ->\n io:format("Button 2 pressed!~n",[]).\n}}}\n
@@Code notes@@\nThe receive block accepts every kind of event that is activated:\nFor window: keypress, buttonpress, motion\nFor button: enter, leave.\nWhat about a click event? click is on by default. \n\nNotice a couple of things: \n* clicking a button triggers both buttonpress (window), and click (button). buttonpress is first\n* holding down the button sends a series of click messages, but only one buttonpress\n* if the window has focus, then a keypress or buttonpress anywhere sends a message \n\n{{{\n-module(ex6).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0,init/0]).\n\nstart() ->\n spawn(ex6,init,[]).\n\ninit() ->\n S = gs:start(),\n W = gs:create(window,S,[{map,true},{keypress,true},\n {buttonpress,true},{motion,true}]),\n gs:create(button,W,[{label,{text,"PressMe"}},{enter,true},\n {leave,true}]),\n event_loop().\n\nevent_loop() ->\n receive\n X ->\n io:format("Got event: ~w~n",[X]),\n event_loop()\n end.\n}}}
@@Code notes@@\nI have modified this slightly, to use a start/0 function.\nThe original code generates a lot of warnings about unused variables.\n\nThis shows config/2 in use, after the window is created, but before\nthe event_loop. In this case the window object is sent to the event loop.\n\nEvents that are activated are: motion, keypress, buttonpress, buttonrelease, and configure.\nThe configure option captures resizing of the window (height and width in pixels)\nand moving the window as a whole (H and W don't change), though it doesn't tell\nyou where it moved to relative to the screen as a whole. \n\nCuriously, mouse motion is detected going over the window (visible portion), \neven if it does not have focus!\n\nCertain keypresses are captured, using the Arg list:\n* a = {gs,Win,keypress,Data, [a | Rest]}\n* shift a = {gs,Win,keypress,Data, [_,65,1 | Rest]} \n* <ctrl>-c = {gs,Win,keypress,Data, [c,_,_,1 | Rest]} \n* <return> = {gs,Win,keypress,Data, ['Return' | Rest]} \n\nI don't see an obvious pattern here, so I will look around for more\ninfo on keypress.\n\n{{{\n-module(ex7).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0, mk_window/0]).\n\nstart() -> mk_window().\n\nmk_window() ->\n S= gs:start(),\n Win= gs:create(window,S,[{motion,true},{map,true}]),\n gs:config(Win,[{configure,true},{keypress,true}]),\n gs:config(Win,[{buttonpress,true}]),\n gs:config(Win,[{buttonrelease,true}]),\n event_loop(Win).\n\nevent_loop(Win) -> \n receive\n {gs,Win,motion,Data,[X,Y | Rest]} ->\n %% mouse moved to position X Y\n io:format("mouse moved to X:~w Y:~w~n",[X,Y]);\n {gs,Win,configure,Data,[W,H | Rest]} ->\n %% window was resized by user\n io:format("window resized W:~w H:~w~n",[W,H]);\n {gs,Win,buttonpress,Data,[1,X,Y | Rest]} -> \n %% button 1 was pressed at location X Y\n io:format("button 1 pressed X:~w Y:~w~n",[X,Y]);\n {gs,Win,buttonrelease,Data,[_,X,Y | Rest]} ->\n %% Any button (1-3) was released over X Y\n io:format("Any button released X:~w Y:~w~n",[X,Y]);\n {gs,Win,keypress,Data,[a | Rest]} -> \n %% key `a' was pressed in window\n io:format("key a was pressed in window~n");\n {gs,Win,keypress,Data,[_,65,1 | Rest]} ->\n %% Key shift-a\n io:format("shift-a was pressed in window~n");\n {gs,Win,keypress,Data,[c,_,_,1 | Rest]} ->\n %% CTRL_C pressed\n io:format("CTRL_C was pressed in window~n");\n {gs,Win,keypress,Data, ['Return' | Rest]} ->\n %% Return key pressed\n io:format("Return key was pressed in window~n")\n end,\n event_loop(Win).\n}}}
@@Code notes@@\nI added a 'destroy' message to the receive block. Otherwise the program hangs.\n\nThis program show that two radiobuttons can share the same 'value'\n(and both appear to be marked in the window). Personally, I don't \nsee any use for this.\n\nThe real issue is what is going on with the Args of the\nreceive message for radiobuttons. How do you interpret this:\n{{{\n[Text, Grp, a | Rest]\n}}}\nWhen the code is compiled it gives off warning msgs about unused variables. Since the\nvariables aren't used, this code isn't much help in explaining the Args:\n{{{\n3> c(ex8). \n./ex8.erl:16: Warning: variable 'Any_Rb' is unused\n./ex8.erl:16: Warning: variable 'Data' is unused\n./ex8.erl:16: Warning: variable 'Grp' is unused\n./ex8.erl:16: Warning: variable 'Rest' is unused\n./ex8.erl:16: Warning: variable 'Text' is unused\n./ex8.erl:19: Warning: variable 'Data' is unused\n./ex8.erl:19: Warning: variable 'Grp' is unused\n./ex8.erl:19: Warning: variable 'Rest' is unused\n./ex8.erl:19: Warning: variable 'Text' is unused\n{ok,ex8}\n}}}\n\n{{{\n-module(ex8).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0]).\n\nstart() ->\n gs:window(win,gs:start(),{map,true}),\n gs:radiobutton(rb1,win,[{label,{text,"rb1"}},{value,a},{y,0}]),\n gs:radiobutton(rb2,win,[{label,{text,"rb2"}},{value,a},{y,30}]),\n gs:radiobutton(rb3,win,[{label,{text,"rb3"}},{value,b},{y,60}]),\n rb_loop().\n\nrb_loop() ->\n receive\n {gs,Any_Rb,click,Data,[Text, Grp, a | Rest]} ->\n io:format("either rb1 or rb2 is on.~n",[]),\n rb_loop();\n {gs,rb3,click,Data,[Text, Grp, b | Rest]} ->\n io:format("rb3 is selected.~n",[]),\n rb_loop();\n %% the next line was added (and the semicolon to the line above)\n {gs,_, destroy, _,_} -> bye\n end.\n}}}
@@Code notes@@\nThis example used an 'attribute' option of an object. It uses\nthe text option of the entry object. \nthe keypress option for the entry object is turned on\n{{{\n gs:create(entry,entry,Win,[{x,10},{y,30},{width,130},\n {keypress,true}]),\n}}}\nkeypress messages are monitored by these two statements:\n{{{\n{gs,entry,keypress,_,['Return'|_]} ->\n...\n{gs,entry,keypress,_,_} -> % all other keypresses\n...\n}}}\nThe first matches on <ReturnKey>, the second matches on anything \n(except <ReturnKey>). Until <ReturnKey> is typed, nothing\nhappens except to repeat the loop. When <ReturnKey> is hit,\nthen the entry object is read and stored in the variable Text.\n{{{\nText=gs:read(entry,text), \n}}}\nSee [[gs:read/2 |read/2]]. text (with the small 't') is an\nattribute option for [[entry]] objects. That means it can\nstore a value. The text attribute of an entry object stores\na string. \nClicking the ok button does the same thing.\n\nHow does the value of the text attribute get into\nthe erlang shell? By the next line in loop/1: \n{{{\nPid ! {entry_reply,{name,Text}}\n}}}\nLook at how the code starts. The init/1 function is spawned\nas a process. The parameter (Pid) is filled with\nself() from start/0. self() thus comes from whatever\nprocess is performing start/0. In this case, the process\nrunning start/0 is the shell. So, the shell process is Pid in\ninit/1. init/1 sends Pid along to the loop/1 function.\nloop/1 sends the message to Pid. \nWhile all this has been going on the shell has been\nin a receive block waiting for a message. It looks for\na message formatted like this:\n{{{\n {entry_reply, Reply} \n}}}\nWhen it get it, the text attribute value (stored in\nReply) is isolated then used as the 'then' part of \nthe receive statement (-> Reply).\n\n@@Further note@@\nIf you remove the {keypress,true} option from the entry object,\nletters will still appear in the box. (Don't confuse the keypress\noption with the enable option). The text you are typing will\nstill go into the entry object. The ok button will work\nthe same. The only noticeable difference is that the 'Return' key\nwon't do anything. \n\n\n{{{\n-module(ex9).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0,init/1]).\n\nstart() ->\n spawn(ex9, init, [self()]),\n receive\n {entry_reply, Reply} -> Reply\n end.\n\ninit(Pid) ->\n S = gs:start(),\n Win = gs:create(window,S,[{title,"Entry Demo"},\n {width,150},{height,100}]),\n gs:create(label,Win,[{label,{text,"What's your name?"}},\n {width,150}]),\n gs:create(entry,entry,Win,[{x,10},{y,30},{width,130},\n {keypress,true}]),\n gs:create(button,ok,Win,[{width,45},{y,60},{x,10},\n {label,{text,"Ok"}}]),\n gs:create(button,cancel,Win,[{width,60},{y,60},{x,80},\n {label,{text,"Cancel"}}]),\n gs:config(Win,{map,true}),\n loop(Pid).\n\nloop(Pid) ->\n receive\n {gs,entry,keypress,_,['Return'|_]} ->\n Text=gs:read(entry,text),\n Pid ! {entry_reply,{name,Text}};\n {gs,entry,keypress,_,_} -> % all other keypresses\n loop(Pid);\n {gs,ok,click,_,_} ->\n Text=gs:read(entry,text),\n Pid ! {entry_reply,{name,Text}};\n {gs,cancel,click,_,_} ->\n Pid ! {entry_reply,cancel};\n X ->\n io:format("Got X=~w~n",[X]),\n loop(Pid)\n end.\n}}}
@@Code notes@@\nThis module shows one way to create a listbox object.\nLook at the options for the listbox object:\n{{{\n [{x,5},{y,65},{width,160},\n {height,195},{vscroll,right},\n {click,true},{doubleclick,true}])\n}}}\nA single click reconfigures the entry object:\n{{{\n {gs,Lb,click,_,[Idx, Txt|_]} ->\n gs:config(Entry,{text,Txt}),\n}}}\nA doubleclick sends a message to the shell\n(Idx is an unused variable. It generates\na warning when compiling):\n{{{\n {gs,Lb,doubleclick,_,[Idx, Txt|_]} ->\n Pid ! {browser,{ok,Txt}};\n}}}\nThe ok button sends \n{{{\n-module(ex10).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0, init/3]).\n\nstart() ->\n start("Pick a fruit:", \n [apple, banana, lemon, orange, strawberry, \n mango, kiwi, pear, cherry,pineapple,peach,apricot]).\n\nstart(Text,Items) ->\n spawn(ex10,init,[self(),Text,Items]), \n receive\n {browser,Result} -> Result\n end.\n\ninit(Pid,Text,Items) ->\n S=gs:start(),\n Win=gs:window(S,[{width,250},{height,270},\n {title,"Browser"}]),\n Lbl=gs:label(Win,[{label,{text,Text}},{width,250}]),\n Entry=gs:entry(Win,[{y,35},{width,240},{x,5},\n {keypress,true},\n {setfocus,true}]),\n Lb=gs:listbox(Win,[{x,5},{y,65},{width,160},\n {height,195},{vscroll,right},\n {click,true},{doubleclick,true}]),\n Ok=gs:button(Win,[{label,{text,"OK"}},\n {width,40},{x,185},{y,175}]),\n Cancel=gs:button(Win,[{label,{text,"Cancel"}},\n {x,175},{y,225},{width,65}]),\n gs:config(Lb,[{items,Items}]),\n gs:config(Win,{map,true}),\n browser_loop(Pid,Ok,Cancel,Entry,Lb).\n\nbrowser_loop(Pid,Ok,Cancel,Entry,Lb) ->\n receive\n {gs,Ok,click,_,_} ->\n Txt=gs:read(Entry,text),\n Pid ! {browser,{ok,Txt}};\n {gs,Cancel,click,_,_} ->\n Pid ! {browser,cancel};\n {gs,Entry,keypress,_,['Return'|_]} ->\n Txt=gs:read(Entry,text),\n Pid ! {browser,{ok,Txt}};\n {gs,Entry,keypress,_,_} ->\n browser_loop(Pid,Ok,Cancel,Entry,Lb);\n {gs,Lb,click,_,[Idx, Txt|_]} ->\n gs:config(Entry,{text,Txt}),\n browser_loop(Pid,Ok,Cancel,Entry,Lb);\n {gs,Lb,doubleclick,_,[Idx, Txt|_]} ->\n Pid ! {browser,{ok,Txt}};\n {gs,_,destroy,_,_} ->\n Pid ! {browser,cancel};\n X ->\n io:format("Got X=~w~n",[X]),\n browser_loop(Pid,Ok,Cancel,Entry,Lb)\n end.\n}}}
@@Code notes@@\nThis module creates several scale objects and uses the\nData field of the gs message in pattern matching. \n\nHow does it work? Each scale object has a different\ndata value {data, red}, {data,blue}, {data, green}.\nEach of those has a pattern in the receive block. \nHere's the pattern for Data = red. \n\n{{\n {gs,_,click,red,[New_R|_]} ->\n}}\nIt is the Args that we are interested in:\nNew_R is the head of the Args list. It contains\nthe number value of that particular scale. That \nnumber is fed back to the loop:\n{{{\n loop(W,New_R,G,B);\n}}}\n\nSo why does the color change? Because, the \nfirst thing the loop does is reconfigure the windows,\nmodifying the background option:\n{{{\n gs:config(W,{bg,{R,G,B}}),\n}}}\n(bg = background option)\n\nNote: The button has a label with an image instead of text\nThe name of the image file is "die_icon" (a bitmap), \nbut it is not provided with the code. I have tried\nother bitmaps (.bmp) as well as .gif files and cannot\nget any of them to work here. I have changed the\nlabel to text to make the button visible.\n\n\n{{{\n-module(ex11).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/3 $ ').\n\n-export([start/0,init/0]).\n\nstart() ->\n spawn(ex11,init,[]).\n\ninit() ->\n I= gs:start(),\n W= gs:window(I,[{title,"Color Demo"},\n {width,300},{height,195}]), \n%% B=gs:button(W,[{label,{image,"die_icon"}},{x,271},{y,166},\n%% {width,30}]),\n B=gs:button(W,[{label,{text,"bye!"}},{x,271},{y,166},\n {width,30}]),\n gs:config(B,[{bg,yellow},{fg,hotpink1},{data,quit}]),\n gs:scale(W,[{text,"Red"},{y,0},{range,{0,255}},\n {orient,horizontal},\n {height,65},{data,red},{pos,42}]),\n gs:scale(W,[{text,"Blue"},{y,65},{range,{0,255}},\n {orient,horizontal},\n {height,65},{data,blue},{pos,42}]),\n gs:scale(W,[{text,"Green"},{y,130},{range,{0,255}},\n {orient,horizontal},\n {height,65},{data,green},{pos,42}]),\n gs:config(W,{map,true}),\n loop(W,0,0,0).\n\nloop(W,R,G,B) ->\n gs:config(W,{bg,{R,G,B}}),\n receive\n {gs,_,click,red,[New_R|_]} ->\n loop(W,New_R,G,B);\n {gs,_,click,green,[New_G|_]} ->\n loop(W,R,New_G,B);\n {gs,_,click,blue,[New_B|_]} ->\n loop(W,R,G,New_B);\n {gs,_,click,quit,_} ->\n true;\n {gs,W,destroy,_,_} ->\n true\n end.\n}}}
@@Code notes@@\nExample of how to build a grid object with gridlines. \nThe content of each gridline is hardcoded, without a loop\nwhich doesn't lend itself meaningful use. It would be\nbetter if it at least read a list and created a series\nof gridlines. \n\nThis code also uses [[create_tree/2]]. The two parameters\nare Parent, Tree. Parent is gs:start(). Tree is a list. \nThe tree has one element, a tuple. \n\nThis may be right: {object, [options]}\n\nIt is rather convoluted and I will need some time to figure \nout how the pieces fit together. I don't know why anyone\nwould want to build a grid this way. \n\n\n{{{\n-module(ex12).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0,init/0]).\n\nstart() -> spawn(ex12, init, []).\n\ninit() ->\n R=[{window,[{width,200},{height,200},{title,"grid"},{map, true}],\n {grid, [{x,10},{y,10},{height,180},{width,180},{columnwidths,[80,60]},\n {rows,{1, 20}}],\n [{gridline,[{text,{1,"NAME"}},{text,{2,"PHONE"}},\n {font,{screen,bold,12}},{row,1},{click,false}]},\n {gridline,[{text,{1,"Adam"}},{text,{2,"1234"}},{row,2}]},\n {gridline,[{text,{1,"Beata"}},{text,{2,"4321"}},{row,3}]},\n {gridline,[{text,{1,"Thomas"}},{text,{2,"1432"}},{row,4}]},\n {gridline,[{text,{1,"Bond"}},{text,{2,"007"}},{row,5}]},\n {gridline,[{text,{1,"King"}},{text,{2,"112"}},{row,6}]},\n {gridline,[{text,{1,"Eva"}},{text,{2,"4123"}},{row,7}]}]}}],\n gs:create_tree(gs:start(),R),\n loop().\n\nloop() ->\n receive\n {gs,_Win,destroy,_Data,_Args} -> bye;\n {gs,_Gridline,click,_Data,[Col,Row,Text|_]} ->\n io:format("Click at col:~p row:~p text:~p~n",[Col,Row,Text]),\n loop();\n Msg ->\n io:format("Got ~p~n",[Msg]),\n loop()\n end.\n}}}
@@Code notes@@\nPatience is a virtue when creating menus -- they are so damn long!\n\nNotice how the help section of the menu has checkmarks\nthat can be turned on and off (the itemtype option).\n{{{\n Y = gs:create(menuitem, Hmnu, [{label, {text,"You"}},\n {itemtype, check}]),\n M = gs:create(menuitem, me, Hmnu, [{label, {text, "Me"}},\n {itemtype, check}]),\n}}}\nArgs of the click message for the 'You' menuitem, clicked twice \n{{{\n["You",0,mcb0,true]}\n["You",0,mcb0,false]}\n}}}\n\nThe Args of the click message for the color menuitem, \n{{{\n["Red",0,gr1,v0]\n["Blue",1,gr1,v1]\n["Black",2,gr1,v2]\n}}}\nThe loop carries Exit (a menuitem object) around with it as a parameter. Why?\n{{{\n Exit = gs:create(menuitem, Fmnu,\n [{label,{text, "Exit"}}]),\n ...\n loop(Exit, Win).\n}}}\nResults of clicking You, Me and Doit: Notice that You\nwas created with create/3 and Me was created with create/4\nThe doit menuitem object stores the ObjID of the You and Me menuitem\nobjects in its data option. {doit, YouId, MeId} \nIn the loop, the select option of the You and\nMe menuitem objects is read using the YouId and MeId\n{{{\nOther:{gs,{35,<0.33.0>},click,[],["You",0,mcb0,false]}\nOther:{gs,me,click,[],["Me",1,mcb1,false]}\nDoit. HelpMe:false, HelpYou:false, Args:["Doit!",4]\nOther:{gs,{35,<0.33.0>},click,[],["You",0,mcb0,true]}\nOther:{gs,me,click,[],["Me",1,mcb1,true]}\nDoit. HelpMe:true, HelpYou:true, Args:["Doit!",4]\nOther:{gs,{35,<0.33.0>},click,[],["You",0,mcb0,false]}\nDoit. HelpMe:true, HelpYou:false, Args:["Doit!",4]\n}}}\n\nThere are many unused variables in this code.\n{{{\n1> c(ex13).\n./ex13.erl:56: Warning: variable 'Index' is unused\n./ex13.erl:56: Warning: variable 'Rest' is unused\n./ex13.erl:56: Warning: variable 'Txt' is unused\n./ex13.erl:58: Warning: variable 'Index' is unused\n./ex13.erl:58: Warning: variable 'Rest' is unused\n./ex13.erl:58: Warning: variable 'Txt' is unused\n./ex13.erl:60: Warning: variable 'Index' is unused\n./ex13.erl:60: Warning: variable 'Rest' is unused\n./ex13.erl:60: Warning: variable 'Txt' is unused\n{ok,ex13}\n}}}\n\n\n{{{\n-module(ex13).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0,init/0]).\n\nstart() -> spawn(ex13, init, []).\n\ninit() ->\n I=gs:start(),\n Win=gs:window(I, [{width,200},{height,100},\n {title,"menu"},{map, true}]),\n Bar = gs:create(menubar, Win, []),\n Fmb = gs:create(menubutton, Bar,\n [{label,{text,"File"}}]),\n Emb = gs:create(menubutton, Bar,\n [{label,{text,"Edit"}}]),\n Hmb = gs:create(menubutton, Bar,\n [{label,{text,"Help"}},{side,right}]),\n Fmnu = gs:create(menu, Fmb, []),\n Emnu = gs:create(menu, Emb, []),\n Hmnu = gs:create(menu, Hmb, []),\n gs:create(menuitem, load, Fmnu,\n [{label,{text, "Load"}}]),\n gs:create(menuitem, save, Fmnu,\n [{label,{text, "Save"}}]),\n Exit = gs:create(menuitem, Fmnu,\n [{label,{text, "Exit"}}]),\n Color = gs:create(menuitem, Emnu,\n [{label,{text, "Color"}},\n {itemtype, cascade}]),\n Cmnu = gs:create(menu, Color, [{disabledfg,gray}]),\n gs:create(menuitem, Cmnu, [{label, {text,"Red"}},\n {data, {new_color, red}},\n {itemtype,radio},{group,gr1}]),\n gs:create(menuitem, Cmnu, [{label, {text,"Blue"}},\n {data, {new_color, blue}},\n {itemtype,radio},{group,gr1}]),\n gs:create(menuitem,Cmnu, [{label, {text,"Black"}},\n {data, {new_color, black}},\n {itemtype,radio},{group,gr1}]),\n Y = gs:create(menuitem, Hmnu, [{label, {text,"You"}},\n {itemtype, check}]),\n M = gs:create(menuitem, me, Hmnu, [{label, {text, "Me"}},\n {itemtype, check}]),\n gs:create(menuitem, Hmnu, [{itemtype, separator}]),\n gs:create(menuitem, Hmnu, [{label, {text, "Other"}},\n {itemtype, check},\n {enable,false}]),\n gs:create(menuitem, doit, Hmnu, [{label, {text, "Doit!"}},\n {data, {doit, Y, M}}]),\n loop(Exit, Win).\n\nloop(Exit, Win) ->\n receive\n {gs, save, click, _Data, [Txt, Index | Rest]} ->\n io:format("Save~n");\n {gs, load, click, _Data, [Txt, Index | Rest]} ->\n io:format("Load~n");\n {gs, Exit, click, _Data, [Txt, Index | Rest]} ->\n io:format("Exit~n"),\n exit(normal);\n {gs, _MnuItem, click, {new_color, Color}, Args} ->\n io:format("Change color to ~w. Args:~p~n",\n [Color, Args]),\n gs:config(Win, [{bg, Color}]);\n {gs, doit, click, {doit, YouId, MeId}, Args} ->\n HelpMe = gs:read(MeId, select),\n HelpYou = gs:read(YouId, select),\n io:format("Doit. HelpMe:~w, HelpYou:~w, Args:~p~n",\n [HelpMe, HelpYou, Args]);\n Other -> io:format("Other:~p~n",[Other])\n end,\n loop(Exit, Win).\n}}}
@@Code notes\n* editor object\n* button object that clears the editor\n**editor must be enabled to be able to do editor command option 'clear'. Done in code, then reset.\n**the clear option has no 'value'. It won't work if in a tuple. \n* checkbutton object that enables/disables the editor\n* button object that inserts text into the editor at current editor cursor location.\n** gs:config(editor,{insert, {insert, TimeStr}}) \n**also enables editor, then reset it after inserting. \n* current time (hour, minute, second) accessed\n* quit button calls exit(normal).\n\neditor object\ninsert is a command option: {insert, {Where, Text}}\nvalue is a tuple (Where, Text}, Where is one of [insert,{Row,lineend},end,{Row,Col}]\ninsert = current cursor position\n[Row, lineend] = end of a specific row.\nend = end of editor text\n[Row, Col] = specific location\n\nexample: gs:config(editor1, {insert, {end, "put me last"}}). \n\n{{{\n-module(ex14).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/2 $ ').\n\n-export([start/0,init/0]).\n\nstart() -> spawn(ex14, init, []).\n\ninit() ->\n Y = [{y,0},{height, 30},{width, 90}],\n R=[{window, [{width, 400},{height, 300}, {title,"editor"},{map, true}],\n [{editor,editor,[{x,0},{y, 35},{width,300},{height,250},\n {insert,{'end',"Edit this text!"}},{vscroll,right}]},\n {button, clear, [{label, {text, "Clear"}},{x,0} | Y]},\n {checkbutton,enable,[{label,{text,"Enable"}},{select,false},{x,100}|Y]},\n {button, time, [{label, {text, "Insert Time"}},{x,200} | Y]},\n {button, quit, [{label, {text, "Quit"}},{x,300} | Y]}]}],\n gs:create_tree(gs:start(),R),\n gs:config(editor,{enable,false}),\n loop().\n\nloop() ->\n receive\n {gs, clear, _, _, _} ->\n io:format("clear editor~n"),\n Enable = gs:read(editor, enable),\n gs:config(editor,{enable, true}),\n gs:config(editor,clear),\n gs:config(editor,{enable, Enable});\n {gs, enable, _, _, [_Txt, _Grp, Enable|_]} ->\n io:format("Enable: ~w~n", [Enable]),\n gs:config(editor,{enable, Enable});\n {gs, time, _, _, _} ->\n TimeStr = io_lib:format("Hr:Min:Sec is now ~w:~w:~w~n",\n tuple_to_list(time())),\n io:format("Insert Time: ~s~n", [TimeStr]),\n Enable = gs:read(editor, enable),\n gs:config(editor,{enable, true}),\n gs:config(editor,{insert, {insert, TimeStr}}),\n gs:config(editor,{enable, Enable});\n {gs, quit, _, _, _} ->\n exit(normal);\n Other ->\n io:format("Other:~w~n",[Other])\n end,\n loop().\n}}}\n
@@Code notes@@\n*change fonts by configuring font option of a text object\n{{{\n gs:create(text,can1,[{font,Font},{text,Txt},{coords,[{0,Y+1}]}]),\n}}}\nwhere Font is one of [{times,19},{screen,16},{helvetica,bold,21},\n {symbol,12},{times,[bold,italic],33},{courier,6}]\n\nunused variable\n{{{\n1> c(ex15).\n./ex15.erl:14: Warning: variable 'E' is unused\n{ok,ex15}\n}}}\n{{{\n-module(ex15).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/3 $ ').\n\n-export([start/0,init/0]).\n\nstart() -> spawn(ex15, init, []).\n\ninit() ->\n I=gs:start(),\n Win=gs:create(window, I,\n [{width, 400},{height, 250},\n {title,"Font Demo"},{map, true}]),\n E = gs:create(canvas, can1,Win,\n [{x,0},{y, 0},{width,400},{height,250}]),\n Fonts = [{times,19},{screen,16},{helvetica,bold,21},\n {symbol,12},{times,[bold,italic],33},{courier,6}],\n show_fonts_in_boxes(Fonts,0),\n receive\n {gs,_Id,destroy,_Data,_Arg} -> bye\n end.\n\nshow_fonts_in_boxes([],_) -> done;\nshow_fonts_in_boxes([Font|Fonts],Y) ->\n Txt = io_lib:format("Hi! ~p",[Font]),\n {Width,Height} = gs:read(can1,{font_wh,{Font,Txt}}),\n Y2=Y+Height+2,\n gs:create(rectangle,can1,[{coords,[{0,Y},{Width,Y2}]}]),\n gs:create(text,can1,[{font,Font},{text,Txt},{coords,[{0,Y+1}]}]),\n show_fonts_in_boxes(Fonts,Y2+1).\n}}}
@@Code notes@@\nrandom drawing of text, rectangles and ovals.\n* a window with a canvas\n* erlang:now/0 \n* random:seed/3\n* random:uniform/1\n\n{{{\n-module(ex16).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/3 $ ').\n\n-export([start/0,init/0]).\n\nstart() -> spawn(ex16, init, []).\n\ninit() ->\n I=gs:start(),\n Win=gs:create(window, I,\n [{width, 200},{height, 200},\n {title,"Default Demo"},{map, true}]),\n gs:create(canvas, can1,Win,\n [{x,0},{y, 0},{width,200},{height,200},\n {default,text,{font,{courier,bold,19}}},\n {default,text,{fg,blue}},\n {default,rectangle,{fill,red}},{default,text,{text,"Pow!"}},\n {default,oval,{fill,green}}]),\n {A,B,C} = erlang:now(),\n random:seed(A,B,C),\n loop().\n\nloop() ->\n receive\n {gs,_Id,destroy,_Data,_Arg} -> bye\n after 500 ->\n XY = {random:uniform(200),random:uniform(200)},\n draw(random:uniform(3),XY),\n loop()\n end.\n\ndraw(1,XY) ->\n gs:create(text,can1,[{coords,[XY]}]);\ndraw(2,XY) ->\n XY2 = {random:uniform(200),random:uniform(200)},\n gs:create(rectangle,can1,[{coords,[XY,XY2]}]);\ndraw(3,XY) ->\n XY2 = {random:uniform(200),random:uniform(200)},\n gs:create(oval,can1,[{coords,[XY,XY2]}]).\n}}}
@@Code notes@@\n*geometry\n*uses [[gs:ObjType/1/2/3]] instead of [[gs:create/2/3/4]]\n\nframe object\n*name = packer\n*parent = window (Win\n*options = [{stretch,1,50},{stretch,2,50},{stretch,1,50}]\n\nbutton objects \n*use the pack_xy option\n**pack_xy takes a 2-tuple value. Example: {pack_xy,{3,1}}\n\neditor object \n*has vscroll and hscroll options.\n**vscroll is set at 'true' \n**vscroll appears on the left side of the editor window.\n**use {vscroll, right} \n{{{\n-module(ex17).\n-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').\n-vsn('$Revision: /main/release/1 $ ').\n\n-export([start/0,init/0]).\n\nstart() -> spawn(ex17, init, []).\n\ninit() ->\n WH = [{width,200},{height,300}],\n Win = gs:window(gs:start(),[{map,true},{configure,true},\n {title,"Packer Demo"}|WH]),\n gs:frame(packer,Win,[{packer_x,[{stretch,1,50},{stretch,2,50},\n {stretch,1,50}]},\n {packer_y,[{fixed,30},{stretch,1}]}]),\n gs:button(packer,[{label,{text,"left"}},{pack_xy,{1,1}}]),\n gs:button(packer,[{label,{text,"middle"}},{pack_xy,{2,1}}]),\n gs:button(packer,[{label,{text,"right"}},{pack_xy,{3,1}}]),\n gs:editor(packer,[{pack_xy,{{1,3},2}},{vscroll,true},{hscroll,true}]),\n gs:config(packer,WH), % refresh to initial size\n loop().\n\nloop() ->\n receive\n {gs,_Id,destroy,_Data,_Arg} -> bye;\n {gs,_Id,configure,_Data,[W,H|_]} ->\n gs:config(packer,[{width,W},{height,H}]), % repack\n loop();\n Other ->\n io:format("loop got: ~p~n",[Other]),\n loop()\n end.\n}}}
Parents\n* [[frame]]\n* [[window]]\nChildren\n* [[button]]\n* [[radiobutton]]\n* [[checkbutton]] \n* [[canvas]], \n* [[editor]], \n* [[entry]], \n* [[frame]], \n* [[grid]], \n* [[label]], \n* [[listbox]], \n* [[menubar]], \n* [[scale]]\n* [[menubutton]]\n* [[menu]] (popups)\n{{{\ndefault_options(frame) -> [{height,100}, {width,150}, {x,0}, {y,0}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% FRAME OPTIONS\n%%\n%% Attributes:\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bg Color\n%% bw Int\n%% data Data\n%% height Int\n%% highlightbg Color\n%% highlightbw Int\n%% highlightfg Color\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%% width Int\n%% x Int\n%% y Int\n%% cursor arrow|busy|cross|hand|help|resize|text\n%%\n%% Commands:\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n}}}
Parents\n* [[frame]]\n* [[window]]\nChildren \n* [[gridline]]\n{{{\ndefault_options(grid) -> [{bg,grey}, {cellheight,20},\n {columnwidths, [80,80,80,80]},\n {fg,black}, {font,{screen, 12}},\n {height,100},\n {hscroll,bottom},\n {rows,{1,10}},\n {vscroll,right},\n {width,300},\n {x,0}, {y,0}];\n}}}\n\nNote that cellheight is not mentioned in the comments to the source code.\n{{{\n%%-----------------------------------------------------------------------------\n%% GRID OPTIONS\n%%\n%% rows {ViewFrom, ViewTo}\n%% columnwidths [CW1, CW2, ..., CWn]\n%% vscroll Bool | left | right\n%% hscroll Bool | top | bottom\n%% x Coord\n%% y Coord\n%% width Int\n%% height Int\n%% fg Color (lines and default line color)\n%% bg Color\n%%-----------------------------------------------------------------------------\n}}}
Parents\n* [[grid]]\nChildren \n* none\n{{{\ndefault_options(gridline) -> [{click,true}, {doubleclick,false}, {row,undefined}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% GRIDLINE OPTIONS\n%%\n%% text Text\n%% row Row\n%% data Data\n%% fg Color (default is the same as grid fg)\n%% click Bool\n%%\n%%-----------------------------------------------------------------------------\n}}}
Parents\n* none\nChildren\n* [[window]]\nNot really an object, but the starting point\nis always the gs server, gs:start().\n{{{\nstart() ->\n S = gs:start(),\n %% the parent of a top-level window is the gs server\n Win = gs:create(window,S,[{width,200},{height,100}]),\n ...\n}}}\n\n
If you spend a little time looking at gs_make.erl, you will get a glimmer of how the objects are grouped, and and how options are bundled with the various objects,. It is not a cut and dry process, there are many combinations.\n\n@@Code notes@@\nIf you look through here, you will not find 'click'. So how is it that certain objects recognize the \nclick event? The answer lies in gstk_widgets.erl, where a lot of default are set. A portion of that file is here: [[Default options]]\n\n{{{\n%%gs_make.erl (gs.1.5.7)\n\n%% ``The contents of this file are subject to the Erlang Public License,\n%% Version 1.1, (the "License"); you may not use this file except in\n%% compliance with the License. You should have received a copy of the\n%% Erlang Public License along with this software. If not, it can be\n%% retrieved via the world wide web at http://www.erlang.org/.\n%% \n%% Software distributed under the License is distributed on an "AS IS"\n%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See\n%% the License for the specific language governing rights and limitations\n%% under the License.\n%% \n%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.\n%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings\n%% AB. All Rights Reserved.''\n%% \n%% $Id$\n%%\n-module(gs_make).\n\n-export([start/0]).\n\nstart() ->\n Terms = the_config(),\n DB=fill_ets(Terms),\n {ok,OutFd} = file:open("gstk_generic.hrl",write),\n put(stdout,OutFd),\n% io:format("terms: ~p ~n ets:~p~n",[Terms,ets:tab2list(DB)]),\n p("% Don't edit this file. It was generated by gs_make:start/0 "),\n p("at ~p-~p-~p, ~p:~p:~p.\sn\sn",\n lists:append(tuple_to_list(date()),tuple_to_list(time()))),\n gen_out_opts(DB),\n gen_read(DB),\n file:close(OutFd),\n {ok,"gstk_generic.hrl",DB}.\n\nfill_ets(Terms) ->\n DB = ets:new(gs_mapping,[bag,public]),\n fill_ets(DB,Terms).\n\nfill_ets(DB,[]) -> DB;\nfill_ets(DB,[{Objs,Opt,Fun,Access}|Terms]) ->\n fill_ets(DB,lists:flatten(Objs),Opt,Fun,Access),\n fill_ets(DB,Terms).\n\nfill_ets(_DB,[],_,_,_) -> done;\nfill_ets(DB,[Obj|Objs],Opt,Fun,rw) ->\n ets:insert(DB,{Obj,Opt,Fun,read}),\n ets:insert(DB,{Obj,Opt,Fun,write}),\n fill_ets(DB,Objs,Opt,Fun,rw);\nfill_ets(DB,[Obj|Objs],Opt,Fun,r) ->\n ets:insert(DB,{Obj,Opt,Fun,read}),\n fill_ets(DB,Objs,Opt,Fun,r);\nfill_ets(DB,[Obj|Objs],Opt,Fun,w) ->\n ets:insert(DB,{Obj,Opt,Fun,write}),\n fill_ets(DB,Objs,Opt,Fun,w).\n\n \n \ngen_out_opts(DB) ->\n ObjTypes = lists:flatten(ordsets:from_list(ets:match(DB,{'$1','_','_',write}))),\n p("out_opts([Option|Options],Gstkid,TkW,DB,ExtraArg,S,P,C) ->\sn"),\n p(" {Opt,Val} =\sn"),\n p(" case Option of \sn"),\n p(" {{default,Cat,Key},V} -> {default,{Cat,{Key,V}}};\sn"),\n p(" {_Key,_V} -> Option;\sn"),\n p(" {default,Cat,Opti} -> {default,{Cat,Opti}};\sn"),\n p(" Atom when is_atom(Atom) -> {Atom,undefined};\sn"),\n p(" _ -> {error, {invalid_option,Option}}\sn"),\n p(" end,\sn"),\n p(" case Gstkid#gstkid.objtype of\sn"),\n gen_out_type_case_clauses(merge_types(ObjTypes),DB),\n p(" Q -> exit({internal_error,unknown_objtype,Q})\sn"),\n p(" end;\sn"),\n p("out_opts([],_Gstkid,_TkW,_DB,_ExtraArg,S,P,C) -> \sn"),\n p(" {S,P,C}.\sn").\n\n\ngen_out_type_case_clauses([],_DB) -> done;\ngen_out_type_case_clauses([Objtype|Objtypes],DB) ->\n OptsFuns = lists:map(fun(L) -> list_to_tuple(L) end,\n ets:match(DB,{Objtype,'$1','$2',write})),\n p(" ~p -> \sncase Opt of\sn",[Objtype]),\n gen_opt_case_clauses(merge_opts(opt_prio(),OptsFuns)),\n p(" _ -> \sn"),\n p(" handle_external_opt_call([Option|Options],Gstkid,TkW,DB,ExtraArg,"\n " gstk_~p:option(Option,Gstkid,TkW,DB,ExtraArg),S,P,C)\sn",\n [Objtype]),\n p(" end;\sn"),\n gen_out_type_case_clauses(Objtypes,DB).\n\ngen_opt_case_clauses([]) ->\n done;\ngen_opt_case_clauses([{Opt,Fun}|OptFuncs]) ->\n p(" ~p ->\sn",[Opt]),\n p(" ~p(Val,Options,Gstkid,TkW,DB,ExtraArg,S,P,C);\sn",[Fun]),\n gen_opt_case_clauses(OptFuncs).\n\ngen_read(DB) ->\n ObjTypes = lists:flatten(ordsets:from_list(ets:match(DB,{'$1','_','_',read}))),\n p("read_option(DB,Gstkid,TkW,Option,ExtraArg) ->\sn"),\n p(" Key = case Option of\sn"),\n p(" Atom when is_atom(Atom) -> Atom;\sn"),\n p(" Opt when is_tuple(Opt) -> element(1,Opt)\sn"),\n p(" end,\sn"),\n p(" case Gstkid#gstkid.objtype of\sn"),\n gen_read_type_clauses(merge_types(ObjTypes),DB),\n p(" Q -> exit({internal_error,unknown_objtype,Q})\sn"),\n p(" end.\sn").\n \n\ngen_read_type_clauses([],_) -> done;\ngen_read_type_clauses([Objtype|Objtypes],DB) ->\n OptsFuns = lists:map(fun(L) -> list_to_tuple(L) end,\n ets:match(DB,{Objtype,'$1','$2',read})),\n p(" ~p -> \sncase Key of\sn",[Objtype]),\n gen_readopt_case_clauses(merge_opts(opt_prio(),OptsFuns)),\n p(" _ -> \snhandle_external_read(gstk_~p:read_option(Option,Gstkid,TkW,DB,ExtraArg))\sn",[Objtype]),\n p(" end;\sn"),\n gen_read_type_clauses(Objtypes,DB).\n\ngen_readopt_case_clauses([]) ->\n done;\ngen_readopt_case_clauses([{Opt,Fun}|OptFuncs]) ->\n p(" ~p -> \sn~p(Option,Gstkid,TkW,DB,ExtraArg);\sn",[Opt,Fun]),\n gen_readopt_case_clauses(OptFuncs).\n\n\np(Str) ->\n ok = io:format(get(stdout),Str,[]).\n\np(Format,Data) ->\n ok = io:format(get(stdout),Format,Data).\n\n%%----------------------------------------------------------------------\n%% There items should be placed early in a case statement.\n%%----------------------------------------------------------------------\nobj_prio() -> [rectangle,line,gridline,image,button,canvas,checkbutton,radiobutton].\nopt_prio() -> [x,y,width,height,move,coords,data].\n\nmerge_types(Types) ->\n T2 = ordsets:from_list(Types),\n P2 = ordsets:from_list(obj_prio()),\n obj_prio() ++ ordsets:subtract(T2, P2).\n\nmerge_opts([],L) -> L;\nmerge_opts([Opt|Opts],Dict) ->\n case gs:assq(Opt,Dict) of\n {value,V} -> [{Opt,V}|merge_opts(Opts,lists:keydelete(Opt,1,Dict))];\n false -> merge_opts(Opts,Dict)\n end.\n\nthe_config() ->\n Buttons=[button,checkbutton,radiobutton],\n AllPureTk = [Buttons,canvas,editor,entry,frame,label,listbox,\n menubar,menubutton,scale,window],\n CanvasObj = [arc,image,line,oval,polygon,rectangle,text],\n All = [AllPureTk,CanvasObj,grid,gridline,menu,menuitem,gs],\n Containers = [canvas,frame,grid,menu,menubar,menubutton,menuitem,window],\n Ob1 = [Buttons,canvas,grid,frame,label,entry,editor,listbox,scale],\n Ob2 = [button,checkbutton,radiobutton,label,menubutton],\n Ob3 = [Buttons,frame,label,entry,editor,listbox,scale,menubutton,\n menubar,menu],\n Ob4 = [canvas,editor,listbox],\n [{[Buttons,entry,scale,menubutton],enable,gen_enable,rw},\n {[Buttons,label,entry,scale,menubutton,menu],fg,gen_fg,rw},\n {[Buttons,label,entry,scale,menubutton,menu],bg,gen_bg,rw},\n {Ob1,anchor,gen_anchor,rw},\n {Ob1,height,gen_height,r},\n {Ob1--[frame],height,gen_height,w},\n {Ob1,width,gen_width,r},\n {Ob1--[frame],width,gen_width,w},\n {Ob1,pack_x,gen_pack_x,rw},\n {Ob1,pack_y,gen_pack_y,rw},\n {Ob1,pack_xy,gen_pack_xy,w},\n {Ob1,x,gen_x,rw},\n {Ob1,y,gen_y,rw},\n {Ob1,raise,gen_raise,w},\n {Ob1,lower,gen_lower,w},\n {Ob2,align,gen_align,rw},\n {Ob2,font,gen_font,rw},\n {Ob2,justify,gen_justify,rw},\n {Ob2,padx,gen_padx,rw},\n {Ob2,pady,gen_pady,rw},\n {Containers,default,gen_default,w},\n {[AllPureTk,menu],relief,gen_relief,rw},\n {[AllPureTk,menu],bw,gen_bw,rw},\n {[Buttons,canvas,frame,label,entry,scale,menubutton,menu,menubar],\n setfocus,gen_setfocus,rw},\n {Ob3,buttonpress,gen_buttonpress,rw}, \n {Ob3,buttonrelease,gen_buttonrelease,rw},\n {Ob3,configure,gen_configure,rw},\n {[Ob3,window],destroy,gen_destroy,rw},\n {[Ob3,window],enter,gen_enter,rw},\n {[Ob3,window],leave,gen_leave,rw},\n {[Ob3,window],focus,gen_focus_ev,rw},\n {[Ob3,window],keypress,gen_keypress,rw},\n {[Ob3,window],keyrelease,gen_keyrelease,rw},\n {Ob3,motion,gen_motion,rw},\n %% events containing x,y are special\n {[window],buttonpress,gen_buttonpress,r},\n {[window],buttonrelease,gen_buttonrelease,r},\n {[window],motion,gen_motion,r},\n {All,font_wh,gen_font_wh,r},\n {All,choose_font,gen_choose_font,r},\n {All,data,gen_data,rw},\n {All,children,gen_children,r},\n {All,id,gen_id,r},\n {All,parent,gen_parent,r},\n {All,type,gen_type,r},\n {All,beep,gen_beep,w},\n {All,keep_opt,gen_keep_opt,w},\n {All,flush,gen_flush,rw},\n {AllPureTk,highlightbw,gen_highlightbw,rw},\n {AllPureTk,highlightbg,gen_highlightbg,rw},\n {AllPureTk,highlightfg,gen_highlightfg,rw},\n {AllPureTk,cursor,gen_cursor,rw}, % bug\n {[Buttons,label,menubutton],label,gen_label,rw},\n {[Buttons,menubutton,menu],activebg,gen_activebg,rw},\n {[Buttons,menubutton,menu],activefg,gen_activefg,rw},\n {[entry],selectbg,gen_selectbg,rw},\n {[entry],selectbw,gen_selectbw,rw},\n {[entry],selectfg,gen_selectfg,rw},\n {Ob4,activebg,gen_so_activebg,rw},\n {Ob4,bc,gen_so_bc,rw},\n {Ob4,bg,gen_so_bg,rw},\n {Ob4,hscroll,gen_so_hscroll,r},\n {Ob4,scrollbg,gen_so_scrollbg,rw},\n {Ob4,scrollfg,gen_so_scrollfg,rw},\n {Ob4,scrolls,gen_so_scrolls,w},\n {Ob4,selectbg,gen_so_selectbg,rw},\n {Ob4,selectbg,gen_so_selectbg,rw},\n {Ob4,selectbw,gen_so_selectbw,rw},\n {Ob4,selectbw,gen_so_selectbw,rw},\n {Ob4,selectfg,gen_so_selectfg,rw},\n {Ob4,selectfg,gen_so_selectfg,rw},\n {Ob4,vscroll,gen_so_vscroll,r},\n {CanvasObj,coords,gen_citem_coords,rw},\n {CanvasObj,lower,gen_citem_lower,w},\n {CanvasObj,raise,gen_citem_raise,w},\n {CanvasObj,move,gen_citem_move,w},\n {CanvasObj,setfocus,gen_citem_setfocus,rw},\n {CanvasObj,buttonpress,gen_citem_buttonpress,w}, % should be rw\n {CanvasObj,buttonrelease,gen_citem_buttonrelease,w},\n {CanvasObj,enter,gen_citem_enter,w},\n {CanvasObj,focus,gen_citem_setfocus,w},\n {CanvasObj,keypress,gen_citem_keypress,w},\n {CanvasObj,keyrelease,gen_citem_keyrelease,w},\n {CanvasObj,leave,gen_citem_leave,w},\n {CanvasObj,motion,gen_citem_motion,w},\n {CanvasObj,buttonpress,gen_buttonpress,r}, \n {CanvasObj,buttonrelease,gen_buttonrelease,r},\n {CanvasObj,configure,gen_configure,r},\n {CanvasObj,destroy,gen_destroy,r},\n {CanvasObj,enter,gen_enter,r},\n {CanvasObj,leave,gen_leave,r},\n {CanvasObj,focus,gen_focus_ev,r},\n {CanvasObj,keypress,gen_keypress,r},\n {CanvasObj,keyrelease,gen_keyrelease,r},\n {CanvasObj,motion,gen_motion,r},\n {[arc,oval,polygon,rectangle],fill,gen_citem_fill,rw}].\n\n}}}\n
Parents\n*[[canvas]]\nChildren\n* none\n{{{\ndefault_options(image) -> [{anchor,nw}, {coords,[{0,0}]}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% BITMAP OPTIONS\n%%\n%% Attributes:\n%% anchor n|w|e|s|nw|sw|ne|se|center\n%% bg Color\n%% bitmap String\n%% coords [{X,Y}]\n%% data Data\n%% fg Color\n%%\n%% Attributes for gifs only:\n%% pix_val {{X,Y},Color}|{{{X1,Y1},{X2,Y2}},Color]\n%% save String\n%% refresh\n%%\n%% Commands:\n%% lower\n%% move {Dx, Dy}\n%% raise\n%% scale {Xo, Yo, Sx, Sy}\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% pix_val {X,Y}\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%%\n}}}
Parents\n* [[frame]]\n* [[window]]\nChildren \n* none\n{{{\ndefault_options(label) -> [{height,30}, {width,100}, {x,0}, {y,0}];\n}}}\n{{{\n%% LABEL OPTIONS\n%%\n%% Attributes:\n%% align n,w,s,e,nw,se,ne,sw,center\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bg Color\n%% bw Int\n%% data Data\n%% fg Color\n%% font Font\n%% height Int\n%% highlightbg Color\n%% highlightbw Int\n%% highlightfg Color\n%% justify left|right|center\n%% label {text, String} | {image, BitmapFile}\n%% padx Int (Pixels)\n%% pady Int (Pixels)\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%% underline Int\n%% width Int\n%% wraplength Int\n%% x Int\n%% y Int\n%%\n%% Commands:\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% cursor ??????\n%% focus ?????? (-takefocus)\n%%\n}}}
Parents\n*[[canvas]]\nChildren\n* none\n{{{\ndefault_options(line) -> [{coords, [{-1,-1},{-1,-1}]}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% LINE OPTIONS\n%%\n%% Attributes:\n%% arrow none | first | last | both\n%% capstyle butt | projecting | round\n%% coords [{X1,Y1}, {X2,Y2} | {Xn,Yn}]\n%% data Data\n%% fg Color\n%% joinstyle miter | bevel | round\n%% smooth Bool\n%% splinesteps Int\n%% stipple Bool\n%% width Wth\n%%\n%% Commands:\n%% lower\n%% move {Dx, Dy}\n%% raise\n%% scale {Xo, Yo, Sx, Sy}\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%%\n}}}
Parents\n* [[frame]]\n* [[window]]\nChildren \n* none\n{{{\ndefault_options(listbox) -> [{height,130}, {hscroll,true},\n {selectmode,single}, {vscroll,true},\n {width,125}, {x,0}, {y,0}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% LISTBOX OPTIONS\n%%\n%% Attributes:\n%% activebg Color\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bc Color\n%% bg Color\n%% bw Wth\n%% data Data\n%% fg Color\n%% height Int\n%% highlightbg Color\n%% highlightbw Wth\n%% highlightfg Color\n%% hscroll Bool | top | bottom\n%% items [String, String, ... String]\n%% relief Relief\n%% scrollbg Color\n%% scrollfg Color\n%% selectbg Color\n%% selectbw Width\n%% selectfg Color\n%% selection Index | clear\n%% selectmode single|browse|multiple|extended\n%% vscroll Bool | left | right\n%% width Int\n%% x Int\n%% xselection Bool (Good name?????)\n%% y Int\n%%\n%% Commands:\n%% add {Index, String} | String\n%% change {Index, String}\n%% clear\n%% del Index | {FromIdx, ToIdx}\n%% get Index\n%% see Index\n%% selection => [Idx1,Idx2,Idx3...]\n%% setfocus Bool\n%% size Int\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% click [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% doubleclick [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n}}}
Parents\n* [[frame]] (for popup menus)\n* [[window]] (for popup menus)\n* [[menubutton]]\n* [[menuitem]] (with {itemtype, cascade })\nChildren \n* [[menuitem]]\n{{{\ndefault_options(menu) -> [];\n}}}\n{{{\n%%------------------------------------------------------------------------------\n%% MENU OPTIONS\n%%\n%% Attribute:\n%% activebg Color\n%% activebw Int\n%% activefg Color\n%% bg Color\n%% bw Int\n%% data Data\n%% disabledfg Color\n%% fg Color\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%% selectcolor Color\n%%\n%% Commands:\n%% setfocus [Bool | {Bool, Data}]\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% post {X,Y}\n%% unpost\n%% align n,w,s,e,nw,se,ne,sw,center\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% cursor ??????\n%% focus ?????? (-takefocus)\n%% height Int\n%% justify left|right|center (multiline text only)\n%% width Int\n%% x Int (valid only for popup menus)\n%% y Int (valid only for popup menus)\n%%\n}}}
Parents\n* [[frame]]\n* [[window]]\nChildren \n* [[menubutton]]\n{{{\ndefault_options(menubar) -> [{bw,2}, {height,25}, {highlightbw,0},\n {relief,raised}];\n}}}\n{{{\n%%------------------------------------------------------------------------------\n%% MENUBAR OPTIONS\n%%\n%% Attributes:\n%% bg Color\n%% bw Int\n%% data Data\n%% height Int\n%% highlightbg Color\n%% highlightbw Int\n%% highlightfg Color\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%%\n%% Commands:\n%% setfocus [Bool | {Bool, Data}]\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% align How\n%%\n}}}
Parents\n* [[menubar]]\n* [[frame]]\n* [[window]]\nChildren \n* [[menu]]\n{{{\ndefault_options(menubutton) -> [{anchor,nw}, {side,left}];\n}}}\n{{{\n%%------------------------------------------------------------------------------\n%% MENUBUTTON OPTIONS\n%%\n%% Attributes:\n%% activebg Color\n%% activefg Color\n%% align n,w,s,e,nw,se,ne,sw,center\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bg Color\n%% bw Int\n%% data Data\n%% disabledfg Color\n%% fg Color\n%% font Font\n%% height Int\n%% highlightbg Color\n%% highlightbw Int\n%% highlightfg Color\n%% justify left|right|center (multiline text only)\n%% label {text, String} | {image, BitmapFile}\n%% padx Int (Pixels)\n%% pady Int (Pixels)\n%% relief Relief [flat|raised| sunken | ridge | groove]\n%% side left | right (valid only in menubars)\n%% underline Int\n%% width Int\n%% wraplength Int\n%% x Int (not valid in menubars)\n%% y Int (not valid in menubars)\n%%\n%% Commands:\n%% enable Bool\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% activate ?????? (kontra enable, true)\n%% state ??????\n%% cursor ??????\n%% image ??????\n%% focus ?????? (-takefocus)\n%%\n}}}
Parents\n* [[menu]]\nChildren \n* [[menu]] (with {itemtype, cascade })\n{{{\ndefault_options(menuitem) -> [{click,true}, {index,last}, {itemtype,normal}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% MENUITEM OPTIONS\n%%\n%% Attribute:\n%% accelerator String\n%% activebg Color\n%% activefg Color\n%% bg Color\n%% color Color (same as fg)\n%% data Data\n%% fg Color\n%% font Font\n%% group Atom (valid only for radio type)\n%% index Int\n%% itemtype normal|check|radio|separator|cascade (|tearoff)\n%% label {text, String} | {image, BitmapFile}\n%% menu Menu (valid only for cascade type)\n%% selectbg Color\n%% underline Int\n%% value Atom\n%%\n%% Commands:\n%% activate\n%% enable Bool\n%% invoke\n%%\n%% Events:\n%% click [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% font Font\n%% read menu on cascades\n%%\n}}}
This object has defaults but not documented\n\nSee gstk_widgets.erl: \n{{{\ndefault_options(message) -> [{height,75}, {width,100}];\n}}}
using [[create/3 |create/2/3/4]]\n\n S = gs:start(),\n %% the parent of a top-level window is the gs server\n Win = gs:create(window,S,[{width,200},{height,100}]),\n\nusing [[create/4 |create/2/3/4]]\n\n S = gs:start(),\n %% the parent of a top-level window is the gs server\n Win = gs:create(window,win, S,[{width,200},{height,100}]),\n\n----\n\nObjects must be created in a hierarchical order. \n\ninit() -> \n S = gs:start(),\n gs:create(window,win1,S,[{width,200},{height,100}]),\n gs:create(button,b1,win1,[{label, {text,"Press Me"}}]),\n gs:config(win1, {map,true}),\n\nIf the button is created before the parent window, the button \nwill not appear in the window. However, it will not cause a \ncompiler error.\n\ninit() -> \n S = gs:start(),\n %%child before parent is wrong\n gs:create(button,b1,win1,[{label, {text,"Press Me"}}]),\n gs:create(window,win1,S,[{width,200},{height,100}]),\n gs:config(win1, {map,true}),\n\nSo, you can't just create the objects in groups (like all \nthe buttons in one section of code) and be assured it will\nwork. \n
Parents\n*[[canvas]]\nChildren\n* none\n{{{\ndefault_options(oval) -> [{coords, [{0,0},{0,0}]}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% OVAL OPTIONS\n%%\n%% Options:\n%% bw Int\n%% coords [{X1,Y1}, {X2,Y2}]\n%% data Data\n%% fg Color\n%% fill Color\n%% stipple Bool\n%%\n%% Commands:\n%% lower\n%% move {Dx, Dy}\n%% raise\n%% scale {Xo, Yo, Sx, Sy}\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%%\n}}}
Parents\n*[[canvas]]\nChildren\n* none\n{{{\ndefault_options(polygon) -> [{coords, [{0,0},{0,0}]}, {fg,black}, {fill,none}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% POLYGON OPTIONS\n%%\n%% Attributes:\n%% bw Int\n%% coords [{X1,Y1}, {X2,Y2} | {Xn,Yn}]\n%% data Data\n%% fg Color\n%% fill Color\n%% smooth Bool\n%% splinesteps Int\n%% stipple Bool\n%%\n%% Commands:\n%% lower\n%% move {Dx, Dy}\n%% raise\n%% scale {Xo, Yo, Sx, Sy}\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n}}}
This object has defaults, but is not documented.\n\nSee gstk_widgets.erl: \n{{{\ndefault_options(prompter) -> [{height,200}, {prompt,[]}, {width,300}];\n}}}\nthere is no gstk_prompter.erl file.
Parents\n* [[frame]]\n* [[window]]\nChildren\n* none\n{{{\ndefault_options(radiobutton) -> [{click,true}, {height,30}, {width,100},\n {x,0}, {y,0}];\n}}}\n{{{\n%%------------------------------------------------------------------------------\n%% RADIOBUTTON OPTIONS\n%%\n%% Attributes:\n%% activebg Color\n%% activefg Color\n%% align n,w,s,e,nw,se,ne,sw,center\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bg Color\n%% bw Int\n%% data Data\n%% disabledfg Color\n%% enable Bool\n%% fg Color\n%% group Atom\n%% groupid Groupid\n%% height Int\n%% highlightbg Color\n%% highlightbw Int\n%% highlightfg Color\n%% justify left|right|center\n%% label {text, String} | {image, BitmapFile}\n%% padx Int (Pixels)\n%% pady Int (Pixels)\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%% selectbg Color\n%% underline Int\n%% value Atom\n%% width Int\n%% wraplength Int\n%% x Int\n%% y Int\n%%\n%% Commands:\n%% flash\n%% invoke \n%% select Bool\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% click [Bool | {Bool, Data}]\n%% configure [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% cursor ??????\n%% focus ?????? (-takefocus)\n%% font ??????\n%%\n}}}
@@read(GSObj, Key) -> Value @@\n\nTypes:\n\n~GSObj = gsobj()\nKey = atom()\nValue = term()\n\nReturns the value of an option key for the specified graphical object.\n
Parents\n*[[canvas]]\nChildren\n* none\n{{{\ndefault_options(rectangle) -> [{coords, [{0,0},{0,0}]}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% RECTANGLE OPTIONS\n%%\n%% Attributes:\n%% bw Int\n%% coords [{X1,Y1}, {X2,Y2}]\n%% data Data\n%% fg Color\n%% fill Color\n%% stipple Bool\n%%\n%% Commands:\n%% lower\n%% move {Dx, Dy}\n%% raise\n%% scale {Xo, Yo, Sx, Sy}\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n}}}
Parents\n* [[frame]]\n* [[window]]\nChildren \n* none\n{{{\ndefault_options(scale) -> [{click,true}, {height,50}, {width,100},\n {x,0}, {y,0}];\n}}}\n{{{\n%%-------------------------------------------------------------------------\n%% SCALE OPTIONS\n%%\n%% Attributes:\n%% activebg Color\n%% anchor n,w,s,e,nw,se,ne,sw,center\n%% bg Color\n%% bw Int\n%% data Data\n%% fg Color\n%% height Int\n%% highlightbg Color\n%% highlightbw Int\n%% highlightfg Color\n%% orient vertical | horizontal\n%% range {From, To}\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%% showvalue Bool\n%% text String\n%% width Int\n%% x Int\n%% y Int\n%%\n%% Commands:\n%% enable Bool\n%% pos Int\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% click [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n}}}
This object has defaults (albeit an empty list), but is not documented.\n\nSee gstk_widgets.erl: \n{{{\ndefault_options(scrollbar) -> [];\n}}}
@@start() -> ~ObjId@@\n\nStarts GS, unless it is already started, and returns its object identifier.\n\n
@@stop() -> void()@@\n\nStops GS and closes all windows. This function is not the opposite of \nstart/0 as it will cause all applications to lose their GS objects. \n\n
Parents\n*[[canvas]]\nChildren\n* none\n\n@@Note@@ text does not have scrollbar options -- use editor instead\n{{{\ndefault_options(text) -> [{anchor,nw}, {coords,[{0,0}]}, {justify,left}];\n}}}\n{{{\n%%-----------------------------------------------------------------------------\n%% TEXT OPTIONS\n%%\n%% Attributes:\n%% anchor n|w|e|s|nw|sw|ne|se|center\n%% coords [{X,Y}]\n%% data Data\n%% fg Color\n%% font Font\n%% justify left | center | right\n%% stipple Bool\n%% text String\n%% width Int (line length in characters)\n%%\n%% Commands:\n%% lower\n%% move {Dx, Dy}\n%% raise\n%% scale {Xo, Yo, Sx, Sy}\n%% setfocus Bool\n%%\n%% Events:\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%%\n%% Read Options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% fontfamily ?????? Family\n%% fontsize ?????? Size\n%% style ?????? [bold,italic]\n%%\n}}}
Here are some differences. I am sure there are more. E = Erlang V = Visual Tcl\n\n*background color of E is slightly darker\n*E editor with vscroll, hscroll and V's text and scrollbars: text area of editor is smaller (The scrollbars use up some of the H and W).\n*V has -bordermode ignore, which apparently keeps from creating ugly bold lines around objects that have focus.
Parents\n* [[gs]]\n* [[window]]\nChildren\n* [[window]]\n* [[button]]\n* [[radiobutton]]\n* [[checkbutton]] \n* [[canvas]] \n* [[editor]], \n* [[entry]], \n* [[frame]], \n* [[grid]], \n* [[label]], \n* [[listbox]], \n* [[menubar]], \n* [[scale]]\n* [[menubutton]]\n* [[menu]] \n{{{\ndefault_options(window) -> [{configure,false}, {cursor,arrow}, {destroy,true},\n {height,200}, {map,false}, {width,300}];\n}}}\n{{{\n%%------------------------------------------------------------------------------\n%% WINDOW OPTIONS\n%%\n%% Attributes:\n%% x Int\n%% y Int\n%% width Int\n%% height Int\n%% bg Color\n%% bw Int\n%% relief Relief [flat|raised|sunken|ridge|groove]\n%% highlightbw Int\n%% highlightbg Color\n%% highlightfg Color\n%% map Bool\n%% iconify Bool\n%% title String\n%% iconname String \n%% iconbitmap Bitmap\n%% iconmask Bitmap\n%% data Data\n%% cursor arrow|busy|cross|hand|help|resize|text\n%%\n%% Commands:\n%% raise \n%% lower \n%% setfocus Bool\n%%\n%% Events:\n%% configure [Bool | {Bool, Data}]\n%% enter [Bool | {Bool, Data}]\n%% leave [Bool | {Bool, Data}]\n%% motion [Bool | {Bool, Data}]\n%% keypress [Bool | {Bool, Data}]\n%% keyrelease [Bool | {Bool, Data}]\n%% buttonpress [Bool | {Bool, Data}]\n%% buttonrelease [Bool | {Bool, Data}]\n%% focus [Bool | {Bool, Data}]\n%% destroy [Bool | {Bool, Data}]\n%%\n%% Read options:\n%% children\n%% id\n%% parent\n%% type\n%%\n%% Not Implemented:\n%% screen ?????????\n%% map \n%% unmap \n%% iconify\n%% deiconify\n%% focusmodel [active|passive] (wm focusmodel)\n%%\n}}}\n