Coder Social home page Coder Social logo

Comments (10)

mikedeboer avatar mikedeboer commented on May 24, 2024

Luckily you're not the first to be faced with this problem ;)

To examples of APIs that have evolved in two different technologies with a JS API:

Personally I like the Titanium approach a lot because of its simplicity. Two pages of docs and I know what to do. AIR is more concise and probably supports more variations and use-cases, but the docs are at least 10pp and I'm still not sure where to start. But that's just my 2cts ;)

from chromeless.

mikedeboer avatar mikedeboer commented on May 24, 2024

I did some more investigation in this area and found that Prism already had this functionality implemented. Matt Gertner is working on an FF4/ xulrunner 2 compatible version of Prism, called Refractor, and he will let me know when it's available for testing. Even so, I don't like a dependency like that. Matt is not affiliated with Mozilla and there might be an interest for Chromeless to port the Prism code over to this project eventually.
But that would require someone with knowledge about C++ and compiling xulrunner.

Thoughts?

from chromeless.

lloyd avatar lloyd commented on May 24, 2024

ok, so I did a little research last night and think I have a proposal.

Here are the conclusions I've got:

  1. There's no programatic way to manipulate application menus
  2. #1 is probably due to the fact that application menus work so differently on OSX and windows (in the former its the top bar, in the latter its embedded into the window and may be hidden)
  3. XULRunner renders windows based on xul tags embedded in the document

As far as I can tell, prism manipulates window controls by programmatically manipulating dom elements under toolbox > menu at the top level. AFAICT, prism can make some assumptions and take some shortcuts given that its customized for site specific browsing, not general application development.

