-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UI: support showing basic context menus #246
Conversation
Sources/UI/MenuElement.swift
Outdated
public var image: Image? | ||
public let image: Image? | ||
|
||
public typealias Submenu = ContextMenu |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
I’ve changed the submenu structure a little bit: moved
@compnerd please let me know what you think about this! |
discussed offline - the API surface is likely going to revert to something that was there previously |
(only rebased for now, will address the feedback a bit later) |
ea1bcb9
to
c5bf2f7
Compare
Examples/UICatalog/UICatalog.swift
Outdated
@@ -110,6 +110,19 @@ final class UICatalog: ApplicationDelegate, SceneDelegate { | |||
window.addSubview(self.tableview) | |||
window.addSubview(self.imageview) | |||
|
|||
window.rootViewController?.titleMenu = Menu(children: [ | |||
Menu(title: "Foo", children: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of Foo
and Bar
. What do you think of creating a UICatalog
menu (or perhaps Application
?) with an entry for Quit
?
I think it would be nice to have a mixture of predefined menu items and custom menu items.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeap, sounds good, replaced the menu with "Application", since it's right under the window title which says "UICatalog".
If I understand the API design correctly, the logic for suggested menu items would belong somewhere in ContextMenuConfiguration
, but I haven't really touched it yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I realized that you are looking at context menus, not application menus. In such a case, perhaps the application doesn't make sense :-(. But creating a new UI element to attach the context menu makes sense (perhaps a TextField?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I've mixed up the menu types in my comment above, sorry. The titleMenu
field is about window title menus, not context menus, so ContextMenuConfiguration
doesn't apply here.
Examples/UICatalog/UICatalog.swift
Outdated
]), | ||
]) | ||
|
||
self.progress.addInteraction(ContextMenuInteraction(delegate: self)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of adding an additional label to demonstrate the context menu? I'd like to eventually migrate to a more fleshed out application with a view controller per type of control and demonstrate different behaviors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out the menu logic doesn't actually work for Label
s – the WM_CONTEXTMENU
events are dispatched to a Window
containing the label instead of the label itself.
We'll probably need a LabelProxy
to be able to handle the events properly, I'll add it in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the proxy sounds good to me, and as a separate PR sounds perfect!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately adding the proxy didn't help, but wrapping the label in a view solves the issue. Sent #306.
@@ -67,3 +69,48 @@ public class MenuElement { | |||
self.image = image | |||
} | |||
} | |||
|
|||
internal class Win32MenuElement { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there reference semantics that are needed, or can we use value semantics here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're passing a reference to Win32MenuElement.info
as a parameter to InsertMenuItemW
on Menu.swift:303
, that won't compile if Win32MenuElement
is a struct.
Menu.swift:303:23: error: cannot pass immutable value as inout argument: 'child' is a 'let' constant
&(child.info))
^ ~~~~~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, what if you make children
a var
instead? I think that it might be possible to get away with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, that doesn't help, the same error occurs. That's probably because even though children
is mutable, its elements still need mutating
keyword for modifying operations.
f4484c4
to
68b0a98
Compare
} else { | ||
subMenu = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unnecessary, the declaration should be initialized to nil
anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I remove the else
block, it stops compiling:
swift-win32\Sources\SwiftWin32\UI\MenuElement.swift:105:60: error: constant 'subMenu' used before being initialized
return Win32MenuElement(title: element.title, subMenu: subMenu, fType: MFT_STRING)
^
} else { | ||
view.win32ContextMenu = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be need right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is executed if the menu was non-nil
during previous contextMenuInteraction
invocation, but is nil
now and shouldn't be shown. The assignment also removes the reference to the outdated menu, allowing it to deinit if not referenced anywhere else.
/azp run VS2019 |
Azure Pipelines successfully started running 1 pipeline(s). |
347818f
to
a24d8da
Compare
I think I've addressed all the problematic parts: removed window title menus (will add as a separate PR), and fixed the code issues. |
/azp run VS2019 |
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Just added the missing file to CMakeLists, the build should pass now. |
This change adds support for basic context menus (attached to a
View
instance) and window title menus. For both types of menus submenus are supported.