GSoC Writer Table Styles; Create by example; fix undo

- Create style by example, tracked by undo;
- Fixed delete style, now is tracked by undo

Change-Id: Ic39b549b0b970b1b15001d527a82fb26e4a630aa
Reviewed-on: https://gerrit.libreoffice.org/27990
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
This commit is contained in:
Jakub Trzebiatowski 2016-08-02 14:57:17 +02:00 committed by Miklos Vajna
parent 1b482aec4e
commit 0943ee2dec
13 changed files with 277 additions and 22 deletions

View File

@ -1259,6 +1259,10 @@ public:
/// Return the available table styles.
SwTableAutoFormatTable& GetTableStyles() { return *mpTableStyles.get(); }
const SwTableAutoFormatTable& GetTableStyles() const { return *mpTableStyles.get(); }
// Create a new table style. Tracked by Undo.
SwTableAutoFormat* MakeTableStyle(const OUString& rName, bool bBroadcast = false);
// Delete table style named rName. If pAffectedTables is not null, it contains pointers to affected tables. Tracked by undo.
std::unique_ptr<SwTableAutoFormat> DelTableStyle(const OUString& rName, bool bBroadcast = false, std::vector<SwTable*>* pAffectedTables = nullptr);
const SwCellStyleTable& GetCellStyles() const { return *mpCellStyles.get(); }
SwCellStyleTable& GetCellStyles() { return *mpCellStyles.get(); }

View File

@ -50,7 +50,7 @@ class SW_DLLPUBLIC SwDocStyleSheet : public SfxStyleSheetBase
SwFrameFormat* pFrameFormat;
const SwPageDesc* pDesc;
const SwNumRule* pNumRule;
const SwTableAutoFormat* pTableFormat;
SwTableAutoFormat* pTableFormat;
const SwBoxAutoFormat* pBoxFormat;
SwDoc& rDoc;
SfxItemSet aCoreSet;
@ -135,6 +135,7 @@ public:
const SwPageDesc* GetPageDesc();
const SwNumRule* GetNumRule();
void SetNumRule(const SwNumRule& rRule);
SwTableAutoFormat* GetTableFormat();
virtual bool IsUsed() const override;
};

View File

@ -150,7 +150,9 @@ enum SwUndoId
// --> #i73249#
UNDO_FLYFRMFMT_TITLE, // 112
UNDO_FLYFRMFMT_DESCRIPTION, // 113
UNDO_STD_END= UNDO_FLYFRMFMT_DESCRIPTION,
UNDO_TBLSTYLE_CREATE, // 114
UNDO_TBLSTYLE_DELETE, // 115
UNDO_STD_END= UNDO_TBLSTYLE_DELETE,
// UI undo ID's...
UNDO_UI_REPLACE = UNDO_STD_END + 1,

View File

@ -358,6 +358,8 @@ public:
void EraseAutoFormat(size_t i);
void EraseAutoFormat(const OUString& rName);
std::unique_ptr<SwTableAutoFormat> ReleaseAutoFormat(size_t i);
/// Removes an autoformat. Returns pointer to the removed autoformat or nullptr.
std::unique_ptr<SwTableAutoFormat> ReleaseAutoFormat(const OUString& rName);
/// Find table style with the provided name, return nullptr when not found.
SwTableAutoFormat* FindAutoFormat(const OUString& rName) const;

View File

