protected virtual void ShowDropDown() { if (HasChildren) { PopupMenu = new Gtk.Menu(); PopupMenu.Hidden += (s, o) => HideDropDown(); PopupMenu.SelectionDone += (s, e) => { var i = 0; }; Populate(PopupMenu); PopupMenu.ShowAll(); PopupMenu.Popup(null, null, delegate(Gtk.Menu menu, out int x, out int y, out bool push_in) { var all = ContentWidget.Allocation; var loc = GtkBackendHelper.ConvertToScreenCoordinates(ContentWidget, new Xwt.Point(0, all.Height)); x = (int)loc.X; y = (int)loc.Y; push_in = true; }, 0, Gtk.Global.CurrentEventTime); PopupMenu.WidthRequest = this.Widget.Allocation.Width; } }
public static PopupWindow Show(Widget reference, Xwt.Rectangle positionRect, Widget child) { var popup = new PopupWindow(child); var topLevel = (Window)reference.Toplevel; popup.DestroyWithParent = true; popup.BorderWidth = topLevel.BorderWidth; // bounds of reference widget in screen coordinates var referenceBounds = Xwt.Rectangle.Zero; // position of popup Func <Xwt.Point> calcPosition = () => { referenceBounds = new Xwt.Rectangle( GtkBackendHelper.ConvertToScreenCoordinates(reference, Xwt.Point.Zero), new Xwt.Size(reference.Allocation.Width, reference.Allocation.Height)); if (positionRect == Xwt.Rectangle.Zero) { positionRect = new Xwt.Rectangle(Xwt.Point.Zero, referenceBounds.Size); } positionRect = positionRect.Offset(referenceBounds.Location); return(new Xwt.Point(positionRect.X, positionRect.Bottom)); }; var popupPosition = calcPosition(); if (child == null) { popup.SetSizeRequest((int)referenceBounds.Width, (int)referenceBounds.Height); } else { popup.DefaultWidth = 10; child.ShowAll(); } var topLevelPos = GtkBackendHelper.ConvertToScreenCoordinates(topLevel, Xwt.Point.Zero); popup.TransientPosition = popupPosition.Offset(-topLevelPos.X, -topLevelPos.Y); Gtk.SizeAllocatedHandler sizeAllocated = (o, args) => { popup.Move((int)popupPosition.X, (int)popupPosition.Y); popup.GrabFocus(); }; popup.SizeAllocated += sizeAllocated; topLevel.AddEvents((int)Gdk.EventMask.StructureMask); topLevel.ConfigureEvent -= popup.TopLevelConfigureEvent; topLevel.ConfigureEvent += popup.TopLevelConfigureEvent; // if the mouse is moved in toplevel-window: Gtk.MotionNotifyEventHandler topLevelMotion = (s, args) => { if (topLevel == null) { return; } topLevelPos = GtkBackendHelper.ConvertToScreenCoordinates(topLevel, Xwt.Point.Zero); var referencePos = GtkBackendHelper.ConvertToScreenCoordinates(reference, Xwt.Point.Zero); // take args in sceen coordinates: var motionPos = new Xwt.Point(args.Event.XRoot, args.Event.YRoot);//topLevelPos.Offset (args.Event.X, args.Event.Y); var tolerance = popup.Tolerance; var popupSize = new Xwt.Size(popup.Allocation.Width, popup.Allocation.Height); // var refBounds = new Xwt.Rectangle (refPos, screenBounds.Size); var motionBounds = new Xwt.Rectangle( referencePos.X - tolerance.Left, referencePos.Y - tolerance.Top, popupSize.Width + tolerance.HorizontalSpacing, popupSize.Height + tolerance.VerticalSpacing); // TODO: hide if other event than move-event occurs outside of popup window // TODO: something is wrong with referencepos; maybe ConvertToScreenCoordinates has an error if (!motionBounds.Contains(motionPos)) { popup.HideAll(); } }; topLevel.MotionNotifyEvent += topLevelMotion; //ClientEvent: a message has been received from another application. popup.ShowAll(); popup.Hidden += (o, args) => { topLevel.ConfigureEvent -= popup.TopLevelConfigureEvent; topLevel.MotionNotifyEvent -= topLevelMotion; popup.ReleaseInnerWidget(); popup.Destroy(); }; return(popup); }