blob: 90688f99094eefa7497916ffe1b66b1a2af8402d [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef SC_DPCONTROL_HXX
#define SC_DPCONTROL_HXX
#include "rtl/ustring.hxx"
#include "tools/gen.hxx"
#include "tools/fract.hxx"
#include "vcl/popupmenuwindow.hxx"
#include "vcl/button.hxx"
#include "vcl/scrbar.hxx"
#include "vcl/timer.hxx"
#include "svx/checklbx.hxx"
#include <boost/shared_ptr.hpp>
#include <memory>
#include <hash_map>
namespace com { namespace sun { namespace star {
namespace accessibility {
class XAccessible;
}
}}}
class OutputDevice;
class Point;
class Size;
class StyleSettings;
class Window;
class ScDocument;
class ScAccessibleFilterMenu;
/**
* This class takes care of physically drawing field button controls inside
* data pilot tables.
*/
class ScDPFieldButton
{
public:
ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle, const Fraction* pZoomX = NULL, const Fraction* pZoomY = NULL,
ScDocument* pDoc = NULL);
~ScDPFieldButton();
void setText(const ::rtl::OUString& rText);
void setBoundingBox(const Point& rPos, const Size& rSize, bool bLayoutRTL);
void setDrawBaseButton(bool b);
void setDrawPopupButton(bool b);
void setHasHiddenMember(bool b);
void setPopupPressed(bool b);
void setPopupLeft(bool b);
void draw();
void getPopupBoundingBox(Point& rPos, Size& rSize) const;
private:
void drawPopupButton();
private:
Point maPos;
Size maSize;
::rtl::OUString maText;
Fraction maZoomX;
Fraction maZoomY;
ScDocument* mpDoc;
OutputDevice* mpOutDev;
const StyleSettings* mpStyle;
bool mbBaseButton;
bool mbPopupButton;
bool mbHasHiddenMember;
bool mbPopupPressed;
bool mbPopupLeft;
};
// ============================================================================
class ScMenuFloatingWindow : public PopupMenuFloatingWindow
{
public:
static size_t MENU_NOT_SELECTED;
/**
* Action to perform when an event takes place. Create a sub-class of
* this to implement the desired action.
*/
class Action
{
public:
virtual void execute() = 0;
};
explicit ScMenuFloatingWindow(Window* pParent, ScDocument* pDoc, sal_uInt16 nMenuStackLevel = 0);
virtual ~ScMenuFloatingWindow();
virtual void MouseMove(const MouseEvent& rMEvt);
virtual void MouseButtonDown(const MouseEvent& rMEvt);
virtual void MouseButtonUp(const MouseEvent& rMEvt);
virtual void KeyInput(const KeyEvent& rKEvt);
virtual void Paint(const Rectangle& rRect);
virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
void addMenuItem(const ::rtl::OUString& rText, bool bEnabled, Action* pAction);
ScMenuFloatingWindow* addSubMenuItem(const ::rtl::OUString& rText, bool bEnabled);
void setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu);
void selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer);
void clearSelectedMenuItem();
ScMenuFloatingWindow* getSubMenuWindow(size_t nPos) const;
bool isMenuItemSelected(size_t nPos) const;
size_t getSelectedMenuItem() const;
void setName(const ::rtl::OUString& rName);
const ::rtl::OUString& getName() const;
void executeMenuItem(size_t nPos);
void getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const;
ScMenuFloatingWindow* getParentMenuWindow() const;
protected:
void drawMenuItem(size_t nPos);
void drawAllMenuItems();
const Font& getLabelFont() const;
void queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu);
void queueCloseSubMenu();
void launchSubMenu(bool bSetMenuPos);
void endSubMenu(ScMenuFloatingWindow* pSubMenu);
void fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const;
ScDocument* getDoc();
protected:
::com::sun::star::uno::Reference<
::com::sun::star::accessibility::XAccessible > mxAccessible;
private:
struct SubMenuItemData;
void handleMenuTimeout(SubMenuItemData* pTimer);
void resizeToFitMenuItems();
void highlightMenuItem(size_t nPos, bool bSelected);
size_t getEnclosingMenuItem(const Point& rPos) const;
size_t getSubMenuPos(ScMenuFloatingWindow* pSubMenu);
/**
* Fire a menu highlight event since the accessibility framework needs
* this to track focus on menu items.
*/
void fireMenuHighlightedEvent();
/**
* Make sure that the specified submenu is permanently up, the submenu
* close timer is not active, and the correct menu item associated with
* the submenu is highlighted.
*/
void setSubMenuFocused(ScMenuFloatingWindow* pSubMenu);
/**
* When a menu item of an invisible submenu is selected, we need to make
* sure that all its parent menu(s) are visible, with the right menu item
* highlighted in each of the parents. Calling this method ensures it.
*/
void ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu);
/**
* Dismiss any visible child submenus when a menu item of a parent menu is
* selected.
*/
void ensureSubMenuNotVisible();
/**
* Dismiss all visible popup menus and set focus back to the application
* window. This method is called e.g. when a menu action is fired.
*/
void terminateAllPopupMenus();
DECL_LINK( PopupEndHdl, void* );
private:
struct MenuItemData
{
::rtl::OUString maText;
bool mbEnabled;
::boost::shared_ptr<Action> mpAction;
::boost::shared_ptr<ScMenuFloatingWindow> mpSubMenuWin;
MenuItemData();
};
::std::vector<MenuItemData> maMenuItems;
struct SubMenuItemData
{
Timer maTimer;
ScMenuFloatingWindow* mpSubMenu;
size_t mnMenuPos;
DECL_LINK( TimeoutHdl, void* );
SubMenuItemData(ScMenuFloatingWindow* pParent);
void reset();
private:
ScMenuFloatingWindow* mpParent;
};
SubMenuItemData maOpenTimer;
SubMenuItemData maCloseTimer;
Font maLabelFont;
// Name of this menu window, taken from the menu item of the parent window
// that launches it (if this is a sub menu). If this is a top-level menu
// window, then this name can be anything.
::rtl::OUString maName;
size_t mnSelectedMenu;
size_t mnClickedMenu;
ScDocument* mpDoc;
ScMenuFloatingWindow* mpParentMenu;
ScMenuFloatingWindow* mpActiveSubMenu;
};
// ============================================================================
/**
* This class implements a popup window for field button, for quick access
* of hide-item list, and possibly more stuff related to field options.
*/
class ScDPFieldPopupWindow : public ScMenuFloatingWindow
{
public:
/**
* Extended data that the client code may need to store. Create a
* sub-class of this and store data there.
*/
struct ExtendedData {};
explicit ScDPFieldPopupWindow(Window* pParent, ScDocument* pDoc);
virtual ~ScDPFieldPopupWindow();
virtual void MouseMove(const MouseEvent& rMEvt);
virtual long Notify(NotifyEvent& rNEvt);
virtual void Paint(const Rectangle& rRect);
virtual Window* GetPreferredKeyInputWindow();
virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
void setMemberSize(size_t n);
void addMember(const ::rtl::OUString& rName, bool bVisible);
void initMembers();
const Size& getWindowSize() const;
void getResult(::std::hash_map< ::rtl::OUString, bool, ::rtl::OUStringHash>& rResult);
void close(bool bOK);
/**
* Set auxiliary data that the client code might need. Note that this
* popup window class manages its life time; no explicit deletion of the
* instance is needed in the client code.
*/
void setExtendedData(ExtendedData* p);
/**
* Get the store auxiliary data, or NULL if no such data is stored.
*/
ExtendedData* getExtendedData();
void setOKAction(Action* p);
private:
struct Member
{
::rtl::OUString maName;
bool mbVisible;
Member();
};
class CancelButton : public ::CancelButton
{
public:
CancelButton(ScDPFieldPopupWindow* pParent);
virtual void Click();
private:
ScDPFieldPopupWindow* mpParent;
};
enum SectionType {
WHOLE, // entire window
LISTBOX_AREA_OUTER, // box enclosing the check box items.
LISTBOX_AREA_INNER, // box enclosing the check box items.
SINGLE_BTN_AREA, // box enclosing the single-action buttons.
CHECK_TOGGLE_ALL, // check box for toggling all items.
BTN_SINGLE_SELECT,
BTN_SINGLE_UNSELECT,
BTN_OK, // OK button
BTN_CANCEL, // Cancel button
};
void getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const;
void setAllMemberState(bool bSet);
void selectCurrentMemberOnly(bool bSet);
void cycleFocus(bool bReverse = false);
DECL_LINK( ButtonHdl, Button* );
DECL_LINK( TriStateHdl, TriStateBox* );
DECL_LINK( CheckHdl, SvTreeListBox* );
private:
SvxCheckListBox maChecks;
TriStateBox maChkToggleAll;
ImageButton maBtnSelectSingle;
ImageButton maBtnUnselectSingle;
OKButton maBtnOk;
CancelButton maBtnCancel;
::std::vector<Window*> maTabStopCtrls;
size_t mnCurTabStop;
::std::vector<Member> maMembers;
::std::auto_ptr<ExtendedData> mpExtendedData;
::std::auto_ptr<Action> mpOKAction;
const Size maWndSize; /// hard-coded window size.
TriState mePrevToggleAllState;
};
#endif