@ -62,6 +62,7 @@
#include "UndoManager.hxx"
#include <textsh.hxx>
#include <frmmgr.hxx>
#include <tblafmt.hxx>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
@ -200,6 +201,7 @@ public:
void testTdf99004();
void testTdf84695();
void testTdf84695NormalChar();
void testTableStyleUndo();
CPPUNIT_TEST_SUITE(SwUiWriterTest);
CPPUNIT_TEST(testReplaceForward);
@ -302,6 +304,7 @@ public:
CPPUNIT_TEST(testTdf99004);
CPPUNIT_TEST(testTdf84695);
CPPUNIT_TEST(testTdf84695NormalChar);
CPPUNIT_TEST(testTableStyleUndo);
CPPUNIT_TEST_SUITE_END();
private:
@ -3765,6 +3768,38 @@ void SwUiWriterTest::testTdf84695NormalChar()
CPPUNIT_ASSERT_EQUAL(OUString("a"), xShape->getString());
}
void SwUiWriterTest::testTableStyleUndo()
{
SwDoc* pDoc = createDoc();
sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
sal_Int32 nStyleCount = pDoc->GetTableStyles().size();
SwTableAutoFormat* pStyle = pDoc->MakeTableStyle("Test Style");
SvxBrushItem aBackground(Color(0xFF00FF), RES_BACKGROUND );
pStyle->GetBoxFormat(0).SetBackground(aBackground);
CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
rUndoManager.Undo();
CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount);
rUndoManager.Redo();
CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
// check if attributes are preserved
pStyle = pDoc->GetTableStyles().FindAutoFormat("Test Style");
CPPUNIT_ASSERT(pStyle);
CPPUNIT_ASSERT(pStyle->GetBoxFormat(0).GetBackground() == aBackground);
pDoc->DelTableStyle("Test Style");
CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount);
rUndoManager.Undo();
CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount + 1);
pStyle = pDoc->GetTableStyles().FindAutoFormat("Test Style");
// check if attributes are preserved
CPPUNIT_ASSERT(pStyle);
CPPUNIT_ASSERT(pStyle->GetBoxFormat(0).GetBackground() == aBackground);
rUndoManager.Undo();
CPPUNIT_ASSERT_EQUAL(sal_Int32(pDoc->GetTableStyles().size()), nStyleCount);
}
CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
CPPUNIT_PLUGIN_IMPLEMENT();

View File

