Jump to content
Developer Wiki and Function Reference Links ×

Script Palette Screen Orginization


Recommended Posts

Hello All:

Would anyone know if it would be possible to script a script to organize script palettes in the GUI.  Manytimes they end up all over my workspace but it would be nice to have them stacked in an instant.  

 

Instead of this

 

image.thumb.png.0f712c5156ce6ee56f18b48dc21be1fb.png

 

I would like this. 

image.png.299bc889f1445ca49dd10eff85c16829.png

  • Like 1
Link to comment
  • 1 month later...

I can confirm Pat and Josh's comments.

 

IMHO, VW's palette control is a real weak spot. Moving from a 3-monitor setup (laptop/32" display/27" display is our standard setup for all staff) to "laptop only" scrambles everything. When plugging back into my dock - powering all displays - the OIP, Navigation palette, Resource Browser, Tool palette(s), and any custom script palettes need to to be moved back to their original position.

 

Time consuming, and extremely frustrating. Also, the "Save Palette Position" command is useless. I remove it from our workspaces so as to not give staff false hope...

This should be a simple fix. Screen parameters can be saved and restored (other Mac apps do this flawlessly). Can someone from VW explain why this has been an issue since the early days of MC/VW?

 

 

V-G

--

Former Olympic Gymnast representing Kazakhstan........NOTTTT!!

 

  • Like 1
Link to comment
  • 2 weeks later...
Posted (edited)
On 8/11/2024 at 4:28 PM, DomC said:

have an own approach of organizing through one single palette, which have Favorite Scripts but can access to non-favorite scripts as well over the separator. Also there is a dialog, which allows to add and remove script to the favorite palette. Not finished yet (i will have to implement some presets to easy reset palettes to default)

This is so cool! 🤯 I wish I could read it, LOL, and I had a better understanding of how this works. 

 

I have a file folder filled with external scripts and I would love to be able to adapt your dialog box to invoke those scripts so I could just have one script built into the workspace and have all the scripts live in the workgroup folder.  That way they could be invoked from anywhere without having to add each one to the workspace or the drawing.  

Edited by The Hamma
Link to comment

I always try to code and comment in in english (anyway the code is not good documented on this prototype script). However this is a good idea to access to the external resource and even not copy the script resource on the working document. The steps would be:

1. Read Workgroup folder in the Windows Registry or the Macintosh Application Support. Which can be done somewhere in this forum there is a workflow to read this path.
2. Adapt the script (The Starter Palette is just one column, if you have over hundred script it will fill up the screen, so this maybe has to by changed to dynamically create more columns if needed)
3. You could use the starter Script from my example.



 



class vssmPaletteRunner():
	dialog_dict = {}
	def run_palette(st_palette_name = 'ArgumentPalettenname', exclude_palettes=['ST Script Module'], res_path = ''):

		listID, numItems = vs.BuildResourceListN(49, res_path)#Symbols
		id_dict = {}
		dialog_dict = {}
		
		res_names = []
		res_dict = {}
		for i in range(numItems):
			res_name = vs.GetNameFromResourceList(listID, i)
			if res_name != '':				
				res_names.append(res_name)
				res_dict[res_name] = i


		dialog_dict['res_names'] = res_names
			
				
		def dialog_main():
			def CreateDialog():


				dialog = vs.CreateLayout( 'Scripte Schnellzugriff', False, 'OK', 'Abbrechen')

				last_item_id = 10
				act_item_id = last_item_id + 1
				vs.CreateStaticText( dialog, act_item_id, 'Klicke auf die gewünschte \rFunktion.\r', -1 )
				#vs.SetStaticTextColorN( dialog, act_item_id, 2)
				vs.SetFirstLayoutItem( dialog, act_item_id )

				
				for res_name in dialog_dict['res_names']:
					last_item_id = act_item_id
					act_item_id += 1
					fill_number = 55 - len(res_name)
					fill_string = ' ' * fill_number
					#vs.AlrtDialog(str([last_item_id, act_item_id, res_name]))
					#vs.CreatePushButton( dialog, act_item_id, res_name + fill_string)
					#vs.CreatePushButton( dialog, act_item_id, ' ' * 50)
					vs.CreateStaticText(dialog, act_item_id, res_name, -1)
					vs.SetItemClickable(dialog, act_item_id, True)
					#vs.AlignItemEdge( dialog, act_item_id, 3, 1, 1 )
					#vs.CreateStandardIconControl(dialog, act_item_id, 0)
					vs.SetBelowItem( dialog, last_item_id, act_item_id, 0, 0 )
					if 'Elektro' in res_name:
						#res = vs.GetColorButton(dialog, act_item_id)
						vs.SetColorButton(dialog, act_item_id, 65000,0,0)
						#res = vs.GetColorButton(dialog, act_item_id)


					last_item_id = act_item_id
					id_dict[str(act_item_id)] = res_name

				
				last_item_id = act_item_id
				act_item_id += 1
				vs.CreateStaticText(dialog, act_item_id, '  ', -1)
				vs.SetBelowItem( dialog, last_item_id, act_item_id, 0, 0 )
						
				return dialog

			# Sample dialog handler
			# Uncomment this code if you want to display the dialog

			def DialogHandler(item, data):

				if item == 12255: #Enter Dialog

					for key in id_dict:
						id = int(key)
						vs.SetItemClickable(dialog, id, True)
						#vs.SetItemText(dialog, id, id_dict[key]) # works also
						#vs.SetControlText(dialog, id, id_dict[key]) #crash
						#vs.AlignItemEdge( dialog, id, 3, 1, 1 )
						vs.SetStaticTextColorN( dialog, id, 2) #does nothing
						#vs.SetColorButton(dialog, id, 62000,0,0) #does nothing
			
				if 10 < item < 10000:
					dialog_dict['func_id'] = str(item)
					return 1
						
				if item == 1:
					pass

			result = False
			dialog = CreateDialog()

			if vs.RunLayoutDialogN(dialog, DialogHandler, False) == 1:
				result = True

			return result



		result = dialog_main()





		if result:
			func_id = dialog_dict.get('func_id', False)
			
			if func_id:
				script_name = id_dict[func_id]
				
				script_id = res_dict[script_name]
				#vs.AlrtDialog(str([script_name, func_id, script_id]))
				
				try:
					existing_res = vs.GetObject(script_name)
					if existing_res != vs.Handle(0):
						vs.DelObject(existing_res)
						
				except:
					pass
					
						
				new_res = vs.ImportResToCurFileN(listID, script_id, None)
				vs.PythonExecute(str(vs.GetScriptResource(script_name)[1]))
				
				
				
				vs.DelObject(new_res)
				#GetScriptResource

				
