Skip to content

Commit dbbd5df

Browse files
hansonrhansonr
authored andcommitted
menus - SwingJS-site.zip
- better alignment and sizes of checkboxs and radiobtns - adds dynamic adding and removing of menu items - adds MenuListener events
1 parent 2439f08 commit dbbd5df

File tree

15 files changed

+284
-179
lines changed

15 files changed

+284
-179
lines changed
347 Bytes
Binary file not shown.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20181116031148
1+
20181117132055
347 Bytes
Binary file not shown.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20181116031148
1+
20181117132055
347 Bytes
Binary file not shown.

sources/net.sf.j2s.java.core/src/swingjs/api/js/JSSwingMenu.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ public interface JSSwingMenu {
88
void hideMenu(JPopupMenu menu);
99
void setMenu(JPopupMenu menu);
1010
void showMenu(JPopupMenu menu, int x, int y);
11+
void updateMenu(JPopupMenu menu);
12+
void updateMenuItem(JPopupMenu menu, DOMNode domNode);
1113

1214

1315
}

sources/net.sf.j2s.java.core/src/swingjs/jquery/j2sMenu.js

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,16 @@ try{
3030
role:"menu",
3131
blur:null,
3232
focus:null,
33-
select:null},
34-
_create:function(){this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length)
33+
select:null
34+
},
35+
36+
37+
_create:function(){
38+
39+
if (typeof this.options.delay == "number")
40+
this.delay = this.options.delay;
41+
42+
this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length)
3543
.attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),
3644
this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},
3745
"click .ui-state-disabled > a":function(e){e.preventDefault()},
@@ -44,16 +52,21 @@ try{
4452
this._on(this.document,{
4553
click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),n=!1}})},
4654

47-
48-
4955
_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},
5056
_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},
5157
_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},
5258
refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus);r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),r=t.prev("a"),i=e("<span>").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-+GG+GG\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},
5359
_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},
5460
focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},
5561
_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},
56-
blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},
62+
blur:function(e,t){
63+
64+
if (this.active && typeof t == "undefined" && e.relatedTarget && e.relatedTarget.getAttribute("role") != "presentation") {
65+
this.element.hide();
66+
}
67+
68+
69+
t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},
5770
_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},
5871
_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},
5972
collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},
@@ -181,6 +194,38 @@ Swing.initMenuItem = function(item) {
181194
item.icon && (item.icon = '<img src="' + item._applet._j2sPath + '/' + item.icon + '" style="max-height: 20px;" />')
182195
}
183196