@ -1194,6 +1194,22 @@ std::unique_ptr<SwTableAutoFormat> SwTableAutoFormatTable::ReleaseAutoFormat(siz
return pRet;
}
std::unique_ptr<SwTableAutoFormat> SwTableAutoFormatTable::ReleaseAutoFormat(const OUString& rName)
{
std::unique_ptr<SwTableAutoFormat> pRet(nullptr);
for (auto iter = m_pImpl->m_AutoFormats.begin();
iter != m_pImpl->m_AutoFormats.end(); ++iter)
{
if ((*iter)->GetName() == rName)
{
pRet = std::move(*iter);
m_pImpl->m_AutoFormats.erase(iter);
break;
}
}
return pRet;
}
SwTableAutoFormat* SwTableAutoFormatTable::FindAutoFormat(const OUString& rName) const
{
for (auto &rFormat : m_pImpl->m_AutoFormats)

View File

@ -4613,4 +4613,62 @@ bool SwDoc::HasTableAnyProtection( const SwPosition* pPos,
return bHasProtection;
}
SwTableAutoFormat* SwDoc::MakeTableStyle(const OUString& rName, bool bBroadcast)
{
SwTableAutoFormat aTableFormat(rName);
GetTableStyles().AddAutoFormat(aTableFormat);
SwTableAutoFormat* pTableFormat = GetTableStyles().FindAutoFormat(rName);
getIDocumentState().SetModified();
if (GetIDocumentUndoRedo().DoesUndo())
{
SwUndo * pUndo = new SwUndoTableStyleMake(rName, this);
GetIDocumentUndoRedo().AppendUndo(pUndo);
}
if (bBroadcast)
BroadcastStyleOperation(rName, SfxStyleFamily::Table, SfxStyleSheetHintId::CREATED);
return pTableFormat;
}
std::unique_ptr<SwTableAutoFormat> SwDoc::DelTableStyle(const OUString& rName, bool bBroadcast, std::vector<SwTable*>* pAffectedTables)
{
if (bBroadcast)
BroadcastStyleOperation(rName, SfxStyleFamily::Table, SfxStyleSheetHintId::ERASED);
std::unique_ptr<SwTableAutoFormat> pReleasedFormat = GetTableStyles().ReleaseAutoFormat(rName);
std::vector<SwTable*> vAffectedTables;
if (pReleasedFormat.get())
{
size_t nTableCount = GetTableFrameFormatCount(true);
for (size_t i=0; i < nTableCount; ++i)
{
SwFrameFormat* pFrameFormat = &GetTableFrameFormat(i, true);
SwTable* pTable = SwTable::FindTable(pFrameFormat);
if (pTable->GetTableStyleName() == pReleasedFormat->GetName())
{
pTable->SetTableStyleName("");
vAffectedTables.push_back(pTable);
}
}
getIDocumentState().SetModified();
if (GetIDocumentUndoRedo().DoesUndo())
{
SwUndo * pUndo = new SwUndoTableStyleDelete(std::move(pReleasedFormat), vAffectedTables, this);
GetIDocumentUndoRedo().AppendUndo(pUndo);
}
}
if (pAffectedTables)
*pAffectedTables = vAffectedTables;
return pReleasedFormat;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -378,6 +378,36 @@ public:
void InsertSort( std::vector<sal_uInt16>& rArr, sal_uInt16 nIdx );
class SwUndoTableStyleMake : public SwUndo
{
OUString m_sName;
std::unique_ptr<SwTableAutoFormat> m_pAutoFormat;
public:
SwUndoTableStyleMake(const OUString& rName, const SwDoc* pDoc);
virtual ~SwUndoTableStyleMake();
virtual void UndoImpl( ::sw::UndoRedoContext & ) override;
virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
virtual SwRewriter GetRewriter() const override;
};
class SwUndoTableStyleDelete : public SwUndo
{
std::unique_ptr<SwTableAutoFormat> m_pAutoFormat;
std::vector<SwTable*> m_rAffectedTables;
public:
SwUndoTableStyleDelete(std::unique_ptr<SwTableAutoFormat> pAutoFormat, const std::vector<SwTable*>& rAffectedTables, const SwDoc* pDoc);
virtual ~SwUndoTableStyleDelete();
virtual void UndoImpl( ::sw::UndoRedoContext & ) override;
virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
virtual SwRewriter GetRewriter() const override;
};
#endif // INCLUDED_SW_SOURCE_CORE_INC_UNDOTABLE_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -138,9 +138,11 @@
#define STR_NUMDOWN (CORE_REPEAT_END +66)
#define STR_UNDO_FLYFRMFMT_TITLE (CORE_REPEAT_END +67)
#define STR_UNDO_FLYFRMFMT_DESCRITPTION (CORE_REPEAT_END +68)
#define STR_UNDO_TBLSTYLE_CREATE (CORE_REPEAT_END +69)
#define STR_UNDO_TBLSTYLE_DELETE (CORE_REPEAT_END +70)
// !!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!
#define CORE_UNDO_END STR_UNDO_FLYFRMFMT_DESCRITPTION// !!!! umsetzen !!!
#define CORE_UNDO_END STR_UNDO_TBLSTYLE_DELETE// !!!! umsetzen !!!
// UI-Undo Klammerungen
#define UI_UNDO_BEGIN (CORE_UNDO_END + 1)

View File

@ -650,6 +650,14 @@ String STR_UNDO_FLYFRMFMT_DESCRITPTION
{
Text[ en-US ] = "Change object description of $1";
};
String STR_UNDO_TBLSTYLE_CREATE
{
Text[ en-US ] = "Create table style: $1";
};
String STR_UNDO_TBLSTYLE_DELETE
{
Text[ en-US ] = "Delete table style: $1";
};
String STR_UNDO_TABLE_DELETE
{
Text [ en-US ] = "Delete table" ;

View File

@ -3170,4 +3170,67 @@ void CheckTable( const SwTable& rTable )
}
#endif
SwUndoTableStyleMake::SwUndoTableStyleMake(const OUString& rName, const SwDoc* pDoc)
: SwUndo(UNDO_TBLSTYLE_CREATE, pDoc),
m_sName(rName)
{ }
SwUndoTableStyleMake::~SwUndoTableStyleMake()
{ }
void SwUndoTableStyleMake::UndoImpl(::sw::UndoRedoContext & rContext)
{
m_pAutoFormat = rContext.GetDoc().DelTableStyle(m_sName, true);
}
void SwUndoTableStyleMake::RedoImpl(::sw::UndoRedoContext & rContext)
{
if (m_pAutoFormat.get())
{
SwTableAutoFormat* pFormat = rContext.GetDoc().MakeTableStyle(m_sName, true);
if (pFormat)
{
*pFormat = *m_pAutoFormat;
m_pAutoFormat.reset(nullptr);
}
}
}
SwRewriter SwUndoTableStyleMake::GetRewriter() const
{
SwRewriter aResult;
aResult.AddRule(UndoArg1, m_sName);
return aResult;
}
SwUndoTableStyleDelete::SwUndoTableStyleDelete(std::unique_ptr<SwTableAutoFormat> pAutoFormat, const std::vector<SwTable*>& rAffectedTables, const SwDoc* pDoc)
: SwUndo(UNDO_TBLSTYLE_DELETE, pDoc),
m_pAutoFormat(std::move(pAutoFormat)),
m_rAffectedTables(rAffectedTables)
{ }
SwUndoTableStyleDelete::~SwUndoTableStyleDelete()
{ }
void SwUndoTableStyleDelete::UndoImpl(::sw::UndoRedoContext & rContext)
{
SwTableAutoFormat* pNewFormat = rContext.GetDoc().MakeTableStyle(m_pAutoFormat->GetName(), true);
*pNewFormat = *m_pAutoFormat;
for (size_t i=0; i < m_rAffectedTables.size(); i++)
m_rAffectedTables[i]->SetTableStyleName(m_pAutoFormat->GetName());
}
void SwUndoTableStyleDelete::RedoImpl(::sw::UndoRedoContext & rContext)
{
// Don't need to remember deleted table style nor affected tables, because they must be the same as these already known.
rContext.GetDoc().DelTableStyle(m_pAutoFormat->GetName());
}
SwRewriter SwUndoTableStyleDelete::GetRewriter() const
{
SwRewriter aResult;
aResult.AddRule(UndoArg1, m_pAutoFormat->GetName());
return aResult;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -84,6 +84,7 @@
#include "swabstdlg.hxx"
#include <list.hxx>
#include <paratr.hxx>
#include <tblafmt.hxx>
extern bool g_bNoInterrupt; // in swmodule.cxx
@ -121,6 +122,7 @@ void SwDocShell::StateStyleSheet(SfxItemSet& rSet, SwWrtShell* pSh)
{
// determine current template to every family
OUString aName;
SwTableAutoFormat aTableAutoFormat("dummy"); // needed to check if can take a table auto format at current cursor position
switch (nWhich)
{
case SID_STYLE_APPLY:
@ -249,7 +251,8 @@ void SwDocShell::StateStyleSheet(SfxItemSet& rSet, SwWrtShell* pSh)
? SfxStyleFamily::Frame != nActualFamily
: ( SfxStyleFamily::Frame == nActualFamily ||
SfxStyleFamily::Page == nActualFamily ||
(SfxStyleFamily::Pseudo == nActualFamily && !pShell->GetNumRuleAtCurrCursorPos())) )
(SfxStyleFamily::Pseudo == nActualFamily && !pShell->GetNumRuleAtCurrCursorPos()) ||
(SfxStyleFamily::Table == nActualFamily && !pShell->GetTableAutoFormat(aTableAutoFormat))) )
{
rSet.DisableItem( nWhich );
}
@ -259,7 +262,8 @@ void SwDocShell::StateStyleSheet(SfxItemSet& rSet, SwWrtShell* pSh)
if( (pShell->IsFrameSelected()
? SfxStyleFamily::Frame != nActualFamily
: SfxStyleFamily::Frame == nActualFamily) ||
(SfxStyleFamily::Pseudo == nActualFamily && !pShell->GetNumRuleAtCurrCursorPos()) )
(SfxStyleFamily::Pseudo == nActualFamily && !pShell->GetNumRuleAtCurrCursorPos()) ||
(SfxStyleFamily::Table == nActualFamily && !pShell->GetTableAutoFormat(aTableAutoFormat)) )
{
rSet.DisableItem( nWhich );
}
@ -1268,6 +1272,21 @@ SfxStyleFamily SwDocShell::MakeByExample( const OUString &rName, SfxStyleFamily
}
}
break;
case SfxStyleFamily::Table:
{
SwTableAutoFormat* pFormat = pStyle->GetTableFormat();
if (pCurrWrtShell->GetTableAutoFormat(*pFormat))
{
pCurrWrtShell->StartAllAction();
pCurrWrtShell->SetTableStyle(rName);
pCurrWrtShell->EndAllAction();
}
}
break;
default: break;
}
return nFamily;

