Beispiel #1
0
    def build(self):

        self._current_lang = None
        self.current_lang_ulubione_file = None
        self.current_lang_dict = None
        self.current_lang_ulubione = None

        sm = ScreenManager()

        # Ustawienie tła
        with sm.canvas:
            Color(1, 1, 1)
            rect = Rectangle(source="img/tlo.png", size=Window.size)

        # Skalowanie obrazka przy zmianie wymiarów okna (orientacji telefonu)
        def resize_action(size, pos):
            sm.size = Window.size
            rect.size = Window.size

        sm.bind(pos=resize_action, size=resize_action)

        # Aplikacje którymi zarządzamy
        sm.add_widget(MenuScreen(name='menu'))
        sm.add_widget(LearnScreen(name='game'))
        sm.add_widget(MemoryScreen(name='memory'))
        sm.add_widget(SettingsScreen(name='settings'))

        return sm
Beispiel #2
0
class MainApp(App):
    show_add_bottle_popup = BooleanProperty(False)
    scanned_upc = StringProperty("")
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.bottle_adder = BottleAdder()
        self.bind(scanned_upc=self.add_new_bottle)
    
    def build(self):
        self.sm = ScreenManager()
        self.sm.add_widget(StartScreen())
        self.sm.add_widget(LiquorScreen())
        self.sm.add_widget(MixingScreen())
        self.sm.add_widget(DrinkSelectScreen())
        def set_canvas(inst, value):
            with self.sm.canvas.before:
                from kivy.graphics import Color, Rectangle
                from scorpion.ui.textures import radial_gradient
                Color(1, 1, 1)
                Rectangle(texture=radial_gradient(), size=value)
        self.sm.bind(size=set_canvas)
        return self.sm
    
    def set_screen(self, screen_name):
        self.sm.current = screen_name
    def get_screen(self, screen = None):
        if screen is None:
            return self.sm.current_screen
        else:
            return self.sm.get_screen(screen)
    
    def add_new_bottle(self, inst, value):
        if value == "" and inst != None: return
        self.bottle_adder.open(value)
        self.scanned_upc = ""
Beispiel #3
0
 def add_scrim(self, instance_manager: ScreenManager) -> None:
     with instance_manager.canvas.after:
         self._scrim_color = Color(rgba=[0, 0, 0, 0])
         self._scrim_rectangle = Rectangle(pos=instance_manager.pos,
                                           size=instance_manager.size)
         instance_manager.bind(
             pos=self.update_scrim_rectangle,
             size=self.update_scrim_rectangle,
         )
