/* BrowserCanvas::showItem * Scrolls the view to show [item] if it is currently off-screen. If * [top] is true, the item will be shown on the top row, otherwise, * the item will be shown on the bottom row *******************************************************************/ void BrowserCanvas::showItem(int item, bool top) { // Check item index if (item < 0 || item >= (int)items_filter.size()) return; // Determine y-position of item int num_cols = GetSize().x / fullItemSizeX(); int y_top = (item / num_cols) * fullItemSizeY(); int y_bottom = y_top + fullItemSizeY(); // Check if item is above current view if (y_top < yoff || y_bottom > yoff + GetSize().y) { if (top) { // Scroll view to show the item on the top row yoff = y_top; if (scrollbar) scrollbar->SetThumbPosition(yoff); } else { // Scroll view to show the item on the bottom row yoff = y_bottom - GetSize().y; if (scrollbar) scrollbar->SetThumbPosition(yoff); } } }
/* BrowserCanvas::showItem * Scrolls the view to show [item] if it is currently off-screen. If * [where] is positive, the item will be shown on the top row; if * negative, the item will be shown on the bottom row; if zero, the * item will be roughly centered. *******************************************************************/ void BrowserCanvas::showItem(int item, int where) { // Check item index if (item < 0 || item >= (int)items_filter.size()) return; // Determine y-position of item int num_cols = GetSize().x / fullItemSizeX(); int y_top = (item / num_cols) * fullItemSizeY(); int y_bottom = y_top + fullItemSizeY(); int _yoff = yoff; // Check if item is outside current view (but always center an item if // asked) if (y_top < yoff || y_bottom > yoff + GetSize().y || where == 0) { if (where > 0) // Scroll view to show the item on the top row yoff = y_top; else if (where < 0) // Scroll view to show the item on the bottom row yoff = y_bottom - GetSize().y; else { // Scroll view to put the item's middle in the middle of the canvas yoff = y_top + (fullItemSizeY() - GetSize().y) / 2; if (yoff < 0) yoff = 0; } if (scrollbar) scrollbar->SetThumbPosition(yoff); } }
/* BrowserCanvas::onMouseEvent * Called when a key is pressed within the canvas *******************************************************************/ void BrowserCanvas::onKeyDown(wxKeyEvent& e) { int num_cols = GetSize().x / fullItemSizeX(); int offset; // Down arrow if (e.GetKeyCode() == WXK_DOWN) offset = num_cols; // Up arrow else if (e.GetKeyCode() == WXK_UP) offset = -1 * num_cols; // Left arrow else if (e.GetKeyCode() == WXK_LEFT) offset = -1; // Right arrow else if (e.GetKeyCode() == WXK_RIGHT) offset = 1; // Page up else if (e.GetKeyCode() == WXK_PAGEUP) offset = -1 * num_cols * max(GetSize().y / fullItemSizeY(), 1); // Page down else if (e.GetKeyCode() == WXK_PAGEDOWN) offset = num_cols * max(GetSize().y / fullItemSizeY(), 1); else { e.Skip(); return; } // Clamp selection int selected = itemIndex(item_selected) + offset; if (selected < 0) selected = 0; else if (selected >= (int)items_filter.size()) selected = (int)items_filter.size() - 1; selectItem(selected); showItem(selected, -1 * offset); // Refresh canvas Refresh(); }
/* BrowserCanvas::onScrollLineDown * Called when the scrollbar recieves a 'line down' command (ie when * the down arrow is clicked) *******************************************************************/ void BrowserCanvas::onScrollLineDown(wxScrollEvent& e) { // Scroll down by one row scrollbar->SetThumbPosition(yoff + fullItemSizeY()); // Update y-offset and refresh yoff = scrollbar->GetThumbPosition(); Refresh(); }
/* BrowserCanvas::onMouseEvent * Called when any mouse event is generated (click, scroll, etc) *******************************************************************/ void BrowserCanvas::onMouseEvent(wxMouseEvent& e) { // --- Scroll wheel --- if (e.GetEventType() == wxEVT_MOUSEWHEEL) { // Detemine the scroll multiplier float scroll_mult = (float)e.GetWheelRotation() / (float)e.GetWheelDelta(); // Scrolling by 1.0 means by 1 row int scroll_amount = (fullItemSizeY()) * -scroll_mult; // Do scroll scrollbar->SetThumbPosition(yoff + scroll_amount); // Update y-offset and refresh yoff = scrollbar->GetThumbPosition(); Refresh(); } // --- Left click --- else if (e.GetEventType() == wxEVT_LEFT_DOWN) { // Clear selection item_selected = NULL; // Get column clicked & number of columns int col_width = GetSize().x / num_cols; int col = e.GetPosition().x / col_width; // Get row clicked int row = (e.GetPosition().y - top_y) / (fullItemSizeY()); // Select item selectItem(top_index + (row * num_cols) + col); Refresh(); } e.Skip(); }
/* BrowserCanvas::updateScrollBar * Updates the associated scrollbar's properties depending on the * number of items, the canvas size, etc. *******************************************************************/ void BrowserCanvas::updateScrollBar() { // Do nothing special if no scrollbar present if (!scrollbar) return; // Determine total height of all items int rows = (double)items_filter.size() / (double)num_cols + 0.9999; int total_height = rows * fullItemSizeY(); // Setup scrollbar scrollbar->SetScrollbar(scrollbar->GetThumbPosition(), GetSize().y, total_height, GetSize().y); yoff = scrollbar->GetThumbPosition(); }
/* BrowserCanvas::getViewedIndex * Return the unfiltered index of the item currently in the middle of the * viewport, or -1 if no items are visible *******************************************************************/ int BrowserCanvas::getViewedIndex() { if (items_filter.empty()) return -1; int viewport_height = GetSize().y; int row_height = fullItemSizeY(); int viewport_mid_y = yoff + viewport_height / 2.0; int viewed_row = viewport_mid_y / row_height; int viewed_item_id = (viewed_row + 0.5) * num_cols; if (viewed_item_id < 0) viewed_item_id = 0; else if ((unsigned)viewed_item_id >= items_filter.size()) viewed_item_id = items_filter.size() - 1; return items_filter[viewed_item_id]; }
/* BrowserCanvas::updateLayout * Updates variables concerning the object layout, then updates the * associated scrollbar's properties depending on the number of * items, the canvas size, etc. *******************************************************************/ void BrowserCanvas::updateLayout(int viewed_index) { if (scrollbar && viewed_index < 0) viewed_index = getViewedIndex(); // Determine number of columns num_cols = GetSize().x / fullItemSizeX(); // Update the scrollbar, if present if (scrollbar) { // Try to keep the view scrolled to roughly the same area: find the // item currently in the middle, and keep it there // If the given item is no longer visible, find the first filtered item // after it that is int filtered_viewed_index = -1; for (unsigned a = 0; a < items_filter.size(); a++) if (items_filter[a] >= viewed_index) { filtered_viewed_index = a; break; } if (filtered_viewed_index < 0) filtered_viewed_index = items_filter.size() - 1; // Determine total height of all items int rows = (double)items_filter.size() / (double)num_cols + 0.9999; int total_height = rows * fullItemSizeY(); int viewport_height = GetSize().y; // Setup scrollbar scrollbar->SetScrollbar(scrollbar->GetThumbPosition(), viewport_height, total_height, viewport_height); showItem(filtered_viewed_index, 0); } Refresh(); }
/* BrowserCanvas::draw * Handles drawing of the canvas content *******************************************************************/ void BrowserCanvas::draw() { // Setup the viewport glViewport(0, 0, GetSize().x, GetSize().y); // Setup the screen projection glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, GetSize().x, GetSize().y, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Setup colours rgba_t col_bg, col_text; bool text_shadow = true; if (browser_bg_type == 1) { // Get system panel background colour wxColour bgcolwx = Drawing::getPanelBGColour(); col_bg.set(bgcolwx.Red(), bgcolwx.Green(), bgcolwx.Blue()); // Get system text colour wxColour textcol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); col_text.set(textcol.Red(), textcol.Green(), textcol.Blue()); // Check text colour brightness, if it's dark don't draw text shadow rgba_t col_temp = col_text; wxColor::MakeGrey(&col_temp.r, &col_temp.g, &col_temp.b); if (col_temp.r < 60) text_shadow = false; } else { // Otherwise use black background col_bg.set(0, 0, 0); // And white text col_text.set(255, 255, 255); } // Clear glClearColor(col_bg.fr(), col_bg.fg(), col_bg.fb(), 1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Translate to inside of pixel (otherwise inaccuracies can occur on certain gl implementations) if (OpenGL::accuracyTweak()) glTranslatef(0.375f, 0.375f, 0); // Draw background if required if (browser_bg_type == 0) drawCheckeredBackground(); // Init for texture drawing glEnable(GL_TEXTURE_2D); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glLineWidth(2.0f); // Draw items int x = item_border; int y = item_border; int col_width = GetSize().x / num_cols; int col = 0; top_index = -1; for (unsigned a = 0; a < items_filter.size(); a++) { // If we're not yet into the viewable area, skip if (y < yoff - fullItemSizeY()) { col++; if (col >= num_cols) { col = 0; y += fullItemSizeY(); // Canvas is filled, stop drawing if (y > yoff + GetSize().y) break; } continue; } // If we're drawing the first non-hidden item, save it if (top_index < 0) { top_index = a; top_y = y - yoff; } // Determine current x position int xgap = (col_width - fullItemSizeX()) * 0.5; x = item_border + xgap + (col * col_width); // Draw selection box if selected if (item_selected == items[items_filter[a]]) { // Setup glDisable(GL_TEXTURE_2D); glColor4f(0.3f, 0.5f, 1.0f, 0.3f); glPushMatrix(); glTranslated(x, y - yoff, 0); glTranslated(-item_border, -item_border, 0); // Selection background glBegin(GL_QUADS); glVertex2i(2, 2); glVertex2i(2, fullItemSizeY()-3); glVertex2i(fullItemSizeX()-3, fullItemSizeY()-3); glVertex2i(fullItemSizeX()-3, 2); glEnd(); // Selection border glColor4f(0.6f, 0.8f, 1.0f, 1.0f); glBegin(GL_LINE_LOOP); glVertex2i(2, 2); glVertex2i(2, fullItemSizeY()-3); glVertex2i(fullItemSizeX()-3, fullItemSizeY()-3); glVertex2i(fullItemSizeX()-3, 2); glEnd(); // Finish glPopMatrix(); glEnable(GL_TEXTURE_2D); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); } // Draw item if (item_size <= 0) items[items_filter[a]]->draw(browser_item_size, x, y - yoff, font, show_names, item_type, col_text, text_shadow); else items[items_filter[a]]->draw(item_size, x, y - yoff, font, show_names, item_type, col_text, text_shadow); // Move over for next item col++; if (col >= num_cols) { col = 0; y += fullItemSizeY(); // Canvas is filled, stop drawing if (y > yoff + GetSize().y) break; } } // Swap Buffers SwapBuffers(); }