1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_sc.hxx"
26*b1cdbd2cSJim Jagielski
27*b1cdbd2cSJim Jagielski // INCLUDE ---------------------------------------------------------------
28*b1cdbd2cSJim Jagielski
29*b1cdbd2cSJim Jagielski #include "dpcontrol.hxx"
30*b1cdbd2cSJim Jagielski #include "dpcontrol.hrc"
31*b1cdbd2cSJim Jagielski
32*b1cdbd2cSJim Jagielski #include <vcl/outdev.hxx>
33*b1cdbd2cSJim Jagielski #include <vcl/settings.hxx>
34*b1cdbd2cSJim Jagielski #include <tools/wintypes.hxx>
35*b1cdbd2cSJim Jagielski #include <vcl/decoview.hxx>
36*b1cdbd2cSJim Jagielski #include "strload.hxx"
37*b1cdbd2cSJim Jagielski #include "global.hxx"
38*b1cdbd2cSJim Jagielski #include "scitems.hxx"
39*b1cdbd2cSJim Jagielski #include "document.hxx"
40*b1cdbd2cSJim Jagielski #include "docpool.hxx"
41*b1cdbd2cSJim Jagielski #include "patattr.hxx"
42*b1cdbd2cSJim Jagielski
43*b1cdbd2cSJim Jagielski #include "AccessibleFilterMenu.hxx"
44*b1cdbd2cSJim Jagielski #include "AccessibleFilterTopWindow.hxx"
45*b1cdbd2cSJim Jagielski
46*b1cdbd2cSJim Jagielski #include <com/sun/star/accessibility/XAccessible.hpp>
47*b1cdbd2cSJim Jagielski #include <com/sun/star/accessibility/XAccessibleContext.hpp>
48*b1cdbd2cSJim Jagielski
49*b1cdbd2cSJim Jagielski using ::com::sun::star::uno::Reference;
50*b1cdbd2cSJim Jagielski using ::com::sun::star::accessibility::XAccessible;
51*b1cdbd2cSJim Jagielski using ::com::sun::star::accessibility::XAccessibleContext;
52*b1cdbd2cSJim Jagielski using ::rtl::OUString;
53*b1cdbd2cSJim Jagielski using ::rtl::OUStringHash;
54*b1cdbd2cSJim Jagielski using ::std::vector;
55*b1cdbd2cSJim Jagielski using ::std::hash_map;
56*b1cdbd2cSJim Jagielski using ::std::auto_ptr;
57*b1cdbd2cSJim Jagielski
ScDPFieldButton(OutputDevice * pOutDev,const StyleSettings * pStyle,const Fraction * pZoomX,const Fraction * pZoomY,ScDocument * pDoc)58*b1cdbd2cSJim Jagielski ScDPFieldButton::ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle, const Fraction* pZoomX, const Fraction* pZoomY, ScDocument* pDoc) :
59*b1cdbd2cSJim Jagielski mpDoc(pDoc),
60*b1cdbd2cSJim Jagielski mpOutDev(pOutDev),
61*b1cdbd2cSJim Jagielski mpStyle(pStyle),
62*b1cdbd2cSJim Jagielski mbBaseButton(true),
63*b1cdbd2cSJim Jagielski mbPopupButton(false),
64*b1cdbd2cSJim Jagielski mbHasHiddenMember(false),
65*b1cdbd2cSJim Jagielski mbPopupPressed(false),
66*b1cdbd2cSJim Jagielski mbPopupLeft(false)
67*b1cdbd2cSJim Jagielski {
68*b1cdbd2cSJim Jagielski if (pZoomX)
69*b1cdbd2cSJim Jagielski maZoomX = *pZoomX;
70*b1cdbd2cSJim Jagielski else
71*b1cdbd2cSJim Jagielski maZoomX = Fraction(1, 1);
72*b1cdbd2cSJim Jagielski
73*b1cdbd2cSJim Jagielski if (pZoomY)
74*b1cdbd2cSJim Jagielski maZoomY = *pZoomY;
75*b1cdbd2cSJim Jagielski else
76*b1cdbd2cSJim Jagielski maZoomY = Fraction(1, 1);
77*b1cdbd2cSJim Jagielski }
78*b1cdbd2cSJim Jagielski
~ScDPFieldButton()79*b1cdbd2cSJim Jagielski ScDPFieldButton::~ScDPFieldButton()
80*b1cdbd2cSJim Jagielski {
81*b1cdbd2cSJim Jagielski }
82*b1cdbd2cSJim Jagielski
setText(const OUString & rText)83*b1cdbd2cSJim Jagielski void ScDPFieldButton::setText(const OUString& rText)
84*b1cdbd2cSJim Jagielski {
85*b1cdbd2cSJim Jagielski maText = rText;
86*b1cdbd2cSJim Jagielski }
87*b1cdbd2cSJim Jagielski
setBoundingBox(const Point & rPos,const Size & rSize,bool bLayoutRTL)88*b1cdbd2cSJim Jagielski void ScDPFieldButton::setBoundingBox(const Point& rPos, const Size& rSize, bool bLayoutRTL)
89*b1cdbd2cSJim Jagielski {
90*b1cdbd2cSJim Jagielski maPos = rPos;
91*b1cdbd2cSJim Jagielski maSize = rSize;
92*b1cdbd2cSJim Jagielski if (bLayoutRTL)
93*b1cdbd2cSJim Jagielski {
94*b1cdbd2cSJim Jagielski // rPos is the logical-left position, adjust maPos to visual-left (inside the cell border)
95*b1cdbd2cSJim Jagielski maPos.X() -= maSize.Width() - 1;
96*b1cdbd2cSJim Jagielski }
97*b1cdbd2cSJim Jagielski }
98*b1cdbd2cSJim Jagielski
setDrawBaseButton(bool b)99*b1cdbd2cSJim Jagielski void ScDPFieldButton::setDrawBaseButton(bool b)
100*b1cdbd2cSJim Jagielski {
101*b1cdbd2cSJim Jagielski mbBaseButton = b;
102*b1cdbd2cSJim Jagielski }
103*b1cdbd2cSJim Jagielski
setDrawPopupButton(bool b)104*b1cdbd2cSJim Jagielski void ScDPFieldButton::setDrawPopupButton(bool b)
105*b1cdbd2cSJim Jagielski {
106*b1cdbd2cSJim Jagielski mbPopupButton = b;
107*b1cdbd2cSJim Jagielski }
108*b1cdbd2cSJim Jagielski
setHasHiddenMember(bool b)109*b1cdbd2cSJim Jagielski void ScDPFieldButton::setHasHiddenMember(bool b)
110*b1cdbd2cSJim Jagielski {
111*b1cdbd2cSJim Jagielski mbHasHiddenMember = b;
112*b1cdbd2cSJim Jagielski }
113*b1cdbd2cSJim Jagielski
setPopupPressed(bool b)114*b1cdbd2cSJim Jagielski void ScDPFieldButton::setPopupPressed(bool b)
115*b1cdbd2cSJim Jagielski {
116*b1cdbd2cSJim Jagielski mbPopupPressed = b;
117*b1cdbd2cSJim Jagielski }
118*b1cdbd2cSJim Jagielski
setPopupLeft(bool b)119*b1cdbd2cSJim Jagielski void ScDPFieldButton::setPopupLeft(bool b)
120*b1cdbd2cSJim Jagielski {
121*b1cdbd2cSJim Jagielski mbPopupLeft = b;
122*b1cdbd2cSJim Jagielski }
123*b1cdbd2cSJim Jagielski
draw()124*b1cdbd2cSJim Jagielski void ScDPFieldButton::draw()
125*b1cdbd2cSJim Jagielski {
126*b1cdbd2cSJim Jagielski const long nMargin = 2;
127*b1cdbd2cSJim Jagielski bool bOldMapEnablaed = mpOutDev->IsMapModeEnabled();
128*b1cdbd2cSJim Jagielski mpOutDev->EnableMapMode(false);
129*b1cdbd2cSJim Jagielski
130*b1cdbd2cSJim Jagielski if (mbBaseButton)
131*b1cdbd2cSJim Jagielski {
132*b1cdbd2cSJim Jagielski // Background
133*b1cdbd2cSJim Jagielski Rectangle aRect(maPos, maSize);
134*b1cdbd2cSJim Jagielski mpOutDev->SetLineColor(mpStyle->GetFaceColor());
135*b1cdbd2cSJim Jagielski mpOutDev->SetFillColor(mpStyle->GetFaceColor());
136*b1cdbd2cSJim Jagielski mpOutDev->DrawRect(aRect);
137*b1cdbd2cSJim Jagielski
138*b1cdbd2cSJim Jagielski // Border lines
139*b1cdbd2cSJim Jagielski mpOutDev->SetLineColor(mpStyle->GetLightColor());
140*b1cdbd2cSJim Jagielski mpOutDev->DrawLine(Point(maPos), Point(maPos.X(), maPos.Y()+maSize.Height()-1));
141*b1cdbd2cSJim Jagielski mpOutDev->DrawLine(Point(maPos), Point(maPos.X()+maSize.Width()-1, maPos.Y()));
142*b1cdbd2cSJim Jagielski
143*b1cdbd2cSJim Jagielski mpOutDev->SetLineColor(mpStyle->GetShadowColor());
144*b1cdbd2cSJim Jagielski mpOutDev->DrawLine(Point(maPos.X(), maPos.Y()+maSize.Height()-1),
145*b1cdbd2cSJim Jagielski Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
146*b1cdbd2cSJim Jagielski mpOutDev->DrawLine(Point(maPos.X()+maSize.Width()-1, maPos.Y()),
147*b1cdbd2cSJim Jagielski Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
148*b1cdbd2cSJim Jagielski
149*b1cdbd2cSJim Jagielski // Field name.
150*b1cdbd2cSJim Jagielski // Get the font and size the same way as in scenario selection (lcl_DrawOneFrame in gridwin4.cxx)
151*b1cdbd2cSJim Jagielski Font aTextFont( mpStyle->GetAppFont() );
152*b1cdbd2cSJim Jagielski if ( mpDoc )
153*b1cdbd2cSJim Jagielski {
154*b1cdbd2cSJim Jagielski // use ScPatternAttr::GetFont only for font size
155*b1cdbd2cSJim Jagielski Font aAttrFont;
156*b1cdbd2cSJim Jagielski static_cast<const ScPatternAttr&>(mpDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).
157*b1cdbd2cSJim Jagielski GetFont( aAttrFont, SC_AUTOCOL_BLACK, mpOutDev, &maZoomY );
158*b1cdbd2cSJim Jagielski aTextFont.SetSize( aAttrFont.GetSize() );
159*b1cdbd2cSJim Jagielski }
160*b1cdbd2cSJim Jagielski mpOutDev->SetFont(aTextFont);
161*b1cdbd2cSJim Jagielski mpOutDev->SetTextColor(mpStyle->GetButtonTextColor());
162*b1cdbd2cSJim Jagielski
163*b1cdbd2cSJim Jagielski Point aTextPos = maPos;
164*b1cdbd2cSJim Jagielski long nTHeight = mpOutDev->GetTextHeight();
165*b1cdbd2cSJim Jagielski aTextPos.setX(maPos.getX() + nMargin);
166*b1cdbd2cSJim Jagielski aTextPos.setY(maPos.getY() + (maSize.Height()-nTHeight)/2);
167*b1cdbd2cSJim Jagielski
168*b1cdbd2cSJim Jagielski mpOutDev->Push(PUSH_CLIPREGION);
169*b1cdbd2cSJim Jagielski mpOutDev->IntersectClipRegion(aRect);
170*b1cdbd2cSJim Jagielski mpOutDev->DrawText(aTextPos, maText);
171*b1cdbd2cSJim Jagielski mpOutDev->Pop();
172*b1cdbd2cSJim Jagielski }
173*b1cdbd2cSJim Jagielski
174*b1cdbd2cSJim Jagielski if (mbPopupButton)
175*b1cdbd2cSJim Jagielski drawPopupButton();
176*b1cdbd2cSJim Jagielski
177*b1cdbd2cSJim Jagielski mpOutDev->EnableMapMode(bOldMapEnablaed);
178*b1cdbd2cSJim Jagielski }
179*b1cdbd2cSJim Jagielski
getPopupBoundingBox(Point & rPos,Size & rSize) const180*b1cdbd2cSJim Jagielski void ScDPFieldButton::getPopupBoundingBox(Point& rPos, Size& rSize) const
181*b1cdbd2cSJim Jagielski {
182*b1cdbd2cSJim Jagielski long nW = maSize.getWidth() / 2;
183*b1cdbd2cSJim Jagielski long nH = maSize.getHeight();
184*b1cdbd2cSJim Jagielski if (nW > 18)
185*b1cdbd2cSJim Jagielski nW = 18;
186*b1cdbd2cSJim Jagielski if (nH > 18)
187*b1cdbd2cSJim Jagielski nH = 18;
188*b1cdbd2cSJim Jagielski
189*b1cdbd2cSJim Jagielski // #i114944# AutoFilter button is left-aligned in RTL.
190*b1cdbd2cSJim Jagielski // DataPilot button is always right-aligned for now, so text output isn't affected.
191*b1cdbd2cSJim Jagielski if (mbPopupLeft)
192*b1cdbd2cSJim Jagielski rPos.setX(maPos.getX());
193*b1cdbd2cSJim Jagielski else
194*b1cdbd2cSJim Jagielski rPos.setX(maPos.getX() + maSize.getWidth() - nW);
195*b1cdbd2cSJim Jagielski rPos.setY(maPos.getY() + maSize.getHeight() - nH);
196*b1cdbd2cSJim Jagielski rSize.setWidth(nW);
197*b1cdbd2cSJim Jagielski rSize.setHeight(nH);
198*b1cdbd2cSJim Jagielski }
199*b1cdbd2cSJim Jagielski
drawPopupButton()200*b1cdbd2cSJim Jagielski void ScDPFieldButton::drawPopupButton()
201*b1cdbd2cSJim Jagielski {
202*b1cdbd2cSJim Jagielski Point aPos;
203*b1cdbd2cSJim Jagielski Size aSize;
204*b1cdbd2cSJim Jagielski getPopupBoundingBox(aPos, aSize);
205*b1cdbd2cSJim Jagielski
206*b1cdbd2cSJim Jagielski // Background & outer black border
207*b1cdbd2cSJim Jagielski mpOutDev->SetLineColor(COL_BLACK);
208*b1cdbd2cSJim Jagielski mpOutDev->SetFillColor(mpStyle->GetFaceColor());
209*b1cdbd2cSJim Jagielski mpOutDev->DrawRect(Rectangle(aPos, aSize));
210*b1cdbd2cSJim Jagielski
211*b1cdbd2cSJim Jagielski if (!mbPopupPressed)
212*b1cdbd2cSJim Jagielski {
213*b1cdbd2cSJim Jagielski // border lines
214*b1cdbd2cSJim Jagielski mpOutDev->SetLineColor(mpStyle->GetLightColor());
215*b1cdbd2cSJim Jagielski mpOutDev->DrawLine(Point(aPos.X()+1, aPos.Y()+1), Point(aPos.X()+1, aPos.Y()+aSize.Height()-2));
216*b1cdbd2cSJim Jagielski mpOutDev->DrawLine(Point(aPos.X()+1, aPos.Y()+1), Point(aPos.X()+aSize.Width()-2, aPos.Y()+1));
217*b1cdbd2cSJim Jagielski
218*b1cdbd2cSJim Jagielski mpOutDev->SetLineColor(mpStyle->GetShadowColor());
219*b1cdbd2cSJim Jagielski mpOutDev->DrawLine(Point(aPos.X()+1, aPos.Y()+aSize.Height()-2),
220*b1cdbd2cSJim Jagielski Point(aPos.X()+aSize.Width()-2, aPos.Y()+aSize.Height()-2));
221*b1cdbd2cSJim Jagielski mpOutDev->DrawLine(Point(aPos.X()+aSize.Width()-2, aPos.Y()+1),
222*b1cdbd2cSJim Jagielski Point(aPos.X()+aSize.Width()-2, aPos.Y()+aSize.Height()-2));
223*b1cdbd2cSJim Jagielski }
224*b1cdbd2cSJim Jagielski
225*b1cdbd2cSJim Jagielski // the arrowhead
226*b1cdbd2cSJim Jagielski Color aArrowColor = mbHasHiddenMember ? mpStyle->GetHighlightLinkColor() : mpStyle->GetButtonTextColor();
227*b1cdbd2cSJim Jagielski mpOutDev->SetLineColor(aArrowColor);
228*b1cdbd2cSJim Jagielski mpOutDev->SetFillColor(aArrowColor);
229*b1cdbd2cSJim Jagielski Point aCenter(aPos.X() + (aSize.Width() >> 1), aPos.Y() + (aSize.Height() >> 1));
230*b1cdbd2cSJim Jagielski Point aPos1, aPos2;
231*b1cdbd2cSJim Jagielski aPos1.X() = aCenter.X() - 4;
232*b1cdbd2cSJim Jagielski aPos2.X() = aCenter.X() + 4;
233*b1cdbd2cSJim Jagielski aPos1.Y() = aCenter.Y() - 3;
234*b1cdbd2cSJim Jagielski aPos2.Y() = aCenter.Y() - 3;
235*b1cdbd2cSJim Jagielski
236*b1cdbd2cSJim Jagielski if (mbPopupPressed)
237*b1cdbd2cSJim Jagielski {
238*b1cdbd2cSJim Jagielski aPos1.X() += 1;
239*b1cdbd2cSJim Jagielski aPos2.X() += 1;
240*b1cdbd2cSJim Jagielski aPos1.Y() += 1;
241*b1cdbd2cSJim Jagielski aPos2.Y() += 1;
242*b1cdbd2cSJim Jagielski }
243*b1cdbd2cSJim Jagielski
244*b1cdbd2cSJim Jagielski do
245*b1cdbd2cSJim Jagielski {
246*b1cdbd2cSJim Jagielski ++aPos1.X();
247*b1cdbd2cSJim Jagielski --aPos2.X();
248*b1cdbd2cSJim Jagielski ++aPos1.Y();
249*b1cdbd2cSJim Jagielski ++aPos2.Y();
250*b1cdbd2cSJim Jagielski mpOutDev->DrawLine(aPos1, aPos2);
251*b1cdbd2cSJim Jagielski }
252*b1cdbd2cSJim Jagielski while (aPos1 != aPos2);
253*b1cdbd2cSJim Jagielski
254*b1cdbd2cSJim Jagielski if (mbHasHiddenMember)
255*b1cdbd2cSJim Jagielski {
256*b1cdbd2cSJim Jagielski // tiny little box to display in presence of hidden member(s).
257*b1cdbd2cSJim Jagielski Point aBoxPos(aPos.X() + aSize.Width() - 5, aPos.Y() + aSize.Height() - 5);
258*b1cdbd2cSJim Jagielski if (mbPopupPressed)
259*b1cdbd2cSJim Jagielski {
260*b1cdbd2cSJim Jagielski aBoxPos.X() += 1;
261*b1cdbd2cSJim Jagielski aBoxPos.Y() += 1;
262*b1cdbd2cSJim Jagielski }
263*b1cdbd2cSJim Jagielski Size aBoxSize(3, 3);
264*b1cdbd2cSJim Jagielski mpOutDev->DrawRect(Rectangle(aBoxPos, aBoxSize));
265*b1cdbd2cSJim Jagielski }
266*b1cdbd2cSJim Jagielski }
267*b1cdbd2cSJim Jagielski
268*b1cdbd2cSJim Jagielski // ============================================================================
269*b1cdbd2cSJim Jagielski
MenuItemData()270*b1cdbd2cSJim Jagielski ScMenuFloatingWindow::MenuItemData::MenuItemData() :
271*b1cdbd2cSJim Jagielski mbEnabled(true),
272*b1cdbd2cSJim Jagielski mpAction(static_cast<ScDPFieldPopupWindow::Action*>(NULL)),
273*b1cdbd2cSJim Jagielski mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
274*b1cdbd2cSJim Jagielski {
275*b1cdbd2cSJim Jagielski }
276*b1cdbd2cSJim Jagielski
277*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
278*b1cdbd2cSJim Jagielski
SubMenuItemData(ScMenuFloatingWindow * pParent)279*b1cdbd2cSJim Jagielski ScMenuFloatingWindow::SubMenuItemData::SubMenuItemData(ScMenuFloatingWindow* pParent) :
280*b1cdbd2cSJim Jagielski mpSubMenu(NULL),
281*b1cdbd2cSJim Jagielski mnMenuPos(MENU_NOT_SELECTED),
282*b1cdbd2cSJim Jagielski mpParent(pParent)
283*b1cdbd2cSJim Jagielski {
284*b1cdbd2cSJim Jagielski maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl) );
285*b1cdbd2cSJim Jagielski maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
286*b1cdbd2cSJim Jagielski }
287*b1cdbd2cSJim Jagielski
reset()288*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::SubMenuItemData::reset()
289*b1cdbd2cSJim Jagielski {
290*b1cdbd2cSJim Jagielski mpSubMenu = NULL;
291*b1cdbd2cSJim Jagielski mnMenuPos = MENU_NOT_SELECTED;
292*b1cdbd2cSJim Jagielski maTimer.Stop();
293*b1cdbd2cSJim Jagielski }
294*b1cdbd2cSJim Jagielski
IMPL_LINK(ScMenuFloatingWindow::SubMenuItemData,TimeoutHdl,void *,EMPTYARG)295*b1cdbd2cSJim Jagielski IMPL_LINK( ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl, void*, EMPTYARG )
296*b1cdbd2cSJim Jagielski {
297*b1cdbd2cSJim Jagielski mpParent->handleMenuTimeout(this);
298*b1cdbd2cSJim Jagielski return 0;
299*b1cdbd2cSJim Jagielski }
300*b1cdbd2cSJim Jagielski
301*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
302*b1cdbd2cSJim Jagielski
303*b1cdbd2cSJim Jagielski size_t ScMenuFloatingWindow::MENU_NOT_SELECTED = 999;
304*b1cdbd2cSJim Jagielski
ScMenuFloatingWindow(Window * pParent,ScDocument * pDoc,sal_uInt16 nMenuStackLevel)305*b1cdbd2cSJim Jagielski ScMenuFloatingWindow::ScMenuFloatingWindow(Window* pParent, ScDocument* pDoc, sal_uInt16 nMenuStackLevel) :
306*b1cdbd2cSJim Jagielski PopupMenuFloatingWindow(pParent),
307*b1cdbd2cSJim Jagielski maOpenTimer(this),
308*b1cdbd2cSJim Jagielski maCloseTimer(this),
309*b1cdbd2cSJim Jagielski maName(OUString::createFromAscii("ScMenuFloatingWindow")),
310*b1cdbd2cSJim Jagielski mnSelectedMenu(MENU_NOT_SELECTED),
311*b1cdbd2cSJim Jagielski mnClickedMenu(MENU_NOT_SELECTED),
312*b1cdbd2cSJim Jagielski mpDoc(pDoc),
313*b1cdbd2cSJim Jagielski mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent)),
314*b1cdbd2cSJim Jagielski mpActiveSubMenu(NULL)
315*b1cdbd2cSJim Jagielski {
316*b1cdbd2cSJim Jagielski SetMenuStackLevel(nMenuStackLevel);
317*b1cdbd2cSJim Jagielski
318*b1cdbd2cSJim Jagielski // TODO: How do we get the right font to use here ?
319*b1cdbd2cSJim Jagielski const sal_uInt16 nPopupFontHeight = 12;
320*b1cdbd2cSJim Jagielski const StyleSettings& rStyle = GetSettings().GetStyleSettings();
321*b1cdbd2cSJim Jagielski maLabelFont = rStyle.GetLabelFont();
322*b1cdbd2cSJim Jagielski maLabelFont.SetHeight(nPopupFontHeight);
323*b1cdbd2cSJim Jagielski SetFont(maLabelFont);
324*b1cdbd2cSJim Jagielski
325*b1cdbd2cSJim Jagielski SetText(OUString::createFromAscii("ScMenuFloatingWindow"));
326*b1cdbd2cSJim Jagielski SetPopupModeEndHdl( LINK(this, ScMenuFloatingWindow, PopupEndHdl) );
327*b1cdbd2cSJim Jagielski }
328*b1cdbd2cSJim Jagielski
~ScMenuFloatingWindow()329*b1cdbd2cSJim Jagielski ScMenuFloatingWindow::~ScMenuFloatingWindow()
330*b1cdbd2cSJim Jagielski {
331*b1cdbd2cSJim Jagielski EndPopupMode();
332*b1cdbd2cSJim Jagielski }
333*b1cdbd2cSJim Jagielski
MouseMove(const MouseEvent & rMEvt)334*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::MouseMove(const MouseEvent& rMEvt)
335*b1cdbd2cSJim Jagielski {
336*b1cdbd2cSJim Jagielski const Point& rPos = rMEvt.GetPosPixel();
337*b1cdbd2cSJim Jagielski size_t nSelectedMenu = getEnclosingMenuItem(rPos);
338*b1cdbd2cSJim Jagielski setSelectedMenuItem(nSelectedMenu, true, false);
339*b1cdbd2cSJim Jagielski
340*b1cdbd2cSJim Jagielski Window::MouseMove(rMEvt);
341*b1cdbd2cSJim Jagielski }
342*b1cdbd2cSJim Jagielski
MouseButtonDown(const MouseEvent & rMEvt)343*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::MouseButtonDown(const MouseEvent& rMEvt)
344*b1cdbd2cSJim Jagielski {
345*b1cdbd2cSJim Jagielski const Point& rPos = rMEvt.GetPosPixel();
346*b1cdbd2cSJim Jagielski mnClickedMenu = getEnclosingMenuItem(rPos);
347*b1cdbd2cSJim Jagielski Window::MouseButtonDown(rMEvt);
348*b1cdbd2cSJim Jagielski }
349*b1cdbd2cSJim Jagielski
MouseButtonUp(const MouseEvent & rMEvt)350*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt)
351*b1cdbd2cSJim Jagielski {
352*b1cdbd2cSJim Jagielski executeMenuItem(mnClickedMenu);
353*b1cdbd2cSJim Jagielski mnClickedMenu = MENU_NOT_SELECTED;
354*b1cdbd2cSJim Jagielski Window::MouseButtonUp(rMEvt);
355*b1cdbd2cSJim Jagielski }
356*b1cdbd2cSJim Jagielski
KeyInput(const KeyEvent & rKEvt)357*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt)
358*b1cdbd2cSJim Jagielski {
359*b1cdbd2cSJim Jagielski const KeyCode& rKeyCode = rKEvt.GetKeyCode();
360*b1cdbd2cSJim Jagielski bool bHandled = true;
361*b1cdbd2cSJim Jagielski size_t nSelectedMenu = mnSelectedMenu;
362*b1cdbd2cSJim Jagielski size_t nLastMenuPos = maMenuItems.size() - 1;
363*b1cdbd2cSJim Jagielski switch (rKeyCode.GetCode())
364*b1cdbd2cSJim Jagielski {
365*b1cdbd2cSJim Jagielski case KEY_UP:
366*b1cdbd2cSJim Jagielski if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0)
367*b1cdbd2cSJim Jagielski nSelectedMenu = nLastMenuPos;
368*b1cdbd2cSJim Jagielski else
369*b1cdbd2cSJim Jagielski --nSelectedMenu;
370*b1cdbd2cSJim Jagielski setSelectedMenuItem(nSelectedMenu, false, false);
371*b1cdbd2cSJim Jagielski break;
372*b1cdbd2cSJim Jagielski case KEY_DOWN:
373*b1cdbd2cSJim Jagielski if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
374*b1cdbd2cSJim Jagielski nSelectedMenu = 0;
375*b1cdbd2cSJim Jagielski else
376*b1cdbd2cSJim Jagielski ++nSelectedMenu;
377*b1cdbd2cSJim Jagielski setSelectedMenuItem(nSelectedMenu, false, false);
378*b1cdbd2cSJim Jagielski break;
379*b1cdbd2cSJim Jagielski case KEY_LEFT:
380*b1cdbd2cSJim Jagielski if (mpParentMenu)
381*b1cdbd2cSJim Jagielski mpParentMenu->endSubMenu(this);
382*b1cdbd2cSJim Jagielski break;
383*b1cdbd2cSJim Jagielski case KEY_RIGHT:
384*b1cdbd2cSJim Jagielski {
385*b1cdbd2cSJim Jagielski if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED)
386*b1cdbd2cSJim Jagielski break;
387*b1cdbd2cSJim Jagielski
388*b1cdbd2cSJim Jagielski const MenuItemData& rMenu = maMenuItems[mnSelectedMenu];
389*b1cdbd2cSJim Jagielski if (!rMenu.mbEnabled || !rMenu.mpSubMenuWin)
390*b1cdbd2cSJim Jagielski break;
391*b1cdbd2cSJim Jagielski
392*b1cdbd2cSJim Jagielski maOpenTimer.mnMenuPos = mnSelectedMenu;
393*b1cdbd2cSJim Jagielski maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get();
394*b1cdbd2cSJim Jagielski launchSubMenu(true);
395*b1cdbd2cSJim Jagielski }
396*b1cdbd2cSJim Jagielski break;
397*b1cdbd2cSJim Jagielski case KEY_RETURN:
398*b1cdbd2cSJim Jagielski if (nSelectedMenu != MENU_NOT_SELECTED)
399*b1cdbd2cSJim Jagielski executeMenuItem(nSelectedMenu);
400*b1cdbd2cSJim Jagielski break;
401*b1cdbd2cSJim Jagielski default:
402*b1cdbd2cSJim Jagielski bHandled = false;
403*b1cdbd2cSJim Jagielski }
404*b1cdbd2cSJim Jagielski
405*b1cdbd2cSJim Jagielski if (!bHandled)
406*b1cdbd2cSJim Jagielski Window::KeyInput(rKEvt);
407*b1cdbd2cSJim Jagielski }
408*b1cdbd2cSJim Jagielski
Paint(const Rectangle &)409*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::Paint(const Rectangle& /*rRect*/)
410*b1cdbd2cSJim Jagielski {
411*b1cdbd2cSJim Jagielski const StyleSettings& rStyle = GetSettings().GetStyleSettings();
412*b1cdbd2cSJim Jagielski Color aBackColor = rStyle.GetMenuColor();
413*b1cdbd2cSJim Jagielski Color aBorderColor = rStyle.GetShadowColor();
414*b1cdbd2cSJim Jagielski
415*b1cdbd2cSJim Jagielski Rectangle aCtrlRect(Point(0, 0), GetOutputSizePixel());
416*b1cdbd2cSJim Jagielski
417*b1cdbd2cSJim Jagielski // Window background
418*b1cdbd2cSJim Jagielski bool bNativeDrawn = true;
419*b1cdbd2cSJim Jagielski if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
420*b1cdbd2cSJim Jagielski {
421*b1cdbd2cSJim Jagielski SetClipRegion();
422*b1cdbd2cSJim Jagielski bNativeDrawn = DrawNativeControl(
423*b1cdbd2cSJim Jagielski CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
424*b1cdbd2cSJim Jagielski ImplControlValue(), OUString());
425*b1cdbd2cSJim Jagielski }
426*b1cdbd2cSJim Jagielski else
427*b1cdbd2cSJim Jagielski bNativeDrawn = false;
428*b1cdbd2cSJim Jagielski
429*b1cdbd2cSJim Jagielski if (!bNativeDrawn)
430*b1cdbd2cSJim Jagielski {
431*b1cdbd2cSJim Jagielski SetFillColor(aBackColor);
432*b1cdbd2cSJim Jagielski SetLineColor(aBorderColor);
433*b1cdbd2cSJim Jagielski DrawRect(aCtrlRect);
434*b1cdbd2cSJim Jagielski }
435*b1cdbd2cSJim Jagielski
436*b1cdbd2cSJim Jagielski // Menu items
437*b1cdbd2cSJim Jagielski SetTextColor(rStyle.GetMenuTextColor());
438*b1cdbd2cSJim Jagielski drawAllMenuItems();
439*b1cdbd2cSJim Jagielski }
440*b1cdbd2cSJim Jagielski
CreateAccessible()441*b1cdbd2cSJim Jagielski Reference<XAccessible> ScMenuFloatingWindow::CreateAccessible()
442*b1cdbd2cSJim Jagielski {
443*b1cdbd2cSJim Jagielski if (!mxAccessible.is())
444*b1cdbd2cSJim Jagielski {
445*b1cdbd2cSJim Jagielski Reference<XAccessible> xAccParent = mpParentMenu ?
446*b1cdbd2cSJim Jagielski mpParentMenu->GetAccessible() : GetAccessibleParentWindow()->GetAccessible();
447*b1cdbd2cSJim Jagielski
448*b1cdbd2cSJim Jagielski mxAccessible.set(new ScAccessibleFilterMenu(xAccParent, this, maName, 999, getDoc()));
449*b1cdbd2cSJim Jagielski ScAccessibleFilterMenu* p = static_cast<ScAccessibleFilterMenu*>(
450*b1cdbd2cSJim Jagielski mxAccessible.get());
451*b1cdbd2cSJim Jagielski
452*b1cdbd2cSJim Jagielski vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
453*b1cdbd2cSJim Jagielski for (itr = itrBeg; itr != itrEnd; ++itr)
454*b1cdbd2cSJim Jagielski {
455*b1cdbd2cSJim Jagielski size_t nPos = ::std::distance(itrBeg, itr);
456*b1cdbd2cSJim Jagielski p->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
457*b1cdbd2cSJim Jagielski }
458*b1cdbd2cSJim Jagielski }
459*b1cdbd2cSJim Jagielski
460*b1cdbd2cSJim Jagielski return mxAccessible;
461*b1cdbd2cSJim Jagielski }
462*b1cdbd2cSJim Jagielski
addMenuItem(const OUString & rText,bool bEnabled,Action * pAction)463*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
464*b1cdbd2cSJim Jagielski {
465*b1cdbd2cSJim Jagielski MenuItemData aItem;
466*b1cdbd2cSJim Jagielski aItem.maText = rText;
467*b1cdbd2cSJim Jagielski aItem.mbEnabled = bEnabled;
468*b1cdbd2cSJim Jagielski aItem.mpAction.reset(pAction);
469*b1cdbd2cSJim Jagielski maMenuItems.push_back(aItem);
470*b1cdbd2cSJim Jagielski }
471*b1cdbd2cSJim Jagielski
addSubMenuItem(const OUString & rText,bool bEnabled)472*b1cdbd2cSJim Jagielski ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
473*b1cdbd2cSJim Jagielski {
474*b1cdbd2cSJim Jagielski MenuItemData aItem;
475*b1cdbd2cSJim Jagielski aItem.maText = rText;
476*b1cdbd2cSJim Jagielski aItem.mbEnabled = bEnabled;
477*b1cdbd2cSJim Jagielski aItem.mpSubMenuWin.reset(new ScMenuFloatingWindow(this, mpDoc, GetMenuStackLevel()+1));
478*b1cdbd2cSJim Jagielski aItem.mpSubMenuWin->setName(rText);
479*b1cdbd2cSJim Jagielski maMenuItems.push_back(aItem);
480*b1cdbd2cSJim Jagielski return aItem.mpSubMenuWin.get();
481*b1cdbd2cSJim Jagielski }
482*b1cdbd2cSJim Jagielski
drawMenuItem(size_t nPos)483*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::drawMenuItem(size_t nPos)
484*b1cdbd2cSJim Jagielski {
485*b1cdbd2cSJim Jagielski if (nPos >= maMenuItems.size())
486*b1cdbd2cSJim Jagielski return;
487*b1cdbd2cSJim Jagielski
488*b1cdbd2cSJim Jagielski Point aPos;
489*b1cdbd2cSJim Jagielski Size aSize;
490*b1cdbd2cSJim Jagielski getMenuItemPosSize(nPos, aPos, aSize);
491*b1cdbd2cSJim Jagielski
492*b1cdbd2cSJim Jagielski DecorationView aDecoView(this);
493*b1cdbd2cSJim Jagielski long nXOffset = 5;
494*b1cdbd2cSJim Jagielski long nYOffset = (aSize.Height() - maLabelFont.GetHeight())/2;
495*b1cdbd2cSJim Jagielski DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0, STRING_LEN,
496*b1cdbd2cSJim Jagielski maMenuItems[nPos].mbEnabled ? TEXT_DRAW_MNEMONIC : TEXT_DRAW_DISABLE);
497*b1cdbd2cSJim Jagielski
498*b1cdbd2cSJim Jagielski if (maMenuItems[nPos].mpSubMenuWin)
499*b1cdbd2cSJim Jagielski {
500*b1cdbd2cSJim Jagielski long nFontHeight = maLabelFont.GetHeight();
501*b1cdbd2cSJim Jagielski Point aMarkerPos = aPos;
502*b1cdbd2cSJim Jagielski aMarkerPos.Y() += aSize.Height()/2 - nFontHeight/4 + 1;
503*b1cdbd2cSJim Jagielski aMarkerPos.X() += aSize.Width() - nFontHeight + nFontHeight/4;
504*b1cdbd2cSJim Jagielski Size aMarkerSize(nFontHeight/2, nFontHeight/2);
505*b1cdbd2cSJim Jagielski aDecoView.DrawSymbol(Rectangle(aMarkerPos, aMarkerSize),
506*b1cdbd2cSJim Jagielski SYMBOL_SPIN_RIGHT, GetTextColor(), 0);
507*b1cdbd2cSJim Jagielski }
508*b1cdbd2cSJim Jagielski }
509*b1cdbd2cSJim Jagielski
drawAllMenuItems()510*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::drawAllMenuItems()
511*b1cdbd2cSJim Jagielski {
512*b1cdbd2cSJim Jagielski size_t n = maMenuItems.size();
513*b1cdbd2cSJim Jagielski for (size_t i = 0; i < n; ++i)
514*b1cdbd2cSJim Jagielski highlightMenuItem(i, i == mnSelectedMenu);
515*b1cdbd2cSJim Jagielski }
516*b1cdbd2cSJim Jagielski
getLabelFont() const517*b1cdbd2cSJim Jagielski const Font& ScMenuFloatingWindow::getLabelFont() const
518*b1cdbd2cSJim Jagielski {
519*b1cdbd2cSJim Jagielski return maLabelFont;
520*b1cdbd2cSJim Jagielski }
521*b1cdbd2cSJim Jagielski
executeMenuItem(size_t nPos)522*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::executeMenuItem(size_t nPos)
523*b1cdbd2cSJim Jagielski {
524*b1cdbd2cSJim Jagielski if (nPos >= maMenuItems.size())
525*b1cdbd2cSJim Jagielski return;
526*b1cdbd2cSJim Jagielski
527*b1cdbd2cSJim Jagielski if (!maMenuItems[nPos].mpAction)
528*b1cdbd2cSJim Jagielski // no action is defined.
529*b1cdbd2cSJim Jagielski return;
530*b1cdbd2cSJim Jagielski
531*b1cdbd2cSJim Jagielski maMenuItems[nPos].mpAction->execute();
532*b1cdbd2cSJim Jagielski terminateAllPopupMenus();
533*b1cdbd2cSJim Jagielski }
534*b1cdbd2cSJim Jagielski
setSelectedMenuItem(size_t nPos,bool bSubMenuTimer,bool bEnsureSubMenu)535*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu)
536*b1cdbd2cSJim Jagielski {
537*b1cdbd2cSJim Jagielski if (mnSelectedMenu == nPos)
538*b1cdbd2cSJim Jagielski // nothing to do.
539*b1cdbd2cSJim Jagielski return;
540*b1cdbd2cSJim Jagielski
541*b1cdbd2cSJim Jagielski if (bEnsureSubMenu)
542*b1cdbd2cSJim Jagielski {
543*b1cdbd2cSJim Jagielski // Dismiss any child popup menu windows.
544*b1cdbd2cSJim Jagielski if (mnSelectedMenu < maMenuItems.size() &&
545*b1cdbd2cSJim Jagielski maMenuItems[mnSelectedMenu].mpSubMenuWin &&
546*b1cdbd2cSJim Jagielski maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
547*b1cdbd2cSJim Jagielski {
548*b1cdbd2cSJim Jagielski maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
549*b1cdbd2cSJim Jagielski }
550*b1cdbd2cSJim Jagielski
551*b1cdbd2cSJim Jagielski // The popup is not visible, yet a menu item is selected. The request
552*b1cdbd2cSJim Jagielski // most likely comes from the accessible object. Make sure this
553*b1cdbd2cSJim Jagielski // window, as well as all its parent windows are visible.
554*b1cdbd2cSJim Jagielski if (!IsVisible() && mpParentMenu)
555*b1cdbd2cSJim Jagielski mpParentMenu->ensureSubMenuVisible(this);
556*b1cdbd2cSJim Jagielski }
557*b1cdbd2cSJim Jagielski
558*b1cdbd2cSJim Jagielski selectMenuItem(mnSelectedMenu, false, bSubMenuTimer);
559*b1cdbd2cSJim Jagielski selectMenuItem(nPos, true, bSubMenuTimer);
560*b1cdbd2cSJim Jagielski mnSelectedMenu = nPos;
561*b1cdbd2cSJim Jagielski
562*b1cdbd2cSJim Jagielski fireMenuHighlightedEvent();
563*b1cdbd2cSJim Jagielski }
564*b1cdbd2cSJim Jagielski
getSelectedMenuItem() const565*b1cdbd2cSJim Jagielski size_t ScMenuFloatingWindow::getSelectedMenuItem() const
566*b1cdbd2cSJim Jagielski {
567*b1cdbd2cSJim Jagielski return mnSelectedMenu;
568*b1cdbd2cSJim Jagielski }
569*b1cdbd2cSJim Jagielski
handleMenuTimeout(SubMenuItemData * pTimer)570*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::handleMenuTimeout(SubMenuItemData* pTimer)
571*b1cdbd2cSJim Jagielski {
572*b1cdbd2cSJim Jagielski if (pTimer == &maOpenTimer)
573*b1cdbd2cSJim Jagielski {
574*b1cdbd2cSJim Jagielski // Close any open submenu immediately.
575*b1cdbd2cSJim Jagielski if (maCloseTimer.mpSubMenu)
576*b1cdbd2cSJim Jagielski {
577*b1cdbd2cSJim Jagielski maCloseTimer.mpSubMenu->EndPopupMode();
578*b1cdbd2cSJim Jagielski maCloseTimer.mpSubMenu = NULL;
579*b1cdbd2cSJim Jagielski maCloseTimer.maTimer.Stop();
580*b1cdbd2cSJim Jagielski }
581*b1cdbd2cSJim Jagielski
582*b1cdbd2cSJim Jagielski launchSubMenu(false);
583*b1cdbd2cSJim Jagielski }
584*b1cdbd2cSJim Jagielski else if (pTimer == &maCloseTimer)
585*b1cdbd2cSJim Jagielski {
586*b1cdbd2cSJim Jagielski // end submenu.
587*b1cdbd2cSJim Jagielski if (maCloseTimer.mpSubMenu)
588*b1cdbd2cSJim Jagielski {
589*b1cdbd2cSJim Jagielski maOpenTimer.mpSubMenu = NULL;
590*b1cdbd2cSJim Jagielski
591*b1cdbd2cSJim Jagielski maCloseTimer.mpSubMenu->EndPopupMode();
592*b1cdbd2cSJim Jagielski maCloseTimer.mpSubMenu = NULL;
593*b1cdbd2cSJim Jagielski
594*b1cdbd2cSJim Jagielski highlightMenuItem(maOpenTimer.mnMenuPos, false);
595*b1cdbd2cSJim Jagielski maOpenTimer.mnMenuPos = MENU_NOT_SELECTED;
596*b1cdbd2cSJim Jagielski }
597*b1cdbd2cSJim Jagielski }
598*b1cdbd2cSJim Jagielski }
599*b1cdbd2cSJim Jagielski
queueLaunchSubMenu(size_t nPos,ScMenuFloatingWindow * pMenu)600*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu)
601*b1cdbd2cSJim Jagielski {
602*b1cdbd2cSJim Jagielski if (!pMenu)
603*b1cdbd2cSJim Jagielski return;
604*b1cdbd2cSJim Jagielski
605*b1cdbd2cSJim Jagielski // Set the submenu on launch queue.
606*b1cdbd2cSJim Jagielski if (maOpenTimer.mpSubMenu)
607*b1cdbd2cSJim Jagielski {
608*b1cdbd2cSJim Jagielski if (maOpenTimer.mpSubMenu == pMenu)
609*b1cdbd2cSJim Jagielski {
610*b1cdbd2cSJim Jagielski if (pMenu == maCloseTimer.mpSubMenu)
611*b1cdbd2cSJim Jagielski maCloseTimer.reset();
612*b1cdbd2cSJim Jagielski return;
613*b1cdbd2cSJim Jagielski }
614*b1cdbd2cSJim Jagielski
615*b1cdbd2cSJim Jagielski // new submenu is being requested.
616*b1cdbd2cSJim Jagielski queueCloseSubMenu();
617*b1cdbd2cSJim Jagielski }
618*b1cdbd2cSJim Jagielski
619*b1cdbd2cSJim Jagielski maOpenTimer.mpSubMenu = pMenu;
620*b1cdbd2cSJim Jagielski maOpenTimer.mnMenuPos = nPos;
621*b1cdbd2cSJim Jagielski maOpenTimer.maTimer.Start();
622*b1cdbd2cSJim Jagielski }
623*b1cdbd2cSJim Jagielski
queueCloseSubMenu()624*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::queueCloseSubMenu()
625*b1cdbd2cSJim Jagielski {
626*b1cdbd2cSJim Jagielski if (!maOpenTimer.mpSubMenu)
627*b1cdbd2cSJim Jagielski // There is no submenu to close.
628*b1cdbd2cSJim Jagielski return;
629*b1cdbd2cSJim Jagielski
630*b1cdbd2cSJim Jagielski // Stop any submenu on queue for opening.
631*b1cdbd2cSJim Jagielski maOpenTimer.maTimer.Stop();
632*b1cdbd2cSJim Jagielski
633*b1cdbd2cSJim Jagielski maCloseTimer.mpSubMenu = maOpenTimer.mpSubMenu;
634*b1cdbd2cSJim Jagielski maCloseTimer.mnMenuPos = maOpenTimer.mnMenuPos;
635*b1cdbd2cSJim Jagielski maCloseTimer.maTimer.Start();
636*b1cdbd2cSJim Jagielski }
637*b1cdbd2cSJim Jagielski
launchSubMenu(bool bSetMenuPos)638*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::launchSubMenu(bool bSetMenuPos)
639*b1cdbd2cSJim Jagielski {
640*b1cdbd2cSJim Jagielski Point aPos;
641*b1cdbd2cSJim Jagielski Size aSize;
642*b1cdbd2cSJim Jagielski getMenuItemPosSize(maOpenTimer.mnMenuPos, aPos, aSize);
643*b1cdbd2cSJim Jagielski ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu;
644*b1cdbd2cSJim Jagielski
645*b1cdbd2cSJim Jagielski if (!pSubMenu)
646*b1cdbd2cSJim Jagielski return;
647*b1cdbd2cSJim Jagielski
648*b1cdbd2cSJim Jagielski sal_uInt32 nOldFlags = GetPopupModeFlags();
649*b1cdbd2cSJim Jagielski SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
650*b1cdbd2cSJim Jagielski pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
651*b1cdbd2cSJim Jagielski pSubMenu->StartPopupMode(
652*b1cdbd2cSJim Jagielski Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
653*b1cdbd2cSJim Jagielski pSubMenu->AddPopupModeWindow(this);
654*b1cdbd2cSJim Jagielski if (bSetMenuPos)
655*b1cdbd2cSJim Jagielski pSubMenu->setSelectedMenuItem(0, false, false); // select menu item after the popup becomes fully visible.
656*b1cdbd2cSJim Jagielski SetPopupModeFlags(nOldFlags);
657*b1cdbd2cSJim Jagielski }
658*b1cdbd2cSJim Jagielski
endSubMenu(ScMenuFloatingWindow * pSubMenu)659*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::endSubMenu(ScMenuFloatingWindow* pSubMenu)
660*b1cdbd2cSJim Jagielski {
661*b1cdbd2cSJim Jagielski if (!pSubMenu)
662*b1cdbd2cSJim Jagielski return;
663*b1cdbd2cSJim Jagielski
664*b1cdbd2cSJim Jagielski pSubMenu->EndPopupMode();
665*b1cdbd2cSJim Jagielski maOpenTimer.reset();
666*b1cdbd2cSJim Jagielski
667*b1cdbd2cSJim Jagielski size_t nMenuPos = getSubMenuPos(pSubMenu);
668*b1cdbd2cSJim Jagielski if (nMenuPos != MENU_NOT_SELECTED)
669*b1cdbd2cSJim Jagielski {
670*b1cdbd2cSJim Jagielski highlightMenuItem(nMenuPos, true);
671*b1cdbd2cSJim Jagielski mnSelectedMenu = nMenuPos;
672*b1cdbd2cSJim Jagielski fireMenuHighlightedEvent();
673*b1cdbd2cSJim Jagielski }
674*b1cdbd2cSJim Jagielski }
675*b1cdbd2cSJim Jagielski
fillMenuItemsToAccessible(ScAccessibleFilterMenu * pAccMenu) const676*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const
677*b1cdbd2cSJim Jagielski {
678*b1cdbd2cSJim Jagielski vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
679*b1cdbd2cSJim Jagielski for (itr = itrBeg; itr != itrEnd; ++itr)
680*b1cdbd2cSJim Jagielski {
681*b1cdbd2cSJim Jagielski size_t nPos = ::std::distance(itrBeg, itr);
682*b1cdbd2cSJim Jagielski pAccMenu->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
683*b1cdbd2cSJim Jagielski }
684*b1cdbd2cSJim Jagielski }
685*b1cdbd2cSJim Jagielski
getDoc()686*b1cdbd2cSJim Jagielski ScDocument* ScMenuFloatingWindow::getDoc()
687*b1cdbd2cSJim Jagielski {
688*b1cdbd2cSJim Jagielski return mpDoc;
689*b1cdbd2cSJim Jagielski }
690*b1cdbd2cSJim Jagielski
resizeToFitMenuItems()691*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::resizeToFitMenuItems()
692*b1cdbd2cSJim Jagielski {
693*b1cdbd2cSJim Jagielski if (maMenuItems.empty())
694*b1cdbd2cSJim Jagielski return;
695*b1cdbd2cSJim Jagielski
696*b1cdbd2cSJim Jagielski vector<MenuItemData>::const_iterator itr = maMenuItems.begin(), itrEnd = maMenuItems.end();
697*b1cdbd2cSJim Jagielski long nTextWidth = 0;
698*b1cdbd2cSJim Jagielski for (; itr != itrEnd; ++itr)
699*b1cdbd2cSJim Jagielski nTextWidth = ::std::max(GetTextWidth(itr->maText), nTextWidth);
700*b1cdbd2cSJim Jagielski
701*b1cdbd2cSJim Jagielski size_t nLastPos = maMenuItems.size()-1;
702*b1cdbd2cSJim Jagielski Point aPos;
703*b1cdbd2cSJim Jagielski Size aSize;
704*b1cdbd2cSJim Jagielski getMenuItemPosSize(nLastPos, aPos, aSize);
705*b1cdbd2cSJim Jagielski aPos.X() += nTextWidth + 15;
706*b1cdbd2cSJim Jagielski aPos.Y() += aSize.Height() + 5;
707*b1cdbd2cSJim Jagielski SetOutputSizePixel(Size(aPos.X(), aPos.Y()));
708*b1cdbd2cSJim Jagielski }
709*b1cdbd2cSJim Jagielski
selectMenuItem(size_t nPos,bool bSelected,bool bSubMenuTimer)710*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer)
711*b1cdbd2cSJim Jagielski {
712*b1cdbd2cSJim Jagielski if (nPos >= maMenuItems.size() || nPos == MENU_NOT_SELECTED)
713*b1cdbd2cSJim Jagielski {
714*b1cdbd2cSJim Jagielski queueCloseSubMenu();
715*b1cdbd2cSJim Jagielski return;
716*b1cdbd2cSJim Jagielski }
717*b1cdbd2cSJim Jagielski
718*b1cdbd2cSJim Jagielski if (!maMenuItems[nPos].mbEnabled)
719*b1cdbd2cSJim Jagielski {
720*b1cdbd2cSJim Jagielski queueCloseSubMenu();
721*b1cdbd2cSJim Jagielski return;
722*b1cdbd2cSJim Jagielski }
723*b1cdbd2cSJim Jagielski
724*b1cdbd2cSJim Jagielski highlightMenuItem(nPos, bSelected);
725*b1cdbd2cSJim Jagielski
726*b1cdbd2cSJim Jagielski if (bSelected)
727*b1cdbd2cSJim Jagielski {
728*b1cdbd2cSJim Jagielski if (mpParentMenu)
729*b1cdbd2cSJim Jagielski mpParentMenu->setSubMenuFocused(this);
730*b1cdbd2cSJim Jagielski
731*b1cdbd2cSJim Jagielski if (bSubMenuTimer)
732*b1cdbd2cSJim Jagielski {
733*b1cdbd2cSJim Jagielski if (maMenuItems[nPos].mpSubMenuWin)
734*b1cdbd2cSJim Jagielski {
735*b1cdbd2cSJim Jagielski ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get();
736*b1cdbd2cSJim Jagielski queueLaunchSubMenu(nPos, pSubMenu);
737*b1cdbd2cSJim Jagielski }
738*b1cdbd2cSJim Jagielski else
739*b1cdbd2cSJim Jagielski queueCloseSubMenu();
740*b1cdbd2cSJim Jagielski }
741*b1cdbd2cSJim Jagielski }
742*b1cdbd2cSJim Jagielski }
743*b1cdbd2cSJim Jagielski
clearSelectedMenuItem()744*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::clearSelectedMenuItem()
745*b1cdbd2cSJim Jagielski {
746*b1cdbd2cSJim Jagielski selectMenuItem(mnSelectedMenu, false, false);
747*b1cdbd2cSJim Jagielski mnSelectedMenu = MENU_NOT_SELECTED;
748*b1cdbd2cSJim Jagielski }
749*b1cdbd2cSJim Jagielski
getSubMenuWindow(size_t nPos) const750*b1cdbd2cSJim Jagielski ScMenuFloatingWindow* ScMenuFloatingWindow::getSubMenuWindow(size_t nPos) const
751*b1cdbd2cSJim Jagielski {
752*b1cdbd2cSJim Jagielski if (maMenuItems.size() <= nPos)
753*b1cdbd2cSJim Jagielski return NULL;
754*b1cdbd2cSJim Jagielski
755*b1cdbd2cSJim Jagielski return maMenuItems[nPos].mpSubMenuWin.get();
756*b1cdbd2cSJim Jagielski }
757*b1cdbd2cSJim Jagielski
isMenuItemSelected(size_t nPos) const758*b1cdbd2cSJim Jagielski bool ScMenuFloatingWindow::isMenuItemSelected(size_t nPos) const
759*b1cdbd2cSJim Jagielski {
760*b1cdbd2cSJim Jagielski return nPos == mnSelectedMenu;
761*b1cdbd2cSJim Jagielski }
762*b1cdbd2cSJim Jagielski
setName(const OUString & rName)763*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::setName(const OUString& rName)
764*b1cdbd2cSJim Jagielski {
765*b1cdbd2cSJim Jagielski maName = rName;
766*b1cdbd2cSJim Jagielski }
767*b1cdbd2cSJim Jagielski
getName() const768*b1cdbd2cSJim Jagielski const OUString& ScMenuFloatingWindow::getName() const
769*b1cdbd2cSJim Jagielski {
770*b1cdbd2cSJim Jagielski return maName;
771*b1cdbd2cSJim Jagielski }
772*b1cdbd2cSJim Jagielski
highlightMenuItem(size_t nPos,bool bSelected)773*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::highlightMenuItem(size_t nPos, bool bSelected)
774*b1cdbd2cSJim Jagielski {
775*b1cdbd2cSJim Jagielski if (nPos == MENU_NOT_SELECTED)
776*b1cdbd2cSJim Jagielski return;
777*b1cdbd2cSJim Jagielski
778*b1cdbd2cSJim Jagielski const StyleSettings& rStyle = GetSettings().GetStyleSettings();
779*b1cdbd2cSJim Jagielski Color aBackColor = rStyle.GetMenuColor();
780*b1cdbd2cSJim Jagielski SetFillColor(aBackColor);
781*b1cdbd2cSJim Jagielski SetLineColor(aBackColor);
782*b1cdbd2cSJim Jagielski
783*b1cdbd2cSJim Jagielski Point aPos;
784*b1cdbd2cSJim Jagielski Size aSize;
785*b1cdbd2cSJim Jagielski getMenuItemPosSize(nPos, aPos, aSize);
786*b1cdbd2cSJim Jagielski Rectangle aRegion(aPos,aSize);
787*b1cdbd2cSJim Jagielski
788*b1cdbd2cSJim Jagielski if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
789*b1cdbd2cSJim Jagielski {
790*b1cdbd2cSJim Jagielski Push(PUSH_CLIPREGION);
791*b1cdbd2cSJim Jagielski IntersectClipRegion(Rectangle(aPos, aSize));
792*b1cdbd2cSJim Jagielski Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
793*b1cdbd2cSJim Jagielski DrawNativeControl(
794*b1cdbd2cSJim Jagielski CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
795*b1cdbd2cSJim Jagielski ImplControlValue(), OUString());
796*b1cdbd2cSJim Jagielski
797*b1cdbd2cSJim Jagielski Pop();
798*b1cdbd2cSJim Jagielski }
799*b1cdbd2cSJim Jagielski
800*b1cdbd2cSJim Jagielski bool bNativeDrawn = true;
801*b1cdbd2cSJim Jagielski if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
802*b1cdbd2cSJim Jagielski {
803*b1cdbd2cSJim Jagielski ControlState nState = bSelected ? CTRL_STATE_SELECTED : 0;
804*b1cdbd2cSJim Jagielski if (maMenuItems[nPos].mbEnabled)
805*b1cdbd2cSJim Jagielski nState |= CTRL_STATE_ENABLED;
806*b1cdbd2cSJim Jagielski bNativeDrawn = DrawNativeControl(
807*b1cdbd2cSJim Jagielski CTRL_MENU_POPUP, PART_MENU_ITEM, aRegion, nState, ImplControlValue(), OUString());
808*b1cdbd2cSJim Jagielski }
809*b1cdbd2cSJim Jagielski else
810*b1cdbd2cSJim Jagielski bNativeDrawn = false;
811*b1cdbd2cSJim Jagielski
812*b1cdbd2cSJim Jagielski if (!bNativeDrawn)
813*b1cdbd2cSJim Jagielski {
814*b1cdbd2cSJim Jagielski if (bSelected)
815*b1cdbd2cSJim Jagielski {
816*b1cdbd2cSJim Jagielski aBackColor = rStyle.GetMenuHighlightColor();
817*b1cdbd2cSJim Jagielski SetFillColor(aBackColor);
818*b1cdbd2cSJim Jagielski SetLineColor(aBackColor);
819*b1cdbd2cSJim Jagielski }
820*b1cdbd2cSJim Jagielski DrawRect(Rectangle(aPos,aSize));
821*b1cdbd2cSJim Jagielski }
822*b1cdbd2cSJim Jagielski
823*b1cdbd2cSJim Jagielski Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor();
824*b1cdbd2cSJim Jagielski SetTextColor(aTextColor);
825*b1cdbd2cSJim Jagielski drawMenuItem(nPos);
826*b1cdbd2cSJim Jagielski }
827*b1cdbd2cSJim Jagielski
getMenuItemPosSize(size_t nPos,Point & rPos,Size & rSize) const828*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const
829*b1cdbd2cSJim Jagielski {
830*b1cdbd2cSJim Jagielski const sal_uInt16 nLeftMargin = 5;
831*b1cdbd2cSJim Jagielski const sal_uInt16 nTopMargin = 5;
832*b1cdbd2cSJim Jagielski const sal_uInt16 nMenuItemHeight = static_cast< sal_uInt16 >( maLabelFont.GetHeight()*1.8 );
833*b1cdbd2cSJim Jagielski
834*b1cdbd2cSJim Jagielski Size aWndSize = GetSizePixel();
835*b1cdbd2cSJim Jagielski
836*b1cdbd2cSJim Jagielski Point aPos1(nLeftMargin, nTopMargin);
837*b1cdbd2cSJim Jagielski Size aSize1(aWndSize.Width() - nLeftMargin*2, nMenuItemHeight);
838*b1cdbd2cSJim Jagielski
839*b1cdbd2cSJim Jagielski rPos = aPos1;
840*b1cdbd2cSJim Jagielski rPos.Y() += aSize1.Height()*nPos;
841*b1cdbd2cSJim Jagielski rSize = aSize1;
842*b1cdbd2cSJim Jagielski }
843*b1cdbd2cSJim Jagielski
getParentMenuWindow() const844*b1cdbd2cSJim Jagielski ScMenuFloatingWindow* ScMenuFloatingWindow::getParentMenuWindow() const
845*b1cdbd2cSJim Jagielski {
846*b1cdbd2cSJim Jagielski return mpParentMenu;
847*b1cdbd2cSJim Jagielski }
848*b1cdbd2cSJim Jagielski
getEnclosingMenuItem(const Point & rPos) const849*b1cdbd2cSJim Jagielski size_t ScMenuFloatingWindow::getEnclosingMenuItem(const Point& rPos) const
850*b1cdbd2cSJim Jagielski {
851*b1cdbd2cSJim Jagielski size_t n = maMenuItems.size();
852*b1cdbd2cSJim Jagielski for (size_t i = 0; i < n; ++i)
853*b1cdbd2cSJim Jagielski {
854*b1cdbd2cSJim Jagielski Point aPos;
855*b1cdbd2cSJim Jagielski Size aSize;
856*b1cdbd2cSJim Jagielski getMenuItemPosSize(i, aPos, aSize);
857*b1cdbd2cSJim Jagielski Rectangle aRect(aPos, aSize);
858*b1cdbd2cSJim Jagielski if (aRect.IsInside(rPos))
859*b1cdbd2cSJim Jagielski return i;
860*b1cdbd2cSJim Jagielski }
861*b1cdbd2cSJim Jagielski return MENU_NOT_SELECTED;
862*b1cdbd2cSJim Jagielski }
863*b1cdbd2cSJim Jagielski
getSubMenuPos(ScMenuFloatingWindow * pSubMenu)864*b1cdbd2cSJim Jagielski size_t ScMenuFloatingWindow::getSubMenuPos(ScMenuFloatingWindow* pSubMenu)
865*b1cdbd2cSJim Jagielski {
866*b1cdbd2cSJim Jagielski size_t n = maMenuItems.size();
867*b1cdbd2cSJim Jagielski for (size_t i = 0; i < n; ++i)
868*b1cdbd2cSJim Jagielski {
869*b1cdbd2cSJim Jagielski if (maMenuItems[i].mpSubMenuWin.get() == pSubMenu)
870*b1cdbd2cSJim Jagielski return i;
871*b1cdbd2cSJim Jagielski }
872*b1cdbd2cSJim Jagielski return MENU_NOT_SELECTED;
873*b1cdbd2cSJim Jagielski }
874*b1cdbd2cSJim Jagielski
fireMenuHighlightedEvent()875*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::fireMenuHighlightedEvent()
876*b1cdbd2cSJim Jagielski {
877*b1cdbd2cSJim Jagielski if (mnSelectedMenu == MENU_NOT_SELECTED)
878*b1cdbd2cSJim Jagielski return;
879*b1cdbd2cSJim Jagielski
880*b1cdbd2cSJim Jagielski if (!mxAccessible.is())
881*b1cdbd2cSJim Jagielski return;
882*b1cdbd2cSJim Jagielski
883*b1cdbd2cSJim Jagielski Reference<XAccessibleContext> xAccCxt = mxAccessible->getAccessibleContext();
884*b1cdbd2cSJim Jagielski if (!xAccCxt.is())
885*b1cdbd2cSJim Jagielski return;
886*b1cdbd2cSJim Jagielski
887*b1cdbd2cSJim Jagielski Reference<XAccessible> xAccMenu = xAccCxt->getAccessibleChild(mnSelectedMenu);
888*b1cdbd2cSJim Jagielski if (!xAccMenu.is())
889*b1cdbd2cSJim Jagielski return;
890*b1cdbd2cSJim Jagielski
891*b1cdbd2cSJim Jagielski VclAccessibleEvent aEvent(VCLEVENT_MENU_HIGHLIGHT, xAccMenu);
892*b1cdbd2cSJim Jagielski FireVclEvent(&aEvent);
893*b1cdbd2cSJim Jagielski }
894*b1cdbd2cSJim Jagielski
setSubMenuFocused(ScMenuFloatingWindow * pSubMenu)895*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::setSubMenuFocused(ScMenuFloatingWindow* pSubMenu)
896*b1cdbd2cSJim Jagielski {
897*b1cdbd2cSJim Jagielski maCloseTimer.reset();
898*b1cdbd2cSJim Jagielski size_t nMenuPos = getSubMenuPos(pSubMenu);
899*b1cdbd2cSJim Jagielski if (mnSelectedMenu != nMenuPos)
900*b1cdbd2cSJim Jagielski {
901*b1cdbd2cSJim Jagielski highlightMenuItem(nMenuPos, true);
902*b1cdbd2cSJim Jagielski mnSelectedMenu = nMenuPos;
903*b1cdbd2cSJim Jagielski }
904*b1cdbd2cSJim Jagielski }
905*b1cdbd2cSJim Jagielski
ensureSubMenuVisible(ScMenuFloatingWindow * pSubMenu)906*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu)
907*b1cdbd2cSJim Jagielski {
908*b1cdbd2cSJim Jagielski if (mpParentMenu)
909*b1cdbd2cSJim Jagielski mpParentMenu->ensureSubMenuVisible(this);
910*b1cdbd2cSJim Jagielski
911*b1cdbd2cSJim Jagielski if (pSubMenu->IsVisible())
912*b1cdbd2cSJim Jagielski return;
913*b1cdbd2cSJim Jagielski
914*b1cdbd2cSJim Jagielski // Find the menu position of the submenu.
915*b1cdbd2cSJim Jagielski size_t nMenuPos = getSubMenuPos(pSubMenu);
916*b1cdbd2cSJim Jagielski if (nMenuPos != MENU_NOT_SELECTED)
917*b1cdbd2cSJim Jagielski {
918*b1cdbd2cSJim Jagielski setSelectedMenuItem(nMenuPos, false, false);
919*b1cdbd2cSJim Jagielski
920*b1cdbd2cSJim Jagielski Point aPos;
921*b1cdbd2cSJim Jagielski Size aSize;
922*b1cdbd2cSJim Jagielski getMenuItemPosSize(nMenuPos, aPos, aSize);
923*b1cdbd2cSJim Jagielski
924*b1cdbd2cSJim Jagielski sal_uInt32 nOldFlags = GetPopupModeFlags();
925*b1cdbd2cSJim Jagielski SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
926*b1cdbd2cSJim Jagielski pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
927*b1cdbd2cSJim Jagielski pSubMenu->StartPopupMode(
928*b1cdbd2cSJim Jagielski Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
929*b1cdbd2cSJim Jagielski pSubMenu->AddPopupModeWindow(this);
930*b1cdbd2cSJim Jagielski SetPopupModeFlags(nOldFlags);
931*b1cdbd2cSJim Jagielski }
932*b1cdbd2cSJim Jagielski }
933*b1cdbd2cSJim Jagielski
ensureSubMenuNotVisible()934*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::ensureSubMenuNotVisible()
935*b1cdbd2cSJim Jagielski {
936*b1cdbd2cSJim Jagielski if (mnSelectedMenu <= maMenuItems.size() &&
937*b1cdbd2cSJim Jagielski maMenuItems[mnSelectedMenu].mpSubMenuWin &&
938*b1cdbd2cSJim Jagielski maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
939*b1cdbd2cSJim Jagielski {
940*b1cdbd2cSJim Jagielski maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
941*b1cdbd2cSJim Jagielski }
942*b1cdbd2cSJim Jagielski
943*b1cdbd2cSJim Jagielski EndPopupMode();
944*b1cdbd2cSJim Jagielski }
945*b1cdbd2cSJim Jagielski
terminateAllPopupMenus()946*b1cdbd2cSJim Jagielski void ScMenuFloatingWindow::terminateAllPopupMenus()
947*b1cdbd2cSJim Jagielski {
948*b1cdbd2cSJim Jagielski EndPopupMode();
949*b1cdbd2cSJim Jagielski if (mpParentMenu)
950*b1cdbd2cSJim Jagielski mpParentMenu->terminateAllPopupMenus();
951*b1cdbd2cSJim Jagielski }
952*b1cdbd2cSJim Jagielski
IMPL_LINK(ScMenuFloatingWindow,PopupEndHdl,void *,EMPTYARG)953*b1cdbd2cSJim Jagielski IMPL_LINK( ScMenuFloatingWindow, PopupEndHdl, void*, EMPTYARG )
954*b1cdbd2cSJim Jagielski {
955*b1cdbd2cSJim Jagielski clearSelectedMenuItem();
956*b1cdbd2cSJim Jagielski return 0;
957*b1cdbd2cSJim Jagielski }
958*b1cdbd2cSJim Jagielski
959*b1cdbd2cSJim Jagielski // ============================================================================
960*b1cdbd2cSJim Jagielski
Member()961*b1cdbd2cSJim Jagielski ScDPFieldPopupWindow::Member::Member() :
962*b1cdbd2cSJim Jagielski mbVisible(true)
963*b1cdbd2cSJim Jagielski {
964*b1cdbd2cSJim Jagielski }
965*b1cdbd2cSJim Jagielski
966*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
967*b1cdbd2cSJim Jagielski
CancelButton(ScDPFieldPopupWindow * pParent)968*b1cdbd2cSJim Jagielski ScDPFieldPopupWindow::CancelButton::CancelButton(ScDPFieldPopupWindow* pParent) :
969*b1cdbd2cSJim Jagielski ::CancelButton(pParent), mpParent(pParent) {}
970*b1cdbd2cSJim Jagielski
Click()971*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::CancelButton::Click()
972*b1cdbd2cSJim Jagielski {
973*b1cdbd2cSJim Jagielski mpParent->EndPopupMode();
974*b1cdbd2cSJim Jagielski ::CancelButton::Click();
975*b1cdbd2cSJim Jagielski }
976*b1cdbd2cSJim Jagielski
977*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
978*b1cdbd2cSJim Jagielski
ScDPFieldPopupWindow(Window * pParent,ScDocument * pDoc)979*b1cdbd2cSJim Jagielski ScDPFieldPopupWindow::ScDPFieldPopupWindow(Window* pParent, ScDocument* pDoc) :
980*b1cdbd2cSJim Jagielski ScMenuFloatingWindow(pParent, pDoc),
981*b1cdbd2cSJim Jagielski maChecks(this, 0),
982*b1cdbd2cSJim Jagielski maChkToggleAll(this, 0),
983*b1cdbd2cSJim Jagielski maBtnSelectSingle (this, 0),
984*b1cdbd2cSJim Jagielski maBtnUnselectSingle(this, 0),
985*b1cdbd2cSJim Jagielski maBtnOk(this),
986*b1cdbd2cSJim Jagielski maBtnCancel(this),
987*b1cdbd2cSJim Jagielski mnCurTabStop(0),
988*b1cdbd2cSJim Jagielski mpExtendedData(NULL),
989*b1cdbd2cSJim Jagielski mpOKAction(NULL),
990*b1cdbd2cSJim Jagielski maWndSize(240, 330),
991*b1cdbd2cSJim Jagielski mePrevToggleAllState(STATE_DONTKNOW)
992*b1cdbd2cSJim Jagielski {
993*b1cdbd2cSJim Jagielski maTabStopCtrls.reserve(7);
994*b1cdbd2cSJim Jagielski maTabStopCtrls.push_back(this);
995*b1cdbd2cSJim Jagielski maTabStopCtrls.push_back(&maChecks);
996*b1cdbd2cSJim Jagielski maTabStopCtrls.push_back(&maChkToggleAll);
997*b1cdbd2cSJim Jagielski maTabStopCtrls.push_back(&maBtnSelectSingle);
998*b1cdbd2cSJim Jagielski maTabStopCtrls.push_back(&maBtnUnselectSingle);
999*b1cdbd2cSJim Jagielski maTabStopCtrls.push_back(&maBtnOk);
1000*b1cdbd2cSJim Jagielski maTabStopCtrls.push_back(&maBtnCancel);
1001*b1cdbd2cSJim Jagielski
1002*b1cdbd2cSJim Jagielski const StyleSettings& rStyle = GetSettings().GetStyleSettings();
1003*b1cdbd2cSJim Jagielski
1004*b1cdbd2cSJim Jagielski Point aPos;
1005*b1cdbd2cSJim Jagielski Size aSize;
1006*b1cdbd2cSJim Jagielski getSectionPosSize(aPos, aSize, WHOLE);
1007*b1cdbd2cSJim Jagielski SetOutputSizePixel(aSize);
1008*b1cdbd2cSJim Jagielski Size aOutSize = GetOutputSizePixel();
1009*b1cdbd2cSJim Jagielski
1010*b1cdbd2cSJim Jagielski getSectionPosSize(aPos, aSize, BTN_OK);
1011*b1cdbd2cSJim Jagielski maBtnOk.SetPosSizePixel(aPos, aSize);
1012*b1cdbd2cSJim Jagielski maBtnOk.SetFont(getLabelFont());
1013*b1cdbd2cSJim Jagielski maBtnOk.SetClickHdl( LINK(this, ScDPFieldPopupWindow, ButtonHdl) );
1014*b1cdbd2cSJim Jagielski maBtnOk.Show();
1015*b1cdbd2cSJim Jagielski
1016*b1cdbd2cSJim Jagielski getSectionPosSize(aPos, aSize, BTN_CANCEL);
1017*b1cdbd2cSJim Jagielski maBtnCancel.SetPosSizePixel(aPos, aSize);
1018*b1cdbd2cSJim Jagielski maBtnCancel.SetFont(getLabelFont());
1019*b1cdbd2cSJim Jagielski maBtnCancel.Show();
1020*b1cdbd2cSJim Jagielski
1021*b1cdbd2cSJim Jagielski getSectionPosSize(aPos, aSize, LISTBOX_AREA_INNER);
1022*b1cdbd2cSJim Jagielski maChecks.SetPosSizePixel(aPos, aSize);
1023*b1cdbd2cSJim Jagielski maChecks.SetFont(getLabelFont());
1024*b1cdbd2cSJim Jagielski maChecks.SetCheckButtonHdl( LINK(this, ScDPFieldPopupWindow, CheckHdl) );
1025*b1cdbd2cSJim Jagielski maChecks.Show();
1026*b1cdbd2cSJim Jagielski
1027*b1cdbd2cSJim Jagielski getSectionPosSize(aPos, aSize, CHECK_TOGGLE_ALL);
1028*b1cdbd2cSJim Jagielski maChkToggleAll.SetPosSizePixel(aPos, aSize);
1029*b1cdbd2cSJim Jagielski maChkToggleAll.SetFont(getLabelFont());
1030*b1cdbd2cSJim Jagielski maChkToggleAll.SetText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_TOGGLE_ALL).GetString());
1031*b1cdbd2cSJim Jagielski maChkToggleAll.SetControlBackground(rStyle.GetMenuColor());
1032*b1cdbd2cSJim Jagielski maChkToggleAll.SetClickHdl( LINK(this, ScDPFieldPopupWindow, TriStateHdl) );
1033*b1cdbd2cSJim Jagielski maChkToggleAll.Show();
1034*b1cdbd2cSJim Jagielski
1035*b1cdbd2cSJim Jagielski getSectionPosSize(aPos, aSize, BTN_SINGLE_SELECT);
1036*b1cdbd2cSJim Jagielski maBtnSelectSingle.SetPosSizePixel(aPos, aSize);
1037*b1cdbd2cSJim Jagielski maBtnSelectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_SELECT_CURRENT).GetString());
1038*b1cdbd2cSJim Jagielski maBtnSelectSingle.SetModeImage(Image(ScResId(RID_IMG_SELECT_CURRENT)), BMP_COLOR_NORMAL);
1039*b1cdbd2cSJim Jagielski maBtnSelectSingle.SetClickHdl( LINK(this, ScDPFieldPopupWindow, ButtonHdl) );
1040*b1cdbd2cSJim Jagielski maBtnSelectSingle.Show();
1041*b1cdbd2cSJim Jagielski
1042*b1cdbd2cSJim Jagielski getSectionPosSize(aPos, aSize, BTN_SINGLE_UNSELECT);
1043*b1cdbd2cSJim Jagielski maBtnUnselectSingle.SetPosSizePixel(aPos, aSize);
1044*b1cdbd2cSJim Jagielski maBtnUnselectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_UNSELECT_CURRENT).GetString());
1045*b1cdbd2cSJim Jagielski maBtnUnselectSingle.SetModeImage(Image(ScResId(RID_IMG_UNSELECT_CURRENT)), BMP_COLOR_NORMAL);
1046*b1cdbd2cSJim Jagielski maBtnUnselectSingle.SetClickHdl( LINK(this, ScDPFieldPopupWindow, ButtonHdl) );
1047*b1cdbd2cSJim Jagielski maBtnUnselectSingle.Show();
1048*b1cdbd2cSJim Jagielski }
1049*b1cdbd2cSJim Jagielski
~ScDPFieldPopupWindow()1050*b1cdbd2cSJim Jagielski ScDPFieldPopupWindow::~ScDPFieldPopupWindow()
1051*b1cdbd2cSJim Jagielski {
1052*b1cdbd2cSJim Jagielski }
1053*b1cdbd2cSJim Jagielski
getSectionPosSize(Point & rPos,Size & rSize,SectionType eType) const1054*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const
1055*b1cdbd2cSJim Jagielski {
1056*b1cdbd2cSJim Jagielski // constant parameters.
1057*b1cdbd2cSJim Jagielski const sal_uInt16 nListBoxMargin = 5; // horizontal distance from the side of the dialog to the listbox border.
1058*b1cdbd2cSJim Jagielski const sal_uInt16 nListBoxInnerPadding = 5;
1059*b1cdbd2cSJim Jagielski const sal_uInt16 nTopMargin = 5;
1060*b1cdbd2cSJim Jagielski const sal_uInt16 nMenuHeight = 60;
1061*b1cdbd2cSJim Jagielski const sal_uInt16 nSingleItemBtnAreaHeight = 32; // height of the middle area below the list box where the single-action buttons are.
1062*b1cdbd2cSJim Jagielski const sal_uInt16 nBottomBtnAreaHeight = 50; // height of the bottom area where the OK and Cancel buttons are.
1063*b1cdbd2cSJim Jagielski const sal_uInt16 nBtnWidth = 90;
1064*b1cdbd2cSJim Jagielski const sal_uInt16 nLabelHeight = static_cast< sal_uInt16 >( getLabelFont().GetHeight() );
1065*b1cdbd2cSJim Jagielski const sal_uInt16 nBtnHeight = nLabelHeight*2;
1066*b1cdbd2cSJim Jagielski const sal_uInt16 nBottomMargin = 10;
1067*b1cdbd2cSJim Jagielski const sal_uInt16 nMenuListMargin = 20;
1068*b1cdbd2cSJim Jagielski
1069*b1cdbd2cSJim Jagielski // parameters calculated from constants.
1070*b1cdbd2cSJim Jagielski const sal_uInt16 nListBoxWidth = static_cast< sal_uInt16 >( maWndSize.Width() - nListBoxMargin*2 );
1071*b1cdbd2cSJim Jagielski const sal_uInt16 nListBoxHeight = static_cast< sal_uInt16 >( maWndSize.Height() - nTopMargin - nMenuHeight -
1072*b1cdbd2cSJim Jagielski nMenuListMargin - nSingleItemBtnAreaHeight - nBottomBtnAreaHeight );
1073*b1cdbd2cSJim Jagielski
1074*b1cdbd2cSJim Jagielski const sal_uInt16 nSingleBtnAreaY = nTopMargin + nMenuHeight + nListBoxHeight + nMenuListMargin - 1;
1075*b1cdbd2cSJim Jagielski
1076*b1cdbd2cSJim Jagielski switch (eType)
1077*b1cdbd2cSJim Jagielski {
1078*b1cdbd2cSJim Jagielski case WHOLE:
1079*b1cdbd2cSJim Jagielski {
1080*b1cdbd2cSJim Jagielski rPos = Point(0, 0);
1081*b1cdbd2cSJim Jagielski rSize = maWndSize;
1082*b1cdbd2cSJim Jagielski }
1083*b1cdbd2cSJim Jagielski break;
1084*b1cdbd2cSJim Jagielski case LISTBOX_AREA_OUTER:
1085*b1cdbd2cSJim Jagielski {
1086*b1cdbd2cSJim Jagielski rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
1087*b1cdbd2cSJim Jagielski rSize = Size(nListBoxWidth, nListBoxHeight);
1088*b1cdbd2cSJim Jagielski }
1089*b1cdbd2cSJim Jagielski break;
1090*b1cdbd2cSJim Jagielski case LISTBOX_AREA_INNER:
1091*b1cdbd2cSJim Jagielski {
1092*b1cdbd2cSJim Jagielski rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
1093*b1cdbd2cSJim Jagielski rPos.X() += nListBoxInnerPadding;
1094*b1cdbd2cSJim Jagielski rPos.Y() += nListBoxInnerPadding;
1095*b1cdbd2cSJim Jagielski
1096*b1cdbd2cSJim Jagielski rSize = Size(nListBoxWidth, nListBoxHeight);
1097*b1cdbd2cSJim Jagielski rSize.Width() -= nListBoxInnerPadding*2;
1098*b1cdbd2cSJim Jagielski rSize.Height() -= nListBoxInnerPadding*2;
1099*b1cdbd2cSJim Jagielski }
1100*b1cdbd2cSJim Jagielski break;
1101*b1cdbd2cSJim Jagielski case SINGLE_BTN_AREA:
1102*b1cdbd2cSJim Jagielski {
1103*b1cdbd2cSJim Jagielski rPos = Point(nListBoxMargin, nSingleBtnAreaY);
1104*b1cdbd2cSJim Jagielski rSize = Size(nListBoxWidth, nSingleItemBtnAreaHeight);
1105*b1cdbd2cSJim Jagielski }
1106*b1cdbd2cSJim Jagielski break;
1107*b1cdbd2cSJim Jagielski case CHECK_TOGGLE_ALL:
1108*b1cdbd2cSJim Jagielski {
1109*b1cdbd2cSJim Jagielski long h = nLabelHeight*3/2; // check box height is heuristically 150% of the text height.
1110*b1cdbd2cSJim Jagielski rPos = Point(nListBoxMargin, nSingleBtnAreaY);
1111*b1cdbd2cSJim Jagielski rPos.X() += 5;
1112*b1cdbd2cSJim Jagielski rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
1113*b1cdbd2cSJim Jagielski rSize = Size(70, h);
1114*b1cdbd2cSJim Jagielski }
1115*b1cdbd2cSJim Jagielski break;
1116*b1cdbd2cSJim Jagielski case BTN_SINGLE_SELECT:
1117*b1cdbd2cSJim Jagielski {
1118*b1cdbd2cSJim Jagielski long h = 26;
1119*b1cdbd2cSJim Jagielski rPos = Point(nListBoxMargin, nSingleBtnAreaY);
1120*b1cdbd2cSJim Jagielski rPos.X() += 150;
1121*b1cdbd2cSJim Jagielski rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
1122*b1cdbd2cSJim Jagielski rSize = Size(h, h);
1123*b1cdbd2cSJim Jagielski }
1124*b1cdbd2cSJim Jagielski break;
1125*b1cdbd2cSJim Jagielski case BTN_SINGLE_UNSELECT:
1126*b1cdbd2cSJim Jagielski {
1127*b1cdbd2cSJim Jagielski long h = 26;
1128*b1cdbd2cSJim Jagielski rPos = Point(nListBoxMargin, nSingleBtnAreaY);
1129*b1cdbd2cSJim Jagielski rPos.X() += 150 + h + 10;
1130*b1cdbd2cSJim Jagielski rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
1131*b1cdbd2cSJim Jagielski rSize = Size(h, h);
1132*b1cdbd2cSJim Jagielski }
1133*b1cdbd2cSJim Jagielski break;
1134*b1cdbd2cSJim Jagielski case BTN_OK:
1135*b1cdbd2cSJim Jagielski {
1136*b1cdbd2cSJim Jagielski long x = (maWndSize.Width() - nBtnWidth*2)/3;
1137*b1cdbd2cSJim Jagielski long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
1138*b1cdbd2cSJim Jagielski rPos = Point(x, y);
1139*b1cdbd2cSJim Jagielski rSize = Size(nBtnWidth, nBtnHeight);
1140*b1cdbd2cSJim Jagielski }
1141*b1cdbd2cSJim Jagielski break;
1142*b1cdbd2cSJim Jagielski case BTN_CANCEL:
1143*b1cdbd2cSJim Jagielski {
1144*b1cdbd2cSJim Jagielski long x = (maWndSize.Width() - nBtnWidth*2)/3*2 + nBtnWidth;
1145*b1cdbd2cSJim Jagielski long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
1146*b1cdbd2cSJim Jagielski rPos = Point(x, y);
1147*b1cdbd2cSJim Jagielski rSize = Size(nBtnWidth, nBtnHeight);
1148*b1cdbd2cSJim Jagielski }
1149*b1cdbd2cSJim Jagielski break;
1150*b1cdbd2cSJim Jagielski default:
1151*b1cdbd2cSJim Jagielski ;
1152*b1cdbd2cSJim Jagielski }
1153*b1cdbd2cSJim Jagielski }
1154*b1cdbd2cSJim Jagielski
setAllMemberState(bool bSet)1155*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::setAllMemberState(bool bSet)
1156*b1cdbd2cSJim Jagielski {
1157*b1cdbd2cSJim Jagielski size_t n = maMembers.size();
1158*b1cdbd2cSJim Jagielski for (size_t i = 0; i < n; ++i)
1159*b1cdbd2cSJim Jagielski maChecks.CheckEntryPos(static_cast< sal_uInt16 >( i ), bSet);
1160*b1cdbd2cSJim Jagielski }
1161*b1cdbd2cSJim Jagielski
selectCurrentMemberOnly(bool bSet)1162*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::selectCurrentMemberOnly(bool bSet)
1163*b1cdbd2cSJim Jagielski {
1164*b1cdbd2cSJim Jagielski setAllMemberState(!bSet);
1165*b1cdbd2cSJim Jagielski sal_uInt16 nSelected = maChecks.GetSelectEntryPos();
1166*b1cdbd2cSJim Jagielski maChecks.CheckEntryPos(nSelected, bSet);
1167*b1cdbd2cSJim Jagielski }
1168*b1cdbd2cSJim Jagielski
cycleFocus(bool bReverse)1169*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::cycleFocus(bool bReverse)
1170*b1cdbd2cSJim Jagielski {
1171*b1cdbd2cSJim Jagielski maTabStopCtrls[mnCurTabStop]->SetFakeFocus(false);
1172*b1cdbd2cSJim Jagielski maTabStopCtrls[mnCurTabStop]->LoseFocus();
1173*b1cdbd2cSJim Jagielski if (mnCurTabStop == 0)
1174*b1cdbd2cSJim Jagielski clearSelectedMenuItem();
1175*b1cdbd2cSJim Jagielski
1176*b1cdbd2cSJim Jagielski if (bReverse)
1177*b1cdbd2cSJim Jagielski {
1178*b1cdbd2cSJim Jagielski if (mnCurTabStop > 0)
1179*b1cdbd2cSJim Jagielski --mnCurTabStop;
1180*b1cdbd2cSJim Jagielski else
1181*b1cdbd2cSJim Jagielski mnCurTabStop = maTabStopCtrls.size() - 1;
1182*b1cdbd2cSJim Jagielski }
1183*b1cdbd2cSJim Jagielski else
1184*b1cdbd2cSJim Jagielski {
1185*b1cdbd2cSJim Jagielski ++mnCurTabStop;
1186*b1cdbd2cSJim Jagielski if (mnCurTabStop >= maTabStopCtrls.size())
1187*b1cdbd2cSJim Jagielski mnCurTabStop = 0;
1188*b1cdbd2cSJim Jagielski }
1189*b1cdbd2cSJim Jagielski maTabStopCtrls[mnCurTabStop]->SetFakeFocus(true);
1190*b1cdbd2cSJim Jagielski maTabStopCtrls[mnCurTabStop]->GrabFocus();
1191*b1cdbd2cSJim Jagielski }
1192*b1cdbd2cSJim Jagielski
IMPL_LINK(ScDPFieldPopupWindow,ButtonHdl,Button *,pBtn)1193*b1cdbd2cSJim Jagielski IMPL_LINK( ScDPFieldPopupWindow, ButtonHdl, Button*, pBtn )
1194*b1cdbd2cSJim Jagielski {
1195*b1cdbd2cSJim Jagielski if (pBtn == &maBtnOk)
1196*b1cdbd2cSJim Jagielski close(true);
1197*b1cdbd2cSJim Jagielski else if (pBtn == &maBtnSelectSingle)
1198*b1cdbd2cSJim Jagielski {
1199*b1cdbd2cSJim Jagielski selectCurrentMemberOnly(true);
1200*b1cdbd2cSJim Jagielski CheckHdl(&maChecks);
1201*b1cdbd2cSJim Jagielski }
1202*b1cdbd2cSJim Jagielski else if (pBtn == &maBtnUnselectSingle)
1203*b1cdbd2cSJim Jagielski {
1204*b1cdbd2cSJim Jagielski selectCurrentMemberOnly(false);
1205*b1cdbd2cSJim Jagielski CheckHdl(&maChecks);
1206*b1cdbd2cSJim Jagielski }
1207*b1cdbd2cSJim Jagielski return 0;
1208*b1cdbd2cSJim Jagielski }
1209*b1cdbd2cSJim Jagielski
IMPL_LINK(ScDPFieldPopupWindow,TriStateHdl,TriStateBox *,EMPTYARG)1210*b1cdbd2cSJim Jagielski IMPL_LINK( ScDPFieldPopupWindow, TriStateHdl, TriStateBox*, EMPTYARG )
1211*b1cdbd2cSJim Jagielski {
1212*b1cdbd2cSJim Jagielski switch (mePrevToggleAllState)
1213*b1cdbd2cSJim Jagielski {
1214*b1cdbd2cSJim Jagielski case STATE_NOCHECK:
1215*b1cdbd2cSJim Jagielski maChkToggleAll.SetState(STATE_CHECK);
1216*b1cdbd2cSJim Jagielski setAllMemberState(true);
1217*b1cdbd2cSJim Jagielski break;
1218*b1cdbd2cSJim Jagielski case STATE_CHECK:
1219*b1cdbd2cSJim Jagielski maChkToggleAll.SetState(STATE_NOCHECK);
1220*b1cdbd2cSJim Jagielski setAllMemberState(false);
1221*b1cdbd2cSJim Jagielski break;
1222*b1cdbd2cSJim Jagielski case STATE_DONTKNOW:
1223*b1cdbd2cSJim Jagielski default:
1224*b1cdbd2cSJim Jagielski maChkToggleAll.SetState(STATE_CHECK);
1225*b1cdbd2cSJim Jagielski setAllMemberState(true);
1226*b1cdbd2cSJim Jagielski break;
1227*b1cdbd2cSJim Jagielski }
1228*b1cdbd2cSJim Jagielski
1229*b1cdbd2cSJim Jagielski mePrevToggleAllState = maChkToggleAll.GetState();
1230*b1cdbd2cSJim Jagielski return 0;
1231*b1cdbd2cSJim Jagielski }
1232*b1cdbd2cSJim Jagielski
IMPL_LINK(ScDPFieldPopupWindow,CheckHdl,SvTreeListBox *,pChecks)1233*b1cdbd2cSJim Jagielski IMPL_LINK( ScDPFieldPopupWindow, CheckHdl, SvTreeListBox*, pChecks )
1234*b1cdbd2cSJim Jagielski {
1235*b1cdbd2cSJim Jagielski if (pChecks != &maChecks)
1236*b1cdbd2cSJim Jagielski return 0;
1237*b1cdbd2cSJim Jagielski
1238*b1cdbd2cSJim Jagielski size_t nNumChecked = maChecks.GetCheckedEntryCount();
1239*b1cdbd2cSJim Jagielski if (nNumChecked == maMembers.size())
1240*b1cdbd2cSJim Jagielski // all members visible
1241*b1cdbd2cSJim Jagielski maChkToggleAll.SetState(STATE_CHECK);
1242*b1cdbd2cSJim Jagielski else if (nNumChecked == 0)
1243*b1cdbd2cSJim Jagielski // no members visible
1244*b1cdbd2cSJim Jagielski maChkToggleAll.SetState(STATE_NOCHECK);
1245*b1cdbd2cSJim Jagielski else
1246*b1cdbd2cSJim Jagielski maChkToggleAll.SetState(STATE_DONTKNOW);
1247*b1cdbd2cSJim Jagielski
1248*b1cdbd2cSJim Jagielski mePrevToggleAllState = maChkToggleAll.GetState();
1249*b1cdbd2cSJim Jagielski return 0;
1250*b1cdbd2cSJim Jagielski }
1251*b1cdbd2cSJim Jagielski
MouseMove(const MouseEvent & rMEvt)1252*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::MouseMove(const MouseEvent& rMEvt)
1253*b1cdbd2cSJim Jagielski {
1254*b1cdbd2cSJim Jagielski ScMenuFloatingWindow::MouseMove(rMEvt);
1255*b1cdbd2cSJim Jagielski
1256*b1cdbd2cSJim Jagielski size_t nSelectedMenu = getSelectedMenuItem();
1257*b1cdbd2cSJim Jagielski if (nSelectedMenu == MENU_NOT_SELECTED)
1258*b1cdbd2cSJim Jagielski queueCloseSubMenu();
1259*b1cdbd2cSJim Jagielski }
1260*b1cdbd2cSJim Jagielski
Notify(NotifyEvent & rNEvt)1261*b1cdbd2cSJim Jagielski long ScDPFieldPopupWindow::Notify(NotifyEvent& rNEvt)
1262*b1cdbd2cSJim Jagielski {
1263*b1cdbd2cSJim Jagielski switch (rNEvt.GetType())
1264*b1cdbd2cSJim Jagielski {
1265*b1cdbd2cSJim Jagielski case EVENT_KEYUP:
1266*b1cdbd2cSJim Jagielski {
1267*b1cdbd2cSJim Jagielski const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
1268*b1cdbd2cSJim Jagielski const KeyCode& rCode = pKeyEvent->GetKeyCode();
1269*b1cdbd2cSJim Jagielski bool bShift = rCode.IsShift();
1270*b1cdbd2cSJim Jagielski if (rCode.GetCode() == KEY_TAB)
1271*b1cdbd2cSJim Jagielski {
1272*b1cdbd2cSJim Jagielski cycleFocus(bShift);
1273*b1cdbd2cSJim Jagielski return true;
1274*b1cdbd2cSJim Jagielski }
1275*b1cdbd2cSJim Jagielski }
1276*b1cdbd2cSJim Jagielski break;
1277*b1cdbd2cSJim Jagielski }
1278*b1cdbd2cSJim Jagielski return ScMenuFloatingWindow::Notify(rNEvt);
1279*b1cdbd2cSJim Jagielski }
1280*b1cdbd2cSJim Jagielski
Paint(const Rectangle & rRect)1281*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::Paint(const Rectangle& rRect)
1282*b1cdbd2cSJim Jagielski {
1283*b1cdbd2cSJim Jagielski ScMenuFloatingWindow::Paint(rRect);
1284*b1cdbd2cSJim Jagielski
1285*b1cdbd2cSJim Jagielski const StyleSettings& rStyle = GetSettings().GetStyleSettings();
1286*b1cdbd2cSJim Jagielski Color aMemberBackColor = rStyle.GetFieldColor();
1287*b1cdbd2cSJim Jagielski Color aBorderColor = rStyle.GetShadowColor();
1288*b1cdbd2cSJim Jagielski
1289*b1cdbd2cSJim Jagielski Point aPos;
1290*b1cdbd2cSJim Jagielski Size aSize;
1291*b1cdbd2cSJim Jagielski getSectionPosSize(aPos, aSize, LISTBOX_AREA_OUTER);
1292*b1cdbd2cSJim Jagielski
1293*b1cdbd2cSJim Jagielski // Member list box background
1294*b1cdbd2cSJim Jagielski SetFillColor(aMemberBackColor);
1295*b1cdbd2cSJim Jagielski SetLineColor(aBorderColor);
1296*b1cdbd2cSJim Jagielski DrawRect(Rectangle(aPos,aSize));
1297*b1cdbd2cSJim Jagielski
1298*b1cdbd2cSJim Jagielski // Single-action button box
1299*b1cdbd2cSJim Jagielski getSectionPosSize(aPos, aSize, SINGLE_BTN_AREA);
1300*b1cdbd2cSJim Jagielski SetFillColor(rStyle.GetMenuColor());
1301*b1cdbd2cSJim Jagielski DrawRect(Rectangle(aPos,aSize));
1302*b1cdbd2cSJim Jagielski }
1303*b1cdbd2cSJim Jagielski
GetPreferredKeyInputWindow()1304*b1cdbd2cSJim Jagielski Window* ScDPFieldPopupWindow::GetPreferredKeyInputWindow()
1305*b1cdbd2cSJim Jagielski {
1306*b1cdbd2cSJim Jagielski return maTabStopCtrls[mnCurTabStop];
1307*b1cdbd2cSJim Jagielski }
1308*b1cdbd2cSJim Jagielski
CreateAccessible()1309*b1cdbd2cSJim Jagielski Reference<XAccessible> ScDPFieldPopupWindow::CreateAccessible()
1310*b1cdbd2cSJim Jagielski {
1311*b1cdbd2cSJim Jagielski if (!mxAccessible.is())
1312*b1cdbd2cSJim Jagielski {
1313*b1cdbd2cSJim Jagielski mxAccessible.set(new ScAccessibleFilterTopWindow(
1314*b1cdbd2cSJim Jagielski GetAccessibleParentWindow()->GetAccessible(), this, getName(), getDoc()));
1315*b1cdbd2cSJim Jagielski ScAccessibleFilterTopWindow* pAccTop = static_cast<ScAccessibleFilterTopWindow*>(mxAccessible.get());
1316*b1cdbd2cSJim Jagielski fillMenuItemsToAccessible(pAccTop);
1317*b1cdbd2cSJim Jagielski
1318*b1cdbd2cSJim Jagielski pAccTop->setAccessibleChild(
1319*b1cdbd2cSJim Jagielski maChecks.CreateAccessible(), ScAccessibleFilterTopWindow::LISTBOX);
1320*b1cdbd2cSJim Jagielski pAccTop->setAccessibleChild(
1321*b1cdbd2cSJim Jagielski maChkToggleAll.CreateAccessible(), ScAccessibleFilterTopWindow::TOGGLE_ALL);
1322*b1cdbd2cSJim Jagielski pAccTop->setAccessibleChild(
1323*b1cdbd2cSJim Jagielski maBtnSelectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_ON_BTN);
1324*b1cdbd2cSJim Jagielski pAccTop->setAccessibleChild(
1325*b1cdbd2cSJim Jagielski maBtnUnselectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_OFF_BTN);
1326*b1cdbd2cSJim Jagielski pAccTop->setAccessibleChild(
1327*b1cdbd2cSJim Jagielski maBtnOk.CreateAccessible(), ScAccessibleFilterTopWindow::OK_BTN);
1328*b1cdbd2cSJim Jagielski pAccTop->setAccessibleChild(
1329*b1cdbd2cSJim Jagielski maBtnCancel.CreateAccessible(), ScAccessibleFilterTopWindow::CANCEL_BTN);
1330*b1cdbd2cSJim Jagielski }
1331*b1cdbd2cSJim Jagielski
1332*b1cdbd2cSJim Jagielski return mxAccessible;
1333*b1cdbd2cSJim Jagielski }
1334*b1cdbd2cSJim Jagielski
setMemberSize(size_t n)1335*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::setMemberSize(size_t n)
1336*b1cdbd2cSJim Jagielski {
1337*b1cdbd2cSJim Jagielski maMembers.reserve(n);
1338*b1cdbd2cSJim Jagielski }
1339*b1cdbd2cSJim Jagielski
addMember(const OUString & rName,bool bVisible)1340*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::addMember(const OUString& rName, bool bVisible)
1341*b1cdbd2cSJim Jagielski {
1342*b1cdbd2cSJim Jagielski Member aMember;
1343*b1cdbd2cSJim Jagielski aMember.maName = rName;
1344*b1cdbd2cSJim Jagielski aMember.mbVisible = bVisible;
1345*b1cdbd2cSJim Jagielski maMembers.push_back(aMember);
1346*b1cdbd2cSJim Jagielski }
1347*b1cdbd2cSJim Jagielski
initMembers()1348*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::initMembers()
1349*b1cdbd2cSJim Jagielski {
1350*b1cdbd2cSJim Jagielski size_t n = maMembers.size();
1351*b1cdbd2cSJim Jagielski size_t nVisMemCount = 0;
1352*b1cdbd2cSJim Jagielski for (size_t i = 0; i < n; ++i)
1353*b1cdbd2cSJim Jagielski {
1354*b1cdbd2cSJim Jagielski maChecks.InsertEntry(maMembers[i].maName);
1355*b1cdbd2cSJim Jagielski maChecks.CheckEntryPos(static_cast< sal_uInt16 >( i ), maMembers[i].mbVisible);
1356*b1cdbd2cSJim Jagielski if (maMembers[i].mbVisible)
1357*b1cdbd2cSJim Jagielski ++nVisMemCount;
1358*b1cdbd2cSJim Jagielski }
1359*b1cdbd2cSJim Jagielski if (nVisMemCount == n)
1360*b1cdbd2cSJim Jagielski {
1361*b1cdbd2cSJim Jagielski // all members visible
1362*b1cdbd2cSJim Jagielski maChkToggleAll.SetState(STATE_CHECK);
1363*b1cdbd2cSJim Jagielski mePrevToggleAllState = STATE_CHECK;
1364*b1cdbd2cSJim Jagielski }
1365*b1cdbd2cSJim Jagielski else if (nVisMemCount == 0)
1366*b1cdbd2cSJim Jagielski {
1367*b1cdbd2cSJim Jagielski // no members visible
1368*b1cdbd2cSJim Jagielski maChkToggleAll.SetState(STATE_NOCHECK);
1369*b1cdbd2cSJim Jagielski mePrevToggleAllState = STATE_NOCHECK;
1370*b1cdbd2cSJim Jagielski }
1371*b1cdbd2cSJim Jagielski else
1372*b1cdbd2cSJim Jagielski {
1373*b1cdbd2cSJim Jagielski maChkToggleAll.SetState(STATE_DONTKNOW);
1374*b1cdbd2cSJim Jagielski mePrevToggleAllState = STATE_DONTKNOW;
1375*b1cdbd2cSJim Jagielski }
1376*b1cdbd2cSJim Jagielski }
1377*b1cdbd2cSJim Jagielski
getWindowSize() const1378*b1cdbd2cSJim Jagielski const Size& ScDPFieldPopupWindow::getWindowSize() const
1379*b1cdbd2cSJim Jagielski {
1380*b1cdbd2cSJim Jagielski return maWndSize;
1381*b1cdbd2cSJim Jagielski }
1382*b1cdbd2cSJim Jagielski
getResult(hash_map<OUString,bool,OUStringHash> & rResult)1383*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::getResult(hash_map<OUString, bool, OUStringHash>& rResult)
1384*b1cdbd2cSJim Jagielski {
1385*b1cdbd2cSJim Jagielski typedef hash_map<OUString, bool, OUStringHash> ResultMap;
1386*b1cdbd2cSJim Jagielski ResultMap aResult;
1387*b1cdbd2cSJim Jagielski size_t n = maMembers.size();
1388*b1cdbd2cSJim Jagielski for (size_t i = 0; i < n; ++i)
1389*b1cdbd2cSJim Jagielski {
1390*b1cdbd2cSJim Jagielski bool bState = maChecks.IsChecked(static_cast< sal_uInt16 >( i ));
1391*b1cdbd2cSJim Jagielski aResult.insert(ResultMap::value_type(maMembers[i].maName, bState));
1392*b1cdbd2cSJim Jagielski }
1393*b1cdbd2cSJim Jagielski rResult.swap(aResult);
1394*b1cdbd2cSJim Jagielski }
1395*b1cdbd2cSJim Jagielski
close(bool bOK)1396*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::close(bool bOK)
1397*b1cdbd2cSJim Jagielski {
1398*b1cdbd2cSJim Jagielski if (bOK && mpOKAction.get())
1399*b1cdbd2cSJim Jagielski mpOKAction->execute();
1400*b1cdbd2cSJim Jagielski
1401*b1cdbd2cSJim Jagielski EndPopupMode();
1402*b1cdbd2cSJim Jagielski }
1403*b1cdbd2cSJim Jagielski
setExtendedData(ExtendedData * p)1404*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::setExtendedData(ExtendedData* p)
1405*b1cdbd2cSJim Jagielski {
1406*b1cdbd2cSJim Jagielski mpExtendedData.reset(p);
1407*b1cdbd2cSJim Jagielski }
1408*b1cdbd2cSJim Jagielski
getExtendedData()1409*b1cdbd2cSJim Jagielski ScDPFieldPopupWindow::ExtendedData* ScDPFieldPopupWindow::getExtendedData()
1410*b1cdbd2cSJim Jagielski {
1411*b1cdbd2cSJim Jagielski return mpExtendedData.get();
1412*b1cdbd2cSJim Jagielski }
1413*b1cdbd2cSJim Jagielski
setOKAction(Action * p)1414*b1cdbd2cSJim Jagielski void ScDPFieldPopupWindow::setOKAction(Action* p)
1415*b1cdbd2cSJim Jagielski {
1416*b1cdbd2cSJim Jagielski mpOKAction.reset(p);
1417*b1cdbd2cSJim Jagielski }
1418*b1cdbd2cSJim Jagielski
1419