197+
Swing.updateMenu = function(menu) {
198+
if (menu.uiClassID) {
199+
// for SwingJS the top node is domNode itself, which is already <ul>
200+
var node = menu.ui.domNode;
201+
if (node != menu.$ulTop[0]) {
202+
if (menu.$ulTop) {
203+
//bindMenuActionCommands(menu._actionEvent, menu, false);
204+
menu.$ulTop.remove();
205+
}
206+
menu.setContainer(J2S.$(node));
207+
J2S.$(node).addClass("swingjsPopupMenu");
208+
}
209+
J2S.$after("body",node);
210+
node.style.display = "block";
211+
} else {
212+
menu.$ulTop.html(menu.toHTML());
213+
bindMenuActionCommands(menu._actionEvent, menu, true);
214+
}
215+
menu.$ulTop.menu({delay:300}).menu('refresh');
216+
if (menu.uiClassID)
217+
menu.$ulTop.find("[role=menuitem]").each(function(){Swing.updateMenuItem(menu, this);});
218+
menu._tainted = false;
219+
}
220+
221+
Swing.updateMenuItem = function(menu, node) {
222+
J2S.unsetMouse(node);
223+
node.applet = menu._applet;
224+
node._frameViewer = menu.invoker.getFrameViewer$();
225+
node._menu = menu;
226+
J2S.setMouse(node, true);
227+
}
228+
184229
Swing.showMenu = function(menu, x, y) {
185230
// called by javajs.swing.JPopupMenu and swingjs.plaf.JSPopupMenuUI (menu.uiClassID)
186231
// allow for a user callback for customization of menu
@@ -189,49 +234,22 @@ Swing.showMenu = function(menu, x, y) {
189234
for (var i in menu._applet._menus)
190235
Swing.hideMenu(menu._applet._menus[i], true);
191236
if (J2S._showMenuCallback)
192-
J2S._showMenuCallback(menu, x, y);
237+
J2S._showMenuCallback(menu, x, y);
193238
var wasTainted = menu._tainted;
194-
if (menu._tainted) {
195-
if (menu.uiClassID) {
196-
// for SwingJS the top node is domNode itself, which is already <ul>
197-
var node = menu.ui.domNode;
198-
if (node != menu.$ulTop[0]) {
199-
if (menu.$ulTop) {
200-
//bindMenuActionCommands(menu._actionEvent, menu, false);
201-
menu.$ulTop.remove();
202-
}
203-
menu.setContainer(J2S.$(node));
204-
J2S.$(node).addClass("swingjsPopupMenu");
205-
}
206-
J2S.$after("body",node);
207-
node.style.display = "block";
208-
} else {
209-
menu.$ulTop.html(menu.toHTML());
210-
bindMenuActionCommands(menu._actionEvent, menu, true);
211-
}
212-
menu._tainted = false;
213-
}
239+
if (menu._tainted)
240+
Swing.updateMenu(menu);
214241
menu.setPosition(x, y);
215-
menu.$ulTop.hide().menu().menu('refresh').show();
216-
if (menu.uiClassID && wasTainted) {
217-
menu.$ulTop.find("[role=menuitem]").each(function(){
218-
var node = this;
219-
node.applet = menu._applet;
220-
node._frameViewer = menu.invoker.getFrameViewer$();
221-
node._menu = menu;
222-
J2S.setMouse(node, true);
223-
});
224-
}
225-
menu._visible = true;
226-
menu.timestamp = System.currentTimeMillis$();
227-
menu.dragBind(true);
228-
menu.$ulTop.unbind('clickoutjsmol mousemoveoutjsmol');
229-
if (!J2S._persistentMenu)
230-
menu.$ulTop.bind('clickoutjsmol mousemoveoutjsmol', function(evspecial, target, ev) {
231-
if (System.currentTimeMillis$() - menu.timestamp > 1000)
232-
Swing.hideMenu(menu);
233-
});
234-
menu.$ulTop.bind("contextmenu", function() {return false;});
242+
menu.$ulTop.hide().menu().show();
243+
menu._visible = true;
244+
menu.timestamp = System.currentTimeMillis$();
245+
menu.dragBind(true);
246+
// menu.$ulTop.unbind('clickoutjsmol mousemoveoutjsmol');
247+
// if (!J2S._persistentMenu)
248+
// menu.$ulTop.bind('clickoutjsmol mousemoveoutjsmol', function(evspecial, target, ev) {
249+
// if (System.currentTimeMillis$() - menu.timestamp > 500)
250+
// Swing.hideMenu(menu);
251+
// });
252+
menu.$ulTop.bind("contextmenu", function() {return false;});
235253
}
236254

237255
Swing.hideMenu = function(menu, force) {
@@ -252,7 +270,7 @@ Swing.disposeMenu = function(menu) {
252270
if (menu.uiClassID) {
253271
menu.$ulTop.find("[role=menuitem]").each(function(){
254272
this.applet = menu.ui.applet;
255-
J2S.setMouse(this, false);
273+
J2S.unsetMouse(this);
256274
});
257275
} else {
258276
Swing.bindMenuActionCommands(menu, false);

sources/net.sf.j2s.java.core/src/swingjs/plaf/JSButtonUI.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,12 @@ protected DOMNode createItem(String type, DOMNode label) {
136136
if (text == null && icon == null)
137137
return itemNode;
138138
centeringNode = menuAnchorNode = newDOMObject("a", id + type + "_a");
139-
DOMNode.setStyles(menuAnchorNode, "margin", "1px 4px 1px 4px");
139+
DOMNode.setStyles(menuAnchorNode, "margin", "1px 2px 1px 2px");
140140
itemNode.appendChild(menuAnchorNode);
141141
if (label == null) {
142142
// not a radio or checkbox
143143
// TODO: add vertical centering
144+
boolean hasIcon = (iconNode != null);
144145
if (iconNode == null)
145146
iconNode = newDOMObject("span", id + "_icon");
146147
if (textNode == null)

sources/net.sf.j2s.java.core/src/swingjs/plaf/JSCheckBoxMenuItemUI.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ public class JSCheckBoxMenuItemUI extends JSCheckBoxUI {
1010
public JSCheckBoxMenuItemUI() {
1111
super();
1212
isMenuItem = true;
13-
}
13+
actionItemOffset = "-7px";
14+
}
1415

1516
@Override
1617
protected String getPropertyPrefix() {

sources/net.sf.j2s.java.core/src/swingjs/plaf/JSComponentUI.java

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import javax.swing.Icon;
3636
import javax.swing.ImageIcon;
3737
import javax.swing.JComponent;
38+
import javax.swing.JPopupMenu;
3839
import javax.swing.SwingConstants.*;
3940
import javax.swing.UIManager;
4041
import javax.swing.event.ChangeEvent;
@@ -110,6 +111,8 @@ public class JSComponentUI extends ComponentUI
110111

111112
private static final Color rootPaneColor = new Color(238, 238, 238);
112113

114+
private static final int MENUITEM_OFFSET = 11;
115+
113116
final J2SInterface J2S = JSUtil.J2S;
114117
/**
115118
* provides a unique id for any component; set on instantiation
@@ -157,6 +160,8 @@ public JComponent getTargetParent() {
157160
return targetParent;
158161
}
159162

163+
protected JPopupMenu menu;
164+
160165
// MouseInputListener mouseInputListener;
161166

162167
/**
@@ -393,6 +398,8 @@ public void setDraggable(JSFunction f) {
393398

394399
private JQuery jquery = JSUtil.getJQuery();
395400

401+
protected boolean isPopupMenu;
402+
396403
public JSComponentUI() {
397404
setDoc();
398405
}
@@ -693,15 +700,8 @@ public void stateChanged(ChangeEvent e) {
693700
@Override
694701
public void propertyChange(PropertyChangeEvent e) {
695702
String prop = e.getPropertyName();
696-
if (prop == "ancestor") {
697-
JComponent p = (JComponent) jc.getParent();
698-
while (p != null) {
699-
JSComponentUI parentui = (JSComponentUI) (p == null ? null : p.getUI());
700-
if (parentui != null)
701-
parentui.setTainted();
702-
p = (JComponent) p.getParent();
703-
}
704-
703+
if (prop == "ancestor") {
704+
updatePropertyAncestor(false);
705705
if (e.getNewValue() == null)
706706
return;
707707
if (isDisposed && c.visible && e.getNewValue() != null)
@@ -710,13 +710,41 @@ public void propertyChange(PropertyChangeEvent e) {
710710
propertyChangedCUI(prop);
711711
}
712712

713+
private void updatePropertyAncestor(boolean fromButtonListener) {
714+
if (fromButtonListener) {
715+
setTainted();
716+
setHTMLElement();
717+
}
718+
JComponent p = (JComponent) jc.getParent();
719+
while (p != null) {
720+
JSComponentUI parentui = (JSComponentUI) (p == null ? null : p.getUI());
721+
if (parentui != null) {
722+
parentui.setTainted();
723+
parentui.setHTMLElement();
724+
if (fromButtonListener) {
725+
if (parentui.menu != null) {
726+
// System.out.println(
727+
// "ancestor " + fromButtonListener + " " + id + " " + parentui.id + " " + p.isVisible());
728+
((JSPopupMenuUI) parentui).updateMenu();
729+
} else if (parentui.isPopupMenu && p.getParent() == null) {
730+
p = (JComponent) ((JPopupMenu) p).getInvoker();
731+
continue;
732+
}
733+
}
734+
}
735+
p = (JComponent) p.getParent();
736+
}
737+
}
738+
713739
/**
714740
* plaf ButtonListener and TextListener will call this to update common
715741
* properties such as "text".
716742
*
717743
* @param prop
718744
*/
719745
void propertyChangedFromListener(String prop) {
746+
if (prop == "ancestor")
747+
updatePropertyAncestor(true);
720748
propertyChangedCUI(prop);
721749
}
722750

@@ -876,8 +904,10 @@ protected void debugDump(DOMNode d) {
876904
System.out.println(DOMNode.getAttr(d, "outerHTML"));
877905
}
878906

879-
protected static void vCenter(DOMNode obj, int offset) {
880-
DOMNode.setStyles(obj, "top", "50%", "transform", "translateY(" + offset + "%)");
907+
protected static void vCenter(DOMNode obj, int offset, float scale) {
908+
DOMNode.setStyles(obj, "top", "50%", "transform",
909+
(scale > 0 ? "scale(" + scale + "," + scale + ")" : "")
910+
+"translateY(" + offset + "%)");
881911
}
882912

883913
/**
@@ -1535,6 +1565,8 @@ private void setSizeFromComponent(int width, int height, int op) {
15351565

15361566
private Object dropTarget = this; // unactivated
15371567

1568+
protected String actionItemOffset;
1569+
15381570
protected void setJSDimensions(int width, int height) {
15391571
if (jsActualWidth > 0)
15401572
width = jsActualWidth;
@@ -1565,6 +1597,8 @@ protected void setHorizontalButtonAlignments(JComponent b, int pos, int align) {
15651597

15661598

15671599
int wIcon = Math.max(0, setHTMLSize1(iconNode, false, false).width - 1);
1600+
if (isMenuItem && actionNode != null)
1601+
wIcon = 15;
15681602
int wText = setHTMLSize1(textNode, false, false).width - 1;
15691603

15701604
// But we need to slightly underestimate it so that the
@@ -1611,8 +1645,6 @@ protected void setHorizontalButtonAlignments(JComponent b, int pos, int align) {
16111645
if (alignRight) {
16121646
if (buttonNode != null) {
16131647
DOMNode.setStyles(buttonNode, "right","0");
1614-
} else {
1615-
System.out.println("HHHMMM");
16161648
}
16171649
}
16181650
}
@@ -1626,7 +1658,7 @@ protected void setHorizontalButtonAlignments(JComponent b, int pos, int align) {
16261658
DOMNode.setStyles(centeringNode, poslr, "0px", "text-align", alignlr);
16271659
//if (buttonNode != null) {
16281660
DOMNode.setStyles(domNode, "text-align", null, "left", null, "right", null);
1629-
DOMNode.setStyles(domNode, "text-align", alignlr, poslr, "0px");
1661+
DOMNode.setStyles(domNode, "text-align", alignlr, poslr, px0);
16301662
//}
16311663
if (centered) {
16321664
int w = (buttonNode == null ?
@@ -1646,7 +1678,7 @@ protected void setHorizontalButtonAlignments(JComponent b, int pos, int align) {
16461678
DOMNode.setStyles(iconNode, poslr, wText + "px");
16471679
} else {
16481680
DOMNode.setStyles(textNode, poslr, (wIcon) + "px");
1649-
DOMNode.setStyles(iconNode, poslr, "0px");
1681+
DOMNode.setStyles(iconNode, poslr, (!isMenuItem ? "0px" : ltr ? actionItemOffset : "-3px"));
16501682
}
16511683
}
16521684

@@ -1691,8 +1723,11 @@ protected void setIconAndText(String prop, Icon icon, int gap, String text) {
16911723
if (icon != null)
16921724
canAlignIcon = true;
16931725
} else {
1694-
if (icon == null) {
1726+
if (icon == null) {
16951727
canAlignText = allowTextAlignment;
1728+
if (iconNode != null && isMenuItem && actionNode == null && text != null) {
1729+
DOMNode.addHorizontalGap(iconNode, gap + MENUITEM_OFFSET);
1730+
}
16961731
} else {
16971732
// vCenter(imageNode, 10); // perhaps? Not sure if this is a
16981733
// good idea

0 commit comments

Comments
 (0)