is it possible for a function inside an odcl function?

Started by andrew, January 07, 2010, 01:41:22 PM

Previous topic - Next topic

andrew

i was looking to put a repeat inside of a listview function to keep the fill list dynamic based on the list length

for example


(setq final_lst (dcl_Control_GetList test_Form3_ListBox2))
(setq f_lst_cnt (length final_lst))
(setq lst_cnt 0)
(dcl_ListView_FillList test_Form3_ListView1
  (list
    (repeat f_lst_cnt
      (list (nth lst_cnt final_lst))
      (setq lst_cnt (1+ lst_cnt))
     )
  )
)



Fred Tomke

I recommend you to build the list outside before calling dcl_listview_filllist because this method throws an error when the list is nil

Make it this way.

Code (autolisp) Select

(if (setq lstList (createlist))
  (dcl_listview_filllist MyProject_MyForm_MyListview lstList)
  (dcl_listview_clear MyProject_MyForm_MyListview)
); if


Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

BazzaCAD

#2
Yes it's possible to have a function inside a odcl function.
For example you have (list) & (setq) inside of it.
But the (repeat) function isn't the problem.
The problem is that it's not building the list...
If you run:

Code (autolisp) Select

(list
 (repeat f_lst_cnt
     (list (nth lst_cnt final_lst))
     (setq lst_cnt (1+ lst_cnt))
 )
)


You get a single number in a list, (3) for example, since (setq lst_cnt (1+ lst_cnt)) was the last code passed to the first (list).

You need to build a temp lisp before you call the FillList

Code (autolisp) Select
(setq xlst nil)
(repeat f_lst_cnt
   (setq xlst (append xlst (list (nth lst_cnt final_lst))))
   (setq lst_cnt (1+ lst_cnt))
)

(dcl_ListView_FillList test_Form3_ListView1 xlst)


a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom

Fred Tomke

Barry, andrew, I just saw the sample from Barry and I decided to build a little test for you - just for your knowledge.

Please test both of the functions below and tell me if you feel a difference in performance.
Both the the commands return the same result.

Code (autolisp) Select