View File

@ -301,12 +301,19 @@ static const SwNumRule* lcl_FindNumRule( SwDoc& rDoc,
return pRule;
}
static const SwTableAutoFormat* lcl_FindTableStyle(SwDoc& rDoc, const OUString& rName, SwDocStyleSheet *pStyle = nullptr)
static SwTableAutoFormat* lcl_FindTableStyle(SwDoc& rDoc, const OUString& rName, SwDocStyleSheet *pStyle = nullptr, bool bCreate = true)
{
const SwTableAutoFormat* pFormat = nullptr;
SwTableAutoFormat* pFormat = nullptr;
if (!rName.isEmpty())
{
pFormat = rDoc.GetTableStyles().FindAutoFormat(rName);
if (!pFormat && bCreate)
{
SwTableAutoFormat aNew(rName);
rDoc.GetTableStyles().AddAutoFormat(aNew);
}
}
if(pStyle)
{
@ -2004,7 +2011,7 @@ bool SwDocStyleSheet::FillStyleSheet(
break;
case SfxStyleFamily::Table:
pTableFormat = lcl_FindTableStyle(rDoc, aName, this);
pTableFormat = lcl_FindTableStyle(rDoc, aName, this, bCreate);
SetMask((pTableFormat && pTableFormat->IsUserDefined()) ? SFXSTYLEBIT_USERDEF : 0);
bRet = bPhysical = (nullptr != pTableFormat);
break;
@ -2131,6 +2138,18 @@ void SwDocStyleSheet::Create()
pNumRule = pRule;
}
break;
case SfxStyleFamily::Table:
if (aName.isEmpty())
return;
pTableFormat = lcl_FindTableStyle(rDoc, aName);
if (!pTableFormat)
{
rDoc.MakeTableStyle(aName);
pTableFormat = rDoc.GetTableStyles().FindAutoFormat(aName);
SAL_WARN_IF(!pTableFormat, "sw.ui", "Recently added auto format not found");
}
break;
default:; //prevent warning
}
bPhysical = true;
@ -2165,12 +2184,21 @@ const SwNumRule * SwDocStyleSheet::GetNumRule()
return pNumRule;
}
void SwDocStyleSheet::SetNumRule(const SwNumRule& rRule)
{
OSL_ENSURE(pNumRule, "Wo ist die NumRule");
rDoc.ChgNumRuleFormats( rRule );
}
SwTableAutoFormat* SwDocStyleSheet::GetTableFormat()
{
if(!bPhysical)
FillStyleSheet( FillPhysical );
assert(pTableFormat && "SwDocStyleSheet table style, SwTableAutoFormat not found");
return pTableFormat;
}
// re-generate Name AND Family from String
// First() and Next() (see below) insert an identification letter at Pos.1
@ -2470,20 +2498,7 @@ void SwDocStyleSheetPool::Remove( SfxStyleSheetBase* pStyle)
case SfxStyleFamily::Table:
{
const SwTableAutoFormat* pFormat = lcl_FindTableStyle(rDoc, sName);
if (pFormat)
{
size_t nTableCount = rDoc.GetTableFrameFormatCount(true);
for (size_t i=0; i < nTableCount; ++i)
{
SwFrameFormat* pFrameFormat = &rDoc.GetTableFrameFormat(i, true);
SwTable* pTable = SwTable::FindTable(pFrameFormat);
if (pTable->GetTableStyleName() == pFormat->GetName())
pTable->SetTableStyleName("");
}
rDoc.GetTableStyles().EraseAutoFormat(pFormat->GetName());
}
rDoc.DelTableStyle(sName);
}
break;