def set_help_of(self, hoverable, wait_time=1000, pos=None): """NB : help needs a timed menu to work.""" try: self.visible = False hoverable.add_elements([self]) hoverable._help_element = self hoverable._help_wait_time = wait_time hoverable._help_pos = pos hoverable._help_reaction = Reaction(constants.THORPY_EVENT, hoverable._reaction_help, {"id": constants.EVENT_TIME}, reac_name=constants.REAC_HELP) except AttributeError: raise Exception("Cannot set helper of an element who does not have\ _reaction_help method.") ## def copy(self): ## copy_children = [e.copy() for e in self.get_elements()] ## e = self.__class__(self.get_text(), elements=copy_children) ## e.set_size(self.get_fus_size()) ## return e
def make_fontsize_setter(fn, const_text="", slider_length=100, limvals=(6, 36)): from thorpy.miscgui.reaction import Reaction from thorpy.miscgui.metadata import MetaDataManager from thorpy.elements.launchers.paramsetterlauncher import ParamSetterLauncher from thorpy.miscgui.varset import VarSet import os, sys varset = VarSet() varset.add("fontsize", value=style.FONT_SIZE, text="Font size:", limits=limvals, more={"length": slider_length}) button = ParamSetterLauncher.make([varset], const_text, const_text, text_ok="Apply") def reac_func(event): if event.what == constants.LAUNCH_DONE: font_size = varset.get_value("fontsize") mdm = MetaDataManager() mdm.read_data(fn) mdm.data["font_size"] = font_size ## print("writing", mdm.data, fn) mdm.write_data(fn) #restart script python = sys.executable os.execl(python, python, *sys.argv) reac = Reaction(constants.THORPY_EVENT, reac_func, { "id": constants.EVENT_UNLAUNCH, "launcher": button.launcher }) button.add_reaction(reac) return button
def __init__(self, length, limvals=None, text="", elements=None, normal_params=None, initial_value=None): if initial_value is None: initial_value = 0 if limvals[0] <= initial_value <= limvals[ 1]: #will be False if initial_value is None self.initial_value = initial_value else: if initial_value is not None: functions.debug_msg("Initial value for slider was not in the\ limvals range. Auto set to limvals[0].") self.initial_value = limvals[0] self._drag_element = DraggerX(self) super(SliderX, self).__init__(length, limvals, text, elements) self._drag_element.finish() self.add_elements(list([self._drag_element])) reac_click = Reaction(pygame.MOUSEBUTTONDOWN, self._func_reac_click) self.add_reaction(reac_click)
def launch_blocking_choices(text, choices, parent=None, title_fontsize=None, title_fontcolor=None, main_color=None, click_quit=False): """choices is a list of either tuple(text,func) or elements""" if title_fontsize is None: title_fontsize = style.FONT_SIZE if title_fontcolor is None: title_fontcolor = style.FONT_COLOR ## elements = [make_button(t,f) for t,f in choices] #old form elements = [] for choice in choices: if isinstance(choice, tuple): elements.append(make_button(choice[0],choice[1])) else: elements.append(choice) ghost = make_stored_ghost(elements) e_text = make_text(text, title_fontsize, title_fontcolor) box = Box.make([e_text, ghost]) if main_color: box.set_main_color(main_color) box.center() from thorpy.miscgui.reaction import ConstantReaction, Reaction from thorpy import functions for e in elements: reac = ConstantReaction(constants.THORPY_EVENT, functions.quit_menu_func, {"id":constants.EVENT_UNPRESS, "el":e}) box.add_reaction(reac) def click_outside(e): if not box.get_fus_rect().collidepoint(e.pos): functions.quit_menu_func() box.add_reaction(Reaction(pygame.MOUSEBUTTONDOWN, click_outside)) from thorpy.menus.tickedmenu import TickedMenu m = TickedMenu(box) m.play() box.unblit() if parent: parent.partial_blit(None, box.get_fus_rect()) box.update()
def _set_launcher(self): launcher = launchmod.Launcher(self.launched, launching=self) reac_enter = ConstantReaction(constants.THORPY_EVENT, launcher.launch, {"id": constants.EVENT_UNPRESS, "el":self}) ## reac_name="reac_launch") reac_done = ConstantReaction(constants.THORPY_EVENT, self._unlaunch_done, {"id": constants.EVENT_DONE, "el":self.launched}) ## reac_name="reac_done") reac_cancel = ConstantReaction(constants.THORPY_EVENT, self._unlaunch_cancel, {"id": constants.EVENT_CANCEL, "el":self.launched}) ## reac_name="reac_cancel") if self.click_cancel: reac_click_cancel = Reaction(parameters.MOUSEBUTTONUP, self._unlaunch_click_cancel, params={"launcher":launcher}) ## reac_name="reac_click_cancel") self.launched.add_reaction(reac_click_cancel) self.add_reaction(reac_enter) self.launched.add_reaction(reac_done) self.launched.add_reaction(reac_cancel) self.launcher = launcher
def _set_launcher(self): launcher = launchmod.Launcher(self.launched, launching=self) reac_enter = ConstantReaction(constants.THORPY_EVENT, launcher.launch, {"id": constants.EVENT_UNPRESS, "el":self}) ## reac_name="reac_launch") reac_done = ConstantReaction(constants.THORPY_EVENT, self.unlaunch, {"id": constants.EVENT_DDL, "el":self.launched}) ## reac_name="reac_done") if self.click_cancel: reac_cancel = Reaction(parameters.MOUSEBUTTONUP, launchmod.func_click_quit, params={"launcher":launcher, "what":CLICK_QUIT}) ## reac_name="reac_cancel") self.launched.add_reaction(reac_cancel) self.add_reaction(reac_enter) self.launched.add_reaction(reac_done) def func_before(): self.launched.stick_to(self, "bottom", "top") self.launched.blit() self.launched.update() launcher.func_before = func_before self.launcher = launcher
def get_launcher(launched, click_quit=False, launching=None, autocenter=True): """Prepare and return a launcher object for launching <launched>.""" launcher = Launcher(launched, launching=launching) launcher.autocenter = autocenter reac_done = ConstantReaction(constants.THORPY_EVENT, launcher.unlaunch_done, {"id": constants.EVENT_DONE, "el":launched}, {"what": DONE}, reac_name="reac_done") reac_cancel = ConstantReaction(constants.THORPY_EVENT, launcher.unlaunch_cancel, {"id": constants.EVENT_CANCEL, "el":launched}, {"what": CANCEL}, reac_name="reac_cancel") if click_quit: reac_clickquit = Reaction(parameters.MOUSEBUTTONUP, func_click_quit, {"button":parameters.LEFT_CLICK_BUTTON}, {"launcher":launcher, "what":CLICK_QUIT}, reac_name="reac_clickquit") launched.add_reaction(reac_clickquit) launched.add_reaction(reac_done) launched.add_reaction(reac_cancel) return launcher
def make_font_setter(fn, const_text="", var_text="", ddl_size="auto"): from thorpy.elements.launchers.dropdownlistlauncher import DropDownListLauncher from thorpy.miscgui.reaction import Reaction from thorpy.miscgui.metadata import MetaDataManager import os, sys titles = list(constants.AVAILABLE_FONTS) titles.sort() button = DropDownListLauncher.make(const_text, var_text, titles, show_select=False, ddlf_size=ddl_size) def reac_func(event): font = event.value mdm = MetaDataManager() mdm.read_data(fn) mdm.data["font"] = font mdm.write_data(fn) #restart script python = sys.executable os.execl(python, python, * sys.argv) reac = Reaction(constants.THORPY_EVENT, reac_func, {"id":constants.EVENT_DDL, "el":button}) button.add_reaction(reac) return button
def set_animated(self, pps, imgs, state=None): """ <pps>: Number of periods per seconds. It means that regardless of the number of frames, the whole set of frame is refreshed <pps> times per second (of course, a high pps is limited by machine performances). <imgs>: List of frames (pygame surfaces). <state>: Element state for which the animation accounts. None means element's current state. NOTE : self's fus_rect and state properties doesn't adapt to the images, so use images of the same size in order to prevent bugs. Next version will provide auto-inflatable animations. """ n = len(imgs) #factor 1000 because the thick will be in millisec #factor 2 because Clock.get_time() returns time between two last iters. interval = 1000. / (pps*n) self._tot_ticks = 0 self._current_frame = 0 reac = Reaction(constants.THORPY_EVENT, self._change_animation_frame, {"id":constants.EVENT_TIME}, {"imgs":imgs, "interval":interval, "state":state}, "thorpy animation") self.add_reaction(reac)
def __init__(self, text="", elements=None, normal_params=None, press_params=None, finish=True): """Clickable that can be dragged/dropped.""" super(Draggable, self).__init__(text, elements, normal_params, press_params, finish=False) # not polite set, because of standard _press painter args self.press_params.params["painter args"] = { "pressed": False, "size": style.SIZE } reac_motion = Reaction(MOUSEMOTION, self._reaction_drag, reac_name=constants.REAC_MOTION) self.add_reaction(reac_motion) self._constraints = (1., 1.) if finish: self.finish()
def launch_choices(text, choices, title_fontsize=None, title_fontcolor=None, click_quit=False): """choices are tuple (text,func)""" if title_fontsize is None: title_fontsize = style.FONT_SIZE if title_fontcolor is None: title_fontcolor = style.FONT_COLOR ## elements = [make_button(t,f) for t,f in choices] elements = [] for choice in choices: if isinstance(choice, tuple): elements.append(make_button(choice[0], choice[1])) else: elements.append(choice) ghost = make_stored_ghost(elements) e_text = make_text(text, title_fontsize, title_fontcolor) box = Box.make([e_text, ghost]) box.center() from thorpy.miscgui.launchers.launcher import launch from thorpy.miscgui.reaction import ConstantReaction, Reaction from thorpy import functions launcher = launch(box) for e in elements: reac = ConstantReaction(constants.THORPY_EVENT, launcher.unlaunch, { "id": constants.EVENT_UNPRESS, "el": e }, {"what": None}) box.add_reaction(reac) def click_outside(e): if not box.get_fus_rect().collidepoint(e.pos): functions.quit_menu_func() box.add_reaction(Reaction(pygame.MOUSEBUTTONDOWN, click_outside)) return launcher
def make_display_options_setter(fn, const_text="", sliders_length=100, limvalsw=(400, None), limvalsh=(400, None), restart_app=True): from thorpy.miscgui.reaction import Reaction from thorpy.miscgui.metadata import MetaDataManager from thorpy.elements.launchers.paramsetterlauncher import ParamSetterLauncher from thorpy.miscgui.varset import VarSet import os, sys varset = VarSet() w, h = functions.get_screen_size() maxsize = functions.get_current_application().max_screen_size if limvalsw[1] is None: limvalsw = (limvalsw[0], maxsize[0]) if limvalsh[1] is None: limvalsh = (limvalsh[0], maxsize[1]) fullscreen = bool(functions.get_screen().get_flags() & pygame.FULLSCREEN) varset.add("screen_w", value=int(w), text="Screen width: ", limits=limvalsw) varset.add("screen_h", value=int(h), text="Screen height: ", limits=limvalsh) varset.add("fullscreen", value=fullscreen, text="Fullscreen") button = ParamSetterLauncher.make([varset], const_text, const_text, text_ok="Apply") def reac_func_norestart(event): if event.what == constants.LAUNCH_DONE: w, h = varset.get_value("screen_w"), varset.get_value("screen_h") mdm = MetaDataManager() mdm.read_data(fn) mdm.data["screen_w"] = w mdm.data["screen_h"] = h mdm.data["fullscreen"] = varset.get_value("fullscreen") ## print("writing", mdm.data, fn) mdm.write_data(fn) #restart script flags = functions.get_screen().get_flags() if varset.get_value("fullscreen"): flags |= pygame.FULLSCREEN else: flags = 0 pygame.display.set_mode((w, h), flags) functions.get_current_menu()._elements[0].get_oldest_ancester( ).unblit_and_reblit() button.launched.blit() button.launched.update() def reac_func_restart(event): if event.what == constants.LAUNCH_DONE: w, h = varset.get_value("screen_w"), varset.get_value("screen_h") mdm = MetaDataManager() mdm.read_data(fn) mdm.data["screen_w"] = w mdm.data["screen_h"] = h mdm.data["fullscreen"] = varset.get_value("fullscreen") ## print("writing", mdm.data, fn) mdm.write_data(fn) #restart script python = sys.executable os.execl(python, python, *sys.argv) reac_func = reac_func_restart if restart_app else reac_func_norestart reac = Reaction(constants.THORPY_EVENT, reac_func, { "id": constants.EVENT_UNLAUNCH, "launcher": button.launcher }) button.add_reaction(reac) return button
def __init__(self, name="", elements=None, normal_params=None, press_params=None, value="", size=(None, None), namestyle=None, varlink_func=None, quit_on_click=False, value_type=str, finish=True): """Element fo text insertion. <name>: text of the title before the inserter. <value>: initial text inside the inserter. <size>: if not (None,None), a 2-tuple specifying the size of the text insertion zone. <quit_on_click>: if True, make the inserter lose focus when mouse click outside its area. """ namestyle = style.STYLE_INSERTER_NAME if namestyle is None else namestyle if size[0] is None: s0 = style.SIZE[0] else: s0 = size[0] if size[1] is None: s1 = style.Y_SMALL_SIZE else: s1 = size[1] size = (s0, s1) self.cursor = None super(Inserter, self).__init__("", elements, normal_params, press_params, finish=False) self._name_element = self._get_name_element(name, namestyle) self.add_elements([self._name_element]) self._iwriter = _InsertWriter(value) self.add_elements([self._iwriter]) self.quit_on_click = quit_on_click self._value_type = value_type painter = functions.obtain_valid_painter(painterstyle.INSERTER_PAINTER, color=style.DEF_COLOR2, pressed=True, size=(s0, s1)) self.set_painter(painter) self.normal_params.polite_set( "states hover", [constants.STATE_NORMAL, constants.STATE_PRESSED]) self.press_params.polite_set( "states hover", [constants.STATE_NORMAL, constants.STATE_PRESSED]) self._activated = False self._value = value self._inserted = self._value self._cursor_index = len(self._inserted) reac_keypress = Reaction(KEYDOWN, self._reaction_keydown, reac_name=constants.REAC_KEYPRESS) self.add_reaction(reac_keypress) self._keyer = Keyer() self._hide_mouse = self.normal_params.params.get("hide mouse", False) self._varlink_func = varlink_func self.repeat_delay = parameters.KEY_DELAY self.repeat_interval = parameters.KEY_INTERVAL self.deactivate_on_focus = [] self.auto_resize = True self.numeric_only = False self.int_only = False if finish: self.finish()
def __init__(self, path="./", ddl_size=None, normal_params=None, folders=True, files=True, file_types=None, text="", finish=True): """File and folder browser for a. <path>: the path of the folder in which browser browse files. <ddl_size>: if not None, force the size of the dropdown list of files. <folders>: if True, displays folders to user. <files>: if True, displays file to user. <file_types>: if not None, pass a list of files formats that you wand to be valid for user choice. <text>: title text of the browser. """ ddl_size = style.BROWSERLIGHT_DDL_SIZE if ddl_size is None else ddl_size super(BrowserLight, self).__init__(normal_params=normal_params, finish=False) self.path = self.set_path(path) self.last_done_path = str(self.path) self._ddl_size = ddl_size self.file_types = file_types self.folders = folders self.files = files # DropDownListFast actual_folders, actual_files = self._get_folders_and_files() actual_files = self._filter_files(actual_files) if not folders: actual_folders = None if not files: actual_files = [] self._ddlf = DropDownListFast(size=self._ddl_size, titles=actual_files, folders=actual_folders, has_lift=True, finish=False) ## self._ddlf.finish() # selection button inserter_width = 3 * ddl_size[0] // 4 ## if inserter_width > style.MAX_INSERTER_WIDTH: ## inserter_width = style.MAX_INSERTER_WIDTH self._selected = Inserter("Selected : ", size=(inserter_width, None)) if isinstance(text, str): self.text_element = OneLineText(text) else: self.text_element = text self._path_element = PathElement(father=self, abspath=True) self.add_elements([ self.text_element, self._path_element, self._ddlf, self._selected ]) reac_pressed = Reaction(parameters.BUTTON_UNPRESS_EVENT, self._reaction_press, {"button": 1}, reac_name=constants.REAC_PRESSED) ## self._ddlf._force_lift = True self._ddlf.finish() self.add_reaction(reac_pressed) self._clicked = None self._something_selected = False painter = functions.obtain_valid_painter(painterstyle.BOX_PAINTER, pressed=True, radius=style.BOX_RADIUS) self.set_painter(painter) self._last_click = -2 * parameters.DOUBLE_CLICK_DELAY if finish: self.finish()
def _set_unpress_reaction(self, type_, args=None): if not args: args = {} reac_unpress = Reaction(type_, self._reaction_unpress, args, reac_name=constants.REAC_UNPRESS) self.add_reaction(reac_unpress)