ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/kgsueme/kgsueme/superchat.pl
Revision: 1.1
Committed: Thu May 20 23:09:53 2004 UTC (20 years ago) by pcg
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 package superchat;
2    
3     # waaay cool widget. well... maybe at one point in the future
4    
5     use Gtk2;
6    
7     use Glib::Object::Subclass
8     Gtk2::VBox,
9     signals => {
10     command => {
11     flags => [qw/run-first/],
12     return_type => undef, # void return
13     param_types => [Glib::Scalar, Glib::Scalar],
14     },
15     };
16    
17     my $tagtable = new Gtk2::TextTagTable;
18    
19     {
20     my %tags = (
21     default => { foreground => "black" },
22     node => { foreground => "#0000b0", event => 1 },
23     move => { foreground => "#0000b0", event => 1 },
24     user => { foreground => "#0000b0", event => 1 },
25     coord => { foreground => "#0000b0", event => 1 },
26     error => { foreground => "#ff0000", event => 1 },
27     header => { weight => 800, pixels_above_lines => 6 },
28     description => { weight => 800, foreground => "blue" },
29     infoblock => { weight => 700, foreground => "blue" },
30     );
31    
32     while (my ($k, $v) = each %tags) {
33     my $tag = new Gtk2::TextTag $k;
34     if (delete $v->{event}) {
35     ###
36     }
37     $tag->set (%$v);
38     $tagtable->add ($tag);
39     }
40     }
41    
42     sub INIT_INSTANCE {
43     my $self = shift;
44    
45     $self->signal_connect (destroy => sub {
46     remove Glib::Source delete $self->{idle} if $self->{idle};
47     %{$_[0]} = ();
48     });
49    
50     $self->{buffer} = new Gtk2::TextBuffer $tagtable;
51    
52     $self->{widget} = new Gtk2::ScrolledWindow;
53     $self->{widget}->set_policy("never", "always");
54     $self->pack_start ($self->{widget}, 1, 1, 0);
55    
56     $self->{widget}->add ($self->{view} = new_with_buffer Gtk2::TextView $self->{buffer});
57     $self->{view}->set_wrap_mode ("word");
58     $self->{view}->set_cursor_visible (0);
59    
60     $self->{view}->set_editable (0);
61    
62     $self->{view}->signal_connect (motion_notify_event => sub {
63     my ($widget, $event) = @_;
64    
65     my $window = $widget->get_window ("text");
66     if ($event->window == $window) {
67     my ($win, $x, $y, $mask) = $window->get_pointer;
68     # warn "TAG EVENT @_ ($window, $win, $x, $y, $mask)\n";
69     #gtk_text_view_window_to_buffer_coords (text_view,
70     # GTK_TEXT_WINDOW_TEXT,
71     # text_view->drag_start_x,
72     # text_view->drag_start_y,
73     # &buffer_x,
74     # &buffer_y);
75     #
76     # gtk_text_layout_get_iter_at_pixel (text_view->layout,
77     # &iter,
78     # buffer_x, buffer_y);
79     #
80     # gtk_text_view_start_selection_dnd (text_view, &iter, event);
81     # return TRUE;
82     }
83     0;
84     });
85    
86     $self->pack_start (($self->{entry} = new Gtk2::Entry), 0, 1, 0);
87    
88     $self->{entry}->signal_connect(activate => sub {
89     my ($entry) = @_;
90     my $text = $entry->get_text;
91     $entry->set_text("");
92    
93     my ($cmd, $arg);
94    
95     if ($text =~ /^\/(\S+)\s*(.*)$/) {
96     ($cmd, $arg) = ($1, $2);
97     } else {
98     ($cmd, $arg) = ("say", $text);
99     }
100    
101     $self->signal_emit (command => $cmd, $arg);
102     });
103    
104    
105     $self->set_end;
106     }
107    
108     sub do_command {
109     my ($self, $cmd, $arg, %arg) = @_;
110     }
111    
112     sub set_end {
113     my ($self) = @_;
114    
115     # this is probably also a hack...
116     $self->{idle} ||= add Glib::Idle sub {
117     $self->{view}->scroll_to_iter ($self->{buffer}->get_end_iter, 0, 0, 0, 0)
118     if $self->{view};
119     delete $self->{idle};
120     };
121     }
122    
123     sub at_end {
124     my ($self) = @_;
125    
126     # this is, maybe, a bad hack :/
127     my $adj = $self->{widget}->get_vadjustment;
128     $adj->value + $adj->page_size >= $adj->upper - 0.5;
129     }
130    
131     sub append_text {
132     my ($self, $text) = @_;
133    
134     my $at_end = $self->at_end;
135    
136     my @tag;
137     $text = "<default>$text</default>";
138    
139     # pseudo-simplistic-xml-parser
140     for (;;) {
141     $text =~ /\G<([^>]+)>/gc or last;
142     my $tag = $1;
143     if ($tag =~ s/^\///) {
144     pop @tag;
145     } else {
146     push @tag, $tag;
147     }
148    
149     $text =~ /\G([^<]*)/gc or last;
150     $self->{buffer}->insert_with_tags_by_name ($self->{buffer}->get_end_iter, util::xmlto $1, $tag[-1])
151     if length $1;
152     }
153    
154     $self->set_end if $at_end;
155     }
156    
157     sub set_text {
158     my ($self, $text) = @_;
159    
160     my $at_end = $self->at_end;
161    
162     $self->{buffer}->set_text ("");
163     $self->append_text ($text);
164    
165     $self->set_end if $at_end;
166     }
167    
168     1;
169