xref: /aoo4110/main/sc/source/ui/cctrl/dpcontrol.cxx (revision b1cdbd2c)
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