maemo.org - Talk

maemo.org - Talk (https://talk.maemo.org/index.php)
-   Development (https://talk.maemo.org/forumdisplay.php?f=13)
-   -   Shaped widgets? (transparent background) (https://talk.maemo.org/showthread.php?t=16720)

Khertan 2008-11-13 10:48

Re: Shaped widgets? (transparent background)
 
Yep i use cairo drawing but on label ... my try to display a gtk.treeview is unsuccessfull at this time ... :)

darethehair 2008-11-13 13:15

Re: Shaped widgets? (transparent background)
 
khertan:

If you feel even more daring, perhaps sometime you can attempt an applet that draws a graphic (say, a sphere or rectangle, using Cairo), then adds a PyGTK button...?

konttori 2008-11-22 08:21

Re: Shaped widgets? (transparent background)
 
Hmm.. someone needs to make an example applet with cairo and mouse click handling so that we can start simulating button behavior by using pixmaps/vectors.

mece 2010-01-29 19:56

Re: Shaped widgets? (transparent background)
 
Quote:

Originally Posted by konttori (Post 243830)
Hmm.. someone needs to make an example applet with cairo and mouse click handling so that we can start simulating button behavior by using pixmaps/vectors.

Hmm, I actually did that today, so I can write something up. I'll put it here first, and then you can tell me how it's the wrong method :)

In the meanwhile, can someone tell me how I can get a gtk.Label inside an EventBox to be upon a transparent surface? I can only seem to get it either invisible or with black background. Worked around it design wise, though, but would be nice to know how to do it.

mece 2010-01-29 21:10

Re: Shaped widgets? (transparent background)
 
4 Attachment(s)
Ok I wrote an example widget with images for buttons.

I attatched the images if you want to test it out. simply save this code to a .py file, and copy the image files either to
/home/user/buttons/
or wherever you want, but change the imagedir variable in the code to point at the right place.

Code:

# hildon home widget, png button example

import hildondesktop
import gtk
import cairo

imagepath = "/home/user/comic-widget/images/"

class ExamplePlugin(hildondesktop.HomePluginItem):
        def __init__(self):
                hildondesktop.HomePluginItem.__init__(self)
                self.set_size_request(96, 97) # make the widget a nice size.
                # Interestingly, having the exactly correct amount of space, makes it not work properly, hence the 1 pixel extra.
                self.vbox = gtk.VBox()
                self.hbox = gtk.HBox() # Horisontally arranged box to put your buttons in
                self.hbox.set_size_request(96, 48)
                screen = self.get_screen()
                colormap = screen.get_rgba_colormap()
                self.set_colormap(colormap)
                self.set_app_paintable(True)
                self.label = gtk.Label()
                self.label.set_markup("<small>Buttons</small>")

                # The event boxes.
                self.e_text = gtk.EventBox()
                self.e_text.set_name('text')
                self.e_text.set_size_request(96, 48)
                self.e_next = gtk.EventBox()
                self.e_next.set_name('next') #  The name is nice to have if you want to link it to a file name for example.
                self.e_next.set_size_request(48, 48) # I have 48x48px buttons :)
                self.e_prev = gtk.EventBox()
                self.e_prev.set_name('prev')
                self.e_prev.set_size_request(48, 48)

                # Add the label:
                self.e_text.add(self.label)

                # Preload som images an throw them in a dict.
                # I don't know if this actually helps make things snappy, but it was the simplest way I could think of.

                self.images = { 'next0':cairo.ImageSurface.create_from_png(imagepath + "next0-48x48.png"),
                                        'next1':cairo.ImageSurface.create_from_png(imagepath + "next1-48x48.png"),
                                        'prev0':cairo.ImageSurface.create_from_png(imagepath + "prev0-48x48.png"),
                                        'prev1':cairo.ImageSurface.create_from_png(imagepath + "prev1-48x48.png") }

                #*****************************************************************
                # now here's the important part: make some events.
                # I have the same event for release and leave because my event handler checks if it was a real click or a bailout
                self.e_next.set_events(gtk.gdk.BUTTON_PRESS_MASK|gtk.gdk.BUTTON_RELEASE_MASK|gtk.gdk.LEAVE_NOTIFY)
                self.e_next.connect("button-press-event", self.button_press)
                self.e_next.connect("button-release-event", self.button_release)
                self.e_next.connect("leave-notify-event", self.button_release)

                self.e_prev.set_events(gtk.gdk.BUTTON_PRESS_MASK|gtk.gdk.BUTTON_RELEASE_MASK|gtk.gdk.LEAVE_NOTIFY)
                self.e_prev.connect("button-press-event", self.button_press)
                self.e_prev.connect("button-release-event", self.button_release)
                self.e_prev.connect("leave-notify-event", self.button_release)

                # now let's put those eventboxes in the hbox
                self.vbox.pack_end(self.hbox,False,False,0)
                self.vbox.pack_end(self.e_text,False,False,0)
                self.hbox.pack_start(self.e_prev,False,False,0) # No padding for me, since I have a tight squeeze to get the buttons in.
                self.hbox.pack_end(self.e_next,False,False,0)
                self.hbox.show_all()
               
                #now add the stuff to the widget, and show it. (it's empty though)
               
                self.vbox.show_all()
                self.add(self.vbox)

        #now some functions.

        #expose function, runs automagically when the widget feels exposed.

        def do_expose_event(widget, event):
                cr = widget.window.cairo_create() # create a cairo thingamabob
                widget.draw(widget.e_prev,0) # call my show button function, first arg is where to put image, and second is which image.
                widget.draw(widget.e_next,0) # again for the other image

                # paint some background.
                cr.set_operator(cairo.OPERATOR_SOURCE)
                region = gtk.gdk.region_rectangle(event.area) # limit what to color
                cr.region(region)
                # bg_color=gtk.gdk.color_parse('#000000')
                cr.set_source_rgba (0.0, 0.0, 0.0, 0.5)        # Black, with 50% opacity. Nice!
                cr.fill_preserve() # lets fill it with that.


                return False

        # Function that draws a button preloaded in the images dictionary.
        def draw(self, target, postfix):
                cr_e = target.window.cairo_create()
                cr_e.set_source_rgba(0.0, 0.0, 0.0, 0.5) # If you, like I do, have transparency in your buttons,
                cr_e.set_operator(cairo.OPERATOR_SOURCE) #  you need to paint the background first.
                cr_e.paint()

                cr_e.set_operator(cairo.OPERATOR_OVER) # Not sure about this, but it works.
                # Now I have set it up so that the key in the dict to cairo imagesurface object is the name of the eventbox + a number.
                # 0 for idle, 1 for pressed..
                cr_e.set_source_surface(self.images[target.get_name() + str(postfix)], 0, 0) # here's where the magic is done
                cr_e.paint()

        # now the event handlers
        # I don't want to do anything other than switch image on press down.
        def button_press(self, widget, event):
                # this is needed because the second click can trigger a _2BUTTON_PRESS
                # and the third a _3BUTTON_PRESS, along with the regular BUTTON_PRESS
                # and I only want to switch images once.
                if not event.type == gtk.gdk.BUTTON_PRESS:
                        return False
                self.draw(widget, "1") #call the draw function, switch to image 1 which means pressed


        # then the button_release event.
        def button_release(self, widget, event):
                #check if it was released or moved out.
                if event.type == gtk.gdk.BUTTON_RELEASE:
                        # here is where you actually do whatever the button is for. I'll print something.
                        print "Success! The button was clicked!"

                else:
                        # if you want to do something with a button click that was bailed from, that would be here.
                        print "You almost clicked that button, but then you dragged away at the last minute!"
                # then call the draw function, regardless of the type of release.
                # I think is nice to do it after the action, so that you get a visual queue
                # when the thing that should be done is done. At least it's nice in my widget.
                self.draw(widget, "0")

# register the plugin.

hd_plugin_type = ExamplePlugin

# This bit below is so that you can run the widget standalone.
if __name__ == "__main__":
        import gobject
        gobject.type_register(hd_plugin_type)
        obj = gobject.new(hd_plugin_type, plugin_id="plugin_id")
        obj.show_all()
        gtk.main()

Gaah! The code looks very confusing here. Copy it to your favorite editor and it will hopefully look nicer :)