Beispiel #4
0
class SmoothieHost(App):
    is_connected = BooleanProperty(False)
    status = StringProperty("Not Connected")
    wpos = ListProperty([0, 0, 0])
    mpos = ListProperty([0, 0, 0, 0, 0, 0])
    fr = NumericProperty(0)
    frr = NumericProperty(0)
    fro = NumericProperty(100)
    sr = NumericProperty(0)
    lp = NumericProperty(0)
    is_inch = BooleanProperty(False)
    is_spindle_on = BooleanProperty(False)
    is_abs = BooleanProperty(True)
    is_desktop = NumericProperty(0)
    is_cnc = BooleanProperty(False)
    tab_top = BooleanProperty(False)
    main_window = ObjectProperty()
    gcode_file = StringProperty()
    is_show_camera = BooleanProperty(False)
    is_spindle_camera = BooleanProperty(False)
    manual_tool_change = BooleanProperty(False)
    is_v2 = BooleanProperty(True)
    wait_on_m0 = BooleanProperty(False)

    # Factory.register('Comms', cls=Comms)
    def __init__(self, **kwargs):
        super(SmoothieHost, self).__init__(**kwargs)
        if len(sys.argv) > 1:
            # override com port
            self.use_com_port = sys.argv[1]
        else:
            self.use_com_port = None
        self.webserver = False
        self._blanked = False
        self.blank_timeout = 0
        self.last_touch_time = 0
        self.camera_url = None
        self.loaded_modules = []
        self.secs = 0
        self.fast_stream = False
        self.last_probe = {'X': 0, 'Y': 0, 'Z': 0, 'status': False}
        self.tool_scripts = ToolScripts()
        self.desktop_changed = False

    def build_config(self, config):
        config.setdefaults(
            'General', {
                'last_gcode_path': os.path.expanduser("~"),
                'last_print_file': '',
                'serial_port': 'serial:///dev/ttyACM0',
                'report_rate': '1.0',
                'blank_timeout': '0',
                'manual_tool_change': 'false',
                'wait_on_m0': 'false',
                'fast_stream': 'false',
                'v2': 'false',
                'is_spindle_camera': 'false'
            })
        config.setdefaults(
            'UI', {
                'display_type': "RPI Touch",
                'cnc': 'false',
                'tab_top': 'false',
                'screen_size': 'auto',
                'screen_pos': 'auto',
                'filechooser': 'default'
            })

        config.setdefaults(
            'Extruder', {
                'last_bed_temp': '60',
                'last_hotend_temp': '185',
                'length': '20',
                'speed': '300',
                'hotend_presets': '185 (PLA), 230 (ABS)',
                'bed_presets': '60 (PLA), 110 (ABS)'
            })
        config.setdefaults('Jog', {'xy_feedrate': '3000'})
        config.setdefaults(
            'Web', {
                'webserver': 'false',
                'show_video': 'false',
                'camera_url': 'http://localhost:8080/?action=snapshot'
            })

    def build_settings(self, settings):
        jsondata = """
            [
                { "type": "title",
                  "title": "UI Settings" },

                { "type": "options",
                  "title": "Desktop Layout",
                  "desc": "Select Display layout, RPI is for 7in touch screen layout",
                  "section": "UI",
                  "key": "display_type",
                  "options": ["RPI Touch", "Small Desktop", "Large Desktop", "Wide Desktop", "RPI Full Screen"]
                },

                { "type": "bool",
                  "title": "CNC layout",
                  "desc": "Turn on for a CNC layout, otherwise it is a 3D printer Layout",
                  "section": "UI",
                  "key": "cnc"
                },

                { "type": "bool",
                  "title": "Tabs on top",
                  "desc": "TABS are on top of the screen",
                  "section": "UI",
                  "key": "tab_top"
                },

                { "type": "options",
                  "title": "File Chooser",
                  "desc": "Which filechooser to use in desktop mode",
                  "section": "UI",
                  "key": "filechooser",
                  "options": ["default", "wx", "zenity", "kdialog"]
                },

                { "type": "title",
                  "title": "General Settings" },

                { "type": "numeric",
                  "title": "Report rate",
                  "desc": "Rate in seconds to query for status from Smoothie",
                  "section": "General",
                  "key": "report_rate" },

                { "type": "numeric",
                  "title": "Blank Timeout",
                  "desc": "Inactive timeout in seconds before screen will blank",
                  "section": "General",
                  "key": "blank_timeout" },

                { "type": "bool",
                  "title": "Manual Tool change",
                  "desc": "On M6 let user do a manual tool change",
                  "section": "General",
                  "key": "manual_tool_change"
                },

                { "type": "bool",
                  "title": "Wait on M0",
                  "desc": "On M0 popup a dialog and pause until it is dismissed",
                  "section": "General",
                  "key": "wait_on_m0"
                },

                { "type": "bool",
                  "title": "Spindle Camera",
                  "desc": "Enable the spindle camera screen",
                  "section": "General",
                  "key": "is_spindle_camera"
                },

                { "type": "bool",
                  "title": "Version 2 Smoothie",
                  "desc": "Select for version 2 smoothie",
                  "section": "General",
                  "key": "v2"
                },

                { "type": "bool",
                  "title": "Fast Stream",
                  "desc": "Allow fast stream for laser over network",
                  "section": "General",
                  "key": "fast_stream"
                },

                { "type": "title",
                  "title": "Web Settings" },

                { "type": "bool",
                  "title": "Web Server",
                  "desc": "Turn on Web server to remotely check progress",
                  "section": "Web",
                  "key": "webserver"
                },

                { "type": "bool",
                  "title": "Show Video",
                  "desc": "Display mjpeg video in web progress",
                  "section": "Web",
                  "key": "show_video"
                },

                { "type": "string",
                  "title": "Camera URL",
                  "desc": "URL for camera stream",
                  "section": "Web",
                  "key": "camera_url"
                },

                { "type": "title",
                  "title": "Extruder Settings" },

                { "type": "string",
                  "title": "Hotend Presets",
                  "desc": "Set the comma separated presets for the hotend temps",
                  "section": "Extruder",
                  "key": "hotend_presets"
                },

                { "type": "string",
                  "title": "Bed Presets",
                  "desc": "Set the comma separated presets for the bed temps",
                  "section": "Extruder",
                  "key": "bed_presets"
                }
            ]


        """
        settings.add_json_panel('SmooPie application',
                                self.config,
                                data=jsondata)

    def on_config_change(self, config, section, key, value):
        # print("config changed: {} - {}: {}".format(section, key, value))
        token = (section, key)
        if token == ('UI', 'cnc'):
            self.is_cnc = value == "1"
        elif token == ('UI', 'display_type'):
            self.desktop_changed = True
            self.main_window.display("NOTICE: Restart is needed")
        elif token == ('UI', 'tab_top'):
            self.tab_top = value == "1"
        elif token == ('Extruder', 'hotend_presets'):
            self.main_window.ids.extruder.ids.set_hotend_temp.values = value.split(
                ',')
        elif token == ('Extruder', 'bed_presets'):
            self.main_window.ids.extruder.ids.set_bed_temp.values = value.split(
                ',')
        elif token == ('General', 'blank_timeout'):
            self.blank_timeout = float(value)
        elif token == ('General', 'manual_tool_change'):
            self.manual_tool_change = value == '1'
        elif token == ('General', 'wait_on_m0'):
            self.wait_on_m0 = value == '1'
        elif token == ('General', 'v2'):
            self.is_v2 = value == '1'
        elif token == ('Web', 'camera_url'):
            self.camera_url = value
        else:
            self.main_window.display("NOTICE: Restart is needed")

    def on_stop(self):
        # The Kivy event loop is about to stop, stop the async main loop
        self.comms.stop()  # stop the aysnc loop
        if self.is_webserver:
            self.webserver.stop()
        if self.blank_timeout > 0:
            # unblank if blanked
            self.unblank_screen()
        # stop any loaded modules
        for m in self.loaded_modules:
            m.stop()

    def on_start(self):
        # in case we added something to the defaults, make sure they are written to the ini file
        self.config.update_config('smoothiehost.ini')

    def window_request_close(self, win):
        if self.desktop_changed:
            # if the desktop changed we reset the window size and pos
            self.config.set('UI', 'screen_size', 'auto')
            self.config.set('UI', 'screen_pos', 'auto')
            self.config.write()

        elif self.is_desktop == 2 or self.is_desktop == 3:
            # Window.size is automatically adjusted for density, must divide by density when saving size
            self.config.set(
                'UI', 'screen_size',
                "{}x{}".format(int(Window.size[0] / Metrics.density),
                               int(Window.size[1] / Metrics.density)))
            self.config.set('UI', 'screen_pos',
                            "{},{}".format(Window.top, Window.left))
            Logger.info(
                'close: Window.size: {}, Window.top: {}, Window.left: {}'.
                format(Window.size, Window.top, Window.left))

            self.config.write()

        return False

    def build(self):
        lt = self.config.get('UI', 'display_type')
        dtlut = {
            "RPI Touch": 0,
            "Small Desktop": 1,
            "Large Desktop": 2,
            "Wide Desktop": 3,
            "RPI Full Screen": 4
        }

        self.is_desktop = dtlut.get(lt, 0)

        # load the layouts for the desktop screen
        if self.is_desktop == 1:
            Builder.load_file('desktop.kv')
            Window.size = (1024, 768)

        elif self.is_desktop == 2 or self.is_desktop == 3 or self.is_desktop == 4:
            Builder.load_file('desktop_large.kv' if self.is_desktop ==
                              2 else 'desktop_wide.kv')
            if self.is_desktop != 4:
                # because rpi_egl does not like to be told the size
                s = self.config.get('UI', 'screen_size')
                if s == 'auto':
                    Window.size = (1280,
                                   1024) if self.is_desktop == 2 else (1280,
                                                                       800)
                elif 'x' in s:
                    (w, h) = s.split('x')
                    Window.size = (int(w), int(h))
                p = self.config.get('UI', 'screen_pos')
                if p != 'auto' and ',' in p:
                    (t, l) = p.split(',')
                    Window.top = int(t)
                    Window.left = int(l)
            Window.bind(on_request_close=self.window_request_close)

        else:
            self.is_desktop = 0
            # load the layouts for rpi 7" touch screen
            Builder.load_file('rpi.kv')

        self.is_cnc = self.config.getboolean('UI', 'cnc')
        self.tab_top = self.config.getboolean('UI', 'tab_top')
        self.is_webserver = self.config.getboolean('Web', 'webserver')
        self.is_show_camera = self.config.getboolean('Web', 'show_video')
        self.is_spindle_camera = self.config.getboolean(
            'General', 'is_spindle_camera')
        self.manual_tool_change = self.config.getboolean(
            'General', 'manual_tool_change')
        self.wait_on_m0 = self.config.getboolean('General', 'wait_on_m0')
        self.is_v2 = self.config.getboolean('General', 'v2')

        self.comms = Comms(App.get_running_app(),
                           self.config.getfloat('General', 'report_rate'))
        self.gcode_file = self.config.get('General', 'last_print_file')
        self.sm = ScreenManager()
        ms = MainScreen(name='main')
        self.main_window = ms.ids.main_window
        self.sm.add_widget(ms)
        self.sm.add_widget(GcodeViewerScreen(name='viewer', comms=self.comms))
        self.config_editor = ConfigEditor(name='config_editor')
        self.sm.add_widget(self.config_editor)
        self.gcode_help = GcodeHelp(name='gcode_help')
        self.sm.add_widget(self.gcode_help)
        if self.is_desktop == 0:
            self.text_editor = TextEditor(name='text_editor')
            self.sm.add_widget(self.text_editor)

        self.blank_timeout = self.config.getint('General', 'blank_timeout')
        Logger.info("SmoothieHost: screen blank set for {} seconds".format(
            self.blank_timeout))

        self.sm.bind(on_touch_down=self._on_touch)
        Clock.schedule_interval(self._every_second, 1)

        # select the file chooser to use
        # select which one we want from config
        filechooser = self.config.get('UI', 'filechooser')
        if self.is_desktop > 0:
            if filechooser != 'default':
                NativeFileChooser.type_name = filechooser
                Factory.register('filechooser', cls=NativeFileChooser)
                try:
                    f = Factory.filechooser()
                except Exception:
                    Logger.error(
                        "SmoothieHost: can't use selected file chooser: {}".
                        format(filechooser))
                    Factory.unregister('filechooser')
                    Factory.register('filechooser', cls=FileDialog)

            else:
                # use Kivy filechooser
                Factory.register('filechooser', cls=FileDialog)

            # we want to capture arrow keys
            Window.bind(on_key_down=self._on_keyboard_down)
        else:
            # use Kivy filechooser
            Factory.register('filechooser', cls=FileDialog)

        # setup for cnc or 3d printer
        if self.is_cnc:
            if self.is_desktop < 3:
                # remove Extruder panel from tabpanel and tab
                self.main_window.ids.tabs.remove_widget(
                    self.main_window.ids.tabs.extruder_tab)

        # if not CNC mode then do not show the ZABC buttons in jogrose
        if not self.is_cnc:
            self.main_window.ids.tabs.jog_rose.jogrosemain.remove_widget(
                self.main_window.ids.tabs.jog_rose.abc_panel)

        if self.is_webserver:
            self.webserver = ProgressServer()
            self.webserver.start(self, 8000)

        if self.is_show_camera:
            self.camera_url = self.config.get('Web', 'camera_url')
            self.sm.add_widget(CameraScreen(name='web cam'))
            self.main_window.tools_menu.add_widget(
                ActionButton(text='Web Cam',
                             on_press=lambda x: self._show_web_cam()))

        if self.is_spindle_camera:
            if self.is_desktop in [0, 4]:
                try:
                    self.sm.add_widget(SpindleCamera(name='spindle camera'))
                except Exception as err:
                    self.main_window.display(
                        'ERROR: failed to load spindle camera. Check logs')
                    Logger.error(
                        'Main: spindle camera exception: {}'.format(err))

            self.main_window.tools_menu.add_widget(
                ActionButton(text='Spindle Cam',
                             on_press=lambda x: self._show_spindle_cam()))

        # load any modules specified in config
        self._load_modules()

        if self.blank_timeout > 0:
            # unblank if blanked
            self.unblank_screen()

        return self.sm

    def _show_spindle_cam(self):
        if self.is_desktop in [0, 4]:
            self.sm.current = "spindle camera"
        else:
            # we run it as a separate program so it is in its own window
            subprocess.Popen(['python3', 'spindle_camera.py'],
                             stdout=subprocess.DEVNULL,
                             stderr=subprocess.DEVNULL)

    def _show_web_cam(self):
        self.sm.current = "web cam"

    def _on_keyboard_down(self, instance, key, scancode, codepoint, modifiers):
        # print("key: {}, scancode: {}, codepoint: {}, modifiers: {}".format(key, scancode, codepoint, modifiers))
        # control uses finer move, shift uses coarse move
        v = 0.1
        if len(modifiers) == 1:
            if modifiers[0] == 'ctrl':
                v = 0.01
            elif modifiers[0] == 'shift':
                v = 1

        choices = {
            273: "Y{}".format(v),
            275: "X{}".format(v),
            274: "Y{}".format(-v),
            276: "X{}".format(-v),
            280: "Z{}".format(v),
            281: "Z{}".format(-v)
        }

        s = choices.get(key, None)
        if s is not None:
            self.comms.write('$J {}\n'.format(s))
            return True

        # handle command history if in desktop mode
        if self.is_desktop > 0:
            if v == 0.01:  # it is a control key
                if codepoint == 'p':
                    # get previous history by finding all the recently sent commands
                    history = [
                        x['text'] for x in self.main_window.ids.log_window.data
                        if x['text'].startswith('<< ')
                    ]
                    if history:
                        last = history.pop()
                        self.main_window.ids.entry.text = last[3:]
                elif codepoint == 'n':
                    # get next history
                    pass
                elif codepoint == 'c':
                    # clear console
                    self.main_window.ids.log_window.data = []

        return False

    def command_input(self, s):
        if s.startswith('!'):
            # shell command send to unix shell
            self.main_window.display('> {}'.format(s))
            try:
                p = subprocess.Popen(s[1:],
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     shell=True,
                                     universal_newlines=True)
                result, err = p.communicate()
                for l in result.splitlines():
                    self.main_window.display(l)
                for l in err.splitlines():
                    self.main_window.display(l)
                if p.returncode != 0:
                    self.main_window.display('returncode: {}'.format(
                        p.returncode))
            except Exception as err:
                self.main_window.display('> command exception: {}'.format(err))

        elif s == '?':
            self.gcode_help.populate()
            self.sm.current = 'gcode_help'

        else:
            self.main_window.display('<< {}'.format(s))
            self.comms.write('{}\n'.format(s))

    # when we hit enter it refocuses the the input
    def _refocus_text_input(self, *args):
        Clock.schedule_once(self._refocus_it)

    def _refocus_it(self, *args):
        self.main_window.ids.entry.focus = True

    def _load_modules(self):
        if not self.config.has_section('modules'):
            return

        try:
            for key in self.config['modules']:
                Logger.info("load_modules: loading module {}".format(key))
                mod = importlib.import_module('modules.{}'.format(key))
                if mod.start(self.config['modules'][key]):
                    Logger.info("load_modules: loaded module {}".format(key))
                    self.loaded_modules.append(mod)
                else:
                    Logger.info(
                        "load_modules: module {} failed to start".format(key))

        except Exception:
            Logger.warn("load_modules: exception: {}".format(
                traceback.format_exc()))

    def _every_second(self, dt):
        ''' called every second '''

        self.secs += 1
        if self.blank_timeout > 0 and not self.main_window.is_printing:
            self.last_touch_time += 1
            if self.last_touch_time >= self.blank_timeout:
                self.last_touch_time = 0
                self.blank_screen()

    def blank_screen(self):
        try:
            with open('/sys/class/backlight/rpi_backlight/bl_power', 'w') as f:
                f.write('1\n')
            self._blanked = True
        except Exception:
            Logger.warning("SmoothieHost: unable to blank screen")

    def unblank_screen(self):
        try:
            with open('/sys/class/backlight/rpi_backlight/bl_power', 'w') as f:
                f.write('0\n')
        except Exception:
            pass

    def _on_touch(self, a, b):
        self.last_touch_time = 0
        if self._blanked:
            self._blanked = False
            self.unblank_screen()
            return True

        return False
