Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - oofoe

#16
Hi!



I'm trying to wire up a text-area with a keyboard event so I can detect if the user presses the escape key while typing. It works fine for text-field Title (see below), but the handler never gets called for keypresses in Body. I have wired the standard handler into gs:no-action because it either only gets fired on pressing the enter key (text-field) or doesn't have any information about non-textual keys (text-area).



Can anyone point out where I'm going wrong?



Thanks!



(load (append (env "NEWLISPDIR") "/guiserver.lsp"))
(gs:init)

(define (field-key id type code modifiers)
  "( id type code modifiers --) Handler for keyboard."

  (println "Key for " id " " type ", " code " with " modifiers "."))

(define (layout)
  "( --) Layout GUI."

  (gs:text-field 'Title 'gs:no-action 64)
  (gs:key-event  'Title 'field-key)
  (gs:text-area  'Body  'gs:no-action)
  (gs:key-event  'Body  'field-key)
  (gs:frame 'F  0 0  800 600  "Text Keyboard Event Test")
  (gs:set-border-layout 'F)
  (gs:add-to 'F  'Title "north"  'Body "center")
  (gs:set-visible 'F true))

(layout)
(gs:listen)
#17
Hi!



I'd like to report a bug with canvases when used with scroll bars. If you run the following code, it creates a 2048x2048 canvas, then places it into a scrolled pane. You can scroll the canvas, but it will not repaint when you stop scrolling. Even forcing a gs:update (click on canvas) will not repaint it.



However, changing the window size will, which proves that scrollable large canvases should be doable, just maybe an event isn't getting propagated correctly on the Java side?



Thanks very much!


(load (append (env "NEWLISPDIR") "/guiserver.lsp"))
(gs:init)

(define (canvas-unclick)
  "( --) Handler for mouse button release."

  (gs:update)) ;; Note that this doesn't work.

(define (layout)
  "( --) Layout GUI."

  (gs:canvas 'Canvas)
  (gs:mouse-released 'Canvas 'canvas-unclick)

  (gs:panel 'Stretcher 2048 2048)
  (gs:set-border-layout 'Stretcher)
  (gs:add-to 'Stretcher 'Canvas "center")

  (gs:scroll-pane 'Workspace 'Stretcher)

  (gs:frame 'F  0 0  800 600  "Scrolling Canvas Test")
  (gs:add-to 'F 'Workspace)

  (gs:fill-rect 'shape   50  50  500 500  '(1 1 0))
  (gs:fill-rect 'shape  250 250  500 500  '(0 1 0))
  (gs:fill-rect 'shape  500 500  500 500  '(0 1 1))

  (gs:set-visible 'F true))

(layout)
(gs:listen)
#18
Hi!



The "!" is a shell command -- it has its own environment every time it's run, which is not saved between invocations.



So, this: (! "set final_answer=42")
is probably working, but when you run this: (! "echo $final_answer")
the previous environment is destroyed in favour of the new one.



You can use the env function for this because it sets the variable in the environment of the currently running process -- newlisp itself:

(env "final_answer" 42)
(! "echo $final_answer")


Hope this helps!
#19
Hi!



Don't know if this is the best place to post this, but I did use this "in the real world" to compute my weight and balance for my flight yesterday...



This program makes it easy to do your weight and balance calculations so you can determine your position in the performance envelope before you take off into the wild blue yonder! Use it in conjunction with your Pilot's Operating Handbook to make sure you won't have any problems with your loading scenario.



https://bitbucket.org/oofoe/wb/overview">//https://bitbucket.org/oofoe/wb/overview



Even if you're not interested in aviation per se, it may be interesting as a demonstration of setting up a spreadsheet-like interface with recalculation every time the user presses enter.



I am planning some improvements, but right now it does do all the computations. Comments and suggestions welcome!
#20
OK, after some head scratching, I figured I must be experiencing some sort of redraw problem.



I changed the code to this:



 (gs:delete-tag 'I false)
 (gs:draw-image 'I path  0 0   (psize 1) (psize 0))
 (gs:draw-text 'I path  21 25  '(0 0 0))
 (gs:draw-text 'I path  20 24  '(1 1 0))
 (gs:show-tag 'I)


Note the addition of arguments to control redraw at the end of delete-tag call.



And that seems to mitigate the problems. There are still pauses before the new image shows up, but I imagine that's just the loading/decompression/scaling overhead.
#21
Hi!



I'm doing a simple picture viewer using the GUI server. However, I am having an odd problem where sometimes the image loads and sometimes it doesn't. If I advance to the next image then come back to one that didn't load, it will often load then.



I am using this to clear the previous image, then load and draw a new image into the canvas:


 (gs:delete-tag 'I)
 (gs:draw-image 'I path  0 0   (psize 1) (psize 0))
 (gs:draw-text 'I path  21 25  '(0 0 0))
 (gs:draw-text 'I path  20 24  '(1 1 0)))


The images are generally about 4Kx2.5K, scaled to 625x521 (for the psize argument).



When the image load fails (?), the text draws following it fail also, so nothing is shown.



Any ideas as to what's going on -- and how I can fix it?



Thanks!
#22
OK, that's basically what I was suggesting in the last para, except that my modification looked like this:
(define (Plane:firewall)
(setf (self 1) 2700) (self))


It doesn't seem very efficient to have to replace the entire data structure each time I want to do an update. OOP may not be a good fit for this in NewLISP.



The approach I'm using is typical in other languages for dealing with particle simulations and the like. Maybe I should just use a list of lists and a double setf? However, the idea of OOP-style behaviour is very attractive.



Thanks for looking at it!
#23
Hello!



I am trying to set up a little simulation project, but I am running into some problems with FOOPS and pass by value...



I have a Plane class, which considers the engine RPM and the altitude of the airplane:

(new Class 'Plane)

(define (Plane:Plane rpm alt)
(list 'Plane rpm alt))


Now, I might have methods that change the internal state of a particular instance of the Plane object. Here is one that firewalls the engine (goes to full throttle for a climb):
(define (Plane:firewall)
(setf (self 1) 2700))


This seems to work well enough for a single named instance of Plane:
(setq aplane (Plane 1900 2000))
(println "Original: " aplane)
(:firewall aplane)
(println "Modified: " aplane)


Which produces:
Original: (Plane 1900 2000)
Modified: (Plane 2700 2000)


However, if I try to create a list of many airplanes:
(setq
planes (list
(Plane 2700 0)
(Plane 2100 1250)
(Plane 1500 900)))

(println "Original: " planes)
(dolist (p planes) (:firewall p))
(println "Modified: " planes)


This is what happens:
Original: ((Plane 2700 0) (Plane 2100 1250) (Plane 1500 900))
Modified: ((Plane 2700 0) (Plane 2100 1250) (Plane 1500 900))


As you can see, nothing is changed. Upon further investigation (printing "p" after the :firewall call) I see that the intermediate object p is changed, but not stored to the list "planes". I assume that this is happening because as dolist iterates through planes, each Plane object is copied to p.



What is the best way to handle updating an object in a list of objects like this?



Also, for what it's worth, I have considered modifying :firewall to return self so I can do this:
(dotimes (i (length planes))
(setf (planes i) (:firewall (planes i))))


But I hope you can tell me there's a better way to handle it!



Thanks!
#24
Whither newLISP? / Closure?
April 04, 2013, 05:03:24 AM
Hi!



I'm working through the early examples of the "Stratified Design" paper[1] and I've run (almost immediately!) into something that doesn't seem to work.



They describe an average-damp function that given a function, returns a new function that averages the value with the result of the function:


(define (average)
(div (apply 'add (args)) (length (args))))

(define (average-damp f)
(fn (x)
(average x (f x))))


You might use it like this: ((average-damp (fn (y) (+ 2 y))) 3)



And expect to get 4 (the average of 3 and the result of adding 2 to 3). However, instead I get this:


ERR: invalid function : (f x)
called from user defined function average


I assume that this is happening because the function f, that is passed to average-damp is not lexically closed in the new function that's returned, because NewLisp is not doing that sort of thing.



I have looked through the "Functions as Data" section of the Code Patterns and those examples didn't seem to help. I tried both "expand" and "letex" and they didn't seem to help.



So, is it possible to implement something like average-damp in NewLisp, and how would you do it?



Thanks!



[1] See http://dspace.mit.edu/bitstream/handle/1721.1/6064/AIM-986.pdf?sequence=2">http://dspace.mit.edu/bitstream/handle/ ... sequence=2">http://dspace.mit.edu/bitstream/handle/1721.1/6064/AIM-986.pdf?sequence=2
#25
Thanks for taking a look Micheal!



Here's my latest stab at it. Although it could be better, it's not bad. It allows me to only specify a property name once, for instance. The major disadvantage is that if I want to set a property to nil, this won't do it since it uses a nil value as an indicator that you want to get the stored value of the property.


(define (property i value)  (if value (setf ((self) i) value))  ((self) i))

; h3. Node

(new Class 'Node)

(define (Node:title v)  (property 1 v))
(define (Node:where v)  (property 2 v))
(define (Node:colour v) (property 3 v))

; h2. Tests

(define (assert what pass)
  (println what "..." ('("FAILED" "OK") (if pass 1 0))))

(setq n (Node "Sample" '(9 4) "green" nil ""))

(assert "Title set" (= "Sample" (:title n)))
(:title n "Revised")
(assert "Title changed" (= "Revised" (:title n)))

(assert "Coordinates set" (= '(9 4) (:where n)))
(:where n '(44 99))
(assert "Coordinates changed" (= '(44 99) (:where n)))

(exit) ; Comment out for post-mortem debugging.


It would certainly be nice to hack a macro which would allow a friendlier property specification syntax, but so far this eludes me.
#26
As I understand it, setf can not only set a variable, it can also set a "place", in this case, a position in a list. So I can create a simple class:

(new class 'Node)

(setq n (Node "test" '(5 3)))


If want to inspect or change the Node's coordinates, I can do this:

(println "location: " (n 2))
(setf (n 2) '(9 9))
(println "new location: " (n 2))


However, if I want to encapsulate the list access into the class, it doesn't work for setting:


(define (Node:where) ((self) 2))
(println "location: " (:where n))
(setf (:where n) '(14 3))
(println "same old location: " (:where n))


Is there any way to do anything like the above without having to define a separate getter and setter?



Thanks!
#27
Whither newLISP? / Object Philosophy...
January 20, 2013, 11:43:58 AM
Hi!



Not sure if this is the best place to post this, but I wondered if anybody could tell me if I'm doing this correctly. The idea is that I want named attributes for my object, and I only want to have to specify them once.



If this isn't too crazy, is there any way to make it the default behaviour for new objects? (EDIT: To clarify, I want to create a macro or something that will let me make it the default behaviour for new objects in my program, not the NewLisp distribution itself...)



Thanks!


; h1. Node Class Test

; h2. Node Class

(new Class 'Node)

(set 'Node:parms '((title  "Untitled")
                   (where  (0 0))))

(define (Node:Node)
  (let ((parms (copy Node:parms))
        (parm  nil)
        (data  (list Node)))
    (doargs (i)
            (setq parm (pop parms))
            (if parm (push (list (parm 0) i) data -1)))
    (append data parms)
    ))

(define (Node:get key)  
  (lookup key (self)))

(define (Node:set key value)  
  (setf (assoc key (self)) (list key value)))


; h2. Tests

(define (test what pass)
  (println what "..." ('("FAILED" "OK") (if pass 1 0))))

(setq n (Node "Fantastiche"))

(test "Title set" (= "Fantastiche" (:get n 'title)))

(test "Default location" (= '(0 0) (:get n 'where)))

(:set n 'where '(10.0 14.5))
(test "New location" (= '(10.0 14.5) (:get n 'where)))
#28
Thanks for the update!



For what it's worth, the GUI documentation would really benefit from more code examples like the main NewLisp manual. If you feel it's sufficiently clear, please feel free to use my test program for gs:set-border-layout!



If you're interested in having more runnable examples for other GUI server functions, I would be happy to supply you with more -- I'm currently hacking a new program up and have been studying the GUI stuff intensively lately.
#29
OK, figured it out almost as soon as I posted. The problem is that the canonical directions (north, south, etc.) must be strings. Can't be symbols that I expect to be converted to strings, must absolutely, positively only be strings.



For what it's worth, I think this is a bug in light of the "String constants for type and orientation constants can be given as symbols" shortcut method mentioned in the documentation.



However! In the meantime, this is all I had to change to get it to work:


(gs:add-to 'main 'i1 "north"  'i2 "west"  'i3 "east")
#30
Hi!



This may just be that I'm not reading the documentation closely enough, however if I understand correctly, the "border" layout style allows five sections -- north, south, east, west and center -- and they should work together.



So, this piece of code should show a red box on top, with the bottom divided evenly between a green box on the left and a blue box on the right.



Instead I get a single blue box that fills the entire frame. Any ideas? Thanks!


(load (append (env "NEWLISPDIR") "/guiserver.lsp"))

(gs:init)
(gs:set-trace true)
(gs:set-look-and-feel "javax.swing.plaf.metal.MetalLookAndFeel")

(gs:frame 'main 100 100 512 512 "Layout Test")

(gs:set-border-layout 'main)

(gs:panel 'i1 100 100)  (gs:set-color 'i1 1 0 0)
(gs:panel 'i2 100 100)  (gs:set-color 'i2 0 1 0)
(gs:panel 'i3 100 100)  (gs:set-color 'i3 0 0 1)

(gs:add-to 'main 'i1 'north  'i2 'west  'i3 'east)

(gs:set-visible 'main true)
(gs:listen)


I've tried using separate (gs:add-to) calls and putting the panels inside an inset panel with the border layout, but nothing seems to work. By the way: newLisp v10.4.4, newLISP-GS v.1.47 on Windows 7