this should have been sent to the list...

so my answer forwarded to here.

----- Forwarded message from oli...@first.in-berlin.de -----

Date: Sun, 1 Aug 2010 23:40:45 +0200
From: oli...@first.in-berlin.de
To: LightningIsMyName <lightningismyn...@gmail.com>
Subject: Re: [Gimp-developer] small Wishlist regarding Guides
User-Agent: Mutt/1.5.20 (2009-06-14)


On Sun, Aug 01, 2010 at 06:42:00PM +0300, LightningIsMyName wrote:
> Hello
> >  - non-rectangle-bound guides:
> >       Guides that can be enabled to have any angle, which means that they do

> I think we have seen this request already several times and I
> definitely agree it could be useful. Your request made me take a look
> at the code (app/display/gimpdisplayshell-draw.c,
> app/core/gimpimage-guides.c, /app/core/gimpguide.c) and it actually
> seems possible. I'll add it to my to-try list for when I have some
> more time.

Fine :)

> >  - boundary guides, instead of middle.guides:
> >    Guides, where the outer boundary of a drawing tool snaps to the guide 
> > (instead the middle of the
> >    drawing tool snapping to the guide).
> >
> >    This would be helpful for drawing in general, and correcting pictures: 
> > the color will
> >    not pass this line of the guide, which means, you can be sure no color 
> > enters a certain region.
> This does not seem trivial to code - in fact with how I remember the
> paint core works, this is going to be one very hard hack...
> Also, I think that if the purpose is just to stay inside of the lines
> you can use a selection (create it using the guides and freeform

The selection does not has the magnetic behaviour as a guide has.

Maybe even a freely definable guide would help here,
or a magnetic selection, or something like this.... ?!

> >  - Adding Multiple Guides
> >    (there is a Script for this on www.meetthegimp.org, but native would be 
> > nice)
> >
> >    This feature is good for some repetitive tasks, where a lot of Guides 
> > will be needed,
> >    something like a guide-grid.
> Can you give a direct link to the script?

I didn't found the link by myself, but I have the script local on my machine 
and can attach it.
It's not writen by me. But I may look for the original link later (or ask the 

> I definitely agree this
> sounds useful - it's worth checking if we can simply include this
> script with GIMP

The GUI/behaviour could be enhanced, and could be more Gimp-like.
But it's already useful and has saved me a lot of time in some tasks.

> (or at least if you give us a link to it, we'll be
> able to write something similar with extra features if needed).

I will attach it here.

I hope attachements are not blocked here.


import os

from gimpfu import *
import os.path
import pygtk
import gtk

gettext.install("gimp20-python", gimp.locale_directory, unicode=True)

def debugMessage(Message):
    dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, 

def findMaxDimensionOfImage(Image, Direction):
    if (Direction == 0):
       limit_value = pdb.gimp_image_height(Image) -1
       limit_value = pdb.gimp_image_width(Image) -1
    return limit_value

# This defines the class
class addMultipleGuidesDialog:

    # Things to do with the image reference
    imageRef = 0
    def set_imageRef(self,Image):
      self.imageRef = Image
    def get_imageRef(self):
      return self.imageRef

    # Things to do with the guides we create      
    thisGuide = 0
    def set_thisGuide(self, guideRef):
      self.thisGuide = guideRef
    def get_thisGuide(self):
      return self.thisGuide

    # RadioGroup
    radio_group = []
    def set_radioGroup(self, radioGroup):
      self.radio_group = radioGroup
    def get_radioGroup(self):
      return self.radio_group
    # Adjustment
    the_adjustment = 0
    def set_adjustment(self, newAdjustment):
      self.the_adjustment = newAdjustment;
    def get_adjustment(self):
      return self.the_adjustment

    # Labels (possible to change later for translation purposes)
    Labels = ["Horizontal", "Vertical", "Add", "Close", "Remove Last"]
#    Labels = ["H", "V", "A", "C"]
    def get_Labels(self, labelIndex):
      return self.Labels[labelIndex]

    # This is a callback function. The data arguments are ignored
    # in this example. More on callbacks below.
    def hello(self, widget, data=None):
        print "Finished"
    def findActiveRadioButton(self):
        active = [r for r in self.get_radioGroup() if r.get_active()][0]
        return active.get_label()

    # call back for the Add button
    def add_guide(self, widget, Data):
        activeLabel = self.findActiveRadioButton()
        position = Data.get_value()
        if (activeLabel == self.get_Labels(0)):
           currentGuide = pdb.gimp_image_add_hguide(self.get_imageRef(), 
           currentGuide = pdb.gimp_image_add_vguide(self.get_imageRef(), 

    def remove_last_guide(self, widget, Data):
        thisGuide = self.get_thisGuide()
        if (thisGuide != 0):
          pdb.gimp_image_delete_guide(self.get_imageRef(), thisGuide)
    # Limit the upper value for the spin button
    def limit_spin(self, widget, Data):
        # find out which radio button is selected
        activeLabel = self.findActiveRadioButton()
        if (activeLabel == self.get_Labels(0)):        # horizontal selected
           limit_value = findMaxDimensionOfImage(self.get_imageRef(), 0)
        else:                                          # vertical selected
           limit_value = findMaxDimensionOfImage(self.get_imageRef(), 1)
        # get the current value of the spinbutton
        adjustment = self.get_adjustment()
        current_value = adjustment.get_value()
         # if the current value is greater than the new limit, force the value 
to be the new limit
        if (current_value > limit_value): current_value = limit_value
        adjustment.set_all(current_value, 0, limit_value, 1, 10, 0)  # set the 
new value and upper limit
    def delete_event(self, widget, event, data=None):
        # If you return FALSE in the "delete_event" signal handler,
        # GTK will emit the "destroy" signal. Returning TRUE means
        # you don't want the window to be destroyed.
        # This is useful for popping up 'are you sure you want to quit?'
        # type dialogs.
        print "delete event occurred"

        # Change FALSE to TRUE and the main window will not be destroyed
        # with a "delete_event".
        return False

    # Another callback
    def destroy(self, widget, data=None):
        Image = self.get_imageRef()

    # things to do after the instance has been created but before doing any work
    def setup(self, widget, Data):
        Image = Data[0]
        self.set_imageRef(Image)         # set the image reference
        self.limit_spin(None,None)         # set the max value allowed for 
position based on image size
    def __init__(self):
        # create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title("Add Multiple Guides")
        # When the window is given the "delete_event" signal (this is given
        # by the window manager, usually by the "close" option, or on the
        # titlebar), we ask it to call the delete_event () function
        # as defined above. The data passed to the callback
        # function is NULL and is ignored in the callback function.
        self.window.connect("delete_event", self.delete_event)

        # Here we connect the "destroy" event to a signal handler.
        # This event occurs when we call gtk_widget_destroy() on the window,
        # or if we return FALSE in the "delete_event" callback.
        self.window.connect("destroy", self.destroy)

        # Sets the border width of the window.

        # We create a box to pack widgets into. This is described in detail
        # in the "packing" section. The box is not really visible, it
        # is just used as a tool to arrange widgets.
        self.window_box = gtk.VBox(False, 0)
        self.box1 = gtk.HBox(False, 0)
        self.box2 = gtk.HBox(False, 0)
        self.box3 = gtk.HBox(False, 0)
        self.window_box.pack_start(self.box1, True, True, 10)
        self.window_box.pack_start(self.box3, True, True, 10)
        self.window_box.pack_start(self.box2, True, True, 10)

        # Creates a new button with the label "Close".
        self.button1 = gtk.Button(self.get_Labels(3))

        # When the button receives the "clicked" signal, it will call the
        # function hello() passing it None as its argument.  The hello()
        # function is defined above.
        self.button1.connect("clicked", self.hello, None)

        # This will cause the window to be destroyed by calling
        # gtk_widget_destroy(window) when "clicked".  Again, the destroy
        # signal could come from here, or the window manager.
        self.button1.connect_object("clicked", gtk.Widget.destroy, self.window)

        # This packs the button into the window (a GTK container).
        self.box2.pack_start(self.button1, True, True, 10)

        # The final step is to display this newly created widget.

        # Create the first radio button widget
        self.radio1 = gtk.RadioButton(None, self.get_Labels(0), False)
        # Create the second radio button, passing a ref to the first to define 
the group
        self.radio2 = gtk.RadioButton(self.radio1, self.get_Labels(1), False)   
        # pack them into a box
        self.box1.pack_start(self.radio1, True, True, 5)
        self.box1.pack_start(self.radio2, True, True, 5)
        # and make them visible
        # create an adjustment for the spin widget
        # At the moment the upper value is set the same as the standard new 
guide dialog
                           # value lower upper step_incr, page_incr, page_size  
        limit_value = 1000
#        limit_value = findMaxValue(self.get_imageRef(), 0)  
        self.adjustment = gtk.Adjustment(0, 0, limit_value, 1, 10, 0)
        self.set_adjustment(gtk.Adjustment(0, 0, limit_value, 1, 10, 0))
        # create a spin widget to alow user to set the position required
        self.spin_button = gtk.SpinButton(self.get_adjustment(), 
climb_rate=0.0, digits=0)
        # pack the spinbutton into the box
        self.box1.pack_start(self.spin_button, True, True, 5)
        # Create a button to add the guide when pressed
        self.button2 = gtk.Button(self.get_Labels(2))
        self.button2.connect("clicked", self.add_guide, self.spin_button)
        self.box1.pack_start(self.button2, True, True, 10)
        # create a button to remove the last guide
        self.button3 = gtk.Button(self.get_Labels(4))
        self.button3.connect("clicked", self.remove_last_guide, None)
        self.box3.pack_end(self.button3, False, False, 10)

        # connect the radio buttons to a call back
        self.radio1.connect("released", self.limit_spin, self.adjustment)
        self.radio2.connect("released", self.limit_spin, self.adjustment)

        # Show everything

    def main(self):
        # All PyGTK applications must have a gtk.main(). Control ends here
        # and waits for an event to occur (like a key press or mouse event).

# The important stuff starts here    
def pygtk_addMultipleGuides(img, drw):
    hello = addMultipleGuidesDialog()   # create an instance of the dialog
    hello.setup(None,[img,drw])         # initialise some important things
    hello.main()                        # start the gui

    "Add Multiple Guides",
    "(Version 0.1)",
    "Meetthegimp-Community http://forum.meetthegimp.org";,
    "GPL License",
    "<Image>/contributed/Add Multiple Guides",

----- End forwarded message -----
Gimp-developer mailing list

Reply via email to