OSDN Git Service

update a chartool (pygtk version) to be able to search chars by a character code
[sawarabi-fonts/sawarabi-fonts.git] / chartool / pygtk / main.py
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3
4 import gtk
5 import os
6 import pygtk
7 import re
8
9
10 class Controller:
11     def __init__(self, glade_file_path):
12         builder = gtk.Builder()
13         builder.add_from_file(glade_file_path)
14         builder.connect_signals(self)
15
16         self.entries = dict([(nm, builder.get_object("entry_%s" % nm)) \
17                                  for nm in ['search', 'code', 'name']])
18         self.search_action = SearchAction(self.entries['search'])
19         self.label_char = builder.get_object('label_char')
20         self.menu_label_char = builder.get_object('menu_label_char')
21         self.font_name = None
22         self.font_dialog = builder.get_object('fontselectiondialog')
23         self.window = builder.get_object('window_main')
24         self.window.show()
25
26         gtk.main()
27
28     def end_application(self, widget, data=None):
29         gtk.main_quit()
30         return False
31
32     def on_button_search_clicked(self, widget, data=None):
33         a = self.search_action
34         a.set_next()
35         a.put_code(self.entries['code'])
36         a.put_char(self.label_char, self.font_name)
37
38         return False
39
40     def on_entry_search_activate(self, widget, data=None):
41         self.on_button_search_clicked(widget, data)
42
43         return False
44
45     def on_label_char_button_press_event(self, widget, event=None):
46         if event.button == 3:
47             self.menu_label_char.popup(None, None, None, event.button, event.time)
48             return True
49         return False
50
51     def on_menuitem_font_activate(self, widget, event=None):
52         self.font_dialog.show()
53
54         return False
55
56     def on_fontsel_cancel_button_clicked(self, widget, data=None):
57         self.font_dialog.hide()
58
59         return False
60
61     def on_fontsel_ok_button_clicked(self, widget, data=None):
62         self.font_name = self.font_dialog.get_font_name()
63         self.font_dialog.hide()
64         self.search_action.put_char(self.label_char, self.font_name)
65
66         return False
67
68
69 class SearchAction:
70     re_hex = re.compile(r"[0-9a-fA-F]")
71
72     def __init__(self, entry_search):
73         self.entry_search = entry_search
74         self.char_util = CharUtil()
75         self.code = None
76         self.char = ''
77
78     def set_next(self):
79         en = self.entry_search
80         buf = en.get_text().decode('utf-8')
81         if len(buf) == 0: return
82
83         pos = en.get_position()
84         if pos == len(buf): pos = 0
85         region = self.get_target_region(buf, pos)
86         target = buf[region[0]:region[1]]
87         en.select_region(region[0], region[1])
88         ch = self.char_util.get_unichar(target)
89
90         self.code = hex(ord(ch))
91         self.char = ch
92
93     def put_code(self, entry):
94         if not self.code: return
95
96         entry.set_text(self.code)
97
98     def put_char(self, label, font_name):
99         if not self.char: return
100         if not font_name: font_name = '80'
101
102         mu = '<span font="%s">%s</span>' % (font_name, self.char)
103         label.set_markup(mu)
104
105     def get_target_region(self, text, pos):
106         ch = text[pos:pos + 1]
107         rlen = 0
108         llen = 0
109         while rlen <= 4 and self.char_util.is_hex_char(ch):
110             rlen += 1
111             if pos + rlen >= len(text): break
112             ch = text[(pos + rlen):(pos + rlen + 1)]
113         if rlen >= 1 and rlen < 5:
114             while rlen + llen <= 4 and pos - llen > 0:
115                 ch = text[(pos - llen - 1):(pos - llen)]
116                 if not self.char_util.is_hex_char(ch): break
117                 llen += 1
118         ret = (pos - llen, pos + rlen)
119         if ret == (pos, pos): return (pos, pos + 1)
120         return ret
121
122 class CharUtil:
123     def is_hex_char(self, char):
124         return (char >= '0' and char <= '9') or \
125             (char >= 'a' and char <= 'f') or \
126             (char >= 'A' and char <= 'F')
127
128     def get_unichar(self, buf):
129         if len(buf) <= 1: return buf
130
131         return unichr(int(buf, 16))
132
133
134 if __name__ == '__main__':
135     path = os.path.abspath(os.path.dirname(__file__))
136     Controller(os.path.join(path, 'window_main.glade'))