diff options
Diffstat (limited to 'wizards/com/sun/star/wizards/agenda')
12 files changed, 5219 insertions, 0 deletions
diff --git a/wizards/com/sun/star/wizards/agenda/AgendaTemplate.java b/wizards/com/sun/star/wizards/agenda/AgendaTemplate.java new file mode 100644 index 000000000000..422f4c8134f9 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaTemplate.java @@ -0,0 +1,1961 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package com.sun.star.wizards.agenda; + +import java.util.Calendar; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Vector; + + +import com.sun.star.awt.TextEvent; +import com.sun.star.beans.PropertyValue; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.XIndexAccess; +import com.sun.star.container.XNamed; +import com.sun.star.document.XDocumentProperties; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XTerminateListener; +import com.sun.star.i18n.NumberFormatIndex; +import com.sun.star.lang.Locale; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.table.XCell; +import com.sun.star.table.XTableRows; +import com.sun.star.text.*; +import com.sun.star.uno.Any; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.util.XNumberFormatsSupplier; +import com.sun.star.util.XNumberFormatter; +import com.sun.star.util.XSearchDescriptor; +import com.sun.star.util.XSearchable; +import com.sun.star.wizards.common.FileAccess; +import com.sun.star.wizards.common.Helper; +import com.sun.star.wizards.common.JavaTools; +import com.sun.star.wizards.common.NumberFormatter; +import com.sun.star.wizards.document.OfficeDocument; +import com.sun.star.wizards.text.TextDocument; +import com.sun.star.wizards.text.TextSectionHandler; +import com.sun.star.wizards.ui.UnoDialog2; +import com.sun.star.wizards.ui.event.DataAware; + +/** + * + * The classes here implement the whole document-functionality of the agenda wizard: + * the live-preview and the final "creation" of the document, when the user clicks "finish". <br/> + * <br/> + * <h2>Some terminology:<h2/> + * items are names or headings. we don't make any distinction. + * + * <br/> + * The Agenda Template is used as general "controller" of the whole document, whereas the + * two child-classes ItemsTable and TopicsTable control the item tables (note plural!) and the + * topics table (note singular). + * <br/> <br/> + * Other small classes are used to abstract the handling of cells and text and we + * try to use them as components. + * <br/><br/> + * We tried to keep the Agenda Template as flexible as possible, though there + * must be many limitations, because it is generated dynamically.<br/><br/> + * To keep the template flexible the following decisions were made:<br/> + * 1. Item tables.<br/> + * 1.a. there might be arbitrary number of Item tables.<br/> + * 1.b. Item tables design (bordewr, background) is arbitrary.<br/> + * 1.c. Items text styles are individual, and use stylelist styles with predefined names.<br/> + * As result the following limitations:<br/> + * Pairs of Name->value for each item.<br/> + * Tables contain *only* those pairs.<br/> + * 2. Topics table.<br/> + * 2.a. arbitrary structure.<br/> + * 2.b. design is arbitrary.<br/> + * As result the following limitations:<br/> + * No column merge is allowed.<br/> + * One compolsary Heading row.<br/> + * <br/><br/> + * To let the template be flexible, we use a kind of "detection": we look where + * the items are read the design of each table, reaplying it after writing the + * table. + * <br/><br/> + * A note about threads:<br/> + * Many methods here are synchronized, in order to avoid colission made by + * events fired too often. + * @author rpiterman + * + */ +public class AgendaTemplate extends TextDocument implements TemplateConsts, DataAware.Listener +{ + + /** + * resources. + */ + AgendaWizardDialogResources resources; + /** + * data model. This keeps the status of the agenda document, and + * every redraw is done according to this data. + * Exception: topic data is written programatically, event-oriented. + */ + CGAgenda agenda; + /** + * the UNO Text Document serrvice + */ + Object document; + /** + * Service Factory + */ + XMultiServiceFactory docMSF; + /** + * The template-filename of the current template. + * Since we often re-link section and the break the link, + * inorder to restore them, we need a template to link to. + * This is practically an identicall copy of the current template. + */ + String template; + /** + * used for common operations on sections. + */ + TextSectionHandler textSectionHandler; + /** + * a component loader. + */ + XComponentLoader xComponentLoader; + /** + * an array containing all ItemTable object (which control each an Items + * Table in the document. + */ + ItemsTable[] itemsTables; + /** + * the controller of the topics table. + */ + Topics topics; + /** + * Stores reusable OOo Placeholder TextFields to insert to the document. + */ + Map itemsCache; + /** + * This map is used to find which tables contains a certain Item, so + * the keys are the different Items, the Objects are the ItemTable controllers. + * When an Item must be redrawn (because the user checked or uncheced it), + * the controller is retrieved from this Map, and a redraw is issued on this controller. + */ + Map itemsMap = new Hashtable(11); + /** + * A temporary variable used to list all items and map them. + */ + List _allItems = new Vector(); + /** + * keep a reference on some static items in the document, + * so when their content is changed (through the user), we + * can just reference them and set their text. + */ + TextElement teTitle, teDate, teTime, teLocation; + XTextRange trTitle, trDate, trTime, trLocation; + /** + * used to format the date / time. + */ + int dateFormat, timeFormat; + XNumberFormatter dateFormatter, timeFormatter; + /** + * used to transfare time from VCL to UNO. + */ + long docNullTime; + Calendar calendar; + /** + * used to set the document title property (step 6). + */ + private XDocumentProperties m_xDocProps; + + /** + * loads the given template, and analyze its structure. + * @param templateURL + * @param topics + * @see AgendaTemplate.initialize() + * @see AgendaTemplate.initializeData() + */ + public synchronized void load(String templateURL, List topics) + { + template = calcTemplateName(templateURL); + document = loadAsPreview(templateURL, false); + docMSF = ((XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, document)); + xFrame.getComponentWindow().setEnable(false); + xTextDocument.lockControllers(); + initialize(); + initializeData(topics); + xTextDocument.unlockControllers(); + } + + /** + * The agenda templates are in format of aw-XXX.ott + * the templates name is then XXX.ott. + * This method calculates it. + * @param url + * @return the template name without the "aw-" at the beginning. + */ + private String calcTemplateName(String url) + { + return FileAccess.connectURLs(FileAccess.getParentDir(url), FileAccess.getFilename(url).substring(3)); + } + + /** + * synchronize the document to the model.<br/> + * this method rewrites all titles, item tables , and the topics table- + * thus synchronizing the document to the data model (CGAgenda). + * @param topicsData since the model does not contain Topics + * information (it is only actualized on save) the given list + * supplies this information. + */ + private void initializeData(List topicsData) + { + for (int i = 0; i < itemsTables.length; i++) + { + try + { + itemsTables[i].write(""); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + redrawTitle("txtTitle"); + redrawTitle("txtDate"); + redrawTitle("txtTime"); + redrawTitle("cbLocation"); + + topics.writeAll(topicsData); + + setTemplateTitle(agenda.cp_TemplateName); + + } + + /** + * redraws/rewrites the table which contains the given item + * This method is called when the user checks/unchecks an item. + * The table is being found, in which the item is, and redrawn. + * @param itemName + */ + public synchronized void redraw(String itemName) + { + try + { + // get the table in which the item is... + Object itemsTable = + itemsMap.get(itemName); + // rewrite the table. + ((ItemsTable) itemsTable).write(null); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * update the documents title property to the given title + * @param newTitle new title. + */ + synchronized void setTemplateTitle(String newTitle) + { + m_xDocProps.setTitle(newTitle); + } + + /** + * constructor. The document is *not* loaded here. + * only some formal members are set. + * @param xmsf_ service factory. + * @param agenda_ the data model (CGAgenda) + * @param resources_ resources. + */ + AgendaTemplate(XMultiServiceFactory xmsf_, CGAgenda agenda_, AgendaWizardDialogResources resources_, XTerminateListener listener) + { + super(xmsf_, listener, "WIZARD_LIVE_PREVIEW"); + + agenda = agenda_; + resources = resources_; + + if (itemsCache == null) + { + initItemsCache(); + } + _allItems = null; + + } + + /** + * checks the data model if the + * item corresponding to the given string should be shown + * @param itemName a string representing an Item (name or heading). + * @return true if the model specifies that the item should be displayed. + */ + boolean isShowItem(String itemName) + { + if (itemName.equals(FILLIN_MEETING_TYPE)) + { + return agenda.cp_ShowMeetingType; + } + else if (itemName.equals(FILLIN_READ)) + { + return agenda.cp_ShowRead; + } + else if (itemName.equals(FILLIN_BRING)) + { + return agenda.cp_ShowBring; + } + else if (itemName.equals(FILLIN_NOTES)) + { + return agenda.cp_ShowNotes; + } + else if (itemName.equals(FILLIN_FACILITATOR)) + { + return agenda.cp_ShowFacilitator; + } + else if (itemName.equals(FILLIN_TIMEKEEPER)) + { + return agenda.cp_ShowTimekeeper; + } + else if (itemName.equals(FILLIN_NOTETAKER)) + { + return agenda.cp_ShowNotetaker; + } + else if (itemName.equals(FILLIN_PARTICIPANTS)) + { + return agenda.cp_ShowAttendees; + } + else if (itemName.equals(FILLIN_CALLED_BY)) + { + return agenda.cp_ShowCalledBy; + } + else if (itemName.equals(FILLIN_OBSERVERS)) + { + return agenda.cp_ShowObservers; + } + else if (itemName.equals(FILLIN_RESOURCE_PERSONS)) + { + return agenda.cp_ShowResourcePersons; + } + else + { + throw new IllegalArgumentException("No such item"); + } + } + + /** + * itemsCache is a Map containing all agenda item. These are object which + * "write themselfs" to the table, given a table cursor. + * A cache is used in order to reuse the objects, instead of recreate them. + * This method fills the cache will all items objects (names and headings). + */ + private void initItemsCache() + { + itemsCache = new Hashtable(11); + + XMultiServiceFactory xmsf = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, document); + // Headings + + itemsCache.put(FILLIN_MEETING_TYPE, + new AgendaItem(FILLIN_MEETING_TYPE, new TextElement(resources.itemMeetingType, STYLE_MEETING_TYPE), + new PlaceholderElement(STYLE_MEETING_TYPE_TEXT, resources.reschkMeetingTitle_value, resources.resPlaceHolderHint, xmsf))); + + itemsCache.put(FILLIN_BRING, + new AgendaItem(FILLIN_BRING, new TextElement(resources.itemBring, STYLE_BRING), + new PlaceholderElement(STYLE_BRING_TEXT, resources.reschkBring_value, resources.resPlaceHolderHint, xmsf))); + + itemsCache.put(FILLIN_READ, + new AgendaItem(FILLIN_READ, new TextElement(resources.itemRead, STYLE_READ), + new PlaceholderElement(STYLE_READ_TEXT, resources.reschkRead_value, resources.resPlaceHolderHint, xmsf))); + + itemsCache.put(FILLIN_NOTES, + new AgendaItem(FILLIN_NOTES, new TextElement(resources.itemNote, STYLE_NOTES), + new PlaceholderElement(STYLE_NOTES_TEXT, resources.reschkNotes_value, resources.resPlaceHolderHint, xmsf))); + + // Names + + itemsCache.put(FILLIN_CALLED_BY, + new AgendaItem(FILLIN_CALLED_BY, new TextElement(resources.itemCalledBy, STYLE_CALLED_BY), + new PlaceholderElement(STYLE_CALLED_BY_TEXT, resources.reschkConvenedBy_value, resources.resPlaceHolderHint, xmsf))); + + itemsCache.put(FILLIN_FACILITATOR, + new AgendaItem(FILLIN_FACILITATOR, new TextElement(resources.itemFacilitator, STYLE_FACILITATOR), + new PlaceholderElement(STYLE_FACILITATOR_TEXT, resources.reschkPresiding_value, resources.resPlaceHolderHint, xmsf))); + + itemsCache.put(FILLIN_PARTICIPANTS, + new AgendaItem(FILLIN_PARTICIPANTS, new TextElement(resources.itemAttendees, STYLE_PARTICIPANTS), + new PlaceholderElement(STYLE_PARTICIPANTS_TEXT, resources.reschkAttendees_value, resources.resPlaceHolderHint, xmsf))); + + itemsCache.put(FILLIN_NOTETAKER, + new AgendaItem(FILLIN_NOTETAKER, new TextElement(resources.itemNotetaker, STYLE_NOTETAKER), + new PlaceholderElement(STYLE_NOTETAKER_TEXT, resources.reschkNoteTaker_value, resources.resPlaceHolderHint, xmsf))); + + itemsCache.put(FILLIN_TIMEKEEPER, + new AgendaItem(FILLIN_TIMEKEEPER, new TextElement(resources.itemTimekeeper, STYLE_TIMEKEEPER), + new PlaceholderElement(STYLE_TIMEKEEPER_TEXT, resources.reschkTimekeeper_value, resources.resPlaceHolderHint, xmsf))); + + itemsCache.put(FILLIN_OBSERVERS, + new AgendaItem(FILLIN_OBSERVERS, new TextElement(resources.itemObservers, STYLE_OBSERVERS), + new PlaceholderElement(STYLE_OBSERVERS_TEXT, resources.reschkObservers_value, resources.resPlaceHolderHint, xmsf))); + + itemsCache.put(FILLIN_RESOURCE_PERSONS, + new AgendaItem(FILLIN_RESOURCE_PERSONS, new TextElement(resources.itemResource, STYLE_RESOURCE_PERSONS), + new PlaceholderElement(STYLE_RESOURCE_PERSONS_TEXT, resources.reschkResourcePersons_value, resources.resPlaceHolderHint, xmsf))); + + } + + /** + * Initializes a template.<br/> + * This method does the following tasks:<br/> + * Get a Time and Date format for the document, and retrieve the null date of the document (which is + * document-specific).<br/> + * Initializes the Items Cache map. + * Analyses the document:<br/> + * -find all "fille-ins" (apear as >xxx< in the document). + * -analyze all items sections (and the tables in them). + * -locate the titles and actualize them + * -analyze the topics table + */ + private void initialize() + { + /* + * Get the default locale of the document, and create the date and time formatters. + */ + XMultiServiceFactory docMSF = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, document); + try + { + Object defaults = docMSF.createInstance("com.sun.star.text.Defaults"); + Locale l = (Locale) Helper.getUnoStructValue(defaults, "CharLocale"); + + java.util.Locale jl = new java.util.Locale( + l.Language, l.Country, l.Variant); + + calendar = Calendar.getInstance(jl); + + XNumberFormatsSupplier nfs = (XNumberFormatsSupplier) UnoRuntime.queryInterface(XNumberFormatsSupplier.class, document); + Object formatSettings = nfs.getNumberFormatSettings(); + com.sun.star.util.Date date = (com.sun.star.util.Date) Helper.getUnoPropertyValue(formatSettings, "NullDate"); + + calendar.set(date.Year, date.Month - 1, date.Day); + + docNullTime = JavaTools.getTimeInMillis(calendar); + + dateFormat = NumberFormatter.getNumberFormatterKey(nfs, NumberFormatIndex.DATE_SYSTEM_LONG); + timeFormat = NumberFormatter.getNumberFormatterKey(nfs, NumberFormatIndex.TIME_HHMM); + + + dateFormatter = NumberFormatter.createNumberFormatter(xMSF, nfs); + timeFormatter = NumberFormatter.createNumberFormatter(xMSF, nfs); + } + catch (Exception ex) + { + ex.printStackTrace(); + throw new NullPointerException("Fatal Error: could not initialize locale or date/time formats."); + } + + /* + * get the document properties object. + */ + m_xDocProps = OfficeDocument.getDocumentProperties(document); + + initItemsCache(); + initializeItems(); + initializeTitles(); + initializeItemsSections(); + XMultiServiceFactory xMultiServiceFactory = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, document); + textSectionHandler = new TextSectionHandler(xMultiServiceFactory, (XTextDocument) UnoRuntime.queryInterface(XTextDocument.class, document)); + initializeTopics(); + _allItems.clear(); + _allItems = null; + } + + /** + * locates the titles (name, location, date, time) and saves a reference to thier Text ranges. + * + */ + private void initializeTitles() + { + XTextRange item = null; + + XMultiServiceFactory xmsf = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, document); + + for (int i = 0; i < _allItems.size(); i++) + { + item = (XTextRange) _allItems.get(i); + String text = item.getString().trim().toLowerCase(); + if (text.equals(FILLIN_TITLE)) + { + + teTitle = new PlaceholderTextElement(item, resources.resPlaceHolderTitle, resources.resPlaceHolderHint, xmsf); + trTitle = item; + _allItems.remove(i--); + } + else if (text.equals(FILLIN_DATE)) + { + teDate = new PlaceholderTextElement(item, resources.resPlaceHolderDate, resources.resPlaceHolderHint, xmsf); + trDate = item; + _allItems.remove(i--); + } + else if (text.equals(FILLIN_TIME)) + { + teTime = new PlaceholderTextElement(item, resources.resPlaceHolderTime, resources.resPlaceHolderHint, xmsf); + trTime = item; + _allItems.remove(i--); + } + else if (text.equals(FILLIN_LOCATION)) + { + teLocation = new PlaceholderTextElement(item, resources.resPlaceHolderLocation, resources.resPlaceHolderHint, xmsf); + trLocation = item; + _allItems.remove(i--); + } + } + } + + private void initializeTopics() + { + topics = new Topics(); + } + + private void initializeItems() + { + _allItems = searchFillInItems(); + } + + /** + * searches the document for items in the format ">*<" + * @return a vector containing the XTextRanges of the found items + */ + private List searchFillInItems() + { + try + { + XSearchable xSearchable = (XSearchable) UnoRuntime.queryInterface(XSearchable.class, document); + XSearchDescriptor sd = xSearchable.createSearchDescriptor(); + sd.setSearchString("<[^>]+>"); + sd.setPropertyValue("SearchRegularExpression", Boolean.TRUE); + sd.setPropertyValue("SearchWords", Boolean.TRUE); + + XIndexAccess ia = xSearchable.findAll(sd); + + List l = new Vector(ia.getCount()); + for (int i = 0; i < ia.getCount(); i++) + { + try + { + l.add((XTextRange) UnoRuntime.queryInterface(XTextRange.class, ia.getByIndex(i))); + } + catch (Exception ex) + { + System.err.println("Nonfatal Error in finding fillins."); + } + } + return l; + } + catch (Exception ex) + { + ex.printStackTrace(); + throw new IllegalArgumentException("Fatal Error: Loading template failed: searching fillins failed"); + } + } + + /** + * analyze the item sections in the template. delegates the analyze of each table to the + * ItemsTable class. + */ + private void initializeItemsSections() + { + String[] sections = getSections(document, TemplateConsts.SECTION_ITEMS); + + // for each section - there is a table... + itemsTables = new ItemsTable[sections.length]; + + for (int i = 0; i < itemsTables.length; i++) + { + try + { + itemsTables[i] = new ItemsTable(getSection(sections[i]), getTable(sections[i])); + } + catch (Exception ex) + { + ex.printStackTrace(); + throw new IllegalArgumentException("Fatal Error while initialilzing Template: items table in section " + sections[i]); + } + } + + } + + private String[] getSections(Object document, String s) + { + XTextSectionsSupplier xTextSectionsSupplier = (XTextSectionsSupplier) UnoRuntime.queryInterface(XTextSectionsSupplier.class, document); + String[] allSections = xTextSectionsSupplier.getTextSections().getElementNames(); + return getNamesWhichStartWith(allSections, s); + } + + Object getSection(String name) throws NoSuchElementException, WrappedTargetException + { + XTextSectionsSupplier xTextSectionsSupplier = (XTextSectionsSupplier) UnoRuntime.queryInterface(XTextSectionsSupplier.class, document); + return ((Any) (xTextSectionsSupplier.getTextSections().getByName(name))).getObject(); + } + + Object getTable(String name) throws NoSuchElementException, WrappedTargetException + { + XTextTablesSupplier xTextTablesSupplier = (XTextTablesSupplier) UnoRuntime.queryInterface(XTextTablesSupplier.class, document); + return ((Any) xTextTablesSupplier.getTextTables().getByName(name)).getObject(); + } + + /** + * implementation of DataAware.Listener, is + * called when title/date/time or location are + * changed. + */ + public synchronized void eventPerformed(Object param) + { + TextEvent te = (TextEvent) param; + String controlName = (String) Helper.getUnoPropertyValue( + UnoDialog2.getModel(te.Source), + "Name"); + redrawTitle(controlName); + + } + + private synchronized void redrawTitle(String controlName) + { + if (controlName.equals("txtTitle")) + { + writeTitle(teTitle, trTitle, agenda.cp_Title); + } + else if (controlName.equals("txtDate")) + { + writeTitle(teDate, trDate, getDateString(agenda.cp_Date)); + } + else if (controlName.equals("txtTime")) + { + writeTitle(teTime, trTime, getTimeString(agenda.cp_Time)); + } + else if (controlName.equals("cbLocation")) + { + writeTitle(teLocation, trLocation, agenda.cp_Location); + } + else + { + throw new IllegalArgumentException("No such title control..."); + } + } + + private void writeTitle(TextElement te, XTextRange tr, String text) + { + te.text = (text == null ? "" : text); + te.write(tr); + } + private static long DAY_IN_MILLIS = (24 * 60 * 60 * 1000); + + private String getDateString(String d) + { + if (d == null || d.equals("")) + { + return ""; + } + int date = new Integer(d).intValue(); + calendar.clear(); + calendar.set(date / 10000, + (date % 10000) / 100 - 1, + date % 100); + + long date1 = JavaTools.getTimeInMillis(calendar); + /* + * docNullTime and date1 are in millis, but + * I need a day... + */ + double daysDiff = (date1 - docNullTime) / DAY_IN_MILLIS + 1; + + return dateFormatter.convertNumberToString(dateFormat, daysDiff); + } + + private String getTimeString(String s) + { + if (s == null || s.equals("")) + { + return ""; + } + int time = new Integer(s).intValue(); + + double t = ((double) (time / 1000000) / 24) + ((double) ((time % 1000000) / 1000) / (24 * 60)); + return timeFormatter.convertNumberToString(timeFormat, t); + } + + /* ******************************************* + * F I N I S H + *********************************************/ + /** the user clicked finish **/ + public synchronized void finish(List topics) + { + createMinutes(topics); + deleteHiddenSections(); + textSectionHandler.removeAllTextSections(); + } + + /** + * hidden sections exist when an item's section is hidden because the + * user specified not to display any items which it contains. + * When finishing the wizard removes this sections entireley from the document. + */ + private void deleteHiddenSections() + { + XTextSectionsSupplier xTextSectionsSupplier = (XTextSectionsSupplier) UnoRuntime.queryInterface(XTextSectionsSupplier.class, document); + String[] allSections = xTextSectionsSupplier.getTextSections().getElementNames(); + try + { + for (int i = 0; i < allSections.length; i++) + { + Object section = getSection(allSections[i]); + //Try3.showProps(section); + boolean visible = ((Boolean) Helper.getUnoPropertyValue(section, "IsVisible")).booleanValue(); + if (!visible) + { + ((XTextContent) UnoRuntime.queryInterface(XTextContent.class, section)).getAnchor().setString(""); + } + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + /** + * create the minutes for the given topics or remove the minutes section from the document. + * If no topics are supplied, or the user + * specified not to create minuts, the minutes section will be removed, + * @param topicsData supplies PropertyValue arrays containing the values for the topics. + */ + public synchronized void createMinutes(List topicsData) + { + + // if the minutes section should be removed (the + // user did not check "create minutes") + if (!agenda.cp_IncludeMinutes || (topicsData.size() <= 1)) + { + try + { + Object minutesAllSection = getSection(SECTION_MINUTES_ALL); + XTextSection xTextSection = (XTextSection) UnoRuntime.queryInterface(XTextSection.class, minutesAllSection); + xTextSection.getAnchor().setString(""); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + // the user checked "create minutes" + else + { + try + { + String itemText; + XTextRange item; + int topicStartTime = 0; + try + { + topicStartTime = new Integer(agenda.cp_Time).intValue(); + } + catch (Exception ex) + { + } + + String time; + + // first I replace the minutes titles... + List items = searchFillInItems(); + for (int itemIndex = 0; itemIndex < items.size(); itemIndex++) + { + item = (XTextRange) items.get(itemIndex); + itemText = item.getString().trim().toLowerCase(); + + if (itemText.equals(FILLIN_MINUTES_TITLE)) + { + fillMinutesItem(item, agenda.cp_Title, resources.resPlaceHolderTitle); + } + else if (itemText.equals(FILLIN_MINUTES_LOCATION)) + { + fillMinutesItem(item, agenda.cp_Location, resources.resPlaceHolderLocation); + } + else if (itemText.equals(FILLIN_MINUTES_DATE)) + { + fillMinutesItem(item, getDateString(agenda.cp_Date), resources.resPlaceHolderDate); + } + else if (itemText.equals(FILLIN_MINUTES_TIME)) + { + fillMinutesItem(item, getTimeString(agenda.cp_Time), resources.resPlaceHolderTime); + } + } + + items.clear(); + + /* + * now add minutes for each topic. + * The template contains *one* minutes section, so + * we first use the one available, and then add a new one... + * + * topics data has *always* an empty topic at the end... + */ + for (int i = 0; i < topicsData.size() - 1; i++) + { + PropertyValue[] topic = (PropertyValue[]) topicsData.get(i); + + items = searchFillInItems(); + for (int itemIndex = 0; itemIndex < items.size(); itemIndex++) + { + item = (XTextRange) items.get(itemIndex); + itemText = item.getString().trim().toLowerCase(); + + if (itemText.equals(FILLIN_MINUTE_NUM)) + { + fillMinutesItem(item, topic[0].Value, ""); + } + else if (itemText.equals(FILLIN_MINUTE_TOPIC)) + { + fillMinutesItem(item, topic[1].Value, ""); + } + else if (itemText.equals(FILLIN_MINUTE_RESPONSIBLE)) + { + fillMinutesItem(item, topic[2].Value, ""); + } + else if (itemText.equals(FILLIN_MINUTE_TIME)) + { + int topicTime = 0; + + try + { + topicTime = (new Integer((String) topic[3].Value)).intValue(); + } + catch (Exception ex) + { + } + // if the topic has no time, we do not display any time here. + if (topicTime == 0 || topicStartTime == 0) + { + time = (String) topic[3].Value; + } + else + { + time = getTimeString(String.valueOf(topicStartTime)) + " - "; + topicStartTime += topicTime * 1000; + time += getTimeString(String.valueOf(topicStartTime)); + } + fillMinutesItem(item, time, ""); + } + } + + textSectionHandler.removeTextSectionbyName(SECTION_MINUTES); + + // after the last section we do not insert a new one. + if (i < topicsData.size() - 2) + { + textSectionHandler.insertTextSection(SECTION_MINUTES, template, false); + } + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + } + + /** + * given a text range and a text, fills the given + * text range with the given text. + * If the given text is empty, uses a placeholder with the giveb placeholder text. + * @param range text range to fill + * @param text the text to fill to the text range object. + * @param placeholder the placeholder text to use, if the text argument is empty (null or "") + */ + private void fillMinutesItem(XTextRange range, Object text, String placeholder) + { + String paraStyle = (String) Helper.getUnoPropertyValue(range, "ParaStyleName"); + range.setString((String) text); + Helper.setUnoPropertyValue(range, "ParaStyleName", paraStyle); + if (text == null || text.equals("")) + { + if (placeholder != null && !placeholder.equals("")) + { + XTextContent placeHolder = createPlaceHolder(docMSF, placeholder, resources.resPlaceHolderHint); + try + { + range.getStart().getText().insertTextContent(range.getStart(), placeHolder, true); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + } + } + + /** + * creates a placeholder field with the given text and given hint. + * @param xmsf service factory + * @param ph place holder text + * @param hint hint text + * @return the place holder field. + */ + public static XTextContent createPlaceHolder(XMultiServiceFactory xmsf, String ph, String hint) + { + Object placeHolder; + try + { + placeHolder = xmsf.createInstance("com.sun.star.text.TextField.JumpEdit"); + } + catch (Exception ex) + { + ex.printStackTrace(); + return null; + } + Helper.setUnoPropertyValue(placeHolder, "PlaceHolder", ph); + Helper.setUnoPropertyValue(placeHolder, "Hint", hint); + Helper.setUnoPropertyValue(placeHolder, "PlaceHolderType", new Short(PlaceholderType.TEXT)); + return (XTextContent) UnoRuntime.queryInterface(XTextContent.class, placeHolder); + + } + + /* + * $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + * ================================= + * The ItemTable class + * ================================= + * $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + */ + public class ItemsTable + { + + Object table; + Object section; + /** + * the items in the table. + */ + List items = new Vector(6); + + public ItemsTable(Object section_, Object table_) + { + + table = table_; + section = section_; + + AgendaItem ai; + XTextRange item; + String iText; + + /* go through all <*> items in the document + * and each one if it is in this table. + * If they are, register them to belong here, notice their order + * and remove them from the list of all <*> items, so the next + * search will be faster. + */ + for (int i = 0; i < _allItems.size(); i++) + { + item = (XTextRange) _allItems.get(i); + Object t = Helper.getUnoPropertyValue(item, "TextTable"); + if ((t instanceof Any) && ((Any) t).getObject() == table) + { + iText = item.getString().toLowerCase().trim(); + ai = (AgendaItem) itemsCache.get(item.getString().toLowerCase().trim()); + if (ai != null) + { + items.add(ai); + _allItems.remove(i--); + itemsMap.put(iText, this); + } + } + } + + } + + /** + * link the section to the template. this will restore the original table + * with all the items.<br/> + * then break the link, to make the section editable.<br/> + * then, starting at cell one, write all items that should be visible. + * then clear the rest and remove obsolete rows. + * If no items are visible, hide the section. + * @param dummy we need a param to make this an Implementation of AgendaElement. + * @throws Exception + */ + public synchronized void write(Object dummy) throws Exception + { + synchronized(this) + { + String name = getName(section); + + // link and unlink the section to the template. + textSectionHandler.linkSectiontoTemplate(section, template, name); + textSectionHandler.breakLinkOfTextSection(section); + + // we need to get a new instance after linking. + table = getTable(name); + section = getSection(name); + + XTextTable xTextTable = (XTextTable) UnoRuntime.queryInterface(XTextTable.class, table); + XTextTableCursor cursor = xTextTable.createCursorByCellName("A1"); + AgendaItem ai; + // should this section be visible? + boolean visible = false; + + // write items + // =========== + String cellName = ""; + + /* now go through all items that belong to this + * table. Check each one agains the model. If it should + * be display, call it's write method. + * All items are of type AgendaItem which means they write + * two cells to the table: a title (text) and a placeholder. + * see AgendaItem class below. + */ + for (int i = 0; i < items.size(); i++) + { + ai = (AgendaItem) items.get(i); + if (isShowItem(ai.name)) + { + visible = true; + ai.table = table; + ai.write(cursor); + // I store the cell name which was last written... + cellName = cursor.getRangeName(); + + cursor.goRight((short) 1, false); + + } + } + + Helper.setUnoPropertyValue(section, "IsVisible", visible ? Boolean.TRUE : Boolean.FALSE); + if (!visible) + { + return; + /* remove obsolete rows + * ==================== + * if the cell that was last written is the current cell, + * it means this is the end of the table, so we end here. + * (because after getting the cellName above, I call the goRight method. + * If it did not go right, it means its the last cell. + */ + } + if (cellName.equals(cursor.getRangeName())) + { + return; + /* + * if not, we continue and clear all cells until we are at the end of the row. + */ + } + Object cell; + while ((!cellName.equals(cursor.getRangeName()) && (!cursor.getRangeName().startsWith("A")))) + { + cell = xTextTable.getCellByName(cursor.getRangeName()); + ((XTextRange) UnoRuntime.queryInterface(XTextRange.class, cell)).setString(""); + cellName = cursor.getRangeName(); + cursor.goRight((short) 1, false); + } + + /* + * again: if we are at the end of the table, end here. + */ + if (cellName.equals(cursor.getRangeName())) + { + return; + } + int rowIndex = getRowIndex(cursor); + int rowsCount = getRowCount((XTextTable) UnoRuntime.queryInterface(XTextTable.class, table)); + + /* now before deleteing i move the cursor up so it + * does not disappear, because it will crash office. + */ + cursor.gotoStart(false); + + if (rowsCount >= rowIndex) + { + removeTableRows(table, rowIndex - 1, (rowsCount - rowIndex) + 1); + } + } + } + } + + /* + * $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + * ================================= + * The Topics class + * ================================= + * $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + */ + /** + * This class handles the preview of the topics table. + * You can call it the controller of the topics table. + * It differs from ItemsTable in that it has no data model - + * the update is done programttically.<br/> + * <br/> + * The decision to make this class a class by its own + * was done out of logic reasons and not design/functionality reasons, + * since there is anyway only one instance of this class at runtime + * it could have also be implemented in the AgendaTemplate class + * but for clarity and separation I decided to make a sub class for it. + * + * @author rp143992 + */ + public class Topics + { + + /** + * the topics table + */ + XTextTable table; + /** + * A List of Cell Formatters for the first row. + */ + List firstRowFormat = new Vector(); + /** + * A List of Cell Formatters for the last row. + * (will contain them in reverse order) + */ + List lastRowFormat = new Vector(); + /** + * the format of the cell of each topic cell. + */ + List topicCellFormats = new Vector(); + /** + * for each topic cell there is + * a member in this vector + */ + List topicCells = new Vector(); + int rowsPerTopic; + /** + * fields which hold the number of the + * fillins in the cells vectors. + */ + int numCell = -1; + int topicCell = -1; + int responsibleCell = -1; + int timeCell = -1; + /** + * this is a list which traces which topics were written to the document + * and which not. When a cell needs to be actualized, it is checked that the + * whole topic is already present in the document, using this vector. + * The vector contains nulls for topics which were not written, and + * empty strings for topics which were written (though any other + * object would also do - i check only if it is a null or not...); + */ + List writtenTopics = new Vector(); + + /** + * Analyze the structure of the Topics table. + * The structure Must be as follows:<br> + * -One Header Row. <br> + * -arbitrary number of rows per topic <br> + * -arbitrary content in the topics row <br> + * -only soft formatting will be restored. <br> + * -the topic rows must repeat three times. <br> + * -in the topics rows, placeholders for number, topic, responsible, and duration + * must be placed.<br> + * <br> + * A word about table format: to reconstruct the format of the + * table we hold to the following formats: first row (header), topic, and last row. + * We hold the format of the last row, because one might wish to give it + * a special format, other than the one on the bottom of each topic. + * The left and right borders of the whole table are, on the other side, + * part of the topics rows format, and need not be preserved seperateley. + */ + public Topics() + { + Object t; + + Map topicItems = new Hashtable(4); + + // This is the topics table. say hallo :-) + try + { + t = getTable(SECTION_TOPICS); + } + catch (Exception ex) + { + ex.printStackTrace(); + throw new IllegalArgumentException("Fatal error while loading template: table " + SECTION_TOPICS + " could not load."); + } + + // and this is the XTable. + table = ((XTextTable) UnoRuntime.queryInterface(XTextTable.class, t)); + + /* first I store all <*> ranges + * which are in the topics table. + * I store each <*> range in this - the key + * is the cell it is in. Later when analyzing the topic, + * cell by cell, I check in this map to know + * if a cell contains a <*> or not. + */ + Hashtable items = new Hashtable(); + + XTextRange item; + Object cell; + for (int i = 0; i < _allItems.size(); i++) + { + item = (XTextRange) _allItems.get(i); + t = Helper.getUnoPropertyValue(item, "TextTable"); + if ((t instanceof Any) && ((Any) t).getObject() == table) + { + cell = Helper.getUnoPropertyValue(item, "Cell"); + items.put(((Any) cell).getObject(), item); + } + } + + /* + * in the topics table, there are always one + * title row and three topics defined. + * So no mutter how many rows a topic takes - we + * can restore its structure and format. + */ + int rows = getRowCount(table); + + rowsPerTopic = (rows - 1) / 3; + + String firstCell = "A" + (1 + rowsPerTopic + 1); + String afterLastCell = "A" + (1 + (rowsPerTopic * 2) + 1); + + // go to the first row of the 2. topic + XTextTableCursor cursor = table.createCursorByCellName(firstCell); + XTextRange range; + + // analyze the structure of the topic rows. + while (!cursor.getRangeName().equals(afterLastCell)) + { + cell = table.getCellByName(cursor.getRangeName()); + XTextRange xTextRange = (XTextRange) UnoRuntime.queryInterface(XTextRange.class, cell); + // first I store the content and para style of the cell + AgendaElement ae = new TextElement(xTextRange); + // if the cell contains a relevant <...> + // i add the text element to the hash, + // so it's text can be updated later. + range = (XTextRange) items.get(cell); + if (range != null) + { + topicItems.put(xTextRange.getString().toLowerCase().trim(), ae); + } + + topicCells.add(ae); + + // and store the format of the cell. + topicCellFormats.add(new TableCellFormatter(table.getCellByName(cursor.getRangeName()))); + + // goto next cell. + cursor.goRight((short) 1, false); + } + + /* + * now - in which cell is every fillin? + */ + numCell = topicCells.indexOf(topicItems.get(FILLIN_TOPIC_NUMBER)); + topicCell = topicCells.indexOf(topicItems.get(FILLIN_TOPIC_TOPIC)); + responsibleCell = topicCells.indexOf(topicItems.get(FILLIN_TOPIC_RESPONSIBLE)); + timeCell = topicCells.indexOf(topicItems.get(FILLIN_TOPIC_TIME)); + + + + /* now that we know how the topics look like, + * we get the format of the first and last rows. + */ + + // format of first row + cursor.gotoStart(false); + do + { + firstRowFormat.add(new TableCellFormatter(table.getCellByName(cursor.getRangeName()))); + cursor.goRight((short) 1, false); + } + while (!cursor.getRangeName().startsWith("A")); + + // format of the last row + cursor.gotoEnd(false); + while (!cursor.getRangeName().startsWith("A")) + { + lastRowFormat.add(new TableCellFormatter(table.getCellByName(cursor.getRangeName()))); + cursor.goLeft((short) 1, false); + } + // we missed the A cell - so we have to add it also.. + lastRowFormat.add(new TableCellFormatter(table.getCellByName(cursor.getRangeName()))); + + removeTableRows(table, 1 + rowsPerTopic, rows - rowsPerTopic - 1); + + } + + /** + * @param topic the topic number to write + * @param data the data of the topic. + * @return the number of rows that have been added + * to the table. 0 or a negative number: no rows added. + */ + private int write2(int topic, PropertyValue[] data) throws Exception + { + while (topic >= writtenTopics.size()) + { + writtenTopics.add(null); + } + writtenTopics.set(topic, ""); + + // make sure threr are enough rows for me... + int rows = getRowCount(table); + int reqRows = 1 + (topic + 1) * rowsPerTopic; + int firstRow = reqRows - rowsPerTopic + 1; + int diff = reqRows - rows; + if (diff > 0) + { + insertTableRows(table, rows, diff); // set the item's text... + } + setItemText(numCell, data[0].Value); + setItemText(topicCell, data[1].Value); + setItemText(responsibleCell, data[2].Value); + setItemText(timeCell, data[3].Value); + + // now write ! + XTextTableCursor cursor = table.createCursorByCellName("A" + firstRow); + + for (int i = 0; i < topicCells.size(); i++) + { + ((AgendaElement) topicCells.get(i)).write(table.getCellByName(cursor.getRangeName())); + cursor.goRight((short) 1, false); + } + + // now format ! + cursor.gotoCellByName("A" + firstRow, false); + + formatTable(cursor, topicCellFormats, false); + + return diff; + + } + + /** + * check if the topic with the given index is written to the table. + * @param topic the topic number (0 base) + * @return true if the topic is already written to the table. False if not. + * (false would mean new rows must be added to the table in order to + * be able to write this topic). + */ + private boolean isWritten(int topic) + { + return (writtenTopics.size() > topic && writtenTopics.get(topic) != null); + } + + /** + * rewrites a single cell containing. + * This is used in order to refresh the topic/responsible/duration data in the + * preview document, in response to a change in the gui (by the user). + * Since the structure of the topics table is flexible, we don't reference a cell + * number. Rather, we use "what" argument to specify which cell should be redrawn. + * The Topics object, which analyzed the structure of the topics table appon + * initialization, refreshes the approperiate cell. + * @param topic index of the topic (0 based). + * @param what 0 for num, 1 for topic, 2 for responsible, 3 for duration + * @param data the row's data. + * @throws Exception if something goes wrong (thow nothing should) + */ + public void writeCell(int topic, int what, PropertyValue[] data) throws Exception + { + // if the whole row should be written... + if (!isWritten(topic)) + { + write(topic, data); + // write only the "what" cell. + } + else + { + // calculate the table row. + int firstRow = 1 + (topic * rowsPerTopic) + 1; + // go to the first cell of this topic. + XTextTableCursor cursor = table.createCursorByCellName("A" + firstRow); + + TextElement te = null; + int cursorMoves = 0; + + switch (what) + { + case 0: + te = setItemText(numCell, data[0].Value); + cursorMoves = numCell; + break; + case 1: + te = setItemText(topicCell, data[1].Value); + cursorMoves = topicCell; + break; + case 2: + te = setItemText(responsibleCell, data[2].Value); + cursorMoves = responsibleCell; + break; + case 3: + te = setItemText(timeCell, data[3].Value); + cursorMoves = timeCell; + break; + } + // move the cursor to the needed cell... + cursor.goRight((short) cursorMoves, false); + XCell xc = table.getCellByName(cursor.getRangeName()); + // and write it ! + te.write(xc); + ((TableCellFormatter) topicCellFormats.get(cursorMoves)).format(xc); + + } + } + + /** + * writes the given topic. + * if the first topic was involved, reformat the + * first row. + * If any rows were added to the table, reformat + * the last row. + * @param topic the index of the topic to write. + * @param data the topic's data. (see TopicsControl + * for explanation about the topics data model) + * @throws Exception if something goes wrong (though nothing should). + */ + public void write(int topic, PropertyValue[] data) throws Exception + { + int diff = write2(topic, data); + /* if the first topic has been written, + * one needs to reformat the first row. + */ + if (topic == 0) + { + formatFirstRow(); + } + /* + * if any rows were added, one needs to format + * the whole table again. + */ + if (diff > 0) + { + formatLastRow(); + } + } + + /** + * Writes all the topics to thetopics table. + * @param topicsData a List containing all Topic's Data. + */ + public void writeAll(List topicsData) + { + try + { + for (int i = 0; i < topicsData.size() - 1; i++) + { + write2(i, (PropertyValue[]) topicsData.get(i)); + } + formatLastRow(); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + /** + * removes obsolete rows, reducing the + * topics table to the given number of topics. + * Note this method does only reducing - if + * the number of topics given is greater than the + * number of actuall topics it does *not* add + * new rows ! + * Note also that the first topic will never be removed. + * If the table contains no topics, the whole section will + * be removed uppon finishing. + * The reason for that is a "table-design" one: the first topic is + * maintained in order to be able to add rows with a design of this topic, + * and not of the header row. + * @param topics the number of topics the table should contain. + * @throws Exception + */ + public void reduceDocumentTo(int topics) throws Exception + { + // we never remove the first topic... + if (topics <= 0) + { + topics = 1; + } + XTableRows tableRows = table.getRows(); + int targetNumOfRows = topics * rowsPerTopic + 1; + if (tableRows.getCount() > targetNumOfRows) + { + tableRows.removeByIndex(targetNumOfRows, tableRows.getCount() - targetNumOfRows); + } + formatLastRow(); + while (writtenTopics.size() > topics) + { + writtenTopics.remove(topics); + } + } + + /** + * reapply the format of the first (header) row. + */ + private void formatFirstRow() + { + XTextTableCursor cursor = table.createCursorByCellName("A1"); + formatTable(cursor, firstRowFormat, false); + } + + /** + * reaply the format of the last row. + */ + private void formatLastRow() + { + XTextTableCursor cursor = table.createCursorByCellName("A1"); + cursor.gotoEnd(false); + formatTable(cursor, lastRowFormat, true); + } + + /** + * returns a text element for the given cell, + * which will write the given text. + * @param cell the topics cell number. + * @param value the value to write. + * @return a TextElement object which will write the given value + * to the given cell. + */ + private TextElement setItemText(int cell, Object value) + { + if (cell >= 0) + { + TextElement te = ((TextElement) topicCells.get(cell)); + if (te != null) + { + te.text = value.toString(); + } + return te; + } + return null; + } + + /** + * formats a series of cells from the given one, + * using the given List of TableCellFormatter objects, + * in the given order. + * This method is used to format the first (header) and the last + * rows of the table. + * @param cursor a table cursor, pointing to the start cell to format + * @param formats a List containing TableCellFormatter objects. Each will format one cell in the direction specified. + * @param reverse if true the cursor will move left, formatting in reverse order (used for the last row). + */ + private void formatTable(XTextTableCursor cursor, List formats, boolean reverse) + { + for (int i = 0; i < formats.size(); i++) + { + ((TableCellFormatter) formats.get(i)).format(table.getCellByName(cursor.getRangeName())); + if (reverse) + { + cursor.goLeft((short) 1, false); + } + else + { + cursor.goRight((short) 1, false); + } + } + } + } + + + /* + * ================================= + * Here are some static help methods + * ================================= + */ + public static String[] getNamesWhichStartWith(String[] allNames, String prefix) + { + Vector v = new Vector(); + for (int i = 0; i < allNames.length; i++) + { + if (allNames[i].startsWith(prefix)) + { + v.add(allNames[i]); + } + } + String[] s = new String[v.size()]; + System.arraycopy(v.toArray(), 0, s, 0, s.length); + return s; + } + + /** + * Convenience method, costs the given object to an XNamed, and returnes its name. + * @param obj an XNamed object. + * @return the name of the given object. + */ + public static String getName(Object obj) + { + return ((XNamed) UnoRuntime.queryInterface(XNamed.class, obj)).getName(); + } + + /** + * convenience method, for removing a number of cells from a table. + * @param table + * @param start + * @param count + */ + public static void removeTableRows(Object table, int start, int count) + { + XTableRows rows = ((XTextTable) UnoRuntime.queryInterface(XTextTable.class, table)).getRows(); + rows.removeByIndex(start, count); + } + + /** + * Convenience method for inserting some cells into a table. + * @param table + * @param start + * @param count + */ + public static void insertTableRows(Object table, int start, int count) + { + XTableRows rows = ((XTextTable) UnoRuntime.queryInterface(XTextTable.class, table)).getRows(); + rows.insertByIndex(start, count); + } + + /** + * returns the row index for this cursor, assuming + * the cursor points to a single cell. + * @param cursor + * @return the row index in which the cursor is. + */ + public static int getRowIndex(XTextTableCursor cursor) + { + return getRowIndex(cursor.getRangeName()); + } + + /** + * returns the row index for this cell name. + * @param cellName + * @return the row index for this cell name. + */ + public static int getRowIndex(String cellName) + { + return Integer.parseInt(cellName.substring(1)); + } + + /** + * returns the rows count of this table, assuming + * there is no vertical merged cells. + * @param table + * @return the rows count of the given table. + */ + public static int getRowCount(XTextTable table) + { + String[] cells = table.getCellNames(); + return getRowIndex(cells[cells.length - 1]); + } +} + +/* + * =========================================================================================== + * + * End of AgendaTempalte class + * + * =========================================================================================== + * + */ +/* + * ================================= + * The AgendaElement interface + * ================================= + */ +/** + * Interface that is used for writing content to a Uno Text / TextRange + * @author rp143992 + * + */ +interface AgendaElement +{ + + void write(Object any) throws Exception; +} + + +/* + * ================================= + * The ParaStyled class + * ================================= + */ +/** + * Basic implementation of the AgendaElement interface - + * writes nothing, but applies a ParaStyle to the given XText/XTextRange + * @author rp143992 + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +class ParaStyled implements AgendaElement +{ + + String paraStyle; + + ParaStyled(String paraStyle_) + { + paraStyle = paraStyle_; + } + + void format(Object textRange) + { + XText o; + o = ((XText) UnoRuntime.queryInterface(XText.class, textRange)); + if (o == null) + { + o = ((XTextRange) UnoRuntime.queryInterface(XTextRange.class, textRange)).getText(); + } + XTextRange xtr = (XTextRange) UnoRuntime.queryInterface(XTextRange.class, textRange); + XTextCursor cursor = o.createTextCursorByRange(xtr); + + Helper.setUnoPropertyValue(cursor, "ParaStyleName", paraStyle); + } + + public void write(Object textRange) + { + format(textRange); + } +} + +/* + * ================================= + * The TextElement class + * ================================= + */ +/** + * A basic implementation of AgendaElement: + * writes a String to the given XText/XTextRange, and applies + * a ParaStyle to it (using the parent class). + * @author rp143992 + */ +class TextElement extends ParaStyled +{ + + String text; + + TextElement(XTextRange range) + { + this(range.getString(), (String) Helper.getUnoPropertyValue(range.getStart(), "ParaStyleName")); + } + + TextElement(String text_, String paraStyle_) + { + super(paraStyle_); + text = text_; + } + + public void write(Object textRange) + { + ((XTextRange) UnoRuntime.queryInterface(XTextRange.class, textRange)).setString(text); + if (!text.equals("")) + { + super.write(textRange); + } + } +} + +/** + * A Text element which, if the text to write is empty (null or "") + * inserts a placeholder instead. + * @author rp143992 + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +class PlaceholderTextElement extends TextElement +{ + + String hint; + String placeHolderText; + XMultiServiceFactory xmsf; + + PlaceholderTextElement(XTextRange textRange, String placeHolderText_, String hint_, XMultiServiceFactory xmsf_) + { + super(textRange); + placeHolderText = placeHolderText_; + hint = hint_; + xmsf = xmsf_; + } + + PlaceholderTextElement(String text, String paraStyle, String placeHolderText_, String hint_, XMultiServiceFactory xmsf_) + { + super(text, paraStyle); + placeHolderText = placeHolderText_; + hint = hint_; + xmsf = xmsf_; + } + + public void write(Object textRange) + { + super.write(textRange); + if (text == null || text.equals("")) + { + XTextRange xTextRange = (XTextRange) UnoRuntime.queryInterface(XTextRange.class, textRange); + try + { + XTextContent xTextContent = AgendaTemplate.createPlaceHolder(xmsf, placeHolderText, hint); + xTextRange.getText().insertTextContent(xTextRange.getStart(), xTextContent, true); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + } +} + +/* + * ================================= + * The PlaceHolder class + * ================================= + */ +/** + * An Agenda element which writes no text, but inserts a placeholder, and formats + * it using a ParaStyleName. + * @author rp143992 + * + */ +class PlaceholderElement extends ParaStyled +{ + + String hint; + String placeHolderText; + XMultiServiceFactory xmsf; + + PlaceholderElement(String paraStyle, String placeHolderText_, String hint_, XMultiServiceFactory xmsf_) + { + super(paraStyle); + placeHolderText = placeHolderText_; + hint = hint_; + xmsf = xmsf_; + } + + public void write(Object textRange) + { + XTextRange xTextRange = (XTextRange) UnoRuntime.queryInterface(XTextRange.class, textRange); + try + { + XTextContent xTextContent = AgendaTemplate.createPlaceHolder(xmsf, placeHolderText, hint); + xTextRange.getText().insertTextContent(xTextRange.getStart(), xTextContent, true); + super.write(textRange); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } +} + + +/* + * ================================= + * The AgendaItem class + * ================================= + */ +/** + * An implementation of AgendaElement which + * gets as a parameter a table cursor, and writes + * a text to the cell marked by this table cursor, and + * a place holder to the next cell. + * @author rp143992 + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +class AgendaItem implements AgendaElement +{ + + TextElement textElement; + AgendaElement field; + public Object table; + String name; + + AgendaItem(String name_, TextElement te, AgendaElement f) + { + name = name_; + field = f; + textElement = te; + } + + public void write(Object tableCursor) throws Exception + { + XTextTableCursor xTextTableCursor = (XTextTableCursor) UnoRuntime.queryInterface(XTextTableCursor.class, tableCursor); + XTextTable xTextTable = (XTextTable) UnoRuntime.queryInterface(XTextTable.class, table); + + String cellname = xTextTableCursor.getRangeName(); + Object cell = xTextTable.getCellByName(cellname); + + textElement.write(cell); + + xTextTableCursor.goRight((short) 1, false); + + //second field is actually always null... + // this is a preparation for adding placeholders. + if (field != null) + { + field.write(xTextTable.getCellByName(xTextTableCursor.getRangeName())); + } + } +} + +/* + * ================================= + * The TableCellFormatter class + * ================================= + */ +/** + * reads/write a table cell format from/to a table cell or a group of cells. + * + */ +class TableCellFormatter +{ + + static String[] properties = new String[] + { + "BackColor", + "BackTransparent", + "BorderDistance", + "BottomBorder", + "BottomBorderDistance", + "LeftBorder", + "LeftBorderDistance", + "RightBorder", + "RightBorderDistance", + "TopBorder", + "TopBorderDistance" + }; + private Object[] values = new Object[properties.length]; + + public TableCellFormatter(Object tableCell) + { + for (int i = 0; i < properties.length; i++) + { + values[i] = Helper.getUnoPropertyValue(tableCell, properties[i]); + } + } + + public void format(Object tableCell) + { + Helper.setUnoPropertyValues(tableCell, properties, values); + } +} + + + + diff --git a/wizards/com/sun/star/wizards/agenda/AgendaWizardDialog.java b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialog.java new file mode 100644 index 000000000000..55119ea28325 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialog.java @@ -0,0 +1,384 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package com.sun.star.wizards.agenda; + +import com.sun.star.awt.FontDescriptor; +import com.sun.star.awt.XButton; +import com.sun.star.awt.XCheckBox; +import com.sun.star.awt.XControl; +import com.sun.star.awt.XDateField; +import com.sun.star.awt.XFixedText; +import com.sun.star.awt.XListBox; +import com.sun.star.awt.XRadioButton; +import com.sun.star.awt.XTextComponent; +import com.sun.star.awt.XTimeField; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.wizards.common.Helper; +import com.sun.star.wizards.ui.UIConsts; +import com.sun.star.wizards.ui.WizardDialog; + +/** + * This class is generated Automatically.... + * bla bla bla + */ +public abstract class AgendaWizardDialog extends WizardDialog implements AgendaWizardDialogConst, UIConsts { + //GUI Components as Class members. + XFixedText lblTitle1; + XCheckBox chkMinutes; + XFixedText lblHelp1; + XFixedText lblPageDesign; + XListBox listPageDesign; + //Image Control + XControl imgHelp1; + XControl imgHelp2; + XControl imgHelp3; + XControl imgHelp4; + XControl imgHelp6; + XFixedText lblTitle2; + XFixedText lblTime; + XFixedText lblTitle; + XFixedText lblLocation; + XTextComponent cbLocation; + XTimeField txtTime; + XTextComponent txtTitle; + XFixedText lblHelp2; + XFixedText lblDate; + XDateField txtDate; + XFixedText lblTitle3; + XCheckBox chkMeetingTitle; + XCheckBox chkRead; + XCheckBox chkBring; + XCheckBox chkNotes; + XFixedText lblHelp3; + XFixedText lblTitle5; + XCheckBox chkConvenedBy; + XCheckBox chkPresiding; + XCheckBox chkNoteTaker; + XCheckBox chkTimekeeper; + XCheckBox chkAttendees; + XCheckBox chkObservers; + XCheckBox chkResourcePersons; + XFixedText lblHelp4; + XFixedText lblTitle4; + XFixedText lblTopic; + XFixedText lblResponsible; + XFixedText lblDuration; + //XFixedText lblHelp5; + XTextComponent txtTemplateName; + XRadioButton optCreateAgenda; + XRadioButton optMakeChanges; + XFixedText lblProceed; + XFixedText lblTemplateName; + XFixedText lblTemplatePath; + XFixedText lblTitle6; + XTextComponent txtTemplatePath; + XButton btnTemplatePath; + XFixedText lblHelp6; + XFixedText lblHelpPg6; + XButton btnInsert; + XButton btnRemove; + XButton btnUp; + XButton btnDown; + + final private String IMGHELP1_HID = ""; + + + //Font Descriptors as Class members. + FontDescriptor fontDescriptor1 = new FontDescriptor(); + FontDescriptor fontDescriptor2 = new FontDescriptor(); + FontDescriptor fontDescriptor4 = new FontDescriptor(); + + //Resources Object + AgendaWizardDialogResources resources; + + private String[] PROPS_LIST = new String[] {"Dropdown", "Height", "HelpURL", "PositionX", "PositionY", "Step", "TabIndex", "Width"}; + private String[] PROPS_LABEL_B = new String[] {"FontDescriptor", "Height", "Label", "MultiLine", "PositionX", "PositionY", "Step", "TabIndex", "Width"}; + private String[] PROPS_CHECK = new String[] {"Height", "HelpURL", "Label", "PositionX", "PositionY", "State", "Step", "TabIndex", "Width"}; + private String[] PROPS_BUTTON = new String[] {"Height", "HelpURL", "Label", "PositionX", "PositionY", "Step", "TabIndex", "Width"}; + private String[] PROPS_X = new String[] {"Height", "HelpURL", "PositionX", "PositionY", "Step", "TabIndex", "Width"}; + private String[] PROPS_TEXTAREA = new String[] {"Height", "Label", "MultiLine", "PositionX", "PositionY", "Step", "TabIndex", "Width"}; + private String[] PROPS_TEXT = new String[] {"Height", "Label", "PositionX", "PositionY", "Step", "TabIndex", "Width"}; + private String[] PROPS_IMAGE = new String[] {"Border", "Height", "HelpURL", "ImageURL", "PositionX", "PositionY", "ScaleImage", "Step", "TabIndex", "Width"}; + + private static final Short NO_BORDER = new Short((short)0); + + public AgendaWizardDialog(XMultiServiceFactory xmsf) { + super(xmsf,HID); + //Load Resources + resources = new AgendaWizardDialogResources(xmsf); + + //set dialog properties... + Helper.setUnoPropertyValues(xDialogModel, + new String[] { "Closeable","Height","Moveable","PositionX","PositionY","Step","TabIndex","Title","Width"}, + new Object[] { Boolean.TRUE,new Integer(210),Boolean.TRUE,new Integer(200),new Integer(52),INTEGERS[1],new Short((short)1),resources.resAgendaWizardDialog_title,new Integer(310)} + ); + + //Set member- FontDescriptors... + fontDescriptor1.Weight = 150; + fontDescriptor1.Underline = com.sun.star.awt.FontUnderline.SINGLE; + fontDescriptor2.Weight = 100; + fontDescriptor4.Weight = 150; + } + + //build components + public void buildStep1() { + lblTitle1 = insertLabel("lblTitle1", + PROPS_LABEL_B, + new Object[] { fontDescriptor4,INTEGER_16,resources.reslblTitle1_value,Boolean.TRUE,new Integer(91),INTEGERS[8],INTEGERS[1],new Short((short)100),new Integer(212)} + ); + lblPageDesign = insertLabel("lblPageDesign", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblPageDesign_value,new Integer(97),new Integer(32),INTEGERS[1],new Short((short)101),new Integer(66)} + ); + listPageDesign = insertListBox("listPageDesign", null, null, + PROPS_LIST, + new Object[] { Boolean.TRUE,INTEGER_12,LISTPAGEDESIGN_HID,new Integer(166),new Integer(30),INTEGERS[1],new Short((short)102),new Integer(70)} + ); + chkMinutes = insertCheckBox("chkMinutes", null, + PROPS_CHECK, + new Object[] { INTEGERS[9],CHKMINUTES_HID,resources.reschkMinutes_value,new Integer(97),new Integer(50),new Short((short)0),INTEGERS[1],new Short((short)103),new Integer(203)} + ); + imgHelp1 = insertImage("imgHelp1", + PROPS_IMAGE, + new Object[] { NO_BORDER, INTEGERS[10],IMGHELP1_HID, AgendaWizardDialogConst.INFO_IMAGE_URL, new Integer(92),new Integer(145), Boolean.FALSE, INTEGERS[1], new Short((short)104),INTEGERS[10]} + ); + lblHelp1 = insertLabel("lblHelp1", + PROPS_TEXTAREA, + new Object[] { new Integer(39),resources.reslblHelp1_value,Boolean.TRUE,new Integer(104),new Integer(145),INTEGERS[1],new Short((short)105),new Integer(199)} + ); + + } + + public void buildStep2() { + lblTitle2 = insertLabel("lblTitle2", + PROPS_LABEL_B, + new Object[] { fontDescriptor4,INTEGER_16,resources.reslblTitle2_value,Boolean.TRUE,new Integer(91),INTEGERS[8],INTEGERS[2],new Short((short)200),new Integer(212)} + ); + lblDate = insertLabel("lblDate", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblDate_value,new Integer(97),new Integer(32),INTEGERS[2],new Short((short)201),new Integer(66)} + ); + txtDate = insertDateField("txtDate", null, + PROPS_LIST, + new Object[] { Boolean.TRUE,INTEGER_12,TXTDATE_HID,new Integer(166),new Integer(30),INTEGERS[2],new Short((short)202),new Integer(70)} + ); + lblTime = insertLabel("lblTime", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblTime_value,new Integer(97),new Integer(50),INTEGERS[2],new Short((short)203),new Integer(66)} + ); + txtTime = insertTimeField("txtTime", null, + new String[] {"Height", "HelpURL", "PositionX", "PositionY", "Step", "StrictFormat", "TabIndex", "Width"}, + new Object[] { INTEGER_12,TXTTIME_HID,new Integer(166),new Integer(48),INTEGERS[2],Boolean.TRUE,new Short((short)204),new Integer(70)} + ); + + lblTitle = insertLabel("lblTitle", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblTitle_value,new Integer(97),new Integer(68),INTEGERS[2],new Short((short)205),new Integer(66)} + ); + txtTitle = insertTextField("txtTitle", null, + new String[] {"Height", "HelpURL", "MultiLine", "PositionX", "PositionY", "Step", "TabIndex", "Width"}, + new Object[] { new Integer(26),TXTTITLE_HID,Boolean.TRUE,new Integer(166),new Integer(66),INTEGERS[2],new Short((short)206),new Integer(138)} + ); + lblLocation = insertLabel("lblLocation", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblLocation_value,new Integer(97),new Integer(100),INTEGERS[2],new Short((short)207),new Integer(66)} + ); + cbLocation = insertTextField("cbLocation", null,null, + new String[] { "Height", "HelpURL", "MultiLine", "PositionX", "PositionY", "Step", "TabIndex", "Width"}, + new Object[] { new Integer(34),CBLOCATION_HID,Boolean.TRUE,new Integer(166),new Integer(98),INTEGERS[2],new Short((short)208),new Integer(138)} + ); + + imgHelp2 = insertImage("imgHelp2", + PROPS_IMAGE, + new Object[] { NO_BORDER, INTEGERS[10],IMGHELP1_HID,AgendaWizardDialogConst.INFO_IMAGE_URL, new Integer(92),new Integer(145),Boolean.FALSE, INTEGERS[2],new Short((short)209),INTEGERS[10]} + ); + lblHelp2 = insertLabel("lblHelp2", + PROPS_TEXTAREA, + new Object[] { new Integer(39),resources.reslblHelp2_value,Boolean.TRUE,new Integer(104),new Integer(145),INTEGERS[2],new Short((short)210),new Integer(199)} + ); + + } + + public void buildStep3() { + lblTitle3 = insertLabel("lblTitle3", + PROPS_LABEL_B, + new Object[] { fontDescriptor4,INTEGER_16,resources.reslblTitle3_value,Boolean.TRUE,new Integer(91),INTEGERS[8],INTEGERS[3],new Short((short)300),new Integer(212)} + ); + chkMeetingTitle = insertCheckBox("chkMeetingTitle", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKMEETINGTITLE_HID,resources.reschkMeetingTitle_value,new Integer(97),new Integer(32),new Short((short)1),INTEGERS[3],new Short((short)301),new Integer(69)} + ); + chkRead = insertCheckBox("chkRead", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKREAD_HID,resources.reschkRead_value,new Integer(97),new Integer(46),new Short((short)0),INTEGERS[3],new Short((short)302),new Integer(162)} + ); + chkBring = insertCheckBox("chkBring", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKBRING_HID,resources.reschkBring_value,new Integer(97),new Integer(60),new Short((short)0),INTEGERS[3],new Short((short)303),new Integer(162)} + ); + chkNotes = insertCheckBox("chkNotes", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKNOTES_HID,resources.reschkNotes_value,new Integer(97),new Integer(74),new Short((short)1),INTEGERS[3],new Short((short)304),new Integer(160)} + ); + imgHelp3 = insertImage("imgHelp3", + PROPS_IMAGE, + new Object[] { NO_BORDER, INTEGERS[10],IMGHELP1_HID,AgendaWizardDialogConst.INFO_IMAGE_URL, new Integer(92),new Integer(145),Boolean.FALSE, INTEGERS[3],new Short((short)305),INTEGERS[10]} + ); + lblHelp3 = insertLabel("lblHelp3", + PROPS_TEXTAREA, + new Object[] { new Integer(39),resources.reslblHelp3_value,Boolean.TRUE,new Integer(104),new Integer(145),INTEGERS[3],new Short((short)306),new Integer(199)} + ); + } + + public void buildStep4() { + lblTitle5 = insertLabel("lblTitle5", + PROPS_LABEL_B, + new Object[] { fontDescriptor4,INTEGER_16,resources.reslblTitle5_value,Boolean.TRUE,new Integer(91),INTEGERS[8],INTEGERS[4],new Short((short)400),new Integer(212)} + ); + chkConvenedBy = insertCheckBox("chkConvenedBy", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKCONVENEDBY_HID,resources.reschkConvenedBy_value,new Integer(97),new Integer(32),new Short((short)1),INTEGERS[4],new Short((short)401),new Integer(150)} + ); + chkPresiding = insertCheckBox("chkPresiding", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKPRESIDING_HID,resources.reschkPresiding_value,new Integer(97),new Integer(46),new Short((short)0),INTEGERS[4],new Short((short)402),new Integer(150)} + ); + chkNoteTaker = insertCheckBox("chkNoteTaker", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKNOTETAKER_HID,resources.reschkNoteTaker_value,new Integer(97),new Integer(60),new Short((short)0),INTEGERS[4],new Short((short)403),new Integer(150)} + ); + chkTimekeeper = insertCheckBox("chkTimekeeper", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKTIMEKEEPER_HID,resources.reschkTimekeeper_value,new Integer(97),new Integer(74),new Short((short)0),INTEGERS[4],new Short((short)404),new Integer(150)} + ); + chkAttendees = insertCheckBox("chkAttendees", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKATTENDEES_HID,resources.reschkAttendees_value,new Integer(97),new Integer(88),new Short((short)1),INTEGERS[4],new Short((short)405),new Integer(150)} + ); + chkObservers = insertCheckBox("chkObservers", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKOBSERVERS_HID,resources.reschkObservers_value,new Integer(97),new Integer(102),new Short((short)0),INTEGERS[4],new Short((short)406),new Integer(150)} + ); + chkResourcePersons = insertCheckBox("chkResourcePersons", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],CHKRESOURCEPERSONS_HID,resources.reschkResourcePersons_value,new Integer(97),new Integer(116),new Short((short)0),INTEGERS[4],new Short((short)407),new Integer(150)} + ); + imgHelp4 = insertImage("imgHelp4", + PROPS_IMAGE, + new Object[] { NO_BORDER, INTEGERS[10],IMGHELP1_HID,AgendaWizardDialogConst.INFO_IMAGE_URL, new Integer(92),new Integer(145),Boolean.FALSE, INTEGERS[4],new Short((short)408),INTEGERS[10]} + ); + lblHelp4 = insertLabel("lblHelp4", + PROPS_TEXTAREA, + new Object[] { new Integer(39),resources.reslblHelp4_value,Boolean.TRUE,new Integer(104),new Integer(145),INTEGERS[4],new Short((short)409),new Integer(199)} + ); + } + + public void buildStep5() { + lblTitle4 = insertLabel("lblTitle4", + PROPS_LABEL_B, + new Object[] { fontDescriptor4,INTEGER_16,resources.reslblTitle4_value,Boolean.TRUE,new Integer(91),INTEGERS[8],INTEGERS[5],new Short((short)500),new Integer(212)} + ); + lblTopic = insertLabel("lblTopic", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblTopic_value,new Integer(107),new Integer(28),INTEGERS[5],new Short((short)71),new Integer(501)} + ); + lblResponsible = insertLabel("lblResponsible", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblResponsible_value,new Integer(195),new Integer(28),INTEGERS[5],new Short((short)72),new Integer(502)} + ); + lblDuration = insertLabel("lblDuration", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblDuration_value,new Integer(267),new Integer(28),INTEGERS[5],new Short((short)73),new Integer(503)} + ); + + + + + + btnInsert = insertButton("btnInsert", BTNINSERT_ACTION_PERFORMED, + PROPS_BUTTON, + new Object[] { INTEGER_14,BTNINSERT_HID,resources.resButtonInsert,new Integer(92),new Integer(136),INTEGERS[5],new Short((short)580),INTEGER_40} + ); + btnRemove = insertButton("btnRemove", BTNREMOVE_ACTION_PERFORMED, + PROPS_BUTTON, + new Object[] { INTEGER_14,BTNREMOVE_HID,resources.resButtonRemove,new Integer(134),new Integer(136),INTEGERS[5],new Short((short)581),INTEGER_40} + ); + btnUp = insertButton("btnUp", BTNUP_ACTION_PERFORMED, + PROPS_BUTTON, + new Object[] { INTEGER_14,BTNUP_HID,resources.resButtonUp,new Integer(222),new Integer(136),INTEGERS[5],new Short((short)582),INTEGER_40} + ); + btnDown = insertButton("btnDown", BTNDOWN_ACTION_PERFORMED, + PROPS_BUTTON, + new Object[] { INTEGER_14,BTNDOWN_HID,resources.resButtonDown,new Integer(264),new Integer(136),INTEGERS[5],new Short((short)583),INTEGER_40} + ); + + + } + + public void buildStep6() { + + lblTitle6 = insertLabel("lblTitle6", + PROPS_LABEL_B, + new Object[] { fontDescriptor4,INTEGER_16,resources.reslblTitle6_value,Boolean.TRUE,new Integer(91),INTEGERS[8],INTEGERS[6],new Short((short)600),new Integer(212)} + ); + lblHelpPg6 = insertLabel("lblHelpPg6", + PROPS_TEXTAREA, + new Object[] { new Integer(24),resources.reslblHelpPg6_value,Boolean.TRUE,new Integer(97),new Integer(32),INTEGERS[6],new Short((short)601),new Integer(204)} + ); + + lblTemplateName = insertLabel("lblTemplateName", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblTemplateName_value,new Integer(97),new Integer(62),INTEGERS[6],new Short((short)602),new Integer(101)} + ); + txtTemplateName = insertTextField("txtTemplateName", TXTTEMPLATENAME_TEXT_CHANGED, + PROPS_X, + new Object[] { INTEGER_12,TXTTEMPLATENAME_HID,new Integer(202),new Integer(60),INTEGERS[6],new Short((short)603),new Integer(100)} + ); + lblProceed = insertLabel("lblProceed", + PROPS_TEXT, + new Object[] { INTEGERS[8],resources.reslblProceed_value,new Integer(97),new Integer(101),INTEGERS[6],new Short((short)607),new Integer(204)} + ); + optCreateAgenda = insertRadioButton("optCreateAgenda", null, + PROPS_CHECK, + new Object[] { INTEGERS[8],OPTCREATEAGENDA_HID,resources.resoptCreateAgenda_value,new Integer(103),new Integer(113),new Short((short)1),INTEGERS[6],new Short((short)608),new Integer(198)} + ); + optMakeChanges = insertRadioButton("optMakeChanges", null, + PROPS_BUTTON, + new Object[] { INTEGERS[8],OPTMAKECHANGES_HID,resources.resoptMakeChanges_value,new Integer(103),new Integer(125),INTEGERS[6],new Short((short)609),new Integer(198)} + ); + imgHelp6 = insertImage("imgHelp6", + PROPS_IMAGE, + new Object[] { NO_BORDER, INTEGERS[10],IMGHELP1_HID,AgendaWizardDialogConst.INFO_IMAGE_URL, new Integer(92),new Integer(145),Boolean.FALSE, INTEGERS[6],new Short((short)610),INTEGERS[10]} + ); + lblHelp6 = insertLabel("lblHelp6", + PROPS_TEXTAREA, + new Object[] { new Integer(39),resources.reslblHelp6_value,Boolean.TRUE,new Integer(104),new Integer(145),INTEGERS[6],new Short((short)611),new Integer(199)} + ); + + } + +}
\ No newline at end of file diff --git a/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogConst.java b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogConst.java new file mode 100644 index 000000000000..08f2fabfb8d9 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogConst.java @@ -0,0 +1,107 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package com.sun.star.wizards.agenda; + +public interface AgendaWizardDialogConst { + + /** + * These are event method names, used with reflection + * to call the methods under these names uppon + * events. + */ + + final String LISTPAGEDESIGN_ACTION_PERFORMED = "pageDesignChanged"; + final String TXTTEMPLATENAME_TEXT_CHANGED = "templateTitleChanged"; + final String BTNTEMPLATEPATH_ACTION_PERFORMED = "saveAs"; + final String BTNINSERT_ACTION_PERFORMED = "insertRow"; + final String BTNREMOVE_ACTION_PERFORMED = "removeRow"; + final String BTNUP_ACTION_PERFORMED = "rowUp"; + final String BTNDOWN_ACTION_PERFORMED = "rowDown"; + + final String INFO_IMAGE_URL = "private:resource/dbu/image/19205"; + /* ==================================== + * Help IDs + * ==================================== + */ + final int HID = 41051; + + /* + * "HID:(hid)" - the dialog + * "HID:(hid+1) - the help button + * "HID:(hid+2)" - the back button + * "HID:(hid+3)" - the next button + * "HID:(hid+4)" - the create button + * "HID:(hid+5)" - the cancel button + */ + + final String LISTPAGEDESIGN_HID = "HID:" + (HID + 6); + final String CHKMINUTES_HID = "HID:" + (HID + 7); + final String TXTTIME_HID = "HID:" + (HID + 8); + final String TXTDATE_HID = "HID:" + (HID + 9); + final String TXTTITLE_HID = "HID:" + (HID + 10); + final String CBLOCATION_HID = "HID:" + (HID + 11); + + final String CHKMEETINGTITLE_HID = "HID:" + (HID + 12); + final String CHKREAD_HID = "HID:" + (HID + 13); + final String CHKBRING_HID = "HID:" + (HID + 14); + final String CHKNOTES_HID = "HID:" + (HID + 15); + + final String CHKCONVENEDBY_HID = "HID:" + (HID + 16); + final String CHKPRESIDING_HID = "HID:" + (HID + 17); + final String CHKNOTETAKER_HID = "HID:" + (HID + 18); + final String CHKTIMEKEEPER_HID = "HID:" + (HID + 19); + final String CHKATTENDEES_HID = "HID:" + (HID + 20); + final String CHKOBSERVERS_HID = "HID:" + (HID + 21); + final String CHKRESOURCEPERSONS_HID = "HID:" + (HID + 22); + + final String TXTTEMPLATENAME_HID = "HID:" + (HID + 23); + final String TXTTEMPLATEPATH_HID = "HID:" + (HID + 24); + final String BTNTEMPLATEPATH_HID = "HID:" + (HID + 25); + + final String OPTCREATEAGENDA_HID = "HID:" + (HID + 26); + final String OPTMAKECHANGES_HID = "HID:" + (HID + 27); + + final String BTNINSERT_HID = "HID:" + (HID + 28); + final String BTNREMOVE_HID = "HID:" + (HID + 29); + final String BTNUP_HID = "HID:" + (HID + 30); + final String BTNDOWN_HID = "HID:" + (HID + 31); + + final int LAST_HID = HID + 32; + + /* + * 32 : scroll bar + * 33 - 35 first topics row + * 36 - 38 second + * 39 - 41 + * 42 - 44 + * 45 - 47 + * total 5 rows / 3 controls. + */ + + +} +
\ No newline at end of file diff --git a/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogImpl.java b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogImpl.java new file mode 100644 index 000000000000..4701f27110cd --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogImpl.java @@ -0,0 +1,597 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.wizards.agenda; + +import java.util.Vector; + +import com.sun.star.awt.ItemEvent; +import com.sun.star.awt.VclWindowPeerAttribute; +import com.sun.star.awt.XItemListener; +import com.sun.star.awt.XWindow; +import com.sun.star.awt.XWindowPeer; +import com.sun.star.beans.PropertyValue; +import com.sun.star.frame.XStorable; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.task.XInteractionHandler; +import com.sun.star.text.XTextDocument; +//import com.sun.star.uno.Exception; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.util.CloseVetoException; +import com.sun.star.util.XCloseable; +import com.sun.star.wizards.common.Configuration; +import com.sun.star.wizards.common.Desktop; +import com.sun.star.wizards.common.FileAccess; +import com.sun.star.wizards.common.Helper; +import com.sun.star.wizards.common.NoValidPathException; +import com.sun.star.wizards.common.SystemDialog; +import com.sun.star.wizards.document.OfficeDocument; +import com.sun.star.wizards.text.ViewHandler; +import com.sun.star.wizards.ui.PathSelection; +import com.sun.star.wizards.ui.XPathSelectionListener; +import com.sun.star.wizards.ui.event.DataAware; +import com.sun.star.wizards.ui.event.RadioDataAware; +import com.sun.star.wizards.ui.event.UnoDataAware; + +/** + * This class is the dialog implementation class - + * there is not much business logic here - but mostley + * event methods. + * Some event methods are also implemented in TopicsControl and TopicsControl.ControlRow. + * @author rp143992 + */ +public class AgendaWizardDialogImpl extends AgendaWizardDialog +{ + /** + * used to prevent a double start of the wizard. + */ + static boolean running; + + /** + * the preview document controller. + */ + AgendaTemplate agendaTemplate; + /** + * the data model, read from the OOo configuration. + * (live synchronized: when the user changes the gui, + * the data model changes, except for topics). + */ + private CGAgenda agenda; + + /** + * the topics control, a gui element which + * manipulates the topics data according to the + * user's input. + */ + private TopicsControl topicsControl; + + /** + * an array with two array memebers: + * agendaTemplates[0] contains an array with + * UI template names. + * agendaTemplates[1] contains an array with + * corresponding URLs. + */ + private String[][] agendaTemplates; + + PathSelection myPathSelection; + + String sTemplatePath; + String sUserTemplatePath; + String sBitmapPath; + + String sPath; + + /** constructor */ + public AgendaWizardDialogImpl(XMultiServiceFactory xmsf) + { + super(xmsf); + } + + protected void enterStep(int OldStep, int NewStep) {} + protected void leaveStep(int OldStep, int NewStep) {} + + /** + * read the configuration data, open the specified template, + * initialize the template controller (AgendaTemplate) and + * set the status of the displayed template to the one + * read from the configuration. + * build the dialog. + * Synchronize the dialog to the same status (read from + * the configuration). + * show the dialog. + */ + public void startWizard() { + running = true; + try { + // read configuration data. + agenda = new CGAgenda(); + + Object root = Configuration.getConfigurationRoot(xMSF, "/org.openoffice.Office.Writer/Wizards/Agenda", false); + agenda.readConfiguration(root,"cp_"); + + // initialize the agenda template + agendaTemplate = new AgendaTemplate(xMSF, agenda, resources, this); + initializeTemplates(); + + agendaTemplate.load(agendaTemplates[1][agenda.cp_AgendaType] , new Vector()); + + // build the dialog. + buildStep1(); + buildStep2(); + buildStep3(); + buildStep4(); + buildStep5(); + topicsControl = new TopicsControl(this,xMSF, agenda); + buildStep6(); + drawNaviBar(); + + initializePaths(); + + //special Control for setting the save Path: + insertPathSelectionControl(); + + // create the peer + XWindow xw = agendaTemplate.xFrame.getContainerWindow(); + XWindowPeer xWindowPeer = (XWindowPeer) UnoRuntime.queryInterface(XWindowPeer.class, xw); + this.createWindowPeer( xWindowPeer ); + + // initialize roadmap + this.addRoadmap(); + this.insertRoadMapItems( + new String[] { resources.resStep1, resources.resStep2, resources.resStep3, resources.resStep4, resources.resStep5, resources.resStep6, } , + new int[] { 1,2,3,4,5,6}, + new boolean[] { true,true,true,true,true,true } + ); + this.setMaxStep(6); + + // synchronize GUI and CGAgenda object. + makeDA(); + if(myPathSelection.xSaveTextBox.getText().equalsIgnoreCase("")) {myPathSelection.initializePath();} + + executeDialog(agendaTemplate.xFrame); + removeTerminateListener(); + closeDocument(); + running = false; + + } + catch (Exception ex) { + removeTerminateListener(); + ex.printStackTrace(); + running=false; + return; + } + + + } + + private class myPathSelectionListener implements XPathSelectionListener { + public void validatePath() { + if (myPathSelection.usedPathPicker) { + filenameChanged = true; + } + myPathSelection.usedPathPicker = false; + } + } + + + public void insertPathSelectionControl() { + myPathSelection = new PathSelection(xMSF, this, PathSelection.TransferMode.SAVE, PathSelection.DialogTypes.FILE); + myPathSelection.insert(6, 97, 70, 205, (short) 45, resources.reslblTemplatePath_value, true, "HID:" + ( HID + 24 ), "HID:" + ( HID + 25 )); + myPathSelection.sDefaultDirectory = sUserTemplatePath; + myPathSelection.sDefaultName = "myAgendaTemplate.ott"; + myPathSelection.sDefaultFilter = "writer8_template"; + myPathSelection.addSelectionListener(new myPathSelectionListener()); + } + + private void initializePaths() { + try { + sTemplatePath = FileAccess.getOfficePath(xMSF, "Template", "share", "/wizard"); + sUserTemplatePath = FileAccess.getOfficePath(xMSF, "Template", "user", ""); + sBitmapPath = FileAccess.combinePaths(xMSF, sTemplatePath, "/wizard/bitmap"); + } catch (NoValidPathException e) { + e.printStackTrace(); + } + } + + private void checkSavePath() { + if (agenda.cp_TemplatePath == null || + agenda.cp_TemplatePath.equals("") || + !getFileAccess().exists(FileAccess.getParentDir(agenda.cp_TemplatePath),false) || + !getFileAccess().isDirectory(FileAccess.getParentDir(agenda.cp_TemplatePath ))) + { + try { + agenda.cp_TemplatePath = + FileAccess.connectURLs( + FileAccess.getOfficePath(xMSF, "Work", "", "") , + resources.resDefaultFilename + ); + } + catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + /** + * bind controls to the agenda member (DataAware model) + */ + private void makeDA() { + + setControlProperty("listPageDesign", "StringItemList", agendaTemplates[0]); + + checkSavePath(); + //setFilename(agenda.cp_TemplatePath); + + UnoDataAware.attachListBox( agenda, "cp_AgendaType", listPageDesign , null, true ).updateUI(); + UnoDataAware.attachCheckBox( agenda, "cp_IncludeMinutes", chkMinutes, null, true).updateUI(); + + UnoDataAware.attachEditControl(agenda, "cp_Title", txtTitle, agendaTemplate , true).updateUI(); + UnoDataAware.attachDateControl(agenda, "cp_Date", txtDate, agendaTemplate , true).updateUI(); + UnoDataAware.attachTimeControl(agenda, "cp_Time", txtTime, agendaTemplate , true).updateUI(); + UnoDataAware.attachEditControl(agenda, "cp_Location", cbLocation, agendaTemplate , true).updateUI(); + + UnoDataAware.attachCheckBox(agenda,"cp_ShowMeetingType", chkMeetingTitle , new RedrawListener( TemplateConsts.FILLIN_MEETING_TYPE ) , true); + UnoDataAware.attachCheckBox(agenda,"cp_ShowRead", chkRead , new RedrawListener( TemplateConsts.FILLIN_READ ) , true).updateUI(); + UnoDataAware.attachCheckBox(agenda,"cp_ShowBring", chkBring , new RedrawListener( TemplateConsts.FILLIN_BRING ) , true).updateUI(); + UnoDataAware.attachCheckBox(agenda,"cp_ShowNotes", chkNotes , new RedrawListener( TemplateConsts.FILLIN_NOTES ) , true).updateUI(); + + UnoDataAware.attachCheckBox(agenda,"cp_ShowCalledBy", chkConvenedBy , new RedrawListener( TemplateConsts.FILLIN_CALLED_BY ) , true).updateUI(); + UnoDataAware.attachCheckBox(agenda,"cp_ShowFacilitator", chkPresiding , new RedrawListener( TemplateConsts.FILLIN_FACILITATOR ) , true).updateUI(); + UnoDataAware.attachCheckBox(agenda,"cp_ShowNotetaker", chkNoteTaker , new RedrawListener( TemplateConsts.FILLIN_NOTETAKER ) , true).updateUI(); + UnoDataAware.attachCheckBox(agenda,"cp_ShowTimekeeper", chkTimekeeper , new RedrawListener( TemplateConsts.FILLIN_TIMEKEEPER ) , true).updateUI(); + UnoDataAware.attachCheckBox(agenda,"cp_ShowAttendees", chkAttendees , new RedrawListener( TemplateConsts.FILLIN_PARTICIPANTS ) , true).updateUI(); + UnoDataAware.attachCheckBox(agenda,"cp_ShowObservers", chkObservers , new RedrawListener( TemplateConsts.FILLIN_OBSERVERS ) , true).updateUI(); + UnoDataAware.attachCheckBox(agenda,"cp_ShowResourcePersons", chkResourcePersons , new RedrawListener( TemplateConsts.FILLIN_RESOURCE_PERSONS ) , true).updateUI(); + + UnoDataAware.attachEditControl(agenda, "cp_TemplateName", txtTemplateName, null, true).updateUI(); + RadioDataAware.attachRadioButtons( agenda, "cp_ProceedMethod", + new Object[] {optCreateAgenda, optMakeChanges} ,null,true).updateUI(); + + listPageDesign.addItemListener(new XItemListener() { + public void itemStateChanged(ItemEvent ie) { + pageDesignChanged(ie); + } + public void disposing(EventObject eo) {} + }); + } + + /** used in developement to start the wizard */ + public static void main(String args[]) + { + String ConnectStr = "uno:socket,host=127.0.0.1,port=8100;urp,negotiate=0,forcesynchronous=1;StarOffice.ServiceManager"; + try { + XMultiServiceFactory xLocMSF = Desktop.connect(ConnectStr); + AgendaWizardDialogImpl wizard = new AgendaWizardDialogImpl(xLocMSF); + wizard.startWizard(); + + } + catch (Exception exception) { + exception.printStackTrace(); + } + } + + + /* + private void initializePaths() { + try { + + sUserTemplatePath = FileAccess.getOfficePath(xMSF, "Template", "user"); + sBitmapPath = FileAccess.combinePaths(xMSF, sTemplatePath, "/wizard/bitmap"); + } catch (NoValidPathException e) { + e.printStackTrace(); + } + }*/ + + /** + * read the available agenda wizard templates. + */ + public boolean initializeTemplates() { + try { + String sTemplatePath = FileAccess.getOfficePath(xMSF, "Template", "share", "/wizard"); + + //sCurrentNorm = Norms[getCurrentLetter().cp_Norm]; + String sAgendaPath = FileAccess.combinePaths(xMSF, sTemplatePath, "/wizard/agenda" ); + + agendaTemplates = FileAccess.getFolderTitles(xMSF, "aw" , sAgendaPath); + + return true; + } catch (NoValidPathException nopathexception) { + nopathexception.printStackTrace(); + return false; + } catch (Exception exception) { + exception.printStackTrace(); + return false; + } + } + + /* ****************************** + * Event methods + * ****************************** + */ + + /** + * first page, page design listbox changed. + */ + public void pageDesignChanged(ItemEvent ie) { + int selected = ie.Selected; + try { + agendaTemplate.load( agendaTemplates[1][selected] , topicsControl.getTopicsData()); + } + catch (Exception ex) { + SystemDialog.showMessageBox(xMSF, "ErrBox", VclWindowPeerAttribute.OK, resources.resErrOpenTemplate); + ex.printStackTrace(); + } + } + + /** + * last page, template title changed... + */ + public void templateTitleChanged() { + String title = (String)Helper.getUnoPropertyValue( getModel(txtTemplateName), "Text" ); + agendaTemplate.setTemplateTitle( title ); + } + + + private FileAccess fileAccess1; + /** convenience method. + * instead of creating a FileAccess object every time + * it is needed, I have a FileAccess object memeber. + * the first time it is needed it will be created, and + * then be reused... + * @return the FileAccess memeber object. + */ + private FileAccess getFileAccess() { + if (fileAccess1 == null) + try { + fileAccess1 = new FileAccess(xMSF); + } catch (Exception e) { + e.printStackTrace(); + } + return fileAccess1; + + } + /** + * indicates if the filename was changed by the user through + * the "save as" dialog. + * If it is so, one needs not warn the user + * upon overwrite, since she was already warned. + */ + private boolean filenameChanged = false; + + /** + * last page, "browse" ("...") button was clicked... + */ + public void saveAs() { + try { + + checkSavePath(); + + SystemDialog saveAs = SystemDialog.createStoreDialog(xMSF); + saveAs.addFilterToDialog("ott","writer8_template",true); + // call the saveAs dialog. + String url = saveAs.callStoreDialog( + FileAccess.getParentDir(agenda.cp_TemplatePath), + FileAccess.getFilename(agenda.cp_TemplatePath)); + + if (url != null) { + agenda.cp_TemplatePath = url; + setFilename(url); + filenameChanged = true; + } + } + catch (Exception ex) { + ex.printStackTrace(); + } + + + } + + /** + * is called when the user + * changes the path through the "save as" dialog. + * The path displayed is a translated, user-friendly, platform dependant path. + * @param url the new save url. + */ + private void setFilename(String url) { + try { + String path = getFileAccess().getPath(url,""); + Helper.setUnoPropertyValue( getModel(myPathSelection.xSaveTextBox), "Text", path); + } + catch (Exception ex) { + ex.printStackTrace(); + } + + } + + public void insertRow() { + topicsControl.insertRow(); + } + + public void removeRow() { + topicsControl.removeRow(); + } + + public void rowUp() { + topicsControl.rowUp(); + } + + public void rowDown() { + topicsControl.rowDown(); + } + + + /* ************************ + * Navigation bar methods + * ************************ + */ + + public void cancelWizard() { + xDialog.endExecute(); + running = false; + } + + public boolean finishWizard() { + boolean bSaveSuccess = false; // pesimistic :( + XTextDocument xTextDocument; + + try { + FileAccess fileAccess = new FileAccess(xMSF); + sPath = myPathSelection.getSelectedPath(); + if (sPath.equals("")) { + myPathSelection.triggerPathPicker(); + sPath = myPathSelection.getSelectedPath(); + } + sPath = fileAccess.getURL(sPath); + + //first, if the filename was not changed, thus + //it is coming from a saved session, check if the + // file exists and warn the user. + if (!filenameChanged) + if (fileAccess.exists(sPath, true)) { + + int answer = SystemDialog.showMessageBox(xMSF, xControl.getPeer(), "MessBox", VclWindowPeerAttribute.YES_NO + VclWindowPeerAttribute.DEF_NO, resources.resFileExists); + if (answer == 3) // user said: no, do not overwrite.... + return false; + } + + agendaTemplate.xTextDocument.lockControllers(); + + xTextDocument = (XTextDocument)UnoRuntime.queryInterface(XTextDocument.class,agendaTemplate.document); + + bSaveSuccess = OfficeDocument.store(xMSF, xTextDocument, sPath , "writer8_template", false, resources.resErrSaveTemplate ); + } catch (Exception e) { + SystemDialog.showMessageBox(xMSF, xControl.getPeer(), "ErrBox", VclWindowPeerAttribute.OK, resources.resErrSaveTemplate); + //e.printStackTrace(); + } + + if (bSaveSuccess) { + try { + topicsControl.saveTopics(agenda); + Object root = Configuration.getConfigurationRoot(xMSF, "/org.openoffice.Office.Writer/Wizards/Agenda", true); + agenda.writeConfiguration(root,"cp_"); + Configuration.commit(root); + } + catch (Exception ex) { + ex.printStackTrace(); + } + + agendaTemplate.finish( topicsControl.getTopicsData()); + try { + XStorable xStoreable = (XStorable) UnoRuntime.queryInterface(XStorable.class, agendaTemplate.document); + xStoreable.store(); + } + catch (Exception ex) { + SystemDialog.showMessageBox(xMSF, "ErrBox", VclWindowPeerAttribute.OK, resources.resErrSaveTemplate); + ex.printStackTrace(); + } + + //xWindow.setVisible(false); + //running = false; + agendaTemplate.xTextDocument.unlockControllers(); + //closeDocument(); + //removeTerminateListener(); + + PropertyValue loadValues[] = new PropertyValue[2]; + loadValues[0] = new PropertyValue(); + loadValues[0].Name = "AsTemplate"; + if (agenda.cp_ProceedMethod == 1) { + loadValues[0].Value = Boolean.TRUE; + } else { + loadValues[0].Value = Boolean.FALSE; + } + loadValues[1] = new PropertyValue(); + loadValues[1].Name = "InteractionHandler"; + try { + XInteractionHandler xIH = (XInteractionHandler) UnoRuntime.queryInterface(XInteractionHandler.class, xMSF.createInstance("com.sun.star.comp.uui.UUIInteractionHandler")); + loadValues[1].Value = xIH; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //Object oDoc = OfficeDocument.load(Desktop.getDesktop(xMSF), agenda.cp_TemplatePath, "_default", new PropertyValue[0]); + Object oDoc = OfficeDocument.load(Desktop.getDesktop(xMSF), sPath, "_default", new PropertyValue[0]); + xTextDocument = (com.sun.star.text.XTextDocument) oDoc; + XMultiServiceFactory xDocMSF = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, xTextDocument); + ViewHandler myViewHandler = new ViewHandler(xDocMSF, xTextDocument); + try { + myViewHandler.setViewSetting("ZoomType", new Short(com.sun.star.view.DocumentZoomType.OPTIMAL)); + } + catch (Exception ex) { + ex.printStackTrace(); + } + } else { + agendaTemplate.xTextDocument.unlockControllers(); + return false; + } + xDialog.endExecute(); + running = false; + return true; + } + + private void closeDocument() { + try { + //xComponent.dispose(); + XCloseable xCloseable = (XCloseable) UnoRuntime.queryInterface(XCloseable.class, agendaTemplate.xFrame); + xCloseable.close(false); + } catch (CloseVetoException e) { + e.printStackTrace(); + } + } + + /* ******************** + * Sub Classes + * ******************** + */ + + + /** + * this class is used to redraw an item's table when + * the user clicks one of the checkboxes in step 3 or 4. + */ + private class RedrawListener implements DataAware.Listener { + + private String itemName; + + public RedrawListener(String itemName_) { + itemName = itemName_; + } + + /* (non-Javadoc) + * @see com.sun.star.wizards.ui.event.DataAware.Listener#eventPerformed(java.lang.Object) + */ + public void eventPerformed(Object event) { + agendaTemplate.xTextDocument.lockControllers(); + agendaTemplate.redraw(itemName); + agendaTemplate.xTextDocument.unlockControllers(); + } + } + + +} +
\ No newline at end of file diff --git a/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogResources.java b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogResources.java new file mode 100644 index 000000000000..21730c9aa040 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogResources.java @@ -0,0 +1,221 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package com.sun.star.wizards.agenda; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.wizards.common.Resource; + +public class AgendaWizardDialogResources extends Resource { + + final static String UNIT_NAME = "dbwizres"; + final static String MODULE_NAME = "dbw"; + final static int RID_AGENDAWIZARDDIALOG_START = 5000; + final static int RID_COMMON_START = 500; + + + String resAgendaWizardDialog_title; + String resoptMakeChanges_value; + String reslblTemplateName_value; + String reslblTemplatePath_value; + String reslblProceed_value; + String reslblTitle1_value; + String reslblTitle3_value; + String reslblTitle2_value; + String reslblTitle4_value; + String reslblTitle5_value; + String reslblTitle6_value; + String reschkMinutes_value; + String reslblHelp1_value; + String reslblTime_value; + String reslblTitle_value; + String reslblLocation_value; + String reslblHelp2_value; + String resbtnTemplatePath_value; + String resoptCreateAgenda_value; + String reslblHelp6_value; + String reslblTopic_value; + String reslblResponsible_value; + String reslblDuration_value; + String reschkConvenedBy_value; + String reschkPresiding_value; + String reschkNoteTaker_value; + String reschkTimekeeper_value; + String reschkAttendees_value; + String reschkObservers_value; + String reschkResourcePersons_value; + String reslblHelp4_value; + String reschkMeetingTitle_value; + String reschkRead_value; + String reschkBring_value; + String reschkNotes_value; + String reslblHelp3_value; + + String reslblDate_value; + String reslblHelpPg6_value; + String reslblPageDesign_value; + + String resDefaultFilename; + String resDefaultTitle; + + String resErrSaveTemplate; + + String resPlaceHolderTitle; + String resPlaceHolderDate; + String resPlaceHolderTime; + String resPlaceHolderLocation; + String resPlaceHolderHint; + + String resStep1; + String resStep2; + String resStep3; + String resStep4; + String resStep5; + String resStep6; + + String resErrOpenTemplate; + + String itemMeetingType; + String itemRead; + String itemBring; + String itemNote; + String itemCalledBy; + String itemFacilitator; + String itemNotetaker; + String itemTimekeeper; + String itemAttendees; + String itemObservers; + String itemResource; + + String resButtonInsert; + String resButtonRemove; + String resButtonUp; + String resButtonDown; + + + + + // *** common resources *** + + String resFileExists; + +public AgendaWizardDialogResources(XMultiServiceFactory xmsf) { + super(xmsf,UNIT_NAME,MODULE_NAME); + + /** + * Delete the String, uncomment the getResText method + * + */ + resAgendaWizardDialog_title = getResText(RID_AGENDAWIZARDDIALOG_START + 1); + resoptMakeChanges_value = getResText(RID_AGENDAWIZARDDIALOG_START + 2); + reslblTemplateName_value = getResText(RID_AGENDAWIZARDDIALOG_START + 3); + reslblTemplatePath_value = getResText(RID_AGENDAWIZARDDIALOG_START + 4); + reslblProceed_value = getResText(RID_AGENDAWIZARDDIALOG_START + 5); + reslblTitle1_value = getResText(RID_AGENDAWIZARDDIALOG_START + 6); + reslblTitle3_value = getResText(RID_AGENDAWIZARDDIALOG_START + 7); + reslblTitle2_value = getResText(RID_AGENDAWIZARDDIALOG_START + 8); + reslblTitle4_value = getResText(RID_AGENDAWIZARDDIALOG_START + 9); + reslblTitle5_value = getResText(RID_AGENDAWIZARDDIALOG_START + 10); + reslblTitle6_value = getResText(RID_AGENDAWIZARDDIALOG_START + 11); + reschkMinutes_value = getResText(RID_AGENDAWIZARDDIALOG_START + 12); + reslblHelp1_value = getResText(RID_AGENDAWIZARDDIALOG_START + 13); + reslblTime_value = getResText(RID_AGENDAWIZARDDIALOG_START + 14); + reslblTitle_value = getResText(RID_AGENDAWIZARDDIALOG_START + 15); + reslblLocation_value = getResText(RID_AGENDAWIZARDDIALOG_START + 16); + reslblHelp2_value = getResText(RID_AGENDAWIZARDDIALOG_START + 17); + resbtnTemplatePath_value = getResText(RID_AGENDAWIZARDDIALOG_START + 18); + resoptCreateAgenda_value = getResText(RID_AGENDAWIZARDDIALOG_START + 19); + reslblHelp6_value = getResText(RID_AGENDAWIZARDDIALOG_START + 20); + reslblTopic_value = getResText(RID_AGENDAWIZARDDIALOG_START + 21); + reslblResponsible_value = getResText(RID_AGENDAWIZARDDIALOG_START + 22); + reslblDuration_value = getResText(RID_AGENDAWIZARDDIALOG_START + 23); + reschkConvenedBy_value = getResText(RID_AGENDAWIZARDDIALOG_START + 24); + reschkPresiding_value = getResText(RID_AGENDAWIZARDDIALOG_START + 25); + reschkNoteTaker_value = getResText(RID_AGENDAWIZARDDIALOG_START + 26); + reschkTimekeeper_value = getResText(RID_AGENDAWIZARDDIALOG_START + 27); + reschkAttendees_value = getResText(RID_AGENDAWIZARDDIALOG_START + 28); + reschkObservers_value = getResText(RID_AGENDAWIZARDDIALOG_START + 29); + reschkResourcePersons_value = getResText(RID_AGENDAWIZARDDIALOG_START + 30); + reslblHelp4_value = getResText(RID_AGENDAWIZARDDIALOG_START + 31); + reschkMeetingTitle_value = getResText(RID_AGENDAWIZARDDIALOG_START + 32); + reschkRead_value = getResText(RID_AGENDAWIZARDDIALOG_START + 33); + reschkBring_value = getResText(RID_AGENDAWIZARDDIALOG_START + 34); + reschkNotes_value = getResText(RID_AGENDAWIZARDDIALOG_START + 35); + reslblHelp3_value = getResText(RID_AGENDAWIZARDDIALOG_START + 36); + reslblDate_value = getResText(RID_AGENDAWIZARDDIALOG_START + 38); + reslblHelpPg6_value = getResText(RID_AGENDAWIZARDDIALOG_START + 39); + reslblPageDesign_value = getResText(RID_AGENDAWIZARDDIALOG_START + 40); + + resDefaultFilename = getResText(RID_AGENDAWIZARDDIALOG_START + 41); + resDefaultFilename = resDefaultFilename.substring(0,resDefaultFilename.length()-4) + ".ott"; + + resDefaultTitle = getResText(RID_AGENDAWIZARDDIALOG_START + 42); + + resErrSaveTemplate = getResText(RID_AGENDAWIZARDDIALOG_START + 43); + + resPlaceHolderTitle = getResText(RID_AGENDAWIZARDDIALOG_START + 44); + resPlaceHolderDate = getResText(RID_AGENDAWIZARDDIALOG_START + 45); + resPlaceHolderTime = getResText(RID_AGENDAWIZARDDIALOG_START + 46); + resPlaceHolderLocation = getResText(RID_AGENDAWIZARDDIALOG_START + 47); + resPlaceHolderHint = getResText(RID_AGENDAWIZARDDIALOG_START + 48); + + + resStep1 = getResText(RID_AGENDAWIZARDDIALOG_START + 50); + resStep2 = getResText(RID_AGENDAWIZARDDIALOG_START + 51); + resStep3 = getResText(RID_AGENDAWIZARDDIALOG_START + 52); + resStep4 = getResText(RID_AGENDAWIZARDDIALOG_START + 53); + resStep5 = getResText(RID_AGENDAWIZARDDIALOG_START + 54); + resStep6 = getResText(RID_AGENDAWIZARDDIALOG_START + 55); + + resErrOpenTemplate = getResText(RID_AGENDAWIZARDDIALOG_START + 56); + + itemMeetingType = getResText(RID_AGENDAWIZARDDIALOG_START + 57); + itemBring = getResText(RID_AGENDAWIZARDDIALOG_START + 58); + itemRead = getResText(RID_AGENDAWIZARDDIALOG_START + 59); + itemNote = getResText(RID_AGENDAWIZARDDIALOG_START + 60); + + itemCalledBy = getResText(RID_AGENDAWIZARDDIALOG_START + 61); + itemFacilitator = getResText(RID_AGENDAWIZARDDIALOG_START + 62); + itemAttendees = getResText(RID_AGENDAWIZARDDIALOG_START + 63); + itemNotetaker = getResText(RID_AGENDAWIZARDDIALOG_START + 64); + itemTimekeeper = getResText(RID_AGENDAWIZARDDIALOG_START + 65); + itemObservers = getResText(RID_AGENDAWIZARDDIALOG_START + 66); + itemResource = getResText(RID_AGENDAWIZARDDIALOG_START + 67); + + resButtonInsert = getResText(RID_AGENDAWIZARDDIALOG_START + 68); + resButtonRemove = getResText(RID_AGENDAWIZARDDIALOG_START + 69); + resButtonUp = getResText(RID_AGENDAWIZARDDIALOG_START + 70); + resButtonDown = getResText(RID_AGENDAWIZARDDIALOG_START + 71); + + /* + * Common resources + */ + + resFileExists = getResText(RID_COMMON_START + 19); + + } +} diff --git a/wizards/com/sun/star/wizards/agenda/CGAgenda.java b/wizards/com/sun/star/wizards/agenda/CGAgenda.java new file mode 100644 index 000000000000..b7dc1cc37c00 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/CGAgenda.java @@ -0,0 +1,83 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package com.sun.star.wizards.agenda; + +import com.sun.star.wizards.common.ConfigGroup; +import com.sun.star.wizards.common.ConfigSet; + +/** + * CGAgenda means Configuration Group Agenda. + * This object encapsulates a OOo configuration group, used + * to save the state of the agenda wizard for reloading uppon + * next start. + */ +public class CGAgenda extends ConfigGroup +{ + + /** step 1 - design*/ + public int cp_AgendaType; + /** step 1 - include minutes*/ + public boolean cp_IncludeMinutes; + /** step 2 - title */ + public String cp_Title = ""; + /** step 2 - date */ + public String cp_Date; + /** step 2 - time */ + public String cp_Time; + /** step 2 - location */ + public String cp_Location = ""; + /** step 3 - show meeting type */ + public boolean cp_ShowMeetingType; + /** step 3 - show read */ + public boolean cp_ShowRead; + /** step 3 - show bring */ + public boolean cp_ShowBring; + /** step 3 - show notes */ + public boolean cp_ShowNotes; + /** step 4 - show called by */ + public boolean cp_ShowCalledBy; + /** step 4 - show facilitator */ + public boolean cp_ShowFacilitator; + /** step 4 - show notes taker */ + public boolean cp_ShowNotetaker; + /** step 4 - show time keeper */ + public boolean cp_ShowTimekeeper; + /** step 4 - show attendees */ + public boolean cp_ShowAttendees; + /** step 4 - show observers */ + public boolean cp_ShowObservers; + /** step 4 - show resource persons */ + public boolean cp_ShowResourcePersons; + /** page 6 - template title */ + public String cp_TemplateName; + /** page 6 - template url */ + public String cp_TemplatePath; + /** page 6 - how to proceed */ + public int cp_ProceedMethod; + /** page 5 - topics ( a set )*/ + public ConfigSet cp_Topics = new ConfigSet(CGTopic.class); +} diff --git a/wizards/com/sun/star/wizards/agenda/CGTopic.java b/wizards/com/sun/star/wizards/agenda/CGTopic.java new file mode 100644 index 000000000000..74b818205b9f --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/CGTopic.java @@ -0,0 +1,87 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package com.sun.star.wizards.agenda; + + +import com.sun.star.beans.PropertyValue; +import com.sun.star.wizards.common.ConfigGroup; +import com.sun.star.wizards.common.Indexable; + +/** + * CGTopic means: Configuration Group Topic. + * This object encapsulates a configuration group with topic information. + * Since the topics gui conftrol uses its own data model, there is + * also code here to convert from the data model to CGTopic object (the constructor) + * and vice versa (setDataToRow method - used when loading the last session...) + */ +public class CGTopic extends ConfigGroup implements Indexable { + + /** sort order */ + public int cp_Index; + /** topic name */ + public String cp_Topic; + /** responsible */ + public String cp_Responsible; + /** time */ + public String cp_Time; + + public CGTopic() {} + + /** + * create a new CGTopic object with data from the given row. + * the row object is a PropertyValue array, as used + * by the TopicsControl's data model. + * @param row PropertyValue array as used by the TopicsControl data model. + */ + public CGTopic( Object row) { + PropertyValue[] pv = (PropertyValue[])row; + String num = (String)pv[0].Value; + cp_Index = Integer.valueOf(num.substring(0,num.length() - 1)).intValue(); + cp_Topic = (String)pv[1].Value; + cp_Responsible = (String)pv[2].Value; + cp_Time = (String)pv[3].Value; + } + + /** + * copies the data in this CGTopic object + * to the given row. + * @param row the row object (PropertyValue array) to + * copy the data to. + */ + public void setDataToRow(Object row) { + PropertyValue[] pv = (PropertyValue[])row; + pv[0].Value = "" + cp_Index + "."; + pv[1].Value = cp_Topic; + pv[2].Value = cp_Responsible; + pv[3].Value = cp_Time; + } + + public int getIndex() { + return cp_Index; + } + +} diff --git a/wizards/com/sun/star/wizards/agenda/CallWizard.java b/wizards/com/sun/star/wizards/agenda/CallWizard.java new file mode 100644 index 000000000000..69b62c56e4f7 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/CallWizard.java @@ -0,0 +1,240 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package com.sun.star.wizards.agenda; + +import com.sun.star.beans.XPropertyAccess; +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.XSingleServiceFactory; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.task.XJob; +import com.sun.star.task.XJobExecutor; +import com.sun.star.uno.Type; + +/** + * This class capsulates the class, that implements the minimal component, a factory for + * creating the service (<CODE>__getServiceFactory</CODE>) and a method, that writes the + * information into the given registry key (<CODE>__writeRegistryServiceInfo</CODE>). + * + * @author $author$ + * @version $Revision: 1.5.52.1 $ + */ +public class CallWizard { + + /** + * Gives a factory for creating the service. This method is called by the + * <code>JavaLoader</code> + * + * <p></p> + * + * @param stringImplementationName The implementation name of the component. + * @param xMSF The service manager, who gives access to every known service. + * @param xregistrykey Makes structural information (except regarding tree + * structures) of a single registry key accessible. + * + * @return Returns a <code>XSingleServiceFactory</code> for creating the component. + * + * @see com.sun.star.comp.loader.JavaLoader# + */ + public static XSingleServiceFactory __getServiceFactory(String stringImplementationName, XMultiServiceFactory xMSF, XRegistryKey xregistrykey) { + XSingleServiceFactory xsingleservicefactory = null; + + if (stringImplementationName.equals(WizardImplementation.class.getName())) { + xsingleservicefactory = FactoryHelper.getServiceFactory(WizardImplementation.class, WizardImplementation.__serviceName, xMSF, xregistrykey); + } + + return xsingleservicefactory; + } + + /** + * Writes the service information into the given registry key. This method is called + * by the <code>JavaLoader</code>. + * + * @param xregistrykey Makes structural information (except regarding tree + * structures) of a single registry key accessible. + * + * @return returns true if the operation succeeded + * + * @see com.sun.star.comp.loader.JavaLoader# + */ + public static boolean __writeRegistryServiceInfo(XRegistryKey xregistrykey) { + return FactoryHelper.writeRegistryServiceInfo(WizardImplementation.class.getName(), WizardImplementation.__serviceName, xregistrykey); + } + + /** + * This class implements the component. At least the interfaces XServiceInfo, + * XTypeProvider, and XInitialization should be provided by the service. + */ + public static class WizardImplementation implements XInitialization, XTypeProvider, XServiceInfo, XJobExecutor { + + /** + * The constructor of the inner class has a XMultiServiceFactory parameter. + * + * @param xmultiservicefactoryInitialization A special service factory could be + * introduced while initializing. + */ + public WizardImplementation(XMultiServiceFactory xmultiservicefactoryInitialization) { + xmultiservicefactory = xmultiservicefactoryInitialization; + + if (xmultiservicefactory != null) { + + } + } + + /** + * Execute Wizard + * + * @param str only valid parameter is 'start' at the moment. + */ + + public void trigger(String str) { + try { + if (str.equalsIgnoreCase("start")) { + AgendaWizardDialogImpl aw = new AgendaWizardDialogImpl(xmultiservicefactory); + if (!AgendaWizardDialogImpl.running) { + aw.startWizard(); + } + } + } + catch (Exception ex) { + ex.printStackTrace(); + } + } + + //******************************************* + + /** + * The service name, that must be used to get an instance of this service. + */ + private static final String __serviceName = "com.sun.star.wizards.agenda.CallWizard"; + + /** + * The service manager, that gives access to all registered services. + */ + private XMultiServiceFactory xmultiservicefactory; + + /** + * This method is a member of the interface for initializing an object directly + * after its creation. + * + * @param object This array of arbitrary objects will be passed to the component + * after its creation. + * + * @throws com.sun.star.uno.Exception Every exception will not be handled, but + * will be passed to the caller. + */ + public void initialize(Object[] object) throws com.sun.star.uno.Exception { + + } + + /** + * This method returns an array of all supported service names. + * + * @return Array of supported service names. + */ + public java.lang.String[] getSupportedServiceNames() { + String[] stringSupportedServiceNames = new String[1]; + stringSupportedServiceNames[0] = __serviceName; + + return (stringSupportedServiceNames); + } + + /** + * This method returns true, if the given service will be supported by the + * component. + * + * @param stringService Service name. + * + * @return True, if the given service name will be supported. + */ + public boolean supportsService(String stringService) { + boolean booleanSupportsService = false; + + if (stringService.equals(__serviceName)) { + booleanSupportsService = true; + } + + return (booleanSupportsService); + } + + /** + * This method returns an array of bytes, that can be used to unambiguously + * distinguish between two sets of types, e.g. to realise hashing functionality + * when the object is introspected. Two objects that return the same ID also + * have to return the same set of types in getTypes(). If an unique + * implementation Id cannot be provided this method has to return an empty + * sequence. Important: If the object aggregates other objects the ID has to be + * unique for the whole combination of objects. + * + * @return Array of bytes, in order to distinguish between two sets. + */ + public byte[] getImplementationId() { + byte[] byteReturn = { + }; + + try { + byteReturn = ("" + this.hashCode()).getBytes(); + } catch (Exception exception) { + System.err.println(exception); + } + + return (byteReturn); + } + + /** + * Return the class name of the component. + * + * @return Class name of the component. + */ + public java.lang.String getImplementationName() { + return (WizardImplementation.class.getName()); + } + + /** + * Provides a sequence of all types (usually interface types) provided by the + * object. + * + * @return Sequence of all types (usually interface types) provided by the + * service. + */ + public com.sun.star.uno.Type[] getTypes() { + Type[] typeReturn = { + }; + + try { + typeReturn = new Type[] { new Type(XPropertyAccess.class), new Type(XJob.class), new Type(XJobExecutor.class), new Type(XTypeProvider.class), new Type(XServiceInfo.class), new Type(XInitialization.class)}; + } catch (Exception exception) { + System.err.println(exception); + } + + return (typeReturn); + } + } +} diff --git a/wizards/com/sun/star/wizards/agenda/MANIFEST.MF b/wizards/com/sun/star/wizards/agenda/MANIFEST.MF new file mode 100644 index 000000000000..b9a31ef4732c --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/MANIFEST.MF @@ -0,0 +1,2 @@ +RegistrationClassName: com.sun.star.wizards.agenda.CallWizard +UNO-Type-Path: diff --git a/wizards/com/sun/star/wizards/agenda/TemplateConsts.java b/wizards/com/sun/star/wizards/agenda/TemplateConsts.java new file mode 100644 index 000000000000..44ce6a1e0f0e --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/TemplateConsts.java @@ -0,0 +1,146 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package com.sun.star.wizards.agenda; + +/** + * @author rpiterman + * + */ +public interface TemplateConsts +{ + + public final static String FILLIN_TITLE = "<title>"; + public final static String FILLIN_DATE = "<date>"; + public final static String FILLIN_TIME = "<time>"; + public final static String FILLIN_LOCATION = "<location>"; + /** + * section name <b>prefix</b> for sections that contain items. + * this is also used as table name prefix, since each items section + * must contain a table whos name is identical name to the section's name. + */ + public final static String SECTION_ITEMS = "AGENDA_ITEMS"; + /** + * the name of the section which contains the topics. + */ + public final static String SECTION_TOPICS = "AGENDA_TOPICS"; + /** + * the name of the parent minutes section. + */ + public final static String SECTION_MINUTES_ALL = "MINUTES_ALL"; + /** + * the name of the child nimutes section. + * This section will be duplicated for each topic. + */ + public final static String SECTION_MINUTES = "MINUTES"; //public final static String AGENDA_ITEM = "AGENDA_ITEM"; + /** + * taged headings and names. + * These will be searched in item tables (in the template) and will be + * replaced with resource strings. + * + * headings... + */ + public final static String FILLIN_MEETING_TYPE = "<meeting-type>"; + public final static String FILLIN_BRING = "<bring>"; + public final static String FILLIN_READ = "<read>"; + public final static String FILLIN_NOTES = "<notes>"; + /** + * names... + */ + public final static String FILLIN_CALLED_BY = "<called-by>"; + public final static String FILLIN_FACILITATOR = "<facilitator>"; + public final static String FILLIN_PARTICIPANTS = "<attendees>"; + public final static String FILLIN_NOTETAKER = "<notetaker>"; + public final static String FILLIN_TIMEKEEPER = "<timekeeper>"; + public final static String FILLIN_OBSERVERS = "<observers>"; + public final static String FILLIN_RESOURCE_PERSONS = "<resource-persons>"; + /** + * Styles (paragraph styles) used for agenda items. + * headings styles + * + */ + public final static String STYLE_MEETING_TYPE = "MeetingType"; + public final static String STYLE_BRING = "Bring"; + public final static String STYLE_READ = "Read"; + public final static String STYLE_NOTES = "Notes"; + /** + * names styles + */ + public final static String STYLE_CALLED_BY = "CalledBy"; + public final static String STYLE_FACILITATOR = "Facilitator"; + public final static String STYLE_PARTICIPANTS = "Attendees"; + public final static String STYLE_NOTETAKER = "Notetaker"; + public final static String STYLE_TIMEKEEPER = "Timekeeper"; + public final static String STYLE_OBSERVERS = "Observers"; + public final static String STYLE_RESOURCE_PERSONS = "ResourcePersons"; + /** + * Styles (paragraph styles) used for the <b>text</b> of agenda items + * The agenda wizard creates fill-in fields with the given styles...) + * + * headings fields styles + */ + public final static String STYLE_MEETING_TYPE_TEXT = "MeetingTypeText"; + public final static String STYLE_BRING_TEXT = "BringText"; + public final static String STYLE_READ_TEXT = "ReadText"; + public final static String STYLE_NOTES_TEXT = "NotesText"; + /** + * names field styles + */ + public final static String STYLE_CALLED_BY_TEXT = "CalledByText"; + public final static String STYLE_FACILITATOR_TEXT = "FacilitatorText"; + public final static String STYLE_PARTICIPANTS_TEXT = "AttendeesText"; + public final static String STYLE_NOTETAKER_TEXT = "NotetakerText"; + public final static String STYLE_TIMEKEEPER_TEXT = "TimekeeperText"; + public final static String STYLE_OBSERVERS_TEXT = "ObserversText"; + public final static String STYLE_RESOURCE_PERSONS_TEXT = "ResourcePersonsText"; + /** + * Fillins for the topic table. + * These strings will be searched inside the topic table as + * part of detecting its structure. + */ + public final static String FILLIN_TOPIC_NUMBER = "<num>"; + public final static String FILLIN_TOPIC_TOPIC = "<topic>"; + public final static String FILLIN_TOPIC_RESPONSIBLE = "<responsible>"; + public final static String FILLIN_TOPIC_TIME = "<topic-time>"; + /** + * fillins for minutes. + * These will be searched in the minutes section and will be replaced + * with the appropriate data. + */ + public final static String FILLIN_MINUTES_TITLE = "<minutes-title>"; + public final static String FILLIN_MINUTES_LOCATION = "<minutes-location>"; + public final static String FILLIN_MINUTES_DATE = "<minutes-date>"; + public final static String FILLIN_MINUTES_TIME = "<minutes-time>"; + /** + * Minutes-topic fillins + * These will be searched in the minutes-child-section, and + * will be replaced with topic data. + */ + public final static String FILLIN_MINUTE_NUM = "<mnum>"; + public final static String FILLIN_MINUTE_TOPIC = "<mtopic>"; + public final static String FILLIN_MINUTE_RESPONSIBLE = "<mresponsible>"; + public final static String FILLIN_MINUTE_TIME = "<mtime>"; +} diff --git a/wizards/com/sun/star/wizards/agenda/TopicsControl.java b/wizards/com/sun/star/wizards/agenda/TopicsControl.java new file mode 100644 index 000000000000..eb13e2f8b65c --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/TopicsControl.java @@ -0,0 +1,1320 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package com.sun.star.wizards.agenda; + +import java.util.List; + +import com.sun.star.awt.FocusEvent; +import com.sun.star.awt.Key; +import com.sun.star.awt.KeyEvent; +import com.sun.star.awt.KeyModifier; +import com.sun.star.awt.Selection; +import com.sun.star.awt.XControl; +import com.sun.star.awt.XFocusListener; +import com.sun.star.awt.XKeyListener; +import com.sun.star.awt.XTextComponent; +import com.sun.star.awt.XWindow; +import com.sun.star.beans.PropertyValue; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.wizards.common.Helper; +import com.sun.star.wizards.common.Properties; +import com.sun.star.wizards.ui.ControlScroller; +import com.sun.star.wizards.ui.UnoDialog2; +import com.sun.star.wizards.ui.event.EventNames; +import com.sun.star.wizards.ui.event.MethodInvocation; + +/** + * @author rpiterman + * This class implements the UI functionality of the topics scroller control. + * <br/> + * During developement, there has been a few changes which were not *fully* done - + * mainly in converting the topics and time boxes from combobox and time box to normal textboxes, + * so in the code they might be referenced as combobox or timebox. This should be + * rather understood as topicstextbox and timetextbox. + * <br/> + * <br/> + * Important behaiviour of this control is that there is always a + * blank row at the end, in which the user can enter data.<br/> + * Once the row is not blank (thus, the user entered data...), + * a new blank row is added.<br/> + * Once the user removes the last *unempty* row, by deleteing its data, it becomes + * the *last empty row* and the one after is being automatically removed.<br/> + * <br/> + * The contorl shows 5 rows at a time.<br/> + * If, for example, only 2 rows exist (from which the 2ed one is empty...) + * then the other three rows, which do not exist in the data model, are disabled. + * <br/> + * The following other functionality is implemented: + * <br/> + * 0. synchroniting data between controls, data model and live preview. + * 1. Tab scrolling.<br/> + * 2. Keyboard scrolling.<br/> + * 3. Removing rows and adding new rows.<br/> + * 4. Moving rows up and down. <br/> + * <br/> + * This control relays on the ControlScroller control which uses the following + * Data model:<br/> + * 1. It uses a vector, whos members are arrays of PropertyValue.<br/> + * 2. Each array represents a row.<br/> + * (Note: the Name and Value memebrs of the PropertyValue object are being used...) + * 3. Each property Value represents a value for a single control with the following rules:<br/> + * 3. a. the Value of the property is used for as value of the controls (usually text).<br/> + * 3. b. the Name of the property is used to map values to UI controls in the following manner:<br/> + * 3. b. 1. only the Name of the first X Rows is regarded, where X is the number of visible rows + * (in the agenda wizard this would be 5, since 5 topic rows are visible on the dialog).<br/> + * 3. b. 2. The Names of the first X (or 5...) rows are the names of the UI Controls to + * hold values. When the control scroller scrolls, it looks at the first 5 rows and uses + * the names specified there to map the current values to the specified controls. + * <br/> + * This data model makes the following limitations on the implementation: + * When moving rows, only the values should be moved. The Rows objects, which contain + * also the Names of the controls should not be switched. <br/> + * also when deleting or inserting rows, attention should be paid that no rows should be removed + * or inserted. Instead, only the Values should rotate. + * <br/> + * <br/> + * To save the topics in the registry a ConfigSet of objects of type CGTopic is + * being used. + * This one is not synchronized "live", since it is unnecessary... instead, it is + * synchronized on call, before the settings should be saved. + */ +public class TopicsControl extends ControlScroller implements XFocusListener +{ + + /** + * The name prefix of the number (label) controls + */ + public static final String LABEL = "lblTopicCnt_"; + /** + * The name prefix of the topic (text) controls + */ + public static final String TOPIC = "txtTopicTopic_"; + /** + * The name prefix of the responsible (text) controls + */ + public static final String RESP = "cbTopicResp_"; + /** + * The name prefix of the time (text) controls + */ + public static final String TIME = "txtTopicTime_"; + Object lastFocusControl; + int lastFocusRow; + /** + * the last + * topic text box. + * When pressing tab on this one a scroll down *may* be performed. + */ + private Object firstTopic; + /** + * the first time box. + * When pressing shift-tab on this control, a scroll up *may* be performed. + */ + private Object lastTime; + /** + * is used when constructing to track the tab index + * of the created control rows. + */ + private int tabIndex = 520; + + /** + * create a new TopicControl. Since this is used specifically for the + * agenda dialog, I use step 5, and constant location - and need no paramter... + * @param dialog the parent dialog + * @param xmsf service factory + * @param agenda the Agenda configuration data (contains the current topics data). + */ + public TopicsControl(AgendaWizardDialog dialog, XMultiServiceFactory xmsf, CGAgenda agenda) + { + super(dialog, xmsf, 5, 92, 38, 212, 5, 18, AgendaWizardDialogConst.LAST_HID); + initializeScrollFields(agenda); + initialize(agenda.cp_Topics.getSize() + 1); + + // set some focus listeners for TAB scroll down and up... + try + { + + // prepare scroll down on tab press... + Object lastTime = ((ControlRow) ControlGroupVector.get(nblockincrement - 1)).timebox; + + MethodInvocation mi = new MethodInvocation("lastControlKeyPressed", this, KeyEvent.class); + dialog.getGuiEventListener().add(TIME + (nblockincrement - 1), EventNames.EVENT_KEY_PRESSED, mi); + + addKeyListener(lastTime, (XKeyListener) dialog.getGuiEventListener()); + + //prepare scroll up on tab press... + firstTopic = ((ControlRow) ControlGroupVector.get(0)).textbox; + + mi = new MethodInvocation("firstControlKeyPressed", this, KeyEvent.class); + dialog.getGuiEventListener().add(TOPIC + 0, EventNames.EVENT_KEY_PRESSED, mi); + + addKeyListener(firstTopic, (XKeyListener) dialog.getGuiEventListener()); + + } + catch (NoSuchMethodException ex) + { + ex.printStackTrace(); + } + + } + + /** + * Is used to add a keylistener to different controls... + */ + static void addKeyListener(Object control, XKeyListener listener) + { + XWindow xlastControl = (XWindow) UnoRuntime.queryInterface(XWindow.class, + control); + xlastControl.addKeyListener(listener); + } + + /** + * Is used to add a focuslistener to different controls... + */ + static void addFocusListener(Object control, XFocusListener listener) + { + XWindow xlastControl = (XWindow) UnoRuntime.queryInterface(XWindow.class, + control); + xlastControl.addFocusListener(listener); + } + + /** + * Implementation of the parent class... + */ + protected void initializeScrollFields() + { + } + + /** + * initializes the data of the control. + * @param agenda + */ + protected void initializeScrollFields(CGAgenda agenda) + { + // create a row for each topic with the given values.... + for (int i = 0; i < agenda.cp_Topics.getSize(); i++) + { + PropertyValue[] row = newRow(i); + ((CGTopic) agenda.cp_Topics.getElementAt(i)).setDataToRow(row); + // a parent class method + registerControlGroup(row, i); + this.updateDocumentRow(i); + } + // inserts a blank row at the end... + insertRowAtEnd(); + } + + /** + * Insert a blank (empty) row + * as last row of the control. + * The control has always a blank row at the + * end, which enables the user to enter data... + */ + protected void insertRowAtEnd() + { + int l = scrollfields.size(); + registerControlGroup(newRow(l), l); + setTotalFieldCount(l + 1); + + // if the new row is visible, it must have been disabled + // so it should be now enabled... + if (l - nscrollvalue < nblockincrement) + { + ((ControlRow) ControlGroupVector.get(l - nscrollvalue)).setEnabled(true); + } + } + + /** + * The Topics Set in the CGAgenda object is synchronized to + * the current content of the topics. + * @param agenda + */ + void saveTopics(CGAgenda agenda) + { + agenda.cp_Topics.clear(); + for (int i = 0; i < scrollfields.size() - 1; i++) + { + agenda.cp_Topics.add(i, + new CGTopic(scrollfields.get(i))); + } + } + + /** + * overrides the parent class method to also enable the + * row whenever data is written to it. + * @param guiRow + */ + protected void fillupControls(int guiRow) + { + super.fillupControls(guiRow); + ((ControlRow) ControlGroupVector.get(guiRow)).setEnabled(true); + } + + /** + * remove the last row + */ + protected void removeLastRow() + { + int l = scrollfields.size(); + + // if we should scroll up... + if ((l - nscrollvalue >= 1) && (l - nscrollvalue <= nblockincrement) && nscrollvalue > 0) + { + while ((l - nscrollvalue >= 1) && (l - nscrollvalue <= nblockincrement) && nscrollvalue > 0) + { + setScrollValue(nscrollvalue - 1); + } + } + // if we should disable a row... + else if (nscrollvalue == 0 && l - 1 < nblockincrement) + { + ControlRow cr = (ControlRow) ControlGroupVector.get(l - 1); + cr.setEnabled(false); + } + + unregisterControlGroup(l - 1); + setTotalFieldCount(l - 1); + } + + /** + * in order to use the "move up", "down" "insert" and "remove" buttons, + * we track the last control the gained focus, in order to know which + * row should be handled. + * @param fe + */ + public void focusGained(FocusEvent fe) + { + XControl xc = (XControl) UnoRuntime.queryInterface(XControl.class, fe.Source); + focusGained(xc); + } + + /** + * Sometimes I set the focus programatically to a control + * (for example when moving a row up or down, the focus should move + * with it). + * In such cases, no VCL event is being triggered so it must + * be called programtically. + * This is done by this method. + * @param control + */ + private void focusGained(XControl control) + { + try + { + //calculate in which row we are... + String name = (String) Helper.getUnoPropertyValue(UnoDialog2.getModel(control), "Name"); + int i = name.indexOf("_"); + String num = name.substring(i + 1); + lastFocusRow = Integer.valueOf(num).intValue() + nscrollvalue; + lastFocusControl = control; + // enable/disable the buttons... + enableButtons(); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + /** + * enable or disable the buttons according to the + * current row we are in. + */ + private void enableButtons() + { + UnoDialog2.setEnabled(getAD().btnInsert, (lastFocusRow < scrollfields.size() - 1 ? Boolean.TRUE : Boolean.FALSE)); + UnoDialog2.setEnabled(getAD().btnRemove, (lastFocusRow < scrollfields.size() - 1 ? Boolean.TRUE : Boolean.FALSE)); + UnoDialog2.setEnabled(getAD().btnUp, (lastFocusRow > 0 ? Boolean.TRUE : Boolean.FALSE)); + UnoDialog2.setEnabled(getAD().btnDown, (lastFocusRow < scrollfields.size() - 1 ? Boolean.TRUE : Boolean.FALSE)); + } + + /** + * compolsary implementation of FocusListener. + * @param fe + */ + public void focusLost(FocusEvent fe) + { + } + + /** + * compolsary implementation of FocusListener. + * @param o + */ + public void disposing(EventObject o) + { + } + + /** + * Convenience method. Is used to get a reference of + * the template controller (live preview in background). + * @return the parent dialog, casted to AgendaWizardDialog. + */ + private AgendaWizardDialog getAD() + { + return (AgendaWizardDialog) this.CurUnoDialog; + } + + /** + * move the current row up + */ + public void rowUp() + { + rowUp(lastFocusRow - nscrollvalue, lastFocusControl); + } + + /** + * move the current row down. + */ + public void rowDown() + { + rowDown(lastFocusRow - nscrollvalue, lastFocusControl); + } + + private void lockDoc() + { + //((AgendaWizardDialogImpl)CurUnoDialog).agendaTemplate.xTextDocument.lockControllers(); + } + + private void unlockDoc() + { + //((AgendaWizardDialogImpl)CurUnoDialog).agendaTemplate.xTextDocument.unlockControllers(); + } + + /** + * Removes the current row. + * See general class documentation explanation about the + * data model used and the limitations which explain the implementation here. + */ + public void removeRow() + { + lockDoc(); + for (int i = lastFocusRow; i < scrollfields.size() - 1; i++) + { + PropertyValue[] pv1 = (PropertyValue[]) scrollfields.get(i); + PropertyValue[] pv2 = (PropertyValue[]) scrollfields.get(i + 1); + pv1[1].Value = pv2[1].Value; + pv1[2].Value = pv2[2].Value; + pv1[3].Value = pv2[3].Value; + updateDocumentRow(i); + if (i - nscrollvalue < nblockincrement) + { + fillupControls(i - nscrollvalue); + } + } + removeLastRow(); + // update the live preview background document + reduceDocumentToTopics(); + + // the focus should return to the edit control + focus(lastFocusControl); + unlockDoc(); + } + + /** + * Inserts a row before the current row. + * See general class documentation explanation about the + * data model used and the limitations which explain the implementation here. + */ + public void insertRow() + { + lockDoc(); + insertRowAtEnd(); + for (int i = scrollfields.size() - 2; i > lastFocusRow; i--) + { + PropertyValue[] pv1 = (PropertyValue[]) scrollfields.get(i); + PropertyValue[] pv2 = (PropertyValue[]) scrollfields.get(i - 1); + pv1[1].Value = pv2[1].Value; + pv1[2].Value = pv2[2].Value; + pv1[3].Value = pv2[3].Value; + updateDocumentRow(i); + if (i - nscrollvalue < nblockincrement) + { + fillupControls(i - nscrollvalue); + } + } + + // after rotating all the properties from this row on, + // we clear the row, so it is practically a new one... + PropertyValue[] pv1 = (PropertyValue[]) scrollfields.get(lastFocusRow); + pv1[1].Value = ""; + pv1[2].Value = ""; + pv1[3].Value = ""; + + // update the preview document. + updateDocumentRow(lastFocusRow); + + fillupControls(lastFocusRow - nscrollvalue); + + focus(lastFocusControl); + unlockDoc(); + } + + /** + * create a new row with the given index. + * The index is important because it is used in the + * Name member of the PropertyValue objects. + * To know why see general class documentation above (data model explanation). + * @param i the index of the new row + * @return + */ + private PropertyValue[] newRow(int i) + { + PropertyValue[] pv = new PropertyValue[4]; + pv[0] = Properties.createProperty(LABEL + i, "" + (i + 1) + "."); + pv[1] = Properties.createProperty(TOPIC + i, ""); + pv[2] = Properties.createProperty(RESP + i, ""); + pv[3] = Properties.createProperty(TIME + i, ""); + return pv; + } + + /** + * Implementation of ControlScroller + * This is a UI method which inserts a new row to the control. + * It uses the child-class ControlRow. (see below). + * @param _index + * @param npos + * @see ControlRow + */ + protected void insertControlGroup(int _index, int npos) + { + ControlRow oControlRow = new ControlRow((AgendaWizardDialog) CurUnoDialog, iCompPosX, npos, _index, tabIndex); + ControlGroupVector.addElement(oControlRow); + tabIndex += 4; + } + + /** + * Implementation of ControlScroller + * This is a UI method which makes a row visibele. + * As far as I know it is never called. + * @param _index + * @param _bIsVisible + * @see ControlRow + */ + protected void setControlGroupVisible(int _index, boolean _bIsVisible) + { + ((ControlRow) ControlGroupVector.get(_index)).setVisible(_bIsVisible); + + } + + /** + * Checks if a row is empty. + * This is used when the last row is changed. + * If it is empty, the next row (which is always blank) is removed. + * If it is not empty, a next row must exist. + * @param row the index number of the row to check. + * @return true if empty. false if not. + */ + protected boolean isRowEmpty(int row) + { + PropertyValue[] data = getTopicData(row); + + // now - is this row empty? + return data[1].Value.equals("") && + data[2].Value.equals("") && + data[3].Value.equals(""); + + } + /** + * is used for data tracking. + */ + private Object[] oldData; + + /** + * update the preview document and + * remove/insert rows if needed. + * @param guiRow + * @param column + */ + synchronized void fieldChanged(int guiRow, int column) + { + synchronized(this) + { + + try + { + // First, I update the document + PropertyValue[] data = getTopicData(guiRow + nscrollvalue); + + if (data == null) + { + return; + } + boolean equal = true; + + if (oldData != null) + { + for (int i = 0; i < data.length && equal; i++) + { + equal = (equal & data[i].Value.equals(oldData[i])); + } + if (equal) + { + return; + } + } + else + { + oldData = new Object[4]; + } + for (int i = 0; i < data.length; i++) + { + oldData[i] = data[i].Value; + } + updateDocumentCell(guiRow + nscrollvalue, column, data); + + if (isRowEmpty(guiRow + nscrollvalue)) + { + /* if this is the row before the last one + * (the last row is always empty) + * delete the last row... + */ + if (guiRow + nscrollvalue == scrollfields.size() - 2) + { + removeLastRow(); + + /* + * now consequentially check the last two rows, + * and remove the last one if they are both empty. + * (actually I check always the "before last" row, + * because the last one is always empty... + */ + while (scrollfields.size() > 1 && isRowEmpty(scrollfields.size() - 2)) + { + removeLastRow(); + } + ControlRow cr = (ControlRow) ControlGroupVector.get(scrollfields.size() - nscrollvalue - 1); + + // if a remove was performed, set focus to the last row with some data in it... + focus(getControl(cr, column)); + + // update the preview document. + reduceDocumentToTopics(); + } + + } + else + { // row contains data + // is this the last row? + if ((guiRow + nscrollvalue + 1) == scrollfields.size()) + { + insertRowAtEnd(); + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + + } + } + + /** + * return the corresponding row data for the given index. + * @param topic index of the topic to get. + * @return a PropertyValue array with the data for the given topic. + */ + public PropertyValue[] getTopicData(int topic) + { + if (topic < scrollfields.size()) + { + return (PropertyValue[]) scrollfields.get(topic); + } + else + { + return null; + } + } + + /** + * If the user presses tab on the last control, and + * there *are* more rows in the model, scroll down. + * @param event + */ + public void lastControlKeyPressed(KeyEvent event) + { + // if tab without shift was pressed... + if ((event.KeyCode == Key.TAB) && (event.Modifiers == 0)) + // if there is another row... + { + if ((nblockincrement + nscrollvalue) < scrollfields.size()) + { + setScrollValue(nscrollvalue + 1); + //focus(firstTopic); + focus(getControl((ControlRow) ControlGroupVector.get(4), 1)); + + } + } + } + + /** + * If the user presses shift-tab on the first control, and + * there *are* more rows in the model, scroll up. + * @param event + */ + public void firstControlKeyPressed(KeyEvent event) + { + // if tab with shift was pressed... + if ((event.KeyCode == Key.TAB) && (event.Modifiers == KeyModifier.SHIFT)) + { + if (nscrollvalue > 0) + { + setScrollValue(nscrollvalue - 1); + focus(lastTime); + } + } + } + + /** + * sets focus to the given control. + * @param textControl + */ + private void focus(Object textControl) + { + ((XWindow) UnoRuntime.queryInterface(XWindow.class, textControl)).setFocus(); + XTextComponent xTextComponent = (XTextComponent) UnoRuntime.queryInterface(XTextComponent.class, textControl); + String text = xTextComponent.getText(); + xTextComponent.setSelection(new Selection(0, text.length())); + XControl xc = (XControl) UnoRuntime.queryInterface(XControl.class, textControl); + focusGained(xc); + } + + /** + * moves the given row one row down. + * @param guiRow the gui index of the row to move. + * @param control the control to gain focus after moving. + */ + synchronized void rowDown(int guiRow, Object control) + { + // only perform if this is not the last row. + int actuallRow = guiRow + nscrollvalue; + if (actuallRow + 1 < scrollfields.size()) + { + // get the current selection + Selection selection = getSelection(control); + + // the last row should scroll... + boolean scroll = guiRow == (nblockincrement - 1); + if (scroll) + { + setScrollValue(nscrollvalue + 1); + } + int scroll1 = nscrollvalue; + + switchRows(guiRow, guiRow + (scroll ? -1 : 1)); + + if (nscrollvalue != scroll1) + { + guiRow += (nscrollvalue - scroll1); + } + setSelection(guiRow + (scroll ? 0 : 1), control, selection); + } + } + + synchronized void rowUp(int guiRow, Object control) + { + // only perform if this is not the first row + int actuallRow = guiRow + nscrollvalue; + if (actuallRow > 0) + { + // get the current selection + Selection selection = getSelection(control); + + // the last row should scroll... + boolean scroll = (guiRow == 0); + if (scroll) + { + setScrollValue(nscrollvalue - 1); + } + switchRows(guiRow, guiRow + (scroll ? 1 : -1)); + + setSelection(guiRow - (scroll ? 0 : 1), control, selection); + } + } + + /** + * moves the cursor up. + * @param guiRow + * @param control + */ + synchronized void cursorUp(int guiRow, Object control) + { + // is this the last full row ? + int actuallRow = guiRow + nscrollvalue; + //if this is the first row + if (actuallRow == 0) + { + return; + // the first row should scroll... + } + boolean scroll = (guiRow == 0); + ControlRow upperRow; + if (scroll) + { + setScrollValue(nscrollvalue - 1); + upperRow = (ControlRow) ControlGroupVector.get(guiRow); + } + else + { + upperRow = (ControlRow) ControlGroupVector.get(guiRow - 1); + } + focus(getControl(upperRow, control)); + + } + + /** + * moves the cursor down + * @param guiRow + * @param control + */ + synchronized void cursorDown(int guiRow, Object control) + { + // is this the last full row ? + int actuallRow = guiRow + nscrollvalue; + //if this is the last row, exit + if (actuallRow == scrollfields.size() - 1) + { + return; + // the first row should scroll... + } + boolean scroll = (guiRow == nblockincrement - 1); + ControlRow lowerRow; + if (scroll) + { + setScrollValue(nscrollvalue + 1); + lowerRow = (ControlRow) ControlGroupVector.get(guiRow); + } + // if we scrolled we are done... + //otherwise... + else + { + lowerRow = (ControlRow) ControlGroupVector.get(guiRow + 1); + } + focus(getControl(lowerRow, control)); + } + + /** + * changes the values of the given rows with eachother + * @param row1 one can figure out what this parameter is... + * @param row2 one can figure out what this parameter is... + */ + private void switchRows(int row1, int row2) + { + PropertyValue[] o1 = (PropertyValue[]) scrollfields.get(row1 + nscrollvalue); + PropertyValue[] o2 = (PropertyValue[]) scrollfields.get(row2 + nscrollvalue); + + Object temp = null; + for (int i = 1; i < o1.length; i++) + { + temp = o1[i].Value; + o1[i].Value = o2[i].Value; + o2[i].Value = temp; + } + + fillupControls(row1); + fillupControls(row2); + + updateDocumentRow(row1 + nscrollvalue, o1); + updateDocumentRow(row2 + nscrollvalue, o2); + + /* + * if we changed the last row, add another one... + */ + if ((row1 + nscrollvalue + 1 == scrollfields.size()) || + (row2 + nscrollvalue + 1 == scrollfields.size())) + { + insertRowAtEnd(); + /* + * if we did not change the last row but + * we did change the one before - check if we + * have two empty rows at the end. + * If so, delete the last one... + */ + } + else if ((row1 + nscrollvalue) + (row2 + nscrollvalue) == (scrollfields.size() * 2 - 5)) + { + if (isRowEmpty(scrollfields.size() - 2) && isRowEmpty(scrollfields.size() - 1)) + { + removeLastRow(); + reduceDocumentToTopics(); + } + } + } + + /** + * returns the current Selection of a text field + * @param control a text field from which the Selection object + * should be gotten. + * @return the selection object. + */ + private Selection getSelection(Object control) + { + return ((XTextComponent) UnoRuntime.queryInterface(XTextComponent.class, control)).getSelection(); + } + + /** + * sets a text selection to a given control. + * This is used when one moves a row up or down. + * After moving row X to X+/-1, the selection (or cursor position) of the + * last focused control should be restored. + * The control's row is the given guiRow. + * The control's column is detecte4d according to the given event. + * This method is called as subsequent to different events, + * thus it is comfortable to use the event here to detect the column, + * rather than in the different event methods. + * @param guiRow the row of the control to set the selection to. + * @param eventSource helps to detect the control's column to set the selection to. + * @param s the selection object to set. + */ + private void setSelection(int guiRow, Object eventSource, Selection s) + { + ControlRow cr = (ControlRow) ControlGroupVector.get(guiRow); + Object control = getControl(cr, eventSource); + ((XWindow) UnoRuntime.queryInterface(XWindow.class, control)).setFocus(); + ((XTextComponent) UnoRuntime.queryInterface(XTextComponent.class, control)).setSelection(s); + } + + /** + * returns a control out of the given row, according to a column number. + * @param cr control row object. + * @param column the column number. + * @return the control... + */ + private Object getControl(ControlRow cr, int column) + { + switch (column) + { + case 0: + return cr.label; + case 1: + return cr.textbox; + case 2: + return cr.combobox; + case 3: + return cr.timebox; + default: + throw new IllegalArgumentException("No such column"); + } + } + + /** + * returns a control out of the given row, which is + * in the same column as the given control. + * @param cr control row object + * @param control a control indicating a column. + * @return + */ + private Object getControl(ControlRow cr, Object control) + { + int column = getColumn(control); + return getControl(cr, column); + } + + /** + * returns the column number of the given control. + * @param control + * @return + */ + private int getColumn(Object control) + { + String name = (String) Helper.getUnoPropertyValue(UnoDialog2.getModel(control), "Name"); + if (name.startsWith(TOPIC)) + { + return 1; + } + if (name.startsWith(RESP)) + { + return 2; + } + if (name.startsWith(TIME)) + { + return 3; + } + if (name.startsWith(LABEL)) + { + return 0; + } + return -1; + } + + /** + * updates the given row in the preview document. + * @param row + */ + private void updateDocumentRow(int row) + { + updateDocumentRow(row, (PropertyValue[]) scrollfields.get(row)); + } + + /** + * update the given row in the preview document with the given data. + * @param row + * @param data + */ + private void updateDocumentRow(int row, PropertyValue[] data) + { + try + { + ((AgendaWizardDialogImpl) CurUnoDialog).agendaTemplate.topics.write(row, data); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + /** + * updates a single cell in the preview document. + * Is called when a single value is changed, since we really + * don't have to update the whole row for one small changhe... + * @param row the data row to update (topic number). + * @param column the column to update (a gui column, not a document column). + * @param data the data of the entire row. + */ + private void updateDocumentCell(int row, int column, PropertyValue[] data) + { + try + { + ((AgendaWizardDialogImpl) CurUnoDialog).agendaTemplate.topics.writeCell(row, column, data); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + /** + * when removeing rows, this method updates + * the preview document to show the number of rows + * according to the data model. + */ + private void reduceDocumentToTopics() + { + try + { + ((AgendaWizardDialogImpl) CurUnoDialog).agendaTemplate.topics.reduceDocumentTo(scrollfields.size() - 1); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + /** + * needed to make this data poblic. + * @return the List containing the topics data. + */ + public List getTopicsData() + { + return scrollfields; + } + /** + * A static member used for the child-class ControlRow (GUI Constant) + */ + private static Integer I_12 = new Integer(12); + /** + * A static member used for the child-class ControlRow (GUI Constant) + */ + private static Integer I_8 = new Integer(8); + /** + * A static member used for the child-class ControlRow (GUI Constant) + */ + private static final String[] LABEL_PROPS = new String[] + { + "Height", "Label", "PositionX", "PositionY", "Step", "TabIndex", "Width" + }; + /** + * A static member used for the child-class ControlRow (GUI Constant) + */ + private static final String[] TEXT_PROPS = new String[] + { + "Height", "HelpURL", "PositionX", "PositionY", "Step", "TabIndex", "Width" + }; + + /** + * + * @author rp143992 + * A class represting a single GUI row. + * Note that the instance methods of this class + * are being called and handle controls of + * a single row. + */ + public class ControlRow implements XKeyListener + { + + /** + * the number (label) control + */ + Object label; + /** + * the topic (text) control + */ + Object textbox; + /** + * the responsible (text, yes, text) control + */ + Object combobox; + /** + * the time (text, yes, text) control + */ + Object timebox; + /** + * the row offset of this instance (0 = first gui row) + */ + int offset; + + /** + * called through an event listener when the + * topic text is changed by the user. + * updates the data model and the preview document. + */ + public void topicTextChanged() + { + try + { + // update the data model + fieldInfo(offset, 1); + // update the preview document + fieldChanged(offset, 1); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + /** + * called through an event listener when the + * responsible text is changed by the user. + * updates the data model and the preview document. + */ + public void responsibleTextChanged() + { + try + { + // update the data model + fieldInfo(offset, 2); + // update the preview document + fieldChanged(offset, 2); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + /** + * called through an event listener when the + * time text is changed by the user. + * updates the data model and the preview document. + */ + public void timeTextChanged() + { + try + { + // update the data model + fieldInfo(offset, 3); + // update the preview document + fieldChanged(offset, 3); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + /** + * constructor. Create the row in the given dialog given cordinates, + * with the given offset (row number) and tabindex. + * Note that since I use this specifically for the agenda wizard, + * the step and all control coordinates inside the + * row are constant (5). + * @param dialog the agenda dialog + * @param x x coordinates + * @param y y coordinates + * @param i the gui row index + * @param tabindex first tab index for this row. + */ + public ControlRow(AgendaWizardDialog dialog, int x, int y, int i, int tabindex) + { + + offset = i; + + Integer y_ = new Integer(y); + + label = dialog.insertLabel(LABEL + i, + LABEL_PROPS, + new Object[] + { + I_8, "" + (i + 1) + ".", new Integer(x + 4), new Integer(y + 2), IStep, new Short((short) tabindex), new Integer(10) + }); + + textbox = dialog.insertTextField(TOPIC + i, "topicTextChanged", this, + TEXT_PROPS, + new Object[] + { + I_12, "HID:" + (curHelpIndex + i * 3 + 1), new Integer(x + 15), y_, IStep, new Short((short) (tabindex + 1)), new Integer(84) + }); + + combobox = dialog.insertTextField(RESP + i, "responsibleTextChanged", this, + TEXT_PROPS, + new Object[] + { + I_12, "HID:" + (curHelpIndex + i * 3 + 2), new Integer(x + 103), y_, IStep, new Short((short) (tabindex + 2)), new Integer(68) + }); + + timebox = dialog.insertTextField(TIME + i, "timeTextChanged", this, + TEXT_PROPS, + new Object[] + { + I_12, "HID:" + (curHelpIndex + i * 3 + 3), new Integer(x + 175), y_, IStep, new Short((short) (tabindex + 3)), new Integer(20) + }); + + setEnabled(false); + addKeyListener(textbox, this); + addKeyListener(combobox, this); + addKeyListener(timebox, this); + + addFocusListener(textbox, TopicsControl.this); + addFocusListener(combobox, TopicsControl.this); + addFocusListener(timebox, TopicsControl.this); + + } + + /** + * not implemented. + * @param visible + */ + public void setVisible(boolean visible) + { + // Helper.setUnoPropertyValue(UnoDialog2.getModel(button),"Visible", visible ? Boolean.TRUE : Boolean.FASLE); + } + + /** + * enables/disables the row. + * @param enabled true for enable, false for disable. + */ + public void setEnabled(boolean enabled) + { + Boolean b = enabled ? Boolean.TRUE : Boolean.FALSE; + UnoDialog2.setEnabled(label, b); + UnoDialog2.setEnabled(textbox, b); + UnoDialog2.setEnabled(combobox, b); + UnoDialog2.setEnabled(timebox, b); + } + + /** + * Impelementation of XKeyListener. + * Optionally performs the one of the following: + * cursor up, or down, row up or down + */ + public void keyPressed(KeyEvent event) + { + if (isMoveDown(event)) + { + rowDown(offset, event.Source); + } + else if (isMoveUp(event)) + { + rowUp(offset, event.Source); + } + else if (isDown(event)) + { + cursorDown(offset, event.Source); + } + else if (isUp(event)) + { + cursorUp(offset, event.Source); + } + enableButtons(); + } + + /** + * returns the column number of the given control. + * The given control must belong to this row or + * an IllegalArgumentException will accure. + * @param control + * @return an int columnd number of the given control (0 to 3). + */ + private int getColumn(Object control) + { + if (control == textbox) + { + return 1; + } + else if (control == combobox) + { + return 2; + } + else if (control == timebox) + { + return 3; + } + else if (control == label) + { + return 0; + } + else + { + throw new IllegalArgumentException("Control is not part of this ControlRow"); + } + } + + private boolean isMoveDown(KeyEvent e) + { + return (e.KeyCode == Key.DOWN) && (e.Modifiers == KeyModifier.MOD1); + } + + private boolean isMoveUp(KeyEvent e) + { + return (e.KeyCode == Key.UP) && (e.Modifiers == KeyModifier.MOD1); + } + + private boolean isDown(KeyEvent e) + { + return (e.KeyCode == Key.DOWN) && (e.Modifiers == 0); + } + + private boolean isUp(KeyEvent e) + { + return (e.KeyCode == Key.UP) && (e.Modifiers == 0); + } + + public void keyReleased(KeyEvent arg0) + { + } + + + /* (non-Javadoc) + * @see com.sun.star.lang.XEventListener#disposing(com.sun.star.lang.EventObject) + */ + public void disposing(EventObject arg0) + { + } + } +} diff --git a/wizards/com/sun/star/wizards/agenda/makefile.mk b/wizards/com/sun/star/wizards/agenda/makefile.mk new file mode 100644 index 000000000000..314dcf3b7da9 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/makefile.mk @@ -0,0 +1,71 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = ..$/..$/..$/..$/.. +PRJNAME = wizards +TARGET = agenda +PACKAGE = com$/sun$/star$/wizards$/agenda + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +#.INCLUDE : $(PRJ)$/util$/makefile.pmk + +JARFILES= unoil.jar \ + jurt.jar \ + ridl.jar \ + juh.jar \ + java_uno.jar \ + java_uno_accessbridge \ + commonwizards.jar + +CUSTOMMANIFESTFILE= MANIFEST.MF + +JARCLASSDIRS = com$/sun$/star$/wizards$/agenda +JARTARGET = $(TARGET).jar +JARCLASSPATH = commonwizards.jar + +# --- Files -------------------------------------------------------- + +JAVAFILES= \ + AgendaTemplate.java \ + AgendaWizardDialog.java \ + AgendaWizardDialogConst.java \ + AgendaWizardDialogImpl.java \ + AgendaWizardDialogResources.java \ + CGAgenda.java \ + CGTopic.java \ + CallWizard.java \ + TemplateConsts.java \ + TopicsControl.java + + +JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk |