Author Topic: Force Input value : edit_box  (Read 518 times)

0 Members and 1 Guest are viewing this topic.

Grrr1337

  • Bull Frog
  • Posts: 314
Force Input value : edit_box
« on: November 17, 2016, 05:25:11 pm »
Hi guys,
I'm new into DCL, and I'm still on the learning curve.
I have a few issues and questions about the current .lsp and .dcl I'm working on:
DCL
Code: [Select]
// Input_Test.dcl
Input_Test
: dialog
{ label = "Test dialog";
: edit_box
{
key = " K1 ";
label = " Fill String ";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
: edit_box
{
key = " K2 ";
label = " Fill Real ";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
: edit_box
{
key = " K3 ";
label = " Fill Integer ";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
spacer; ok_cancel;
}
LSP
Code: [Select]
; Input_Test.lsp
(vl-load-com)
(defun C:Input_Test ( / dcl_id Lst )

(if (findfile "Input_Test.dcl")
(progn
(setq dcl_id (load_dialog "Input_Test.dcl"))
(if (not (new_dialog "Input_Test" dcl_id)) (exit) )
(foreach x '("K1" "K2" "K3")
(action_tile x (strcat "(setq Lst (cons (cons "(chr 34) x (chr 34)" $value) Lst))"))
)
(start_dialog)
(unload_dialog dcl_id)
(alert (vl-princ-to-string Lst))
)
(alert "Could not find the \nInput_Test.dcl file!")
)
(princ)
); defun


1. The first (unexpected) issue I'm having that the "Lst" quote always returns nil, I expected from it to return an assoc list
2. How do I force the user to fill all the edit_boxes before selecting the OK button?
3. Is there a way to force what type of input is provided in each edit_box, STR/REAL/INT ?

roy_043

  • Swamp Rat
  • Posts: 1431
  • BricsCAD 16
Re: Force Input value : edit_box
« Reply #1 on: November 18, 2016, 11:49:27 am »
1.
Make sure the keys in the DCL match those used in the LSP. " K1 " /= "K1".
You are already using $value, note that you can use $key as well.
2.a.
In every action callback you can check if all edit_boxes contain (valid) strings, and then disable/enable the OK button using the mode_tile function. The drawback is that the user must then press enter or tab after filling out the final edit_box.
2.b.
Use an alert or an error tile to report the problem after the user presses OK.
3.
You will have to use your own functions to validate user input. The get_tile function always returns a string.
« Last Edit: November 18, 2016, 01:05:32 pm by roy_043 »

ribarm

  • Water Moccasin
  • Posts: 1632
  • Marko Ribar, architect
Re: Force Input value : edit_box
« Reply #2 on: November 18, 2016, 03:28:01 pm »
Maybe this LISP can help...

Code: [Select]
;|
// Input_Test.dcl
Input_Test : dialog
{ label = "Test dialog";
: edit_box
{
key = "K1";
label = " Fill String ";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
: edit_box
{
key = "K2";
label = " Fill Real ";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
: edit_box
{
key = "K3";
label = " Fill Integer ";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
spacer; ok_cancel;
}
|;
; Input_Test.lsp
(defun C:Input_Test ( / makedcl dcl dcln dcl_id Lst )
  (defun makedcl ( lsp / sfsp dcl f1 f2 l )
    (defun sfsp ( / s p pl )
      (vl-load-com)
      (setq s (vla-get-supportpath (vla-get-files (vla-get-preferences (vlax-get-acad-object)))))
      (setq s (strcat s ";"))
      (while (not (eq s ""))
        (setq p (substr s 1 (vl-string-search ";" s)))
        (setq s (substr s (+ 2 (strlen p))))
        (setq pl (cons p pl))
      )
      (reverse pl)
    )
    (setq dcl (strcat (vl-string-right-trim "\\" (car (sfsp))) "\\Input_Test.dcl"))
    (setq f1 (open dcl "w"))
    (setq f2 (open lsp "r"))
    (while (/= (setq l (read-line f2)) "|;")
      (if (/= l ";|")
        (write-line l f1)
      )
    )
    (close f2)
    (close f1)
    dcl
  )

  (alert "If you have this lisp loaded in clipboard through PASTECLIP command,\nhit ESC twice to terminate routine, press win key+R, press ctrl+V, press ctrl+shift+home, press ctrl+C, press ESC, click with mouse, type USERS1 at command prompt, press ctrl+V + ENTER\nand restart this routine and when this message pops up click OK...")
  (if (/= (getvar 'users1) "")
    (setq dcl (makedcl (vl-string-trim (chr 34) (getvar 'users1))))
    (setq dcl (makedcl (getfiled "POINT TO THIS LSP FILE AND CLICK OK" "\\" "lsp" 16)))
  )
  (if dcl
    (progn
      (vl-file-copy dcl (setq dcln (strcat (vl-string-right-trim "\\" (vl-filename-directory dcl)) "\\temp.dcl")))
      (setq dcl_id (load_dialog dcln))
      (if (not (new_dialog "Input_Test" dcl_id)) (exit) )
      (foreach x '("K1" "K2" "K3")
        (action_tile x (strcat "(setq Lst (cons (cons " (chr 34) x (chr 34) " $value) Lst))"))
      )
      (start_dialog)
      (unload_dialog dcl_id)
      (if (not (vl-every '(lambda ( x ) (vl-position x '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "."))) (mapcar 'chr (vl-string->list (cdr (assoc "K1" Lst))))))
        (prompt "\nValid string input - string input contains at least one non numerical character...")
        (prompt "\nNot valid string input...")
      )
      (if (and (vl-every '(lambda ( x ) (vl-position x '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "."))) (mapcar 'chr (vl-string->list (cdr (assoc "K2" Lst))))) (= (length (vl-remove (ascii ".") (vl-string->list (cdr (assoc "K2" Lst))))) (1- (length (vl-string->list (cdr (assoc "K2" Lst)))))))
        (progn
          (prompt "\nValid real number input...")
          (setq Lst (subst (cons "K2" (read (cdr (assoc "K2" Lst)))) (assoc "K2" Lst) Lst))
        )
        (prompt "\nNot valid real number input...")
      )
      (if (vl-every '(lambda ( x ) (vl-position x '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9"))) (mapcar 'chr (vl-string->list (cdr (assoc "K3" Lst)))))
        (progn
          (prompt "\nValid integer input...")
          (setq Lst (subst (cons "K3" (read (cdr (assoc "K3" Lst)))) (assoc "K3" Lst) Lst))
        )
        (prompt "\nNot valid integer input...")
      )
      (alert (vl-prin1-to-string (reverse Lst)))
      (vl-file-delete dcln)
      (vl-file-delete dcl)
    )
    (alert "Could not find the \nInput_Test.dcl file!")
  )
  (princ)
)
« Last Edit: November 19, 2016, 10:12:46 am by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Grrr1337

  • Bull Frog
  • Posts: 314
Re: Force Input value : edit_box
« Reply #3 on: November 18, 2016, 04:15:07 pm »
Thanks Roy,
I've followed the steps:
1. - Solved
2.a. - Could not figure out how to obtain the key from " ok_cancel;  " in the dcl file, so created them "manually" instead, using : button
2.b. - Solved with alert, but could not figure out the error tile, since included the new loop in the .lsp file which resets the dialog, hence the message left unseen
3. - Will be solved, thanks I'll work about it thru lisp

Heres the progress:
DCL
Code: [Select]
// Input_Test.dcl
Input_Test
: dialog
{ label = "Test dialog";
: edit_box
{
key = "K1";
label = "Fill String";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
: edit_box
{
key = "K2";
label = "Fill Real";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
: edit_box
{
key = "K3";
label = "Fill Integer";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
spacer;
// ok_cancel;
: row
{
alignment = bottom;
: button // add done, and exit keys instead of ok_cancel buttons
{
key = "done";
label = "OK";
is_default = true;
width = 3;
fixed_height = true;
alignment = left;
}
: button
{
key = "exit";
label = "CANCEL";
is_default = false;
width = 3;
fixed_height = true;
alignment = right;
}
}
: errtile
{
width = 34;
}
}
LSP
Code: [Select]
; Input_Test.lsp
(vl-load-com)
(defun C:test ( / Lst )
(setq Lst (list (list))) ; create nested list '(nil) - so it would be non-nil value
(while
(and
Lst ; if Cancel is pressed this loop will stop
(or (/= (length Lst) 3) ; all edit_box were filled
(member "" (mapcar 'cdr Lst))) ; all edit_box contain valid strings
)
(setq Lst (GetInput)) ; must use subfunction, so it will work inside this loop
)
(alert (vl-princ-to-string Lst)) ; alert the end list result
(princ)
); defun

(defun GetInput ( / dcl_id dlgRtn RtnLst )
(if (findfile "Input_Test.dcl")
(progn
(setq dcl_id (load_dialog "Input_Test.dcl"))
(if (not (new_dialog "Input_Test" dcl_id)) (exit) )
(foreach x '("K1" "K2" "K3")
(action_tile x (strcat "(setq RtnLst (cons (cons $key $value) RtnLst))")) ; $key will work also
)
(action_tile "done"
"(if
(vl-some
(quote
(lambda (x)
(= (get_tile x) \"\")
)
)
(list \"K1\" \"K2\" \"K3\")
)
(alert \"You must fill everything!\")
(done_dialog)
)"
)
(action_tile "exit" "(setq RtnLst nil) (done_dialog)")
(setq dlgRtn (start_dialog)) ; If Cancel is pressed dlgRtn will be 0.
(unload_dialog dcl_id)
)
(alert "Could not find the \nInput_Test.dcl file!")
)
; (if (/= 0 dlgRtn) ; unneeded, since the "manual" OK CANCEL buttons
(reverse RtnLst)
; )
)
Hi Marko, I've just seen your comment... will reply soon about it, thanks in advance.
EDIT:
Marko,
The functions checking for string, real, int input seems to work. I tried writing something similar, before Roy's comment (also by using vl-every with vl-string->list).
 I'll check yours more carefully and try to improve them, one thing I noticed that "" gets valid integer input.
 BTW 1234567890 can be strings aswell, so perhaps checking if the string is /= "" may be enough ( for example "Grrr1337" won't be treated as a valid string ).
 I like your method of loading the dcl, using read-line - its new for me!
Thanks alot!

This wiring of dcl-lsp with *_tile functions is kinda annoynig I hope I'll get use to it.
« Last Edit: November 18, 2016, 04:57:08 pm by Grrr1337 »

ribarm

  • Water Moccasin
  • Posts: 1632
  • Marko Ribar, architect
Re: Force Input value : edit_box
« Reply #4 on: November 19, 2016, 06:29:25 am »
I've changed my lsp file, added (alert) message... Study the code and alert prompt to get used to use implemented DCL inside LSP...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

roy_043

  • Swamp Rat
  • Posts: 1431
  • BricsCAD 16
Re: Force Input value : edit_box
« Reply #5 on: November 19, 2016, 08:12:02 am »
@ribarm:
Have you tried using the LSP file directly as the DCL file?
This 'mixed mode' file works on BricsCAD:
Code: [Select]
// ;|
// Input_Test.dcl
Input_Test : dialog {
  ...
}
/* |;
; Input_Test.lsp
(defun C:Input_Test ( / makedcl dcl dcln dcl_id Lst )
  ...
  (setq dcl_id (load_dialog "Input_Test.lsp"))
  ...
)

In conjunction with the BricsCAD (vl-list-loaded-lisp) function to retrieve the path of the LSP file this setup may have some potential.

Grrr1337

  • Bull Frog
  • Posts: 314
Re: Force Input value : edit_box
« Reply #6 on: November 19, 2016, 08:15:04 am »
I've changed my lsp file, added (alert) message... Study the code and alert prompt to get used to use implemented DCL inside LSP...
I actually know how to make a temporary dcl file and write in the DCL code there as a string,
 but I thought that if I have to ask in the DCL section, it would be better to show it separately (as the DCL will look more readable).
Your method is very clever by including the dcl code as comment, since it remains readable and stays in the .lsp file.
Thanks again, I'll study it!

roy_043

  • Swamp Rat
  • Posts: 1431
  • BricsCAD 16
Re: Force Input value : edit_box
« Reply #7 on: November 19, 2016, 08:23:47 am »
@Grrr1337:
For the keys used in standard tiles look in the:
Programmable Dialog Box Reference

ribarm

  • Water Moccasin
  • Posts: 1632
  • Marko Ribar, architect
Re: Force Input value : edit_box
« Reply #8 on: November 19, 2016, 08:43:23 am »
@ribarm:
Have you tried using the LSP file directly as the DCL file?
This 'mixed mode' file works on BricsCAD:
Code: [Select]
// ;|
// Input_Test.dcl
Input_Test : dialog {
  ...
}
/* |;
; Input_Test.lsp
(defun C:Input_Test ( / makedcl dcl dcln dcl_id Lst )
  ...
  (setq dcl_id (load_dialog "Input_Test.lsp"))
  ...
)

In conjunction with the BricsCAD (vl-list-loaded-lisp) function to retrieve the path of the LSP file this setup may have some potential.

No this won't work for me, neither (vl-list-loaded-lisp)... I'll have to stick with my example...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Grrr1337

  • Bull Frog
  • Posts: 314
Re: Force Input value : edit_box
« Reply #9 on: November 19, 2016, 09:55:32 am »
Going a bit offtopic, but I wanted to share this with you guys:

I wrote something interesting, after analysing Marko's code.
However I didn't focused on the input types problem, but more on the "DCL code inside of the LSP code".
You might find the 2 subfunctions useful "GetLstBetweenRows" and "MakeTempDCL" :
Code: [Select]
; Example Test function:
(defun C:test ( / fpath LstDCLcode ActionTilesFunc RtnLst R )
(if (setq fpath (getfiled "Open the same lisp file" "" "lsp" 0))
(progn
; test of "GetLstBetweenRows" :
(setq LstDCLcode (GetLstBetweenRows fpath ";| // START DCL" "// END DCL |;"))
(alert (apply 'strcat (mapcar '(lambda (x) (strcat "\n" x)) LstDCLcode))) ; display the result of "GetLstBetweenRows"
; test of "MakeTempDCL" :
(setq ActionTilesFunc
"
(foreach x '(\"K1\" \"K2\" \"K3\")
(action_tile x (strcat \"(setq RtnLst (cons (cons \"(chr 34) x (chr 34)\" $value) RtnLst))\"))
)
"
)
(setq R (MakeTempDCL "Input_Test" LstDCLcode ActionTilesFunc "(reverse RtnLst)"))
(alert (vl-princ-to-string R))
); progn
); if
(princ)
); defun C:test

; This is the sample DCL code that "GetLstBetweenRows" subfunction will look for:
;| // START DCL
Input_Test : dialog
{ label = "Test dialog";
: edit_box
{
key = "K1";
label = " Fill String ";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
: edit_box
{
key = "K2";
label = " Fill Real ";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
: edit_box
{
key = "K3";
label = " Fill Integer ";
edit_width = 20;
edit_limit = 12;
is_enabled = true;
}
spacer; ok_cancel;
}
// END DCL |;

; GetLstBetweenRows will extract "List of Strings" Between the specified StartRow and EndRow (exclusive)
(defun GetLstBetweenRows ( fpath StartRow EndRow / o row Lst )
(setq o (open fpath "r"))
(while (/= (setq row (read-line o)) StartRow) row)
(while (/= (setq row (read-line o)) EndRow) (setq Lst (cons row Lst)) )
(close o)
(setq Lst (reverse Lst))
); defun GetLstBetweenRows


; Template for creating a temporary DCL file, from the dialog's name, List of Strings which contains the DCL code
(defun MakeTempDCL ( DlgName LstDCLcode ActionTilesFunc toRtn / FpathWithFname fileDCL dcl_id ) ; works

(setq FpathWithFname (vl-filename-mktemp "AnyNameForDclFile.dcl"))
(setq fileDCL (open FpathWithFname "w"))
(foreach x LstDCLcode (write-line x fileDCL))
(close fileDCL)
(setq dcl_id (load_dialog FpathWithFname))
(and (not (new_dialog DlgName dcl_id))(exit))
(eval (read ActionTilesFunc))
(start_dialog)
(unload_dialog dcl_id)
(vl-file-delete FpathWithFname)
(eval (read toRtn))

); defun MakeTempDCL
"MakeTempDCL" isn't fully complete yet, but it does the job in this example.
 Will figure out of better way of populating the "keys" and somehow automate the RtnLst symbol.
At the moment ActionTilesFunc and toRtn input arguments for it are not very user-friendly.

roy_043

  • Swamp Rat
  • Posts: 1431
  • BricsCAD 16
Re: Force Input value : edit_box
« Reply #10 on: November 19, 2016, 10:48:07 am »
FWIW:
Here is an example of a 'mixed mode' file (apparently BricsCAD only).
File name: "MixedMode.lsp".
Code: [Select]
// ;|
MixedMode : dialog {
  label = "MixedMode Test Dialog";
  : boxed_column {
    : text {value = "DCL and LSP in a single file (BricsCAD only)";}
  }
  ok_only;
}
/* |;
(defun c:MixedMode ( / dcl fnm)
  (if
    (and
      (setq fnm
        (vl-some
          '(lambda (str)
            (if (wcmatch (strcase str) "*MIXEDMODE*") str)
          )
          (reverse (vl-list-loaded-lisp))
        )
      )
      (setq dcl (load_dialog fnm))
    )
    (progn
      (new_dialog "MixedMode" dcl)
      (start_dialog)
      (unload_dialog dcl)
    )
  )
  (princ)
)