Source code: com/memoire/bu/BuBrowserFrame.java
1 /**
2 * @modification $Date: 2003/01/16 10:20:37 $
3 * @statut unstable
4 * @file BuBrowserFrame.java
5 * @version 0.36
6 * @author Guillaume Desnoix
7 * @email guillaume@desnoix.com
8 * @license GNU General Public License 2 (GPL2)
9 * @copyright 1998-2001 Guillaume Desnoix
10 */
11
12 package com.memoire.bu;
13
14 import com.memoire.bu.*;
15 import com.memoire.dnd.*;
16 import com.memoire.fu.*;
17 import com.memoire.re.*;
18
19 import java.awt.*;
20 import java.awt.event.*;
21 import java.beans.*;
22 import java.net.*;
23 import java.io.*;
24 import java.util.*;
25
26 import javax.swing.*;
27 import javax.swing.border.*;
28 import javax.swing.event.*;
29 import javax.swing.text.*;
30 import javax.swing.text.html.*;
31
32 /**
33 * A tiny HTML browser.
34 * Is an internal frame on the desktop and an alternative
35 * to an external browser as lynx ;-)
36 */
37
38 public class BuBrowserFrame
39 extends BuInternalFrame
40 implements ActionListener, BuCutCopyPasteInterface
41 {
42 protected BuCommonImplementation app_;
43 protected JComponent content_;
44 protected BuLabel lbUrl_;
45 protected BuLabel lbLink_;
46 protected XHtmlPane pane_;
47
48 protected BuButton btAvancer_;
49 protected BuButton btReculer_;
50 protected BuButton btRafraichir_;
51 protected BuButton btMaison_;
52
53 public BuBrowserFrame()
54 { this(null); }
55
56 public BuBrowserFrame(BuCommonImplementation _app)
57 { this(_app,null); }
58
59 public BuBrowserFrame(BuCommonImplementation _app, String _source)
60 {
61 super("",true,true,true,true);
62 app_=_app;
63
64 setName("ifNAVIGATEUR");
65 if(app_!=null)
66 app_.installContextHelp(getRootPane(),"bu/p-navigateur.html");
67
68 content_=(JComponent)getContentPane();
69 content_.setLayout(new BuBorderLayout(5,5));
70 content_.setBorder(new EmptyBorder(5,5,5,5));
71
72 lbUrl_=new BuLabel("-");
73 lbUrl_.setFont(BuLib.deriveFont("Label",Font.PLAIN,-2));
74 lbUrl_.setBorder(new EmptyBorder(2,2,2,2));
75 content_.add(lbUrl_,BuBorderLayout.NORTH);
76
77 lbLink_=new BuLabel("-");
78 lbLink_.setFont(BuLib.deriveFont("Label",Font.PLAIN,-2));
79 lbLink_.setBorder(new EmptyBorder(2,2,2,2));
80 content_.add(lbLink_,BuBorderLayout.SOUTH);
81
82 pane_=new XHtmlPane();
83 content_.add(pane_,BuBorderLayout.CENTER);
84
85 btAvancer_=new BuButton();
86 btAvancer_.setActionCommand("AVANCER");
87 btAvancer_.setToolTipText
88 (BuResource.BU.getString("Avancer à la page suivante"));
89 btAvancer_.setIcon(BuResource.BU.loadToolCommandIcon("AVANCER"));
90 btAvancer_.setName("btAVANCER");
91 btAvancer_.setRequestFocusEnabled(false);
92 btAvancer_.addActionListener(this);
93
94 btReculer_=new BuButton();
95 btReculer_.setActionCommand("RECULER");
96 btReculer_.setToolTipText
97 (BuResource.BU.getString("Revenir à la page précédente"));
98 btReculer_.setIcon(BuResource.BU.loadToolCommandIcon("RECULER"));
99 btReculer_.setName("btRECULER");
100 btReculer_.setRequestFocusEnabled(false);
101 btReculer_.addActionListener(this);
102
103 btRafraichir_=new BuButton();
104 btRafraichir_.setActionCommand("RAFRAICHIR");
105 btRafraichir_.setToolTipText
106 (BuResource.BU.getString("Rafraîchir la page"));
107 btRafraichir_.setIcon(BuResource.BU.loadToolCommandIcon("RAFRAICHIR"));
108 btRafraichir_.setName("btRAFRAICHIR");
109 btRafraichir_.setRequestFocusEnabled(false);
110 btRafraichir_.addActionListener(this);
111
112 btMaison_=new BuButton();
113 btMaison_.setActionCommand("MAISON");
114 btMaison_.setToolTipText
115 (BuResource.BU.getString("Aller à la page principale"));
116 btMaison_.setIcon(BuResource.BU.getToolIcon("www"));
117 btMaison_.setName("btMAISON");
118 btMaison_.setRequestFocusEnabled(false);
119 btMaison_.addActionListener(this);
120
121 btAvancer_.setEnabled(false);
122 btReculer_.setEnabled(false);
123 //if(app_==null) btMaison_.setEnabled(false);
124
125 /*
126 JRootPane rootpane=getRootPane();
127 KeyStroke ksAvancer=KeyStroke.getKeyStroke
128 (KeyEvent.VK_RIGHT,KeyEvent.CTRL_MASK|KeyEvent.ALT_MASK,false);
129 KeyStroke ksReculer=KeyStroke.getKeyStroke
130 (KeyEvent.VK_LEFT ,KeyEvent.CTRL_MASK|KeyEvent.ALT_MASK,false);
131 ActionListener alAvancer=new ActionListener()
132 {
133 public void actionPerformed(ActionEvent _evt)
134 {
135 BuBrowserFrame.this.actionPerformed
136 (new ActionEvent(BuBrowserFrame.this,
137 ActionEvent.ACTION_PERFORMED,"AVANCER"));
138 }
139 };
140 ActionListener alReculer=new ActionListener()
141 {
142 public void actionPerformed(ActionEvent _evt)
143 {
144 BuBrowserFrame.this.actionPerformed
145 (new ActionEvent(BuBrowserFrame.this,
146 ActionEvent.ACTION_PERFORMED,"RECULER"));
147 }
148 };
149 rootpane.unregisterKeyboardAction(ksAvancer);
150 rootpane.unregisterKeyboardAction(ksReculer);
151 rootpane.registerKeyboardAction
152 (alAvancer,ksAvancer,JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
153 rootpane.registerKeyboardAction
154 (alReculer,ksReculer,JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
155 */
156
157 if(_source!=null) setHtmlSource(_source);
158
159 setTitle(BuResource.BU.getString("Navigateur"));
160 setFrameIcon(BuResource.BU.getFrameIcon("www"));
161
162 Dimension ps=new Dimension(400,500);
163 setSize(ps);
164 setPreferredSize(ps);
165 }
166
167 public void setSelected(boolean _state) throws PropertyVetoException
168 {
169 super.setSelected(_state);
170 if(isSelected()) pane_.requestFocus();
171 }
172
173 public void actionPerformed(ActionEvent _evt)
174 {
175 String action=_evt.getActionCommand();
176 //System.err.println("BuBrowserFrame : "+action);
177
178 if("RECULER".equals(action))
179 {
180 pane_.back();
181 }
182 else
183 if("AVANCER".equals(action))
184 {
185 pane_.forward();
186 }
187 else
188 if("RAFRAICHIR".equals(action))
189 {
190 pane_.reload();
191 }
192 else
193 if("MAISON".equals(action))
194 {
195 if(app_!=null)
196 setDocumentUrl(app_.getInformationsSoftware().baseManUrl());
197 else
198 setHtmlSource(INTRO,"Introduction");
199 }
200 }
201
202 public void setDocumentUrl(URL _url)
203 {
204 setDocumentUrl(""+_url);
205 }
206
207 public void setDocumentUrl(String _s)
208 {
209 try
210 {
211 if(_s.startsWith("mailto:")) throw new MalformedURLException();
212 if(_s.startsWith("https:")) throw new MalformedURLException();
213 if(_s.startsWith("file:")&&_s.endsWith("/")) _s+="index.html";
214 URL url=new URL(_s);
215 pane_.linkActivated(url);
216 }
217 catch (MalformedURLException ex)
218 {
219 setHtmlSource
220 ("<HTML><BODY><P>This URL can not be displayed:</P><SMALL><TT>"+
221 _s+" </TT></SMALL><P>If it is correct, please use an external"+
222 " browser.</P></BODY></HTML>","Error");
223 // System.err.println("Malformed URL: " + ex);
224 }
225 }
226
227 public String getHtmlSource()
228 { return pane_.getHtmlSource(); }
229
230 public void setHtmlSource(String _source)
231 { setHtmlSource(_source,null); }
232
233 public void setHtmlSource(String _source, String _titre)
234 {
235 if((_titre==null)||("".equals(_titre))) _titre=" ";
236 pane_.setHtmlSource(_source,_titre);
237 }
238
239 /**
240 * @deprecated
241 */
242 public JEditorPane getEditorPane()
243 { return pane_.getEditorPane(); }
244
245 class XHtmlPane extends BuScrollPane
246 implements HyperlinkListener
247 {
248 private BuEditorPane html_;
249 private Cursor cursor_;
250 private Vector avant_,apres_;
251
252 public XHtmlPane()
253 {
254 html_=new BuEditorPane();
255 html_.setEditable(false);
256 html_.setBorder(new EmptyBorder(0,0,0,0));
257 html_.addHyperlinkListener(this);
258 cursor_=html_.getCursor();
259 avant_ =new Vector();
260 apres_ =new Vector();
261
262 JViewport vp=getViewport();
263 vp.add(html_);
264 }
265
266 public JEditorPane getEditorPane()
267 { return html_; }
268
269 public void back()
270 {
271 int l=avant_.size();
272 if(l>1)
273 {
274 URL url=(URL)avant_.elementAt(l-2);
275 URL cur=(URL)avant_.elementAt(l-1);
276 System.err.println("BACK "+url);
277 avant_.removeElementAt(l-1);
278 apres_.insertElementAt(cur,0);
279 linkActivated(url);
280 }
281 }
282
283 public void forward()
284 {
285 if(apres_.size()>0)
286 {
287 int l=avant_.size();
288 URL url=(URL)apres_.elementAt(0);
289 URL cur=(URL)avant_.elementAt(l-1);
290 System.err.println("FORWARD "+url);
291 apres_.removeElementAt(0);
292 linkActivated(url);
293 }
294 }
295
296 public void reload()
297 {
298 int l=avant_.size();
299 if(l>0)
300 {
301 URL url=(URL)avant_.elementAt(l-1);
302 System.err.println("RELOAD "+url);
303 avant_.removeElementAt(l-1);
304 setHtmlSource("Reload "+url,"Reload");
305 linkActivated(url);
306 }
307 }
308
309 public void hyperlinkUpdate(HyperlinkEvent _evt)
310 {
311 if(_evt.getEventType()==HyperlinkEvent.EventType.ACTIVATED)
312 {
313 linkActivated(_evt.getURL());
314 }
315 else
316 if(_evt.getEventType()==HyperlinkEvent.EventType.ENTERED)
317 {
318 lbLink_.setText(""+_evt.getURL());
319 }
320 else
321 if(_evt.getEventType()==HyperlinkEvent.EventType.EXITED)
322 {
323 lbLink_.setText("-");
324 }
325 }
326
327 private Runnable current_=null;
328
329 public void linkActivated(final URL _url)
330 {
331 try
332 {
333 String f=_url.getFile();
334 if(f==null) f="";
335 f=f.toLowerCase();
336 if(f.endsWith(".gif")||f.endsWith(".jpg")||f.endsWith(".jpeg"))
337 {
338 setHtmlSource("<IMG SRC=\""+_url+"\">",f);
339 }
340 else
341 {
342 String h=_url.getHost();
343 if((h==null)||"".equals(h)) h="localhost";
344 lbUrl_.setText("Connexion: "+h+" ...");
345 /*
346 new BuTaskOperation
347 (app_,getTitle(),
348 new XPageLoader(_url)).start();
349 */
350 Runnable runnable=new XPageLoader(_url);
351
352 if(!SwingUtilities.isEventDispatchThread())
353 SwingUtilities.invokeLater(runnable);
354 else
355 runnable.run();
356 }
357 }
358 catch(Exception ex)
359 {
360 lbUrl_.setText("Bad URL: "+_url);
361 BuBrowserFrame.this.getToolkit().beep();
362 }
363 }
364
365 public String getHtmlSource()
366 {
367 return html_.getText();
368 }
369
370 public final void setHtmlSource(String _source,String _titre)
371 {
372 setHtmlSource0(_source,_titre);
373 }
374
375 public void setHtmlSource0(final String _source,final String _titre)
376 {
377 Runnable runnable=new Runnable()
378 {
379 public void run()
380 {
381 lbUrl_.setText(_titre);
382
383 try
384 {
385 EditorKit ek=html_.getEditorKitForContentType("text/html");
386 HTMLDocument dk=(HTMLDocument)ek.createDefaultDocument();
387 ek.read(new StringReader(_source),dk,0);
388
389 updateStyles(dk.getStyleSheet());
390
391 /*
392 SimpleAttributeSet s=new SimpleAttributeSet();
393 StyleConstants.setFontFamily(s,"SansSerif");
394 dk.setCharacterAttributes(0,dk.getLength(),s,false);
395 */
396
397 html_.setEditorKit(ek);
398 html_.setDocument(dk);
399 }
400 catch(Exception ex)
401 {
402 html_.setText("Couldn't understand html source.\n\n"+_source);
403 ex.printStackTrace();
404 }
405 }
406 };
407
408 if(!SwingUtilities.isEventDispatchThread())
409 SwingUtilities.invokeLater(runnable);
410 else
411 runnable.run();
412 }
413
414 class XPageLoader implements Runnable
415 {
416 private URL url_;
417
418 XPageLoader(URL _url)
419 {
420 url_=_url;
421 }
422
423 public void run()
424 {
425 boolean encore=true;
426
427 while((current_!=null)&&(current_!=this))
428 {
429 try { Thread.sleep(400); }
430 catch(Exception ex) { }
431 }
432
433 current_=this;
434 html_.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
435
436 while(encore)
437 {
438 if(url_==null)
439 {
440 encore=false;
441 }
442 else
443 {
444 Document doc=html_.getDocument();
445 try
446 {
447 //html_.setPage(url_);
448 boolean again=false;
449
450 EditorKit ek=html_.getEditorKitForContentType("text/html");
451 HTMLDocument dk=(HTMLDocument)ek.createDefaultDocument();
452 dk.setBase(url_);
453 dk.putProperty("IgnoreCharsetDirective", new Boolean(true));
454
455 ek.read(new InputStreamReader
456 (url_.openStream(),"iso-8859-1"),dk,0);
457
458
459 updateStyles(dk.getStyleSheet());
460
461 html_.setEditorKit(ek);
462 html_.setDocument(dk);
463
464 avant_.addElement(url_);
465 btAvancer_.setEnabled(apres_.size()>0);
466 btReculer_.setEnabled(avant_.size()>1);
467
468 encore=false;
469 }
470 catch (Exception ex)
471 {
472 System.err.println("%%% "+ex);
473 html_.setDocument(doc);
474 lbUrl_.setText("Bad URL: "+url_);
475 BuBrowserFrame.this.getToolkit().beep();
476 encore=true;
477 }
478 finally
479 {
480 lbUrl_.setText("Page: "+url_.getFile());
481 url_=null;
482 }
483 }
484
485 Container parent=html_.getParent();
486 parent.repaint();
487 }
488
489 if(current_==this)
490 {
491 html_.setCursor(cursor_);
492 current_=null;
493 }
494 }
495 }
496 }
497
498 private static final void updateStyles(StyleSheet _styles)
499 {
500 if(_styles!=null)
501 {
502 Enumeration rules=_styles.getStyleNames();
503 while(rules.hasMoreElements())
504 {
505 String name=(String)rules.nextElement();
506 Style rule=_styles.getStyle(name);
507
508 if(StyleConstants.ALIGN_JUSTIFIED
509 ==StyleConstants.getAlignment(rule))
510 StyleConstants.setAlignment
511 (rule,StyleConstants.ALIGN_LEFT);
512 }
513 }
514 }
515
516 // BuInternalFrame
517
518 public String[] getEnabledActions()
519 {
520 String[] r=new String[] { "COPIER" };
521 return r;
522 }
523
524 public JComponent[] getSpecificTools()
525 {
526 JComponent[] r=new JComponent[4];
527 r[0]=btReculer_;
528 r[1]=btAvancer_;
529 r[2]=btRafraichir_;
530 r[3]=btMaison_;
531 return r;
532 }
533
534 // BuCutCopyPasteInterface
535
536 public void cut () { }
537 public void copy () { pane_.getEditorPane().copy(); }
538 public void paste () { }
539 public void duplicate() { }
540
541 // Test
542
543 private static final String INTRO=
544 "<HTML><BODY><H1>Bienvenue ;-)</H1>"+
545 "<P>Liens<UL>"+
546 //"<LI><A HREF=\"http://localhost/\" >Local host</A></LI>"+
547 "<LI><A HREF=\"http://www.memoire.com/\" >Memoire.com</A></LI>"+
548 "<LI><A HREF=\"http://www.desnoix.com/jdistro/\" >JDistro.com</A></LI>"+
549 "<LI><A HREF=\"http://www.connectandwork.com/meerkat/\">C&W Meerkat</A></LI>"+
550 "<LI><A HREF=\"http://pharos.inria.fr/Java/\" >Canal Java</A></LI>"+
551 "<LI><A HREF=\"http://www.debian.org/\" >Debian</A></LI>"+
552 //"<LI><A HREF=\"file:///home/desnoix/conges.gif\">Test GIF</A></LI>"+
553 //"<LI><A HREF=\"file:///home/desnoix/DELL.txt\">Test TXT</A></LI>"+
554 "</UL></P></BODY></HTML>";
555
556 public static void main(String[] _args)
557 {
558 final JFrame f=new JFrame();
559 final BuBrowserFrame b=new BuBrowserFrame();
560 final JComponent[] c=b.getSpecificTools();
561 final JComponent x=(JComponent)b.getContentPane();
562
563 x.setPreferredSize(new Dimension(640,350));
564
565 BuToolBar t=new BuToolBar();
566 for(int i=0;i<c.length;i++) t.add(c[i]);
567
568 BuPanel p=new BuPanel(new BorderLayout());
569 p.add("Center",x);
570 p.add("North" ,t);
571
572 f.setContentPane(p);
573 f.setTitle(BuResource.BU.getString("Navigateur"));
574 f.pack();
575 f.show();
576 f.setLocation(200,100);
577 BuRegistry.register(f);
578
579 f.addWindowListener(new WindowAdapter()
580 {
581 public void windowClosing(WindowEvent _evt)
582 {
583 f.hide();
584 f.dispose();
585 BuRegistry.unregister(f);
586 }
587 });
588
589 //b.setDocumentUrl("http://www.memoire.com/guillaume-desnoix/alma/");
590
591 if(_args.length>0)
592 {
593 URL url=FuLib.createURL(_args[0]);
594 if(url!=null) b.setDocumentUrl(url);
595 else b.setDocumentUrl(_args[0]);
596 }
597 else
598 b.setHtmlSource(INTRO,"Introduction");
599 }
600 }