Dialog with List Browser

From Vectorlab
Jump to: navigation, search


A resizable dialog with a list browser, pull down menues, an enhanced pulldown menu, radio and check boxes. This is the basic example for the article List Browsers. With this dialog you can experiment the different results in List Browsers, according to their four basic features: Column Data Items, Control Type, Display Type, Column Owner. By Orso B. Schmid

The compiler mode is enabled automatically by this script. Remember to turn it off!

LB Test.png

{
copyright 2009-2018 (c) CAD-BIM-Manager.com
Orso B. Schmid's test for List Browsers

This code is available to you under the MIT licencing
http://www.opensource.org/licenses/mit-license.php

2009		created
Jan 2018	rewritten for compatibility with VW 2017
}
PROCEDURE LB_Test;

CONST
	
	{ various user choices }
	cChGr_ItemDisplay = 8;
		cPull_ItemDisplay = 9;
	cChGr_EditDisplay = 10;
		cPull_EditDisplay = 11;
	cCh_MultiImages = 12;
	
	cChGr_ColDataItem = 20;
		cRa_txtToggles = 21;
		cRa_imgToggles = 22;
		cSt_PreloadImg = 23;
		cPull_PreloadImg = 24;
	
	cChGr_DragDrop = 25;
	cPull_DragDrop = 26;
	
	cSt_OwnerType	= 27;
	cSt_ControlType = 28;
	
	cLB	= 30; { list browser }
	
	cGr_Bot = 40;
		cCh_MoreRows = 41;
		cCh_ShowEvents = 42;
		cSt_Message = 43;
	
	{ FYI: control type flags }
	kLBcntrNone				= 1; { also called Static }
	kLBcntrRadio			= 2;
	kLBcntrMultiState		= 3;
	kLBcntrSingleInstance	= 4;
	kLBcntrNoClick			= 5; 
	kLBcntrNumber			= 6;
	kLBcntrMultipleImages	= 7;
	kLBctrDiscTriangl		= 8;
	
	{ FYI: column owner flags }
	kLBNotOwnerDrawn		= 0;
	kLBSolidRect			= 1;
	kLBDualSolidRect		= 2;
	kLBPatRect				= 3;
	kLBDualPatRect			= 4;
	kLBGradientOrImage		= 5;
	kLBBlankOwnerDrawn		= 6;
	kLBTxtOwnerDrawn		= 7;
	kLBDashedLine			= 8;
	
	{ FYI: edit and display type flags }
	kLBdispImageOnly	= 1;
	kLBdispTextOnly		= 2;
	kLBdispImageAndText	= 3;
	
	{ dialog constants for resizement }
	kAl_Rig		= 1; { Right }
	kAl_Bot		= 2; { Bottom }
	kAl_Lef		= 3; { Left }
	kAl_resiz	= 0; { Resize }
	kAl_shift	= 1; { Move }

VAR
	gD 	: LONGINT;
	gImgCnt, gPreloadImg : INTEGER;
	gVectorFill, gLineType : LONGINT;
	gIsMac : BOOLEAN;
	
	gControlTypeStr : ARRAY[1..8] OF STRING;
	gDisplayTypeStr : ARRAY[1..4] OF STRING;
	gColOwnerStr : ARRAY[1..9] OF STRING;
	
	n, temp_i		: INTEGER;
	temp_L		: LONGINT;
	temp_r		: REAL;
	temp_s		: STRING;
	temp_b		: BOOLEAN;
	temp_h		: HANDLE;


{ ************************************************ }
{ gets a choice index }
FUNCTION D_PullIntChoice(dlog, pullID: LONGINT): INTEGER;
	VAR
		outSelectedChoiceText : STRING;
	BEGIN
		GetSelectedChoiceInfo(dlog, pullID, 0, D_PullIntChoice, outSelectedChoiceText); { from VW15 }
	END;
	

{ ************************************************* }
{ gets choice from radio, checkbox items }
FUNCTION R_GetBooleanItem(dlog, radioOrCheckID: LONGINT): BOOLEAN;
	BEGIN
		GetBooleanItem(dlog, radioOrCheckID, R_GetBooleanItem); { from VW15 }
	END;
	

{ ************************************************* }
{ returns count of choices in a pulldown menu }
FUNCTION R_GetChoiceCount(d, pullID: LONGINT): INTEGER;
	BEGIN
		GetChoiceCount(d, pullID, R_GetChoiceCount); { from VW15 }
	END;


