update author list in license for (JAL-826)
[jalview.git] / src / jalview / gui / BlogReader.java
1 /*******************************************************************************
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
4  *
5  * This file is part of Jalview.
6  *
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  *******************************************************************************/
18 package jalview.gui;
19
20 import jalview.bin.Cache;
21 import java.awt.BorderLayout;
22 import java.awt.Component;
23 import java.awt.Dimension;
24 import java.awt.Font;
25 import java.awt.Rectangle;
26 import java.awt.event.ActionEvent;
27 import java.awt.event.ActionListener;
28 import java.awt.event.KeyEvent;
29 import java.awt.event.MouseEvent;
30 import java.awt.event.WindowAdapter;
31 import java.awt.event.WindowEvent;
32 import java.beans.PropertyChangeListener;
33 import java.text.DateFormat;
34 import java.text.SimpleDateFormat;
35 import java.util.ArrayList;
36 import java.util.Calendar;
37 import java.util.Collections;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Map;
41
42 import javax.swing.AbstractAction;
43 import javax.swing.AbstractButton;
44 import javax.swing.Action;
45 import javax.swing.DefaultListCellRenderer;
46 import javax.swing.DefaultListModel;
47 import javax.swing.Icon;
48 import javax.swing.ImageIcon;
49 import javax.swing.JButton;
50 import javax.swing.JFrame;
51 import javax.swing.JLabel;
52 import javax.swing.JList;
53 import javax.swing.JMenuItem;
54 import javax.swing.JPanel;
55 import javax.swing.JPopupMenu;
56 import javax.swing.JScrollPane;
57 import javax.swing.JSplitPane;
58 import javax.swing.JToolBar;
59 import javax.swing.ListSelectionModel;
60 import javax.swing.SwingUtilities;
61 import javax.swing.event.HyperlinkEvent;
62 import javax.swing.event.HyperlinkListener;
63 import javax.swing.event.ListSelectionEvent;
64 import javax.swing.event.ListSelectionListener;
65
66 import org.robsite.jswingreader.action.MarkChannelAsRead;
67 import org.robsite.jswingreader.action.MarkChannelAsUnread;
68 import org.robsite.jswingreader.action.MarkItemAsRead;
69 import org.robsite.jswingreader.action.MarkItemAsUnread;
70 import org.robsite.jswingreader.action.UpdatableAction;
71 import org.robsite.jswingreader.model.Channel;
72 import org.robsite.jswingreader.model.ChannelListModel;
73 import org.robsite.jswingreader.model.Item;
74 import org.robsite.jswingreader.model.SimpleRSSParser;
75 import org.robsite.jswingreader.ui.BlogContentPane;
76 import org.robsite.jswingreader.ui.ItemReadTimer;
77 import org.robsite.jswingreader.ui.Main;
78 import org.robsite.jswingreader.ui.util.ContextMenuMouseAdapter;
79
80 /**
81  * Blog reading window, adapted from JSwingReader's
82  * org.robsite.jswingreader.ui.MainWindow class
83  */
84
85 public class BlogReader extends JPanel
86 {
87   private JButton buttonRefresh = new JButton();
88
89   private JToolBar toolBar = new JToolBar();
90
91   private JLabel statusBar = new JLabel();
92
93   private JPanel panelMain = new JPanel();
94
95   private BorderLayout layoutMain = new BorderLayout();
96
97   private BorderLayout borderLayout1 = new BorderLayout();
98
99   private JPanel topPanel = new JPanel();
100
101   private JPanel bottomPanel = new JPanel();
102
103   private JSplitPane topBottomSplitPane = new JSplitPane();
104
105   private JList listItems = new JList(new DefaultListModel());
106
107   // SWITCH IN JALVIEW HTML VIEWER PANE HERE
108   private BlogContentPane textDescription = new BlogContentPane();
109
110   // ADD IN JALVIEW BANNER FOR PRETTINESS
111   private BorderLayout borderLayout4 = new BorderLayout();
112
113   private BorderLayout borderLayout5 = new BorderLayout();
114
115   private ChannelListModel _channelModel = null;
116
117   private JList listChannels = new JList();
118
119   private Action exitAction = new Action()
120   {
121
122     @Override
123     public void actionPerformed(ActionEvent arg0)
124     {
125       if (xf!=null)
126       {
127         xf.dispose();
128       }
129       xf=null;jd=null;
130       if (parent != null)
131       {
132         parent.showNews(false);
133       }
134
135     }
136
137     @Override
138     public void setEnabled(boolean arg0)
139     {
140
141     }
142
143     @Override
144     public void removePropertyChangeListener(PropertyChangeListener arg0)
145     {
146       // TODO Auto-generated method stub
147
148     }
149
150     @Override
151     public void putValue(String arg0, Object arg1)
152     {
153       // TODO Auto-generated method stub
154
155     }
156
157     @Override
158     public boolean isEnabled()
159     {
160       // TODO Auto-generated method stub
161       return true;
162     }
163
164     @Override
165     public Object getValue(String arg0)
166     {
167       // TODO Auto-generated method stub
168       return null;
169     }
170
171     @Override
172     public void addPropertyChangeListener(PropertyChangeListener arg0)
173     {
174       // TODO Auto-generated method stub
175
176     }
177   };
178
179   private JFrame xf = null;
180
181   private JalviewDialog jd = null;
182
183   private JalviewDialog createDialog()
184   {
185
186     return jd = new JalviewDialog()
187     {
188
189       @Override
190       protected void raiseClosed()
191       {
192         if (parent != null)
193         {
194           Cache.log.info("News window closed.");
195           jd=null;
196           parent.showNews(false);
197         }
198       }
199
200       @Override
201       protected void okPressed()
202       {
203         // TODO Auto-generated method stub
204
205       }
206
207       @Override
208       protected void cancelPressed()
209       {
210         // TODO Auto-generated method stub
211
212       }
213     };
214   };
215
216   private JLabel lblChannels = new JLabel();
217
218   private List _updatableActions = new ArrayList();
219
220   private ItemReadTimer _itemTimer = null;
221
222   private JPopupMenu _popupItems = null;
223
224   private JPopupMenu _popupChannels = null;
225
226   private String lastm = "";
227
228   private boolean newsnew = false;
229
230   private Desktop parent = null;
231
232   BlogReader()
233   {
234     this(null);
235   }
236
237   // should we ignore fake gui events
238   private boolean updating = false;
239
240   public BlogReader(Desktop desktop)
241   {
242     Cache.log.info("Constructing news reader.");
243
244     parent = desktop;
245     _channelModel = new ChannelListModel();
246     // Construct our jalview news channel
247     Channel chan = new Channel();
248     chan.setURL(jalview.bin.Cache.getDefault(
249             "JALVIEW_NEWS_RSS",
250             jalview.bin.Cache.getDefault("www.jalview.org",
251                     "http://www.jalview.org") + "/feeds/desktop/rss"));
252     loadLastM();
253     _channelModel.addChannel(chan);
254     updating = true;
255     try
256     {
257       jbInit();
258       postInit();
259     } catch (Exception e)
260     {
261       e.printStackTrace();
262     }
263
264     initItems(chan);
265     updating = false;
266     boolean setvisible = checkForNew(chan, true);
267
268     if (setvisible)
269     {
270
271       Cache.log.info("Will show jalview news automatically");
272       showNews();
273     }
274     Cache.log.info("Completed construction of reader.");
275
276   }
277
278   /**
279    * check if the news panel's container is visible
280    */
281   public boolean isVisible()
282   {
283     if (parent == null)
284     {
285       return xf != null && xf.isVisible();
286     }
287     return jd != null && jd.isVisible();
288   }
289
290   /**
291    * display the container for the news panel
292    */
293   public void showNews()
294   {
295     final BlogReader me = this;
296     SwingUtilities.invokeLater(new Runnable()
297     {
298       @Override
299       public void run()
300       {
301         Rectangle bounds = new Rectangle(5, 5, 550, 350);
302         if (parent == null)
303         {
304           xf = new JFrame();
305           xf.setContentPane(me);
306           xf.addWindowListener(new WindowAdapter()
307           {
308             public void windowClosing(WindowEvent e)
309             {
310               ActionEvent actionEvent = new ActionEvent(this,
311                       ActionEvent.ACTION_FIRST, (String) exitAction
312                               .getValue(Action.NAME));
313               exitAction.actionPerformed(actionEvent);
314             }
315
316             public void windowOpened(WindowEvent e)
317             {
318             }
319           });
320           me.setSize(new Dimension(550, 350));
321           xf.setVisible(true);
322         }
323         else
324         {
325           createDialog();
326           bounds = new Rectangle(5, 5, 550, 350);
327           jd.initDialogFrame(me, true, false, "News from www.jalview.org",
328                   bounds.width, bounds.height);
329           Cache.log.info("Displaying news.");
330           jd.waitForInput();
331         }
332       }
333     });
334   }
335
336   /**
337    * update hasnew flag and mark all new messages as unread.
338    */
339   private boolean checkForNew(Channel chan, boolean updateItems)
340   {
341
342     if (!updating || updateItems)
343     {
344       newsnew = false;
345     }
346     java.util.Date earliest = null;
347     try
348     {
349       earliest = new SimpleDateFormat("YYYY-MM-DD").parse(chan
350               .getHTTPLastModified());
351     } catch (Exception x)
352     {
353     }
354     ;
355     if (chan != null && chan.getItems() != null)
356     {
357       Cache.log.debug("Scanning news items: newsnew=" + newsnew
358               + " and lastDate is " + lastDate);
359       for (Item i : (List<Item>) chan.getItems())
360       {
361         boolean isread = lastDate == null ? false
362                 : (i.getPublishDate() != null && !lastDate.before(i
363                         .getPublishDate()));
364
365         if (!updating || updateItems)
366         {
367           newsnew |= !isread;
368         }
369         if (updateItems)
370         {
371           i.setRead(isread);
372         }
373         if (i.getPublishDate() != null && !i.isRead())
374         {
375           if (earliest == null || earliest.after(i.getPublishDate()))
376           {
377             earliest = i.getPublishDate();
378           }
379         }
380       }
381     }
382     if (!updateItems && !updating && lastDate == null)
383     {
384       lastDate = earliest;
385     }
386     return newsnew;
387   }
388
389   java.util.Date lastDate = null;
390
391   private void loadLastM()
392   {
393     lastDate = Cache.getDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED");
394   }
395
396   private void saveLastM(Item item)
397   {
398     if (item != null)
399     {
400       if (item.getPublishDate() != null)
401       {
402         if (lastDate == null || item.getPublishDate().after(lastDate))
403         {
404           lastDate = item.getPublishDate();
405         }
406       }
407
408       if (_channelModel.getElementAt(0) != null)
409       {
410         checkForNew((Channel) _channelModel.getElementAt(0), false);
411       }
412       if (lastDate != null)
413       {
414         jalview.bin.Cache.setDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED",
415                 lastDate);
416         jalview.bin.Cache.log.info("Saved last read date as "
417                 + jalview.bin.Cache.date_format.format(lastDate));
418
419       }
420     }
421   }
422
423   private void jbInit() throws Exception
424   {
425     setLayout(layoutMain);
426     panelMain.setLayout(borderLayout1);
427     topPanel.setLayout(borderLayout5);
428     bottomPanel.setLayout(borderLayout4);
429     topBottomSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
430     topBottomSplitPane.setDividerLocation(100);
431     topBottomSplitPane.setTopComponent(topPanel);
432     topBottomSplitPane.setBottomComponent(bottomPanel);
433     JScrollPane spTextDescription = new JScrollPane(textDescription);
434     textDescription.setText("");
435     statusBar.setText(" [Status] ");
436     buttonRefresh.addActionListener(new ActionListener()
437     {
438
439       @Override
440       public void actionPerformed(ActionEvent e)
441       {
442         refreshNews();
443       }
444     });
445     add(statusBar, BorderLayout.SOUTH);
446     toolBar.add(buttonRefresh);
447     toolBar.addSeparator();
448     JLabel about = new JLabel(
449             "brought to you by JSwingReader (jswingreader.sourceforge.net)");
450     toolBar.add(about);
451     toolBar.setFloatable(false);
452     add(toolBar, BorderLayout.NORTH);
453     panelMain.add(topBottomSplitPane, BorderLayout.CENTER);
454     add(panelMain, BorderLayout.CENTER);
455     JScrollPane spListItems = new JScrollPane(listItems);
456     listItems
457             .setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
458     topPanel.add(spListItems, BorderLayout.CENTER);
459     bottomPanel.add(spTextDescription, BorderLayout.CENTER);
460     listChannels.setModel(_channelModel);
461
462     listItems.addMouseListener(new java.awt.event.MouseAdapter()
463     {
464       public void mouseClicked(MouseEvent e)
465       {
466         listItems_mouseClicked(e);
467       }
468     });
469     _popupItems = _buildItemsPopupMenu();
470     _popupChannels = _buildChannelsPopupMenu();
471     ContextMenuMouseAdapter popupAdapter = new ContextMenuMouseAdapter(
472             _popupItems);
473     ContextMenuMouseAdapter popupChannelsAdapter = new ContextMenuMouseAdapter(
474             _popupChannels);
475     listItems.addMouseListener(popupAdapter);
476     listItems.setCellRenderer(new ItemsRenderer());
477     lblChannels.setText("Channels");
478   }
479
480   private void postInit()
481   {
482     // clear the default hyperlink listener and replace with our own.
483     for (HyperlinkListener hll : textDescription.getHyperlinkListeners())
484     {
485       textDescription.removeHyperlinkListener(hll);
486     }
487     textDescription.addHyperlinkListener(new HyperlinkListener()
488     {
489       public void hyperlinkUpdate(HyperlinkEvent e)
490       {
491         if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
492         {
493           Desktop.showUrl(e.getURL().toExternalForm());
494         }
495       }
496     });
497
498     listItems.addListSelectionListener(new ListSelectionListener()
499     {
500       public void valueChanged(ListSelectionEvent e)
501       {
502         if (e.getValueIsAdjusting() == false)
503         {
504           _itemsValueChanged(listItems);
505         }
506       }
507     });
508     listChannels.setSelectedIndex(1);
509     _updateAllActions();
510     _updateToolbarButtons();
511
512     _itemTimer = new ItemReadTimer(listChannels, listItems);
513     _itemsValueChanged(listItems);
514   }
515
516   public class LaunchJvBrowserOnItem extends AbstractAction implements
517           UpdatableAction
518   {
519     JList _listItems = null;
520
521     public LaunchJvBrowserOnItem(JList listItems)
522     {
523       super("Open in Browser");
524       this.putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_O));
525       this.putValue(Action.LONG_DESCRIPTION, "Open in Browser");
526       _listItems = listItems;
527     }
528
529     public void actionPerformed(ActionEvent e)
530     {
531       Object o = _listItems.getSelectedValue();
532       if (o instanceof Item)
533       {
534         Item item = (Item) o;
535         item.setRead(true);
536         _listItems.repaint();
537
538         Desktop.showUrl(item.getLink());
539       }
540     }
541
542     public void update(Object o)
543     {
544       setEnabled(true);
545       if (_listItems == null || _listItems.getModel().getSize() == 0)
546       {
547         setEnabled(false);
548       }
549       else if (_listItems.getSelectedIndex() == -1)
550       {
551         setEnabled(false);
552       }
553     }
554
555   }
556
557   private JPopupMenu _buildItemsPopupMenu()
558   {
559     JPopupMenu popup = new JPopupMenu();
560     popup.add(new JMenuItem(new LaunchJvBrowserOnItem(listItems)));
561     popup.addSeparator();
562     popup.add(new JMenuItem(new MarkItemAsRead(listItems)));
563     popup.add(new JMenuItem(new MarkItemAsUnread(listItems)));
564     return popup;
565   }
566
567   private JPopupMenu _buildChannelsPopupMenu()
568   {
569     JPopupMenu popup = new JPopupMenu();
570     popup.add(new JMenuItem(new MarkChannelAsRead(listChannels, listItems)));
571     popup.add(new JMenuItem(
572             new MarkChannelAsUnread(listChannels, listItems)));
573     return popup;
574   }
575
576   private void initItems(Channel channel)
577   {
578     if (channel == null)
579     {
580       channel = new Channel();
581     }
582     if (!channel.isOpen() && channel.getURL() != null)
583     {
584       try
585       {
586         SimpleRSSParser.parse(channel);
587       } catch (Exception ex)
588       {
589         ex.printStackTrace();
590       }
591     }
592     DefaultListModel itemsModel = (DefaultListModel) listItems.getModel();
593     itemsModel.clear();
594     Iterator iter = (channel.getItems() != null) ? channel.getItems()
595             .iterator() : Collections.EMPTY_LIST.iterator();
596     while (iter.hasNext())
597     {
598       itemsModel.addElement(iter.next());
599     }
600     if (itemsModel.getSize() > 0)
601     {
602       listItems.setSelectedIndex(0);
603       _itemsValueChanged(listItems);
604     }
605     setStatusBarText(channel.getURL());
606     _updateAllActions();
607   }
608
609   private void _itemsValueChanged(JList itemList)
610   {
611     Item item = (Item) itemList.getSelectedValue();
612     if (item == null)
613     {
614       if (itemList.getModel().getSize() > 0)
615       {
616         item = (Item) itemList.getModel().getElementAt(0);
617       }
618       if (item == null)
619       {
620         item = new Item();
621       }
622       else
623       {
624         itemList.setSelectedIndex(0);
625       }
626     }
627
628     if (_itemTimer != null)
629     {
630       // prefer a shorter delay than 5s
631       _itemTimer.setDelay(300);
632       _itemTimer.start();
633       _itemTimer.setLastItem(item);
634       final Item lastitem = item;
635       _itemTimer.addActionListener(new ActionListener()
636       {
637
638         @Override
639         public void actionPerformed(ActionEvent e)
640         {
641           saveLastM(lastitem);
642         }
643       });
644     }
645
646     setStatusBarText(item.getLink());
647     textDescription.setBlogText(item);
648     _updateAllActions();
649   }
650
651   public void setStatusBarText(String text)
652   {
653     statusBar.setText(text);
654   }
655
656   private void _updateAllActions()
657   {
658     Iterator iter = _updatableActions.iterator();
659     while (iter.hasNext())
660     {
661       UpdatableAction action = (UpdatableAction) iter.next();
662       action.update(this);
663     }
664   }
665
666   private void _updateToolbarButtons()
667   {
668     Map general = (Map) Main.getPreferences().get("general");
669     if (general == null)
670     {
671       return;
672     }
673
674     Component[] components = toolBar.getComponents();
675     for (int i = 0; i < components.length; i++)
676     {
677       Component component = components[i];
678       if (component instanceof JButton)
679       {
680         JButton button = (JButton) component;
681         if (Boolean.toString(false).equals(general.get("useToolBarText")))
682         {
683           // Remove the text if preferences state no toolbar text
684           button.setText("");
685         }
686         if (Boolean.toString(true).equals(general.get("radioTextBelow")))
687         {
688           button.setVerticalTextPosition(AbstractButton.BOTTOM);
689           button.setHorizontalTextPosition(AbstractButton.CENTER);
690         }
691         else if (Boolean.toString(true).equals(
692                 general.get("radioTextRight")))
693         {
694           button.setVerticalTextPosition(AbstractButton.CENTER);
695           button.setHorizontalTextPosition(AbstractButton.RIGHT);
696         }
697       }
698     }
699   }
700
701   private void listItems_mouseClicked(MouseEvent e)
702   {
703     if (e.getClickCount() == 2 && e.getModifiersEx() == MouseEvent.NOBUTTON)
704     {
705       Item item = (Item) listItems.getSelectedValue();
706       item.setRead(true);
707       saveLastM(item);
708       if (_itemTimer != null)
709       {
710         _itemTimer.stop();
711       }
712
713       Action action = new LaunchJvBrowserOnItem(listItems);
714       ActionEvent event = new ActionEvent(this,
715               ActionEvent.ACTION_PERFORMED, "LaunchBrowserOnItem");
716       action.actionPerformed(event);
717     }
718   }
719
720   /**
721    * force the news panel to refresh
722    */
723   public void refreshNews()
724   {
725     try
726     {
727       initItems((Channel) _channelModel.getElementAt(0));
728
729     } catch (Exception x)
730     {
731     }
732   }
733
734   public static void main(String args[])
735   {
736     // this tests the detection of new news based on the last read date stored
737     // in jalview properties
738     jalview.bin.Cache.loadProperties(null);
739     jalview.bin.Cache.initLogger();
740     // test will advance read date each time
741     Calendar today = Calendar.getInstance(), lastread = Calendar
742             .getInstance();
743     lastread.set(1983, 01, 01);
744     while (lastread.before(today))
745     {
746       Cache.setDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED",
747               lastread.getTime());
748       BlogReader me = new BlogReader();
749       System.out.println("Set last date to "
750               + jalview.bin.Cache.date_format.format(lastread.getTime()));
751       if (me.isNewsNew())
752       {
753         Cache.log.info("There is news to read.");
754       }
755       else
756       {
757         Cache.log.info("There is no new news.");
758         me.xf.setTitle("Testing : Last read is " + me.lastDate);
759         me.showNews();
760         me.xf.toFront();
761       }
762       Cache.log.info("Waiting for closure.");
763       do
764       {
765         try
766         {
767           Thread.sleep(300);
768         } catch (InterruptedException x)
769         {
770         }
771         ;
772       } while (me.isVisible());
773
774       if (me.isNewsNew())
775       {
776         Cache.log.info("Still new news after reader displayed.");
777       }
778       if (lastread.getTime().before(me.lastDate))
779       {
780         Cache.log.info("The news was read.");
781         lastread.setTime(me.lastDate);
782       }
783       else
784       {
785         lastread.add(Calendar.MONTH, 1);
786       }
787       
788     }
789   }
790
791   boolean isNewsNew()
792   {
793     return newsnew;
794   }
795 }
796
797 class ChannelsRenderer extends DefaultListCellRenderer
798 {
799   private final static Icon _icon = new ImageIcon(
800           Main.class.getResource("image/ComposeMail16.gif"));
801
802   public Component getListCellRendererComponent(JList list, Object value,
803           int index, boolean isSelected, boolean cellHasFocus)
804   {
805     JLabel component = (JLabel) super.getListCellRendererComponent(list,
806             value, index, isSelected, cellHasFocus);
807     component.setIcon(ChannelsRenderer._icon);
808     if (value instanceof Channel)
809     {
810       Channel channel = (Channel) value;
811       component.setText(channel.getTitle() + " ("
812               + channel.getUnreadItemCount() + ")");
813       component.setToolTipText(channel.getURL());
814     }
815     return component;
816   }
817 }
818
819 class ItemsRenderer extends DefaultListCellRenderer
820 {
821   private final static Icon _icon = new ImageIcon(
822           Main.class.getResource("image/ComposeMail16.gif"));
823
824   public Component getListCellRendererComponent(JList list, Object value,
825           int index, boolean isSelected, boolean cellHasFocus)
826   {
827     JLabel component = (JLabel) super.getListCellRendererComponent(list,
828             value, index, isSelected, cellHasFocus);
829     component.setIcon(ItemsRenderer._icon);
830     if (value instanceof Item)
831     {
832       Item item = (Item) value;
833       if (item.getPublishDate() != null)
834       {
835         component.setText(DateFormat.getDateInstance().format(
836                 item.getPublishDate())
837                 + " " + item.getTitle());
838       }
839       component.setToolTipText(item.getLink());
840       if (!item.isRead())
841       {
842         component.setFont(component.getFont().deriveFont(Font.BOLD));
843       }
844       else
845       {
846         component.setFont(component.getFont().deriveFont(Font.PLAIN));
847       }
848     }
849     return component;
850   }
851 }