Skip to content

Instantly share code, notes, and snippets.

@ShikiOkasaka
Created February 21, 2019 11:59
Show Gist options
  • Save ShikiOkasaka/6939177720649ef88f3f52c3e646b9b9 to your computer and use it in GitHub Desktop.
Save ShikiOkasaka/6939177720649ef88f3f52c3e646b9b9 to your computer and use it in GitHub Desktop.
ibusの周辺テキストをつかった漢字入力に対応したアプリの例。
#!/usr/bin/python3
#
# Copyright (c) 2017 Esrille Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib
import cairo
class Example(Gtk.Window):
def __init__(self):
super(Example, self).__init__()
canvas = Gtk.DrawingArea()
canvas.connect("draw", self.on_draw)
self.add(canvas)
self.set_title("IMContext Demo")
self.resize(640, 48)
self.set_position(Gtk.WindowPosition.CENTER)
self.connect("delete-event", Gtk.main_quit)
self.show_all()
self.connect("key-press-event", self.on_key_press)
self.connect("key-release-event", self.on_key_release)
self.connect("focus-in-event", self.on_focus_in)
self.connect("focus-out-event", self.on_focus_out)
self.im_context = Gtk.IMMulticontext();
self.im_context.set_client_window(canvas.get_window())
self.im_context.connect("commit", self.on_commit);
self.im_context.connect("delete-surrounding", self.on_delete_surrounding);
self.im_context.connect("retrieve-surrounding", self.on_retrieve_surrounding);
self.im_context.connect("preedit-changed", self.on_preedit_changed);
self.im_context.connect("preedit-end", self.on_preedit_end);
self.im_context.connect("preedit-start", self.on_preedit_start);
self.__text = 'こんにちは、世界!'
self.__cur = len(self.__text)
self.__blink = True
self.__active = False
self.__preedit = ('', None, 0)
GLib.timeout_add(600, self.on_blink)
def on_blink(self):
self.__blink ^= True
self.queue_draw()
return True
def on_draw(self, wid, cr):
context = wid.get_style_context()
width = wid.get_allocated_width()
height = wid.get_allocated_height()
cr.set_source_rgb(255, 255, 255)
cr.rectangle(0, 0, width, height)
cr.fill()
cr.set_source_rgb(0, 0, 0)
cr.select_font_face("Noto Sans Mono CJK JP", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
cr.set_font_size(16)
cr.move_to(10, 26)
current = self.__text[:self.__cur]
if self.__preedit[0]:
text = current + self.__preedit[0] + self.__text[self.__cur:]
current += self.__preedit[0][:self.__preedit[2]]
else:
text = self.__text
cr.show_text(text)
ext = cr.text_extents(current)
# Display the caret:
#
# Pick x_advance not width.
# ext would look like (2.0, -14.0, 206.0, 16.0, 256.0, 0.0).
r = Gdk.Rectangle()
r.x, r.y, r.width, r.height = 10 + ext[4], 12, 2, 16
self.im_context.set_cursor_location(r)
if self.__blink and self.__active:
cr.rectangle(r.x, r.y, r.width, r.height)
cr.fill()
def on_focus_in(self, wid, event):
self.__active = True
self.im_context.focus_in()
return True;
def on_focus_out(self, wid, event):
self.__active = False
self.im_context.focus_out()
return True;
def on_key_press(self, wid, event):
# print("'", Gdk.keyval_name(event.keyval), "', ", event.state, sep='')
if self.im_context.filter_keypress(event):
return True;
if event.keyval == Gdk.KEY_BackSpace:
if 0 < self.__cur:
self.__text = self.__text[:self.__cur - 1] + self.__text[self.__cur:]
self.__cur -= 1
self.queue_draw()
return True
elif event.keyval == Gdk.KEY_Left:
if 0 < self.__cur:
self.__cur -= 1
self.queue_draw()
return True
elif event.keyval == Gdk.KEY_Right:
if self.__cur < len(self.__text):
self.__cur += 1
self.queue_draw()
return True
elif event.keyval == Gdk.KEY_Home:
if 0 < self.__cur:
self.__cur = 0
self.queue_draw()
return True
elif event.keyval == Gdk.KEY_End:
if self.__cur < len(self.__text):
self.__cur = len(self.__text)
self.queue_draw()
return True
return False;
def on_key_release(self, wid, event):
if self.im_context.filter_keypress(event):
return True;
return False;
def on_commit(self, wid, str):
self.__text = self.__text[:self.__cur] + str + self.__text[self.__cur:]
self.__cur += len(str)
self.queue_draw()
def on_retrieve_surrounding(self, wid):
self.im_context.set_surrounding(self.__text, len(self.__text.encode()), len(self.__text[:self.__cur].encode()))
return True
def on_delete_surrounding(self, wid, offset, n_chars):
begin = self.__cur + offset
if begin < 0:
return False
end = self.__cur + offset + n_chars
if len(self.__text) < end:
return False
self.__text = self.__text[:begin] + self.__text[end:]
if end <= self.__cur:
self.__cur -= n_chars
elif begin <= self.__cur:
self.__cur = begin
self.queue_draw()
return True
def on_preedit_changed(self, wid):
self.__preedit = self.im_context.get_preedit_string()
self.queue_draw()
return False
def on_preedit_end(self, wid):
self.__preedit = self.im_context.get_preedit_string()
self.queue_draw()
return False
def on_preedit_start(self, wid):
self.__preedit = self.im_context.get_preedit_string()
self.queue_draw()
return False
def main():
app = Example()
Gtk.main()
if __name__ == "__main__":
main()
@ShikiOkasaka
Copy link
Author

フォントはnotoをつかっています。インストール手順は、

$ sudo apt install fonts-noto-cjk

です。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment