Jump to content

Error on a cancel button in DCL


AdamW

Recommended Posts

Can Anyone tell me where Ive gone wrong. Im newish to lisp and very new to DCL. A colleague from work has helped me and I have also read Lee Macs website and Afra Lisps website to get me to this point, but now Im a little stuck.

Every time I hit the cancel button button i get this error

 

; error: bad argument type: consp "Canceled"

 

The Ultimate goal would be when the cancel button is hit it would cancel the dialogue and print a message "Cancelled by User"

 

The Lisp is as follows

(defun c:Material-sizes ()

;Get Initial Values if set to nil
(if (= timber_length nil) (setq timber_length "4800"))
(if (= Ply_length nil) (setq Ply_length "2400"))


(defun DControl ()
(setq dcl-id (load_dialog (findfile "Materials.dcl")))
(if (not (new_dialog "Materials" dcl-id "" '(-1 -1))
)
(exit)
(progn

(setq Output "Canceled")

(set_tile "eb1" timber_length)
(set_tile "eb2" Ply_length)


(action_tile "accept" "(result)(done_dialog 1)")
(action_tile "cancel" "(done_dialog 0)")

(defun result ()
(setq Output (list "v1.0"
(get_tile "eb1")(get_tile "eb2")
)
))
(start_dialog)
))
Output)

(setq Output (DControl))

(setq
timber_length (atof (nth 1 Output))
Ply_length (atof (nth 2 Output))
)


;Do the calculations
;This lengthy section has been removed


;reset Variables to strings
(setq timber_length (rtos timber_length 2 2))
(setq Ply_length (rtos Ply_length 2 2))

;clean exit
(princ)
 )

The DCL is as follows

//---------------------------------//
cbut
   : retirement_button
   {
   alignment     = centered ;
   key           = "cancel" ;
   label         = "Cancel" ;
   is_cancel    = true ;
   fixed_width     = true ;
   width         = 12 ;
   }

okbut
   : retirement_button
   {
   alignment     = centered ;
   key           = "accept" ;
   label         = "Update" ;
   is_default     = true ;
   fixed_width     = true ;
   width         = 12 ;
   }


edbox
   : edit_box
   {
   fixed_width    = true;
   edit_width     = 6;
   }

//---------------------------------//
tile_a
   :boxed_column
   {
   label = "Defaults" ;

   :edbox {key = "eb1"; label = "Timber length"; alignment = right;}
   :edbox {key = "eb2"; label = "Ply Length"; alignment = right;}
   }


//---------------------------------//
Materials
   : dialog
   {
   fixed_width = true;
   width = 40;
   label = "Materials";
tile_a;
cbut;
okbut;
}

//---------------------------------//

Thanks in advance

Link to comment
Share on other sites

I am no expert on dcl's but the ok_cancel combo returns as you say the variable "Cancel" so wether you click ok or cancel you can save these two answers and do a if outside the dcl. The problem may be trying to do to much inside the dcl. You dont appear to be saving the click on these buttons.

 

This is just an example of the way I do it. Ps I need to add the cancel to my code.

(setq dcl_id (load_dialog  fname))
(if (not (new_dialog "ddgetval2" dcl_id))
(exit))
(mode_tile "key1" 3)
(set_tile "key1" (setq val1 def1))
(action_tile "key1" "(setq val1 $value)")
(mode_tile "key2" 3)
(set_tile "key2" (setq val2 def2))
(action_tile "key2" "(setq val2 $value)")
; put the action tile ok and cancel here as a saved variable
(action_tile "cancel" "(setq action "Yes")")
(start_dialog)
(done_dialog)
(unload_dialog dcl_id)
; returns the value of val1 and val2 as strings
(vl-file-delete fname)
) 

Link to comment
Share on other sites

