Supporting the Mac OS menubar in JavaFX
steve.x.northover at oracle.com
steve.x.northover at oracle.com
Thu Jan 12 12:55:34 PST 2012
What we are really talking about here is whether we are either:
1) distributing the native state to many potential different menu bars
(yes, I know that a real application will only have one menu bar per
stage, but the API allows the multiple to be specified and we must
handle it) and allowing the application to position menu bars in the
scene (with a "zero size" supplied for free due to the native property)
or
2) having the native state in one place (no ambiguity) and having FX
position the menu bar in a standard place (no "zero size" magic).
Certainly, with no API on Stage, there are no decisions about where to
place the menu bar when non-native and the API is called (ie. if we have
Stage.setMenuBarArea(), then we need to write code in the non-native
case for Stage in places that we may not yet support a native menu bar
or may never support a native menu bar.
I'm still not happy, but the CSS argument is a good one. I'm not happy,
but let's go with the property and see how this one plays out.
Steve
On 12/01/2012 3:16 PM, Richard Bair wrote:
> Hi Steve,
>
> I know what you mean about wanting to have an API without error modes. In this case though I think it is a little restricting. I might for example want to provide different stylesheets for different platforms. On one platform I have the menu bar at the top in its "usual" place, but on another platform I might have the menu bar on the left or bottom. I might want to use CSS to toggle "use native please" vs. on another platform I would use CSS to just use emulated. Because setting stage.setMenuBar(node) would be a hard-coded call, I wouldn't have this flexibility to style it from CSS.
>
> I think it should be called "useSystemMenuBar" or "useNativeMenuBar" over "useGlobalMenuBar" -- just because we might want to allow you to use native menus on windows instead of emulated and they would be per-stage rather than "global" or application wide.
>
> Thanks
> Richard
>
> On Jan 9, 2012, at 12:11 PM, steve.x.northover at oracle.com wrote:
>
>> Having the property on MenuBar rather than the API on stage means that you can set the property on two menu bars at the same time and FX must choose one. There can't be two native menu bars at the same time on the same stage so why have API that allows it? Having an API in stage means that an application can easily query what the current menu bar is or whether there is a menu bar rather than performing the same search that FX does.
>>
>> I suppose that you could add API in stage later but that would mean two sets of API to do the same thing and the question about which one would win when they are mixed and matched.
>>
>> Steve
>>
>> On 09/01/2012 2:50 PM, Paru Somashekar wrote:
>>> On 1/9/12 10:45 AM, steve.x.northover at oracle.com wrote:
>>>> Hello!
>>>>
>>>> I believe there are problems with 1) and 2). First off, there is no way to mix and match. For example, suppose I want some shells to use the global menu bar and others to use a local menu bar. Further, application code may put trimmings around a menu bar and when the menu bar is "hoisted up", the window might look strange.
>>> The useGlobalMenuBar property on Menubar would not be a static property. So we could mix and match as the property is per MenuBar.
>>>> If we are doing 3), I think a better approach would be for the application to decide whether it is using native menu bars or not by explicitly setting a menu bar on a stage. It makes sense because on platforms like Windows and GTK, there is a one-to-one mapping between stage and menu bar so why not make this explicit in the API? One of the problems with having API in Stage is that we don't want a reference to MenuBar. Why don't we define something like Stage.setMenyBarArea() or something like that to take a Node or another type instead?
>>> We were thinking that for this release, having a property on MenuBar which is set to false by default will ensure backwards and forwards compatibility (with minimal code changes for the application developer). If we want to change that to an API on Stage for a future release - it could be easily done without breaking compatibility.
>>>
>>> thanks,
>>> Paru.
>>>
>>>> Steve
>>>>
>>>> On 09/01/2012 1:30 PM, Paru Somashekar wrote:
>>>>> Hello All,
>>>>>
>>>>> The following is the proposal (follow up from previous email by Jonathan) from UI Controls team towards an API to support native Mac OS menubar.
>>>>>
>>>>> 1) A new property useGlobalMenuBar would be added to MenuBar class whose initial value will be set to a default dictated by a property settable via CSS ( and set to false by default). Once again, for the first cut of this support in this release, this will be the only public API for native menubar support.
>>>>>
>>>>> 2) In the case when we have multiple Menubars specified on a stage, the first one wins and will be made global, i.e. provided the platform supports native integration and useGlobalMenuBar is set to true.
>>>>>
>>>>> 3) As mentioned in a previous email by Jonathan, we will have hooks to switch between stages when they become active and swap menu bars. In the case when we don’t find a Menubar, it will be nulled out. This is the path we are choosing for now and we realize that we can change this later with no backward compatibility issues.
>>>>> We are extending the same concept to the scenario where, when the last window closes; it will be nulled out as well and hence there is no concept of a default menubar.
>>>>>
>>>>> thanks,
>>>>> Paru.
>>>>>
>>>>> On 12/14/11 5:20 PM, Kevin Rushforth wrote:
>>>>>> An API on Stage to set a menu bar has a certain elegance, plus it gets around the backward compatibility and inconsistency problems that having "native" on by default would create. Unfortunately, as Rich pointed out earlier, it creates an unwanted dependency from a modularity point of view since Stage will be in the base module and should not depend on anything in controls.
>>>>>>
>>>>>> -- Kevin
>>>>>>
>>>>>>
>>>>>> steve.x.northover at oracle.com wrote:
>>>>>>> Hello all,
>>>>>>>
>>>>>>> How about an API in Stage where you set the menu bar for the stage? This is the menu that you wish to be native and the application very is clear about this. There can only be one real menu bar on Windows. Application code can ask for the menu bar and add items to it. If you have a property, application code needs to do the same search that FX does to determine if there is an active menu bar.
>>>>>>>
>>>>>>> Here is what I think about focus: On the Mac, when a stage gets focus, it sets the native menu bar. When it loses focus, it clears the native menu bar. Retaining the menu from the previous stage is unlikely to be the right thing to do as an application can have many different stages around and only the application can know whether the current menu bar applies to a stage.
>>>>>>>
>>>>>>> Steve
>>>>>>>
>>>>>>> On 14/12/2011 6:31 PM, Jonathan Giles wrote:
>>>>>>>> Hi All,
>>>>>>>>
>>>>>>>> Here's an update from the UI controls team as to how we see the native Mac OS menubar support working. Your thoughts are appreciated.
>>>>>>>>
>>>>>>>> After discussing it again today, we think that the approach suggested by Richard in an earlier email in this thread makes the best sense, in terms of modularity and code cleanliness. I'll explain this further shortly...
>>>>>>>>
>>>>>>>> The thinking is to add a new property to javafx.scene.control.MenuBar. We haven't settled on a name, but it's something along the lines of 'native', 'global', 'globalMenuBar', 'screenMenuBar', or 'applicationMenuBar'. Whatever property name we use, we'll expand it out to have the usual set*/get*/*property methods. This would be the only public API we end up adding for native menubar support. For the remainder of this email I refer to this property as 'native'.
>>>>>>>>
>>>>>>>> This property will by default be true, indicating that on platforms where we support native integration, it'll happen by default.
>>>>>>>>
>>>>>>>> On a platform that supports native integration, we'll find the 'first' MenuBar in the scene that has the 'native' property set to true. We can't guarantee that we'll find necessarily the physically top-most MenuBar as that is really a matter of how the scenegraph is laid out. Of course, this is only a problem in situations where the scene contains multiple MenuBars where 'native' is true in more than one of them, which we hope won't often be the case. If a Scene does have multiple MenuBars with 'native' set to true, the behaviour is undefined. If the wrong MenuBar is made native, you can help provide a hint by setting 'native' to false in the relevant place(s).
>>>>>>>>
>>>>>>>> We'll also hook into the Stage and listen to the relevant events, such that when a Stage gains focus, we'll switch in any native menubars found in the scene of that stage. If no relevant MenuBar is found, then we can either retain the MenuBar from the previous stage, or null it out. I'm going to assume the former is by far going to win this vote, but feel free to surprise me.
>>>>>>>>
>>>>>>>> Using this approach, developer code should be cleaner. Your user interface should position a MenuBar where it makes sense for your application, regardless of the operating system (normally at the very top of your scene). On platforms where native integration is supported, the JavaFX-rendered MenuBar will not be rendered (although it'll likely remain in the scenegraph as a no-op control). If the 'native' property changes, we'll flick between the native and JavaFX-rendered MenuBar as expected. This approach means there is no operating system dependent code in your user interface.
>>>>>>>>
>>>>>>>> As I mentioned - we're totally open to discussion on any of these points. Any thoughts?
>>>>>>>>
>>>>>>>> -- Jonathan
>>>>>>>>
>>>>>>>> On 10/12/2011 8:56 a.m., Jonathan Giles wrote:
>>>>>>>>> Hi all,
>>>>>>>>>
>>>>>>>>> One of the things we're planning to support in JavaFX 2.1 is the native Mac OS menubar. This email is intended primarily to discuss the API one expects to see to set a MenuBar in the native Mac OS menubar area. Your feedback is sought and will be very much appreciated.
>>>>>>>>>
>>>>>>>>> The current thinking is that Application feels like the right place to specify a global, application-wide javafx.scene.control.MenuBar on. It could be assumed that if a developer were to set this property, and the operating system upon which the end-user was running the JavaFX application was Mac OS, that the menubar will be displayed using the native Mac OS menubar. Of course, if a developer wants a cross-platform look and feel, they could just place the MenuBar in the stage as per usual and it would display as it currently does. This approach opens up a number of questions and issues:
>>>>>>>>>
>>>>>>>>> 1) What happens in the case of the end-user being on Windows? Is the Application.MenuBar ignored, or is it automagically added to the main Stage? (I would argue for totally ignoring it....but that leads to the next point).
>>>>>>>>> 2) This approach means there needs to be operating specific code in the UI to test whether a non-native MenuBar should be added (in the case of Windows, for example). This starts to clutter the UI code, and without careful consideration by the developer may result in needing to duplicate their MenuBar code. Is there a better approach?
>>>>>>>>>
>>>>>>>>> Another place to specify a MenuBar would be on Stage, rather than (or in addition to), Application. Having a MenuBar property on Stage would allow for the MenuBar to change based on the currently focused Stage - but I'm not certain this is desirable or even the expected behaviour of Mac OS. Therefore, I'm thinking that this is not likely to happen unless we hear otherwise.
>>>>>>>>>
>>>>>>>>> Like I said, we're at a very early exploration point in this process. The controls team is very keen to hear feedback from the community, as well as from the owners of the Application API, and the Mac OS experts on this list.
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>> -- Jonathan
More information about the openjfx-dev
mailing list