Given all this, I propose the following implementation tactics:

  • Each chromeless window will become a proper window element, with embedded toolbox and browser:

    ...

    • as a result of this change, there should be zero impact on browser code
    • an arbitrary menu api exposed as commonjs can be exposed to browsercode (mike's proposed some) - this involves a convenient way of specifying the hierarchy, and of specifying event listeners to be invoked when items are selected
    • the menu api will be implemented with javascript that can extract the toolbox tag from the outer xul node and manipulate its contents to match the hierarchy provided by browser code
    • an application on windows may simply enable the window level menu toolbar
    • for each window spawned by an application, the browser code can determine whether or not to display the menu toolbar
    • a fallout of the previous two points is that a developer may chose on windows (and linux) to implement their entire menu system in HTML, or they may use the chromeless provided toolbar
    • on OSX, developers will use the toolbar system
    • For the first pass implementation, we'll say there's one menu per application, rather than one menu per window (which XUL supports). (Unless someone has a compelling and common use case where the additional control would be needed)

I've already done a bit of a proof of concept and think that this approach should work. Thoughts?

from chromeless.

lloyd avatar lloyd commented on May 24, 2024

An update and request for thoughts on API. I've got menu specification working on the menu_api branch using the techniques proposed above, and it looks pretty good. I took a look at adobe and at titanium APIs for manipulating app menus and considered both a programmatic (build up lotsa hierarchical objects) and a declarative api (specify menu structure by providing a hierarchical javascript datastructure. At the moment I'm leaning toward the latter (and have it mostly implemented). Here's some sample code of both approaches:

https://github.com/mozilla/chromeless/tree/menu_api/tests/menu

thoughts?

from chromeless.

mikedeboer avatar mikedeboer commented on May 24, 2024

Hi Lloyd, great progress! I see now that Prism has the exact same approach as you describe above.
About the proposed APIs, I think that it's VERY important that you can programmatically alter the menu structure during the apps lifetime. It seems that the static menu definition would not fit this requirement, thus the programmatic API would have my vote. However, it does not need to be less declarative and nice as the JS struct API! If you like, I'd like to take a shot at implementing the complete menu API that is flexible, yet declarative.
If you can give me some pointers and a working base, I can do the rest in my spare time. Then I'll build a prototype and show you my API proposal - to see if you like it ;)

I hope you agree!

from chromeless.

lloyd avatar lloyd commented on May 24, 2024

yo mike!

With the declarative API I was expecting that it would be possible to change the structure at runtime, simply by re-setting the menu.

What I've got in the menu_api branch right now defines a single property that can be get or set: require('menu').appMenu. At the time its set the code will verify the javascript structure and throw an exception if there's any semantic errors.

Please have a look and give me your thoughts on the api, beyond this property, app code can add listeners, optionally providing the "path" to the menu item that a listener should be bound to:

menu.addListener([ 'File', '*' ], function(itemSelected) { ... });

So it's very functional, the work left is to test that with the restrucuturing I haven't broken anything and to add keyboard shortcuts. What I've found is that we probably want to implement a general means of binding shortcut keys now, and that the menu.js and keybinding.js implementations should privately interact so that as a developer you can build a menu item and simply specify shortcuts in that menu structure. Additionally, you can explicitly bind keys.

any contributions are totally welcome! My goal is to have complete keybinding and menu implementations by end of next week.

from chromeless.

mikedeboer avatar mikedeboer commented on May 24, 2024

@lloyd, I'm afraid that I'm not in favor of the declarative approach, allow me to try and explain to you why:

  • Menu structures have the tendency to grow exceedingly large with the size and complexity of the apps that Chromeless will host. When a mutation to the menu occurs and that results in an entire redraw of the menus, that will become an expensive operation.
  • When you don't want mutation events to require a complete redraw, you have to maintain state within the Menu API layer to allow it to perform partial redraw or in-place mutation through the DOM API. Maintaining such state is complex, because you have the diff the entire menu-tree with the new/ updated state and execute actions based on the resulting changeset.
  • In Cloud9, everything is an extension that is loaded dynamically and each extension is responsible for updating the main menu entries. So, when you combine Cloud9 with the declarative API, you can imagine that there will be about 40 menu redraws at application load-time, or the menu diff-ing mechanism must be flawless.

What I meant with my 'mixed-mode' API is the following:

var file = new menu.Menu({
    caption: "File",
    hotkey: "f",
    onClick: function(e) {...},
    children: [
        new menu.Menu({ label: "Open...", hotkey: "o" }),
        new menu.Seperator(),
        new menu.Menu({ label: "Quit", hotkey: "q" })
    ]
});

See? And on the 'children' object you can simply implement the Array functions like 'push', 'pop', 'splice', etc. to do mutations on the menu tree, so that no-one needs to learn a new API! And you can also do item.label = "Som'else";, because you can use the awesomeness of getters and setters...

What do you think?

from chromeless.

lloyd avatar lloyd commented on May 24, 2024

Hey mike! I totally understand your concerns about performance. To try to get an understanding of what we're really looking at, I put together a performance test for menu update:

https://github.com/mozilla/chromeless/blob/menu_api/tests/menu/perf_test.html

Results? On my macbook pro An update of a menu with 49 (7 top level with 7 kids each) entries takes about 10ms.

So I'm kinda thinking that our focus for this first pass should be something dead simple that's really nice to use. I think there's about four use cases that could drive the design:

  1. Specification of initial menu structure
  2. adding a menu item in a specific place
  3. removing a menu item
  4. dis/en abling a specific item

My guess here is that a nice convenient api for these cases might just magically be something that could also be implemented in an efficient manner. I'm inspired by jquery's use of selectors for DOM manipulation :)

I've got to give this a rest for a while, so I encourage you to play with apis if your imagination is sparked, the menu_api branch is in a nice state for play.

I'll pick up again midweek and we can lock in a specific initial api approach and get it done.

from chromeless.

mikedeboer avatar mikedeboer commented on May 24, 2024

hi Lloyd, please take a look at my implementation that is added to my pull request: #53

Have fun!

from chromeless.

lloyd avatar lloyd commented on May 24, 2024

merged! all we need is a little documentation around menu support.

from chromeless.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.