diff options
-rw-r--r-- | extras/source/glade/libreoffice-catalog.xml.in | 3 | ||||
-rw-r--r-- | include/svtools/valueset.hxx | 201 | ||||
-rw-r--r-- | include/svx/SvxColorValueSet.hxx | 13 | ||||
-rw-r--r-- | include/vcl/customweld.hxx | 19 | ||||
-rw-r--r-- | include/vcl/layout.hxx | 24 | ||||
-rw-r--r-- | include/vcl/weld.hxx | 16 | ||||
-rw-r--r-- | sc/inc/scabstdlg.hxx | 8 | ||||
-rw-r--r-- | sc/qa/unit/screenshots/screenshots.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/attrdlg/scdlgfact.cxx | 13 | ||||
-rw-r--r-- | sc/source/ui/attrdlg/scdlgfact.hxx | 17 | ||||
-rw-r--r-- | sc/source/ui/inc/tabbgcolordlg.hxx | 29 | ||||
-rw-r--r-- | sc/source/ui/miscdlgs/tabbgcolordlg.cxx | 90 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwshf.cxx | 2 | ||||
-rw-r--r-- | sc/uiconfig/scalc/ui/tabcolordialog.ui | 53 | ||||
-rw-r--r-- | svtools/source/control/valueacc.cxx | 983 | ||||
-rw-r--r-- | svtools/source/control/valueimp.hxx | 198 | ||||
-rw-r--r-- | svtools/source/control/valueset.cxx | 1455 | ||||
-rw-r--r-- | svx/source/tbxctrls/SvxColorValueSet.cxx | 74 | ||||
-rw-r--r-- | vcl/source/app/customweld.cxx | 6 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 23 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 56 |
21 files changed, 3168 insertions, 117 deletions
diff --git a/extras/source/glade/libreoffice-catalog.xml.in b/extras/source/glade/libreoffice-catalog.xml.in index 22b33767161b..04fbd09c5a22 100644 --- a/extras/source/glade/libreoffice-catalog.xml.in +++ b/extras/source/glade/libreoffice-catalog.xml.in @@ -338,9 +338,6 @@ <glade-widget-class title="TableValueSet" name="sdlo-TableValueSet" generic-name="Set of Table Value Options" parent="GtkDrawingArea" icon-name="widget-gtk-drawingarea"/> - <glade-widget-class title="ScTabBgColorValueSet" name="scuilo-ScTabBgColorValueSet" - generic-name="Set of Tab Color Options" parent="GtkDrawingArea" - icon-name="widget-gtk-drawingarea"/> <glade-widget-class title="CsvTableBox" name="sclo-ScCsvTableBox" generic-name="CSV Table Box" parent="GtkDrawingArea" icon-name="widget-gtk-drawingarea"/> diff --git a/include/svtools/valueset.hxx b/include/svtools/valueset.hxx index 000e00268874..5530adf33da8 100644 --- a/include/svtools/valueset.hxx +++ b/include/svtools/valueset.hxx @@ -25,6 +25,7 @@ #include <vcl/ctrl.hxx> #include <vcl/virdev.hxx> #include <vcl/timer.hxx> +#include <vcl/customweld.hxx> #include <memory> #include <vector> @@ -36,6 +37,7 @@ class DataChangedEvent; class ScrollBar; struct ValueSetItem; +struct SvtValueSetItem; class ValueSetAcc; class ValueItemAcc; @@ -178,6 +180,7 @@ to be set (before Show) with SetStyle(). *************************************************************************/ typedef std::vector<ValueSetItem*> ValueItemList; +typedef std::vector<SvtValueSetItem*> SvtValueItemList; #define WB_ITEMBORDER (WinBits(0x00010000)) #define WB_DOUBLEBORDER (WinBits(0x00020000)) @@ -405,6 +408,204 @@ public: void SetEdgeBlending(bool bNew); }; +class SVT_DLLPUBLIC SvtValueSet : public weld::CustomWidgetController +{ +private: + + ScopedVclPtr<VirtualDevice> maVirDev; + css::uno::Reference<css::accessibility::XAccessible> mxAccessible; + SvtValueItemList mItemList; + std::unique_ptr<SvtValueSetItem> mpNoneItem; + tools::Rectangle maNoneItemRect; + tools::Rectangle maItemListRect; + long mnItemWidth; + long mnItemHeight; + long mnTextOffset; + long mnVisLines; + long mnLines; + long mnUserItemWidth; + long mnUserItemHeight; + sal_uInt16 mnSelItemId; + sal_uInt16 mnHighItemId; + sal_uInt16 mnCols; + sal_uInt16 mnCurCol; + sal_uInt16 mnUserCols; + sal_uInt16 mnUserVisLines; + sal_uInt16 mnFirstLine; + sal_uInt16 mnSpacing; + DrawFrameStyle mnFrameStyle; + Color maColor; + OUString maText; + WinBits mnStyle; + Link<SvtValueSet*,void> maDoubleClickHdl; + Link<SvtValueSet*,void> maSelectHdl; + Link<SvtValueSet*,void> maHighlightHdl; + + bool mbFormat : 1; + bool mbNoSelection : 1; + bool mbBlackSel : 1; + bool mbDoubleSel : 1; + bool mbScroll : 1; + bool mbFullMode : 1; + bool mbEdgeBlending : 1; + bool mbHasVisibleItems : 1; + + friend class SvtValueSetAcc; + friend class SvtValueItemAcc; + + SVT_DLLPRIVATE void ImplInitSettings( bool bFont, bool bForeground, bool bBackground ); + + SVT_DLLPRIVATE void ImplInitScrollBar(); + SVT_DLLPRIVATE void ImplDeleteItems(); + SVT_DLLPRIVATE void ImplFormatItem(vcl::RenderContext const & rRenderContext, SvtValueSetItem* pItem, tools::Rectangle aRect); + SVT_DLLPRIVATE void ImplDrawItemText(vcl::RenderContext& rRenderContext, const OUString& rStr); + SVT_DLLPRIVATE void ImplDrawSelect(vcl::RenderContext& rRenderContext, sal_uInt16 nItemId, const bool bFocus, const bool bDrawSel); + SVT_DLLPRIVATE void ImplDrawSelect(vcl::RenderContext& rRenderContext); + SVT_DLLPRIVATE void ImplDraw(vcl::RenderContext& rRenderContext); + SVT_DLLPRIVATE bool ImplScroll( const Point& rPos ); + SVT_DLLPRIVATE size_t ImplGetItem( const Point& rPoint ) const; + SVT_DLLPRIVATE SvtValueSetItem* ImplGetItem( size_t nPos ); + SVT_DLLPRIVATE SvtValueSetItem* ImplGetFirstItem(); + SVT_DLLPRIVATE sal_uInt16 ImplGetVisibleItemCount() const; + SVT_DLLPRIVATE void ImplInsertItem( SvtValueSetItem *const pItem, const size_t nPos ); + SVT_DLLPRIVATE tools::Rectangle ImplGetItemRect( size_t nPos ) const; + SVT_DLLPRIVATE void ImplFireAccessibleEvent( short nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue ); + SVT_DLLPRIVATE bool ImplHasAccessibleListeners(); + DECL_DLLPRIVATE_LINK( ImplScrollHdl, ScrollBar*, void ); + + SvtValueSet (const SvtValueSet &) = delete; + SvtValueSet & operator= (const SvtValueSet &) = delete; + +protected: + virtual css::uno::Reference<css::accessibility::XAccessible> CreateAccessible() override; + +public: + SvtValueSet(); + virtual ~SvtValueSet() override; + + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual bool KeyInput( const KeyEvent& rKEvt ) override; + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; + virtual void GetFocus() override; + virtual void LoseFocus() override; + virtual void Resize() override; + virtual void StyleUpdated() override; + virtual OUString RequestHelp(tools::Rectangle& rHelpRect) override; + + virtual void Select(); + virtual void UserDraw( const UserDrawEvent& rUDEvt ); + + OUString GetText() const { return maText; } + void SetText(const OUString& rText) { maText = rText; } + void SetStyle(WinBits nStyle) { mnStyle = nStyle; } + WinBits GetStyle() const { return mnStyle; } + + /// Insert @rImage item. + void InsertItem(sal_uInt16 nItemId, const Image& rImage); + /// Insert @rImage item with @rStr as either a legend or tooltip depending on @bShowLegend. + void InsertItem(sal_uInt16 nItemId, const Image& rImage, + const OUString& rStr, size_t nPos = VALUESET_APPEND, bool bShowLegend = false); + /// Insert an @rColor item with @rStr tooltip. + void InsertItem(sal_uInt16 nItemId, const Color& rColor, + const OUString& rStr); + /// Insert an User Drawn item. + void InsertItem(sal_uInt16 nItemId, size_t nPos = VALUESET_APPEND); + /// Insert an User Drawn item with @rStr tooltip. + void InsertItem(sal_uInt16 nItemId, const OUString& rStr, size_t nPos); + void RemoveItem(sal_uInt16 nItemId); + + void Clear(); + + size_t GetItemCount() const; + size_t GetItemPos( sal_uInt16 nItemId ) const; + sal_uInt16 GetItemId( size_t nPos ) const; + sal_uInt16 GetItemId( const Point& rPos ) const; + tools::Rectangle GetItemRect( sal_uInt16 nItemId ) const; + void EnableFullItemMode( bool bFullMode ); + + void SetColCount( sal_uInt16 nNewCols = 1 ); + sal_uInt16 GetColCount() const + { + return mnUserCols; + } + void SetLineCount( sal_uInt16 nNewLines = 0 ); + sal_uInt16 GetLineCount() const + { + return mnUserVisLines; + } + void SetItemWidth( long nItemWidth ); + void SetItemHeight( long nLineHeight ); + Size GetLargestItemSize(); + void RecalculateItemSizes(); + + void SelectItem( sal_uInt16 nItemId ); + sal_uInt16 GetSelectedItemId() const + { + return mnSelItemId; + } + size_t GetSelectItemPos() const + { + return GetItemPos( mnSelItemId ); + } + bool IsItemSelected( sal_uInt16 nItemId ) const + { + return !mbNoSelection && (nItemId == mnSelItemId); + } + void SetNoSelection(); + bool IsNoSelection() const + { + return mbNoSelection; + } + + void SetItemImage( sal_uInt16 nItemId, const Image& rImage ); + Image GetItemImage( sal_uInt16 nItemId ) const; + void SetItemColor( sal_uInt16 nItemId, const Color& rColor ); + Color GetItemColor( sal_uInt16 nItemId ) const; + void SetItemData( sal_uInt16 nItemId, void* pData ); + void* GetItemData( sal_uInt16 nItemId ) const; + void SetItemText( sal_uInt16 nItemId, const OUString& rStr ); + OUString GetItemText( sal_uInt16 nItemId ) const; + void SetColor( const Color& rColor ); + void SetColor() + { + SetColor(COL_TRANSPARENT); + } + bool IsColor() const + { + return maColor.GetTransparency() == 0; + } + + void SetExtraSpacing( sal_uInt16 nNewSpacing ); + + void Format(vcl::RenderContext const & rRenderContext); + void SetFormat(); + + Size CalcWindowSizePixel(const Size& rItemSize, + sal_uInt16 nCalcCols = 0, + sal_uInt16 nCalcLines = 0) const; + Size CalcItemSizePixel(const Size& rSize) const; + + void SetSelectHdl(const Link<SvtValueSet*,void>& rLink) + { + maSelectHdl = rLink; + } + void SetDoubleClickHdl(const Link<SvtValueSet*,void>& rLink) + { + maDoubleClickHdl = rLink; + } + + void SetHighlightHdl(const Link<SvtValueSet*,void>& rLink); + + bool GetEdgeBlending() const + { + return mbEdgeBlending; + } + void SetEdgeBlending(bool bNew); +}; + + #endif // INCLUDED_SVTOOLS_VALUESET_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/SvxColorValueSet.hxx b/include/svx/SvxColorValueSet.hxx index 1e6d6a615c79..32026c351814 100644 --- a/include/svx/SvxColorValueSet.hxx +++ b/include/svx/SvxColorValueSet.hxx @@ -42,6 +42,19 @@ public: Size layoutToGivenHeight(sal_uInt32 nHeight, sal_uInt32 nEntryCount); }; +class SVX_DLLPUBLIC ColorValueSet : public SvtValueSet +{ +public: + ColorValueSet(); + + virtual void Resize() override; + + void addEntriesForXColorList(const XColorList& rXColorList, sal_uInt32 nStartIndex = 1); + void addEntriesForColorSet(const std::set<Color>& rColorSet, const OUString& rNamePrefix); + Size layoutAllVisible(sal_uInt32 nEntryCount); + Size layoutToGivenHeight(sal_uInt32 nHeight, sal_uInt32 nEntryCount); +}; + #endif // INCLUDED_SVX_SVXCOLORVALUESET_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/customweld.hxx b/include/vcl/customweld.hxx index 274db81bd781..2395bc5e45f6 100644 --- a/include/vcl/customweld.hxx +++ b/include/vcl/customweld.hxx @@ -21,6 +21,10 @@ private: weld::DrawingArea* m_pDrawingArea; public: + virtual css::uno::Reference<css::accessibility::XAccessible> CreateAccessible() + { + return css::uno::Reference<css::accessibility::XAccessible>(); + } virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) = 0; virtual void Resize() {} virtual void MouseButtonDown(const MouseEvent&) {} @@ -30,17 +34,15 @@ public: virtual void LoseFocus() {} virtual void StyleUpdated() { Invalidate(); } virtual bool KeyInput(const KeyEvent&) { return false; } - virtual css::uno::Reference<css::accessibility::XAccessible> CreateAccessible() - { - return css::uno::Reference<css::accessibility::XAccessible>(); - } virtual tools::Rectangle GetFocusRect() { return tools::Rectangle(); } virtual FactoryFunction GetUITestFactory() const { return nullptr; } + virtual OUString RequestHelp(tools::Rectangle&) { return OUString(); } Size const& GetOutputSizePixel() const { return m_aSize; } void SetOutputSizePixel(const Size& rSize) { m_aSize = rSize; } virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) { m_pDrawingArea = pDrawingArea; } weld::DrawingArea* GetDrawingArea() const { return m_pDrawingArea; } void Invalidate() { m_pDrawingArea->queue_draw(); } + static bool IsUpdateMode() { return true; } void Invalidate(const tools::Rectangle& rRect) { m_pDrawingArea->queue_draw_area(rRect.Left(), rRect.Top(), rRect.GetWidth(), @@ -51,13 +53,21 @@ public: void GrabFocus() { m_pDrawingArea->grab_focus(); } bool HasFocus() const { return m_pDrawingArea->has_focus(); } bool IsVisible() const { return m_pDrawingArea->get_visible(); } + bool IsReallyVisible() const { return m_pDrawingArea->is_visible(); } bool IsEnabled() const { return m_pDrawingArea->get_sensitive(); } + int GetTextHeight() const { return m_pDrawingArea->get_text_height(); } + OUString GetAccessibleName() const { return m_pDrawingArea->get_accessible_name(); } void grab_add() { m_pDrawingArea->grab_add(); } void grab_remove() { m_pDrawingArea->grab_remove(); } void set_size_request(int nWidth, int nHeight) { m_pDrawingArea->set_size_request(nWidth, nHeight); } + void queue_resize() { m_pDrawingArea->queue_resize(); } + CustomWidgetController() + : m_pDrawingArea(nullptr) + { + } virtual ~CustomWidgetController(); }; @@ -77,6 +87,7 @@ private: DECL_LINK(DoKeyPress, const KeyEvent&, bool); DECL_LINK(DoFocusRect, weld::Widget&, tools::Rectangle); DECL_LINK(DoStyleUpdated, weld::Widget&, void); + DECL_LINK(DoRequestHelp, tools::Rectangle&, OUString); public: CustomWeld(weld::Builder& rBuilder, const OString& rDrawingId, diff --git a/include/vcl/layout.hxx b/include/vcl/layout.hxx index 6423d12488b9..d2fefe01f875 100644 --- a/include/vcl/layout.hxx +++ b/include/vcl/layout.hxx @@ -14,6 +14,7 @@ #include <vcl/button.hxx> #include <vcl/dialog.hxx> #include <vcl/fixed.hxx> +#include <vcl/help.hxx> #include <vcl/scrbar.hxx> #include <vcl/split.hxx> #include <vcl/svapp.hxx> @@ -627,6 +628,7 @@ private: Link<const KeyEvent&, bool> m_aKeyPressHdl; Link<const KeyEvent&, bool> m_aKeyReleaseHdl; Link<VclDrawingArea&, void> m_aStyleUpdatedHdl; + Link<tools::Rectangle&, OUString> m_aQueryTooltipHdl; virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override { @@ -677,6 +679,24 @@ private: Invalidate(); } } + virtual void RequestHelp(const HelpEvent& rHelpEvent) override + { + if (rHelpEvent.GetMode() & (HelpEventMode::QUICK | HelpEventMode::BALLOON)) + { + Point aPos(rHelpEvent.GetMousePosPixel()); + tools::Rectangle aHelpArea(aPos.X(), aPos.Y()); + OUString sHelpTip = m_aQueryTooltipHdl.Call(aHelpArea); + if (sHelpTip.isEmpty()) + return; + Point aPt = OutputToScreenPixel(aHelpArea.TopLeft()); + aHelpArea.SetLeft(aPt.X()); + aHelpArea.SetTop(aPt.Y()); + aPt = OutputToScreenPixel(aHelpArea.BottomRight()); + aHelpArea.SetRight(aPt.X()); + aHelpArea.SetBottom(aPt.Y()); + Help::ShowQuickHelp(this, aHelpArea, sHelpTip); + } + } virtual FactoryFunction GetUITestFactory() const override { if (m_pFactoryFunction) @@ -732,6 +752,10 @@ public: { m_aStyleUpdatedHdl = rLink; } + void SetQueryTooltipHdl(const Link<tools::Rectangle&, OUString>& rLink) + { + m_aQueryTooltipHdl = rLink; + } }; //Get first window of a pTopLevel window as diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index ace717371fdd..963a7e509ebf 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -79,6 +79,8 @@ public: virtual void set_accessible_name(const OUString& rName) = 0; virtual OUString get_accessible_name() const = 0; + virtual void set_tooltip_text(const OUString& rTip) = 0; + virtual void connect_focus_in(const Link<Widget&, void>& rLink) { assert(!m_aFocusInHdl.IsSet()); @@ -94,6 +96,9 @@ public: virtual void grab_add() = 0; virtual void grab_remove() = 0; + //true for rtl, false otherwise + virtual bool get_direction() const = 0; + virtual Container* weld_parent() const = 0; virtual ~Widget() {} @@ -790,6 +795,12 @@ protected: Link<const KeyEvent&, bool> m_aKeyReleaseHdl; Link<Widget&, void> m_aStyleUpdatedHdl; Link<Widget&, tools::Rectangle> m_aGetFocusRectHdl; + Link<tools::Rectangle&, OUString> m_aQueryTooltipHdl; + + OUString signal_query_tooltip(tools::Rectangle& rHelpArea) + { + return m_aQueryTooltipHdl.Call(rHelpArea); + } public: void connect_draw(const Link<draw_args, void>& rLink) { m_aDrawHdl = rLink; } @@ -813,8 +824,13 @@ public: { m_aGetFocusRectHdl = rLink; } + void connect_query_tooltip(const Link<tools::Rectangle&, OUString>& rLink) + { + m_aQueryTooltipHdl = rLink; + } virtual void queue_draw() = 0; virtual void queue_draw_area(int x, int y, int width, int height) = 0; + virtual void queue_resize() = 0; virtual a11yref get_accessible_parent() = 0; virtual a11yrelationset get_accessible_relation_set() = 0; }; diff --git a/sc/inc/scabstdlg.hxx b/sc/inc/scabstdlg.hxx index 7d76402c9411..707e2cda6569 100644 --- a/sc/inc/scabstdlg.hxx +++ b/sc/inc/scabstdlg.hxx @@ -507,10 +507,10 @@ public: const OString& rHelpId, const OString& rEditHelpId) = 0; - virtual VclPtr<AbstractScTabBgColorDlg> CreateScTabBgColorDlg ( vcl::Window* pParent, - const OUString& rTitle, //Dialog Title - const OUString& rTabBgColorNoColorText, //Label for no tab color - const Color& rDefaultColor ) = 0; //Currently selected Color + virtual VclPtr<AbstractScTabBgColorDlg> CreateScTabBgColorDlg(weld::Window* pParent, + const OUString& rTitle, //Dialog Title + const OUString& rTabBgColorNoColorText, //Label for no tab color + const Color& rDefaultColor) = 0; //Currently selected Color virtual VclPtr<AbstractScImportOptionsDlg> CreateScImportOptionsDlg ( bool bAscii, const ScImportOptions* pOptions, diff --git a/sc/qa/unit/screenshots/screenshots.cxx b/sc/qa/unit/screenshots/screenshots.cxx index 9eb753dd61fd..8b16314fd87d 100644 --- a/sc/qa/unit/screenshots/screenshots.cxx +++ b/sc/qa/unit/screenshots/screenshots.cxx @@ -217,7 +217,7 @@ VclPtr<VclAbstractDialog> ScScreenshotTest::createDialogByID(sal_uInt32 nID) case 9: // "modules/scalc/ui/tabcolordialog.ui" { - pReturnDialog = mpFact->CreateScTabBgColorDlg(mpViewShell->GetDialogParent(), + pReturnDialog = mpFact->CreateScTabBgColorDlg(mpViewShell->GetFrameWeld(), ScResId(SCSTR_SET_TAB_BG_COLOR), ScResId(SCSTR_NO_TAB_BG_COLOR), Color(0xff00ff) ); break; diff --git a/sc/source/ui/attrdlg/scdlgfact.cxx b/sc/source/ui/attrdlg/scdlgfact.cxx index b4ca85ca8711..4134e6f2a0a4 100644 --- a/sc/source/ui/attrdlg/scdlgfact.cxx +++ b/sc/source/ui/attrdlg/scdlgfact.cxx @@ -187,7 +187,11 @@ short AbstractScSortWarningDlg_Impl::Execute() return m_xDlg->run(); } -IMPL_ABSTDLG_BASE(AbstractScTabBgColorDlg_Impl); +short AbstractScTabBgColorDlg_Impl::Execute() +{ + return m_xDlg->run(); +} + IMPL_ABSTDLG_BASE(AbstractScImportOptionsDlg_Impl); IMPL_ABSTDLG_BASE(AbstractScTextImportOptionsDlg_Impl); IMPL_ABSTDLG_BASE(ScAbstractTabDialog_Impl); @@ -660,7 +664,7 @@ OUString AbstractScStringInputDlg_Impl::GetInputString() const void AbstractScTabBgColorDlg_Impl::GetSelectedColor( Color& rColor ) const { - pDlg->GetSelectedColor( rColor ); + m_xDlg->GetSelectedColor( rColor ); } void AbstractScImportOptionsDlg_Impl::GetImportOptions( ScImportOptions& rOptions ) const @@ -932,13 +936,12 @@ VclPtr<AbstractScStringInputDlg> ScAbstractDialogFactory_Impl::CreateScStringInp } VclPtr<AbstractScTabBgColorDlg> ScAbstractDialogFactory_Impl::CreateScTabBgColorDlg( - vcl::Window* pParent, + weld::Window* pParent, const OUString& rTitle, const OUString& rTabBgColorNoColorText, const Color& rDefaultColor) { - VclPtr<ScTabBgColorDlg> pDlg = VclPtr<ScTabBgColorDlg>::Create( pParent, rTitle, rTabBgColorNoColorText, rDefaultColor ); - return VclPtr<AbstractScTabBgColorDlg_Impl>::Create( pDlg ); + return VclPtr<AbstractScTabBgColorDlg_Impl>::Create(new ScTabBgColorDlg(pParent, rTitle, rTabBgColorNoColorText, rDefaultColor)); } VclPtr<AbstractScImportOptionsDlg> ScAbstractDialogFactory_Impl::CreateScImportOptionsDlg ( diff --git a/sc/source/ui/attrdlg/scdlgfact.hxx b/sc/source/ui/attrdlg/scdlgfact.hxx index d4197582ac8e..cd63bb3a7418 100644 --- a/sc/source/ui/attrdlg/scdlgfact.hxx +++ b/sc/source/ui/attrdlg/scdlgfact.hxx @@ -478,7 +478,14 @@ public: class AbstractScTabBgColorDlg_Impl : public AbstractScTabBgColorDlg { - DECL_ABSTDLG_BASE( AbstractScTabBgColorDlg_Impl, ScTabBgColorDlg ) +protected: + std::unique_ptr<ScTabBgColorDlg> m_xDlg; +public: + explicit AbstractScTabBgColorDlg_Impl(ScTabBgColorDlg* p) + : m_xDlg(p) + { + } + virtual short Execute() override; virtual void GetSelectedColor( Color& rColor ) const override; }; @@ -643,10 +650,10 @@ public: const OString& rHelpId, const OString& rEditHelpId) override; - virtual VclPtr<AbstractScTabBgColorDlg> CreateScTabBgColorDlg ( vcl::Window* pParent, - const OUString& rTitle, //Dialog Title - const OUString& rTabBgColorNoColorText, //Label for no tab color - const Color& rDefaultColor ) override; //Currently selected Color + virtual VclPtr<AbstractScTabBgColorDlg> CreateScTabBgColorDlg(weld::Window* pParent, + const OUString& rTitle, //Dialog Title + const OUString& rTabBgColorNoColorText, //Label for no tab color + const Color& rDefaultColor) override; //Currently selected Color virtual VclPtr<AbstractScImportOptionsDlg> CreateScImportOptionsDlg ( bool bAscii, const ScImportOptions* pOptions, diff --git a/sc/source/ui/inc/tabbgcolordlg.hxx b/sc/source/ui/inc/tabbgcolordlg.hxx index e0a5166632ed..16327bf4c0b3 100644 --- a/sc/source/ui/inc/tabbgcolordlg.hxx +++ b/sc/source/ui/inc/tabbgcolordlg.hxx @@ -25,45 +25,44 @@ #include <vcl/button.hxx> #include <svx/SvxColorValueSet.hxx> -class ScTabBgColorDlg : public ModalDialog +class ScTabBgColorDlg : public weld::GenericDialogController { public: - ScTabBgColorDlg( vcl::Window* pParent, - const OUString& rTitle, - const OUString& rTabBgColorNoColorText, - const Color& rDefaultColor ); + ScTabBgColorDlg(weld::Window* pParent, + const OUString& rTitle, + const OUString& rTabBgColorNoColorText, + const Color& rDefaultColor); virtual ~ScTabBgColorDlg() override; - virtual void dispose() override; void GetSelectedColor( Color& rColor ) const; - class ScTabBgColorValueSet : public SvxColorValueSet + class ScTabBgColorValueSet : public ColorValueSet { public: - ScTabBgColorValueSet(vcl::Window* pParent, WinBits nStyle); + ScTabBgColorValueSet(); virtual ~ScTabBgColorValueSet() override; - virtual void dispose() override; void SetDialog(ScTabBgColorDlg* pTabBgColorDlg) { m_pTabBgColorDlg = pTabBgColorDlg; } - virtual void KeyInput( const KeyEvent& rKEvt ) override; + virtual bool KeyInput( const KeyEvent& rKEvt ) override; private: - VclPtr<ScTabBgColorDlg> m_pTabBgColorDlg; + ScTabBgColorDlg* m_pTabBgColorDlg; }; private: - VclPtr<ScTabBgColorValueSet> m_pTabBgColorSet; - VclPtr<OKButton> m_pBtnOk; Color m_aTabBgColor; const OUString m_aTabBgColorNoColorText; + ScTabBgColorValueSet m_aTabBgColorSet; + std::unique_ptr<weld::CustomWeld> m_xTabBgColorSet; + std::unique_ptr<weld::Button> m_xBtnOk; void FillColorValueSets_Impl(); - DECL_LINK(TabBgColorDblClickHdl_Impl, ValueSet*, void); - DECL_LINK(TabBgColorOKHdl_Impl, Button*, void); + DECL_LINK(TabBgColorDblClickHdl_Impl, SvtValueSet*, void); + DECL_LINK(TabBgColorOKHdl_Impl, weld::Button&, void); }; #endif // INCLUDED_SC_SOURCE_UI_INC_TABBGCOLORDLG_HXX diff --git a/sc/source/ui/miscdlgs/tabbgcolordlg.cxx b/sc/source/ui/miscdlgs/tabbgcolordlg.cxx index d9b98985641e..b413da07bf16 100644 --- a/sc/source/ui/miscdlgs/tabbgcolordlg.cxx +++ b/sc/source/ui/miscdlgs/tabbgcolordlg.cxx @@ -31,36 +31,26 @@ #define HDL(hdl) LINK(this,ScTabBgColorDlg,hdl) -ScTabBgColorDlg::ScTabBgColorDlg(vcl::Window* pParent, const OUString& rTitle, +ScTabBgColorDlg::ScTabBgColorDlg(weld::Window* pParent, const OUString& rTitle, const OUString& rTabBgColorNoColorText, const Color& rDefaultColor) - : ModalDialog(pParent, "TabColorDialog", "modules/scalc/ui/tabcolordialog.ui") + : GenericDialogController(pParent, "modules/scalc/ui/tabcolordialog.ui", "TabColorDialog") , m_aTabBgColor(rDefaultColor) , m_aTabBgColorNoColorText(rTabBgColorNoColorText) - + , m_xTabBgColorSet(new weld::CustomWeld(*m_xBuilder, "colorset", m_aTabBgColorSet)) + , m_xBtnOk(m_xBuilder->weld_button("ok")) { - get(m_pTabBgColorSet, "colorset"); - m_pTabBgColorSet->SetDialog(this); - m_pTabBgColorSet->SetColCount(SvxColorValueSet::getColumnCount()); - get(m_pBtnOk, "ok"); + m_aTabBgColorSet.SetDialog(this); + m_aTabBgColorSet.SetColCount(SvxColorValueSet::getColumnCount()); - SetText( rTitle ); - SetStyle(GetStyle() | WB_BORDER | WB_STDFLOATWIN | WB_3DLOOK | WB_DIALOGCONTROL | WB_SYSTEMWINDOW | WB_STANDALONE | WB_HIDE); + m_xDialog->set_title(rTitle); FillColorValueSets_Impl(); - m_pTabBgColorSet->SetDoubleClickHdl( HDL(TabBgColorDblClickHdl_Impl) ); - m_pBtnOk->SetClickHdl( HDL(TabBgColorOKHdl_Impl) ); + m_aTabBgColorSet.SetDoubleClickHdl(HDL(TabBgColorDblClickHdl_Impl)); + m_xBtnOk->connect_clicked(HDL(TabBgColorOKHdl_Impl)); } ScTabBgColorDlg::~ScTabBgColorDlg() { - disposeOnce(); -} - -void ScTabBgColorDlg::dispose() -{ - m_pTabBgColorSet.clear(); - m_pBtnOk.clear(); - ModalDialog::dispose(); } void ScTabBgColorDlg::GetSelectedColor( Color& rColor ) const @@ -86,74 +76,53 @@ void ScTabBgColorDlg::FillColorValueSets_Impl() if ( pColorList.is() ) { nColorCount = pColorList->Count(); - m_pTabBgColorSet->addEntriesForXColorList(*pColorList); + m_aTabBgColorSet.addEntriesForXColorList(*pColorList); } if (nColorCount) { - const WinBits nBits(m_pTabBgColorSet->GetStyle() | WB_NAMEFIELD | WB_ITEMBORDER | WB_NONEFIELD | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_NOPOINTERFOCUS); - m_pTabBgColorSet->SetText( m_aTabBgColorNoColorText ); - m_pTabBgColorSet->SetStyle( nBits ); + const WinBits nBits(m_aTabBgColorSet.GetStyle() | WB_NAMEFIELD | WB_ITEMBORDER | WB_NONEFIELD | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_NOPOINTERFOCUS); + m_aTabBgColorSet.SetText(m_aTabBgColorNoColorText); + m_aTabBgColorSet.SetStyle(nBits); } //lock down a preferred size const sal_uInt32 nColCount = SvxColorValueSet::getColumnCount(); const sal_uInt32 nRowCount(ceil(double(nColorCount)/nColCount)); const sal_uInt32 nLength = SvxColorValueSet::getEntryEdgeLength(); - Size aSize(m_pTabBgColorSet->CalcWindowSizePixel(Size(nLength, nLength), nColCount, nRowCount)); - m_pTabBgColorSet->set_width_request(aSize.Width()+8); - m_pTabBgColorSet->set_height_request(aSize.Height()+8); - - m_pTabBgColorSet->SelectItem(0); + Size aSize(m_aTabBgColorSet.CalcWindowSizePixel(Size(nLength, nLength), nColCount, nRowCount)); + m_xTabBgColorSet->set_size_request(aSize.Width() + 8, aSize.Height() + 8); + m_aTabBgColorSet.SelectItem(0); } /// Handler, called when color selection is changed -IMPL_LINK_NOARG(ScTabBgColorDlg, TabBgColorDblClickHdl_Impl, ValueSet*, void) +IMPL_LINK_NOARG(ScTabBgColorDlg, TabBgColorDblClickHdl_Impl, SvtValueSet*, void) { - sal_uInt16 nItemId = m_pTabBgColorSet->GetSelectedItemId(); - Color aColor = nItemId ? ( m_pTabBgColorSet->GetItemColor( nItemId ) ) : COL_AUTO; + sal_uInt16 nItemId = m_aTabBgColorSet.GetSelectedItemId(); + Color aColor = nItemId ? ( m_aTabBgColorSet.GetItemColor( nItemId ) ) : COL_AUTO; m_aTabBgColor = aColor; - EndDialog( RET_OK ); + m_xDialog->response(RET_OK); } // Handler, called when the OK button is pushed -IMPL_LINK_NOARG(ScTabBgColorDlg, TabBgColorOKHdl_Impl, Button*, void) +IMPL_LINK_NOARG(ScTabBgColorDlg, TabBgColorOKHdl_Impl, weld::Button&, void) { - sal_uInt16 nItemId = m_pTabBgColorSet->GetSelectedItemId(); - Color aColor = nItemId ? ( m_pTabBgColorSet->GetItemColor( nItemId ) ) : COL_AUTO; + sal_uInt16 nItemId = m_aTabBgColorSet.GetSelectedItemId(); + Color aColor = nItemId ? ( m_aTabBgColorSet.GetItemColor( nItemId ) ) : COL_AUTO; m_aTabBgColor = aColor; - EndDialog( RET_OK ); + m_xDialog->response(RET_OK); } -ScTabBgColorDlg::ScTabBgColorValueSet::ScTabBgColorValueSet(vcl::Window* pParent, WinBits nStyle) - : SvxColorValueSet(pParent, nStyle) - , m_pTabBgColorDlg(nullptr) +ScTabBgColorDlg::ScTabBgColorValueSet::ScTabBgColorValueSet() + : m_pTabBgColorDlg(nullptr) { } ScTabBgColorDlg::ScTabBgColorValueSet::~ScTabBgColorValueSet() { - disposeOnce(); -} - -void ScTabBgColorDlg::ScTabBgColorValueSet::dispose() -{ - m_pTabBgColorDlg.clear(); - SvxColorValueSet::dispose(); -} - -extern "C" SAL_DLLPUBLIC_EXPORT void makeScTabBgColorValueSet(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap & rMap) -{ - WinBits nWinBits = WB_TABSTOP; - - OUString sBorder = BuilderUtils::extractCustomProperty(rMap); - if (!sBorder.isEmpty()) - nWinBits |= WB_BORDER; - - rRet = VclPtr<ScTabBgColorDlg::ScTabBgColorValueSet>::Create(pParent, nWinBits); } -void ScTabBgColorDlg::ScTabBgColorValueSet::KeyInput( const KeyEvent& rKEvt ) +bool ScTabBgColorDlg::ScTabBgColorValueSet::KeyInput( const KeyEvent& rKEvt ) { switch ( rKEvt.GetKeyCode().GetCode() ) { @@ -163,11 +132,12 @@ void ScTabBgColorDlg::ScTabBgColorValueSet::KeyInput( const KeyEvent& rKEvt ) sal_uInt16 nItemId = GetSelectedItemId(); const Color& aColor = nItemId ? ( GetItemColor( nItemId ) ) : COL_AUTO; m_pTabBgColorDlg->m_aTabBgColor = aColor; - m_pTabBgColorDlg->EndDialog(RET_OK); + m_pTabBgColorDlg->response(RET_OK); + return true; } break; } - SvxColorValueSet::KeyInput(rKEvt); + return ColorValueSet::KeyInput(rKEvt); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/tabvwshf.cxx b/sc/source/ui/view/tabvwshf.cxx index 20ee198565fe..83056b0ea4b6 100644 --- a/sc/source/ui/view/tabvwshf.cxx +++ b/sc/source/ui/view/tabvwshf.cxx @@ -787,7 +787,7 @@ void ScTabViewShell::ExecuteTable( SfxRequest& rReq ) ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); OSL_ENSURE(pFact, "ScAbstractFactory create fail!"); ScopedVclPtr<AbstractScTabBgColorDlg> pDlg(pFact->CreateScTabBgColorDlg( - GetDialogParent(), + GetFrameWeld(), ScResId(SCSTR_SET_TAB_BG_COLOR), ScResId(SCSTR_NO_TAB_BG_COLOR), aTabBgColor)); diff --git a/sc/uiconfig/scalc/ui/tabcolordialog.ui b/sc/uiconfig/scalc/ui/tabcolordialog.ui index b9b239f8c605..a71c77d4c27f 100644 --- a/sc/uiconfig/scalc/ui/tabcolordialog.ui +++ b/sc/uiconfig/scalc/ui/tabcolordialog.ui @@ -1,29 +1,22 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.1 --> <interface domain="sc"> - <!-- interface-requires LibreOffice 1.0 --> - <!-- interface-requires gtk+ 3.0 --> + <requires lib="gtk+" version="3.18"/> <object class="GtkDialog" id="TabColorDialog"> <property name="can_focus">False</property> <property name="border_width">6</property> + <property name="modal">True</property> + <property name="default_width">0</property> + <property name="default_height">0</property> <property name="type_hint">dialog</property> + <child> + <placeholder/> + </child> <child internal-child="vbox"> <object class="GtkBox" id="dialog-vbox1"> <property name="can_focus">False</property> <property name="orientation">vertical</property> <property name="spacing">12</property> - <child> - <object class="scuilo-ScTabBgColorValueSet" id="colorset:border"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> <child internal-child="action_area"> <object class="GtkButtonBox" id="dialog-action_area1"> <property name="can_focus">False</property> @@ -66,6 +59,36 @@ <property name="position">2</property> </packing> </child> + <child> + <object class="GtkScrolledWindow" id="scroll"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="hscrollbar_policy">never</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkDrawingArea" id="colorset"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> </object> </child> <action-widgets> diff --git a/svtools/source/control/valueacc.cxx b/svtools/source/control/valueacc.cxx index 443dfc875d70..34cf5c41a0aa 100644 --- a/svtools/source/control/valueacc.cxx +++ b/svtools/source/control/valueacc.cxx @@ -61,6 +61,32 @@ uno::Reference< accessibility::XAccessible > const & ValueSetItem::GetAccessible return mxAcc; } +SvtValueSetItem::SvtValueSetItem( SvtValueSet& rParent ) + : mrParent(rParent) + , mnId(0) + , meType(VALUESETITEM_NONE) + , mbVisible(true) + , mpData(nullptr) + , mxAcc() +{ +} + + +SvtValueSetItem::~SvtValueSetItem() +{ + if( mxAcc.is() ) + { + static_cast< ValueItemAcc* >( mxAcc.get() )->ParentDestroyed(); + } +} + +uno::Reference< accessibility::XAccessible > const & SvtValueSetItem::GetAccessible( bool bIsTransientChildrenDisabled ) +{ + if( !mxAcc.is() ) + mxAcc = new SvtValueItemAcc( this, bIsTransientChildrenDisabled ); + + return mxAcc; +} ValueSetAcc::ValueSetAcc( ValueSet* pParent ) : ValueSetAccComponentBase (m_aMutex), @@ -1036,4 +1062,961 @@ sal_Int64 SAL_CALL ValueItemAcc::getSomething( const uno::Sequence< sal_Int8 >& return nRet; } +SvtValueItemAcc::SvtValueItemAcc( SvtValueSetItem* pParent, bool bIsTransientChildrenDisabled ) : + mpParent( pParent ), + mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled ) +{ +} + +SvtValueItemAcc::~SvtValueItemAcc() +{ +} + +void SvtValueItemAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue ) +{ + if( !nEventId ) + return; + + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners ); + accessibility::AccessibleEventObject aEvtObject; + + aEvtObject.EventId = nEventId; + aEvtObject.Source = static_cast<uno::XWeak*>(this); + aEvtObject.NewValue = rNewValue; + aEvtObject.OldValue = rOldValue; + + for (auto const& tmpListener : aTmpListeners) + { + tmpListener->notifyEvent( aEvtObject ); + } +} + + +void SvtValueItemAcc::ParentDestroyed() +{ + const ::osl::MutexGuard aGuard( maMutex ); + mpParent = nullptr; +} + +namespace +{ + class theSvtValueItemAccUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSvtValueItemAccUnoTunnelId > {}; +} + +const uno::Sequence< sal_Int8 >& SvtValueItemAcc::getUnoTunnelId() +{ + return theSvtValueItemAccUnoTunnelId::get().getSeq(); +} + + +SvtValueItemAcc* SvtValueItemAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData ) + throw() +{ + try + { + uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY ); + return( xUnoTunnel.is() ? reinterpret_cast<SvtValueItemAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( SvtValueItemAcc::getUnoTunnelId() ))) : nullptr ); + } + catch(const css::uno::Exception&) + { + return nullptr; + } +} + + +uno::Reference< accessibility::XAccessibleContext > SAL_CALL SvtValueItemAcc::getAccessibleContext() +{ + return this; +} + + +sal_Int32 SAL_CALL SvtValueItemAcc::getAccessibleChildCount() +{ + return 0; +} + + +uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueItemAcc::getAccessibleChild( sal_Int32 ) +{ + throw lang::IndexOutOfBoundsException(); +} + + +uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueItemAcc::getAccessibleParent() +{ + const SolarMutexGuard aSolarGuard; + uno::Reference< accessibility::XAccessible > xRet; + + if( mpParent ) + xRet = mpParent->mrParent.mxAccessible; + + return xRet; +} + + +sal_Int32 SAL_CALL SvtValueItemAcc::getAccessibleIndexInParent() +{ + const SolarMutexGuard aSolarGuard; + // The index defaults to -1 to indicate the child does not belong to its + // parent. + sal_Int32 nIndexInParent = -1; + + if( mpParent ) + { + bool bDone = false; + + sal_uInt16 nCount = mpParent->mrParent.ImplGetVisibleItemCount(); + SvtValueSetItem* pItem; + for (sal_uInt16 i=0; i<nCount && !bDone; i++) + { + // Guard the retrieval of the i-th child with a try/catch block + // just in case the number of children changes in the mean time. + try + { + pItem = mpParent->mrParent.ImplGetItem(i); + } + catch (const lang::IndexOutOfBoundsException&) + { + pItem = nullptr; + } + + // Do not create an accessible object for the test. + if (pItem != nullptr && pItem->mxAcc.is()) + if (pItem->GetAccessible( mbIsTransientChildrenDisabled ).get() == this ) + { + nIndexInParent = i; + bDone = true; + } + } + } + + //if this valueset contain a none field(common value is default), then we should increase the real index and set the noitem index value equal 0. + if ( mpParent && ( (mpParent->mrParent.GetStyle() & WB_NONEFIELD) != 0 ) ) + { + SvtValueSetItem* pFirstItem = mpParent->mrParent.ImplGetItem (VALUESET_ITEM_NONEITEM); + if( pFirstItem && pFirstItem ->GetAccessible(mbIsTransientChildrenDisabled).get() == this ) + nIndexInParent = 0; + else + nIndexInParent++; + } + return nIndexInParent; +} + + +sal_Int16 SAL_CALL SvtValueItemAcc::getAccessibleRole() +{ + return accessibility::AccessibleRole::LIST_ITEM; +} + + +OUString SAL_CALL SvtValueItemAcc::getAccessibleDescription() +{ + return OUString(); +} + + +OUString SAL_CALL SvtValueItemAcc::getAccessibleName() +{ + const SolarMutexGuard aSolarGuard; + + if( mpParent ) + { + if (mpParent->maText.isEmpty()) + return "Item " + OUString::number(static_cast<sal_Int32>(mpParent->mnId)); + else + return mpParent->maText; + } + + return OUString(); +} + + +uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL SvtValueItemAcc::getAccessibleRelationSet() +{ + return uno::Reference< accessibility::XAccessibleRelationSet >(); +} + + +uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL SvtValueItemAcc::getAccessibleStateSet() +{ + const SolarMutexGuard aSolarGuard; + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper; + + if( mpParent ) + { + pStateSet->AddState (accessibility::AccessibleStateType::ENABLED); + pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE); + pStateSet->AddState (accessibility::AccessibleStateType::SHOWING); + pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE); + if ( !mbIsTransientChildrenDisabled ) + pStateSet->AddState (accessibility::AccessibleStateType::TRANSIENT); + + // SELECTABLE + pStateSet->AddState( accessibility::AccessibleStateType::SELECTABLE ); + // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSABLE ); + + // SELECTED + if( mpParent->mrParent.GetSelectedItemId() == mpParent->mnId ) + { + pStateSet->AddState( accessibility::AccessibleStateType::SELECTED ); + // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSED ); + } + } + + return pStateSet; +} + + +lang::Locale SAL_CALL SvtValueItemAcc::getLocale() +{ + const SolarMutexGuard aSolarGuard; + uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() ); + lang::Locale aRet( "", "", "" ); + + if( xParent.is() ) + { + uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + + if( xParentContext.is() ) + aRet = xParentContext->getLocale(); + } + + return aRet; +} + + +void SAL_CALL SvtValueItemAcc::addAccessibleEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener ) +{ + const ::osl::MutexGuard aGuard( maMutex ); + + if( !rxListener.is() ) + return; + + bool bFound = false; + + for (auto const& eventListener : mxEventListeners) + { + if(eventListener == rxListener) + { + bFound = true; + break; + } + } + + if (!bFound) + mxEventListeners.push_back( rxListener ); +} + + +void SAL_CALL SvtValueItemAcc::removeAccessibleEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener ) +{ + const ::osl::MutexGuard aGuard( maMutex ); + + if( rxListener.is() ) + { + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = + std::find(mxEventListeners.begin(), mxEventListeners.end(), rxListener); + + if (aIter != mxEventListeners.end()) + mxEventListeners.erase(aIter); + } +} + + +sal_Bool SAL_CALL SvtValueItemAcc::containsPoint( const awt::Point& aPoint ) +{ + const awt::Rectangle aRect( getBounds() ); + const Point aSize( aRect.Width, aRect.Height ); + const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y ); + + return tools::Rectangle( aNullPoint, aSize ).IsInside( aTestPoint ); +} + +uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueItemAcc::getAccessibleAtPoint( const awt::Point& ) +{ + uno::Reference< accessibility::XAccessible > xRet; + return xRet; +} + +awt::Rectangle SAL_CALL SvtValueItemAcc::getBounds() +{ + const SolarMutexGuard aSolarGuard; + awt::Rectangle aRet; + + if( mpParent ) + { + tools::Rectangle aRect( mpParent->mrParent.GetItemRect(mpParent->mnId) ); + tools::Rectangle aParentRect( Point(), mpParent->mrParent.GetOutputSizePixel() ); + + aRect.Intersection( aParentRect ); + + aRet.X = aRect.Left(); + aRet.Y = aRect.Top(); + aRet.Width = aRect.GetWidth(); + aRet.Height = aRect.GetHeight(); + } + + return aRet; +} + +awt::Point SAL_CALL SvtValueItemAcc::getLocation() +{ + const awt::Rectangle aRect( getBounds() ); + awt::Point aRet; + + aRet.X = aRect.X; + aRet.Y = aRect.Y; + + return aRet; +} + +awt::Point SAL_CALL SvtValueItemAcc::getLocationOnScreen() +{ + const SolarMutexGuard aSolarGuard; + uno::Reference<accessibility::XAccessible> xParent(getAccessibleParent()); + awt::Point aRet; + + if (mpParent && xParent) + { + uno::Reference<accessibility::XAccessibleContext> xParentContext(xParent->getAccessibleContext()); + uno::Reference<accessibility::XAccessibleComponent> xParentComponent(xParentContext, css::uno::UNO_QUERY_THROW); + awt::Point aParentScreenLoc(xParentComponent->getLocationOnScreen()); + const Point aOwnRelativeLoc = mpParent->mrParent.GetItemRect(mpParent->mnId).TopLeft(); + + aRet.X = aParentScreenLoc.X + aOwnRelativeLoc.X(); + aRet.X = aParentScreenLoc.Y + aOwnRelativeLoc.Y(); + } + + return aRet; +} + +awt::Size SAL_CALL SvtValueItemAcc::getSize() +{ + const awt::Rectangle aRect( getBounds() ); + awt::Size aRet; + + aRet.Width = aRect.Width; + aRet.Height = aRect.Height; + + return aRet; +} + +void SAL_CALL SvtValueItemAcc::grabFocus() +{ + // nothing to do +} + +sal_Int32 SAL_CALL SvtValueItemAcc::getForeground( ) +{ + Color nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor(); + return static_cast<sal_Int32>(nColor); +} + +sal_Int32 SAL_CALL SvtValueItemAcc::getBackground( ) +{ + Color nColor; + if (mpParent && mpParent->meType == VALUESETITEM_COLOR) + nColor = mpParent->maColor; + else + nColor = Application::GetSettings().GetStyleSettings().GetWindowColor(); + return static_cast<sal_Int32>(nColor); +} + +sal_Int64 SAL_CALL SvtValueItemAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) +{ + sal_Int64 nRet; + + if( ( rId.getLength() == 16 ) && ( 0 == memcmp( SvtValueItemAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) ) + nRet = reinterpret_cast< sal_Int64 >( this ); + else + nRet = 0; + + return nRet; +} + +SvtValueSetAcc::SvtValueSetAcc( SvtValueSet* pParent ) : + ValueSetAccComponentBase (m_aMutex), + mpParent( pParent ), + mbIsFocused(false) +{ +} + + +SvtValueSetAcc::~SvtValueSetAcc() +{ +} + + +void SvtValueSetAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue ) +{ + if( !nEventId ) + return; + + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners ); + accessibility::AccessibleEventObject aEvtObject; + + aEvtObject.EventId = nEventId; + aEvtObject.Source = static_cast<uno::XWeak*>(this); + aEvtObject.NewValue = rNewValue; + aEvtObject.OldValue = rOldValue; + + for (auto const& tmpListener : aTmpListeners) + { + try + { + tmpListener->notifyEvent( aEvtObject ); + } + catch(const uno::Exception&) + { + } + } +} + +namespace +{ + class theSvtValueSetAccUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSvtValueSetAccUnoTunnelId > {}; +} + +const uno::Sequence< sal_Int8 >& SvtValueSetAcc::getUnoTunnelId() +{ + return theSvtValueSetAccUnoTunnelId::get().getSeq(); +} + + +SvtValueSetAcc* SvtValueSetAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData ) + throw() +{ + try + { + uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY ); + return( xUnoTunnel.is() ? reinterpret_cast<SvtValueSetAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( SvtValueSetAcc::getUnoTunnelId() ))) : nullptr ); + } + catch(const css::uno::Exception&) + { + return nullptr; + } +} + + +void SvtValueSetAcc::GetFocus() +{ + mbIsFocused = true; + + // Broadcast the state change. + css::uno::Any aOldState, aNewState; + aNewState <<= css::accessibility::AccessibleStateType::FOCUSED; + FireAccessibleEvent( + css::accessibility::AccessibleEventId::STATE_CHANGED, + aOldState, aNewState); +} + + +void SvtValueSetAcc::LoseFocus() +{ + mbIsFocused = false; + + // Broadcast the state change. + css::uno::Any aOldState, aNewState; + aOldState <<= css::accessibility::AccessibleStateType::FOCUSED; + FireAccessibleEvent( + css::accessibility::AccessibleEventId::STATE_CHANGED, + aOldState, aNewState); +} + + +uno::Reference< accessibility::XAccessibleContext > SAL_CALL SvtValueSetAcc::getAccessibleContext() +{ + ThrowIfDisposed(); + return this; +} + + +sal_Int32 SAL_CALL SvtValueSetAcc::getAccessibleChildCount() +{ + const SolarMutexGuard aSolarGuard; + ThrowIfDisposed(); + + sal_Int32 nCount = mpParent->ImplGetVisibleItemCount(); + if (HasNoneField()) + nCount += 1; + return nCount; +} + + +uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueSetAcc::getAccessibleChild( sal_Int32 i ) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + SvtValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(i)); + + if( !pItem ) + throw lang::IndexOutOfBoundsException(); + + uno::Reference< accessibility::XAccessible > xRet = pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ ); + return xRet; +} + +uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueSetAcc::getAccessibleParent() +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + return mpParent->GetDrawingArea()->get_accessible_parent(); +} + +sal_Int32 SAL_CALL SvtValueSetAcc::getAccessibleIndexInParent() +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + + // -1 for child not found/no parent (according to specification) + sal_Int32 nRet = -1; + + uno::Reference<accessibility::XAccessible> xParent(getAccessibleParent()); + if (!xParent) + return nRet; + + try + { + uno::Reference<accessibility::XAccessibleContext> xParentContext(xParent->getAccessibleContext()); + + // iterate over parent's children and search for this object + if ( xParentContext.is() ) + { + sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); + for ( sal_Int32 nChild = 0; ( nChild < nChildCount ) && ( -1 == nRet ); ++nChild ) + { + uno::Reference<XAccessible> xChild(xParentContext->getAccessibleChild(nChild)); + if ( xChild.get() == this ) + nRet = nChild; + } + } + } + catch (const uno::Exception&) + { + OSL_FAIL( "OAccessibleContextHelper::getAccessibleIndexInParent: caught an exception!" ); + } + + return nRet; +} + +sal_Int16 SAL_CALL SvtValueSetAcc::getAccessibleRole() +{ + ThrowIfDisposed(); + return accessibility::AccessibleRole::LIST; +} + + +OUString SAL_CALL SvtValueSetAcc::getAccessibleDescription() +{ + ThrowIfDisposed(); + return OUString( "ValueSet" ); +} + + +OUString SAL_CALL SvtValueSetAcc::getAccessibleName() +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + OUString aRet; + + if (mpParent) + { + aRet = mpParent->GetAccessibleName(); + } + + return aRet; +} + +uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL SvtValueSetAcc::getAccessibleRelationSet() +{ + ThrowIfDisposed(); + SolarMutexGuard g; + return mpParent->GetDrawingArea()->get_accessible_relation_set(); +} + +uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL SvtValueSetAcc::getAccessibleStateSet() +{ + ThrowIfDisposed(); + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper(); + + // Set some states. + pStateSet->AddState (accessibility::AccessibleStateType::ENABLED); + pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE); + pStateSet->AddState (accessibility::AccessibleStateType::SHOWING); + pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE); + pStateSet->AddState (accessibility::AccessibleStateType::MANAGES_DESCENDANTS); + pStateSet->AddState (accessibility::AccessibleStateType::FOCUSABLE); + if (mbIsFocused) + pStateSet->AddState (accessibility::AccessibleStateType::FOCUSED); + + return pStateSet; +} + + +lang::Locale SAL_CALL SvtValueSetAcc::getLocale() +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() ); + lang::Locale aRet( "", "", "" ); + + if( xParent.is() ) + { + uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + + if( xParentContext.is() ) + aRet = xParentContext->getLocale (); + } + + return aRet; +} + + +void SAL_CALL SvtValueSetAcc::addAccessibleEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener ) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (m_aMutex); + + if( !rxListener.is() ) + return; + + bool bFound = false; + + for (auto const& eventListener : mxEventListeners) + { + if(eventListener == rxListener) + { + bFound = true; + break; + } + } + + if (!bFound) + mxEventListeners.push_back( rxListener ); +} + + +void SAL_CALL SvtValueSetAcc::removeAccessibleEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener ) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (m_aMutex); + + if( rxListener.is() ) + { + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = + std::find(mxEventListeners.begin(), mxEventListeners.end(), rxListener); + + if (aIter != mxEventListeners.end()) + mxEventListeners.erase(aIter); + } +} + + +sal_Bool SAL_CALL SvtValueSetAcc::containsPoint( const awt::Point& aPoint ) +{ + ThrowIfDisposed(); + const awt::Rectangle aRect( getBounds() ); + const Point aSize( aRect.Width, aRect.Height ); + const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y ); + + return tools::Rectangle( aNullPoint, aSize ).IsInside( aTestPoint ); +} + + +uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueSetAcc::getAccessibleAtPoint( const awt::Point& aPoint ) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + const sal_uInt16 nItemId = mpParent->GetItemId( Point( aPoint.X, aPoint.Y ) ); + uno::Reference< accessibility::XAccessible > xRet; + + if ( nItemId ) + { + const size_t nItemPos = mpParent->GetItemPos( nItemId ); + + if( VALUESET_ITEM_NONEITEM != nItemPos ) + { + SvtValueSetItem *const pItem = mpParent->mItemList[nItemPos]; + xRet = pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ ); + } + } + + return xRet; +} + + +awt::Rectangle SAL_CALL SvtValueSetAcc::getBounds() +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + const Point aOutPos; + const Size aOutSize( mpParent->GetOutputSizePixel() ); + awt::Rectangle aRet; + + aRet.X = aOutPos.X(); + aRet.Y = aOutPos.Y(); + aRet.Width = aOutSize.Width(); + aRet.Height = aOutSize.Height(); + + return aRet; +} + + +awt::Point SAL_CALL SvtValueSetAcc::getLocation() +{ + ThrowIfDisposed(); + const awt::Rectangle aRect( getBounds() ); + awt::Point aRet; + + aRet.X = aRect.X; + aRet.Y = aRect.Y; + + return aRet; +} + + +awt::Point SAL_CALL SvtValueSetAcc::getLocationOnScreen() +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + awt::Point aScreenLoc(0, 0); + + uno::Reference<accessibility::XAccessible> xParent(getAccessibleParent()); + if (xParent) + { + uno::Reference<accessibility::XAccessibleContext> xParentContext(xParent->getAccessibleContext()); + uno::Reference<accessibility::XAccessibleComponent> xParentComponent(xParentContext, css::uno::UNO_QUERY); + OSL_ENSURE( xParentComponent.is(), "SvtValueSetAcc::getLocationOnScreen: no parent component!" ); + if ( xParentComponent.is() ) + { + awt::Point aParentScreenLoc( xParentComponent->getLocationOnScreen() ); + awt::Point aOwnRelativeLoc( getLocation() ); + aScreenLoc.X = aParentScreenLoc.X + aOwnRelativeLoc.X; + aScreenLoc.Y = aParentScreenLoc.Y + aOwnRelativeLoc.Y; + } + } + + return aScreenLoc; +} + + +awt::Size SAL_CALL SvtValueSetAcc::getSize() +{ + ThrowIfDisposed(); + const awt::Rectangle aRect( getBounds() ); + awt::Size aRet; + + aRet.Width = aRect.Width; + aRet.Height = aRect.Height; + + return aRet; +} + +void SAL_CALL SvtValueSetAcc::grabFocus() +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + mpParent->GrabFocus(); +} + +sal_Int32 SAL_CALL SvtValueSetAcc::getForeground( ) +{ + ThrowIfDisposed(); + Color nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor(); + return static_cast<sal_Int32>(nColor); +} + +sal_Int32 SAL_CALL SvtValueSetAcc::getBackground( ) +{ + ThrowIfDisposed(); + Color nColor = Application::GetSettings().GetStyleSettings().GetWindowColor(); + return static_cast<sal_Int32>(nColor); +} + +void SAL_CALL SvtValueSetAcc::selectAccessibleChild( sal_Int32 nChildIndex ) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + SvtValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex)); + + if(pItem == nullptr) + throw lang::IndexOutOfBoundsException(); + + mpParent->SelectItem( pItem->mnId ); + mpParent->Select (); +} + + +sal_Bool SAL_CALL SvtValueSetAcc::isAccessibleChildSelected( sal_Int32 nChildIndex ) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + SvtValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex)); + + if (pItem == nullptr) + throw lang::IndexOutOfBoundsException(); + + bool bRet = mpParent->IsItemSelected( pItem->mnId ); + return bRet; +} + + +void SAL_CALL SvtValueSetAcc::clearAccessibleSelection() +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + mpParent->SetNoSelection(); +} + + +void SAL_CALL SvtValueSetAcc::selectAllAccessibleChildren() +{ + ThrowIfDisposed(); + // unsupported due to single selection only +} + + +sal_Int32 SAL_CALL SvtValueSetAcc::getSelectedAccessibleChildCount() +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + sal_Int32 nRet = 0; + + for( sal_uInt16 i = 0, nCount = getItemCount(); i < nCount; i++ ) + { + SvtValueSetItem* pItem = getItem (i); + + if( pItem && mpParent->IsItemSelected( pItem->mnId ) ) + ++nRet; + } + + return nRet; +} + + +uno::Reference< accessibility::XAccessible > SAL_CALL SvtValueSetAcc::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + uno::Reference< accessibility::XAccessible > xRet; + + for( sal_uInt16 i = 0, nCount = getItemCount(), nSel = 0; ( i < nCount ) && !xRet.is(); i++ ) + { + SvtValueSetItem* pItem = getItem(i); + + if( pItem && mpParent->IsItemSelected( pItem->mnId ) && ( nSelectedChildIndex == static_cast< sal_Int32 >( nSel++ ) ) ) + xRet = pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ ); + } + + return xRet; +} + + +void SAL_CALL SvtValueSetAcc::deselectAccessibleChild( sal_Int32 nChildIndex ) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + // Because of the single selection we can reset the whole selection when + // the specified child is currently selected. + if (isAccessibleChildSelected(nChildIndex)) + mpParent->SetNoSelection(); +} + + +sal_Int64 SAL_CALL SvtValueSetAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) +{ + sal_Int64 nRet; + + if( ( rId.getLength() == 16 ) && ( 0 == memcmp( SvtValueSetAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) ) + nRet = reinterpret_cast< sal_Int64 >( this ); + else + nRet = 0; + + return nRet; +} + + +void SAL_CALL SvtValueSetAcc::disposing() +{ + ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> > aListenerListCopy; + + { + // Make a copy of the list and clear the original. + const SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard (m_aMutex); + aListenerListCopy = mxEventListeners; + mxEventListeners.clear(); + + // Reset the pointer to the parent. It has to be the one who has + // disposed us because he is dying. + mpParent = nullptr; + } + + // Inform all listeners that this objects is disposing. + lang::EventObject aEvent (static_cast<accessibility::XAccessible*>(this)); + for (auto const& listenerCopy : aListenerListCopy) + { + try + { + listenerCopy->disposing (aEvent); + } + catch(const uno::Exception&) + { + // Ignore exceptions. + } + } +} + + +sal_uInt16 SvtValueSetAcc::getItemCount() const +{ + sal_uInt16 nCount = mpParent->ImplGetVisibleItemCount(); + // When the None-Item is visible then increase the number of items by + // one. + if (HasNoneField()) + nCount += 1; + return nCount; +} + +SvtValueSetItem* SvtValueSetAcc::getItem (sal_uInt16 nIndex) const +{ + SvtValueSetItem* pItem = nullptr; + + if (HasNoneField()) + { + if (nIndex == 0) + // When present the first item is the then always visible none field. + pItem = mpParent->ImplGetItem (VALUESET_ITEM_NONEITEM); + else + // Shift down the index to compensate for the none field. + nIndex -= 1; + } + if (pItem == nullptr) + pItem = mpParent->ImplGetItem (nIndex); + + return pItem; +} + + +void SvtValueSetAcc::ThrowIfDisposed() +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + SAL_WARN("svx", "Calling disposed object. Throwing exception:"); + throw lang::DisposedException ( + "object has been already disposed", + static_cast<uno::XWeak*>(this)); + } + else + { + DBG_ASSERT (mpParent!=nullptr, "SvtValueSetAcc not disposed but mpParent == NULL"); + } +} + +bool SvtValueSetAcc::HasNoneField() const +{ + assert(mpParent && "SvtValueSetAcc::HasNoneField called with mpParent==NULL"); + return ((mpParent->GetStyle() & WB_NONEFIELD) != 0); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/control/valueimp.hxx b/svtools/source/control/valueimp.hxx index b791b4243672..66c59fa6f24b 100644 --- a/svtools/source/control/valueimp.hxx +++ b/svtools/source/control/valueimp.hxx @@ -48,6 +48,7 @@ enum ValueSetItemType }; class ValueSet; +class SvtValueSet; struct ValueSetItem { @@ -68,6 +69,25 @@ struct ValueSetItem GetAccessible( bool bIsTransientChildrenDisabled ); }; +struct SvtValueSetItem +{ + SvtValueSet& mrParent; + sal_uInt16 mnId; + sal_uInt8 meType; + bool mbVisible; + Image maImage; + Color maColor; + OUString maText; + void* mpData; + css::uno::Reference< css::accessibility::XAccessible > mxAcc; + + explicit SvtValueSetItem( SvtValueSet& rParent ); + ~SvtValueSetItem(); + + css::uno::Reference< css::accessibility::XAccessible > const & + GetAccessible( bool bIsTransientChildrenDisabled ); +}; + typedef ::cppu::WeakComponentImplHelper< css::accessibility::XAccessible, css::accessibility::XAccessibleEventBroadcaster, @@ -191,6 +211,121 @@ private: bool HasNoneField() const; }; +class SvtValueSetAcc : + public ::cppu::BaseMutex, + public ValueSetAccComponentBase +{ +public: + + explicit SvtValueSetAcc(SvtValueSet* pParent); + virtual ~SvtValueSetAcc() override; + + void FireAccessibleEvent( short nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue ); + bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); } + + static SvtValueSetAcc* getImplementation( const css::uno::Reference< css::uno::XInterface >& rxData ) throw(); + +public: + + /** Called by the corresponding ValueSet when it gets the focus. + Stores the new focus state and broadcasts a state change event. + */ + void GetFocus(); + + /** Called by the corresponding ValueSet when it loses the focus. + Stores the new focus state and broadcasts a state change event. + */ + void LoseFocus(); + + // XAccessible + virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override; + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override; + virtual void SAL_CALL removeAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override; + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) override; + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) override; + virtual sal_Int16 SAL_CALL getAccessibleRole( ) override; + virtual OUString SAL_CALL getAccessibleDescription( ) override; + virtual OUString SAL_CALL getAccessibleName( ) override; + virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) override; + virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) override; + virtual css::lang::Locale SAL_CALL getLocale( ) override; + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override; + virtual css::awt::Rectangle SAL_CALL getBounds( ) override; + virtual css::awt::Point SAL_CALL getLocation( ) override; + virtual css::awt::Point SAL_CALL getLocationOnScreen( ) override; + virtual css::awt::Size SAL_CALL getSize( ) override; + virtual void SAL_CALL grabFocus( ) override; + virtual sal_Int32 SAL_CALL getForeground( ) override; + virtual sal_Int32 SAL_CALL getBackground( ) override; + + // XAccessibleSelection + virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) override; + virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) override; + virtual void SAL_CALL clearAccessibleSelection( ) override; + virtual void SAL_CALL selectAllAccessibleChildren( ) override; + virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) override; + virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) override; + + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rId ) override; + +private: + ::std::vector< css::uno::Reference< + css::accessibility::XAccessibleEventListener > > mxEventListeners; + SvtValueSet* mpParent; + /// The current FOCUSED state. + bool mbIsFocused; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId(); + + /** Tell all listeners that the object is dying. This callback is + usually called from the WeakComponentImplHelper class. + */ + virtual void SAL_CALL disposing() override; + + /** Return the number of items. This takes the None-Item into account. + */ + sal_uInt16 getItemCount() const; + + /** Return the item associated with the given index. The None-Item is + taken into account which, when present, is taken to be the first + (with index 0) item. + @param nIndex + Index of the item to return. The index 0 denotes the None-Item + when present. + @return + Returns NULL when the given index is out of range. + */ + SvtValueSetItem* getItem (sal_uInt16 nIndex) const; + + /** Check whether or not the object has been disposed (or is in the + state of being disposed). If that is the case then + DisposedException is thrown to inform the (indirect) caller of the + foul deed. + @throws css::lang::DisposedException + */ + void ThrowIfDisposed(); + + /** Check whether the value set has a 'none' field, i.e. a field (button) + that deselects any items (selects none of them). + @return + Returns <true/> if there is a 'none' field and <false/> if it is + missing. + */ + bool HasNoneField() const; +}; + + class ValueItemAcc : public ::cppu::WeakImplHelper< css::accessibility::XAccessible, css::accessibility::XAccessibleEventBroadcaster, css::accessibility::XAccessibleContext, @@ -254,6 +389,69 @@ public: virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rId ) override; }; +class SvtValueItemAcc : public ::cppu::WeakImplHelper< css::accessibility::XAccessible, + css::accessibility::XAccessibleEventBroadcaster, + css::accessibility::XAccessibleContext, + css::accessibility::XAccessibleComponent, + css::lang::XUnoTunnel > +{ +private: + + ::std::vector< css::uno::Reference< + css::accessibility::XAccessibleEventListener > > mxEventListeners; + ::osl::Mutex maMutex; + SvtValueSetItem* mpParent; + bool mbIsTransientChildrenDisabled; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId(); + +public: + + SvtValueItemAcc(SvtValueSetItem* pParent, bool bIsTransientChildrenDisabled); + virtual ~SvtValueItemAcc() override; + + void ParentDestroyed(); + + void FireAccessibleEvent( short nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue ); + + static SvtValueItemAcc* getImplementation( const css::uno::Reference< css::uno::XInterface >& rxData ) throw(); + +public: + + // XAccessible + virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override; + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override; + virtual void SAL_CALL removeAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override; + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) override; + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) override; + virtual sal_Int16 SAL_CALL getAccessibleRole( ) override; + virtual OUString SAL_CALL getAccessibleDescription( ) override; + virtual OUString SAL_CALL getAccessibleName( ) override; + virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) override; + virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) override; + virtual css::lang::Locale SAL_CALL getLocale( ) override; + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override; + virtual css::awt::Rectangle SAL_CALL getBounds( ) override; + virtual css::awt::Point SAL_CALL getLocation( ) override; + virtual css::awt::Point SAL_CALL getLocationOnScreen( ) override; + virtual css::awt::Size SAL_CALL getSize( ) override; + virtual void SAL_CALL grabFocus( ) override; + virtual sal_Int32 SAL_CALL getForeground( ) override; + virtual sal_Int32 SAL_CALL getBackground( ) override; + + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rId ) override; +}; + #endif // INCLUDED_SVTOOLS_SOURCE_CONTROL_VALUEIMP_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/control/valueset.cxx b/svtools/source/control/valueset.cxx index 54d7e3bbbf02..3c8e5cbcc753 100644 --- a/svtools/source/control/valueset.cxx +++ b/svtools/source/control/valueset.cxx @@ -2275,4 +2275,1459 @@ void ValueSet::SetEdgeBlending(bool bNew) } } +SvtValueSet::SvtValueSet() + : maVirDev( VclPtr<VirtualDevice>::Create()) + , maColor(COL_TRANSPARENT) + , mnStyle(0) + , mbFormat(true) +{ + maVirDev->SetBackground(Application::GetSettings().GetStyleSettings().GetFaceColor()); + + mpNoneItem.reset(nullptr); + + mnItemWidth = 0; + mnItemHeight = 0; + mnTextOffset = 0; + mnVisLines = 0; + mnLines = 0; + mnUserItemWidth = 0; + mnUserItemHeight = 0; + mnFirstLine = 0; + mnSelItemId = 0; + mnHighItemId = 0; + mnCols = 0; + mnCurCol = 0; + mnUserCols = 0; + mnUserVisLines = 0; + mnSpacing = 0; + mnFrameStyle = DrawFrameStyle::NONE; + mbNoSelection = true; + mbBlackSel = false; + mbDoubleSel = false; + mbScroll = false; + mbFullMode = true; + mbEdgeBlending = false; + mbHasVisibleItems = false; +} + +void SvtValueSet::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + // #106446#, #106601# force mirroring of virtual device + maVirDev->EnableRTL(pDrawingArea->get_direction()); + CustomWidgetController::SetDrawingArea(pDrawingArea); +} + +Reference<XAccessible> SvtValueSet::CreateAccessible() +{ + if (!mxAccessible) + mxAccessible.set(new SvtValueSetAcc(this)); + return mxAccessible; +} + +SvtValueSet::~SvtValueSet() +{ + Reference<XComponent> xComponent(mxAccessible, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + + ImplDeleteItems(); +} + +void SvtValueSet::ImplDeleteItems() +{ + const size_t n = mItemList.size(); + + for ( size_t i = 0; i < n; ++i ) + { + SvtValueSetItem* pItem = mItemList[i]; + if ( pItem->mbVisible && ImplHasAccessibleListeners() ) + { + Any aOldAny; + Any aNewAny; + + aOldAny <<= pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ ); + ImplFireAccessibleEvent(AccessibleEventId::CHILD, aOldAny, aNewAny); + } + + delete pItem; + } + + mItemList.clear(); +} + +void SvtValueSet::Select() +{ + maSelectHdl.Call( this ); +} + +void SvtValueSet::UserDraw( const UserDrawEvent& ) +{ +} + +size_t SvtValueSet::ImplGetItem( const Point& rPos ) const +{ + if (!mbHasVisibleItems) + { + return VALUESET_ITEM_NOTFOUND; + } + + if (mpNoneItem.get() && maNoneItemRect.IsInside(rPos)) + { + return VALUESET_ITEM_NONEITEM; + } + + if (maItemListRect.IsInside(rPos)) + { + const int xc = rPos.X() - maItemListRect.Left(); + const int yc = rPos.Y() - maItemListRect.Top(); + // The point is inside the area of item list, + // let's find the containing item. + const int col = xc / (mnItemWidth + mnSpacing); + const int x = xc % (mnItemWidth + mnSpacing); + const int row = yc / (mnItemHeight + mnSpacing); + const int y = yc % (mnItemHeight + mnSpacing); + + if (x < mnItemWidth && y < mnItemHeight) + { + // the point is inside item rect and not inside spacing + const size_t item = (mnFirstLine + row) * static_cast<size_t>(mnCols) + col; + if (item < mItemList.size()) + { + return item; + } + } + } + + return VALUESET_ITEM_NOTFOUND; +} + +SvtValueSetItem* SvtValueSet::ImplGetItem( size_t nPos ) +{ + if (nPos == VALUESET_ITEM_NONEITEM) + return mpNoneItem.get(); + else + return (nPos < mItemList.size()) ? mItemList[nPos] : nullptr; +} + +SvtValueSetItem* SvtValueSet::ImplGetFirstItem() +{ + return mItemList.size() ? mItemList[0] : nullptr; +} + +sal_uInt16 SvtValueSet::ImplGetVisibleItemCount() const +{ + sal_uInt16 nRet = 0; + const size_t nItemCount = mItemList.size(); + + for ( size_t n = 0; n < nItemCount; ++n ) + { + if ( mItemList[n]->mbVisible ) + ++nRet; + } + + return nRet; +} + +void SvtValueSet::ImplFireAccessibleEvent( short nEventId, const Any& rOldValue, const Any& rNewValue ) +{ + SvtValueSetAcc* pAcc = SvtValueSetAcc::getImplementation(mxAccessible); + + if( pAcc ) + pAcc->FireAccessibleEvent( nEventId, rOldValue, rNewValue ); +} + +bool SvtValueSet::ImplHasAccessibleListeners() +{ + SvtValueSetAcc* pAcc = SvtValueSetAcc::getImplementation(mxAccessible); + return( pAcc && pAcc->HasAccessibleListeners() ); +} + +void SvtValueSet::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + if (GetStyle() & WB_FLATVALUESET) + { + const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); + rRenderContext.SetLineColor(); + rRenderContext.SetFillColor(rStyleSettings.GetFaceColor()); + long nOffY = maVirDev->GetOutputSizePixel().Height(); + Size aWinSize(GetOutputSizePixel()); + rRenderContext.DrawRect(tools::Rectangle(Point(0, nOffY ), Point( aWinSize.Width(), aWinSize.Height()))); + } + + ImplDraw(rRenderContext); +} + +void SvtValueSet::GetFocus() +{ + SAL_INFO("svtools", "value set getting focus"); + Invalidate(); + CustomWidgetController::GetFocus(); + + // Tell the accessible object that we got the focus. + SvtValueSetAcc* pAcc = SvtValueSetAcc::getImplementation(mxAccessible); + if (pAcc) + pAcc->GetFocus(); +} + +void SvtValueSet::LoseFocus() +{ + SAL_INFO("svtools", "value set losing focus"); + Invalidate(); + CustomWidgetController::LoseFocus(); + + // Tell the accessible object that we lost the focus. + SvtValueSetAcc* pAcc = SvtValueSetAcc::getImplementation(mxAccessible); + if( pAcc ) + pAcc->LoseFocus(); +} + +void SvtValueSet::Resize() +{ + mbFormat = true; + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + CustomWidgetController::Resize(); +} + +bool SvtValueSet::KeyInput( const KeyEvent& rKeyEvent ) +{ + size_t nLastItem = mItemList.size(); + + if ( !nLastItem || !ImplGetFirstItem() ) + return CustomWidgetController::KeyInput(rKeyEvent); + + if (mbFormat) + Invalidate(); + + --nLastItem; + + const size_t nCurPos = mnSelItemId ? GetItemPos(mnSelItemId) + : (mpNoneItem.get() ? VALUESET_ITEM_NONEITEM : 0); + size_t nItemPos = VALUESET_ITEM_NOTFOUND; + size_t nVStep = mnCols; + + switch (rKeyEvent.GetKeyCode().GetCode()) + { + case KEY_HOME: + nItemPos = mpNoneItem.get() ? VALUESET_ITEM_NONEITEM : 0; + break; + + case KEY_END: + nItemPos = nLastItem; + break; + + case KEY_LEFT: + if (nCurPos != VALUESET_ITEM_NONEITEM) + { + if (nCurPos) + { + nItemPos = nCurPos-1; + } + else if (mpNoneItem.get()) + { + nItemPos = VALUESET_ITEM_NONEITEM; + } + } + break; + + case KEY_RIGHT: + if (nCurPos < nLastItem) + { + if (nCurPos == VALUESET_ITEM_NONEITEM) + { + nItemPos = 0; + } + else + { + nItemPos = nCurPos+1; + } + } + break; + + case KEY_PAGEUP: + if (rKeyEvent.GetKeyCode().IsShift() || rKeyEvent.GetKeyCode().IsMod1() || rKeyEvent.GetKeyCode().IsMod2()) + { + return CustomWidgetController::KeyInput(rKeyEvent); + } + nVStep *= mnVisLines; + SAL_FALLTHROUGH; + case KEY_UP: + if (nCurPos != VALUESET_ITEM_NONEITEM) + { + if (nCurPos == nLastItem) + { + const size_t nCol = mnCols ? nLastItem % mnCols : 0; + if (nCol < mnCurCol) + { + // Move to previous row/page, keeping the old column + nVStep -= mnCurCol - nCol; + } + } + if (nCurPos >= nVStep) + { + // Go up of a whole page + nItemPos = nCurPos-nVStep; + } + else if (mpNoneItem.get()) + { + nItemPos = VALUESET_ITEM_NONEITEM; + } + else if (nCurPos > mnCols) + { + // Go to same column in first row + nItemPos = nCurPos % mnCols; + } + } + break; + + case KEY_PAGEDOWN: + if (rKeyEvent.GetKeyCode().IsShift() || rKeyEvent.GetKeyCode().IsMod1() || rKeyEvent.GetKeyCode().IsMod2()) + { + return CustomWidgetController::KeyInput(rKeyEvent); + } + nVStep *= mnVisLines; + SAL_FALLTHROUGH; + case KEY_DOWN: + if (nCurPos != nLastItem) + { + if (nCurPos == VALUESET_ITEM_NONEITEM) + { + nItemPos = nVStep-mnCols+mnCurCol; + } + else + { + nItemPos = nCurPos+nVStep; + } + if (nItemPos > nLastItem) + { + nItemPos = nLastItem; + } + } + break; + + case KEY_RETURN: + if (GetStyle() & WB_NO_DIRECTSELECT) + { + Select(); + break; + } + SAL_FALLTHROUGH; + default: + return CustomWidgetController::KeyInput(rKeyEvent); + } + + if ( nItemPos == VALUESET_ITEM_NOTFOUND ) + return false; + + if ( nItemPos!=VALUESET_ITEM_NONEITEM && nItemPos<nLastItem ) + { + // update current column only in case of a new position + // which is also not a "specially" handled one. + mnCurCol = mnCols ? nItemPos % mnCols : 0; + } + const sal_uInt16 nItemId = (nItemPos != VALUESET_ITEM_NONEITEM) ? GetItemId( nItemPos ) : 0; + if ( nItemId != mnSelItemId ) + { + SelectItem( nItemId ); + if (!(GetStyle() & WB_NO_DIRECTSELECT)) + { + // select only if WB_NO_DIRECTSELECT is not set + Select(); + } + } + + return true; +} + +void SvtValueSet::MouseButtonDown( const MouseEvent& rMouseEvent ) +{ + if ( rMouseEvent.IsLeft() ) + { + SvtValueSetItem* pItem = ImplGetItem( ImplGetItem( rMouseEvent.GetPosPixel() ) ); + if (pItem && !rMouseEvent.IsMod2()) + { + if (rMouseEvent.GetClicks() == 1) + { + SelectItem( pItem->mnId ); + if (!(GetStyle() & WB_NOPOINTERFOCUS)) + GrabFocus(); + Select(); + } + else if ( rMouseEvent.GetClicks() == 2 ) + maDoubleClickHdl.Call( this ); + + return; + } + } + + CustomWidgetController::MouseButtonDown( rMouseEvent ); +} + +size_t SvtValueSet::GetItemCount() const +{ + return mItemList.size(); +} + +size_t SvtValueSet::GetItemPos( sal_uInt16 nItemId ) const +{ + for ( size_t i = 0, n = mItemList.size(); i < n; ++i ) { + if ( mItemList[i]->mnId == nItemId ) { + return i; + } + } + return VALUESET_ITEM_NOTFOUND; +} + +sal_uInt16 SvtValueSet::GetItemId( size_t nPos ) const +{ + return ( nPos < mItemList.size() ) ? mItemList[nPos]->mnId : 0 ; +} + +sal_uInt16 SvtValueSet::GetItemId( const Point& rPos ) const +{ + size_t nItemPos = ImplGetItem( rPos ); + if ( nItemPos != VALUESET_ITEM_NOTFOUND ) + return GetItemId( nItemPos ); + + return 0; +} + +tools::Rectangle SvtValueSet::GetItemRect( sal_uInt16 nItemId ) const +{ + const size_t nPos = GetItemPos( nItemId ); + + if ( nPos!=VALUESET_ITEM_NOTFOUND && mItemList[nPos]->mbVisible ) + return ImplGetItemRect( nPos ); + + return tools::Rectangle(); +} + +void SvtValueSet::EnableFullItemMode( bool bFullMode ) +{ + mbFullMode = bFullMode; +} + +tools::Rectangle SvtValueSet::ImplGetItemRect( size_t nPos ) const +{ + const size_t nVisibleBegin = static_cast<size_t>(mnFirstLine)*mnCols; + const size_t nVisibleEnd = nVisibleBegin + static_cast<size_t>(mnVisLines)*mnCols; + + // Check if the item is inside the range of the displayed ones, + // taking into account that last row could be incomplete + if ( nPos<nVisibleBegin || nPos>=nVisibleEnd || nPos>=mItemList.size() ) + return tools::Rectangle(); + + nPos -= nVisibleBegin; + + const size_t row = mnCols ? nPos/mnCols : 0; + const size_t col = mnCols ? nPos%mnCols : 0; + const long x = maItemListRect.Left()+col*(mnItemWidth+mnSpacing); + const long y = maItemListRect.Top()+row*(mnItemHeight+mnSpacing); + + return tools::Rectangle( Point(x, y), Size(mnItemWidth, mnItemHeight) ); +} + +void SvtValueSet::SetFormat() +{ + mbFormat = true; +} + +void SvtValueSet::ImplDraw(vcl::RenderContext& rRenderContext) +{ + if (mbFormat) + Format(rRenderContext); + + Point aDefPos; + Size aSize = maVirDev->GetOutputSizePixel(); + + rRenderContext.DrawOutDev(aDefPos, aSize, aDefPos, aSize, *maVirDev.get()); + + // draw parting line to the Namefield + if (GetStyle() & WB_NAMEFIELD) + { + if (!(GetStyle() & WB_FLATVALUESET)) + { + const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); + Size aWinSize(GetOutputSizePixel()); + Point aPos1(NAME_LINE_OFF_X, mnTextOffset + NAME_LINE_OFF_Y); + Point aPos2(aWinSize.Width() - (NAME_LINE_OFF_X * 2), mnTextOffset + NAME_LINE_OFF_Y); + if (!(rStyleSettings.GetOptions() & StyleSettingsOptions::Mono)) + { + rRenderContext.SetLineColor(rStyleSettings.GetShadowColor()); + rRenderContext.DrawLine(aPos1, aPos2); + aPos1.AdjustY( 1 ); + aPos2.AdjustY( 1 ); + rRenderContext.SetLineColor(rStyleSettings.GetLightColor()); + } + else + rRenderContext.SetLineColor(rStyleSettings.GetWindowTextColor()); + rRenderContext.DrawLine(aPos1, aPos2); + } + } + + ImplDrawSelect(rRenderContext); +} + +void SvtValueSet::SelectItem( sal_uInt16 nItemId ) +{ + size_t nItemPos = 0; + + if ( nItemId ) + { + nItemPos = GetItemPos( nItemId ); + if ( nItemPos == VALUESET_ITEM_NOTFOUND ) + return; + } + + if ( !((mnSelItemId != nItemId) || mbNoSelection) ) + return; + + sal_uInt16 nOldItem = mnSelItemId ? mnSelItemId : 1; + mnSelItemId = nItemId; + mbNoSelection = false; + + bool bNewOut = !mbFormat && IsReallyVisible() && IsUpdateMode(); + bool bNewLine = false; + + // if necessary scroll to the visible area + if (mbScroll && nItemId && mnCols) + { + sal_uInt16 nNewLine = static_cast<sal_uInt16>(nItemPos / mnCols); + if ( nNewLine < mnFirstLine ) + { + mnFirstLine = nNewLine; + bNewLine = true; + } + else if ( nNewLine > static_cast<sal_uInt16>(mnFirstLine+mnVisLines-1) ) + { + mnFirstLine = static_cast<sal_uInt16>(nNewLine-mnVisLines+1); + bNewLine = true; + } + } + + if ( bNewOut ) + { + if ( bNewLine ) + { + // redraw everything if the visible area has changed + mbFormat = true; + } + Invalidate(); + } + + if( ImplHasAccessibleListeners() ) + { + // focus event (deselect) + if( nOldItem ) + { + const size_t nPos = GetItemPos( nItemId ); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + ValueItemAcc* pItemAcc = ValueItemAcc::getImplementation( + mItemList[nPos]->GetAccessible( false/*bIsTransientChildrenDisabled*/ ) ); + + if( pItemAcc ) + { + Any aOldAny; + Any aNewAny; + aOldAny <<= Reference<XInterface>(static_cast<cppu::OWeakObject*>(pItemAcc)); + ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny ); + } + } + } + + // focus event (select) + const size_t nPos = GetItemPos( mnSelItemId ); + + SvtValueSetItem* pItem; + if( nPos != VALUESET_ITEM_NOTFOUND ) + pItem = mItemList[nPos]; + else + pItem = mpNoneItem.get(); + + ValueItemAcc* pItemAcc = nullptr; + if (pItem != nullptr) + pItemAcc = ValueItemAcc::getImplementation( pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ ) ); + + if( pItemAcc ) + { + Any aOldAny; + Any aNewAny; + aNewAny <<= Reference<XInterface>(static_cast<cppu::OWeakObject*>(pItemAcc)); + ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny); + } + + // selection event + Any aOldAny; + Any aNewAny; + ImplFireAccessibleEvent(AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny); + } + maHighlightHdl.Call(this); +} + +void SvtValueSet::SetNoSelection() +{ + mbNoSelection = true; + + if (IsReallyVisible() && IsUpdateMode()) + Invalidate(); +} + +void SvtValueSet::Format(vcl::RenderContext const & rRenderContext) +{ + Size aWinSize(GetOutputSizePixel()); + size_t nItemCount = mItemList.size(); + WinBits nStyle = GetStyle(); + long nTxtHeight = rRenderContext.GetTextHeight(); + long nOff; + long nNoneHeight; + long nNoneSpace; + + // calculate item offset + if (nStyle & WB_ITEMBORDER) + { + if (nStyle & WB_DOUBLEBORDER) + nOff = ITEM_OFFSET_DOUBLE; + else + nOff = ITEM_OFFSET; + } + else + nOff = 0; + + // consider size, if NameField does exist + if (nStyle & WB_NAMEFIELD) + { + mnTextOffset = aWinSize.Height() - nTxtHeight - NAME_OFFSET; + aWinSize.AdjustHeight( -(nTxtHeight + NAME_OFFSET) ); + + if (!(nStyle & WB_FLATVALUESET)) + { + mnTextOffset -= NAME_LINE_HEIGHT + NAME_LINE_OFF_Y; + aWinSize.AdjustHeight( -(NAME_LINE_HEIGHT + NAME_LINE_OFF_Y) ); + } + } + else + mnTextOffset = 0; + + // consider offset and size, if NoneField does exist + if (nStyle & WB_NONEFIELD) + { + nNoneHeight = nTxtHeight + nOff; + nNoneSpace = mnSpacing; + } + else + { + nNoneHeight = 0; + nNoneSpace = 0; + + if (mpNoneItem.get()) + mpNoneItem.reset(nullptr); + } + + // calculate number of columns + if (!mnUserCols) + { + if (mnUserItemWidth) + { + mnCols = static_cast<sal_uInt16>((aWinSize.Width() - mnSpacing) / (mnUserItemWidth + mnSpacing)); + if (mnCols <= 0) + mnCols = 1; + } + else + { + mnCols = 1; + } + } + else + { + mnCols = mnUserCols; + } + + // calculate number of rows + mbScroll = false; + + // Floor( (M+N-1)/N )==Ceiling( M/N ) + mnLines = (static_cast<long>(nItemCount) + mnCols - 1) / mnCols; + if (mnLines <= 0) + mnLines = 1; + + long nCalcHeight = aWinSize.Height() - nNoneHeight; + if (mnUserVisLines) + { + mnVisLines = mnUserVisLines; + } + else if (mnUserItemHeight) + { + mnVisLines = (nCalcHeight - nNoneSpace + mnSpacing) / (mnUserItemHeight + mnSpacing); + if (!mnVisLines) + mnVisLines = 1; + } + else + { + mnVisLines = mnLines; + } + + if (mnLines > mnVisLines) + mbScroll = true; + + if (mnLines <= mnVisLines) + { + mnFirstLine = 0; + } + else + { + if (mnFirstLine > static_cast<sal_uInt16>(mnLines - mnVisLines)) + mnFirstLine = static_cast<sal_uInt16>(mnLines - mnVisLines); + } + + // calculate item size + const long nColSpace = (mnCols - 1) * static_cast<long>(mnSpacing); + const long nLineSpace = ((mnVisLines - 1) * mnSpacing) + nNoneSpace; + if (mnUserItemWidth && !mnUserCols) + { + mnItemWidth = mnUserItemWidth; + if (mnItemWidth > aWinSize.Width() - nColSpace) + mnItemWidth = aWinSize.Width() - nColSpace; + } + else + mnItemWidth = (aWinSize.Width() - nColSpace) / mnCols; + if (mnUserItemHeight && !mnUserVisLines) + { + mnItemHeight = mnUserItemHeight; + if (mnItemHeight > nCalcHeight - nNoneSpace) + mnItemHeight = nCalcHeight - nNoneSpace; + } + else + { + nCalcHeight -= nLineSpace; + mnItemHeight = nCalcHeight / mnVisLines; + } + + // Init VirDev + maVirDev->SetSettings(rRenderContext.GetSettings()); + maVirDev->SetOutputSizePixel(aWinSize); + + // nothing is changed in case of too small items + if ((mnItemWidth <= 0) || + (mnItemHeight <= ((nStyle & WB_ITEMBORDER) ? 4 : 2)) || + !nItemCount) + { + mbHasVisibleItems = false; + + if (nStyle & WB_NONEFIELD) + { + if (mpNoneItem.get()) + { + mpNoneItem->mbVisible = false; + mpNoneItem->maText = GetText(); + } + } + + for (size_t i = 0; i < nItemCount; i++) + { + mItemList[i]->mbVisible = false; + } + } + else + { + mbHasVisibleItems = true; + + // determine Frame-Style + if (nStyle & WB_DOUBLEBORDER) + mnFrameStyle = DrawFrameStyle::DoubleIn; + else + mnFrameStyle = DrawFrameStyle::In; + + // determine selected color and width + // if necessary change the colors, to make the selection + // better detectable + const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); + Color aHighColor(rStyleSettings.GetHighlightColor()); + if (((aHighColor.GetRed() > 0x80) || (aHighColor.GetGreen() > 0x80) || + (aHighColor.GetBlue() > 0x80)) || + ((aHighColor.GetRed() == 0x80) && (aHighColor.GetGreen() == 0x80) && + (aHighColor.GetBlue() == 0x80))) + { + mbBlackSel = true; + } + else + { + mbBlackSel = false; + } + // draw the selection with double width if the items are bigger + if ((nStyle & WB_DOUBLEBORDER) && + ((mnItemWidth >= 25) && (mnItemHeight >= 20))) + { + mbDoubleSel = true; + } + else + { + mbDoubleSel = false; + } + + // calculate offsets + long nStartX; + long nStartY; + if (mbFullMode) + { + long nAllItemWidth = (mnItemWidth * mnCols) + nColSpace; + long nAllItemHeight = (mnItemHeight * mnVisLines) + nNoneHeight + nLineSpace; + nStartX = (aWinSize.Width() - nAllItemWidth) / 2; + nStartY = (aWinSize.Height() - nAllItemHeight) / 2; + } + else + { + nStartX = 0; + nStartY = 0; + } + + // calculate and draw items + maVirDev->SetLineColor(); + long x = nStartX; + long y = nStartY; + + // create NoSelection field and show it + if (nStyle & WB_NONEFIELD) + { + if (!mpNoneItem) + mpNoneItem.reset(new SvtValueSetItem(*this)); + + mpNoneItem->mnId = 0; + mpNoneItem->meType = VALUESETITEM_NONE; + mpNoneItem->mbVisible = true; + maNoneItemRect.SetLeft( x ); + maNoneItemRect.SetTop( y ); + maNoneItemRect.SetRight( maNoneItemRect.Left() + aWinSize.Width() - x - 1 ); + maNoneItemRect.SetBottom( y + nNoneHeight - 1 ); + + ImplFormatItem(rRenderContext, mpNoneItem.get(), maNoneItemRect); + + y += nNoneHeight + nNoneSpace; + } + + // draw items + sal_uLong nFirstItem = static_cast<sal_uLong>(mnFirstLine) * mnCols; + sal_uLong nLastItem = nFirstItem + (mnVisLines * mnCols); + + maItemListRect.SetLeft( x ); + maItemListRect.SetTop( y ); + maItemListRect.SetRight( x + mnCols * (mnItemWidth + mnSpacing) - mnSpacing - 1 ); + maItemListRect.SetBottom( y + mnVisLines * (mnItemHeight + mnSpacing) - mnSpacing - 1 ); + + if (!mbFullMode) + { + // If want also draw parts of items in the last line, + // then we add one more line if parts of these line are + // visible + if (y + (mnVisLines * (mnItemHeight + mnSpacing)) < aWinSize.Height()) + nLastItem += mnCols; + maItemListRect.SetBottom( aWinSize.Height() - y ); + } + for (size_t i = 0; i < nItemCount; i++) + { + SvtValueSetItem* pItem = mItemList[i]; + + if (i >= nFirstItem && i < nLastItem) + { + if (!pItem->mbVisible && ImplHasAccessibleListeners()) + { + Any aOldAny; + Any aNewAny; + + aNewAny <<= pItem->GetAccessible(false/*bIsTransientChildrenDisabled*/); + ImplFireAccessibleEvent(AccessibleEventId::CHILD, aOldAny, aNewAny); + } + + pItem->mbVisible = true; + ImplFormatItem(rRenderContext, pItem, tools::Rectangle(Point(x, y), Size(mnItemWidth, mnItemHeight))); + + if (!((i + 1) % mnCols)) + { + x = nStartX; + y += mnItemHeight + mnSpacing; + } + else + x += mnItemWidth + mnSpacing; + } + else + { + if (pItem->mbVisible && ImplHasAccessibleListeners()) + { + Any aOldAny; + Any aNewAny; + + aOldAny <<= pItem->GetAccessible(false/*bIsTransientChildrenDisabled*/); + ImplFireAccessibleEvent(AccessibleEventId::CHILD, aOldAny, aNewAny); + } + + pItem->mbVisible = false; + } + } + } + + // waiting for the next since the formatting is finished + mbFormat = false; +} + +void SvtValueSet::ImplDrawSelect(vcl::RenderContext& rRenderContext) +{ + if (!IsReallyVisible()) + return; + + const bool bFocus = HasFocus(); + if (!bFocus && mbNoSelection) + { + ImplDrawItemText(rRenderContext, OUString()); + return; + } + + ImplDrawSelect(rRenderContext, mnSelItemId, bFocus, !mbNoSelection); +} + +void SvtValueSet::ImplDrawSelect(vcl::RenderContext& rRenderContext, sal_uInt16 nItemId, const bool bFocus, const bool bDrawSel ) +{ + SvtValueSetItem* pItem; + tools::Rectangle aRect; + if (nItemId) + { + const size_t nPos = GetItemPos( nItemId ); + pItem = mItemList[ nPos ]; + aRect = ImplGetItemRect( nPos ); + } + else if (mpNoneItem.get()) + { + pItem = mpNoneItem.get(); + aRect = maNoneItemRect; + } + else if (bFocus && (pItem = ImplGetFirstItem())) + { + aRect = ImplGetItemRect(0); + } + else + { + return; + } + + if (!pItem->mbVisible) + return; + + // draw selection + const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); + rRenderContext.SetFillColor(); + + Color aDoubleColor(rStyleSettings.GetHighlightColor()); + Color aSingleColor(rStyleSettings.GetHighlightTextColor()); + if (!mbDoubleSel) + { + /* + * #99777# contrast enhancement for thin mode + */ + const Wallpaper& rWall = maVirDev->GetBackground(); + if (!rWall.IsBitmap() && ! rWall.IsGradient()) + { + const Color& rBack = rWall.GetColor(); + if (rBack.IsDark() && ! aDoubleColor.IsBright()) + { + aDoubleColor = COL_WHITE; + aSingleColor = COL_BLACK; + } + else if (rBack.IsBright() && !aDoubleColor.IsDark()) + { + aDoubleColor = COL_BLACK; + aSingleColor = COL_WHITE; + } + } + } + + // specify selection output + WinBits nStyle = GetStyle(); + if (nStyle & WB_MENUSTYLEVALUESET) + { + if (bDrawSel) + { + rRenderContext.SetLineColor(mbBlackSel ? COL_BLACK : aDoubleColor); + rRenderContext.DrawRect(aRect); + } + } + else + { + if (bDrawSel) + { + rRenderContext.SetLineColor(mbBlackSel ? COL_BLACK : aDoubleColor); + rRenderContext.DrawRect(aRect); + } + if (mbDoubleSel) + { + aRect.AdjustLeft( 1 ); + aRect.AdjustTop( 1 ); + aRect.AdjustRight( -1 ); + aRect.AdjustBottom( -1 ); + if (bDrawSel) + rRenderContext.DrawRect(aRect); + } + aRect.AdjustLeft( 1 ); + aRect.AdjustTop( 1 ); + aRect.AdjustRight( -1 ); + aRect.AdjustBottom( -1 ); + tools::Rectangle aRect2 = aRect; + aRect.AdjustLeft( 1 ); + aRect.AdjustTop( 1 ); + aRect.AdjustRight( -1 ); + aRect.AdjustBottom( -1 ); + if (bDrawSel) + rRenderContext.DrawRect(aRect); + if (mbDoubleSel) + { + aRect.AdjustLeft( 1 ); + aRect.AdjustTop( 1 ); + aRect.AdjustRight( -1 ); + aRect.AdjustBottom( -1 ); + if (bDrawSel) + rRenderContext.DrawRect(aRect); + } + + if (bDrawSel) + { + rRenderContext.SetLineColor(mbBlackSel ? COL_WHITE : aSingleColor); + } + else + { + rRenderContext.SetLineColor(COL_LIGHTGRAY); + } + rRenderContext.DrawRect(aRect2); + } + + ImplDrawItemText(rRenderContext, pItem->maText); +} + +void SvtValueSet::ImplFormatItem(vcl::RenderContext const & rRenderContext, SvtValueSetItem* pItem, tools::Rectangle aRect) +{ + WinBits nStyle = GetStyle(); + if (nStyle & WB_ITEMBORDER) + { + aRect.AdjustLeft(1 ); + aRect.AdjustTop(1 ); + aRect.AdjustRight( -1 ); + aRect.AdjustBottom( -1 ); + + if (nStyle & WB_FLATVALUESET) + { + sal_Int32 nBorder = (nStyle & WB_DOUBLEBORDER) ? 2 : 1; + + aRect.AdjustLeft(nBorder ); + aRect.AdjustTop(nBorder ); + aRect.AdjustRight( -nBorder ); + aRect.AdjustBottom( -nBorder ); + } + else + { + DecorationView aView(maVirDev.get()); + aRect = aView.DrawFrame(aRect, mnFrameStyle); + } + } + + if (pItem == mpNoneItem.get()) + pItem->maText = GetText(); + + if (!((aRect.GetHeight() > 0) && (aRect.GetWidth() > 0))) + return; + + const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); + + if (pItem == mpNoneItem.get()) + { + maVirDev->SetFont(rRenderContext.GetFont()); + maVirDev->SetTextColor((nStyle & WB_MENUSTYLEVALUESET) ? rStyleSettings.GetMenuTextColor() : rStyleSettings.GetWindowTextColor()); + maVirDev->SetTextFillColor(); + maVirDev->SetFillColor((nStyle & WB_MENUSTYLEVALUESET) ? rStyleSettings.GetMenuColor() : rStyleSettings.GetWindowColor()); + maVirDev->DrawRect(aRect); + Point aTxtPos(aRect.Left() + 2, aRect.Top()); + long nTxtWidth = rRenderContext.GetTextWidth(pItem->maText); + if ((aTxtPos.X() + nTxtWidth) > aRect.Right()) + { + maVirDev->SetClipRegion(vcl::Region(aRect)); + maVirDev->DrawText(aTxtPos, pItem->maText); + maVirDev->SetClipRegion(); + } + else + maVirDev->DrawText(aTxtPos, pItem->maText); + } + else if (pItem->meType == VALUESETITEM_COLOR) + { + maVirDev->SetFillColor(pItem->maColor); + maVirDev->DrawRect(aRect); + } + else + { + if (IsColor()) + maVirDev->SetFillColor(maColor); + else if (nStyle & WB_MENUSTYLEVALUESET) + maVirDev->SetFillColor(rStyleSettings.GetMenuColor()); + else if (IsEnabled()) + maVirDev->SetFillColor(rStyleSettings.GetWindowColor()); + else + maVirDev->SetFillColor(rStyleSettings.GetFaceColor()); + maVirDev->DrawRect(aRect); + + if (pItem->meType == VALUESETITEM_USERDRAW) + { + UserDrawEvent aUDEvt(nullptr, maVirDev.get(), aRect, pItem->mnId); + UserDraw(aUDEvt); + } + else + { + Size aImageSize = pItem->maImage.GetSizePixel(); + Size aRectSize = aRect.GetSize(); + Point aPos(aRect.Left(), aRect.Top()); + aPos.AdjustX((aRectSize.Width() - aImageSize.Width()) / 2 ); + + if (pItem->meType != VALUESETITEM_IMAGE_AND_TEXT) + aPos.AdjustY((aRectSize.Height() - aImageSize.Height()) / 2 ); + + DrawImageFlags nImageStyle = DrawImageFlags::NONE; + if (!IsEnabled()) + nImageStyle |= DrawImageFlags::Disable; + + if (aImageSize.Width() > aRectSize.Width() || + aImageSize.Height() > aRectSize.Height()) + { + maVirDev->SetClipRegion(vcl::Region(aRect)); + maVirDev->DrawImage(aPos, pItem->maImage, nImageStyle); + maVirDev->SetClipRegion(); + } + else + maVirDev->DrawImage(aPos, pItem->maImage, nImageStyle); + + if (pItem->meType == VALUESETITEM_IMAGE_AND_TEXT) + { + maVirDev->SetFont(rRenderContext.GetFont()); + maVirDev->SetTextColor((nStyle & WB_MENUSTYLEVALUESET) ? rStyleSettings.GetMenuTextColor() : rStyleSettings.GetWindowTextColor()); + maVirDev->SetTextFillColor(); + + long nTxtWidth = maVirDev->GetTextWidth(pItem->maText); + + if (nTxtWidth > aRect.GetWidth()) + maVirDev->SetClipRegion(vcl::Region(aRect)); + + maVirDev->DrawText(Point(aRect.Left() + + (aRect.GetWidth() - nTxtWidth) / 2, + aRect.Bottom() - maVirDev->GetTextHeight()), + pItem->maText); + + if (nTxtWidth > aRect.GetWidth()) + maVirDev->SetClipRegion(); + } + } + } + + const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0); + + if (nEdgeBlendingPercent) + { + const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor()); + const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor()); + const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100); + const BitmapEx aBlendFrame(createBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight)); + + if (!aBlendFrame.IsEmpty()) + { + maVirDev->DrawBitmapEx(aRect.TopLeft(), aBlendFrame); + } + } +} + +void SvtValueSet::ImplDrawItemText(vcl::RenderContext& rRenderContext, const OUString& rText) +{ + if (!(GetStyle() & WB_NAMEFIELD)) + return; + + Size aWinSize(GetOutputSizePixel()); + long nTxtWidth = rRenderContext.GetTextWidth(rText); + long nTxtOffset = mnTextOffset; + + // delete rectangle and show text + if (GetStyle() & WB_FLATVALUESET) + { + const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); + rRenderContext.SetLineColor(); + rRenderContext.SetFillColor(rStyleSettings.GetFaceColor()); + rRenderContext.DrawRect(tools::Rectangle(Point(0, nTxtOffset), Point(aWinSize.Width(), aWinSize.Height()))); + rRenderContext.SetTextColor(rStyleSettings.GetButtonTextColor()); + } + else + { + nTxtOffset += NAME_LINE_HEIGHT+NAME_LINE_OFF_Y; + rRenderContext.SetBackground(Application::GetSettings().GetStyleSettings().GetFaceColor()); + rRenderContext.Erase(tools::Rectangle(Point(0, nTxtOffset), Point(aWinSize.Width(), aWinSize.Height()))); + } + rRenderContext.DrawText(Point((aWinSize.Width() - nTxtWidth) / 2, nTxtOffset + (NAME_OFFSET / 2)), rText); +} + +bool SvtValueSet::ImplScroll(const Point& rPos) +{ + if (!mbScroll || !maItemListRect.IsInside(rPos)) + return false; + + const long nScrollOffset = (mnItemHeight <= 16) ? SCROLL_OFFSET / 2 : SCROLL_OFFSET; + bool bScroll = false; + + if (rPos.Y() <= maItemListRect.Top() + nScrollOffset) + { + if (mnFirstLine > 0) + { + --mnFirstLine; + bScroll = true; + } + } + else if (rPos.Y() >= maItemListRect.Bottom() - nScrollOffset) + { + if (mnFirstLine < static_cast<sal_uInt16>(mnLines - mnVisLines)) + { + ++mnFirstLine; + bScroll = true; + } + } + + if (!bScroll) + return false; + + mbFormat = true; + Invalidate(); + return true; +} + +void SvtValueSet::StyleUpdated() +{ + mbFormat = true; + Invalidate(); +} + +void SvtValueSet::SetColCount( sal_uInt16 nNewCols ) +{ + if ( mnUserCols != nNewCols ) + { + mnUserCols = nNewCols; + mbFormat = true; + queue_resize(); + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } +} + +Color SvtValueSet::GetItemColor( sal_uInt16 nItemId ) const +{ + size_t nPos = GetItemPos( nItemId ); + + if ( nPos != VALUESET_ITEM_NOTFOUND ) + return mItemList[nPos]->maColor; + else + return Color(); +} + +Size SvtValueSet::CalcWindowSizePixel( const Size& rItemSize, sal_uInt16 nDesireCols, + sal_uInt16 nDesireLines ) const +{ + size_t nCalcCols = nDesireCols; + size_t nCalcLines = nDesireLines; + + if ( !nCalcCols ) + { + if ( mnUserCols ) + nCalcCols = mnUserCols; + else + nCalcCols = 1; + } + + if ( !nCalcLines ) + { + nCalcLines = mnVisLines; + + if ( mbFormat ) + { + if ( mnUserVisLines ) + nCalcLines = mnUserVisLines; + else + { + // Floor( (M+N-1)/N )==Ceiling( M/N ) + nCalcLines = (mItemList.size()+nCalcCols-1) / nCalcCols; + if ( !nCalcLines ) + nCalcLines = 1; + } + } + } + + Size aSize( rItemSize.Width() * nCalcCols, rItemSize.Height() * nCalcLines ); + WinBits nStyle = GetStyle(); + long nTxtHeight = GetTextHeight(); + long n; + + if ( nStyle & WB_ITEMBORDER ) + { + if ( nStyle & WB_DOUBLEBORDER ) + n = ITEM_OFFSET_DOUBLE; + else + n = ITEM_OFFSET; + + aSize.AdjustWidth(n * nCalcCols ); + aSize.AdjustHeight(n * nCalcLines ); + } + else + n = 0; + + if ( mnSpacing ) + { + aSize.AdjustWidth(mnSpacing * (nCalcCols - 1) ); + aSize.AdjustHeight(mnSpacing * (nCalcLines - 1) ); + } + + if ( nStyle & WB_NAMEFIELD ) + { + aSize.AdjustHeight(nTxtHeight + NAME_OFFSET ); + if ( !(nStyle & WB_FLATVALUESET) ) + aSize.AdjustHeight(NAME_LINE_HEIGHT + NAME_LINE_OFF_Y ); + } + + if ( nStyle & WB_NONEFIELD ) + { + aSize.AdjustHeight(nTxtHeight + n + mnSpacing ); + } + + return aSize; +} + +void SvtValueSet::InsertItem( sal_uInt16 nItemId, const Color& rColor, + const OUString& rText ) +{ + SvtValueSetItem* pItem = new SvtValueSetItem( *this ); + pItem->mnId = nItemId; + pItem->meType = VALUESETITEM_COLOR; + pItem->maColor = rColor; + pItem->maText = rText; + ImplInsertItem( pItem, VALUESET_APPEND ); +} + +void SvtValueSet::ImplInsertItem( SvtValueSetItem *const pItem, const size_t nPos ) +{ + DBG_ASSERT( pItem->mnId, "ValueSet::InsertItem(): ItemId == 0" ); + DBG_ASSERT( GetItemPos( pItem->mnId ) == VALUESET_ITEM_NOTFOUND, + "ValueSet::InsertItem(): ItemId already exists" ); + + if ( nPos < mItemList.size() ) { + SvtValueItemList::iterator it = mItemList.begin(); + ::std::advance( it, nPos ); + mItemList.insert( it, pItem ); + } else { + mItemList.push_back( pItem ); + } + + queue_resize(); + + mbFormat = true; + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); +} + +void SvtValueSet::SetEdgeBlending(bool bNew) +{ + if(mbEdgeBlending != bNew) + { + mbEdgeBlending = bNew; + mbFormat = true; + + if (GetDrawingArea() && IsReallyVisible() && IsUpdateMode()) + { + Invalidate(); + } + } +} + +Size SvtValueSet::CalcItemSizePixel( const Size& rItemSize) const +{ + Size aSize = rItemSize; + + WinBits nStyle = GetStyle(); + if ( nStyle & WB_ITEMBORDER ) + { + long n; + + if ( nStyle & WB_DOUBLEBORDER ) + n = ITEM_OFFSET_DOUBLE; + else + n = ITEM_OFFSET; + + aSize.AdjustWidth(n ); + aSize.AdjustHeight(n ); + } + + return aSize; +} + +void SvtValueSet::SetLineCount( sal_uInt16 nNewLines ) +{ + if ( mnUserVisLines != nNewLines ) + { + mnUserVisLines = nNewLines; + mbFormat = true; + queue_resize(); + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } +} + +void SvtValueSet::SetItemWidth( long nNewItemWidth ) +{ + if ( mnUserItemWidth != nNewItemWidth ) + { + mnUserItemWidth = nNewItemWidth; + mbFormat = true; + queue_resize(); + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } +} + +void SvtValueSet::SetItemHeight( long nNewItemHeight ) +{ + if ( mnUserItemHeight != nNewItemHeight ) + { + mnUserItemHeight = nNewItemHeight; + mbFormat = true; + queue_resize(); + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } +} + +OUString SvtValueSet::RequestHelp(tools::Rectangle& rHelpRect) +{ + Point aPos = rHelpRect.TopLeft(); + const size_t nItemPos = ImplGetItem( aPos ); + OUString sRet; + if (nItemPos != VALUESET_ITEM_NOTFOUND) + { + rHelpRect = ImplGetItemRect(nItemPos); + sRet = GetItemText(ImplGetItem(nItemPos)->mnId); + } + return sRet; +} + +OUString SvtValueSet::GetItemText(sal_uInt16 nItemId) const +{ + const size_t nPos = GetItemPos(nItemId); + + if ( nPos != VALUESET_ITEM_NOTFOUND ) + return mItemList[nPos]->maText; + + return OUString(); +} + +void SvtValueSet::SetColor(const Color& rColor) +{ + maColor = rColor; + mbFormat = true; + if (IsReallyVisible() && IsUpdateMode()) + Invalidate(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/SvxColorValueSet.cxx b/svx/source/tbxctrls/SvxColorValueSet.cxx index b56fd4d7be12..62e2dc8a596e 100644 --- a/svx/source/tbxctrls/SvxColorValueSet.cxx +++ b/svx/source/tbxctrls/SvxColorValueSet.cxx @@ -29,6 +29,11 @@ SvxColorValueSet::SvxColorValueSet(vcl::Window* _pParent, WinBits nWinStyle) SetEdgeBlending(true); } +ColorValueSet::ColorValueSet() +{ + SetEdgeBlending(true); +} + VCL_BUILDER_FACTORY_CONSTRUCTOR(SvxColorValueSet, WB_TABSTOP) sal_uInt32 SvxColorValueSet::getMaxRowCount() @@ -71,6 +76,25 @@ void SvxColorValueSet::addEntriesForXColorList(const XColorList& rXColorList, sa } } +void ColorValueSet::addEntriesForXColorList(const XColorList& rXColorList, sal_uInt32 nStartIndex) +{ + const sal_uInt32 nColorCount(rXColorList.Count()); + + for(sal_uInt32 nIndex(0); nIndex < nColorCount; nIndex++, nStartIndex++) + { + const XColorEntry* pEntry = rXColorList.GetColor(nIndex); + + if(pEntry) + { + InsertItem(nStartIndex, pEntry->GetColor(), pEntry->GetName()); + } + else + { + OSL_ENSURE(false, "OOps, XColorList with empty entries (!)"); + } + } +} + void SvxColorValueSet::addEntriesForColorSet(const std::set<Color>& rColorSet, const OUString& rNamePrefix) { sal_uInt32 nStartIndex = 1; @@ -126,6 +150,12 @@ void SvxColorValueSet::Resize() ValueSet::Resize(); } +void ColorValueSet::Resize() +{ + layoutToGivenHeight(GetOutputSizePixel().Height(), GetItemCount()); + SvtValueSet::Resize(); +} + Size SvxColorValueSet::layoutToGivenHeight(sal_uInt32 nHeight, sal_uInt32 nEntryCount) { if(!nEntryCount) @@ -170,4 +200,48 @@ Size SvxColorValueSet::layoutToGivenHeight(sal_uInt32 nHeight, sal_uInt32 nEntry return aNewSize; } +Size ColorValueSet::layoutToGivenHeight(sal_uInt32 nHeight, sal_uInt32 nEntryCount) +{ + if(!nEntryCount) + { + nEntryCount++; + } + + const Size aItemSize(SvxColorValueSet::getEntryEdgeLength() - 2, SvxColorValueSet::getEntryEdgeLength() - 2); + const WinBits aWinBits(GetStyle() & ~WB_VSCROLL); + + // get size with all fields disabled + const WinBits aWinBitsNoScrollNoFields(GetStyle() & ~(WB_VSCROLL|WB_NAMEFIELD|WB_NONEFIELD)); + SetStyle(aWinBitsNoScrollNoFields); + const Size aSizeNoScrollNoFields(CalcWindowSizePixel(aItemSize, SvxColorValueSet::getColumnCount())); + + // get size with all needed fields + SetStyle(aWinBits); + Size aNewSize(CalcWindowSizePixel(aItemSize, SvxColorValueSet::getColumnCount())); + + const Size aItemSizePixel(CalcItemSizePixel(aItemSize)); + // calculate field height and available height for requested height + const sal_uInt32 nFieldHeight(aNewSize.Height() - aSizeNoScrollNoFields.Height()); + const sal_uInt32 nAvailableHeight(nHeight >= nFieldHeight ? nHeight - nFieldHeight + aItemSizePixel.Height() - 1 : 0); + + // calculate how many lines can be shown there + const sal_uInt32 nLineCount(nAvailableHeight / aItemSizePixel.Height()); + const sal_uInt32 nLineMax(ceil(double(nEntryCount)/SvxColorValueSet::getColumnCount())); + + if(nLineMax > nLineCount) + { + SetStyle(aWinBits|WB_VSCROLL); + } + + // set height to wanted height + aNewSize.setHeight( nHeight ); + + SetItemWidth(aItemSize.Width()); + SetItemHeight(aItemSize.Height()); + SetColCount(SvxColorValueSet::getColumnCount()); + SetLineCount(nLineCount); + + return aNewSize; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/customweld.cxx b/vcl/source/app/customweld.cxx index 706d3992304e..860a9d2c515e 100644 --- a/vcl/source/app/customweld.cxx +++ b/vcl/source/app/customweld.cxx @@ -30,6 +30,7 @@ CustomWeld::CustomWeld(weld::Builder& rBuilder, const OString& rDrawingId, m_xDrawingArea->connect_key_press(LINK(this, CustomWeld, DoKeyPress)); m_xDrawingArea->connect_focus_rect(LINK(this, CustomWeld, DoFocusRect)); m_xDrawingArea->connect_style_updated(LINK(this, CustomWeld, DoStyleUpdated)); + m_xDrawingArea->connect_query_tooltip(LINK(this, CustomWeld, DoRequestHelp)); m_rWidgetController.SetDrawingArea(m_xDrawingArea.get()); } @@ -77,6 +78,11 @@ IMPL_LINK_NOARG(CustomWeld, DoStyleUpdated, weld::Widget&, void) { m_rWidgetController.StyleUpdated(); } + +IMPL_LINK(CustomWeld, DoRequestHelp, tools::Rectangle&, rHelpArea, OUString) +{ + return m_rWidgetController.RequestHelp(rHelpArea); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 154e1adb420f..2c6fdac648ae 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -346,6 +346,11 @@ public: return m_xWidget->GetAccessibleName(); } + virtual void set_tooltip_text(const OUString& rTip) override + { + m_xWidget->SetQuickHelpText(rTip); + } + virtual void connect_focus_in(const Link<Widget&, void>& rLink) override { m_xWidget->AddEventListener(LINK(this, SalInstanceWidget, FocusInListener)); @@ -368,6 +373,11 @@ public: m_xWidget->ReleaseMouse(); } + virtual bool get_direction() const override + { + return m_xWidget->IsRTLEnabled(); + } + virtual weld::Container* weld_parent() const override; virtual ~SalInstanceWidget() override @@ -1720,6 +1730,7 @@ private: DECL_LINK(KeyPressHdl, const KeyEvent&, bool); DECL_LINK(KeyReleaseHdl, const KeyEvent&, bool); DECL_LINK(StyleUpdatedHdl, VclDrawingArea&, void); + DECL_LINK(QueryTooltipHdl, tools::Rectangle&, OUString); public: SalInstanceDrawingArea(VclDrawingArea* pDrawingArea, const a11yref& rAlly, @@ -1737,6 +1748,7 @@ public: m_xDrawingArea->SetKeyPressHdl(LINK(this, SalInstanceDrawingArea, KeyPressHdl)); m_xDrawingArea->SetKeyReleaseHdl(LINK(this, SalInstanceDrawingArea, KeyReleaseHdl)); m_xDrawingArea->SetStyleUpdatedHdl(LINK(this, SalInstanceDrawingArea, StyleUpdatedHdl)); + m_xDrawingArea->SetQueryTooltipHdl(LINK(this, SalInstanceDrawingArea, QueryTooltipHdl)); } virtual void queue_draw() override @@ -1749,6 +1761,11 @@ public: m_xDrawingArea->Invalidate(tools::Rectangle(Point(x, y), Size(width, height))); } + virtual void queue_resize() override + { + m_xDrawingArea->queue_resize(); + } + virtual a11yref get_accessible_parent() override { vcl::Window* pParent = m_xDrawingArea->GetParent(); @@ -1782,6 +1799,7 @@ public: virtual ~SalInstanceDrawingArea() override { + m_xDrawingArea->SetQueryTooltipHdl(Link<tools::Rectangle&, OUString>()); m_xDrawingArea->SetStyleUpdatedHdl(Link<VclDrawingArea&, void>()); m_xDrawingArea->SetMousePressHdl(Link<const MouseEvent&, void>()); m_xDrawingArea->SetMouseMoveHdl(Link<const MouseEvent&, void>()); @@ -1836,6 +1854,11 @@ IMPL_LINK_NOARG(SalInstanceDrawingArea, StyleUpdatedHdl, VclDrawingArea&, void) m_aStyleUpdatedHdl.Call(*this); } +IMPL_LINK(SalInstanceDrawingArea, QueryTooltipHdl, tools::Rectangle&, rHelpArea, OUString) +{ + return m_aQueryTooltipHdl.Call(rHelpArea); +} + //ComboBox and ListBox have similar apis, ComboBoxes in LibreOffice have an edit box and ListBoxes //don't. This distinction isn't there in Gtk. Use a template to sort this problem out. template <class vcl_type> diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 6ed971e2123b..da393b7ced7e 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -1253,6 +1253,17 @@ public: virtual void set_size_request(int nWidth, int nHeight) override { + GtkWidget* pParent = gtk_widget_get_parent(m_pWidget); + if (GTK_IS_VIEWPORT(pParent)) + { + pParent = gtk_widget_get_parent(pParent); + if (GTK_IS_SCROLLED_WINDOW(pParent)) + { + gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(pParent), nWidth); + gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(pParent), nHeight); + return; + } + } gtk_widget_set_size_request(m_pWidget, nWidth, nHeight); } @@ -1369,6 +1380,11 @@ public: return OUString(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8); } + virtual void set_tooltip_text(const OUString& rTip) override + { + gtk_widget_set_tooltip_text(m_pWidget, OUStringToOString(rTip, RTL_TEXTENCODING_UTF8).getStr()); + } + virtual weld::Container* weld_parent() const override; virtual OString get_buildable_name() const override @@ -1422,6 +1438,11 @@ public: gtk_grab_remove(m_pWidget); } + virtual bool get_direction() const override + { + return gtk_widget_get_direction(m_pWidget) == GTK_TEXT_DIR_RTL; + } + virtual ~GtkInstanceWidget() override { if (m_nFocusInSignalId) @@ -3307,9 +3328,9 @@ public: { gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(pParent), nWidth); gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(pParent), nHeight); + return; } - else - gtk_widget_set_size_request(m_pWidget, nWidth, nHeight); + gtk_widget_set_size_request(m_pWidget, nWidth, nHeight); } virtual void set_selection_mode(bool bMultiple) override @@ -3524,9 +3545,9 @@ public: { gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(pParent), nWidth); gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(pParent), nHeight); + return; } - else - gtk_widget_set_size_request(m_pWidget, nWidth, nHeight); + gtk_widget_set_size_request(m_pWidget, nWidth, nHeight); } virtual void set_text(const OUString& rText) override @@ -3627,6 +3648,7 @@ private: gulong m_nKeyPressSignalId; gulong m_nKeyReleaseSignalId; gulong m_nStyleUpdatedSignalId; + gulong m_nQueryTooltip; static gboolean signalDraw(GtkWidget*, cairo_t* cr, gpointer widget) { @@ -3688,6 +3710,24 @@ private: { m_aStyleUpdatedHdl.Call(*this); } + static gboolean signalQueryTooltip(GtkWidget*, gint x, gint y, + gboolean /*keyboard_mode*/, GtkTooltip *tooltip, + gpointer widget) + { + GtkInstanceDrawingArea* pThis = static_cast<GtkInstanceDrawingArea*>(widget); + tools::Rectangle aHelpArea(x, y); + OUString aTooltip = pThis->signal_query_tooltip(aHelpArea); + if (aTooltip.isEmpty()) + return false; + gtk_tooltip_set_text(tooltip, OUStringToOString(aTooltip, RTL_TEXTENCODING_UTF8).getStr()); + GdkRectangle aGdkHelpArea; + aGdkHelpArea.x = aHelpArea.Left(); + aGdkHelpArea.y = aHelpArea.Top(); + aGdkHelpArea.width = aHelpArea.GetWidth(); + aGdkHelpArea.height = aHelpArea.GetHeight(); + gtk_tooltip_set_tip_area(tooltip, &aGdkHelpArea); + return true; + } static gboolean signalButton(GtkWidget*, GdkEventButton* pEvent, gpointer widget) { GtkInstanceDrawingArea* pThis = static_cast<GtkInstanceDrawingArea*>(widget); @@ -3815,7 +3855,9 @@ public: , m_nKeyPressSignalId(g_signal_connect(m_pDrawingArea, "key-press-event", G_CALLBACK(signalKey), this)) , m_nKeyReleaseSignalId(g_signal_connect(m_pDrawingArea,"key-release-event", G_CALLBACK(signalKey), this)) , m_nStyleUpdatedSignalId(g_signal_connect(m_pDrawingArea,"style-updated", G_CALLBACK(signalStyleUpdated), this)) + , m_nQueryTooltip(g_signal_connect(m_pDrawingArea, "query-tooltip", G_CALLBACK(signalQueryTooltip), this)) { + gtk_widget_set_has_tooltip(m_pWidget, true); g_object_set_data(G_OBJECT(m_pDrawingArea), "g-lo-GtkInstanceDrawingArea", this); } @@ -3840,6 +3882,11 @@ public: gtk_widget_queue_draw_area(GTK_WIDGET(m_pDrawingArea), x, y, width, height); } + virtual void queue_resize() override + { + gtk_widget_queue_resize(GTK_WIDGET(m_pDrawingArea)); + } + virtual a11yref get_accessible_parent() override { //get_accessible_parent should only be needed for the vcl implementation, @@ -3865,6 +3912,7 @@ public: g_object_unref(m_pAccessible); if (m_pSurface) cairo_surface_destroy(m_pSurface); + g_signal_handler_disconnect(m_pDrawingArea, m_nQueryTooltip); g_signal_handler_disconnect(m_pDrawingArea, m_nStyleUpdatedSignalId); g_signal_handler_disconnect(m_pDrawingArea, m_nKeyPressSignalId); g_signal_handler_disconnect(m_pDrawingArea, m_nKeyReleaseSignalId); |