RSS/Atom feed Twitter
Site is read-only, email is disabled

[oliver@first.in-berlin.de: Re: small Wishlist regarding Guides]

This discussion is connected to the gimp-developer-list.gnome.org mailing list which is provided by the GIMP developers and not related to gimpusers.com.

This is a read-only list on gimpusers.com so this discussion thread is read-only, too.

1 of 1 message available
Toggle history

Please log in to manage your subscriptions.

[oliver@first.in-berlin.de: Re: small Wishlist regarding Guides] oliver@first.in-berlin.de 01 Aug 23:44
oliver@first.in-berlin.de
2010-08-01 23:44:28 UTC (over 14 years ago)

[oliver@first.in-berlin.de: Re: small Wishlist regarding Guides]

hello,

this should have been sent to the list...

so my answer forwarded to here.

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

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

Hi,

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 admin).

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.

Ciao, Oliver

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, Message) dialog.run()
dialog.hide()

def findMaxDimensionOfImage(Image, Direction): if (Direction == 0):
limit_value = pdb.gimp_image_height(Image) -1 else:
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(), position) else:
currentGuide = pdb.gimp_image_add_vguide(self.get_imageRef(), position) self.set_thisGuide(currentGuide)

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()
Image.undo_group_end()
gtk.main_quit()

# 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 Image.undo_group_start()

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. self.window.set_border_width(10)

# 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.window.add(self.window_box)
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. self.button1.show()

# 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
self.radio1.show()
self.radio2.show()
self.set_radioGroup(self.radio1.get_group())
# 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) self.spin_button.show()

# 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) self.button2.show()

# 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) self.button3.show()

# 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 self.box1.show()
self.box2.show()
self.box3.show()
self.window_box.show()
self.window.show()

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). gtk.main()

# 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

register( "python-fu-pygtk_addMultipleGuides", "Add Multiple Guides",
"(Version 0.1)",
"Meetthegimp-Community http://forum.meetthegimp.org", "GPL License",
"2009",
"/contributed/Add Multiple Guides", "*",
[],
[],
pygtk_addMultipleGuides)

main()

----- End forwarded message -----