Beispiel #5
0
class Main(App):
    # These are to handle Android switching away from the app or locking the screen.
    # I don't want to do anything on pause, but I do want to go back to the main screen if it was paused for a while.
    def on_pause(self):
        kivy.logger.Logger.debug('Main: pausing')
        self.pause_time = time.time()
        return True
    def on_resume(self):
        kivy.logger.Logger.debug('Main: resuming')
        if time.time()-self.pause_time > 5:
            self.screen_manager.current = 'chooser'

    # This disables kivy's settings panel, normally accessible by pressing F1
    def open_settings(self, *args):
        pass

    ## "Navbar" button functions
    def pressed_win(self, *args):
        if 'btn_functions' in dir(self.screen_manager.current_screen) and self.screen_manager.current_screen.btn_functions[0] != None:
            self.screen_manager.current_screen.btn_functions[0]()
        return False # I'm returning false here so that the button still triggers the next on_release event
    def pressed_home(self, *args):
        if 'btn_functions' in dir(self.screen_manager.current_screen) and self.screen_manager.current_screen.btn_functions[1] != None:
            self.screen_manager.current_screen.btn_functions[1]()
        return False # I'm returning false here so that the button still triggers the next on_release event
    def pressed_back(self, *args):
        if 'btn_functions' in dir(self.screen_manager.current_screen) and self.screen_manager.current_screen.btn_functions[2] != None:
            self.screen_manager.current_screen.btn_functions[2]()
        return False # I'm returning false here so that the button still triggers the next on_release event
    def update_buttons(self, *args):
        if 'btns' in dir(self.screen_manager.current_screen):
            win, home, back = self.screen_manager.current_screen.btns
            if win == None:
                self.win_btn.opacity = 0
            else:
                self.win_btn.opacity = 1
                self.win_btn.background_normal = win
                self.win_btn.background_down = self.win_btn.background_normal
            if home == None:
                self.home_btn.opacity = 0
            else:
                self.home_btn.opacity = 1
                self.home_btn.background_normal = home
                self.home_btn.background_down = self.home_btn.background_normal
            if back == None:
                self.back_btn.opacity = 0
            else:
                self.back_btn.opacity = 1
                self.back_btn.background_normal = back
                self.back_btn.background_down = self.back_btn.background_normal


    ## These functions should probably be put somewhat inside the painter widget.
    def finish_paint(self, good = True):
        self.paint_screen.image.label.text = ''
        if good:
            self.goto_screen('photostrip', 'right')
    def save_painter(self):
        savedir = self.paint_screen.image.source+'.overlays'
        try:
            filesystem.listdir(savedir)
        except:
            if not filesystem.is_dir(savedir):
                filesystem.mkdir(savedir)
        index = 0
        filename = '%02d.png'
        try:
            dircontents = os.listdir(savedir)
        except: # Probably using the HTTP filesystem.
            tmpused = True
            filepath = tempfile.mktemp() + '.png'
        else:
            tmpused = False
            while filename % index in dircontents:
                index += 1
            filepath = filesystem.join(savedir, filename % index)
        if self.paint_screen.painter.save_png(filepath) and (not tmpused or filesystem.savefile(savedir, 'png', filepath)): # If saving the file works and either the tmpfile was not used ot the second stage of saving works.
            self.paint_screen.painter.do_drawing = False # Stop drawing on the image until the canvas gets cleared (by switching screen)
            self.paint_screen.image.label.color = (0,0.75,0,1)
            self.paint_screen.image.label.text = 'Saved'
            Clock.schedule_once(lambda arg: self.finish_paint(True), 2)
        else:
            self.paint_screen.image.label.color = (0.75,0,0,1)
            self.paint_screen.image.label.text = 'FAILED to save the drawing, sorry.'
            Clock.schedule_once(lambda arg: self.finish_paint(False), 3)

    def goto_screen(self, screen_name, direction):
        self.screen_manager.transition.direction = direction
        self.screen_manager.current = screen_name
    # This function is just to keep the screen_manager size with window resizing
    def update_size(self, root, value):
        self.screen_manager.size = (root.width-192, root.height)

    def build(self):
        root = FloatLayout()

        ## Screen Manager
        self.screen_manager = ScreenManager(transition=SlideTransition(),size_hint=[None,None], pos_hint={'left': 1})
        root.bind(size=self.update_size)
        root.add_widget(self.screen_manager)

        ## "Navbar" Buttons
        ## These are meant to work like the Android navbar would, and I have named them as such.
        # These two functions are used for a indicator for the button being pressed.
        def rend_circle(btn):
            with btn.canvas:
                Color(1,1,1,0.25)
                size = (btn.size[0], btn.size[1]*1.5)
                btn.hl = Ellipse(pos=( btn.pos[0]+((btn.size[0]/2)-(size[0]/2)), btn.pos[1]+((btn.size[1]/2)-(size[1]/2)) ), size=size)
                Color(1,1,1,1) # Reset the color, otherwise the background goes dark
        def derend_circle(btn):
            btn.canvas.remove(btn.hl)
        self.win_btn = Button(text='', size_hint=[None,None],size=[192,192],height=192,pos_hint={'right': 1, 'center_y': 0.8})
        self.win_btn.bind(on_press=rend_circle)
        self.win_btn.bind(on_release=derend_circle)
        self.win_btn.bind(on_release=self.pressed_win)

        self.home_btn = Button(text='', size_hint=[None,None],size=[192,192],pos_hint={'right': 1, 'center_y': 0.5})
        self.home_btn.bind(on_press=rend_circle)
        self.home_btn.bind(on_release=derend_circle)
        self.home_btn.bind(on_release=self.pressed_home)

        self.back_btn = Button(text='', size_hint=[None,None],size=[192,192],pos_hint={'right': 1, 'center_y': 0.2})
        self.back_btn.bind(on_press=rend_circle)
        self.back_btn.bind(on_release=derend_circle)
        self.back_btn.bind(on_release=self.pressed_back)

        root.add_widget(self.win_btn)
        root.add_widget(self.home_btn)
        root.add_widget(self.back_btn)

        # Render the background
        def update_rect(instance, value):
            instance.bg.pos = instance.pos
            instance.bg.size = instance.size
        self.screen_manager.bind(size=update_rect,pos=update_rect)
        with self.screen_manager.canvas.before:
            self.screen_manager.bg = Rectangle(source='background.png')

        Loader.loading_image = 'loading.png'
        ## FileChooser
        chooser_screen = Screen(name='chooser')
        chooser = FileChooserGalleryView(rootpath=PHOTOS_PATH)
        chooser.file_system = filesystem
        def select_folder(chooser, photostrip):
            photostrip.set_path(chooser.current_entry.path)
            self.goto_screen('photostrip', 'left')
        chooser.bind(on_select_folder=lambda args:select_folder(chooser, photostrip))
        chooser_screen.add_widget(chooser)

        ## Painter
        self.paint_screen = PaintScreen(name='painter')
        self.paint_screen.bind(on_leave=lambda src: self.paint_screen.painter.clear())

        ## ImageViewer
        viewer_screen = ViewerScreen(name='viewer')
        viewer_screen.bind(on_enter=lambda src:setattr(self.paint_screen.image,'source',viewer_screen.image.source))

        ## Photo strip
        def foo(a):
            print type(a), a
        photostrip_screen = Screen(name='photostrip')
        photostrip = PhotoStrip()
        photostrip_screen.add_widget(photostrip)
        photostrip.bind(
                on_press=lambda src,fn:viewer_screen.set_image(fn),
                on_release=lambda src,fn: self.goto_screen('painter', 'left'),
        )

        # Set up the icons and functions for the navbar buttons
        chooser_screen.btns             = [None,                                       'ic_action_refresh.png',      None]
        chooser_screen.btn_functions    = [None,                                       chooser._trigger_update,      None]

        photostrip_screen.btns          = [None,                                       None,                         'ic_sysbar_back.png']
        photostrip_screen.btn_functions = [None,                                       None,                         lambda:self.goto_screen('chooser', 'right')]

        viewer_screen.btns              = ['ic_action_edit.png',                       None,                         'ic_sysbar_back.png']
        viewer_screen.btn_functions     = [lambda:self.goto_screen('painter', 'left'), viewer_screen.drawing_toggle, lambda:self.goto_screen('photostrip', 'right')]

        self.paint_screen.btns          = ['ic_action_save.png',                       None,                         'ic_action_discard.png']
        self.paint_screen.btn_functions = [self.save_painter,                          None,                         lambda:self.goto_screen('photostrip', 'right')]

        # Finally, add the screens to the manager
        self.screen_manager.add_widget(chooser_screen)
        self.screen_manager.add_widget(photostrip_screen)
        self.screen_manager.add_widget(viewer_screen)
        self.screen_manager.add_widget(self.paint_screen)

        # Set the navbar buttons from the variables set above
        self.screen_manager.transition.bind(on_complete=self.update_buttons)
        self.update_buttons()

        return root
