Skip to content
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

Merged
merged 1 commit into from
Dec 8, 2020

Conversation

egorzhdan
Copy link
Contributor

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.

public var image: Image?
public let image: Image?

public typealias Submenu = ContextMenu

This comment was marked as outdated.

@egorzhdan
Copy link
Contributor Author

I’ve changed the submenu structure a little bit: moved title from Menu to MenuItem for a couple reasons:

  • context menus don’t have a title
  • window title menu items are not required to have submenus, they can just act as buttons

@compnerd please let me know what you think about this!

@compnerd
Copy link
Owner

compnerd commented Nov 5, 2020

discussed offline - the API surface is likely going to revert to something that was there previously

@egorzhdan egorzhdan marked this pull request as draft November 21, 2020 20:15
@egorzhdan
Copy link
Contributor Author

(only rebased for now, will address the feedback a bit later)

@egorzhdan egorzhdan force-pushed the master branch 4 times, most recently from ea1bcb9 to c5bf2f7 Compare November 27, 2020 19:52
@@ -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: [
Copy link
Owner

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.

Copy link
Contributor Author

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.

Copy link
Owner

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?)

Copy link
Contributor Author

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.

]),
])

self.progress.addInteraction(ContextMenuInteraction(delegate: self))
Copy link
Owner

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.

Copy link
Contributor Author

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 Labels – 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.

Copy link
Owner

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!

Copy link
Contributor Author

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.

Sources/SwiftWin32/UI/Interaction.swift Outdated Show resolved Hide resolved
Sources/SwiftWin32/UI/Menu.swift Outdated Show resolved Hide resolved
Sources/SwiftWin32/UI/Menu.swift Outdated Show resolved Hide resolved
Sources/SwiftWin32/UI/Menu.swift Outdated Show resolved Hide resolved
Sources/SwiftWin32/UI/MenuElement.swift Outdated Show resolved Hide resolved
@@ -67,3 +69,48 @@ public class MenuElement {
self.image = image
}
}

internal class Win32MenuElement {
Copy link
Owner

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?

Copy link
Contributor Author

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))
                      ^ ~~~~~

Copy link
Owner

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.

Copy link
Contributor Author

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.

@egorzhdan egorzhdan force-pushed the master branch 4 times, most recently from f4484c4 to 68b0a98 Compare December 1, 2020 10:12
Comment on lines +104 to +105
} else {
subMenu = nil
Copy link
Owner

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.

Copy link
Contributor Author

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)
                                                           ^

Comment on lines +25 to +26
} else {
view.win32ContextMenu = nil
Copy link
Owner

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?

Copy link
Contributor Author

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.

@compnerd
Copy link
Owner

compnerd commented Dec 3, 2020

/azp run VS2019

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@egorzhdan egorzhdan force-pushed the master branch 2 times, most recently from 347818f to a24d8da Compare December 8, 2020 11:00
@egorzhdan egorzhdan marked this pull request as ready for review December 8, 2020 11:05
@egorzhdan egorzhdan changed the title UI: support showing basic context & window menus UI: support showing basic context menus Dec 8, 2020
@egorzhdan
Copy link
Contributor Author

I think I've addressed all the problematic parts: removed window title menus (will add as a separate PR), and fixed the code issues.

@compnerd
Copy link
Owner

compnerd commented Dec 8, 2020

/azp run VS2019

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Owner

@compnerd compnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@egorzhdan
Copy link
Contributor Author

Just added the missing file to CMakeLists, the build should pass now.

@compnerd compnerd merged commit 842d5c3 into compnerd:master Dec 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants