Jump to content
Developer Wiki and Function Reference Links ×

MultiLine Text Box in a PIO


Recommended Posts

Hey folks

 

I've created a plug in object that has several definitions.  I need to create multi line text within the PIO somehow to be referenced by a Data Tag (like how a callout uses a multiline text box).  I've hit a wall in my knowldge of PIO creation and vectorscript.  Anyone have any ideas?

 

Thanks

Link to comment
3 hours ago, Marc Powell said:

I've created a plug in object that has several definitions.  I need to create multi line text within the PIO somehow to be referenced by a Data Tag (like how a callout uses a multiline text box).

 

This might help:

 

            CreateText (TxtStr1);     (Creates block of text)
            TxtHndTmp := LNewObj;     (Assigns the block of text to a handle)
            SetTextWrap (TxtHndTmp,true);     (Tells the text block to wrap)
            SetTextWidth (TxtHndTmp, PBlkWdth);     (Tells the block of text how wide it is to be)

 

Link to comment

Thanks, Andrew

 

I don't need to actually display the text, just enter it into the OIP so it exists to be referenced (like a text line in a record format, but with the ability to enter data with carriage returns) by a data tag or the data manager.  The issue is getting the input.

 

I've been working on this for a couple days now and I've created the plug-in object and have created a dialogue box that will accept the amount of text I need to accept (with the dialog builder), but I'm now having trouble marrying the two and assigning it to a "name".

 

What I'm trying to do is draw a plug in object that represents a cable drop or a cable break (done and it works) and add fields in the OIP that would show up on different sheets or a truss tape (which I've got all of them except a text box that will allow for carriage return).  I can't get a parameter to show up in the OIP that will allow for multiple lines of text, so I am trying to get a dialog box that will allow me to enter text that I can then create data tag styles to refer to the text.

 

Make sense?  Any advice would be more than welcome.

 

Thanks

Link to comment

