World: r3wp
[I'm new] Ask any question, and a helpful person will try to answer.
older newer | first last |
mhinson 7-May-2009 [2124] | Hi, I have been working on a bit of code for some time & it now does something usefull for me, but to use it I am coding the output file into the code & running it repeatedly against every file in a directory. I thought it would be nice for it to have a very simple GUI to navigate to the input directory & output file & perhaps display some indicator of progress. Is this something a beginner might hope to add to existing code, or should I start from scratch again with the GUI part, then try to recreate my code in the view Layout part? Thanks. |
Henrik 7-May-2009 [2125] | you can create a prototype of the GUI first, by just creating a layout with the placement of the styles you want. afterwards you can make it work as you want using SET-FACE, GET-FACE, etc. |
mhinson 7-May-2009 [2126] | I will have a fiddle & see if I can understand that. Thanks very much Henrik |
Henrik 7-May-2009 [2127] | It's very easy to create prototypes and VID is excellent for that: view layout [ across space 2 box blue 300x300 "List View" box yellow 100x300 "Buttons" return box red 402x24 "OK/Cancel Panel" ] |
mhinson 7-May-2009 [2128x2] | Thanks, I started looking at this before & got confused with how I extract the information I can see on the screen & use it in the context of another block of code. With VB I think event handelers pop up everywhere? not sure but I think it is something like that. I couldnt work out how the same sort of thing is done in Rebol. |
if I have view layout [box green 400x400 field] the interpreter wont even load any more lines of script while the box is on the screen, so I am guessing I have to call the rest of my code from within the view layout block? | |
Henrik 7-May-2009 [2130x3] | Here's some learning by doing: With the above line of code, activate the console and press escape. The event handler is returned to the console. Now you can control the window interactively. Type UNVIEW. |
Then try this line: view layout [b: box green 400x400 f: field] Go back to console and escape. b/color: yellow show b set-face f "hello" get-face f hide f show f That's how you access UI parts. | |
If you want to return the event handler to the UI, type DO-EVENTS. | |
mhinson 7-May-2009 [2133] | Unview! wow, that will save me exiting the console a hundred times a day!! That is a top tip & should be in a prominate place for newbies. |
Henrik 7-May-2009 [2134] | If you want to show a window and return to console immediately, use VIEW/NEW instead. |
mhinson 7-May-2009 [2135x2] | This might be doable even for me. Thanks for these tips, I have read so much about Rebol, but I never seem to take it in properly. One of the great things with rebol is how I can test even the smallest fragment of code in the console, this makes it very friendly. Thanks for your help. |
I have been looking at the library examples & noticed that some of them start off with something like navigator: make object! [ The ones like this dont do anything so I am guessing I need to use this code in a way I have not come across yet. I have been madley trying things like make a: navigator and looking up make in the documentation, but not understanding the answers. | |
Henrik 7-May-2009 [2137] | make object! is the same as making a context. If you see an entire script wrapped in make object! [] or context [], it is because it was desired to use this script with other scripts without polluting the global namespace. |
mhinson 7-May-2009 [2138] | Oh, I see, the actual functions are inside the object. |
Henrik 7-May-2009 [2139] | Try this: context [ a: 2 set 'b 3 set 'c does [return a] ] >> a >> b >> c A simple way to control what's private and public. |
mhinson 7-May-2009 [2140] | I see, that is good. I have seen the 'b syntax used but not understood it yet. I see in your example the set 'b 3 seems like b: 3 in the global context. Thanks very much for your tips, they are a great help. |
Sunanda 7-May-2009 [2141] | On the other hand, if you want 'a, 'b, 'c to be local to the context -- so other parts of your application can also have their own 'a. 'b and 'c without overwriting each other: my-api: context [ a: 2 b: 3 c: does [return a + b] ] my-api/a: 5 ;; override default value print my-api/c ;; executes function in context |
mhinson 7-May-2009 [2142] | I wondered how the xxx/xxx/xxx paths to data were constructed... I was thinking of this sort of thing as a way to refer to valuse in a multi demensional array by name rather than number house: context [ room1: context [ items: [bed chair table] ] room2: context [ items: [TV sofa HiFi] ] ] |
Sunanda 7-May-2009 [2143] | That's the way I do it, using 'context / make object! Some people prefer using blocks rather than objects: blk: [a 4 b 5 c 6] blk/b == 5 blk/b: 99 probe blk == [a 4 b 99 c 6] There are advantages and disadvantages to each approach. |
mhinson 7-May-2009 [2144] | I used to get the same sort of effect in Pascal by defining ordinal types with values that were meaningfull words & use them to index my arrays. |
Sunanda 7-May-2009 [2145] | :-) ..... You could think of it as a type of associative array. |
mhinson 7-May-2009 [2146] | A question: if I want to provide a dialoge to navigate to a directory can I call up the ms windows file open & save dialogs, or do I have to do it all in rebol. I cant find any examples of this & dont have the skills to create my own... I like the idea of having a GUI interface, but I may have to go back to command line if it is too hard for me :-) |
Sunanda 7-May-2009 [2147] | File open dialog is simple. source request-file :-) |
mhinson 7-May-2009 [2148] | oh, that was simpler than expected. Thanks very much. I must say I dont think Rebol is very easy to learn, but once all these tricks are known it must be very easy to write things quickly. Perl is like a tool shop & a tree for wood, while Rebol is like a high street full of all sorts of shops as well as tools. |
Sunanda 7-May-2009 [2149] | And unexpected pot holes :-) |
mhinson 7-May-2009 [2150] | There is a request-dir too, but it is a bit of a joke. Looks like the way to go is to use the request-file then extract the directory. Why would request-dir even exist in such a feeble state? Sorry, I hope I am not speaking out of turn, but if anyone had that pop up they would think it was a bit odd. |
Sunanda 7-May-2009 [2151] | No, request-dir is pretty low standard. |
Henrik 7-May-2009 [2152x2] | some parts are sub-par, like request-color as well. fortunately it's possible to rewrite them. |
large parts of the GUI system was written in a very short time by Carl alone back early in this decade and has not been officially upgraded. | |
mhinson 7-May-2009 [2154] | Excuseme please, but can someone pull me out of the mud here please? filenames: request-file/title/filter/path {Select all files to read} [*.txt] %/D/Rebol/X/!conf/ What have I not understood this time? Why does the documentation have no examples I can find? Sorry to be always asking :-( |
Henrik 7-May-2009 [2155] | two arguments are necessary for the /TITLE refinement. |
mhinson 7-May-2009 [2156x2] | I added an extra string for the title and now get this similar failure >> filenames: request-file/title/filter/path {Select all files to read} {x} [*.txt] %/D/Rebol/X/!conf/ ** Script Error: Invalid argument: *.txt * *.r *.reb *.rip *.txt *.jpg *.gif *.bmp *.png ** Where: request-file ** Near: done: local-request-file data: reduce [tt/text ob/text clean-path where picked filt-names filt-values found? any [only]... |
AH a string "*.txt" for the filter works Thanks for your help | |
Gregg 11-May-2009 [2158x2] | Large message coming, with examples of showing progress. Note that it uses INCLUDE and FILE-LIST, so adapt accordingly, and let me know if I left any other dependencies in it that cause it not to work. It was quickly hacked from existing code. |
REBOL [] do %include.r include %file-list.r flash-wnd: flash "Finding test files..." if file: request-file/only [ files: read first split-path file ] if none? file [halt] items: collect/only item [ foreach file files [item: reduce [file none]] ] unview/only flash-wnd ;------------------------------------------------------------------------------- ;-- Generic functions call*: func [cmd] [ either find first :call /show [call/show cmd] [call cmd] ] change-each: func [ [throw] "Change each value in the series by applying a function to it" 'word [word!] "Word or block of words to set each time (will be local)" series [series!] "The series to traverse" body [block!] "Block to evaluate. Return value to change current item to." /local do-body ][ do-body: func reduce [[throw] word] body forall series [change/only series do-body series/1] ; The newer FORALL doesn't return the series at the tail like the old one ; did, but it will return the result of the block, which is CHANGE's result, ; so we need to explicitly return the series here. series ] collect: func [ "Collects block evaluations." [throw] 'word block [block!] "Block to evaluate." /into dest [block!] "Where to append results" /only "Insert series results as series" /local fn code marker at-marker? marker* mark replace-marker rules ][ block: copy/deep block dest: any [dest make block! []] fn: func [val] compose [(pick [insert insert/only] not only) tail dest get/any 'val get/any 'val ] code: 'fn marker: to set-word! word at-marker?: does [mark/1 = marker] replace-marker: does [change/part mark code 1] marker*: [mark: set-word! (if at-marker? [replace-marker])] parse block rules: [any [marker* | into rules | skip]] do block head :dest ] edit-file: func [file] [ ;print mold file call* join "notepad.exe " to-local-file file ;join test-file-dir file ] flatten: func [block [any-block!]][ parse block [ any [block: any-block! (change/part block first block 1) :block | skip] ] head block ] logic-to-words: func [block] [ change-each val block [either logic? val [to word! form val] [:val]] ] standardize: func [ "Make sure a block contains standard key-value pairs, using a template block" block [block!] "Block to standardize" template [block!] "Key value template pairs" ][ foreach [key val] template [ if not found? find/skip block key 2 [ repend block [key val] ] ] ] tally: func [ "Counts values in the series; returns a block of [value count] sub-blocks." series [series!] /local result blk ][ result: make block! length? unique series foreach value unique series [repend result [value reduce [value 0]]] foreach value series [ blk: first next find/skip result value 2 blk/2: blk/2 + 1 ] extract next result 2 ] ;------------------------------------------------------------------------------- counts: none refresh: has [i] [ reset-counts i: 0 foreach item items [ i: i + 1 set-status reform ["Testing" mold item/1] item/2: random/only reduce [true false] show main-lst set-face f-prog i / length? items wait .25 ] update-counts set-status mold counts ] reset-counts: does [counts: copy [total 0 passed 0 failed 0]] set-status: func [value] [set-face status form value] update-counts: has [pass-fail] [ counts/total: length? items pass-fail: logic-to-words flatten tally collect res [foreach item items [res: item/2]] ;result (e.g.): [true 2012 false 232] standardize pass-fail [true 0 false 0] counts/passed: pass-fail/true counts/failed: pass-fail/false ] ;--------------------------------------------------------------- main-lst: sld: ; The list and slider faces c-1: ; A face we use for some sizing calculations none ml-cnt: ; Used to track the result list slider value. visible-rows: ; How many result items are visible at one time. 0 lay: layout [ origin 5x5 space 1x0 across style col-hdr text 100 center black mint - 20 text 600 navy bold { This is a sample using file-list and updating progress as files are processed. } return pad 0x10 col-hdr "Result" col-hdr 400 "File" col-hdr 100 return pad -2x0 ; The first block for a LIST specifies the sub-layout of a "row", ; which can be any valid layout, not just a simple "line" of data. ; The SUPPLY block for a list is the code that gets called to display ; data, in this case as the list is scrolled. Here COUNT tells us ; which ~visible~ row data is being requested for. We add that to the ; offset (ML-CNT) set as the slider is moved. INDEX tells us which ; ~face~ in the sub-layout the data is going to. ; COUNT is defined in the list style itself, as a local variable in ; the 'pane function. main-lst: list 607x300 [ across space 1x0 origin 0x0 style cell text 100x20 black mint + 25 center middle c-1: cell cell 400 left cell [edit-file item/1] ] supply [ count: count + ml-cnt item: pick items count face/text: either item [ switch index [ 1 [ face/color: switch item/2 reduce [none [gray] false [red] true [green]] item/2 ] 2 [mold item/1] 3 ["Edit"] ] ] [none] ] sld: scroller 16x298 [ ; use SLIDER for older versions of View if ml-cnt <> (val: to-integer value * subtract length? items visible-rows) [ ml-cnt: val show main-lst ] ] return pad 0x20 f-prog: progress 600x16 return status: text 500 return button 200 "Run" [refresh show lay] pad 200 button "Quit" #"^q" [quit] ] visible-rows: to integer! (main-lst/size/y / c-1/size/y) either visible-rows >= length? items [ sld/step: 0 sld/redrag 1 ][ sld/step: 1 / ((length? items) - visible-rows) sld/redrag (max 1 visible-rows) / length? items ] view lay | |
mhinson 12-May-2009 [2160] | Hi, I am trying to reduce the number of global variables I use in functions & so my functions return blocks, but I have not discovered any simple way to dereference the information in the variables, within the blocks.. I have written a function to do it, but I guess there is a built in function if I could find it. Or at least something a bit more elegant than this: "return_value_of_block_component" function. Any tips most welcome please. f1: func [a] [ b: join a "-Bee" c: join a "-Cee" return [b c] ] d: f1 {Hi} return_value_of_block_component: func [block component] [ foreach element block [ if element = component [return reduce [element]] ] ] H: return_value_of_block_component d 'b I: return_value_of_block_component d 'c print H print I |
BrianH 12-May-2009 [2161] | For f1, reduce the block before you return it. Then use set [a b] f1 "blah" to get the values. |
Henrik 12-May-2009 [2162] | about returning complex values: generally it's easier to just pass objects around. |
mhinson 12-May-2009 [2163] | Brian if I reduce the block I cant reference the values in the block by name (b & c in my example). or perhaps I dont know how to? |
BrianH 12-May-2009 [2164] | If you need the names, create an object and return that like Henrik says. If you need the values, my method will work. |
Henrik 12-May-2009 [2165] | vars: make object! [ b: c: none ] f1: func [a] [ vars/b: join a "-Bee" vars/c: join b "-Cee" vars ] |
mhinson 12-May-2009 [2166] | I see, it looks as if both techniques will help me in different cases |
Henrik 12-May-2009 [2167] | when using objects, you will have less maintenance and you have one place where your object contents is defined. imagine if you have 10 different functions that would return blocks (10 block definitions) versus 10 functions that return objects (1 object definition). |
mhinson 12-May-2009 [2168x2] | I dont understand how this prevents the sort of problems I might get using global variables? I was expecting to have to define the object inside the function to keep all the variables local to the function. |
I am thinking that if I take care with these things I will be able to reuse fragments of code in lots of projects without worrying that I have used the same global variable in two places that conflict. | |
[unknown: 5] 12-May-2009 [2170x2] | no you must use the /local switch to do that. |
func [arg1 arg2 /local lc1 lc2 ...][body...] | |
mhinson 12-May-2009 [2172] | Paul, how does that relate to using objects please? |
[unknown: 5] 12-May-2009 [2173] | Only the things you define in a function as local are local. |
older newer | first last |