1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 package com.sun.star.wizards.text;
28 
29 import java.util.Calendar;
30 import java.util.GregorianCalendar;
31 
32 import com.sun.star.container.NoSuchElementException;
33 import com.sun.star.container.XNameAccess;
34 import com.sun.star.document.XDocumentProperties;
35 import com.sun.star.document.XDocumentPropertiesSupplier;
36 import com.sun.star.frame.XController;
37 import com.sun.star.frame.XComponentLoader;
38 import com.sun.star.frame.XDesktop;
39 import com.sun.star.frame.XFramesSupplier;
40 import com.sun.star.frame.XLoadable;
41 import com.sun.star.frame.XModel;
42 import com.sun.star.frame.XModule;
43 import com.sun.star.frame.XTerminateListener;
44 import com.sun.star.frame.XStorable;
45 import com.sun.star.i18n.NumberFormatIndex;
46 import com.sun.star.awt.Size;
47 import com.sun.star.awt.XWindow;
48 import com.sun.star.awt.XWindowPeer;
49 import com.sun.star.beans.PropertyValue;
50 import com.sun.star.beans.PropertyVetoException;
51 import com.sun.star.lang.Locale;
52 import com.sun.star.lang.WrappedTargetException;
53 import com.sun.star.lang.XComponent;
54 import com.sun.star.lang.XMultiServiceFactory;
55 
56 import com.sun.star.style.XStyle;
57 import com.sun.star.style.XStyleFamiliesSupplier;
58 import com.sun.star.task.XStatusIndicatorFactory;
59 import com.sun.star.text.XPageCursor;
60 import com.sun.star.text.XSimpleText;
61 import com.sun.star.text.XText;
62 import com.sun.star.text.XTextContent;
63 import com.sun.star.text.XTextCursor;
64 import com.sun.star.text.XTextDocument;
65 import com.sun.star.text.XTextViewCursor;
66 import com.sun.star.text.XTextViewCursorSupplier;
67 import com.sun.star.uno.UnoRuntime;
68 import com.sun.star.util.DateTime;
69 import com.sun.star.util.XModifiable;
70 import com.sun.star.util.XNumberFormatsSupplier;
71 import com.sun.star.util.XRefreshable;
72 import com.sun.star.wizards.common.Configuration;
73 import com.sun.star.wizards.common.Desktop;
74 import com.sun.star.wizards.common.Helper;
75 import com.sun.star.wizards.common.JavaTools;
76 import com.sun.star.wizards.common.Helper.DateUtils;
77 import com.sun.star.wizards.common.PropertyNames;
78 import com.sun.star.wizards.document.OfficeDocument;
79 
80 public class TextDocument
81 {
82 
83     public XComponent xComponent;
84     public com.sun.star.text.XTextDocument xTextDocument;
85     public com.sun.star.util.XNumberFormats NumberFormats;
86     public com.sun.star.document.XDocumentProperties m_xDocProps;
87     public com.sun.star.task.XStatusIndicator xProgressBar;
88     public com.sun.star.frame.XFrame xFrame;
89     public XText xText;
90     public XMultiServiceFactory xMSFDoc;
91     public XMultiServiceFactory xMSF;
92     public com.sun.star.util.XNumberFormatsSupplier xNumberFormatsSupplier;
93     public com.sun.star.awt.XWindowPeer xWindowPeer;
94     public int PageWidth;
95     public int ScaleWidth;
96     public Size DocSize;
97     public com.sun.star.awt.Rectangle PosSize;
98     public com.sun.star.lang.Locale CharLocale;
99     public XStorable xStorable;
100 
101     // creates an instance of TextDocument and creates a named frame. No document is actually loaded into this frame.
102     public TextDocument(XMultiServiceFactory xMSF, XTerminateListener listener, String FrameName)
103     {
104         this.xMSF = xMSF;
105         xFrame = OfficeDocument.createNewFrame(xMSF, listener, FrameName);
106     }
107 
108     // creates an instance of TextDocument by loading a given URL as preview
109     public TextDocument(XMultiServiceFactory xMSF, String _sPreviewURL, boolean bShowStatusIndicator, XTerminateListener listener)
110     {
111         this.xMSF = xMSF;
112 
113         xFrame = OfficeDocument.createNewFrame(xMSF, listener);
114         xTextDocument = loadAsPreview(_sPreviewURL, true);
115         xComponent = UnoRuntime.queryInterface(XComponent.class, xTextDocument);
116 
117         if (bShowStatusIndicator)
118         {
119             showStatusIndicator();
120         }
121         init();
122     }
123 
124     // creates an instance of TextDocument from the desktop's current frame
125     public TextDocument(XMultiServiceFactory xMSF, boolean bShowStatusIndicator, XTerminateListener listener)
126     {
127         this.xMSF = xMSF;
128 
129         XDesktop xDesktop = Desktop.getDesktop(xMSF);
130         XFramesSupplier xFrameSupplier = UnoRuntime.queryInterface(XFramesSupplier.class, xDesktop);
131         xFrame = xFrameSupplier.getActiveFrame();
132         xComponent = UnoRuntime.queryInterface(XComponent.class, xFrame.getController().getModel());
133         xTextDocument = UnoRuntime.queryInterface(XTextDocument.class, xComponent);
134 
135         if (bShowStatusIndicator)
136         {
137             showStatusIndicator();
138         }
139         init();
140     }
141 
142     public static class ModuleIdentifier
143     {
144 
145         private String m_identifier;
146 
147         protected final String getIdentifier()
148         {
149             return m_identifier;
150         }
151 
152         public ModuleIdentifier(String _identifier)
153         {
154             m_identifier = _identifier;
155         }
156     }
157 
158     // creates an instance of TextDocument containing a blank text document
159     public TextDocument(XMultiServiceFactory xMSF, ModuleIdentifier _moduleIdentifier, boolean bShowStatusIndicator)
160     {
161         this.xMSF = xMSF;
162 
163         try
164         {
165             // create the empty document, and set its module identifier
166             xTextDocument = UnoRuntime.queryInterface(XTextDocument.class,
167                     xMSF.createInstance("com.sun.star.text.TextDocument"));
168 
169             XLoadable xLoadable = UnoRuntime.queryInterface(XLoadable.class, xTextDocument);
170             xLoadable.initNew();
171 
172             XModule xModule = UnoRuntime.queryInterface(XModule.class,
173                     xTextDocument);
174             xModule.setIdentifier(_moduleIdentifier.getIdentifier());
175 
176             // load the document into a blank frame
177             XDesktop xDesktop = Desktop.getDesktop(xMSF);
178             XComponentLoader xLoader = UnoRuntime.queryInterface(XComponentLoader.class, xDesktop);
179             PropertyValue[] loadArgs = new PropertyValue[]
180             {
181                 new PropertyValue("Model", -1, xTextDocument, com.sun.star.beans.PropertyState.DIRECT_VALUE)
182             };
183             xLoader.loadComponentFromURL("private:object", "_blank", 0, loadArgs);
184 
185             // remember some things for later usage
186             xFrame = xTextDocument.getCurrentController().getFrame();
187             xComponent = UnoRuntime.queryInterface(XComponent.class, xTextDocument);
188         }
189         catch (Exception e)
190         {
191             // TODO: it seems the whole project does not really have an error handling. Other menthods
192             // seem to generally silence errors, so we can't do anything else here ...
193         }
194 
195         if (bShowStatusIndicator)
196         {
197             showStatusIndicator();
198         }
199         init();
200     }
201 
202     //creates an instance of TextDocument from a given XTextDocument
203     public TextDocument(XMultiServiceFactory xMSF, XTextDocument _textDocument, boolean bshowStatusIndicator)
204     {
205         this.xMSF = xMSF;
206         xFrame = _textDocument.getCurrentController().getFrame();
207         xComponent = UnoRuntime.queryInterface(XComponent.class, _textDocument);
208         xTextDocument = UnoRuntime.queryInterface(XTextDocument.class, xComponent);
209         //PosSize = xFrame.getComponentWindow().getPosSize();
210         if (bshowStatusIndicator)
211         {
212             XStatusIndicatorFactory xStatusIndicatorFactory = UnoRuntime.queryInterface(XStatusIndicatorFactory.class, xFrame);
213             xProgressBar = xStatusIndicatorFactory.createStatusIndicator();
214             xProgressBar.start(PropertyNames.EMPTY_STRING, 100);
215             xProgressBar.setValue(5);
216         }
217         xWindowPeer = UnoRuntime.queryInterface(XWindowPeer.class, xFrame.getComponentWindow());
218         xMSFDoc = UnoRuntime.queryInterface(XMultiServiceFactory.class, xTextDocument);
219         xNumberFormatsSupplier = UnoRuntime.queryInterface(XNumberFormatsSupplier.class, xTextDocument);
220 
221         XDocumentPropertiesSupplier xDocPropsSuppl = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, xTextDocument);
222         m_xDocProps = xDocPropsSuppl.getDocumentProperties();
223         CharLocale = (Locale) Helper.getUnoStructValue((Object) xComponent, "CharLocale");
224         xText = xTextDocument.getText();
225     }
226 
227     private void init()
228     {
229         xWindowPeer = UnoRuntime.queryInterface(XWindowPeer.class, xFrame.getComponentWindow());
230         xMSFDoc = UnoRuntime.queryInterface(XMultiServiceFactory.class, xTextDocument);
231         xNumberFormatsSupplier = UnoRuntime.queryInterface(XNumberFormatsSupplier.class, xTextDocument);
232         XDocumentPropertiesSupplier xDocPropsSuppl = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, xTextDocument);
233         m_xDocProps = xDocPropsSuppl.getDocumentProperties();
234         CharLocale = (Locale) Helper.getUnoStructValue((Object) xComponent, "CharLocale");
235         xStorable = UnoRuntime.queryInterface(XStorable.class, xTextDocument);
236         xText = xTextDocument.getText();
237     }
238 
239     private void showStatusIndicator()
240     {
241         XStatusIndicatorFactory xStatusIndicatorFactory = UnoRuntime.queryInterface(XStatusIndicatorFactory.class, xFrame);
242         xProgressBar = xStatusIndicatorFactory.createStatusIndicator();
243         xProgressBar.start(PropertyNames.EMPTY_STRING, 100);
244         xProgressBar.setValue(5);
245     }
246 
247     public XTextDocument loadAsPreview(String sDefaultTemplate, boolean asTemplate)
248     {
249         PropertyValue loadValues[] = new PropertyValue[3];
250         //      open document in the Preview mode
251         loadValues[0] = new PropertyValue();
252         loadValues[0].Name = PropertyNames.READ_ONLY;
253         loadValues[0].Value = Boolean.TRUE;
254         loadValues[1] = new PropertyValue();
255         loadValues[1].Name = "AsTemplate";
256         loadValues[1].Value = asTemplate ? Boolean.TRUE : Boolean.FALSE;
257         loadValues[2] = new PropertyValue();
258         loadValues[2].Name = "Preview";
259         loadValues[2].Value = Boolean.TRUE;
260 
261         //set the preview document to non-modified mode in order to avoid the 'do u want to save' box
262         if (xTextDocument != null)
263         {
264             try
265             {
266                 XModifiable xModi = UnoRuntime.queryInterface(XModifiable.class, xTextDocument);
267                 xModi.setModified(false);
268             }
269             catch (PropertyVetoException e1)
270             {
271                 e1.printStackTrace(System.out);
272             }
273         }
274         Object oDoc = OfficeDocument.load(xFrame, sDefaultTemplate, "_self", loadValues);
275         xTextDocument = (com.sun.star.text.XTextDocument) oDoc;
276         DocSize = getPageSize();
277         xMSFDoc = UnoRuntime.queryInterface(XMultiServiceFactory.class, xTextDocument);
278 
279         ViewHandler myViewHandler = new ViewHandler(xMSFDoc, xTextDocument);
280         try
281         {
282             myViewHandler.setViewSetting("ZoomType", new Short(com.sun.star.view.DocumentZoomType.ENTIRE_PAGE));
283         }
284         catch (Exception e)
285         {
286             e.printStackTrace();
287         }
288 
289         TextFieldHandler myFieldHandler = new TextFieldHandler(xMSF, xTextDocument);
290         myFieldHandler.updateDocInfoFields();
291 
292         return xTextDocument;
293 
294     }
295 
296     public Size getPageSize()
297     {
298         try
299         {
300             XStyleFamiliesSupplier xStyleFamiliesSupplier = UnoRuntime.queryInterface(XStyleFamiliesSupplier.class, xTextDocument);
301             com.sun.star.container.XNameAccess xNameAccess = null;
302             xNameAccess = xStyleFamiliesSupplier.getStyleFamilies();
303             com.sun.star.container.XNameContainer xPageStyleCollection = null;
304             xPageStyleCollection = UnoRuntime.queryInterface(com.sun.star.container.XNameContainer.class, xNameAccess.getByName("PageStyles"));
305             XStyle xPageStyle = UnoRuntime.queryInterface(XStyle.class, xPageStyleCollection.getByName("First Page"));
306             return (Size) Helper.getUnoPropertyValue(xPageStyle, "Size");
307 
308         }
309         catch (Exception exception)
310         {
311             exception.printStackTrace(System.out);
312             return null;
313         }
314     }
315 
316     //creates an instance of TextDocument and creates a frame and loads a document
317     public TextDocument(XMultiServiceFactory xMSF, String URL, PropertyValue[] xArgs, XTerminateListener listener)
318     {
319         this.xMSF = xMSF;
320         XDesktop xDesktop = Desktop.getDesktop(xMSF);
321 
322         xFrame = OfficeDocument.createNewFrame(xMSF, listener);
323         Object oDoc = OfficeDocument.load(xFrame, URL, "_self", xArgs);
324         xTextDocument = (XTextDocument) oDoc;
325         xComponent = UnoRuntime.queryInterface(XComponent.class, xTextDocument);
326         XWindow xWindow = xFrame.getComponentWindow();
327 
328         xWindowPeer = UnoRuntime.queryInterface(XWindowPeer.class, xFrame.getComponentWindow());
329         xMSFDoc = UnoRuntime.queryInterface(XMultiServiceFactory.class, xTextDocument);
330         xNumberFormatsSupplier = UnoRuntime.queryInterface(XNumberFormatsSupplier.class, xTextDocument);
331 
332         XDocumentPropertiesSupplier xDocPropsSuppl = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, xTextDocument);
333         m_xDocProps = xDocPropsSuppl.getDocumentProperties();
334         CharLocale = (Locale) Helper.getUnoStructValue((Object) xComponent, "CharLocale");
335     }
336 
337     public static XTextCursor createTextCursor(Object oCursorContainer)
338     {
339         XSimpleText xText = UnoRuntime.queryInterface(XSimpleText.class, oCursorContainer);
340         return xText.createTextCursor();
341     }
342 
343     // Todo: This method is  unsecure because the last index is not necessarily the last section
344 
345     // Todo: This Routine should be  modified, because I cannot rely on the last Table in the document to be the last in the TextTables sequence
346     // to make it really safe you must acquire the Tablenames before the insertion and after the insertion of the new Table. By comparing the
347     // two sequences of tablenames you can find out the tablename of the last inserted Table
348 
349     // Todo: This method is  unsecure because the last index is not necessarily the last section
350     public int getCharWidth(String ScaleString)
351     {
352         int iScale = 200;
353         xTextDocument.lockControllers();
354         int iScaleLen = ScaleString.length();
355         com.sun.star.text.XTextCursor xTextCursor = createTextCursor(xTextDocument.getText());
356         xTextCursor.gotoStart(false);
357         com.sun.star.wizards.common.Helper.setUnoPropertyValue(xTextCursor, "PageDescName", "First Page");
358         xTextCursor.setString(ScaleString);
359         XTextViewCursorSupplier xViewCursor = UnoRuntime.queryInterface(XTextViewCursorSupplier.class, xTextDocument.getCurrentController());
360         XTextViewCursor xTextViewCursor = xViewCursor.getViewCursor();
361         xTextViewCursor.gotoStart(false);
362         int iFirstPos = xTextViewCursor.getPosition().X;
363         xTextViewCursor.gotoEnd(false);
364         int iLastPos = xTextViewCursor.getPosition().X;
365         iScale = (iLastPos - iFirstPos) / iScaleLen;
366         xTextCursor.gotoStart(false);
367         xTextCursor.gotoEnd(true);
368         xTextCursor.setString(PropertyNames.EMPTY_STRING);
369         unlockallControllers();
370         return iScale;
371     }
372 
373     public void unlockallControllers()
374     {
375         while (xTextDocument.hasControllersLocked())
376         {
377             xTextDocument.unlockControllers();
378         }
379     }
380 
381     public void refresh()
382     {
383         XRefreshable xRefreshable = UnoRuntime.queryInterface(XRefreshable.class, xTextDocument);
384         xRefreshable.refresh();
385     }
386 
387     /**
388      * This method sets the Author of a Wizard-generated template correctly
389      * and adds a explanatory sentence to the template description.
390      * @param WizardName The name of the Wizard.
391      * @param TemplateDescription The old Description which is being appended with another sentence.
392      * @return void.
393      */
394     public void setWizardTemplateDocInfo(String WizardName, String TemplateDescription)
395     {
396         try
397         {
398             Object uD = Configuration.getConfigurationRoot(xMSF, "/org.openoffice.UserProfile/Data", false);
399             XNameAccess xNA = UnoRuntime.queryInterface(XNameAccess.class, uD);
400             Object gn = xNA.getByName("givenname");
401             Object sn = xNA.getByName("sn");
402             String fullname = gn + PropertyNames.SPACE + sn;
403 
404             Calendar cal = new GregorianCalendar();
405             int year = cal.get(Calendar.YEAR);
406             int month = cal.get(Calendar.MONTH);
407             int day = cal.get(Calendar.DAY_OF_MONTH);
408             DateTime currentDate = new DateTime();
409             currentDate.Day = (short) day;
410             currentDate.Month = (short) month;
411             currentDate.Year = (short) year;
412             DateUtils du = new DateUtils(xMSF, this.xTextDocument);
413             int ff = du.getFormat(NumberFormatIndex.DATE_SYS_DDMMYY);
414             String myDate = du.format(ff, currentDate);
415 
416             XDocumentPropertiesSupplier xDocPropsSuppl = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, xTextDocument);
417             XDocumentProperties xDocProps2 = xDocPropsSuppl.getDocumentProperties();
418             xDocProps2.setAuthor(fullname);
419             xDocProps2.setModifiedBy(fullname);
420             String description = xDocProps2.getDescription();
421             description = description + PropertyNames.SPACE + TemplateDescription;
422             description = JavaTools.replaceSubString(description, WizardName, "<wizard_name>");
423             description = JavaTools.replaceSubString(description, myDate, "<current_date>");
424             xDocProps2.setDescription(description);
425         }
426         catch (NoSuchElementException e)
427         {
428             // TODO Auto-generated catch block
429             e.printStackTrace();
430         }
431         catch (WrappedTargetException e)
432         {
433             // TODO Auto-generated catch block
434             e.printStackTrace();
435         }
436         catch (Exception e)
437         {
438             // TODO Auto-generated catch block
439             e.printStackTrace();
440         }
441     }
442 
443     /**
444      * removes an arbitrary Object which supports the  'XTextContent' interface
445      * @param oTextContent
446      * @return
447      */
448     public boolean removeTextContent(Object oTextContent)
449     {
450         try
451         {
452             XTextContent xTextContent = UnoRuntime.queryInterface(XTextContent.class, oTextContent);
453             xText.removeTextContent(xTextContent);
454             return true;
455         }
456         catch (NoSuchElementException e)
457         {
458             e.printStackTrace(System.out);
459             return false;
460         }
461     }
462 
463     /**
464      * Apparently there is no other way to get the
465      * page count of a text document other than using a cursor and
466      * making it jump to the last page...
467      * @param model the document model.
468      * @return the page count of the document.
469      */
470     public static int getPageCount(Object model)
471     {
472         XModel xModel = UnoRuntime.queryInterface(XModel.class, model);
473         XController xController = xModel.getCurrentController();
474         XTextViewCursorSupplier xTextVCS = UnoRuntime.queryInterface(XTextViewCursorSupplier.class, xController);
475         XTextViewCursor xTextVC = xTextVCS.getViewCursor();
476         XPageCursor xPC = UnoRuntime.queryInterface(XPageCursor.class, xTextVC);
477         xPC.jumpToLastPage();
478         return xPC.getPage();
479     }
480 
481     /* Possible Values for "OptionString" are: "LoadCellStyles", "LoadTextStyles", "LoadFrameStyles",
482     "LoadPageStyles", "LoadNumberingStyles", "OverwriteStyles" */
483 }
484