LibreOffice Module sw (master) 1
UnfloatTableButton.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
11#include <HeaderFooterWin.hxx>
12
13#include <edtwin.hxx>
14#include <view.hxx>
15#include <wrtsh.hxx>
16#include <strings.hrc>
17#include <fmtpdsc.hxx>
18#include <vcl/metric.hxx>
19#include <vcl/settings.hxx>
20#include <viewopt.hxx>
21#include <frame.hxx>
22#include <flyfrm.hxx>
23#include <tabfrm.hxx>
24#include <txtfrm.hxx>
25#include <pagefrm.hxx>
26#include <ndindex.hxx>
27#include <ndtxt.hxx>
28#include <swtable.hxx>
29#include <unoprnms.hxx>
30#include <unotbl.hxx>
31#include <IDocumentState.hxx>
32#include <IDocumentUndoRedo.hxx>
41#include <svl/grabbagitem.hxx>
42#include <doc.hxx>
43
44#define TEXT_PADDING 3
45#define BOX_DISTANCE 3
46#define BUTTON_WIDTH 12
47
49 : SwFrameMenuButtonBase(pEditWin, pFrame, "modules/swriter/ui/unfloatbutton.ui",
50 "UnfloatButton")
51 , m_xPushButton(m_xBuilder->weld_button("button"))
52 , m_sLabel(SwResId(STR_UNFLOAT_TABLE))
53{
54 m_xPushButton->set_accessible_name(m_sLabel);
55 m_xVirDev = m_xPushButton->create_virtual_device();
57}
58
60
62{
63 m_xPushButton.reset();
66}
67
68void UnfloatTableButton::SetOffset(Point aTopRightPixel)
69{
70 // Compute the text size and get the box position & size from it
71 tools::Rectangle aTextRect;
72 m_xVirDev->GetTextBoundRect(aTextRect, m_sLabel);
73 tools::Rectangle aTextPxRect = m_xVirDev->LogicToPixel(aTextRect);
74 FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
75 Size aBoxSize(aTextPxRect.GetWidth() + BUTTON_WIDTH + TEXT_PADDING * 2,
76 aFontMetric.GetLineHeight() + TEXT_PADDING * 2);
77
78 Point aBoxPos(aTopRightPixel.X() - aBoxSize.Width() - BOX_DISTANCE, aTopRightPixel.Y());
79
81 {
82 aBoxPos.setX(aTopRightPixel.X() + BOX_DISTANCE);
83 }
84
85 // Set the position & Size of the window
86 SetPosSizePixel(aBoxPos, aBoxSize);
87 m_xVirDev->SetOutputSizePixel(aBoxSize);
88
90}
91
93{
94 assert(GetFrame()->IsFlyFrame());
95 // const_cast is needed because of bad design of ISwFrameControl and derived classes
96 SwFlyFrame* pFlyFrame = const_cast<SwFlyFrame*>(static_cast<const SwFlyFrame*>(GetFrame()));
97
98 // Find the table inside the text frame
99 SwTabFrame* pTableFrame = nullptr;
100 SwFrame* pLower = pFlyFrame->GetLower();
101 while (pLower)
102 {
103 if (pLower->IsTabFrame())
104 {
105 pTableFrame = static_cast<SwTabFrame*>(pLower);
106 break;
107 }
108 pLower = pLower->GetNext();
109 }
110
111 if (pTableFrame == nullptr)
112 return;
113
114 // Insert the table at the position of the text node which has the frame anchored to
115 SwFrame* pAnchoreFrame = pFlyFrame->AnchorFrame();
116 if (pAnchoreFrame == nullptr || !pAnchoreFrame->IsTextFrame())
117 return;
118
119 SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pAnchoreFrame);
120 if (pTextFrame->GetTextNodeFirst() == nullptr)
121 return;
122
123 SwNodeIndex aInsertPos((*pTextFrame->GetTextNodeFirst()));
124
125 SwTableNode* pTableNode = pTableFrame->GetTable()->GetTableNode();
126 if (pTableNode == nullptr)
127 return;
128
129 SwDoc& rDoc = pTextFrame->GetDoc();
130
131 // tdf#129176: clear "TablePosition" grab bag, since we explicitly change the position here
132 // See DomainMapperTableHandler::endTableGetTableStyle, where the grab bag is filled, and
133 // DocxAttributeOutput::TableDefinition that uses it on export
134 SwFrameFormat* pTableFormat = pTableFrame->GetTable()->GetFrameFormat();
135 assert(pTableFormat);
136 if (const SfxGrabBagItem* pGrabBagItem = pTableFormat->GetAttrSet().GetItem(RES_FRMATR_GRABBAG))
137 {
138 SfxGrabBagItem aGrabBagItem(*pGrabBagItem); // Editable copy
139 if (aGrabBagItem.GetGrabBag().erase("TablePosition"))
140 {
141 css::uno::Any aVal;
142 aGrabBagItem.QueryValue(aVal);
144 = SwXTextTable::CreateXTextTable(pTableFormat);
145 xTable->setPropertyValue(UNO_NAME_TABLE_INTEROP_GRAB_BAG, aVal);
146 }
147 }
148
149 // When we move the table before the first text node, we need to clear RES_PAGEDESC attribute
150 // of the text node otherwise LO will create a page break after the table
151 if (pTextFrame->GetTextNodeFirst())
152 {
153 const SwPageDesc* pPageDesc
154 = pTextFrame->GetPageDescItem().GetPageDesc(); // First text node of the page has this
155 if (pPageDesc)
156 {
157 // First set the existing page desc for the table node
159 GetEditWin()->GetView().GetWrtShell().GetAttrPool());
160 aSet.Put(SwFormatPageDesc(pPageDesc));
161 SwPaM aPaMTable(*pTableNode);
163 aPaMTable, aSet, SetAttrMode::DEFAULT, GetPageFrame()->getRootFrame());
164
165 // Then remove pagedesc from the attributes of the text node
166 aSet.Put(SwFormatPageDesc(nullptr));
167 SwPaM aPaMTextNode(*pTextFrame->GetTextNodeFirst());
169 aPaMTextNode, aSet, SetAttrMode::DEFAULT, GetPageFrame()->getRootFrame());
170 }
171 }
172
173 // Move the table outside of the text frame
174 SwNodeRange aRange(*pTableNode, SwNodeOffset(0), *pTableNode->EndOfSectionNode(),
175 SwNodeOffset(1));
176 rDoc.getIDocumentContentOperations().MoveNodeRange(aRange, aInsertPos.GetNode(),
178
179 // Remove the floating table's frame
180 SwFlyFrameFormat* pFrameFormat = pFlyFrame->GetFormat();
181 if (pFrameFormat)
182 {
183 rDoc.getIDocumentLayoutAccess().DelLayoutFormat(pFrameFormat);
184 }
185
187
188 // Undoing MoveNodeRange() is not working correctly in case of tables, it crashes sometimes
189 // So don't allow to undo after unfloating (similar to MakeFlyAndMove() method)
190 if (rDoc.GetIDocumentUndoRedo().DoesUndo())
191 {
193 }
194}
195
197{
198 if (!m_xVirDev)
199 return;
200
201 m_xVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
203 const ::tools::Rectangle aRect(
204 ::tools::Rectangle(Point(0, 0), m_xVirDev->PixelToLogic(GetSizePixel())));
205
206 // Create button
208
209 // Create the text primitive
211 basegfx::B2DVector aFontSize;
214 false, false);
215
216 FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
217 double nTextOffsetY = aFontMetric.GetAscent() + TEXT_PADDING;
218 double nTextOffsetX = std::abs(aRect.GetWidth() - m_xVirDev->GetTextWidth(m_sLabel)) / 2.0;
219 Point aTextPos(nTextOffsetX, nTextOffsetY);
220
222 aFontSize.getX(), aFontSize.getY(), static_cast<double>(aTextPos.X()),
223 static_cast<double>(aTextPos.Y())));
224
227 aTextMatrix, m_sLabel, 0, m_sLabel.getLength(), std::vector<double>(), {},
228 std::move(aFontAttr), css::lang::Locale(), aLineColor)));
229
230 // Create the processor and process the primitives
232 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
234 aNewViewInfos));
235
236 pProcessor->process(aSeq);
237
238 m_xPushButton->set_custom_button(m_xVirDev.get());
239}
240
241void UnfloatTableButton::ShowAll(bool bShow) { Show(bShow); }
242
243bool UnfloatTableButton::Contains(const Point& rDocPt) const
244{
246 if (aRect.Contains(rDocPt))
247 return true;
248
249 return false;
250}
251
252void UnfloatTableButton::SetReadonly(bool bReadonly) { ShowAll(!bReadonly); }
253
254/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
#define BOX_DISTANCE
#define TEXT_PADDING
#define BUTTON_WIDTH
static bool GetLayoutRTL()
basegfx::BColor getBColor() const
tools::Long GetLineHeight() const
tools::Long GetAscent() const
virtual bool MoveNodeRange(SwNodeRange &, SwNode &, SwMoveFlags)=0
virtual void InsertItemSet(const SwPaM &rRg, const SfxItemSet &, const SetAttrMode nFlags=SetAttrMode::DEFAULT, SwRootFrame const *pLayout=nullptr)=0
virtual void DelLayoutFormat(SwFrameFormat *pFormat)=0
virtual void SetModified()=0
Must be called manually at changes of format.
virtual bool DoesUndo() const =0
Is Undo enabled?
virtual void DelAllUndoObj()=0
Delete all Undo actions.
const std::map< OUString, css::uno::Any > & GetGrabBag() const
bool QueryValue(css::uno::Any &rVal, sal_uInt8 nMemberId=0) const override
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
constexpr tools::Long Width() const
SwFrame * AnchorFrame()
Definition: doc.hxx:192
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:395
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:316
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:145
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:406
Window class for the Writer edit area, this is the one handling mouse and keyboard events and doing t...
Definition: edtwin.hxx:61
general base class for all free-flowing frames
Definition: flyfrm.hxx:79
virtual const SwFlyFrameFormat * GetFormat() const override
Definition: fly.cxx:2897
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:36
SwPageDesc * GetPageDesc()
Definition: fmtpdsc.hxx:61
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
static void PaintButton(drawinglayer::primitive2d::Primitive2DContainer &rSeq, const tools::Rectangle &rRect, bool bOnTop)
Style of a layout element.
Definition: frmfmt.hxx:62
Class sharing some MenuButton code.
VclPtr< VirtualDevice > m_xVirDev
virtual const SwFrame * GetFrame() override
const SwPageFrame * GetPageFrame() const
virtual SwEditWin * GetEditWin() override
virtual void dispose() override
Base class of the Writer layout elements.
Definition: frame.hxx:315
bool IsTextFrame() const
Definition: frame.hxx:1234
SwFrame * GetNext()
Definition: frame.hxx:676
bool IsTabFrame() const
Definition: frame.hxx:1218
SwFrame * GetLower()
Definition: findfrm.cxx:194
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:136
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:710
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:47
const SwTable * GetTable() const
Definition: tabfrm.hxx:158
SwTableNode * GetTableNode() const
Definition: swtable.cxx:2111
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:204
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:165
SwDoc & GetDoc()
Definition: txtfrm.hxx:466
virtual const SwFormatPageDesc & GetPageDescItem() const override
Definition: findfrm.cxx:726
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:463
static Color & GetHeaderFooterMarkColor()
Definition: viewopt.cxx:474
static rtl::Reference< SwXTextTable > CreateXTextTable(SwFrameFormat *pFrameFormat)
Definition: unotbl.cxx:2001
virtual bool Contains(const Point &rDocPt) const override
Returns true if the point is inside the control.
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
virtual void ShowAll(bool bShow) override
virtual void SetReadonly(bool bReadonly) override
std::unique_ptr< weld::Button > m_xPushButton
virtual ~UnfloatTableButton() override
UnfloatTableButton(SwEditWin *pEditWin, const SwFrame *pFrame)
virtual void dispose() override
void SetOffset(Point aTopRightPixel)
void disposeAndClear()
reference_type * get() const
TYPE getX() const
TYPE getY() const
constexpr tools::Long GetWidth() const
bool Contains(const Point &rPOINT) const
virtual Point GetPosPixel() const
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
virtual Size GetSizePixel() const
virtual void SetPosSizePixel(const Point &rNewPos, const Size &rNewSize)
constexpr TypedWhichId< SfxGrabBagItem > RES_FRMATR_GRABBAG(129)
Sequence< sal_Int8 > aSeq
B2DHomMatrix createScaleTranslateB2DHomMatrix(double fScaleX, double fScaleY, double fTranslateX, double fTranslateY)
attribute::FontAttribute getFontAttributeFromVclFont(basegfx::B2DVector &o_rSize, const vcl::Font &rFont, bool bRTL, bool bBiDiStrong)
std::unique_ptr< drawinglayer::processor2d::BaseProcessor2D > createBaseProcessor2DFromOutputDevice(OutputDevice &rTargetOutDev, const drawinglayer::geometry::ViewInformation2D &rViewInformation2D)
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:164
#define UNO_NAME_TABLE_INTEROP_GRAB_BAG
Definition: unoprnms.hxx:864