Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Area.py6
-rw-r--r--Desenho.py2
-rw-r--r--toolbox.py163
-rw-r--r--widgets.py307
4 files changed, 344 insertions, 134 deletions
diff --git a/Area.py b/Area.py
index 74b8fe4..2e979a8 100644
--- a/Area.py
+++ b/Area.py
@@ -69,7 +69,7 @@ import os
import tempfile
import math
import pango
-from fill import *
+from fill import fill
from Desenho import Desenho
from urlparse import urlparse
@@ -139,7 +139,7 @@ class Area(gtk.DrawingArea):
## All values migth be None, execept in 'name' key.
self.tool = {
'name': 'pencil',
- 'line size': 2,
+ 'line size': 4,
'fill color': None,
'stroke color': None,
'line shape': 'circle',
@@ -853,7 +853,6 @@ class Area(gtk.DrawingArea):
logging.debug('Area._set_fill_color(self, color)')
self.gc.set_foreground(color)
- self.janela.textview.modify_text(gtk.STATE_NORMAL, color)
def set_stroke_color(self, color):
"""Set stroke color.
@@ -868,6 +867,7 @@ class Area(gtk.DrawingArea):
self.gc_line.set_line_attributes(1, gtk.gdk.LINE_ON_OFF_DASH,
gtk.gdk.CAP_ROUND, gtk.gdk.JOIN_ROUND)
self.gc_brush.set_foreground(color)
+ self.janela.textview.modify_text(gtk.STATE_NORMAL, color)
def grayscale(self, widget):
"""Apply grayscale effect.
diff --git a/Desenho.py b/Desenho.py
index 9b4c771..4f8f196 100644
--- a/Desenho.py
+++ b/Desenho.py
@@ -587,7 +587,7 @@ class Desenho:
layout = widget.janela.textview.create_pango_layout(text)
- widget.pixmap.draw_layout(widget.gc,
+ widget.pixmap.draw_layout(widget.gc_brush,
widget.oldx, widget.oldy, layout)
widget.pixmap_temp.draw_layout(widget.gc,
widget.oldx, widget.oldy, layout)
diff --git a/toolbox.py b/toolbox.py
index 384cb15..dafb4e7 100644
--- a/toolbox.py
+++ b/toolbox.py
@@ -73,6 +73,7 @@ from sugar.graphics.toolbutton import ToolButton
from sugar.graphics.radiotoolbutton import RadioToolButton
from sugar.graphics.toggletoolbutton import ToggleToolButton
from sugar.graphics.objectchooser import ObjectChooser
+from widgets import ButtonStrokeColor
from sugar.graphics.colorbutton import ColorToolButton
from sugar.graphics import style
@@ -131,6 +132,14 @@ class DrawToolbarBox(ToolbarBox):
stop = StopButton(self._activity)
self.toolbar.insert(stop, -1)
+ # TODO: workaround
+ # the BrushButton does not starts
+ brush_button = tools_builder._stroke_color.color_button
+ brush_button.set_brush_shape(self._activity.area.tool['line shape'])
+ brush_button.set_brush_size(self._activity.area.tool['line size'])
+ if self._activity.area.tool['stroke color'] is not None:
+ brush_button.set_color(self._activity.area.tool['stroke color'])
+
##Make the Edit Toolbar
class DrawEditToolbar(EditToolbar):
@@ -212,117 +221,6 @@ class DrawToolButton(RadioToolButton):
self.set_tooltip(tooltip)
-class ButtonStrokeColor(ColorToolButton):
- """Class to manage the Stroke Color of a Button"""
-
- def __init__(self, activity):
- ColorToolButton.__init__(self)
- self._activity = activity
- self.properties = self._activity.area.tool
- self.connect('notify::color', self._color_button_cb)
-
- def _color_button_cb(self, widget, pspec):
- color = self.get_color()
- self.set_stroke_color(color)
-
- def alloc_color(self, color):
- colormap = self._activity.area.get_colormap()
- return colormap.alloc_color(color.red, color.green, color.blue)
-
- def set_stroke_color(self, color):
- new_color = self.alloc_color(color)
- self._activity.area.set_stroke_color(new_color)
- self.properties['stroke color'] = new_color
-
- def create_palette(self):
- self._palette = self.get_child().create_palette()
-
- color_palette_hbox = self._palette._picker_hbox
-
- content_box = gtk.VBox()
- # We can set size when using either
-
- size_spinbutton = gtk.SpinButton()
-
- # This is where we set restrictions for size:
- # Initial value, minimum value, maximum value, step
- adj = gtk.Adjustment(self.properties['line size'], 1.0, 100.0, 1.0)
- size_spinbutton.set_adjustment(adj)
-
- size_spinbutton.set_numeric(True)
-
- label = gtk.Label(_('Size: '))
-
- hbox = gtk.HBox()
- content_box.pack_start(hbox)
-
- hbox.pack_start(label)
- hbox.pack_start(size_spinbutton)
-
- size_spinbutton.connect('value-changed', self._on_value_changed)
-
- # User is able to choose Shapes for 'Brush' and 'Eraser'
-
- # Changing to gtk.RadioButton
- item1 = gtk.RadioButton(None, _('Circle'))
- item1.set_active(True)
-
- image1 = gtk.Image()
- pixbuf1 = gtk.gdk.pixbuf_new_from_file_at_size(
- './icons/tool-shape-ellipse.svg',
- style.SMALL_ICON_SIZE,
- style.SMALL_ICON_SIZE)
- image1.set_from_pixbuf(pixbuf1)
- item1.set_image(image1)
-
- item2 = gtk.RadioButton(item1, _('Square'))
-
- image2 = gtk.Image()
- pixbuf2 = gtk.gdk.pixbuf_new_from_file_at_size(
- './icons/tool-shape-rectangle.svg',
- style.SMALL_ICON_SIZE,
- style.SMALL_ICON_SIZE)
- image2.set_from_pixbuf(pixbuf2)
- item2.set_image(image2)
-
- item1.connect('toggled', self._on_toggled, self.properties, 'circle')
- item2.connect('toggled', self._on_toggled, self.properties, 'square')
-
- label = gtk.Label(_('Shape'))
-
- content_box.pack_start(label)
- content_box.pack_start(item1)
- content_box.pack_start(item2)
-
- # Creating a CheckButton
- keep_aspect_checkbutton = gtk.CheckButton(_('Keep aspect'))
- ratio = self._activity.area.keep_aspect_ratio
- keep_aspect_checkbutton.set_active(ratio)
- keep_aspect_checkbutton.connect('toggled',
- self._keep_aspect_checkbutton_toggled)
- content_box.pack_start(keep_aspect_checkbutton)
-
- color_palette_hbox.pack_start(gtk.VSeparator(),
- padding=style.DEFAULT_SPACING)
- color_palette_hbox.pack_start(content_box)
- color_palette_hbox.show_all()
-
- return self._palette
-
- def _keep_aspect_checkbutton_toggled(self, checkbutton):
- logging.debug('Keep aspect is Active: %s', checkbutton.get_active())
- self._activity.area.keep_aspect_ratio = checkbutton.get_active()
-
- def _on_value_changed(self, spinbutton):
- size = spinbutton.get_value_as_int()
- self.properties['line size'] = size
- self._activity.area.set_tool(self.properties)
-
- def _on_toggled(self, radiobutton, tool, shape):
- if radiobutton.get_active():
- self.properties['line shape'] = shape
-
-
class ToolsToolbarBuilder():
#Tool default definitions
@@ -339,8 +237,9 @@ class ToolsToolbarBuilder():
self.properties = self._activity.area.tool
self._stroke_color = ButtonStrokeColor(activity)
- self._stroke_color.set_icon_name('icon-stroke')
- self._stroke_color.set_title(_('Stroke Color'))
+ #self._stroke_color.set_icon_name('icon-stroke')
+ self._stroke_color.set_title(_('Brush properties'))
+ self._stroke_color.connect('notify::color', self._color_button_cb)
item = gtk.ToolItem()
item.add(self._stroke_color)
toolbar.insert(item, -1)
@@ -349,13 +248,15 @@ class ToolsToolbarBuilder():
separator.set_draw(True)
toolbar.insert(separator, -1)
+ """
self._tool_pencil = DrawToolButton('tool-pencil',
activity.tool_group, _('Pencil'))
toolbar.insert(self._tool_pencil, -1)
- activity.tool_group = self._tool_pencil
+ """
self._tool_brush = DrawToolButton('tool-brush',
activity.tool_group, _('Brush'))
+ activity.tool_group = self._tool_brush
toolbar.insert(self._tool_brush, -1)
self._tool_eraser = DrawToolButton('tool-eraser',
@@ -377,8 +278,8 @@ class ToolsToolbarBuilder():
# New connect method
# Using dictionnaries to control tool's properties
- self._tool_pencil.connect('clicked', self.set_tool,
- self._TOOL_PENCIL_NAME)
+ #self._tool_pencil.connect('clicked', self.set_tool,
+ # self._TOOL_PENCIL_NAME)
self._tool_brush.connect('clicked', self.set_tool,
self._TOOL_BRUSH_NAME)
self._tool_eraser.connect('clicked', self.set_tool,
@@ -400,6 +301,13 @@ class ToolsToolbarBuilder():
self.properties['name'] = tool_name
self._activity.area.set_tool(self.properties)
+ def _color_button_cb(self, widget, pspec):
+ logging.error('ToolsToolbarBuilder._color_button_cb')
+
+ new_color = widget.alloc_color(widget.get_color())
+ self._activity.area.set_stroke_color(new_color)
+ self.properties['stroke color'] = new_color
+
class ButtonFillColor(ColorToolButton):
"""Class to manage the Fill Color of a Button"""
@@ -508,7 +416,7 @@ class ShapesToolbar(gtk.Toolbar):
self._fill_color = ButtonFillColor(activity)
self._fill_color.set_icon_name('icon-fill')
- self._fill_color.set_title(_('Fill Color'))
+ self._fill_color.set_title(_('Shapes properties'))
item = gtk.ToolItem()
item.add(self._fill_color)
self.insert(item, -1)
@@ -599,22 +507,17 @@ class ShapesToolbar(gtk.Toolbar):
##Make the Text Toolbar
class TextToolbar(gtk.Toolbar):
- _ACTION_TEXT = {'name': 'text',
- 'line size': None,
- 'fill color': None,
- 'stroke color': None,
- 'line shape': None,
- 'fill': True,
- 'vertices': None}
+ _ACTION_TEXT_NAME = 'text'
def __init__(self, activity):
gtk.Toolbar.__init__(self)
self._activity = activity
+ self.properties = self._activity.area.tool
self._text = DrawToolButton('text', activity.tool_group, _('Type'))
self.insert(self._text, -1)
- self._text.connect('clicked', self.set_tool, self._ACTION_TEXT)
+ self._text.connect('clicked', self.set_tool, self._ACTION_TEXT_NAME)
separator = gtk.SeparatorToolItem()
separator.set_draw(True)
@@ -630,10 +533,12 @@ class TextToolbar(gtk.Toolbar):
self._italic.show()
self._italic.connect('clicked', self.__italic_bt_cb)
+ """
self._text_color = ButtonFillColor(activity)
item = gtk.ToolItem()
item.add(self._text_color)
self.insert(item, -1)
+ """
separator = gtk.SeparatorToolItem()
separator.set_draw(True)
@@ -713,11 +618,9 @@ class TextToolbar(gtk.Toolbar):
return None
return model[active][0]
- def set_tool(self, widget, tool):
- #FIXME: this callback must change as others buttons get enabled
- new_color = self._text_color.get_color()
- tool['fill color'] = self._text_color.alloc_color(new_color)
- self._activity.area.set_tool(tool)
+ def set_tool(self, widget, tool_name):
+ self.properties['name'] = tool_name
+ self._activity.area.set_tool(self.properties)
##Make the Images Toolbar
diff --git a/widgets.py b/widgets.py
new file mode 100644
index 0000000..832649b
--- /dev/null
+++ b/widgets.py
@@ -0,0 +1,307 @@
+# -*- coding: utf-8 -*-
+
+from gettext import gettext as _
+
+import gtk
+import gobject
+
+from sugar.graphics import style
+from sugar.graphics.palette import ToolInvoker
+from sugar.graphics.colorbutton import _ColorButton
+
+
+class BrushButton(_ColorButton):
+ """This is a ColorButton but show the color, the size and the shape
+ of the brush.
+ Instead of a color selector dialog it will pop up a Sugar palette.
+ As a preview an DrawingArea is used, to use the same methods to
+ draw than in the main window.
+ """
+
+ __gtype_name__ = 'BrushButton'
+
+ def __init__(self, **kwargs):
+ self._title = _('Choose brush properties')
+ self._color = gtk.gdk.Color(0, 0, 0)
+ self._has_palette = True
+ self._has_invoker = True
+ self._palette = None
+ self._accept_drag = True
+ self._brush_size = 2
+ self._brush_shape = 'circle'
+ self._preview = gtk.DrawingArea()
+ self._preview.set_size_request(style.STANDARD_ICON_SIZE,
+ style.STANDARD_ICON_SIZE)
+
+ gobject.GObject.__init__(self, **kwargs)
+ self._preview.set_events(gtk.gdk.BUTTON_PRESS_MASK)
+
+ self._preview.connect('button_press_event', self.__mouse_down_cb)
+ self._preview.connect("expose_event", self.expose)
+ self.set_image(self._preview)
+
+ self._gc = None
+
+ if self._has_palette and self._has_invoker:
+ self._invoker = WidgetInvoker(self)
+ # FIXME: This is a hack.
+ self._invoker.has_rectangle_gap = lambda: False
+ self._invoker.palette = self._palette
+
+ def _setup(self):
+ if self.get_window() is not None:
+ self._preview.fill_color = ''
+ self._preview.show()
+ self.pixmap = gtk.gdk.Pixmap(self.get_window(),
+ style.STANDARD_ICON_SIZE,
+ style.STANDARD_ICON_SIZE, 24)
+ self._gc = self.get_window().new_gc()
+ self.show_all()
+
+ def get_brush_size(self):
+ return self._brush_size
+
+ def set_brush_size(self, brush_size):
+ self._brush_size = brush_size
+ self._preview.queue_draw()
+
+ brush_size = gobject.property(type=int, getter=get_brush_size,
+ setter=set_brush_size)
+
+ def get_brush_shape(self):
+ return self._brush_shape
+
+ def set_brush_shape(self, brush_shape):
+ self._brush_shape = brush_shape
+ self._preview.queue_draw()
+
+ brush_shape = gobject.property(type=str, getter=get_brush_shape,
+ setter=set_brush_shape)
+
+ def set_color(self, color):
+ # receive gtk.gdk.Color
+ self._color = color
+ self._preview.queue_draw()
+
+ def expose(self, widget, event):
+ if self._gc is None:
+ self._setup()
+
+ if self.get_window() is not None:
+ center = style.STANDARD_ICON_SIZE / 2
+ self.pixmap.draw_rectangle(self._preview.get_style().white_gc,
+ True, 0, 0, style.STANDARD_ICON_SIZE, style.STANDARD_ICON_SIZE)
+ self._gc.set_foreground(self._color)
+
+ if(self._brush_shape == 'circle'):
+ self.pixmap.draw_arc(self._gc, True,
+ center - self._brush_size / 2,
+ center - self._brush_size / 2,
+ self._brush_size, self._brush_size, 0, 360 * 64)
+ if(self._brush_shape == 'square'):
+ self.pixmap.draw_rectangle(self._gc, True,
+ center - self._brush_size / 2,
+ center - self._brush_size / 2,
+ self._brush_size, self._brush_size)
+
+ area = event.area
+ widget.window.draw_drawable(self._gc, self.pixmap,
+ area[0], area[1], area[0], area[1], area[2], area[3])
+ return False
+
+ def do_style_set(self, previous_style):
+ pass
+
+ def set_icon_name(self, icon_name):
+ pass
+
+ def get_icon_name(self):
+ pass
+
+ def set_icon_size(self, icon_size):
+ pass
+
+ def get_icon_size(self):
+ pass
+
+ def __mouse_down_cb(self, event):
+ if self._palette:
+ if not self._palette.is_up():
+ self._palette.popup(immediate=True,
+ state=self._palette.SECONDARY)
+ else:
+ self._palette.popdown(immediate=True)
+ return True
+
+
+class ButtonStrokeColor(gtk.ToolItem):
+ """Class to manage the Stroke Color of a Button"""
+
+ __gtype_name__ = 'BrushColorToolButton'
+ __gsignals__ = {'color-set': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ tuple())}
+
+ def __init__(self, activity, **kwargs):
+ self._activity = activity
+ self.properties = self._activity.area.tool
+ self._accelerator = None
+ self._tooltip = None
+ self._palette_invoker = ToolInvoker()
+ self._palette = None
+
+ gobject.GObject.__init__(self, **kwargs)
+
+ # The gtk.ToolButton has already added a normal button.
+ # Replace it with a ColorButton
+ self.color_button = BrushButton(has_invoker=False)
+ self.add(self.color_button)
+ self.color_button.set_brush_size(2)
+ self.color_button.set_brush_shape('circle')
+
+ # The following is so that the behaviour on the toolbar is correct.
+ self.color_button.set_relief(gtk.RELIEF_NONE)
+
+ self._palette_invoker.attach_tool(self)
+
+ # This widget just proxies the following properties to the colorbutton
+ self.color_button.connect('notify::color', self.__notify_change)
+ self.color_button.connect('notify::icon-name', self.__notify_change)
+ self.color_button.connect('notify::icon-size', self.__notify_change)
+ self.color_button.connect('notify::title', self.__notify_change)
+ self.color_button.connect('can-activate-accel',
+ self.__button_can_activate_accel_cb)
+
+ def __button_can_activate_accel_cb(self, button, signal_id):
+ # Accept activation via accelerators regardless of this widget's state
+ return True
+
+ def __notify_change(self, widget, pspec):
+ new_color = self.alloc_color(self.get_color())
+ self.color_button.set_color(new_color)
+ self.notify(pspec.name)
+
+ def _color_button_cb(self, widget, pspec):
+ color = self.get_color()
+ self.set_stroke_color(color)
+
+ def alloc_color(self, color):
+ colormap = self._activity.area.get_colormap()
+ return colormap.alloc_color(color.red, color.green, color.blue)
+
+ def create_palette(self):
+ self._palette = self.get_child().create_palette()
+
+ color_palette_hbox = self._palette._picker_hbox
+ content_box = gtk.VBox()
+ size_spinbutton = gtk.SpinButton()
+ # This is where we set restrictions for size:
+ # Initial value, minimum value, maximum value, step
+ adj = gtk.Adjustment(self.properties['line size'], 1.0, 100.0, 1.0)
+ size_spinbutton.set_adjustment(adj)
+ size_spinbutton.set_numeric(True)
+
+ label = gtk.Label(_('Size: '))
+ hbox = gtk.HBox()
+ content_box.pack_start(hbox)
+
+ hbox.pack_start(label)
+ hbox.pack_start(size_spinbutton)
+ size_spinbutton.connect('value-changed', self._on_value_changed)
+
+ # User is able to choose Shapes for 'Brush' and 'Eraser'
+ item1 = gtk.RadioButton(None, _('Circle'))
+ item1.set_active(True)
+ image1 = gtk.Image()
+ pixbuf1 = gtk.gdk.pixbuf_new_from_file_at_size(
+ './icons/tool-shape-ellipse.svg',
+ style.SMALL_ICON_SIZE,
+ style.SMALL_ICON_SIZE)
+ image1.set_from_pixbuf(pixbuf1)
+ item1.set_image(image1)
+
+ item2 = gtk.RadioButton(item1, _('Square'))
+ image2 = gtk.Image()
+ pixbuf2 = gtk.gdk.pixbuf_new_from_file_at_size(
+ './icons/tool-shape-rectangle.svg',
+ style.SMALL_ICON_SIZE,
+ style.SMALL_ICON_SIZE)
+ image2.set_from_pixbuf(pixbuf2)
+ item2.set_image(image2)
+
+ item1.connect('toggled', self._on_toggled, self.properties, 'circle')
+ item2.connect('toggled', self._on_toggled, self.properties, 'square')
+
+ label = gtk.Label(_('Shape'))
+
+ content_box.pack_start(label)
+ content_box.pack_start(item1)
+ content_box.pack_start(item2)
+
+ keep_aspect_checkbutton = gtk.CheckButton(_('Keep aspect'))
+ ratio = self._activity.area.keep_aspect_ratio
+ keep_aspect_checkbutton.set_active(ratio)
+ keep_aspect_checkbutton.connect('toggled',
+ self._keep_aspect_checkbutton_toggled)
+ content_box.pack_start(keep_aspect_checkbutton)
+
+ color_palette_hbox.pack_start(gtk.VSeparator(),
+ padding=style.DEFAULT_SPACING)
+ color_palette_hbox.pack_start(content_box)
+ color_palette_hbox.show_all()
+ return self._palette
+
+ def _keep_aspect_checkbutton_toggled(self, checkbutton):
+ self._activity.area.keep_aspect_ratio = checkbutton.get_active()
+
+ def _on_value_changed(self, spinbutton):
+ size = spinbutton.get_value_as_int()
+ self.properties['line size'] = size
+ self._activity.area.set_tool(self.properties)
+ self.color_button.set_brush_size(self.properties['line size'])
+
+ def _on_toggled(self, radiobutton, tool, shape):
+ if radiobutton.get_active():
+ self.properties['line shape'] = shape
+ self.color_button.set_brush_shape(shape)
+ self.color_button.set_brush_size(self.properties['line size'])
+
+ def get_palette_invoker(self):
+ return self._palette_invoker
+
+ def set_palette_invoker(self, palette_invoker):
+ self._palette_invoker.detach()
+ self._palette_invoker = palette_invoker
+
+ palette_invoker = gobject.property(
+ type=object, setter=set_palette_invoker, getter=get_palette_invoker)
+
+ def set_color(self, color):
+ self.color_button.set_color(color)
+
+ def get_color(self):
+ return self.get_child().props.color
+
+ color = gobject.property(type=object, getter=get_color, setter=set_color)
+
+ def set_title(self, title):
+ self.get_child().props.title = title
+
+ def get_title(self):
+ return self.get_child().props.title
+
+ title = gobject.property(type=str, getter=get_title, setter=set_title)
+
+ def do_expose_event(self, event):
+ child = self.get_child()
+ allocation = self.get_allocation()
+ if self._palette and self._palette.is_up():
+ invoker = self._palette.props.invoker
+ invoker.draw_rectangle(event, self._palette)
+ elif child.state == gtk.STATE_PRELIGHT:
+ child.style.paint_box(event.window, gtk.STATE_PRELIGHT,
+ gtk.SHADOW_NONE, event.area,
+ child, 'toolbutton-prelight',
+ allocation.x, allocation.y,
+ allocation.width, allocation.height)
+
+ gtk.ToolButton.do_expose_event(self, event)