@Marc Powell What do you know about Event Enabled plug-ins?  I was able to fab up this quick example of what you might be looking for.  When you press the button, it opens a dialog box with a multi-line text box.  When you press OK, it passes the contents of that box back to the PIO's parameter using a combination of GetMultilineText and ResetObject.  I'm attaching the plug-in itself and have the code pasted below (don't judge, I wrote it in maybe 10 minutes so nothing is annotated).  It is a Point PIO with a single parameter, called "text" and is set to Event-Enabled.

 

image.thumb.png.5cae1e7928a46ee1c09983bb33a88bb7.png

 

PROCEDURE MultilineTest;

CONST

	kResetEventID = 3;
	kObjXPropHasUIOverride = 8;
	kWidgetButton = 12;
	kObjOnInitXProperties = 5;
	kObjOnObjectUIButtonHit = 35;
	kButton1ID = 3000;
	
	kFontEnabled = 800;
	
VAR

	objName:STRING;
	objHd,recHd,wallHd:HANDLE;
	text:STRING;
	theEvent,theButton,dialog,layoutDialog:LONGINT;
	result:BOOLEAN;

FUNCTION DrawDialog(DName:STRING) : LONGINT;

	CONST
	
		kTextWidth = 50;
		kTextHeight = 20;

	VAR
	
		dia:LONGINT;
		
	BEGIN
		dia:=CreateLayout(DName,FALSE,'OK','Cancel');
		
		CreateEditTextBox(dia,11,'',kTextWidth,kTextHeight);
		
		SetFirstLayoutItem(dia,11);
		
		DrawDialog:=dia;
	END;

PROCEDURE DialogHandler(VAR item,data:LONGINT);

	BEGIN
		CASE item OF
			SetupDialogC:
				BEGIN
					IF(text <> '') THEN SetItemText(dialog,11,text);
				END;
			1:
				BEGIN
					GetMultilineText(dialog,11,text);
					SetRField(objHd,GetName(recHd),'text',text);
					ResetObject(objHd);
				END;
			2:
				BEGIN
				END;
		END;
	END;

BEGIN
	text:=Ptext;
	
	IF GetCustomObjectInfo(objName,objHd,recHd,wallHd) THEN SetObjectVariableBoolean(objHd,kFontEnabled,TRUE);
	
	vsoGetEventInfo(theEvent,theButton);
	
	CASE theEvent OF
		kObjOnInitXProperties:
			BEGIN
				result:=SetObjPropVS(kObjXPropHasUIOverride,TRUE);
				result:=SetObjPropVS(kWidgetButton,TRUE);
				result:=vsoInsertAllParams;
				
				result:=vsoAppendWidget(kWidgetButton,kButton1ID,'Edit Text',0);
			END;
		kObjOnObjectUIButtonHit:
			BEGIN
				CASE theButton OF
					kButton1ID:
						BEGIN
							dialog:=DrawDialog('Set Text');
							layoutDialog:=RunLayoutDialog(dialog,DialogHandler);
						END;
				END;
			END;
		kResetEventID:
			BEGIN
				Locus(0,0);
				IF(text <> '') THEN CreateText(text);
			END;
	END;
END;

Run(MultilineTest);

 

The plug-in object attached to this message can be found in the Research and Development category of the Workspace Editor and will work on any version of Vectorworks 2019 or newer.

Multiline Test.vso

Link to comment

@Jesse CogswellI'm pretty new to anything more than basic vectorscript and haven't done any real coding in a couple of decades (even then, it was very rudimentary).  That said - THIS HELPED IMMENSELY.  I was able to take the small bit of code I wrote for the PIO and integrate your code into it and am now getting exactly what I wanted to accomplish.  Thanks a ton.  I'm still working on applying attributes to the line work in the PIO and I'm looking to have it draw two different ways depending on which selection is in a particular parameter.  I'll share the object when I get it to a somewhat final stage, but this was a huge help.

 

THANK YOU!

 

By the way - how do you like your ZenBook Duo?  I bought the same model several months ago and have been loving it.  I have an odd issue where my pallets don't want to move down to the smaller screen when I have VW open on the main display.  I'll drag them down and as soon as they hit the bottom bound of the primary display, they just won't move any further.  The cursor gets down there, but the window just won't move past the bottom of the primary.  It's odd.

Link to comment

I love my Zenbook Pro Duo.  I was interested ever since Asus showed off the original one with the non-hinged bottom screen.  When my Surface Book 2 was finally no longer powerful enough for what I needed and was looking at upgrades, the Asus was the same price as a Surface Book 3 and was much more powerful, so I pulled the trigger.  Always having a second display handy is life changing.  90% of the time, I just have Notepad++ running on it, keeping track of all of the notes I have on my various projects.  But I also do a fair bit of lighting console programming, and the second screen has been great for placing direct selects (basically extra buttons for things like macros, groups, and color palettes).

 

I have never tried to move Vectorworks palettes down onto it.  Vectorworks gets really cranky if you move palettes around to monitors with different scale factors and/or resolutions, so I can only imagine the trouble it's giving you.  I do all of my drafting on a big 42" 4K monitor scaled at 100%, so the VW interface doesn't get in the way of anything and I don't feel the need to move palettes outside of the VW application window.  But I just did a little test with VW2023 and was able to move palettes down, but I wasn't able to place them near the top of the bottom display without the title bar snapping up to the bottom of the top display.

 

image.thumb.png.b00180a7ba5d5ad93f92a789c83582d9.png

Link to comment

Yep...  my pallets do the same thing.  I'll bet you are correct - it has to do with two separate destinations that have different scaling.  I do an OK amount of programing now a days, and it works great for setting up a show before I get onsite.  I've pre patched and set groups and such in several airports on my way out to gigs and that touchscreen works very well as a software control surface.  Also, its great for when I'm using Vision at home for small test modules.  Super quick setup rather than having to get a console in the office.

 

As for this PIO I'm putting together - it works well in it's current state, but I moved around the parameters in the parameters hierarchy to display in a certain in the OIP, and it seems like the text that is entered in the dialogue box only updates the text in the first text parameter in the list from a hierarchical standpoint.  I've attached the .vso to this post and here are the parameters as they currently stand:

image.png.18018201b734f8add7441b367426fc3f.png

 

Also, here is the code:

 

Quote

 

PROCEDURE CableDropBreak;

CONST

    kResetEventID = 3;
    kObjXPropHasUIOverride = 8;
    kWidgetButton = 12;
    kObjOnInitXProperties = 5;
    kObjOnObjectUIButtonHit = 35;
    kButton1ID = 3000;
    
    kFontEnabled = 800;

VAR

    LineVal,NLineVal,HalfLineVal,NHalfLineVal,OvalVal,NOvalVal,HalfOvalVal,NHalfOvalVal : REAL;
    BreakDrop:STRING;
    objName:STRING;
    objHd,recHd,wallHd:HANDLE;
    text:STRING;
    theEvent,theButton,dialog,layoutDialog:LONGINT;
    result:BOOLEAN;
    
FUNCTION DrawDialog(DName:STRING) : LONGINT;

    CONST
    
        kTextWidth = 50;
        kTextHeight = 20;

    VAR
    
        dia:LONGINT;
        
    BEGIN
        dia:=CreateLayout(DName,FALSE,'OK','Cancel');
        
        CreateEditTextBox(dia,11,'',kTextWidth,kTextHeight);
        
        SetFirstLayoutItem(dia,11);
        
        DrawDialog:=dia;
    END;

PROCEDURE DialogHandler(VAR item,data:LONGINT);

    BEGIN
        CASE item OF
            SetupDialogC:
                BEGIN
                    IF(text <> '') THEN SetItemText(dialog,11,text);
                END;
            1:
                BEGIN
                    GetMultilineText(dialog,11,text);
                    SetRField(objHd,GetName(recHd),'CableTextDT',text);
                    ResetObject(objHd);
                END;
            2:
                BEGIN
                END;
        END;
    END;

BEGIN
    text:=PCableTextDT;
    
    IF GetCustomObjectInfo(objName,objHd,recHd,wallHd) THEN SetObjectVariableBoolean(objHd,kFontEnabled,TRUE);
    
    vsoGetEventInfo(theEvent,theButton);
    
    CASE theEvent OF
        kObjOnInitXProperties:
            BEGIN
                result:=SetObjPropVS(kObjXPropHasUIOverride,TRUE);
                result:=SetObjPropVS(kWidgetButton,TRUE);
                result:=vsoInsertAllParams;
                
                result:=vsoAppendWidget(kWidgetButton,kButton1ID,'Cable Drop/Break Text',0);
            END;
        kObjOnObjectUIButtonHit:
            BEGIN
                CASE theButton OF
                    kButton1ID:
                        BEGIN
                            dialog:=DrawDialog('Contents');
                            layoutDialog:=RunLayoutDialog(dialog,DialogHandler);
                        END;
                END;
            END;
        kResetEventID:
            BEGIN
                
                {Remove Brackets to create text box as part of PIO}
                {Locus(0,0);
                IF(text <> '') THEN CreateText(text);}                
                {Define Variable Values}
                LineVal := POverallObjSize;
                NLineVal := 0 - POverallObjSize;
                HalfLineVal :=  LineVal / 2;
                NHalfLineVal :=  (0 - LineVal) / 2;
                OvalVal := (POverallObjSize/4)*3;
                NOvalVal := ((0 - POverallObjSize)/4)*3;
                HalfOvalVal := OvalVal / 2;
                NHalfOvalVal := (0 - OvalVal) / 2;

                {Draw Object}
                Oval(NHalfOvalVal, NHalfOvalVal, HalfOvalVal, HalfOvalVal);
                Move(HalfLineVal, HalfLineVal);
                Line(NLineVal, NLineVal);
                Move(0, LineVal);
                Line(LineVal, NLineVal);
                Move(NHalfLineVal, HalfLineVal);
                
            END;
    END;
END;

Run(CableDropBreak);

 


I thought I made an edit in your code that would pull the text from and update directly to 'CableTextDT', but that isn't the case currently.  Any ideas?  I'm sure I integrated the code incorrectly, but I can't figure out where I went wrong.

 

Thanks

Cable Break Test.vso

Link to comment

The code is working properly as far as I can tell.  When you press OK on the dialog box, the CableTextDT is updating properly, as seen in the OIP.  Your kResetEventID code currently isn't doing anything with the data (stored in the text variable).  If you want the text displayed, you will need to add a line to the tune of:

IF (text <> '') THEN CreateText(text);

 

image.thumb.png.5a688fa14161628193b0c6f4fd346d65.png

 

Handles were undoubtedly the hardest concept for me to wrap my head around.  All of my coding experience before Vectorscript was with object-oriented languages (Java and Python).  With an OO language, you would define an object and all needed subroutines (such as get/set commands) as methods.  Once an object is defined, you could assign it to a variable.  As an example, you could have something like rect1 = Rectangle(<width>,<height>).  The variable rect1 is now defined as a Rectangle object.  So if you wanted to get the width again for some computation, you would use width = rect1.GetWidth().  Because Vectorscript / Pascal is not object-oriented, you instead use handles as a way to assign objects to variables.  Most of the time in VS, you need to create the object first, then use something like LNewObj to store the object's handle into a variable for use later.  If you are immediately making changes to an object (such as formatting your text in the above example), you don't need to store the object in a handle because you can keep using LNewObj until you create another object.  But if you need to access the text later in the code, it is best to store it as a handle.

 

One thing to watch out for when using LNewObj on text objects is that if the text object is empty, it won't return a handle.  So any formatting you try to do on an empty text object will instead affect the object created before the text.  So I always use an IF statement to test the string to make sure it's not empty before creating and formatting a text object.

 

One of the most important handles when making Plug-in Objects is the currently executing plug-in's handle (named objHd in my code) since that's what you use to update the parameters such as your CableTextDT parameter using SetRField.  To get the handle, you use GetCustomObjectInfo to return the name of the PIO (objName, Cable Break Test in your example), the handle of the current PIO object (objHd), a handle to the parametric record (recHd), and the wall the PIO is inserted in (wallHd for PIOs that can be inserted in walls).  This function returns a boolean (TRUE if successful), so I usually combine it with a SetObjectVariableBoolean(objHd, 800, TRUE) which enables all text in the PIO to inherit from the Text menu of the PIO object itself.

 

As for event enabled plug-ins, I have an example object that has all of the necessary code commented out so that you can see what it is doing and why it is needed.  Have a look if you want a better understanding of how to handle event enabled plug-ins, so that you can add things like double-click behavior and collapsing sections of the Object Info Palette:

 

Link to comment

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
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...