SDK:Working with VWListBrowserCtrl: Difference between revisions

From Vectorworks Developer
Jump to navigation Jump to search
 
Line 265: Line 265:
columnCheck.SetColumnType( kListBrowserControlMultiState );
columnCheck.SetColumnType( kListBrowserControlMultiState );
columnCheck.SetItemDisplayType( kListBrowserDisplayImageOnly );
columnCheck.SetItemDisplayType( kListBrowserDisplayImageOnly );
columnCheck.InsertColumnChoice( kChecked, fImageIndexBlank );
columnCheck.InsertColumnChoice( kUncheced, fImageIndexBlank );
columnCheck.InsertColumnChoice( kUncheced, fImageIndexCheckmark );
columnCheck.InsertColumnChoice( kChecked, fImageIndexCheckmark );
</code>
</code>



Latest revision as of 04:20, 25 January 2020

.SDK|SDK ..SDK:Types|SDK Types ..SDK:Using the SDK|Using the SDK ..VCOM:VCOM (Vectorworks Component Object Model)|VCOM Basics ..VCOM:Class Reference|VCOM Class Reference

Adding images to the list browser control

The images are to be added at initialization time to the control, and later they are used by IDs. Normally the IDs are by the order the images are added:

There are two functions for adding images in the list browser control:

// Adds image from ICN# resource.
// (You need to put icl8s image 
// along with a mask for each ICN# resource)
size_t AddImage(size_t resourceID,
                size_t resourceIDSelected = 0);
// Adds standard image in the image list for this control
// These images are defined by VectorWorks
size_t AddImageStandard(EStandardImageID image,
                        EStandardImageID selImage
                                     = kStandardImageID_None);

Here is a list of available standard images:

enum EStandardImageID {
	kStandardImageID_None,
	kStandardImageID_Blank,              //blank icon used for clearing
	kStandardImageID_DiamondBlack,
	kStandardImageID_DiamondHollow,
	kStandardImageID_DiamondGray,
	kStandardImageID_RedCrossedCircle,
	kStandardImageID_CheckMark,
	kStandardImageID_CheckMarkWhite,
	kStandardImageID_LeftBlackArrow,
	kStandardImageID_RightBlackArrow,
	kStandardImageID_LeftHollowArrow,
	kStandardImageID_RightHollowArraw,
	kStandardImageID_LeftThinArrow,
	kStandardImageID_RightThinkArrow,
	kStandardImageID_BallBlack,
	kStandardImageID_BallHollow,
	kStandardImageID_Slash,
	kStandardImageID_XMark,
};

Now you initialize your list browser control in the 'Setup' event of the dialog:

