odk/CustomTarget_build-examples.mk | 1 odk/Package_examples.mk | 2 odk/examples/cpp/SWriter/Makefile | 77 ++++++ odk/examples/cpp/SWriter/SWriter.cxx | 445 +++++++++++++++++++++++++++++++++++ 4 files changed, 525 insertions(+)
New commits: commit f838bd875f6059376aa5223bda5032db21503bab Author: Daniel Lee <[email protected]> AuthorDate: Sat Dec 27 11:32:35 2025 -0600 Commit: Hossein <[email protected]> CommitDate: Mon Feb 16 13:00:04 2026 +0100 tdf#143122 Port the SWriter sdk example to cpp Change-Id: I6846b31ab98787de8d62ffcff33fa166986cae05 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196251 Tested-by: Jenkins Reviewed-by: Hossein <[email protected]> diff --git a/odk/CustomTarget_build-examples.mk b/odk/CustomTarget_build-examples.mk index 476da4e61078..a18656d3d943 100644 --- a/odk/CustomTarget_build-examples.mk +++ b/odk/CustomTarget_build-examples.mk @@ -29,6 +29,7 @@ my_example_dirs = \ cpp/complextoolbarcontrols \ cpp/counter \ cpp/remoteclient \ + cpp/SWriter \ python/toolpanel \ python/minimal-extension \ diff --git a/odk/Package_examples.mk b/odk/Package_examples.mk index f0b4eff160a6..a5533b7750fa 100644 --- a/odk/Package_examples.mk +++ b/odk/Package_examples.mk @@ -471,6 +471,8 @@ $(eval $(call gb_Package_add_files_with_dir,odk_examples,$(SDKDIRNAME)/examples, cpp/counter/countermain.cxx \ cpp/remoteclient/Makefile \ cpp/remoteclient/remoteclient.cxx \ + cpp/SWriter/Makefile \ + cpp/SWriter/SWriter.cxx \ dotnet/WriterDemo/csharp/Makefile \ dotnet/WriterDemo/csharp/WriterDemo.cs \ dotnet/WriterDemo/fsharp/Makefile \ diff --git a/odk/examples/cpp/SWriter/Makefile b/odk/examples/cpp/SWriter/Makefile new file mode 100644 index 000000000000..e34190e85961 --- /dev/null +++ b/odk/examples/cpp/SWriter/Makefile @@ -0,0 +1,77 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# Builds the C++ SWriter example of the SDK. + +PRJ=../../.. +SETTINGS=$(PRJ)/settings + +include $(SETTINGS)/settings.mk +include $(SETTINGS)/std.mk + +# Define non-platform/compiler specific settings +COMPONENT_NAME=SWriter + +OUT_COMP_INC = $(OUT_INC)/$(COMPONENT_NAME) +OUT_COMP_GEN = $(OUT_MISC)/$(COMPONENT_NAME) +OUT_COMP_OBJ=$(OUT_OBJ)/$(COMPONENT_NAME) + +CXXFILES = SWriter.cxx + +OBJFILES = $(patsubst %.cxx,$(OUT_SLO_COMP)/%.$(OBJ_EXT),$(CXXFILES)) + +ENV_OFFICE_TYPES=-env:URE_MORE_TYPES=$(URLPREFIX)$(OFFICE_TYPES) + +# Targets +.PHONY: ALL +ALL : \ + CppSWriterExample + +include $(SETTINGS)/stdtarget.mk + +$(OUT_COMP_OBJ)/%.$(OBJ_EXT) : %.cxx $(SDKTYPEFLAG) + -$(MKDIR) $(subst /,$(PS),$(@D)) + $(CC) $(CC_FLAGS) $(CC_INCLUDES) -I$(OUT_COMP_INC) $(CC_DEFINES) $(CC_OUTPUT_SWITCH)$(subst /,$(PS),$@) $< + +$(OUT_BIN)/SWriter$(EXE_EXT) : $(OUT_COMP_OBJ)/SWriter.$(OBJ_EXT) + -$(MKDIR) $(subst /,$(PS),$(@D)) + -$(MKDIR) $(subst /,$(PS),$(OUT_COMP_GEN)) +ifeq "$(OS)" "WIN" + $(LINK) $(EXE_LINK_FLAGS) /OUT:$@ /MAP:$(OUT_COMP_GEN)/$(basename $(@F)).map \ + $< $(CPPUHELPERLIB) $(CPPULIB) $(SALHELPERLIB) $(SALLIB) +else + $(LINK) $(EXE_LINK_FLAGS) $(LINK_LIBS) -o $@ $< \ + $(CPPUHELPERLIB) $(CPPULIB) $(SALHELPERLIB) $(SALLIB) $(STDC++LIB) +ifeq "$(OS)" "MACOSX" + $(INSTALL_NAME_URELIBS_BIN) $@ +endif +endif + +CppSWriterExample : $(OUT_BIN)/SWriter$(EXE_EXT) + @echo -------------------------------------------------------------------------------- + @echo The example connects to the office server, create an empty document and puts + @echo some text, a table, and a text frame on it. + @echo - + @echo Use the following command to execute the example! + @echo - + @echo $(MAKE) SWriter.run + @echo - + @echo -------------------------------------------------------------------------------- + +%.run: $(OUT_BIN)/SWriter$(EXE_EXT) + cd $(subst /,$(PS),$(OUT_BIN)) && $(basename $@) $(ENV_OFFICE_TYPES) + +.PHONY: clean +clean : + -$(DELRECURSIVE) $(subst /,$(PS),$(OUT_COMP_INC)) + -$(DELRECURSIVE) $(subst /,$(PS),$(OUT_COMP_GEN)) + -$(DELRECURSIVE) $(subst /,$(PS),$(OUT_COMP_OBJ)) + -$(DEL) $(subst \,\,$(subst /,$(PS),$(OUT_BIN)/SWriter*)) + +# vim: set noet sw=4 ts=4: diff --git a/odk/examples/cpp/SWriter/SWriter.cxx b/odk/examples/cpp/SWriter/SWriter.cxx new file mode 100644 index 000000000000..789396cb7bc7 --- /dev/null +++ b/odk/examples/cpp/SWriter/SWriter.cxx @@ -0,0 +1,445 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <iostream> +#include <sal/main.h> +#include <cppuhelper/bootstrap.hxx> +#include <rtl/bootstrap.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/bridge/XUnoUrlResolver.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/text/TextContentAnchorType.hpp> +#include <com/sun/star/text/ControlCharacter.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/text/XTextCursor.hpp> +#include <com/sun/star/text/XTextDocument.hpp> +#include <com/sun/star/text/XTextFrame.hpp> +#include <com/sun/star/text/XTextTable.hpp> + +using namespace cppu; +using namespace rtl; +using namespace css::uno; +using namespace css::lang; +using namespace css::beans; +using namespace css::bridge; +using namespace css::frame; +using namespace css::text; +using namespace css::table; +using namespace css::drawing; +using namespace css::container; +using namespace css::awt; +using namespace css::uno; + +Reference<XComponent> openWriter(Reference<XComponentContext> xContext); +void insertIntoCell(OUString cellName, OUString theText, Reference<XTextTable> xTextTable); + +// comment: Step 1: bootstrap UNO and get the remote component context +// Step 2: open an empty text document +// Step 3: enter some text +// Step 4: insert a text table +// Step 5: insert colored text +// Step 6: insert a text frame + +int main() +{ + //oooooooooooooooooooooooooooStep 1oooooooooooooooooooooooooooooooooooooooo + // bootstrap UNO and get the remote component context. The context can + // be used to get the service manager + + Reference<XComponentContext> xContext = NULL; + try + { + // get the remote office component context + xContext = bootstrap(); + } + catch (Exception& e) + { + std::cout << "Error: cannot do bootstrapping." << std::endl << e.Message << std::endl; + exit(1); + } + + //oooooooooooooooooooooooooooStep 2oooooooooooooooooooooooooooooooooooooooo + // open an empty document. In this case it's a writer document. + // For this purpose an instance of com.sun.star.frame.Desktop + // is created. It's interface XDesktop provides the XComponentLoader, + // which is used to open the document via loadComponentFromURL + + Reference<XComponent> xComponent = NULL; + xComponent = openWriter(xContext); + Reference<XTextDocument> xTextDocument = NULL; + try + { + xTextDocument.set(xComponent, UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Could not get document." << std::endl << e.Message << std::endl; + exit(1); + } + + //oooooooooooooooooooooooooooStep 3oooooooooooooooooooooooooooooooooooooooo + // insert some text. + // For this purpose get the Text-Object of the document and create the + // cursor. Now it is possible to insert a text at the cursor-position + // via insertString + + // get text object + Reference<XText> xText = xTextDocument->getText(); + + // create cursor object + Reference<XTextCursor> xTextCursor = xText->createTextCursor(); + Reference<XTextRange> xTextRange = NULL; + try + { + xTextRange.set(xTextCursor, UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Could not get text range from cursor." << std::endl << e.Message << std::endl; + exit(1); + } + + // insert some text + xText->insertString(xTextRange, "The first line in the newly created text document. ", false); + xText->insertString(xTextRange, "Now we're in the second line. ", false); + + //oooooooooooooooooooooooooooStep 4oooooooooooooooooooooooooooooooooooooooo + // insert a text table. + // For this purpose get MultiServiceFactory of the document, create an + // instance of com.sun.star.text.TextTable and initialize it. Now it can + // be inserted at the cursor position via insertTextContent. + // After that some properties are changed and some data is inserted. + + // inserting a text table + std::cout << "Inserting a text table" << std::endl; + + // get MSF of document + Reference<XMultiServiceFactory> xMSF = NULL; + try + { + xMSF.set(xTextDocument, UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Couldn't get multi-service factory." << std::endl << e.Message << std::endl; + exit(1); + } + + // create text table + Reference<XTextTable> xTextTable = NULL; + Reference<XTextContent> xTextContent = NULL; + try + { + xTextTable.set(xMSF->createInstance("com.sun.star.text.TextTable"), UNO_QUERY_THROW); + xTextContent.set(xTextTable, UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Couldn't create table." << std::endl << e.Message << std::endl; + exit(1); + } + + // initialize text table with 4 columns and 4 rows + xTextTable->initialize(4, 4); + + Reference<XPropertySet> xRowProps = NULL; + + // insert table + try + { + xText->insertTextContent(xTextRange, xTextContent, false); + // get first row properties + Reference<XTableRows> xTextTableRows = xTextTable->getRows(); + xRowProps.set(xTextTableRows->getByIndex(0), UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Couldn't insert table." << std::endl << e.Message << std::endl; + exit(1); + } + + // get table props + Reference<XPropertySet> xTableProps = NULL; + try + { + xTableProps.set(xTextTable, UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Couldn't get table properties." << std::endl << e.Message << std::endl; + exit(1); + } + + // change back color + try + { + xTableProps->setPropertyValue("BackTransparent", Any(sal_Bool(false))); + xTableProps->setPropertyValue("BackColor", Any(sal_Int32(13421823))); + xRowProps->setPropertyValue("BackTransparent", Any(sal_Bool(false))); + xRowProps->setPropertyValue("BackColor", Any(sal_Int32(6710932))); + } + catch (Exception& e) + { + std::cout << "Couldn't change table color." << std::endl << e.Message << std::endl; + exit(1); + } + + // write text in the table headers + std::cout << "Write text in the table headers" << std::endl; + + insertIntoCell("A1", "FirstColumn", xTextTable); + insertIntoCell("B1", "SecondColumn", xTextTable); + insertIntoCell("C1", "ThirdColumn", xTextTable); + insertIntoCell("D1", "SUM", xTextTable); + + //Insert Something in the text table + std::cout << "Insert something in the text table" << std::endl; + + (xTextTable->getCellByName("A2"))->setValue(22.5); + (xTextTable->getCellByName("B2"))->setValue(5615.3); + (xTextTable->getCellByName("C2"))->setValue(-2315.7); + (xTextTable->getCellByName("D2"))->setFormula("sum <A2:C2>"); + (xTextTable->getCellByName("A3"))->setValue(21.5); + (xTextTable->getCellByName("B3"))->setValue(615.3); + (xTextTable->getCellByName("C3"))->setValue(-315.7); + (xTextTable->getCellByName("D3"))->setFormula("sum <A3:C3>"); + (xTextTable->getCellByName("A4"))->setValue(121.5); + (xTextTable->getCellByName("B4"))->setValue(-615.3); + (xTextTable->getCellByName("C4"))->setValue(415.7); + (xTextTable->getCellByName("D4"))->setFormula("sum <A4:C4>"); + + //oooooooooooooooooooooooooooStep 5oooooooooooooooooooooooooooooooooooooooo + // insert a colored text. + // Get the propertySet of the cursor, change the CharColor and add a + // shadow. Then insert the Text via InsertString at the cursor position. + + // get property set of the cursor + Reference<XPropertySet> xCursorProps = NULL; + try + { + xCursorProps.set(xTextCursor, UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Couldn't get cursor properties." << std::endl << e.Message << std::endl; + exit(1); + } + + // change the color and add a shadow + try + { + xCursorProps->setPropertyValue("CharColor", Any(sal_Int32(255))); + xCursorProps->setPropertyValue("CharShadowed", Any(sal_Bool(true))); + } + catch (Exception& e) + { + std::cout << "Couldn't change table color." << std::endl << e.Message << std::endl; + exit(1); + } + + // create a paragraph break + try + { + xText->insertControlCharacter(xTextRange, ControlCharacter::PARAGRAPH_BREAK, false); + } + catch (Exception& e) + { + std::cout << "Couldn't insert paragraph break." << std::endl << e.Message << std::endl; + exit(1); + } + + // insert colored text + std::cout << "Inserting colored text" << std::endl; + + xText->insertString(xTextRange, "This is a colored text - blue with shadow ", false); + + // create a paragraph break + try + { + xText->insertControlCharacter(xTextRange, ControlCharacter::PARAGRAPH_BREAK, false); + } + catch (Exception& e) + { + std::cout << "Couldn't insert paragraph break." << std::endl << e.Message << std::endl; + exit(1); + } + + //oooooooooooooooooooooooooooStep 6oooooooooooooooooooooooooooooooooooooooo + // insert a text frame. + // create an instance of com.sun.star.text.TextFrame using the MSF of the + // document. Change some properties an insert it. + // Now get the text-Object of the frame and the corresponding cursor. + // Insert some text via insertString. + + // create a text frame + Reference<XTextFrame> xTextFrame = NULL; + Reference<XTextContent> xFrameContent = NULL; + try + { + xTextFrame.set(xMSF->createInstance("com.sun.star.text.TextFrame"), UNO_QUERY_THROW); + xFrameContent.set(xTextFrame, UNO_QUERY_THROW); + Reference<XShape> xFrameShape(xTextFrame, UNO_QUERY_THROW); + Size frameSize(15000, 400); //(width, height) + xFrameShape->setSize(frameSize); + } + catch (Exception& e) + { + std::cout << "Couldn't create text frame." << std::endl << e.Message << std::endl; + exit(1); + } + + // get property set of the text frame + Reference<XPropertySet> xFrameProps = NULL; + try + { + xFrameProps.set(xTextFrame, UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Couldn't get frame properties." << std::endl << e.Message << std::endl; + exit(1); + } + + // change the anchor type + try + { + xFrameProps->setPropertyValue("AnchorType", Any(TextContentAnchorType_AS_CHARACTER)); + } + catch (Exception& e) + { + std::cout << "Couldn't change frame anchor type." << std::endl << e.Message << std::endl; + exit(1); + } + + // insert the text frame + std::cout << "Inserting the text frame" << std::endl; + try + { + xText->insertTextContent(xTextRange, xFrameContent, false); + } + catch (Exception& e) + { + std::cout << "Couldn't insert frame." << std::endl << e.Message << std::endl; + exit(1); + } + + // get text from frame + Reference<XText> xFrameText = xTextFrame->getText(); + + // create cursor object + Reference<XTextCursor> xFrameCursor = xFrameText->createTextCursor(); + Reference<XTextRange> xFrameRange = NULL; + try + { + xFrameRange.set(xFrameCursor, UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Couldn't get frame text range from cursor." << std::endl + << e.Message << std::endl; + exit(1); + } + + // insert some text + xFrameText->insertString(xFrameRange, "The first line in the newly created text frame.", false); + xFrameText->insertString(xFrameRange, " With this second line the height of the frame raises.", + false); + + // create a paragraph break + try + { + xText->insertControlCharacter(xTextRange, ControlCharacter::PARAGRAPH_BREAK, false); + } + catch (Exception& e) + { + std::cout << "Couldn't insert paragraph break." << std::endl << e.Message << std::endl; + exit(1); + } + + // change the color and remove shadow + try + { + xCursorProps->setPropertyValue("CharColor", Any(sal_Int32(65536))); + xCursorProps->setPropertyValue("CharShadowed", Any(sal_Bool(false))); + } + catch (Exception& e) + { + std::cout << "Couldn't change text color." << std::endl << e.Message << std::endl; + exit(1); + } + + xText->insertString(xTextRange, " That's all for now !!", false); + + return 0; +} + +Reference<XComponent> openWriter(Reference<XComponentContext> xContext) +{ + Reference<XComponent> xComp = NULL; + try + { + // getting the remote LibreOffice service manager + Reference<XMultiComponentFactory> xMCF = xContext->getServiceManager(); + + Reference<XInterface> oDesktop + = xMCF->createInstanceWithContext("com.sun.star.frame.Desktop", xContext); + Reference<XComponentLoader> xCLoader(oDesktop, UNO_QUERY_THROW); + Sequence<PropertyValue> szEmptyArgs(0); + OUString strDoc("private:factory/swriter"); + xComp = xCLoader->loadComponentFromURL(strDoc, "_blank", 0, szEmptyArgs); + } + catch (Exception& e) + { + std::cout << "Error opening writer." << std::endl << e.Message << std::endl; + exit(1); + } + + return xComp; +} + +void insertIntoCell(OUString cellName, OUString theText, Reference<XTextTable> xTextTable) +{ + Reference<XText> xCellText = NULL; + Reference<XPropertySet> xCellProps = NULL; + Reference<XTextRange> xCellTextRange = NULL; + try + { + xCellText.set(xTextTable->getCellByName(cellName), UNO_QUERY_THROW); + // create a cursor object + Reference<XTextCursor> xCellTextCursor = xCellText->createTextCursor(); + xCellTextRange.set(xCellTextCursor, UNO_QUERY_THROW); + xCellProps.set(xCellTextCursor, UNO_QUERY_THROW); + } + catch (Exception& e) + { + std::cout << "Couldn't get cell text, cursor properties, or text range." << std::endl + << e.Message << std::endl; + } + + // change the color + try + { + xCellProps->setPropertyValue("CharColor", Any(sal_Int32(16777215))); + } + catch (Exception& e) + { + std::cout << "Couldn't change cell text color." << std::endl << e.Message << std::endl; + exit(1); + } + + xCellText->insertString(xCellTextRange, theText, true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