{ ************************************************ }
FUNCTION DialogLayout: INTEGER;
	CONST
		cLBWidth	= 130;	{ width in characters }
		cLBHeight	= 20;	
		cWidth		= 25;
	VAR 
		dlog, i : INTEGER;
	
	BEGIN
		dlog := CreateResizableLayout('Orso''s List Browsers test', FALSE, 'Close', '', TRUE, TRUE);
		
		CreateCheckBoxGroupBox(dlog, cChGr_ItemDisplay, '    Item Display: ', TRUE);
			CreatePullDownMenu(dlog, cPull_ItemDisplay, cWidth);
			SetFirstGroupItem(dlog, cChGr_ItemDisplay, cPull_ItemDisplay);
		
		CreateCheckBoxGroupBox(dlog, cChGr_EditDisplay, '    Edit Display: ', TRUE);
			CreatePullDownMenu(dlog, cPull_EditDisplay, cWidth);
			SetFirstGroupItem(dlog, cChGr_EditDisplay, cPull_EditDisplay);
			
		CreateCheckBox(dlog, cCh_MultiImages, 'Multi images');
		
		CreateCheckBoxGroupBox(dlog, cChGr_ColDataItem, 'Create Column Data Items:', TRUE);
			CreateRadioButton(dlog, cRa_txtToggles, 'Text toggles');
			CreateRadioButton(dlog, cRa_imgToggles, 'Image toggles');
		
			CreateStaticText(dlog, cSt_PreloadImg, 'Preload item: ', -1);
			CreateEnhancedPullDownMenu(dlog, cPull_PreloadImg, cWidth, TRUE);
			
			SetFirstGroupItem(dlog, cChGr_ColDataItem, cRa_txtToggles);
				SetRightItem(dlog, cRa_txtToggles, cRa_imgToggles, 0, 0);
				SetBelowItem(dlog, cRa_txtToggles, cSt_PreloadImg, 0, 0);
				SetRightItem(dlog, cSt_PreloadImg, cPull_PreloadImg, 0, 0);
		
		CreateCheckBoxGroupBox(dlog, cChGr_DragDrop, 'Drag and Drop column:', TRUE);
			CreatePullDownMenu(dlog, cPull_DragDrop, cWidth);
		
			SetFirstGroupItem(dlog, cChGr_DragDrop, cPull_DragDrop);
		
		CreateStaticText(dlog, cSt_OwnerType, 'Column Owner', cWidth);
		CreateStaticText(dlog, cSt_ControlType, 'Control Types', cWidth);
		
		CreateLB(dlog, cLB, cLBWidth, cLBHeight); 
		
		CreateGroupBox(dlog, cGr_Bot, '', FALSE);
			CreateCheckBox(dlog, cCh_ShowEvents, 'Show events on cell click');
			CreateStaticText(dlog, cSt_Message, '<message bar>', cLBWidth);
			SetStaticTextColor(dlog, cSt_Message, 255, 0, 0); 
		
			{ I am not using here a CreateRadioButtonGroupBox because it crashes }
			CreateCheckBox(dlog, cCh_MoreRows, 'More generic rows');
			
			SetFirstGroupItem(dlog, cGr_Bot, cCh_ShowEvents);
				SetRightItem(dlog, cCh_ShowEvents, cCh_MoreRows, 0, 0);
				SetBelowItem(dlog, cCh_ShowEvents, cSt_Message, 0, 0);
		
 		SetFirstLayoutItem(dlog, cChGr_ItemDisplay);
 			SetRightItem(dlog, cChGr_ItemDisplay, cChGr_EditDisplay, 0, 0);
 			SetRightItem(dlog, cChGr_EditDisplay, cCh_MultiImages, 0, 0);
 			
 			SetBelowItem(dlog, cChGr_ItemDisplay, cChGr_ColDataItem, 0, 0);
 			SetRightItem(dlog, cChGr_ColDataItem, cChGr_DragDrop, 0, 0);
 			
 			SetBelowItem(dlog, cChGr_ColDataItem, cLB, 0, 0);
 			SetBelowItem(dlog, cLB, cGr_Bot, 0, 0);
			
		SetEdgeBinding(dlog, cLB, TRUE, TRUE, TRUE, TRUE);
		SetEdgeBinding(dlog, cGr_Bot, TRUE, TRUE, FALSE, TRUE);
		
		{ return the dialog ID }
		DialogLayout := dlog;
	END;


