[gnome-contacts] Add menu button



commit f7e921ecfbf046d2640c31026e20077890b51768
Author: Alexander Larsson <alexl redhat com>
Date:   Wed May 25 20:18:24 2011 +0200

    Add menu button

 src/Makefile.am               |    1 +
 src/contacts-app.vala         |   26 ++++--
 src/contacts-menu-button.vala |  182 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 200 insertions(+), 9 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 8a8e121..4df38bf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,7 @@ gnome_contacts_SOURCES = \
 	contacts-app.vala \
 	contacts-contact.vala \
 	contacts-starred-button.vala \
+	contacts-menu-button.vala \
 	contacts-hover-image.vala \
 	contacts-store.vala \
 	contacts-clickable.vala \
diff --git a/src/contacts-app.vala b/src/contacts-app.vala
index 6318cb6..0de1342 100644
--- a/src/contacts-app.vala
+++ b/src/contacts-app.vala
@@ -474,15 +474,23 @@ public class Contacts.App : Window {
     button = new Button.with_label(_("Edit"));
     bbox.pack_start (button, false, false, 0);
 
-    button = new Button ();
-    var label = new Label (_("More"));
-    var arrow = new Arrow (ArrowType.DOWN, ShadowType.NONE);
-    var hbox2 = new Box (Orientation.HORIZONTAL, 0);
-    hbox2.pack_start (label, true, false, 0);
-    hbox2.pack_start (arrow, false, false, 0);
-    button.add (hbox2);
-    bbox.pack_end (button, false, false, 0);
-    bbox.set_child_secondary (button, true);
+    MenuButton menu_button = new MenuButton (_("More"));
+
+    bbox.pack_end (menu_button, false, false, 0);
+    bbox.set_child_secondary (menu_button, true);
+
+    var menu = new Menu ();
+    var mi = new MenuItem.with_label (_("Add/Remove linked contacts..."));
+    menu.append (mi);
+    mi.show ();
+    mi = new MenuItem.with_label (_("Send..."));
+    menu.append (mi);
+    mi.show ();
+    mi = new MenuItem.with_label (_("Delete"));
+    menu.append (mi);
+    mi.show ();
+
+    menu_button.set_menu (menu);
 
     grid.show_all ();
   }
diff --git a/src/contacts-menu-button.vala b/src/contacts-menu-button.vala
new file mode 100644
index 0000000..9d29808
--- /dev/null
+++ b/src/contacts-menu-button.vala
@@ -0,0 +1,182 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
+/*
+ * Copyright (C) 2011 Alexander Larsson <alexl redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+using Gtk;
+
+public class Contacts.MenuButton : ToggleButton  {
+  Menu? menu;
+  bool popup_in_progress;
+
+  public MenuButton (string label) {
+    set_focus_on_click (false);
+
+    var label_widget = new Label (label);
+    var arrow = new Arrow (ArrowType.DOWN, ShadowType.NONE);
+    var grid = new Grid ();
+    grid.set_orientation (Orientation.HORIZONTAL);
+    grid.add (label_widget);
+    grid.add (arrow);
+    grid.set_row_spacing (3);
+    grid.set_hexpand (true);
+    grid.set_halign (Align.CENTER);
+    this.add (grid);
+  }
+
+  ~MenuButton () {
+    set_menu (null);
+  }
+
+  private void menu_position (Menu menu, out int x, out int y, out bool push_in) {
+    Allocation allocation;
+    get_allocation (out allocation);
+
+    int sx = 0;
+    int sy = 0;
+
+    if (!get_has_window ()) {
+      sx += allocation.x;
+      sy += allocation.y;
+    }
+
+    get_window ().get_root_coords (sx, sy, out sx, out sy);
+
+    Requisition menu_req;
+    Gdk.Rectangle monitor;
+
+    menu.get_preferred_size (null, out menu_req);
+
+    if (get_direction () == TextDirection.LTR)
+      x = sx;
+    else
+      x = sx + allocation.width - menu_req.width;
+    y = sy;
+
+    var window = get_window ();
+    var screen = get_screen ();
+    var monitor_num = screen.get_monitor_at_window (window);
+    if (monitor_num < 0)
+      monitor_num = 0;
+    screen.get_monitor_geometry (monitor_num, out monitor);
+
+    if (x < monitor.x)
+      x = monitor.x;
+    else if (x + menu_req.width > monitor.x + monitor.width)
+      x = monitor.x + monitor.width - menu_req.width;
+
+    if (monitor.y + monitor.height - y - allocation.height >= menu_req.height)
+      y += allocation.height;
+    else if (y - monitor.y >= menu_req.height)
+      y -= menu_req.height;
+    else if (monitor.y + monitor.height - y - allocation.height > y - monitor.y)
+      y += allocation.height;
+    else
+      y -= menu_req.height;
+
+    menu.set_monitor (monitor_num);
+
+    Window? toplevel = menu.get_parent() as Window;
+    if (toplevel != null && !toplevel.get_visible())
+      toplevel.set_type_hint (Gdk.WindowTypeHint.DROPDOWN_MENU);
+
+    push_in = false;
+  }
+
+  public override void toggled () {
+    if (get_active ()) {
+      if (!popup_in_progress)
+	menu.popup (null, null, menu_position, 1, Gtk.get_current_event_time ());
+    } else {
+      menu.popdown ();
+    }
+  }
+
+  public override bool button_press_event (Gdk.EventButton event) {
+    var ewidget = Gtk.get_event_widget ((Gdk.Event)(&event));
+
+    if (ewidget != this ||
+	get_active ())
+      return false;
+
+    menu.popup (null, null, menu_position, 1, Gtk.get_current_event_time ());
+    set_active (true);
+    popup_in_progress = true;
+    return true;
+  }
+
+  public override bool button_release_event (Gdk.EventButton event) {
+    bool popup_in_progress_saved = popup_in_progress;
+    popup_in_progress = false;
+
+    var ewidget = Gtk.get_event_widget ((Gdk.Event)(&event));
+
+    if (ewidget == this &&
+	!popup_in_progress_saved &&
+	get_active ()) {
+      menu.popdown ();
+      return true;
+    }
+    if (ewidget != this)    {
+      menu.popdown ();
+      return true;
+    }
+    return false;
+  }
+
+  private void menu_show (Widget menu) {
+    popup_in_progress = true;
+    set_active (true);
+    popup_in_progress = false;
+  }
+
+  private void menu_hide (Widget menu) {
+    set_active (false);
+  }
+
+  private void menu_detach (Menu menu) {
+  }
+
+  public void set_menu (Menu? menu) {
+    if (this.menu != null) {
+      this.menu.show.disconnect (menu_show);
+      this.menu.hide.disconnect (menu_hide);
+      this.menu.detach ();
+    }
+
+    this.menu = menu;
+
+    if (this.menu != null) {
+      this.menu.show.connect (menu_show);
+      this.menu.hide.connect (menu_hide);
+      this.menu.attach_to_widget (this, menu_detach);
+    }
+  }
+
+  public override bool draw (Cairo.Context cr) {
+    var context = get_style_context ();
+    context.save ();
+    if (get_active ()) {
+      context.add_class (STYLE_CLASS_MENUBAR);
+      context.add_class (STYLE_CLASS_MENUITEM);
+    }
+    base.draw (cr);
+    context.restore ();
+    return false;
+  }
+
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]