def __init__(self, stage, troubleshoot_cb, skip_cb): super(TroubleshootOrDisconnect, self).__init__(orientation=Gtk.Orientation.VERTICAL) self._stage = stage self.set_hexpand(False) self.set_vexpand(False) self.set_margin_left(40) self.set_margin_right(40) desc = Gtk.Label('Oops there was a problem connecting to internet.') desc.set_line_wrap(True) add_class(desc, 'console-screen-desc') img_path = self._stage.media_path("troubleshooting.png") image = Gtk.Image.new_from_file(img_path) troubleshoot = KanoButton('FIX IT') troubleshoot.connect('clicked', self._cb_wrapper, troubleshoot_cb) skip = KanoButton('SKIP', color="orange") skip.connect('clicked', self._cb_wrapper, skip_cb) buttons = Gtk.HBox(False, 0) buttons.pack_start(troubleshoot, True, True, 20) buttons.pack_start(skip, True, True, 0) self.pack_start(desc, False, False, 40) self.pack_start(image, False, False, 20) self.pack_start(buttons, False, False, 30)
def __init__(self, main_window=None): self._determine_screen_ratio() self._scale_factor = self._get_scale_factor() self._widgets = {} self._scheduled = [] self._main_window = None if main_window: self._main_window = main_window self._keys = {} main_window.set_key_events_handlers(self._key_press_cb_wrapper, self._key_release_cb_wrapper) self._overlay = Gtk.Overlay() self._background = Gtk.Image() self._background.set_halign(Gtk.Align.START) self._background.set_valign(Gtk.Align.START) self._overlay.add(self._background) self._last_motion = time.time() self._fixed = Gtk.Fixed() self._overlay.add_overlay(self._fixed) # True if the scene is shown on the screen self._active = False self._eb = Gtk.EventBox() self._eb.set_size_request(self._w, self._h) self._eb.add(self._overlay) add_class(self._eb, 'scene-backdrop')
def third_scroll(self): self._clear() heading = Gtk.Label('New quest') add_class(heading, 'scroll-heading') world = Gtk.Image.new_from_file(self._stage.media_path('world.png')) copy = [ "Journey to Kano World", ] text_widgets = self._get_text_widgets(copy) button = KanoButton('OK', color='orange') button.connect('clicked', cb_wrapper, self._stage._ctl.next_stage) heading.set_margin_top(35) self._vbox.pack_start(heading, False, False, 0) world.set_margin_top(35) self._vbox.pack_start(world, False, False, 0) text_widgets[0].set_margin_top(40) for w in text_widgets: self._vbox.pack_start(w, False, False, 0) button.set_margin_top(40) button.set_margin_left(80) button.set_margin_right(80) self._vbox.pack_start(button, False, False, 0) self.show_all()
def __init__(self, stage): super(Scroll, self).__init__() self._stage = stage self.add(Gtk.Image.new_from_file(stage.media_path('scroll.png'))) fixed = Gtk.Fixed() self.add_overlay(fixed) self._eb = Gtk.EventBox() add_class(self._eb, 'scroll-content-area') self._eb.set_size_request(450, 487) fixed.put(self._eb, 100, 95) vbox = Gtk.VBox(False, 0) vbox.set_vexpand(True) vbox.set_hexpand(True) vbox.set_margin_left(10) vbox.set_margin_right(10) self._vbox = vbox self._eb.add(self._vbox) self.first_scroll()
def __init__(self, stage, try_again_cb, skip_cb): super(AreYouSure, self).__init__(orientation=Gtk.Orientation.VERTICAL) self._stage = stage self.set_hexpand(False) self.set_vexpand(False) self.set_margin_left(40) self.set_margin_right(40) heading = Gtk.Label('Are You Sure?') heading.set_margin_top(20) add_class(heading, 'console-screen-heading') desc = Gtk.Label("Kano uses WiFi to stay up to date" + "\nwith all new software updates, apps" + "\nand features.") desc.set_justify(Gtk.Justification.CENTER) desc.set_line_wrap(True) add_class(desc, 'console-screen-desc') try_again = KanoButton('TRY AGAIN') try_again.connect('clicked', self._cb_wrapper, try_again_cb) skip = KanoButton('YES I WANT TO SKIP', color="grey") skip.connect('clicked', self._cb_wrapper, skip_cb, 'init-flow-wifi-skipped') buttons = Gtk.HBox(False, 0) buttons.pack_start(try_again, True, True, 20) buttons.pack_start(skip, True, True, 0) self.pack_start(heading, False, False, 30) self.pack_start(desc, False, False, 40) self.pack_start(buttons, False, False, 40)
def _get_text_widgets(self, lines): widgets = [] for line in lines: label = Gtk.Label(line) label.set_line_wrap(False) label.set_justify(Gtk.Justification.LEFT) add_class(label, 'scroll-text') label.set_margin_bottom(8) widgets.append(label) return widgets
def __init__(self, stage, overscan_ctl, next_cb): super(Window2, self).__init__() add_class(self, 'overscan-window') head_img = Gtk.Image.new_from_file(stage.media_path('hint2.png')) box = Gtk.VBox() self.add(box) box.pack_start(head_img, False, False, 0) heading = Gtk.Label('Use UP and DOWN keys') heading.set_margin_top(25) heading.set_margin_bottom(25) add_class(heading, 'notebook-heading') box.pack_start(heading, False, False, 0) label_copy = 'Stretch or shrink your screen, until the white lines' text1 = Gtk.Label(label_copy) text1.set_margin_bottom(5) add_class(text1, 'notebook-text') box.pack_start(text1, False, False, 0) text2 = Gtk.Label('are lined up with the edges') text2.set_margin_bottom(25) add_class(text2, 'notebook-text') box.pack_start(text2, False, False, 0) buttons = Gtk.HBox(halign=Gtk.Align.CENTER) buttons.set_margin_bottom(25) done = KanoButton('DONE', color='green') buttons.pack_start(done, False, False, 0) done.connect('clicked', cb_wrapper, next_cb) box.pack_start(buttons, False, False, 0)
def __init__(self, stage, bg_path, bg_x_align, bg_y_align, text, text_margin, back_cb, fwd_cb): super(SlideScreen, self).__init__() self._stage = stage bg = Gtk.Image.new_from_file(bg_path) align = Gtk.Alignment.new(bg_x_align, bg_y_align, 0, 0) align.add(bg) self.add(align) back = Gtk.Button() back_arr = stage.media_path('navigation-arrow-left.png') back.add(Gtk.Image.new_from_file(back_arr)) back.set_halign(Gtk.Align.CENTER) back.set_valign(Gtk.Align.CENTER) back.set_margin_left(25) back.connect('clicked', self._cb_wrapper, back_cb) attach_cursor_events(back) fwd = Gtk.Button() fwd_arr = stage.media_path('navigation-arrow-right.png') fwd.add(Gtk.Image.new_from_file(fwd_arr)) fwd.set_halign(Gtk.Align.CENTER) fwd.set_valign(Gtk.Align.CENTER) fwd.set_margin_right(25) fwd.connect('clicked', self._cb_wrapper, fwd_cb) attach_cursor_events(fwd) help_text = Gtk.Label(text) add_class(help_text, 'console-screen-help-text') help_text.set_line_wrap(True) help_text.set_justify(Gtk.Justification.CENTER) help_text.set_valign(Gtk.Align.CENTER) help_text.set_halign(Gtk.Align.CENTER) help_text.set_margin_left(20) help_text.set_margin_right(20) help_text.set_margin_top(text_margin) hbox = Gtk.HBox(False, 0) hbox.pack_start(back, False, False, 0) hbox.pack_start(help_text, True, False, 0) hbox.pack_start(fwd, False, False, 0) self.add_overlay(hbox)
def __init__(self, stage, yes_cb, no_cb): super(Window1, self).__init__() add_class(self, 'overscan-window') head_img = Gtk.Image.new_from_file(stage.media_path('hint1.png')) box = Gtk.VBox() self.add(box) box.pack_start(head_img, False, False, 0) heading = Gtk.Label('Let\'s set up your screen') heading.set_margin_top(25) heading.set_margin_bottom(25) add_class(heading, 'notebook-heading') box.pack_start(heading, False, False, 0) heading = Gtk.Label('Are the white lines touching the edges?') heading.set_margin_bottom(35) add_class(heading, 'notebook-text') box.pack_start(heading, False, False, 0) buttons = Gtk.HBox(halign=Gtk.Align.CENTER) buttons.set_margin_bottom(25) yes = KanoButton('YES', color='green') yes.connect('clicked', cb_wrapper, yes_cb) buttons.pack_start(yes, False, False, 0) no = KanoButton('NO', color='red') no.connect('clicked', cb_wrapper, no_cb) buttons.pack_start(no, False, False, 10) box.pack_start(buttons, False, False, 0)
def __init__(self, stage, now_cb, later_cb): super(ParentalScreen, self).__init__(False, 0) self.set_hexpand(False) self.set_vexpand(False) self.set_margin_left(40) self.set_margin_right(40) heading = Gtk.Label('For parents...') add_class(heading, 'console-screen-heading') copy = 'You can put a safety filter on Kano\'s internet. ' + \ 'You can set it now or later.' desc = Gtk.Label(copy) desc.set_line_wrap(True) add_class(desc, 'console-screen-desc') padlock = Gtk.Image.new_from_file(stage.media_path('padlock.png')) later = KanoButton('GOT IT') later.connect('clicked', self._cb_wrapper, later_cb, 'init-flow-parental-skipped') later.set_size_request(200, 50) now = OrangeButton('SET NOW') now.connect('clicked', self._cb_wrapper, now_cb, 'init-flow-parental-set') emptylabel = Gtk.Label(" ") buttons = Gtk.ButtonBox() buttons.set_layout(Gtk.ButtonBoxStyle.SPREAD) buttons.pack_start(emptylabel, True, True, 0) buttons.pack_start(later, True, True, 20) buttons.pack_start(now, True, True, 20) self.pack_start(heading, False, False, 30) self.pack_start(desc, False, False, 20) self.pack_start(padlock, False, False, 10) self.pack_start(buttons, True, True, 30)
def __init__(self, stage, connected_cb, disconnected_cb): super(WifiConsole, self).__init__() self._stage = stage self._connected_cb = connected_cb self._disconnected_cb = disconnected_cb console_img_path = self._stage.media_path('console-large.png') bg = Gtk.Image.new_from_file(console_img_path) fixed = Gtk.Fixed() self._eb = Gtk.EventBox() add_class(self._eb, 'console-content-area') self._eb.set_size_request(719, 543) self.add(bg) self.add_overlay(fixed) fixed.put(self._eb, 146, 157) self._eb.set_border_width(10) self.parental_question_screen()
def __init__(self, stage, image_path, image_scale, image_align, title, copy, buttons): super(Notebook, self).__init__() self.add( Gtk.Image.new_from_file(stage.media_path('lonely-notebook.png'))) fixed = Gtk.Fixed() self.add_overlay(fixed) self._eb = Gtk.EventBox() add_class(self._eb, 'notebook-content-area') self._eb.set_size_request(415, 460) fixed.put(self._eb, 20, 70) vbox = Gtk.VBox(False, 0) vbox.set_vexpand(True) vbox.set_hexpand(True) vbox.set_margin_left(10) vbox.set_margin_right(10) img = scale_image(Gtk.Image.new_from_file(image_path), image_scale) img_align = Gtk.Alignment.new(image_align, 0.5, 0, 0) img_align.add(img) img_align.set_vexpand(True) img_align.set_hexpand(True) vbox.pack_start(img_align, False, False, 0) heading = Gtk.Label(title) add_class(heading, 'notebook-heading') copy_widgets = [] for line in copy: l = Gtk.Label(line) l.set_line_wrap(False) l.set_justify(Gtk.Justification.CENTER) add_class(l, 'notebook-text') l.set_halign(Gtk.Align.CENTER) copy_widgets.append(l) # Pack heading vbox.pack_start(heading, False, False, 0) heading.set_margin_top(15) heading.set_margin_bottom(15) for w in copy_widgets: vbox.pack_start(w, False, False, 3) hbox = Gtk.HBox(False, 10) hbox.set_margin_top(15) hbox.set_halign(Gtk.Align.CENTER) for b in buttons: button = KanoButton(b['label'], color=b['color']) button.connect('clicked', cb_wrapper, b['callback']) hbox.pack_start(button, False, False, 0) vbox.pack_start(hbox, False, False, 0) self._eb.add(vbox)
def __init__(self, stage, image_path, image_scale, image_align, title, copy, buttons): super(Notebook, self).__init__() self.add(Gtk.Image.new_from_file(stage.media_path('lonely-notebook.png'))) fixed = Gtk.Fixed() self.add_overlay(fixed) self._eb = Gtk.EventBox() add_class(self._eb, 'notebook-content-area') self._eb.set_size_request(415, 460) fixed.put(self._eb, 20, 70) vbox = Gtk.VBox(False, 0) vbox.set_vexpand(True) vbox.set_hexpand(True) vbox.set_margin_left(10) vbox.set_margin_right(10) img = scale_image(Gtk.Image.new_from_file(image_path), image_scale) img_align = Gtk.Alignment.new(image_align, 0.5, 0, 0) img_align.add(img) img_align.set_vexpand(True) img_align.set_hexpand(True) vbox.pack_start(img_align, False, False, 0) heading = Gtk.Label(title) add_class(heading, 'notebook-heading') copy_widgets = [] for line in copy: l = Gtk.Label(line) l.set_line_wrap(False) l.set_justify(Gtk.Justification.CENTER) add_class(l, 'notebook-text') l.set_halign(Gtk.Align.CENTER) copy_widgets.append(l) # Pack heading vbox.pack_start(heading, False, False, 0) heading.set_margin_top(15) heading.set_margin_bottom(15) for w in copy_widgets: vbox.pack_start(w, False, False, 3) hbox = Gtk.HBox(False, 10) hbox.set_margin_top(15) hbox.set_halign(Gtk.Align.CENTER) for b in buttons: button = KanoButton(b['label'], color=b['color']) button.connect('clicked', cb_wrapper, b['callback']) hbox.pack_start(button, False, False, 0) vbox.pack_start(hbox, False, False, 0) self._eb.add(vbox)
def __init__(self, stage, scene, yes_cb, no_cb): super(ConsoleScreen, self).__init__() self.set_size_request(368*scene.scale_factor, 179*scene.scale_factor) add_class(self, 'console-screen') if scene.scale_factor > 0.8: add_class(self, 'font-large') else: add_class(self, 'font-small') vbox = Gtk.VBox(False, 0) vbox.set_halign(Gtk.Align.CENTER) # vbox.set_valign(Gtk.Align.CENTER) question = Gtk.Label('Can you see the lights?') question.set_line_wrap(True) question.set_justify(Gtk.Justification.CENTER) question.set_valign(Gtk.Align.CENTER) add_class(question, 'console-screen-question') vbox.pack_start(question, True, False, 0) hbox = Gtk.HBox(False, 20) hbox.set_halign(Gtk.Align.CENTER) hbox.set_valign(Gtk.Align.CENTER) yes = KanoButton('YES') yes.connect('clicked', cb_wrapper, yes_cb) no = KanoButton('NO', color='red') no.connect('clicked', cb_wrapper, no_cb) hbox.pack_start(yes, False, False, 0) hbox.pack_start(no, False, False, 0) vbox.pack_start(hbox, True, False, 0) self.add(vbox)
def _setup_fourth_scene(self): scene = Scene(self._ctl.main_window) scene.set_background(self._wallpapers['4-3'], self._wallpapers['16-9']) # Pass the callback of what we want to launch in the profile icon self._add_profile_icon(scene) self._add_world_icon(scene, offline=(not is_registered())) self._add_taskbar(scene) # Go through all the desktop icons and add them to the desktop # Either go through all files in a folder with a specific pattern, or # just list them in an array # All icons are in /usr/share/icons/Kano/88x88/apps # or /usr/share/kano-desktop/icons parent_dir = "/usr/share/kano-desktop/icons" parent_dir_2 = "/usr/share/icons/Kano/88x88/apps" self._apps_next_button_shown = False # Order the icons needed icon_info = [ ("snake", os.path.join(parent_dir, "snake.png")), ("pong", os.path.join(parent_dir, "pong.png")), ("minecraft", os.path.join(parent_dir, "make-minecraft.png")), ("music", os.path.join(parent_dir, "sonicpi.png")), ("internet", os.path.join(parent_dir, "internet-desktop.png")), ("apps", os.path.join(parent_dir, "apps.png")), ("home", os.path.join(parent_dir, "kano-homefolder.png")), ("art", os.path.join(parent_dir_2, "kano-draw.png")), ("terminal-quest", os.path.join(parent_dir_2, "linux-story.png")), ("make-light", os.path.join(parent_dir, "make-light.png")), ("scratch", os.path.join(parent_dir, "scratch.png")), ("video", os.path.join(parent_dir_2, "video.png")) #("plus", os.path.join(parent_dir, "plus-icon.png")) ] self._desktop_icons = { "snake": { "text": "Customize your own Snake game,\n" + "and share special gameboards.", "position": [0, 340], "source_align": 0.1 }, "pong": { "text": "You can make this classic game yourself,\n" + "with new rules, cheats, and powers.", "position": [0, 340], "source_align": 0.42 }, "minecraft": { "text": "Normal people play Minecraft.\n" + "On Kano, you can hack the game with code.", "position": [95, 340], "source_align": 0.5 }, "terminal-quest": { "text": "The Terminal talks to the computer's\n" + "brain directly. Use its powers to go on a quest.", "position": [0, 210], "source_align": 0.37 }, "make-light": { "text": "Learn about LEDs and turn code\n" + "into light with Make Light.", "position": [167, 210], "source_align": 0.5 }, "music": { "text": "You can make sounds, beats, loops,\n" + "and songs on Kano.", "position": [290, 340], "source_align": 0.5 }, "art": { "text": "Ever drawn or painted?\n" + "You can create incredible artworks with code.", "position": [0, 210], "source_align": 0.07 }, "internet": { "text": "You can browse the web.", "position": [490, 360], "source_align": 0.5 }, "scratch": { "text": "You can play with code blocks.", "position": [315, 220], "source_align": 0.5 }, "home": { "text": "Look at your files and folders here.", "position": [550, 360], "source_align": 1.0 }, "apps": { "text": "Find even more apps here.", "position": [620, 360], "source_align": 0.5 }, "video": { "text": "YouTube", "position": [570, 220], "source_align": 0.5 } } fixed = Gtk.Fixed() fixed.set_size_request(1024, 720) scene.add_widget(fixed, Placement(0.5, 1.0, 0), Placement(0.5, 1.0, 0), name="icon_grid_fixed") icon_grid = Gtk.Grid() icon_grid.set_row_spacing(35) icon_grid.set_column_spacing(35) row = 1 column = 0 # Add the persistent click on everything label label = Gtk.Label('Click on each of the app icons') add_class(label, 'desktop-label') fixed.put(label, 350, 325) for info in icon_info: (name, f) = info icon = Gtk.Button() self._desktop_icons[name]['icon'] = Gtk.Image.new_from_file(f) icon.set_image(self._desktop_icons[name]['icon']) icon.connect('enter-notify-event', self._desktop_icon_enter_cb) icon.connect('leave-notify-event', self._desktop_icon_leave_cb) icon.set_opacity(self.DESKTOP_ICON_OPACITY) attach_cursor_events(icon) icon.connect("clicked", self._change_apps_speechbubble_text, name, scene) icon_grid.attach(icon, column, row, 1, 1) column += 1 if column >= 7: column = 0 row -= 1 fixed.put(icon_grid, 40, 380) # Pack the speechbubble into a fixed so it the same distance from # apps for all resolutions. speechbubble_fixed = Gtk.Fixed() speechbubble_fixed.set_size_request(1024, 720) speechbubble_fixed.put( SpeechBubble(text='These are your Apps!\n' + 'You can make games, songs,\n' + 'artworks and more,\n' + 'then share them to World.', source=SpeechBubble.BOTTOM), 300, 100) scene.add_widget(speechbubble_fixed, Placement(0.5, 1), Placement(0.5, 1), name="app_speechbubble") return scene
def add_widget(self, widget, p43, p169, clicked_cb=None, key=None, name=None, modal=False): placement = p43 if self._screen_ratio == self.RATIO_4_3 else p169 final_scale = placement.scale * self._scale_factor if final_scale != 1 and placement.scale != 0: if widget.__class__.__name__ == 'Image': if widget.get_animation(): widget = scale_gif(widget, final_scale) else: widget = scale_image(widget, final_scale) elif issubclass(widget.__class__, ActiveImage): widget.scale(final_scale) else: if placement.scale != 1.0: raise RuntimeError('Can\'t scale regular widgets!') if issubclass(widget.__class__, ActiveImage): root_widget = widget.get_widget() else: root_widget = widget if clicked_cb: # ActiveImage already comes in a button wrapper if not issubclass(widget.__class__, ActiveImage): button_wrapper = Gtk.Button() button_wrapper.add(root_widget) root_widget = button_wrapper attach_cursor_events(root_widget) if isinstance(clicked_cb, (list, tuple)): root_widget.connect('clicked', self._clicked_cb_wrapper, clicked_cb[0], *clicked_cb[1:]) else: root_widget.connect('clicked', self._clicked_cb_wrapper, clicked_cb) if key is not None: if not hasattr(self, '_keys'): msg = 'Scene must be initialised with main_window to ' + \ 'be able to receive key events.' raise RuntimeError(msg) cbs = {'action': clicked_cb} if issubclass(widget.__class__, ActiveImage): cbs['down'] = widget.down cbs['up'] = widget.up self._keys[key] = cbs align = Gtk.Alignment.new(placement.x, placement.y, 0, 0) align.add(root_widget) align.set_size_request(self._w, self._h) wrapper = align if modal: wrapper = Gtk.EventBox() add_class(wrapper, 'modal') wrapper.add(align) wrapper.show_all() self._fixed.put(wrapper, 0, 0) if name is not None: self._widgets[name] = wrapper
def __init__(self, stage, next_cb): super(Notebook, self).__init__() self.add(Gtk.Image.new_from_file(stage.media_path('notebook.png'))) fixed = Gtk.Fixed() self.add_overlay(fixed) self._eb = Gtk.EventBox() add_class(self._eb, 'notebook-content-area') self._eb.set_size_request(425, 570) fixed.put(self._eb, 200, 90) vbox = Gtk.VBox(False, 0) vbox.set_vexpand(True) vbox.set_hexpand(True) vbox.set_margin_left(10) vbox.set_margin_right(10) heading = Gtk.Label('Screen machine') add_class(heading, 'heading') add_class(heading, 'notebook-heading') body_lines = [ "Use the up and down arrows on the", "keyboard to adjust the picture until the", "screen pushing machine lines up with the", "edges of your TV." ] body_widgets = [] for line in body_lines: body = Gtk.Label(line) body.set_line_wrap(False) body.set_justify(Gtk.Justification.LEFT) add_class(body, 'notebook-text') body.set_halign(Gtk.Align.START) body_widgets.append(body) # TODO: info legend_data = [ {'icon': 'up-icon.png', 'desc': 'on your keyboard to increase'}, {'icon': 'down-icon.png', 'desc': 'on your keyboard to decrease'}, {'icon': 'ok-icon.png', 'desc': 'click the button to confirm'} ] legend_widgets = [] for l in legend_data: legend = Gtk.HBox(False, 0) icon = Gtk.Image.new_from_file(stage.media_path(l['icon'])) desc = Gtk.Label(l['desc']) add_class(desc, 'notebook-text') legend.pack_start(icon, False, False, 0) legend.pack_start(desc, False, False, 10) legend_widgets.append(legend) button = KanoButton('GO') button.connect('clicked', cb_wrapper, next_cb) # Pack heading vbox.pack_start(heading, False, False, 10) heading.set_margin_bottom(20) for w in body_widgets: vbox.pack_start(w, False, False, 8) legend_widgets[0].set_margin_top(30) for w in legend_widgets: vbox.pack_start(w, False, False, 10) button.set_margin_top(30) vbox.pack_start(button, False, False, 0) self._eb.add(vbox)