From 4c28b3f19f9e4c0ff432a0bfc0ef2519a3694ba2 Mon Sep 17 00:00:00 2001 From: PulkoMandy Date: Sat, 16 Jul 2022 13:37:30 +0200 Subject: [PATCH] Screen preferences: use a matrix menu for the resolution list When there are a lot of display resolutions available, the menu can become very high. Switch to a "matrix" menu with 3 columns in this case to keep it a reasonable size. Change-Id: I826be06a91bd1bcae600cc333e34d4a9dd7b3df5 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5320 Reviewed-by: nephele nephele Reviewed-by: John Scipione Reviewed-by: Adrien Destugues Tested-by: Commit checker robot --- src/preferences/screen/ScreenWindow.cpp | 61 ++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/src/preferences/screen/ScreenWindow.cpp b/src/preferences/screen/ScreenWindow.cpp index 9e4f33777e..f60d53dac4 100644 --- a/src/preferences/screen/ScreenWindow.cpp +++ b/src/preferences/screen/ScreenWindow.cpp @@ -307,13 +307,53 @@ ScreenWindow::ScreenWindow(ScreenSettings* settings) B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING); controlsBox->AddChild(outerControlsView); - fResolutionMenu = new BPopUpMenu("resolution", true, true); + menu_layout layout = B_ITEMS_IN_COLUMN; + // There are modes in the list with the same resolution but different bpp or refresh rates. + // We don't want to take these into account when computing the menu layout, so we need to + // count how many entries we will really have in the menu. + int fullModeCount = fScreenMode.CountModes(); + int modeCount = 0; + int index = 0; uint16 maxWidth = 0; uint16 maxHeight = 0; uint16 previousWidth = 0; uint16 previousHeight = 0; - for (int32 i = 0; i < fScreenMode.CountModes(); i++) { + for (int32 i = 0; i < fullModeCount; i++) { + screen_mode mode = fScreenMode.ModeAt(i); + + if (mode.width == previousWidth && mode.height == previousHeight) + continue; + modeCount++; + previousWidth = mode.width; + previousHeight = mode.height; + if (maxWidth < mode.width) + maxWidth = mode.width; + if (maxHeight < mode.height) + maxHeight = mode.height; + } + + if (modeCount > 16) + layout = B_ITEMS_IN_MATRIX; + + fResolutionMenu = new BPopUpMenu("resolution", true, true, layout); + + // Compute the size we should allocate to each item in the menu + BRect itemRect; + if (layout == B_ITEMS_IN_MATRIX) { + BFont menuFont; + font_height fontHeight; + + fResolutionMenu->GetFont(&menuFont); + menuFont.GetHeight(&fontHeight); + itemRect.left = itemRect.top = 0; + itemRect.bottom = fontHeight.ascent + fontHeight.descent + 4; + itemRect.right = menuFont.StringWidth("99999x99999") + 16; + rows = modeCount / 3 + 1; + } + + index = 0; + for (int32 i = 0; i < fullModeCount; i++) { screen_mode mode = fScreenMode.ModeAt(i); if (mode.width == previousWidth && mode.height == previousHeight) @@ -321,10 +361,6 @@ ScreenWindow::ScreenWindow(ScreenSettings* settings) previousWidth = mode.width; previousHeight = mode.height; - if (maxWidth < mode.width) - maxWidth = mode.width; - if (maxHeight < mode.height) - maxHeight = mode.height; BMessage* message = new BMessage(POP_RESOLUTION_MSG); message->AddInt32("width", mode.width); @@ -333,7 +369,18 @@ ScreenWindow::ScreenWindow(ScreenSettings* settings) BString name; name << mode.width << " x " << mode.height; - fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); + if (layout == B_ITEMS_IN_COLUMN) + fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); + else { + int y = index % rows; + int x = index / rows; + itemRect.OffsetTo(x * itemRect.Width(), y * itemRect.Height()); + printf("i %d x %d y %d\n", index, x, y); + itemRect.PrintToStream(); + fResolutionMenu->AddItem(new BMenuItem(name.String(), message), itemRect); + } + + index++; } fMonitorView->SetMaxResolution(maxWidth, maxHeight);