PageRenderTime 42ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/netbeans-7.3/openide.loaders/src/org/openide/awt/DynaMenuModel.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 348 lines | 262 code | 23 blank | 63 comment | 88 complexity | bf10c6ae0a0219386a42020f69e8e1e6 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.openide.awt;
  45. import java.awt.Component;
  46. import java.util.ArrayList;
  47. import java.util.Arrays;
  48. import java.util.Collections;
  49. import java.util.HashMap;
  50. import java.util.Iterator;
  51. import java.util.List;
  52. import java.util.Map;
  53. import javax.swing.Action;
  54. import javax.swing.Icon;
  55. import javax.swing.JComponent;
  56. import javax.swing.JMenu;
  57. import javax.swing.JMenuItem;
  58. import javax.swing.JPopupMenu;
  59. import javax.swing.JSeparator;
  60. import javax.swing.UIManager;
  61. import org.openide.filesystems.FileObject;
  62. import org.openide.util.ImageUtilities;
  63. import org.openide.util.Utilities;
  64. import org.openide.util.actions.Presenter;
  65. /**
  66. *
  67. * @author mkleint
  68. */
  69. class DynaMenuModel {
  70. private static final Icon BLANK_ICON = ImageUtilities.loadImageIcon("org/openide/loaders/empty.gif", false); // NOI18N
  71. private List<JComponent> menuItems;
  72. private HashMap<DynamicMenuContent, JComponent[]> actionToMenuMap;
  73. private boolean isWithIcons = false;
  74. /** Creates a new instance of DynaMenuModel */
  75. public DynaMenuModel() {
  76. actionToMenuMap = new HashMap<DynamicMenuContent, JComponent[]>();
  77. }
  78. public void loadSubmenu(List<Object> cInstances, JMenu m, Map<Object,FileObject> cookiesToFiles) {
  79. // clear first - refresh the menu's content
  80. boolean addSeparator = false;
  81. Icon curIcon = null;
  82. Iterator it = cInstances.iterator();
  83. menuItems = new ArrayList<JComponent>(cInstances.size());
  84. actionToMenuMap.clear();
  85. while (it.hasNext()) {
  86. Object obj = it.next();
  87. if (obj instanceof Action) {
  88. FileObject file = cookiesToFiles.get(obj);
  89. if (file != null) {
  90. AcceleratorBinding.setAccelerator((Action) obj, file);
  91. }
  92. }
  93. if (obj instanceof Presenter.Menu) {
  94. // does this still apply??
  95. obj = ((Presenter.Menu)obj).getMenuPresenter();
  96. }
  97. if (obj instanceof DynamicMenuContent) {
  98. if(addSeparator) {
  99. menuItems.add(null);
  100. addSeparator = false;
  101. }
  102. DynamicMenuContent mn = (DynamicMenuContent)obj;
  103. JComponent[] itms = convertArray(mn.getMenuPresenters());
  104. actionToMenuMap.put(mn, itms);
  105. Iterator itx = Arrays.asList(itms).iterator();
  106. while (itx.hasNext()) {
  107. JComponent comp = (JComponent)itx.next();
  108. menuItems.add(comp);
  109. // check icon
  110. isWithIcons = checkIcon(comp, isWithIcons);
  111. }
  112. continue;
  113. }
  114. if (obj instanceof JMenuItem) {
  115. if(addSeparator) {
  116. menuItems.add(null);
  117. addSeparator = false;
  118. }
  119. // check icon
  120. isWithIcons = checkIcon(obj, isWithIcons);
  121. menuItems.add((JMenuItem)obj);
  122. } else if (obj instanceof JSeparator) {
  123. addSeparator = menuItems.size() > 0;
  124. } else if (obj instanceof Action) {
  125. if(addSeparator) {
  126. menuItems.add(null);
  127. addSeparator = false;
  128. }
  129. Action a = (Action)obj;
  130. Actions.MenuItem item = new Actions.MenuItem(a, true);
  131. // check icon
  132. isWithIcons = checkIcon(item, isWithIcons);
  133. actionToMenuMap.put(item, new JComponent[] {item});
  134. menuItems.add(item);
  135. }
  136. }
  137. if (isWithIcons) {
  138. menuItems = alignVertically(menuItems);
  139. }
  140. // fill menu with built items
  141. JComponent curItem = null;
  142. boolean wasSeparator = false;
  143. for (Iterator<JComponent> iter = menuItems.iterator(); iter.hasNext(); ) {
  144. curItem = iter.next();
  145. if (curItem == null) {
  146. // null means separator
  147. curItem = createSeparator();
  148. }
  149. m.add(curItem);
  150. boolean isSeparator = curItem instanceof JSeparator;
  151. if (isSeparator && wasSeparator) {
  152. curItem.setVisible(false);
  153. }
  154. if (!(curItem instanceof InvisibleMenuItem)) {
  155. wasSeparator = isSeparator;
  156. }
  157. }
  158. }
  159. private boolean checkIcon(Object obj, boolean isWithIconsAlready) {
  160. if (isWithIconsAlready) {
  161. return isWithIconsAlready;
  162. }
  163. if (obj instanceof JMenuItem) {
  164. if (((JMenuItem)obj).getIcon() != null && !BLANK_ICON.equals(((JMenuItem)obj).getIcon())) {
  165. return true;
  166. }
  167. }
  168. return false;
  169. }
  170. public void checkSubmenu(JMenu menu) {
  171. boolean oldisWithIcons = isWithIcons;
  172. boolean changed = false;
  173. for (Map.Entry<DynamicMenuContent, JComponent[]> entry: actionToMenuMap.entrySet()) {
  174. DynamicMenuContent pres = entry.getKey();
  175. JComponent[] old = entry.getValue();
  176. int oldIndex = 0;
  177. Component[] menuones = menu.getPopupMenu().getComponents();
  178. int menuIndex = old.length > 0 ? findFirstItemIndex(old[0], menuones) : -1;
  179. JComponent[] newones = convertArray(pres.synchMenuPresenters(unconvertArray(old)));
  180. if (!compareEqualArrays(old, newones)) {
  181. if (menuIndex < 0) {
  182. menuIndex = 0;
  183. } else {
  184. for (int i = 0; i < old.length; i++) {
  185. if (old[i] != null) {
  186. menu.getPopupMenu().remove(old[i]);
  187. menuItems.remove(old[i]);
  188. }
  189. }
  190. }
  191. for (int i = 0; i < newones.length; i++) {
  192. ///TODO now what to do with icon alignments..
  193. JComponent one = newones[i];
  194. menu.getPopupMenu().add(one, i + menuIndex);
  195. changed = true;
  196. menuItems.add(one);
  197. boolean thisOneHasIcon = checkIcon(one, false);
  198. if (!thisOneHasIcon && isWithIcons) {
  199. alignVertically(Collections.singletonList(one));
  200. }
  201. if (thisOneHasIcon && !isWithIcons) {
  202. isWithIcons = true;
  203. }
  204. }
  205. entry.setValue(newones);
  206. }
  207. }
  208. boolean hasAnyIcons = false;
  209. Component[] menuones = menu.getPopupMenu().getComponents();
  210. for (int i = 0; i < menuones.length; i++) {
  211. if (menuones[i] != null) {
  212. hasAnyIcons = checkIcon(menuones[i], hasAnyIcons);
  213. if (hasAnyIcons) {
  214. break;
  215. }
  216. }
  217. }
  218. checkSeparators(menuones, menu.getPopupMenu());
  219. if (!hasAnyIcons && isWithIcons) {
  220. isWithIcons = false;
  221. }
  222. if (oldisWithIcons != isWithIcons) {
  223. menuItems = alignVertically(menuItems);
  224. }
  225. if (changed && Utilities.isWindows()) {
  226. //#67847 on windows, we need revalidation otherwise strange effects kick in..
  227. menu.getPopupMenu().revalidate();
  228. }
  229. }
  230. static void checkSeparators(Component[] menuones, JPopupMenu parent) {
  231. boolean wasSeparator = false;
  232. for (int i = 0; i < menuones.length; i++) {
  233. Component curItem = menuones[i];
  234. if (curItem != null) {
  235. boolean isSeparator = curItem instanceof JSeparator;
  236. if (isSeparator) {
  237. boolean isVisible = curItem.isVisible();
  238. if (isVisible != !wasSeparator) {
  239. //MACOSX whenever a property like enablement or visible is changed, need to remove and add.
  240. // could be possibly split to work differetly on other platform..
  241. parent.remove(i);
  242. JSeparator newOne = createSeparator();
  243. newOne.setVisible(!wasSeparator);
  244. parent.add(newOne, i);
  245. }
  246. }
  247. if (!(curItem instanceof InvisibleMenuItem)) {
  248. wasSeparator = isSeparator;
  249. }
  250. }
  251. }
  252. }
  253. private JComponent[] convertArray(JComponent[] arr) {
  254. if (arr == null || arr.length == 0) {
  255. return new JComponent[] { new InvisibleMenuItem() };
  256. }
  257. JComponent[] toRet = new JComponent[arr.length];
  258. for (int i = 0; i < arr.length; i++) {
  259. if (arr[i] == null) {
  260. toRet[i] = createSeparator();
  261. } else {
  262. toRet[i] = arr[i];
  263. }
  264. }
  265. return toRet;
  266. }
  267. private JComponent[] unconvertArray(JComponent[] arr) {
  268. if (arr.length == 1 && arr[0] instanceof InvisibleMenuItem) {
  269. return new JComponent[0];
  270. } else {
  271. return arr;
  272. }
  273. }
  274. private int findFirstItemIndex(JComponent first, Component[] menuItems) {
  275. for (int i = 0; i < menuItems.length; i++) {
  276. if (first == menuItems[i]) {
  277. return i;
  278. }
  279. }
  280. return -1;
  281. }
  282. private boolean compareEqualArrays(JComponent[] one, JComponent[] two) {
  283. if (one.length != two.length) {
  284. return false;
  285. }
  286. for (int i = 0; i < one.length; i++) {
  287. if (one[i] != two[i]) {
  288. return false;
  289. }
  290. }
  291. return true;
  292. }
  293. /** Removes icons from all direct menu items of this menu.
  294. * Not recursive, */
  295. private List<JComponent> alignVertically(List<JComponent> menuItems) {
  296. //#204646 - some L&Fs show check boxes and action icons in the same menu column (e.g. Vista l&f)
  297. //so do not use blank icons in such cases
  298. if( !UIManager.getBoolean( "Nb.MenuBar.VerticalAlign" ) ) //NOI18N
  299. return menuItems;
  300. List<JComponent> result = new ArrayList<JComponent>(menuItems.size());
  301. JMenuItem curItem = null;
  302. for (JComponent obj: menuItems) {
  303. if (obj instanceof JMenuItem) {
  304. curItem = (JMenuItem)obj;
  305. if (isWithIcons && curItem != null && curItem.getIcon() == null) {
  306. curItem.setIcon(BLANK_ICON);
  307. } else if (!isWithIcons && curItem != null) {
  308. curItem.setIcon(null);
  309. }
  310. }
  311. result.add(obj);
  312. }
  313. return result;
  314. }
  315. static final class InvisibleMenuItem extends JMenuItem {
  316. public boolean isVisible() {
  317. return false;
  318. }
  319. }
  320. private static JSeparator createSeparator() {
  321. JMenu menu = new JMenu();
  322. menu.addSeparator();
  323. return (JSeparator)menu.getPopupMenu().getComponent(0);
  324. }
  325. }