Those of you who actually know pygtk, please point out the redundant or erroreous bits. Perhaps after a while it's good enough to be put in the wiki.

Oh an btw, this widget also illustrates the label issue I mentioned. If someone can show me how to make the label background be the same 50% opacity as the button part, then I'd be a happy camper

trlopes1974 2011-02-02 18:29

Re: Shaped widgets? (transparent background)
 
Hello.
I was trying to add more that one layout to the widget.

I was trying to accomplish something like:

< 1 IMAGE + 2 images (top/bottom) + 2 labels (top+bottom) >
by addind a HBOX (for 1 IMAGE) and 2 VBOX (one for the 2 images and another for the 2 labels) but it seems to be impossible to add more that one.

/usr/lib/hildon-desktop/helloworld.py:115: GtkWarning: Attempting to add a widget with type GtkVBox to a helloworld+HelloHomePlugin, but as a GtkBin subclass a helloworld+HelloHomePlugin can only contain one widget at a time; it already contains a widget of type GtkHBox


Any suggestions?

Thanks

nicolai 2011-02-02 20:49

Re: Shaped widgets? (transparent background)
 
The homeplugin is only a GtkContainer and can not take more than one
widget. If you want to put more widgets, use another hbox or vbox widget
and put your other boxes into this.

For a more complex layout you may have to use
several nesting boxes. Or maybe another layout container
like GtkTable.