vssmPaletteRunner.run_palette(res_path = '/Users/dominiquecorpataux/Downloads/test2.vwx')


I modified a little:
1. BuildResourceListN with a path to the file
2. Deleted the part with the palette-name-filter

That is is defined as a class is not necessary for single use. Just is necessary if you want to call the function outside in another script to path values between different scripts.
And the fullPath is the path to the workgroup folder Script Document. You can test with a single path to your script document.

Two open things:
1. I think the script have to be temporary imported to run and deleted after which looks not very elegant
2. "vs.PythonExecute(str(vs.GetScriptResource(script_name)[1]))" runs a python script. I do not know how to run pascal code here. 
 

Link to comment
5 hours ago, DomC said:

Two open things:
1. I think the script have to be temporary imported to run and deleted after which looks not very elegant
2. "vs.PythonExecute(str(vs.GetScriptResource(script_name)[1]))" runs a python script. I do not know how to run pascal code here.

I was thinking more using this to run external pyton script that was in a text file. 

import _main
	_main.execute()

https://developer.vectorworks.net/index.php/Python_Sample_Menu_Command

 

Link to comment

Aha, then you could use this one. I like this idea. Also for myself i have tons of scripts and this one can help execute them fast with a menu command and one single click.

Thinkable ToDoes:
- What would be cool, a palette with a searchable list browser or similar. I was never able to create propper popup with search bar
- maybe support for sub-folders in module directory

 

import os
import importlib

dialog_dict = {}

def get_py_files(directory):
    # Traverse the directory tree and collect all .py files without their extensions
    py_files = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith(".py"):
                # Add the file name without the .py extension to the list
                py_files.append(os.path.splitext(file)[0])
    return py_files

def run_palette(directory=''):
    # Set the directory to search for Python scripts
    vs.PythonSetSearchPath(directory)  # Set the search path for Python modules
    dialog_dict['res_names'] = get_py_files(directory)  # Get all .py files
    id_dict = {}

    def dialog_main():
        def CreateDialog():
            # Create the main dialog layout
            dialog = vs.CreateLayout('Scripte Schnellzugriff', False, 'OK', 'Abbrechen')

            last_item_id = 10
            act_item_id = last_item_id + 1
            vs.CreateStaticText(dialog, act_item_id, 'Klicke auf die gewünschte \rFunktion.\r', -1)
            vs.SetFirstLayoutItem(dialog, act_item_id)

            # Create static text items for each script name
            for res_name in dialog_dict['res_names']:
                last_item_id = act_item_id
                act_item_id += 1
                vs.CreateStaticText(dialog, act_item_id, res_name, -1)
                vs.SetItemClickable(dialog, act_item_id, True)
                vs.SetBelowItem(dialog, last_item_id, act_item_id, 0, 0)
                id_dict[str(act_item_id)] = res_name

            # Add a spacer at the end
            last_item_id = act_item_id
            act_item_id += 1
            vs.CreateStaticText(dialog, act_item_id, '  ', -1)
            vs.SetBelowItem(dialog, last_item_id, act_item_id, 0, 0)

            return dialog

        def DialogHandler(item, data):
            if 10 < item < 10000:
                dialog_dict['func_id'] = str(item)
                return 1

        dialog = CreateDialog()
        result = vs.RunLayoutDialogN(dialog, DialogHandler, False) == 1

        return result

    result = dialog_main()

    if result:
        func_id = dialog_dict.get('func_id', False)
        func_name = id_dict[func_id]

        if func_id:
            # Dynamically import and execute the selected module
            module = importlib.import_module(func_name)

directory_with_pytho_modules '/Volumes/SD_Card/Dropbox/Entwicklung/python_scripte'
# Run the palette function to start the dialog
run_palette(directory = directory_with_python_modules)


 

  • Like 1
Link to comment

Ob

2 hours ago, DomC said:

Aha, then you could use this one. I like this idea. Also for myself i have tons of scripts and this one can help execute them fast with a menu command and one single click.

 

Obviously you are very fluent in Python.  Many of my scripts are also in Vectorscript.  I have not been able to find a command to run an external vectorscript other than the "DoMenuTextByName('Run Script',00);" but that requires you to choose the script in a dialog box.  

 

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