(defun c:buildlist_using_append (/ lst cnt)
  (setq lst '() cnt -1)
  (repeat 10000
    (setq lst (append lst (list (setq cnt (1+ cnt)))))
  ); repeat
  (list (car lst) (last lst)) ;; the list is too long to return
); c:buildlist_using_append

(defun c:buildlist_using_cons (/ lst cnt)
  (setq lst '() cnt -1)
  (repeat 10000
    (setq lst (cons (setq cnt (1+ cnt)) lst))
  ); repeat
  (setq lst (reverse lst)) ;; it's the only difference to the append method
  (list (car lst) (last lst)) ;; the list is too long to return
); c:buildlist_using_cons


But maybe you've already known that. In that case I apologize and I ask you to ignore this.

Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

BazzaCAD

WOW Fred thanks.
CONS is defiantly much faster.
Thanks for teaching me something new.
As always, you da man. :)
a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom

Kerry

Speeaking of skinning cats ...
Say the (dcl_Control_GetList test_Form3_ListBox2) returns something like this ;
Code (autolisp) Select

(setq ListBoxDataLst (list "Alpha"     "Bravo"     "Charlie"   "Delta"     "Echo"
                          "Foxtrot"   "Golf"      "Hotel"     "India"     "Juliet"
                         )
)


You could try something like this ;
Code (autolisp) Select


(setq ItemImageIndex 0
     ListViewDataLst
      (mapcar '(lambda (x) (list x (setq ItemImageIndex (1+ ItemImageIndex))))
              ListBoxDataLst
      )
)




which returns :

Quote
;| returns
(("Alpha" 1) ("Bravo" 2)
            ("Charlie" 3)
            ("Delta" 4)
            ("Echo" 5)
            ("Foxtrot" 6)
            ("Golf" 7)
            ("Hotel" 8 )
            ("India" 9)
            ("Juliet" 10)
)
|;


Perfection is not optional.
My other home is TheSwamp

andrew

Fred,
the lists i built outside the function i couldnt get to work
so i was trying different things

your repeat function with the cons or append was a great little learner for me, cons was much faster
thanks

Barry & Kerry
thanks for your input
although Kerry, i dont understand the lamda thing so i dont really use it.

Fred Tomke

#7
andrew,

using mapcar and lambda is very easy

mapcar applies a function to each list item of the lists given as arguments

Code (autolisp) Select
(setq lstA '(1 2 3 4))
(setq lstB '("a" "b" "c" "d"))
(mapcar 'cons lstA lstB)


returns ((1 . "a") (2 . "b") (3 . "c") (4 . "d"))
The number of lists must match to the number of arguments which are needed by the function which mapcar is applying (cons needs two).


lambda is for being lazy and to avoid defining a named function  ;)

means

you can either do

Code (autolisp) Select

;; define function, make the function name local in the current lisp command
(defun make_list (strItem) (list strItem (setq ItemImageIndex (1+ ItemImageIndex))))

(setq ItemImageIndex 0
      lstData (mapcar 'make_list (list "Alpha" "Bravo" "Charlie" "Delta")))


or you do

Code (autolisp) Select

(setq ItemImageIndex 0
      lstData (mapcar '(lambda (strItem) (list strItem (setq ItemImageIndex (1+ ItemImageIndex))))
                       (list "Alpha" "Bravo" "Charlie" "Delta")))


The arguments von the anonym function must match to the number of lists which are given to mapcar.

An example: you want to get the midpoint between two given points.

Code (autolisp) Select
(setq p1 (getpoint "\nPoint 1:"))
(setq p2 (getpoint "\nPoint 2:"))
(setq pMid (mapcar '* (mapcar '+ p1 p2) '(0.5 0.5 0.5)))


Everything's clear?  ;)
Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

andrew

i think i need a little more guidance
here is the code im using, it reads a txt file, adds the contents to a list box and then i get to select of that list box to a list view and eventually at the same time it will copy the exact same contents the list view has to another text file, i already have that code.

now the problem:
this code works for any one line i select and displays in the list view. if i select another line, it changes to that line and does not add to the list view.
as you can see in the code, im using append but it doesnt seem to work. how can i get the line i select to add to the list to be displayed
and keep adding to it as long as i keep selecting.



(defun c:dwgbrowser_Form3_OnInitialize (/ ofile curline file_content_list)

  (setq datafile (findfile "test.txt"))
  (setq ofile (open datafile "r")) 
  (while (setq curline (read-line ofile)) 
    (setq file_content_list (cons curline file_content_list)) 
  ) 
  (close ofile) 
  (setq file_content_list (reverse file_content_list))
(dcl_Control_SetList dwgbrowser_Form3_ListBox1 file_content_list)
;(dcl_Control_SetList dwgbrowser_Form3_ListBox2 (nth 1 file_content_list))
(dcl_ListView_AddColumns dwgbrowser_Form3_ListView1
  (list
    (list "Title" 0 100)
    (list "Drawing" 0 100)
    (list "Revision" 0 100)
  )
)

)

(defun c:dwgbrowser_Form3_TextButton1_OnClicked (/ items title rev dwgnum make_lst show_list)

(setq items (dcl_ListBox_GetSelectedItems dwgbrowser_Form3_ListBox1))
(setq new_item items)

;;get title
(setq title (substr (nth 0 items) 1 34))

;;gets rev
(setq rev (substr (nth 0 items) (- (strlen (nth 0 items)) 4)))

;;gets dwg
(setq dwgnum (substr (nth 0 items) 43 7))

(defun make_list (strItem)
(list strItem)
)

(setq make_lst (mapcar 'list (make_list title) (make_list dwgnum) (make_list rev)))

(setq show_list (reverse (append show_list make_lst)))
(dcl_ListView_FillList dwgbrowser_Form3_ListView1 show_list)

) ;end defun

BazzaCAD

Have a look at the "ListBoxCopyPaste" project in the Samples folder.
I think it's doing exactly what you're trying to do...
a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom

andrew

Hi Barry,
thanks for the reply.

I did look at that, but thats going from list box to list box,
im trying to go from list box to list view

Fred Tomke

andrew,

Please be so kind and send me the odcl, the lsp and the txt you want to read in.

Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

andrew

#12
Fred,
Thanks for the reply

I got it to work... so far

here is the code im currently using to achieve what im after
it might not be the best way to get the info but so far its working



(defun c:dwgbrowser_Form3_OnInitialize (/ ofile curline file_content_list)

 (setq datafile (findfile "test.txt"))
 (setq ofile (open datafile "r"))  
 (while (setq curline (read-line ofile))  
   (setq file_content_list (cons curline file_content_list))  
 )  
 (close ofile)  
 (setq file_content_list (reverse file_content_list))
(dcl_Control_SetList dwgbrowser_Form3_ListBox1 file_content_list)
;(dcl_Control_SetList dwgbrowser_Form3_ListBox2 (nth 1 file_content_list))
(dcl_ListView_AddColumns dwgbrowser_Form3_ListView1
 (list
   (list "Name" 0 100)
   (list "Size" 0 100)
   (list "Date" 0 100)
 )
)

)


(defun c:dwgbrowser_Form3_TextButton1_OnClicked (/ items title rev dwgnum make_lst show_lst)

(setq items (dcl_ListBox_GetSelectedItems dwgbrowser_Form3_ListBox1))
(setq new_item items)

;;get title
(setq title (substr (nth 0 items) 1 34))

;;gets rev
(setq rev (substr (nth 0 items) 53))

;;gets dwg number
(setq dwgnum (substr (nth 0 items) 43 7))

(setq make_lst (dcl_ListView_AddItem dwgbrowser_Form3_ListView1 title dwgnum rev))

(setq show_lst (mapcar 'list make_lst))

(dcl_ListView_FillList dwgbrowser_Form3_ListView1 show_lst)

) ;end defun


edit: this line (setq show_lst (mapcar 'list make_lst)) causes errors. it still does what i want it to do but returns  errors

Command: (dcl_Form_Show dwgbrowser_Form3)
; error: bad argument type: listp 0
; error: bad argument type: listp 1
; error: bad argument type: listp 2
; error: bad argument type: listp 3

attached are the files, the code in question is at the end of the file

Fred Tomke

andrew,

that cannot work

Code (autolisp) Select
(setq make_lst (dcl_ListView_AddItem dwgbrowser_Form3_ListView1 title dwgnum rev))

The AddItem method returns an integer of the newly added row.
But in

Code (autolisp) Select
(setq show_lst (mapcar 'list make_lst))

make_list must be a list and must not be an integer.

Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

andrew

#14
Thanks Fred.
I got it working with no errors :)
here is the code i used

(defun c:dwgbrowser_Form3_TextButton1_OnClicked (/ items title rev dwgnum make_lst stritem)
(setq items (dcl_ListBox_GetSelectedItems dwgbrowser_Form3_ListBox1))

;;get title
(setq title (substr (nth 0 items) 1 34))

;;gets rev
(setq rev (substr (nth 0 items) 53))

;;gets dwg number
(setq dwgnum (substr (nth 0 items) 43 7))

(defun make_list (strItem)
(list strItem)
)

(setq make_lst (mapcar 'list (make_list title) (make_list dwgnum) (make_list rev)))
(setq show_lst (append show_lst make_lst))
(dcl_ListView_FillList dwgbrowser_Form3_ListView1 show_lst)


now here is another question

in the list view, if there is an row that i decide to delete
what would be the best way to approach it?

is there an easy way to delete a row?
there should be a function to delete a row like there is for deleting a column