Beispiel #6
0
class KivyBabelComic(App):
    def __init__(self, **kwargs):
        super(KivyBabelComic,self).__init__(**kwargs)
    def build(self):
        self.sm = ScreenManager()
        self.sm.add_widget(KivyVisor())
        self.sm.bind(on_touch_down=self.on_touch_down)
        return self.sm


    def on_touch_down(self, obj, event):
        '''
        vamos a capturar eventos en estas zonas
        *************************
        *                       *
        *                       *
        *                       *
        *                       *
        * *                   * *
        *3*                   *4*
        * *                   * *
        *                       *
        *                       *
        *                       *
        *1*       *2*         *3*
        * *       * *         * *
        *************************
        :param widget:
        :param event:
        :return:
        '''

        if obj != self.sm: return
        #zona1 = ((0, Window.width * 0.1), (Window.height * 0.1 + Window.height * 0.5,Window.height * -0.1 + Window.height * 0.5 ))

        zona2 = ((Window.width * 0.5 - Window.width * 0.1, Window.width * 0.5 + Window.width * 0.1),
                 (0, Window.height * 0.1))
        #zona3 = ((Window.width - Window.width * 0.1, Window.width), (Window.height * 0.1 + Window.height * 0.5 , Window.height * -0.1 + Window.height * 0.5))


        if (zona2[0][0]< event.pos[0] and event.pos[0] < zona2[0][1]) and (zona2[1][0]<event.pos[1] and event.pos[1]<zona2[1][1]):
            box = GridLayout(cols=5)
            botonAncho = Button(text="nada")
            botonAncho.bind(on_press=self.nada)
            box.add_widget(botonAncho)
            botonCentrado = Button(text="nada")
            botonCentrado.bind(on_press=self.nada)
            box.add_widget(botonCentrado)
            botonSalir = Button(text="salir")
            botonSalir.bind(on_press=self.salir)
            box.add_widget(botonSalir)


            p = Popup(title='Test popup',  size_hint=(None, None), size=(400, 150))
            p.add_widget(box)

            p.open()
    def nada(self,  event):
        print("Falta implementar")

    def salir(self, event):
        self.stop()
