diff --git a/mopidy_touchscreen/graphic_utils/screen_objects.py b/mopidy_touchscreen/graphic_utils/screen_objects.py index 1c97f3d..e3b5c59 100644 --- a/mopidy_touchscreen/graphic_utils/screen_objects.py +++ b/mopidy_touchscreen/graphic_utils/screen_objects.py @@ -86,12 +86,13 @@ class TextItem(BaseItem): scroll_speed = 5 - def __init__(self, font, text, pos, size, center=False): + def __init__(self, font, text, pos, size, center=False, background=None): self.font = font self.text = text self.color = (255, 255, 255) self.box = self.font.render(text, True, self.color) self.box = self.box.convert_alpha() + self.background = background if size is not None: if size[1] == -1: height = self.font.size(text)[1] @@ -143,6 +144,9 @@ class TextItem(BaseItem): return BaseItem.update(self) def render(self, surface): + if self.background: + surface.fill(self.background, rect=self.rect_in_pos) + pygame.draw.rect(surface, (0, 0, 0), self.rect_in_pos, 1) if self.fit_horizontal: surface.blit( self.box, ((self.pos[0] + self.margin), @@ -163,10 +167,16 @@ class TextItem(BaseItem): if text != self.text: if change_size: TextItem.__init__(self, self.font, text, self.pos, - None, self.center) + None, self.center, self.background) else: TextItem.__init__(self, self.font, text, self.pos, - self.size, self.center) + self.size, self.center, self.background) + + def add_text(self, add_text, change_size): + self.set_text(self.text+add_text, change_size) + + def remove_text(self, chars, change_size): + self.set_text(self.text[:-chars], change_size) class TouchObject(BaseItem): @@ -208,8 +218,9 @@ class TouchObject(BaseItem): class TouchAndTextItem(TouchObject, TextItem): - def __init__(self, font, text, pos, size, center=False): - TextItem.__init__(self, font, text, pos, size, center=center) + def __init__(self, font, text, pos, size, center=False, background=None): + TextItem.__init__(self, font, text, pos, size, center=center, + background=background) TouchObject.__init__(self, pos, self.size) self.active_color = (0, 150, 255) self.normal_box = self.box diff --git a/mopidy_touchscreen/input/input_manager.py b/mopidy_touchscreen/input/input_manager.py index 75d12d4..23375c5 100644 --- a/mopidy_touchscreen/input/input_manager.py +++ b/mopidy_touchscreen/input/input_manager.py @@ -20,6 +20,9 @@ class InputManager(): right = 3 enter = 4 + special_keys = [pygame.K_DOWN, pygame.K_UP, pygame.K_LEFT, + pygame.K_RIGHT, pygame.K_RETURN] + def __init__(self, size): self.down_pos = (0, 0) self.up_pos = (0, 0) @@ -37,13 +40,13 @@ class InputManager(): touch_event = InputEvent(InputManager.swipe, self.down_pos, self.up_pos, True, - InputManager.up) + InputManager.up, None) return touch_event elif event.button == 5: touch_event = InputEvent(InputManager.swipe, self.down_pos, self.up_pos, True, - InputManager.down) + InputManager.down, None) return touch_event elif event.button == 1 and self.down_button == 1: touch_event = self.mouse_up(event) @@ -51,7 +54,7 @@ class InputManager(): elif event.button == 3 and self.down_button == 3: touch_event = InputEvent(InputManager.long_click, self.down_pos, self.up_pos, - None, None) + None, None, None) return touch_event else: return None @@ -59,14 +62,20 @@ class InputManager(): self.mouse_down(event) return None elif event.type == pygame.KEYDOWN: - self.key_down(event) - return None + return self.key_down(event) elif event.type == pygame.KEYUP: return self.key_up(event) def key_down(self, event): - self.last_key = event.key - self.down_time = time.time() + if len(event.unicode) > 0 and event.key not in \ + InputManager.special_keys: + print event + return InputEvent(InputManager.key, None, None, None, + None, event.unicode) + else: + self.last_key = event.key + self.down_time = time.time() + return None def key_up(self, event): if self.last_key == event.key: @@ -84,7 +93,7 @@ class InputManager(): return None if direction is not None: return InputEvent(InputManager.key, None, None, None, - direction) + direction, self.last_key) def mouse_down(self, event): self.down_pos = event.pos @@ -119,10 +128,11 @@ class InputManager(): class InputEvent(): def __init__(self, event_type, down_pos, current_pos, vertical, - direction): + direction, unicode=None): self.type = event_type self.down_pos = down_pos self.current_pos = current_pos + self.unicode = unicode if event_type is InputManager.swipe and direction is None: if vertical: if self.down_pos[1] < self.current_pos[1]: diff --git a/mopidy_touchscreen/screen_manager.py b/mopidy_touchscreen/screen_manager.py index e1932fc..f19ce07 100644 --- a/mopidy_touchscreen/screen_manager.py +++ b/mopidy_touchscreen/screen_manager.py @@ -9,7 +9,7 @@ from pkg_resources import Requirement, resource_filename import pygame -from screens import LibraryScreen, MainScreen, MenuScreen,\ +from screens import Keyboard, LibraryScreen, MainScreen, MenuScreen,\ PlaylistScreen, SearchScreen, Tracklist @@ -39,6 +39,7 @@ class ScreenManager(): self.input_manager = InputManager(size) self.down_bar_objects = ScreenObjectsManager() self.down_bar = None + self.keyboard = None self.init_manager(size) @@ -132,9 +133,12 @@ class ScreenManager(): def update(self): surface = self.background.draw_background() - self.screens[self.current_screen].update(surface) - surface.blit(self.down_bar, (0, self.base_size * 7)) - self.down_bar_objects.render(surface) + if self.keyboard: + self.keyboard.update(surface) + else: + self.screens[self.current_screen].update(surface) + surface.blit(self.down_bar, (0, self.base_size * 7)) + self.down_bar_objects.render(surface) return surface def track_started(self, track): @@ -149,7 +153,9 @@ class ScreenManager(): def event(self, event): event = self.input_manager.event(event) if event is not None: - if not self.manage_event(event): + if self.keyboard is not None: + self.keyboard.touch_event(event) + elif not self.manage_event(event): self.screens[self.current_screen].touch_event(event) def manage_event(self, event): @@ -218,3 +224,10 @@ class ScreenManager(): def resize(self, event): self.init_manager(event.size) + + def open_keyboard(self, input_listener): + self.keyboard = Keyboard(self.size, self.base_size, self, + self.fonts, input_listener) + + def close_keyboard(self): + self.keyboard = None diff --git a/mopidy_touchscreen/screens/__init__.py b/mopidy_touchscreen/screens/__init__.py index 51dc1c4..6b9a9d9 100644 --- a/mopidy_touchscreen/screens/__init__.py +++ b/mopidy_touchscreen/screens/__init__.py @@ -1,5 +1,6 @@ # flake8: noqa from library_screen import LibraryScreen +from keyboard_screen import Keyboard from main_screen import MainScreen from menu_screen import MenuScreen from playlist_screen import PlaylistScreen diff --git a/mopidy_touchscreen/screens/keyboard_screen.py b/mopidy_touchscreen/screens/keyboard_screen.py new file mode 100644 index 0000000..b25b204 --- /dev/null +++ b/mopidy_touchscreen/screens/keyboard_screen.py @@ -0,0 +1,128 @@ +import pygame + +from .base_screen import BaseScreen +from ..graphic_utils import ScreenObjectsManager, TouchAndTextItem +from ..input import InputManager + + +class Keyboard(BaseScreen): + + def __init__(self, size, base_size, manager, fonts, listener): + BaseScreen.__init__(self, size, base_size, manager, fonts) + self.base_width = size[0]/10 + self.base_height = size[1]/5 + self.listener = listener + self.manager = manager + try: + self.font is None + except AttributeError: + self.font = pygame.font.SysFont("arial", size[1]/6) + self.keyboards = [ScreenObjectsManager(), ScreenObjectsManager()] + self.other_objects = ScreenObjectsManager() + self.current_keyboard = 0 + + rows = [['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'], + ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '-'], + [',', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '.', '_']] + + line = self.base_height + for row in rows: + pos = 0 + for key in row: + button = \ + TouchAndTextItem(self.font, key, + (pos, line), + (self.base_width, self.base_height), + center=True, background=(150, 150, 150)) + self.keyboards[self.current_keyboard].\ + set_touch_object(key, button) + pos += self.base_width + line += self.base_height + + self.current_keyboard = 1 + rows = [['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], + ['!', '@', '#', '$', '%', '&', '/', '(', ')', '='], + ['?', '{', '}', '_', '[', ']', '+', '<', '>', '*']] + line = self.base_height + for row in rows: + pos = 0 + for key in row: + button = \ + TouchAndTextItem(self.font, key, (pos, line), + (self.base_width, self.base_height), + center=True, background=(150, 150, 150)) + self.keyboards[self.current_keyboard].\ + set_touch_object(key, button) + pos += self.base_width + line += self.base_height + self.current_keyboard = 0 + + # Symbol button + button = TouchAndTextItem(self.font, "123", + (0, self.base_height*4), + (self.base_width*2, self.base_height), + center=True, background=(150, 150, 150)) + self.other_objects.set_touch_object("symbols", button) + + # remove button + button = TouchAndTextItem(self.font, "<-", + (self.base_width*2, self.base_height*4), + (self.base_width*2, self.base_height), + center=True, background=(150, 150, 150)) + self.other_objects.set_touch_object("remove", button) + + # Space button + button = TouchAndTextItem(self.font, " ", + (self.base_width*4, self.base_height*4), + (self.base_width*4, self.base_height), + center=True, background=(150, 150, 150)) + self.other_objects.set_touch_object("space", button) + + # OK button + button = TouchAndTextItem(self.font, "->", + (self.base_width*8, self.base_height*4), + (self.base_width*2, self.base_height), + center=True, background=(150, 150, 150)) + self.other_objects.set_touch_object("ok", button) + + # EditText button + button = TouchAndTextItem(self.font, "", + (0, 0), + (self.base_width*10, self.base_height), + center=True) + self.other_objects.set_object("text", button) + + def update(self, screen): + screen.fill((0, 0, 0)) + self.keyboards[self.current_keyboard].render(screen) + self.other_objects.render(screen) + + def touch_event(self, touch_event): + if touch_event.type == InputManager.click: + keys = self.keyboards[self.current_keyboard]\ + .get_touch_objects_in_pos(touch_event.current_pos) + for key in keys: + self.other_objects.get_object("text").add_text(key, False) + keys = self.other_objects.get_touch_objects_in_pos( + touch_event.current_pos) + for key in keys: + if key == 'symbols': + if self.current_keyboard == 0: + self.current_keyboard = 1 + else: + self.current_keyboard = 0 + elif key == "remove": + self.other_objects.get_object("text").remove_text(1, False) + elif key == "space": + self.other_objects.get_object("text").add_text(" ", False) + elif key == "ok": + text = self.other_objects.get_object("text").text + self.listener.text_input(text) + self.manager.close_keyboard() + elif touch_event.type == InputManager.key: + if len(touch_event.unicode): + if touch_event.unicode == u'\x08': + self.other_objects.get_object("text").remove_text(1, False) + else: + self.other_objects.get_object("text").add_text( + touch_event.unicode, False) diff --git a/mopidy_touchscreen/screens/search_screen.py b/mopidy_touchscreen/screens/search_screen.py index 9015d18..5eee51f 100644 --- a/mopidy_touchscreen/screens/search_screen.py +++ b/mopidy_touchscreen/screens/search_screen.py @@ -3,7 +3,7 @@ from base_screen import BaseScreen import pygame from ..graphic_utils import ListView,\ - ScreenObjectsManager, TextItem, TouchAndTextItem + ScreenObjectsManager, TouchAndTextItem from ..input import InputManager @@ -23,33 +23,43 @@ class SearchScreen(BaseScreen): self.screen_objects = ScreenObjectsManager() self.query = "" + # Search button + button = TouchAndTextItem(self.fonts['icon'], u" \ue986", + (0, self.base_size), + None, center=True) + self.screen_objects.set_touch_object( + "search", button) + + x = button.get_right_pos() + # Query text - text = TextItem(self.fonts['base'], self.query, (0, 0), - (self.size[0], self.base_size), center=True) - self.screen_objects.set_object("query", text) + text = TouchAndTextItem(self.fonts['base'], self.query, (0, 0), + (self.size[0], self.base_size), center=True) + self.screen_objects.set_touch_object("query", text) # Mode buttons - button_size = (self.size[0] / 3, self.base_size) + button_size = ((self.size[0]-x)/3, self.base_size) self.mode_objects_keys = ["mode_track", "mode_album", "mode_artist"] # Track button button = TouchAndTextItem(self.fonts['base'], "Track", - (0, self.base_size), - button_size, center=True) + (x, self.base_size), + (button_size[0], self.base_size), + center=True) self.screen_objects.set_touch_object( self.mode_objects_keys[0], button) # Album button button = TouchAndTextItem(self.fonts['base'], "Album", - (button_size[0], self.base_size), + (button_size[0]+x, self.base_size), button_size, center=True) self.screen_objects.set_touch_object( self.mode_objects_keys[1], button) # Artist button button = TouchAndTextItem(self.fonts['base'], "Artist", - (button_size[0]*2, self.base_size), + (button_size[0]*2+x, self.base_size), button_size, center=True) self.screen_objects.set_touch_object( self.mode_objects_keys[2], button) @@ -61,7 +71,7 @@ class SearchScreen(BaseScreen): self.top_bar.fill((0, 0, 0, 128)) self.mode = -1 self.set_mode(mode=mode_track_name) - self.set_query("") + self.set_query("Search") def update(self, screen): screen.blit(self.top_bar, (0, 0)) @@ -79,7 +89,7 @@ class SearchScreen(BaseScreen): def set_query(self, query=""): self.query = query - self.screen_objects.get_object("query").set_text( + self.screen_objects.get_touch_object("query").set_text( self.query, False) def search(self, query=None, mode=None): @@ -130,8 +140,15 @@ class SearchScreen(BaseScreen): self.search(mode=1) if clicked == self.mode_objects_keys[2]: self.search(mode=2) + if clicked == "query" or clicked == "search": + self.manager.open_keyboard(self) else: - self.list_view.touch_event(touch_event) + pos = self.list_view.touch_event(touch_event) + if pos is not None: + self.manager.core.tracklist.clear() + self.manager.core.tracklist.add( + uri=self.results[pos].uri) + self.manager.core.playback.play() def change_screen(self, direction): if direction == InputManager.right: @@ -142,4 +159,9 @@ class SearchScreen(BaseScreen): if self.mode > 0: self.set_mode(self.mode-1) return True + else: + self.manager.open_keyboard(self) return False + + def text_input(self, text): + self.search(text, self.mode)