{ ************************************************ }	
PROCEDURE DialogDriver(VAR item:LONGINT; data:LONGINT);
	VAR
		event, eventRow, eventCol : INTEGER;
		inform : STRING;
		
		i, temp_i : INTEGER;
		temp_s : STRING;
		temp_L : LONGINT;
	

	{ **************************** }
	{ create one column for each Control Type }
	PROCEDURE LB_CreateColumns(dlog, LB: INTEGER);
		VAR
			controlType, col, w: INTEGER;
			temp_b : BOOLEAN;
			gTitles: ARRAY[1..20] OF STRING;
		
		BEGIN
			{ the first column (index 0) is the Column Owner, which applies to each row }
			col := InsertLBColumn(dlog, LB, GetNumLBColumns(dlog, LB), 'Col. Owner', 120);
		
			{ Mac and PC have different text width handling }
			{ to operate on the column width is idiotic. 
			This can be done much better for the whole LB }
			w := 95;
			IF NOT gIsMac THEN
				w := 78;
			
			{ add one column for each Control type }
			FOR controlType:=1 TO 8 DO BEGIN
				col := InsertLBColumn(dlog, LB, GetNumLBColumns(dlog, LB), gControlTypeStr[controlType], w);
				temp_b := SetLBControlType(dlog, LB, col, controlType);
			END;
			
			temp_b := EnableLBClickAllDataChange(dlog, LB, TRUE);
			temp_b := SetLBColumnWidth(dlog, LB, 0, 0, 120); { first col is wider }
		
			EnableLBRadioColumnLines(dlog, LB, kLBcntrRadio, TRUE);
			{ this will only be effective on Control Type radio }
			{ it also needs Column Data Items to be set up for the column }
		
			EnableLBColumnLines(dlog, LB, TRUE);
			SetLBSortColumn(dlog, LB, 0, TRUE); 
			{ sorting is on by default, no need to enable it }
			
			SetLBHierDispColumn(dlog, LB, kLBctrDiscTriangl); { this wants kLBdispImageAndText }
			{ Warning: SetLBHierDispColumn collides with sorting and raises alerts }
		END; { LB_CreateColumns }


	{ **************************** }
	{ creates a list of column data items for the specified column index "col" }
	PROCEDURE LB_CreateColDataItems(dlog, LB, col: INTEGER);
		VAR
			dataItemCnt : INTEGER;
		 
		BEGIN
			dataItemCnt := -1;
		
			{ text toggles }
			IF R_GetBooleanItem(dlog, cRa_txtToggles) THEN BEGIN
				dataItemCnt := InsertLBColumnDataItem(dlog, LB, col, 'Orso', -1, -1, 0);
				dataItemCnt := InsertLBColumnDataItem(dlog, LB, col, 'Atta', -1, -1, 0);
				dataItemCnt := InsertLBColumnDataItem(dlog, LB, col, 'Ax', -1, -1, 0);
				{ dataItemCnt increments all the times starting 0 }
			END
		
			{ image toggles }
			ELSE BEGIN
				{ this will build your Column Data Items list or the Radio columns }
				dataItemCnt := InsertLBColumnDataItem(dlog, LB, col, 'visible', gImgCnt-3, -1, 0);
				dataItemCnt := InsertLBColumnDataItem(dlog, LB, col, 'invisible', gImgCnt-2, -1, 0);
				dataItemCnt := InsertLBColumnDataItem(dlog, LB, col, 'grayed', gImgCnt-1, -1, 0);
				dataItemCnt := InsertLBColumnDataItem(dlog, LB, col, 'no', gImgCnt, -1, 0);
			END;
		END;


	{ **************************** }
	{ setup LB columns }
	PROCEDURE LB_LoadColumns(dlog, LB: INTEGER);
		VAR
			col: INTEGER;
			temp_b : BOOLEAN;
		
		BEGIN
			{ now setup the columns accordingly }
			{ we leave the first column out (index 0), since we have labels there }
			FOR col := 1 TO GetNumLBColumns(dlog, LB) -1 DO BEGIN
			
				{ reset: apparently Item and Edit display are now (VW 2017 or perhaps before) interchangeable, 
				the last used is valid for both }
				temp_b := SetLBItemDisplayType(dlog, LB, col, 0);
				temp_b := SetLBEditDisplayType(dlog, LB, col, 0); 
				
				IF R_GetBooleanItem(dlog, cChGr_ItemDisplay) THEN
					temp_b := SetLBItemDisplayType(dlog, LB, col, D_PullIntChoice(gD, cPull_ItemDisplay)); 
				
				IF R_GetBooleanItem(dlog, cChGr_EditDisplay) THEN
					temp_b := SetLBEditDisplayType(dlog, LB, col, D_PullIntChoice(gD, cPull_EditDisplay));
			
				{ create a list of column data items for each column }
				{ here for each column we make the same list }
				IF R_GetBooleanItem(dlog, cChGr_ColDataItem) THEN
					LB_CreateColDataItems(dlog, LB, col);
				
				temp_b := SetLBColumnHeaderToolTip(dlog, LB, col, Concat(
					'Item: ', GetLBItemDisplayType(dlog, LB, col), 
					'; Edit: ', GetLBEditDisplayType(dlog, LB, col)
					), '');
			END;
		
			{ add hints to the first col, that we left outside the loop }
			temp_b := SetLBColumnHeaderToolTip(dlog, LB, 0, Concat(
				'Item: ', GetLBItemDisplayType(dlog, LB, 0), 
				'; Edit: ', GetLBEditDisplayType(dlog, LB, 0)
				), '');
			
			IF EnableLBDragAndDrop(dlog, LB, R_GetBooleanItem(dlog, cChGr_DragDrop)) THEN
				temp_b := SetLBDragDropColumn(dlog, LB, D_PullIntChoice(dlog, cPull_DragDrop) +1);
				{ +1 because the pull index is 0-based }
		END;
	

	{ ************************************************ }
	{ 
	++++ ONLY FOR EXPERIMENTS +++++

	loads cells with resource thumbnails and names.
	The routine below doesn't check for valid resource types.
	This will work with all resources creating a thumbnail in the Resource Browser.
	This can positively run you out of memory on heavy resource thumbnails like textures.

	Use the typical GetType constants for setting the resource type to be loaded, for example:

	16: sym definition
	66: hatch definition
	97: texture definiton EXTREMELLY heavy, any user click causes the watch-cursor
	119: image fill definition
	120: gradient fill definition
	127: wall style


	Thus you can see how bad thumbnails aside of gradients display
	Try it on a document with some symbols

	the list browser has two columns, 
	col 0 has control Static, item display text: we load the symbol name
	col 1 Static, item display image: we load here the sym thumbnail
	}

	PROCEDURE LB_LoadIndexedResources(dlog, LB: INTEGER; resourceType: INTEGER);
		VAR
			resList, cnt : LONGINT;
			resName : STRING;
			row, col : INTEGER;
			temp_b : BOOLEAN;
		
		{ ************************************************ }
		{ reads obj type descriptions from the VW resources }
		{ these do not need to be laoden, like IP Resources and }
		{ they are localized: from VW LocalD.qtr, string 4501 }
		{ the extended descriptions are in VW LocalD.qtr, string 4504 }
		{ the subtypes are in VW LocalD.qtr, string 4505 }
		FUNCTION H_GetTypeName(aType: INTEGER): STRING;
			VAR
				typeStr, extendedExplan : STRING;
			BEGIN
				H_GetTypeName := '<unknown>';
				aType := aType + 1;
			
				GetResourceString(typeStr, 4501, aType);
				IF typeStr <> '()' THEN BEGIN
					GetResourceString(extendedExplan, 4504, aType);
					H_GetTypeName := Concat(typeStr, ' ', extendedExplan);
				END;
			END;
		
		BEGIN
			IF DeleteAllLBItems(dlog, LB) THEN BEGIN
				EnableLBUpdates(dlog, LB, FALSE);
			
				resList := BuildResourceList(resourceType, 0, '', cnt); 
				{ if you did some resource renaming during dialog execution this can mess up the list, 
				in this case you better redo the list.
				You don't need to redo it if your resList is not modified during dialog execution }
			
				IF cnt > 0 THEN BEGIN
					row := -1;
					col := 0;
				
					WHILE (row+1) < cnt DO BEGIN
						resName := GetNameFromResourceList(resList, row+2); { this is a 1-based list }
					
						{ resource name at column 0 }
						row := InsertLBItem(dlog, LB, GetNumLBItems(dlog, LB), resName);
						temp_b := SetLBColumnOwnerDrawnType(dlog, LB, row, col, kLBTxtOwnerDrawn); { text owner }
						
						{ resource icon at column 1 }
						IF SetLBColumnOwnerDrawnType(dlog, LB, row, col +1, kLBGradientOrImage) THEN { vectorfll owner }
							temp_b := SetLBItemGradientOrImageRefNumber(dlog, LB, row, col+1, Name2Index(resName));
					END;
				
				END ELSE
					AlrtDialog(Concat('Resource list for object type "' , H_GetTypeName(resourceType), '" is either empty or not parsable') );
			
				EnableLBUpdates(dlog, LB, TRUE);
				temp_b := RefreshLB(dlog, LB);
			END;
		END; { LB_LoadIndexedResources }


	{ ************************************************ }
	{ load rows in a LB, remember to empty it first! }
	PROCEDURE LB_LoadRows(dlog, LB: INTEGER);
		VAR
			colOwner, col, row, n	: INTEGER;
			temp_b : BOOLEAN;
		
		BEGIN
			{ pause updating while we reset the LB, this makes it faster }
			EnableLBUpdates(dlog, LB, FALSE);
		
			{ insert 1 row for each Column Owner (cell property) }
			FOR colOwner := 0 TO 8 DO BEGIN
			
				{ add a row at the end }
				row := InsertLBItem(dlog, LB, GetNumLBItems(dlog, LB), gColOwnerStr[colOwner +1]);
				{ +1 because the string array is 1-based }
				{ set the Column Owner name on the first cell of the first column }
			
				{ setup cell infos in each column of the row }
				{ we leave the first cell out, where we have labels }
				FOR col := 1 TO GetNumLBColumns(dlog, LB) -1 DO BEGIN
			
					{ as ColumnOwnerDrawnType I can reuse the column index }
					{ column index = Column Owner Type }
					IF SetLBColumnOwnerDrawnType(dlog, LB, row, col, colOwner) = FALSE THEN
						AlrtDialog(Concat('Hey! Finally the Owner works on cell: ', row, col))
						{ this never happens, ha ha! }
					
					{ insert a string and loads the imagine set in gPreloadImg, which is user's choice }
					ELSE IF SetLBItemInfo(dlog, LB, row, col, Concat(row, ',', col), gPreloadImg) THEN BEGIN
						
						{ add text with a divider: this will display as disclosure }
						temp_b := SetLBItemInfo(dlog, LB, row, kLBctrDiscTriangl, 'Test-one-two-tree', -1);
						
						{ I set each cell to use the ColumnDataItem, if any available. 
						This overrides any value previously defined in SetLBItemInfo }
						IF R_GetBooleanItem(dlog, cChGr_ColDataItem) & (GetNumLBColumnDataItems(dlog, LB, col) > 0) THEN
							temp_b := SetLBItemUsingColumnDataItem(dlog, LB, row, col, gPreloadImg);
					
						IF R_GetBooleanItem(dlog, cCh_MultiImages) THEN
							temp_b := SetLBImageIndexes(dlog, LB, row, col, 
								'Vectorworks/Standard Images/ViewBarSavedViews.png', 
								'Vectorworks/Standard Images/Viewports.png', 
								'Vectorworks/Standard Images/Layers.png'
							);
					
						{ we have one row for each Column Owner }
						CASE row OF
						kLBSolidRect, kLBDualSolidRect, kLBPatRect, kLBDualPatRect:
							BEGIN
								temp_b := SetLBItemFillForeColor(dlog, LB, row, col, 255, 0, 0); { enough for Solid Rect }
								temp_b := SetLBItemFillBackColor(dlog, LB, row, col, 0, 255, 0); { needed for dual solid and pattern }
								
								temp_b := SetLBItemPenForeColor(dlog, LB, row, col, 245, 125, 60);
								temp_b := SetLBItemPenBackColor(dlog, LB, row, col, 0, 0, 255);
								
								temp_b := SetLBItemPatternIndex(dlog, LB, row, col, 25); { pattern index }
							END;
						
						kLBGradientOrImage:
							temp_b := SetLBItemGradientOrImageRefNumber(dlog, LB, row, col, gVectorFill); { gradient index }
					
						kLBDashedLine:
							BEGIN
								temp_b := SetLBItemLineType(dlog, LB, row, col, gLineType, 15);
								temp_b := SetLBItemPenForeColor(dlog, LB, row, col, 0, 255, 255);
								temp_b := SetLBItemPenBackColor(dlog, LB, row, col, 240, 240, 240); { nearly white background }
							END;
						END; { CASE }
						
					END ELSE
						AlrtDialog(Concat('SetLBItemInfo failed on col: ', col));
				END; { FOR col }
			END; { FOR colOwner }
		
			{ add extra cells with defaults: control none, display text }
			IF R_GetBooleanItem(dlog, cCh_MoreRows) THEN
				FOR n:=0 TO 40 DO BEGIN
			
					row := InsertLBItem(dlog, LB, GetNumLBItems(dlog, LB), Concat(row+1, ',0'));
					FOR col:=1 TO GetNumLBColumns(dlog, LB)-1 DO begin
						IF SetLBItemInfo(dlog, LB, row, col, Concat(row, ',', col), gPreloadImg) THEN BEGIN
					
							{ do your experiments here }
						END;
					
						{ do your experiments here }
					END;
				END;
				
			EnableLBHierDisplay(dlog, LB, TRUE); { must be at the end or it won't work }
			EnableLBUpdates(dlog, LB, TRUE);
			temp_b := RefreshLB(gD, cLB);
		END; { LB_LoadRows }


	{ ************************************************ }
	{ destroy LBs }
	PROCEDURE LB_Destroy(dlog, LB: INTEGER);
		VAR
			col : INTEGER;
			temp_b : BOOLEAN;
		BEGIN
			temp_b := DeleteAllLBItems(dlog, LB);
		
			FOR col:=0 TO GetNumLBColumns(dlog, LB)-1 DO
				RemoveAllLBColumnDataItems(dlog, LB, col);
		END;


	{ ************************************************ }
	{ destroy LBs and rebuild them anew }
	PROCEDURE LB_Reset;
		VAR
			event, eventRow, eventCol, itemIndex : INTEGER;
		
			temp_i : INTEGER;
			temp_s : STRING;
			temp_b : BOOLEAN;
		BEGIN
			{ disable column data item toggles if not chosen }
		
			{ preload an image }
			gPreloadImg := D_PullIntChoice(gD, cPull_PreloadImg);
		
			{ the last pulldown menu item is always -1 }
			IF gPreloadImg = R_GetChoiceCount(gD, cPull_PreloadImg) -1 THEN
				gPreloadImg := -1;
		
			LB_Destroy(gD, cLB); { destroy all LBs data }
				
			{ get users choices for Display and Edit Types }
			{ increased because pull is 0-based }
			LB_LoadColumns(gD, cLB);
		
			{ reload all rows with data }
			LB_LoadRows(gD, cLB); { rebuild the rows }
		
			{ pehaps you want to try this instead of LB_LoadRows }
			{LB_LoadIndexedResources(gD, cLB, 66);} { here loading hatches, change it as you please }
		
			(* uncomment this if you wish to explore List Browsers events outside the cLB's CASE block item:
					******* DON'T DO IT IN YOUR REAL CODES ******* 
		
			AlrtDialog(Concat(GetLBEventInfo(gD, cLB, event, eventRow, eventCol)));
			AlrtDialog(Concat('event: ', event, Chr(13), 'last sel row: ', eventRow, Chr(13), 'last sel col: ', eventCol));
			*)
		END;
		
	
	{ DialogDriver }
	BEGIN
		CASE item OF
			SetupDialogC: 
				BEGIN
					{ these arrays don't actually need to be globals or to be all here, I put them here for clarity }
					{ Control types, used in LB_CreateColumns }
					gControlTypeStr[1] := 'Static';
					gControlTypeStr[2] := 'Radio';
					gControlTypeStr[3] := 'Multi State';
					gControlTypeStr[4] := 'Single Instance Icon';
					gControlTypeStr[5] := 'Static icon';
					gControlTypeStr[6] := 'Number';
					gControlTypeStr[7] := 'Multiple Icons';
					gControlTypeStr[8] := 'Disclosure Triangle'; { for hierarchical display, introduced by VW 17 (2012) VW 18 (2013) }
	
					{ Column Owner types, used in LB_LoadRows }
					gColOwnerStr[1] := 'None';
					gColOwnerStr[2] := 'Solid rect ';
					gColOwnerStr[3] := 'Dual solid rect ';
					gColOwnerStr[4] := 'Pattern rect';
					gColOwnerStr[5] := 'Dual pattern rect';
					gColOwnerStr[6] := 'Gradient or image';
					gColOwnerStr[7] := 'Blank';
					gColOwnerStr[8] := 'Text';
					gColOwnerStr[9] := 'Dashed line';
	
					{ Item and Edit display types, used below }
					gDisplayTypeStr[1] := 'Image';
					gDisplayTypeStr[2] := 'Text only';
					gDisplayTypeStr[3] := 'Image and Text';
					
					{ edit and display types flags }
					AddChoice(gD, cPull_ItemDisplay, '<nothing set>', 0);
					AddChoice(gD, cPull_EditDisplay,'<nothing set>', 0);
				
					FOR i:= 1 TO 3 DO BEGIN
						AddChoice(gD, cPull_ItemDisplay, gDisplayTypeStr[i], R_GetChoiceCount(gD, cPull_ItemDisplay));
						AddChoice(gD, cPull_EditDisplay, gDisplayTypeStr[i], R_GetChoiceCount(gD, cPull_EditDisplay));
					END;
					
					SelectChoice(gD, cPull_ItemDisplay, 0, TRUE); { preselects '<nothing set>' }
					SelectChoice(gD, cPull_EditDisplay, 1, TRUE); { preselects 'Image' }
					SetBooleanItem(gD, cChGr_EditDisplay, TRUE);
					
					
					SetBooleanItem(gD, cChGr_ColDataItem, TRUE);
					SetBooleanItem(gD, cRa_txtToggles, FALSE);
					SetBooleanItem(gD, cRa_imgToggles, TRUE);
					SetBooleanItem(gD, cCh_MultiImages, TRUE);
					
					{ disable column data item toggles if not chosen }
					
					{ add images to the Icons List, available to the whole List Browser }
					gImgCnt := -1; { init }
					gImgCnt := AddListBrowserImage(gD, cLB, 'Vectorworks/Standard Images/Visible.png'); { black open eye 16x14 px }
					gImgCnt := AddListBrowserImage(gD, cLB, 'Vectorworks/Standard Images/Invisible.png'); { cross 16x14 px }
					gImgCnt := AddListBrowserImage(gD, cLB, 'Vectorworks/Standard Images/Gray.png'); { gray open eye 16x14 px }
					gImgCnt := AddListBrowserImage(gD, cLB, 'Vectorworks/Standard Images/DontSave.png'); { forbidden sign }
					
					{ init image preloading pull }
					temp_i := InsertEnhanPullDownMenuItem(gD, cPull_PreloadImg, 'Visible', 'Vectorworks/Standard Images/Visible.png');
					temp_i := InsertEnhanPullDownMenuItem(gD, cPull_PreloadImg, 'Invisible', 'Vectorworks/Standard Images/Invisible.png');
					temp_i := InsertEnhanPullDownMenuItem(gD, cPull_PreloadImg, 'Gray', 'Vectorworks/Standard Images/Gray.png');
					temp_i := InsertEnhanPullDownMenuItem(gD, cPull_PreloadImg, 'Forbidden', 'Vectorworks/Standard Images/DontSave.png');
					temp_i := InsertEnhanPullDownMenuItem(gD, cPull_PreloadImg, '-1', 'Vectorworks/Standard Images/Blank.png'); { add "-1", empty image }
					
					gPreloadImg := 3;
					SelectChoice(gD, cPull_PreloadImg, gPreloadImg, TRUE);
					
					{ drag and drop choices }
					SetBooleanItem(gD, cChGr_DragDrop, TRUE);
					FOR i:= 1 TO 8 DO { array of 8 items, see VARs }
						AddChoice(gD, cPull_DragDrop, Concat(i, ' ', gControlTypeStr[i]), R_GetChoiceCount(gD, cPull_DragDrop));
						
					SelectChoice(gD, cPull_DragDrop, 5, TRUE); { preselects Control Type Number }
					
					{ create one column for each Control Type }
					LB_CreateColumns(gD, cLB);
					LB_Reset;
				END;
				
			cLB : 
				BEGIN
					IF R_GetBooleanItem(gD, cCh_ShowEvents) THEN
						IF GetLBEventInfo(gD, cLB, event, eventRow, eventCol) THEN
							AlrtDialog(Concat('event: ', event, Chr(13), 'last sel row: ', eventRow, Chr(13), 'last sel col: ', eventCol))
						ELSE
							AlrtDialog('GetLBEventInfo returned FALSE');
					
					IF eventCol = kLBctrDiscTriangl THEN BEGIN
						IF HierLBItemIsClosed(gD, cLB, eventRow) THEN 
							HierLBItemOpened(gD, cLB, eventRow, FALSE, temp_i)
						ELSE
							HierLBItemClosed(gD, cLB, eventRow, FALSE); 
					END;
					
				(* 	
					uncomment this if you wish to experiment finding in Single Instance item 
					this is only meanigful if you have column data items activated
					
					'Atta' is the second data item that we loaded
					IF R_GetBooleanItem(gD, cRa_txtToggles) THEN BEGIN
						IF FindLBColumnItem(gD, cLB, kLBcntrSingleInstance, 'Atta', i) THEN
							AlrtDialog(concat('Searching Atta in Col 4, found her at row: ', i));
						
						IF FindLBColumnDataItem(gD, cLB, kLBcntrSingleInstance, 'Atta', i) THEN
							AlrtDialog(concat('Searching data item Atta in Col 4, found her at row: ', i));
					END;
				*)
				END;
				
			cPull_ItemDisplay, cPull_EditDisplay,
			cChGr_DragDrop, cPull_DragDrop, cCh_MultiImages, 
			cChGr_ColDataItem, cRa_txtToggles, cRa_imgToggles, cPull_PreloadImg, 
			cCh_ShowEvents, cCh_MoreRows:
				BEGIN
					{ I begin here some user info. This can get pretty complicated and is awfully boring. }
					{ debug it yourself (there are bugs) and if you come out with something nice, send it to me }
					CASE item OF 
					cPull_ItemDisplay :
						BEGIN
							temp_i := D_PullIntChoice(gD, cPull_ItemDisplay);
							inform := 'Apparently this is not operative any longer, only Edit Display works (tested under VW 2017)';
						END;
							
					cPull_EditDisplay, cPull_PreloadImg :
						BEGIN
							temp_i := D_PullIntChoice(gD, cPull_EditDisplay);
							IF temp_i = 2 THEN
								inform := 'You cannot see preloaded images while Edit Display is set to "Text Only"';
						END;
						
					cPull_DragDrop :
						IF D_PullIntChoice(gD, cPull_DragDrop) <> 5 THEN 
							inform := 'Drag an drop works only on Control Type "Number". Select a row in the "Number" column and drag it elsewhere.';
						
					cRa_txtToggles:
						inform := 'Click on some cells to toggle this sequence independently from the images: Orso, Atta, Ax';
						
					cCh_ShowEvents:
						inform := 'If on, clicking on a cell will raise an alert showing relevant List Browser events.';
						
					cCh_MoreRows:
						inform := 'If on, Creates more generic cells for you to experiment. You should add cell experiments in the subroutine LB_LoadRows ';
					END;
					
					SetItemText(gD, cSt_Message, inform);
					LB_Reset; { destroys the LB and rebuilds it }
				END;
				
				
			{ OK button }
			1: 	BEGIN
					{ do you want do something at dialog exit? put it here }
				END;
		END;
 	END; { DialogDriver }


{ ************************************************** }
{ ********************* MAIN *********************** }
BEGIN
	SetPref(407, TRUE); { compiler mode, remember to turn it off!!!! }
	
	GetVersion(n, n, n, n); { last checked value is the platform }
	gIsMac := (n = 1);
	gD := DialogLayout;
		
	temp_s := 'LB gradient';
	temp_h := GetObject(temp_s);
	
	{ whatsoever gradient to demonstrate the owner "Gradient or image" }
	IF temp_h = NIL THEN BEGIN
		temp_h := CreateGradient(temp_s);
		temp_i := InsertGradientSegment(temp_h, 0, 0.5, 255, 255, 255);
		temp_i := InsertGradientSegment(temp_h, 0.3, 0.5, 0, 255, 255);
		temp_i := InsertGradientSegment(temp_h, 0.7, 0.5, 255, 255, 255);
	END;
	gVectorFill := Name2Index(temp_s);
	
	{ whatsoever line type to demonstrate the owner "Dashed Line" }
	temp_s := 'LB Line Style';
	temp_h := GetObject(temp_s);
	IF temp_h = NIL THEN
		SetDashStyleN(temp_s, TRUE, 1, 5", 2"); { this wants page inches }
	gLineType := Name2Index(temp_s);
	
	IF VerifyLayout(gD) THEN
		temp_L := RunLayoutDialog(gD, DialogDriver)
	ELSE
		AlrtDialog('You made a mess again.');
END;
Run(LB_Test);