/* * Created on Nov 2, 2007 */ package net.sf.thingamablog.gui.editor; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Event; import java.awt.Font; import java.awt.GraphicsEnvironment; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Vector; import javax.swing.AbstractAction; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.JToolBar; import javax.swing.KeyStroke; import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLEditorKit; import javax.swing.undo.UndoManager; import net.atlanticbb.tantlinger.i18n.I18n; import net.atlanticbb.tantlinger.ui.DefaultAction; import net.atlanticbb.tantlinger.ui.UIUtils; import net.atlanticbb.tantlinger.ui.text.CompoundUndoManager; import net.atlanticbb.tantlinger.ui.text.Entities; import net.atlanticbb.tantlinger.ui.text.HTMLUtils; import net.atlanticbb.tantlinger.ui.text.IndentationFilter; import net.atlanticbb.tantlinger.ui.text.SourceCodeEditor; import net.atlanticbb.tantlinger.ui.text.TextEditPopupManager; import net.atlanticbb.tantlinger.ui.text.WysiwygHTMLEditorKit; import net.atlanticbb.tantlinger.ui.text.actions.ClearStylesAction; import net.atlanticbb.tantlinger.ui.text.actions.FindReplaceAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLEditorActionFactory; import net.atlanticbb.tantlinger.ui.text.actions.HTMLElementPropertiesAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLFontAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLFontColorAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLHorizontalRuleAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLImageAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLInlineAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLLineBreakAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLLinkAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLTableAction; import net.atlanticbb.tantlinger.ui.text.actions.HTMLTextEditAction; import net.atlanticbb.tantlinger.ui.text.actions.SpecialCharAction; import net.atlanticbb.tantlinger.ui.text.dialogs.HyperlinkDialog; import net.atlanticbb.tantlinger.ui.text.dialogs.ImageDialog; import net.sf.thingamablog.TBGlobals; import net.sf.thingamablog.blog.Author; import net.sf.thingamablog.blog.AuthorEvent; import net.sf.thingamablog.blog.AuthorListener; import net.sf.thingamablog.blog.BackendException; import net.sf.thingamablog.blog.BlogEntry; import net.sf.thingamablog.blog.CategoryEvent; import net.sf.thingamablog.blog.CategoryListener; import net.sf.thingamablog.blog.TBWeblog; import net.sf.thingamablog.blog.Weblog; import net.sf.thingamablog.blog.WeblogEvent; import net.sf.thingamablog.blog.WeblogList; import net.sf.thingamablog.blog.WeblogListener; import net.sf.thingamablog.gui.TBAbout; import net.sf.thingamablog.gui.TBHelpAction; import net.sf.thingamablog.gui.app.WeblogPreviewer; import novaworx.syntax.SyntaxFactory; import novaworx.textpane.SyntaxDocument; import novaworx.textpane.SyntaxGutter; import novaworx.textpane.SyntaxGutterBase; import org.bushe.swing.action.ActionList; import org.bushe.swing.action.ActionManager; import org.bushe.swing.action.ActionUIFactory; import org.dts.spell.SpellChecker; import org.dts.spell.dictionary.OpenOfficeSpellDictionary; import org.dts.spell.dictionary.SpellDictionary; import org.dts.spell.swing.JTextComponentSpellChecker; import com.tantlinger.jdatepicker.JCalendarComboBox; //TODO table edit actions on wysiwyg popup menu //TODO editor should close if in update mode and weblog is deleted /** * @author Bob Tantlinger * */ public class EntryEditor extends JFrame { /** * */ private static final long serialVersionUID = 1L; private static final I18n i18n = I18n.getInstance("net.sf.thingamablog.gui.editor"); //$NON-NLS-1$ public static final int NEW_ENTRY_MODE = -1; public static final int UPDATE_ENTRY_MODE = -2; public static final int WYSIWYG = 0; //wysiwyg editor tab public static final int SOURCE = 1;//source editor tab; private static final String INVALID_TAGS[] = {"html", "head", "body", "title"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ private JEditorPane wysEditor; private SourceCodeEditor srcEditor; private JTextComponent focusedEditor; private JComboBox fontFamilyCombo; private JComboBox paragraphCombo; private JButton fontSizeButton; private JTabbedPane tabs; private JMenuBar menuBar; private JToolBar formatToolBar, mainToolBar; private JPopupMenu wysPopupMenu, srcPopupMenu; private JComboBox siteCombo, authorCombo; private JCalendarComboBox dateCombo; private JTextField titleField; private JCheckBox markModifiedCb; private CategoryEditorPane catPane; private JSplitPane attribSplitPane; private ActionList actionList; private FocusListener focusHandler = new FocusHandler(); private DocumentListener textChangedHandler = new TextChangedHandler(); private ActionListener fontChangeHandler = new FontChangeHandler(); private ActionListener paragraphComboHandler = new ParagraphComboHandler(); private CaretListener caretHandler = new CaretHandler(); private MouseListener popupHandler = new PopupHandler(); private WeblogChangeListener changeListener = new WeblogChangeListener(); private boolean isWysTextChanged; private boolean shouldAskToSave; private boolean cancelled = true; private boolean isPublish = false; private int mode = NEW_ENTRY_MODE; private BlogEntry entry; private Weblog weblog; private WeblogList weblogList; public EntryEditor(Weblog blog, WeblogList list) throws BackendException { this(new BlogEntry(), blog, list, NEW_ENTRY_MODE); } public EntryEditor(BlogEntry e, Weblog blog, WeblogList list) throws BackendException { this(e, blog, list, UPDATE_ENTRY_MODE); } public EntryEditor(BlogEntry e, Weblog blog, WeblogList list, int entryMode) throws BackendException { entry = e; weblogList = list; weblog = blog; mode = entryMode; if(entry.isDraft()) entry.setDate(new Date()); setIconImage((UIUtils.getIcon(UIUtils.X16, "edit1.png")).getImage()); //$NON-NLS-1$ setTitle(entry.getTitle()); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { closeEditor(); } }); //register a listener with the weblogs to update changes for(int i = 0; i < weblogList.getWeblogCount(); i++) { Weblog w = weblogList.getWeblogAt(i); w.addAuthorListener(changeListener); w.addCategoryListener(changeListener); w.addWeblogListener(changeListener); } initUI(); if(mode == NEW_ENTRY_MODE && getEditMode() == WYSIWYG && (entry.getText() == null || entry.getText().equals(""))) //$NON-NLS-1$ entry.setText("<p></p>"); //$NON-NLS-1$ if(getEditMode() == WYSIWYG) { insertHTML(entry.getText(), 0); wysEditor.setCaretPosition(0); CompoundUndoManager.discardAllEdits(wysEditor.getDocument()); } else { srcEditor.setText(entry.getText()); srcEditor.setCaretPosition(0); CompoundUndoManager.discardAllEdits(srcEditor.getDocument()); } updateState(); shouldAskToSave = false; } public int getEditMode() { return tabs.getSelectedIndex(); } /* **************** UI initialization methods ********************/ private void initUI() throws BackendException { createEditorTabs(); createEditorActions(); createAttributesComponent(); JPanel editorPanel = new JPanel(new BorderLayout()); editorPanel.add(formatToolBar, BorderLayout.NORTH); editorPanel.add(tabs, BorderLayout.CENTER); JPanel mainPanel = new JPanel(new BorderLayout()); mainPanel.add(attribSplitPane, BorderLayout.NORTH); mainPanel.add(editorPanel, BorderLayout.CENTER); getContentPane().add(mainToolBar, BorderLayout.NORTH); getContentPane().add(mainPanel, BorderLayout.CENTER); setJMenuBar(menuBar); } private void createAttributesComponent() throws BackendException { siteCombo = new JComboBox(weblogList.getWeblogs()); siteCombo.setSelectedItem(weblog); //we have to change cats and authors when the weblog selection changes siteCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { weblog = (Weblog)siteCombo.getSelectedItem(); //File dir = EntryImageUtils.getImageDirectory(weblog); //.... TODO resolve relative Image URLs updateAuthors(weblog); updateCategories(weblog); } }); //can't select diff weblog if we're updating the entry siteCombo.setEnabled(mode == NEW_ENTRY_MODE); catPane = new CategoryEditorPane(); catPane.setCategories(weblog.getCategories(), entry); Author authors[] = weblog.getAuthors(); authorCombo = new JComboBox(authors); authorCombo.addItem(""); //$NON-NLS-1$ if(mode == UPDATE_ENTRY_MODE) { for(int i = 0; i < authors.length; i++) if(authors[i].getString().equals(entry.getAuthor().getString())) authorCombo.setSelectedIndex(i); } titleField = new JTextField(); titleField.setText(entry.getTitle()); titleField.addCaretListener(new CaretListener() { public void caretUpdate(CaretEvent e) { setTitle(titleField.getText()); } }); titleField.addFocusListener(focusHandler); TextEditPopupManager.getInstance().registerJTextComponent(titleField); Date d = (mode == NEW_ENTRY_MODE || entry.getDate() == null) ? new Date() : entry.getDate(); dateCombo = new JCalendarComboBox(d, true, (mode == NEW_ENTRY_MODE) || entry.isDraft()); markModifiedCb = new JCheckBox(i18n.str("mark_as_modified")); //$NON-NLS-1$ markModifiedCb.setSelected(true); markModifiedCb.setEnabled(!entry.isDraft()); markModifiedCb.setVisible(mode == UPDATE_ENTRY_MODE); JPanel attPanel = new JPanel(new GridBagLayout()); attPanel.setBorder(BorderFactory.createEmptyBorder(16, 5, 16, 5)); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(0, 0, 0, 5); gbc.gridy = 0; attPanel.add(new JLabel(i18n.str("site")), gbc); //$NON-NLS-1$ gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridy = 0; gbc.weightx = 1.0; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(0, 0, 0, 0); gbc.gridx = 1; attPanel.add(siteCombo, gbc); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(0, 10, 0, 5); gbc.gridy = 0; attPanel.add(new JLabel(i18n.str("author")), gbc); //$NON-NLS-1$ gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridy = 0; gbc.weightx = 1.0; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(0, 0, 0, 0); gbc.gridx = 3; attPanel.add(authorCombo, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(5, 0, 0, 0); gbc.gridy = 1; attPanel.add(new JLabel(i18n.str("title")), gbc); //$NON-NLS-1$ gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridy = 1; gbc.weightx = 1.0; gbc.anchor = GridBagConstraints.WEST; gbc.gridwidth = 3; gbc.insets = new Insets(5, 0, 0, 0); gbc.gridx = 1; attPanel.add(titleField, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.insets = new Insets(5, 0, 0, 5); gbc.gridy = 2; attPanel.add(new JLabel(i18n.str("date")), gbc); //$NON-NLS-1$ gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridy = 2; gbc.weightx = 1.0; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(5, 0, 0, 0); gbc.gridx = 1; attPanel.add(dateCombo, gbc); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.gridwidth = 2; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(5, 5, 0, 0); gbc.fill = GridBagConstraints.NONE; gbc.gridy = 2; attPanel.add(markModifiedCb, gbc); JScrollPane catScroller = new JScrollPane(catPane); catScroller.getViewport().setBackground(catPane.getBackground()); catScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); catScroller.setPreferredSize(new Dimension(160, 5/*topPanel.getHeight()*/)); JPanel catPanel = new JPanel(new BorderLayout()); catPanel.add(new JLabel(i18n.str("categories") + ":"), BorderLayout.NORTH); //$NON-NLS-1$ //$NON-NLS-2$ catPanel.add(catScroller, BorderLayout.CENTER); attribSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); attribSplitPane.setLeftComponent(attPanel); attribSplitPane.setRightComponent(catPanel); } private void createEditorActions() { menuBar = new JMenuBar(); actionList = new ActionList("editor-actions"); //$NON-NLS-1$ ActionList paraActions = new ActionList("paraActions"); //$NON-NLS-1$ ActionList fontSizeActions = new ActionList("fontSizeActions"); //$NON-NLS-1$ ActionList editActions = HTMLEditorActionFactory.createEditActionList(); ActionList mainToolBarActions = new ActionList("mainToolBar"); //$NON-NLS-1$ Action objectPropertiesAction = new PropertiesAction(); //create editor popupmenus wysPopupMenu = ActionUIFactory.getInstance().createPopupMenu(editActions); wysPopupMenu.addSeparator(); wysPopupMenu.add(objectPropertiesAction); srcPopupMenu = ActionUIFactory.getInstance().createPopupMenu(editActions); // create file menu JMenu fileMenu = new JMenu(i18n.str("file")); //$NON-NLS-1$ fileMenu.setMnemonic(i18n.mnem("file")); //$NON-NLS-1$ Action act = new EntryAction(getMode(), true); actionList.add(act); fileMenu.add(act); mainToolBarActions.add(act); act = new EntryAction(getMode(), false); actionList.add(act); fileMenu.add(act); mainToolBarActions.add(act); act = new SaveAsDraftAction(); actionList.add(act); fileMenu.add(act); mainToolBarActions.add(act); JMenuItem close = new JMenuItem(i18n.str("close")); //$NON-NLS-1$ close.setMnemonic(i18n.mnem("close")); //$NON-NLS-1$ close.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { closeEditor(); } }); fileMenu.addSeparator(); fileMenu.add(close); menuBar.add(fileMenu); // create edit menu ActionList lst = new ActionList("edits"); //$NON-NLS-1$ act = new ChangeTabAction(0); lst.add(act); act = new ChangeTabAction(1); lst.add(act); lst.add(null);//separator lst.addAll(editActions); lst.add(null); lst.add(new FindReplaceAction(false)); actionList.addAll(lst); JMenu editMenu = ActionUIFactory.getInstance().createMenu(lst); editMenu.setText(i18n.str("edit")); //$NON-NLS-1$ editMenu.setMnemonic(i18n.mnem("edit")); //$NON-NLS-1$ editActions.remove(editActions.size() - 1); //remove select all editActions.remove(editActions.size() - 1);//remove separator editActions.remove(editActions.size() - 1); //remove paste formatted mainToolBarActions.add(null); mainToolBarActions.addAll(editActions); menuBar.add(editMenu); //create format menu JMenu formatMenu = new JMenu(i18n.str("format")); //$NON-NLS-1$ formatMenu.setMnemonic(i18n.mnem("format")); //$NON-NLS-1$ lst = HTMLEditorActionFactory.createFontSizeActionList();//HTMLEditorActionFactory.createInlineActionList(); actionList.addAll(lst); formatMenu.add(createMenu(lst, i18n.str("size"))); //$NON-NLS-1$ fontSizeActions.addAll(lst); lst = HTMLEditorActionFactory.createInlineActionList(); actionList.addAll(lst); formatMenu.add(createMenu(lst, i18n.str("style"))); //$NON-NLS-1$ act = new HTMLFontColorAction(); actionList.add(act); formatMenu.add(act); act = new HTMLFontAction(); actionList.add(act); formatMenu.add(act); act = new ClearStylesAction(); actionList.add(act); formatMenu.add(act); formatMenu.addSeparator(); lst = HTMLEditorActionFactory.createBlockElementActionList(); actionList.addAll(lst); formatMenu.add(createMenu(lst, i18n.str("paragraph"))); //$NON-NLS-1$ paraActions.addAll(lst); lst = HTMLEditorActionFactory.createListElementActionList(); actionList.addAll(lst); formatMenu.add(createMenu(lst, i18n.str("list"))); //$NON-NLS-1$ formatMenu.addSeparator(); paraActions.addAll(lst); lst = HTMLEditorActionFactory.createAlignActionList(); actionList.addAll(lst); formatMenu.add(createMenu(lst, i18n.str("align"))); //$NON-NLS-1$ JMenu tableMenu = new JMenu(i18n.str("table")); //$NON-NLS-1$ lst = HTMLEditorActionFactory.createInsertTableElementActionList(); actionList.addAll(lst); tableMenu.add(createMenu(lst, i18n.str("insert"))); //$NON-NLS-1$ lst = HTMLEditorActionFactory.createDeleteTableElementActionList(); actionList.addAll(lst); tableMenu.add(createMenu(lst, i18n.str("delete"))); //$NON-NLS-1$ formatMenu.add(tableMenu); formatMenu.addSeparator(); actionList.add(objectPropertiesAction); formatMenu.add(objectPropertiesAction); menuBar.add(formatMenu); ActionList insertActions = new ActionList("insertActions"); //$NON-NLS-1$ act = new HTMLLinkAction(); insertActions.add(act); act = new InternalLinkAction(); insertActions.add(act); insertActions.add(null);//separator act = new WeblogImageAction(); insertActions.add(act); act = new HTMLTableAction(); insertActions.add(act); insertActions.add(null); act = new HTMLLineBreakAction(); insertActions.add(act); act = new HTMLHorizontalRuleAction(); insertActions.add(act); act = new SpecialCharAction(); insertActions.add(act); actionList.addAll(insertActions); JMenu insertMenu = ActionUIFactory.getInstance().createMenu(insertActions); insertMenu.setText(i18n.str("insert")); //$NON-NLS-1$ insertMenu.setMnemonic(i18n.mnem("insert")); //$NON-NLS-1$ menuBar.add(insertMenu); JMenu toolsMenu = new JMenu(i18n.str("tools")); //$NON-NLS-1$ toolsMenu.setMnemonic(i18n.mnem("tools")); //$NON-NLS-1$ act = new SpellCheckAction(); actionList.add(act); mainToolBarActions.add(null); mainToolBarActions.add(act); toolsMenu.add(act); act = new PreviewAction(); actionList.add(act); mainToolBarActions.add(null); mainToolBarActions.add(act); toolsMenu.add(act); menuBar.add(toolsMenu); JMenu helpMenu = new JMenu(i18n.str("help")); //$NON-NLS-1$ helpMenu.setMnemonic(i18n.mnem("help")); //$NON-NLS-1$ Action help = new TBHelpAction( i18n.str("help_contents_"), "ch03.item2"); //$NON-NLS-1$ //$NON-NLS-2$ help.putValue(Action.SMALL_ICON, UIUtils.getIcon(UIUtils.X16, "help.png")); //$NON-NLS-1$ help.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0)); help.putValue(Action.MNEMONIC_KEY, new Integer(i18n.mnem("help_contents_"))); //$NON-NLS-1$ helpMenu.add(help); JMenuItem aboutItem = new JMenuItem(i18n.str("about_")); //$NON-NLS-1$ aboutItem.setMnemonic(i18n.mnem("about_")); //$NON-NLS-1$ aboutItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { TBAbout.showAboutBox(EntryEditor.this); } }); helpMenu.add(aboutItem); menuBar.add(helpMenu); createMainToolBar(mainToolBarActions); createFormatToolBar(paraActions, fontSizeActions, insertActions); } private void createMainToolBar(List actions) { mainToolBar = new JToolBar(); mainToolBar.setFloatable(false); for(Iterator it = actions.iterator(); it.hasNext();) { Action a = (Action)it.next(); if(a == null) mainToolBar.addSeparator(); else { UIUtils.addToolBarButton(mainToolBar, a); /*Icon li = (Icon)a.getValue(ActionManager.LARGE_ICON); UIUtils.add JButton b = mainToolBar.add(a); if(li != null) b.setIcon(li);*/ } } } private void createFormatToolBar(ActionList blockActs, ActionList fontSizeActs, ActionList insertActions) { formatToolBar = new JToolBar(); formatToolBar.setFloatable(false); formatToolBar.setFocusable(false); Font comboFont = new Font("Dialog", Font.PLAIN, 12); //$NON-NLS-1$ PropertyChangeListener propLst = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if(evt.getPropertyName().equals("selected")) //$NON-NLS-1$ { if(evt.getNewValue().equals(Boolean.TRUE)) { paragraphCombo.removeActionListener(paragraphComboHandler); paragraphCombo.setSelectedItem(evt.getSource()); paragraphCombo.addActionListener(paragraphComboHandler); } } } }; for(Iterator it = blockActs.iterator(); it.hasNext();) { Object o = it.next(); if(o instanceof DefaultAction) ((DefaultAction)o).addPropertyChangeListener(propLst); } paragraphCombo = new JComboBox(toArray(blockActs)); paragraphCombo.setPreferredSize(new Dimension(120, 22)); paragraphCombo.setMinimumSize(new Dimension(120, 22)); paragraphCombo.setMaximumSize(new Dimension(120, 22)); paragraphCombo.setFont(comboFont); paragraphCombo.addActionListener(paragraphComboHandler); paragraphCombo.setRenderer(new ParagraphComboRenderer()); formatToolBar.add(paragraphCombo); formatToolBar.addSeparator(); Vector fonts = new Vector(); fonts.add("Default"); //$NON-NLS-1$ fonts.add("serif"); //$NON-NLS-1$ fonts.add("sans-serif"); //$NON-NLS-1$ fonts.add("monospaced"); //$NON-NLS-1$ GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); fonts.addAll(Arrays.asList(gEnv.getAvailableFontFamilyNames())); fontFamilyCombo = new JComboBox(fonts); fontFamilyCombo.setPreferredSize(new Dimension(150, 22)); fontFamilyCombo.setMinimumSize(new Dimension(150, 22)); fontFamilyCombo.setMaximumSize(new Dimension(150, 22)); fontFamilyCombo.setFont(comboFont); fontFamilyCombo.addActionListener(fontChangeHandler); formatToolBar.add(fontFamilyCombo); fontSizeButton = new JButton(UIUtils.getIcon(UIUtils.X16, "fontsize.png")); //$NON-NLS-1$ fontSizeButton.setToolTipText(i18n.str("size")); //$NON-NLS-1$ final JPopupMenu sizePopup = ActionUIFactory.getInstance().createPopupMenu(fontSizeActs); ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent e) { sizePopup.show(fontSizeButton, 0, fontSizeButton.getHeight()); } }; fontSizeButton.addActionListener(al); configToolbarButton(fontSizeButton); formatToolBar.add(fontSizeButton); Action act = new HTMLFontColorAction(); actionList.add(act); addToToolBar(formatToolBar, act); formatToolBar.addSeparator(); act = new HTMLInlineAction(HTMLInlineAction.BOLD); act.putValue(ActionManager.BUTTON_TYPE, ActionManager.BUTTON_TYPE_VALUE_TOGGLE); actionList.add(act); addToToolBar(formatToolBar, act); act = new HTMLInlineAction(HTMLInlineAction.ITALIC); act.putValue(ActionManager.BUTTON_TYPE, ActionManager.BUTTON_TYPE_VALUE_TOGGLE); actionList.add(act); addToToolBar(formatToolBar, act); act = new HTMLInlineAction(HTMLInlineAction.UNDERLINE); act.putValue(ActionManager.BUTTON_TYPE, ActionManager.BUTTON_TYPE_VALUE_TOGGLE); actionList.add(act); addToToolBar(formatToolBar, act); formatToolBar.addSeparator(); List alst = HTMLEditorActionFactory.createListElementActionList(); for(Iterator it = alst.iterator(); it.hasNext();) { act = (Action)it.next(); act.putValue(ActionManager.BUTTON_TYPE, ActionManager.BUTTON_TYPE_VALUE_TOGGLE); actionList.add(act); addToToolBar(formatToolBar, act); } formatToolBar.addSeparator(); alst = HTMLEditorActionFactory.createAlignActionList(); for(Iterator it = alst.iterator(); it.hasNext();) { act = (Action)it.next(); act.putValue(ActionManager.BUTTON_TYPE, ActionManager.BUTTON_TYPE_VALUE_TOGGLE); actionList.add(act); addToToolBar(formatToolBar, act); } formatToolBar.addSeparator(); for(Iterator it = insertActions.iterator(); it.hasNext();) { act = (Action)it.next(); if(act == null) formatToolBar.addSeparator(); else addToToolBar(formatToolBar, act); } } private void addToToolBar(JToolBar toolbar, Action act) { AbstractButton button = ActionUIFactory.getInstance().createButton(act); configToolbarButton(button); toolbar.add(button); } /** * Converts an action list to an array. * Any of the null "separators" or sub ActionLists are ommited from the array. * @param lst * @return */ private Action[] toArray(ActionList lst) { List acts = new ArrayList(); for(Iterator it = lst.iterator(); it.hasNext();) { Object v = it.next(); if(v != null && v instanceof Action) acts.add(v); } return (Action[])acts.toArray(new Action[acts.size()]); } private void configToolbarButton(AbstractButton button) { button.setText(null); button.setMnemonic(0); button.setMargin(new Insets(1, 1, 1, 1)); Dimension size = new Dimension(22, 22); button.setMaximumSize(size); button.setMinimumSize(size); button.setPreferredSize(size); button.setFocusable(false); button.setFocusPainted(false); //button.setBorder(plainBorder); Action a = button.getAction(); if(a != null) button.setToolTipText(a.getValue(Action.NAME).toString()); } private JMenu createMenu(ActionList lst, String menuName) { JMenu m = ActionUIFactory.getInstance().createMenu(lst); m.setText(menuName); return m; } private void createEditorTabs() { tabs = new JTabbedPane(SwingConstants.BOTTOM); wysEditor = createWysiwygEditor(); srcEditor = createSourceEditor(); tabs.addTab(i18n.str("edit"), new JScrollPane(wysEditor)); //$NON-NLS-1$ JScrollPane scrollPane = new JScrollPane(srcEditor); SyntaxGutter gutter = new SyntaxGutter(srcEditor); SyntaxGutterBase gutterBase = new SyntaxGutterBase(gutter); scrollPane.setRowHeaderView(gutter); scrollPane.setCorner(ScrollPaneConstants.LOWER_LEFT_CORNER, gutterBase); tabs.addTab(i18n.str("edit_tab"), scrollPane); //$NON-NLS-1$ try { tabs.setSelectedIndex(Integer.parseInt(TBGlobals.getProperty("EDITOR_TYPE"))); //$NON-NLS-1$ } catch(NumberFormatException ex){} tabs.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { updateEditView(); } }); } private SourceCodeEditor createSourceEditor() { SourceCodeEditor ed = new SourceCodeEditor(); SyntaxDocument doc = new SyntaxDocument(); doc.setSyntax(SyntaxFactory.getSyntax("html")); //$NON-NLS-1$ CompoundUndoManager cuh = new CompoundUndoManager(doc, new UndoManager()); doc.addUndoableEditListener(cuh); doc.setDocumentFilter(new IndentationFilter()); doc.addDocumentListener(textChangedHandler); ed.setDocument(doc); ed.addFocusListener(focusHandler); ed.addCaretListener(caretHandler); ed.addMouseListener(popupHandler); ed.setFont(TBGlobals.getEditorFont()); return ed; } private JEditorPane createWysiwygEditor() { JEditorPane ed = new JTextPane(); HTMLEditorKit editorKit = new WysiwygHTMLEditorKit(); //change default body font to Tahoma... The default font can't handle //some greek characters editorKit.getStyleSheet().addRule("body { font-family:Tahoma; }"); ed.setEditorKitForContentType("text/html", editorKit); //$NON-NLS-1$ ed.setContentType("text/html"); //$NON-NLS-1$ ed.addCaretListener(caretHandler); ed.addFocusListener(focusHandler); ed.addMouseListener(popupHandler); HTMLDocument document = (HTMLDocument)ed.getDocument(); CompoundUndoManager cuh = new CompoundUndoManager(document, new UndoManager()); document.addUndoableEditListener(cuh); document.addDocumentListener(textChangedHandler); return ed; } /* ****************** end UI creation methods ********************** */ private void insertHTML(String html, int location) { try { HTMLEditorKit kit = (HTMLEditorKit)wysEditor.getEditorKit(); Document doc = wysEditor.getDocument(); StringReader reader = new StringReader(HTMLUtils.jEditorPaneizeHTML(html)); kit.read(reader, doc, location); //wysEditor.read(reader, doc); } catch (Exception ex) { ex.printStackTrace(); } } // called when changing tabs private void updateEditView() { Document doc = null; if(getEditMode() == WYSIWYG) { String topText = removeInvalidTags(srcEditor.getText()); wysEditor.setText(""); //$NON-NLS-1$ insertHTML(topText, 0); wysEditor.setCaretPosition(0); //CompoundUndoManager.discardAllEdits(wysEditor.getDocument()); doc = wysEditor.getDocument(); } else { String topText = removeInvalidTags(wysEditor.getText()); if(isWysTextChanged || srcEditor.getText().equals("")) //$NON-NLS-1$ { String t = deIndent(removeInvalidTags(topText)); t = Entities.HTML40.unescapeUnknownEntities(t); srcEditor.setText(t); } srcEditor.setCaretPosition(0); //CompoundUndoManager.discardAllEdits(srcEditor.getDocument()); doc = srcEditor.getDocument(); } TBGlobals.putProperty("EDITOR_TYPE", getEditMode() + ""); //$NON-NLS-1$ //$NON-NLS-2$ CompoundUndoManager.discardAllEdits(doc); CompoundUndoManager.updateUndo(doc); isWysTextChanged = false; updateState(); } /* ******************************************************************* * Methods for dealing with HTML between wysiwyg and source editors * ******************************************************************/ private String deIndent(String html) { String ws = "\n "; //$NON-NLS-1$ StringBuffer sb = new StringBuffer(html); while(sb.indexOf(ws) != -1) { int s = sb.indexOf(ws); int e = s + ws.length(); sb.delete(s, e); sb.insert(s, "\n"); //$NON-NLS-1$ } return sb.toString(); } private String removeInvalidTags(String html) { for(int i = 0; i < INVALID_TAGS.length; i++) { html = deleteOccurance(html, '<' + INVALID_TAGS[i] + '>'); html = deleteOccurance(html, "</" + INVALID_TAGS[i] + '>'); //$NON-NLS-1$ } return html.trim(); } private String deleteOccurance(String text, String word) { StringBuffer sb = new StringBuffer(text); int p; while((p = sb.toString().toLowerCase().indexOf(word.toLowerCase())) != -1) { sb.delete(p, p + word.length()); } return sb.toString(); } /* ************************************* */ /** * Manages the 'selected' state of affairs of UI components */ private void updateState() { if(focusedEditor == wysEditor) { fontFamilyCombo.removeActionListener(fontChangeHandler); String fontName = HTMLUtils.getFontFamily(wysEditor); if(fontName == null) fontFamilyCombo.setSelectedIndex(0); else fontFamilyCombo.setSelectedItem(fontName); fontFamilyCombo.addActionListener(fontChangeHandler); } actionList.putContextValueForAll(HTMLTextEditAction.EDITOR, focusedEditor); //actionList.updateEnabledForAll(); } public boolean hasUserCancelled() { return cancelled; } public boolean hasUserClickedPublish() { return isPublish; } public int getMode() { return mode; } public BlogEntry getEntry() { return entry; } public Weblog getSelectedWeblog() { return weblog; } public void setTitle(String title) { String entry = i18n.str("new_entry"); //$NON-NLS-1$ if(mode == UPDATE_ENTRY_MODE) entry = i18n.str("update_entry"); //$NON-NLS-1$ if(title.equals("")) //$NON-NLS-1$ title = i18n.str("untitled"); //$NON-NLS-1$ entry += " [" + title +"]"; //$NON-NLS-1$ //$NON-NLS-2$ super.setTitle(entry); } public void setVisible(boolean b) { if(b) { Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); int x = ((d.width - getSize().width) / 2); int y = ((d.height - getSize().height) / 2); setLocation(x, y); try { int loc = Integer.parseInt(TBGlobals.getProperty("EDITOR_DIV")); //$NON-NLS-1$ attribSplitPane.setDividerLocation(loc); attribSplitPane.setResizeWeight((double)loc/getWidth()); } catch(Exception ex) { System.out.println(ex.getMessage()); attribSplitPane.setDividerLocation(.80); attribSplitPane.setResizeWeight(.80); } } super.setVisible(b); } public void dispose() { //remove the listeners registered with the weblog for(int i = 0; i < weblogList.getWeblogCount(); i++) { Weblog w = weblogList.getWeblogAt(i); if(w != null) { w.removeAuthorListener(changeListener); w.removeCategoryListener(changeListener); w.removeWeblogListener(changeListener); } } TBGlobals.putProperty("EDITOR_DIV", attribSplitPane.getDividerLocation() + ""); //$NON-NLS-1$ //$NON-NLS-2$ WeblogPreviewer.getInstance().clearPreviewData(); super.dispose(); } private void closeEditor() { if(shouldAskToSave) { String msg = i18n.str("save_changes_draft_msg"); //$NON-NLS-1$ if(mode == UPDATE_ENTRY_MODE) msg = i18n.str("save_changes_msg"); //$NON-NLS-1$ int r = JOptionPane.showConfirmDialog(this, msg, i18n.str("save"), //$NON-NLS-1$ JOptionPane.YES_NO_CANCEL_OPTION); if(r == JOptionPane.YES_OPTION) saveEntryAndExit(entry.isDraft() || mode != UPDATE_ENTRY_MODE); else if(r == JOptionPane.NO_OPTION) dispose(); else return; } else dispose(); } private void saveEntryAndExit(boolean isSaveAsDraft) { if(isSaveAsDraft) { entry.setDraft(true); isPublish = false; entry.setLastModified(null); } else { if(mode == UPDATE_ENTRY_MODE && !entry.isDraft()) { if(markModifiedCb.isSelected()) entry.setLastModified(new Date()); else entry.setLastModified(null); } //shouldn't ever get executed else if(mode == UPDATE_ENTRY_MODE && entry.isDraft()) { entry.setLastModified(null); } entry.setDraft(false); } updateEntry(entry); if(!entry.isDraft()) entry.setText(EntryImageUtils.changeLocalImageURLs(entry.getText(), weblog)); cancelled = false; dispose(); } private void updateEntry(BlogEntry entry) { Object a = authorCombo.getSelectedItem(); if(a instanceof Author) entry.setAuthor((Author)a); entry.setDate(dateCombo.getDate()); entry.setTitle(titleField.getText()); entry.setCategories(catPane.getSelectedCategories()); if(getEditMode() == SOURCE) entry.setText(srcEditor.getText()); else { String txt = removeInvalidTags(wysEditor.getText()); txt = Entities.HTML_BASIC.unescapeUnknownEntities(txt); entry.setText(txt); } } private void updateAuthors(Weblog weblog) { authorCombo.removeAllItems(); try { Author auths[] = weblog.getAuthors(); for(int i = 0; i < auths.length; i++) authorCombo.addItem(auths[i]); } catch(Exception ex){} authorCombo.addItem("");//$NON-NLS-1$ } private void updateCategories(Weblog weblog) { entry.setCategories(new String[0]); try { //TODO if editor isn't visible, catPane doesn't seem to get repainted catPane.setCategories(weblog.getCategories(), entry); catPane.revalidate(); attribSplitPane.repaint(); } catch(BackendException ex) { } } private class CaretHandler implements CaretListener { /* (non-Javadoc) * @see javax.swing.event.CaretListener#caretUpdate(javax.swing.event.CaretEvent) */ public void caretUpdate(CaretEvent e) { updateState(); } } private class PopupHandler extends MouseAdapter { public void mousePressed(MouseEvent e) { checkForPopupTrigger(e); } public void mouseReleased(MouseEvent e) { checkForPopupTrigger(e); } private void checkForPopupTrigger(MouseEvent e) { if(e.isPopupTrigger()) { JPopupMenu p = null; if(e.getSource() == wysEditor) p = wysPopupMenu; else if(e.getSource() == srcEditor) p = srcPopupMenu; else return; p.show(e.getComponent(), e.getX(), e.getY()); } } } private class FocusHandler implements FocusListener { public void focusGained(FocusEvent e) { if(e.getComponent() instanceof JTextComponent) { JTextComponent ed = (JTextComponent)e.getComponent(); //CompoundUndoManager.updateUndo(ed.getDocument()); focusedEditor = ed; updateState(); actionList.updateEnabledForAll(); boolean isWys = focusedEditor == wysEditor; fontSizeButton.setEnabled(focusedEditor == wysEditor || focusedEditor == srcEditor); fontFamilyCombo.setEnabled(isWys && tabs.getSelectedIndex() == 0); paragraphCombo.setEnabled(isWys && tabs.getSelectedIndex() == 0); } } public void focusLost(FocusEvent e) { } } private class TextChangedHandler implements DocumentListener { public void insertUpdate(DocumentEvent e) { textChanged(); } public void removeUpdate(DocumentEvent e) { textChanged(); } public void changedUpdate(DocumentEvent e) { textChanged(); } private void textChanged() { if(tabs.getSelectedIndex() == 0) isWysTextChanged = true; shouldAskToSave = true; } } private class ChangeTabAction extends DefaultAction { /** * */ private static final long serialVersionUID = 1L; int tab; public ChangeTabAction(int tab) { super((tab == 0) ? i18n.str("rich_text") : //$NON-NLS-1$ i18n.str("source")); //$NON-NLS-1$ this.tab = tab; putValue(ActionManager.BUTTON_TYPE, ActionManager.BUTTON_TYPE_VALUE_RADIO); } protected void execute(ActionEvent e) { tabs.setSelectedIndex(tab); setSelected(true); } protected void contextChanged() { setSelected(tabs.getSelectedIndex() == tab); } } private class ParagraphComboHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if(e.getSource() == paragraphCombo) { Action a = (Action)(paragraphCombo.getSelectedItem()); a.actionPerformed(e); } } } private class ParagraphComboRenderer extends DefaultListCellRenderer { /** * */ private static final long serialVersionUID = 1L; public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if(value instanceof Action) { value = ((Action)value).getValue(Action.NAME); } return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); } } private class FontChangeHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if(e.getSource() == fontFamilyCombo && focusedEditor == wysEditor ) { //MutableAttributeSet tagAttrs = new SimpleAttributeSet(); HTMLDocument document = (HTMLDocument)focusedEditor.getDocument(); CompoundUndoManager.beginCompoundEdit(document); if(fontFamilyCombo.getSelectedIndex() != 0) { HTMLUtils.setFontFamily(wysEditor, (String)fontFamilyCombo.getSelectedItem()); } else { HTMLUtils.setFontFamily(wysEditor, null); } CompoundUndoManager.endCompoundEdit(document); } } } //Spell checker action private class SpellCheckAction extends AbstractAction { /** * */ private static final long serialVersionUID = 1L; public SpellCheckAction() { super(i18n.str("check_spelling_")); //$NON-NLS-1$ putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK)); putValue(MNEMONIC_KEY, new Integer(i18n.mnem("check_spelling_"))); //$NON-NLS-1$ putValue(Action.SHORT_DESCRIPTION, getValue(NAME)); putValue(SMALL_ICON, UIUtils.getIcon(UIUtils.X16, "spellcheck.png")); //$NON-NLS-1$ putValue(ActionManager.LARGE_ICON, UIUtils.getIcon(UIUtils.X24, "spellcheck.png")); //$NON-NLS-1$ } public void actionPerformed(ActionEvent e) { File d = new File(TBGlobals.DICT_DIR, TBGlobals.getDictionary() + ".dic"); //$NON-NLS-1$ File a = new File(TBGlobals.DICT_DIR, TBGlobals.getDictionary() + ".aff"); //$NON-NLS-1$ File userDic = new File(TBGlobals.PROP_DIR, "dict.user"); //$NON-NLS-1$ try { SpellDictionary dict = new OpenOfficeSpellDictionary(d, a, userDic); SpellChecker checker = new SpellChecker(dict); JTextComponentSpellChecker textSpellChecker = new JTextComponentSpellChecker(checker); JTextComponent textArea = null; if(getEditMode() == WYSIWYG) textArea = wysEditor; else textArea = srcEditor; if(textSpellChecker.spellCheck(textArea)) { JOptionPane.showMessageDialog(EntryEditor.this, i18n.str("spellcheck_complete"), //$NON-NLS-1$ i18n.str("spellcheck_complete"), //$NON-NLS-1$ JOptionPane.INFORMATION_MESSAGE); } textArea.requestFocusInWindow(); } catch(Exception ex) { UIUtils.showError(EntryEditor.this, i18n.str("spellcheck_error"), ex); //$NON-NLS-1$ } } } private class PreviewAction extends AbstractAction { /** * */ private static final long serialVersionUID = 1L; public PreviewAction() { super(i18n.str("preview_")); //$NON-NLS-1$ putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK)); //Messages.setMnemonic("EntryEditor.Check_Spelling", this); //$NON-NLS-1$ putValue(Action.SHORT_DESCRIPTION, getValue(NAME)); putValue(SMALL_ICON, UIUtils.getIcon(UIUtils.X16, "browser.png")); //$NON-NLS-1$ putValue(ActionManager.LARGE_ICON, UIUtils.getIcon(UIUtils.X24, "browser.png")); //$NON-NLS-1$ } /* (non-Javadoc) * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(ActionEvent e) { BlogEntry temp = new BlogEntry(); updateEntry(temp); try { TBWeblog tbw = (TBWeblog)getSelectedWeblog(); WeblogPreviewer.getInstance().previewInBrowser(tbw, new BlogEntry[]{temp}); } catch(Exception ex) { UIUtils.showError(EntryEditor.this, "Error occured while trying to launch preview.", ex); //$NON-NLS-1$ } } } public class SaveAsDraftAction extends AbstractAction { /** * */ private static final long serialVersionUID = 1L; public SaveAsDraftAction() { super(i18n.str("save_as_draft")); //$NON-NLS-1$ putValue(SHORT_DESCRIPTION, getValue(NAME)); putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_D, Event.CTRL_MASK)); putValue(MNEMONIC_KEY, new Integer(i18n.mnem("save_as_draft"))); //$NON-NLS-1$ putValue(SMALL_ICON, UIUtils.getIcon(UIUtils.X16, "save.png")); //$NON-NLS-1$ putValue(ActionManager.LARGE_ICON, UIUtils.getIcon(UIUtils.X24, "save.png")); //$NON-NLS-1$ } public void actionPerformed(ActionEvent e) { saveEntryAndExit(true); } } private class EntryAction extends AbstractAction { /** * */ private static final long serialVersionUID = 1L; private boolean publishAction = false; public EntryAction(int mode, boolean pubAction) { super(""); //$NON-NLS-1$ if(mode == UPDATE_ENTRY_MODE) { if(pubAction) { putValue(NAME, i18n.str("update_and_publish")); //$NON-NLS-1$ putValue(SMALL_ICON, UIUtils.getIcon(UIUtils.X16, "update_post_pub.png")); //$NON-NLS-1$ putValue(ActionManager.LARGE_ICON, UIUtils.getIcon(UIUtils.X24, "update_post_pub.png")); //$NON-NLS-1$ } else { putValue(NAME, i18n.str("update")); //$NON-NLS-1$ putValue(SMALL_ICON, UIUtils.getIcon(UIUtils.X16, "update_post.png")); //$NON-NLS-1$ putValue(ActionManager.LARGE_ICON, UIUtils.getIcon(UIUtils.X24, "update_post.png")); //$NON-NLS-1$ } } else { if(pubAction) { putValue(NAME, i18n.str("post_and_publish")); //$NON-NLS-1$ putValue(SMALL_ICON, UIUtils.getIcon(UIUtils.X16, "post_pub.png")); //$NON-NLS-1$ putValue(ActionManager.LARGE_ICON, UIUtils.getIcon(UIUtils.X24, "post_pub.png")); //$NON-NLS-1$ } else { putValue(NAME, i18n.str("post")); //$NON-NLS-1$ putValue(SMALL_ICON, UIUtils.getIcon(UIUtils.X16, "post.png")); //$NON-NLS-1$ putValue(ActionManager.LARGE_ICON, UIUtils.getIcon(UIUtils.X24, "post.png")); //$NON-NLS-1$ } } putValue(SHORT_DESCRIPTION, getValue(NAME)); publishAction = pubAction; } public void actionPerformed(ActionEvent e) { boolean saveAsDraft = false; //is the date combo set after the current date? if(dateCombo.getDate().after(new Date())) { int r = JOptionPane.showConfirmDialog(EntryEditor.this, i18n.str("save_as_draft_prompt"), //$NON-NLS-1$ i18n.str("confirm"), JOptionPane.YES_NO_OPTION, //$NON-NLS-1$ JOptionPane.QUESTION_MESSAGE); if(r == JOptionPane.YES_OPTION) saveAsDraft = true; else return; } //entry.setDraft(false); isPublish = publishAction; saveEntryAndExit(saveAsDraft); } } private class InternalLinkAction extends HTMLLinkAction { /** * */ private static final long serialVersionUID = 1L; public InternalLinkAction() { super(); putValue(NAME, i18n.str("internal_link_")); //$NON-NLS-1$ putValue(SMALL_ICON, UIUtils.getIcon(UIUtils.X16, "webloglink.png")); //$NON-NLS-1$ } protected HyperlinkDialog createDialog(JTextComponent ed) { return new InternalLinkDialog(EntryEditor.this, (TBWeblog)getSelectedWeblog()); } } private class WeblogImageAction extends HTMLImageAction { /** * */ private static final long serialVersionUID = 1L; protected ImageDialog createDialog(JTextComponent ed) { return new WeblogImageDialog(EntryEditor.this, getSelectedWeblog()); } } private class PropertiesAction extends HTMLElementPropertiesAction { /** * */ private static final long serialVersionUID = 1L; protected ImageDialog createImageDialog() { return new WeblogImageDialog(EntryEditor.this, getSelectedWeblog()); } } //listens for changes on the weblogs and adjusts the editor accordingly private class WeblogChangeListener implements WeblogListener, CategoryListener, AuthorListener { private Weblog getCurrentWeblog() { Weblog w = (Weblog)siteCombo.getSelectedItem(); return w; } public void authorAdded(AuthorEvent e) { updateAuthors(getCurrentWeblog()); } public void authorUpdated(AuthorEvent e) { updateAuthors(getCurrentWeblog()); } public void authorRemoved(AuthorEvent e) { updateAuthors(getCurrentWeblog()); } public void categoryAdded(CategoryEvent e) { updateCategories(getCurrentWeblog()); } public void categoryRenamed(CategoryEvent e) { updateCategories(getCurrentWeblog()); } public void categoryRemoved(CategoryEvent e) { updateCategories(getCurrentWeblog()); } public void entryRemoved(WeblogEvent e) { //the entry we're editing has been deleted //so close the editor if(mode == UPDATE_ENTRY_MODE) { if(entry.getID() == e.getEntry().getID()) closeEditor(); } } public void entryAdded(WeblogEvent e){} public void entryUpdated(WeblogEvent e){} } }