Beispiel #7
0
class CivMapScreen(BoxLayout):
    def __init__(self, **kwargs):
        super(CivMapScreen, self).__init__(**kwargs)
        self.pos = (0, 0)
        self.nations = []
        self.ms = MapScatter(pos_hint={'x': 0, 'y': 0})
        self.add_widget(self.ms)
        self.im = Image(source='civ_board.png',
                        allow_stretch=True,
                        keep_ratio=False,
                        opacity=1.0)
        self.ms.add_widget(self.im)
        self.fl = FloatLayout(size=self.im.size, pos_hint={'x': 0, 'y': 0})
        self.ms.bind(size=self.fl.setter('size'))
        self.im.add_widget(self.fl)
        self.bind(size=self.im.setter('size'))

        self.sm = ScreenManager(pos_hint={
            'x': 1660 / 4058.0,
            'y': 3 / 2910.0
        },
                                size_hint=((3367 - 1660) / 4058.0,
                                           (2907 - 2105) / 2910.0))
        self.fl.add_widget(self.sm)

        self.st = StockPanel(pos_hint={'x': 0, 'y': 0}, size_hint=(1, 1))
        self.st.ccc_btn.bind(on_press=self.change_screen)
        self.sm.bind(size=self.st.lab.setter('size'))
        screen = Screen(name="Stock and Treasury",
                        pos_hint={
                            'x': 0,
                            'y': 0
                        },
                        size_hint=(1, 1))
        screen.add_widget(self.st)
        self.sm.add_widget(screen)

        self.ccc = CivCardCreditsPanel(pos_hint={
            'x': 0,
            'y': 0
        },
                                       size_hint=(1, 1))
        self.ccc.st_btn.bind(on_press=self.change_screen)
        screen = Screen(name='Civ Card Credits',
                        pos_hint={
                            'x': 0,
                            'y': 0
                        },
                        size_hint=(1, 1))
        screen.add_widget(self.ccc)
        self.sm.add_widget(screen)

    def change_screen(self, instance, *args):
        if instance == self.st.ccc_btn:
            self.sm.current = 'Civ Card Credits'
        elif instance == self.ccc.st_btn:
            self.sm.current = 'Stock and Treasury'
        for obj in [self, self.sm, self.st, self.st.lab]:
            print(obj, obj.pos, obj.pos_hint, obj.size, obj.size_hint)

    def add_spotter(self, spotter):
        print(f'Adding {spotter} to {self.fl}')
        self.fl.add_widget(spotter)
