001: /*
002: * Lucane - a collaborative platform
003: * Copyright (C) 2004 Vincent Fiack <vfiack@mail15.com>
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package org.lucane.applications.rssreader.gui;
021:
022: import java.awt.*;
023: import java.awt.event.*;
024: import java.net.ConnectException;
025: import java.net.MalformedURLException;
026: import java.util.ArrayList;
027: import java.util.Collection;
028: import java.util.Collections;
029: import java.util.Iterator;
030:
031: import javax.swing.*;
032: import javax.swing.event.*;
033:
034: import org.jperdian.rss2.RssException;
035: import org.jperdian.rss2.dom.RssChannel;
036: import org.jperdian.rss2.dom.RssItem;
037: import org.lucane.applications.rssreader.RssReader;
038: import org.lucane.applications.rssreader.rss.ChannelInfo;
039: import org.lucane.applications.rssreader.rss.RssItemComparator;
040: import org.lucane.client.Client;
041: import org.lucane.client.Plugin;
042: import org.lucane.client.PluginManager;
043: import org.lucane.client.util.WidgetState;
044: import org.lucane.client.widgets.DialogBox;
045: import org.lucane.client.widgets.ManagedWindow;
046: import org.lucane.common.ConnectInfo;
047:
048: public class MainFrame extends ManagedWindow implements
049: ListSelectionListener, ActionListener, MouseListener {
050: private JButton btnRefresh;
051: private JButton btnAggregate;
052: private JButton btnAddChannel;
053: private JButton btnRemoveChannel;
054: private JButton btnHelp;
055:
056: private JSplitPane split;
057: private JList channels;
058: private JList items;
059: private DefaultListModel rssChannels;
060: private DefaultListModel rssItems;
061: private JProgressBar status;
062: private RssReader plugin;
063:
064: public MainFrame(RssReader plugin) {
065: super (plugin, plugin.getTitle());
066: this .setName("mainFrame");
067:
068: this .plugin = plugin;
069:
070: this .rssChannels = new DefaultListModel();
071: this .rssItems = new DefaultListModel();
072:
073: btnRefresh = new JButton(Client.getImageIcon("refresh.png"));
074: btnRefresh.setToolTipText(plugin.tr("btn.refresh"));
075: btnRefresh.addActionListener(this );
076: btnAggregate = new JButton(plugin.getImageIcon("aggregate.png"));
077: btnAggregate.setToolTipText(plugin.tr("btn.aggregate"));
078: btnAggregate.addActionListener(this );
079: btnAddChannel = new JButton(Client.getImageIcon("add.png"));
080: btnAddChannel.setToolTipText(plugin.tr("btn.addChannel"));
081: btnAddChannel.addActionListener(this );
082: btnRemoveChannel = new JButton(Client
083: .getImageIcon("delete.png"));
084: btnRemoveChannel.setToolTipText(plugin.tr("btn.removeChannel"));
085: btnRemoveChannel.addActionListener(this );
086: btnHelp = new JButton(Client.getImageIcon("help.png"));
087: btnHelp.setToolTipText(plugin.tr("btn.help"));
088: btnHelp.addActionListener(this );
089:
090: JPanel buttonPanel = new JPanel(new BorderLayout());
091: JPanel buttons = new JPanel(new GridLayout(1, 5));
092: buttons.add(btnRefresh);
093: buttons.add(btnAggregate);
094: buttons.add(btnAddChannel);
095: buttons.add(btnRemoveChannel);
096: buttons.add(btnHelp);
097: buttonPanel.add(buttons, BorderLayout.WEST);
098:
099: JPanel channelPanel = new JPanel(new BorderLayout());
100: channels = new JList(rssChannels);
101: channels.addListSelectionListener(this );
102: status = new JProgressBar();
103: channelPanel
104: .add(new JScrollPane(channels), BorderLayout.CENTER);
105: channelPanel.add(status, BorderLayout.SOUTH);
106:
107: items = new JList(rssItems);
108: items.setCellRenderer(new ItemRenderer());
109: items.addMouseListener(this );
110:
111: split = new JSplitPane();
112: split.setName("split");
113: split.setTopComponent(channelPanel);
114: split.setBottomComponent(new JScrollPane(items));
115: split.setOneTouchExpandable(true);
116: split.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
117: split.setDividerLocation(120);
118:
119: getContentPane().add(buttonPanel, BorderLayout.NORTH);
120: getContentPane().add(split, BorderLayout.CENTER);
121:
122: setExitPluginOnClose(true);
123: }
124:
125: public void saveState() {
126: WidgetState.save(plugin.getLocalConfig(), split);
127: }
128:
129: public void restoreState() {
130: WidgetState.restore(plugin.getLocalConfig(), split);
131: }
132:
133: public void actionPerformed(ActionEvent ae) {
134: if (ae.getSource().equals(btnRefresh))
135: valueChanged(null);
136: else if (ae.getSource().equals(btnAggregate))
137: showAllChannels();
138: else if (ae.getSource().equals(btnRemoveChannel)) {
139: ChannelInfo channel = (ChannelInfo) channels
140: .getSelectedValue();
141: if (channel == null)
142: return;
143:
144: if (DialogBox.question(plugin.getTitle(), plugin
145: .tr("msg.removeChannel"))) {
146: plugin.removeChannel(channel);
147: rssItems.clear();
148: }
149: } else if (ae.getSource().equals(btnAddChannel)) {
150: new ChannelDialog(this , plugin).show();
151: } else if (ae.getSource().equals(btnHelp)) {
152: try {
153: Plugin help = PluginManager.getInstance()
154: .newPluginInstance(
155: "org.lucane.applications.helpbrowser",
156: new ConnectInfo[0], true);
157: help.run();
158: help.invoke("showHelp", new Class[] { Plugin.class },
159: new Object[] { plugin });
160: help.invoke("hidePluginList", new Class[0],
161: new Object[0]);
162: } catch (Exception ex) {
163: DialogBox.error(plugin.tr("err.unableToLoadHelp"));
164: ex.printStackTrace();
165: }
166: }
167: }
168:
169: public void valueChanged(ListSelectionEvent lse) {
170: ChannelInfo channel = (ChannelInfo) channels.getSelectedValue();
171: if (channel == null)
172: return;
173:
174: showChannel(channel);
175: }
176:
177: public void refreshChannelList() {
178: rssChannels.clear();
179: Iterator i = plugin.getChannels().iterator();
180: while (i.hasNext())
181: rssChannels.addElement(i.next());
182: }
183:
184: public void showChannel(final ChannelInfo channel) {
185: Runnable refresh = new Runnable() {
186: public void run() {
187: try {
188: rssItems.clear();
189: status.setIndeterminate(true);
190: RssChannel rss = channel.getChannel();
191:
192: Iterator i = rss.getItemList().iterator();
193: while (i.hasNext())
194: rssItems.addElement(i.next());
195: } catch (MalformedURLException mue) {
196: DialogBox.error(plugin.tr("err.wrongUrl") + mue);
197: } catch (RssException re) {
198: //call proxy config if unable to connect
199: if (re.getCause() != null
200: && re.getCause() instanceof ConnectException) {
201: if (DialogBox.question(
202: plugin.tr("err.connect"), plugin
203: .tr("msg.setupProxy")))
204: new ProxyDialog(plugin).show();
205: } else
206: DialogBox.error(plugin.tr("err.rssError") + re);
207: } finally {
208: status.setIndeterminate(false);
209: }
210: }
211: };
212:
213: new Thread(refresh).start();
214: }
215:
216: public void showAllChannels() {
217: Runnable refresh = new Runnable() {
218: public void run() {
219: try {
220: channels.setSelectedValue(null, false);
221: rssItems.clear();
222: status.setIndeterminate(true);
223:
224: Iterator channels = plugin.getChannels().iterator();
225: ArrayList allItems = new ArrayList();
226: while (channels.hasNext()) {
227: ChannelInfo channel = (ChannelInfo) channels
228: .next();
229: Collection items = channel.getChannel()
230: .getItemList();
231: allItems.addAll(items);
232: }
233:
234: Collections.sort(allItems, new RssItemComparator());
235:
236: Iterator i = allItems.iterator();
237: while (i.hasNext())
238: rssItems.addElement(i.next());
239:
240: } catch (MalformedURLException mue) {
241: DialogBox.error(plugin.tr("err.wrongUrl") + mue);
242: } catch (RssException re) {
243: //call proxy config if unable to connect
244: if (re.getCause() != null
245: && re.getCause() instanceof ConnectException) {
246: if (DialogBox.question(
247: plugin.tr("err.connect"), plugin
248: .tr("msg.setupProxy")))
249: new ProxyDialog(plugin).show();
250: } else
251: DialogBox.error(plugin.tr("err.rssError") + re);
252: } finally {
253: status.setIndeterminate(false);
254: }
255: }
256: };
257: new Thread(refresh).start();
258: }
259:
260: public void mousePressed(MouseEvent me) {
261: }
262:
263: public void mouseReleased(MouseEvent me) {
264: }
265:
266: public void mouseEntered(MouseEvent me) {
267: }
268:
269: public void mouseExited(MouseEvent me) {
270: }
271:
272: public void mouseClicked(MouseEvent me) {
273: if (me.getButton() == MouseEvent.BUTTON1
274: && me.getClickCount() == 2) {
275: RssItem item = (RssItem) items.getSelectedValue();
276: if (item == null)
277: return;
278:
279: plugin.openUrl(item.getLink());
280: }
281: }
282: }
|