package textview;
import java.io.FileNotFoundException;
import org.gnome.gdk.Event;
import org.gnome.gdk.EventKey;
import org.gnome.gdk.Keyval;
import org.gnome.gdk.Pixbuf;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.IconSize;
import org.gnome.gtk.ScrolledWindow;
import org.gnome.gtk.Stock;
import org.gnome.gtk.TextBuffer;
import org.gnome.gtk.TextIter;
import org.gnome.gtk.TextTag;
import org.gnome.gtk.TextView;
import org.gnome.gtk.VBox;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.pango.Style;
import org.gnome.pango.Weight;
import static org.freedesktop.bindings.Time.formatTime;
import static org.gnome.gtk.PolicyType.ALWAYS;
import static org.gnome.gtk.PolicyType.NEVER;
import static org.gnome.gtk.ShadowType.IN;
import static org.gnome.gtk.WrapMode.NONE;
import static org.gnome.gtk.WrapMode.WORD;
/**
* An example of rendering multi-line text in an application.
*
* There comes a point when it is difficult to demonstrate complex
* functionality in a trivial example, so so illustrate usage of the powerful
* TextView/TextBuffer APIs, we so we have opted to do something a bit more
* involved.
*
* This program creates the conversation window you might see in a typical
* graphical instant messenger. It has a TextView displaying the conversation
* above, and uses various formatting to differentiate between incoming
* messages and outgoing ones. There is a second TextView at the bottom where
* the user can write the messages and "send" them. Finally, a tiny worker
* thread is kicked off to simulate incoming conversation.
*
* Enjoy!
*
* @author Andrew Cowie
* @author Stefan Prelle
* @author Serkan Kaba
*/
public class ExampleInstantMessenger
{
private final TextBuffer buffer;
private final TextView incoming;
private final TextView outgoing;
private final Pixbuf smiley;
private final TextTag grey, italics, blue;
private ExampleInstantMessenger() {
final Window window;
final VBox top;
final ScrolledWindow scroll1, scroll2;
final Thread other;
Pixbuf tmp;
window = new Window();
window.setTitle("Instant Messaging");
window.setDefaultSize(300, 200);
top = new VBox(false, 3);
window.add(top);
window.connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});
buffer = new TextBuffer();
incoming = new TextView(buffer);
incoming.setEditable(false);
incoming.setCursorVisible(false);
incoming.setPaddingBelowParagraph(10);
incoming.setWrapMode(WORD);
scroll1 = new ScrolledWindow();
scroll1.setPolicy(NEVER, ALWAYS);
scroll1.setShadowType(IN);
scroll1.add(incoming);
top.packStart(scroll1, true, true, 0);
outgoing = new TextView();
outgoing.setSizeRequest(0, 20);
outgoing.setAcceptsTab(false);
outgoing.setWrapMode(NONE);
scroll2 = new ScrolledWindow();
scroll2.setPolicy(NEVER, NEVER);
scroll2.setShadowType(IN);
scroll2.add(outgoing);
top.packStart(scroll2, false, false, 0);
outgoing.connect(new Widget.KeyPressEvent() {
public boolean onKeyPressEvent(Widget source, EventKey event) {
if (event.getKeyval() == Keyval.Return) {
final TextBuffer buffer;
final String str;
buffer = outgoing.getBuffer();
str = buffer.getText();
appendMessage(str, true);
buffer.setText("");
return true;
}
return false;
}
});
outgoing.attachSpell("en");
grey = new TextTag();
grey.setForeground("#777777");
italics = new TextTag();
italics.setStyle(Style.ITALIC);
italics.setForeground("darkgreen");
blue = new TextTag();
blue.setWeight(Weight.BOLD);
blue.setForeground("blue");
try {
tmp = new Pixbuf("doc/examples/textview/face-smile.png");
} catch (FileNotFoundException fnfe) {
System.err.println("Warning: smiley image " + fnfe.getMessage());
tmp = Gtk.renderIcon(window, Stock.MISSING_IMAGE, IconSize.BUTTON);
}
smiley = tmp;
window.showAll();
outgoing.grabFocus();
other = new IncomingConversation();
other.start();
}
private void appendMessage(String msg, boolean outbound) {
final TextIter end;
final long now;
final String timestamp;
final TextTag colour;
int i;
int prev;
end = buffer.getIterEnd();
buffer.insert(end, "\n");
now = System.currentTimeMillis() / 1000;
timestamp = formatTime("%H:%M:%S\t", now);
buffer.insert(end, timestamp, grey);
if (outbound) {
colour = blue;
} else {
colour = null;
}
prev = 0;
while ((i = msg.indexOf(":)", prev)) != -1) {
buffer.insert(end, msg.substring(prev, i), colour);
buffer.insert(end, smiley);
i += 2;
prev = i;
}
buffer.insert(end, msg.substring(prev), colour);
incoming.scrollTo(end);
}
private void startConversationWith(String who) {
final TextIter pointer;
pointer = buffer.getIterStart();
buffer.insert(pointer, "Starting conversation with " + who, italics);
}
public static void main(String[] args) {
Gtk.init(args);
new ExampleInstantMessenger();
Gtk.main();
}
class IncomingConversation extends Thread
{
private final String[] messages;
private IncomingConversation() {
this.setDaemon(true);
messages = new String[] {
"Hello there!",
"Will you be my friend? :)",
"I live in Kenya. " + "It's nice here because it is so warm.",
"Someday, though, I want to see snow. " + "Perhaps I will go climb Kilimanjaro.",
"Did you see the marathon on the last day of the Olympics? "
+ "What a run by Samuel Wanjiru! " + "We are all so proud."
};
startConversationWith("Catherine Ojiambo");
}
public void run() {
for (int i = 0; i < messages.length; i++) {
try {
sleep((int) (1000 + i * 2000 * Math.random()));
} catch (InterruptedException ie) {
}
appendMessage(messages[i], false);
}
}
}
}