Comments (10)
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:
- Adobe AIR (http://www.adobe.com/devnet/air/ajax/quickstart/articles/adding_menus.html)
- Appcelerator Titanium: http://developer.appcelerator.com/apidoc/desktop/latest/Titanium.UI.createMenu-method.html (see http://developer.appcelerator.com/apidoc/desktop/latest/Titanium.UI-module for the entire 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.
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.
ok, so I did a little research last night and think I have a proposal.
Here are the conclusions I've got:
- There's no programatic way to manipulate application menus
- #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)
- 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.
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.
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.
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.
@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.
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:
- Specification of initial menu structure
- adding a menu item in a specific place
- removing a menu item
- 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.
hi Lloyd, please take a look at my implementation that is added to my pull request: #53
Have fun!
from chromeless.
merged! all we need is a little documentation around menu support.
from chromeless.
Related Issues (20)
- Solaris SPARC support
- localStorage doesnt work with enableSystemPrivileges HOT 1
- Add special keys to hotkey api
- IndexedDB doesn't work HOT 3
- Error when Installing on Mac HOT 4
- jQuery Include fails when enableSystemPrivileges HOT 2
- Webcontent.inject fails when the content is loaded from remote webserver HOT 1
- The window size shoud be able to change browser code.
- LSOpenURLsWithRole failed on first run HOT 4
- Drag and Drop fullpath HOT 1
- window.top is the application window
- how could i make chromeless to work without proxy
- installation problem with fetching xulrunner HOT 2
- clearing cache in chromeless
- points to wrong xulrunner repository
- update for B2G
- Want to know HOT 3
- hAS cHROMELESS BEEN tOTALLY aBANDONED?????? HOT 3
- CODE_OF_CONDUCT.md file missing
- Is this project dead?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from chromeless.