[sugar] Read activity modifications
Don Hopkins
dhopkins at DonHopkins.com
Thu May 10 02:07:20 EDT 2007
I've been working on making the Read activity usable in book mode, and
adding other improvements.
I'm updating it to work against the latest build, and I'll put up a tar
file soon.
Here's a summary of my changes and ideas for further improvements.
-Don
Loading icons for gtk buttons from SVG files.
Wrote a LoadIcon(fileName) function that loads an svg file and returns
a GTK pixbuf.
TODO: support different file formats (XPM, PNG, PDF, etc).
TODO: support scaling of the image to a particular size.
TODO: caching images according to file name and size.
Made a gtk.IconFactory for the activity.
Loop over all SVG files in the icons subdirectory of the bundle path.
Loaded all SVG files into icon pixbufs, wrapped them in IconSets,
and added them to the icon manager.
TODO: make a smart IconFactory that supports lazy loading of icons.
Icons are named the same as the file name with the extension stripped
off.
Icons should have a prefix like "read-" to distinguish them from other
icons (like the "stock-" icons).
GTK widgets can be configured to use named icons by setting their
stock-id property.
Implement a new set of toolbars and buttons using custom "Action"
classes and UIManager.
Defined SugarAction, SugarToggleAction, SugarRadioAction subclasses of
stock GTK Action classes, mixing in SugarActionMixin.
Defined SugarToolButton, SugarToggleToolButton, SugarRadioToolButton
subclasses of GTK ToolButton classes, mixing in SugarWidgetMixin.
Defined SugarActionMixin and SugarWidgetMixin classes for shared
Sugar-specific behavior and state.
Added support for "allowed" property, like "sensitive" (enabled),
but it will let you set the focus to the control and see a tooltip
telling the reason it's not allowed.
Added support for "reason" property, a translated text string that
explains the reason an action is not allowed to the user.
TODO: Implement visual indication of "allow" state.
TODO: Make actions show tooltip with disallow reason if user tries
to invoke un-allowed control, but not invoke callback.
Rewrote gtk.ActionGroup methods add_actions, add_toggle_actions,
add_radio_actions in Python instead of C (from pygtk).
Instead of making them differently named class-specific methods of
gtk.ActionGroup, I re-factored them into generic "add_actions" methods
on the corresponding classes.
So instead of calling action_group.add_toggle_actions(entries), you
call SugarToggleAction.add_actions(action_group, entries), or whatever
class you want to add.
This makes it much easier to extend the system with your own sets of
Actions and Widgets, by subclassing SugarAction, and mixin
SugarWidgetMixin into the widget.
TODO: Implement search string entry field, page number entry
field, page count label, as application specific Action/Widget sets.
The gtk.ActionGroup add_*_actions api took a list of entries, where
each entry was a tuple with positional arguments filled with "None"
placeholders.
That was brittle and hard to use, and impossible to extend by adding
new parameters.
Instead, the new interface takes a list of entries, where each entry
is a dictionary instead of a tuple, so it's possible to pass additional
arguments and omit unused keys.
The dictionary entry based API is more open-ended and flexible, so
we can seamlessly add additional parameters in the future without
breaking the API.
Defined optional "action_class" parameter to each entry that
specifies the class to make, which defaults to "self", the class you're
calling the add_action class method on.
So subclasses of Action will automatically get instances of their
class when you call add_action on their class.
TODO: Factor out any class-specific behavior from add_actions into
class method hooks, so Action subclasses can define their own hooks
instead of redefining their own entire add_action methods.
Defined optional *args and **kwargs parameters to add_actions, as
well as to each entry, which are merged and passed to the callback.
You can specify additional parameters to each set of actions you
create at once, and to each individual action, which makes it possible
to define more general purpose actions that you can customize with
parameters and additional callbacks, instead of defining a new special
purpose Action class for each control.
Made a UIManager to create the toolbars from an XML user interface
description.
TODO: Implement an open-ended extensible Pythonic SugarUIManager.
TODO: Allow the applilcation to register new action classes
corresponding to XML elements in the user interface descriptions.
TODO: Extend the SugarUIManager to support other kinds of interfaces
beyond toolbars and menus: gamepad navigation, pie menus, etc.
Implement enabling and disabling actions and toolbar buttons.
Actions automatically take care of enabling and disabling all of their
corresponding toolbar buttons and menu items (proxies).
Implemented a higher level _set_action_sensitive(self, action_name,
sensitive, reason=None) interface for setting the sensitivity and reason
an action is insensitive, which lets you pass a translated string that
describes why an action is disabled, that helps the user figure out what
to do about it.
Wrote code to call _set_action_sensitive at the appropriate time to
enable and disable evince controls (back page, next page, first page,
last page, zoom in, zoom out).
TODO: Use "allowed" instead of "sensitive" to disable controls, so the
user can navigate to them and see tooltips about why they're disabled.
Defined SugarActions for most of the interesting evince functions,
SugarToggleActions for boolean properties, SugarRadioAction for
enumerated properties.
Defined toolbars with buttons and separators to control evince.
Made icons for all of the buttons (first cut placeholder programmer art
for now: round buttons with tiny text labels).
Defined a _bundle_path instance variable in XbookActivity that tells
where the root of the Read activity bundle is.
Added a _startup_file_name instance variable to XbookActivity,
initialized to "userguide.pdf" that's read from the documents
sub-directory of the bundle_path.
This is currently to help me test the Read activity, because the "open
file" button is no longer supported.
But the default startup document could be used to throw up a useful
introduction with links to libraries and documentation. (Once links in
PDF documents work properly).
Wrote a "MANIFEST" file that lists all the files to be installed into
the activity directory.
If you don't have a "MANIFEST" file, the activity builder looks at the
subversion source code control system to figure out which files to
bundle, which doesn't work during development before the files have been
added to source code control.
-Don
More information about the Sugar
mailing list