Any chance of adding a menu to the toggle button widget? A use case would be the tool buttons for inkscape in which clicking an already selected button would popup a menu with secondary tool buttons. This is useful for something like xournal on maemo where a the menu chooses whether to use a pen or an erasor, and the menu allows setting the size of the tool.
Is it clear what I mean, or should I create a mockup?
Here is test implementation I did a while ago in vala:
//======================================================================
// Example of a radio button with a popup menu.
//
// Dov Grobgeld <dov grobgeld gmail com>
// Saturday 2010-01-02 21:51
//
// This code is released under the LGPL.
//----------------------------------------------------------------------
using Gtk;
public class FooRadioToolButton : Gtk.RadioToolButton {
private int click_count = 0;
private Gtk.Window popup;
private Gtk.Widget popup_contents;
public FooRadioToolButton(SList? group,
string stock,
Gtk.Widget? popup_contents = null
) {
if (group != null)
this.set_group(group);
this.stock_id = stock;
if (popup_contents != null)
set_popup_widget(popup_contents);
}
private void set_popup_widget(Gtk.Widget popup_contents)
{
this.popup_contents = popup_contents;
popup = new Gtk.Window(WindowType.POPUP);
popup.set_app_paintable(true);
popup.set_resizable(false);
popup.add(popup_contents);
// This causes the popup window to be popped down when
// clicking outside the window.
popup.button_press_event.connect((widget,event) => {
popdown();
});
}
public void popdown()
{
var display = popup.get_display();
if (display.pointer_is_grabbed())
display.pointer_ungrab (Gdk.CURRENT_TIME);
Gtk.grab_remove(popup);
popup.hide();
}
public override void clicked() {
click_count++;
stdout.printf("clicked=%d\n", click_count);
if (click_count > 1 && popup_contents != null) {
// Place the window according to room and/or preferences
var win = this.get_window();
int win_x, win_y;
win.get_position(out win_x,
out win_y);
stdout.printf("win xy Allocation x,y: (%d %d) (%d %d)\n",
win_x,
win_y,
this.allocation.x,
this.allocation.y);
stdout.printf("content size = (%d,%d)\n",
popup_contents.allocation.width,
popup_contents.allocation.height);
Gtk.Requisition req;
popup.size_request(out req);
stdout.printf("req.height = %d\n", req.height);
popup.move(win_x + this.allocation.x,
win_y + this.allocation.y - req.height);
popup.show_all();
Gtk.grab_add(popup);
Gdk.pointer_grab(popup.window,
true,
Gdk.EventMask.BUTTON_PRESS_MASK
| Gdk.EventMask.BUTTON_RELEASE_MASK
| Gdk.EventMask.POINTER_MOTION_MASK,
null,null,
Gdk.CURRENT_TIME);
// // tbd - popup a menu
// var menu = new Gtk.Menu();
// var img_menu_item = new ImageMenuItem();
// var img = new Image.from_file("/home/dov/pictures/maja.pgm");
// img_menu_item.set_image(img);
// menu.append(img_menu_item);
// menu.show_all();
// menu.popup(null,null,null,0,0);
}
}
public override void toggled() {
click_count=0;
}
}
public class MyApp : Gtk.Window {
construct {
this.destroy += Gtk.main_quit;
this.set_size_request(800,300);
var vbox = new VBox(false, 0);
this.add(vbox);
// A toolbar that will be popped up
var popup_toolbar = new Toolbar();
popup_toolbar.set_style(ToolbarStyle.ICONS);
popup_toolbar.set_show_arrow(false);
popup_toolbar.set_orientation(Orientation.VERTICAL);
unowned SList group = null;
string[] stocks = { Gtk.STOCK_APPLY,
Gtk.STOCK_STOP,
Gtk.STOCK_OPEN
};
Gtk.Widget[] pop_buttons = new Gtk.Widget[3];
for (int i=0; i<3; i++) {
RadioToolButton radio;
var b = new Button.with_label("Press me");
b.clicked.connect((w) => {
stdout.printf("button press!\n");
});
radio = new FooRadioToolButton(group, stocks[i]);
group = radio.get_group();
popup_toolbar.insert(radio, -1);
}
popup_toolbar.show_all();
var toolbar = new Toolbar();
toolbar.set_style(ToolbarStyle.ICONS);
group = null;
stocks = { Gtk.STOCK_EXECUTE,
Gtk.STOCK_OK };
for (int i=0; i<2; i++) {
RadioToolButton radio;
var b = new Button.with_label("Press me");
b.clicked.connect((w) => {
stdout.printf("button press!\n");
});
if (i==0) {
radio = new FooRadioToolButton(group, stocks[i], popup_toolbar);
}
else {
radio = new Gtk.RadioToolButton.from_stock(group, stocks[i]);
}
group = radio.get_group();
toolbar.insert(radio, -1);
}
toolbar.show();
vbox.pack_end(toolbar, false, false, 0);
}
}
int main(string[] args) {
Gtk.init(ref args);
var app = new MyApp();
app.show_all();
Gtk.main();
return 0;
}
Regards,
Dov
On Wed, Mar 3, 2010 at 06:23, Christian Hergert
<chris dronelabs com> wrote:
On Mar 2, 2010, at 2:55 PM, Filippo Argiolas wrote:
To be fair I don't think you completely got what I was trying to say.
I cited the breadcrumb because it's usually visually styled as a group
of buttons (that behave like radios plus some more complicated logic)
grouped together into a "single big button" that contains several
ones. If you look at the screenshots in that link I think it's pretty
clear, I'd like a way to "visually merge" together several buttons
into a grouping container. Look at this mockup too, it should make it
clear enough:
http://people.gnome.org/~fargiolas/toggle-button-mockup.png
I don't want to detract from your conversation, but in case you haven't written up code for that toggle button mockup, I wrote one last year (in python, c, and c#).
http://audidude.com/?p=61
http://github.com/chergert/custom-gtk-widgets/tree/master/gtkmodebutton
Cheers,
-- Christian