mirror of
https://github.com/gryf/wmdocklib.git
synced 2025-12-19 04:20:17 +01:00
220 lines
6.4 KiB
Python
220 lines
6.4 KiB
Python
"""pywmhelpers.py
|
|
|
|
Various helper functions when writing wm dockapps in Python. This module
|
|
is way better commented than the pywmgeneral one. This is the one
|
|
intented for use in applications. Many functions are just wrappers
|
|
around the ones in pywmgeneral but with nicer interfaces and better
|
|
documentation.
|
|
|
|
Copyright (C) 2003 Kristoffer Erlandsson
|
|
|
|
Licensed under the GNU General Public License
|
|
|
|
|
|
Changes:
|
|
|
|
2006-10-10 Mario Frasca
|
|
redesigned xpm initialization
|
|
|
|
2003-06-25 Kristoffer Erlandsson
|
|
Updated documentation
|
|
|
|
2003-06-24 Kristoffer Erlandsson
|
|
Some changes to handle the additional event handling in pywmgeneral
|
|
|
|
2003-06-16 Kristoffer Erlandsson
|
|
First workingish version
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
|
|
from wmdocklib import pywmgeneral
|
|
|
|
|
|
charset_start = None
|
|
charset_width = None
|
|
|
|
RGB_FILE_LIST = ['/etc/X11/rgb.txt',
|
|
'/usr/lib/X11/rgb.txt',
|
|
'/usr/share/X11/rgb.txt',
|
|
'/usr/X11R6/lib/X11/rgb.txt',
|
|
'/usr/lib/X11/rgb.txt']
|
|
|
|
|
|
def get_font_char_size(font_name):
|
|
"""Return char size infered from font name.
|
|
|
|
It is expected, that font should have char size included in the file name,
|
|
i.e.
|
|
|
|
charset_8x12_big_black.xpm
|
|
6x8-small.xpm
|
|
|
|
so the pattern searched here would be WxH, where W and H are char width
|
|
and height (including interval between chars and lines) and x is literally
|
|
x.
|
|
"""
|
|
res = re.match(r'.*?(?P<w>[0-9]+)(?:\((?P<t>[0-9]+)\))?x(?P<h>[0-9]+).*',
|
|
font_name)
|
|
if not res:
|
|
return None, None
|
|
|
|
return int(res.groupdict().get('w')), int(res.groupdict().get('h'))
|
|
|
|
|
|
def get_center_start_pos(string, area_width, char_width, offset):
|
|
"""Get the x starting position if we want to paint string centred."""
|
|
string_width = len(string) * char_width
|
|
text_area = area_width - offset * 2 - 1
|
|
return (text_area - string_width) / 2
|
|
|
|
|
|
def get_vertical_spacing(num_lines, margin, char_height, height, y_offset):
|
|
"""Return the optimal spacing between a number of lines.
|
|
|
|
margin is the space we want between the first line and the top."""
|
|
height = height - (num_lines * char_height + 1) - y_offset * 2 - margin
|
|
return height / (num_lines - 1)
|
|
|
|
|
|
def read_xpm(obj):
|
|
"""Read the xpm in filename or treat object as a string with XPM data.
|
|
|
|
Return the pair (palette, pixels).
|
|
|
|
palette is a dictionary char->color (no translation attempted).
|
|
pixels is a list of strings.
|
|
|
|
Raise IOError if we run into trouble when trying to read the file. This
|
|
function has not been tested extensively. do not try to use more than
|
|
"""
|
|
if obj.startswith('/* XPM */'):
|
|
lines = obj.split('\n')
|
|
else:
|
|
with open(obj, 'r') as fobj:
|
|
lines = fobj.read().split('\n')
|
|
|
|
string = ''.join(lines)
|
|
data = []
|
|
while True:
|
|
next_str_start = string.find('"')
|
|
if next_str_start != -1:
|
|
next_str_end = string.find('"', next_str_start + 1)
|
|
if next_str_end != -1:
|
|
data.append(string[next_str_start + 1:next_str_end])
|
|
string = string[next_str_end + 1:]
|
|
continue
|
|
break
|
|
|
|
palette = {}
|
|
color_count = int(data[0].split(' ')[2])
|
|
chars_per_color = int(data[0].split(' ')[3])
|
|
assert chars_per_color == 1
|
|
|
|
for i in range(color_count):
|
|
color_char = data[i+1][0]
|
|
color_name = data[i+1][1:].split()[1]
|
|
palette[color_char] = color_name
|
|
data = data[1 + int(data[0].split(' ')[2]):]
|
|
return palette, data
|
|
|
|
|
|
def redraw_xy(x, y):
|
|
"""Redraw a given region of the window."""
|
|
pywmgeneral.redraw_window_xy(x, y)
|
|
|
|
|
|
def copy_xpm_area(sourceX, sourceY, width, height, targetX, targetY):
|
|
"""Copy an area of the global XPM."""
|
|
(sourceX, sourceY, width, height, targetX,
|
|
targetY) = (int(sourceX), int(sourceY), int(width), int(height),
|
|
int(targetX), int(targetY))
|
|
if width > 0 or height > 0:
|
|
pywmgeneral.copy_xpm_area(sourceX, sourceY, width, height,
|
|
targetX, targetY)
|
|
|
|
|
|
def add_mouse_region(index, left, top, right=None, bottom=None, width=None,
|
|
height=None):
|
|
"""Add a mouse region in the window."""
|
|
if right is bottom is None:
|
|
right = left + width
|
|
bottom = top + height
|
|
pywmgeneral.add_mouse_region(index, left, top, right, bottom)
|
|
|
|
|
|
def check_mouse_region(x, y):
|
|
"""Check if x,y is in any mouse region. Return that region, otherwise -1.
|
|
"""
|
|
return pywmgeneral.check_mouse_region(x, y)
|
|
|
|
|
|
def get_event():
|
|
"""Check for XEvents and return one if found.
|
|
|
|
Return None if we find no events. There may be events pending still
|
|
after this function is called. If an event which we handle is found,
|
|
return a dictionary with information about it. All dictionaries
|
|
contain a 'type' field identifying the event. Now existing events
|
|
with dictionary keys are:
|
|
'buttonrelease':
|
|
x, y, button
|
|
'destroynotify':
|
|
"""
|
|
return pywmgeneral.check_for_events()
|
|
|
|
|
|
def get_color_code(color_name, rgb_fname=None):
|
|
"""Convert a color to rgb code usable in an xpm.
|
|
|
|
We use the file rgb_fname for looking up the colors. Return None
|
|
if we find no match. The rgb_fname should be like the one found in
|
|
/usr/lib/X11R6/rgb.txt on most sytems.
|
|
"""
|
|
if color_name.startswith('#'):
|
|
return color_name
|
|
|
|
if rgb_fname is None:
|
|
for fn in RGB_FILE_LIST:
|
|
if os.access(fn, os.R_OK):
|
|
rgb_fname = fn
|
|
break
|
|
|
|
if rgb_fname is None:
|
|
raise ValueError('cannot find rgb file')
|
|
|
|
with open(rgb_fname, 'r') as fobj:
|
|
lines = fobj.readlines()
|
|
|
|
for line in lines:
|
|
if line[0] != '!':
|
|
words = line.split()
|
|
if len(words) > 3:
|
|
name = ' '.join(words[3:])
|
|
if color_name.lower() == name.lower():
|
|
# Found the right color, get it's code
|
|
try:
|
|
r = int(words[0])
|
|
g = int(words[1])
|
|
b = int(words[2])
|
|
except ValueError:
|
|
continue
|
|
|
|
return f'#{r:02x}{g:02x}{b:02x}'
|
|
return None
|
|
|
|
|
|
def get_unique_key(dict_to_check):
|
|
for char in range(40, 126):
|
|
char = chr(char)
|
|
if char not in dict_to_check:
|
|
return char
|
|
|
|
|
|
def normalize_color(color):
|
|
if color.startswith('#'):
|
|
return color
|
|
else:
|
|
return get_color_code(color)
|