Exemplo n.º 1
0
void
Grid::PostRender (Context *ctx, Region *region, bool skip_children)
{
	// render our chidren if we need to
	if (!skip_children) {
		VisualTreeWalker walker = VisualTreeWalker (this, ZForward, false);
		while (UIElement *child = walker.Step ())
			child->DoRender (ctx, region);
	}
	
	if (GetShowGridLines () && ctx->IsMutable ()) {
		double offset = 0;
		double dash = 4;
		ColumnDefinitionCollection *cols = GetColumnDefinitionsNoAutoCreate ();
		RowDefinitionCollection *rows = GetRowDefinitionsNoAutoCreate ();
		cairo_t *cr = ctx->Cairo ();
		int col_count = cols ? cols->GetCount () : 0;
		int row_count = rows ? rows->GetCount () : 0;
		
		cairo_save (cr);
		RenderLayoutClip (cr);
		cairo_set_line_width(cr, 1.0);
		// Initially render a blue color
		cairo_set_dash (cr, &dash, 1, offset);
		cairo_set_source_rgb (cr, 0.4, 0.4, 1.0);
		cairo_new_path (cr);

		// Draw gridlines between each pair of columns/rows
		for (int count = 0; count < 2; count++) {
			for (int i = 0, offset = 0; i < col_count - 1; i++) {
				ColumnDefinition *def = cols->GetValueAt (i)->AsColumnDefinition ();
				offset += def->GetActualWidth ();
				cairo_move_to (cr, offset, 0);
				cairo_line_to (cr, offset, GetActualHeight ());
			}
			
			for (int i = 0, offset = 0; i < row_count - 1; i++) {
				RowDefinition *def = rows->GetValueAt (i)->AsRowDefinition ();
				offset += def->GetActualHeight ();
				cairo_move_to (cr, 0, offset);
				cairo_line_to (cr, GetActualWidth (), offset);
			}
			
			cairo_stroke (cr);
			
			// For the second pass render a yellow color in the gaps between the previous dashes
			cairo_set_dash (cr, &dash, 1, dash);
			cairo_set_source_rgb (cr, 1.0, 1.0, 0.3);
		}
		cairo_restore (cr);
	}		

	// Chain up, but skip children since we've already rendered them here.
	UIElement::PostRender (ctx, region, true);
}
Exemplo n.º 2
0
Size 
Canvas::ArrangeOverrideWithError (Size finalSize, MoonError *error)
{
	VisualTreeWalker walker = VisualTreeWalker (this);
	while (FrameworkElement *child = (FrameworkElement *)walker.Step ()) {
		Size desired = child->GetDesiredSize ();
		Rect child_final = Rect (GetLeft (child), GetTop (child),
					 desired.width, desired.height);
		child->ArrangeWithError (child_final, error);
		//child->ClearValue (LayoutInformation::LayoutClipProperty);
	}

	return finalSize;
}
Exemplo n.º 3
0
Size
Canvas::MeasureOverrideWithError (Size availableSize, MoonError *error)
{
	Size childSize = Size (INFINITY, INFINITY); 

	VisualTreeWalker walker = VisualTreeWalker (this);
	while (UIElement *child = walker.Step ()) {
		child->MeasureWithError (childSize, error);
	}

	Size desired = Size (0,0);

	return desired;
}
Exemplo n.º 4
0
Size
Grid::ArrangeOverrideWithError (Size finalSize, MoonError *error)
{
	ColumnDefinitionCollection *columns = GetColumnDefinitionsNoAutoCreate ();
	RowDefinitionCollection *rows = GetRowDefinitionsNoAutoCreate ();

	int col_count = columns ? columns->GetCount () : 0;
	int row_count = rows ? rows->GetCount () : 0;

	RestoreMeasureResults ();

	Size total_consumed = Size (0, 0);
	for (int c = 0; c < col_matrix_dim; c++)
		total_consumed.width += col_matrix [c][c].size;
	for (int r = 0; r < row_matrix_dim; r++)
		total_consumed.height += row_matrix [r][r].size;

	if (total_consumed.width != finalSize.width)
		ExpandStarCols (finalSize);
	if (total_consumed.height != finalSize.height)
		ExpandStarRows (finalSize);

	for (int c = 0; c < col_count; c++)
		columns->GetValueAt (c)->AsColumnDefinition ()->SetActualWidth (col_matrix [c][c].size);
	for (int r = 0; r < row_count; r++)
		rows->GetValueAt (r)->AsRowDefinition ()->SetActualHeight (row_matrix [r][r].size);

	VisualTreeWalker walker = VisualTreeWalker (this);
	while (UIElement *child = walker.Step ()) {
		gint32 col = MIN (Grid::GetColumn (child), col_matrix_dim - 1);
		gint32 row = MIN (Grid::GetRow (child), row_matrix_dim - 1);
		gint32 colspan = MIN (Grid::GetColumnSpan (child), col_matrix_dim - col);
		gint32 rowspan = MIN (Grid::GetRowSpan (child), row_matrix_dim - row);

		Rect child_final = Rect (0, 0, 0, 0);
		for (int c = 0; c < col; c++)
			child_final.x += col_matrix [c][c].size;
		for (int c = col; c < col + colspan; c++)
			child_final.width += col_matrix [c][c].size;

		for (int r = 0; r < row; r++)
			child_final.y += row_matrix [r][r].size;
		for (int r = row; r < row + rowspan; r++)
			child_final.height += row_matrix [r][r].size;

		child->ArrangeWithError (child_final, error);
	}

	return finalSize;
}
Exemplo n.º 5
0
Size
Border::MeasureOverrideWithError (Size availableSize, MoonError *error)
{
	Size desired = Size (0,0);

	Thickness border = *GetPadding () + *GetBorderThickness ();

	// Get the desired size of our child, and include any margins we set
	VisualTreeWalker walker = VisualTreeWalker (this);
	while (UIElement *child = walker.Step ()) {
		child->MeasureWithError (availableSize.GrowBy (-border), error);
		desired = child->GetDesiredSize ();
	}

	desired = desired.GrowBy (border);

	desired = desired.Min (availableSize);

	return desired;
}
Exemplo n.º 6
0
Size
Border::ArrangeOverrideWithError (Size finalSize, MoonError *error)
{
	Thickness border = *GetPadding () + *GetBorderThickness ();
	Size arranged = finalSize;
	
	VisualTreeWalker walker = VisualTreeWalker (this);
	while (UIElement *child = walker.Step ()) {
		Rect childRect (0,0,finalSize.width,finalSize.height);

		childRect = childRect.GrowBy (-border);


		child->ArrangeWithError (childRect, error);

		arranged = Size (childRect.width, childRect.height).GrowBy (border);

		arranged = arranged.Max (finalSize);
	}

	return finalSize;
}
Exemplo n.º 7
0
Size
Grid::MeasureOverrideWithError (Size availableSize, MoonError *error)
{
	Size totalSize = availableSize;

	ColumnDefinitionCollection *columns = GetColumnDefinitionsNoAutoCreate ();
	RowDefinitionCollection *rows = GetRowDefinitionsNoAutoCreate ();

	int col_count = columns ? columns->GetCount () : 0;
	int row_count = rows ? rows->GetCount () : 0;
	Size total_stars = Size (0,0);

	bool empty_rows = row_count == 0;
	bool empty_cols = col_count == 0;

	if (empty_rows) row_count = 1;
	if (empty_cols) col_count = 1;

	CreateMatrices (row_count, col_count);

	if (empty_rows) {
		row_matrix [0][0] = Segment (0.0, 0, INFINITY, GridUnitTypeStar);
		row_matrix [0][0].stars = 1.0;
		total_stars.height += 1.0;
	}
	else {
		for (int i = 0; i < row_count; i ++) {
			RowDefinition *rowdef = rows->GetValueAt (i)->AsRowDefinition ();
			GridLength* height = rowdef->GetHeight();

			rowdef->SetActualHeight (INFINITY);
			row_matrix [i][i] = Segment (0.0, rowdef->GetMinHeight (), rowdef->GetMaxHeight (), height->type);

			if (height->type == GridUnitTypePixel) {
				row_matrix [i][i].size = Grid::Clamp (height->val, row_matrix [i][i].min, row_matrix [i][i].max);
				rowdef->SetActualHeight (row_matrix [i][i].size);
			}
			if (height->type == GridUnitTypeStar) {
				row_matrix [i][i].stars = height->val;
				total_stars.height += height->val;
			}
		}
	}

	if (empty_cols) {
		col_matrix [0][0] = Segment (0.0, 0, INFINITY, GridUnitTypeStar);
		col_matrix [0][0].stars = 1.0;
		total_stars.width += 1.0;
	}
	else {
		for (int i = 0; i < col_count; i ++) {
			ColumnDefinition *coldef = columns->GetValueAt (i)->AsColumnDefinition ();
			GridLength *width = coldef->GetWidth ();

			coldef->SetActualWidth (INFINITY);
			col_matrix [i][i] = Segment (0.0, coldef->GetMinWidth (), coldef->GetMaxWidth (), width->type);

			if (width->type == GridUnitTypePixel) {
				col_matrix [i][i].size = Grid::Clamp (width->val, col_matrix [i][i].min, col_matrix [i][i].max);
				coldef->SetActualWidth (col_matrix [i][i].size);
			}
			if (width->type == GridUnitTypeStar) {
				col_matrix [i][i].stars = width->val;
				total_stars.width += width->val;
			}
		}
	}

	List sizes;
	GridNode *node;
	GridNode *separator = new GridNode (NULL, 0, 0, 0);
	sizes.Append (separator);
	
	// Pre-process the grid children so that we know what types of elements we have so
	// we can apply our special measuring rules.
	GridWalker grid_walker (this, row_matrix, row_matrix_dim, col_matrix, col_matrix_dim);
	for (int i = 0; i < 6; i++) {
		// These bools tell us which grid element type we should be measuring. i.e.
		// 'star/auto' means we should measure elements with a star row and auto col
		bool auto_auto = i == 0;
		bool star_auto = i == 1;
		bool auto_star = i == 2;
		bool star_auto_again = i == 3;
		bool non_star = i == 4;
		bool remaining_star = i == 5;
		
		VisualTreeWalker walker = VisualTreeWalker (this);
		while (UIElement *child = walker.Step ()) {
			gint32 col, row;
			gint32 colspan, rowspan;
			Size child_size = Size (0,0);
			bool star_col = false;
			bool star_row = false;
			bool auto_col = false;
			bool auto_row = false;

			col = MIN (Grid::GetColumn (child), col_count - 1);
			row = MIN (Grid::GetRow (child), row_count - 1);
			colspan = MIN (Grid::GetColumnSpan (child), col_count - col);
			rowspan = MIN (Grid::GetRowSpan (child), row_count - row);

			for (int r = row; r < row + rowspan; r++) {
				star_row |= row_matrix [r][r].type == GridUnitTypeStar;
				auto_row |= row_matrix [r][r].type == GridUnitTypeAuto;
			}
			for (int c = col; c < col + colspan; c++) {
				star_col |= col_matrix [c][c].type == GridUnitTypeStar;
				auto_col |= col_matrix [c][c].type == GridUnitTypeAuto;
			}

			// This series of if statements checks whether or not we should measure
			// the current element and also if we need to override the sizes
			// passed to the Measure call. 
			
			// If the element has Auto rows and Auto columns and does not span Star
			// rows/cols it should only be measured in the auto_auto phase.
			// There are similar rules governing auto/star and star/auto elements.
			// NOTE: star/auto elements are measured twice. The first time with
			// an override for height, the second time without it.
			if (auto_row && auto_col && !star_row && !star_col) {
				if (!auto_auto)
					continue;
				child_size.width = INFINITY;
				child_size.height = INFINITY;
			}
			else if (star_row && auto_col && !star_col) {
				if (!(star_auto || star_auto_again))
					continue;

				if (star_auto && grid_walker.HasAutoStar ())
					child_size.height = INFINITY;
				child_size.width = INFINITY;
			} else if (auto_row && star_col && !star_row) {
				if (!auto_star)
					continue;
				
				child_size.height = INFINITY;
			} else if ((auto_row || auto_col) && !(star_row || star_col)) {
				if (!non_star)
					continue;
				if (auto_row)
					child_size.height = INFINITY;
				if (auto_col)
					child_size.width = INFINITY;
			} else if (!(star_row || star_col)) {
				if (!non_star)
					continue;
			} else {
				if (!remaining_star)
					continue;
			}

			for (int r = row; r < row + rowspan; r++) {
				if (row_matrix [r][r].type == GridUnitTypeStar) {
					double v = availableSize.height * row_matrix [r][r].stars / total_stars.height;
					child_size.height += Grid::Clamp (v, row_matrix [r][r].min, row_matrix [r][r].max);
				} else {
					child_size.height += row_matrix [r][r].size;
				}
			}
			for (int c = col; c < col + colspan; c++) {
				if (col_matrix [c][c].type == GridUnitTypeStar) {
					double v = availableSize.width * col_matrix [c][c].stars / total_stars.width;
					child_size.width += Grid::Clamp (v, col_matrix [c][c].min, col_matrix [c][c].max);
				} else {
					child_size.width += col_matrix [c][c].size;
				}
			}

			child->MeasureWithError (child_size, error);
			Size desired = child->GetDesiredSize();
	
			// Elements distribute their height based on two rules:
			// 1) Elements with rowspan/colspan == 1 distribute their height first
			// 2) Everything else distributes in a LIFO manner.
			// As such, add all UIElements with rowspan/colspan == 1 after the separator in
			// the list and everything else before it. Then to process, just keep popping
			// elements off the end of the list.
			if (!star_auto) {
				node = new GridNode (row_matrix, row + rowspan - 1, row, desired.height);
				sizes.InsertBefore (node, node->row == node->col ? separator->next : separator);
			}
			node = new GridNode (col_matrix, col + colspan  - 1, col, desired.width);
			sizes.InsertBefore (node, node->row == node->col ? separator->next : separator);
		}
		
		sizes.Unlink (separator);

		while (GridNode *node= (GridNode *) sizes.Last ()) {
			node->matrix [node->row][node->col].size = MAX (node->matrix [node->row][node->col].size, node->size);
			AllocateGridSegments (row_count, col_count);
			sizes.Remove (node);
		}

		// Calculate how much unused space we have so the next round of
		// measurements uses the right sizes for Star segments
		availableSize = totalSize;
		for (int r = 0; r < row_matrix_dim; r++)
			if (row_matrix [r][r].type != GridUnitTypeStar)
				availableSize.height = MAX (availableSize.height - row_matrix [r][r].size, 0);

		for (int c = 0; c < col_matrix_dim; c++)
			if (col_matrix [c][c].type != GridUnitTypeStar)
				availableSize.width = MAX (availableSize.width - col_matrix [c][c].size, 0);

		sizes.Append (separator);
	}
	
	// Once we have measured and distributed all sizes, we have to store
	// the results. Every time we want to expand the rows/cols, this will
	// be used as the baseline.
	SaveMeasureResults ();
	
	sizes.Remove (separator);

	// We have to calulate the desired grid size before expanding
	// star segments to consume available space.
	Size grid_size = Size (0, 0);
	for (int c = 0; c < col_count; c ++)
		grid_size.width += col_matrix [c][c].size;
	for (int r = 0; r < row_count; r ++)
		grid_size.height += row_matrix [r][r].size;


	// This is where we do the final expansion of star rows. Right now the value
	// of 'size' for star segments in row_matrix and col_matrix contains the
	// size that the segments would naturally take up.

	bool hasChildren = GetChildren ()->GetCount () > 0;
	if (totalSize.width != INFINITY && hasChildren)
		ExpandStarCols (totalSize);
	if (totalSize.height != INFINITY && hasChildren)
		ExpandStarRows (totalSize);

	// now choose whichever is smaller, our chosen size or the availableSize.
	return grid_size;
}