(defun c:Material-sizes  () ;Get Initial Values if set to nil
 (if (= timber_length nil) (setq timber_length "4800"))
 (if (= Ply_length nil) (setq Ply_length "2400"))
 
 (defun DControl  ()
   (setq dcl-id (load_dialog (findfile "Materials.dcl")))
   (if (not (new_dialog "Materials" dcl-id "" '(-1 -1)))
     (exit)
     (progn (setq Output "Canceled")
            (set_tile "eb1" timber_length)
            (set_tile "eb2" Ply_length)
            (action_tile "accept" "(result)(done_dialog 1)")
            (action_tile "cancel" "(done_dialog 0)")
            (defun result () (setq Output (list "v1.0" (get_tile "eb1") (get_tile "eb2"))))
            (start_dialog)
     )
   )
   Output
 )
 
 (setq Output (DControl))
 (if (not (eq Output "Canceled"))
   (progn
     (setq timber_length (atof (nth 1 Output))
           Ply_length    (atof (nth 2 Output))) ;Do the calculations
     ;This lengthy section has been removed
     ;reset Variables to strings
     (setq timber_length (rtos timber_length 2 2))
     (setq Ply_length (rtos Ply_length 2 2))
    )
   (princ "\nCanceled by User")
  )
 ;clean exit
 (princ)
)
 

 

 

FWIW

Materials : dialog {label="Materials";fixed_width=true;width=40;
 :boxed_row {label="Defaults";
   :column {:text {label="Timber Length";} :text {label="Ply Length";}}
   :column {:edit_box {key="eb1";} :edit_box {key="eb2";}}}
 ok_cancel;
}
 
Edited by rlx
Link to comment
Share on other sites

On 8/17/2018 at 5:50 PM, AdamW said:

Can Anyone tell me where Ive gone wrong... ; error: bad argument type: consp "Canceled"

Basically in DControl you setq your result to "Canceled", and if the tile hit is accept, you override it in the result function. If you hit cancel (hence skip the override), the value stored is still the string "Cancelled", which triggers the error  when you try to get (nth 1 Output) of a string. A simple modification would be to check whether the variable contains a list, and if not exit after displaying the string you want ie "The user has cancelled"

(defun c:Material-sizes ()
  
  ;Get Initial Values if set to nil
  (if (= timber_length nil) (setq timber_length "4800"))
  (if (= Ply_length nil) (setq Ply_length "2400"))
   
  (defun DControl ()
    (setq dcl-id (load_dialog (findfile "Materials.dcl")))
    (if (not (new_dialog "Materials" dcl-id "" '(-1 -1))
             )
      (exit)
      (progn
        (setq Output "Canceled")
        (set_tile "eb1" timber_length)
        (set_tile "eb2" Ply_length)
        (action_tile "accept" "(result)(done_dialog 1)")
        (action_tile "cancel" "(done_dialog 0)")
        
        (defun result ()
          (setq Output (list "v1.0"
                             (get_tile "eb1")(get_tile "eb2")
                             )
                )
        )
        (start_dialog)
        )
      )
    Output)
  
  (setq Output (DControl))
  ;(alert (vl-princ-to-string output))
  (if (not (listp Output))
    (progn
      (alert "Cancelled by User")
      (exit)
      )
    )
  (setq
    timber_length (atof (nth 1 Output))
    Ply_length (atof (nth 2 Output))
  )
    
  ;Do the calculations
  ;This lengthy section has been removed
    
  ;reset Variables to strings
  (setq timber_length (rtos timber_length 2 2))
  (setq Ply_length (rtos Ply_length 2 2))
  
  ;clean exit
  (princ)
  )

Cheers!

edit: I just saw that rlx offered a working solution... I'll still leave my reply as the original question was "Why...".  

Edited by Jef!
Link to comment
Share on other sites

Just a nitpicky thing but:

;;This
(if (= timber_length nil)
  (setq timber_length "4800")
)
(if (= ply_length nil)
  (setq ply_length "2400")
)
;; Could be this
(or timber_length (setq timber_length "4800"))
(or ply_length (setq ply_length "2400"))

 

  • Like 1
Link to comment
Share on other sites

6 hours ago, ronjonp said:

;; Could be this (or timber_length (setq timber_length "4800")) (or ply_length (setq ply_length "2400"))

or this:

(setq timber_length (cond ( timber_length ) ( "4800") ) )
(setq Ply_length (cond ( Ply_length ) ( "2400") ) )

or even:

; (mapcar 'AssignFirstVal '((timber_length "4800")(Ply_length "2400")))
; (mapcar 'AssignFirstVal '((a 1)(b 2)(c 3)))
; (AssignFirstVal '(x 123))
(defun AssignFirstVal ( L / sym val )
  (mapcar 'set '(sym val) L)
  (set sym (cond ( (eval sym) ) ( val ) ) )
)

:beer:

Link to comment
Share on other sites

1 hour ago, Grrr said:

(set sym (cond ( (eval sym) ) ( val ) ) )

Why set the value of the variable to itself? How about -

(cond ((eval sym)) ((set sym val)))

 

Link to comment
Share on other sites

Lee has a good point here. Despite that for an average user it can become hard to spot all variables to localize them when they are declared like that.

 If someones writes 

(if (= timber_length nil)
    (setq timber_length "4800")
)

the next logic step would be that

(if (null timber_length)
    (setq timber_length "4800")
)

After that, as mentioned by ronjonp the or approach looks like a concept that can be understood by the OP and brings a bite size of new material. I'm not sure the OP is at a level to grasp concepts that use mapcars/set/eval since the original request for help was to find out why (nth 1 "calcelled") was bombing. Nitpicky thingy too :)

Link to comment
Share on other sites

8 hours ago, Lee Mac said:

Why set the value of the variable to itself? How about -


(cond ((eval sym)) ((set sym val)))

Goot point indeed, but now looking at it, the line could be reduced a bit with the or function, just like Ron did -

(or (eval sym) (set sym val))

Talking about the AssignFirstVal subfoo

 

7 hours ago, Jef! said:

Lee has a good point here. Despite that for an average user it can become hard to spot all variables to localize them when they are declared like that.

I agree, but as far I see here the intention is to keep timber_length and Ply_length global

 

7 hours ago, Jef! said:

I'm not sure the OP is at a level to grasp concepts that use mapcars/set/eval

No one requires from him to understand the subfoo that uses these functions. The only thing needed is to know what this does:

(mapcar 'AssignFirstVal '((timber_length "4800")(Ply_length "2400")))
Link to comment
Share on other sites

No one has mentioned this:

The standard practice is to use the return value of the start_dialog function to determine which button (or other tile) was used to close the dialog. The return value will be the integer specified in the done_dialog call.

Link to comment
Share on other sites

well if we're all nutpicking , I see no action tile for the edit boxes so if you're nut want to change them , you might as well leave them out or make them part of this party.

(defun c:Material-sizes ( / f p d r drv otbr oply)
  
  (defun Go_Process_Yourself ()
    ; needs data verification
    (setq timber_length (atof timber_length) Ply_length (atof Ply_length))
    ; calcy calcy
    (princ "\nCalculating.........Timber!!!")
    (setq timber_length (rtos timber_length 2 2) Ply_length (rtos Ply_length 2 2))
  )
    
  (and (or timber_length (setq timber_length "4800"))
       (or Ply_length (setq Ply_length "2400"))
       (setq p (open (setq f (vl-filename-mktemp ".dcl")) "w"))
       (mapcar ''((x)(princ x p))
	       '("M:dialog {label=\"Materials\";fixed_width=true;width=40;"
		     ":boxed_row {label=\"Defaults\";"
		     ":column {:text {label=\"Timber Length\";} :text {label=\"Ply Length\";}}"
		     ":column {:edit_box {key=\"eb1\";} :edit_box {key=\"eb2\";}}} ok_cancel;}"))
       (not (setq p (close p)))(< 0 (setq d (load_dialog f)))(new_dialog "M" d)
       (progn
         (set_tile "eb1" (setq otbr timber_length))
	     (set_tile "eb2" (setq oply Ply_length))
         (action_tile "eb1" "(setq timber_length $value)");verify data
	     (action_tile "eb2" "(setq Ply_length $value)");verify data
         (action_tile "accept" "(done_dialog 1)")
         (action_tile "cancel" "(done_dialog 0)")
         (setq drv (start_dialog))(unload_dialog d)(vl-file-delete f)
       )
  )
  (cond
    ((= drv 0)
     (setq timber_length otbr Ply_length oply)
     (princ "\nCanceled by User"))
    (t (Go_Process_Yourself))
  )
  (princ)
)

but I think you've all scared OP away with your mapcar's & evals haha

Edited by rlx
Link to comment
Share on other sites

@rlx:

Call it nitpicking or call it fundamental: In the latest version of your code the globals timber_length and Ply_length can change even if the user hits the Cancel button.

Link to comment
Share on other sites

correct and if OP types :beer: instead of a number in one of the edit boxes I still won't get drunk... :beer:

but ok , fixed it even though OP hasn't responded anymore

Edited by rlx
  • Funny 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...