Beispiel #8
0
class Main(App):
    # These are to handle Android switching away from the app or locking the screen.
    # I don't want to do anything on pause, but I do want to go back to the main screen if it was paused for a while.
    def on_pause(self):
        kivy.logger.Logger.debug('Main: pausing')
        self.pause_time = time.time()
        return True

    def on_resume(self):
        kivy.logger.Logger.debug('Main: resuming')
        if time.time() - self.pause_time > 5:
            self.screen_manager.current = 'chooser'

    # This disables kivy's settings panel, normally accessible by pressing F1
    def open_settings(self, *args):
        pass

    ## "Navbar" button functions
    def pressed_win(self, *args):
        if 'btn_functions' in dir(
                self.screen_manager.current_screen
        ) and self.screen_manager.current_screen.btn_functions[0] != None:
            self.screen_manager.current_screen.btn_functions[0]()
        return False  # I'm returning false here so that the button still triggers the next on_release event

    def pressed_home(self, *args):
        if 'btn_functions' in dir(
                self.screen_manager.current_screen
        ) and self.screen_manager.current_screen.btn_functions[1] != None:
            self.screen_manager.current_screen.btn_functions[1]()
        return False  # I'm returning false here so that the button still triggers the next on_release event

    def pressed_back(self, *args):
        if 'btn_functions' in dir(
                self.screen_manager.current_screen
        ) and self.screen_manager.current_screen.btn_functions[2] != None:
            self.screen_manager.current_screen.btn_functions[2]()
        return False  # I'm returning false here so that the button still triggers the next on_release event

    def update_buttons(self, *args):
        if 'btns' in dir(self.screen_manager.current_screen):
            win, home, back = self.screen_manager.current_screen.btns
            if win == None:
                self.win_btn.opacity = 0
            else:
                self.win_btn.opacity = 1
                self.win_btn.background_normal = win
                self.win_btn.background_down = self.win_btn.background_normal
            if home == None:
                self.home_btn.opacity = 0
            else:
                self.home_btn.opacity = 1
                self.home_btn.background_normal = home
                self.home_btn.background_down = self.home_btn.background_normal
            if back == None:
                self.back_btn.opacity = 0
            else:
                self.back_btn.opacity = 1
                self.back_btn.background_normal = back
                self.back_btn.background_down = self.back_btn.background_normal

    ## These functions should probably be put somewhat inside the painter widget.
    def finish_paint(self, good=True):
        self.paint_screen.image.label.text = ''
        if good:
            self.goto_screen('photostrip', 'right')

    def save_painter(self):
        savedir = self.paint_screen.image.source + '.overlays'
        try:
            filesystem.listdir(savedir)
        except:
            if not filesystem.is_dir(savedir):
                filesystem.mkdir(savedir)
        index = 0
        filename = '%02d.png'
        try:
            dircontents = os.listdir(savedir)
        except:  # Probably using the HTTP filesystem.
            tmpused = True
            filepath = tempfile.mktemp() + '.png'
        else:
            tmpused = False
            while filename % index in dircontents:
                index += 1
            filepath = filesystem.join(savedir, filename % index)
        if self.paint_screen.painter.save_png(filepath) and (
                not tmpused or filesystem.savefile(savedir, 'png', filepath)
        ):  # If saving the file works and either the tmpfile was not used ot the second stage of saving works.
            self.paint_screen.painter.do_drawing = False  # Stop drawing on the image until the canvas gets cleared (by switching screen)
            self.paint_screen.image.label.color = (0, 0.75, 0, 1)
            self.paint_screen.image.label.text = 'Saved'
            Clock.schedule_once(lambda arg: self.finish_paint(True), 2)
        else:
            self.paint_screen.image.label.color = (0.75, 0, 0, 1)
            self.paint_screen.image.label.text = 'FAILED to save the drawing, sorry.'
            Clock.schedule_once(lambda arg: self.finish_paint(False), 3)

    def goto_screen(self, screen_name, direction):
        self.screen_manager.transition.direction = direction
        self.screen_manager.current = screen_name

    # This function is just to keep the screen_manager size with window resizing
    def update_size(self, root, value):
        self.screen_manager.size = (root.width - 192, root.height)

    def build(self):
        root = FloatLayout()

        ## Screen Manager
        self.screen_manager = ScreenManager(transition=SlideTransition(),
                                            size_hint=[None, None],
                                            pos_hint={'left': 1})
        root.bind(size=self.update_size)
        root.add_widget(self.screen_manager)

        ## "Navbar" Buttons
        ## These are meant to work like the Android navbar would, and I have named them as such.
        # These two functions are used for a indicator for the button being pressed.
        def rend_circle(btn):
            with btn.canvas:
                Color(1, 1, 1, 0.25)
                size = (btn.size[0], btn.size[1] * 1.5)
                btn.hl = Ellipse(
                    pos=(btn.pos[0] + ((btn.size[0] / 2) - (size[0] / 2)),
                         btn.pos[1] + ((btn.size[1] / 2) - (size[1] / 2))),
                    size=size)
                Color(1, 1, 1,
                      1)  # Reset the color, otherwise the background goes dark

        def derend_circle(btn):
            btn.canvas.remove(btn.hl)

        self.win_btn = Button(text='',
                              size_hint=[None, None],
                              size=[192, 192],
                              height=192,
                              pos_hint={
                                  'right': 1,
                                  'center_y': 0.8
                              })
        self.win_btn.bind(on_press=rend_circle)
        self.win_btn.bind(on_release=derend_circle)
        self.win_btn.bind(on_release=self.pressed_win)

        self.home_btn = Button(text='',
                               size_hint=[None, None],
                               size=[192, 192],
                               pos_hint={
                                   'right': 1,
                                   'center_y': 0.5
                               })
        self.home_btn.bind(on_press=rend_circle)
        self.home_btn.bind(on_release=derend_circle)
        self.home_btn.bind(on_release=self.pressed_home)

        self.back_btn = Button(text='',
                               size_hint=[None, None],
                               size=[192, 192],
                               pos_hint={
                                   'right': 1,
                                   'center_y': 0.2
                               })
        self.back_btn.bind(on_press=rend_circle)
        self.back_btn.bind(on_release=derend_circle)
        self.back_btn.bind(on_release=self.pressed_back)

        root.add_widget(self.win_btn)
        root.add_widget(self.home_btn)
        root.add_widget(self.back_btn)

        # Render the background
        def update_rect(instance, value):
            instance.bg.pos = instance.pos
            instance.bg.size = instance.size

        self.screen_manager.bind(size=update_rect, pos=update_rect)
        with self.screen_manager.canvas.before:
            self.screen_manager.bg = Rectangle(source='background.png')

        Loader.loading_image = 'loading.png'
        ## FileChooser
        chooser_screen = Screen(name='chooser')
        chooser = FileChooserGalleryView(rootpath=PHOTOS_PATH)
        chooser.file_system = filesystem

        def select_folder(chooser, photostrip):
            photostrip.set_path(chooser.current_entry.path)
            self.goto_screen('photostrip', 'left')

        chooser.bind(
            on_select_folder=lambda args: select_folder(chooser, photostrip))
        chooser_screen.add_widget(chooser)

        ## Painter
        self.paint_screen = PaintScreen(name='painter')
        self.paint_screen.bind(
            on_leave=lambda src: self.paint_screen.painter.clear())

        ## ImageViewer
        viewer_screen = ViewerScreen(name='viewer')
        viewer_screen.bind(on_enter=lambda src: setattr(
            self.paint_screen.image, 'source', viewer_screen.image.source))

        ## Photo strip
        def foo(a):
            print type(a), a

        photostrip_screen = Screen(name='photostrip')
        photostrip = PhotoStrip()
        photostrip_screen.add_widget(photostrip)
        photostrip.bind(
            on_press=lambda src, fn: viewer_screen.set_image(fn),
            on_release=lambda src, fn: self.goto_screen('painter', 'left'),
        )

        # Set up the icons and functions for the navbar buttons
        chooser_screen.btns = [None, 'ic_action_refresh.png', None]
        chooser_screen.btn_functions = [None, chooser._trigger_update, None]

        photostrip_screen.btns = [None, None, 'ic_sysbar_back.png']
        photostrip_screen.btn_functions = [
            None, None, lambda: self.goto_screen('chooser', 'right')
        ]

        viewer_screen.btns = ['ic_action_edit.png', None, 'ic_sysbar_back.png']
        viewer_screen.btn_functions = [
            lambda: self.goto_screen('painter', 'left'),
            viewer_screen.drawing_toggle,
            lambda: self.goto_screen('photostrip', 'right')
        ]

        self.paint_screen.btns = [
            'ic_action_save.png', None, 'ic_action_discard.png'
        ]
        self.paint_screen.btn_functions = [
            self.save_painter, None,
            lambda: self.goto_screen('photostrip', 'right')
        ]

        # Finally, add the screens to the manager
        self.screen_manager.add_widget(chooser_screen)
        self.screen_manager.add_widget(photostrip_screen)
        self.screen_manager.add_widget(viewer_screen)
        self.screen_manager.add_widget(self.paint_screen)

        # Set the navbar buttons from the variables set above
        self.screen_manager.transition.bind(on_complete=self.update_buttons)
        self.update_buttons()

        return root