+Sun September 4 2011 Shyouzou Sugitani <shy@users.sourceforge.jp>
+ * Observer関連のメソッドを修正した.
+ (SakuraクラスでのObserverの管理データはlist型からdict型に変更.)
+ * アイコン化解除イベントが間違って発行される場合があったのを修正した.
+
+Sat September 3 2011 Shyouzou Sugitani <shy@users.sourceforge.jp>
+ * コード全体をリファクタリング.
+ - New-style classの使用を拡大.(property使用を増やした.)
+ - リストの内包表記を積極的に使用.
+ * setup.pyのためにMANIFEST.inを追加した.
+ *lib/main.py: 変数名の変更忘れがあったのを修正.
+ *install.py:
+ コンソールからバルーンをインストールすると落ちる問題を修正.
+ * \n[half]を使用するとバルーンの表示がおかしくなることがあったのを修正.
+ (高さが半分に変更された行がスクロールで表示範囲外に出た後に
+ 表示領域内の行の位置を修正する処理が抜けていた.)
+ * easyballoon互換モジュールで表示されるバルーンもサーフェスの
+ 倍率変更に即追従するようにした.
+
Sun August 28 2011 Shyouzou Sugitani <shy@users.sourceforge.jp>
* バージョン4.2.5リリース.
--- /dev/null
+include COPYING KNOWN_ISSUES ChangeLog NEWS README README.ninix TODO.ninix
+recursive-include doc *.txt
+recursive-include locale *.po
+prune bin
if ghost_conf:
self.ghosts[ghost_dir] = ghost_conf[ghost_dir]
else:
- self.ghosts[i] = None ## FIXME
+ self.ghosts[ghost_dir] = None ## FIXME
item = self.__create_ghost_list_item(ghost_dir)
item['instance'] = self.create_ghost(ghost_conf[ghost_dir])
if exists:
self.ghost_list[num] = item
else:
self.ghost_list.insert(num, item)
- self.console.update() # XXX
def vanish_sakura(self, sakura):
# remove ghost
self.app.quit()
return True
+ def do_install(self, filename):
+ try:
+ target_dir = self.installer.install(
+ filename, ninix.home.get_ninix_home())
+ except:
+ target_dir = None
+ if target_dir is not None:
+ self.app.add_sakura(target_dir)
+ self.update()
+
def file_chooser(self, widget=None, event=None):
response = self.file_chooser.run()
if response == gtk.RESPONSE_OK:
filename = self.file_chooser.get_filename()
- try:
- target_dir = self.installer.install(
- filename, ninix.home.get_ninix_home())
- except:
- target_dir = None
- if target_dir is not None:
- self.app.add_sakura(target_dir)
+ self.do_install(filename)
elif response == gtk.RESPONSE_CANCEL:
pass
self.file_chooser.hide()
if scheme == 'file' and os.path.exists(pathname):
filelist.append(pathname)
for filename in filelist:
- try:
- target_dir = self.installer.install(
- filename, ninix.home.get_ninix_home())
- except:
- target_dir = None
- if target_dir is not None:
- self.app.add_sakura(target_dir)
+ self.do_install(filename)
return True
if self.opened:
return
self.history = history
- self.items = []
- for name, (clock, path) in self.history.iteritems():
- self.items.append((name, clock, path))
+ self.items = \
+ [(name, clock, path) for name, (clock, path) in \
+ self.history.iteritems()]
self.items[:] = [(x[1], x) for x in self.items]
self.items.sort()
self.items[:] = [x for x_1, x in self.items]
return ninix.config.null_config()
def create_from_file(path):
- buf = []
with open(path) as f:
- for line in f:
- line = line.strip()
- if not line:
- continue
- buf.append(line)
+ buf = [line.strip() for line in f if line.strip()]
return create_from_buffer(buf)
def create_from_buffer(buf):
def __init__(self, callback):
self.callback = callback
self.synchronized = []
- self.__scalling = 0
- self.__scale = 100 # %
- self.__use_pna = False
- self.__alpha_channel = 1.0
self.user_interaction = False
self.window = []
# create communicatebox
if len(self.window) > side:
self.window[side].reset_text_count()
- def set_use_pna(self, flag):
- if self.__use_pna == bool(flag):
- return
- self.__use_pna = bool(flag)
- for balloon_window in self.window:
- balloon_window.set_use_pna(self.__use_pna)
-
- def set_alpha_channel(self, alpha):
- if not 0.1 <= alpha <= 1.0 or alpha is None:
- alpha = 1.0
- if self.__alpha_channel == alpha:
- return
- self.__alpha_channel = alpha
- for balloon_window in self.window:
- balloon_window.set_alpha_channel(self.__alpha_channel)
-
- def set_scale(self, scale):
- if self.__scale == scale:
- return
- self.__scale = scale # %
- for balloon_window in self.window:
- balloon_window.set_scale(self.__scale)
-
- def get_scalling(self):
- return self.__scalling
-
- def set_scalling(self, flag):
- if self.__scalling == flag:
- return
- self.__scalling = flag
+ def reset_balloon(self):
for balloon_window in self.window:
- balloon_window.set_scalling(self.__scalling)
+ balloon_window.reset_balloon()
def create_gtk_window(self, title):
window = ninix.pix.TransparentWindow()
gtk_window, side, balloon_window_callback, self.desc, balloon,
id_format)
self.window.append(balloon_window)
- # BalloonWindow default should be same as Balloon default
- balloon_window.set_scalling(self.__scalling)
- balloon_window.set_scale(self.__scale)
- balloon_window.set_use_pna(self.__use_pna)
- balloon_window.set_alpha_channel(self.__alpha_channel)
- balloon_window.set_fonts(self.callback['get_preference']('balloon_fonts'))
- if side > 1:
- balloon_window.set_balloon(0) ## FIXME
def reset_fonts(self):
- font_name = self.callback['get_preference']('balloon_fonts')
for window in self.window:
- window.set_fonts(font_name)
+ window.reset_fonts()
def get_balloon_directory(self):
return self.directory
self.inputbox.show(default)
-class BalloonWindow:
+class BalloonWindow(object):
def __init__(self, window, side, callback, desc, balloon, id_format):
self.window = window
self.images = []
self.width = 0
self.height = 0
- self.__scalling = 0
- self.__scale = 100 # %
- self.__use_pna = False
- self.__alpha_channel = 1.0
self.__font_name = ''
self.text_count = 0
self.balloon_pixbuf = None
# initialize
self.direction = min(side, 1) ## kluge: multi character
self.position = (0, 0)
+ self.reset_fonts()
self.clear_text()
+ @property
+ def scale(self):
+ scalling = self.callback['get_preference']('balloon_scalling')
+ scale = self.callback['get_preference']('surface_scale')
+ return scale if scalling else 100 # %
+
def get_balloon_windowposition(self):
winpos_x = self.__get_with_scaling('windowposition.x', int, 0)
winpos_y = self.__get_with_scaling('windowposition.y', int, 0)
#assert balloon_id in self.balloon
try:
path, config = self.balloon[balloon_id]
+ use_pna = self.callback['get_preference']('use_pna')
pixbuf = ninix.pix.create_pixbuf_from_file(
- path, use_pna=self.__use_pna)
+ path, use_pna=use_pna)
except:
return None
- scale = self.get_scale()
+ scale = self.scale
w = pixbuf.get_width()
h = pixbuf.get_height()
w = max(8, int(w * scale / 100))
pixbuf = pixbuf.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
return pixbuf, (w, h)
- def set_use_pna(self, flag):
- self.__use_pna = flag
- self.reset_balloon()
-
- def set_fonts(self, font_name):
+ def reset_fonts(self):
+ font_name = self.callback['get_preference']('balloon_fonts')
if self.__font_name == font_name:
return
self.font_desc = pango.FontDescription(font_name)
['font.height', 'font.size'], int, default_size)
pango_size = size * 3 / 4 # convert from Windows to GTK+
pango_size *= pango.SCALE
- scale = self.get_scale()
+ scale = self.scale
self.font_desc.set_size(pango_size * scale / 100)
self.__font_name = font_name
self.layout.set_font_description(self.font_desc)
self.layout.set_wrap(pango.WRAP_CHAR) # XXX
# font for sstp message
if self.side == 0:
- self.sstp_font_desc = pango.FontDescription(self.__font_name)
+ self.sstp_font_desc = pango.FontDescription(font_name)
pango_size = self.sstp_font_desc.get_size()
if pango_size == 0:
default_size = 10 # for Windows environment
if self.__shown:
self.darea.queue_draw()
- def set_alpha_channel(self, value):
- self.__alpha_channel = value
- self.reset_balloon()
-
- def get_scale(self):
- return self.__scale if self.__scalling else 100 # %
-
- def set_scale(self, scale):
- self.__scale = scale # %
- self.reset_balloon()
-
- def set_scalling(self, flag):
- self.__scalling = flag
- self.reset_balloon()
+ @property
+ def alpha_channel(self):
+ alpha = self.callback['get_preference']('balloon_alpha')
+ if alpha is None or not 0.1 <= alpha <= 1.0:
+ alpha = 1.0
+ return alpha
def reset_sstp_marker(self):
if self.side == 0:
value = default_value
if value < 0:
value = base + value
- return int(value * self.get_scale() / 100)
+ return int(value * self.scale / 100)
def __get_with_scaling(self, name, conv, default_value):
path, config = self.balloon[self.balloon_id]
value = self.desc.get_with_type(name, conv)
if value is None:
value = default_value
- return conv(value * self.get_scale() / 100)
+ return conv(value * self.scale / 100)
def __move(self):
x, y = self.get_position()
self.window.resize_move(x, y)
def set_position(self, base_x, base_y):
+ if self.balloon_id is None: ## FIXME
+ return
px, py = self.get_balloon_windowposition()
if self.direction == 0:
w, h = self.get_balloon_size()
cr.paint()
cr.restore()
cr.set_source_pixbuf(self.balloon_pixbuf[0], 0, 0)
- cr.paint_with_alpha(self.__alpha_channel)
+ cr.paint_with_alpha(self.alpha_channel)
# draw images
for i in range(len(self.images)):
pixbuf, (w, h), (x, y) = self.images[i]
- scale = self.get_scale()
+ scale = self.scale
w = max(8, int(w * scale / 100))
h = max(8, int(h * scale / 100))
if x == 'centerx':
continue
pixbuf = pixbuf.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
cr.set_source_pixbuf(pixbuf, x, y)
- cr.paint_with_alpha(self.__alpha_channel)
+ cr.paint_with_alpha(self.alpha_channel)
# draw text
i = self.lineno
j = len(self.text_buffer)
x, y, w, h = self.line_regions[line]
if self.text_buffer[i].endswith('\n[half]'):
new_y = int(y + (self.font_height + self.line_space) / 2)
- self.update_line_regions(line + 1, new_y)
markup = self.set_markup(i, self.text_buffer[i][:-7])
- self.layout.set_markup(markup)
- cr.set_source_rgba(*self.text_normal_color)
- cr.move_to(x, y)
- cr.show_layout(self.layout)
else:
+ new_y = int(y + self.font_height + self.line_space)
markup = self.set_markup(i, self.text_buffer[i])
- self.layout.set_markup(markup)
- cr.set_source_rgba(*self.text_normal_color)
- cr.move_to(x, y)
- cr.show_layout(self.layout)
+ self.update_line_regions(line + 1, new_y)
+ self.layout.set_markup(markup)
+ cr.set_source_rgba(*self.text_normal_color)
+ cr.move_to(x, y)
+ cr.show_layout(self.layout)
if self.sstp_pixbuf is not None:
for l, c in self.sstp_marker:
if l == i:
my = y + (self.font_height + self.line_space) / 2
my = my - mh / 2
cr.set_source_pixbuf(self.sstp_pixbuf[0], mx, my)
- cr.paint_with_alpha(self.__alpha_channel)
+ cr.paint_with_alpha(self.alpha_channel)
i += 1
line += 1
del cr
self.__ghosts[sakura] = (name, s0, s1)
def get_otherghostname(self, name):
- otherghostname = []
- for value in self.__ghosts.itervalues():
- if value[0] != name:
- otherghostname.append(chr(1).join(value))
- return otherghostname
+ return [chr(1).join(value) for value in self.__ghosts.itervalues() \
+ if value[0] != name]
def send_message(self, name, sender, sentence):
if name == '__SYSTEM_ALL_GHOST__':
return default
def __str__(self):
- buf = []
- for item in self.iteritems():
- buf.append('%s,%s\n' % item)
- return ''.join(buf)
+ return ''.join(['%s,%s\n' % item for item in self.iteritems()])
def create_from_file(path):
- buf = []
with open(path) as f:
- for line in f:
- if not line.strip():
- continue
- buf.append(line)
+ buf = [line.strip() for line in f if line.strip()]
return create_from_buffer(buf)
def create_from_buffer(buf):
name = name.replace('\\', '/')
head, tail = os.path.split(name)
name = tail
- if name:
- if name.lower().endswith('.dll'): # XXX
- name = name[:-4]
- else:
+ if not name:
return None
+ if name.lower().endswith('.dll'): # XXX
+ name = name[:-4]
module = self.__import_module(name)
if not module:
return None
- else:
- instance = None
- if self.__type == 'saori':
- if getattr(module, 'Saori', None):
- saori = module.Saori()
- if getattr(saori, 'need_ghost_backdoor', None):
- saori.need_ghost_backdoor(self.__sakura)
- else:
- saori = None
- instance = saori
- elif self.__type == 'shiori':
- if getattr(module, 'Shiori', None):
- shiori = module.Shiori(dll_name)
- if getattr(shiori, 'use_saori', None):
- shiori.use_saori(self.__saori_lib)
- else:
- shiori = None
- instance = shiori
- if instance is None:
- del module
- del sys.modules[name]
- return instance
+ instance = None
+ if self.__type == 'saori':
+ if getattr(module, 'Saori', None):
+ saori = module.Saori()
+ if getattr(saori, 'need_ghost_backdoor', None):
+ saori.need_ghost_backdoor(self.__sakura)
+ else:
+ saori = None
+ instance = saori
+ elif self.__type == 'shiori':
+ if getattr(module, 'Shiori', None):
+ shiori = module.Shiori(dll_name)
+ if getattr(shiori, 'use_saori', None):
+ shiori.use_saori(self.__saori_lib)
+ else:
+ shiori = None
+ instance = shiori
+ if instance is None:
+ del module
+ del sys.modules[name]
+ return instance
def __import_module(self, name):
fp = None
def setup(self):
self.blns = self.read_bln_txt(self.dir)
- return 1 if self.blns else 0
+ if self.blns:
+ self.__sakura.attach_observer(self)
+ return 1
+ else:
+ return 0
def read_bln_txt(self, dir):
blns = {}
bln[bln_id].destroy()
del bln[bln_id]
self.blns = {}
+ self.__sakura.detach_observer(self)
return 1
+ def observer_update(self, event, args): ## FIXME
+ if event == 'set scale':
+ for name in self.blns:
+ data, bln = self.blns[name]
+ for bln_id in bln.keys():
+ if bln[bln_id]:
+ bln[bln_id].reset_scale()
+
def execute(self, argument):
if not argument:
return self.RESPONSE[400]
self.blns[name] = (data, {})
return None
-class Balloon:
+
+class Balloon(object):
def __init__(self, sakura, dir, data,
text, offset_x, offset_y, name, bln_id):
except:
self.destroy()
return
- self.scale = self.get_sakura_status('SurfaceScale') ## FIXME
+ self.balloon_pixbuf = balloon_pixbuf
w = balloon_pixbuf.get_width()
h = balloon_pixbuf.get_height()
- w = max(8, int(w * self.scale / 100))
- h = max(8, int(h * self.scale / 100))
- balloon_pixbuf = balloon_pixbuf.scale_simple(
- w, h, gtk.gdk.INTERP_BILINEAR)
- mask_pixmap = gtk.gdk.Pixmap(None, w, h, 1)
- balloon_pixbuf.render_threshold_alpha(
- mask_pixmap, 0, 0, 0, 0, w, h, 1)
- self.x, self.y = self.get_coordinate(w, h)
+ self.x = self.y = 0
if 'offset.x' in data:
- self.x += self.direction * int(int(data['offset.x']) * self.scale / 100)
+ self.x += self.direction * int(data['offset.x'])
if 'offset.y' in data:
- self.y += int(int(data['offset.y']) * self.scale / 100)
+ self.y += int(data['offset.y'])
if 'offset.random' in data:
- self.x += int(int(data['offset.random']) * random.randrange(-1, 2) * self.scale / 100)
- self.y += int(int(data['offset.random']) * random.randrange(-1, 2) * self.scale / 100)
- self.x += self.direction * int(offset_x * self.scale / 100)
- self.y += int(offset_y * self.scale / 100)
- self.left = int(int(data.get('disparea.left', 0)) * self.scale / 100)
- self.right = int(int(data.get('disparea.right', w)) * self.scale / 100)
- self.top = int(int(data.get('disparea.top', 0)) * self.scale / 100)
- self.bottom = int(int(data.get('disparea.bottom', h)) * self.scale / 100)
- self.window.mask = mask_pixmap
- self.current_balloon_pixbuf = balloon_pixbuf
+ self.x += int(data['offset.random']) * random.randrange(-1, 2)
+ self.y += int(data['offset.random']) * random.randrange(-1, 2)
+ self.x += self.direction * int(offset_x)
+ self.y += int(offset_y)
+ self.action_x = 0
+ self.action_y = 0
+ self.vx = 0
+ self.vy = 0
+ self.left = int(data.get('disparea.left', 0))
+ self.right = int(data.get('disparea.right', w))
+ self.top = int(data.get('disparea.top', 0))
+ self.bottom = int(data.get('disparea.bottom', h))
self.script = None
self.darea = gtk.DrawingArea()
self.darea.set_events(gtk.gdk.EXPOSURE_MASK|
self.darea.connect('button_release_event', self.button_release)
self.darea.connect('motion_notify_event', self.motion_notify)
self.darea.connect('leave_notify_event', self.leave_notify)
- self.darea.set_size_request(w, h)
self.darea.show()
self.window.add(self.darea)
self.darea.realize()
self.window.realize()
self.window.window.set_back_pixmap(None, False)
- self.window.resize_move(self.x, self.y)
+ self.set_skin()
+ self.set_position()
self.layout = None
if text != 'noscript' and \
(self.right - self.left) and (self.bottom - self.top):
fontcolor_b = int(data['font.color'][4:6], 16) / 255.0
self.fontcolor = (fontcolor_r, fontcolor_g, fontcolor_b)
default_font_size = 12 # for Windows environment
- font_size = int(data.get('font.size', default_font_size))
- font_size = font_size * 3 / 4 # convert from Windows to GTK+
- font_size = font_size * self.scale / 100 * pango.SCALE
+ self.font_size = int(data.get('font.size', default_font_size))
self.layout = pango.Layout(self.darea.get_pango_context())
self.font_desc = pango.FontDescription()
self.font_desc.set_family('Sans') # FIXME
- self.font_desc.set_size(font_size)
if data.get('font.bold') == 'on':
self.font_desc.set_weight(pango.WEIGHT_BOLD)
- self.layout.set_font_description(self.font_desc)
self.layout.set_wrap(pango.WRAP_CHAR)
- self.layout.set_width((self.right - self.left) * 1024)
- self.slide_vx = int(int(data.get('slide.vx', 0)) * self.scale / 100)
- self.slide_vy = int(int(data.get('slide.vy', 0)) * self.scale / 100)
+ self.set_layout()
+ self.slide_vx = int(data.get('slide.vx', 0))
+ self.slide_vy = int(data.get('slide.vy', 0))
self.slide_autostop = int(data.get('slide.autostop', 0))
if data.get('action.method') in ['sinwave', 'vibrate']:
action = data['action.method']
self.visible = 0
self.x_root = None
self.y_root = None
- self.action_x = 0
- self.action_y = 0
- self.vx = 0
- self.vy = 0
- self.text_pos_x = self.left
- self.text_pos_y = self.top
self.processed_script = None
self.processed_text = ''
self.text = ''
logging.error(self.script)
self.timeout_id = glib.timeout_add(10, self.do_idle_tasks)
+ def set_position(self):
+ if self.window is None:
+ return
+ new_x = self.base_x + int((self.x + self.action_x + self.vx) * self.scale / 100)
+ new_y = self.base_y + int((self.y + self.action_y + self.vy) * self.scale / 100)
+ self.window.resize_move(new_x, new_y)
+
+ def set_skin(self):
+ if self.window is None:
+ return
+ self.scale = self.get_sakura_status('SurfaceScale') ## FIXME
+ balloon_pixbuf = self.balloon_pixbuf
+ w = balloon_pixbuf.get_width()
+ h = balloon_pixbuf.get_height()
+ w = max(8, int(w * self.scale / 100))
+ h = max(8, int(h * self.scale / 100))
+ balloon_pixbuf = balloon_pixbuf.scale_simple(
+ w, h, gtk.gdk.INTERP_BILINEAR)
+ mask_pixmap = gtk.gdk.Pixmap(None, w, h, 1)
+ balloon_pixbuf.render_threshold_alpha(
+ mask_pixmap, 0, 0, 0, 0, w, h, 1)
+ self.window.mask = mask_pixmap
+ self.current_balloon_pixbuf = balloon_pixbuf
+ self.darea.set_size_request(w, h)
+ self.base_x, self.base_y = self.get_coordinate(w, h)
+
+ def set_layout(self):
+ if self.window is None:
+ return
+ if self.layout is None:
+ return
+ font_size = self.font_size * 3 / 4 # convert from Windows to GTK+
+ font_size = font_size * self.scale / 100 * pango.SCALE
+ self.font_desc.set_size(font_size)
+ self.layout.set_font_description(self.font_desc)
+ self.layout.set_width(
+ int((self.right - self.left) * 1024 * self.scale / 100))
+
+ def reset_scale(self):
+ if self.window is None:
+ return
+ self.set_skin()
+ self.set_position()
+ self.set_layout()
+ self.darea.queue_draw()
+
+ @property
def clickerase(self):
return self.data.get('clickerase', 'on') == 'on'
+ @property
def dragmove_horizontal(self):
return self.data.get('dragmove.horizontal') == 'on'
+ @property
def dragmove_vertical(self):
return self.data.get('dragmove.vertical') == 'on'
% self.action['ref2'])
/ self.action['ref2'])
if self.action['ref0']:
- self.action_y = int(offset * self.scale / 100)
+ self.action_y = int(offset)
else:
- self.action_x = int(offset * self.scale / 100)
+ self.action_x = int(offset)
elif self.action['method'] == 'vibrate':
offset = (int((time.time() - self.start_time) * 1000) / \
self.action['ref2']) % 2
- self.action_x = int(offset * self.action['ref0'] * self.scale / 100)
- self.action_y = int(offset * self.action['ref1'] * self.scale / 100)
+ self.action_x = int(offset * self.action['ref0'])
+ self.action_y = int(offset * self.action['ref1'])
if (self.slide_vx != 0 or self.slide_vy != 0) and \
self.slide_autostop > 0 and \
self.slide_autostop * 0.001 + 0.05 <= time.time() - self.start_time:
- self.vx = self.direction * int((self.slide_autostop / 50.0 + 1) * self.slide_vx * self.scale / 100)
+ self.vx = self.direction * int((self.slide_autostop / 50.0 + 1) * self.slide_vx)
self.slide_vx = 0
- self.vy = int((self.slide_autostop / 50.0 + 1) * self.slide_vy * self.scale / 100)
+ self.vy = int((self.slide_autostop / 50.0 + 1) * self.slide_vy)
self.slide_vy = 0
if self.slide_vx != 0:
- self.vx = self.direction * int(((time.time() - self.start_time) * self.slide_vx * self.scale / 100) / 50 * 1000.)
+ self.vx = self.direction * int(((time.time() - self.start_time) * self.slide_vx) / 50 * 1000.)
if self.slide_vy != 0:
- self.vy = int(((time.time() - self.start_time) * self.slide_vy * self.scale / 100) / 50 * 1000.)
- self.window.resize_move(int(self.x + self.action_x + self.vx),
- int(self.y + self.action_y + self.vy))
+ self.vy = int(((time.time() - self.start_time) * self.slide_vy) / 50 * 1000.)
+ self.set_position()
if self.processed_script or self.processed_text:
self.interpret_script()
self.talking = 0 if self.talking and not sakura_talking else sakura_talking
cr.paint()
if self.layout:
cr.set_source_rgb(*self.fontcolor)
- cr.move_to(self.left, self.top)
+ cr.move_to(int(self.left * self.scale / 100),
+ int(self.top * self.scale / 100))
cr.show_layout(self.layout)
del cr
if event.type == gtk.gdk._2BUTTON_PRESS:
x = int(event.x * 100 / self.scale)
y = int(event.y * 100 / self.scale)
- self.__sakura.notify_event('OnEBMouseDoubleClick', self.name,
- x, y, self.id)
+ self.__sakura.notify_event(
+ 'OnEBMouseDoubleClick', self.name, x, y, self.id)
return True
def button_release(self, widget, event):
y = int(event.y * 100 / self.scale)
if event.type == gtk.gdk.BUTTON_RELEASE:
if event.button == 1:
- self.__sakura.notify_event('OnEBMouseClick', self.name,
- x, y, self.id, 0)
+ self.__sakura.notify_event(
+ 'OnEBMouseClick', self.name, x, y, self.id, 0)
elif event.button == 3:
- self.__sakura.notify_event('OnEBMouseClick', self.name,
- x, y, self.id, 1)
- if self.clickerase():
+ self.__sakura.notify_event(
+ 'OnEBMouseClick', self.name, x, y, self.id, 1)
+ if self.clickerase:
self.destroy()
return True
def motion_notify(self, widget, event):
+ scale = self.scale
if self.x_root is not None and \
self.y_root is not None:
x_delta = int(event.x_root - self.x_root)
y_delta = int(event.y_root - self.y_root)
if event.state & gtk.gdk.BUTTON1_MASK:
- if self.dragmove_horizontal():
- self.x += x_delta
- if self.dragmove_vertical():
- self.y += y_delta
- self.window.resize_move(int(self.x + self.action_x + self.vx),
- int(self.y + self.action_y + self.vy))
+ if self.dragmove_horizontal:
+ self.x += x_delta * 100 / scale
+ if self.dragmove_vertical:
+ self.y += y_delta * 100 / scale
+ self.set_position()
self.x_root = event.x_root
self.y_root = event.y_root
if self.move_notify_time is None or \
time.time() - self.move_notify_time > 500 * 0.001:
- x = int(event.x * 100 / self.scale)
- y = int(event.y * 100 / self.scale)
- self.__sakura.notify_event('OnEBMouseMove', self.name,
- x, y, self.id)
+ x = int(event.x * 100 / scale)
+ y = int(event.y * 100 / scale)
+ self.__sakura.notify_event(
+ 'OnEBMouseMove', self.name, x, y, self.id)
self.move_notify_time = time.time()
return True
target_dir = self.install_redo_supplement(filename, tmpdir, homedir)
elif filetype == 'balloon':
target_dir = self.install_balloon(filename, tmpdir, homedir)
+ target_dir = None # XXX
elif filetype == 'kinoko':
self.install_kinoko(filename, tmpdir, homedir)
target_dir = None # XXX
# find balloon
balloon_dir = inst and inst.get('balloon.directory')
if balloon_dir:
- balloon_list = []
balloon_dir = ninix.home.get_normalized_path(balloon_dir)
balloon_dst = os.path.join(homedir, 'balloon', balloon_dir)
balloon_src = inst and inst.get('balloon.source.directory')
if os.path.exists(balloon_dst):
# uninstall older versions of the balloon
self.remove_files_and_dirs(balloon_dst, [])
+ balloon_list = []
for path in self.list_all_files(tmpdir, balloon_src):
balloon_list.append((os.path.join(tmpdir, path),
os.path.join(homedir, 'balloon', path)))
return target
def install_balloon(self, archive, srcdir, homedir):
- filelist = []
# find install.txt
inst = ninix.home.read_install_txt(srcdir)
if inst is None:
fatal('"directory" not found in install.txt')
target_dir = target_dir.encode('utf-8')
dstdir = os.path.join(homedir, 'balloon', target_dir)
+ filelist = []
for path in self.list_all_files(srcdir, ''):
filelist.append((os.path.join(srcdir, path),
os.path.join(dstdir, path)))
shutil.rmtree(kinoko_dir)
def install_kinoko(self, archive, srcdir, homedir):
- filelist = []
# find kinoko.ini
kinoko = ninix.home.read_kinoko_ini(srcdir)
if kinoko is None:
dstdir = os.path.join(
homedir, 'kinoko', os.path.basename(archive)[:-4])
# find files
+ filelist = []
for filename in os.listdir(srcdir):
path = os.path.join(srcdir, filename)
if os.path.isfile(path):
shutil.rmtree(nekoninni_dir)
def install_nekoninni(self, archive, srcdir, homedir):
- filelist = []
# find install.txt
inst = ninix.home.read_install_txt(srcdir)
if inst is None:
target_dir = target_dir.encode('utf-8')
dstdir = os.path.join(homedir, 'nekodorif', 'skin', target_dir)
# find files
+ filelist = []
for filename in os.listdir(srcdir):
path = os.path.join(srcdir, filename)
if os.path.isfile(path):
shutil.rmtree(katochan_dir)
def install_katochan(self, archive, srcdir, homedir):
- filelist = []
# find install.txt
inst = ninix.home.read_install_txt(srcdir)
if inst is None:
target_dir = target_dir.encode('utf-8')
dstdir = os.path.join(homedir, 'nekodorif', 'katochan', target_dir)
# find files
+ filelist = []
for filename in os.listdir(srcdir):
path = os.path.join(srcdir, filename)
if os.path.isfile(path):
}
self.__skin_list = None
actions = gtk.ActionGroup('Actions')
- entry = []
- for value in self.__menu_list.itervalues():
- entry.append(value[0])
+ entry = [value[0] for value in self.__menu_list.itervalues()]
actions.add_actions(tuple(entry))
ui_manager = gtk.UIManager()
ui_manager.insert_action_group(actions, 0)
def finalize(self):
self.__running = 0
- self.target.delete_observer(self)
+ self.target.detach_observer(self)
if self.skin is not None:
self.skin.destroy()
- def notify_observer(self, event, args): ## FIXME
+ def observer_update(self, event, args):
if self.skin is None:
return
if event in ['set position', 'set surface']:
scale = self.target.get_surface_scale()
self.skin.set_scale(scale)
elif event == 'hide':
- if not self.target.surface_is_shown(0):
+ side = args
+ if side == 0: # sakura side
self.skin.hide()
elif event == 'iconified':
self.skin.hide()
self.finalize()
elif event == 'move surface':
side, xoffset, yoffset = args
- if side == 0:
+ if side == 0: # sakura side
self.skin.set_position(xoffset, yoffset)
elif event == 'raise':
side = args
- if side == 0:
+ if side == 0: # sakura side
self.skin.set_position() ## FIXME
else:
##logging.debug('OBSERVER(kinoko): ignore - %s' % event)
def load(self, data, target):
self.data = data
self.target = target
- self.target.set_observer(self)
+ self.target.attach_observer(self)
self.accelgroup = gtk.AccelGroup()
self.load_skin()
if self.skin is None:
menu_callback[key] = self.callback[key]
self.__menu = Menu(menu_callback, self.accelgroup)
self.__scale = scale
- self.__shown = 0
+ self.__shown = False
self.surface_id = 0 # dummy
self.window = ninix.pix.TransparentWindow()
self.window.set_focus_on_map(False)
self.window.add_accel_group(self.accelgroup) ## FIXME
if self.data['animation'] is not None:
path = os.path.join(self.data['dir'], self.data['animation'])
- self.seriko = ninix.seriko.Controler(
- {'': ninix.seriko.get_actors(ninix.config.create_from_file(path))})
+ actors = {'': ninix.seriko.get_actors(ninix.config.create_from_file(path))}
else:
base, ext = os.path.splitext(self.data['base'])
path = os.path.join(self.data['dir'], ''.join((base, 'a.txt')))
if os.path.exists(path):
- self.seriko = ninix.seriko.Controler(
- {'': ninix.seriko.get_actors(ninix.config.create_from_file(path))})
+ actors = {'': ninix.seriko.get_actors(ninix.config.create_from_file(path))}
else:
- self.seriko = ninix.seriko.Controler({'': []})
+ actors = {'': []}
+ self.seriko = ninix.seriko.Controler(
+ actors, {'get_preference': self.get_preference})
path = os.path.join(self.data['dir'], self.data['base'])
try:
self.pixbuf = ninix.pix.create_pixbuf_from_file(path)
self.seriko.start(self)
self.seriko.invoke_kinoko(self)
+ def get_preference(self, name): # dummy
+ if name == 'animation_quality':
+ return 1.0
+ else:
+ return None
+
def show(self):
if not self.__shown:
self.window.show()
- self.__shown = 1
+ self.__shown = True
def hide(self):
if self.__shown:
self.window.hide()
- self.__shown = 0
+ self.__shown = False
def append_actor(self, frame, actor):
self.seriko.append_actor(frame, actor)
self.__fontcolor = {'normal': '#000000', 'prelight': '#ffffff'} ## FIXME
self.__sidebar_width = 0
actions = gtk.ActionGroup('Actions')
- entry = []
- for key, value in self.__menu_list.iteritems():
- if key != 'Stick':
- entry.append(value[0])
+ entry = [value[0] for key, value in self.__menu_list.iteritems() \
+ if key != 'Stick']
actions.add_actions(tuple(entry))
actions.add_toggle_actions(tuple([self.__menu_list['Stick'][0]]))
self.ui_manager = gtk.UIManager()
}
self.__katochan_list = None
actions = gtk.ActionGroup('Actions')
- entry = []
- for value in self.__menu_list.itervalues():
- entry.append(value[0])
+ entry = [value[0] for value in self.__menu_list.itervalues()]
actions.add_actions(tuple(entry))
ui_manager = gtk.UIManager()
ui_manager.insert_action_group(actions, 0)
self.skin = None
self.katochan = None
- def notify_observer(self, event, args): ## FIXME
+ def observer_update(self, event, args):
if event in ['set position', 'set surface']:
if self.skin is not None:
self.skin.set_position()
return 0
self.dir = dir
self.target = target
- self.target.set_observer(self)
+ self.target.attach_observer(self)
self.accelgroup = gtk.AccelGroup()
scale = self.target.get_surface_scale()
skin_callback ={
def finalize(self):
self.__running = 0
- self.target.delete_observer(self)
+ self.target.detach_observer(self)
if self.katochan is not None:
self.katochan.destroy()
if self.skin is not None:
gtk.Window.__init__(self, type)
self.set_app_paintable(True)
self.screen_changed()
- self.truncated = False ## FIXME: property(dependent for truncate)
- self.truncate = (0, 0) ## FIXME: property
+ self.truncated = False
+ self.mask_offset = (0, 0)
fixed = gtk.Fixed()
fixed.show()
gtk.Window.add(self, fixed) # XXX
self.connect_after('size_allocate', self.size_allocate)
def set_mask(self, mask):
- x, y = self.truncate
+ x, y = self.mask_offset
self.__mask = mask
if self.is_composited():
self.input_shape_combine_mask(mask, x, y)
self.input_shape_combine_mask(self.mask, 0, 0)
else:
self.shape_combine_mask(self.mask, 0, 0)
- self.truncate = (0, 0)
+ self.mask_offset = (0, 0)
self.truncated = False
def resize_move(self, x, y, xoffset=0, yoffset=0):
else:
self.shape_combine_mask(self.mask, offset_x, offset_y)
self.truncated = True
- self.truncate = (offset_x, offset_y)
+ self.mask_offset = (offset_x, offset_y)
self.__position = (new_x, new_y)
self.__child.queue_draw()
self.sstp_handle = None
self.sstp_entry_db = None
self.sstp_request_handler = None
- # error: 'loose'(default) or 'strict'
+ # error = 'loose'(default) or 'strict'
self.script_parser = ninix.script.Parser(error='loose')
self.char = 2 # 'sakura' and 'kero'
self.script_queue = []
self.__dll = ninix.dll.Library(
'shiori', default_path, saori_lib=saori_lib)
self.__temp_mode = 0
- self.__observer = []
+ self.__observers = {}
balloon_callback = {
'is_paused': self.is_paused,
'notify_balloon_click': self.notify_balloon_click,
def select_kinoko(self, event, item):
self.callback['select_kinoko'](item, self)
- def set_observer(self, observer):
- if observer not in self.__observer:
- self.__observer.append(observer)
+ def attach_observer(self, observer):
+ if observer not in self.__observers:
+ self.__observers[observer] = 1
- def notify_observer(self, event, args=()):
- for observer in self.__observer:
- observer.notify_observer(event, args)
+ def notify_observer(self, event, args=None):
+ args = args or ()
+ for observer in self.__observers.keys():
+ observer.observer_update(event, args)
- def delete_observer(self, observer):
- for i in range(len(self.__observer)):
- if self.__observer[i] == observer:
- del self.__observer[i]
- break
+ def detach_observer(self, observer):
+ if observer in self.__observers:
+ del self.__observers[observer]
def new(self, desc, shiori_dir, use_makoto, surface_set, prefix,
shiori_dll, shiori_name): ## FIXME
self.idle_start = time.time()
def notify_preference_changed(self): ## FIXME
- self.balloon.reset_fonts()
- flag = self.callback['get_preference']('use_pna')
- self.set_use_pna(flag)
- scale = self.callback['get_preference']('surface_scale')
- self.set_surface_scale(scale)
- flag = self.callback['get_preference']('balloon_scalling')
- self.set_balloon_scalling(flag)
- alpha = self.callback['get_preference']('surface_alpha')
- self.set_surface_alpha(alpha)
- alpha = self.callback['get_preference']('balloon_alpha')
- self.set_balloon_alpha(alpha)
- quality = self.callback['get_preference']('animation_quality')
- self.set_animation_quality(quality)
- flag = self.callback['get_preference']('seriko_inactive')
- self.set_seriko_inactive(flag)
-
- def set_use_pna(self, flag): ## FIXME
- self.surface.set_use_pna(flag)
- self.balloon.set_use_pna(flag)
-
- def set_surface_alpha(self, alpha): ## FIXME
- self.surface.set_alpha_channel(alpha)
-
- def set_balloon_alpha(self, alpha): ## FIXME
- self.balloon.set_alpha_channel(alpha)
-
- def set_animation_quality(self, quality): ## FIXME
- self.surface.set_animation_quality(quality)
-
- def set_seriko_inactive(self, flag): ## FIXME
- self.surface.set_seriko_inactive(flag)
-
- def set_balloon_scalling(self, flag): ## FIXME
- self.balloon.set_scalling(flag)
+ self.balloon.reset_fonts() ## FIXME
+ self.surface.reset_surface()
+ self.notify_observer('set scale') ## FIXME
+ self.balloon.reset_balloon()
def get_surface_position(self, side):
result = self.surface.get_position(side)
self.reset_script(1)
self.stand_by(1)
self.notify_event('OnWindowStateMinimize')
+ self.notify_observer('iconified')
def notify_deiconified(self):
if not self.cantalk:
self.callback['select_current_sakura']()
if not self.passivemode:
self.notify_event('OnWindowStateRestore')
+ self.notify_observer('deiconified')
def notify_link_selection(self, link_id, text, number):
if self.script_origin == self.FROM_SSTP_CLIENT and \
self.surface.set_surface_default(side)
def get_surface_scale(self):
- return self.surface.get_scale()
-
- def set_surface_scale(self, scale):
- self.surface.set_scale(scale)
- self.balloon.set_scale(scale)
+ return self.callback['get_preference']('surface_scale')
def get_surface_size(self, side):
result = self.surface.get_surface_size(side)
dump = self.src
return 'ParserError: column %s: %s\n%s' % (column, self.message, dump)
+
class Parser:
def __init__(self, error='strict'):
return token, lexeme
def parse(self, s):
- if not s: return []
+ if not s:
+ return []
# tokenize the script
self.src = s
self.tokens = self.tokenize(self.src)
DEFAULT_FPS = 30.0 # current default
- def __init__(self, seriko):
+ def __init__(self, seriko, callback):
self.seriko = seriko
+ self.callback = callback
self.exclusive_actor = None
self.base_id = None
self.timeout_id = None
self.active = []
self.__move = None
self.__dirty = 1
- self.__inactive = False
-
- def is_active(self):
- return not bool(self.__inactive)
def set_base_id(self, window, surface_id):
if surface_id == '-2':
def append_actor(self, frame, actor):
self.active.append((frame, actor))
- def set_animation_quality(self, quality, window):
- if self.timeout_id is not None:
- glib.source_remove(self.timeout_id)
- if quality is None:
- quality = 1.0
- self.fps = self.DEFAULT_FPS * quality
- if self.timeout_id is not None:
- self.timeout_id = glib.timeout_add(
- int(1000.0 / self.fps), # [msec]
- self.update, window)
-
- def set_inactive(self, flag, window):
- self.__inactive = bool(flag)
- self.__dirty = 1 # XXX
-
def update_frame(self, window):
frame, actor = self.get_actor_next(window)
last_actor = actor
def update(self, window):
## FIXME: Use g_source_get_time. (glib.glib_version > (2, 27, 3))
current_tick = glib.get_current_time() # [sec]
+ quality = self.callback['get_preference']('animation_quality')
+ self.fps = self.DEFAULT_FPS * quality
if self.prev_tick == 0: ## First time
delta_tick = 1000.0 / self.fps # [msec]
else:
if self.__move is not None:
window.move_surface(*self.__move)
self.__move = None
- return True
+ self.timeout_id = glib.timeout_add(int(1000.0 / self.fps), # [msec]
+ self.update, window)
+ return False
def lock_exclusive(self, window, actor):
assert self.exclusive_actor is None
def __init__(self, callback):
self.window = []
self.__menu = None
- self.__scale = 100 # %
self.desc = None
- self.__use_pna = False
- self.__alpha_channel = 1.0
self.callback = callback
self.mikire = 0
self.kasanari = 0
- def set_use_pna(self, flag):
- if self.__use_pna == bool(flag):
- return
- self.__use_pna = bool(flag)
- for surface_window in self.window:
- surface_window.set_use_pna(self.__use_pna)
-
- def set_alpha_channel(self, alpha):
- if not 0.1 <= alpha <= 1.0 or alpha is None:
- alpha = 1.0
- if self.__alpha_channel == alpha:
- return
- self.__alpha_channel = alpha
- for surface_window in self.window:
- surface_window.set_alpha_channel(self.__alpha_channel)
-
- def get_scale(self):
- return self.__scale
-
- def set_scale(self, scale):
- if self.__scale == scale:
- return
- self.__scale = scale # %
- for surface_window in self.window:
- surface_window.set_scale(self.__scale)
- self.callback['notify_observer']('set scale') ## FIXME
-
- def set_animation_quality(self, quality):
- for surface_window in self.window:
- surface_window.set_animation_quality(quality)
-
- def set_seriko_inactive(self, flag):
- for surface_window in self.window:
- surface_window.set_seriko_inactive(flag)
-
def finalize(self):
for surface_window in self.window:
surface_window.destroy()
def window_iconify(self, flag):
gtk_window = self.window[0].window
- if flag:
- if not gtk_window.window.get_state() & \
- gtk.gdk.WINDOW_STATE_ICONIFIED:
- gtk_window.iconify()
- else:
- if gtk_window.window.get_state() & gtk.gdk.WINDOW_STATE_ICONIFIED:
- gtk_window.deiconify()
+ iconified = gtk_window.window.get_state() & \
+ gtk.gdk.WINDOW_STATE_ICONIFIED
+ if flag and not iconified:
+ gtk_window.iconify()
+ elif not flag and iconified:
+ gtk_window.deiconify()
def window_state(self, window, event):
if not self.callback['is_running']():
return
+ if not (event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED):
+ return
if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
if window == self.window[0].window:
self.callback['notify_iconified']()
- self.callback['notify_observer']('iconified')
for surface_window in self.window:
gtk_window = surface_window.window
if gtk_window != window and \
self.__surface, tooltips, self.__pixbufs, seriko, self.__region,
mayuna, bind, default)
self.window.append(surface_window)
- # SurfaceWindow default settings should be same as current Surface ones
- surface_window.set_scale(self.__scale)
- surface_window.set_use_pna(self.__use_pna)
- surface_window.set_alpha_channel(self.__alpha_channel)
- # Seriko default settings
- quality = self.callback['get_preference']('animation_quality')
- surface_window.set_animation_quality(quality)
- flag = self.callback['get_preference']('seriko_inactive')
- surface_window.set_seriko_inactive(flag)
- #surface_window.set_surface(default) # Don't do this.
def get_mayuna_menu(self):
for side, index in [('sakura', 0), ('kero', 1)]:
else:
return None
- def reset_surface(self, side):
- if len(self.window) > side:
- self.window[side].reset_surface()
+ def reset_surface(self):
+ for window in self.window:
+ window.reset_surface()
def set_surface_default(self, side):
if side is None:
else:
return None, None
- def get_direction(self, side):
- if len(self.window) > side:
- return self.window[side].get_direction()
- else:
- return 0
-
def reset_balloon_position(self):
for side in range(len(self.window)):
x, y = self.get_position(side)
- direction = self.get_direction(side)
+ direction = self.window[side].direction
ox, oy = self.get_balloon_offset(side)
self.callback['set_balloon_direction'](side, direction)
if direction == 0: # left
def show(self, side):
if len(self.window) > side:
self.window[side].show()
- self.callback['notify_observer']('show') ## FIXME
- self.callback['notify_observer']('raise', (side)) # XXX ## FIXME
def hide_all(self):
for side in range(len(self.window)):
self.window[side].hide()
- self.callback['notify_observer']('hide') ## FIXME
def hide(self, side):
if len(self.window) > side:
self.window[side].hide()
- self.callback['notify_observer']('hide') ## FIXME
def raise_all(self):
for side in range(len(self.window)):
self.window[side].raise_()
- self.callback['notify_observer']('raise', (side)) ## FIXME
def raise_(self, side):
if len(self.window) > side:
self.window[side].raise_()
- self.callback['notify_observer']('raise', (side)) ## FIXME
def lower_all(self):
for side in range(len(self.window)):
self.window[side].lower()
- self.callback['notify_observer']('lower') ## FIXME
def lower(self, side):
if len(self.window) > side:
self.window[side].lower()
- self.callback['notify_observer']('lower') ## FIXME
def invoke(self, side, actor_id):
if len(self.window) > side:
self.kasanari = 0
-class SurfaceWindow:
+class SurfaceWindow(object):
# DnD data types
dnd_targets = [
self.alias = alias
self.tooltips = tooltips
self.align = 0
- self.__scale = 100 # %
- self.__use_pna = False
- self.__alpha_channel = 1.0
- self.__current_part = ''
+ self.__current_part = '' ## FIXME
if self.alias is not None:
default_id = self.alias.get(default_id, [default_id])[0]
self.surface = surface
self.surface_id = default_id
self.pixbuf = pixbuf
self.current_surface_pixbuf = None # XXX
- self.seriko = ninix.seriko.Controler(seriko)
+ seriko_callback = {
+ 'get_preference': self.callback['get_preference'],
+ }
+ self.seriko = ninix.seriko.Controler(seriko, seriko_callback)
self.region = region
self.mayuna = mayuna
self.bind = bind
self.__shown = False
self.window_offset = (0, 0)
self.set_position(0, 0)
- self.set_direction(0)
+ self.__direction = 0
self.dragged = False
self.x_root = None
self.y_root = None
self.window.window.set_back_pixmap(None, False)
self.set_surface(None)
- def set_use_pna(self, flag):
- self.__use_pna = bool(flag)
- self.reset_surface()
-
- def set_alpha_channel(self, value):
- self.__alpha_channel = value
- self.reset_surface()
+ def get_direction(self):
+ return self.__direction
- def get_scale(self):
- return self.__scale
-
- def set_scale(self, scale):
- self.__scale = scale # %
- self.reset_surface()
+ def set_direction(self, direction):
+ self.__direction = direction # 0: left, 1: right
+ self.callback['set_balloon_direction'](self.side, direction)
- def set_animation_quality(self, quality):
- self.seriko.set_animation_quality(quality, self)
+ direction = property(get_direction, set_direction)
- def set_seriko_inactive(self, flag):
- self.seriko.set_inactive(flag, self)
+ @property
+ def scale(self):
+ return self.callback['get_preference']('surface_scale')
def drag_data_received(self, widget, context, x, y, data, info, time):
logging.debug('Content-type: %s' % data.type)
def create_pixbuf_from_file(self, pixbuf_id):
assert pixbuf_id in self.pixbuf
+ use_pna = self.callback['get_preference']('use_pna')
try:
pixbuf = ninix.pix.create_pixbuf_from_file(
- self.pixbuf[pixbuf_id][0], use_pna=self.__use_pna)
+ self.pixbuf[pixbuf_id][0], use_pna=use_pna)
except:
logging.debug('cannot load surface #%s' % pixbuf_id)
return ninix.pix.create_blank_pixbuf(100, 100)
for element, x, y in self.pixbuf[pixbuf_id][1:]:
try:
overlay = ninix.pix.create_pixbuf_from_file(
- element, use_pna=self.__use_pna)
+ element, use_pna=use_pna)
except:
continue
w = overlay.get_width()
def draw_region(self):
cr = self.darea.window.cairo_create()
cr.save()
- scale = self.get_scale()
+ scale = self.scale
for part, x1, y1, x2, y2 in self.collisions:
x1 = x1 * scale / 100
x2 = x2 * scale / 100
return surface_pixbuf
def update_frame_buffer(self):
- if self.seriko.is_active():
+ if not self.callback['get_preference']('seriko_inactive'):
surface_pixbuf = self.create_surface_pixbuf(self.seriko.base_id)
assert surface_pixbuf is not None
# draw overlays
surface_pixbuf = self.create_surface_pixbuf()
w = surface_pixbuf.get_width()
h = surface_pixbuf.get_height()
- scale = self.get_scale()
+ scale = self.scale
w = max(8, w * scale / 100)
h = max(8, h * scale / 100)
surface_pixbuf = surface_pixbuf.scale_simple(
cr.paint()
cr.restore()
cr.set_source_pixbuf(self.current_surface_pixbuf, 0, 0)
- cr.paint_with_alpha(self.__alpha_channel)
+ alpha_channel = self.callback['get_preference']('surface_alpha')
+ cr.paint_with_alpha(alpha_channel)
del cr
if self.callback['get_preference']('check_collision'):
self.draw_region()
x = self.desc.get_with_type('%s.balloon.offsetx' % name, int, 0)
if y is None:
y = self.desc.get_with_type('%s.balloon.offsety' % name, int, 0)
- scale = self.get_scale()
+ scale = self.scale
x = x * scale / 100
y = y * scale / 100
return x, y
def get_collision_area(self, part):
for p, x1, y1, x2, y2 in self.collisions: ## FIXME
if p == part:
- scale = self.get_scale()
+ scale = self.scale
x1 = x1 * scale / 100
x2 = x2 * scale / 100
y1 = y1 * scale / 100
w, h = 100, 100 # XXX
else:
w, h = ninix.pix.get_png_size(self.pixbuf[surface_id][0])
- scale = self.get_scale()
+ scale = self.scale
w = max(8, int(w * scale / 100))
h = max(8, int(h * scale / 100))
return w, h
path, config = self.surface[basename]
value = config.get_with_type(name, conv)
if value is not None:
- scale = self.get_scale()
+ scale = self.scale
value = conv(value * scale / 100)
return value
centery = self.__get_with_scaling('point.kinoko.centery', int)
return centerx, centery
- def get_direction(self): ## FIXME: property
- return self.direction
-
- def set_direction(self, direction): ## FIXME: property
- self.direction = direction # 0: left, 1: right
- self.callback['set_balloon_direction'](self.side, direction)
-
def set_position(self, x, y):
self.position = (x, y)
new_x, new_y = self.get_position()
if self.__shown:
self.window.resize_move(new_x, new_y)
left, top, scrn_w, scrn_h = ninix.pix.get_workarea()
- if x > left + scrn_w / 2:
- direction = 0
- else:
- direction = 1
- self.set_direction(direction)
+ direction = 0 if x > left + scrn_w / 2 else 1
+ self.direction = direction
ox, oy = self.get_balloon_offset()
if direction == 0: # left
base_x = new_x + ox
self.window.resize_move(x, y) # XXX: call before showing the window
self.darea.show()
self.window.show()
+ self.callback['notify_observer']('show', (self.side))
+ self.callback['notify_observer']('raise', (self.side))
def hide(self):
if self.__shown:
self.window.hide()
self.__shown = False
+ self.callback['notify_observer']('hide', (self.side))
def raise_(self):
self.window.window.raise_()
+ self.callback['notify_observer']('raise', (self.side))
def lower(self):
self.window.window.lower()
+ self.callback['notify_observer']('lower', (self.side))
def button_press(self, window, event):
self.callback['reset_idle_time']()
x = int(event.x)
y = int(event.y)
- scale = self.get_scale()
+ scale = self.scale
x = int(x * 100 / scale)
y = int(y * 100 / scale)
self.x_root = event.x_root
x, y, state = self.darea.window.get_pointer()
else:
x, y, state = event.x, event.y, event.state
- scale = self.get_scale()
+ scale = self.scale
x = int(x * 100 / scale)
y = int(y * 100 / scale)
part = self.get_touched_region(x, y)
def scroll(self, darea, event):
x = int(event.x)
y = int(event.y)
- scale = self.get_scale()
+ scale = self.scale
x = int(x * 100 / scale)
y = int(y * 100 / scale)
if event.direction == gtk.gdk.SCROLL_UP:
def window_enter_notify(self, window, event):
x, y, state = event.x, event.y, event.state
- scale = self.get_scale()
+ scale = self.scale
x = int(x * 100 / scale)
y = int(y * 100 / scale)
self.callback['notify_event'](
def window_leave_notify(self, window, event):
x, y, state = event.x, event.y, event.state
- scale = self.get_scale()
+ scale = self.scale
x = int(x * 100 / scale)
y = int(y * 100 / scale)
if self.__current_part != '': # XXX
# PURPOSE. See the GNU General Public License for more details.
#
-NUMBER = '4.2.5'
+NUMBER = '4.2.6'
CODENAME = 'voodoo programming'
VERSION = '%s (%s)' % (NUMBER, CODENAME)