Page 1 of 1

Setting parent

Posted: 30 Apr 2015, 21:09
by Rick
I have a function where I create a border control and I give it a background based on a resource name. After this function is done I don't see anything and I'm guessing it's because it has no parent. How can I set the parent and is there anything else I'm missing here? I get that I have a memory leak with this but I'll store the border in a list later I just want to get it displayed on screen and test with different resolutions.
int LuaNoesis::CreateItem(lua_State* L)
{
	int iconHeight = lua_tonumber(L, -1);
	int iconWidth = lua_tonumber(L, -2);
	string itemName = lua_tostring(L, -3);

	// get 1 inventory slot so we can get it's size to help us resize our new item so it matches the sceen resolution since the inventory slots automatically scale based on screen resolution
	UIElement* e = uiRenderer->GetXAML()->FindName<UIElement>("_00");

	// create a border element where the image inside is the resource item name and where the size of the border is the width and height multiplied by the size of 1 inventory slot (since this can change based on res)
	Border* item = new Border();
	Ptr<ResourceKeyString> key = ResourceKeyString::Create(itemName.c_str());
	ImageBrush* itemIcon = uiRenderer->GetXAML()->FindResource<ImageBrush>(key.GetPtr());
	item->SetBackground(itemIcon);
	item->SetWidth(e->GetRenderSize().width);
	item->SetHeight(e->GetRenderSize().height);

	return 0;
}
The parent would be a Grid control so would also need to know how to set this items position as well.

Re: Setting parent

Posted: 30 Apr 2015, 22:08
by sfernandez
Hi,

You can add the Border to the Grid.Children collection. And Grid children are positioned inside the Grid using the attached properties Grid.Row, Grid.Column, Grid.RowSpan and Grid.ColumnSpan, and all the common layout properties (Margin, HorizontalAlignment, VerticalAlignment) to place it inside the cell:
void AddBorder(Grid* parent, UIElement* child,
  NsUInt32 row, NsUInt32 column, NsUInt32 rowSpan, NsUInt32 columnSpan)
{
  Grid::SetRow(child, row);
  Grid::SetColumn(child, column);
  Grid::SetRowSpan(child, rowSpan);
  Grid::SetColumnSpan(child, columnSpan);
  parent->GetChildren()->Add(child);
}
int LuaNoesis::CreateItem(lua_State* L)
{
   //...
   Border* item = new Border();
   //...
   AddBorder(parentGrid, item, 0, 0, 1, 1); // place border in Row=0, Column=0

   return 0;
} 

Re: Setting parent

Posted: 01 May 2015, 01:58
by Rick
So that worked to make the icon look like it's inside the grid area. I am curious though as to when I do the dragging idea how to move the border around with the mouse. I noticed in your inventory example you were using a canvas. Is that required? I don't have a canvas holding all of this. I just have a master grid. What are my options here to make that border follow my mouse when it's moving once I handle the mousedown and move events like you guys did.

If I do use a canvas I assume it would have to be a parent to the grids so that it covers the entire screen. If that is the case is there a way to make something always draw on top of everything else on the canvas?

Re: Setting parent

Posted: 06 May 2015, 01:46
by sfernandez
So that worked to make the icon look like it's inside the grid area. I am curious though as to when I do the dragging idea how to move the border around with the mouse. I noticed in your inventory example you were using a canvas. Is that required? I don't have a canvas holding all of this. I just have a master grid. What are my options here to make that border follow my mouse when it's moving once I handle the mousedown and move events like you guys did.
You don't require a Canvas to move elements in the screen, you can assign a TranslateTransform to the RenderTransform property of any element and use that to move it:
Ptr<Border> border = *new Border();
Ptr<TranslateTransform> trans = *new TranslateTransform();
border->SetRenderTransform(trans.GetPtr());
...
trans->SetX(mousePos.x);
trans->SetY(mousePos.y); 
Canvas is just another type of Panel that uses the Canvas.Left (or Canvas.Right) and Canvas.Top (or Canvas.Bottom) properties to layout children of the panel.
If I do use a canvas I assume it would have to be a parent to the grids so that it covers the entire screen. If that is the case is there a way to make something always draw on top of everything else on the canvas?
In NoesisGUI the UI visual tree is drawn traversing the elements depth-first. So first children is the first one to be drawn, and last children is the last one to be drawn.
If you add your border at the end of the Children collection of the root Panel, then it will be on top of all other elements in the UI:
rootPanel->GetChildren()->Add(border.GetPtr());

Re: Setting parent

Posted: 08 May 2015, 03:08
by jsantos
Border* item = new Border();
I wanted to comment about this line of code, because there is an important missing detail. That line will leak because you are not manually freeing the memory in your code. Problem is that it is not easy to know when to free a GUI element. That is the reason we provide smart pointers. So instead of the above line you should do:
Ptr<Border> item = *new Border();
That way, the border is removed whenever there are no more references to it.