From 800e3caabcd9c85b0b2ae9299217ea31d0309545 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Sun, 28 Oct 2007 09:45:28 +0000 Subject: Initial import --- (limited to 'gui') diff --git a/gui/__init__.py b/gui/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gui/__init__.py diff --git a/gui/canvaslistbox.py b/gui/canvaslistbox.py new file mode 100644 index 0000000..feb21c0 --- /dev/null +++ b/gui/canvaslistbox.py @@ -0,0 +1,67 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +import gtk +import hippo + +from sugar.graphics import style + +from gui import theme +from gui import page + + +# TODO- height seems bust +class CanvasListBox(hippo.CanvasWidget): + def __init__(self, width = 0, height = 0): + self._entries_div = hippo.CanvasBox() + + # props not set properly in constructor + self._entries_div.props.background_color=theme.COLOR_PAGE.get_int() + self._entries_div.props.spacing=style.DEFAULT_SPACING + self._entries_div.props.padding=10 + self._entries_div.props.orientation=hippo.ORIENTATION_VERTICAL + + # Munge it all up into something we can stick into a gtk.ScrolledWindow + canvas = hippo.Canvas() + canvas.set_root(self._entries_div) + canvas.show() + + hbox = gtk.HBox() + hbox.set_flags(gtk.HAS_FOCUS | gtk.CAN_FOCUS) + hbox.pack_start(canvas) + hbox.show() + + scroller = gtk.ScrolledWindow() + scroller.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + if width > 0 or height > 0: + scroller.set_size_request(width, height) # TODO -> Size according to _entries_div w/ a max_entries or somesuch ? + viewport = gtk.Viewport() + viewport.set_shadow_type(gtk.SHADOW_NONE) + viewport.add(hbox) + viewport.show() + scroller.add(viewport) + scroller.show() + + hippo.CanvasWidget.__init__(self, + widget=scroller, + padding=0, + spacing=0, + border=1, + border_color=theme.COLOR_DARK_GREEN.get_int()) + + + def append(self, entry): + self._entries_div.append(entry) + diff --git a/gui/frame.py b/gui/frame.py new file mode 100644 index 0000000..fcbd0de --- /dev/null +++ b/gui/frame.py @@ -0,0 +1,205 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +import gobject +import gtk +import hippo +import logging + +from i18n import LanguageComboBox +from gettext import gettext as _ + +from globals import Globals + +from util.decorators import Property +from gui import theme + +import pages.choose +import pages.edit + +from persistence.jokebook import Jokebook + +class Frame(hippo.Canvas): + + def __init__(self): + hippo.Canvas.__init__(self) + + # Root Frame ############################################################### + # Holds: Everything + self.__root = hippo.CanvasBox( + orientation=hippo.ORIENTATION_VERTICAL) + self.set_root(self.__root) + + # Application Header ####################################################### + # Holds: App logo, language box, lessons plan box + self.__header = self.__make_header() + self.__root.append(self.__header) + + # Page Container ########################################################### + # Holds: The currently open UI page + self.__container = hippo.CanvasBox( + border=theme.BORDER_WIDTH, + border_color=theme.COLOR_FRAME.get_int(), + background_color=theme.COLOR_BACKGROUND.get_int(), + spacing=4, + padding_top=20, + padding_left=40, + padding_right=40, + padding_bottom=20, + orientation=hippo.ORIENTATION_VERTICAL) + self.__root.append(self.__container, hippo.PACK_EXPAND) + + self.__page = hippo.CanvasBox( + box_height=theme.PAGE_HEIGHT, # TODO -> Pull width/height from theme - and make sure all + # children pull their sizes relative to this box + background_color=theme.COLOR_PAGE.get_int(), + border=4, + border_color=theme.COLOR_PAGE_BORDER.get_int(), + spacing=8, + padding=20, + xalign=hippo.ALIGNMENT_CENTER, + orientation=hippo.ORIENTATION_VERTICAL) + self.__container.append(self.__page) + + self.__page_class = None + + # Application Footer ####################################################### + # Holds: Task buttons + self.__footer = self.__make_footer() + self.__container.append(self.__footer) + + + + def __make_header(self): + ret = hippo.CanvasBox( + orientation=hippo.ORIENTATION_HORIZONTAL) + + # logo + logo = gtk.Image() + logo.set_from_file(Globals.logo) + ret.append(hippo.CanvasWidget(widget=logo)) + + # language selection box + language = hippo.CanvasWidget( + background_color=theme.COLOR_BACKGROUND.get_int(), + border_top=theme.BORDER_WIDTH, + border_left=theme.BORDER_WIDTH, + border_color=theme.COLOR_FRAME.get_int(), + padding_top=12, + padding_bottom=12, + padding_left=100, + padding_right=100, + yalign=hippo.ALIGNMENT_CENTER, + orientation=hippo.ORIENTATION_VERTICAL) + button = LanguageComboBox() + button.install() + language.props.widget = button + button.set_name('Fubar') + ret.append(language, hippo.PACK_EXPAND) + + # lesson plans + lesson_plans = hippo.CanvasWidget( + background_color=theme.COLOR_BACKGROUND.get_int(), + border_top=theme.BORDER_WIDTH, + border_left=theme.BORDER_WIDTH, + border_right=theme.BORDER_WIDTH, + border_color=theme.COLOR_FRAME.get_int(), + padding_top=12, + padding_bottom=12, + padding_left=30, + padding_right=30, + yalign=hippo.ALIGNMENT_CENTER, + orientation=hippo.ORIENTATION_VERTICAL) + button = gtk.Button(_('Lesson Plans')) + lesson_plans.props.widget = theme.theme_widget(button) + ret.append(lesson_plans, hippo.PACK_EXPAND) + + return ret + + + + def __make_footer(self): + ret = hippo.CanvasBox( + padding_right=8, + padding_top=8, + padding_bottom=0, + spacing=8, + orientation=hippo.ORIENTATION_HORIZONTAL) + button = gtk.Button(_('Read Jokebooks')) + button.connect('clicked', self.__do_clicked_read) + self.__button_read = hippo.CanvasWidget(widget=theme.theme_widget(button)) + ret.append(self.__button_read) + button = gtk.Button(_('Make Jokebook')) + button.connect('clicked', self.__do_clicked_make) + self.__button_make = hippo.CanvasWidget(widget=theme.theme_widget(button)) + ret.append(self.__button_make) + return ret + + + + @property + def page_class(self): + if self.__page_class is None: + # say, for e.g. we're connecting to another activity and we haven't set a + # default page yet + self.__page_class = pages.choose.Choose + return self.__page_class + + + @Property + def page(): + def get(self): return self.__page + def set(self, value): + self.__page_class = type(value) + self.__page.clear() + self.__page.append(value) + + # some rules for the buttons in the footer + if not Globals.JokeMachineActivity.is_initiator \ + and type(value) is pages.choose.Choose: + self.__button_read.set_visible(False) + self.__button_make.set_visible(False) + elif not Globals.JokeMachineActivity.is_initiator: + self.__button_read.set_visible(True) + self.__button_make.set_visible(False) + elif type(value) is pages.choose.Choose: + self.__button_read.set_visible(False) + self.__button_make.set_visible(True) + elif type(value) is pages.edit.Edit: + self.__button_read.set_visible(True) + self.__button_make.set_visible(False) + elif type(value) is pages.preview.Preview: + self.__button_read.set_visible(True) + self.__button_make.set_visible(False) + else: + self.__button_read.set_visible(True) + self.__button_make.set_visible(False) + + + + def __do_clicked_read(self, button): + Globals.JokeMachineActivity.set_page(pages.choose.Choose) + + + + def __do_clicked_make(self, button): + # create a new jokebook + jokebook = Jokebook() + jokebook.id = Globals.JokeMachineState.next_jokebook_id + logging.info('Created new jokebook with id: %d' % jokebook.id) + jokebook.owner = Globals.nickname + Globals.JokeMachineState.jokebooks.append(jokebook) + Globals.JokeMachineActivity.set_page(pages.edit.Edit, jokebook) + \ No newline at end of file diff --git a/gui/lessonplanwidget.py b/gui/lessonplanwidget.py new file mode 100644 index 0000000..b9a1a62 --- /dev/null +++ b/gui/lessonplanwidget.py @@ -0,0 +1,59 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +import locale +import gtk + +from abiword import Canvas as AbiCanvas + + +class LessonPlanWidget(gtk.Notebook): + + def __init__ (self, basepath): + """Create a Notebook widget for displaying lesson plans in tabs. + + basepath -- string, path of directory containing lesson plans. + """ + super(LessonPlanWidget, self).__init__() + lessons = filter(lambda x: os.path.isdir(os.path.join(basepath, 'lessons', x)), + os.listdir(os.path.join(basepath, 'lessons'))) + lessons.sort() + for lesson in lessons: + self._load_lesson(os.path.join(basepath, 'lessons', lesson), + _(lesson)) + + + def _load_lesson (self, path, name): + """Load the lesson content from a .abw, taking l10n into account. + + path -- string, path of lesson plan file, e.g. lessons/Introduction + lesson -- string, name of lesson + """ + code, encoding = locale.getdefaultlocale() + canvas = AbiCanvas() + canvas.show() + files = map(lambda x: os.path.join(path, '%s.abw' % x), + ('_'+code.lower(), '_'+code.split('_')[0].lower(), + 'default')) + files = filter(lambda x: os.path.exists(x), files) + # On jhbuild, the first works, on XO image 432 the second works: + try: + canvas.load_file('file://%s' % files[0], 'text/plain') + except: + canvas.load_file('file://%s' % files[0]) + canvas.view_online_layout() + canvas.zoom_width() + canvas.set_show_margin(False) + self.append_page(canvas, gtk.Label(name)) diff --git a/gui/page.py b/gui/page.py new file mode 100644 index 0000000..54dd596 --- /dev/null +++ b/gui/page.py @@ -0,0 +1,357 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +import os +import gtk +import cairo # for getting png for CanvasImage +import pango +import hippo +import logging +import StringIO + +from gettext import gettext as _ + +from sugar.graphics import style +from sugar.graphics.objectchooser import ObjectChooser + +# argh! +try: + from sugar.graphics.roundbox import RoundBox +except ImportError: + try: + from sugar.graphics.roundbox import CanvasRoundBox as RoundBox + except ImportError: + from sugar.graphics.canvasroundbox import CanvasRoundBox as RoundBox + + +from util.persistence import Persistent, PersistentProperty + +from util.audioplayer import AudioPlayer + + +from gui import theme +from globals import Globals + + +class Page(hippo.CanvasBox): + + def __init__(self, **kwargs): + hippo.CanvasBox.__init__(self, **kwargs) + + self.__alternate_color_listrows = False + self.__color_listrow = theme.COLOR_LIST_ROW_ALT.get_int() + + + def append(self, item, **kwargs): + hippo.CanvasBox.append(self, item, **kwargs) + + + @property + def color_listrow(self): + if not self.__alternate_color_listrows: + return theme.COLOR_LIST_ROW.get_int() + if self.__color_listrow == theme.COLOR_LIST_ROW_ALT.get_int(): + self.__color_listrow = theme.COLOR_LIST_ROW.get_int() + else: + self.__color_listrow = theme.COLOR_LIST_ROW_ALT.get_int() + return self.__color_listrow + + + def make_listrow(self, contents = None): + list_row = RoundBox() + list_row.props.border = 0 # properties not being set properly by constructor + list_row.props.padding = theme.DEFAULT_PADDING + list_row.props.padding_right=0 + list_row.props.background_color = self.color_listrow + if contents is not None: + list_row.append(contents) + return list_row + + + def make_audiobox(self, obj, property, width): + + image_file = os.path.join(Globals.pwd, theme.AUDIO_CHOOSE) + if not os.path.exists(image_file): + logging.debug('cannot find %s' % image_file) + return hippo.CanvasBox() + + surface = cairo.ImageSurface.create_from_png(image_file) + preview_sound = hippo.CanvasImage(image=surface, + xalign=hippo.ALIGNMENT_START, + yalign=hippo.ALIGNMENT_CENTER) + preview_sound.connect('button-press-event', self.__do_clicked_preview_sound, obj, property) + + if hasattr(obj, property) and getattr(obj, property) != None: + sound_name = getattr(obj, property) + else: + sound_name = _('Click to choose a sound') + + choose_sound = hippo.CanvasText(text=sound_name, + xalign=hippo.ALIGNMENT_START, + font_desc=theme.FONT_BODY.get_pango_desc()) + choose_sound.connect('button-press-event', self.__do_clicked_choose_sound, obj, property) + + sound_box = RoundBox() + sound_box.props.padding = 2 + sound_box.props.spacing = 10 + sound_box.props.box_width = width + sound_box.props.border=theme.BORDER_WIDTH_CONTROL / 2 + sound_box.props.border_color=theme.COLOR_DARK_GREEN.get_int() + sound_box.props.orientation=hippo.ORIENTATION_HORIZONTAL + sound_box.props.xalign=hippo.ALIGNMENT_START + sound_box.append(preview_sound) + sound_box.append(choose_sound) + + deglitch_box = hippo.CanvasBox(xalign=hippo.ALIGNMENT_START, box_width=width) + deglitch_box.append(sound_box) + return deglitch_box + + + def make_imagebox(self, obj, property = None, width=-1, height=-1, editable=True, padding=0): + image = self.__get_property_value(obj, property) + if image == '' or image == None: + image = theme.IMAGE_CHOOSE + file_name = os.path.join(Globals.pwd, image) + logging.debug('make_imagebox(%r)' % file_name) + + # TODO -> handle landscape/portrait properly + + # load image - could be cleaner on the whole... :) + try: + if hasattr(obj, 'image_blob') and getattr(obj, 'image_blob') is not None: + image_file = StringIO.StringIO(obj.image_blob) + surface = cairo.ImageSurface.create_from_png(image_file) + else: + surface = cairo.ImageSurface.create_from_png(file_name) + except Exception, e: + logging.error('Error while loading image: %r' % e) + + # set border + if editable: + border_width = 0 + else: + border_width = theme.BORDER_WIDTH_IMAGE + + # the image itself + cover_image = hippo.CanvasImage(image=surface, + border=border_width, + border_color=theme.COLOR_BLACK.get_int(), + xalign=hippo.ALIGNMENT_CENTER, + yalign=hippo.ALIGNMENT_CENTER, + scale_width=width, + scale_height=height) + if editable: + cover_image.set_clickable(True) + cover_image.connect('button-press-event', self.__do_clicked_image, obj, 'image_blob') + image_box = RoundBox() + image_box.props.padding = 0 + image_box.props.spacing = 0 + image_box.props.border=theme.BORDER_WIDTH_CONTROL + image_box.props.border_color=theme.COLOR_DARK_GREEN.get_int() + image_box.append(cover_image) + else: + image_box = cover_image + + # Grrr... RoundedBoxes and CanvasImages expand their width to their parent + # unless they're in a CanvasBox + deglitch_box = hippo.CanvasBox(xalign=hippo.ALIGNMENT_CENTER, padding=padding) + deglitch_box.append(image_box) + return deglitch_box + + + def make_bodytext(self, text, width=-1, xalign = hippo.ALIGNMENT_START, text_color = theme.COLOR_BLACK): + return hippo.CanvasText(text=text, + size_mode=hippo.CANVAS_SIZE_WRAP_WORD, + box_width=width, + xalign=xalign, + color=text_color.get_int(), + font_desc=theme.FONT_BODY.get_pango_desc()) + + + def make_textbox(self, obj, property, width=300, height=100, editable=True): + value = self.__get_property_value(obj, property) + textbox = self.__textview(value, width, height, editable, True) + textbox.control.get_buffer().connect('changed', self.__do_changed_control, obj, property) + return textbox + + + def make_field(self, label, label_width, obj, property, field_width, editable=True): + value = self.__get_property_value(obj, property) + field_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, + xalign=hippo.ALIGNMENT_START, + spacing=10) + field_box.append(hippo.CanvasText(text=label, + box_width=label_width, + xalign=hippo.ALIGNMENT_START, + color=theme.COLOR_DARK_GREEN.get_int(), + font_desc=theme.FONT_BODY.get_pango_desc())) + #if editable: + textfield = self.__textview(value, field_width, -1, editable, False) + textfield.control.get_buffer().connect('changed', self.__do_changed_control, obj, property) + field_box.append(textfield) + #else: # TODO - move to __textview() + #glitch_box = CanvasBox(box_width=field_width) + #glitch_box.append(hippo.CanvasText(text=value, + #size_mode=hippo.CANVAS_SIZE_WRAP_WORD, + #box_width=field_width, + #xalign=hippo.ALIGNMENT_START, + #font_desc=theme.FONT_BODY.get_pango_desc())) + #field_box.append(glitch_box) + return field_box + + + # Refactor into a CanvasTextView class + # TODO: Implement editable and multiline + # TODO: Lose multiline and change height variable to num_lines + def __textview(self, text, width=300, height=-1, editable=True, multiline=False): + textview = gtk.TextView() + textview.get_buffer().set_text(text) + + # control props + textview.set_wrap_mode(gtk.WRAP_WORD) + font = font_desc=theme.FONT_TEXTBOX.get_pango_desc() + font.set_weight(pango.WEIGHT_LIGHT) + textview.modify_font(font) + textview.modify_base(gtk.STATE_NORMAL, theme.COLOR_TEXTBOX.get_gdk_color()) + textview.set_editable(editable) + textview.set_cursor_visible(editable) + if height == -1: + context = textview.create_pango_context() + layout = pango.Layout(context) + layout.set_font_description(font) # TODO theme.FONT_BODY should be a pango.FontDescription, not a string + layout.set_text(text[ : text.find('\n')]) + (w, h) = layout.get_pixel_size() + height = h #+ theme.BORDER_WIDTH_CONTROL / 2 # fudge factor - on the XO-1 hardware all known solutions evaporate + textview.set_size_request(width, height) + textview.set_border_window_size(gtk.TEXT_WINDOW_LEFT, 0) + textview.set_border_window_size(gtk.TEXT_WINDOW_RIGHT, 0) + textview.set_border_window_size(gtk.TEXT_WINDOW_TOP, 0) + textview.set_border_window_size(gtk.TEXT_WINDOW_BOTTOM, 0) + textview.show() + + if editable: # because rounded corners are well... pretty + border_box = RoundBox() + border_box.control = textview + border_box.props.padding = 2 + border_box.props.spacing = 0 + border_box.props.border=theme.BORDER_WIDTH_CONTROL / 2 + border_box.props.border_color=theme.COLOR_DARK_GREEN.get_int() + border_box.props.background_color=theme.COLOR_TEXTBOX.get_int() + border_box.props.xalign=hippo.ALIGNMENT_START + #border_box.props.box_width = width + #border_box.props.box_height = height + + # TODO - File bug: RoundBox seriously messes with TextView's + # (and other things) width !! + deglitch_box = hippo.CanvasBox() + deglitch_box.append(hippo.CanvasWidget(widget=textview)) + border_box.append(deglitch_box) + return border_box + + no_edit_box = hippo.CanvasWidget(widget=textview) + no_edit_box.control = textview + return no_edit_box + + + def __get_property_value(self, obj, property): + # TODO - Clean entire Model/View mechanism up so that we're not + # passing objects and text properties around at all + if obj is None: + return '' + if type(obj) is str: + return obj + if hasattr(obj, '__metaclass__') and obj.__metaclass__ is Persistent and hasattr(obj, property): + value = getattr(obj, property) + if value is None: + return '' + return value + logging.debug('__get_property_value error: Unknown object type %r', type(obj)) + return obj + + + def __do_changed_control(self, control, obj, property): + '''Update object model with control values''' + if hasattr(obj, property) and hasattr(control.props, 'text'): + setattr(obj, property, control.props.text) + else: + print 'NO PROPERTY OR TEXT' + + + def __do_clicked_image(self, control, event, obj, property): + # Courtesy of Write.activity - toolbar.py + chooser = ObjectChooser(_('Choose image'), + Globals.JokeMachineActivity, #._parent, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + try: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT: + logging.debug('ObjectChooser: %r' % chooser.get_selected_object()) + journal_object = chooser.get_selected_object() + if hasattr(obj, 'image_blob') and journal_object and journal_object.file_path: + logging.debug('Getting journal object: %r, %s', journal_object, journal_object.file_path) + # Set the image now + f = open(journal_object.file_path, 'r') + raw = f.read() + f.close() + obj.image = str(journal_object.metadata['title']) + obj.image_blob = raw + # refresh the image + image_file = StringIO.StringIO(obj.image_blob) + surface = cairo.ImageSurface.create_from_png(image_file) + control.props.image = surface + finally: + chooser.hide() + chooser.destroy() + del chooser + + + def __do_clicked_choose_sound(self, control, event, obj, property): + logging.debug('choosing sound file') + chooser = ObjectChooser(_('Choose Sound'), + Globals.JokeMachineActivity, #._parent, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + try: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT: + logging.debug('ObjectChooser: %r' % chooser.get_selected_object()) + journal_object = chooser.get_selected_object() + if hasattr(obj, 'sound_blob') and journal_object and journal_object.file_path: + logging.debug('Getting journal object: %r, %s, %s', journal_object, journal_object.file_path, journal_object.metadata['title']) + # Set the sound now + f = open(journal_object.file_path, 'r') + raw = f.read() + f.close() + obj.sound = str(journal_object.metadata['title']) + obj.sound_blob = raw + control.props.text = obj.sound + finally: + chooser.hide() + chooser.destroy() + del chooser + + + def __do_clicked_preview_sound(self, control, event, obj, property): + + if not hasattr(obj, 'sound_blob') or getattr(obj, 'sound_blob') == None: + logging.debug('No sound to preview') + return + + player = AudioPlayer() + #player.uri = sound_file + player.raw = obj.sound_blob + player.play() + + + \ No newline at end of file diff --git a/gui/theme.py b/gui/theme.py new file mode 100644 index 0000000..9e3d393 --- /dev/null +++ b/gui/theme.py @@ -0,0 +1,159 @@ +import gtk + +from sugar.graphics import style + + +# This is all rather horrible - but it will keep us afloat while Sugar +# stabilizes + + +# colors ####################################################################### + +COLOR_LIGHT_GREEN = style.Color('#66CC00') +COLOR_DARK_GREEN = style.Color('#027F01') +COLOR_PINK = style.Color('#FF0198') +COLOR_YELLOW = style.Color('#FFFF00') +COLOR_GRAY = style.Color('#ACACAC') +COLOR_LIGHT_GRAY = style.Color('#E2E2E3') +COLOR_RED = style.Color('#FF0000') +COLOR_WHITE = style.Color('#FFFFFF') +COLOR_BLACK = style.Color('#000000') +COLOR_BLUE = style.Color('#0000FF') + +# deprecated colors from style.COLOR_* +COLOR_PANEL_GREY = style.Color('#C0C0C0') +COLOR_TOOLBAR_GREY = style.Color('#404040') +COLOR_TEXT_FIELD_GREY = style.Color('#E5E5E5') + + +COLOR_FG_BUTTONS = ( + (gtk.STATE_NORMAL, style.Color('#CCFF99')), + (gtk.STATE_ACTIVE, style.Color('#CCFF99')), + (gtk.STATE_PRELIGHT, style.Color('#CCFF99')), + (gtk.STATE_SELECTED, style.Color('#CCFF99')), + (gtk.STATE_INSENSITIVE, style.Color('#CCFF99')), +) +COLOR_BG_BUTTONS = ( + (gtk.STATE_NORMAL, style.Color('#027F01')), + (gtk.STATE_ACTIVE, style.Color('#014D01')), + (gtk.STATE_PRELIGHT, style.Color('#016D01')), + (gtk.STATE_SELECTED, style.Color('#027F01')), + (gtk.STATE_INSENSITIVE, style.Color('#027F01')), +) +COLOR_BG_RADIOBUTTONS = ( + (gtk.STATE_NORMAL, COLOR_LIGHT_GRAY), + (gtk.STATE_ACTIVE, COLOR_LIGHT_GRAY), + (gtk.STATE_PRELIGHT, COLOR_LIGHT_GRAY), + (gtk.STATE_SELECTED, COLOR_LIGHT_GRAY), + (gtk.STATE_INSENSITIVE, COLOR_LIGHT_GRAY), +) +COLOR_FG_RADIOBUTTONS = ( + (gtk.STATE_NORMAL, COLOR_DARK_GREEN), + (gtk.STATE_ACTIVE, COLOR_DARK_GREEN), + (gtk.STATE_PRELIGHT, COLOR_DARK_GREEN), + (gtk.STATE_SELECTED, COLOR_DARK_GREEN), + (gtk.STATE_INSENSITIVE, COLOR_DARK_GREEN), +) + + +# ui elements ################################################################## + +COLOR_BACKGROUND = COLOR_LIGHT_GREEN +COLOR_FRAME = COLOR_YELLOW +COLOR_PAGE = COLOR_WHITE +COLOR_PAGE_BORDER = COLOR_PINK +COLOR_LIST_BACKGROUND = COLOR_PANEL_GREY +COLOR_LIST_BORDER = COLOR_TOOLBAR_GREY +COLOR_LIST_ROW = COLOR_TEXT_FIELD_GREY +COLOR_LIST_ROW_ALT = COLOR_GRAY +COLOR_TEXTBOX = COLOR_PAGE +COLOR_LINK = COLOR_BLUE +COLOR_TAB_ACTIVE = COLOR_DARK_GREEN +COLOR_TAB_INACTIVE = COLOR_LIGHT_GREEN +COLOR_TAB_SEPERATOR = COLOR_LIGHT_GRAY +COLOR_TAB_TEXT = COLOR_WHITE + + +# constants #################################################################### + +zoom = style.zoom + +PAGE_HEIGHT = style.zoom(635) # don't ask +TABS_HEIGHT = style.zoom(480) # 465 450 +PREVIEW_HEIGHT = style.zoom(519) # 564 + +PADDING_TAB = style.zoom(6) +DEFAULT_PADDING = style.zoom(6) +DEFAULT_SPACING = style.zoom(8) +BORDER_WIDTH = style.zoom(6) +BORDER_WIDTH_CONTROL = style.zoom(12) +BORDER_WIDTH_IMAGE = style.zoom(1) +SPACER_VERTICAL = style.zoom(20) +SPACER_HORIZONTAL = style.zoom(20) + +# fonts ######################################################################## + +#FONT_SIZE = zoom(7 * _XO_DPI / _get_screen_dpi()) +#FONT_NORMAL = Font('Bitstream Vera Sans %d' % FONT_SIZE) +#_XO_DPI = 200.0 +FONT_SIZE_LARGE = style.zoom(10 * style._XO_DPI / style._get_screen_dpi()) +FONT_LARGE = style.Font('Bitstream Vera Sans %d' % FONT_SIZE_LARGE) + +#FONT_LARGE = style.FONT_NORMAL #'Sans 18' +FONT_BODY = style.FONT_NORMAL #'Sans 14' +FONT_BODY_BOLD = style.FONT_BOLD #'Sans Bold 14' +FONT_TABS = style.FONT_NORMAL #'Sans 12' +FONT_TEXTBOX = style.FONT_NORMAL #'Sans 10' + + +# images ####################################################################### + +IMAGE_CHOOSE = 'resources/image.png' +AUDIO_CHOOSE = 'resources/audio.png' + + +# helpers ###################################################################### + +# TODO - deprecate in favor of gtkrc +def theme_widget(widget, width=-1, height=-1, highlight=False): + """Apply colors to gtk Widgets + + widget is the widget + width, height are optional width and height for resizing the widget + highlight is a boolean to override the theme and apply a + different color to show "you are here". + + returns the modified widget. + """ + + return widget + + #if widget == None: + #print 'theme.theme_widget(widget=None) !' + #return + + #for state, color in COLOR_BG_BUTTONS: + #if highlight: + #widget.modify_bg(state, gtk.gdk.color_parse("#CCFF99")) + #else: + #widget.modify_bg(state, color.get_gdk_color()) + + #if hasattr(widget, 'get_child'): + #c = widget.get_child() + #if c is not None: + #for state, color in COLOR_FG_BUTTONS: + #if highlight: + #c.modify_fg(state, COLOR_DARK_GREEN.get_gdk_color()) + #else: + #c.modify_fg(state, color.get_gdk_color()) + #else: + #for state, color in COLOR_FG_BUTTONS: + #widget.modify_fg(state, color.get_gdk_color()) + + #if width > 0 or height > 0: + #widget.set_size_request(width, height) + + #return widget + + + -- cgit v0.9.1