2
// MenuButtonBackend.cs
5
// Lluis Sanchez <lluis@xamarin.com>
6
// Michael Hutchinson <mhutch@xamarin.com>
8
// Copyright (c) 2011 Xamarin Inc
10
// Permission is hereby granted, free of charge, to any person obtaining a copy
11
// of this software and associated documentation files (the "Software"), to deal
12
// in the Software without restriction, including without limitation the rights
13
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
// copies of the Software, and to permit persons to whom the Software is
15
// furnished to do so, subject to the following conditions:
17
// The above copyright notice and this permission notice shall be included in
18
// all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31
namespace Xwt.GtkBackend
33
public class MenuButtonBackend: ButtonBackend, IMenuButtonBackend
37
public MenuButtonBackend ()
41
public override void Initialize ()
44
Widget.ButtonPressEvent += HandleClicked;
45
((Gtk.Widget)Widget).StateChanged += HandleStateChanged;
48
new IMenuButtonEventSink EventSink {
49
get { return (IMenuButtonEventSink)base.EventSink; }
53
void HandleClicked (object sender, Gtk.ButtonPressEventArgs e)
55
if (e.Event.Button != 1)
58
Gtk.Menu menu = CreateMenu ();
63
//make sure the button looks depressed
64
Gtk.ReliefStyle oldRelief = Widget.Relief;
65
Widget.Relief = Gtk.ReliefStyle.Normal;
67
//clean up after the menu's done
68
menu.Hidden += delegate {
69
Widget.Relief = oldRelief ;
71
((Gtk.Widget)Widget).State = Gtk.StateType.Normal;
73
//FIXME: for some reason the menu's children don't get activated if we destroy
74
//directly here, so use a timeout to delay it
75
GLib.Timeout.Add (100, delegate {
80
menu.Popup (null, null, PositionFunc, 1, Gtk.Global.CurrentEventTime);
84
void HandleStateChanged (object o, Gtk.StateChangedArgs args)
86
Gtk.Widget w = (Gtk.Widget)Widget;
87
//while the menu's open, make sure the button looks depressed
88
if (isOpen && w.State != Gtk.StateType.Active)
89
w.State = Gtk.StateType.Active;
92
void PositionFunc (Gtk.Menu mn, out int x, out int y, out bool push_in)
94
Gtk.Widget w = (Gtk.Widget)Widget;
95
w.GdkWindow.GetOrigin (out x, out y);
96
Gdk.Rectangle rect = w.Allocation;
98
y += rect.Y + rect.Height;
100
//if the menu would be off the bottom of the screen, "drop" it upwards
101
if (y + mn.Requisition.Height > w.Screen.Height) {
102
y -= mn.Requisition.Height;
106
//let GTK reposition the button if it still doesn't fit on the screen
110
Gtk.Menu CreateMenu ()
112
MenuBackend m = null;
113
Toolkit.Invoke (delegate {
114
m = (MenuBackend) EventSink.OnCreateMenu ();
116
return m != null ? m.Menu : null;