Ejemplo n.º 1
0
void grid::request_reduce_height(const unsigned maximum_height)
{
	point size = get_best_size();
	if(size.y <= static_cast<int>(maximum_height)) {
		/** @todo this point shouldn't be reached, find out why it does. */
		return;
	}

	const unsigned too_high = size.y - maximum_height;
	unsigned reduced = 0;
	for(size_t row = 0; row < rows_; ++row) {
		unsigned wanted_height = row_height_[row] - (too_high - reduced);
		/**
		 * @todo Improve this code.
		 *
		 * Now we try every item to be reduced, maybe items need a flag whether
		 * or not to try to reduce and also evaluate whether the force
		 * reduction is still needed.
		 */
		if(too_high - reduced >= row_height_[row]) {
			DBG_GUI_L << LOG_HEADER << " row " << row << " height "
					  << row_height_[row] << " want to reduce " << too_high
					  << " is too small to be reduced fully try 1 pixel.\n";

			wanted_height = 1;
		}

		/* Reducing the height of a widget causes the widget to save its new size
		in widget::layout_size_. After that, get_best_size() will return that
		size and not the originally calculated optimal size.
		Thus, it's perfectly correct that grid::calculate_best_size() that we
		call later calls get_best_size() for child widgets as if size reduction
		had never happened. */
		const unsigned height = grid_implementation::row_request_reduce_height(
				*this, row, wanted_height);

		if(height < row_height_[row]) {
			unsigned reduction = row_height_[row] - height;

			DBG_GUI_L << LOG_HEADER << " row " << row << " height "
					  << row_height_[row] << " want to reduce " << too_high
					  << " reduced " << reduction << " pixels.\n";

			size.y -= reduction;
			reduced += reduction;
		}

		if(size.y <= static_cast<int>(maximum_height)) {
			break;
		}
	}

	size = calculate_best_size();

	DBG_GUI_L << LOG_HEADER << " Requested maximum " << maximum_height
			  << " resulting height " << size.y << ".\n";

	set_layout_size(size);
}
Ejemplo n.º 2
0
void tgrid::request_reduce_height(const unsigned maximum_height)
{
	tpoint size = get_best_size();
	if(size.y <= static_cast<int>(maximum_height)) {
		/** @todo this point shouldn't be reached, find out why it does. */
		return;
	}

	const unsigned too_high = size.y - maximum_height;
	unsigned reduced = 0;
	for(size_t row = 0; row < rows_; ++row) {
		unsigned wanted_height = row_height_[row] - (too_high - reduced);
		/**
		 * @todo Improve this code.
		 *
		 * Now we try every item to be reduced, maybe items need a flag whether
		 * or not to try to reduce and also evaluate whether the force
		 * reduction is still needed.
		 */
		if(too_high - reduced >= row_height_[row]) {
			DBG_GUI_L << LOG_HEADER << " row " << row << " height "
					  << row_height_[row] << " want to reduce " << too_high
					  << " is too small to be reduced fully try 1 pixel.\n";

			wanted_height = 1;
		}

		const unsigned height = tgrid_implementation::row_request_reduce_height(
				*this, row, wanted_height);

		if(height < row_height_[row]) {
			DBG_GUI_L << LOG_HEADER << " row " << row << " height "
					  << row_height_[row] << " want to reduce " << too_high
					  << " reduced " << row_height_[row] - height
					  << " pixels.\n";

			size.y -= row_height_[row] - height;
			row_height_[row] = height;
		}

		if(size.y <= static_cast<int>(maximum_height)) {
			break;
		}
	}

	size = calculate_best_size();

	DBG_GUI_L << LOG_HEADER << " Requested maximum " << maximum_height
			  << " resulting height " << size.y << ".\n";

	set_layout_size(size);
}
Ejemplo n.º 3
0
tpoint twidget::get_best_size() const
{
	if (is_empty_rect(fix_rect_)) {
		tpoint result = layout_size_;
		if (result == tpoint(0, 0)) {
			result = calculate_best_size();
		}
		return result;

	} else {
		return tpoint(fix_rect_.w, fix_rect_.h);
	}
}
Ejemplo n.º 4
0
tpoint twidget::get_best_size() const
{
	assert(visible_ != INVISIBLE);

	tpoint result = layout_size_;
	if(result == tpoint(0, 0)) {
		result = calculate_best_size();
	}

#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
	last_best_size_ = result;
#endif
	return result;
}
Ejemplo n.º 5
0
void grid::request_placement(dispatcher&, const event::ui_event, bool& handled, bool&)
{
	if (get_window()->invalidate_layout_blocked()) {
		handled = true;
		return;
	}

	point size = get_size();
	point best_size = calculate_best_size();
	if(size.x >= best_size.x && size.y >= best_size.y) {
		place(get_origin(), size);
		handled = true;
		return;
	}

	recalculate_best_size();

	if(size.y >= best_size.y) {
		// We have enough space in the Y direction, but not in the X direction.
		// Try wrapping the content.
		request_reduce_width(size.x);
		best_size = get_best_size();

		if(size.x >= best_size.x && size.y >= best_size.y) {
			// Wrapping succeeded, we still fit vertically.
			place(get_origin(), size);
			handled = true;
			return;
		} else {
			// Wrapping failed, we no longer fit.
			// Reset the sizes of child widgets.
			layout_initialize(true);
		}
	}

	/*
	Not enough space.
	Let the event flow higher up.
	This is a pre-event handler, so the event flows upwards. */
}
Ejemplo n.º 6
0
point widget::get_best_size() const
{
	assert(visible_ != visibility::invisible);

	point result = layout_size_;
	if(result == point()) {
		result = calculate_best_size();
		//Adjust to linked widget size if linked widget size was already calculated.
		if(!get_window()->get_need_layout() && !linked_group_.empty())
		{
			point linked_size = get_window()->get_linked_size(linked_group_);
			result.x = std::max(result.x, linked_size.x);
			result.y = std::max(result.y, linked_size.y);
		}
	}

#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
	last_best_size_ = result;
#endif

	return result;
}
Ejemplo n.º 7
0
void grid::request_reduce_width(const unsigned maximum_width)
{
	point size = get_best_size();
	if(size.x <= static_cast<int>(maximum_width)) {
		/** @todo this point shouldn't be reached, find out why it does. */
		return;
	}

	const unsigned too_wide = size.x - maximum_width;
	unsigned reduced = 0;
	for(size_t col = 0; col < cols_; ++col) {
		if(too_wide - reduced >= col_width_[col]) {
			DBG_GUI_L << LOG_HEADER << " column " << col
					  << " is too small to be reduced.\n";
			continue;
		}

		const unsigned wanted_width = col_width_[col] - (too_wide - reduced);
		const unsigned width
				= grid_implementation::column_request_reduce_width(
						*this, col, wanted_width);

		if(width < col_width_[col]) {
			unsigned reduction = col_width_[col] - width;

			DBG_GUI_L << LOG_HEADER << " reduced " << reduction
					  << " pixels for column " << col << ".\n";

			size.x -= reduction;
			reduced += reduction;
		}

		if(size.x <= static_cast<int>(maximum_width)) {
			break;
		}
	}

	set_layout_size(calculate_best_size());
}
Ejemplo n.º 8
0
void tgrid::place(const tpoint& origin, const tpoint& size)
{
	log_scope2(log_gui_layout, LOG_SCOPE_HEADER);

	/***** INIT *****/

	twidget::place(origin, size);

	if(!rows_ || !cols_) {
		return;
	}

	// call the calculate so the size cache gets updated.
	const tpoint best_size = calculate_best_size();

	assert(row_height_.size() == rows_);
	assert(col_width_.size() == cols_);
	assert(row_grow_factor_.size() == rows_);
	assert(col_grow_factor_.size() == cols_);

	DBG_GUI_L << LOG_HEADER << " best size " << best_size << " available size "
			  << size << ".\n";

	/***** BEST_SIZE *****/

	if(best_size == size) {
		layout(origin);
		return;
	}

	if(best_size.x > size.x || best_size.y > size.y) {
		// The assertion below fails quite often so try to give as much information as possible.
		std::stringstream out;
		out << " Failed to place a grid, we have " << size << " space but we need " << best_size << " space.";
		out << " This happened at a grid with the id '" << id() << "'";
		twidget* pw = parent();
		while(pw != nullptr) {
			out << " in a '" << typeid(*pw).name() << "' with the id '" << pw->id() << "'";
			pw = pw->parent();
		}
		ERR_GUI_L << LOG_HEADER << out.str() << ".\n";

		return;
	}

	/***** GROW *****/

	// expand it.
	if(size.x > best_size.x) {
		const unsigned w = size.x - best_size.x;
		unsigned w_size = std::accumulate(
			col_grow_factor_.begin(), col_grow_factor_.end(), 0);

		DBG_GUI_L << LOG_HEADER << " extra width " << w
			<< " will be divided amount " << w_size << " units in "
			<< cols_ << " columns.\n";

		if(w_size == 0) {
			// If all sizes are 0 reset them to 1
			for(auto & val : col_grow_factor_)
			{
				val = 1;
			}
			w_size = cols_;
		}
		// We might have a bit 'extra' if the division doesn't fix exactly
		// but we ignore that part for now.
		const unsigned w_normal = w / w_size;
		for(unsigned i = 0; i < cols_; ++i) {
			col_width_[i] += w_normal * col_grow_factor_[i];
			DBG_GUI_L << LOG_HEADER << " column " << i
				<< " with grow factor " << col_grow_factor_[i]
			<< " set width to " << col_width_[i] << ".\n";
		}
	}

	if(size.y > best_size.y) {
		const unsigned h = size.y - best_size.y;
		unsigned h_size = std::accumulate(
			row_grow_factor_.begin(), row_grow_factor_.end(), 0);
		DBG_GUI_L << LOG_HEADER << " extra height " << h
			<< " will be divided amount " << h_size << " units in "
			<< rows_ << " rows.\n";

		if(h_size == 0) {
			// If all sizes are 0 reset them to 1
			for(auto & val : row_grow_factor_)
			{
				val = 1;
			}
			h_size = rows_;
		}
		// We might have a bit 'extra' if the division doesn't fix exactly
		// but we ignore that part for now.
		const unsigned h_normal = h / h_size;
		for(unsigned i = 0; i < rows_; ++i) {
			row_height_[i] += h_normal * row_grow_factor_[i];
			DBG_GUI_L << LOG_HEADER << " row " << i << " with grow factor "
				<< row_grow_factor_[i] << " set height to "
				<< row_height_[i] << ".\n";
		}
	}

	layout(origin);
	return;
}
Ejemplo n.º 9
0
tpoint tgrid::recalculate_best_size()
{
	tpoint best_size = calculate_best_size();
	set_layout_size(best_size);
	return best_size;
}