void GUITable::draw() { if (!IsVisible) return; gui::IGUISkin *skin = Environment->getSkin(); // draw background bool draw_background = m_background.getAlpha() > 0; if (m_border) skin->draw3DSunkenPane(this, m_background, true, draw_background, AbsoluteRect, &AbsoluteClippingRect); else if (draw_background) skin->draw2DRectangle(this, m_background, AbsoluteRect, &AbsoluteClippingRect); // get clipping rect core::rect<s32> client_clip(AbsoluteRect); client_clip.UpperLeftCorner.Y += 1; client_clip.UpperLeftCorner.X += 1; client_clip.LowerRightCorner.Y -= 1; client_clip.LowerRightCorner.X -= 1; if (m_scrollbar->isVisible()) { client_clip.LowerRightCorner.X = m_scrollbar->getAbsolutePosition().UpperLeftCorner.X; } client_clip.clipAgainst(AbsoluteClippingRect); // draw visible rows s32 scrollpos = m_scrollbar->getPos(); s32 row_min = scrollpos / m_rowheight; s32 row_max = (scrollpos + AbsoluteRect.getHeight() - 1) / m_rowheight + 1; row_max = MYMIN(row_max, (s32) m_visible_rows.size()); core::rect<s32> row_rect(AbsoluteRect); if (m_scrollbar->isVisible()) row_rect.LowerRightCorner.X -= skin->getSize(gui::EGDS_SCROLLBAR_SIZE); row_rect.UpperLeftCorner.Y += row_min * m_rowheight - scrollpos; row_rect.LowerRightCorner.Y = row_rect.UpperLeftCorner.Y + m_rowheight; for (s32 i = row_min; i < row_max; ++i) { Row *row = &m_rows[m_visible_rows[i]]; bool is_sel = i == m_selected; video::SColor color = m_color; if (is_sel) { skin->draw2DRectangle(this, m_highlight, row_rect, &client_clip); color = m_highlight_text; } for (s32 j = 0; j < row->cellcount; ++j) drawCell(&row->cells[j], color, row_rect, client_clip); row_rect.UpperLeftCorner.Y += m_rowheight; row_rect.LowerRightCorner.Y += m_rowheight; } // Draw children IGUIElement::draw(); }
void PopupMenuWindow::on_render(Canvas &canvas, const Rect &update_rect) { Rect rect = get_geometry().get_size(); if (menu.impl->joiner_width > 0) { Rect joiner_rect(0, 0, menu.impl->joiner_width, part_menubar_joiner.get_css_height()); part_menubar_joiner.render_box(canvas, joiner_rect); } Rect client_box = get_content_box(); int offset = 0; int count = menu.get_item_count(); for (int index = 0; index < count; index++) { PopupMenuItem item = menu.get_item_at(index); bool is_selected = (index == selected); int row_height = 0; if (item.is_separator()) { row_height = part_separator.get_css_height(); Rect separator_render_rect(client_box.left, offset, client_box.right, offset+row_height); Rect separator_content_rect = part_separator.get_content_box(separator_render_rect); separator_content_rect.right -= 4; // This thing is already a hack (render to content to render content as render, wtf? :)) separator_content_rect.top += 3; // More hacks.. separator_content_rect.bottom += 3; // Something is really wrong about this stuff. But it fixes the visual layout. part_separator.render_box(canvas, separator_content_rect); } else { part_item_row.set_pseudo_class(CssStr::selected, is_selected); part_item_icon.set_pseudo_class(CssStr::selected, is_selected); part_item_label.set_pseudo_class(CssStr::selected, is_selected); part_item_row.set_pseudo_class(CssStr::disabled, item.is_disabled()); part_item_icon.set_pseudo_class(CssStr::disabled, item.is_disabled()); part_item_check.set_pseudo_class(CssStr::disabled, item.is_disabled()); part_item_label.set_pseudo_class(CssStr::disabled, item.is_disabled()); part_item_accel_label.set_pseudo_class(CssStr::disabled, item.is_disabled()); row_height = part_item_row.get_css_height(); // row rect Rect row_rect(Point(client_box.left, client_box.top + offset), Size(client_box.right, row_height)); part_item_row.render_box(canvas, row_rect); Rect row_box = part_item_row.get_content_box(row_rect); // icon or check if (item.is_checkable()) { if (item.is_checked()) { Rect rect(Point(row_box.left, (row_box.top + row_box.bottom)/2 - check_size.height/2), check_size); part_item_check.render_box(canvas, rect); } } else { PixelBuffer pbuf_icon = item.get_icon(); if (!pbuf_icon.is_null()) { Size icon_size = pbuf_icon.get_size(); Rect rect(Point(row_box.left, (row_box.top + row_box.bottom)/2 - icon_size.height/2), icon_size); Image image(canvas, pbuf_icon, pbuf_icon.get_size()); //TODO: This is slow, and probably should be cached image.set_linear_filter(false); Colorf color = Colorf::white; if (item.is_disabled()) image.set_alpha(0.25f); image.draw(canvas, rect); } } // item text Size text_size = part_item_label.get_render_text_size(canvas, item.get_text()); Size text_full_size = part_item_label.get_border_box(text_size).get_size(); Rect label_render_rect(row_box.left + icon_column_width, row_box.top, row_box.left + icon_column_width + text_full_size.width, row_box.bottom); Rect label_content_rect = part_item_label.get_content_box(label_render_rect); part_item_label.render_box(canvas, label_render_rect); part_item_label.render_text(canvas, item.get_text(), label_content_rect); int center_y = row_box.get_center().y; int arrow_width = part_submenu_arrow.get_css_width(); int arrow_height = part_submenu_arrow.get_css_height(); if (item.has_submenu()) { Rect arrow_rect( row_box.right - arrow_width, center_y - arrow_height/2, row_box.right, center_y + arrow_height/2); Rect arrow_content = part_submenu_arrow.get_content_box(arrow_rect); part_submenu_arrow.render_box(canvas, arrow_content); } else if (!item.get_accelerator_text().empty()) { // accelerator text Size accel_text_size = part_item_accel_label.get_render_text_size(canvas, item.get_accelerator_text()); Size accel_text_full_size = part_item_accel_label.get_border_box(accel_text_size).get_size(); Rect accel_render_rect( row_box.right-arrow_width-accel_text_full_size.width, label_content_rect.top, row_box.right-arrow_width, label_content_rect.bottom); Rect accel_content_rect = part_item_accel_label.get_content_box(accel_render_rect); part_item_accel_label.render_text( canvas, item.get_accelerator_text(), accel_content_rect); } } offset += row_height; } }