void CSampleDlg::OnSetUpEvent()
{
	VWDialog::OnSetUpEvent();

	VWListBrowserCtrl*	pListBrowser	= this->GetListBrowserCtrlByID( kMyListBrowsr );

	// filling up the image list
	pListBrowser->AddImageStandard( kStandardImageID_DiamondBlack );
	pListBrowser->AddImageStandard( kStandardImageID_DiamondHollow );
	pListBrowser->AddImageStandard( kStandardImageID_DiamondGray );

	// ...

Note The order of filling in the images determine the index that this icon is represented with. In this example the 'DiamondBlack' icon has index of 0; 'DiamondHollow' has index of 1; and 'DiamondGray' 2;

After that you need to fill up the columns in the list browser control:

Adding text containing column

VWListBrowserColumn  col0  = pListBrowser->AddColumn( "None", 100 );

Adding image containing column

VWListBrowserColumn col0  = m_pListBrowser->AddColumn( "Header" , 20);
col0.SetColumnType(kListBrowserControlNone);
col0.SetItemDisplayType(kListBrowserDisplayImageOnly);

Adding radio changing images column

VWListBrowserColumn  col1  = pListBrowser->AddColumn( "Radio", 100 );
col1.SetColumnType( kListBrowserControlRadio );

col1.InsertColumnChoice( "a", 0 );
col1.InsertColumnChoice( "b", 1 );
col1.InsertColumnChoice( "c", 2 );

col1.EnableRadioColumnLines( true );
  1. InsertColumnChoice - puts set of images that will alternate within this column. Note that the name of each choice (the text value) should be unique within the column.
  2. EnableRadioColumnLines - when calling this with true, you enable dividing lines between the coices to be drawn.

Note! When you fill the list with items you should use the function:

pListBrowser->GetItem( rowIndex, colIndex ).SetItemUsingColumnDataItem( imageIndex );

to set up the initial state of the radio column item image.

Adding multi state column

VWListBrowserColumn  col2  = pListBrowser->AddColumn( "MultiState", 100 );
col2.SetColumnType( kListBrowserControlMultiState );
col2.SetItemDisplayType( kListBrowserDisplayImageAndText );

col2.InsertColumnChoice( "aa", 0 );
col2.InsertColumnChoice( "bb", 1 );
col2.InsertColumnChoice( "cc", 2 );
  1. SetItemDisplayType - you can mix up this column values with text only, image only, or text and image (kListBrowserDisplayImageOnly, kListBrowserDisplayTextOnly, kListBrowserDisplayImageAndText)
  2. InsertColumnChoice - you add the alternatives that this column may contain. The choices are switched by the user's click of the mouse on each row's column.

Adding single instance column

VWListBrowserColumn  col3  = pListBrowser->AddColumn( "SingleInstance", 100 );
col3.SetColumnType( kListBrowserControlSingleInstance );
col3.SetItemDisplayType( kListBrowserDisplayImageAndText );
 
col3.InsertColumnChoice( "aaa", 0 );
col3.InsertColumnChoice( "bba", 1 );
col3.InsertColumnChoice( "cca", 2 );

Adding 'NoClick' column

VWListBrowserColumn  col4  = pListBrowser->AddColumn( "NoClick", 100 );
col4.SetColumnType( kListBrowserControlNoClick );

Adding 'Number' column

VWListBrowserColumn  col5  = pListBrowser->AddColumn( "Number", 100 );
col5.SetColumnType( kListBrowserControlNumber );
 
col5.SetAsDragAndDropColumn();

Note! This is the column that can be used to drag&drop. To do that you have to mark the column with 'SetAsDragAndDropColumn' call. And you have to enable the drag&drop support for the control:

pListBrowser->EnableDragAndDrop( true );

Adding multiple images column

VWListBrowserColumn  col6  = pListBrowser->AddColumn( "MultImages", 100 );
col6.SetColumnType( kListBrowserControlMultipleImages );
col6.SetItemDisplayType( kListBrowserDisplayImageOnly );

col6.InsertColumnChoice( "aaaaaa", 0 );
col6.InsertColumnChoice( "bbabba", 1 );
col6.InsertColumnChoice( "ccacca", 2 );

Adding color column

VWListBrowserColumn clrCol = pListBrowser->AddColumn( "Color", 100 );
clrCol.SetColumnType( kListBrowserControlNoClick );
clrCol.SetItemDisplayType( kListBrowserDisplayImageOnly );

...

VWListBrowserItem	colorItem	= pListBrowser->GetItem( index, 2 );
colorItem.SetOwnerDrawnType( kListBrowserSolidRect );
colorItem.SetItemFillBackColor( fColorBack );
colorItem.SetItemFillForeColor( fColorFore );
colorItem.SetItemPenBackColor( fColorBack );
colorItem.SetItemPenForeColor( fColorFore );

Adding line style column

VWListBrowserColumn	lineCol	= pListBrowser->AddColumn( "Line Style", 70 );
lineCol.SetColumnType( kListBrowserControlNoClick );
lineCol.SetItemDisplayType( kListBrowserDisplayImageOnly );

...

CRGBColor dashForeColor;
dashForeColor.SetFrontColor();

VWListBrowserItem itemLineStyle = pListBrowser->GetItem( itemIndex, 3 );
itemLineStyle.SetOwnerDrawnType( kListBrowserDashedLine );
itemLineStyle.SetItemDashStyle( fLineStyle, fLineWeight );
itemLineStyle.SetItemPenForeColor( dashForeColor );


Update: After the line styles became resources, the 'SetItemDashStyle' doesn't work any more. You should use 'gSDK->SetListBrowserItemLineTypeRef' untile the SDK is updated to accomodate for this.

InternalIndex fLineStyle = ...;

VWListBrowserItem itemLineStyle = pListBrowser->GetItem( itemIndex, 3 );
itemLineStyle.SetOwnerDrawnType( kListBrowserDashedLine );
gSDK->SetListBrowserItemLineTypeRef( this->GetDialogID(), pListBrowser->GetControlID(), Sint32(itemIndex), Sint32(3), fLineStyle< 0 ? (-1 * fLineStyle) : 0, fLineWeight );
itemLineStyle.SetItemPenForeColor( dashForeColor );

Working with items

pListBrowser->GetItem( 0, 0 ).SetItemText( "text 0" );
pListBrowser->GetItem( 0, 5 ).SetItemText( "0" );
pListBrowser->GetItem( 0, 6 ).SetMultImageIndexes( 1534, 1535, 1536 );

pListBrowser->GetItem( 1, 0 ).SetItemText( "text 1" );
pListBrowser->GetItem( 1, 5 ).SetItemText( "1" );
pListBrowser->GetItem( 1, 6 ).SetMultImageIndexes( 2, 1 );

pListBrowser->GetItem( 2, 0 ).SetItemText( "text 2" );
pListBrowser->GetItem( 2, 5 ).SetItemText( "2" );

An example of single image columns:

size_t check = pListBrowser->AddImageStandard(kStandardImageID_CheckMark);
size_t uncheck = pListBrowser->AddImageStandard(kStandardImageID_Blank);

...

pListBrowser->GetItem( 0, 0 ).SetItemImage(check);
pListBrowser->GetItem( 1, 0 ).SetItemImage(uncheck);

Creating a check mark column

// list browser constants
#define		kChecked	"Yes"
#define		kUncheced	"No"

size_t	fImageIndexBlank;
size_t	fImageIndexCheckmark;


	fImageIndexBlank	= fListCtrl->AddImageStandard( kStandardImageID_Blank );
#if GS_WIN
	fImageIndexCheckmark	= fListCtrl->AddImageStandard( kStandardImageID_CheckMark, kStandardImageID_CheckMarkWhite );
#else
	fImageIndexCheckmark	= fListCtrl->AddImageStandard( kStandardImageID_CheckMark );
#endif

	VWListBrowserColumn  columnCheck  = fListCtrl->AddColumn( resLoader.Load(kStr_Visible), 120 );
	columnCheck.SetColumnType( kListBrowserControlMultiState );
	columnCheck.SetItemDisplayType( kListBrowserDisplayImageOnly );
	columnCheck.InsertColumnChoice( kUncheced, fImageIndexBlank );
	columnCheck.InsertColumnChoice( kChecked, fImageIndexCheckmark );

If the you are after implemented radio control behavior with image column, set the following to the column:

	columnCheck.SetColumnType( kListBrowserControlSingleInstance );

Drag & Drop column

Drag and Drop is a property of the column but you also need to enable it in the control:

VWListBrowserCtrl*	settingsList	= this->GetListBrowserCtrlByID( kSettingsList );
settingsList->EnableDragAndDrop( true );

VWListBrowserColumn  columnNum  = settingsList->AddColumn( resLoader.Load(kStr_ColNumber), 30 );
columnNum.SetColumnType( kListBrowserControlNumber );
columnNum.SetAsDragAndDropColumn();

Then you need to handle the event coming from the list browser control. Note, we are relying on the first column to be the numeric column for the drag&drop, plus to contain indices that refer to our local data for the list (farrParamsLocalData)

void CMyDialog::OnParametersList(long controlID, VWDialogEventArgs& eventArgs)
{
	VWListBrowserCtrl*	settingsList	= this->GetListBrowserCtrlByID( kSettingsList );
	
	if ( eventArgs.IsListBrowserDoubleClickEvent() )
	{
		this->OnEditBtn( controlID, eventArgs );
	}
	else if ( eventArgs.IsListBrowserDrawNDropEnd() )
	{
		TEditFiledLocalDataArray	parametersOriginal = farrParamsLocalData;

		farrParamsLocalData.clear();
		size_t	rowsCnt = settingsList->GetRowsCount();
		for(size_t i=0; i<rowsCnt; i++)
		{
			long	originalIndex	= settingsList->GetItem( i, 0 ).GetItemText().atoi() - 1;

			VERIFYN( kVStanev, originalIndex >= 0 && originalIndex < parametersOriginal.size() );
			const SEditFieldLocalData&	itemData = parametersOriginal[ originalIndex ];
			farrParamsLocalData.push_back( itemData );
		}

		// rebuild the list and select the necessary rows
		this->UpdateParametersList( );
	}
}

Also, there is a function to refill the list updating the numbers on the drag&drop column. This function also preserves the original selection:

void CMyDialog::UpdateParametersList()
{
	VWListBrowserCtrl*	settingsList	= this->GetListBrowserCtrlByID( kSettingsList );

	TSizeTArray		arrSelIndices;
	TXStringSTLArray	arrSelNames;

	settingsList->GetSelectedItemIndices( arrSelIndices );
	for(size_t i=0, cnt=arrSelIndices.size(); i<cnt; i++)
	{
		TXString	selName = settingsList->GetItem( arrSelIndices[i], 2 ).GetItemText();
		arrSelNames.push_back( selName );
	}

	arrSelIndices.clear();
	settingsList->DeleteAllRows();

	for(size_t i=0, cnt=farrParamsLocalData.size(); i<cnt; i++)
	{
		const SEditFieldLocalData&	paramData = farrParamsLocalData[ i ];

		size_t rowIndex = settingsList->AddRow( TXStringExt::Format( "%d", i + 1 ) );
		settingsList->GetItem( rowIndex, 1 ).SetItemImage( paramData.fUse? fImageIndexCheckmark : fImageIndexBlank );
		settingsList->GetItem( rowIndex, 2 ).SetItemText( paramData.fName );
		settingsList->GetItem( rowIndex, 3 ).SetItemText( paramData.fPrettyName );
		settingsList->GetItem( rowIndex, 3 ).SetItemText( paramData.fType);
		settingsList->GetItem( rowIndex, 5 ).SetItemText( paramData.fDefaultValue );

		if ( std::find( arrSelNames.begin(), arrSelNames.end(), paramData.fName ) != arrSelNames.end() )
		{
			arrSelIndices.push_back( i );
		}
	}

	settingsList->SetSelectedItemIndices( arrSelIndices, true );
}

Alternatively, you can use provided data for the drag&drop indices:

void  CMyDialog::OnParamsList(long controlID, VWFC::VWUI::VWDialogEventArgs& eventArgs)
{
	static bool sWaitDropInfoMessage = false;
	static VWDialogEventArgs::SListBrowserDragDropInfo sDropInfo;
	if ( sWaitDropInfoMessage )
	{
		VWDialogEventArgs::SListBrowserDragDropInfo* dropInfo = eventArgs.GetListBrowserDropInfo();
		if ( dropInfo )
			sDropInfo = *dropInfo;

		sWaitDropInfoMessage = false;
	}
	else if ( eventArgs.IsListBrowserNextMessageIsDropInfo() )
	{
		sWaitDropInfoMessage = true;
	}
	else if ( eventArgs.IsListBrowserDrawNDropEnd() )
	{
		VWListBrowserCtrl*	paramsList		= this->GetListBrowserCtrlByID( kParametersList );

		size_t	paramsCnt		= farrParameters.size();
		size_t	dragParamIndex	= sDropInfo.iDragIndex >= 0 ? paramsList->GetRowMarker( sDropInfo.iDragIndex ) : size_t(-1);
		size_t	dropParamIndex	= sDropInfo.iDropIndex >= 0 ? paramsList->GetRowMarker( sDropInfo.iDropIndex ) : size_t(-1);
		if ( VERIFYN( kVStanev, dragParamIndex < paramsCnt && dropParamIndex < paramsCnt ) )
		{
			const FieldSpec& dragParamDef = farrParameters[ dragParamIndex ];

			if ( dropParamIndex + 1 <= dragParamIndex )
			{
				farrParameters.insert( farrParameters.begin() + dropParamIndex, dragParamDef );
				farrParameters.erase( farrParameters.begin() + dragParamIndex + 1 );

				this->FillParameters( true, dropParamIndex );
			}
			else 
			{
				farrParameters.insert( farrParameters.begin() + dropParamIndex + 1, dragParamDef );
				farrParameters.erase( farrParameters.begin() + dragParamIndex );

				this->FillParameters( true, dropParamIndex );
			}
		}
	}
	else if ( eventArgs.IsListBrowserDoubleClickEvent() )
	{
		this->OnParamEditBtn( controlID, eventArgs );
	}
	else
	{
		// this is just a protection!
		sWaitDropInfoMessage = false;
	}
}

This uses calls that might be missing in older VWFC versions. However, they can still be used:

struct SListBrowserDragDropInfo
{
	std::vector<int>		vIndicesDragged;
	int						iDragIndex;
	int						iDropIndex;
	int						iSortState;

	SListBrowserDragDropInfo() { iDragIndex = iDropIndex = iSortState = -1; }
};

bool VWDialogEventArgs::IsListBrowserNextMessageIsDropInfo() const
{
	return this->GetEventData() == -50;
}

VWDialogEventArgs::SListBrowserDragDropInfo* VWDialogEventArgs::GetListBrowserDropInfo()
{
	return (SListBrowserDragDropInfo*) this->GetEventData();
}

See Also

SDK:Creating handler class for VectorScript layout dialog | SDK:Creating handler class for manual layout dialog | SDK:Working with Dynamic Data Exchange (DDX) |