SamIWas Posted January 24, 2017 Share Posted January 24, 2017 I've done plenty of Vectorscript, having written several dozen including my own custom Vectorworks to lighting console 3d/patch exporter. So I'm no stranger to coding. I am trying to learn to make some basic custom dialogs , but every example I look at just melts my brain. I can't even figure out what relates to what and how the information in the fields gets passed to the rest of the script. I've read over all the ones listed on the developer page and tried to break them down, to no avail. I've used the Dialog Builder, but it's not the layout I have issues with. All I'm looking for is to create a dialog with a few text edit boxes, maybe a checkbox or two, and possibly a drop-down with basic user-entry info. I've succeeded in creating the layout with the fields and tested those out, and gotten a report on whether I clicked "Cancel" or "OK". Now, I just need to figure out how to pass the information that is typed into a text box or selected in a drop down to a simple variable. But it seems that even something that simple involves all sorts of complicated coding. Is there something I'm missing here? Quote Link to comment
JBenghiat Posted January 24, 2017 Share Posted January 24, 2017 Have you written the dialog event handler? This is what you pass to RunNamedDialog that tells VW how to respond to each UI event. You use GetItemText to set a variable to the value in a text field. You generally get all dialog data in the event handler when the user presses the ok button. Use global variables to access the data outside the handler. Is there a specific example we can help you parse? -Josh Quote Link to comment
SamIWas Posted January 24, 2017 Author Share Posted January 24, 2017 2 hours ago, JBenghiat said: Have you written the dialog event handler? This is what you pass to RunNamedDialog that tells VW how to respond to each UI event. You use GetItemText to set a variable to the value in a text field. You generally get all dialog data in the event handler when the user presses the ok button. Use global variables to access the data outside the handler. Is there a specific example we can help you parse? -Josh Hey Josh, I have not written the handler. That's where I get confused looking at others' scripts, trying to figure out their handler and function parts and how it all relates. Here is my code so far. I can clean up the layout later, and this was just something to learn. But all I want to do from here is pass 6 to the Universe field in the Lighting Device record, and pass 7 to the Address field. And if 8 is checked (want to make this the default but still looking into that), it will run 7 through a script to format it. I think if I can get those basics down, I can then dig into the meat of it all. Thanks for any help...I know you're the master at this stuff! Procedure DIALOG; VAR id : LONGINT; result : LONGINT; BEGIN id:=CreateLayout('Assign Address',FALSE,'Apply','Cancel'); CreateStaticText(id,4,'Assign Universe:',-1); CreateStaticText(id,5,'Assign Address:',-1); CreateEditInteger(id,6,0,6); CreateEditInteger(id,7,0,6); CreateCheckBox(id,8,'Use three digits for address'); SetFirstLayoutItem(id,4); SetRightItem(id,4,6,0,0); SetBelowItem(id,4,5,0,0); SetRightItem(id,5,7,0,0); SetBelowItem(id,5,8,0,0); SetHelpText(id,6,'Enter universe here'); SetHelpText(id,7,'Enter DMX address here'); SetHelpText(id,7,'Check if DMX address should have 3 digits. Exaample: DMX 45 = 045'); result:=RunLayoutDialog(id,NIL); Message(result); END; RUN(DIALOG); Quote Link to comment
SamIWas Posted January 24, 2017 Author Share Posted January 24, 2017 As far as one to parse the meaning of, here's a simple dialog to create a rectangle. It may have come from this site somewhere... In red is what is confusing.... Procedure DialogTest; TYPE U_RECT = STRUCTURE a: REAL; b: REAL; END; VARgRectObj: U_RECT; FUNCTION SetUpDialog(rectObj: U_RECT): LONGINT; VAR ID: LONGINT; BEGIN ID:= CreateLayout('Rect Dimensions',TRUE,'OK','Cancel'); {Text fields} CreateStaticText( ID, 05, 'Value-a', 15); CreateStaticText( ID, 06, 'Value-b', 15); {Box fields} CreateEditReal( ID, 15, 1, rectObj.a, 10); CreateEditReal( ID, 16, 1, rectObj.b, 10); {Text layout} SetFirstLayoutItem( ID, 05); SetBelowItem( ID, 05, 06, 0, 0); {Box layout} SetRightItem( ID, 05, 15, 0, 0); SetRightItem( ID, 06, 16, 0, 0); SetHelpText(ID, 1,'Click to accept values'); SetHelpText(ID, 2,'Click to cancel operation'); SetHelpText(ID, 15,'Enter width'); SetHelpText(ID, 16,'Enter height'); SetUpDialog:= ID; END; FUNCTION GetRect(VAR rectObj: U_RECT): BOOLEAN; VAR a,b: REAL; ID,dlogResult: LONGINT; PROCEDURE DriveDialog(VAR item:LONGINT; data:LONGINT); VAR i,choiceNo: INTEGER; foundName: BOOLEAN; BEGIN CASE item OF SetupDialogC: BEGIN END; 1: {OK} BEGIN IF GetEditReal(ID,15,1,a) THEN rectObj.a:= a; IF GetEditReal(ID,16,1,b) THEN rectObj.b:= b; END; 2: {Cancel} BEGIN END; END; END; BEGINGetRect:= FALSE; ID:= SetUpDialog(rectObj); IF VerifyLayout(ID) THEN BEGIN dlogResult:= RunLayoutDialog(ID,DriveDialog); IF dlogResult = 1 THEN GetRect:= TRUE; END ELSE AlrtDialog('Cannot create the dialog'); END; BEGIN gRectObj.a:= 1.25; gRectObj.b:= 2.64;IF GetRect(gRectObj) THEN BEGIN Rect(0,0,gRectObj.a,gRectObj.b); END; END; Run(DialogTest); Quote Link to comment
twk Posted January 26, 2017 Share Posted January 26, 2017 I've tabbed the code to make it easier to read: Procedure DialogTest; TYPE U_RECT = STRUCTURE a: REAL; b: REAL; END; VAR gRectObj: U_RECT; FUNCTION SetUpDialog(rectObj: U_RECT): LONGINT; VAR ID: LONGINT; BEGIN ID:= CreateLayout('Rect Dimensions',TRUE,'OK','Cancel'); {Text fields} CreateStaticText( ID, 05, 'Value-a', 15); CreateStaticText( ID, 06, 'Value-b', 15); {Box fields} CreateEditReal( ID, 15, 1, rectObj.a, 10); CreateEditReal( ID, 16, 1, rectObj.b, 10); {Text layout} SetFirstLayoutItem( ID, 05); SetBelowItem( ID, 05, 06, 0, 0); {Box layout} SetRightItem( ID, 05, 15, 0, 0); SetRightItem( ID, 06, 16, 0, 0); SetHelpText(ID, 1,'Click to accept values'); SetHelpText(ID, 2,'Click to cancel operation'); SetHelpText(ID, 15,'Enter width'); SetHelpText(ID, 16,'Enter height'); SetUpDialog:= ID; END; FUNCTION GetRect(VAR rectObj: U_RECT): BOOLEAN; VAR a,b: REAL; ID,dlogResult: LONGINT; PROCEDURE DriveDialog(VAR item:LONGINT; data:LONGINT); VAR i,choiceNo: INTEGER; foundName: BOOLEAN; BEGIN CASE item OF SetupDialogC: BEGIN END; 1: {OK} BEGIN IF GetEditReal(ID,15,1,a) THEN rectObj.a:= a; IF GetEditReal(ID,16,1,b) THEN rectObj.b:= b; END; 2: {Cancel} BEGIN END; END; END; BEGIN GetRect:= FALSE; ID:= SetUpDialog(rectObj); IF VerifyLayout(ID) THEN BEGIN dlogResult:= RunLayoutDialog(ID,DriveDialog); IF dlogResult = 1 THEN GetRect:= TRUE; END ELSE AlrtDialog('Cannot create the dialog'); END; BEGIN gRectObj.a:= 1.25; gRectObj.b:= 2.64; IF GetRect(gRectObj) THEN BEGIN Rect(0,0,gRectObj.a,gRectObj.b); END; END; Run(DialogTest); (1) 'gRectObj' is a user-defined variable type. Declared a couple lines up: TYPE U_RECT = STRUCTURE a: REAL; b: REAL; END; (2) The GetEditReal(ID,15,1,a) and GetEditReal(ID,16,1,b) calls are retrieving data from the dialog item (15, 16), storing each in 'a' and 'b' respectively. and the "IF" statement in those lines are basically saying, if there is a real number stored in those dialog items, store them in as the rectObj.a, and rectObj.b variables. As you can see the custom/user defined variable U_RECT has two components to it a,b. So rectObj is a U_RECT type of variable, having these two components. More info on GetEditReal : http://developer.vectorworks.net/index.php/VS:GetEditReal (3) BEGIN GetRect:= FALSE; ID:= SetUpDialog(rectObj); IF VerifyLayout(ID) THEN BEGIN dlogResult:= RunLayoutDialog(ID,DriveDialog); IF dlogResult = 1 THEN GetRect:= TRUE; END ELSE AlrtDialog('Cannot create the dialog'); END; This is the main code of the FUNCTION > GetRect(VAR rectObj: U_RECT): BOOLEAN (4) IF GetRect(gRectObj) THEN BEGIN Rect(0,0,gRectObj.a,gRectObj.b); END; This is basically saying if the function GetRect returns TRUE then draw the rectangle. Hope this helps Tui Quote Link to comment
JBenghiat Posted January 26, 2017 Share Posted January 26, 2017 Just to comment on the overall code structure as well, when you run the dialog, you provide the ID of the dialog and the name of a procedure for handling the dialog events (DriveDialog). This procedure runs every time the user interacts with the dialog, looping until the user has selected OK or cancel. The procedure uses two variables that get set to the ID of the item with which the user has interacted, and sometimes additional information (in this case item and data). VS has two special constants, SetupDialogC and SetDownDialogC, that let the procedure know the dialog is about to display and is about to close, respectively. This SetUpDialogC is where you would set any default values. Because the dialog handler is a self-contained procedure, you need global variables (simply a variable defined in the scope of the main program) for storing any results you want to access outside of the dialog handler. Usually, you set these values during the OK event (item = 1). HTH, Josh Quote Link to comment
JBenghiat Posted January 26, 2017 Share Posted January 26, 2017 Just to comment on the overall code structure as well, when you run the dialog, you provide the ID of the dialog and the name of a procedure for handling the dialog events (DriveDialog). This procedure runs every time the user interacts with the dialog, looping until the user has selected OK or cancel. The procedure uses two variables that get set to the ID of the item with which the user has interacted, and sometimes additional information (in this case item and data). VS has two special constants, SetupDialogC and SetDownDialogC, that let the procedure know the dialog is about to display and is about to close, respectively. This SetUpDialogC is where you would set any default values. Because the dialog handler is a self-contained procedure, you need global variables (simply a variable defined in the scope of the main program) for storing any results you want to access outside of the dialog handler. Usually, you set these values during the OK event (item = 1). HTH, Josh 1 Quote Link to comment
twk Posted January 27, 2017 Share Posted January 27, 2017 Interesting @JBenghiat.. I never knew of the SetDownDialogC. What is that normally used for? or How would you use that? Thanks Tui Quote Link to comment
JBenghiat Posted January 27, 2017 Share Posted January 27, 2017 19 minutes ago, twk said: Interesting @JBenghiat.. I never knew of the SetDownDialogC. What is that normally used for? or How would you use that? Thanks Tui I really don't use it much, but that would be the place to do things like save the dialog position. There is also a ResizeDilogC for when the user has resized the dialog. -Josh 1 Quote Link to comment
SamIWas Posted January 27, 2017 Author Share Posted January 27, 2017 Thanks for the info, guys! Had a busy day today, but will look more into it tomorrow when I might have a fresh brain. Quote Link to comment
SamIWas Posted February 10, 2017 Author Share Posted February 10, 2017 I've been experimenting some more, and decided that the examples I was working with were too complicated to learn from. So I found a much simpler one, but still have a question or two... ------------------------------------------------------------- Procedure test; var gValue : integer; function Mydialog(var lValue:integer):boolean; VAR id :INTEGER; result :INTEGER; PROCEDURE Dialog_Handler(VAR item :LONGINT; data :LONGINT); var Bool: boolean; BEGIN GetBooleanItem(id, 5, Bool); if Bool THEN lValue := 0; GetBooleanItem(id, 6, Bool); if Bool THEN lValue := 2; GetBooleanItem(id, 7, Bool); if Bool THEN lValue := -1; END; BEGIN id := CreateLayout('Set Visibility', FALSE, 'OK', 'Cancel'); CreateGroupBox(id,4,'Visibility:',true); CreateRadioButton(id,5,'Show'); CreateRadioButton(id,6,'Grey'); CreateRadioButton(id,7,'Hide'); SetFirstLayoutItem(id,4); SetFirstGroupItem(id,4,5); SetBelowItem(id,5,6,0,0); SetBelowItem(id,6,7,0,0); result := RunLayoutDialog(id, Dialog_Handler); if result = 2 then Mydialog := false else Mydialog := true; END; {Mydialog} begin {main} if Mydialog(gValue) then begin message(concat(gValue)); end; end; {main} run(test); ------------------------------------------------------------- So, the part that is blue is a no-brianer. Not worried about that at all. I'll start with questions... gValue is specified as a variable for procedure "test" as an integer. But, nowhere in the script is gValue given a value. During a function, a value is given to variable lValue. But at the end of the script, a message displays gValue with the value given to lValue. Where is gValue being given its value from lValue? In Procedure Dialog_Handler, I know i can add in GetItemText calls to retrieve strings from CreateEditText boxes and GetEditInteger/Real calls to retrieve numbers from CreateEditInteger/Real boxes in the layout. I assume that I need extra variables of String, Integer, and Real types to collect the info. So, let's say I do the following (changes in red) function Mydialog(var lValue:integer;univ:string):boolean; VAR id :INTEGER; result :INTEGER; PROCEDURE Dialog_Handler(VAR item :LONGINT; data :LONGINT); var Bool: boolean; BEGIN GetItemText(id, 8, univ); GetBooleanItem(id, 5, Bool); if Bool THEN lValue := 0; GetBooleanItem(id, 6, Bool); if Bool THEN lValue := 2; GetBooleanItem(id, 7, Bool); if Bool THEN lValue := -1; END; How does univ get passed down? Did I even put univ in the right place? At some point, something is going to click, and I'll be able to fully grasp what is going on start writing more complex dialogs. Quote Link to comment
JBenghiat Posted February 10, 2017 Share Posted February 10, 2017 First off, this example is a little non-standard, and the dialog handler really isn't a proper handler, and will only work for demonstration purposes. This may not actually be a great example to try and emulate. The argument in Mydialog() has the keyword VAR in front of it, and would be a pointer in other programming languages: lValue doesn't actually store a LONGINT, but rather the address of another LONGINT variable. In this case, when you pass gValue to Mydialog, Mydialog effectively substitutes the variable name gValue every time you see lValue. It's a bit of a cleaner way to deal with scope, though because the dialog handler takes specific arguments, lValue really becomes a global in Mydialog. The answer to your question of fetching the text value depends on the scope where you need it. Let's say you want to just extend this example In the scope of test, define the variable: gTxtValue :STRING; Define the function Mydialog as: function Mydialog(VAR lValue :integer; VAR lTxtValue :STRING) :boolean; Call mydialog: ...Mydialog(gValue, gTxtValue)... and of course retrieving the field value would be: GetItemTextID(id, 8, lTxtValue); The dialog handler here is fairly incomplete, as you constantly retrieve values for every dialog event. You really want a CASE statement so that the right part of the code executes for each "item" with which the user interacts. Retrieving the values into your globals would only be in the case that the user clicks the OK button, item = 1. Your questions seem to be more related to VectorScript variables and scope rather than dialogs specifically, so I highly recommend starting here for the language fundamentals: http://developer.vectorworks.net/images/7/72/VectorScriptGuide.pdf VS is based on Pascal, so you can also investigate Pascal basics, though note that VS is a proprietary version of the language. If you are new to programming in general, I recommend learning Python instead. The VS and Python API have identical commands, but with Python you are learning a contemporary programming language with a simpler syntax. HTH, Josh Quote Link to comment
SamIWas Posted February 10, 2017 Author Share Posted February 10, 2017 3 hours ago, JBenghiat said: First off, this example is a little non-standard, and the dialog handler really isn't a proper handler, and will only work for demonstration purposes. This may not actually be a great example to try and emulate. The argument in Mydialog() has the keyword VAR in front of it, and would be a pointer in other programming languages: lValue doesn't actually store a LONGINT, but rather the address of another LONGINT variable. In this case, when you pass gValue to Mydialog, Mydialog effectively substitutes the variable name gValue every time you see lValue. It's a bit of a cleaner way to deal with scope, though because the dialog handler takes specific arguments, lValue really becomes a global in Mydialog. The answer to your question of fetching the text value depends on the scope where you need it. Let's say you want to just extend this example In the scope of test, define the variable: gTxtValue :STRING; Define the function Mydialog as: function Mydialog(VAR lValue :integer; VAR lTxtValue :STRING) :boolean; Call mydialog: ...Mydialog(gValue, gTxtValue)... and of course retrieving the field value would be: GetItemTextID(id, 8, lTxtValue); The dialog handler here is fairly incomplete, as you constantly retrieve values for every dialog event. You really want a CASE statement so that the right part of the code executes for each "item" with which the user interacts. Retrieving the values into your globals would only be in the case that the user clicks the OK button, item = 1. Your questions seem to be more related to VectorScript variables and scope rather than dialogs specifically, so I highly recommend starting here for the language fundamentals: http://developer.vectorworks.net/images/7/72/VectorScriptGuide.pdf VS is based on Pascal, so you can also investigate Pascal basics, though note that VS is a proprietary version of the language. If you are new to programming in general, I recommend learning Python instead. The VS and Python API have identical commands, but with Python you are learning a contemporary programming language with a simpler syntax. HTH, Josh Thanks for the info Josh...I'll keep plugging along using your help above. I knew it probably wasn't the best example, but simpler examples have been hard to find. And what you see above is after I cleaned up the spacing, tabs, and lines! Not really new to programming. I've written over 100 VectorScripts so far to do all sorts of things, including my own custom GrandMA exporter (because I don't like the official one). So far, I've used the standard built-in dialogs. There's just something about the way this custom dialog thing works that isn't connecting in my brain. Seems like it could be so much simpler! Quote Link to comment
SamIWas Posted February 11, 2017 Author Share Posted February 11, 2017 Okay...I'm 95% comfortable with what's going on now. I've got variables passing between the main part and the dialog handler, and reporting at the end. The only exception is the text field, ID 6 (it's a text field just for testing purposes). It doesn't pass to the message at the end. Everything else works as intended, and I think I have the dialog handler written more correctly. So, if you can point me where I'm going wrong on the text field, I will owe you my eternal gratitude, and hopefully put this thread to a close! Procedure AssignInfo; var gValue,gAddr: integer; gUniv:STRING; function Mydialog(var lValue,lAddr:integer;lUniv:STRING):boolean; VAR id :INTEGER; result :INTEGER; PROCEDURE Dialog_Handler(VAR item :LONGINT; data :LONGINT); var Bool: boolean; tUniv:String; tAddr:integer; BEGIN CASE item OF SetupDialogC: BEGIN SetItemText(id,6,'0'); SetEditInteger(id,7,0); SetBooleanItem(id,8,TRUE); END; 1: BEGIN GetItemText(id,6,lUniv); If GetEditInteger(id,7,TAddr) then lAddr:=TAddr; GetBooleanItem(id, 8, Bool); if Bool THEN lValue := 1; END; 2: BEGIN END; END; {case} END; {Dialog Handler} BEGIN id:=CreateLayout('Assign Address',TRUE,'Apply','Cancel'); CreateStaticText(id,4,'Assign Universe:',-1); CreateStaticText(id,5,'Assign Address:',-1); CreateEditText(id,6,'0',6); CreateEditInteger(id,7,0,6); CreateCheckBox(id,8,'Use three digits for address'); SetFirstLayoutItem(id,4); SetRightItem(id,4,6,0,0); SetBelowItem(id,4,5,0,0); SetRightItem(id,5,7,0,0); SetBelowItem(id,5,8,0,0); SetHelpText(id,6,'Enter Universe'); SetHelpText(id,7,'Enter DMX Address '); SetHelpText(id,8,'Convert DMX address to 3 digits. Example: 45 = 045'); result := RunLayoutDialog(id, Dialog_Handler); if result = 2 then Mydialog := false else Mydialog := true; END; {Mydialog} begin {main} if Mydialog(gValue,gAddr,gUniv) then begin message('Universe is ',gUniv,' / Address is ',gAddr,' / Checkbox value is ',gValue); end; end; {main} run(AssignInfo); Quote Link to comment
MullinRJ Posted February 11, 2017 Share Posted February 11, 2017 Hello Sam, You need to make IUniv a variable parameter in your function declaration of MyDialog(). change: function Mydialog(var lValue, lAddr :integer; lUniv :STRING) :boolean; to: function Mydialog(var lValue, lAddr :integer; var lUniv :STRING) :boolean; That's it. Raymond Quote Link to comment
SamIWas Posted February 11, 2017 Author Share Posted February 11, 2017 15 minutes ago, MullinRJ said: Hello Sam, You need to make IUniv a variable parameter in your function declaration of MyDialog(). change: function Mydialog(var lValue, lAddr :integer; lUniv :STRING) :boolean; to: function Mydialog(var lValue, lAddr :integer; var lUniv :STRING) :boolean; That's it. Raymond Holy crap. That did it. I would have never figured that out. Didn't realize you had to declare VAR again for each new type. Weird that the compiler doesn't catch that. Thank you so much everyone! I think I have the basics down and can get started making some new dialogs! Quote Link to comment
MullinRJ Posted February 11, 2017 Share Posted February 11, 2017 8 hours ago, SamIWas said: Weird that the compiler doesn't catch that. Actually, it's not an error, but a feature of the language. It's how you declare passed variables to be local or modifiable. If you don't use the "var" before a variable group, then a copy of the variables are used when the function executes and no changes made to them are returned. When you use "var" before a variable group, then any change you make to them in the routine is returned. Consider the following: procedure Example (with a, b, and c as passed parameters); Begin a := a + 1; b := 3*a + 1; c := a^2 + 2*a*b + c; End; If your procedure declaration is: procedure Example (a, b, c :integer); then no changes to a, b, or c are returned. If your procedure declaration is: procedure Example (var a, b, c :integer); then any changes to a, b, and c are returned; If you only want changes to c returned: procedure Example (a, b :integer; var c :integer); then a and b are local parameters and c will be returned. Of course you could also make "Example" a function and return c as the result. But if you want to return two variables, this would be one way to do it: procedure Example (a :integer; var b, c :integer); Now changes to b and c are returned and a remains unchanged when "Example" terminates. HTH, Raymond Quote Link to comment
SamIWas Posted February 11, 2017 Author Share Posted February 11, 2017 Thanks! Nice info! Finished off my first one last night and it works perfectly. Now to start re-writing all my scripts for 2017. Quote Link to comment
koenr Posted October 11, 2023 Share Posted October 11, 2023 (edited) On 1/27/2017 at 1:39 AM, JBenghiat said: I really don't use it much, but that would be the place to do things like save the dialog position. There is also a ResizeDilogC for when the user has resized the dialog. -Josh Hey, @JBenghiat I want to set the deafult position of a dialog but i don't know in wich part of dialog handler i need to do this? I see a lot about the "kEventDialogPrep" but what item is this? Hope you can help me out here 😄 Edited October 11, 2023 by koenr Quote Link to comment
MullinRJ Posted October 12, 2023 Share Posted October 12, 2023 Hello @koenr, I always save my dialog's position when I exit the event loop, either when item==kOK, or when item==kCancel. As long as you are in the dialog the user can move it, so it doesn't make sense to save the position until the dialog handler is done and things are shutting down. As to your second question, "I see a lot about the "kEventDialogPrep" but what item is this?", I have no idea. Where do you typically see this? The value kEventDialogPrep = 9 looks like a user defined dialog item. Raymond Quote Link to comment
koenr Posted October 12, 2023 Share Posted October 12, 2023 Hello @MullinRJ, I think you missunderstood me but still thanks for your opinion. I'm pretty new to the dialog boxes but i begin to get the hang of it. I tried a lot of thing yesterday evening and i found a solution to my problem. To explain again what the problem was: i made a plugin that zooms to objects one by one and puts those in the midle of the screen. Than i must enter a specific value for that object in my dialogbox (wich appears in the middle of the screen aswell) Now my dialog opens at the topleft corner of my screen so i can see the object that is selected. In vectorscript there is such a thing as: BEGIN CASE item OF SetupDialogC: BEGIN SetLayoutDialogPosistion(dialog, x, y); END; 1: {OK} BEGIN ............ END ................ This constant value "SetupDialogC" doesn't work if you write your code in Python like i do. I needed the integer that would result in this event like "1 → OK". Solution was: Get rid of that case and write all your preparation in the begining of the dialoghandler. Correct me if this is a wrong way of doing things but it seems to work. def DialogHandler(item, data): _b = vs.SetLayoutDialogPosition(dialog, 200, 150) if item == kselect: vint1 = 0 # p = vs.GetPt() # h = vs.PickObject(p) # vint1 = int(vs.GetDimText(h)) vs.SetEditInteger(dialog, kint1, vint1) if item == kOK: _b, rundialog.maatlijn = vs.GetEditInteger(dialog, kint1) return item Quote Link to comment
MullinRJ Posted October 12, 2023 Share Posted October 12, 2023 Hello @koenr, It would not be the first time I misread something, and I suspect it will not be the last. Sorry, I thought you wanted to SAVE the dialog's position, not SET its position. My bad! If you do both you can have the dialog open where you left it last time. That is what I typically do. To have persistent parameters, write the positions to an XML file that VW maintains using vs.SetSavedSetting(category, setting, value) and vs.GetSavedSetting(category, setting) return (boolean, value). You create the category and the setting strings as they pertain to your script. You can save lots of things in the saved settings file and the values will persist between open files and even between VW sessions (assuming VW shuts down properly and does not crash.) It is always advised not to store critical data in the settings file as it is meant for convenience, not security. If you are interested in trapping the kSetupDialogC item, use kSetupDialogC=12255 in your constant declarations. This event# is where you want to position your dialog, and it will only happen once, so if you move the dialog it won't jump back with your next key or mouse event. There is another constant but it is little used, kSetdownDialogC=12256 and it will be generated just before the dialog closes. You could put cleanup code there, but I have never found a need to use it. Still, it's nice to know it exists. You are correct, there is no case statement equivalent in Python, so you need to use a series of if statements, as you have done, or if / elif / elif / ... / else. They are functionally the same as the Pascal case statement. You're on the right path. HTH, Raymond Quote Link to comment
koenr Posted October 12, 2023 Share Posted October 12, 2023 (edited) @MullinRJ That number there → 12255! That was the one i could not find! Thanks again for your help! 😄 I will look into that savedsettings function, it looks pretty good indeed 😉 Edited October 12, 2023 by koenr Quote Link to comment
MullinRJ Posted October 12, 2023 Share Posted October 12, 2023 @koenr, You're welcome. Here is a very rudimentary Python script to save dialog's position. Lightly tested. Modify it any way you like. kOK = 1 kCancel = 2 kSetupDialogC = 12255 dialogName = "DUMMY DIALOG" scriptName = "myScriptName" def SaveDialogPos(dlogID): (_b, X1, Y1, X2, Y2) = vs.GetLayoutDialogPosition(dlogID) if _b: vs.SetSavedSetting(scriptName, 'PosX', vs.Concat(X1)) vs.SetSavedSetting(scriptName, 'PosY', vs.Concat(Y1)) pass def SetDialogPos(dlogID): (_b, defaultX, defaultY, dummyX, dummyY) = vs.GetLayoutDialogPosition(dlogID) (_b, S) = vs.GetSavedSetting(scriptName, 'PosX') if _b: X = vs.Str2Num(S) (_b, S) = vs.GetSavedSetting(scriptName, 'PosY') if _b: Y = vs.Str2Num(S) _b = vs.SetLayoutDialogPosition(dlogID, X, Y) else: _b = vs.SetLayoutDialogPosition(dlogID, defaultX, defaultY) else: _b = vs.SetLayoutDialogPosition(dlogID, defaultX, defaultY) pass def DialogHandler(item, data): if item == kSetupDialogC: SetDialogPos(dlogID) elif item == kOK: SaveDialogPos(dlogID) elif item == kCancel: SaveDialogPos(dlogID) vs.SysBeep() return item ### MAIN ### dlogID = vs.CreateLayout(dialogName, False, "OK", "Cancel") vs.CreateStaticText(dlogID, 10, 'WUMPUS', 30) vs.SetFirstLayoutItem(dlogID, 10) result = vs.RunLayoutDialog(dlogID, DialogHandler) Raymond 1 1 Quote Link to comment
JBenghiat Posted October 12, 2023 Share Posted October 12, 2023 In theory, all VectorScript constants are available in the vs namespace, so vs.SetupDialogC should work. 4 hours ago, MullinRJ said: There is another constant but it is little used, kSetdownDialogC=12256 and it will be generated just before the dialog closes. You could put cleanup code there, but I have never found a need to use it. Still, it's nice to know it exists. This event runs for both the ok and cancel case, so in Raymond’s example above, you wouldn’t need to call SaveDialogPos() in two different cases. 6 hours ago, koenr said: Solution was: Get rid of that case and write all your preparation in the begining of the dialoghandler. Correct me if this is a wrong way of doing things but it seems to work. Vectorworks calls the dialog handler for every user interaction with the dialog, so it can run dozens of times with each dialog session. That means that you will be constantly repositioning the dialog, and if the user drags the dialog to a new position, it will snap back to the coded location. Quote Link to comment
Recommended Posts
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.