summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2017-12-18 19:30:06 +0900
committerTomaž Vajngerl <quikee@gmail.com>2017-12-19 05:26:16 +0100
commit9f3b61e51f7f9de11436b0e4eaec164f2656fbdd (patch)
treeec02561c9b95895c0b5dbc53c49a2bbb64c4566e
parente11234d8d8d8ff2744b77a128f845dbe8e6faa1e (diff)
show rest of the menu bar in a pop-up if the are is too small
In case when the window is to small to show the whole menu then the use couldn't access the rest of the items in the menu. This change adds a button in the end (using the ">>" marker as in toolbar) which on click adds a pop-up that shows the rest of the menu items. Change-Id: I9218dba504464bdd44d61ebb383f7674f3df760f Reviewed-on: https://gerrit.libreoffice.org/46711 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--include/vcl/menu.hxx1
-rw-r--r--vcl/source/window/menu.cxx88
-rw-r--r--vcl/source/window/menubarwindow.cxx41
-rw-r--r--vcl/source/window/menubarwindow.hxx1
-rw-r--r--vcl/source/window/menuitemlist.hxx3
5 files changed, 130 insertions, 4 deletions
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index aa3ee35d2c49..428484d0859c 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -164,6 +164,7 @@ protected:
SAL_DLLPRIVATE Menu* ImplFindMenu( sal_uInt16 nId );
SAL_DLLPRIVATE Size ImplCalcSize( vcl::Window* pWin );
SAL_DLLPRIVATE bool ImplIsVisible( sal_uInt16 nPos ) const;
+ SAL_DLLPRIVATE bool ImplCurrentlyHiddenOnGUI(sal_uInt16 nPos) const;
SAL_DLLPRIVATE bool ImplIsSelectable( sal_uInt16 nPos ) const;
SAL_DLLPRIVATE sal_uInt16 ImplGetVisibleItemCount() const;
SAL_DLLPRIVATE sal_uInt16 ImplGetFirstVisible() const;
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index b6b2faa5206b..983a25a11ad6 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -121,8 +121,50 @@ void ImplClosePopupToolBox( const VclPtr<vcl::Window>& pWin )
}
}
+// TODO: Move to common code with the same function in toolbox
+// Draw the ">>" - more indictor at the coordinates
+void lclDrawMoreIndicator(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ rRenderContext.Push(PushFlags::FILLCOLOR | PushFlags::LINECOLOR);
+ rRenderContext.SetLineColor();
+
+ if (rRenderContext.GetSettings().GetStyleSettings().GetFaceColor().IsDark())
+ rRenderContext.SetFillColor(Color(COL_WHITE));
+ else
+ rRenderContext.SetFillColor(Color(COL_BLACK));
+ float fScaleFactor = rRenderContext.GetDPIScaleFactor();
+
+ int linewidth = 1 * fScaleFactor;
+ int space = 4 * fScaleFactor;
+
+ long width = 8 * fScaleFactor;
+ long height = 5 * fScaleFactor;
+
+ //Keep odd b/c drawing code works better
+ if ( height % 2 == 0 )
+ height--;
+
+ long heightOrig = height;
+
+ long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
+ long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
+ while( height >= 1)
+ {
+ rRenderContext.DrawRect( tools::Rectangle( x, y, x + linewidth, y ) );
+ x += space;
+ rRenderContext.DrawRect( tools::Rectangle( x, y, x + linewidth, y ) );
+ x -= space;
+ y++;
+ if( height <= heightOrig / 2 + 1) x--;
+ else x++;
+ height--;
+ }
+ rRenderContext.Pop();
}
+} // end anonymouse namespace
+
+
Menu::Menu()
: mpFirstDel(nullptr),
pItemList(new MenuItemList),
@@ -1138,6 +1180,22 @@ Menu& Menu::operator=( const Menu& rMenu )
return *this;
}
+// Returns true if the item is completely hidden on the GUI and shouldn't
+// be possible to interact with
+bool Menu::ImplCurrentlyHiddenOnGUI(sal_uInt16 nPos) const
+{
+ MenuItemData* pData = pItemList->GetDataFromPos(nPos);
+ if (pData)
+ {
+ MenuItemData* pPreviousData = pItemList->GetDataFromPos( nPos - 1 );
+ if (pPreviousData && pPreviousData->bHiddenOnGUI)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
bool Menu::ImplIsVisible( sal_uInt16 nPos ) const
{
bool bVisible = true;
@@ -1696,6 +1754,8 @@ void Menu::ImplPaint(vcl::RenderContext& rRenderContext, Size const & rSize,
if (!pThisItemOnly && !IsMenuBar() && nTitleHeight > 0)
ImplPaintMenuTitle(rRenderContext, tools::Rectangle(aTopLeft, aOutSz));
+ bool bHiddenItems = false; // are any items on the GUI hidden
+
for (size_t n = 0; n < nCount; n++)
{
MenuItemData* pData = pItemList->GetDataFromPos( n );
@@ -1921,7 +1981,25 @@ void Menu::ImplPaint(vcl::RenderContext& rRenderContext, Size const & rSize,
{
nMaxItemTextWidth -= nFontHeight - nExtra;
}
- OUString aItemText(getShortenedString(pData->aText, rRenderContext, nMaxItemTextWidth));
+
+ OUString aItemText(pData->aText);
+ pData->bHiddenOnGUI = false;
+
+ if (IsMenuBar()) // In case of menubar if we are out of bounds we shouldn't paint the item
+ {
+ if (nMaxItemTextWidth < rRenderContext.GetTextWidth(aItemText))
+ {
+ aItemText = "";
+ pData->bHiddenOnGUI = true;
+ bHiddenItems = true;
+ }
+ }
+ else
+ {
+ aItemText = getShortenedString(aItemText, rRenderContext, nMaxItemTextWidth);
+ pData->bHiddenOnGUI = false;
+ }
+
rRenderContext.DrawCtrlText(aTmpPos, aItemText, 0, aItemText.getLength(), nStyle, pVector, pDisplayText);
if (bSetTmpBackground)
rRenderContext.SetBackground();
@@ -2014,6 +2092,14 @@ void Menu::ImplPaint(vcl::RenderContext& rRenderContext, Size const & rSize,
else
aTopLeft.X() += pData->aSz.Width();
}
+
+ // draw "more" (">>") indicator if some items have been hidden as they go out of visible area
+ if (bHiddenItems)
+ {
+ sal_Int32 nSize = nFontHeight;
+ tools::Rectangle aRectangle(Point(aOutSz.Width() - nSize, (aOutSz.Height() / 2) - (nSize / 2)), Size(nSize, nSize));
+ lclDrawMoreIndicator(rRenderContext, aRectangle);
+ }
}
Menu* Menu::ImplGetStartMenu()
diff --git a/vcl/source/window/menubarwindow.cxx b/vcl/source/window/menubarwindow.cxx
index 0b4e6b7df5bc..6a8877263b43 100644
--- a/vcl/source/window/menubarwindow.cxx
+++ b/vcl/source/window/menubarwindow.cxx
@@ -160,6 +160,7 @@ void MenuBarWindow::dispose()
aCloseBtn->RemoveEventListener(LINK(this, MenuBarWindow, ToolboxEventHdl));
RemoveEventListener(LINK(this, MenuBarWindow, ShowHideListener));
+ mpParentPopup.disposeAndClear();
aHideBtn.disposeAndClear();
aFloatBtn.disposeAndClear();
aCloseBtn.disposeAndClear();
@@ -301,6 +302,29 @@ void MenuBarWindow::ImplCreatePopup( bool bPreSelectFirst )
Point aItemBottomRight( aItemTopLeft );
aItemBottomRight.X() += pData->aSz.Width();
+ if (pData->bHiddenOnGUI)
+ {
+ mpParentPopup.disposeAndClear();
+ mpParentPopup = VclPtr<PopupMenu>::Create();
+ pActivePopup = mpParentPopup.get();
+
+ for (sal_uInt16 i = nHighlightedItem; i < pMenu->GetItemCount(); ++i)
+ {
+ sal_uInt16 nId = pMenu->GetItemId(i);
+
+ MenuItemData* pParentItemData = pMenu->GetItemList()->GetData(nId);
+
+ mpParentPopup->InsertItem(nId, pParentItemData->aText, pParentItemData->nBits, pParentItemData->sIdent);
+ mpParentPopup->SetHelpId(nId, pParentItemData->aHelpId);
+ mpParentPopup->SetHelpText(nId, pParentItemData->aHelpText);
+ mpParentPopup->SetAccelKey(nId, pParentItemData->aAccelKey);
+ mpParentPopup->SetItemCommand(nId, pParentItemData->aCommandStr);
+ mpParentPopup->SetHelpCommand(nId, pParentItemData->aHelpCommandStr);
+
+ PopupMenu* pPopup = pMenu->GetPopupMenu(nId);
+ mpParentPopup->SetPopupMenu(nId, pPopup);
+ }
+ }
// the menu bar could have height 0 in fullscreen mode:
// so do not use always WindowHeight, as ItemHeight < WindowHeight.
if ( GetSizePixel().Height() )
@@ -340,6 +364,15 @@ void MenuBarWindow::KillActivePopup()
// check for pActivePopup, if stopped by deactivate...
if ( pActivePopup->ImplGetWindow() )
{
+ if (mpParentPopup)
+ {
+ for (sal_uInt16 i = 0; i < mpParentPopup->GetItemCount(); ++i)
+ {
+ sal_uInt16 nId = mpParentPopup->GetItemId(i);
+ MenuItemData* pParentItemData = mpParentPopup->GetItemList()->GetData(nId);
+ pParentItemData->pSubMenu = nullptr;
+ }
+ }
pActivePopup->ImplGetFloatingWindow()->StopExecute();
pActivePopup->ImplGetFloatingWindow()->doShutdown();
pActivePopup->pWindow->doLazyDelete();
@@ -769,7 +802,9 @@ bool MenuBarWindow::HandleKeyEvent( const KeyEvent& rKEvent, bool bFromMenu )
}
MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( n );
- if ( ( pData->eType != MenuItemType::SEPARATOR ) && pMenu->ImplIsVisible( n ) )
+ if (pData->eType != MenuItemType::SEPARATOR &&
+ pMenu->ImplIsVisible(n) &&
+ !pMenu->ImplCurrentlyHiddenOnGUI(n))
{
bool bDoSelect = true;
if( ImplGetSVData()->maNWFData.mbOpenMenuOnF10 )
@@ -891,9 +926,9 @@ void MenuBarWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Recta
aOutputSize.Width() -= aCloseBtn->GetSizePixel().Width();
rRenderContext.SetFillColor(rStyleSettings.GetMenuColor());
-
pMenu->ImplPaint(rRenderContext, aOutputSize, 0);
- if (nHighlightedItem != ITEMPOS_INVALID)
+
+ if (nHighlightedItem != ITEMPOS_INVALID && pMenu && !pMenu->GetItemList()->GetDataFromPos(nHighlightedItem)->bHiddenOnGUI)
HighlightItem(rRenderContext, nHighlightedItem);
else if (ImplGetSVData()->maNWFData.mbRolloverMenubar && nRolloveredItem != ITEMPOS_INVALID)
HighlightItem(rRenderContext, nRolloveredItem);
diff --git a/vcl/source/window/menubarwindow.hxx b/vcl/source/window/menubarwindow.hxx
index c1aa5ce49d0d..bdf785f36d13 100644
--- a/vcl/source/window/menubarwindow.hxx
+++ b/vcl/source/window/menubarwindow.hxx
@@ -69,6 +69,7 @@ private:
VclPtr<Menu> pMenu;
VclPtr<PopupMenu> pActivePopup;
+ VclPtr<PopupMenu> mpParentPopup;
sal_uInt16 nHighlightedItem;
sal_uInt16 nRolloveredItem;
VclPtr<vcl::Window> xSaveFocusId;
diff --git a/vcl/source/window/menuitemlist.hxx b/vcl/source/window/menuitemlist.hxx
index 742c7728921b..cec1cf2073d4 100644
--- a/vcl/source/window/menuitemlist.hxx
+++ b/vcl/source/window/menuitemlist.hxx
@@ -50,6 +50,7 @@ struct MenuItemData
bool bEnabled; // Enabled
bool bVisible; // Visible (note: this flag will not override MenuFlags::HideDisabledEntries when true)
bool bIsTemporary; // Temporary inserted ('No selection possible')
+ bool bHiddenOnGUI;
Size aSz; // only temporarily valid
OUString aAccessibleName; // accessible name
@@ -66,6 +67,7 @@ struct MenuItemData
, bEnabled(false)
, bVisible(false)
, bIsTemporary(false)
+ , bHiddenOnGUI(false)
, pSalMenuItem(nullptr)
{
}
@@ -82,6 +84,7 @@ struct MenuItemData
, bEnabled(false)
, bVisible(false)
, bIsTemporary(false)
+ , bHiddenOnGUI(false)
, pSalMenuItem(nullptr)
{
}