package org.docear.plugin.services.recommendations.mode; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.border.EmptyBorder; import javax.swing.border.TitledBorder; import org.docear.plugin.core.DocearController; import org.docear.plugin.core.event.DocearEvent; import org.docear.plugin.core.event.DocearEventType; import org.docear.plugin.core.io.IOTools; import org.docear.plugin.services.ServiceController; import org.docear.plugin.services.communications.CommunicationsController; import org.docear.plugin.services.recommendations.RecommendationEntry; import org.docear.plugin.services.recommendations.dialog.RecommendationEntryComponent; import org.docear.plugin.services.recommendations.mode.DocearRecommendationsNodeModel.RecommendationContainer; import org.freeplane.core.util.LogUtils; import org.freeplane.core.util.TextUtils; import org.freeplane.features.map.MapModel; import org.freeplane.features.map.NodeModel; import org.freeplane.features.mode.Controller; import org.freeplane.features.mode.ModeController; import org.freeplane.view.swing.map.MapView; import org.freeplane.view.swing.map.NodeView; public class DocearRecommendationsMapView extends MapView { private final class ListLayoutManager implements LayoutManager { public void removeLayoutComponent(Component comp) { } public Dimension preferredLayoutSize(Container parent) { if(parent.getComponentCount() > 0) { Dimension compPref = parent.getComponent(0).getPreferredSize(); // for(Component comp : parent.getComponents()) { // // } Insets insets = new Insets(0, 0, 0, 0); if(parent instanceof JComponent) { insets = ((JComponent) parent).getInsets(); } return new Dimension(compPref.width+insets.left+insets.right, compPref.height*parent.getComponentCount()+insets.top+insets.bottom); } return new Dimension(); } public Dimension minimumLayoutSize(Container parent) { return parent.getMinimumSize(); } public void layoutContainer(Container parent) { int i = parent.getComponentCount()-1; if(i < 0) { return; } Insets insets = new Insets(0, 0, parent.getHeight(), parent.getWidth()); if(parent instanceof JComponent) { insets = ((JComponent) parent).getInsets(); } int width = parent.getWidth()-insets.left-insets.right; int height = parent.getComponent(0).getPreferredSize().height; int x = insets.left; for(; i >= 0; i-- ) { Component comp = parent.getComponent(i); int y = i*height + insets.top; comp.setBounds(x, y, width, height); } } public void addLayoutComponent(String name, Component comp) { } } private static final long serialVersionUID = 1L; public DocearRecommendationsMapView(final MapModel model, final ModeController modeController) { super(model, modeController); this.setLayout(new BorderLayout()); //this.removeAll(); layoutModel(model); } private void layoutModel(MapModel model) { NodeModel node = model.getRootNode(); layoutModel(node, null); } private void layoutModel(NodeModel node, Container parent) { if (node != null) { Object obj = node.getUserObject(); Container container = parent; if (obj instanceof RecommendationEntry) { JComponent comp = getRecommendationComponent((RecommendationEntry) obj); container.add(comp); } else { if(obj instanceof RecommendationContainer) { container = getNewRecommandationContainerComponent(obj.toString()); this.add(container); } else { if(container == null) { container = getNewEmptyContainerComponent(); this.add(container); } if(obj instanceof Component) { container.add((Component) obj); } else { container.add(new JLabel(obj.toString())); } } } if (node.hasChildren()) { for (NodeModel child : node.getChildren()) { layoutModel(child, container); } } } } private JComponent getRecommendationComponent(final RecommendationEntry recommendation) { RecommendationEntryComponent comp = new RecommendationEntryComponent(recommendation); comp.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { URL page = recommendation.getClickUrl(); try { page = redirectRecommendationLink(recommendation, page); } catch (Exception ex) { //click didn't work LogUtils.info(ex.getMessage()); } if(e.getID() == RecommendationEntryComponent.OPEN_RECOMMENDATION) { try { Controller.getCurrentController().getViewController().openDocument(page); } catch (Exception ex) { LogUtils.warn("could not open link to (" + recommendation.getLink() + ")", ex); } } else if(e.getID() == RecommendationEntryComponent.IMPORT_RECOMMENDATION) { DocearController.getController().dispatchDocearEvent(new DocearEvent(page, DocearEventType.IMPORT_TO_LIBRARY, recommendation.getTitle())); } } private URL redirectRecommendationLink(final RecommendationEntry recommendation, URL page) throws IOException, MalformedURLException { URLConnection connection; connection = recommendation.getClickUrl().openConnection(); if(connection instanceof HttpURLConnection) { HttpURLConnection hconn = (HttpURLConnection) connection; hconn.setInstanceFollowRedirects(false); String accessToken = CommunicationsController.getController().getAccessToken(); hconn.addRequestProperty("accessToken", accessToken); int response = hconn.getResponseCode(); boolean redirect = (response >= 300 && response <= 399); /* * In the case of a redirect, we want to actually change the URL * that was input to the new, redirected URL */ if (redirect) { String loc = connection.getHeaderField("Location"); if (loc.startsWith("http", 0)) { page = new URL(loc); } else { page = new URL(page, loc); } } else { if(response == 200) { String content = IOTools.getStringFromStream(connection.getInputStream(), "UTF-8"); String searchPattern = "<meta http-equiv=\"REFRESH\" content=\"0;url="; int pos = content.indexOf(searchPattern); if(pos >= 0) { String loc = content.substring(pos+searchPattern.length()); loc = loc.substring(0,loc.indexOf("\"")); if (loc.startsWith("http", 0)) { page = new URL(loc); } else { page = new URL(page, loc); } } } } } return page; } }); return comp; } private Container getNewRecommandationContainerComponent(String title) { JPanel panel = new JPanel(); panel.setBackground(Color.white); panel.setBorder(new TitledBorder(title)); panel.setLayout(new ListLayoutManager()); this.add(getNewButtonBar(), BorderLayout.NORTH); this.add(panel, BorderLayout.CENTER); return panel; } private Component getNewButtonBar() { JPanel panel = new JPanel(new LayoutManager() { public void removeLayoutComponent(Component comp) { } public Dimension preferredLayoutSize(Container parent) { int count = parent.getComponentCount(); for(Component comp : parent.getComponents()) { Dimension comDim = comp.getPreferredSize(); if(comDim != null) { return new Dimension((parent.getInsets().left+parent.getInsets().right+comDim.width)*count, parent.getInsets().top+parent.getInsets().bottom+comDim.height); } } return null; } public Dimension minimumLayoutSize(Container parent) { for(Component comp : parent.getComponents()) { int count = parent.getComponentCount(); Dimension comDim = comp.getMinimumSize(); if(comDim != null) { return new Dimension((parent.getInsets().left+parent.getInsets().right+comDim.width)*count, parent.getInsets().top+parent.getInsets().bottom+comDim.height); } } return null; } public void layoutContainer(Container parent) { int right = parent.getWidth()-parent.getInsets().right; int top = parent.getInsets().top; int count = parent.getComponentCount(); for(Component comp : parent.getComponents()) { int x = right-comp.getWidth()*count; comp.setLocation(x,top); comp.setSize(comp.getPreferredSize()); count--; } } public void addLayoutComponent(String name, Component comp) { } }); panel.setBackground(Color.white); panel.setBorder(new EmptyBorder(5, 5, 0, 5)); JButton refreshButton = new JButton(new ImageIcon(RecommendationEntryComponent.class.getResource("/icons/view-refresh-7_32x32.png"))); refreshButton.setMinimumSize(new Dimension(50, 50)); refreshButton.setPreferredSize(new Dimension(50, 50)); refreshButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ServiceController.getController().getRecommenationMode().getMapController().refreshRecommendations(); } }); refreshButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); refreshButton.setToolTipText(TextUtils.getText("recommendations.refresh.title")); panel.add(refreshButton); JButton closeButton = new JButton(new ImageIcon(RecommendationEntryComponent.class.getResource("/icons/window-close-2_32x32.png"))); closeButton.setMinimumSize(new Dimension(50, 50)); closeButton.setPreferredSize(new Dimension(50, 50)); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { SwingUtilities.invokeLater(new Runnable() { public void run() { Controller.getCurrentController().close(true); } }); } }); closeButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); closeButton.setToolTipText(TextUtils.getText("recommendations.close.title")); panel.add(closeButton); return panel; } private Container getNewEmptyContainerComponent() { JPanel panel = new JPanel(); panel.setBackground(Color.white); panel.setLayout(new ListLayoutManager()); this.add(getNewButtonBar(), BorderLayout.NORTH); this.add(panel, BorderLayout.CENTER); //this.add(panel); return panel; } public void paint(Graphics g) { try { super.paintInternal(g); } catch (Exception ex) { //DOCEAR - maybe reset to mind map mode //Controller.getCurrentController().selectMode(MModeController.MODENAME); } } public void paintChildren(Graphics g) { super.paintChildrenInternal(g); } public Component add(Component comp, int index) { return super.add(comp, index); } public void centerNode(final NodeView node, boolean slowScroll) { node.setLocation(-9999, -9999); } }