Laboration 6 - Netscrape
I kursens sista labb ska du skriva en förbättrad version av Netscape,
som inte bara surfar utan också tabellerar alla länkar på sidan. Så
här kan det se ut. 
 
Tre av de häftigaste swingkomponenterna kommer att användas, nämligen
JEditorPane, JScrollPane och JTable.
En huvudroll har swingklassen
HTML som hanterar och tolkar webbdokument. 
 Du kommer troligen att behöva importera de här klasserna.
   import java.io.*;
   import java.awt.*;
   import java.awt.event.*;
   import java.net.*;
   import javax.swing.*;
   import javax.swing.event.*;
   import javax.swing.text.html.*;
   import javax.swing.text.*;
Det grafiska gränssnittet
När man ska skriva ett stort program är det ofta lämpligt att börja med
en 
prototyp, dvs ett program som ser ut som den färdiga
produkten med saknar funktionalitet. I det här fallet ska prototypen
visa en 
JFrame med tre komponenter: I norr finns ett textfält,
i centrum en 
JEditorPane och i öster en 
JTable, alla
tomma. Tabellen ska ha femtio rader och två kolumner,
så den får knappast plats i fönstret. Lägg därför in den i ett rullfönster 
som visar lagom många rader i taget.
JTable table = new JTable(50,2);
JScrollPane lankar = new JScrollPane(table);
eller om man klarar sig utan explicit referens till tabellen:
JScrollPane lankar=new JScrollPane(new JTable(50,2));
Det är ännu viktigare att lägga in webbläsaren (centrumkomponenten)
i ett rullfönster eftersom hela webbsidan inte kommer att få plats.
Kör programmet och kolla att det går att skriva text i alla
tre komponenterna. När det gäller webbsidan och länktabellen är det en
oavsiktlig finess (bug eller feature?) men i textfältet ska användaren
skriva in önskad webbadress och vid returtryckning anropas fältets
ActionListener och programmet försöker hämta in angiven webbsida. 
Det är lämpligt att låta Netscrape själv vara lyssnare
och i sin actionPerformed anropa t.ex. 
webbreader.showPage(...) och skicka med fältets text. 
Webbläsaren
Skriv en klass 
Webbreader som ärver från 
JEditorPane
och som har en metod t.ex. 
showPage(webbadress). Egentligen
skulle metoden bara behöva innehålla den enda satsen 
   setPage(webbadress); // där webbadress är en String
men kompilatorn kräver try-catch för att ta hand om fallet att adressen
inte existerar eller inte är kontaktbar. Då ska användaren få ett felmeddelande
och till det ska du använda en 
dialogruta. (Ett bättre namn
vore monologruta eftersom det enda användaren kan göra är att klicka på OK...)
Komponenten heter 
JOptionPane och du får själv kolla hur
anropet ska se ut (tips: den första parametern ska vara 
this).
Gör för säkerhets skull också setEditable(false) i klassens
konstruktor(er). 
När klassen är klar kan Netscrape deklarera   
Webbreader reader = new Webbreader() (alternativt ge
en startadress som konstruktorparameter så att man alltid kan starta på 
en webbsida).
Innan ni går vidare, kolla att programmet fungerar så här långt genom
att titta på några olika webbsidor. Sidan som syns på bilden ovan går
bra att titta på i Netscrape. Även vår huvudstudierektors (Viggo Kann)
sida går bra att titta på. URL till den är
 
