Thursday, October 13, 2011
Tuesday, July 18, 2006
Graphical Threads
Multithreading is so, so very easy in Java. Right. But there are some pitfalls we need to look after. There are no guarantees how threads would behave. Its fully at the mercy of the thread scheduler.
//myrun.java
//please remove the line numbers.
1 class myrun implements Runnable {
2 String data;
3 public int prints;
4 public myrun(String s){
5 data=s;
6 prints=0;
7
8 }
9 public void run(){
10 while(true){
11 System.out.println(data+" printed: "+prints);
12 prints+=5;
13 try {
14 Thread.yield();
15 int flag=(int)(Math.random()*15);
16 if(flag==1)
17 {
18 Thread.sleep(25);
19 }
20 } catch (Exception e) {
21 // TODO
22 }
23 }
24
25 }
26 }
//GUI.java
//Shows the two thraeds which run and displays their progress graphically.
//Please remove the line numbers.
1 import java.awt.Color;
2 import java.awt.Dimension;
3 import java.awt.Graphics;
4
5 import java.awt.Point;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8
9 import java.awt.event.WindowAdapter;
10
11 import java.awt.event.WindowEvent;
12
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16
17 import javax.swing.JFrame;
18 import javax.swing.JLabel;
19 import javax.swing.Timer;
20
21
22 public class GUI extends JLabel{
23 myrun first;
24 myrun second;
25 List<Point> firstPoints=new ArrayList<Point>();
26 List<Point> secondPoints=new ArrayList<Point>();
27 Timer timer;
28 int ticks;
29 static double xNormalise=15000;
30 public GUI(myrun first, myrun second) {
31 setPreferredSize(new Dimension(200,200));
32 this.first=first;
33 this.second=second;
34 timer=new Timer(100, new ActionListener(){
35 public void actionPerformed(ActionEvent e){
36 repaint();
37 }
38 });
39 }
40 public GUI() {
41 setPreferredSize(new Dimension(500,200));
42 this.first=new myrun("First");
43 this.second=new myrun("Second");
44 new Thread(first).start();
45 new Thread(second).start();
46 ticks=0;
47 firstPoints.add(new Point(0,0));
48 secondPoints.add(new Point(0,0));
49 timer=new Timer(100, new ActionListener(){
50 public void actionPerformed(ActionEvent e){
51
52 ticks++;
53
54 int xPos1=(int)(first.prints/xNormalise*getWidth());
55 while(xPos1>getWidth()){
56 xPos1-=getWidth();
57 }
58 int xPos2 = (int)(second.prints/xNormalise*getWidth());
59 while(xPos2>getWidth()){
60 xPos2-=getWidth();
61 }
62 int yPos=ticks;
63 firstPoints.add(new Point(xPos1,yPos));
64 secondPoints.add(new Point(xPos2,yPos));
65 repaint();
66 }
67 });
68
69 timer.start();
70
71 }
72 public void paintComponent(Graphics g){
73 super.paintComponent(g);
74 g.setColor(Color.WHITE);
75 g.fillRect(0,0,getWidth(),getHeight());
76 Point prev1;
77 Point next1;
78 Iterator<Point> i=firstPoints.iterator();
79 prev1 = i.next();
80 next1 = i.next();
81 g.setColor(Color.RED);
82 g.drawLine(prev1.x,prev1.y,next1.x,next1.y);
83 while(i.hasNext()){
84 prev1=next1;
85 next1=i.next();
86 g.drawLine(prev1.x,prev1.y,next1.x,next1.y);
87 }
88 i=secondPoints.iterator();
89 prev1 = i.next();
90 next1 = i.next();
91 g.setColor(Color.GREEN);
92 g.drawLine(prev1.x,prev1.y,next1.x,next1.y);
93 while(i.hasNext()){
94 prev1=next1;
95 next1=i.next();
96 g.drawLine(prev1.x,prev1.y,next1.x,next1.y);
97 }
98
99 }
100 public static void main(String args[]){
101 JFrame f=new JFrame();
102 f.add(new GUI());
103 f.pack();
104 f.setVisible(true);
105 f.addWindowListener(new WindowAdapter(){
106 public void windowClosing(WindowEvent e){
107 System.exit(0);
108 }
109 });
110 }
111
112 }
Sunday, June 25, 2006
JSpaceInavders
So very long back I had written an implementation on space inavders in java. I wrote it like 2.5 years ago.(One of my first programs). Just a link to that http://shabda8.tripod.com/java/
It contains the music files, the images and a fully functional game. Check it out.
Sunday, November 06, 2005
Long back i had wriiten a java implementation of Logo. I have uploaded the source as well as my ideas on how we(Ashwini and me) implemented it. Find it here.. I could not post it here coz, they were really long, 7 files. And I had to break them up into many files.
Friday, November 04, 2005
Java Math Tutor.
* Created on Oct 29, 2005
*/
One of my friends was preparing for cat, which has quantitative tests. So he
needed to work on his calculations. I wrote this for him. It gives arithmatic
problems and their answers. You may set the hardness. Again I hope I have commented
it well enough to understand the code.
package name.shabda.cat;
/**
* @author shabda
*/
public class Cat {
final int sums=10;//The number of questions asked.
final int x=3;//Humm. Why 3? Coz for basic maths operations we need 3 values like 2+3=5.1st 2,2nd 3, third 5.
int hardness=1;//how hard do you want the questions. Heigher values give harder questions.
public int[][] doMultiply(){//returns a array containing arithmatic problems on multiplication.
//Like for 2+3=5, arr[0][0]=2,arr[0][1]=3,arr[0][2]=5.
int[][] arr=new int[sums][x];
for(int i=0;i<sums;i++){
int howHard=(int) Math.pow(10,hardness);
arr[i][0]=(int) (Math.random()*100*howHard);
arr[i][1]=(int) (Math.random()*100*howHard);
arr[i][2]=arr[i][0]*arr[i][1];
}
return arr;
}
public double[][] doDivide(){//returns a array containing arithmatic problems on Division.
int howHard=(int) Math.pow(10,hardness);
double[][] arr=new double[sums][x];
for(int i=0;i<sums;i++){
arr[i][0]=(int) (Math.random()*100*howHard);
arr[i][1]=(int) (Math.random()*100*howHard);
arr[i][2]=arr[i][0]/arr[i][1];
}
return arr;
}
public int[][] doSum(){//returns a array containing arithmatic problems on addition.
int howHard=(int) Math.pow(10,(hardness*2));
int[][] arr=new int[sums][x];
for(int i=0;i<sums;i++){
arr[i][0]=(int) (Math.random()*100*howHard);
arr[i][1]=(int) (Math.random()*100*howHard);
arr[i][2]=arr[i][0]+arr[i][1];
}
return arr;
}
public int[][] doSub(){//returns a array containing arithmatic problems on subtraction.
int howHard=(int) Math.pow(10,(hardness*2));
int[][] arr=new int[sums][x];
for(int i=0;i<sums;i++){
arr[i][0]=(int) (Math.random()*100*howHard);
arr[i][1]=(int) (Math.random()*100*howHard);
arr[i][2]=arr[i][0]-arr[i][1];
}
return arr;
}
public String stringMult(){//Lets convert the array to a nice string.
String data="";
int[][] arr=doMultiply();
for(int i=0;i<sums;i++){
String temp=""+arr[i][0]+"*"+arr[i][1];
data+=temp;
data+="\n";
}
for(int i=0;i<5;i++){
data+="\n";
}
for(int i=0;i<sums;i++){
String temp=""+arr[i][0]+"*"+arr[i][1]+"="+arr[i][2];
data+=temp;
data+="\n";
}
return data;
}
public String stringDiv(){//Lets convert the array to a nice string.
String data="";
double[][] arr=doDivide();
for(int i=0;i<sums;i++){
String temp=""+arr[i][0]+"/"+arr[i][1];
data+=temp;
data+="\n";
}
for(int i=0;i<5;i++){
data+="\n";
}
for(int i=0;i<sums;i++){
String temp=""+arr[i][0]+"/"+arr[i][1]+"="+arr[i][2];
data+=temp;
data+="\n";
}
return data;
}
public String stringSub(){//Lets convert the array to a nice string.
String data="";
int[][] arr=doSub();
for(int i=0;i<sums;i++){
String temp=""+arr[i][0]+"-"+arr[i][1];
data+=temp;
data+="\n";
}
for(int i=0;i<5;i++){
data+="\n";
}
for(int i=0;i<sums;i++){
String temp=""+arr[i][0]+"-"+arr[i][1]+"="+arr[i][2];
data+=temp;
data+="\n";
}
return data;
}
public String stringAdd(){//Lets convert the array to a nice string.
String data="";
int[][] arr=doSum();
for(int i=0;i<sums;i++){
String temp=""+arr[i][0]+"+"+arr[i][1];
data+=temp;
data+="\n";
}
for(int i=0;i<5;i++){
data+="\n";
}
for(int i=0;i<sums;i++){
String temp=""+arr[i][0]+"+"+arr[i][1]+"="+arr[i][2];
data+=temp;
data+="\n";
}
return data;
}
public static void main(String[] args){//Just a check.
Cat app=new Cat();
System.out.println("Div");
System.out.println(app.stringDiv());
System.out.println("Add");
System.out.println(app.stringAdd());
System.out.println("Sub");
System.out.println(app.stringSub());
}
}
And we need a class to display the problems. So here we go.
//CatGui
/*
* Created on Nov 3, 2005
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package name.shabda.cat;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextArea;
/**
* @author shabda
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class CatGui {
Cat engine;
JButton add,sub,mult,div;
JTextArea result;
JPanel buttons,display;
JMenuBar theMenu;
JMenuItem easy=new JMenuItem("easy");
JMenuItem hard=new JMenuItem("hard");
JMenuItem harder=new JMenuItem("harder");
/**
*
*/
public CatGui() {
engine=new Cat();
add=new JButton("add");
sub=new JButton("sub");
mult=new JButton("mult");
div=new JButton("div");
buttons=new JPanel();
buttons.setLayout(new FlowLayout());
buttons.add(add);
buttons.add(sub);
buttons.add(mult);
buttons.add(div);
result=new JTextArea(26,20);
result.setPreferredSize(new Dimension(200,300));
result.setEditable(false);
display=new JPanel();
display.setLayout(new BoxLayout(display, BoxLayout.Y_AXIS));
display.add(result);
display.add(buttons);
addActionListeners();
theMenu=new JMenuBar();
JMenu hardness=new JMenu("how hard?");
hardness.add(easy);
hardness.add(hard);
hardness.add(harder);
theMenu.add(hardness);
}
public void addActionListeners(){
add.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
result.setText(engine.stringAdd());
}});
sub.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
result.setText(engine.stringSub());
}});
mult.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
result.setText(engine.stringMult());
}});
div.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
result.setText(engine.stringDiv());
}});
easy.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
engine.hardness=1;
}});
hard.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
engine.hardness=2;
}});
harder.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
engine.hardness=3;
}});
}
public static void main(String[] args){
CatGui theGui=new CatGui();
JFrame f=new JFrame();
f.getContentPane().add(theGui.display);
f.setJMenuBar(theGui.theMenu);
f.pack();
f.setVisible(true);
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});
}
}
Java Math Tutor
One of my friends was preparing for cat, which has quantitative tests. So he needed to work on his calculations. I wrote this for him. It gives arithmatic problems and their answers. You may set the hardness. Again I hope I have commented it well enough to understand the code.
/*
* Created on Oct 29, 2005
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package name.shabda.cat;
/**
* @author shabda
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class Cat {
final int sums=10;//The number of questions asked.
final int x=3;//Humm. Why 3? Coz for basic maths operations we need 3 values like 2+3=5.1st 2,2nd 3, third 5.
int hardness=1;//how hard do you want the questions. Heigher values give harder questions.
public int[][] doMultiply(){//returns a array containing arithmatic problems on multiplication.
//Like for 2+3=5, arr[0][0]=2,arr[0][1]=3,arr[0][2]=5.
int[][] arr=new int[sums][x];
for(int i=0;i
arr[i][0]=(int) (Math.random()*100*howHard);
arr[i][1]=(int) (Math.random()*100*howHard);
arr[i][2]=arr[i][0]*arr[i][1];
}
return arr;
}
public double[][] doDivide(){//returns a array containing arithmatic problems on Division.
int howHard=(int) Math.pow(10,hardness);
double[][] arr=new double[sums][x];
for(int i=0;i
arr[i][1]=(int) (Math.random()*100*howHard);
arr[i][2]=arr[i][0]/arr[i][1];
}
return arr;
}
public int[][] doSum(){//returns a array containing arithmatic problems on addition.
int howHard=(int) Math.pow(10,(hardness*2));
int[][] arr=new int[sums][x];
for(int i=0;i
arr[i][1]=(int) (Math.random()*100*howHard);
arr[i][2]=arr[i][0]+arr[i][1];
}
return arr;
}
public int[][] doSub(){//returns a array containing arithmatic problems on subtraction.
int howHard=(int) Math.pow(10,(hardness*2));
int[][] arr=new int[sums][x];
for(int i=0;i
arr[i][1]=(int) (Math.random()*100*howHard);
arr[i][2]=arr[i][0]-arr[i][1];
}
return arr;
}
public String stringMult(){//Lets convert the array to a nice string.
String data="";
int[][] arr=doMultiply();
for(int i=0;i
data+=temp;
data+="\n";
}
for(int i=0;i<5;i++){
data+="\n";
}
for(int i=0;i
data+=temp;
data+="\n";
}
return data;
}
public String stringDiv(){//Lets convert the array to a nice string.
String data="";
double[][] arr=doDivide();
for(int i=0;i
data+=temp;
data+="\n";
}
for(int i=0;i<5;i++){
data+="\n";
}
for(int i=0;i
data+=temp;
data+="\n";
}
return data;
}
public String stringSub(){//Lets convert the array to a nice string.
String data="";
int[][] arr=doSub();
for(int i=0;i
data+=temp;
data+="\n";
}
for(int i=0;i<5;i++){
data+="\n";
}
for(int i=0;i
data+=temp;
data+="\n";
}
return data;
}
public String stringAdd(){//Lets convert the array to a nice string.
String data="";
int[][] arr=doSum();
for(int i=0;i
data+=temp;
data+="\n";
}
for(int i=0;i<5;i++){
data+="\n";
}
for(int i=0;i
data+=temp;
data+="\n";
}
return data;
}
public static void main(String[] args){//Just a check.
Cat app=new Cat();
System.out.println("Div");
System.out.println(app.stringDiv());
System.out.println("Add");
System.out.println(app.stringAdd());
System.out.println("Sub");
System.out.println(app.stringSub());
}
}
Java SimpleAnalogClock
This is an implementation of a simple analog clock using Java. Uses just one file. The code is commented well enough to understand, IMHO.
package name.shabda.clock;
import javax.swing.*;
import java.awt.*;
import java.util.Date;
import java.awt.event.*;
/**
*@author shabda raaj and ashwini kumar
*this is our implementation of a simple analog clock
*the idea is simple:
*we get the system time.Class clock gui extends JLabel
*and overrides is paintComponent method to do its
*custom painting.
**/
public class ClockGui extends JLabel{
int centre=getHeight()/2;
Date date=new Date();//date to use
int radiu=(int)(getHeight()*0.4);//radius of clock(outer circle)
int h=getWidth()/2;//x cord of centre of clock
int k=getHeight()/2;//y cord
Timer t=new Timer(1000,new ActionListener(){
public void actionPerformed(ActionEvent e){
repaint();
}
});//t.start repaints the clock every second
Timer t1=new Timer(1000,new ActionListener(){
public void actionPerformed(ActionEvent e){
check();
}
});//t1.start will check for alarm condition
/**
*this does the painting for the clock
*and is fired every second.
**/
public void paintComponent(final Graphics g){
super.paintComponent(g);
g.setColor(Color.cyan);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(Color.red);
for(double i=Math.PI/6;i<(2*Math.PI+Math.PI/6);i+=Math.PI/720){
int x=(int)(radiu*Math.cos(i)+h)-3;
int y=(int)(radiu*Math.sin(i)+k)-3;
radiu=(int)(getHeight()*0.4);
h=getWidth()/2;
k=getHeight()/2;
g.setColor(Color.green);
g.fillOval(x,y,4,4);
}//this draws the outer circle by drawing some very close
//circles.
for(double i=Math.PI/6;i<(2*Math.PI+Math.PI/6);i+=Math.PI/6){
int x=(int)(radiu*Math.cos(i)+h)-3;
int y=(int)(radiu*Math.sin(i)+k)-3;
radiu=(int)(getHeight()*0.4);
h=getWidth()/2;
k=getHeight()/2;
g.setColor(Color.blue);
g.fillOval(x-5,y-5,10,10);
}//this draws the points showing the hours
for(double i=Math.PI/6;i<(2*Math.PI+Math.PI/6);i+=Math.PI/30){
int x=(int)(radiu*Math.cos(i)+h)-3;
int y=(int)(radiu*Math.sin(i)+k)-3;
radiu=(int)(getHeight()*0.4);
h=getWidth()/2;
k=getHeight()/2;
g.setColor(Color.blue);
g.fillOval(x,y,3,3);
}//this draws the points showing the minutes
Date dd=new Date();
String ss=dd.toString().substring(0,10);
Font font = new Font("SansSerif", Font.BOLD, (getHeight())/16);
g.setColor(Color.red);
g.setFont(font);
//write the day and the date
g.drawString(ss,(int)(getWidth()/1.88),(int)(getHeight()/1.95));
drawSecLine(g);//draw second line
drawMinLine(g);//draw minute line
drawHrsLine(g);//draw hour line
g.setColor(Color.red);
int centreX1=getWidth()/2;
int centreY1=getHeight()/2;
g.fillOval(centreX1-6,centreY1-6,12,12);
}//draw a circle in the centre
public ClockGui(String s){
super(s);
Dimension d=new Dimension(300,300);
setPreferredSize(d);
t.start();
t1.start();
}
public void drawSecLine(Graphics g){//function to draw seconds line
g.setColor(Color.red);
date=new Date();
int sec=date.getSeconds();
double angle=Math.PI/2+sec*Math.PI/30-Math.PI;
int endx=(int)(h+radiu*Math.cos(angle));
int endy=(int)(k+radiu*Math.sin(angle));
g.drawLine(h,k,endx,endy);
}
public void drawMinLine(Graphics g){//function to draw minute line
g.setColor(Color.blue);
date=new Date();
int min=date.getMinutes();
double angle=Math.PI/2+min*Math.PI/30-Math.PI;
int radi=(int)(getHeight()/3);
int endx=(int)(h+radi*Math.cos(angle));
int endy=(int)(k+radi*Math.sin(angle));
g.drawLine(h,k,endx,endy);
g.drawLine(h-2,k,endx-2,endy);
g.drawLine(h+2,k,endx+2,endy);
g.drawLine(h+1,k,endx+1,endy);
g.drawLine(h-1,k,endx-1,endy);
}
public void drawHrsLine(Graphics g){//function to draw hour line
g.setColor(Color.magenta);
date=new Date();
int hrs=date.getHours();
int min=date.getMinutes();
int radi=(int)(getHeight()/4);
double angle=(hrs-3)*Math.PI/6+min*Math.PI/360;
int endx=(int)(h+radi*Math.cos(angle));
int endy=(int)(k+radi*Math.sin(angle));
g.drawLine(h+0,k,endx+0,endy);
g.drawLine(h+3,k,endx+3,endy);
g.drawLine(h-3,k,endx-3,endy);
g.drawLine(h+1,k,endx+1,endy);
g.drawLine(h+2,k,endx+2,endy);
g.drawLine(h-1,k,endx-1,endy);
g.drawLine(h-2,k,endx-2,endy);
}
public void check(){
System.out.println("*");
}
public static void main(String[] args){
JFrame frame=new JFrame("AlarmClock v1.0");
ClockGui gui=new ClockGui("");
frame.getContentPane().add(gui);
frame.pack();
frame.show();
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
}
}
Java Hindi office suite: InternetExplorer
Continuing my last post, this contains the code of a Java InternetExplorer replacement. This is a simple web browser with hindi menus and dialogs. Has no support for frames, javascript or applets. Save is not yet correctly imlemented(saves only the html part,not the embedded pictures or other resources). That said here is your code for IExplorer.java
//IExplorer.java
/*
* Created on Dec 16, 2004
*/
package name.shabda.office;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Stack;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.JTextComponent;
import javax.swing.text.html.HTMLEditorKit;
/**
* @author dicky
*/
public class IExplorer extends JFrame {
JEditorPane theView;//the editor where the page is displayed
JTextField add;//address bar
Stack backPages;//stack which contains list of pages to which you can go back
Stack forwardPages;//list of pages to which you can forward
HTMLEditorKit editor;//editor for saving and opening
private JMenuItem back;//the back menu item
private JMenuItem forward;//the forward menu item
private JButton backButton;
private JButton forwardButton;
Hashtable actions;//stores the actions
/**
*
*/
public IExplorer() {
editor=new HTMLEditorKit();
getContentPane().setLayout(new BorderLayout());
theView=getEditor();
createActionTable(theView);//create action table from where we can add the actions to menus
JScrollPane pane=new JScrollPane(theView);
getContentPane().add(pane,BorderLayout.CENTER);
getContentPane().add(getNonEditor(),BorderLayout.NORTH);
addHtmlListener();
setJMenuBar(getMenu());
backPages=new Stack();
forwardPages=new Stack();
try {
setPage(new URL("http://www.aksharmala.com/")); //$NON-NLS-1$
} catch (MalformedURLException e) {
e.printStackTrace();
}
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
/**
* This method registers a html listener on the document.
* */
public void addHtmlListener(){
theView.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
URL url;
try {
url = new URL(add.getText());//the current page
backPages.push(url);//add current page to the stack so you can go back there
url=e.getURL();
forwardPages.clear();
setPage(url);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
}
}});
}
public void setPage(URL s) {
try {
theView.setPage(s);
add.setText(s.toString());
updateMenus();
} catch (IOException e) {
e.printStackTrace();
}
}
public JMenuBar getMenu() {
JMenuBar menu=new JMenuBar();
JMenu file = new JMenu(Messages.getString("NoteTab.4")); //$NON-NLS-1$
JMenuItem open = new JMenuItem(Messages.getString("NoteTab.7")); //$NON-NLS-1$
JMenuItem save = new JMenuItem(Messages.getString("NoteTab.6")); //$NON-NLS-1$
JMenuItem print = new JMenuItem(Messages.getString("NoteTab.8")); //$NON-NLS-1$
open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
open();
}});
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveAs();
}});
file.add(open);
file.add(save);
file.add(print);
menu.add(file);
JMenu edit=new JMenu(Messages.getString("NoteTab.19")); //$NON-NLS-1$
JMenuItem cut = new JMenuItem(Messages.getString("NoteTab.20")); //$NON-NLS-1$
cut.addActionListener(getActionByName(DefaultEditorKit.cutAction));
JMenuItem copy = new JMenuItem(Messages.getString("NoteTab.21")); //$NON-NLS-1$
copy.addActionListener(getActionByName(DefaultEditorKit.copyAction));
JMenuItem paste = new JMenuItem(Messages.getString("NoteTab.22")); //$NON-NLS-1$
paste.addActionListener(getActionByName(DefaultEditorKit.pasteAction));
JMenuItem selectAll = new JMenuItem(Messages.getString("NoteTab.23")); //$NON-NLS-1$
selectAll
.addActionListener(getActionByName(DefaultEditorKit.selectAllAction));
edit.add(cut);
edit.add(copy);
edit.add(paste);
edit.add(selectAll);
menu.add(edit);
JMenu navigate=new JMenu(Messages.getString("IE.2")); //$NON-NLS-1$
back = new JMenuItem(Messages.getString("IE.3")); //$NON-NLS-1$
back.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
URL url;
try {
url=new URL(add.getText());//current page
forwardPages.push(url);
url=(URL) backPages.pop();
setPage(url);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
}});
forward = new JMenuItem(Messages.getString("IE.4")); //$NON-NLS-1$
forward.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
URL url;
try {
url=new URL(add.getText());//current page
backPages.push(url);
url=(URL) forwardPages.pop();
setPage(url);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
}});
JMenuItem home=new JMenuItem(Messages.getString("IE.5")); //$NON-NLS-1$
navigate.add(back);
navigate.add(forward);
navigate.add(home);
menu.add(navigate);
JMenu help=new JMenu(Messages.getString("NoteTab.44")); //$NON-NLS-1$
menu.add(help);
return menu;
}
public JPanel getNonEditor() {
JPanel p=new JPanel();
p.setLayout(new GridLayout(2,1));
p.add(getToolBar2());
p.add(getToolBar());
return p;
}
public JToolBar getToolBar2() {
JToolBar tools=new JToolBar();
backButton=new JButton();
forwardButton=new JButton();
ImageIcon icon=createImageIcon("../images/back.gif", null);
backButton.setIcon(icon);
icon=createImageIcon("../images/forward.gif", null);
forwardButton.setIcon(icon);
JButton open=new JButton();
icon=createImageIcon("../images/open.gif", null);
open.setIcon(icon);
JButton save=new JButton();
icon=createImageIcon("../images/save.gif", null);
save.setIcon(icon);
JButton cut=new JButton();
icon=createImageIcon("../images/cut.gif", null);
cut.setIcon(icon);
JButton copy=new JButton();
icon=createImageIcon("../images/copy.gif", null);
copy.setIcon(icon);
JButton paste=new JButton();
icon=createImageIcon("../images/paste.gif", null);
paste.setIcon(icon);
open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
open();
}});
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveAs();
}});
cut.addActionListener(getActionByName(DefaultEditorKit.cutAction));
copy.addActionListener(getActionByName(DefaultEditorKit.copyAction));
paste.addActionListener(getActionByName(DefaultEditorKit.pasteAction));
backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
URL url;
try {
url=new URL(add.getText());//current page
forwardPages.push(url);
url=(URL) backPages.pop();
setPage(url);
Java Hindi office suite: InternetExplorer
Continuing my last post, this contains the code of a Java InternetExplorer replacement. This is a simple web browser with hindi menus and dialogs. Has no support for frames, javascript or applets. Save is not yet correctly imlemented(saves only the html part,not the embedded pictures or other resources). That said here is your code for IExplorer.java
//IExplorer.java
/*
* Created on Dec 16, 2004
*/
package name.shabda.office;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Stack;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.JTextComponent;
import javax.swing.text.html.HTMLEditorKit;
/**
* @author dicky
*/
public class IExplorer extends JFrame {
JEditorPane theView;//the editor where the page is displayed
JTextField add;//address bar
Stack backPages;//stack which contains list of pages to which you can go back
Stack forwardPages;//list of pages to which you can forward
HTMLEditorKit editor;//editor for saving and opening
private JMenuItem back;//the back menu item
private JMenuItem forward;//the forward menu item
private JButton backButton;
private JButton forwardButton;
Hashtable actions;//stores the actions
/**
*
*/
public IExplorer() {
editor=new HTMLEditorKit();
getContentPane().setLayout(new BorderLayout());
theView=getEditor();
createActionTable(theView);//create action table from where we can add the actions to menus
JScrollPane pane=new JScrollPane(theView);
getContentPane().add(pane,BorderLayout.CENTER);
getContentPane().add(getNonEditor(),BorderLayout.NORTH);
addHtmlListener();
setJMenuBar(getMenu());
backPages=new Stack();
forwardPages=new Stack();
try {
setPage(new URL("http://www.aksharmala.com/")); //$NON-NLS-1$
} catch (MalformedURLException e) {
e.printStackTrace();
}
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
/**
* This method registers a html listener on the document.
* */
public void addHtmlListener(){
theView.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
URL url;
try {
url = new URL(add.getText());//the current page
backPages.push(url);//add current page to the stack so you can go back there
url=e.getURL();
forwardPages.clear();
setPage(url);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
}
}});
}
public void setPage(URL s) {
try {
theView.setPage(s);
add.setText(s.toString());
updateMenus();
} catch (IOException e) {
e.printStackTrace();
}
}
public JMenuBar getMenu() {
JMenuBar menu=new JMenuBar();
JMenu file = new JMenu(Messages.getString("NoteTab.4")); //$NON-NLS-1$
JMenuItem open = new JMenuItem(Messages.getString("NoteTab.7")); //$NON-NLS-1$
JMenuItem save = new JMenuItem(Messages.getString("NoteTab.6")); //$NON-NLS-1$
JMenuItem print = new JMenuItem(Messages.getString("NoteTab.8")); //$NON-NLS-1$
open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
open();
}});
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveAs();
}});
file.add(open);
file.add(save);
file.add(print);
menu.add(file);
JMenu edit=new JMenu(Messages.getString("NoteTab.19")); //$NON-NLS-1$
JMenuItem cut = new JMenuItem(Messages.getString("NoteTab.20")); //$NON-NLS-1$
cut.addActionListener(getActionByName(DefaultEditorKit.cutAction));
JMenuItem copy = new JMenuItem(Messages.getString("NoteTab.21")); //$NON-NLS-1$
copy.addActionListener(getActionByName(DefaultEditorKit.copyAction));
JMenuItem paste = new JMenuItem(Messages.getString("NoteTab.22")); //$NON-NLS-1$
paste.addActionListener(getActionByName(DefaultEditorKit.pasteAction));
JMenuItem selectAll = new JMenuItem(Messages.getString("NoteTab.23")); //$NON-NLS-1$
selectAll
.addActionListener(getActionByName(DefaultEditorKit.selectAllAction));
edit.add(cut);
edit.add(copy);
edit.add(paste);
edit.add(selectAll);
menu.add(edit);
JMenu navigate=new JMenu(Messages.getString("IE.2")); //$NON-NLS-1$
back = new JMenuItem(Messages.getString("IE.3")); //$NON-NLS-1$
back.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
URL url;
try {
url=new URL(add.getText());//current page
forwardPages.push(url);
url=(URL) backPages.pop();
setPage(url);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
}});
forward = new JMenuItem(Messages.getString("IE.4")); //$NON-NLS-1$
forward.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
URL url;
try {
url=new URL(add.getText());//current page
backPages.push(url);
url=(URL) forwardPages.pop();
setPage(url);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
}});
JMenuItem home=new JMenuItem(Messages.getString("IE.5")); //$NON-NLS-1$
navigate.add(back);
navigate.add(forward);
navigate.add(home);
menu.add(navigate);
JMenu help=new JMenu(Messages.getString("NoteTab.44")); //$NON-NLS-1$
menu.add(help);
return menu;
}
public JPanel getNonEditor() {
JPanel p=new JPanel();
p.setLayout(new GridLayout(2,1));
p.add(getToolBar2());
p.add(getToolBar());
return p;
}
public JToolBar getToolBar2() {
JToolBar tools=new JToolBar();
backButton=new JButton();
forwardButton=new JButton();
ImageIcon icon=createImageIcon("../images/back.gif", null);
backButton.setIcon(icon);
icon=createImageIcon("../images/forward.gif", null);
forwardButton.setIcon(icon);
JButton open=new JButton();
icon=createImageIcon("../images/open.gif", null);
open.setIcon(icon);
JButton save=new JButton();
icon=createImageIcon("../images/save.gif", null);
save.setIcon(icon);
JButton cut=new JButton();
icon=createImageIcon("../images/cut.gif", null);
cut.setIcon(icon);
JButton copy=new JButton();
icon=createImageIcon("../images/copy.gif", null);
copy.setIcon(icon);
JButton paste=new JButton();
icon=createImageIcon("../images/paste.gif", null);
paste.setIcon(icon);
open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
open();
}});
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveAs();
}});
cut.addActionListener(getActionByName(DefaultEditorKit.cutAction));
copy.addActionListener(getActionByName(DefaultEditorKit.copyAction));
paste.addActionListener(getActionByName(DefaultEditorKit.pasteAction));
backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
URL url;
try {
url=new URL(add.getText());//current page
forwardPages.push(url);
url=(URL) backPages.pop();
setPage(url);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
}});
forwardButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
URL url;
try {
url=new URL(add.getText());//current page
backPages.push(url);
url=(URL) forwardPages.pop();
setPage(url);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
}});
tools.add(open);
tools.add(save);
tools.addSeparator();
tools.add(cut);
tools.add(copy);
tools.add(paste);
tools.addSeparator();
tools.add(backButton);
tools.add(forwardButton);
return tools;
}
public JToolBar getToolBar() {
JToolBar tools=new JToolBar();
JLabel addL=new JLabel("address");
tools.add(addL);
tools.addSeparator();
add=new JTextField();
add.setPreferredSize(new Dimension(500,20));
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JTextField t= (JTextField) e.getSource();
String s=t.getText();
try {
setPage(new URL(s));
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
}});
tools.add(add);
return tools;
}
/**
* updates the forward and back buttons depending on whether or not they are empty
* */
public void updateMenus() {
if(backPages.isEmpty()) {
back.setEnabled(false);
backButton.setEnabled(false);
}
else {back.setEnabled(true);
backButton.setEnabled(true);
}
if(forwardPages.isEmpty()) {
forward.setEnabled(false);
forwardButton.setEnabled(false);
}
else {forward.setEnabled(true);
forwardButton.setEnabled(true);
}
}
/**
* returns a unditable JEditoPane
* */
public JEditorPane getEditor() {
JEditorPane ed=null;
ed=new JEditorPane();
ed.setEditable(false);
ed.setPreferredSize(new Dimension(500,300));
return ed;
}
public void open() {
JFileChooser fc = new JFileChooser();
fc.addChoosableFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
String extension = getExtension(f);
if (extension != null) {
if (extension.equals("html")) {
return true;
} else {
return false;
}
}
return false;
}
public String getDescription() {
return "HTML Files";
}});
int returnVal = fc.showOpenDialog(IExplorer.this);//this is tricky.I dont
// understand it but..
if (returnVal == JFileChooser.APPROVE_OPTION) {
theView.setText(Messages.getString("NoteTab.47"));//need to show a new file.So clear the screen. //$NON-NLS-1$
File file = fc.getSelectedFile();
try {
FileReader in = new FileReader(file);
editor.read(in, theView.getDocument(), 0);
} catch (Exception ee) {
}
}
}
public void saveAs() {
JFileChooser fc = new JFileChooser();
int returnVal = fc.showSaveDialog(IExplorer.this);//this is tricky.I dont
// understand it but..
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
try {
FileOutputStream out = new FileOutputStream(file);
editor.write(out, theView.getDocument(), 0, theView.getDocument().getLength());
} catch (Exception ee) {
System.out.println(Messages.getString("NoteTab.45")); //$NON-NLS-1$
ee.printStackTrace();
}
}
}
private void createActionTable(JTextComponent textComponent) {
actions = new Hashtable();
Action[] actionsArray = textComponent.getActions();
for (int i = 0; i < actionsArray.length; i++) {
Action a = actionsArray[i];
actions.put(a.getValue(Action.NAME), a);
}
}
private Action getActionByName(String name) {
return (Action) (actions.get(name));
}
/**
* Get the file extension from that file
* */
public static String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1) {
ext = s.substring(i+1).toLowerCase();
}
return ext;
}
protected static ImageIcon createImageIcon(String path,
String description) {
java.net.URL imgURL = NoteTab.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
public static void main(String[] args) {
IExplorer app=new IExplorer();
app.pack();
app.show();
}
}
And again we need the files Messages.java and Messages.properties to display our externalised strings. Here are the codes, same as for NoteTab.java
//Messages.java
/*
* Created on Dec 16, 2004
*/
package name.shabda.office;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* @author dicky
*/
public class Messages {
private static final String BUNDLE_NAME = "name.shabda.office.messages";//$NON-NLS-1$
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
.getBundle(BUNDLE_NAME);
private Messages() {
}
public static String getString(String key) {
// TODO Auto-generated method stub
try {
return RESOURCE_BUNDLE.getString(key);
} catch (MissingResourceException e) {
return '!' + key + '!';
}
}
}
And the hindi localised Messages.properties:
NoteTab.0=\u0939\u093e\u0901
NoteTab.1=\u0928\u0939\u0940\u0902
NoteTab.2=\u0906\u092a\u0915\u0940 \u090f\u0915 \u095e\u093e\u0907\u0932 \u091c\u092e\u093e \u0928\u0939\u0940\u0902 \u0939\u0948\u0964 \u0915\u094d\u092f\u093e \u0909\u0938\u0947 \u091c\u092e\u093e \u0915\u0930 \u0926\u0942\u0901 ?\n
NoteTab.3=File not saved!
NoteTab.4=\u095e\u093e\u0907\u0932
NoteTab.5=\u0928\u092f\u093e
NoteTab.6=\u091c\u092e\u093e \u0915\u0930\u094b
NoteTab.7=\u0916\u094b\u0932\u094b
NoteTab.8=\u091b\u093e\u092a\u094b
NoteTab.9=\u0939\u093e\u0901
NoteTab.10=\u0928\u0939\u0940\u0902
NoteTab.11=Cancel
NoteTab.12=\u0906\u092a\u0915\u0940 \u090f\u0915 \u095e\u093e\u0907\u0932 \u091c\u092e\u093e \u0928\u0939\u0940\u0902 \u0939\u0948\u0964 \u0915\u094d\u092f\u093e \u0909\u0938\u0947 \u091c\u092e\u093e \u0915\u0930 \u0926\u0942\u0901 ?\n
NoteTab.13=File not saved!
NoteTab.14=\u0939\u093e\u0901
NoteTab.15=\u0928\u0939\u0940\u0902
NoteTab.16=Cancel
NoteTab.17=\u0906\u092a\u0915\u0940 \u090f\u0915 \u095e\u093e\u0907\u0932 \u091c\u092e\u093e \u0928\u0939\u0940\u0902 \u0939\u0948\u0964 \u0915\u094d\u092f\u093e \u0909\u0938\u0947 \u091c\u092e\u093e \u0915\u0930 \u0926\u0942\u0901 ?\n
NoteTab.18=File not saved!
NoteTab.19=\u090f\u0921\u093f\u091f
NoteTab.20=\u0915\u093e\u091f\u094b
NoteTab.21=\u0928\u0915\u0932 \u0915\u0930\u094b
NoteTab.22=\u091a\u093f\u092a\u0915\u093e\u0913
NoteTab.23=\u0938\u092c\u0915\u094b \u091a\u0941\u0928\u094b
NoteTab.24=\u0935\u093e\u092a\u0938 \u0915\u0930\u094b
NoteTab.25=\u095e\u093f\u0930 \u0938\u0947 \u0915\u0930\u094b
NoteTab.26=\u095e\u094b\u0930\u094d\u092e\u0948\u091f
NoteTab.27=\u0932\u093e\u0932
NoteTab.28=\u0915\u093e\u0932\u093e
NoteTab.29=\u0928\u0940\u0932\u093e
NoteTab.30=\u0906\u0915\u093e\u0930
NoteTab.31=\u092c\u0921\u093e
NoteTab.32=\u092e\u0927\u094d\u092f\u092e
NoteTab.33=\u091b\u094b\u091f\u093e
NoteTab.34=\u0938\u094d\u091f\u093e\u0907\u0932
NoteTab.35=\u092e\u094b\u091f\u093e
NoteTab.36=\u0928\u0940\u091a\u0947 \u0932\u093e\u0907\u0928
NoteTab.37=\u0924\u093f\u0930\u091b\u093e
NoteTab.38=Red
NoteTab.39=Black
NoteTab.40=Blue
NoteTab.41=
NoteTab.42=
NoteTab.43=
NoteTab.44=\u092e\u0926\u0926
NoteTab.45=exeption\!
NoteTab.46=exeption\!
NoteTab.47=
NoteTab.48=
NoteTab.49=Undo
NoteTab.50=Unable to undo:
NoteTab.51=Redo
NoteTab.52=Unable to redo:
NoteTab.53=\u092f\u0939\u093e\u0901 \u091c\u092e\u093e \u0915\u0930\u094b
NoteTab.54=paste.gif
IE.2=\u0918\u0942\u092e\u094b
IE.3=\u0935\u093e\u092a\u0938 \u091c\u093e\u0913
IE.4=\u0906\u0917\u0947 \u091c\u093e\u0913
IE.5=\u0918\u0930 \u091c\u093e\u0913
PaintIt.12=About
PaintIt.14=\u092c\u0929\u094d\u0926
PaintIt.16=\u0930\u0929\u094d\u0917
PaintIt.17=\u0914\u091c\u093e\u0930
PaintIt.18=\u092f\u0902\u0924\u094d\u0930
PaintIt.19=\u092f\u0902\u0924\u094d\u0930
Java hindi office suite:NoteTab
In our final year, we have to choose a project. I did this for my final year project. This basically is a simple Notepad and Internet explorer replacement, written in java. All the strings are externalised. While writing this we first wrote the program with english text in it. Then we externalised it. As I was using Eclipse this takes just one command. In Java perspective, source>externalise strings. So here are your .java files.
//NoteTab.java
/*
* Created on Dec 15, 2004
*/
package name.shabda.office;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.Hashtable;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.JTextComponent;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.rtf.RTFEditorKit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
/**
* @author dicky
* This class represents a moderately lame notepad replacement.
*/
public class NoteTab extends JFrame {
JTextPane editor;//the area where you write
Hashtable actions;//stores the actions
DefaultStyledDocument doc;//document for the test area
RTFEditorKit rtf = new RTFEditorKit();
protected UndoAction undoAction;//helper for undo jobs
protected RedoAction redoAction;//helper for redo jobs
protected UndoManager undoMan = new UndoManager();
JMenuItem redo;//I need to keep these class members(not local)
JMenuItem undo;//so that undoAction & redoAction can use it
private boolean needSave;//has the status of the document changed from last
// save?
private File currentFile;//File which is currently open.Null if user is
// creating from scratch
/**
* Initialise the class.So i need to 1.add editor to write 2.add menu 3.add
* toolbar
*/
public NoteTab() {
getContentPane().setLayout(new BorderLayout());
editor = addEditor();
doc.addUndoableEditListener(new MyUndoableEditListener());
doc.addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
needSave = true;//something has been inserted.I need to save.
}
public void removeUpdate(DocumentEvent e) {
needSave = true;//something has been removed.I need to save.
}
public void changedUpdate(DocumentEvent e) {
needSave = true;//something has been changed.I need to save.
}
});
JScrollPane pane = new JScrollPane(editor);
getContentPane().add(pane,BorderLayout.CENTER);
createActionTable(editor);
getContentPane().add(getAToolBar(),BorderLayout.NORTH);
setJMenuBar(addMenu());
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if(!needSave) {
System.exit(0);
}else {
Object[] options = { Messages.getString("NoteTab.0"), Messages.getString("NoteTab.1"), }; //$NON-NLS-1$ //$NON-NLS-2$
int n = JOptionPane
.showOptionDialog(NoteTab.this,
Messages.getString("NoteTab.2"), //$NON-NLS-1$
Messages.getString("NoteTab.3"), //$NON-NLS-1$
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options,
options[0]);
if (n == JOptionPane.YES_OPTION) {
//User wants to save the file
save();
System.exit(0);
} else if (n == JOptionPane.NO_OPTION) {
//This file should not be saved
System.exit(0);
}
//TODO add handler for cancel event
}
}
});
}
/**
* I need to add a menu to this frame.
*/
public JMenuBar addMenu() {
JMenuBar theMenu = new JMenuBar();
JMenu file = new JMenu(Messages.getString("NoteTab.4")); //$NON-NLS-1$
JMenuItem new1 = new JMenuItem(Messages.getString("NoteTab.5")); //$NON-NLS-1$
JMenuItem save = new JMenuItem(Messages.getString("NoteTab.6")); //$NON-NLS-1$
JMenuItem saveAs=new JMenuItem(Messages.getString("NoteTab.53")); //$NON-NLS-1$
JMenuItem open = new JMenuItem(Messages.getString("NoteTab.7")); //$NON-NLS-1$
JMenuItem print = new JMenuItem(Messages.getString("NoteTab.8")); //$NON-NLS-1$
new1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!needSave) {//dont need a save.go ahead.
newDoc();
} else {//You need to save the current document before
// proceeding
Object[] options = { Messages.getString("NoteTab.9"), Messages.getString("NoteTab.10"), Messages.getString("NoteTab.11") }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
int n = JOptionPane.showOptionDialog(NoteTab.this,
Messages.getString("NoteTab.12"), //$NON-NLS-1$
Messages.getString("NoteTab.13"), //$NON-NLS-1$
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options,
options[0]);
if (n == JOptionPane.YES_OPTION) {
//User wants to save the file
save();
newDoc();
} else if (n == JOptionPane.NO_OPTION) {
//This file should not be saved
newDoc();
} else if (n == JOptionPane.CLOSED_OPTION
|| n == JOptionPane.CANCEL_OPTION) {
//user has not made up his mind.dont do any thing.
}
}
}
});
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (currentFile != null)//there is current file, so save to it.
{
save();
} else {//no current file. I need to ask the user for location
saveAs();
}
}
});
saveAs.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveAs();
}
});
open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!needSave) {//dont need a save.go ahead.
open();
} else {//You need to save the current document before
// proceeding
Object[] options = { Messages.getString("NoteTab.14"), Messages.getString("NoteTab.15"), Messages.getString("NoteTab.16") }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
int n = JOptionPane.showOptionDialog(NoteTab.this,
Messages.getString("NoteTab.17"), //$NON-NLS-1$
Messages.getString("NoteTab.18"), //$NON-NLS-1$
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options,
options[0]);
if (n == JOptionPane.YES_OPTION) {
//User wants to save the file
save();
open();
} else if (n == JOptionPane.NO_OPTION) {
//This file should not be saved
open();
} else if (n == JOptionPane.CLOSED_OPTION
|| n == JOptionPane.CANCEL_OPTION) {
//user has not made up his mind.dont do any thing.
}
}
}
});
file.add(new1);
file.add(save);
file.add(saveAs);
file.add(open);
file.add(print);
theMenu.add(file);
JMenu edit = new JMenu(Messages.getString("NoteTab.19")); //$NON-NLS-1$
JMenuItem cut = new JMenuItem(Messages.getString("NoteTab.20")); //$NON-NLS-1$
cut.addActionListener(getActionByName(DefaultEditorKit.cutAction));
JMenuItem copy = new JMenuItem(Messages.getString("NoteTab.21")); //$NON-NLS-1$
copy.addActionListener(getActionByName(DefaultEditorKit.copyAction));
JMenuItem paste = new JMenuItem(Messages.getString("NoteTab.22")); //$NON-NLS-1$
paste.addActionListener(getActionByName(DefaultEditorKit.pasteAction));
JMenuItem selectAll = new JMenuItem(Messages.getString("NoteTab.23")); //$NON-NLS-1$
selectAll
.addActionListener(getActionByName(DefaultEditorKit.selectAllAction));
undo = new JMenuItem(Messages.getString("NoteTab.24")); //$NON-NLS-1$
undoAction = new UndoAction();
undo.addActionListener(undoAction);
redo = new JMenuItem(Messages.getString("NoteTab.25")); //$NON-NLS-1$
redoAction = new RedoAction();
redo.addActionListener(redoAction);
edit.add(cut);
edit.add(copy);
edit.add(paste);
edit.add(selectAll);
edit.add(undo);
edit.add(redo);
theMenu.add(edit);
JMenu format = new JMenu(Messages.getString("NoteTab.26")); //$NON-NLS-1$
JMenuItem red = new JMenuItem(Messages.getString("NoteTab.27")); //$NON-NLS-1$
JMenuItem black = new JMenuItem(Messages.getString("NoteTab.28")); //$NON-NLS-1$
JMenuItem blue = new JMenuItem(Messages.getString("NoteTab.29")); //$NON-NLS-1$
JMenu fonts=new JMenu(Messages.getString("NoteTab.30")); //$NON-NLS-1$
JMenuItem bigFont=new JMenuItem(Messages.getString("NoteTab.31")); //$NON-NLS-1$
JMenuItem mediumFont=new JMenuItem(Messages.getString("NoteTab.32")); //$NON-NLS-1$
JMenuItem smallFont=new JMenuItem(Messages.getString("NoteTab.33")); //$NON-NLS-1$
fonts.add(bigFont);
fonts.add(mediumFont);
fonts.add(smallFont);
JMenu style=new JMenu(Messages.getString("NoteTab.34")); //$NON-NLS-1$
JMenuItem bold=new JMenuItem(Messages.getString("NoteTab.35")); //$NON-NLS-1$
JMenuItem underLine=new JMenuItem(Messages.getString("NoteTab.36")); //$NON-NLS-1$
JMenuItem italics=new JMenuItem(Messages.getString("NoteTab.37")); //$NON-NLS-1$
style.add(bold);
style.add(underLine);
style.add(italics);
format.add(red);
format.add(black);
format.add(blue);
format.add(fonts);
format.add(style);
red.addActionListener(new StyledEditorKit.ForegroundAction(Messages.getString("NoteTab.38"), //$NON-NLS-1$
Color.red));
black.addActionListener(new StyledEditorKit.ForegroundAction(Messages.getString("NoteTab.39"), //$NON-NLS-1$
Color.black));
blue.addActionListener(new StyledEditorKit.ForegroundAction(Messages.getString("NoteTab.40"), //$NON-NLS-1$
Color.blue));
bigFont.addActionListener(new StyledEditorKit.FontSizeAction(Messages.getString("NoteTab.41"),20)); //$NON-NLS-1$
bigFont.addActionListener(new StyledEditorKit.FontSizeAction(Messages.getString("NoteTab.42"),15)); //$NON-NLS-1$
smallFont.addActionListener(new StyledEditorKit.FontSizeAction(Messages.getString("NoteTab.43"),10)); //$NON-NLS-1$
bold.addActionListener(new StyledEditorKit.BoldAction());
underLine.addActionListener(new StyledEditorKit.UnderlineAction());
italics.addActionListener(new StyledEditorKit.ItalicAction());
theMenu.add(format);
JMenu help = new JMenu(Messages.getString("NoteTab.44")); //$NON-NLS-1$
theMenu.add(help);
return theMenu;
}
public JToolBar getAToolBar() {
JToolBar tools=new JToolBar();
JButton newDoc=new JButton(); //$NON-NLS-1$
ImageIcon ii=createImageIcon("../images/new.gif", null); //$NON-NLS-1$
newDoc.setIcon(ii);
JButton save=new JButton(); //$NON-NLS-1$
ii=createImageIcon("../images/save.gif", null); //$NON-NLS-1$
save.setIcon(ii);
JButton open=new JButton(); //$NON-NLS-1$
ii=createImageIcon("../images/open.gif", null); //$NON-NLS-1$
open.setIcon(ii);
JButton cut=new JButton(); //$NON-NLS-1$
ii=createImageIcon("../images/cut.gif", null); //$NON-NLS-1$
cut.setIcon(ii);
JButton copy=new JButton(); //$NON-NLS-1$
ii=createImageIcon("../images/copy.gif", null);
copy.setIcon(ii);
JButton paste=new JButton(); //$NON-NLS-1$
ii=createImageIcon("../images/paste.gif", null);
paste.setIcon(ii);
newDoc.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!needSave) {//dont need a save.go ahead.
newDoc();
} else {//You need to save the current document before
// proceeding
Object[] options = { Messages.getString("NoteTab.9"), Messages.getString("NoteTab.10"), Messages.getString("NoteTab.11") }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
int n = JOptionPane.showOptionDialog(NoteTab.this,
Messages.getString("NoteTab.12"), //$NON-NLS-1$
Messages.getString("NoteTab.13"), //$NON-NLS-1$
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options,
options[0]);
if (n == JOptionPane.YES_OPTION) {
//User wants to save the file
save();
newDoc();
} else if (n == JOptionPane.NO_OPTION) {
//This file should not be saved
newDoc();
} else if (n == JOptionPane.CLOSED_OPTION
|| n == JOptionPane.CANCEL_OPTION) {
//user has not made up his mind.dont do any thing.
}
}
}
});
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (currentFile != null)//there is current file, so save to it.
{
save();
} else {//no current file. I need to ask the user for location
saveAs();
}
}
});
open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!needSave) {//dont need a save.go ahead.
open();
} else {//You need to save the current document before
// proceeding
Object[] options = { Messages.getString("NoteTab.14"), Messages.getString("NoteTab.15"), Messages.getString("NoteTab.16") }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
int n = JOptionPane.showOptionDialog(NoteTab.this,
Messages.getString("NoteTab.17"), //$NON-NLS-1$
Messages.getString("NoteTab.18"), //$NON-NLS-1$
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options,
options[0]);
if (n == JOptionPane.YES_OPTION) {
//User wants to save the file
save();
open();
} else if (n == JOptionPane.NO_OPTION) {
//This file should not be saved
open();
} else if (n == JOptionPane.CLOSED_OPTION
|| n == JOptionPane.CANCEL_OPTION) {
//user has not made up his mind.dont do any thing.
}
}
}
});
cut.addActionListener(getActionByName(DefaultEditorKit.cutAction));
copy.addActionListener(getActionByName(DefaultEditorKit.copyAction));
paste.addActionListener(getActionByName(DefaultEditorKit.pasteAction));
tools.add(newDoc);
tools.add(save);
tools.add(open);
tools.addSeparator();
tools.add(cut);
tools.add(copy);
tools.add(paste);
tools.addSeparator();
return tools;
}
/**
* save the file Get file where we want to save the data from the user.
*/
public void saveAs() {
JFileChooser fc = new JFileChooser();
fc.addChoosableFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
String extension = getExtension(f);
if (extension != null) {
if (extension.equals("rtf")) {
return true;
} else {
return false;
}
}
return false;
}
public String getDescription() {
return "Rich Text Format(Hindi) Files";
}});
int returnVal = fc.showSaveDialog(NoteTab.this);//this is tricky.I dont
// understand it but..
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
try {
FileOutputStream out = new FileOutputStream(file);
rtf.write(out, doc, 0, doc.getLength());
needSave = false;//have saved.no need to save it donot edit
} catch (Exception ee) {
System.out.println(Messages.getString("NoteTab.45")); //$NON-NLS-1$
ee.printStackTrace();
}
}
}
/**
* save the file in current file.
*/
public void save() {
if (currentFile != null) {//Current file is not null. Can save without
// bothering user
try {
FileOutputStream out = new FileOutputStream(currentFile);
rtf.write(out, doc, 0, doc.getLength());
needSave = false;//have saved.no need to save it donot edit
} catch (Exception ee) {
System.out.println(Messages.getString("NoteTab.46")); //$NON-NLS-1$
ee.printStackTrace();
}
}
else
saveAs();//Current file is null. I have to ask the user the correct
// place.
}
/**
* open a file.
* Warning! This doesnot check if a save is needed.This
* resposiblity is upto you.
*/
public void open() {
JFileChooser fc = new JFileChooser();
fc.addChoosableFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
String extension = getExtension(f);
if (extension != null) {
if (extension.equals("rtf")) {
return true;
} else {
return false;
}
}
return false;
}
public String getDescription() {
return "Rich Text Format(Hindi) Files";
}});
int returnVal = fc.showOpenDialog(NoteTab.this);//this is tricky.I dont
// understand it but..
if (returnVal == JFileChooser.APPROVE_OPTION) {
editor.setText(Messages.getString("NoteTab.47"));//need to show a new file.So clear the screen. //$NON-NLS-1$
File file = fc.getSelectedFile();
currentFile = file;
try {
FileReader in = new FileReader(file);
rtf.read(in, doc, 0);
} catch (Exception ee) {
}
needSave = false;//just opened a file. No need to save now.
}
}
/**
* this creates a new document to write on. As always we donot check if a
* save is needed This job is left for the caller.
*/
public void newDoc() {
editor.setText(Messages.getString("NoteTab.48"));//clear the editor //$NON-NLS-1$
currentFile = null;//new document.No current file.
needSave = false;
}
/**
* Get a editor for the frame
*/
public JTextPane addEditor() {
//doc=new RTFStyledDocument();
doc = new DefaultStyledDocument();
JTextPane pane = new JTextPane(doc);
pane.setPreferredSize(new Dimension(600, 400));
return pane;
}
/**
* Create a hashTable from the actions supported by this component
*/
private void createActionTable(JTextComponent textComponent) {
actions = new Hashtable();
Action[] actionsArray = textComponent.getActions();
for (int i = 0; i < actionsArray.length; i++) {
Action a = actionsArray[i];
actions.put(a.getValue(Action.NAME), a);
}
}
private Action getActionByName(String name) {
return (Action) (actions.get(name));
}
class UndoAction extends AbstractAction {
public UndoAction() {
super(Messages.getString("NoteTab.49")); //$NON-NLS-1$
undo.setEnabled(false);
}
public void actionPerformed(ActionEvent e) {
try {
undoMan.undo();
} catch (CannotUndoException ex) {
System.out.println(Messages.getString("NoteTab.50") + ex); //$NON-NLS-1$
ex.printStackTrace();
}
updateUndoState();
redoAction.updateRedoState();
}
protected void updateUndoState() {
if (undoMan.canUndo()) {
undo.setEnabled(true);
} else {
undo.setEnabled(false);
}
}
}
class RedoAction extends AbstractAction {
public RedoAction() {
super(Messages.getString("NoteTab.51")); //$NON-NLS-1$
redo.setEnabled(false);
}
public void actionPerformed(ActionEvent e) {
try {
undoMan.redo();
} catch (CannotRedoException ex) {
System.out.println(Messages.getString("NoteTab.52") + ex); //$NON-NLS-1$
ex.printStackTrace();
}
updateRedoState();
undoAction.updateUndoState();
}
protected void updateRedoState() {
if (undoMan.canRedo()) {
redo.setEnabled(true);
} else {
redo.setEnabled(false);
}
}
}
/*
* (non-Javadoc)
*
* @see java.awt.Window#addWindowListener(java.awt.event.WindowListener)
*/
protected class MyUndoableEditListener implements UndoableEditListener {
public void undoableEditHappened(UndoableEditEvent e) {
//Remember the edit and update the menus.
undoMan.addEdit(e.getEdit());
undoAction.updateUndoState();
redoAction.updateRedoState();
}
}
/**
* Create a imageIcon by getting a relative link
* */
protected static ImageIcon createImageIcon(String path,
String description) {
java.net.URL imgURL = NoteTab.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
/**
* Get the file extension from that file
* */
public static String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1) {
ext = s.substring(i+1).toLowerCase();
}
return ext;
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
} catch (Exception e) {
}
NoteTab app = new NoteTab();
app.pack();
app.show();
}
}
But you need two more files to compile it. A Messages.java file is needed to get the strings and messages.properties is needed to keep the actual localised strings. So here is your Messages.java file
//Messages.java
/*
* Created on Dec 16, 2004
*/
package name.shabda.office;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* @author dicky
*/
public class Messages {
private static final String BUNDLE_NAME = "name.shabda.office.messages";//$NON-NLS-1$
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
.getBundle(BUNDLE_NAME);
private Messages() {
}
public static String getString(String key) {
// TODO Auto-generated method stub
try {
return RESOURCE_BUNDLE.getString(key);
} catch (MissingResourceException e) {
return '!' + key + '!';
}
}
}
And the messages.properties file is localised to display the hindi strings.
Some text which are for debugging are not localised.
NoteTab.0=\u0939\u093e\u0901
NoteTab.1=\u0928\u0939\u0940\u0902
NoteTab.2=\u0906\u092a\u0915\u0940 \u090f\u0915 \u095e\u093e\u0907\u0932 \u091c\u092e\u093e \u0928\u0939\u0940\u0902 \u0939\u0948\u0964 \u0915\u094d\u092f\u093e \u0909\u0938\u0947 \u091c\u092e\u093e \u0915\u0930 \u0926\u0942\u0901 ?\n
NoteTab.3=File not saved!
NoteTab.4=\u095e\u093e\u0907\u0932
NoteTab.5=\u0928\u092f\u093e
NoteTab.6=\u091c\u092e\u093e \u0915\u0930\u094b
NoteTab.7=\u0916\u094b\u0932\u094b
NoteTab.8=\u091b\u093e\u092a\u094b
NoteTab.9=\u0939\u093e\u0901
NoteTab.10=\u0928\u0939\u0940\u0902
NoteTab.11=Cancel
NoteTab.12=\u0906\u092a\u0915\u0940 \u090f\u0915 \u095e\u093e\u0907\u0932 \u091c\u092e\u093e \u0928\u0939\u0940\u0902 \u0939\u0948\u0964 \u0915\u094d\u092f\u093e \u0909\u0938\u0947 \u091c\u092e\u093e \u0915\u0930 \u0926\u0942\u0901 ?\n
NoteTab.13=File not saved!
NoteTab.14=\u0939\u093e\u0901
NoteTab.15=\u0928\u0939\u0940\u0902
NoteTab.16=Cancel
NoteTab.17=\u0906\u092a\u0915\u0940 \u090f\u0915 \u095e\u093e\u0907\u0932 \u091c\u092e\u093e \u0928\u0939\u0940\u0902 \u0939\u0948\u0964 \u0915\u094d\u092f\u093e \u0909\u0938\u0947 \u091c\u092e\u093e \u0915\u0930 \u0926\u0942\u0901 ?\n
NoteTab.18=File not saved!
NoteTab.19=\u090f\u0921\u093f\u091f
NoteTab.20=\u0915\u093e\u091f\u094b
NoteTab.21=\u0928\u0915\u0932 \u0915\u0930\u094b
NoteTab.22=\u091a\u093f\u092a\u0915\u093e\u0913
NoteTab.23=\u0938\u092c\u0915\u094b \u091a\u0941\u0928\u094b
NoteTab.24=\u0935\u093e\u092a\u0938 \u0915\u0930\u094b
NoteTab.25=\u095e\u093f\u0930 \u0938\u0947 \u0915\u0930\u094b
NoteTab.26=\u095e\u094b\u0930\u094d\u092e\u0948\u091f
NoteTab.27=\u0932\u093e\u0932
NoteTab.28=\u0915\u093e\u0932\u093e
NoteTab.29=\u0928\u0940\u0932\u093e
NoteTab.30=\u0906\u0915\u093e\u0930
NoteTab.31=\u092c\u0921\u093e
NoteTab.32=\u092e\u0927\u094d\u092f\u092e
NoteTab.33=\u091b\u094b\u091f\u093e
NoteTab.34=\u0938\u094d\u091f\u093e\u0907\u0932
NoteTab.35=\u092e\u094b\u091f\u093e
NoteTab.36=\u0928\u0940\u091a\u0947 \u0932\u093e\u0907\u0928
NoteTab.37=\u0924\u093f\u0930\u091b\u093e
NoteTab.38=Red
NoteTab.39=Black
NoteTab.40=Blue
NoteTab.41=
NoteTab.42=
NoteTab.43=
NoteTab.44=\u092e\u0926\u0926
NoteTab.45=exeption\!
NoteTab.46=exeption\!
NoteTab.47=
NoteTab.48=
NoteTab.49=Undo
NoteTab.50=Unable to undo:
NoteTab.51=Redo
NoteTab.52=Unable to redo:
NoteTab.53=\u092f\u0939\u093e\u0901 \u091c\u092e\u093e \u0915\u0930\u094b
NoteTab.54=paste.gif
IE.2=\u0918\u0942\u092e\u094b
IE.3=\u0935\u093e\u092a\u0938 \u091c\u093e\u0913
IE.4=\u0906\u0917\u0947 \u091c\u093e\u0913
IE.5=\u0918\u0930 \u091c\u093e\u0913
PaintIt.12=About
PaintIt.14=\u092c\u0929\u094d\u0926
PaintIt.16=\u0930\u0929\u094d\u0917
PaintIt.17=\u0914\u091c\u093e\u0930
PaintIt.18=\u092f\u0902\u0924\u094d\u0930
PaintIt.19=\u092f\u0902\u0924\u094d\u0930
Next we will look at the Explorer replacement.