User Tools

Site Tools


Simple Popup Menu Dialog

Summary

Below is an example demonstrating how to construct a simple dialog with a button, name it so its position is stored uniquely from other script constructed dialogs, and react to a user clicking the button by presenting a popup menu.

API Areas of Interest

Example

Simple_PopupMenu_Dialog.dsa
// DAZ Studio version 4.15.0.16 filetype DAZ Script
 
// Define an anonymous function;
// serves as our main loop,
// limits the scope of variables
(function(){
 
	// Initialize 'static' variable
	var s_wMenuClicked = null;
 
	/*********************************************************************/
	// String : A function for retrieving a translation if one exists
	function text( sText )
	{
		// If the version of the application supports qsTr()
		if( typeof( qsTr ) != "undefined" ){
			// Return the translated (if any) text
			return qsTr( sText );
		}
 
		// Return the original text
		return sText;
	};
 
	/*********************************************************************/
	// Point : A function for getting the global cursor position
	function globalCursorPos()
	{
		// Return the global cursor position
		return (new Point).cursorPos();
	};
 
	/*********************************************************************/
	// void : A function for creating a popup menu
	function addPopupMenu( wParent )
	{
		// Return a popup menu
		return new DzPopupMenu( wParent );
	};
 
	/*********************************************************************/
	// Number : A function for creating a popup menu item
	function addPopupMenuItem( wMenu, pixIcon, sText, nId, nIndex )
	{
		// If a menu was not provided
		if( !wMenu ){
			// Return invalid
			return -1;
		}
 
		// If text was not provided or is the wrong type
		if( typeof( sText ) != "string" ){
			// Initialize
			sText = "";
		}
 
		// If an id was not provided or is the wrong type
		if( typeof( nId ) != "number" ){
			// Initialize
			nId = -1;
		}
 
		// If an index was not provided or is the wrong type
		if( typeof( nIndex ) != "number" ){
			// Initialize
			nIndex = -1;
		}
 
		// Get whether or not we are using deprecated API - < 4.15.0.16
		var bDeprecated = typeof( wMenu.insertTextItem ) != "function";
 
		// If we have a pixmap, and we have text, and we are not using deprecated API
		if( pixIcon && !sText.isEmpty() && !bDeprecated ){
			// Insert the item and return the id
			return wMenu.insertItem( pixIcon, sText, nId, nIndex );
		// If we do not have a pixmap, but we have text
		} else if( !pixIcon && !sText.isEmpty() ){
			// If we are not using deprecated API
			if( !bDeprecated ){
				// Insert the item and return the id
				return wMenu.insertTextItem( sText, nId, nIndex );
			// If we are using deprecated API
			} else {
				// Insert the item and return the id
				return wMenu.insertItem( sText, nId, nIndex );
			}
		// If we have a pixmap, but we do not have text
		} else if( pixIcon && sText.isEmpty() ){
			// If we are not using deprecated API
			if( !bDeprecated ){
				// Insert the item and return the id
				return wMenu.insertPixmapItem( pixIcon, nId, nIndex );
			// If we are using deprecated API
			} else {
				// Insert the item and return the id
				return wMenu.insertItem( pixIcon, nId, nIndex );
			}
		}
 
		// Return an invalid id
		return -1;
	};
 
	/*********************************************************************/
	// Object<id,widget> : A function for creating a submenu on a popup menu
	function addPopupSubMenu( wMenu, pixIcon, sText, nId, nIndex )
	{
		// If a menu was not provided
		if( !wMenu ){
			// Return invalid
			return { "id": -1, "widget": null };
		}
 
		// If text was not provided or is the wrong type
		if( typeof( sText ) != "string" ){
			// Initialize
			sText = "";
		}
 
		// If an id was not provided or is the wrong type
		if( typeof( nId ) != "number" ){
			// Initialize
			nId = -1;
		}
 
		// If an index was not provided or is the wrong type
		if( typeof( nIndex ) != "number" ){
			// Initialize
			nIndex = -1;
		}
 
		// Declare working variables
		var wSubMenu;
		var oSubMenu;
 
		// If executed in 4.22.1.149 or newer
		if( App.version64 >= 0x0004001600010095 ){
			// Create a submenu
			wSubMenu = addPopupMenu( wMenu );
 
			// Use the DzPopupMenu
			oSubMenu = wSubMenu;
		// If executed in 4.15.0.16 or newer
		} else if( typeof( wMenu.insertTextSubmenuItem ) == "function" ) {
			// Create a submenu
			wSubMenu = addPopupMenu( wMenu );
 
			// Use the QMenu wrapped by DzPopupMenu
			oSubMenu = wSubMenu.getWidget();
		}
 
		// Initialize
		var nMenuId = -1;
 
		// If we have a submenu
		if( wSubMenu && oSubMenu ){
			// If we have a pixmap, and we have text
			if( pixIcon && !sText.isEmpty() ){
				// Insert the submenu, capture the id
				nMenuId = wMenu.insertSubmenuItem( pixIcon, sText, oSubMenu, nId, nIndex );
			// If we do not have a pixmap, but we have text
			} else if( !pixIcon && !sText.isEmpty() ){
				// Insert the submenu, capture the id
				nMenuId = wMenu.insertTextSubmenuItem( sText, oSubMenu, nId, nIndex );
			// If we have a pixmap, but we do not have text
			} else if( pixIcon && sText.isEmpty() ){
				// Insert the submenu, capture the id
				nMenuId = wMenu.insertPixmapSubmenuItem( pixIcon, oSubMenu, nId, nIndex );
			}
		}
 
		// Return an object with the submenu and id in the parent menu
		return { "id": nMenuId, "widget": wSubMenu };
	};
 
	/*********************************************************************/
	// void : A function for handling a menu item being clicked;
	// the 'this' object is assumed to be a DzPopupMenu object
	function handlePopupMenuItemClicked()
	{
		// Capture the menu containing the item that was clicked
		s_wMenuClicked = this;
	};
 
	/*********************************************************************/
	// void : A function for handling the menu being requested;
	// the 'this' object is assumed to be a DzPushButton object
	function handleButtonClicked()
	{
		// Create a pixmap to use as an icon
		var pixNone = new Pixmap( App.getResourcesPath() + "/images/icons/whatsthissmallicon.png" );
 
		// Create a menu
		var wMenu = addPopupMenu( this );
 
		// If executed in 4.15.0.16 or newer
		var bCanCount = typeof( wMenu.numItems ) == "function";
 
		// Initialize
		var nMenuId = -1;
		var nMenuIdx = bCanCount ? wMenu.numItems() : 0;
 
		// This first item demonstrates how to modify the
		// text and/or pixmap of an item, the creation of
		// other items demonstrate the typical statements
 
		// If executed in a build older than 4.15.0.16
		if( typeof( wMenu.setText ) != "function" ){
			// Create a pixmap item
			nMenuId = wMenu.insertItem( pixNone, nMenuIdx, nMenuIdx );
			// Modify the text
			wMenu.changeItem( nMenuId, text( "<None>" ) );
			// Clear the pixmap for the item
			wMenu.changeItem( nMenuId, null );
		// If executed in 4.15.0.16 or newer
		} else {
			// Create a pixmap item
			nMenuId = wMenu.insertPixmapItem( pixNone, nMenuIdx, nMenuIdx );
			// Modify the text
			wMenu.setText( nMenuId, text( "<None>" ) );
			// If executed in a build older than 4.22.1.149
			if( typeof( wMenu.clearPixmap ) != "function" ){
				// Clear the pixmap for the item
				wMenu.setPixmap( nMenuId, Pixmap() );
			// If executed in 4.22.1.149 or newer
			} else {
				// Clear the pixmap for the item
				wMenu.clearPixmap( nMenuId );
			}
		}
 
		// If executed in 4.15.0.24 or newer
		var bCanConnect = typeof( wMenu.connectItem ) == "function";
 
		// If connections are possible
		if( bCanConnect ){
			// Connect the item to a function that handles it being activated
			wMenu.connectItem( nMenuId, wMenu, handlePopupMenuItemClicked );
		}
 
		// Visually separate the first item from the rest
		nMenuId = wMenu.insertSeparator();
 
		// Initialize
		var nSubMenuId = -1;
		var nSubMenuIdx = -1;
		var wSubMenu = null;
 
		// Update the menu index to the last position
		nMenuIdx = bCanCount ? wMenu.numItems() : nMenuIdx += 1;
 
		// Create a submenu
		var oSubMenu = addPopupSubMenu( wMenu, undefined, text( "Submenu 1" ), nMenuIdx, nMenuIdx );
		// If a submenu was created
		if( oSubMenu["id"] > -1 && oSubMenu["widget"] ){
			// Get the id of the menu item for the submenu
			nMenuId = oSubMenu["id"];
 
			// Get the submenu widget
			wSubMenu = oSubMenu["widget"];
 
			// Update the menu index to the last position
			nSubMenuIdx = bCanCount ? wSubMenu.numItems() : 0;
 
			// Create an item on the submenu
			nSubMenuId = addPopupMenuItem( wSubMenu, pixNone, text( "Sub One" ), nSubMenuIdx, nSubMenuIdx );
			// If connections are possible
			if( bCanConnect ){
				// Connect the item to a function that handles it being activated
				wSubMenu.connectItem( nSubMenuId, wSubMenu, handlePopupMenuItemClicked );
			}
 
			// Update the menu index to the last position
			nSubMenuIdx = bCanCount ? wSubMenu.numItems() : nSubMenuIdx += 1;
 
			// Create an item on the submenu
			nSubMenuId = addPopupMenuItem( wSubMenu, pixNone, text( "Sub Two" ), nSubMenuIdx, nSubMenuIdx );
			// If connections are possible
			if( bCanConnect ){
				// Connect the item to a function that handles it being activated
				wSubMenu.connectItem( nSubMenuId, wSubMenu, handlePopupMenuItemClicked );
			}
 
			// Update the menu index to the last position
			nSubMenuIdx = bCanCount ? wSubMenu.numItems() : nSubMenuIdx += 1;
 
			// Create an item on the submenu
			nSubMenuId = addPopupMenuItem( wSubMenu, pixNone, text( "Sub Three" ), nSubMenuIdx, nSubMenuIdx );
			// If connections are possible
			if( bCanConnect ){
				// Connect the item to a function that handles it being activated
				wSubMenu.connectItem( nSubMenuId, wSubMenu, handlePopupMenuItemClicked );
			}
 
			// Visually separate the submenu items in the main menu from the rest
			nMenuId = wMenu.insertSeparator();
		}
 
		// Update the menu index to the last position
		nMenuIdx = bCanCount ? wMenu.numItems() : nMenuIdx += 1;
 
		// Create an item on the menu
		nMenuId = addPopupMenuItem( wMenu, pixNone, text( "One" ), nMenuIdx, nMenuIdx );
		// If connections are possible
		if( bCanConnect ){
			// Connect the item to a function that handles it being activated
			wMenu.connectItem( nMenuId, wMenu, handlePopupMenuItemClicked );
		}
 
		// Update the menu index to the last position
		nMenuIdx = bCanCount ? wMenu.numItems() : nMenuIdx += 1;
 
		// Create an item on the menu
		nMenuId = addPopupMenuItem( wMenu, pixNone, text( "Two" ), nMenuIdx, nMenuIdx );
		// If connections are possible
		if( bCanConnect ){
			// Connect the item to a function that handles it being activated
			wMenu.connectItem( nMenuId, wMenu, handlePopupMenuItemClicked );
		}
 
		// Update the menu index to the last position
		nMenuIdx = bCanCount ? wMenu.numItems() : nMenuIdx += 1;
 
		// Create an item on the menu
		nMenuId = addPopupMenuItem( wMenu, pixNone, text( "Three" ), nMenuIdx, nMenuIdx );
		// If connections are possible
		if( bCanConnect ){
			// Connect the item to a function that handles it being activated
			wMenu.connectItem( nMenuId, wMenu, handlePopupMenuItemClicked );
		}
 
		// Get the current global cursor position
		var pntPos = globalCursorPos();
 
		// Define whether to use the width of the button
		// for the width of the main menu
		var bButtonWidth = false;
		// If we are using the width of the button
		if( bButtonWidth ){
			// Set the width of the main menu
			wMenu.minWidth = this.width;
		}
 
		// Define whether the menu should be positioned
		// immediately below and adjacent to the button
		var bDropdown = false;
		// If we are positioning the menu like a dropdown
		if( bDropdown ){
			// Set the position
			pntPos.y = this.globalY + this.height;
			pntPos.x = this.globalX;
		}
 
		// Declare working variable
		var nMenuWidth;
 
		// Define whether to use the right side of the menu
		// for justification/positioning
		var bRightJustify = false;
		// If we are using the right side of the menu
		if( bRightJustify ){
			// Get the width of the main menu
			nMenuWidth = wMenu.getWidget().sizeHint.width;
			// If we are positioning the menu like a dropdown
			if( bDropdown ){
				// Adjust the horizontal position
				pntPos.x += this.width - nMenuWidth;
			// If we are positioning the menu like a context menu
			} else {
				// Adjust the horizontal position
				pntPos.x -= nMenuWidth;
			}
		}
 
		// Cause the menu to display;
		// capture the id of the chosen item
		var nResultId = wMenu.exec( pntPos, 0 );
		// If no menu item was chosen
		if( nResultId < 0 ){
			// We are done...
			return;
		}
 
		// If we have a submenu, we cannot use the return value of exec() to look up
		// an item - the context of the value is all menus. If we do not have a
		// submenu, we have a simple scenario that allows us to use the return value
		// of exec() to look up an item - the context of the value is the menu.
 
		// If connections are possible, we have a submenu, and we know which menu has
		// the item that was clicked
		if( bCanConnect && wSubMenu && s_wMenuClicked ) {
			// Set the text of the button to the text of the clicked menu item
			this.text = s_wMenuClicked.text( nResultId );
			// Set the pixmap of the button to the pixmap of the clicked menu item
			this.pixmap = s_wMenuClicked.pixmap( nResultId );
		// If we do not have a submenu
		} else if( !wSubMenu ){
			// Set the text of the button to the text of the clicked menu item
			this.text = wMenu.text( nResultId );
			// Set the pixmap of the button to the pixmap of the clicked menu item
			this.pixmap = wMenu.pixmap( nResultId );
		}
	};
 
	/*********************************************************************/
	// If the application version is less than 4.15.0.16
	if( App.version64 < 0x0004000f00000010 ){
		// We are done...
		return;
	}
 
	// Get the current style
	var oStyle = App.getStyle();
 
	// Create a basic dialog
	var wDlg = new DzBasicDialog();
 
	// Get the wrapped widget for the dialog
	var oDlgWgt = wDlg.getWidget();
 
	// Set the title of the dialog
	wDlg.caption = "My Simple Test";
 
	// Strip the space for a settings key
	var sKey = wDlg.caption.replace( / /g, "" ) + "Dlg";
 
	// Set an [unique] object name on the wrapped dialog widget;
	// this is used for recording position and size separately
	// from all other [uniquely named] DzBasicDialog instances
	oDlgWgt.objectName = sKey;
 
	// Create a push button
	var wButton = new DzPushButton( wDlg );
	wButton.buttonTextFormat = DzWidget.AlignLeft | DzWidget.AlignVCenter;
	wButton.displayDownArrow = true;
	wButton.text = text( "<None>" );
	wButton.clicked.connect( wButton, handleButtonClicked );
 
	// Add the widget to the dialog
	wDlg.addWidget( wButton );
 
	// Get the minimum size of the dialog
	var sizeHint = oDlgWgt.minimumSizeHint;
 
	// Set the fixed size of the dialog
	wDlg.setFixedSize( sizeHint.width, sizeHint.height );
 
	// If the user accepts the dialog
	if( wDlg.exec() ){
		// Do... something
		print( "Use accepted:", wButton.text );
	// If the user rejects the dialog
	} else {
		// Do... something else
		print( "User cancelled." );
	}
 
// Finalize the function and invoke
})();