/** * Copyright (c) 2009 Juwi MacMillan Group GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.juwimm.cms.content.panel; import static de.juwimm.cms.client.beans.Application.getBean; import static de.juwimm.cms.common.Constants.rb; import java.awt.Color; import java.awt.Cursor; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Iterator; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeWillExpandListener; import javax.swing.tree.TreePath; import org.apache.log4j.Logger; import org.tizzit.util.XercesHelper; import org.w3c.dom.CDATASection; import org.w3c.dom.Element; import org.w3c.dom.Node; import de.juwimm.cms.Messages; import de.juwimm.cms.client.beans.Beans; import de.juwimm.cms.common.Constants; import de.juwimm.cms.content.ContentManager; import de.juwimm.cms.content.modules.AbstractModule; import de.juwimm.cms.content.modules.Module; import de.juwimm.cms.gui.tree.CmsTreeRenderer; import de.juwimm.cms.gui.tree.InternalLinkCache; import de.juwimm.cms.gui.tree.InternallinkTreeModel; import de.juwimm.cms.gui.tree.PageNode; import de.juwimm.cms.util.Communication; import de.juwimm.cms.util.UIConstants; import de.juwimm.cms.vo.SiteValue; import de.juwimm.cms.vo.ViewComponentValue; import de.juwimm.cms.vo.ViewDocumentValue; import de.juwimm.swing.DropDownHolder; /** * <p>Title: </p> * <p>Description: </p> * <p>Copyright: Copyright (c) 2002</p> * <p>Company: </p> * @author <a href="mailto:s.kulawik@juwimm.com">Sascha-Matthias Kulawik</a> * @version $Id$ */ public class PanInternalLink extends JPanel { private static Logger log = Logger.getLogger(PanInternalLink.class); private final Communication comm = ((Communication) getBean(Beans.COMMUNICATION)); private final int rootViewId = ((ContentManager) getBean(Beans.CONTENT_MANAGER)).getRootUnitId(); private InternallinkTreeModel currentTreeModel = null; private final JScrollPane jScrollPane1 = new JScrollPane(); private final JTree tree = new JTree(); private final JLabel lblLinkName = new JLabel(); private final JTextField txtLinkname = new JTextField(); private final JButton btnSearchAnker = new JButton(); private final JComboBox cboAnker = new JComboBox(); private Module module; private String errMsg = ""; private boolean treeLink = false; private int targetViewId = 0; private String targetViewLevel = null; private String anchor = null; private boolean loading = false; private final JComboBox cbxViewDocuments = new JComboBox(); private static InternalLinkCache linkCache = new InternalLinkCache(); private final JComboBox cbxRelatedSites = new JComboBox(); private boolean isSymlink = false; private final JCheckBox cbxDisplayTypeInline = new JCheckBox(); private final JCheckBox cbxPopup = new JCheckBox(); private PanPopupDetails panPopupDetails = null; public PanInternalLink(Module module, boolean treeLink, boolean isSymlink) { this(treeLink, isSymlink); this.module = module; this.isSymlink = isSymlink; } public PanInternalLink(boolean treeLink, boolean isSymlink) { this.treeLink = treeLink; this.isSymlink = isSymlink; try { jbInit(); this.txtLinkname.setVisible(!treeLink); this.lblLinkName.setVisible(!treeLink); if (rb != null) { lblLinkName.setText(rb.getString("panel.panelView.lblLinkname")); btnSearchAnker.setText(rb.getString("content.modules.internalLink.btnSearchAnchor")); cbxDisplayTypeInline.setText(rb.getString("content.modules.externalLink.displayTypeInline")); cbxPopup.setText(rb.getString("PanPopupDetails.showInPopup")); } btnSearchAnker.setEnabled(false); TreeWillExpandListener tl = new TreeWillExpandListener() { public void treeWillCollapse(TreeExpansionEvent event) { } public void treeWillExpand(TreeExpansionEvent event) { try { TreePath path = event.getPath(); PageNode entry = (PageNode) path.getLastPathComponent(); if (!entry.isInit() && !entry.isLeaf()) { treeClick(event.getPath()); } } catch (Exception exe) { log.error("Error expanding the tree " + event.getPath(), exe); } } }; MouseListener ml = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { try { int selRow = tree.getRowForLocation(e.getX(), e.getY()); TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); btnSearchAnker.setEnabled(true); if (e.getClickCount() == 2) { if (tree.isExpanded(selPath)) tree.collapsePath(selPath); } else if (selRow != -1) { treeClick(selPath); } } catch (Exception exe) { log.error("Error during mousePressed", exe); } } }; tree.addMouseListener(ml); tree.addTreeWillExpandListener(tl); /* if (currentTreeModel == null || rootViewId != ((PageNode) currentTreeModel.getRoot()).getViewId()) { log.info("Loading TreeModel for Internal Link... Please wait :)"); currentTreeModel = new InternallinkTreeModel(new PageNode(comm.getViewComponent4Unit(rootViewId, -1))); } tree.setModel(currentTreeModel); tree.setCellRenderer(new CmsTreeRenderer()); tree.validate(); tree.repaint(); validate(); repaint(); */ } catch (Exception exe) { log.error("Initialization problem", exe); } } void jbInit() throws Exception { this.setLayout(new GridBagLayout()); lblLinkName.setText(Messages.getString("PanInternalLink.lblLinkname")); btnSearchAnker.setText(Messages.getString("PanInternalLink.btnSearchAnchor")); cboAnker.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent e) { if (!loading) { if (cboAnker.getSelectedIndex() > 0) { anchor = (String) cboAnker.getSelectedItem(); } else { anchor = ""; } } } }); btnSearchAnker.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { btnSearchAnkerActionPerformed(e); } }); jScrollPane1.getViewport().setBackground(Color.white); this.add(lblLinkName, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(5, 5, 0, 5), 6, 0)); this.add(txtLinkname, new GridBagConstraints(1, 0, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 5), 296, 0)); this.add(cbxRelatedSites, new GridBagConstraints(0, 1, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 0, 5), 0, 2)); this.add(cbxViewDocuments, new GridBagConstraints(0, 2, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 0, 5), 0, 2)); this.add(jScrollPane1, new GridBagConstraints(0, 3, 3, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 0, 5), 418, 336)); this.add(btnSearchAnker, new GridBagConstraints(0, 4, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 33, 0)); this.add(cboAnker, new GridBagConstraints(2, 4, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 178, 2)); this.add(cbxDisplayTypeInline, new GridBagConstraints(0, 5, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 33, 0)); jScrollPane1.getViewport().add(tree, null); this.cbxRelatedSites.setVisible(this.isSymlink); this.add(cbxPopup, new GridBagConstraints(0, 6, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); this.cbxPopup.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { cbxPopupStateChanged(e); } }); } private void cbxPopupStateChanged(ItemEvent e) { this.showPopupPanel(e.getStateChange() == ItemEvent.SELECTED); } private void showPopupPanel(boolean show) { if (show) { this.add(this.getPanPopupDetails(), new GridBagConstraints(1, 6, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); } else { this.remove(this.getPanPopupDetails()); } this.revalidate(); this.repaint(); } private PanPopupDetails getPanPopupDetails() { if (this.panPopupDetails == null) { this.panPopupDetails = new PanPopupDetails(); } return this.panPopupDetails; } private void treeClick(TreePath treePath) throws Exception { PageNode pageNode = (PageNode) treePath.getLastPathComponent(); pageNode.loadChildren(); if (pageNode.isRoot()) { TreePath path = new TreePath(currentTreeModel.getPathToRoot(pageNode)); tree.setSelectionPath(path); } else if (!pageNode.isLeaf()) { TreePath path = new TreePath(currentTreeModel.getPathToRoot(pageNode)); if (tree.isCollapsed(path)) { tree.expandPath(path); tree.setSelectionPath(path); } } targetViewId = pageNode.getViewId(); targetViewLevel = pageNode.getViewComponent().getViewLevel(); } void btnSearchAnkerActionPerformed(ActionEvent e) { Thread t = new Thread(new Runnable() { public void run() { setCursor(new Cursor(Cursor.WAIT_CURSOR)); searchAnchor(); setCursor(Cursor.getDefaultCursor()); } }); t.setPriority(Thread.NORM_PRIORITY); t.start(); } public void setAnchorVisible(boolean vis) { btnSearchAnker.setVisible(vis); cboAnker.setVisible(vis); } public void setDisplayTypeEditable(boolean editable) { this.cbxDisplayTypeInline.setVisible(editable); } private void searchAnchor() { loading = true; TreePath tp = this.tree.getSelectionPath(); if (tp != null) { PageNode pageNode = (PageNode) tp.getLastPathComponent(); ViewComponentValue vcd = pageNode.getViewComponent(); if (vcd.getViewType() == Constants.VIEW_TYPE_CONTENT || vcd.getViewType() == Constants.VIEW_TYPE_UNIT) { String[] anchArr = comm.getAnchors(new Integer(vcd.getReference()).intValue()); this.cboAnker.removeAllItems(); this.cboAnker.addItem(rb.getString("content.modules.internalLink.noAnchor")); if (anchArr != null) { for (int i = 0; i < anchArr.length; i++) { this.cboAnker.addItem(AbstractModule.getURLDecoded(anchArr[i])); } } } } loading = false; } public boolean isModuleValid() { errMsg = ""; PageNode pageNode = null; try { pageNode = (PageNode) tree.getSelectionPath().getLastPathComponent(); } catch (Exception exe) { } if (pageNode == null) { errMsg = rb.getString("exception.LinkRequired"); } else if (pageNode.getViewComponent().getViewType() == Constants.VIEW_TYPE_INTERNAL_LINK || pageNode.getViewComponent().getViewType() == Constants.VIEW_TYPE_EXTERNAL_LINK) { errMsg = rb.getString("exception.ValidLinkRequired"); } if (!treeLink) { if (txtLinkname.getText().equals("")) { if (errMsg.equals("")) { errMsg = rb.getString("exception.LinknameRequired"); } else { errMsg = errMsg + "\n" + rb.getString("exception.LinknameRequired"); } } } if (this.cbxPopup.isVisible()) { return (errMsg.equals("")) && this.panPopupDetails.isModuleValid(); } return (errMsg.equals("")); } public String getValidationError() { if (this.cbxPopup.isVisible()) { if (this.errMsg.length() > 0 && this.panPopupDetails.getValidationError().length() > 0) { this.errMsg += "\n"; } this.errMsg += this.panPopupDetails.getValidationError(); } return errMsg; } public Node getProperties() { Element root = ContentManager.getDomDoc().createElement("linkRoot"); this.module.setDescription(this.txtLinkname.getText()); if (targetViewId > 0) { Element elm = ContentManager.getDomDoc().createElement("internalLink"); CDATASection txtNode = ContentManager.getDomDoc().createCDATASection(this.txtLinkname.getText()); elm.appendChild(txtNode); elm.setAttribute("viewid", targetViewId + ""); elm.setAttribute("level", targetViewLevel); if (anchor != null && !"".equalsIgnoreCase(anchor)) { /* PageNode pageNode = (PageNode) tree.getSelectionPath().getLastPathComponent(); ViewComponentValue vcd = pageNode.getViewComponent(); String[] availableAnchors = this.comm.getAnchors(new Integer(vcd.getReference()).intValue()); ArrayList<String> avAnchorsList = new ArrayList<String>(Arrays.asList(availableAnchors)); HashSet<String> avAnchors = new HashSet<String>(avAnchorsList); if (avAnchors.contains(anchor)) { */ elm.setAttribute("anchor", AbstractModule.getURLEncoded(anchor)); /* } else { if (log.isDebugEnabled()) log.debug("Anchor " + anchor + " does not exist and is NOT saved"); } */ } if (cbxDisplayTypeInline.isSelected()) { elm.setAttribute("displayType", "inline"); } else { elm.setAttribute("displayType", "block"); } root.appendChild(elm); if (this.cbxPopup.isVisible() && this.cbxPopup.isSelected()) { root.appendChild(this.getPanPopupDetails().getProperties()); } } return root; } public void clear() { targetViewId = -1; this.txtLinkname.setText(""); this.module.setDescription(""); if (this.panPopupDetails != null) { this.remove(this.panPopupDetails); } this.panPopupDetails = null; } public void setProperties(Node prop) { setCursor(new Cursor(Cursor.WAIT_CURSOR)); try { ItemListener[] sil = cbxRelatedSites.getItemListeners(); for (int i = 0; i < sil.length; i++) { cbxViewDocuments.removeItemListener(sil[i]); } cbxRelatedSites.removeAllItems(); Iterator<DropDownHolder> sit = linkCache.getSites().iterator(); while (sit.hasNext()) { DropDownHolder ddh = sit.next(); cbxRelatedSites.addItem(ddh); } cbxRelatedSites.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { DropDownHolder currentSite = (DropDownHolder) cbxRelatedSites.getSelectedItem(); switchSitesCombo(currentSite); } } }); // initially select current site and default viewdocument DropDownHolder currentSite = linkCache.getSiteDropDownHolder(comm.getSiteId()); this.switchSitesCombo(currentSite); } catch (Exception e) { log.error("Error on filling sites and viewdocuments-dropdown: " + e.getMessage(), e); } try { Node nde = XercesHelper.findNode(prop, "./popup"); if (nde != null) { this.getPanPopupDetails().setProperties(nde); this.cbxPopup.setSelected(true); } else { if (this.panPopupDetails != null) { this.remove(this.panPopupDetails); } this.panPopupDetails = null; this.cbxPopup.setSelected(false); } this.showPopupPanel(this.cbxPopup.isSelected()); } catch (Exception exe) { } try { // if this will go, it is the new syntax. after that take prop.getFirstChild(); Node nde = XercesHelper.findNode(prop, "./internalLink"); if (nde != null) { // this statement has no effect! // ((Element) nde).getAttribute("viewid"); prop = nde; } } catch (Exception exe) { } String strId = ""; try { strId = ((Element) prop).getAttribute("viewid"); } catch (Exception exe) { } try { String displayType = ((Element) prop).getAttribute("displayType"); this.cbxDisplayTypeInline.setSelected("inline".equalsIgnoreCase(displayType)); } catch (Exception exe) { } if (strId != null && !strId.equalsIgnoreCase("")) { try { String lnkDesc = XercesHelper.getNodeValue(prop); this.txtLinkname.setText(lnkDesc); this.module.setDescription(lnkDesc); } catch (Exception exe) { } targetViewId = rootViewId; try { if (Integer.parseInt(strId) > 0) { targetViewId = new Integer(strId).intValue(); if (log.isDebugEnabled()) log.debug("loading targetViewId " + targetViewId); } } catch (Exception exe) { } anchor = ((Element) prop).getAttribute("anchor"); btnSearchAnker.setEnabled(true); SwingUtilities.invokeLater(new Runnable() { public void run() { try { PageNode pageNode = currentTreeModel.findEntry4Id((PageNode) currentTreeModel.getRoot(), targetViewId); if (pageNode == null) { pageNode = loadTree2View(targetViewId); } if (pageNode != null) { TreePath tp = new TreePath(currentTreeModel.getPathToRoot(pageNode)); if (log.isDebugEnabled()) log.debug("expandit"); tree.expandPath(tp); if (log.isDebugEnabled()) log.debug("setselectionpath"); tree.setSelectionPath(tp); tree.scrollPathToVisible(tp); } else { if (log.isDebugEnabled()) log.debug("Could not find ViewComponent " + targetViewId); } } catch (Exception exe) { log.error("Error setting properties in treemodel thread", exe); } if (anchor != null && !anchor.equals("")) { synchronized (anchor) { searchAnchor(); cboAnker.setSelectedItem(AbstractModule.getURLDecoded(anchor)); } } else { cboAnker.removeAllItems(); } setCursor(Cursor.getDefaultCursor()); if (log.isDebugEnabled()) log.debug("finished runner"); } }); } else { targetViewId = 0; this.txtLinkname.setText(""); anchor = null; setCursor(Cursor.getDefaultCursor()); if (log.isDebugEnabled()) log.debug("Got an invalid internal link - won't resolve it"); } } private PageNode loadTree2View(int targetVId) { if (log.isDebugEnabled()) log.debug("loadTree2View " + targetVId); try { Integer[] vec = comm.getParents4ViewComponent(targetVId); Integer viewId; PageNode pageNode = null; for (int i = 0; i < vec.length; i++) { viewId = vec[i]; pageNode = currentTreeModel.findEntry4Id((PageNode) currentTreeModel.getRoot(), viewId); if (pageNode == null) { // node may be located in another site? ViewDocumentValue vdValue = this.comm.getViewDocument4ViewComponent(viewId); if (vdValue != null) { DropDownHolder site = linkCache.getSiteDropDownHolder(vdValue.getSiteId()); DropDownHolder viewDocument = linkCache.getViewDocumentDropDownHolder(vdValue.getSiteId(), vdValue.getViewDocumentId()); if (site != null && viewDocument != null) { this.switchTree(site, viewDocument); } else { log.warn("The current user \"" + this.comm.getUser().getUserName() + "\" must not access site " + vdValue.getSiteId() + " where the target of this link is located!"); JOptionPane.showMessageDialog(UIConstants.getMainFrame(), rb.getString("content.modules.internalLink.target.unavailable.warning"), rb.getString("content.modules.internalLink.target.unavailable.title"), JOptionPane.WARNING_MESSAGE); } } } else if (!pageNode.isInit()) { pageNode.loadChildren(); if (log.isDebugEnabled()) log.debug("loaded " + i); } } pageNode = currentTreeModel.findEntry4Id((PageNode) currentTreeModel.getRoot(), targetViewId); return pageNode; } catch (Exception exe) { log.error("problem loading the tree to this view " + targetVId, exe); } return null; } private void switchTree(DropDownHolder currentSite, DropDownHolder currentViewDocument) { currentTreeModel = linkCache.getModel(((SiteValue) currentSite.getObject()).getSiteId(), currentViewDocument); tree.setModel(currentTreeModel); tree.setCellRenderer(new CmsTreeRenderer()); tree.validate(); tree.repaint(); validate(); repaint(); cbxRelatedSites.setSelectedItem(currentSite); cbxViewDocuments.setSelectedItem(currentViewDocument); } public static InternalLinkCache getLinkCache() { return linkCache; } private void switchSitesCombo(DropDownHolder selectedSite) { DropDownHolder defaultViewDocument = null; ItemListener[] il = cbxViewDocuments.getItemListeners(); for (int i = 0; i < il.length; i++) { cbxViewDocuments.removeItemListener(il[i]); } cbxViewDocuments.removeAllItems(); Iterator<DropDownHolder> it = linkCache.getViewDocuments(((SiteValue) selectedSite.getObject()).getSiteId()).iterator(); while (it.hasNext()) { DropDownHolder ddh = it.next(); cbxViewDocuments.addItem(ddh); if (((ViewDocumentValue) ddh.getObject()).isIsVdDefault()) defaultViewDocument = ddh; } cbxViewDocuments.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { DropDownHolder currentSite = (DropDownHolder) cbxRelatedSites.getSelectedItem(); DropDownHolder currentViewDocument = (DropDownHolder) cbxViewDocuments.getSelectedItem(); switchTree(currentSite, currentViewDocument); } } }); if (selectedSite != null && defaultViewDocument != null) switchTree(selectedSite, defaultViewDocument); } public int getLinkTarget() { return this.targetViewId; } public String getLinkName() { return this.txtLinkname.getText(); } public void setPopupAvailable(boolean available) { this.cbxPopup.setVisible(available); } }