from Xlib import X, XK from clipboard import copy from constants import TARGET from vim import open_vim import text import styles pressed = set() events = [] def event_to_string(self, event): mods = [] if event.state & X.ShiftMask: mods.append('Shift') if event.state & X.ControlMask: mods.append('Control') keycode = event.detail keysym = self.disp.keycode_to_keysym(keycode, 0) char = XK.keysym_to_string(keysym) return ''.join(mod + '+' for mod in mods) + (char if char else '?') def replay(self): for e in events: self.inkscape.send_event(e, propagate=True) self.disp.flush() self.disp.sync() events.clear() pressed.clear() def normal_mode(self, event, char): events.append(event) if event.type == X.KeyPress: if char: pressed.add(event_to_string(self, event)) elif event.type == X.KeyRelease: handled = False if len(pressed) >= 2: fire(self, pressed) handled = True if len(pressed) == 1: ev = next(iter(pressed)) if ev == 't': open_vim(self, compile_latex=False) handled = True if ev == 'Shift+t': open_vim(self, compile_latex=True) handled = True if ev == 'a': self.mode = styles.object_mode handled = True if ev == 'Shift+a': styles.save_object_mode(self) handled = True if ev == 's': self.mode = styles.style_mode handled = True if ev == 'Shift+s': styles.save_style_mode(self) handled = True if ev == 'w': self.press('p') handled = True if ev == 'x': self.press('percent', X.ShiftMask) handled = True if ev == 'f': self.press('b') handled = True if ev == 'z': self.press('z', X.ControlMask) handled = True if ev == 'Shift+z': self.press('Delete') handled = True if ev == '`': self.press('t') self.mode = text.text_mode handled = True if handled: events.clear() pressed.clear() else: replay(self) else: pass # print("hu?") def fire(self, combination): # Stolen from TikZ pt = 1.327 # pixels w = 0.4 * pt thick_width = 0.8 * pt very_thick_width = 1.2 * pt style = { 'stroke-opacity': 1 } if {'s', 'a', 'd', 'g', 'h', 'x', 'e'} & combination: style['stroke'] = 'black' style['stroke-width'] = w style['marker-end'] = 'none' style['marker-start'] = 'none' style['stroke-dasharray'] = 'none' else: style['stroke'] = 'none' if 'g' in combination: w = thick_width style['stroke-width'] = w if 'h' in combination: w = very_thick_width style['stroke-width'] = w if 'a' in combination: style['marker-end'] = f'url(#marker-arrow-{w})' if 'x' in combination: style['marker-start'] = f'url(#marker-arrow-{w})' style['marker-end'] = f'url(#marker-arrow-{w})' if 'd' in combination: style['stroke-dasharray'] = f'{w},{2*pt}' if 'e' in combination: style['stroke-dasharray'] = f'{3*pt},{3*pt}' if 'f' in combination: style['fill'] = 'black' style['fill-opacity'] = 0.12 if 'b' in combination: style['fill'] = 'black' style['fill-opacity'] = 1 if 'w' in combination: style['fill'] = 'white' style['fill-opacity'] = 1 if {'f', 'b', 'w'} & combination: style['marker-end'] = 'none' style['marker-start'] = 'none' if not {'f', 'b', 'w'} & combination: style['fill'] = 'none' style['fill-opacity'] = 1 if style['fill'] == 'none' and style['stroke'] == 'none': return svg = ''' ''' # Arrow style stolen from tikz if ('marker-end' in style and style['marker-end'] != 'none') or \ ('marker-start' in style and style['marker-start'] != 'none'): svg += f''' ''' style_string = ';'.join('{}: {}'.format(key, value) for key, value in sorted(style.items(), key=lambda x: x[0]) ) svg += f'' copy(svg, target=TARGET) self.press('v', X.ControlMask | X.ShiftMask)