trlopes1974 2011-02-02 22:38

Re: Shaped widgets? (transparent background)
 
that's exactly what i was trying to do.
so it is possible to have a main hbox with several child h/vboxes ???
I confess that while testing (as i couldn't see any result) i have moved the show_all() of each box outside the main box container.
I will try again...

thanks

trlopes1974 2011-02-03 19:40

Re: Shaped widgets? (transparent background)
 
just put it to work. Now the next problem. In te above example the draw() function is called on the widget context or trough an event in the ui. How would I call this function on a backend function (answering to a dbus signal for instance). My probelm and (I'm learing on the go) is that I don't know how to pass the ui context ( button press for instance ) of the widget
if I just call widget.draw(self.e_next, '1') outside those event handler I have an error specifying that widget is not a know object( or similar).

trlopes1974 2011-02-04 11:26

Re: Shaped widgets? (transparent background)
 
when I call draw(self.e_fstatus,"1") from an dbus-signal call, it gives-me this error
File "/usr/lib/hildon-desktop/helloworld.py", line 185, in draw
cr_e = target.window.cairo_create()
AttributeError: 'NoneType' object has no attribute 'cairo_create'
in the draw() function I've added
print "DEBUG: button clicked!!!" + widget.get_name()
DEBUG: drawing 0
against what shoul be.
DEBUG: drawing fmtx

nicolai 2011-02-04 11:45

Re: Shaped widgets? (transparent background)
 
What is self.e_fstatus ? Are you sure it is
already initialized when you call the draw function?

Nicolai

ammyt 2011-02-04 12:10

Re: Shaped widgets? (transparent background)
 
regardless of all the hard work you're doing, this once happened to me by accident, bug? maybe? It happened in PR1.2 when I first installed preenv and NFS UC. I added its shortcut on a homescreen then my phone rebooted suddenly. After this, all shortcuts I added showed their icon solely with no box surrounding them. This was gone when I updated to PR1.3, I wish I took a screenshot.

trlopes1974 2011-02-04 18:41

Re: Shaped widgets? (transparent background)
 
self.e_fstatus is an gtkeventbox..
just fixed it :) recoded the draw function just for that "button"..

Nothing like preserverance to overcome the barriers..
NEXT ISSUE... try to understand mediaplayer dbus signals...


All times are GMT. The time now is 18:51.

vBulletin® Version 3.8.8