http://www.nada.kth.se/~viggo.
Surfaren - extrauppgift
När du provkör ditt webbläsarprogram kommer du till din förtrytelse att
märka att man inte kan klicka på länkarna i webbsidan. Det spelar nu ingen
roll för det program som du vill skapa, men kan åtgärdas.
Det räknas som 
extrauppgift - så det är inget krav. 
Om du 
inte vill göra extrauppgift redan nu, gå vidare till uppgiften
Länktabellen nedan!
Två saker måste
göras i webbläsaren: gör setEditable(false)
(kanske redan gjort), så att inte klickningen tolkas som att du vill börja 
ändra i texten och lägg till en HyperlinkListener.
(något om Hyperlinklisteners kommer att finnas i föreläsningsmaterial och ev.
tar vi upp det på en föreläsning, troligen nr 10).
Anropet getURL().toString() till en HyperlinkEvent ger en
fullständig webbadress som kan skrivas in i adressfältet. 
Se till att webbläsaren reagarerar på klickningar av länkarna,
inte bara på att markören (musen) hålls över länken.
Se till att den klickade länken visas i adressfältet hos Netscrape
och att den valda sidan visas som aktuell webbsida. Några små ändringar
i Webbreader eller ev. en ny subklass till densamma
kan fixa detta. När den nya sidan ska visas kan man ha nytta av 
att från programmet framkalla en händelse (ActionEvent)
genom att anropa textfältets postActionEvent().
Andra lösningar finns förstås!
Länktabellen – ingår i grunduppgiften
I den här deluppgiften ska texterna som syns i tabellen till höger i 
bildexemplet ovan tas fram.
Låt Netscrape vila ett tag och skriv ett nytt program som skriver ut
alla länkar i en webbsida. Det kan heta Webbkoll och tills vidare
bara bestå av en main-metod. Man skriver ut en webbsida så här.
   String webbsida="http://www.nada.kth.se/~henrik";
   InputStream in=new URL(webbsida).openConnection().getInputStream();   
   InputStreamReader reader= new InputStreamReader(in);
   while(reader.ready()) 
      System.out.print((char)reader.read());
Kompilatorn kräver try-catch eftersom uppkopplingen kan misslyckas. 
I stället för att själva läsa inströmmen ska ni skapa ett tomt
HTMLDocument och låta ett
HTMLEditorKit läsa in webbsidan till det med
   doc.putProperty("IgnoreCharsetDirective", Boolean.TRUE);
   new HTMLEditorKit().read(reader,doc,0);
(Utan den första satsen får man ChangedCharSetException på alla svenska
sidor som ordentligt anger teckenuppsättningen iso-8859-1.)
En HTML-sida innehåller 
taggar av olika slag och den
tagg som används vid länkar heter A och har ett attribut HREF vars värde
är länkens webbadress. Den nionde raden i tabellen i bildexemplet ovan 
kan motsvaras av följande i html-dokumentet:
<A HREF = "http://www.nada.kth.se/~gerd">hustru</A>
 Iterera nu genom dokumentet från A-tagg 
till A-tagg, läs av attributet HREF och skriv ut dess värde. För detta
ändamål skapas ett Tag.A-iteratorobjekt och ett HREF-attributobjekt. 
Iteratorn stegar sig fram i en while-slinga. 
Skriv ut HREF-attributet inne i slingan.
När det här fungerar, skriv ut den text som står mellan 
A-taggen och dess sluttagg med hjälp av 
it.getStartOffset() och  it.getEndOffset().
Läs i dokumentationen för HTMLDocument hur man kan få ut
en deltext ur dokumentet! Vi går igenom ett liknande exempel (med tagg
men inte attribut) på övning 5 eller 6.
Lägg adress och text i en matris
När utskrifterna fungerar så ändra testprogrammet så att det istället för
en main-metod med utskrift har en metod som returnerar en 
String-matris
med adresser och texter motsvarande tabellen. Matrisen ska ha en begränsad
storlek, t.ex. 50 x 2, oavsett hur många länkar den aktuella 
webbsidan har.
Metoden som returnerar matrisen bör ta webbsidans adress 
(en 
 String) som parameter.
Testa gärna i en main-metod innan den nya metoden används i Netscrape.
Använd matrisen i Netscrape
I Netscrape finns en 
JTable med 50 x 2 positioner,
men från början inget innehåll. Enklaste sättet att ändra på innehållet i en
JTable är att byta ut dess 
modell. Modellen kan skapas
från två 
String-matriser, där den ena är tabellinnehållet och
den andra är tabellens rubriker. Här är ett exempel:
table.setModel(new DefaultTableModel(..., header));
Prickarna ska förstås ersättas med skapandet av matrisen enligt ovan.
Slå gärna upp dokumentationen av JTable för att få veta mer! 
Och sedan kan du ge dej ut och smurfa bland länkarna för att
fira att sista pruttlabben är klar.
Extrauppgift för betygshöjning
Se under rubriken 
Surfaren ovan!