def __init__(self, win, position, gravity, size, width, height, cycle): self.win_id = win.id self.args = (position, gravity, size, width, height ) # TODO: remove me!? self.gravity = gravity workarea = WM.workarea_geometry self.position = absolute_position(workarea, position) self.sizes = absolute_size(win, workarea, size, width, height) dummy = DummyWindow(win, self.position, self.sizes, self.gravity) max_geo = expand_window(dummy, dummy.gravity, sticky=False, vertical_first=cycle) widths = [] for width in self.sizes.width: if max_geo.width - width >= 0 and \ self.position.x - width * position.x >= max_geo.x and \ self.position.x + width * (1 - position.x) <= max_geo.x2: widths.append(width) heights = [] for height in self.sizes.height: if max_geo.height - height >= 0 and \ self.position.y - height * position.y >= max_geo.y and \ self.position.y + height * (1 - position.y) <= max_geo.y2: heights.append(height) width = max(widths) height = max(heights) self.sizes_iterator = Size(get_iterator(self.sizes.width, width), get_iterator(self.sizes.height, height)) [self.sizes_iterator.height, self.sizes_iterator.width][cycle].next() self.previous = Geometry(self.position.x, self.position.y, width, height, self.gravity)
def __init__(self, config, section, key): self.key = key """Section key or key modifier.""" data = dict(config._config.items(section)) self.ignored_actions = set() """List of ignored actions.""" if 'ignore_actions' in data: ignored_actions = data.get('ignore_actions', '').split(', ') self.ignored_actions.update(ignored_actions) self.ignored_actions.update(config.ignored_actions) if 'grid' in self.ignored_actions: self.ignored_actions.update(['grid_width', 'grid_height']) self.gravity = Gravity.parse(data.get('gravity', '')) """Gravity.""" self.direction = Gravity.parse(data.get('direction', '')) """Direction of window movement.""" if not self.direction: self.direction = self.gravity self.position = Gravity.parse(data.get('position', '')) """Position position on :ref:`workarea`.""" if not self.position: self.position = self.gravity elif self.position and not self.gravity: self.gravity = self.position self.size = Size.parse(data.get('widths', ''), data.get('heights', '')) """Window size(s)."""
def size_callback(option, opt_str, value, parser): """Parse width, height, size options to Size.""" largs_callback(option, opt_str, value, parser) # TODO: allow relative size, and absolute size try: if option.dest == 'width': width = Size.parse_value(value) size = Size(width, 0) elif option.dest == 'height': height = Size.parse_value(value) size = Size(0, height) elif option.dest == 'size': size = Size.parse(*value) except (ValueError, TypeError): msg = 'option %s: error parsing Size value: %s' % (opt_str, value) raise optparse.OptionValueError(msg) setattr(parser.values, option.dest, size)
def test_area(self): self.assertEqual(Size.parse('HALF', 'FULL').area, 0.5) self.assertEqual(Size.parse('HALF', '1').area, 0.5) self.assertEqual(Size.parse('HALF', '1.0').area, 0.5) self.assertEqual(Size.parse('HALF', 'HALF*2').area, 0.5) self.assertEqual(Size.parse('HALF', 'QUARTER*2+HALF').area, 0.5) self.assertEqual(Size.parse('1.0/2', '0.1*6-0.1+HALF').area, 0.5) self.assertEqual(Size(10, 10).area, 100) try: # assertRaises doesn't work with properties Size.parse('HALF, FULL', '1').area except ValueError: # "Size.area doesn't support multiple dimensions" pass else: raise AssertionError
def next(self, cycle): """Return new window geometry.""" if cycle == CYCLE_WIDTH: width = self.sizes_iterator.width.next() height = self.previous.height if cycle == CYCLE_HEIGHT: width = self.previous.width height = self.sizes_iterator.height.next() self.previous = Size(width, height) return Geometry(self.position.x, self.position.y, width, height, self.gravity)
def absolute_size(win, workarea, size, width, height): """Return Size containing sorted lists of absolute sizes.""" widths = width.width or size.width or \ float(win.width) / workarea.width heights = height.height or size.height or \ float(win.height) / workarea.height try: widths = set([min([width * workarea.width, workarea.width]) for width in widths]) except TypeError: widths = [min([widths * workarea.width, workarea.width])] try: heights = set([min([height * workarea.height, workarea.height]) for height in heights]) except TypeError: heights = [min([heights * workarea.height, workarea.height])] return Size(sorted(widths), sorted(heights))
def __init__(self, config, section, key): self.key = key data = dict(config._config.items(section)) self.ignored = set() if 'ignore_actions' in data: self.ignored.update(data.get('ignore_actions', '').split(', ')) self.ignored.update(config.ignored) if 'grid' in self.ignored: self.ignored.update(['grid_width', 'grid_height']) self.gravity = Gravity.parse(data.get('gravity', '')) self.direction = Gravity.parse(data.get('direction', '')) if not self.direction: self.direction = self.gravity self.position = Gravity.parse(data.get('position', '')) if not self.position: self.position = self.gravity elif self.position and not self.gravity: self.gravity = self.position self.size = Size.parse(data.get('widths', ''), data.get('heights', ''))
"""grid_actions.py - PyWO actions - placing windows on grid.""" import itertools import logging from pywo.core import Gravity, Geometry, Size, Position, WindowManager from pywo.actions import Action, TYPE_FILTER from pywo.actions.resizer import expand_window __author__ = "Wojciech 'KosciaK' Pietrzok" log = logging.getLogger(__name__) WM = WindowManager() NO_SIZE = Size(0, 0) CYCLE_WIDTH = 0 CYCLE_HEIGHT = 1 class DummyWindow(object): """Dummy Window object, only geometry information is needed.""" gravity = Gravity(0.5, 0.5) def __init__(self, window, position, size, gravity): self.extents = window.extents self.desktop = window.desktop self.id = window.id self.geometry = Geometry(position.x, position.y, min(size.width),
def test_parse(self): self.assertEqual(Size.parse('', ''), None) self.assertEqual(Size.parse('', 'FULL'), None) self.assertEqual(Size.parse('HALF', ''), None) self.assertEqual(Size.parse('HALF', 'FULL'), self.HALF_FULL) self.assertEqual(Size.parse('HALF', '1'), self.HALF_FULL) self.assertEqual(Size.parse('HALF', '1.0'), self.HALF_FULL) self.assertEqual(Size.parse('HALF', 'HALF*2'), self.HALF_FULL) self.assertEqual(Size.parse('HALF', 'QUARTER*2+HALF'), self.HALF_FULL) self.assertEqual(Size.parse('1.0/2', '0.1*6-0.1+HALF'), self.HALF_FULL) self.assertEqual(Size.parse('HALF, FULL', '1'), Size([0.5, 1], 1)) self.assertRaises(ValueError, Size.parse, 'tttgf', '0')
def test_parse_value(self): self.assertEqual(Size.parse_value('FULL'), 1.0) self.assertEqual(Size.parse_value('F'), 1.0) self.assertEqual(Size.parse_value('1'), 1.0) self.assertEqual(Size.parse_value('1.0'), 1.0) self.assertEqual(Size.parse_value('H+H'), 1.0) self.assertEqual(Size.parse_value('H+0.5'), 1.0) self.assertEqual(Size.parse_value('0.25*4'), 1.0) self.assertEqual(Size.parse_value('Q*4'), 1.0) self.assertEqual(Size.parse_value('0.25*2+H'), 1.0) self.assertEqual(Size.parse_value('8*HALF/4'), 1.0) self.assertEqual(Size.parse_value('8*HALF/2-FULL'), 1.0) self.assertEqual(Size.parse_value('HALF'), 0.5) self.assertEqual(Size.parse_value('H'), 0.5) self.assertEqual(Size.parse_value('0.5'), 0.5) self.assertEqual(Size.parse_value('THIRD'), 1.0/3) self.assertEqual(Size.parse_value('T'), 1.0/3) self.assertEqual(Size.parse_value('QUARTER'), 0.25) self.assertEqual(Size.parse_value('Q'), 0.25) self.assertEqual(Size.parse_value('0.25'), 0.25) self.assertEqual(Size.parse_value('HALF,FULL'), [0.5, 1]) self.assertEqual(Size.parse_value(''), None) self.assertEqual(Size.parse_value(' '), None) self.assertRaises(ValueError, Size.parse_value, 'fasdfa')
def setUp(self): self.HALF_FULL = Size(0.5, 1.0)